From 4aa959d59125684109ffab85761522f97f2e723d Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Fri, 10 Jan 2014 17:55:05 +0100 Subject: [PATCH 001/531] MPW server, get and update a gpg file --- lib/Server.rb | 255 ++++++++++++++++++++++++++++++++++++++++++++++++++ mpw-server | 46 +++++++++ 2 files changed, 301 insertions(+) create mode 100644 lib/Server.rb create mode 100755 mpw-server diff --git a/lib/Server.rb b/lib/Server.rb new file mode 100644 index 0000000..77e4415 --- /dev/null +++ b/lib/Server.rb @@ -0,0 +1,255 @@ +#!/usr/bin/ruby + +require 'socket' +require 'json' +require 'highline/import' +require 'digest' +require 'base64' + +require "#{APP_ROOT}/lib/MPW.rb" + +class Server + + attr_accessor :error_msg + + # Constructor + def initialize() + YAML::ENGINE.yamler='syck' + @error_msg = nil + end + + # Start the server + def start() + server = TCPServer.open(@host, @port) + loop do + Thread.start(server.accept) do |client| + msg = self.getClientMessage(client) + + if !msg + next + end + + if msg['gpg_key'].nil? || msg['gpg_key'].empty? || msg['password'].nil? || msg['password'].empty? + self.closeConnection(client) + next + end + + case msg['action'] + when 'get' + client.puts self.getFile(msg) + when 'update' + client.puts self.updateFile(msg) + when 'delete' + client.puts self.deleteFile(msg) + else + client.puts 'Unknown command' + end + + self.closeConnection(client) + end + end + end + + # Get a gpg file + # @args: msg -> message puts by the client + # @rtrn: json message + def getFile(msg) + gpg_key = msg['gpg_key'].sub('@', '_') + + if msg['suffix'].nil? || msg['suffix'].empty? + file_gpg = "#{@data_dir}/#{gpg_key}.yml" + else + file_gpg = "#{@data_dir}/#{gpg_key}-#{msg['suffix']}.yml" + end + + if File.exist?(file_gpg) + gpg_data = YAML::load_file(file_gpg) + salt = gpg_data['gpg']['salt'] + hash = gpg_data['gpg']['hash'] + data = gpg_data['gpg']['data'] + + if self.isAuthorized?(msg['password'], salt, hash) + send_msg = {:action => 'get', + :gpg_key => msg['gpg_key'], + :msg => 'get_done', + :data => data} + else + send_msg = {:action => 'get', + :gpg_key => msg['gpg_key'], + :msg => 'get_fail', + :error => 'not_authorized'} + end + else + send_msg = {:action => 'get', + :gpg_key => msg['gpg_key'], + :msg => 'get_fail', + :error => 'file_not_exist'} + end + + return send_msg.to_json + end + + # Update a file + # @args: msg -> message puts by the client + # @rtrn: json message + def updateFile(msg) + begin + gpg_key = msg['gpg_key'].sub('@', '_') + data = msg['data'] + + if data.nil? || data.empty? + send_msg = {:action => 'update', + :gpg_key => msg['gpg_key'], + :msg => 'update_fail', + :error => 'no_data'} + + return send_msg.to_json + end + + if msg['suffix'].nil? || msg['suffix'].empty? + file_gpg = "#{@data_dir}/#{gpg_key}.yml" + else + file_gpg = "#{@data_dir}/#{gpg_key}-#{msg['suffix']}.yml" + end + + if File.exist?(file_gpg) + gpg_data = YAML::load_file(file_gpg) + salt = gpg_data['gpg']['salt'] + hash = gpg_data['gpg']['hash'] + + else + salt = MPW.generatePassword(4) + hash = Digest::SHA256.hexdigest(salt + msg['password']) + end + + if self.isAuthorized?(msg['password'], salt, hash) + begin + config = {'gpg' => {'salt' => salt, + 'hash' => hash, + 'data' => data}} + + File.open(file_gpg, 'w') do |file| + file << config.to_yaml + end + + send_msg = {:action => 'update', + :gpg_key => msg['gpg_key'], + :msg => 'update_done'} + rescue Exception => e + send_msg = {:action => 'update', + :gpg_key => msg['gpg_key'], + :msg => 'update_fail', + :error => e} + end + else + send_msg = {:action => 'update', + :gpg_key => msg['gpg_key'], + :msg => 'update_fail', + :error => 'not_autorized'} + end + + return send_msg.to_json + rescue Exception => e + puts e + end + end + + # Remove a gpg file + # @args: msg -> message puts by the client + # @rtrn: json message + def deleteFile(msg) + client.puts 'delete a file' + end + + # Check is the hash equal the password with the salt + # @args: password -> the user password + # salt -> the salt + # hash -> the hash of the password with the salt + # @rtrn: true is is good, else false + def isAuthorized?(password, salt, hash) + puts hash + puts YAML::dump(hash) + puts YAML::dump(Digest::SHA256.hexdigest(salt + password)) + puts Digest::SHA256.hexdigest(salt + password) + if hash == Digest::SHA256.hexdigest(salt + password) + return true + else + return false + end + end + + # Get message to client + # @args: client -> client connection + # @rtrn: array of the json string, or false if isn't json message + def getClientMessage(client) + begin + msg = client.gets + return JSON.parse(msg) + rescue + client.puts "Communication it's bad" + self.closeConnection(client) + return false + end + end + + # Close the client connection + # @args: client -> client connection + def closeConnection(client) + client.puts "Closing the connection. Bye!" + client.close + end + + # Check the config file + # @args: file_config -> the configuration file + # @rtrn: true if the config file is correct + def checkconfig(file_config) + begin + config = YAML::load_file(file_config) + @host = config['config']['host'] + @port = config['config']['port'] + @data_dir = config['config']['data_dir'] + @timeout = config['config']['timeout'].to_i + + if @host.empty? || @port.empty? + @error_msg = "Checkconfig failed!" + return false + end + + rescue Exception => e + @error_msg = "Checkconfig failed!\n#{e}" + return false + end + + return true + end + + # Create a new config file + # @args: file_config -> the configuration file + # @rtrn: true if le config file is create + def setup(file_config) + + puts I18n.t('server.form.setup.title') + puts '--------------------' + host = ask(I18n.t('server.form.setup.host')).to_s + port = ask(I18n.t('server.form.setup.port')).to_s + data_dir = ask(I18n.t('server.form.setup.data_dir')).to_s + timeout = ask(I18n.t('server.form.setup.timeout')).to_s + + config = {'config' => {'host' => host, + 'port' => port, + 'data_dir' => data_dir, + 'timeout' => timeout}} + + begin + File.open(file_config, 'w') do |file| + file << config.to_yaml + end + rescue Exception => e + @error_msg = "Can't write the config file!\n#{e}" + return false + end + + return true + end + +end diff --git a/mpw-server b/mpw-server new file mode 100755 index 0000000..f764037 --- /dev/null +++ b/mpw-server @@ -0,0 +1,46 @@ +#!/usr/bin/ruby +# author: nishiki +# mail: nishiki@yaegashi.fr +# info: a simple script who manage your passwords + +require 'rubygems' +require 'optparse' +require 'pathname' + +APP_ROOT = File.dirname(Pathname.new(__FILE__).realpath) +require "#{APP_ROOT}/lib/Server.rb" + +options = {} +OptionParser.new do |opts| + opts.banner = "Usage: mpw-server -c CONFIG [options]" + + opts.on("-c", "--config CONFIG", "Specifie the configuration file") do |config| + options[:config] = config + end + + opts.on("-t", "--check-config", "Check your configuration") do |b| + options[:checkconfig] = b + end + + opts.on("-s", "--setup", "Force a server") do |b| + options[:setup] = b + end + + opts.on("-h", "--help", "Show this message") do |b| + puts opts + exit 0 + end +end.parse! + +server = Server.new + +if options[:checkconfig] + server.checkconfig(options[:config]) +elsif options[:setup] + server.setup(options[:config]) +else + server.checkconfig(options[:config]) + server.start() +end + +exit 0 From f684ebe79b215d032471e6fe148fd61802c54b4c Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Fri, 10 Jan 2014 18:01:56 +0100 Subject: [PATCH 002/531] remove debug exception --- lib/Server.rb | 4 ---- 1 file changed, 4 deletions(-) diff --git a/lib/Server.rb b/lib/Server.rb index 77e4415..7c83e88 100644 --- a/lib/Server.rb +++ b/lib/Server.rb @@ -93,7 +93,6 @@ class Server # @args: msg -> message puts by the client # @rtrn: json message def updateFile(msg) - begin gpg_key = msg['gpg_key'].sub('@', '_') data = msg['data'] @@ -149,9 +148,6 @@ class Server end return send_msg.to_json - rescue Exception => e - puts e - end end # Remove a gpg file From 3662bcb2510e53bba5f279ffd9f698042d368c2d Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Fri, 10 Jan 2014 18:12:24 +0100 Subject: [PATCH 003/531] add delete a gpg file --- lib/Server.rb | 47 ++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 42 insertions(+), 5 deletions(-) diff --git a/lib/Server.rb b/lib/Server.rb index 7c83e88..b90a5f5 100644 --- a/lib/Server.rb +++ b/lib/Server.rb @@ -154,7 +154,48 @@ class Server # @args: msg -> message puts by the client # @rtrn: json message def deleteFile(msg) - client.puts 'delete a file' + gpg_key = msg['gpg_key'].sub('@', '_') + + if msg['suffix'].nil? || msg['suffix'].empty? + file_gpg = "#{@data_dir}/#{gpg_key}.yml" + else + file_gpg = "#{@data_dir}/#{gpg_key}-#{msg['suffix']}.yml" + end + + if !File.exist?(file_gpg) + send_msg = {:action => 'delete', + :gpg_key => msg['gpg_key'], + :msg => 'delete_fail', + :error => 'file_not_exist'} + + return send_msg.to_json + end + + gpg_data = YAML::load_file(file_gpg) + salt = gpg_data['gpg']['salt'] + hash = gpg_data['gpg']['hash'] + + if self.isAuthorized?(msg['password'], salt, hash) + begin + File.unlink(file_gpg) + + send_msg = {:action => 'delete', + :gpg_key => msg['gpg_key'], + :msg => 'delete_done'} + rescue Exception => e + send_msg = {:action => 'delete', + :gpg_key => msg['gpg_key'], + :msg => 'delete_fail', + :error => e} + end + else + send_msg = {:action => 'delete', + :gpg_key => msg['gpg_key'], + :msg => 'delete_fail', + :error => 'not_autorized'} + end + + return send_msg.to_json end # Check is the hash equal the password with the salt @@ -163,10 +204,6 @@ class Server # hash -> the hash of the password with the salt # @rtrn: true is is good, else false def isAuthorized?(password, salt, hash) - puts hash - puts YAML::dump(hash) - puts YAML::dump(Digest::SHA256.hexdigest(salt + password)) - puts Digest::SHA256.hexdigest(salt + password) if hash == Digest::SHA256.hexdigest(salt + password) return true else From 8530f61b76eb0ccec291e8e780c65ccbf4b6967f Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Fri, 10 Jan 2014 22:36:51 +0100 Subject: [PATCH 004/531] translate in french and in english --- i18n/en.yml | 15 +++++++++++++++ i18n/fr.yml | 15 +++++++++++++++ lib/Server.rb | 3 +-- mpw-server | 24 +++++++++++++++++++----- 4 files changed, 50 insertions(+), 7 deletions(-) diff --git a/i18n/en.yml b/i18n/en.yml index 6eecd3c..27a2d11 100644 --- a/i18n/en.yml +++ b/i18n/en.yml @@ -111,6 +111,21 @@ en: display: connect: "Connection to:" nothing: "Nothing result!" + server: + option: + usage: "Usage" + config: "Specifie the configuration file" + checkconfig: "Check the configuration" + setup: "Setup a new configuration file" + help: "Show this message help" + form: + setup: + title: "Serveur configuration" + host: "IP listen: " + port: "Port listen: " + data_dir: "Data directory: " + timeout: "Timeout to second: " + not_valid: "ERROR: Impossible to write the configuration file!" formats: default: ! '%Y-%m-%d' long: ! '%B %d, %Y' diff --git a/i18n/fr.yml b/i18n/fr.yml index ba433fb..770dd21 100644 --- a/i18n/fr.yml +++ b/i18n/fr.yml @@ -111,6 +111,21 @@ fr: display: connect: "Connexion à:" nothing: "Aucun résultat!" + server: + option: + usage: "Utilisation" + config: "Spécifie le fichier de configuration" + checkconfig: "Vérifie le fichier de configuration" + setup: "Permet de générer un nouveau fichier de configuration" + help: "Affiche ce message d'aide" + form: + setup: + title: "Configuration du serveur" + host: "IP d'écoute: " + port: "Port d'écoute: " + data_dir: "Répertoire des données: " + timeout: "Timeout en seconde: " + not_valid: "ERREUR: Impossible d'écire le fichier de configuration!" formats: default: ! '%Y-%m-%d' long: ! '%B %d, %Y' diff --git a/lib/Server.rb b/lib/Server.rb index b90a5f5..77ee2c2 100644 --- a/lib/Server.rb +++ b/lib/Server.rb @@ -260,7 +260,6 @@ class Server # @args: file_config -> the configuration file # @rtrn: true if le config file is create def setup(file_config) - puts I18n.t('server.form.setup.title') puts '--------------------' host = ask(I18n.t('server.form.setup.host')).to_s @@ -278,7 +277,7 @@ class Server file << config.to_yaml end rescue Exception => e - @error_msg = "Can't write the config file!\n#{e}" + puts "#{I18n.t('server.formsetup.not_valid')}\n#{e}" return false end diff --git a/mpw-server b/mpw-server index f764037..3143b59 100755 --- a/mpw-server +++ b/mpw-server @@ -6,32 +6,46 @@ require 'rubygems' require 'optparse' require 'pathname' +require 'locale' +require 'i18n' APP_ROOT = File.dirname(Pathname.new(__FILE__).realpath) require "#{APP_ROOT}/lib/Server.rb" +lang = Locale::Tag.parse(ENV['LANG']).to_simple.to_s[0..1] + +I18n::Backend::Simple.send(:include, I18n::Backend::Fallbacks) +I18n.load_path = Dir["#{APP_ROOT}/i18n/*.yml"] +I18n.default_locale = :en +I18n.locale = lang.to_sym + options = {} OptionParser.new do |opts| - opts.banner = "Usage: mpw-server -c CONFIG [options]" + opts.banner = "#{I18n.t('server.option.usage')}: mpw-server -c CONFIG [options]" - opts.on("-c", "--config CONFIG", "Specifie the configuration file") do |config| + opts.on("-c", "--config CONFIG", I18n.t('server.option.config')) do |config| options[:config] = config end - opts.on("-t", "--check-config", "Check your configuration") do |b| + opts.on("-t", "--checkconfig", I18n.t('server.option.checkconfig')) do |b| options[:checkconfig] = b end - opts.on("-s", "--setup", "Force a server") do |b| + opts.on("-s", "--setup", I18n.t('server.option.setup')) do |b| options[:setup] = b end - opts.on("-h", "--help", "Show this message") do |b| + opts.on("-h", "--help", I18n.t('server.option.help')) do |b| puts opts exit 0 end end.parse! +if options[:config].nil? || options[:config].empty? + puts "#{I18n.t('server.option.usage')}: mpw-server -c CONFIG [options]" + exit 2 +end + server = Server.new if options[:checkconfig] From c0751b3b25344585b34091d2d884c15ffd4bef85 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Fri, 10 Jan 2014 22:49:22 +0100 Subject: [PATCH 005/531] translate checkconfig --- i18n/en.yml | 4 ++++ i18n/fr.yml | 4 ++++ lib/Server.rb | 14 ++++++++++---- 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/i18n/en.yml b/i18n/en.yml index 27a2d11..9a4781a 100644 --- a/i18n/en.yml +++ b/i18n/en.yml @@ -118,6 +118,10 @@ en: checkconfig: "Check the configuration" setup: "Setup a new configuration file" help: "Show this message help" + checkconfig: + fail: "Checkconfig failed:!" + empty: "ERROR: an importe option is missing!" + datadir: "ERROR: le data directory doesn't exist!" form: setup: title: "Serveur configuration" diff --git a/i18n/fr.yml b/i18n/fr.yml index 770dd21..74924b7 100644 --- a/i18n/fr.yml +++ b/i18n/fr.yml @@ -118,6 +118,10 @@ fr: checkconfig: "Vérifie le fichier de configuration" setup: "Permet de générer un nouveau fichier de configuration" help: "Affiche ce message d'aide" + checkconfig: + fail: "Le fichier de configuration est invalide!" + empty: "ERREUR: Une option importante est manquante!" + datadir: "ERREUR: Le répertoire des données n'existe pas!" form: setup: title: "Configuration du serveur" diff --git a/lib/Server.rb b/lib/Server.rb index 77ee2c2..699b355 100644 --- a/lib/Server.rb +++ b/lib/Server.rb @@ -15,7 +15,6 @@ class Server # Constructor def initialize() YAML::ENGINE.yamler='syck' - @error_msg = nil end # Start the server @@ -243,13 +242,20 @@ class Server @data_dir = config['config']['data_dir'] @timeout = config['config']['timeout'].to_i - if @host.empty? || @port.empty? - @error_msg = "Checkconfig failed!" + if @host.empty? || @port.empty? || @data_dir.empty? + puts I18n.t('server.checkconfig.fail') + puts I18n.t('server.checkconfig.empty') + return false + end + + if !Dir.exist?(@data_dir) + puts I18n.t('server.checkconfig.fail') + puts I18n.t('server.checkconfig.datadir') return false end rescue Exception => e - @error_msg = "Checkconfig failed!\n#{e}" + puts "#{I18n.t('server.checkconfig.fail')}\n#{e}" return false end From 55db474039e1c43dbbb87ba8dca6e1ea63915186 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Fri, 10 Jan 2014 22:52:55 +0100 Subject: [PATCH 006/531] remove require base64 --- lib/Server.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/Server.rb b/lib/Server.rb index 699b355..737d9da 100644 --- a/lib/Server.rb +++ b/lib/Server.rb @@ -4,7 +4,6 @@ require 'socket' require 'json' require 'highline/import' require 'digest' -require 'base64' require "#{APP_ROOT}/lib/MPW.rb" From 6b9474e5384920a5e9621455779d822efd53716d Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sat, 11 Jan 2014 15:49:22 +0100 Subject: [PATCH 007/531] fix problem in translate file --- i18n/en.yml | 10 +++++----- i18n/fr.yml | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/i18n/en.yml b/i18n/en.yml index 9a4781a..c2203c4 100644 --- a/i18n/en.yml +++ b/i18n/en.yml @@ -125,11 +125,11 @@ en: form: setup: title: "Serveur configuration" - host: "IP listen: " - port: "Port listen: " - data_dir: "Data directory: " - timeout: "Timeout to second: " - not_valid: "ERROR: Impossible to write the configuration file!" + host: "IP listen: " + port: "Port listen: " + data_dir: "Data directory: " + timeout: "Timeout to second: " + not_valid: "ERROR: Impossible to write the configuration file!" formats: default: ! '%Y-%m-%d' long: ! '%B %d, %Y' diff --git a/i18n/fr.yml b/i18n/fr.yml index 74924b7..a1323be 100644 --- a/i18n/fr.yml +++ b/i18n/fr.yml @@ -125,11 +125,11 @@ fr: form: setup: title: "Configuration du serveur" - host: "IP d'écoute: " - port: "Port d'écoute: " - data_dir: "Répertoire des données: " - timeout: "Timeout en seconde: " - not_valid: "ERREUR: Impossible d'écire le fichier de configuration!" + host: "IP d'écoute: " + port: "Port d'écoute: " + data_dir: "Répertoire des données: " + timeout: "Timeout en seconde: " + not_valid: "ERREUR: Impossible d'écire le fichier de configuration!" formats: default: ! '%Y-%m-%d' long: ! '%B %d, %Y' From e0a120d8f12855c01349398e84c2935ab2392435 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sun, 12 Jan 2014 00:37:46 +0100 Subject: [PATCH 008/531] restructiring the code --- lib/Cli.rb | 58 +++++++++++++------------ lib/MPW.rb | 87 +++---------------------------------- lib/MPWConfig.rb | 109 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 146 insertions(+), 108 deletions(-) create mode 100644 lib/MPWConfig.rb diff --git a/lib/Cli.rb b/lib/Cli.rb index cc67cd1..4947c00 100644 --- a/lib/Cli.rb +++ b/lib/Cli.rb @@ -10,6 +10,7 @@ require 'readline' require 'i18n' require "#{APP_ROOT}/lib/MPW.rb" +require "#{APP_ROOT}/lib/MPWConfig.rb" class Cli @@ -17,14 +18,15 @@ class Cli # @args: lang -> the operating system language # config_file -> a specify config file def initialize(lang, config_file=nil) - @m = MPW.new(config_file) + @config = MPWConfig.new(config_file) - if not @m.checkconfig() + if not @config.checkconfig() self.setup(lang) end + @mpw = MPW.new(@config.file_gpg, @config.key) if not self.decrypt() - puts "#{I18n.t('cli.display.error')}: #{@m.error_msg}" + puts "#{I18n.t('cli.display.error')}: #{@mpw.error_msg}" exit 2 end end @@ -44,28 +46,28 @@ class Cli end I18n.locale = language.to_sym - if @m.setup(key, language, file_gpg, timeout_pwd) + if @config.setup(key, language, file_gpg, timeout_pwd) puts I18n.t('cli.form.setup.valid') else - puts "#{I18n.t('cli.display.error')}: #{@m.error_msg}" + puts "#{I18n.t('cli.display.error')}: #{@config.error_msg}" end - if not @m.checkconfig() - puts "#{I18n.t('cli.display.error')}: #{@m.error_msg}" + if not @config.checkconfig() + puts "#{I18n.t('cli.display.error')}: #{@config.error_msg}" end end # Request the GPG password and decrypt the file def decrypt() @passwd = ask(I18n.t('cli.display.gpg_password')) {|q| q.echo = false} - return @m.decrypt(@passwd) + return @mpw.decrypt(@passwd) end # Display the query's result # @args: search -> the string to search # protocol -> search from a particular protocol def display(search, protocol=nil, group=nil, format=nil) - result = @m.search(search, group, protocol) + result = @mpw.search(search, group, protocol) if not result.empty? result.each do |r| @@ -125,21 +127,21 @@ class Cli port = ask(I18n.t('cli.form.add.port')).to_s comment = ask(I18n.t('cli.form.add.comment')).to_s - if @m.add(name, group, server, protocol, login, passwd, port, comment) - if @m.encrypt() + if @mpw.add(name, group, server, protocol, login, passwd, port, comment) + if @mpw.encrypt() puts I18n.t('cli.form.add.valid') else - puts "#{I18n.t('cli.display.error')}: #{@m.error_msg}" + puts "#{I18n.t('cli.display.error')}: #{@mpw.error_msg}" end else - puts "#{I18n.t('cli.display.error')}: #{@m.error_msg}" + puts "#{I18n.t('cli.display.error')}: #{@mpw.error_msg}" end end # Update an item # @args: id -> the item's id def update(id) - row = @m.searchById(id) + row = @mpw.searchById(id) if not row.empty? puts I18n.t('cli.form.update.title') @@ -153,14 +155,14 @@ class Cli port = ask(I18n.t('cli.form.update.port' , :port => row[MPW::PORT])).to_s comment = ask(I18n.t('cli.form.update.comment' , :comment => row[MPW::COMMENT])).to_s - if @m.update(id, name, group, server, protocol, login, passwd, port, comment) - if @m.encrypt() + if @mpw.update(id, name, group, server, protocol, login, passwd, port, comment) + if @mpw.encrypt() puts I18n.t('cli.form.update.valid') else - puts "#{I18n.t('cli.display.error')}: #{@m.error_msg}" + puts "#{I18n.t('cli.display.error')}: #{@mpw.error_msg}" end else - puts "#{I18n.t('cli.display.error')}: #{@m.error_msg}" + puts "#{I18n.t('cli.display.error')}: #{@mpw.error_msg}" end else puts I18n.t('cli.display.nothing') @@ -172,7 +174,7 @@ class Cli # force -> no resquest a validation def remove(id, force=false) if not force - result = @m.searchById(id) + result = @mpw.searchById(id) if result.length > 0 self.displayFormat(result) @@ -187,11 +189,11 @@ class Cli end if force - if @m.remove(id) - if @m.encrypt() + if @mpw.remove(id) + if @mpw.encrypt() puts I18n.t('cli.form.delete.valid', :id => id) else - puts "#{I18n.t('cli.display.error')}: #{@m.error_msg}" + puts "#{I18n.t('cli.display.error')}: #{@mpw.error_msg}" end else puts I18n.t('cli.form.delete.not_valid') @@ -202,10 +204,10 @@ class Cli # Export the items in a CSV file # @args: file -> the destination file def export(file) - if @m.export(file) + if @mpw.export(file) puts "The export in #{file} is succesfull!" else - puts "#{I18n.t('cli.display.error')}: #{@m.error_msg}" + puts "#{I18n.t('cli.display.error')}: #{@mpw.error_msg}" end end @@ -214,7 +216,7 @@ class Cli # @args: file -> the import file # force -> no resquest a validation def import(file, force=false) - result = @m.importPreview(file) + result = @mpw.importPreview(file) if not force if result.is_a?(Array) && !result.empty? @@ -232,10 +234,10 @@ class Cli end if force - if @m.import(file) && @m.encrypt() + if @mpw.import(file) && @mpw.encrypt() puts I18n.t('cli.form.import.valid') else - puts "#{I18n.t('cli.display.error')}: #{@m.error_msg}" + puts "#{I18n.t('cli.display.error')}: #{@mpw.error_msg}" end end end @@ -247,7 +249,7 @@ class Cli while buf = Readline.readline('<mpw> ', true) - if @m.timeout_pwd < Time.now.to_i - last_access + if @config.timeout_pwd < Time.now.to_i - last_access passwd_confirm = ask(I18n.t('cli.interactive.ask_password')) {|q| q.echo = false} if @passwd.eql?(passwd_confirm) diff --git a/lib/MPW.rb b/lib/MPW.rb index e38ec0a..937ecdf 100644 --- a/lib/MPW.rb +++ b/lib/MPW.rb @@ -6,7 +6,6 @@ require 'rubygems' require 'gpgme' require 'csv' -require 'yaml' require 'i18n' class MPW @@ -22,79 +21,12 @@ class MPW COMMENT = 8 attr_accessor :error_msg - attr_accessor :timeout_pwd - + # Constructor - # @args: file_config -> the specify config file - def initialize(file_config=nil) - @error_msg = nil - @file_config = "#{Dir.home()}/.mpw.cfg" - - if !file_config.nil? && !file_config.empty? - @file_config = file_config - end - end - - # Create a new config file - # @args: key -> the gpg key to encrypt - # lang -> the software language - # file_gpg -> the file who is encrypted - # file_pwd -> the file who stock the password - # timeout_pwd -> time to save the password - # @rtrn: true if le config file is create - def setup(key, lang, file_gpg, timeout_pwd) - - if not key =~ /[a-zA-Z0-9.-_]+\@[a-zA-Z0-9]+\.[a-zA-Z]+/ - @error_msg = I18n.t('error.config.key_bad_format') - return false - end - - if file_gpg.empty? - file_gpg = "#{Dir.home()}/.mpw.gpg" - end - - timeout_pwd.empty? ? (timeout_pwd = 60) : (timeout_pwd = timeout_pwd.to_i) - - config = {'config' => {'key' => key, - 'lang' => lang, - 'file_gpg' => file_gpg, - 'timeout_pwd' => timeout_pwd}} - - begin - File.open(@file_config, 'w') do |file| - file << config.to_yaml - end - rescue Exception => e - @error_msg = "#{I18n.t('error.config.write')}\n#{e}" - return false - end - - return true - end - - # Check the config file - # @rtrn: true if the config file is correct - def checkconfig() - begin - config = YAML::load_file(@file_config) - @key = config['config']['key'] - @lang = config['config']['lang'] - @file_gpg = config['config']['file_gpg'] - @timeout_pwd = config['config']['timeout_pwd'].to_i - - if @key.empty? || @file_gpg.empty? - @error_msg = I18n.t('error.config.check') - return false - end - - I18n.locale = @lang.to_sym - - rescue Exception => e - @error_msg = "#{I18n.t('error.config.check')}\n#{e}" - return false - end - - return true + def initialize(file_gpg, key=nil) + @error_msg = nil + @file_gpg = file_gpg + @key = key end # Decrypt a gpg file @@ -117,10 +49,6 @@ class MPW return true rescue Exception => e - if !@file_pwd.nil? && File.exist?(@file_pwd) - File.delete(@file_pwd) - end - @error_msg = "#{I18n.t('error.gpg_file.decrypt')}\n#{e}" return false end @@ -327,7 +255,7 @@ class MPW end end - # Return + # Return a preview import # @args: file -> path to file import # @rtrn: an array with the items to import, if there is an error return false def importPreview(file) @@ -372,7 +300,6 @@ class MPW result << ([*('A'..'Z'),*('a'..'z'),*('0'..'9')]).sample(length).join return result - #return ([*('A'..'Z'),*('a'..'z'),*('0'..'9')]-%w(0 1 I O l i o)).sample(length).join end - + end diff --git a/lib/MPWConfig.rb b/lib/MPWConfig.rb new file mode 100644 index 0000000..25dac98 --- /dev/null +++ b/lib/MPWConfig.rb @@ -0,0 +1,109 @@ +#!/usr/bin/ruby +# author: nishiki +# mail: nishiki@yaegashi.fr +# info: a simple script who manage your passwords + +require 'rubygems' +require 'yaml' +require 'i18n' + +class MPWConfig + + attr_accessor :error_msg + + attr_accessor :key + attr_accessor :lang + attr_accessor :file_gpg + attr_accessor :timeout_pwd + attr_accessor :sync_host + attr_accessor :sync_port + attr_accessor :sync_pwd + attr_accessor :sync_sufix + + # Constructor + # @args: file_config -> the specify config file + def initialize(file_config=nil) + @error_msg = nil + @file_config = "#{Dir.home()}/.mpw.cfg" + + if !file_config.nil? && !file_config.empty? + @file_config = file_config + end + end + + # Create a new config file + # @args: key -> the gpg key to encrypt + # lang -> the software language + # file_gpg -> the file who is encrypted + # timeout_pwd -> time to save the password + # @rtrn: true if le config file is create + def setup(key, lang, file_gpg, timeout_pwd) + + if not key =~ /[a-zA-Z0-9.-_]+\@[a-zA-Z0-9]+\.[a-zA-Z]+/ + @error_msg = I18n.t('error.config.key_bad_format') + return false + end + + if file_gpg.empty? + file_gpg = "#{Dir.home()}/.mpw.gpg" + end + + timeout_pwd.empty? ? (timeout_pwd = 60) : (timeout_pwd = timeout_pwd.to_i) + + config = {'config' => {'key' => key, + 'lang' => lang, + 'file_gpg' => file_gpg, + 'timeout_pwd' => timeout_pwd, + 'sync_host' => host, + 'sync_port' => port, + 'sync_pwd' => password, + 'sync_suffix' => suffix}} + + begin + File.open(@file_config, 'w') do |file| + file << config.to_yaml + end + rescue Exception => e + @error_msg = "#{I18n.t('error.config.write')}\n#{e}" + return false + end + + return true + end + + # Check the config file + # @rtrn: true if the config file is correct + def checkconfig() + begin + config = YAML::load_file(@file_config) + @key = config['config']['key'] + @lang = config['config']['lang'] + @file_gpg = config['config']['file_gpg'] + @timeout_pwd = config['config']['timeout_pwd'].to_i + @sync_host = config['config']['sync_host'] + @sync_port = config['config']['sync_port'] + @sync_pwd = config['config']['sync_pwd'] + @sync_sufix = config['config']['sync_suffix'] + + if @key.empty? || @file_gpg.empty? + @error_msg = I18n.t('error.config.check') + return false + end + + I18n.locale = @lang.to_sym + + rescue Exception => e + @error_msg = "#{I18n.t('error.config.check')}\n#{e}" + return false + end + + begin + @sync = TCPSocket.new(@sync_host, @sync_port) + rescue + @sync = false + end + + return true + end + +end From 9067a67d506035796d73b6df5079ee8e601048e3 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sun, 12 Jan 2014 00:40:58 +0100 Subject: [PATCH 009/531] remove tcp test --- lib/MPWConfig.rb | 6 ------ 1 file changed, 6 deletions(-) diff --git a/lib/MPWConfig.rb b/lib/MPWConfig.rb index 25dac98..a59f3b5 100644 --- a/lib/MPWConfig.rb +++ b/lib/MPWConfig.rb @@ -97,12 +97,6 @@ class MPWConfig return false end - begin - @sync = TCPSocket.new(@sync_host, @sync_port) - rescue - @sync = false - end - return true end From 477178ecdd13f19775552a464fa5458a9ce21254 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sun, 12 Jan 2014 11:07:54 +0100 Subject: [PATCH 010/531] add last_update --- lib/Server.rb | 39 ++++++++++++++++++++++----------------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/lib/Server.rb b/lib/Server.rb index 737d9da..307d0b6 100644 --- a/lib/Server.rb +++ b/lib/Server.rb @@ -61,26 +61,28 @@ class Server end if File.exist?(file_gpg) - gpg_data = YAML::load_file(file_gpg) - salt = gpg_data['gpg']['salt'] - hash = gpg_data['gpg']['hash'] - data = gpg_data['gpg']['data'] + gpg_data = YAML::load_file(file_gpg) + salt = gpg_data['gpg']['salt'] + hash = gpg_data['gpg']['hash'] + data = gpg_data['gpg']['data'] + last_update = gpg_data['gpg']['last_update'] if self.isAuthorized?(msg['password'], salt, hash) send_msg = {:action => 'get', :gpg_key => msg['gpg_key'], - :msg => 'get_done', + :last_update => last_update, + :msg => 'done', :data => data} else send_msg = {:action => 'get', :gpg_key => msg['gpg_key'], - :msg => 'get_fail', + :msg => 'fail', :error => 'not_authorized'} end else send_msg = {:action => 'get', :gpg_key => msg['gpg_key'], - :msg => 'get_fail', + :msg => 'fail', :error => 'file_not_exist'} end @@ -97,7 +99,7 @@ class Server if data.nil? || data.empty? send_msg = {:action => 'update', :gpg_key => msg['gpg_key'], - :msg => 'update_fail', + :msg => 'fail', :error => 'no_data'} return send_msg.to_json @@ -121,27 +123,30 @@ class Server if self.isAuthorized?(msg['password'], salt, hash) begin - config = {'gpg' => {'salt' => salt, - 'hash' => hash, - 'data' => data}} + last_update = Time.now.to_i + config = {'gpg' => {'salt' => salt, + 'hash' => hash, + 'last_update' => last_update + 'data' => data}} File.open(file_gpg, 'w') do |file| file << config.to_yaml end - send_msg = {:action => 'update', - :gpg_key => msg['gpg_key'], - :msg => 'update_done'} + send_msg = {:action => 'update', + :gpg_key => msg['gpg_key'], + :last_update => last_update + :msg => 'done'} rescue Exception => e send_msg = {:action => 'update', :gpg_key => msg['gpg_key'], - :msg => 'update_fail', - :error => e} + :msg => 'fail', + :error => 'server_error'} end else send_msg = {:action => 'update', :gpg_key => msg['gpg_key'], - :msg => 'update_fail', + :msg => 'fail', :error => 'not_autorized'} end From b9988102d6dda915ce1e3cb8a4bee4a9dc2569f3 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sun, 12 Jan 2014 11:36:56 +0100 Subject: [PATCH 011/531] add last_update in MPWConfig --- lib/MPWConfig.rb | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/lib/MPWConfig.rb b/lib/MPWConfig.rb index a59f3b5..a402ee3 100644 --- a/lib/MPWConfig.rb +++ b/lib/MPWConfig.rb @@ -19,11 +19,12 @@ class MPWConfig attr_accessor :sync_port attr_accessor :sync_pwd attr_accessor :sync_sufix + attr_accessor :sync_last_update # Constructor # @args: file_config -> the specify config file def initialize(file_config=nil) - @error_msg = nil + @error_msg = nil @file_config = "#{Dir.home()}/.mpw.cfg" if !file_config.nil? && !file_config.empty? @@ -57,7 +58,8 @@ class MPWConfig 'sync_host' => host, 'sync_port' => port, 'sync_pwd' => password, - 'sync_suffix' => suffix}} + 'sync_suffix' => suffix, + 'last_update' => 0 }} begin File.open(@file_config, 'w') do |file| @@ -76,14 +78,15 @@ class MPWConfig def checkconfig() begin config = YAML::load_file(@file_config) - @key = config['config']['key'] - @lang = config['config']['lang'] - @file_gpg = config['config']['file_gpg'] - @timeout_pwd = config['config']['timeout_pwd'].to_i - @sync_host = config['config']['sync_host'] - @sync_port = config['config']['sync_port'] - @sync_pwd = config['config']['sync_pwd'] - @sync_sufix = config['config']['sync_suffix'] + @key = config['config']['key'] + @lang = config['config']['lang'] + @file_gpg = config['config']['file_gpg'] + @timeout_pwd = config['config']['timeout_pwd'].to_i + @sync_host = config['config']['sync_host'] + @sync_port = config['config']['sync_port'] + @sync_pwd = config['config']['sync_pwd'] + @sync_sufix = config['config']['sync_suffix'] + @sync_last_update = config['config']['sync_last_update'].to_i if @key.empty? || @file_gpg.empty? @error_msg = I18n.t('error.config.check') From d458a09a75c5fd6fc3f7fd0c25a9703e58af4ebb Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sun, 12 Jan 2014 14:09:32 +0100 Subject: [PATCH 012/531] fix bug --- lib/Server.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/Server.rb b/lib/Server.rb index 307d0b6..361835a 100644 --- a/lib/Server.rb +++ b/lib/Server.rb @@ -126,7 +126,7 @@ class Server last_update = Time.now.to_i config = {'gpg' => {'salt' => salt, 'hash' => hash, - 'last_update' => last_update + 'last_update' => last_update, 'data' => data}} File.open(file_gpg, 'w') do |file| @@ -135,7 +135,7 @@ class Server send_msg = {:action => 'update', :gpg_key => msg['gpg_key'], - :last_update => last_update + :last_update => last_update, :msg => 'done'} rescue Exception => e send_msg = {:action => 'update', From bc276f23c11bc953f2975e7f2a70659459d7f265 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Mon, 13 Jan 2014 20:07:15 +0100 Subject: [PATCH 013/531] add uniq id and date time --- lib/MPW.rb | 94 ++++++++++++++++++++++++++++-------------------------- 1 file changed, 49 insertions(+), 45 deletions(-) diff --git a/lib/MPW.rb b/lib/MPW.rb index 937ecdf..1bd4392 100644 --- a/lib/MPW.rb +++ b/lib/MPW.rb @@ -19,6 +19,7 @@ class MPW PASSWORD = 6 PORT = 7 COMMENT = 8 + DATE = 9 attr_accessor :error_msg @@ -40,10 +41,8 @@ class MPW crypto = GPGME::Crypto.new(:armor => true) data_decrypt = crypto.decrypt(IO.read(@file_gpg), :password => passwd).read - id = 0 data_decrypt.lines do |line| - @data[id] = line.parse_csv.unshift(id) - id += 1; + @data.push(line.parse_csv) end end @@ -63,7 +62,7 @@ class MPW data_to_encrypt = '' @data.each do |row| - data_to_encrypt << row.drop(1).to_csv + data_to_encrypt << row.to_csv end crypto.encrypt(data_to_encrypt, :recipients => @key, :output => file_gpg) @@ -107,11 +106,13 @@ class MPW # @args: id -> the id item # @rtrn: a row with the resultat of the search def searchById(id) - if not @data[id.to_i].nil? - return @data[id.to_i] - else - return Array.new + @data.each do |row| + if @data[ID] == id + return row + end end + + return Array.new() end # Add a new item @@ -136,16 +137,10 @@ class MPW port = nil end - if not @data.last.nil? - id = @data.last - id = id[ID].to_i + 1 - else - id = 0 - end - - row[ID] = id + row[ID] = MPW.generatePassword(16) row[PORT] = port row[NAME] = name.force_encoding('ASCII-8BIT') + row[DATE] = Time.now.to_i group.nil? || group.empty? ? (row[GROUP] = nil) : (row[GROUP] = group.force_encoding('ASCII-8BIT')) server.nil? || server.empty? ? (row[SERVER] = nil) : (row[SERVER] = server.force_encoding('ASCII-8BIT')) protocol.nil? || protocol.empty? ? (row[PROTOCOL] = nil) : (row[PROTOCOL] = protocol.force_encoding('ASCII-8BIT')) @@ -153,7 +148,7 @@ class MPW passwd.nil? || passwd.empty? ? (row[PASSWORD] = nil) : (row[PASSWORD] = passwd.force_encoding('ASCII-8BIT')) comment.nil? || comment.empty? ? (row[COMMENT] = nil) : (row[COMMENT] = comment.force_encoding('ASCII-8BIT')) - @data[id] = row + @data.push(row) return true end @@ -170,45 +165,54 @@ class MPW # comment -> a comment # @rtrn: true if the item has been updated def update(id, name=nil, group=nil, server=nil, protocol=nil, login=nil, passwd=nil, port=nil, comment=nil) - id = id.to_i + i = 0 - if not @data[id].nil? + @data.each do |row| + if not row[ID] == id - if port.to_i <= 0 - port = nil + if port.to_i <= 0 + port = nil + end + + row_update = Array.new() + row[DATE] = Time.now.to_i + + name.nil? || name.empty? ? (row_update[NAME] = row[NAME]) : (row_update[NAME] = name) + group.nil? || group.empty? ? (row_update[GROUP] = row[GROUP]) : (row_update[GROUP] = group) + server.nil? || server.empty? ? (row_update[SERVER] = row[SERVER]) : (row_update[SERVER] = server) + protocol.nil? || protocol.empty? ? (row_update[PROTOCOL] = row[PROTOCOL]) : (row_update[PROTOCOL] = protocol) + login.nil? || login.empty? ? (row_update[LOGIN] = row[LOGIN]) : (row_update[LOGIN] = login) + passwd.nil? || passwd.empty? ? (row_update[PASSWORD] = row[PASSWORD]) : (row_update[PASSWORD] = passwd) + port.nil? || port.empty? ? (row_update[PORT] = row[PORT]) : (row_update[PORT] = port) + comment.nil? || comment.empty? ? (row_update[COMMENT] = row[COMMENT]) : (row_update[COMMENT] = comment) + + @data[i] = row_update + + return true end - row = @data[id] - row_update = Array.new() - - name.nil? || name.empty? ? (row_update[NAME] = row[NAME]) : (row_update[NAME] = name) - group.nil? || group.empty? ? (row_update[GROUP] = row[GROUP]) : (row_update[GROUP] = group) - server.nil? || server.empty? ? (row_update[SERVER] = row[SERVER]) : (row_update[SERVER] = server) - protocol.nil? || protocol.empty? ? (row_update[PROTOCOL] = row[PROTOCOL]) : (row_update[PROTOCOL] = protocol) - login.nil? || login.empty? ? (row_update[LOGIN] = row[LOGIN]) : (row_update[LOGIN] = login) - passwd.nil? || passwd.empty? ? (row_update[PASSWORD] = row[PASSWORD]) : (row_update[PASSWORD] = passwd) - port.nil? || port.empty? ? (row_update[PORT] = row[PORT]) : (row_update[PORT] = port) - comment.nil? || comment.empty? ? (row_update[COMMENT] = row[COMMENT]) : (row_update[COMMENT] = comment) - - @data[id] = row_update - - return true - else - @error_msg = I18n.t('error.update.id_no_exist', :id => id) - return false + i += 1 end + + @error_msg = I18n.t('error.update.id_no_exist', :id => id) + return false end # Remove an item # @args: id -> the item's identifiant # @rtrn: true if the item has been deleted def remove(id) - if not @data.delete_at(id.to_i).nil? - return true - else - @error_msg = I18n.t('error.delete.id_no_exist', :id => id) - return false + i = 0 + @data.each do |row| + if row[ID] == id + @data.delete(i) + return true + end + i += 1 end + + @error_msg = I18n.t('error.delete.id_no_exist', :id => id) + return false end # Export to csv @@ -218,7 +222,7 @@ class MPW begin File.open(file, 'w+') do |file| @data.each do |row| - row.delete_at(ID) + row.delete_at(ID).delete_at(DATE) file << row.to_csv end end From 8b86040af0f16efde46e55bc1d7fe4a980eb2b30 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Tue, 14 Jan 2014 23:00:52 +0100 Subject: [PATCH 014/531] first sync work :) --- lib/Cli.rb | 19 +++++++++ lib/MPW.rb | 58 +++++++++++++++++++++++--- lib/MPWConfig.rb | 46 ++++++++++++++++----- lib/Server.rb | 68 ++++++++++++++++-------------- lib/Sync.rb | 105 +++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 248 insertions(+), 48 deletions(-) create mode 100644 lib/Sync.rb diff --git a/lib/Cli.rb b/lib/Cli.rb index 4947c00..aab3242 100644 --- a/lib/Cli.rb +++ b/lib/Cli.rb @@ -8,9 +8,11 @@ require 'highline/import' require 'pathname' require 'readline' require 'i18n' +require 'yaml' require "#{APP_ROOT}/lib/MPW.rb" require "#{APP_ROOT}/lib/MPWConfig.rb" +require "#{APP_ROOT}/lib/Sync.rb" class Cli @@ -29,6 +31,23 @@ class Cli puts "#{I18n.t('cli.display.error')}: #{@mpw.error_msg}" exit 2 end + + @sync = Sync.new() + if @config.sync_host.nil? || @config.sync_port.nil? + @sync.disable() + elsif !@sync.connect(@config.sync_host, @config.sync_port, @config.key, @config.sync_pwd, @config.sync_suffix) + puts "#{I18n.t('cli.sync.not_connect')}:\n#{@sync.error_msg}" + else + begin + @mpw.sync(@sync.get(@passwd), @config.last_update) + @sync.update(File.open(@config.file_gpg).read) + @config.setLastUpdate() + rescue Exception => e + puts "#{I18n.t('cli.sync.error')}:\n#{e}" + else + @sync.close() + end + end end # Create a new config file diff --git a/lib/MPW.rb b/lib/MPW.rb index 1bd4392..1d15076 100644 --- a/lib/MPW.rb +++ b/lib/MPW.rb @@ -79,7 +79,7 @@ class MPW # @args: search -> the string to search # protocol -> the connection protocol (ssh, web, other) # @rtrn: a list with the resultat of the search - def search(search, group=nil, protocol=nil) + def search(search='', group=nil, protocol=nil) result = Array.new() if !search.nil? @@ -107,7 +107,7 @@ class MPW # @rtrn: a row with the resultat of the search def searchById(id) @data.each do |row| - if @data[ID] == id + if row[ID] == id return row end end @@ -168,14 +168,15 @@ class MPW i = 0 @data.each do |row| - if not row[ID] == id + if row[ID] == id if port.to_i <= 0 port = nil end - row_update = Array.new() - row[DATE] = Time.now.to_i + row_update = Array.new() + row_update[ID] = row[ID] + row_update[DATE] = Time.now.to_i name.nil? || name.empty? ? (row_update[NAME] = row[NAME]) : (row_update[NAME] = name) group.nil? || group.empty? ? (row_update[GROUP] = row[GROUP]) : (row_update[GROUP] = group) @@ -205,7 +206,7 @@ class MPW i = 0 @data.each do |row| if row[ID] == id - @data.delete(i) + @data.delete_at(i) return true end i += 1 @@ -286,6 +287,51 @@ class MPW end end + # Sync remote data and local data + # @args: data_remote -> array with the data remote + # last_update -> last update + # @rtrn: false if data_remote is nil + def sync(data_remote, last_update) + if !data_remote.instance_of?(Array) + return false + end + + @data.each do |l| + j = 0 + update = false + + # Update item + data_remote.each do |r| + if l[ID] == r[ID] + if l[DATE].to_i < r[DATE].to_i + self.update(l[ID], r[NAME], r[GROUP], r[SERVER], r[PROTOCOL], r[LOGIN], r[PASSWORD], r[PORT], r[COMMENT]) + end + update = true + data_remote.delete_at(j) + break + end + j += 1 + end + + # Delete an old item + if !update && l[DATE].to_i < last_update + self.remove(l[ID]) + end + end + + # Add item + data_remote.each do |r| + if r[DATE].to_i > last_update + puts 'add' + @data.push(r) + end + end + + self.encrypt() + + return true + end + # Generate a random password # @args: length -> the length password # @rtrn: a random string diff --git a/lib/MPWConfig.rb b/lib/MPWConfig.rb index a402ee3..790f34e 100644 --- a/lib/MPWConfig.rb +++ b/lib/MPWConfig.rb @@ -15,11 +15,12 @@ class MPWConfig attr_accessor :lang attr_accessor :file_gpg attr_accessor :timeout_pwd + attr_accessor :last_update attr_accessor :sync_host attr_accessor :sync_port attr_accessor :sync_pwd - attr_accessor :sync_sufix - attr_accessor :sync_last_update + attr_accessor :sync_suffix + attr_accessor :last_update # Constructor # @args: file_config -> the specify config file @@ -78,15 +79,15 @@ class MPWConfig def checkconfig() begin config = YAML::load_file(@file_config) - @key = config['config']['key'] - @lang = config['config']['lang'] - @file_gpg = config['config']['file_gpg'] - @timeout_pwd = config['config']['timeout_pwd'].to_i - @sync_host = config['config']['sync_host'] - @sync_port = config['config']['sync_port'] - @sync_pwd = config['config']['sync_pwd'] - @sync_sufix = config['config']['sync_suffix'] - @sync_last_update = config['config']['sync_last_update'].to_i + @key = config['config']['key'] + @lang = config['config']['lang'] + @file_gpg = config['config']['file_gpg'] + @timeout_pwd = config['config']['timeout_pwd'].to_i + @sync_host = config['config']['sync_host'] + @sync_port = config['config']['sync_port'] + @sync_pwd = config['config']['sync_pwd'] + @sync_sufix = config['config']['sync_suffix'] + @last_update = config['config']['last_update'].to_i if @key.empty? || @file_gpg.empty? @error_msg = I18n.t('error.config.check') @@ -102,5 +103,28 @@ class MPWConfig return true end + + def setLastUpdate() + config = {'config' => {'key' => @key, + 'lang' => @lang, + 'file_gpg' => @file_gpg, + 'timeout_pwd' => @timeout_pwd, + 'sync_host' => @sync_host, + 'sync_port' => @sync_port, + 'sync_pwd' => @sync_pwd, + 'sync_suffix' => @sync_uffix, + 'last_update' => Time.now.to_i }} + + begin + File.open(@file_config, 'w') do |file| + file << config.to_yaml + end + rescue Exception => e + @error_msg = "#{I18n.t('error.config.write')}\n#{e}" + return false + end + + return true + end end diff --git a/lib/Server.rb b/lib/Server.rb index 361835a..59d377c 100644 --- a/lib/Server.rb +++ b/lib/Server.rb @@ -21,29 +21,33 @@ class Server server = TCPServer.open(@host, @port) loop do Thread.start(server.accept) do |client| - msg = self.getClientMessage(client) + while true do + msg = self.getClientMessage(client) - if !msg - next - end - - if msg['gpg_key'].nil? || msg['gpg_key'].empty? || msg['password'].nil? || msg['password'].empty? - self.closeConnection(client) - next - end + if !msg + next + end + + if msg['gpg_key'].nil? || msg['gpg_key'].empty? || msg['password'].nil? || msg['password'].empty? + self.closeConnection(client) + next + end - case msg['action'] - when 'get' - client.puts self.getFile(msg) - when 'update' - client.puts self.updateFile(msg) - when 'delete' - client.puts self.deleteFile(msg) - else - client.puts 'Unknown command' + case msg['action'] + when 'get' + client.puts self.getFile(msg) + when 'update' + client.puts self.updateFile(msg) + puts 'update' + when 'delete' + client.puts self.deleteFile(msg) + when 'close' + self.closeConnection(client) + else + client.puts 'Unknown command' + self.closeConnection(client) + end end - - self.closeConnection(client) end end end @@ -68,11 +72,11 @@ class Server last_update = gpg_data['gpg']['last_update'] if self.isAuthorized?(msg['password'], salt, hash) - send_msg = {:action => 'get', - :gpg_key => msg['gpg_key'], + send_msg = {:action => 'get', + :gpg_key => msg['gpg_key'], :last_update => last_update, - :msg => 'done', - :data => data} + :msg => 'done', + :data => data} else send_msg = {:action => 'get', :gpg_key => msg['gpg_key'], @@ -80,10 +84,12 @@ class Server :error => 'not_authorized'} end else - send_msg = {:action => 'get', - :gpg_key => msg['gpg_key'], - :msg => 'fail', - :error => 'file_not_exist'} + send_msg = {:action => 'get', + :gpg_key => msg['gpg_key'], + :last_update => 0, + :data => '', + :msg => 'fail', + :error => 'file_not_exist'} end return send_msg.to_json @@ -129,7 +135,7 @@ class Server 'last_update' => last_update, 'data' => data}} - File.open(file_gpg, 'w') do |file| + File.open(file_gpg, 'w+') do |file| file << config.to_yaml end @@ -242,11 +248,11 @@ class Server begin config = YAML::load_file(file_config) @host = config['config']['host'] - @port = config['config']['port'] + @port = config['config']['port'].to_i @data_dir = config['config']['data_dir'] @timeout = config['config']['timeout'].to_i - if @host.empty? || @port.empty? || @data_dir.empty? + if @host.empty? || @port <= 0 || @data_dir.empty? puts I18n.t('server.checkconfig.fail') puts I18n.t('server.checkconfig.empty') return false diff --git a/lib/Sync.rb b/lib/Sync.rb new file mode 100644 index 0000000..99f7d81 --- /dev/null +++ b/lib/Sync.rb @@ -0,0 +1,105 @@ +#!/usr/bin/ruby +# author: nishiki +# mail: nishiki@yaegashi.fr +# info: a simple script who manage your passwords + +require 'rubygems' +require 'i18n' +require 'socket' +require 'json' + +require "#{APP_ROOT}/lib/MPW.rb" + +class Sync + + attr_accessor :error_msg + + def initialize() + @error_msg = nil + end + + def disable() + @sync = false + end + + def connect(host, port, gpg_key, password, suffix=nil) + @gpg_key = gpg_key + @password = password + @suffix = suffix + + begin + @socket= TCPSocket.new(host, port) + @sync = true + rescue Exception => e + @error_msg = "ERROR: Connection impossible\n#{e}" + @sync = false + end + + return @sync + end + + def get(gpg_password) + send_msg = {:action => 'get', + :gpg_key => @gpg_key, + :password => @password, + :suffix => @suffix} + + @socket.puts send_msg.to_json + msg = JSON.parse(@socket.gets) + + case msg['error'] + when nil, 'file_not_exist' + tmp_file = "/tmp/mpw-#{MPW.generatePassword()}.gpg" + File.open(tmp_file, 'w') do |file| + file << msg['data'] + end + + @mpw = MPW.new(tmp_file) + if !@mpw.decrypt(gpg_password) + return nil + end + + File.unlink(tmp_file) + + return @mpw.search() + when 'not_authorized' + @error_msg = 'not authorized' + else + @error_msg = 'error unknow' + end + + return nil + end + + def update(data) + send_msg = {:action => 'update', + :gpg_key => @gpg_key, + :password => @password, + :suffix => @suffix, + :data => data} + + @socket.puts send_msg.to_json + msg = JSON.parse(@socket.gets) + + case msg['error'] + when nil + return true + when 'not_authorized' + @error_msg = 'not authorized' + when 'no_data' + @error_msg = 'no data' + else + @error_msg = 'error unknow' + end + + return false + end + + def delete() + end + + def close() + send_msg = {:action => 'close'} + @socket.puts send_msg.to_json + end +end From e8c315403e0c76527ea8c987fd155b50282d7a33 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Tue, 14 Jan 2014 23:20:17 +0100 Subject: [PATCH 015/531] remove dev debug --- lib/Server.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/Server.rb b/lib/Server.rb index 59d377c..d3b561b 100644 --- a/lib/Server.rb +++ b/lib/Server.rb @@ -38,7 +38,6 @@ class Server client.puts self.getFile(msg) when 'update' client.puts self.updateFile(msg) - puts 'update' when 'delete' client.puts self.deleteFile(msg) when 'close' From 213743bad22abc8cdc8752a91f8a756f199e0d15 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Wed, 15 Jan 2014 20:01:23 +0100 Subject: [PATCH 016/531] fusion MPW:add and MPW:update --- lib/Cli.rb | 22 +++++----- lib/MPW.rb | 115 ++++++++++++++++++++--------------------------------- 2 files changed, 54 insertions(+), 83 deletions(-) diff --git a/lib/Cli.rb b/lib/Cli.rb index aab3242..ed28ca2 100644 --- a/lib/Cli.rb +++ b/lib/Cli.rb @@ -23,11 +23,11 @@ class Cli @config = MPWConfig.new(config_file) if not @config.checkconfig() - self.setup(lang) + setup(lang) end @mpw = MPW.new(@config.file_gpg, @config.key) - if not self.decrypt() + if not decrypt() puts "#{I18n.t('cli.display.error')}: #{@mpw.error_msg}" exit 2 end @@ -91,9 +91,9 @@ class Cli if not result.empty? result.each do |r| if format.nil? || !format - self.displayFormat(r) + displayFormat(r) else - self.displayFormatAlt(r) + displayFormatAlt(r) end end else @@ -146,7 +146,7 @@ class Cli port = ask(I18n.t('cli.form.add.port')).to_s comment = ask(I18n.t('cli.form.add.comment')).to_s - if @mpw.add(name, group, server, protocol, login, passwd, port, comment) + if @mpw.update(name, group, server, protocol, login, passwd, port, comment) if @mpw.encrypt() puts I18n.t('cli.form.add.valid') else @@ -174,7 +174,7 @@ class Cli port = ask(I18n.t('cli.form.update.port' , :port => row[MPW::PORT])).to_s comment = ask(I18n.t('cli.form.update.comment' , :comment => row[MPW::COMMENT])).to_s - if @mpw.update(id, name, group, server, protocol, login, passwd, port, comment) + if @mpw.update(name, group, server, protocol, login, passwd, port, comment, id) if @mpw.encrypt() puts I18n.t('cli.form.update.valid') else @@ -196,7 +196,7 @@ class Cli result = @mpw.searchById(id) if result.length > 0 - self.displayFormat(result) + displayFormat(result) confirm = ask("#{I18n.t('cli.form.delete.ask', :id => id)} (y/N) ").to_s if confirm =~ /^(y|yes|YES|Yes|Y)$/ @@ -240,7 +240,7 @@ class Cli if not force if result.is_a?(Array) && !result.empty? result.each do |r| - self.displayFormat(r) + displayFormat(r) end confirm = ask("#{I18n.t('cli.form.import.ask', :file => file)} (y/N) ").to_s @@ -286,17 +286,17 @@ class Cli case command[0] when 'display', 'show', 'd', 's' if !command[1].nil? && !command[1].empty? - self.display(command[1], group, command[2]) + display(command[1], group, command[2]) end when 'add', 'a' add() when 'update', 'u' if !command[1].nil? && !command[1].empty? - self.update(command[1]) + update(command[1]) end when 'remove', 'delete', 'r', 'd' if !command[1].nil? && !command[1].empty? - self.remove(command[1]) + remove(command[1]) end when 'group', 'g' if !command[1].nil? && !command[1].empty? diff --git a/lib/MPW.rb b/lib/MPW.rb index 1d15076..6886b85 100644 --- a/lib/MPW.rb +++ b/lib/MPW.rb @@ -115,44 +115,6 @@ class MPW return Array.new() end - # Add a new item - # @args: name -> the item name - # group -> the item group - # server -> the ip or server - # protocol -> the protocol - # login -> the login - # passwd -> the password - # port -> the port - # comment -> a comment - # @rtrn: true if it works - def add(name, group=nil, server=nil, protocol=nil, login=nil, passwd=nil, port=nil, comment=nil) - row = Array.new() - - if name.nil? || name.empty? - @error_msg = I18n.t('error.add.name_empty') - return false - end - - if port.to_i <= 0 - port = nil - end - - row[ID] = MPW.generatePassword(16) - row[PORT] = port - row[NAME] = name.force_encoding('ASCII-8BIT') - row[DATE] = Time.now.to_i - group.nil? || group.empty? ? (row[GROUP] = nil) : (row[GROUP] = group.force_encoding('ASCII-8BIT')) - server.nil? || server.empty? ? (row[SERVER] = nil) : (row[SERVER] = server.force_encoding('ASCII-8BIT')) - protocol.nil? || protocol.empty? ? (row[PROTOCOL] = nil) : (row[PROTOCOL] = protocol.force_encoding('ASCII-8BIT')) - login.nil? || login.empty? ? (row[LOGIN] = nil) : (row[LOGIN] = login.force_encoding('ASCII-8BIT')) - passwd.nil? || passwd.empty? ? (row[PASSWORD] = nil) : (row[PASSWORD] = passwd.force_encoding('ASCII-8BIT')) - comment.nil? || comment.empty? ? (row[COMMENT] = nil) : (row[COMMENT] = comment.force_encoding('ASCII-8BIT')) - - @data.push(row) - - return true - end - # Update an item # @args: id -> the item's identifiant # name -> the item name @@ -164,39 +126,49 @@ class MPW # port -> the port # comment -> a comment # @rtrn: true if the item has been updated - def update(id, name=nil, group=nil, server=nil, protocol=nil, login=nil, passwd=nil, port=nil, comment=nil) - i = 0 + def update(name, group, server, protocol, login, passwd, port, comment, id=nil) + row = Array.new() + update = false - @data.each do |row| - if row[ID] == id - - if port.to_i <= 0 - port = nil - end - - row_update = Array.new() - row_update[ID] = row[ID] - row_update[DATE] = Time.now.to_i - - name.nil? || name.empty? ? (row_update[NAME] = row[NAME]) : (row_update[NAME] = name) - group.nil? || group.empty? ? (row_update[GROUP] = row[GROUP]) : (row_update[GROUP] = group) - server.nil? || server.empty? ? (row_update[SERVER] = row[SERVER]) : (row_update[SERVER] = server) - protocol.nil? || protocol.empty? ? (row_update[PROTOCOL] = row[PROTOCOL]) : (row_update[PROTOCOL] = protocol) - login.nil? || login.empty? ? (row_update[LOGIN] = row[LOGIN]) : (row_update[LOGIN] = login) - passwd.nil? || passwd.empty? ? (row_update[PASSWORD] = row[PASSWORD]) : (row_update[PASSWORD] = passwd) - port.nil? || port.empty? ? (row_update[PORT] = row[PORT]) : (row_update[PORT] = port) - comment.nil? || comment.empty? ? (row_update[COMMENT] = row[COMMENT]) : (row_update[COMMENT] = comment) - - @data[i] = row_update - - return true + i = 0 + @data.each do |r| + if r[ID] == id + row = r + update = true + break end - i += 1 end - @error_msg = I18n.t('error.update.id_no_exist', :id => id) - return false + if port.to_i <= 0 + port = nil + end + + row_update = Array.new() + row_update[DATE] = Time.now.to_i + + id.nil? || id.empty? ? (row_update[ID] = MPW.generatePassword(16)) : (row_update[ID] = row[ID]) + name.nil? || name.empty? ? (row_update[NAME] = row[NAME]) : (row_update[NAME] = name) + group.nil? || group.empty? ? (row_update[GROUP] = row[GROUP]) : (row_update[GROUP] = group) + server.nil? || server.empty? ? (row_update[SERVER] = row[SERVER]) : (row_update[SERVER] = server) + protocol.nil? || protocol.empty? ? (row_update[PROTOCOL] = row[PROTOCOL]) : (row_update[PROTOCOL] = protocol) + login.nil? || login.empty? ? (row_update[LOGIN] = row[LOGIN]) : (row_update[LOGIN] = login) + passwd.nil? || passwd.empty? ? (row_update[PASSWORD] = row[PASSWORD]) : (row_update[PASSWORD] = passwd) + port.nil? || port.empty? ? (row_update[PORT] = row[PORT]) : (row_update[PORT] = port) + comment.nil? || comment.empty? ? (row_update[COMMENT] = row[COMMENT]) : (row_update[COMMENT] = comment) + + if row_update[NAME].nil? || row_update[NAME].empty? + @error_msg = I18n.t('error.update.name_empty') + return false + end + + if update + @data[i] = row_update + else + @data.push(row_update) + end + + return true end # Remove an item @@ -247,7 +219,7 @@ class MPW return false else row = line.parse_csv.unshift(0) - if not add(row[NAME], row[GROUP], row[SERVER], row[PROTOCOL], row[LOGIN], row[PASSWORD], row[PORT], row[COMMENT]) + if not update(row[NAME], row[GROUP], row[SERVER], row[PROTOCOL], row[LOGIN], row[PASSWORD], row[PORT], row[COMMENT]) return false end end @@ -304,7 +276,7 @@ class MPW data_remote.each do |r| if l[ID] == r[ID] if l[DATE].to_i < r[DATE].to_i - self.update(l[ID], r[NAME], r[GROUP], r[SERVER], r[PROTOCOL], r[LOGIN], r[PASSWORD], r[PORT], r[COMMENT]) + update(r[NAME], r[GROUP], r[SERVER], r[PROTOCOL], r[LOGIN], r[PASSWORD], r[PORT], r[COMMENT], l[ID]) end update = true data_remote.delete_at(j) @@ -315,19 +287,18 @@ class MPW # Delete an old item if !update && l[DATE].to_i < last_update - self.remove(l[ID]) + remove(l[ID]) end end # Add item data_remote.each do |r| if r[DATE].to_i > last_update - puts 'add' - @data.push(r) + update(r[NAME], r[GROUP], r[SERVER], r[PROTOCOL], r[LOGIN], r[PASSWORD], r[PORT], r[COMMENT], r[ID]) end end - self.encrypt() + encrypt() return true end From 90086f3262d4b371ca43499f17ca09b457c97645 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Wed, 15 Jan 2014 20:16:14 +0100 Subject: [PATCH 017/531] disable sync if connect fail --- lib/Sync.rb | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/lib/Sync.rb b/lib/Sync.rb index 99f7d81..126b02d 100644 --- a/lib/Sync.rb +++ b/lib/Sync.rb @@ -39,6 +39,10 @@ class Sync end def get(gpg_password) + if !@sync + return nil + end + send_msg = {:action => 'get', :gpg_key => @gpg_key, :password => @password, @@ -72,6 +76,10 @@ class Sync end def update(data) + if !@sync + return true + end + send_msg = {:action => 'update', :gpg_key => @gpg_key, :password => @password, @@ -99,6 +107,10 @@ class Sync end def close() + if !@sync + return + end + send_msg = {:action => 'close'} @socket.puts send_msg.to_json end From 5d19550371975a2dce452b05c8b1f6ebeb446716 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Wed, 15 Jan 2014 20:17:47 +0100 Subject: [PATCH 018/531] add version file --- VERSION | 1 + 1 file changed, 1 insertion(+) create mode 100644 VERSION diff --git a/VERSION b/VERSION new file mode 100644 index 0000000..3eebe6a --- /dev/null +++ b/VERSION @@ -0,0 +1 @@ +1.1.0 - dev From 049ad927f219e05925116424bb866d82a3c40735 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Wed, 15 Jan 2014 20:21:45 +0100 Subject: [PATCH 019/531] update translation for MPW.rb --- i18n/en.yml | 4 +--- i18n/fr.yml | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/i18n/en.yml b/i18n/en.yml index c2203c4..a3141bf 100644 --- a/i18n/en.yml +++ b/i18n/en.yml @@ -1,8 +1,6 @@ --- en: error: - add: - name_empty: "You must define a name!" config: write: "Can't write the config file!" check: "Checkconfig failed!" @@ -18,7 +16,7 @@ en: bad_format: "Can't import, the file is badly formated!" read: "Can't import, unable to read %{file}!" update: - id_no_exist: "Can't update the item, the item %{id} doesn't exist!" + name_empty: "You must define a name!" cli: option: usage: "Usage" diff --git a/i18n/fr.yml b/i18n/fr.yml index a1323be..5ccef5f 100644 --- a/i18n/fr.yml +++ b/i18n/fr.yml @@ -1,8 +1,6 @@ --- fr: error: - add: - name_empty: "Vous devez définir un nom!" config: write: "Impossible d'écrire le fichier de configuration!" check: "Le fichier de configuration est invalide!" @@ -18,7 +16,7 @@ fr: bad_format: "Impossible d'importer le fichier car son format est incorrect!" read: "Impossible d'importer le fichier %{file}, car il n'est pas lisible!" update: - id_no_exist: "Impossible de mettre à jour l'élément %{id}, car il n'existe pas!" + name_empty: "Vous devez définir un nom!" cli: option: usage: "Utilisation" From a01a28112a5280e92c4c6e995016467dfe9ce068 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Wed, 15 Jan 2014 20:52:59 +0100 Subject: [PATCH 020/531] fix bug suffix --- lib/MPWConfig.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/MPWConfig.rb b/lib/MPWConfig.rb index 790f34e..21c1437 100644 --- a/lib/MPWConfig.rb +++ b/lib/MPWConfig.rb @@ -112,7 +112,7 @@ class MPWConfig 'sync_host' => @sync_host, 'sync_port' => @sync_port, 'sync_pwd' => @sync_pwd, - 'sync_suffix' => @sync_uffix, + 'sync_suffix' => @sync_suffix, 'last_update' => Time.now.to_i }} begin From d5c2af0867539f1d48699d533317d981a1c8651b Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Wed, 15 Jan 2014 20:55:17 +0100 Subject: [PATCH 021/531] fix bug suffix --- lib/MPWConfig.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/MPWConfig.rb b/lib/MPWConfig.rb index 21c1437..d68d0c7 100644 --- a/lib/MPWConfig.rb +++ b/lib/MPWConfig.rb @@ -86,7 +86,7 @@ class MPWConfig @sync_host = config['config']['sync_host'] @sync_port = config['config']['sync_port'] @sync_pwd = config['config']['sync_pwd'] - @sync_sufix = config['config']['sync_suffix'] + @sync_suffix = config['config']['sync_suffix'] @last_update = config['config']['last_update'].to_i if @key.empty? || @file_gpg.empty? From 0598ec134f5965f2f912d69619b25bfb3b86f5ea Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Wed, 15 Jan 2014 22:49:01 +0100 Subject: [PATCH 022/531] clean code --- lib/Server.rb | 29 +++++++++++------------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/lib/Server.rb b/lib/Server.rb index d3b561b..5b76de7 100644 --- a/lib/Server.rb +++ b/lib/Server.rb @@ -22,29 +22,29 @@ class Server loop do Thread.start(server.accept) do |client| while true do - msg = self.getClientMessage(client) + msg = getClientMessage(client) if !msg next end if msg['gpg_key'].nil? || msg['gpg_key'].empty? || msg['password'].nil? || msg['password'].empty? - self.closeConnection(client) + closeConnection(client) next end case msg['action'] when 'get' - client.puts self.getFile(msg) + client.puts getFile(msg) when 'update' - client.puts self.updateFile(msg) + client.puts updateFile(msg) when 'delete' - client.puts self.deleteFile(msg) + client.puts deleteFile(msg) when 'close' - self.closeConnection(client) + closeConnection(client) else client.puts 'Unknown command' - self.closeConnection(client) + closeConnection(client) end end end @@ -68,12 +68,10 @@ class Server salt = gpg_data['gpg']['salt'] hash = gpg_data['gpg']['hash'] data = gpg_data['gpg']['data'] - last_update = gpg_data['gpg']['last_update'] - if self.isAuthorized?(msg['password'], salt, hash) + if isAuthorized?(msg['password'], salt, hash) send_msg = {:action => 'get', :gpg_key => msg['gpg_key'], - :last_update => last_update, :msg => 'done', :data => data} else @@ -85,7 +83,6 @@ class Server else send_msg = {:action => 'get', :gpg_key => msg['gpg_key'], - :last_update => 0, :data => '', :msg => 'fail', :error => 'file_not_exist'} @@ -126,12 +123,10 @@ class Server hash = Digest::SHA256.hexdigest(salt + msg['password']) end - if self.isAuthorized?(msg['password'], salt, hash) + if isAuthorized?(msg['password'], salt, hash) begin - last_update = Time.now.to_i config = {'gpg' => {'salt' => salt, 'hash' => hash, - 'last_update' => last_update, 'data' => data}} File.open(file_gpg, 'w+') do |file| @@ -140,7 +135,6 @@ class Server send_msg = {:action => 'update', :gpg_key => msg['gpg_key'], - :last_update => last_update, :msg => 'done'} rescue Exception => e send_msg = {:action => 'update', @@ -183,7 +177,7 @@ class Server salt = gpg_data['gpg']['salt'] hash = gpg_data['gpg']['hash'] - if self.isAuthorized?(msg['password'], salt, hash) + if isAuthorized?(msg['password'], salt, hash) begin File.unlink(file_gpg) @@ -227,8 +221,7 @@ class Server msg = client.gets return JSON.parse(msg) rescue - client.puts "Communication it's bad" - self.closeConnection(client) + closeConnection(client) return false end end From 1a9fb0795053c7a03979e1991f70ecb5353b244c Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Wed, 15 Jan 2014 23:09:57 +0100 Subject: [PATCH 023/531] translate Sync.rb --- i18n/en.yml | 4 ++++ i18n/fr.yml | 4 ++++ lib/Sync.rb | 35 ++++++++++++++++++++++++++--------- 3 files changed, 34 insertions(+), 9 deletions(-) diff --git a/i18n/en.yml b/i18n/en.yml index a3141bf..76bce2a 100644 --- a/i18n/en.yml +++ b/i18n/en.yml @@ -17,6 +17,10 @@ en: read: "Can't import, unable to read %{file}!" update: name_empty: "You must define a name!" + sync: + no_data: "Nothing data!" + not_authorized: "You haven't the access to remote file!" + unknown: "An unknown error is occured!" cli: option: usage: "Usage" diff --git a/i18n/fr.yml b/i18n/fr.yml index 5ccef5f..aa847ed 100644 --- a/i18n/fr.yml +++ b/i18n/fr.yml @@ -17,6 +17,10 @@ fr: read: "Impossible d'importer le fichier %{file}, car il n'est pas lisible!" update: name_empty: "Vous devez définir un nom!" + sync: + no_data: "Aucune data!" + not_authorized: "Vous n'avez pas les autorisations d'accès au fichier distant!" + unknown: "Une erreur inconnue est survenue!" cli: option: usage: "Utilisation" diff --git a/lib/Sync.rb b/lib/Sync.rb index 126b02d..72743a3 100644 --- a/lib/Sync.rb +++ b/lib/Sync.rb @@ -14,30 +14,42 @@ class Sync attr_accessor :error_msg + # Constructor def initialize() @error_msg = nil end + # Disable the sync def disable() @sync = false end + # Connect to server + # @args: host -> the server host + # port -> ther connection port + # gpg_key -> the gpg key + # password -> the remote password + # suffix -> the suffix file + # @rtrn: false if the connection fail def connect(host, port, gpg_key, password, suffix=nil) - @gpg_key = gpg_key - @password = password - @suffix = suffix + @gpg_key = gpg_key + @password = password + @suffix = suffix begin @socket= TCPSocket.new(host, port) @sync = true rescue Exception => e - @error_msg = "ERROR: Connection impossible\n#{e}" + @error_msg = "#{I18n.t('error.sync.connection')}\n#{e}" @sync = false end return @sync end + # Get data on server + # @args: gpg_password -> the gpg password + # @rtrn: nil if nothing data or error def get(gpg_password) if !@sync return nil @@ -51,6 +63,7 @@ class Sync @socket.puts send_msg.to_json msg = JSON.parse(@socket.gets) + puts msg case msg['error'] when nil, 'file_not_exist' tmp_file = "/tmp/mpw-#{MPW.generatePassword()}.gpg" @@ -67,14 +80,17 @@ class Sync return @mpw.search() when 'not_authorized' - @error_msg = 'not authorized' + @error_msg = "#{I18n.t('error.sync.not_authorized')}\n#{e}" else - @error_msg = 'error unknow' + @error_msg = "#{I18n.t('error.sync.unknown')}\n#{e}" end return nil end + # Update the remote data + # @args: data -> the data to send on server + # @rtrn: false if there is a problem def update(data) if !@sync return true @@ -93,11 +109,11 @@ class Sync when nil return true when 'not_authorized' - @error_msg = 'not authorized' + @error_msg = "#{I18n.t('error.sync.not_authorized')}\n#{e}" when 'no_data' - @error_msg = 'no data' + @error_msg = "#{I18n.t('error.sync.no_data')}\n#{e}" else - @error_msg = 'error unknow' + @error_msg = "#{I18n.t('error.sync.unknown')}\n#{e}" end return false @@ -106,6 +122,7 @@ class Sync def delete() end + # Close the connection def close() if !@sync return From a77266daf70d76bdcdd0be0b86ec571311b68f82 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Wed, 15 Jan 2014 23:11:39 +0100 Subject: [PATCH 024/531] restruc the code --- lib/Cli.rb | 35 +++++++++++++++++++---------------- mpw | 23 ++++++++++++++++++----- 2 files changed, 37 insertions(+), 21 deletions(-) diff --git a/lib/Cli.rb b/lib/Cli.rb index ed28ca2..8e2976a 100644 --- a/lib/Cli.rb +++ b/lib/Cli.rb @@ -19,12 +19,8 @@ class Cli # Constructor # @args: lang -> the operating system language # config_file -> a specify config file - def initialize(lang, config_file=nil) - @config = MPWConfig.new(config_file) - - if not @config.checkconfig() - setup(lang) - end + def initialize(lang, config) + @config = config @mpw = MPW.new(@config.file_gpg, @config.key) if not decrypt() @@ -37,16 +33,23 @@ class Cli @sync.disable() elsif !@sync.connect(@config.sync_host, @config.sync_port, @config.key, @config.sync_pwd, @config.sync_suffix) puts "#{I18n.t('cli.sync.not_connect')}:\n#{@sync.error_msg}" - else - begin - @mpw.sync(@sync.get(@passwd), @config.last_update) - @sync.update(File.open(@config.file_gpg).read) - @config.setLastUpdate() - rescue Exception => e - puts "#{I18n.t('cli.sync.error')}:\n#{e}" - else - @sync.close() - end + end + end + + # Destructor + def finalize() + @sync.close() + end + + # Sync the data with the server + def sync() + begin + @mpw.sync(@sync.get(@passwd), @config.last_update) + @sync.update(File.open(@config.file_gpg).read) + @config.setLastUpdate() + puts @sync.error_msg + rescue Exception => e + puts "#{I18n.t('cli.sync.error')}:\n#{e}" end end diff --git a/mpw b/mpw index a313ed7..80f3344 100755 --- a/mpw +++ b/mpw @@ -93,13 +93,17 @@ OptionParser.new do |opts| end end.parse! +config = MPWConfig.new(options[:config]) +check_error = config.checkconfig() -cli = Cli.new(lang, options[:config]) +cli = Cli.new(lang, config) +cli.sync() + +# Setup a new config +if !check_error || !options[:setup].nil? + cli.setup(lang) # Display the item's informations -if not options[:setup].nil? - cli.setup() - elsif not options[:display].nil? cli.display(options[:display], options[:group], options[:type], options[:format]) @@ -125,7 +129,16 @@ elsif not options[:import].nil? # Interactive mode else - cli.interactive + begin + cli.interactive() + rescue SystemExit, Interrupt + cli.sync() + cli = nil + return 1 + end end +cli.sync() +cli = nil + exit 0 From ff15c3d6e79c809f129a58098318ec949c583566 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Wed, 15 Jan 2014 23:13:59 +0100 Subject: [PATCH 025/531] add translate for Sync.rb --- i18n/en.yml | 1 + i18n/fr.yml | 1 + 2 files changed, 2 insertions(+) diff --git a/i18n/en.yml b/i18n/en.yml index 76bce2a..933f3cd 100644 --- a/i18n/en.yml +++ b/i18n/en.yml @@ -18,6 +18,7 @@ en: update: name_empty: "You must define a name!" sync: + connection: "Connection fail!" no_data: "Nothing data!" not_authorized: "You haven't the access to remote file!" unknown: "An unknown error is occured!" diff --git a/i18n/fr.yml b/i18n/fr.yml index aa847ed..3423af1 100644 --- a/i18n/fr.yml +++ b/i18n/fr.yml @@ -18,6 +18,7 @@ fr: update: name_empty: "Vous devez définir un nom!" sync: + connection: "La connexion n'a pu être établie" no_data: "Aucune data!" not_authorized: "Vous n'avez pas les autorisations d'accès au fichier distant!" unknown: "Une erreur inconnue est survenue!" From e0c1f1bfc10f624ec98f4f51de5cab97060efad1 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Wed, 15 Jan 2014 23:16:49 +0100 Subject: [PATCH 026/531] add translate for Cli.rb --- i18n/en.yml | 2 ++ i18n/fr.yml | 2 ++ 2 files changed, 4 insertions(+) diff --git a/i18n/en.yml b/i18n/en.yml index 933f3cd..7805f04 100644 --- a/i18n/en.yml +++ b/i18n/en.yml @@ -104,6 +104,8 @@ en: port: "Port" protocol: "Protocol" server: "Server" + sync: + not_connect: "The server connection fail!" ssh: option: usage: "Usage" diff --git a/i18n/fr.yml b/i18n/fr.yml index 3423af1..9005238 100644 --- a/i18n/fr.yml +++ b/i18n/fr.yml @@ -104,6 +104,8 @@ fr: port: "Port" protocol: "Protocol" server: "Serveur" + sync: + not_connect: "La connexion au serveur n'a pu être établie!" ssh: option: usage: "Utilisation" From 1298caed2e43e6d970b190bd359ad565c32cc72f Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Wed, 15 Jan 2014 23:20:22 +0100 Subject: [PATCH 027/531] remove debug puts --- lib/Cli.rb | 1 - lib/Sync.rb | 1 - 2 files changed, 2 deletions(-) diff --git a/lib/Cli.rb b/lib/Cli.rb index 8e2976a..31c4a57 100644 --- a/lib/Cli.rb +++ b/lib/Cli.rb @@ -47,7 +47,6 @@ class Cli @mpw.sync(@sync.get(@passwd), @config.last_update) @sync.update(File.open(@config.file_gpg).read) @config.setLastUpdate() - puts @sync.error_msg rescue Exception => e puts "#{I18n.t('cli.sync.error')}:\n#{e}" end diff --git a/lib/Sync.rb b/lib/Sync.rb index 72743a3..0c3ed31 100644 --- a/lib/Sync.rb +++ b/lib/Sync.rb @@ -63,7 +63,6 @@ class Sync @socket.puts send_msg.to_json msg = JSON.parse(@socket.gets) - puts msg case msg['error'] when nil, 'file_not_exist' tmp_file = "/tmp/mpw-#{MPW.generatePassword()}.gpg" From e2839d136c8941a43b8ab83e4b097633bb5ab1c2 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Thu, 16 Jan 2014 21:24:08 +0100 Subject: [PATCH 028/531] clean error message with the server --- i18n/en.yml | 6 ++++++ i18n/fr.yml | 10 ++++++++-- lib/Server.rb | 49 ++++++++++++++++++++++--------------------------- lib/Sync.rb | 47 ++++++++++++++++++++++------------------------- 4 files changed, 58 insertions(+), 54 deletions(-) diff --git a/i18n/en.yml b/i18n/en.yml index 7805f04..22f2f7b 100644 --- a/i18n/en.yml +++ b/i18n/en.yml @@ -19,6 +19,7 @@ en: name_empty: "You must define a name!" sync: connection: "Connection fail!" + communication: "A communication problem with the server is appeared!" no_data: "Nothing data!" not_authorized: "You haven't the access to remote file!" unknown: "An unknown error is occured!" @@ -117,6 +118,11 @@ en: connect: "Connection to:" nothing: "Nothing result!" server: + error: + client: + unknown: "An unknown error is appeared!" + no_authorized: "You haven't access to remote file!" + no_data: "Nothing data has been sent!" option: usage: "Usage" config: "Specifie the configuration file" diff --git a/i18n/fr.yml b/i18n/fr.yml index 9005238..b14aa99 100644 --- a/i18n/fr.yml +++ b/i18n/fr.yml @@ -18,8 +18,9 @@ fr: update: name_empty: "Vous devez définir un nom!" sync: - connection: "La connexion n'a pu être établie" - no_data: "Aucune data!" + connection: "La connexion n'a pu être établie!" + communication: "Un problème de communication avec le serveur est apparu!" + no_data: "Aucune donnée!" not_authorized: "Vous n'avez pas les autorisations d'accès au fichier distant!" unknown: "Une erreur inconnue est survenue!" cli: @@ -117,6 +118,11 @@ fr: connect: "Connexion à:" nothing: "Aucun résultat!" server: + error: + client: + unknown: "Une erreur inconnue est apparue!" + no_authorized: "Vous n'avez pas les accès au fichier distant!" + no_data: "Aucune donnée n'a été transmise!" option: usage: "Utilisation" config: "Spécifie le fichier de configuration" diff --git a/lib/Server.rb b/lib/Server.rb index 5b76de7..267105f 100644 --- a/lib/Server.rb +++ b/lib/Server.rb @@ -43,7 +43,10 @@ class Server when 'close' closeConnection(client) else - client.puts 'Unknown command' + send_msg = {:action => 'unknown', + :gpg_key => msg['gpg_key'], + :error => 'server.error.client.unknown'} + client.puts send_msg closeConnection(client) end end @@ -72,20 +75,18 @@ class Server if isAuthorized?(msg['password'], salt, hash) send_msg = {:action => 'get', :gpg_key => msg['gpg_key'], - :msg => 'done', - :data => data} + :data => data, + :error => nil} else send_msg = {:action => 'get', :gpg_key => msg['gpg_key'], - :msg => 'fail', - :error => 'not_authorized'} + :error => 'server.error.client.no_authorized'} end else - send_msg = {:action => 'get', - :gpg_key => msg['gpg_key'], - :data => '', - :msg => 'fail', - :error => 'file_not_exist'} + send_msg = {:action => 'get', + :gpg_key => msg['gpg_key'], + :data => '', + :error => nil} end return send_msg.to_json @@ -101,8 +102,7 @@ class Server if data.nil? || data.empty? send_msg = {:action => 'update', :gpg_key => msg['gpg_key'], - :msg => 'fail', - :error => 'no_data'} + :error => 'server.error.client.no_data'} return send_msg.to_json end @@ -133,20 +133,18 @@ class Server file << config.to_yaml end - send_msg = {:action => 'update', - :gpg_key => msg['gpg_key'], - :msg => 'done'} + send_msg = {:action => 'update', + :gpg_key => msg['gpg_key'], + :error => nil} rescue Exception => e send_msg = {:action => 'update', :gpg_key => msg['gpg_key'], - :msg => 'fail', - :error => 'server_error'} + :error => 'server.error.client.unknown'} end else send_msg = {:action => 'update', :gpg_key => msg['gpg_key'], - :msg => 'fail', - :error => 'not_autorized'} + :error => 'server.error.client.no_authorized'} end return send_msg.to_json @@ -167,8 +165,7 @@ class Server if !File.exist?(file_gpg) send_msg = {:action => 'delete', :gpg_key => msg['gpg_key'], - :msg => 'delete_fail', - :error => 'file_not_exist'} + :error => nil} return send_msg.to_json end @@ -183,18 +180,16 @@ class Server send_msg = {:action => 'delete', :gpg_key => msg['gpg_key'], - :msg => 'delete_done'} + :error => nil} rescue Exception => e send_msg = {:action => 'delete', :gpg_key => msg['gpg_key'], - :msg => 'delete_fail', - :error => e} + :error => 'server.error.client.unknown'} end else send_msg = {:action => 'delete', :gpg_key => msg['gpg_key'], - :msg => 'delete_fail', - :error => 'not_autorized'} + :error => 'server.error.client.no_authorized'} end return send_msg.to_json @@ -285,7 +280,7 @@ class Server file << config.to_yaml end rescue Exception => e - puts "#{I18n.t('server.formsetup.not_valid')}\n#{e}" + puts "#{I18n.t('server.form.setup.not_valid')}\n#{e}" return false end diff --git a/lib/Sync.rb b/lib/Sync.rb index 0c3ed31..a02a08d 100644 --- a/lib/Sync.rb +++ b/lib/Sync.rb @@ -55,16 +55,18 @@ class Sync return nil end - send_msg = {:action => 'get', - :gpg_key => @gpg_key, - :password => @password, - :suffix => @suffix} + send_msg = {:action => 'get', + :gpg_key => @gpg_key, + :password => @password, + :suffix => @suffix} @socket.puts send_msg.to_json msg = JSON.parse(@socket.gets) - case msg['error'] - when nil, 'file_not_exist' + if !msg['error'] + @error_msg = I18n.t('error.sync.communication') + return nil + elsif msg['error'].nil? tmp_file = "/tmp/mpw-#{MPW.generatePassword()}.gpg" File.open(tmp_file, 'w') do |file| file << msg['data'] @@ -76,15 +78,12 @@ class Sync end File.unlink(tmp_file) - return @mpw.search() - when 'not_authorized' - @error_msg = "#{I18n.t('error.sync.not_authorized')}\n#{e}" else - @error_msg = "#{I18n.t('error.sync.unknown')}\n#{e}" + @error_msg = I18n.t(msg['error']) + return nil end - return nil end # Update the remote data @@ -95,29 +94,27 @@ class Sync return true end - send_msg = {:action => 'update', - :gpg_key => @gpg_key, - :password => @password, - :suffix => @suffix, - :data => data} + send_msg = {:action => 'update', + :gpg_key => @gpg_key, + :password => @password, + :suffix => @suffix, + :data => data} @socket.puts send_msg.to_json msg = JSON.parse(@socket.gets) - case msg['error'] - when nil + if !msg['error'] + @error_msg = I18n.t('error.sync.communication') + return false + elsif msg['error'].nil? return true - when 'not_authorized' - @error_msg = "#{I18n.t('error.sync.not_authorized')}\n#{e}" - when 'no_data' - @error_msg = "#{I18n.t('error.sync.no_data')}\n#{e}" else - @error_msg = "#{I18n.t('error.sync.unknown')}\n#{e}" + @error_msg = I18n.t(msg['error']) + return false end - - return false end + # TODO def delete() end From 8c1e2f5e872dab10d16166b1f714ed554a609c99 Mon Sep 17 00:00:00 2001 From: adrien <adrien.waksberg@believedigital.com> Date: Thu, 16 Jan 2014 22:50:54 +0100 Subject: [PATCH 029/531] fix bug with update --- lib/MPW.rb | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/lib/MPW.rb b/lib/MPW.rb index 6886b85..630df2f 100644 --- a/lib/MPW.rb +++ b/lib/MPW.rb @@ -147,7 +147,7 @@ class MPW row_update = Array.new() row_update[DATE] = Time.now.to_i - id.nil? || id.empty? ? (row_update[ID] = MPW.generatePassword(16)) : (row_update[ID] = row[ID]) + id.nil? || id.empty? ? (row_update[ID] = MPW.generatePassword(16)) : (row_update[ID] = id) name.nil? || name.empty? ? (row_update[NAME] = row[NAME]) : (row_update[NAME] = name) group.nil? || group.empty? ? (row_update[GROUP] = row[GROUP]) : (row_update[GROUP] = group) server.nil? || server.empty? ? (row_update[SERVER] = row[SERVER]) : (row_update[SERVER] = server) @@ -298,9 +298,7 @@ class MPW end end - encrypt() - - return true + return encrypt() end # Generate a random password From 77412b4794fe0d6b779693c5e14fef300bfbd8c9 Mon Sep 17 00:00:00 2001 From: adrien <adrien.waksberg@believedigital.com> Date: Thu, 16 Jan 2014 23:29:39 +0100 Subject: [PATCH 030/531] fix bug encoding --- lib/MPW.rb | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/MPW.rb b/lib/MPW.rb index 630df2f..0f2daf6 100644 --- a/lib/MPW.rb +++ b/lib/MPW.rb @@ -157,6 +157,14 @@ class MPW port.nil? || port.empty? ? (row_update[PORT] = row[PORT]) : (row_update[PORT] = port) comment.nil? || comment.empty? ? (row_update[COMMENT] = row[COMMENT]) : (row_update[COMMENT] = comment) + row_update[NAME].nil? ? (row_update[NAME] = row_update[NAME]) : (row_update[NAME] = row_update[NAME].force_encoding('ASCII-8BIT')) + row_update[GROUP].nil? ? (row_update[GROUP] = row_update[GROUP]) : (row_update[GROUP] = row_update[GROUP].force_encoding('ASCII-8BIT')) + row_update[SERVER].nil? ? (row_update[SERVER] = row_update[SERVER]) : (row_update[SERVER] = row_update[SERVER].force_encoding('ASCII-8BIT')) + row_update[PROTOCOL].nil? ? (row_update[PROTOCOL] = row_update[PROTOCOL]) : (row_update[PROTOCOL] = row_update[PROTOCOL].force_encoding('ASCII-8BIT')) + row_update[LOGIN].nil? ? (row_update[LOGIN] = row_update[LOGIN]) : (row_update[LOGIN] = row_update[LOGIN].force_encoding('ASCII-8BIT')) + row_update[PASSWORD].nil? ? (row_update[PASSWORD] = row_update[PASSWORD]) : (row_update[PASSWORD] = row_update[PASSWORD].force_encoding('ASCII-8BIT')) + row_update[COMMENT].nil? ? (row_update[COMMENT] = row_update[COMMENT]) : (row_update[COMMENT] = row_update[COMMENT].force_encoding('ASCII-8BIT')) + if row_update[NAME].nil? || row_update[NAME].empty? @error_msg = I18n.t('error.update.name_empty') return false From 2199e8cf8a4bba39fe624a4a03f60a8d4def8d2b Mon Sep 17 00:00:00 2001 From: adrien <adrien.waksberg@believedigital.com> Date: Thu, 16 Jan 2014 23:33:40 +0100 Subject: [PATCH 031/531] fix check error message --- lib/Sync.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/Sync.rb b/lib/Sync.rb index a02a08d..2fa8ec7 100644 --- a/lib/Sync.rb +++ b/lib/Sync.rb @@ -63,7 +63,7 @@ class Sync @socket.puts send_msg.to_json msg = JSON.parse(@socket.gets) - if !msg['error'] + if !defined?(msg['error']) @error_msg = I18n.t('error.sync.communication') return nil elsif msg['error'].nil? @@ -74,6 +74,7 @@ class Sync @mpw = MPW.new(tmp_file) if !@mpw.decrypt(gpg_password) + puts @mpw.error_msg return nil end @@ -103,7 +104,7 @@ class Sync @socket.puts send_msg.to_json msg = JSON.parse(@socket.gets) - if !msg['error'] + if !defined?(msg['error']) @error_msg = I18n.t('error.sync.communication') return false elsif msg['error'].nil? From 352bc24f1a37158af9e742b1ea580104664c623d Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Thu, 23 Jan 2014 22:32:48 +0100 Subject: [PATCH 032/531] fix bug in mpw-ssh since add sync --- lib/CliSSH.rb | 2 +- mpw-ssh | 22 ++++++++++++++++------ 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/lib/CliSSH.rb b/lib/CliSSH.rb index 7e7d00b..7fba1ad 100644 --- a/lib/CliSSH.rb +++ b/lib/CliSSH.rb @@ -12,7 +12,7 @@ class CliSSH < Cli # Connect to SSH # args: search -> string to search def ssh(search) - result = @m.search(search, nil, 'ssh') + result = @mpw.search(search, nil, 'ssh') if result.length > 0 result.each do |r| diff --git a/mpw-ssh b/mpw-ssh index a991cc1..168803f 100755 --- a/mpw-ssh +++ b/mpw-ssh @@ -39,20 +39,30 @@ OptionParser.new do |opts| options[:config] = config end - opts.on("-h", "--help", I18n.t('ssh.option.help')) do |b| + opts.on("-h", "--help", I18n.t('ssh.option.help')) do puts opts exit 0 end end.parse! -cli = CliSSH.new(lang, options[:config]) -cli.login = options[:login] -cli.server = options[:server] -cli.port = options[:port] +config = MPWConfig.new(options[:config]) +check_error = config.checkconfig() + +cli = CliSSH.new(lang, config) +cli.login = options[:login] +cli.server = options[:server] +cli.port = options[:port] search = ARGV[0] -if ARGV.length < 1 +cli.sync() + +# Setup a new config +if !check_error + cli.setup(lang) + +# Connect ssh +elsif ARGV.length < 1 puts "#{I18n.t('ssh.option.usage')}: mpw-ssh SEARCH [options]" exit 2 end From c654dac5326203f9aa8a0fa1995c6a02fdbfcfb4 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Thu, 23 Jan 2014 22:40:16 +0100 Subject: [PATCH 033/531] close connection --- mpw-ssh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mpw-ssh b/mpw-ssh index 168803f..a517e9e 100755 --- a/mpw-ssh +++ b/mpw-ssh @@ -61,12 +61,12 @@ cli.sync() if !check_error cli.setup(lang) -# Connect ssh elsif ARGV.length < 1 puts "#{I18n.t('ssh.option.usage')}: mpw-ssh SEARCH [options]" exit 2 end cli.ssh(search) +cli = nil exit 0 From 66f07e907cda5140abd4bf318c52aa2e80e3b2f4 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Thu, 23 Jan 2014 23:04:13 +0100 Subject: [PATCH 034/531] fix when sync with the server --- lib/Cli.rb | 20 +++++++++++++++++--- mpw | 3 --- mpw-ssh | 5 ++--- 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/lib/Cli.rb b/lib/Cli.rb index 31c4a57..d68ac04 100644 --- a/lib/Cli.rb +++ b/lib/Cli.rb @@ -34,6 +34,8 @@ class Cli elsif !@sync.connect(@config.sync_host, @config.sync_port, @config.key, @config.sync_pwd, @config.sync_suffix) puts "#{I18n.t('cli.sync.not_connect')}:\n#{@sync.error_msg}" end + + sync() end # Destructor @@ -44,9 +46,17 @@ class Cli # Sync the data with the server def sync() begin - @mpw.sync(@sync.get(@passwd), @config.last_update) - @sync.update(File.open(@config.file_gpg).read) - @config.setLastUpdate() + if !@mpw.sync(@sync.get(@passwd), @config.last_update) + puts "#{I18n.t('cli.display.error')}: #{@mpw.error_msg}" + end + + if !@sync.update(File.open(@config.file_gpg).read) + puts "#{I18n.t('cli.display.error')}: #{@sync.error_msg}" + end + + if !@config.setLastUpdate() + puts "#{I18n.t('cli.display.error')}: #{@config.error_msg}" + end rescue Exception => e puts "#{I18n.t('cli.sync.error')}:\n#{e}" end @@ -150,6 +160,7 @@ class Cli if @mpw.update(name, group, server, protocol, login, passwd, port, comment) if @mpw.encrypt() + sync() puts I18n.t('cli.form.add.valid') else puts "#{I18n.t('cli.display.error')}: #{@mpw.error_msg}" @@ -178,6 +189,7 @@ class Cli if @mpw.update(name, group, server, protocol, login, passwd, port, comment, id) if @mpw.encrypt() + sync() puts I18n.t('cli.form.update.valid') else puts "#{I18n.t('cli.display.error')}: #{@mpw.error_msg}" @@ -212,6 +224,7 @@ class Cli if force if @mpw.remove(id) if @mpw.encrypt() + sync() puts I18n.t('cli.form.delete.valid', :id => id) else puts "#{I18n.t('cli.display.error')}: #{@mpw.error_msg}" @@ -256,6 +269,7 @@ class Cli if force if @mpw.import(file) && @mpw.encrypt() + sync() puts I18n.t('cli.form.import.valid') else puts "#{I18n.t('cli.display.error')}: #{@mpw.error_msg}" diff --git a/mpw b/mpw index 80f3344..f6660f6 100755 --- a/mpw +++ b/mpw @@ -97,7 +97,6 @@ config = MPWConfig.new(options[:config]) check_error = config.checkconfig() cli = Cli.new(lang, config) -cli.sync() # Setup a new config if !check_error || !options[:setup].nil? @@ -132,13 +131,11 @@ else begin cli.interactive() rescue SystemExit, Interrupt - cli.sync() cli = nil return 1 end end -cli.sync() cli = nil exit 0 diff --git a/mpw-ssh b/mpw-ssh index a517e9e..aa0e80a 100755 --- a/mpw-ssh +++ b/mpw-ssh @@ -55,8 +55,6 @@ cli.port = options[:port] search = ARGV[0] -cli.sync() - # Setup a new config if !check_error cli.setup(lang) @@ -64,9 +62,10 @@ if !check_error elsif ARGV.length < 1 puts "#{I18n.t('ssh.option.usage')}: mpw-ssh SEARCH [options]" exit 2 +else + cli.ssh(search) end -cli.ssh(search) cli = nil exit 0 From 961117338cca5217965abfb879f6d5991f43c5f5 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sat, 25 Jan 2014 11:35:12 +0100 Subject: [PATCH 035/531] add log on server --- lib/Server.rb | 44 ++++++++++++++++++++++++++++++++++++++++++-- mpw-server | 5 +++-- 2 files changed, 45 insertions(+), 4 deletions(-) diff --git a/lib/Server.rb b/lib/Server.rb index 267105f..83d6b19 100644 --- a/lib/Server.rb +++ b/lib/Server.rb @@ -4,11 +4,17 @@ require 'socket' require 'json' require 'highline/import' require 'digest' +require 'logger' require "#{APP_ROOT}/lib/MPW.rb" class Server + INFO = 0 + WARNING = 1 + ERROR = 2 + DEBUG = 3 + attr_accessor :error_msg # Constructor @@ -18,9 +24,18 @@ class Server # Start the server def start() - server = TCPServer.open(@host, @port) + begin + server = TCPServer.open(@host, @port) + @log.info("The server is started on #{@host}:#{@port}") + rescue Exception => e + @log.error("Impossible to start the server: #{e}") + exit 2 + end + loop do Thread.start(server.accept) do |client| + @log.info("#{client.peeraddr[3]} is connected") + while true do msg = getClientMessage(client) @@ -35,14 +50,19 @@ class Server case msg['action'] when 'get' + @log.debug("#{client.peeraddr[3]} GET gpg_key=#{msg['gpg_key']} suffix=#{msg['suffix']}") client.puts getFile(msg) when 'update' + @log.debug("#{client.peeraddr[3]} UPDATE gpg_key=#{msg['gpg_key']} suffix=#{msg['suffix']}") client.puts updateFile(msg) when 'delete' + @log.debug("#{client.peeraddr[3]} DELETE gpg_key=#{msg['gpg_key']} suffix=#{msg['suffix']}") client.puts deleteFile(msg) when 'close' + @log.info("#{client.peeraddr[3]} is disconnected") closeConnection(client) else + @log.warning("#{client.peeraddr[3]} is disconnected for unkwnow command") send_msg = {:action => 'unknown', :gpg_key => msg['gpg_key'], :error => 'server.error.client.unknown'} @@ -237,6 +257,7 @@ class Server @host = config['config']['host'] @port = config['config']['port'].to_i @data_dir = config['config']['data_dir'] + @log_file = config['config']['log_file'] @timeout = config['config']['timeout'].to_i if @host.empty? || @port <= 0 || @data_dir.empty? @@ -251,6 +272,24 @@ class Server return false end + if @log_file.nil? || @log_file.empty? + puts I18n.t('server.checkconfig.fail') + puts I18n.t('server.checkconfig.log_file_empty') + return false + #elsif !File.writable?(@log_file) + # puts I18n.t('server.checkconfig.fail') + # puts I18n.t('server.checkconfig.log_file_ro') + # return false + else + begin + @log = Logger.new(@log_file) + rescue + puts I18n.t('server.checkconfig.fail') + puts I18n.t('server.checkconfig.log_file_create') + return false + end + end + rescue Exception => e puts "#{I18n.t('server.checkconfig.fail')}\n#{e}" return false @@ -268,11 +307,13 @@ class Server host = ask(I18n.t('server.form.setup.host')).to_s port = ask(I18n.t('server.form.setup.port')).to_s data_dir = ask(I18n.t('server.form.setup.data_dir')).to_s + log_file = ask(I18n.t('server.form.setup.log_file')).to_s timeout = ask(I18n.t('server.form.setup.timeout')).to_s config = {'config' => {'host' => host, 'port' => port, 'data_dir' => data_dir, + 'log_file' => log_file, 'timeout' => timeout}} begin @@ -286,5 +327,4 @@ class Server return true end - end diff --git a/mpw-server b/mpw-server index 3143b59..016cebf 100755 --- a/mpw-server +++ b/mpw-server @@ -53,8 +53,9 @@ if options[:checkconfig] elsif options[:setup] server.setup(options[:config]) else - server.checkconfig(options[:config]) - server.start() + if server.checkconfig(options[:config]) + server.start() + end end exit 0 From d65316896e38e68e577de3836ad2ab0d9d281434 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sat, 25 Jan 2014 16:53:48 +0100 Subject: [PATCH 036/531] add sync information in cli setup --- lib/Cli.rb | 46 +++++++++++++++++++++++++++++----------------- lib/MPWConfig.rb | 20 +++++++++++++------- mpw | 6 +++++- 3 files changed, 47 insertions(+), 25 deletions(-) diff --git a/lib/Cli.rb b/lib/Cli.rb index d68ac04..03c7595 100644 --- a/lib/Cli.rb +++ b/lib/Cli.rb @@ -21,21 +21,6 @@ class Cli # config_file -> a specify config file def initialize(lang, config) @config = config - - @mpw = MPW.new(@config.file_gpg, @config.key) - if not decrypt() - puts "#{I18n.t('cli.display.error')}: #{@mpw.error_msg}" - exit 2 - end - - @sync = Sync.new() - if @config.sync_host.nil? || @config.sync_port.nil? - @sync.disable() - elsif !@sync.connect(@config.sync_host, @config.sync_port, @config.key, @config.sync_pwd, @config.sync_suffix) - puts "#{I18n.t('cli.sync.not_connect')}:\n#{@sync.error_msg}" - end - - sync() end # Destructor @@ -45,6 +30,16 @@ class Cli # Sync the data with the server def sync() + if !defined?(@sync) + @sync = Sync.new() + + if @config.sync_host.nil? || @config.sync_port.nil? + @sync.disable() + elsif !@sync.connect(@config.sync_host, @config.sync_port, @config.key, @config.sync_pwd, @config.sync_suffix) + puts "#{I18n.t('cli.sync.not_connect')}:\n#{@sync.error_msg}" + end + end + begin if !@mpw.sync(@sync.get(@passwd), @config.last_update) puts "#{I18n.t('cli.display.error')}: #{@mpw.error_msg}" @@ -71,13 +66,22 @@ class Cli key = ask(I18n.t('cli.form.setup.gpg_key')).to_s file_gpg = ask(I18n.t('cli.form.setup.gpg_file', :home => Dir.home())).to_s timeout_pwd = ask(I18n.t('cli.form.setup.timeout')).to_s + sync_host = ask(I18n.t('cli.form.setup.sync_host')).to_s + sync_port = ask(I18n.t('cli.form.setup.sync_port')).to_s + sync_pwd = ask(I18n.t('cli.form.setup.sync_pwd')).to_s + sync_suffix = ask(I18n.t('cli.form.setup.sync_suffix')).to_s if !File.exist?("#{APP_ROOT}/i18n/#{language}.yml") language= 'en' end I18n.locale = language.to_sym - if @config.setup(key, language, file_gpg, timeout_pwd) + sync_host.empty? ? (sync_host = nil) : (sync_host = sync_host) + sync_port.empty? ? (sync_port = nil) : (sync_port = sync_port.to_i) + sync_pwd.empty? ? (sync_pwd = nil) : (sync_pwd = sync_pwd) + sync_suffix.empty? ? (sync_suffix = nil) : (sync_suffix = sync_suffix) + + if @config.setup(key, language, file_gpg, timeout_pwd, sync_host, sync_port, sync_pwd, sync_suffix) puts I18n.t('cli.form.setup.valid') else puts "#{I18n.t('cli.display.error')}: #{@config.error_msg}" @@ -85,13 +89,21 @@ class Cli if not @config.checkconfig() puts "#{I18n.t('cli.display.error')}: #{@config.error_msg}" + exit 2 end end # Request the GPG password and decrypt the file def decrypt() + if !defined?(@mpw) + @mpw = MPW.new(@config.file_gpg, @config.key) + end + @passwd = ask(I18n.t('cli.display.gpg_password')) {|q| q.echo = false} - return @mpw.decrypt(@passwd) + if !@mpw.decrypt(@passwd) + puts "#{I18n.t('cli.display.error')}: #{@mpw.error_msg}" + exit 2 + end end # Display the query's result diff --git a/lib/MPWConfig.rb b/lib/MPWConfig.rb index d68d0c7..6362b4c 100644 --- a/lib/MPWConfig.rb +++ b/lib/MPWConfig.rb @@ -37,9 +37,13 @@ class MPWConfig # @args: key -> the gpg key to encrypt # lang -> the software language # file_gpg -> the file who is encrypted - # timeout_pwd -> time to save the password + # timeout_pwd -> time to save the password + # sync_host -> the server host for synchronization + # sync_port -> the server port for synchronization + # sync_pwd -> the password for synchronization + # sync_suffix -> the suffix file (optionnal) # @rtrn: true if le config file is create - def setup(key, lang, file_gpg, timeout_pwd) + def setup(key, lang, file_gpg, timeout_pwd, sync_host=nil, sync_port=nil, sync_pwd=nil, sync_suffix=nil) if not key =~ /[a-zA-Z0-9.-_]+\@[a-zA-Z0-9]+\.[a-zA-Z]+/ @error_msg = I18n.t('error.config.key_bad_format') @@ -56,10 +60,10 @@ class MPWConfig 'lang' => lang, 'file_gpg' => file_gpg, 'timeout_pwd' => timeout_pwd, - 'sync_host' => host, - 'sync_port' => port, - 'sync_pwd' => password, - 'sync_suffix' => suffix, + 'sync_host' => sync_host, + 'sync_port' => sync_port, + 'sync_pwd' => sync_pwd, + 'sync_suffix' => sync_suffix, 'last_update' => 0 }} begin @@ -86,7 +90,7 @@ class MPWConfig @sync_host = config['config']['sync_host'] @sync_port = config['config']['sync_port'] @sync_pwd = config['config']['sync_pwd'] - @sync_suffix = config['config']['sync_suffix'] + @sync_suffix = config['config']['sync_suffix'] @last_update = config['config']['last_update'].to_i if @key.empty? || @file_gpg.empty? @@ -104,6 +108,8 @@ class MPWConfig return true end + # Set the last update when there is a sync + # @rtrn: true is the file has been updated def setLastUpdate() config = {'config' => {'key' => @key, 'lang' => @lang, diff --git a/mpw b/mpw index f6660f6..e1f0569 100755 --- a/mpw +++ b/mpw @@ -101,9 +101,13 @@ cli = Cli.new(lang, config) # Setup a new config if !check_error || !options[:setup].nil? cli.setup(lang) +end + +cli.decrypt() +cli.sync() # Display the item's informations -elsif not options[:display].nil? +if not options[:display].nil? cli.display(options[:display], options[:group], options[:type], options[:format]) # Remove an item From 445626c7a2abc49652df3652bd6b63e7a4484c0b Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sat, 25 Jan 2014 18:40:47 +0100 Subject: [PATCH 037/531] separate server translation --- i18n/server/en.yml | 25 +++++++++++++++++++++++++ i18n/server/fr.yml | 25 +++++++++++++++++++++++++ lib/Server.rb | 36 ++++++++++++++++-------------------- mpw-server | 14 +++++++------- 4 files changed, 73 insertions(+), 27 deletions(-) create mode 100644 i18n/server/en.yml create mode 100644 i18n/server/fr.yml diff --git a/i18n/server/en.yml b/i18n/server/en.yml new file mode 100644 index 0000000..b3fc13c --- /dev/null +++ b/i18n/server/en.yml @@ -0,0 +1,25 @@ +--- +en: + option: + usage: "Usage" + config: "Specifie the configuration file" + checkconfig: "Check the configuration" + setup: "Setup a new configuration file" + help: "Show this message help" + checkconfig: + fail: "Checkconfig failed:!" + empty: "ERROR: an importe option is missing!" + datadir: "ERROR: le data directory doesn't exist!" + form: + setup: + title: "Serveur configuration" + host: "IP listen: " + port: "Port listen: " + data_dir: "Data directory: " + timeout: "Timeout to second: " + not_valid: "ERROR: Impossible to write the configuration file!" + formats: + default: ! '%Y-%m-%d' + long: ! '%B %d, %Y' + short: ! '%b %d' + custom: ! '%A, %M %B, %Y @ %l:%M%P' diff --git a/i18n/server/fr.yml b/i18n/server/fr.yml new file mode 100644 index 0000000..962ac44 --- /dev/null +++ b/i18n/server/fr.yml @@ -0,0 +1,25 @@ +--- +fr: + option: + usage: "Utilisation" + config: "Spécifie le fichier de configuration" + checkconfig: "Vérifie le fichier de configuration" + setup: "Permet de générer un nouveau fichier de configuration" + help: "Affiche ce message d'aide" + checkconfig: + fail: "Le fichier de configuration est invalide!" + empty: "ERREUR: Une option importante est manquante!" + datadir: "ERREUR: Le répertoire des données n'existe pas!" + form: + setup: + title: "Configuration du serveur" + host: "IP d'écoute: " + port: "Port d'écoute: " + data_dir: "Répertoire des données: " + timeout: "Timeout en seconde: " + not_valid: "ERREUR: Impossible d'écire le fichier de configuration!" + formats: + default: ! '%Y-%m-%d' + long: ! '%B %d, %Y' + short: ! '%b %d' + custom: ! '%A, %M %B, %Y @ %l:%M%P' diff --git a/lib/Server.rb b/lib/Server.rb index 83d6b19..7c617b8 100644 --- a/lib/Server.rb +++ b/lib/Server.rb @@ -261,37 +261,33 @@ class Server @timeout = config['config']['timeout'].to_i if @host.empty? || @port <= 0 || @data_dir.empty? - puts I18n.t('server.checkconfig.fail') - puts I18n.t('server.checkconfig.empty') + puts I18n.t('checkconfig.fail') + puts I18n.t('checkconfig.empty') return false end if !Dir.exist?(@data_dir) - puts I18n.t('server.checkconfig.fail') - puts I18n.t('server.checkconfig.datadir') + puts I18n.t('checkconfig.fail') + puts I18n.t('checkconfig.datadir') return false end if @log_file.nil? || @log_file.empty? - puts I18n.t('server.checkconfig.fail') - puts I18n.t('server.checkconfig.log_file_empty') + puts I18n.t('checkconfig.fail') + puts I18n.t('checkconfig.log_file_empty') return false - #elsif !File.writable?(@log_file) - # puts I18n.t('server.checkconfig.fail') - # puts I18n.t('server.checkconfig.log_file_ro') - # return false else begin @log = Logger.new(@log_file) rescue - puts I18n.t('server.checkconfig.fail') - puts I18n.t('server.checkconfig.log_file_create') + puts I18n.t('checkconfig.fail') + puts I18n.t('checkconfig.log_file_create') return false end end rescue Exception => e - puts "#{I18n.t('server.checkconfig.fail')}\n#{e}" + puts "#{I18n.t('checkconfig.fail')}\n#{e}" return false end @@ -302,13 +298,13 @@ class Server # @args: file_config -> the configuration file # @rtrn: true if le config file is create def setup(file_config) - puts I18n.t('server.form.setup.title') + puts I18n.t('form.setup.title') puts '--------------------' - host = ask(I18n.t('server.form.setup.host')).to_s - port = ask(I18n.t('server.form.setup.port')).to_s - data_dir = ask(I18n.t('server.form.setup.data_dir')).to_s - log_file = ask(I18n.t('server.form.setup.log_file')).to_s - timeout = ask(I18n.t('server.form.setup.timeout')).to_s + host = ask(I18n.t('form.setup.host')).to_s + port = ask(I18n.t('form.setup.port')).to_s + data_dir = ask(I18n.t('form.setup.data_dir')).to_s + log_file = ask(I18n.t('form.setup.log_file')).to_s + timeout = ask(I18n.t('form.setup.timeout')).to_s config = {'config' => {'host' => host, 'port' => port, @@ -321,7 +317,7 @@ class Server file << config.to_yaml end rescue Exception => e - puts "#{I18n.t('server.form.setup.not_valid')}\n#{e}" + puts "#{I18n.t('form.setup.not_valid')}\n#{e}" return false end diff --git a/mpw-server b/mpw-server index 016cebf..07b42f5 100755 --- a/mpw-server +++ b/mpw-server @@ -15,34 +15,34 @@ require "#{APP_ROOT}/lib/Server.rb" lang = Locale::Tag.parse(ENV['LANG']).to_simple.to_s[0..1] I18n::Backend::Simple.send(:include, I18n::Backend::Fallbacks) -I18n.load_path = Dir["#{APP_ROOT}/i18n/*.yml"] +I18n.load_path = Dir["#{APP_ROOT}/i18n/server/*.yml"] I18n.default_locale = :en I18n.locale = lang.to_sym options = {} OptionParser.new do |opts| - opts.banner = "#{I18n.t('server.option.usage')}: mpw-server -c CONFIG [options]" + opts.banner = "#{I18n.t('option.usage')}: mpw-server -c CONFIG [options]" - opts.on("-c", "--config CONFIG", I18n.t('server.option.config')) do |config| + opts.on("-c", "--config CONFIG", I18n.t('option.config')) do |config| options[:config] = config end - opts.on("-t", "--checkconfig", I18n.t('server.option.checkconfig')) do |b| + opts.on("-t", "--checkconfig", I18n.t('option.checkconfig')) do |b| options[:checkconfig] = b end - opts.on("-s", "--setup", I18n.t('server.option.setup')) do |b| + opts.on("-s", "--setup", I18n.t('option.setup')) do |b| options[:setup] = b end - opts.on("-h", "--help", I18n.t('server.option.help')) do |b| + opts.on("-h", "--help", I18n.t('option.help')) do |b| puts opts exit 0 end end.parse! if options[:config].nil? || options[:config].empty? - puts "#{I18n.t('server.option.usage')}: mpw-server -c CONFIG [options]" + puts "#{I18n.t('option.usage')}: mpw-server -c CONFIG [options]" exit 2 end From 1400cf78346d92fc8381374723555f14a7763488 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sun, 26 Jan 2014 11:39:53 +0100 Subject: [PATCH 038/531] separate cli translate --- i18n/cli/en.yml | 121 ++++++++++++++++++++++++++++++++++++++ i18n/cli/fr.yml | 121 ++++++++++++++++++++++++++++++++++++++ i18n/en.yml | 148 ----------------------------------------------- i18n/fr.yml | 148 ----------------------------------------------- lib/Cli.rb | 150 ++++++++++++++++++++++++------------------------ mpw | 34 +++++------ 6 files changed, 334 insertions(+), 388 deletions(-) create mode 100644 i18n/cli/en.yml create mode 100644 i18n/cli/fr.yml delete mode 100644 i18n/en.yml delete mode 100644 i18n/fr.yml diff --git a/i18n/cli/en.yml b/i18n/cli/en.yml new file mode 100644 index 0000000..dc76087 --- /dev/null +++ b/i18n/cli/en.yml @@ -0,0 +1,121 @@ +--- +en: + error: + config: + write: "Can't write the config file!" + check: "Checkconfig failed!" + key_bad_format: "The key string isn't in good format!" + delete: + id_no_exist: "Can't delete the item %{id}, it doesn't exist!" + export: + write: "Can't export, unable to write in %{file}!" + gpg_file: + decrypt: "Can't decrypt file!" + encrypt: "Can't encrypt the GPG file!" + import: + bad_format: "Can't import, the file is badly formated!" + read: "Can't import, unable to read %{file}!" + update: + name_empty: "You must define a name!" + sync: + connection: "Connection fail!" + communication: "A communication problem with the server is appeared!" + no_data: "Nothing data!" + not_authorized: "You haven't the access to remote file!" + unknown: "An unknown error is occured!" + option: + usage: "Usage" + show: "Search and show the items" + show_all: "Show all items" + update: "Update an item" + remove: "Delete an item" + group: "Search the items with specified group" + add: "Add an item" + config: "Specify the configuration file to use" + setup: "Create a new configuration file" + protocol: "Select the items with the specified protocol" + export: "Export all items in a CSV file" + import: "Import item since a CSV file" + force: "Force an action" + format: "Change the display items format by an alternative format" + generate_password: "Generate a random password (default 8 characters)" + help: "Show this help message" + form: + add: + title: "Add a new item" + name: "Enter the name: " + group: "Enter the group (optional): " + server: "Enter the hostname or ip: " + protocol: "Enter the protocol of the connection (ssh, http, other): " + login: "Enter the login connection: " + password: "Enter the the password: " + port: "Enter the connection port (optional): " + comment: "Enter a comment (optional): " + valid: "Item has been added!" + delete: + ask: "Are you sure you want to remove the item %{id} ?" + valid: "The item %{id} has been removed!" + not_valid: "The item %{id} hasn't been removed, because it doesn't exist!" + import: + ask: "Are you sure you want to import this file %{file} ?" + valid: "The import is succesfull!" + not_valid: "No data to import!" + setup: + title: "Setup a new config file" + lang: "Choose your language (en, fr, ...): " + gpg_key: "Enter the GPG key: " + gpg_file: "Enter the path to encrypt file [default=%{home}/.mpw.gpg]: " + timeout: "Enter the timeout (in seconde) to GPG password [default=60]: " + valid: "The config file has been created!" + update: + title: "Update an item" + name: "Enter the name [%{name}]: " + group: "Enter the group [%{group}]: " + server: "Enter the hostname or ip [%{server}]: " + protocol: "Enter the protocol of the connection [%{protocol}]: " + login: "Enter the login connection [%{login}]: " + password: "Enter the the password: " + port: "Enter the connection port [%{port}]: " + comment: "Enter a comment [%{comment}]: " + valid: "Item has been updated!" + interactive: + ask_password: "Password GPG: " + bad_password: "Bad password!" + goodbye: "Goodbye!" + unknown_command: "Unknown command!" + option: + title: "Help" + show: "Search and show the results" + group: "Change the group for the search" + add: "Add an item" + update: "Update an item" + remove: "Remove an item" + help: "Show this message" + quit: "Quit the software" + display: + comment: "Comment" + error: "ERROR" + gpg_password: "Password GPG: " + group: "Group" + login: "Login" + name: "Name" + nothing: "Nothing result!" + password: "Password" + port: "Port" + protocol: "Protocol" + server: "Server" + ssh: + option: + usage: "Usage" + login: "Change the login" + server: "Change the host or the ip" + port: "Change the port" + help: "Show this help message" + display: + connect: "Connection to:" + nothing: "Nothing result!" + formats: + default: ! '%Y-%m-%d' + long: ! '%B %d, %Y' + short: ! '%b %d' + custom: ! '%A, %M %B, %Y @ %l:%M%P' diff --git a/i18n/cli/fr.yml b/i18n/cli/fr.yml new file mode 100644 index 0000000..e80cec7 --- /dev/null +++ b/i18n/cli/fr.yml @@ -0,0 +1,121 @@ +--- +fr: + error: + config: + write: "Impossible d'écrire le fichier de configuration!" + check: "Le fichier de configuration est invalide!" + key_bad_format: "La clé GPG est invalide!" + delete: + id_no_exist: "Impossible de supprimer l'élément %{id}, car il n'existe pas!" + export: + write: "Impossible d'exporter les données dans le fichier %{file}!" + gpg_file: + decrypt: "Impossible de déchiffrer le fichier GPG!" + encrypt: "Impossible de chiffrer le fichier GPG!" + import: + bad_format: "Impossible d'importer le fichier car son format est incorrect!" + read: "Impossible d'importer le fichier %{file}, car il n'est pas lisible!" + update: + name_empty: "Vous devez définir un nom!" + sync: + connection: "La connexion n'a pu être établie!" + communication: "Un problème de communication avec le serveur est apparu!" + no_data: "Aucune donnée!" + not_authorized: "Vous n'avez pas les autorisations d'accès au fichier distant!" + unknown: "Une erreur inconnue est survenue!" + option: + usage: "Utilisation" + show: "Recherche et affiche les éléments" + show_all: "Affiche tous les éléments" + update: "Met à jour un élément" + remove: "Supprime un élément" + group: "Recherche les éléments appartenant au groupe spécifié" + add: "Ajoute un élément" + config: "Spécifie le fichier de configuration à utiliser" + setup: "Création d'un nouveau fichier de configuration" + protocol: "Sélectionne les éléments ayant le protocole spécifié" + export: "Exporte tous les éléments dans un fichier au format CSV" + import: "Importe des éléments depuis un fichier au format CSV" + force: "Force une action, l'action ne demandera pas de confirmation" + format: "Change le format d'affichage des éléments par un alternatif" + generate_password: "Génére un mot de passe aléatoire (défaut 8 caractères)" + help: "Affiche ce message d'aide" + form: + add: + title: "Ajout d'un nouvel élément" + name: "Entrez le nom: " + group: "Entrez le groupe (optionnel): " + server: "Entrez the hostname or ip: " + protocol: "Entrez le protocole de connexion (ssh, http, other): " + login: "Entrez l'identifiant de connexion: " + password: "Entrez le mot de passe: " + port: "Entrez le port de connexion (optionnel): " + comment: "Entrez un commentaire (optionnel): " + valid: "L'élément a bien été ajouté!" + delete: + ask: "Êtes vous sûre de vouloir supprimer l'élément %{id} ?" + valid: "L'élément %{id} a bien été supprimé!" + not_valid: "L'élément %{id} n'a pu être supprimé, car il n'existe pas!" + import: + ask: "Êtes vous sûre de vouloir importer le fichier %{file} ?" + valid: "L'import est un succès!" + not_valid: "Aucune donnée à importer!" + setup: + title: "Création d'un nouveau fichier de configuration" + lang: "Choisissez votre langue (en, fr, ...) [défaut=%{lang}]: " + gpg_key: "Entrez la clé GPG: " + gpg_file: "Entrez le chemin du fichier qui sera chiffré [défaut=%{home}/.mpw.gpg]: " + timeout: "Entrez le temps (en seconde) du mot de passe GPG [défaut=60]: " + valid: "Le fichier de configuration a bien été créé!" + update: + title: "Mis à jour d'un élément" + name: "Entrez le nom [%{name}]: " + group: "Entrez le groupe [%{group}]: " + server: "Entrez le nom de domaine ou l'ip du serveur [%{server}]: " + protocol: "Entrez le protocole de connexion [%{protocol}]: " + login: "Entrez votre identifiant de connexion [%{login}]: " + password: "Entrez le mot de passe: " + port: "Entrez un port de connexion [%{port}]: " + comment: "Entrez un commentaire [%{comment}]: " + valid: "L'élément a bien été mis à jour!" + interactive: + ask_password: "Mot de passe GPG: " + bad_password: "Mauvais mot de passe!" + goodbye: "Au revoir!" + unknown_command: "Commande inconnue!" + option: + title: "Aide" + show: "Cherche et affiche les résulats" + group: "Change de groupe pour la recherche" + add: "Ajout un élément" + update: "Met à jour un élément" + remove: "Supprime un élément" + help: "Affiche ce message d'aide" + quit: "Quitte le programme" + display: + comment: "Commentaire" + error: "ERREUR" + gpg_password: "Mot de passe GPG: " + group: "Groupe" + login: "Identifiant" + name: "Nom" + nothing: "Aucun résultat!" + password: "Mot de passe" + port: "Port" + protocol: "Protocol" + server: "Serveur" + ssh: + option: + usage: "Utilisation" + login: "Change l'identifiant de connexion" + server: "Change le nom de domaine ou l'ip du serveur" + port: "Change le port de connexion" + help: "Affiche ce message d'aide" + display: + connect: "Connexion à:" + nothing: "Aucun résultat!" + formats: + default: ! '%Y-%m-%d' + long: ! '%B %d, %Y' + short: ! '%b %d' + custom: ! '%A, %M %B, %Y @ %l:%M%P' diff --git a/i18n/en.yml b/i18n/en.yml deleted file mode 100644 index 22f2f7b..0000000 --- a/i18n/en.yml +++ /dev/null @@ -1,148 +0,0 @@ ---- -en: - error: - config: - write: "Can't write the config file!" - check: "Checkconfig failed!" - key_bad_format: "The key string isn't in good format!" - delete: - id_no_exist: "Can't delete the item %{id}, it doesn't exist!" - export: - write: "Can't export, unable to write in %{file}!" - gpg_file: - decrypt: "Can't decrypt file!" - encrypt: "Can't encrypt the GPG file!" - import: - bad_format: "Can't import, the file is badly formated!" - read: "Can't import, unable to read %{file}!" - update: - name_empty: "You must define a name!" - sync: - connection: "Connection fail!" - communication: "A communication problem with the server is appeared!" - no_data: "Nothing data!" - not_authorized: "You haven't the access to remote file!" - unknown: "An unknown error is occured!" - cli: - option: - usage: "Usage" - show: "Search and show the items" - show_all: "Show all items" - update: "Update an item" - remove: "Delete an item" - group: "Search the items with specified group" - add: "Add an item" - config: "Specify the configuration file to use" - setup: "Create a new configuration file" - protocol: "Select the items with the specified protocol" - export: "Export all items in a CSV file" - import: "Import item since a CSV file" - force: "Force an action" - format: "Change the display items format by an alternative format" - generate_password: "Generate a random password (default 8 characters)" - help: "Show this help message" - form: - add: - title: "Add a new item" - name: "Enter the name: " - group: "Enter the group (optional): " - server: "Enter the hostname or ip: " - protocol: "Enter the protocol of the connection (ssh, http, other): " - login: "Enter the login connection: " - password: "Enter the the password: " - port: "Enter the connection port (optional): " - comment: "Enter a comment (optional): " - valid: "Item has been added!" - delete: - ask: "Are you sure you want to remove the item %{id} ?" - valid: "The item %{id} has been removed!" - not_valid: "The item %{id} hasn't been removed, because it doesn't exist!" - import: - ask: "Are you sure you want to import this file %{file} ?" - valid: "The import is succesfull!" - not_valid: "No data to import!" - setup: - title: "Setup a new config file" - lang: "Choose your language (en, fr, ...): " - gpg_key: "Enter the GPG key: " - gpg_file: "Enter the path to encrypt file [default=%{home}/.mpw.gpg]: " - timeout: "Enter the timeout (in seconde) to GPG password [default=60]: " - valid: "The config file has been created!" - update: - title: "Update an item" - name: "Enter the name [%{name}]: " - group: "Enter the group [%{group}]: " - server: "Enter the hostname or ip [%{server}]: " - protocol: "Enter the protocol of the connection [%{protocol}]: " - login: "Enter the login connection [%{login}]: " - password: "Enter the the password: " - port: "Enter the connection port [%{port}]: " - comment: "Enter a comment [%{comment}]: " - valid: "Item has been updated!" - interactive: - ask_password: "Password GPG: " - bad_password: "Bad password!" - goodbye: "Goodbye!" - unknown_command: "Unknown command!" - option: - title: "Help" - show: "Search and show the results" - group: "Change the group for the search" - add: "Add an item" - update: "Update an item" - remove: "Remove an item" - help: "Show this message" - quit: "Quit the software" - display: - comment: "Comment" - error: "ERROR" - gpg_password: "Password GPG: " - group: "Group" - login: "Login" - name: "Name" - nothing: "Nothing result!" - password: "Password" - port: "Port" - protocol: "Protocol" - server: "Server" - sync: - not_connect: "The server connection fail!" - ssh: - option: - usage: "Usage" - login: "Change the login" - server: "Change the host or the ip" - port: "Change the port" - help: "Show this help message" - display: - connect: "Connection to:" - nothing: "Nothing result!" - server: - error: - client: - unknown: "An unknown error is appeared!" - no_authorized: "You haven't access to remote file!" - no_data: "Nothing data has been sent!" - option: - usage: "Usage" - config: "Specifie the configuration file" - checkconfig: "Check the configuration" - setup: "Setup a new configuration file" - help: "Show this message help" - checkconfig: - fail: "Checkconfig failed:!" - empty: "ERROR: an importe option is missing!" - datadir: "ERROR: le data directory doesn't exist!" - form: - setup: - title: "Serveur configuration" - host: "IP listen: " - port: "Port listen: " - data_dir: "Data directory: " - timeout: "Timeout to second: " - not_valid: "ERROR: Impossible to write the configuration file!" - formats: - default: ! '%Y-%m-%d' - long: ! '%B %d, %Y' - short: ! '%b %d' - custom: ! '%A, %M %B, %Y @ %l:%M%P' diff --git a/i18n/fr.yml b/i18n/fr.yml deleted file mode 100644 index b14aa99..0000000 --- a/i18n/fr.yml +++ /dev/null @@ -1,148 +0,0 @@ ---- -fr: - error: - config: - write: "Impossible d'écrire le fichier de configuration!" - check: "Le fichier de configuration est invalide!" - key_bad_format: "La clé GPG est invalide!" - delete: - id_no_exist: "Impossible de supprimer l'élément %{id}, car il n'existe pas!" - export: - write: "Impossible d'exporter les données dans le fichier %{file}!" - gpg_file: - decrypt: "Impossible de déchiffrer le fichier GPG!" - encrypt: "Impossible de chiffrer le fichier GPG!" - import: - bad_format: "Impossible d'importer le fichier car son format est incorrect!" - read: "Impossible d'importer le fichier %{file}, car il n'est pas lisible!" - update: - name_empty: "Vous devez définir un nom!" - sync: - connection: "La connexion n'a pu être établie!" - communication: "Un problème de communication avec le serveur est apparu!" - no_data: "Aucune donnée!" - not_authorized: "Vous n'avez pas les autorisations d'accès au fichier distant!" - unknown: "Une erreur inconnue est survenue!" - cli: - option: - usage: "Utilisation" - show: "Recherche et affiche les éléments" - show_all: "Affiche tous les éléments" - update: "Met à jour un élément" - remove: "Supprime un élément" - group: "Recherche les éléments appartenant au groupe spécifié" - add: "Ajoute un élément" - config: "Spécifie le fichier de configuration à utiliser" - setup: "Création d'un nouveau fichier de configuration" - protocol: "Sélectionne les éléments ayant le protocole spécifié" - export: "Exporte tous les éléments dans un fichier au format CSV" - import: "Importe des éléments depuis un fichier au format CSV" - force: "Force une action, l'action ne demandera pas de confirmation" - format: "Change le format d'affichage des éléments par un alternatif" - generate_password: "Génére un mot de passe aléatoire (défaut 8 caractères)" - help: "Affiche ce message d'aide" - form: - add: - title: "Ajout d'un nouvel élément" - name: "Entrez le nom: " - group: "Entrez le groupe (optionnel): " - server: "Entrez the hostname or ip: " - protocol: "Entrez le protocole de connexion (ssh, http, other): " - login: "Entrez l'identifiant de connexion: " - password: "Entrez le mot de passe: " - port: "Entrez le port de connexion (optionnel): " - comment: "Entrez un commentaire (optionnel): " - valid: "L'élément a bien été ajouté!" - delete: - ask: "Êtes vous sûre de vouloir supprimer l'élément %{id} ?" - valid: "L'élément %{id} a bien été supprimé!" - not_valid: "L'élément %{id} n'a pu être supprimé, car il n'existe pas!" - import: - ask: "Êtes vous sûre de vouloir importer le fichier %{file} ?" - valid: "L'import est un succès!" - not_valid: "Aucune donnée à importer!" - setup: - title: "Création d'un nouveau fichier de configuration" - lang: "Choisissez votre langue (en, fr, ...) [défaut=%{lang}]: " - gpg_key: "Entrez la clé GPG: " - gpg_file: "Entrez le chemin du fichier qui sera chiffré [défaut=%{home}/.mpw.gpg]: " - timeout: "Entrez le temps (en seconde) du mot de passe GPG [défaut=60]: " - valid: "Le fichier de configuration a bien été créé!" - update: - title: "Mis à jour d'un élément" - name: "Entrez le nom [%{name}]: " - group: "Entrez le groupe [%{group}]: " - server: "Entrez le nom de domaine ou l'ip du serveur [%{server}]: " - protocol: "Entrez le protocole de connexion [%{protocol}]: " - login: "Entrez votre identifiant de connexion [%{login}]: " - password: "Entrez le mot de passe: " - port: "Entrez un port de connexion [%{port}]: " - comment: "Entrez un commentaire [%{comment}]: " - valid: "L'élément a bien été mis à jour!" - interactive: - ask_password: "Mot de passe GPG: " - bad_password: "Mauvais mot de passe!" - goodbye: "Au revoir!" - unknown_command: "Commande inconnue!" - option: - title: "Aide" - show: "Cherche et affiche les résulats" - group: "Change de groupe pour la recherche" - add: "Ajout un élément" - update: "Met à jour un élément" - remove: "Supprime un élément" - help: "Affiche ce message d'aide" - quit: "Quitte le programme" - display: - comment: "Commentaire" - error: "ERREUR" - gpg_password: "Mot de passe GPG: " - group: "Groupe" - login: "Identifiant" - name: "Nom" - nothing: "Aucun résultat!" - password: "Mot de passe" - port: "Port" - protocol: "Protocol" - server: "Serveur" - sync: - not_connect: "La connexion au serveur n'a pu être établie!" - ssh: - option: - usage: "Utilisation" - login: "Change l'identifiant de connexion" - server: "Change le nom de domaine ou l'ip du serveur" - port: "Change le port de connexion" - help: "Affiche ce message d'aide" - display: - connect: "Connexion à:" - nothing: "Aucun résultat!" - server: - error: - client: - unknown: "Une erreur inconnue est apparue!" - no_authorized: "Vous n'avez pas les accès au fichier distant!" - no_data: "Aucune donnée n'a été transmise!" - option: - usage: "Utilisation" - config: "Spécifie le fichier de configuration" - checkconfig: "Vérifie le fichier de configuration" - setup: "Permet de générer un nouveau fichier de configuration" - help: "Affiche ce message d'aide" - checkconfig: - fail: "Le fichier de configuration est invalide!" - empty: "ERREUR: Une option importante est manquante!" - datadir: "ERREUR: Le répertoire des données n'existe pas!" - form: - setup: - title: "Configuration du serveur" - host: "IP d'écoute: " - port: "Port d'écoute: " - data_dir: "Répertoire des données: " - timeout: "Timeout en seconde: " - not_valid: "ERREUR: Impossible d'écire le fichier de configuration!" - formats: - default: ! '%Y-%m-%d' - long: ! '%B %d, %Y' - short: ! '%b %d' - custom: ! '%A, %M %B, %Y @ %l:%M%P' diff --git a/lib/Cli.rb b/lib/Cli.rb index 03c7595..f848457 100644 --- a/lib/Cli.rb +++ b/lib/Cli.rb @@ -36,40 +36,40 @@ class Cli if @config.sync_host.nil? || @config.sync_port.nil? @sync.disable() elsif !@sync.connect(@config.sync_host, @config.sync_port, @config.key, @config.sync_pwd, @config.sync_suffix) - puts "#{I18n.t('cli.sync.not_connect')}:\n#{@sync.error_msg}" + puts "#{I18n.t('sync.not_connect')}:\n#{@sync.error_msg}" end end begin if !@mpw.sync(@sync.get(@passwd), @config.last_update) - puts "#{I18n.t('cli.display.error')}: #{@mpw.error_msg}" + puts "#{I18n.t('display.error')}: #{@mpw.error_msg}" end if !@sync.update(File.open(@config.file_gpg).read) - puts "#{I18n.t('cli.display.error')}: #{@sync.error_msg}" + puts "#{I18n.t('display.error')}: #{@sync.error_msg}" end if !@config.setLastUpdate() - puts "#{I18n.t('cli.display.error')}: #{@config.error_msg}" + puts "#{I18n.t('display.error')}: #{@config.error_msg}" end rescue Exception => e - puts "#{I18n.t('cli.sync.error')}:\n#{e}" + puts "#{I18n.t('sync.error')}:\n#{e}" end end # Create a new config file # @args: lang -> the software language def setup(lang) - puts I18n.t('cli.form.setup.title') + puts I18n.t('form.setup.title') puts '--------------------' - language = ask(I18n.t('cli.form.setup.lang', :lang => lang)).to_s - key = ask(I18n.t('cli.form.setup.gpg_key')).to_s - file_gpg = ask(I18n.t('cli.form.setup.gpg_file', :home => Dir.home())).to_s - timeout_pwd = ask(I18n.t('cli.form.setup.timeout')).to_s - sync_host = ask(I18n.t('cli.form.setup.sync_host')).to_s - sync_port = ask(I18n.t('cli.form.setup.sync_port')).to_s - sync_pwd = ask(I18n.t('cli.form.setup.sync_pwd')).to_s - sync_suffix = ask(I18n.t('cli.form.setup.sync_suffix')).to_s + language = ask(I18n.t('form.setup.lang', :lang => lang)).to_s + key = ask(I18n.t('form.setup.gpg_key')).to_s + file_gpg = ask(I18n.t('form.setup.gpg_file', :home => Dir.home())).to_s + timeout_pwd = ask(I18n.t('form.setup.timeout')).to_s + sync_host = ask(I18n.t('form.setup.sync_host')).to_s + sync_port = ask(I18n.t('form.setup.sync_port')).to_s + sync_pwd = ask(I18n.t('form.setup.sync_pwd')).to_s + sync_suffix = ask(I18n.t('form.setup.sync_suffix')).to_s if !File.exist?("#{APP_ROOT}/i18n/#{language}.yml") language= 'en' @@ -82,13 +82,13 @@ class Cli sync_suffix.empty? ? (sync_suffix = nil) : (sync_suffix = sync_suffix) if @config.setup(key, language, file_gpg, timeout_pwd, sync_host, sync_port, sync_pwd, sync_suffix) - puts I18n.t('cli.form.setup.valid') + puts I18n.t('form.setup.valid') else - puts "#{I18n.t('cli.display.error')}: #{@config.error_msg}" + puts "#{I18n.t('display.error')}: #{@config.error_msg}" end if not @config.checkconfig() - puts "#{I18n.t('cli.display.error')}: #{@config.error_msg}" + puts "#{I18n.t('display.error')}: #{@config.error_msg}" exit 2 end end @@ -99,9 +99,9 @@ class Cli @mpw = MPW.new(@config.file_gpg, @config.key) end - @passwd = ask(I18n.t('cli.display.gpg_password')) {|q| q.echo = false} + @passwd = ask(I18n.t('display.gpg_password')) {|q| q.echo = false} if !@mpw.decrypt(@passwd) - puts "#{I18n.t('cli.display.error')}: #{@mpw.error_msg}" + puts "#{I18n.t('display.error')}: #{@mpw.error_msg}" exit 2 end end @@ -121,7 +121,7 @@ class Cli end end else - puts I18n.t('cli.display.nothing') + puts I18n.t('display.nothing') end end @@ -130,14 +130,14 @@ class Cli def displayFormat(item) puts '--------------------' puts "Id: #{item[MPW::ID]}" - puts "#{I18n.t('cli.display.name')}: #{item[MPW::NAME]}" - puts "#{I18n.t('cli.display.group')}: #{item[MPW::GROUP]}" - puts "#{I18n.t('cli.display.server')}: #{item[MPW::SERVER]}" - puts "#{I18n.t('cli.display.protocol')}: #{item[MPW::PROTOCOL]}" - puts "#{I18n.t('cli.display.login')}: #{item[MPW::LOGIN]}" - puts "#{I18n.t('cli.display.password')}: #{item[MPW::PASSWORD]}" - puts "#{I18n.t('cli.display.port')}: #{item[MPW::PORT]}" - puts "#{I18n.t('cli.display.comment')}: #{item[MPW::COMMENT]}" + puts "#{I18n.t('display.name')}: #{item[MPW::NAME]}" + puts "#{I18n.t('display.group')}: #{item[MPW::GROUP]}" + puts "#{I18n.t('display.server')}: #{item[MPW::SERVER]}" + puts "#{I18n.t('display.protocol')}: #{item[MPW::PROTOCOL]}" + puts "#{I18n.t('display.login')}: #{item[MPW::LOGIN]}" + puts "#{I18n.t('display.password')}: #{item[MPW::PASSWORD]}" + puts "#{I18n.t('display.port')}: #{item[MPW::PORT]}" + puts "#{I18n.t('display.comment')}: #{item[MPW::COMMENT]}" end # Display an item in the alternative format @@ -159,26 +159,26 @@ class Cli # Form to add a new item def add() row = Array.new() - puts I18n.t('cli.form.add.title') + puts I18n.t('form.add.title') puts '--------------------' - name = ask(I18n.t('cli.form.add.name')).to_s - group = ask(I18n.t('cli.form.add.group')).to_s - server = ask(I18n.t('cli.form.add.server')).to_s - protocol = ask(I18n.t('cli.form.add.protocol')).to_s - login = ask(I18n.t('cli.form.add.login')).to_s - passwd = ask(I18n.t('cli.form.add.password')).to_s - port = ask(I18n.t('cli.form.add.port')).to_s - comment = ask(I18n.t('cli.form.add.comment')).to_s + name = ask(I18n.t('form.add.name')).to_s + group = ask(I18n.t('form.add.group')).to_s + server = ask(I18n.t('form.add.server')).to_s + protocol = ask(I18n.t('form.add.protocol')).to_s + login = ask(I18n.t('form.add.login')).to_s + passwd = ask(I18n.t('form.add.password')).to_s + port = ask(I18n.t('form.add.port')).to_s + comment = ask(I18n.t('form.add.comment')).to_s if @mpw.update(name, group, server, protocol, login, passwd, port, comment) if @mpw.encrypt() sync() - puts I18n.t('cli.form.add.valid') + puts I18n.t('form.add.valid') else - puts "#{I18n.t('cli.display.error')}: #{@mpw.error_msg}" + puts "#{I18n.t('display.error')}: #{@mpw.error_msg}" end else - puts "#{I18n.t('cli.display.error')}: #{@mpw.error_msg}" + puts "#{I18n.t('display.error')}: #{@mpw.error_msg}" end end @@ -188,29 +188,29 @@ class Cli row = @mpw.searchById(id) if not row.empty? - puts I18n.t('cli.form.update.title') + puts I18n.t('form.update.title') puts '--------------------' - name = ask(I18n.t('cli.form.update.name' , :name => row[MPW::NAME])).to_s - group = ask(I18n.t('cli.form.update.group' , :group => row[MPW::GROUP])).to_s - server = ask(I18n.t('cli.form.update.server' , :server => row[MPW::SERVER])).to_s - protocol = ask(I18n.t('cli.form.update.protocol', :protocol => row[MPW::PROTOCOL])).to_s - login = ask(I18n.t('cli.form.update.login' , :login => row[MPW::LOGIN])).to_s - passwd = ask(I18n.t('cli.form.update.password')).to_s - port = ask(I18n.t('cli.form.update.port' , :port => row[MPW::PORT])).to_s - comment = ask(I18n.t('cli.form.update.comment' , :comment => row[MPW::COMMENT])).to_s + name = ask(I18n.t('form.update.name' , :name => row[MPW::NAME])).to_s + group = ask(I18n.t('form.update.group' , :group => row[MPW::GROUP])).to_s + server = ask(I18n.t('form.update.server' , :server => row[MPW::SERVER])).to_s + protocol = ask(I18n.t('form.update.protocol', :protocol => row[MPW::PROTOCOL])).to_s + login = ask(I18n.t('form.update.login' , :login => row[MPW::LOGIN])).to_s + passwd = ask(I18n.t('form.update.password')).to_s + port = ask(I18n.t('form.update.port' , :port => row[MPW::PORT])).to_s + comment = ask(I18n.t('form.update.comment' , :comment => row[MPW::COMMENT])).to_s if @mpw.update(name, group, server, protocol, login, passwd, port, comment, id) if @mpw.encrypt() sync() - puts I18n.t('cli.form.update.valid') + puts I18n.t('form.update.valid') else - puts "#{I18n.t('cli.display.error')}: #{@mpw.error_msg}" + puts "#{I18n.t('display.error')}: #{@mpw.error_msg}" end else - puts "#{I18n.t('cli.display.error')}: #{@mpw.error_msg}" + puts "#{I18n.t('display.error')}: #{@mpw.error_msg}" end else - puts I18n.t('cli.display.nothing') + puts I18n.t('display.nothing') end end @@ -224,12 +224,12 @@ class Cli if result.length > 0 displayFormat(result) - confirm = ask("#{I18n.t('cli.form.delete.ask', :id => id)} (y/N) ").to_s + confirm = ask("#{I18n.t('form.delete.ask', :id => id)} (y/N) ").to_s if confirm =~ /^(y|yes|YES|Yes|Y)$/ force = true end else - puts I18n.t('cli.display.nothing') + puts I18n.t('display.nothing') end end @@ -237,12 +237,12 @@ class Cli if @mpw.remove(id) if @mpw.encrypt() sync() - puts I18n.t('cli.form.delete.valid', :id => id) + puts I18n.t('form.delete.valid', :id => id) else - puts "#{I18n.t('cli.display.error')}: #{@mpw.error_msg}" + puts "#{I18n.t('display.error')}: #{@mpw.error_msg}" end else - puts I18n.t('cli.form.delete.not_valid') + puts I18n.t('form.delete.not_valid') end end end @@ -253,7 +253,7 @@ class Cli if @mpw.export(file) puts "The export in #{file} is succesfull!" else - puts "#{I18n.t('cli.display.error')}: #{@mpw.error_msg}" + puts "#{I18n.t('display.error')}: #{@mpw.error_msg}" end end @@ -270,21 +270,21 @@ class Cli displayFormat(r) end - confirm = ask("#{I18n.t('cli.form.import.ask', :file => file)} (y/N) ").to_s + confirm = ask("#{I18n.t('form.import.ask', :file => file)} (y/N) ").to_s if confirm =~ /^(y|yes|YES|Yes|Y)$/ force = true end else - puts I18n.t('cli.form.import.not_valid') + puts I18n.t('form.import.not_valid') end end if force if @mpw.import(file) && @mpw.encrypt() sync() - puts I18n.t('cli.form.import.valid') + puts I18n.t('form.import.valid') else - puts "#{I18n.t('cli.display.error')}: #{@mpw.error_msg}" + puts "#{I18n.t('display.error')}: #{@mpw.error_msg}" end end end @@ -297,12 +297,12 @@ class Cli while buf = Readline.readline('<mpw> ', true) if @config.timeout_pwd < Time.now.to_i - last_access - passwd_confirm = ask(I18n.t('cli.interactive.ask_password')) {|q| q.echo = false} + passwd_confirm = ask(I18n.t('interactive.ask_password')) {|q| q.echo = false} if @passwd.eql?(passwd_confirm) last_access = Time.now.to_i else - puts I18n.t('cli.interactive.bad_password') + puts I18n.t('interactive.bad_password') next end else @@ -333,21 +333,21 @@ class Cli group = nil end when 'help', 'h', '?' - puts I18n.t('cli.interactive.option.title') + puts I18n.t('interactive.option.title') puts '--------------------' - puts "display, show, d, s SEARCH #{I18n.t('cli.interactive.option.show')}" - puts "group, g #{I18n.t('cli.interactive.option.group')}" - puts "add, a #{I18n.t('cli.interactive.option.add')}" - puts "update, u ID #{I18n.t('cli.interactive.option.update')}" - puts "remove, delete, r, d ID #{I18n.t('cli.interactive.option.remove')}" - puts "help, h, ? #{I18n.t('cli.interactive.option.help')}" - puts "quit, exit, q #{I18n.t('cli.interactive.option.quit')}" + puts "display, show, d, s SEARCH #{I18n.t('interactive.option.show')}" + puts "group, g #{I18n.t('interactive.option.group')}" + puts "add, a #{I18n.t('interactive.option.add')}" + puts "update, u ID #{I18n.t('interactive.option.update')}" + puts "remove, delete, r, d ID #{I18n.t('interactive.option.remove')}" + puts "help, h, ? #{I18n.t('interactive.option.help')}" + puts "quit, exit, q #{I18n.t('interactive.option.quit')}" when 'quit', 'exit', 'q' - puts I18n.t('cli.interactive.goodbye') + puts I18n.t('interactive.goodbye') break else if !command[0].nil? && !command[0].empty? - puts I18n.t('cli.interactive.unknown_command') + puts I18n.t('interactive.unknown_command') end end diff --git a/mpw b/mpw index e1f0569..ef119a1 100755 --- a/mpw +++ b/mpw @@ -16,7 +16,7 @@ require "#{APP_ROOT}/lib/MPW.rb" lang = Locale::Tag.parse(ENV['LANG']).to_simple.to_s[0..1] I18n::Backend::Simple.send(:include, I18n::Backend::Fallbacks) -I18n.load_path = Dir["#{APP_ROOT}/i18n/*.yml"] +I18n.load_path = Dir["#{APP_ROOT}/i18n/cli/*.yml"] I18n.default_locale = :en I18n.locale = lang.to_sym @@ -27,67 +27,67 @@ options[:group] = nil options[:config] = nil OptionParser.new do |opts| - opts.banner = "#{I18n.t('cli.option.usage')}: mpw [options]" + opts.banner = "#{I18n.t('option.usage')}: mpw [options]" - opts.on('-d', '--display [SEARCH]', I18n.t('cli.option.show')) do |search| + opts.on('-d', '--display [SEARCH]', I18n.t('option.show')) do |search| search.nil? ? (options[:display] = '') : (options[:display] = search) end - opts.on('-A', '--show-all', I18n.t('cli.option.show_all')) do + opts.on('-A', '--show-all', I18n.t('option.show_all')) do options[:type] = nil options[:display] = '' end - opts.on('-u', '--update ID', I18n.t('cli.option.update')) do |id| + opts.on('-u', '--update ID', I18n.t('option.update')) do |id| options[:update] = id end - opts.on('-r', '--remove ID', I18n.t('cli.option.remove')) do |id| + opts.on('-r', '--remove ID', I18n.t('option.remove')) do |id| options[:remove] = id end - opts.on('-g', '--group GROUP', I18n.t('cli.option.group')) do |group| + opts.on('-g', '--group GROUP', I18n.t('option.group')) do |group| options[:group] = group end - opts.on('-a', '--add', I18n.t('cli.option.add')) do + opts.on('-a', '--add', I18n.t('option.add')) do options[:add] = true end - opts.on('-c', '--config CONFIG', I18n.t('cli.option.config')) do |config| + opts.on('-c', '--config CONFIG', I18n.t('option.config')) do |config| options[:config] = config end - opts.on('-S', '--setup', I18n.t('cli.option.setup')) do + opts.on('-S', '--setup', I18n.t('option.setup')) do options[:setup] = true end - opts.on('-p', '--protocol PROTOCOL', I18n.t('cli.option.protocol')) do |type| + opts.on('-p', '--protocol PROTOCOL', I18n.t('option.protocol')) do |type| options[:type] = type end - opts.on('-e', '--export FILE', I18n.t('cli.option.export')) do |file| + opts.on('-e', '--export FILE', I18n.t('option.export')) do |file| options[:export] = file end - opts.on('-i', '--import FILE', I18n.t('cli.option.import')) do |file| + opts.on('-i', '--import FILE', I18n.t('option.import')) do |file| options[:import] = file end - opts.on('-f', '--force', I18n.t('cli.option.force')) do + opts.on('-f', '--force', I18n.t('option.force')) do options[:force] = true end - opts.on('-F', '--format', I18n.t('cli.option.format')) do + opts.on('-F', '--format', I18n.t('option.format')) do options[:format] = true end - opts.on('-G', '--generate-password [LENGTH]', I18n.t('cli.option.generate_password')) do |length| + opts.on('-G', '--generate-password [LENGTH]', I18n.t('option.generate_password')) do |length| puts MPW::generatePassword(length) exit 0 end - opts.on('-h', '--help', I18n.t('cli.option.help')) do + opts.on('-h', '--help', I18n.t('option.help')) do puts opts exit 0 end From 174a0282382a104e7a612ad876c7d5ea13097e8f Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sun, 26 Jan 2014 12:13:32 +0100 Subject: [PATCH 039/531] fix bug last_update when sync no work --- lib/Cli.rb | 33 ++++++++++++++++++--------------- lib/Sync.rb | 21 +++++++++------------ 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/lib/Cli.rb b/lib/Cli.rb index f848457..0d426a9 100644 --- a/lib/Cli.rb +++ b/lib/Cli.rb @@ -29,32 +29,35 @@ class Cli end # Sync the data with the server + # @rtnr: true if the synchro is finish def sync() if !defined?(@sync) @sync = Sync.new() - if @config.sync_host.nil? || @config.sync_port.nil? - @sync.disable() - elsif !@sync.connect(@config.sync_host, @config.sync_port, @config.key, @config.sync_pwd, @config.sync_suffix) - puts "#{I18n.t('sync.not_connect')}:\n#{@sync.error_msg}" + if !@config.sync_host.nil? && !@config.sync_port.nil? + if !@sync.connect(@config.sync_host, @config.sync_port, @config.key, @config.sync_pwd, @config.sync_suffix) + puts "#{I18n.t('display.error')}: #{@sync.error_msg}" + end end end begin - if !@mpw.sync(@sync.get(@passwd), @config.last_update) - puts "#{I18n.t('display.error')}: #{@mpw.error_msg}" - end - - if !@sync.update(File.open(@config.file_gpg).read) - puts "#{I18n.t('display.error')}: #{@sync.error_msg}" - end - - if !@config.setLastUpdate() - puts "#{I18n.t('display.error')}: #{@config.error_msg}" + if @sync.enable + if !@mpw.sync(@sync.get(@passwd), @config.last_update) + puts "#{I18n.t('display.error')}: #{@mpw.error_msg}" + elsif !@sync.update(File.open(@config.file_gpg).read) + puts "#{I18n.t('display.error')}: #{@sync.error_msg}" + elsif !@config.setLastUpdate() + puts "#{I18n.t('display.error')}: #{@config.error_msg}" + else + return true + end end rescue Exception => e - puts "#{I18n.t('sync.error')}:\n#{e}" + puts "#{I18n.t('display.error')}: #{I18n.t('sync.error')}\n#{e}" end + + return false end # Create a new config file diff --git a/lib/Sync.rb b/lib/Sync.rb index 2fa8ec7..9969ea5 100644 --- a/lib/Sync.rb +++ b/lib/Sync.rb @@ -13,15 +13,12 @@ require "#{APP_ROOT}/lib/MPW.rb" class Sync attr_accessor :error_msg + attr_accessor :enable # Constructor def initialize() @error_msg = nil - end - - # Disable the sync - def disable() - @sync = false + @enable = false end # Connect to server @@ -37,21 +34,21 @@ class Sync @suffix = suffix begin - @socket= TCPSocket.new(host, port) - @sync = true + @socket = TCPSocket.new(host, port) + @enable = true rescue Exception => e @error_msg = "#{I18n.t('error.sync.connection')}\n#{e}" - @sync = false + @enable = false end - return @sync + return @enable end # Get data on server # @args: gpg_password -> the gpg password # @rtrn: nil if nothing data or error def get(gpg_password) - if !@sync + if !@enable return nil end @@ -91,7 +88,7 @@ class Sync # @args: data -> the data to send on server # @rtrn: false if there is a problem def update(data) - if !@sync + if !@enable return true end @@ -121,7 +118,7 @@ class Sync # Close the connection def close() - if !@sync + if !@enable return end From 1cabe202e739e1ac2759f046125a9d2eb8b71448 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sun, 26 Jan 2014 15:09:48 +0100 Subject: [PATCH 040/531] rename function --- lib/Cli.rb | 12 ++++++------ lib/MPW.rb | 4 ++-- lib/MPWConfig.rb | 2 +- lib/Server.rb | 37 ++++++++++++++++--------------------- mpw | 2 +- mpw-ssh | 2 +- 6 files changed, 27 insertions(+), 32 deletions(-) diff --git a/lib/Cli.rb b/lib/Cli.rb index 0d426a9..b6ed04d 100644 --- a/lib/Cli.rb +++ b/lib/Cli.rb @@ -23,8 +23,8 @@ class Cli @config = config end - # Destructor - def finalize() + # Close sync + def sync_close() @sync.close() end @@ -47,7 +47,7 @@ class Cli puts "#{I18n.t('display.error')}: #{@mpw.error_msg}" elsif !@sync.update(File.open(@config.file_gpg).read) puts "#{I18n.t('display.error')}: #{@sync.error_msg}" - elsif !@config.setLastUpdate() + elsif !@config.set_last_update() puts "#{I18n.t('display.error')}: #{@config.error_msg}" else return true @@ -188,7 +188,7 @@ class Cli # Update an item # @args: id -> the item's id def update(id) - row = @mpw.searchById(id) + row = @mpw.search_by_id(id) if not row.empty? puts I18n.t('form.update.title') @@ -222,7 +222,7 @@ class Cli # force -> no resquest a validation def remove(id, force=false) if not force - result = @mpw.searchById(id) + result = @mpw.search_by_id(id) if result.length > 0 displayFormat(result) @@ -265,7 +265,7 @@ class Cli # @args: file -> the import file # force -> no resquest a validation def import(file, force=false) - result = @mpw.importPreview(file) + result = @mpw.import_preview(file) if not force if result.is_a?(Array) && !result.empty? diff --git a/lib/MPW.rb b/lib/MPW.rb index 0f2daf6..d69f334 100644 --- a/lib/MPW.rb +++ b/lib/MPW.rb @@ -105,7 +105,7 @@ class MPW # Search in some csv data # @args: id -> the id item # @rtrn: a row with the resultat of the search - def searchById(id) + def search_by_id(id) @data.each do |row| if row[ID] == id return row @@ -243,7 +243,7 @@ class MPW # Return a preview import # @args: file -> path to file import # @rtrn: an array with the items to import, if there is an error return false - def importPreview(file) + def import_preview(file) begin result = Array.new() id = 0 diff --git a/lib/MPWConfig.rb b/lib/MPWConfig.rb index 6362b4c..43fdc66 100644 --- a/lib/MPWConfig.rb +++ b/lib/MPWConfig.rb @@ -110,7 +110,7 @@ class MPWConfig # Set the last update when there is a sync # @rtrn: true is the file has been updated - def setLastUpdate() + def set_last_update() config = {'config' => {'key' => @key, 'lang' => @lang, 'file_gpg' => @file_gpg, diff --git a/lib/Server.rb b/lib/Server.rb index 7c617b8..489c8d5 100644 --- a/lib/Server.rb +++ b/lib/Server.rb @@ -9,11 +9,6 @@ require 'logger' require "#{APP_ROOT}/lib/MPW.rb" class Server - - INFO = 0 - WARNING = 1 - ERROR = 2 - DEBUG = 3 attr_accessor :error_msg @@ -37,37 +32,37 @@ class Server @log.info("#{client.peeraddr[3]} is connected") while true do - msg = getClientMessage(client) + msg = get_client_msg(client) if !msg next end if msg['gpg_key'].nil? || msg['gpg_key'].empty? || msg['password'].nil? || msg['password'].empty? - closeConnection(client) + close_connection(client) next end case msg['action'] when 'get' @log.debug("#{client.peeraddr[3]} GET gpg_key=#{msg['gpg_key']} suffix=#{msg['suffix']}") - client.puts getFile(msg) + client.puts get_file(msg) when 'update' @log.debug("#{client.peeraddr[3]} UPDATE gpg_key=#{msg['gpg_key']} suffix=#{msg['suffix']}") - client.puts updateFile(msg) + client.puts update_file(msg) when 'delete' @log.debug("#{client.peeraddr[3]} DELETE gpg_key=#{msg['gpg_key']} suffix=#{msg['suffix']}") - client.puts deleteFile(msg) + client.puts delete_file(msg) when 'close' @log.info("#{client.peeraddr[3]} is disconnected") - closeConnection(client) + close_connection(client) else @log.warning("#{client.peeraddr[3]} is disconnected for unkwnow command") send_msg = {:action => 'unknown', :gpg_key => msg['gpg_key'], :error => 'server.error.client.unknown'} client.puts send_msg - closeConnection(client) + close_connection(client) end end end @@ -77,7 +72,7 @@ class Server # Get a gpg file # @args: msg -> message puts by the client # @rtrn: json message - def getFile(msg) + def get_file(msg) gpg_key = msg['gpg_key'].sub('@', '_') if msg['suffix'].nil? || msg['suffix'].empty? @@ -92,7 +87,7 @@ class Server hash = gpg_data['gpg']['hash'] data = gpg_data['gpg']['data'] - if isAuthorized?(msg['password'], salt, hash) + if is_authorized?(msg['password'], salt, hash) send_msg = {:action => 'get', :gpg_key => msg['gpg_key'], :data => data, @@ -115,7 +110,7 @@ class Server # Update a file # @args: msg -> message puts by the client # @rtrn: json message - def updateFile(msg) + def update_file(msg) gpg_key = msg['gpg_key'].sub('@', '_') data = msg['data'] @@ -143,7 +138,7 @@ class Server hash = Digest::SHA256.hexdigest(salt + msg['password']) end - if isAuthorized?(msg['password'], salt, hash) + if is_authorized?(msg['password'], salt, hash) begin config = {'gpg' => {'salt' => salt, 'hash' => hash, @@ -173,7 +168,7 @@ class Server # Remove a gpg file # @args: msg -> message puts by the client # @rtrn: json message - def deleteFile(msg) + def delete_file(msg) gpg_key = msg['gpg_key'].sub('@', '_') if msg['suffix'].nil? || msg['suffix'].empty? @@ -194,7 +189,7 @@ class Server salt = gpg_data['gpg']['salt'] hash = gpg_data['gpg']['hash'] - if isAuthorized?(msg['password'], salt, hash) + if is_authorized?(msg['password'], salt, hash) begin File.unlink(file_gpg) @@ -220,7 +215,7 @@ class Server # salt -> the salt # hash -> the hash of the password with the salt # @rtrn: true is is good, else false - def isAuthorized?(password, salt, hash) + def is_authorized?(password, salt, hash) if hash == Digest::SHA256.hexdigest(salt + password) return true else @@ -231,7 +226,7 @@ class Server # Get message to client # @args: client -> client connection # @rtrn: array of the json string, or false if isn't json message - def getClientMessage(client) + def get_client_msg(client) begin msg = client.gets return JSON.parse(msg) @@ -243,7 +238,7 @@ class Server # Close the client connection # @args: client -> client connection - def closeConnection(client) + def close_connection(client) client.puts "Closing the connection. Bye!" client.close end diff --git a/mpw b/mpw index ef119a1..b7ebf60 100755 --- a/mpw +++ b/mpw @@ -140,6 +140,6 @@ else end end -cli = nil +cli.sync_close() exit 0 diff --git a/mpw-ssh b/mpw-ssh index aa0e80a..83f835e 100755 --- a/mpw-ssh +++ b/mpw-ssh @@ -66,6 +66,6 @@ else cli.ssh(search) end -cli = nil +cli.sync_close() exit 0 From c76c2db2be80ccbc98a0bcd75f111a4f5c117880 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sun, 26 Jan 2014 17:26:02 +0100 Subject: [PATCH 041/531] fix log disconnected --- lib/Server.rb | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/lib/Server.rb b/lib/Server.rb index 489c8d5..1f995b6 100644 --- a/lib/Server.rb +++ b/lib/Server.rb @@ -38,7 +38,13 @@ class Server next end + if !msg['action'].nil? && msg['action'] == 'close' + @log.info("#{client.peeraddr[3]} is disconnected") + close_connection(client) + end + if msg['gpg_key'].nil? || msg['gpg_key'].empty? || msg['password'].nil? || msg['password'].empty? + @log.warning("#{client.peeraddr[3]} is disconnected because no password or no gpg_key") close_connection(client) next end @@ -53,11 +59,8 @@ class Server when 'delete' @log.debug("#{client.peeraddr[3]} DELETE gpg_key=#{msg['gpg_key']} suffix=#{msg['suffix']}") client.puts delete_file(msg) - when 'close' - @log.info("#{client.peeraddr[3]} is disconnected") - close_connection(client) else - @log.warning("#{client.peeraddr[3]} is disconnected for unkwnow command") + @log.warning("#{client.peeraddr[3]} is disconnected because unkwnow command") send_msg = {:action => 'unknown', :gpg_key => msg['gpg_key'], :error => 'server.error.client.unknown'} From 52c1554e9056ec927a9baf499bc6dda51b43fadf Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sun, 26 Jan 2014 17:48:24 +0100 Subject: [PATCH 042/531] add translate --- i18n/cli/en.yml | 4 ++++ i18n/cli/fr.yml | 4 ++++ i18n/server/en.yml | 1 + i18n/server/fr.yml | 1 + 4 files changed, 10 insertions(+) diff --git a/i18n/cli/en.yml b/i18n/cli/en.yml index dc76087..bf8b9fc 100644 --- a/i18n/cli/en.yml +++ b/i18n/cli/en.yml @@ -66,6 +66,10 @@ en: gpg_key: "Enter the GPG key: " gpg_file: "Enter the path to encrypt file [default=%{home}/.mpw.gpg]: " timeout: "Enter the timeout (in seconde) to GPG password [default=60]: " + sync_host: "Synchronization server: " + sync_port: "Port of the synchronization server: " + sync_pwd: "Password for the synchronization: " + sync_suffix: "Suffix for the synchronization (optionnal): " valid: "The config file has been created!" update: title: "Update an item" diff --git a/i18n/cli/fr.yml b/i18n/cli/fr.yml index e80cec7..0936cdb 100644 --- a/i18n/cli/fr.yml +++ b/i18n/cli/fr.yml @@ -66,6 +66,10 @@ fr: gpg_key: "Entrez la clé GPG: " gpg_file: "Entrez le chemin du fichier qui sera chiffré [défaut=%{home}/.mpw.gpg]: " timeout: "Entrez le temps (en seconde) du mot de passe GPG [défaut=60]: " + sync_host: "Serveur de synchronisation: " + sync_port: "Port du serveur de synchronisation: " + sync_pwd: "Mot de passe pour la synchronisation: " + sync_suffix: "Suffix pour la synchronisation (optionnel): " valid: "Le fichier de configuration a bien été créé!" update: title: "Mis à jour d'un élément" diff --git a/i18n/server/en.yml b/i18n/server/en.yml index b3fc13c..df88dfe 100644 --- a/i18n/server/en.yml +++ b/i18n/server/en.yml @@ -17,6 +17,7 @@ en: port: "Port listen: " data_dir: "Data directory: " timeout: "Timeout to second: " + log_file: "Log file path: " not_valid: "ERROR: Impossible to write the configuration file!" formats: default: ! '%Y-%m-%d' diff --git a/i18n/server/fr.yml b/i18n/server/fr.yml index 962ac44..667757c 100644 --- a/i18n/server/fr.yml +++ b/i18n/server/fr.yml @@ -16,6 +16,7 @@ fr: host: "IP d'écoute: " port: "Port d'écoute: " data_dir: "Répertoire des données: " + log_file: "Chemin du ficier de log: " timeout: "Timeout en seconde: " not_valid: "ERREUR: Impossible d'écire le fichier de configuration!" formats: From 0c89715e3a1cd3a0ff3cfb3851db04f61800e2b8 Mon Sep 17 00:00:00 2001 From: adrien <adrien.waksberg@believedigital.com> Date: Mon, 27 Jan 2014 08:38:34 +0100 Subject: [PATCH 043/531] fix bug --- mpw-ssh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mpw-ssh b/mpw-ssh index 83f835e..39fe1b3 100755 --- a/mpw-ssh +++ b/mpw-ssh @@ -15,7 +15,7 @@ require "#{APP_ROOT}/lib/CliSSH.rb" lang = Locale::Tag.parse(ENV['LANG']).to_simple.to_s[0..1] I18n::Backend::Simple.send(:include, I18n::Backend::Fallbacks) -I18n.load_path = Dir["#{APP_ROOT}/i18n/*.yml"] +I18n.load_path = Dir["#{APP_ROOT}/i18n/cli/*.yml"] I18n.default_locale = :en I18n.locale = lang.to_sym @@ -63,6 +63,8 @@ elsif ARGV.length < 1 puts "#{I18n.t('ssh.option.usage')}: mpw-ssh SEARCH [options]" exit 2 else + cli.decrypt() + cli.sync() cli.ssh(search) end From 074643a1677e58a8b8aa55b50960f779a48728d5 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Mon, 27 Jan 2014 18:27:37 +0100 Subject: [PATCH 044/531] add method salt --- lib/Server.rb | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/lib/Server.rb b/lib/Server.rb index 1f995b6..3baa22f 100644 --- a/lib/Server.rb +++ b/lib/Server.rb @@ -6,8 +6,6 @@ require 'highline/import' require 'digest' require 'logger' -require "#{APP_ROOT}/lib/MPW.rb" - class Server attr_accessor :error_msg @@ -137,7 +135,7 @@ class Server hash = gpg_data['gpg']['hash'] else - salt = MPW.generatePassword(4) + salt = salt() hash = Digest::SHA256.hexdigest(salt + msg['password']) end @@ -321,4 +319,18 @@ class Server return true end + + # Generate a random salt + # @args: length -> the length salt + # @rtrn: a random string + def salt(length=4) + if length.to_i <= 0 || length.to_i > 16 + length = 4 + else + length = length.to_i + end + + return ([*('A'..'Z'),*('a'..'z'),*('0'..'9')]).sample(length).join + end + end From 76c5ab07c7d543189b0a18273bded20a35954a89 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Mon, 27 Jan 2014 20:19:38 +0100 Subject: [PATCH 045/531] rename function --- lib/Cli.rb | 2 +- lib/MPW.rb | 21 ++++++++++----------- lib/Sync.rb | 2 +- mpw | 2 +- 4 files changed, 13 insertions(+), 14 deletions(-) diff --git a/lib/Cli.rb b/lib/Cli.rb index b6ed04d..74f966b 100644 --- a/lib/Cli.rb +++ b/lib/Cli.rb @@ -54,7 +54,7 @@ class Cli end end rescue Exception => e - puts "#{I18n.t('display.error')}: #{I18n.t('sync.error')}\n#{e}" + puts "#{I18n.t('display.error')}: #{e}" end return false diff --git a/lib/MPW.rb b/lib/MPW.rb index d69f334..366f657 100644 --- a/lib/MPW.rb +++ b/lib/MPW.rb @@ -147,15 +147,15 @@ class MPW row_update = Array.new() row_update[DATE] = Time.now.to_i - id.nil? || id.empty? ? (row_update[ID] = MPW.generatePassword(16)) : (row_update[ID] = id) - name.nil? || name.empty? ? (row_update[NAME] = row[NAME]) : (row_update[NAME] = name) - group.nil? || group.empty? ? (row_update[GROUP] = row[GROUP]) : (row_update[GROUP] = group) - server.nil? || server.empty? ? (row_update[SERVER] = row[SERVER]) : (row_update[SERVER] = server) - protocol.nil? || protocol.empty? ? (row_update[PROTOCOL] = row[PROTOCOL]) : (row_update[PROTOCOL] = protocol) - login.nil? || login.empty? ? (row_update[LOGIN] = row[LOGIN]) : (row_update[LOGIN] = login) - passwd.nil? || passwd.empty? ? (row_update[PASSWORD] = row[PASSWORD]) : (row_update[PASSWORD] = passwd) - port.nil? || port.empty? ? (row_update[PORT] = row[PORT]) : (row_update[PORT] = port) - comment.nil? || comment.empty? ? (row_update[COMMENT] = row[COMMENT]) : (row_update[COMMENT] = comment) + id.nil? || id.empty? ? (row_update[ID] = MPW.password(16)) : (row_update[ID] = id) + name.nil? || name.empty? ? (row_update[NAME] = row[NAME]) : (row_update[NAME] = name) + group.nil? || group.empty? ? (row_update[GROUP] = row[GROUP]) : (row_update[GROUP] = group) + server.nil? || server.empty? ? (row_update[SERVER] = row[SERVER]) : (row_update[SERVER] = server) + protocol.nil? || protocol.empty? ? (row_update[PROTOCOL] = row[PROTOCOL]) : (row_update[PROTOCOL] = protocol) + login.nil? || login.empty? ? (row_update[LOGIN] = row[LOGIN]) : (row_update[LOGIN] = login) + passwd.nil? || passwd.empty? ? (row_update[PASSWORD] = row[PASSWORD]) : (row_update[PASSWORD] = passwd) + port.nil? || port.empty? ? (row_update[PORT] = row[PORT]) : (row_update[PORT] = port) + comment.nil? || comment.empty? ? (row_update[COMMENT] = row[COMMENT]) : (row_update[COMMENT] = comment) row_update[NAME].nil? ? (row_update[NAME] = row_update[NAME]) : (row_update[NAME] = row_update[NAME].force_encoding('ASCII-8BIT')) row_update[GROUP].nil? ? (row_update[GROUP] = row_update[GROUP]) : (row_update[GROUP] = row_update[GROUP].force_encoding('ASCII-8BIT')) @@ -312,7 +312,7 @@ class MPW # Generate a random password # @args: length -> the length password # @rtrn: a random string - def self.generatePassword(length=8) + def self.password(length=8) if length.to_i <= 0 length = 8 else @@ -328,5 +328,4 @@ class MPW return result end - end diff --git a/lib/Sync.rb b/lib/Sync.rb index 9969ea5..e85b0ce 100644 --- a/lib/Sync.rb +++ b/lib/Sync.rb @@ -64,7 +64,7 @@ class Sync @error_msg = I18n.t('error.sync.communication') return nil elsif msg['error'].nil? - tmp_file = "/tmp/mpw-#{MPW.generatePassword()}.gpg" + tmp_file = "/tmp/mpw-#{MPW.password()}.gpg" File.open(tmp_file, 'w') do |file| file << msg['data'] end diff --git a/mpw b/mpw index b7ebf60..ff27575 100755 --- a/mpw +++ b/mpw @@ -83,7 +83,7 @@ OptionParser.new do |opts| end opts.on('-G', '--generate-password [LENGTH]', I18n.t('option.generate_password')) do |length| - puts MPW::generatePassword(length) + puts MPW::password(length) exit 0 end From f4e492079578084911f8f9511fb0bd87cb7d1b3d Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Tue, 28 Jan 2014 20:33:00 +0100 Subject: [PATCH 046/531] version 1.1.0 --- CHANGELOG | 7 +++++++ README.md | 1 + VERSION | 2 +- 3 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 CHANGELOG diff --git a/CHANGELOG b/CHANGELOG new file mode 100644 index 0000000..21cf7ae --- /dev/null +++ b/CHANGELOG @@ -0,0 +1,7 @@ += CHANGELOG = + +== v1.1.0 == + +* Add sync with MPW Server +* Add MPW Server +* Fix minors bugs diff --git a/README.md b/README.md index 95dba72..277d937 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ # Manage your passwords! MPW is a little software which stores your passwords in an GPG encrypted file. +MPW can sync your password with a MPW Server. # Installation diff --git a/VERSION b/VERSION index 3eebe6a..e532f18 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.1.0 - dev +1.1.0 - stable From 00aea4f4069db9e4afab8c76822932286796d467 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Wed, 29 Jan 2014 18:40:37 +0100 Subject: [PATCH 047/531] version dev --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index e532f18..4482064 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.1.0 - stable +1.2.0 - dev From 47ee15adb92c05a0f7386a656360de29d1a2a9e4 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Wed, 29 Jan 2014 19:12:24 +0100 Subject: [PATCH 048/531] factorize the code --- lib/MPW.rb | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/lib/MPW.rb b/lib/MPW.rb index 366f657..f82fcc2 100644 --- a/lib/MPW.rb +++ b/lib/MPW.rb @@ -88,9 +88,9 @@ class MPW search = search.force_encoding('ASCII-8BIT') @data.each do |row| - row[NAME].nil? ? (name = nil) : (name = row[NAME].downcase) - row[SERVER].nil? ? (server = nil) : (server = row[SERVER].downcase) - row[COMMENT].nil? ? (comment = nil) : (comment = row[COMMENT].downcase) + name = row[NAME].nil? ? nil : row[NAME].downcase + server = row[SERVER].nil? ? nil : row[SERVER].downcase + comment = row[COMMENT].nil? ? nil : row[COMMENT].downcase if name =~ /^.*#{search}.*$/ || server =~ /^.*#{search}.*$/ || comment =~ /^.*#{search}.*$/ if (protocol.nil? || protocol.eql?(row[PROTOCOL])) && (group.nil? || group.eql?(row[GROUP])) @@ -147,23 +147,23 @@ class MPW row_update = Array.new() row_update[DATE] = Time.now.to_i - id.nil? || id.empty? ? (row_update[ID] = MPW.password(16)) : (row_update[ID] = id) - name.nil? || name.empty? ? (row_update[NAME] = row[NAME]) : (row_update[NAME] = name) - group.nil? || group.empty? ? (row_update[GROUP] = row[GROUP]) : (row_update[GROUP] = group) - server.nil? || server.empty? ? (row_update[SERVER] = row[SERVER]) : (row_update[SERVER] = server) - protocol.nil? || protocol.empty? ? (row_update[PROTOCOL] = row[PROTOCOL]) : (row_update[PROTOCOL] = protocol) - login.nil? || login.empty? ? (row_update[LOGIN] = row[LOGIN]) : (row_update[LOGIN] = login) - passwd.nil? || passwd.empty? ? (row_update[PASSWORD] = row[PASSWORD]) : (row_update[PASSWORD] = passwd) - port.nil? || port.empty? ? (row_update[PORT] = row[PORT]) : (row_update[PORT] = port) - comment.nil? || comment.empty? ? (row_update[COMMENT] = row[COMMENT]) : (row_update[COMMENT] = comment) + row_update[ID] = id.nil? || id.empty? ? MPW.password(16) : id + row_update[NAME] = name.nil? || name.empty? ? row[NAME] : name + row_update[GROUP] = group.nil? || group.empty? ? row[GROUP] : group + row_update[SERVER] = server.nil? || server.empty? ? row[SERVER] : server + row_update[PROTOCOL] = protocol.nil? || protocol.empty? ? row[PROTOCOL] : protocol + row_update[LOGIN] = login.nil? || login.empty? ? row[LOGIN] : login + row_update[PASSWORD] = passwd.nil? || passwd.empty? ? row[PASSWORD] : passwd + row_update[PORT] = port.nil? || port.empty? ? row[PORT] : port + row_update[COMMENT] = comment.nil? || comment.empty? ? row[COMMENT] : comment - row_update[NAME].nil? ? (row_update[NAME] = row_update[NAME]) : (row_update[NAME] = row_update[NAME].force_encoding('ASCII-8BIT')) - row_update[GROUP].nil? ? (row_update[GROUP] = row_update[GROUP]) : (row_update[GROUP] = row_update[GROUP].force_encoding('ASCII-8BIT')) - row_update[SERVER].nil? ? (row_update[SERVER] = row_update[SERVER]) : (row_update[SERVER] = row_update[SERVER].force_encoding('ASCII-8BIT')) - row_update[PROTOCOL].nil? ? (row_update[PROTOCOL] = row_update[PROTOCOL]) : (row_update[PROTOCOL] = row_update[PROTOCOL].force_encoding('ASCII-8BIT')) - row_update[LOGIN].nil? ? (row_update[LOGIN] = row_update[LOGIN]) : (row_update[LOGIN] = row_update[LOGIN].force_encoding('ASCII-8BIT')) - row_update[PASSWORD].nil? ? (row_update[PASSWORD] = row_update[PASSWORD]) : (row_update[PASSWORD] = row_update[PASSWORD].force_encoding('ASCII-8BIT')) - row_update[COMMENT].nil? ? (row_update[COMMENT] = row_update[COMMENT]) : (row_update[COMMENT] = row_update[COMMENT].force_encoding('ASCII-8BIT')) + row_update[] = row_update[NAME].nil? ? nil : row_update[NAME].force_encoding('ASCII-8BIT') + row_update[] = row_update[GROUP].nil? ? nil : row_update[GROUP].force_encoding('ASCII-8BIT') + row_update[] = row_update[SERVER].nil? ? nil : row_update[SERVER].force_encoding('ASCII-8BIT') + row_update[] = row_update[PROTOCOL].nil? ? nil : row_update[PROTOCOL].force_encoding('ASCII-8BIT') + row_update[] = row_update[LOGIN].nil? ? nil : row_update[LOGIN].force_encoding('ASCII-8BIT') + row_update[] = row_update[PASSWORD].nil? ? nil : row_update[PASSWORD].force_encoding('ASCII-8BIT') + row_update[] = row_update[COMMENT].nil? ? nil : row_update[COMMENT].force_encoding('ASCII-8BIT') if row_update[NAME].nil? || row_update[NAME].empty? @error_msg = I18n.t('error.update.name_empty') From 7a50c4cf1c98abbc19847d9bc8d6dd13f62e67bb Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Wed, 29 Jan 2014 19:18:36 +0100 Subject: [PATCH 049/531] factorize the code --- lib/Cli.rb | 10 +++++----- lib/CliSSH.rb | 6 +++--- lib/MPWConfig.rb | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/lib/Cli.rb b/lib/Cli.rb index 74f966b..152f3bf 100644 --- a/lib/Cli.rb +++ b/lib/Cli.rb @@ -79,10 +79,10 @@ class Cli end I18n.locale = language.to_sym - sync_host.empty? ? (sync_host = nil) : (sync_host = sync_host) - sync_port.empty? ? (sync_port = nil) : (sync_port = sync_port.to_i) - sync_pwd.empty? ? (sync_pwd = nil) : (sync_pwd = sync_pwd) - sync_suffix.empty? ? (sync_suffix = nil) : (sync_suffix = sync_suffix) + sync_host = sync_host.empty? ? nil : sync_host + sync_port = sync_port.empty? ? nil : sync_port.to_i + sync_pwd = sync_pwd.empty? ? nil : sync_pwd + sync_suffix = sync_suffix.empty? ? nil : sync_suffix if @config.setup(key, language, file_gpg, timeout_pwd, sync_host, sync_port, sync_pwd, sync_suffix) puts I18n.t('form.setup.valid') @@ -146,7 +146,7 @@ class Cli # Display an item in the alternative format # @args: item -> an array with the item information def displayFormatAlt(item) - item[MPW::PORT].nil? ? (port = '') : (port = ":#{item[MPW::PORT]}") + port = item[MPW::PORT].nil? ? '' : ":#{item[MPW::PORT]}" if item[MPW::PASSWORD].nil? || item[MPW::PASSWORD].empty? if item[MPW::LOGIN].include('@') diff --git a/lib/CliSSH.rb b/lib/CliSSH.rb index 7fba1ad..ebcea04 100644 --- a/lib/CliSSH.rb +++ b/lib/CliSSH.rb @@ -16,9 +16,9 @@ class CliSSH < Cli if result.length > 0 result.each do |r| - @server.nil? ? (server = r[MPW::SERVER]) : (server = @server) - @port.nil? ? (port = r[MPW::PORT]) : (port = @port) - @login.nil? ? (login = r[MPW::LOGIN]) : (login = @login) + server = @server.nil? ? r[MPW::SERVER] : @server + port = @port.nil? ? r[MPW::PORT] : @port + login = @login.nil? ? r[MPW::LOGIN] : @login passwd = r[MPW::PASSWORD] diff --git a/lib/MPWConfig.rb b/lib/MPWConfig.rb index 43fdc66..bce49e6 100644 --- a/lib/MPWConfig.rb +++ b/lib/MPWConfig.rb @@ -54,7 +54,7 @@ class MPWConfig file_gpg = "#{Dir.home()}/.mpw.gpg" end - timeout_pwd.empty? ? (timeout_pwd = 60) : (timeout_pwd = timeout_pwd.to_i) + timeout_pwd = timeout_pwd.empty? ? 60 : timeout_pwd.to_i config = {'config' => {'key' => key, 'lang' => lang, From 96fe71e07d6c67f72492cb8a5ef036cc23da3b29 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Wed, 29 Jan 2014 20:49:39 +0100 Subject: [PATCH 050/531] add module MPW --- MPW/Config.rb | 140 ++++++++++++++++ MPW/MPW.rb | 335 ++++++++++++++++++++++++++++++++++++++ MPW/Sync/MPW.rb | 130 +++++++++++++++ {lib => MPW/UI}/Cli.rb | 53 +++--- {lib => MPW/UI}/CliSSH.rb | 10 +- lib/MPW.rb | 331 ------------------------------------- lib/MPWConfig.rb | 136 ---------------- lib/Sync.rb | 128 --------------- mpw | 6 +- mpw-ssh | 5 +- 10 files changed, 642 insertions(+), 632 deletions(-) create mode 100644 MPW/Config.rb create mode 100644 MPW/MPW.rb create mode 100644 MPW/Sync/MPW.rb rename {lib => MPW/UI}/Cli.rb (86%) rename {lib => MPW/UI}/CliSSH.rb (74%) delete mode 100644 lib/MPW.rb delete mode 100644 lib/MPWConfig.rb delete mode 100644 lib/Sync.rb diff --git a/MPW/Config.rb b/MPW/Config.rb new file mode 100644 index 0000000..74d309c --- /dev/null +++ b/MPW/Config.rb @@ -0,0 +1,140 @@ +#!/usr/bin/ruby +# author: nishiki +# mail: nishiki@yaegashi.fr +# info: a simple script who manage your passwords + +module MPW + + require 'rubygems' + require 'yaml' + require 'i18n' + + class Config + + attr_accessor :error_msg + + attr_accessor :key + attr_accessor :lang + attr_accessor :file_gpg + attr_accessor :timeout_pwd + attr_accessor :last_update + attr_accessor :sync_host + attr_accessor :sync_port + attr_accessor :sync_pwd + attr_accessor :sync_suffix + attr_accessor :last_update + + # Constructor + # @args: file_config -> the specify config file + def initialize(file_config=nil) + @error_msg = nil + @file_config = "#{Dir.home()}/.mpw.cfg" + + if !file_config.nil? && !file_config.empty? + @file_config = file_config + end + end + + # Create a new config file + # @args: key -> the gpg key to encrypt + # lang -> the software language + # file_gpg -> the file who is encrypted + # timeout_pwd -> time to save the password + # sync_host -> the server host for synchronization + # sync_port -> the server port for synchronization + # sync_pwd -> the password for synchronization + # sync_suffix -> the suffix file (optionnal) + # @rtrn: true if le config file is create + def setup(key, lang, file_gpg, timeout_pwd, sync_host=nil, sync_port=nil, sync_pwd=nil, sync_suffix=nil) + + if not key =~ /[a-zA-Z0-9.-_]+\@[a-zA-Z0-9]+\.[a-zA-Z]+/ + @error_msg = I18n.t('error.config.key_bad_format') + return false + end + + if file_gpg.empty? + file_gpg = "#{Dir.home()}/.mpw.gpg" + end + + timeout_pwd = timeout_pwd.empty? ? 60 : timeout_pwd.to_i + + config = {'config' => {'key' => key, + 'lang' => lang, + 'file_gpg' => file_gpg, + 'timeout_pwd' => timeout_pwd, + 'sync_host' => sync_host, + 'sync_port' => sync_port, + 'sync_pwd' => sync_pwd, + 'sync_suffix' => sync_suffix, + 'last_update' => 0 }} + + begin + File.open(@file_config, 'w') do |file| + file << config.to_yaml + end + rescue Exception => e + @error_msg = "#{I18n.t('error.config.write')}\n#{e}" + return false + end + + return true + end + + # Check the config file + # @rtrn: true if the config file is correct + def checkconfig() + begin + config = YAML::load_file(@file_config) + @key = config['config']['key'] + @lang = config['config']['lang'] + @file_gpg = config['config']['file_gpg'] + @timeout_pwd = config['config']['timeout_pwd'].to_i + @sync_host = config['config']['sync_host'] + @sync_port = config['config']['sync_port'] + @sync_pwd = config['config']['sync_pwd'] + @sync_suffix = config['config']['sync_suffix'] + @last_update = config['config']['last_update'].to_i + + if @key.empty? || @file_gpg.empty? + @error_msg = I18n.t('error.config.check') + return false + end + + I18n.locale = @lang.to_sym + + rescue Exception => e + @error_msg = "#{I18n.t('error.config.check')}\n#{e}" + return false + end + + return true + end + + # Set the last update when there is a sync + # @rtrn: true is the file has been updated + def set_last_update() + config = {'config' => {'key' => @key, + 'lang' => @lang, + 'file_gpg' => @file_gpg, + 'timeout_pwd' => @timeout_pwd, + 'sync_host' => @sync_host, + 'sync_port' => @sync_port, + 'sync_pwd' => @sync_pwd, + 'sync_suffix' => @sync_suffix, + 'last_update' => Time.now.to_i }} + + begin + File.open(@file_config, 'w') do |file| + file << config.to_yaml + end + rescue Exception => e + @error_msg = "#{I18n.t('error.config.write')}\n#{e}" + return false + end + + return true + end + + end + +end diff --git a/MPW/MPW.rb b/MPW/MPW.rb new file mode 100644 index 0000000..1f84400 --- /dev/null +++ b/MPW/MPW.rb @@ -0,0 +1,335 @@ +#!/usr/bin/ruby +# author: nishiki +# mail: nishiki@yaegashi.fr +# info: a simple script who manage your passwords + +module MPW + + require 'rubygems' + require 'gpgme' + require 'csv' + require 'i18n' + + class MPW + + ID = 0 + NAME = 1 + GROUP = 2 + PROTOCOL = 3 + SERVER = 4 + LOGIN = 5 + PASSWORD = 6 + PORT = 7 + COMMENT = 8 + DATE = 9 + + attr_accessor :error_msg + + # Constructor + def initialize(file_gpg, key=nil) + @error_msg = nil + @file_gpg = file_gpg + @key = key + end + + # Decrypt a gpg file + # @args: password -> the GPG key password + # @rtrn: true if data has been decrypted + def decrypt(passwd=nil) + @data = Array.new + + begin + if File.exist?(@file_gpg) + crypto = GPGME::Crypto.new(:armor => true) + data_decrypt = crypto.decrypt(IO.read(@file_gpg), :password => passwd).read + + data_decrypt.lines do |line| + @data.push(line.parse_csv) + end + end + + return true + rescue Exception => e + @error_msg = "#{I18n.t('error.gpg_file.decrypt')}\n#{e}" + return false + end + end + + # Encrypt a file + # @rtrn: true if the file has been encrypted + def encrypt() + begin + crypto = GPGME::Crypto.new(:armor => true) + file_gpg = File.open(@file_gpg, 'w+') + + data_to_encrypt = '' + @data.each do |row| + data_to_encrypt << row.to_csv + end + + crypto.encrypt(data_to_encrypt, :recipients => @key, :output => file_gpg) + file_gpg.close + + return true + rescue Exception => e + @error_msg = "#{I18n.t('error.gpg_file.encrypt')}\n#{e}" + return false + end + end + + # Search in some csv data + # @args: search -> the string to search + # protocol -> the connection protocol (ssh, web, other) + # @rtrn: a list with the resultat of the search + def search(search='', group=nil, protocol=nil) + result = Array.new() + + if !search.nil? + search = search.downcase + end + search = search.force_encoding('ASCII-8BIT') + + @data.each do |row| + name = row[NAME].nil? ? nil : row[NAME].downcase + server = row[SERVER].nil? ? nil : row[SERVER].downcase + comment = row[COMMENT].nil? ? nil : row[COMMENT].downcase + + if name =~ /^.*#{search}.*$/ || server =~ /^.*#{search}.*$/ || comment =~ /^.*#{search}.*$/ + if (protocol.nil? || protocol.eql?(row[PROTOCOL])) && (group.nil? || group.eql?(row[GROUP])) + result.push(row) + end + end + end + + return result + end + + # Search in some csv data + # @args: id -> the id item + # @rtrn: a row with the resultat of the search + def search_by_id(id) + @data.each do |row| + if row[ID] == id + return row + end + end + + return Array.new() + end + + # Update an item + # @args: id -> the item's identifiant + # name -> the item name + # group -> the item group + # server -> the ip or hostname + # protocol -> the protocol + # login -> the login + # passwd -> the password + # port -> the port + # comment -> a comment + # @rtrn: true if the item has been updated + def update(name, group, server, protocol, login, passwd, port, comment, id=nil) + row = Array.new() + update = false + + i = 0 + @data.each do |r| + if r[ID] == id + row = r + update = true + break + end + i += 1 + end + + if port.to_i <= 0 + port = nil + end + + row_update = Array.new() + row_update[DATE] = Time.now.to_i + + row_update[ID] = id.nil? || id.empty? ? MPW.password(16) : id + row_update[NAME] = name.nil? || name.empty? ? row[NAME] : name + row_update[GROUP] = group.nil? || group.empty? ? row[GROUP] : group + row_update[SERVER] = server.nil? || server.empty? ? row[SERVER] : server + row_update[PROTOCOL] = protocol.nil? || protocol.empty? ? row[PROTOCOL] : protocol + row_update[LOGIN] = login.nil? || login.empty? ? row[LOGIN] : login + row_update[PASSWORD] = passwd.nil? || passwd.empty? ? row[PASSWORD] : passwd + row_update[PORT] = port.nil? || port.empty? ? row[PORT] : port + row_update[COMMENT] = comment.nil? || comment.empty? ? row[COMMENT] : comment + + row_update[] = row_update[NAME].nil? ? nil : row_update[NAME].force_encoding('ASCII-8BIT') + row_update[] = row_update[GROUP].nil? ? nil : row_update[GROUP].force_encoding('ASCII-8BIT') + row_update[] = row_update[SERVER].nil? ? nil : row_update[SERVER].force_encoding('ASCII-8BIT') + row_update[] = row_update[PROTOCOL].nil? ? nil : row_update[PROTOCOL].force_encoding('ASCII-8BIT') + row_update[] = row_update[LOGIN].nil? ? nil : row_update[LOGIN].force_encoding('ASCII-8BIT') + row_update[] = row_update[PASSWORD].nil? ? nil : row_update[PASSWORD].force_encoding('ASCII-8BIT') + row_update[] = row_update[COMMENT].nil? ? nil : row_update[COMMENT].force_encoding('ASCII-8BIT') + + if row_update[NAME].nil? || row_update[NAME].empty? + @error_msg = I18n.t('error.update.name_empty') + return false + end + + if update + @data[i] = row_update + else + @data.push(row_update) + end + + return true + end + + # Remove an item + # @args: id -> the item's identifiant + # @rtrn: true if the item has been deleted + def remove(id) + i = 0 + @data.each do |row| + if row[ID] == id + @data.delete_at(i) + return true + end + i += 1 + end + + @error_msg = I18n.t('error.delete.id_no_exist', :id => id) + return false + end + + # Export to csv + # @args: file -> a string to match + # @rtrn: true if export work + def export(file) + begin + File.open(file, 'w+') do |file| + @data.each do |row| + row.delete_at(ID).delete_at(DATE) + file << row.to_csv + end + end + + return true + rescue Exception => e + @error_msg = "#{I18n.t('error.export.write', :file => file)}\n#{e}" + return false + end + end + + # Import to csv + # @args: file -> path to file import + # @rtrn: true if the import work + def import(file) + begin + data_new = IO.read(file) + data_new.lines do |line| + if not line =~ /(.*,){6}/ + @error_msg = I18n.t('error.import.bad_format') + return false + else + row = line.parse_csv.unshift(0) + if not update(row[NAME], row[GROUP], row[SERVER], row[PROTOCOL], row[LOGIN], row[PASSWORD], row[PORT], row[COMMENT]) + return false + end + end + end + + return true + rescue Exception => e + @error_msg = "#{I18n.t('error.import.read', :file => file)}\n#{e}" + return false + end + end + + # Return a preview import + # @args: file -> path to file import + # @rtrn: an array with the items to import, if there is an error return false + def import_preview(file) + begin + result = Array.new() + id = 0 + + data = IO.read(file) + data.lines do |line| + if not line =~ /(.*,){6}/ + @error_msg = I18n.t('error.import.bad_format') + return false + else + result.push(line.parse_csv.unshift(id)) + end + + id += 1 + end + + return result + rescue Exception => e + @error_msg = "#{I18n.t('error.import.read', :file => file)}\n#{e}" + return false + end + end + + # Sync remote data and local data + # @args: data_remote -> array with the data remote + # last_update -> last update + # @rtrn: false if data_remote is nil + def sync(data_remote, last_update) + if !data_remote.instance_of?(Array) + return false + end + + @data.each do |l| + j = 0 + update = false + + # Update item + data_remote.each do |r| + if l[ID] == r[ID] + if l[DATE].to_i < r[DATE].to_i + update(r[NAME], r[GROUP], r[SERVER], r[PROTOCOL], r[LOGIN], r[PASSWORD], r[PORT], r[COMMENT], l[ID]) + end + update = true + data_remote.delete_at(j) + break + end + j += 1 + end + + # Delete an old item + if !update && l[DATE].to_i < last_update + remove(l[ID]) + end + end + + # Add item + data_remote.each do |r| + if r[DATE].to_i > last_update + update(r[NAME], r[GROUP], r[SERVER], r[PROTOCOL], r[LOGIN], r[PASSWORD], r[PORT], r[COMMENT], r[ID]) + end + end + + return encrypt() + end + + # Generate a random password + # @args: length -> the length password + # @rtrn: a random string + def self.password(length=8) + if length.to_i <= 0 + length = 8 + else + length = length.to_i + end + + result = '' + while length > 62 do + result << ([*('A'..'Z'),*('a'..'z'),*('0'..'9')]).sample(62).join + length -= 62 + end + result << ([*('A'..'Z'),*('a'..'z'),*('0'..'9')]).sample(length).join + + return result + end + end + +end diff --git a/MPW/Sync/MPW.rb b/MPW/Sync/MPW.rb new file mode 100644 index 0000000..da72e43 --- /dev/null +++ b/MPW/Sync/MPW.rb @@ -0,0 +1,130 @@ +#!/usr/bin/ruby +# author: nishiki +# mail: nishiki@yaegashi.fr +# info: a simple script who manage your passwords + +module MPW + + module Sync + + require 'rubygems' + require 'i18n' + require 'socket' + require 'json' + + class MPW + + attr_accessor :error_msg + attr_accessor :enable + + # Constructor + def initialize() + @error_msg = nil + @enable = false + end + + # Connect to server + # @args: host -> the server host + # port -> ther connection port + # gpg_key -> the gpg key + # password -> the remote password + # suffix -> the suffix file + # @rtrn: false if the connection fail + def connect(host, port, gpg_key, password, suffix=nil) + @gpg_key = gpg_key + @password = password + @suffix = suffix + + begin + @socket = TCPSocket.new(host, port) + @enable = true + rescue Exception => e + @error_msg = "#{I18n.t('error.sync.connection')}\n#{e}" + @enable = false + end + + return @enable + end + + # Get data on server + # @args: gpg_password -> the gpg password + # @rtrn: nil if nothing data or error + def get(gpg_password) + if !@enable + return nil + end + + send_msg = {:action => 'get', + :gpg_key => @gpg_key, + :password => @password, + :suffix => @suffix} + + @socket.puts send_msg.to_json + msg = JSON.parse(@socket.gets) + + if !defined?(msg['error']) + @error_msg = I18n.t('error.sync.communication') + return nil + elsif msg['error'].nil? + tmp_file = "/tmp/mpw-#{MPW.password()}.gpg" + File.open(tmp_file, 'w') do |file| + file << msg['data'] + end + + @mpw = MPW.new(tmp_file) + if !@mpw.decrypt(gpg_password) + puts @mpw.error_msg + return nil + end + + File.unlink(tmp_file) + return @mpw.search() + else + @error_msg = I18n.t(msg['error']) + return nil + end + + end + + # Update the remote data + # @args: data -> the data to send on server + # @rtrn: false if there is a problem + def update(data) + if !@enable + return true + end + + send_msg = {:action => 'update', + :gpg_key => @gpg_key, + :password => @password, + :suffix => @suffix, + :data => data} + + @socket.puts send_msg.to_json + msg = JSON.parse(@socket.gets) + + if !defined?(msg['error']) + @error_msg = I18n.t('error.sync.communication') + return false + elsif msg['error'].nil? + return true + else + @error_msg = I18n.t(msg['error']) + return false + end + end + + # Close the connection + def close() + if !@enable + return + end + + send_msg = {:action => 'close'} + @socket.puts send_msg.to_json + end + end + + end + +end diff --git a/lib/Cli.rb b/MPW/UI/Cli.rb similarity index 86% rename from lib/Cli.rb rename to MPW/UI/Cli.rb index 152f3bf..870c9a2 100644 --- a/lib/Cli.rb +++ b/MPW/UI/Cli.rb @@ -10,9 +10,8 @@ require 'readline' require 'i18n' require 'yaml' -require "#{APP_ROOT}/lib/MPW.rb" -require "#{APP_ROOT}/lib/MPWConfig.rb" -require "#{APP_ROOT}/lib/Sync.rb" +require "#{APP_ROOT}/MPW/MPW" +require "#{APP_ROOT}/MPW/Sync/MPW" class Cli @@ -32,7 +31,7 @@ class Cli # @rtnr: true if the synchro is finish def sync() if !defined?(@sync) - @sync = Sync.new() + @sync = MPW::Sync::MPW.new if !@config.sync_host.nil? && !@config.sync_port.nil? if !@sync.connect(@config.sync_host, @config.sync_port, @config.key, @config.sync_pwd, @config.sync_suffix) @@ -99,7 +98,7 @@ class Cli # Request the GPG password and decrypt the file def decrypt() if !defined?(@mpw) - @mpw = MPW.new(@config.file_gpg, @config.key) + @mpw = MPW::MPW.new(@config.file_gpg, @config.key) end @passwd = ask(I18n.t('display.gpg_password')) {|q| q.echo = false} @@ -132,30 +131,30 @@ class Cli # @args: item -> an array with the item information def displayFormat(item) puts '--------------------' - puts "Id: #{item[MPW::ID]}" - puts "#{I18n.t('display.name')}: #{item[MPW::NAME]}" - puts "#{I18n.t('display.group')}: #{item[MPW::GROUP]}" - puts "#{I18n.t('display.server')}: #{item[MPW::SERVER]}" - puts "#{I18n.t('display.protocol')}: #{item[MPW::PROTOCOL]}" - puts "#{I18n.t('display.login')}: #{item[MPW::LOGIN]}" - puts "#{I18n.t('display.password')}: #{item[MPW::PASSWORD]}" - puts "#{I18n.t('display.port')}: #{item[MPW::PORT]}" - puts "#{I18n.t('display.comment')}: #{item[MPW::COMMENT]}" + puts "Id: #{item[MPW::MPW::ID]}" + puts "#{I18n.t('display.name')}: #{item[MPW::MPW::NAME]}" + puts "#{I18n.t('display.group')}: #{item[MPW::MPW::GROUP]}" + puts "#{I18n.t('display.server')}: #{item[MPW::MPW::SERVER]}" + puts "#{I18n.t('display.protocol')}: #{item[MPW::MPW::PROTOCOL]}" + puts "#{I18n.t('display.login')}: #{item[MPW::MPW::LOGIN]}" + puts "#{I18n.t('display.password')}: #{item[MPW::MPW::PASSWORD]}" + puts "#{I18n.t('display.port')}: #{item[MPW::MPW::PORT]}" + puts "#{I18n.t('display.comment')}: #{item[MPW::MPW::COMMENT]}" end # Display an item in the alternative format # @args: item -> an array with the item information def displayFormatAlt(item) - port = item[MPW::PORT].nil? ? '' : ":#{item[MPW::PORT]}" + port = item[MPW::MPW::PORT].nil? ? '' : ":#{item[MPW::MPW::PORT]}" - if item[MPW::PASSWORD].nil? || item[MPW::PASSWORD].empty? - if item[MPW::LOGIN].include('@') - puts "# #{item[MPW::ID]} #{item[MPW::PROTOCOL]}://#{item[MPW::LOGIN]}@#{item[MPW::SERVER]}#{port}" + if item[MPW::MPW::PASSWORD].nil? || item[MPW::MPW::PASSWORD].empty? + if item[MPW::MPW::LOGIN].include('@') + puts "# #{item[MPW::MPW::ID]} #{item[MPW::MPW::PROTOCOL]}://#{item[MPW::MPW::LOGIN]}@#{item[MPW::MPW::SERVER]}#{port}" else - puts "# #{item[MPW::ID]} #{item[MPW::PROTOCOL]}://{#{item[MPW::LOGIN]}}@#{item[MPW::SERVER]}#{port}" + puts "# #{item[MPW::MPW::ID]} #{item[MPW::MPW::PROTOCOL]}://{#{item[MPW::MPW::LOGIN]}}@#{item[MPW::MPW::SERVER]}#{port}" end else - puts "# #{item[MPW::ID]} #{item[MPW::PROTOCOL]}://{#{item[MPW::LOGIN]}:#{item[MPW::PASSWORD]}}@#{item[MPW::SERVER]}#{port}" + puts "# #{item[MPW::MPW::ID]} #{item[MPW::MPW::PROTOCOL]}://{#{item[MPW::MPW::LOGIN]}:#{item[MPW::MPW::PASSWORD]}}@#{item[MPW::MPW::SERVER]}#{port}" end end @@ -193,14 +192,14 @@ class Cli if not row.empty? puts I18n.t('form.update.title') puts '--------------------' - name = ask(I18n.t('form.update.name' , :name => row[MPW::NAME])).to_s - group = ask(I18n.t('form.update.group' , :group => row[MPW::GROUP])).to_s - server = ask(I18n.t('form.update.server' , :server => row[MPW::SERVER])).to_s - protocol = ask(I18n.t('form.update.protocol', :protocol => row[MPW::PROTOCOL])).to_s - login = ask(I18n.t('form.update.login' , :login => row[MPW::LOGIN])).to_s + name = ask(I18n.t('form.update.name' , :name => row[MPW::MPW::NAME])).to_s + group = ask(I18n.t('form.update.group' , :group => row[MPW::MPW::GROUP])).to_s + server = ask(I18n.t('form.update.server' , :server => row[MPW::MPW::SERVER])).to_s + protocol = ask(I18n.t('form.update.protocol', :protocol => row[MPW::MPW::PROTOCOL])).to_s + login = ask(I18n.t('form.update.login' , :login => row[MPW::MPW::LOGIN])).to_s passwd = ask(I18n.t('form.update.password')).to_s - port = ask(I18n.t('form.update.port' , :port => row[MPW::PORT])).to_s - comment = ask(I18n.t('form.update.comment' , :comment => row[MPW::COMMENT])).to_s + port = ask(I18n.t('form.update.port' , :port => row[MPW::MPW::PORT])).to_s + comment = ask(I18n.t('form.update.comment' , :comment => row[MPW::MPW::COMMENT])).to_s if @mpw.update(name, group, server, protocol, login, passwd, port, comment, id) if @mpw.encrypt() diff --git a/lib/CliSSH.rb b/MPW/UI/CliSSH.rb similarity index 74% rename from lib/CliSSH.rb rename to MPW/UI/CliSSH.rb index ebcea04..9292ca8 100644 --- a/lib/CliSSH.rb +++ b/MPW/UI/CliSSH.rb @@ -3,7 +3,7 @@ # mail: nishiki@yaegashi.fr # info: a simple script who manage your passwords -require "#{APP_ROOT}/lib/Cli.rb" +require "#{APP_ROOT}/MPW/UI/Cli" class CliSSH < Cli @@ -16,11 +16,11 @@ class CliSSH < Cli if result.length > 0 result.each do |r| - server = @server.nil? ? r[MPW::SERVER] : @server - port = @port.nil? ? r[MPW::PORT] : @port - login = @login.nil? ? r[MPW::LOGIN] : @login + server = @server.nil? ? r[MPW::MPW::SERVER] : @server + port = @port.nil? ? r[MPW::MPW::PORT] : @port + login = @login.nil? ? r[MPW::MPW::LOGIN] : @login - passwd = r[MPW::PASSWORD] + passwd = r[MPW::MPW::PASSWORD] if port.nil? || port.empty? port = 22 diff --git a/lib/MPW.rb b/lib/MPW.rb deleted file mode 100644 index f82fcc2..0000000 --- a/lib/MPW.rb +++ /dev/null @@ -1,331 +0,0 @@ -#!/usr/bin/ruby -# author: nishiki -# mail: nishiki@yaegashi.fr -# info: a simple script who manage your passwords - -require 'rubygems' -require 'gpgme' -require 'csv' -require 'i18n' - -class MPW - - ID = 0 - NAME = 1 - GROUP = 2 - PROTOCOL = 3 - SERVER = 4 - LOGIN = 5 - PASSWORD = 6 - PORT = 7 - COMMENT = 8 - DATE = 9 - - attr_accessor :error_msg - - # Constructor - def initialize(file_gpg, key=nil) - @error_msg = nil - @file_gpg = file_gpg - @key = key - end - - # Decrypt a gpg file - # @args: password -> the GPG key password - # @rtrn: true if data has been decrypted - def decrypt(passwd=nil) - @data = Array.new - - begin - if File.exist?(@file_gpg) - crypto = GPGME::Crypto.new(:armor => true) - data_decrypt = crypto.decrypt(IO.read(@file_gpg), :password => passwd).read - - data_decrypt.lines do |line| - @data.push(line.parse_csv) - end - end - - return true - rescue Exception => e - @error_msg = "#{I18n.t('error.gpg_file.decrypt')}\n#{e}" - return false - end - end - - # Encrypt a file - # @rtrn: true if the file has been encrypted - def encrypt() - begin - crypto = GPGME::Crypto.new(:armor => true) - file_gpg = File.open(@file_gpg, 'w+') - - data_to_encrypt = '' - @data.each do |row| - data_to_encrypt << row.to_csv - end - - crypto.encrypt(data_to_encrypt, :recipients => @key, :output => file_gpg) - file_gpg.close - - return true - rescue Exception => e - @error_msg = "#{I18n.t('error.gpg_file.encrypt')}\n#{e}" - return false - end - end - - # Search in some csv data - # @args: search -> the string to search - # protocol -> the connection protocol (ssh, web, other) - # @rtrn: a list with the resultat of the search - def search(search='', group=nil, protocol=nil) - result = Array.new() - - if !search.nil? - search = search.downcase - end - search = search.force_encoding('ASCII-8BIT') - - @data.each do |row| - name = row[NAME].nil? ? nil : row[NAME].downcase - server = row[SERVER].nil? ? nil : row[SERVER].downcase - comment = row[COMMENT].nil? ? nil : row[COMMENT].downcase - - if name =~ /^.*#{search}.*$/ || server =~ /^.*#{search}.*$/ || comment =~ /^.*#{search}.*$/ - if (protocol.nil? || protocol.eql?(row[PROTOCOL])) && (group.nil? || group.eql?(row[GROUP])) - result.push(row) - end - end - end - - return result - end - - # Search in some csv data - # @args: id -> the id item - # @rtrn: a row with the resultat of the search - def search_by_id(id) - @data.each do |row| - if row[ID] == id - return row - end - end - - return Array.new() - end - - # Update an item - # @args: id -> the item's identifiant - # name -> the item name - # group -> the item group - # server -> the ip or hostname - # protocol -> the protocol - # login -> the login - # passwd -> the password - # port -> the port - # comment -> a comment - # @rtrn: true if the item has been updated - def update(name, group, server, protocol, login, passwd, port, comment, id=nil) - row = Array.new() - update = false - - i = 0 - @data.each do |r| - if r[ID] == id - row = r - update = true - break - end - i += 1 - end - - if port.to_i <= 0 - port = nil - end - - row_update = Array.new() - row_update[DATE] = Time.now.to_i - - row_update[ID] = id.nil? || id.empty? ? MPW.password(16) : id - row_update[NAME] = name.nil? || name.empty? ? row[NAME] : name - row_update[GROUP] = group.nil? || group.empty? ? row[GROUP] : group - row_update[SERVER] = server.nil? || server.empty? ? row[SERVER] : server - row_update[PROTOCOL] = protocol.nil? || protocol.empty? ? row[PROTOCOL] : protocol - row_update[LOGIN] = login.nil? || login.empty? ? row[LOGIN] : login - row_update[PASSWORD] = passwd.nil? || passwd.empty? ? row[PASSWORD] : passwd - row_update[PORT] = port.nil? || port.empty? ? row[PORT] : port - row_update[COMMENT] = comment.nil? || comment.empty? ? row[COMMENT] : comment - - row_update[] = row_update[NAME].nil? ? nil : row_update[NAME].force_encoding('ASCII-8BIT') - row_update[] = row_update[GROUP].nil? ? nil : row_update[GROUP].force_encoding('ASCII-8BIT') - row_update[] = row_update[SERVER].nil? ? nil : row_update[SERVER].force_encoding('ASCII-8BIT') - row_update[] = row_update[PROTOCOL].nil? ? nil : row_update[PROTOCOL].force_encoding('ASCII-8BIT') - row_update[] = row_update[LOGIN].nil? ? nil : row_update[LOGIN].force_encoding('ASCII-8BIT') - row_update[] = row_update[PASSWORD].nil? ? nil : row_update[PASSWORD].force_encoding('ASCII-8BIT') - row_update[] = row_update[COMMENT].nil? ? nil : row_update[COMMENT].force_encoding('ASCII-8BIT') - - if row_update[NAME].nil? || row_update[NAME].empty? - @error_msg = I18n.t('error.update.name_empty') - return false - end - - if update - @data[i] = row_update - else - @data.push(row_update) - end - - return true - end - - # Remove an item - # @args: id -> the item's identifiant - # @rtrn: true if the item has been deleted - def remove(id) - i = 0 - @data.each do |row| - if row[ID] == id - @data.delete_at(i) - return true - end - i += 1 - end - - @error_msg = I18n.t('error.delete.id_no_exist', :id => id) - return false - end - - # Export to csv - # @args: file -> a string to match - # @rtrn: true if export work - def export(file) - begin - File.open(file, 'w+') do |file| - @data.each do |row| - row.delete_at(ID).delete_at(DATE) - file << row.to_csv - end - end - - return true - rescue Exception => e - @error_msg = "#{I18n.t('error.export.write', :file => file)}\n#{e}" - return false - end - end - - # Import to csv - # @args: file -> path to file import - # @rtrn: true if the import work - def import(file) - begin - data_new = IO.read(file) - data_new.lines do |line| - if not line =~ /(.*,){6}/ - @error_msg = I18n.t('error.import.bad_format') - return false - else - row = line.parse_csv.unshift(0) - if not update(row[NAME], row[GROUP], row[SERVER], row[PROTOCOL], row[LOGIN], row[PASSWORD], row[PORT], row[COMMENT]) - return false - end - end - end - - return true - rescue Exception => e - @error_msg = "#{I18n.t('error.import.read', :file => file)}\n#{e}" - return false - end - end - - # Return a preview import - # @args: file -> path to file import - # @rtrn: an array with the items to import, if there is an error return false - def import_preview(file) - begin - result = Array.new() - id = 0 - - data = IO.read(file) - data.lines do |line| - if not line =~ /(.*,){6}/ - @error_msg = I18n.t('error.import.bad_format') - return false - else - result.push(line.parse_csv.unshift(id)) - end - - id += 1 - end - - return result - rescue Exception => e - @error_msg = "#{I18n.t('error.import.read', :file => file)}\n#{e}" - return false - end - end - - # Sync remote data and local data - # @args: data_remote -> array with the data remote - # last_update -> last update - # @rtrn: false if data_remote is nil - def sync(data_remote, last_update) - if !data_remote.instance_of?(Array) - return false - end - - @data.each do |l| - j = 0 - update = false - - # Update item - data_remote.each do |r| - if l[ID] == r[ID] - if l[DATE].to_i < r[DATE].to_i - update(r[NAME], r[GROUP], r[SERVER], r[PROTOCOL], r[LOGIN], r[PASSWORD], r[PORT], r[COMMENT], l[ID]) - end - update = true - data_remote.delete_at(j) - break - end - j += 1 - end - - # Delete an old item - if !update && l[DATE].to_i < last_update - remove(l[ID]) - end - end - - # Add item - data_remote.each do |r| - if r[DATE].to_i > last_update - update(r[NAME], r[GROUP], r[SERVER], r[PROTOCOL], r[LOGIN], r[PASSWORD], r[PORT], r[COMMENT], r[ID]) - end - end - - return encrypt() - end - - # Generate a random password - # @args: length -> the length password - # @rtrn: a random string - def self.password(length=8) - if length.to_i <= 0 - length = 8 - else - length = length.to_i - end - - result = '' - while length > 62 do - result << ([*('A'..'Z'),*('a'..'z'),*('0'..'9')]).sample(62).join - length -= 62 - end - result << ([*('A'..'Z'),*('a'..'z'),*('0'..'9')]).sample(length).join - - return result - end -end diff --git a/lib/MPWConfig.rb b/lib/MPWConfig.rb deleted file mode 100644 index bce49e6..0000000 --- a/lib/MPWConfig.rb +++ /dev/null @@ -1,136 +0,0 @@ -#!/usr/bin/ruby -# author: nishiki -# mail: nishiki@yaegashi.fr -# info: a simple script who manage your passwords - -require 'rubygems' -require 'yaml' -require 'i18n' - -class MPWConfig - - attr_accessor :error_msg - - attr_accessor :key - attr_accessor :lang - attr_accessor :file_gpg - attr_accessor :timeout_pwd - attr_accessor :last_update - attr_accessor :sync_host - attr_accessor :sync_port - attr_accessor :sync_pwd - attr_accessor :sync_suffix - attr_accessor :last_update - - # Constructor - # @args: file_config -> the specify config file - def initialize(file_config=nil) - @error_msg = nil - @file_config = "#{Dir.home()}/.mpw.cfg" - - if !file_config.nil? && !file_config.empty? - @file_config = file_config - end - end - - # Create a new config file - # @args: key -> the gpg key to encrypt - # lang -> the software language - # file_gpg -> the file who is encrypted - # timeout_pwd -> time to save the password - # sync_host -> the server host for synchronization - # sync_port -> the server port for synchronization - # sync_pwd -> the password for synchronization - # sync_suffix -> the suffix file (optionnal) - # @rtrn: true if le config file is create - def setup(key, lang, file_gpg, timeout_pwd, sync_host=nil, sync_port=nil, sync_pwd=nil, sync_suffix=nil) - - if not key =~ /[a-zA-Z0-9.-_]+\@[a-zA-Z0-9]+\.[a-zA-Z]+/ - @error_msg = I18n.t('error.config.key_bad_format') - return false - end - - if file_gpg.empty? - file_gpg = "#{Dir.home()}/.mpw.gpg" - end - - timeout_pwd = timeout_pwd.empty? ? 60 : timeout_pwd.to_i - - config = {'config' => {'key' => key, - 'lang' => lang, - 'file_gpg' => file_gpg, - 'timeout_pwd' => timeout_pwd, - 'sync_host' => sync_host, - 'sync_port' => sync_port, - 'sync_pwd' => sync_pwd, - 'sync_suffix' => sync_suffix, - 'last_update' => 0 }} - - begin - File.open(@file_config, 'w') do |file| - file << config.to_yaml - end - rescue Exception => e - @error_msg = "#{I18n.t('error.config.write')}\n#{e}" - return false - end - - return true - end - - # Check the config file - # @rtrn: true if the config file is correct - def checkconfig() - begin - config = YAML::load_file(@file_config) - @key = config['config']['key'] - @lang = config['config']['lang'] - @file_gpg = config['config']['file_gpg'] - @timeout_pwd = config['config']['timeout_pwd'].to_i - @sync_host = config['config']['sync_host'] - @sync_port = config['config']['sync_port'] - @sync_pwd = config['config']['sync_pwd'] - @sync_suffix = config['config']['sync_suffix'] - @last_update = config['config']['last_update'].to_i - - if @key.empty? || @file_gpg.empty? - @error_msg = I18n.t('error.config.check') - return false - end - - I18n.locale = @lang.to_sym - - rescue Exception => e - @error_msg = "#{I18n.t('error.config.check')}\n#{e}" - return false - end - - return true - end - - # Set the last update when there is a sync - # @rtrn: true is the file has been updated - def set_last_update() - config = {'config' => {'key' => @key, - 'lang' => @lang, - 'file_gpg' => @file_gpg, - 'timeout_pwd' => @timeout_pwd, - 'sync_host' => @sync_host, - 'sync_port' => @sync_port, - 'sync_pwd' => @sync_pwd, - 'sync_suffix' => @sync_suffix, - 'last_update' => Time.now.to_i }} - - begin - File.open(@file_config, 'w') do |file| - file << config.to_yaml - end - rescue Exception => e - @error_msg = "#{I18n.t('error.config.write')}\n#{e}" - return false - end - - return true - end - -end diff --git a/lib/Sync.rb b/lib/Sync.rb deleted file mode 100644 index e85b0ce..0000000 --- a/lib/Sync.rb +++ /dev/null @@ -1,128 +0,0 @@ -#!/usr/bin/ruby -# author: nishiki -# mail: nishiki@yaegashi.fr -# info: a simple script who manage your passwords - -require 'rubygems' -require 'i18n' -require 'socket' -require 'json' - -require "#{APP_ROOT}/lib/MPW.rb" - -class Sync - - attr_accessor :error_msg - attr_accessor :enable - - # Constructor - def initialize() - @error_msg = nil - @enable = false - end - - # Connect to server - # @args: host -> the server host - # port -> ther connection port - # gpg_key -> the gpg key - # password -> the remote password - # suffix -> the suffix file - # @rtrn: false if the connection fail - def connect(host, port, gpg_key, password, suffix=nil) - @gpg_key = gpg_key - @password = password - @suffix = suffix - - begin - @socket = TCPSocket.new(host, port) - @enable = true - rescue Exception => e - @error_msg = "#{I18n.t('error.sync.connection')}\n#{e}" - @enable = false - end - - return @enable - end - - # Get data on server - # @args: gpg_password -> the gpg password - # @rtrn: nil if nothing data or error - def get(gpg_password) - if !@enable - return nil - end - - send_msg = {:action => 'get', - :gpg_key => @gpg_key, - :password => @password, - :suffix => @suffix} - - @socket.puts send_msg.to_json - msg = JSON.parse(@socket.gets) - - if !defined?(msg['error']) - @error_msg = I18n.t('error.sync.communication') - return nil - elsif msg['error'].nil? - tmp_file = "/tmp/mpw-#{MPW.password()}.gpg" - File.open(tmp_file, 'w') do |file| - file << msg['data'] - end - - @mpw = MPW.new(tmp_file) - if !@mpw.decrypt(gpg_password) - puts @mpw.error_msg - return nil - end - - File.unlink(tmp_file) - return @mpw.search() - else - @error_msg = I18n.t(msg['error']) - return nil - end - - end - - # Update the remote data - # @args: data -> the data to send on server - # @rtrn: false if there is a problem - def update(data) - if !@enable - return true - end - - send_msg = {:action => 'update', - :gpg_key => @gpg_key, - :password => @password, - :suffix => @suffix, - :data => data} - - @socket.puts send_msg.to_json - msg = JSON.parse(@socket.gets) - - if !defined?(msg['error']) - @error_msg = I18n.t('error.sync.communication') - return false - elsif msg['error'].nil? - return true - else - @error_msg = I18n.t(msg['error']) - return false - end - end - - # TODO - def delete() - end - - # Close the connection - def close() - if !@enable - return - end - - send_msg = {:action => 'close'} - @socket.puts send_msg.to_json - end -end diff --git a/mpw b/mpw index ff27575..ae59416 100755 --- a/mpw +++ b/mpw @@ -10,8 +10,8 @@ require 'locale' require 'i18n' APP_ROOT = File.dirname(Pathname.new(__FILE__).realpath) -require "#{APP_ROOT}/lib/Cli.rb" -require "#{APP_ROOT}/lib/MPW.rb" +require "#{APP_ROOT}/MPW/UI/Cli" +require "#{APP_ROOT}/MPW/Config" lang = Locale::Tag.parse(ENV['LANG']).to_simple.to_s[0..1] @@ -93,7 +93,7 @@ OptionParser.new do |opts| end end.parse! -config = MPWConfig.new(options[:config]) +config = MPW::Config.new(options[:config]) check_error = config.checkconfig() cli = Cli.new(lang, config) diff --git a/mpw-ssh b/mpw-ssh index 39fe1b3..9ba3791 100755 --- a/mpw-ssh +++ b/mpw-ssh @@ -10,7 +10,8 @@ require 'locale' require 'i18n' APP_ROOT = File.dirname(Pathname.new(__FILE__).realpath) -require "#{APP_ROOT}/lib/CliSSH.rb" +require "#{APP_ROOT}/MPW/UI/CliSSH" +require "#{APP_ROOT}/MPW/Config" lang = Locale::Tag.parse(ENV['LANG']).to_simple.to_s[0..1] @@ -45,7 +46,7 @@ OptionParser.new do |opts| end end.parse! -config = MPWConfig.new(options[:config]) +config = MPW::Config.new(options[:config]) check_error = config.checkconfig() cli = CliSSH.new(lang, config) From 1ab3c7e0b0ac69cff28b5f56a209426c9c1791a1 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Wed, 29 Jan 2014 22:49:13 +0100 Subject: [PATCH 051/531] change rescue --- MPW/Sync/MPW.rb | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/MPW/Sync/MPW.rb b/MPW/Sync/MPW.rb index da72e43..054fa28 100644 --- a/MPW/Sync/MPW.rb +++ b/MPW/Sync/MPW.rb @@ -35,14 +35,12 @@ module MPW @password = password @suffix = suffix - begin - @socket = TCPSocket.new(host, port) - @enable = true - rescue Exception => e - @error_msg = "#{I18n.t('error.sync.connection')}\n#{e}" - @enable = false - end - + @socket = TCPSocket.new(host, port) + @enable = true + rescue Exception => e + @error_msg = "#{I18n.t('error.sync.connection')}\n#{e}" + @enable = false + else return @enable end From 83f935dc21affca1ca636e7ab3a3c12d0d520166 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Wed, 29 Jan 2014 23:10:35 +0100 Subject: [PATCH 052/531] beautiful code --- MPW/Sync/MPW.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MPW/Sync/MPW.rb b/MPW/Sync/MPW.rb index 054fa28..14a43c5 100644 --- a/MPW/Sync/MPW.rb +++ b/MPW/Sync/MPW.rb @@ -18,7 +18,7 @@ module MPW attr_accessor :enable # Constructor - def initialize() + def initialize @error_msg = nil @enable = false end @@ -113,7 +113,7 @@ module MPW end # Close the connection - def close() + def close if !@enable return end From 8ac531ffedf37e3bf1fdcdc614f0f7ccdb8f08c9 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Wed, 29 Jan 2014 23:11:01 +0100 Subject: [PATCH 053/531] add Sync/SSH --- MPW/Sync/SSH.rb | 107 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 107 insertions(+) create mode 100644 MPW/Sync/SSH.rb diff --git a/MPW/Sync/SSH.rb b/MPW/Sync/SSH.rb new file mode 100644 index 0000000..b63d912 --- /dev/null +++ b/MPW/Sync/SSH.rb @@ -0,0 +1,107 @@ +#!/usr/bin/ruby +# author: nishiki +# mail: nishiki@yaegashi.fr +# info: a simple script who manage your passwords + +module MPW + + module Sync + + require 'rubygems' + require 'i18n' + + class MPW + + attr_accessor :error_msg + attr_accessor :enable + + # Constructor + def initialize + @error_msg = nil + @enable = false + end + + # Connect to server + # @args: host -> the server host + # port -> ther connection port + # gpg_key -> the gpg key + # password -> the remote password + # suffix -> the suffix file + # @rtrn: false if the connection fail + def connect(host, user, password, path, port=nil) + @host = host + @user = user + @password = password + @path = path + @port = port.nil? || port.empty? ? 22 : port.to_i + + Net::SSH.start(@host, @user, :password => @password, :port => @port) do + end + rescue + @error_msg = "#{I18n.t('error.sync.connection')}\n#{e}" + @enable = false + else + + return @enable + end + + # Get data on server + # @args: gpg_password -> the gpg password + # @rtrn: nil if nothing data or error + def get(gpg_password) + if !@enable + return nil + end + + tmp_file = "/tmp/mpw-#{MPW.password()}.gpg" + Net::SCP.start(@host, @user, :password => @password, :port => @port) do |ssh| + ssh.scp.download(@path, tmp_file) + end + + File.open(tmp_file, 'w') do |file| + file << msg['data'] + end + + @mpw = MPW.new(tmp_file) + if !@mpw.decrypt(gpg_password) + puts @mpw.error_msg + return nil + end + + File.unlink(tmp_file) + + return @mpw.search() + rescue Exception => e + @error_msg = "#{I18n.t('error.sync.download')}\n#{e}" + return nil + end + + # Update the remote data + # @args: data -> the data to send on server + # @rtrn: false if there is a problem + def update(data) + if !@enable + return true + end + + tmp_file = "/tmp/mpw-#{MPW.password()}.gpg" + Net::SCP.start(@host, @user, :password => @password, :port => @port) do |ssh| + ssh.scp.upload(tmp_file, @path) + end + + File.unlink(tmp_file) + + return true + rescue Exception => e + @error_msg = "#{I18n.t('error.sync.upload')}\n#{e}" + return false + end + + # Close the connection + def close + end + end + + end + +end From 958792801ecb21b27209f98fd49dec6db7762e86 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Thu, 30 Jan 2014 23:08:38 +0100 Subject: [PATCH 054/531] recode for multiple protocol to sync --- MPW/Config.rb | 89 ++++++++++++++-------------- MPW/MPW.rb | 154 ++++++++++++++++++++++-------------------------- MPW/Sync/MPW.rb | 33 +++++++---- MPW/Sync/SSH.rb | 24 +++++--- MPW/UI/Cli.rb | 51 ++++++++-------- 5 files changed, 183 insertions(+), 168 deletions(-) diff --git a/MPW/Config.rb b/MPW/Config.rb index 74d309c..92a58fd 100644 --- a/MPW/Config.rb +++ b/MPW/Config.rb @@ -18,10 +18,12 @@ module MPW attr_accessor :file_gpg attr_accessor :timeout_pwd attr_accessor :last_update + attr_accessor :sync_type attr_accessor :sync_host attr_accessor :sync_port + attr_accessor :sync_user attr_accessor :sync_pwd - attr_accessor :sync_suffix + attr_accessor :sync_path attr_accessor :last_update # Constructor @@ -40,12 +42,14 @@ module MPW # lang -> the software language # file_gpg -> the file who is encrypted # timeout_pwd -> time to save the password + # sync_type -> the type to synchronization # sync_host -> the server host for synchronization # sync_port -> the server port for synchronization + # sync_user -> the user for synchronization # sync_pwd -> the password for synchronization # sync_suffix -> the suffix file (optionnal) # @rtrn: true if le config file is create - def setup(key, lang, file_gpg, timeout_pwd, sync_host=nil, sync_port=nil, sync_pwd=nil, sync_suffix=nil) + def setup(key, lang, file_gpg, timeout_pwd, sync_type=nil, sync_host=nil, sync_port=nil, sync_user=nil, sync_pwd=nil, sync_path=nil) if not key =~ /[a-zA-Z0-9.-_]+\@[a-zA-Z0-9]+\.[a-zA-Z]+/ @error_msg = I18n.t('error.config.key_bad_format') @@ -62,77 +66,76 @@ module MPW 'lang' => lang, 'file_gpg' => file_gpg, 'timeout_pwd' => timeout_pwd, + 'sync_type' => sync_type, 'sync_host' => sync_host, 'sync_port' => sync_port, + 'sync_user' => sync_user, 'sync_pwd' => sync_pwd, - 'sync_suffix' => sync_suffix, + 'sync_path' => sync_path, 'last_update' => 0 }} - begin - File.open(@file_config, 'w') do |file| - file << config.to_yaml - end - rescue Exception => e - @error_msg = "#{I18n.t('error.config.write')}\n#{e}" - return false + File.open(@file_config, 'w') do |file| + file << config.to_yaml end - + return true + rescue Exception => e + @error_msg = "#{I18n.t('error.config.write')}\n#{e}" + return false end # Check the config file # @rtrn: true if the config file is correct def checkconfig() - begin - config = YAML::load_file(@file_config) - @key = config['config']['key'] - @lang = config['config']['lang'] - @file_gpg = config['config']['file_gpg'] - @timeout_pwd = config['config']['timeout_pwd'].to_i - @sync_host = config['config']['sync_host'] - @sync_port = config['config']['sync_port'] - @sync_pwd = config['config']['sync_pwd'] - @sync_suffix = config['config']['sync_suffix'] - @last_update = config['config']['last_update'].to_i - - if @key.empty? || @file_gpg.empty? - @error_msg = I18n.t('error.config.check') - return false - end - - I18n.locale = @lang.to_sym - - rescue Exception => e - @error_msg = "#{I18n.t('error.config.check')}\n#{e}" + config = YAML::load_file(@file_config) + @key = config['config']['key'] + @lang = config['config']['lang'] + @file_gpg = config['config']['file_gpg'] + @timeout_pwd = config['config']['timeout_pwd'].to_i + @sync_type = config['config']['sync_type'] + @sync_host = config['config']['sync_host'] + @sync_port = config['config']['sync_port'] + @sync_user = config['config']['sync_user'] + @sync_pwd = config['config']['sync_pwd'] + @sync_path = config['config']['sync_path'] + @last_update = config['config']['last_update'].to_i + + if @key.empty? || @file_gpg.empty? + @error_msg = I18n.t('error.config.check') return false end - + + I18n.locale = @lang.to_sym + return true + rescue Exception => e + @error_msg = "#{I18n.t('error.config.check')}\n#{e}" + return false end # Set the last update when there is a sync # @rtrn: true is the file has been updated - def set_last_update() + def set_last_update config = {'config' => {'key' => @key, 'lang' => @lang, 'file_gpg' => @file_gpg, 'timeout_pwd' => @timeout_pwd, + 'sync_type' => @sync_type, 'sync_host' => @sync_host, 'sync_port' => @sync_port, + 'sync_user' => @sync_user, 'sync_pwd' => @sync_pwd, - 'sync_suffix' => @sync_suffix, + 'sync_path' => @sync_path, 'last_update' => Time.now.to_i }} - begin - File.open(@file_config, 'w') do |file| - file << config.to_yaml - end - rescue Exception => e - @error_msg = "#{I18n.t('error.config.write')}\n#{e}" - return false + File.open(@file_config, 'w') do |file| + file << config.to_yaml end - + return true + rescue Exception => e + @error_msg = "#{I18n.t('error.config.write')}\n#{e}" + return false end end diff --git a/MPW/MPW.rb b/MPW/MPW.rb index 1f84400..c57b696 100644 --- a/MPW/MPW.rb +++ b/MPW/MPW.rb @@ -36,45 +36,41 @@ module MPW # @args: password -> the GPG key password # @rtrn: true if data has been decrypted def decrypt(passwd=nil) - @data = Array.new + @data = [] - begin - if File.exist?(@file_gpg) - crypto = GPGME::Crypto.new(:armor => true) - data_decrypt = crypto.decrypt(IO.read(@file_gpg), :password => passwd).read + if File.exist?(@file_gpg) + crypto = GPGME::Crypto.new(:armor => true) + data_decrypt = crypto.decrypt(IO.read(@file_gpg), :password => passwd).read - data_decrypt.lines do |line| - @data.push(line.parse_csv) - end + data_decrypt.lines do |line| + @data.push(line.parse_csv) end - - return true - rescue Exception => e - @error_msg = "#{I18n.t('error.gpg_file.decrypt')}\n#{e}" - return false end + + return true + rescue Exception => e + @error_msg = "#{I18n.t('error.gpg_file.decrypt')}\n#{e}" + return false end # Encrypt a file # @rtrn: true if the file has been encrypted - def encrypt() - begin - crypto = GPGME::Crypto.new(:armor => true) - file_gpg = File.open(@file_gpg, 'w+') + def encrypt + crypto = GPGME::Crypto.new(:armor => true) + file_gpg = File.open(@file_gpg, 'w+') - data_to_encrypt = '' - @data.each do |row| - data_to_encrypt << row.to_csv - end - - crypto.encrypt(data_to_encrypt, :recipients => @key, :output => file_gpg) - file_gpg.close - - return true - rescue Exception => e - @error_msg = "#{I18n.t('error.gpg_file.encrypt')}\n#{e}" - return false + data_to_encrypt = '' + @data.each do |row| + data_to_encrypt << row.to_csv end + + crypto.encrypt(data_to_encrypt, :recipients => @key, :output => file_gpg) + file_gpg.close + + return true + rescue Exception => e + @error_msg = "#{I18n.t('error.gpg_file.encrypt')}\n#{e}" + return false end # Search in some csv data @@ -159,13 +155,13 @@ module MPW row_update[PORT] = port.nil? || port.empty? ? row[PORT] : port row_update[COMMENT] = comment.nil? || comment.empty? ? row[COMMENT] : comment - row_update[] = row_update[NAME].nil? ? nil : row_update[NAME].force_encoding('ASCII-8BIT') - row_update[] = row_update[GROUP].nil? ? nil : row_update[GROUP].force_encoding('ASCII-8BIT') - row_update[] = row_update[SERVER].nil? ? nil : row_update[SERVER].force_encoding('ASCII-8BIT') - row_update[] = row_update[PROTOCOL].nil? ? nil : row_update[PROTOCOL].force_encoding('ASCII-8BIT') - row_update[] = row_update[LOGIN].nil? ? nil : row_update[LOGIN].force_encoding('ASCII-8BIT') - row_update[] = row_update[PASSWORD].nil? ? nil : row_update[PASSWORD].force_encoding('ASCII-8BIT') - row_update[] = row_update[COMMENT].nil? ? nil : row_update[COMMENT].force_encoding('ASCII-8BIT') + row_update[NAME] = row_update[NAME].nil? ? nil : row_update[NAME].force_encoding('ASCII-8BIT') + row_update[GROUP] = row_update[GROUP].nil? ? nil : row_update[GROUP].force_encoding('ASCII-8BIT') + row_update[SERVER] = row_update[SERVER].nil? ? nil : row_update[SERVER].force_encoding('ASCII-8BIT') + row_update[PROTOCOL] = row_update[PROTOCOL].nil? ? nil : row_update[PROTOCOL].force_encoding('ASCII-8BIT') + row_update[LOGIN] = row_update[LOGIN].nil? ? nil : row_update[LOGIN].force_encoding('ASCII-8BIT') + row_update[PASSWORD] = row_update[PASSWORD].nil? ? nil : row_update[PASSWORD].force_encoding('ASCII-8BIT') + row_update[COMMENT] = row_update[COMMENT].nil? ? nil : row_update[COMMENT].force_encoding('ASCII-8BIT') if row_update[NAME].nil? || row_update[NAME].empty? @error_msg = I18n.t('error.update.name_empty') @@ -202,71 +198,65 @@ module MPW # @args: file -> a string to match # @rtrn: true if export work def export(file) - begin - File.open(file, 'w+') do |file| - @data.each do |row| - row.delete_at(ID).delete_at(DATE) - file << row.to_csv - end + File.open(file, 'w+') do |file| + @data.each do |row| + row.delete_at(ID).delete_at(DATE) + file << row.to_csv end - - return true - rescue Exception => e - @error_msg = "#{I18n.t('error.export.write', :file => file)}\n#{e}" - return false end + + return true + rescue Exception => e + @error_msg = "#{I18n.t('error.export.write', :file => file)}\n#{e}" + return false end # Import to csv # @args: file -> path to file import # @rtrn: true if the import work def import(file) - begin - data_new = IO.read(file) - data_new.lines do |line| - if not line =~ /(.*,){6}/ - @error_msg = I18n.t('error.import.bad_format') + data_new = IO.read(file) + data_new.lines do |line| + if not line =~ /(.*,){6}/ + @error_msg = I18n.t('error.import.bad_format') + return false + else + row = line.parse_csv.unshift(0) + if not update(row[NAME], row[GROUP], row[SERVER], row[PROTOCOL], row[LOGIN], row[PASSWORD], row[PORT], row[COMMENT]) return false - else - row = line.parse_csv.unshift(0) - if not update(row[NAME], row[GROUP], row[SERVER], row[PROTOCOL], row[LOGIN], row[PASSWORD], row[PORT], row[COMMENT]) - return false - end end end - - return true - rescue Exception => e - @error_msg = "#{I18n.t('error.import.read', :file => file)}\n#{e}" - return false end + + return true + rescue Exception => e + @error_msg = "#{I18n.t('error.import.read', :file => file)}\n#{e}" + return false end # Return a preview import # @args: file -> path to file import # @rtrn: an array with the items to import, if there is an error return false def import_preview(file) - begin - result = Array.new() - id = 0 - - data = IO.read(file) - data.lines do |line| - if not line =~ /(.*,){6}/ - @error_msg = I18n.t('error.import.bad_format') - return false - else - result.push(line.parse_csv.unshift(id)) - end - - id += 1 + result = Array.new() + id = 0 + + data = IO.read(file) + data.lines do |line| + if not line =~ /(.*,){6}/ + @error_msg = I18n.t('error.import.bad_format') + return false + else + result.push(line.parse_csv.unshift(id)) end - - return result - rescue Exception => e - @error_msg = "#{I18n.t('error.import.read', :file => file)}\n#{e}" - return false + + id += 1 end + + return result + rescue Exception => e + @error_msg = "#{I18n.t('error.import.read', :file => file)}\n#{e}" + return false end # Sync remote data and local data @@ -308,7 +298,7 @@ module MPW end end - return encrypt() + return encrypt end # Generate a random password diff --git a/MPW/Sync/MPW.rb b/MPW/Sync/MPW.rb index 14a43c5..d0462a8 100644 --- a/MPW/Sync/MPW.rb +++ b/MPW/Sync/MPW.rb @@ -12,7 +12,7 @@ module MPW require 'socket' require 'json' - class MPW + class MPWSync attr_accessor :error_msg attr_accessor :enable @@ -30,12 +30,12 @@ module MPW # password -> the remote password # suffix -> the suffix file # @rtrn: false if the connection fail - def connect(host, port, gpg_key, password, suffix=nil) - @gpg_key = gpg_key + def connect(host, user, password, path, port=nil) + @gpg_key = user @password = password - @suffix = suffix + @suffix = path - @socket = TCPSocket.new(host, port) + @socket = TCPSocket.new(host, port.to_i) @enable = true rescue Exception => e @error_msg = "#{I18n.t('error.sync.connection')}\n#{e}" @@ -64,24 +64,23 @@ module MPW @error_msg = I18n.t('error.sync.communication') return nil elsif msg['error'].nil? - tmp_file = "/tmp/mpw-#{MPW.password()}.gpg" + tmp_file = tmpfile File.open(tmp_file, 'w') do |file| file << msg['data'] end - @mpw = MPW.new(tmp_file) - if !@mpw.decrypt(gpg_password) - puts @mpw.error_msg + mpw = MPW.new(tmp_file) + if !mpw.decrypt(gpg_password) + @error_msg = mpw.error_msg return nil end - + File.unlink(tmp_file) - return @mpw.search() + return mpw.search else @error_msg = I18n.t(msg['error']) return nil end - end # Update the remote data @@ -121,6 +120,16 @@ module MPW send_msg = {:action => 'close'} @socket.puts send_msg.to_json end + + # Generate a random string + # @rtrn: a random string + def tmpfile + result = '' + result << ([*('A'..'Z'),*('a'..'z'),*('0'..'9')]).sample(6).join + + return "/tmp/mpw-#{result}" + end + end end diff --git a/MPW/Sync/SSH.rb b/MPW/Sync/SSH.rb index b63d912..bd92fc6 100644 --- a/MPW/Sync/SSH.rb +++ b/MPW/Sync/SSH.rb @@ -41,7 +41,6 @@ module MPW @error_msg = "#{I18n.t('error.sync.connection')}\n#{e}" @enable = false else - return @enable end @@ -53,7 +52,7 @@ module MPW return nil end - tmp_file = "/tmp/mpw-#{MPW.password()}.gpg" + tmp_file = tmpfile Net::SCP.start(@host, @user, :password => @password, :port => @port) do |ssh| ssh.scp.download(@path, tmp_file) end @@ -62,15 +61,14 @@ module MPW file << msg['data'] end - @mpw = MPW.new(tmp_file) - if !@mpw.decrypt(gpg_password) - puts @mpw.error_msg + mpw = MPW.new(tmp_file) + if !mpw.decrypt(gpg_password) + @error_msg = mpw.error_msg return nil end File.unlink(tmp_file) - - return @mpw.search() + return mpw.search rescue Exception => e @error_msg = "#{I18n.t('error.sync.download')}\n#{e}" return nil @@ -84,7 +82,7 @@ module MPW return true end - tmp_file = "/tmp/mpw-#{MPW.password()}.gpg" + tmp_file = tmpfile Net::SCP.start(@host, @user, :password => @password, :port => @port) do |ssh| ssh.scp.upload(tmp_file, @path) end @@ -100,6 +98,16 @@ module MPW # Close the connection def close end + + # Generate a random string + # @rtrn: a random string + def tmpfile + result = '' + result << ([*('A'..'Z'),*('a'..'z'),*('0'..'9')]).sample(6).join + + return "/tmp/mpw-#{result}" + end + end end diff --git a/MPW/UI/Cli.rb b/MPW/UI/Cli.rb index 870c9a2..1b0ce0b 100644 --- a/MPW/UI/Cli.rb +++ b/MPW/UI/Cli.rb @@ -23,39 +23,44 @@ class Cli end # Close sync - def sync_close() - @sync.close() + def sync_close + @sync.close end # Sync the data with the server # @rtnr: true if the synchro is finish - def sync() + def sync if !defined?(@sync) - @sync = MPW::Sync::MPW.new - - if !@config.sync_host.nil? && !@config.sync_port.nil? - if !@sync.connect(@config.sync_host, @config.sync_port, @config.key, @config.sync_pwd, @config.sync_suffix) - puts "#{I18n.t('display.error')}: #{@sync.error_msg}" - end + case @config.sync_type + when 'mpw' + @sync = MPW::Sync::MPWSync.new + when 'sftp', 'scp', 'ssh' + @sync = MPW::Sync::SSH.new + else + return false end end - begin - if @sync.enable - if !@mpw.sync(@sync.get(@passwd), @config.last_update) - puts "#{I18n.t('display.error')}: #{@mpw.error_msg}" - elsif !@sync.update(File.open(@config.file_gpg).read) - puts "#{I18n.t('display.error')}: #{@sync.error_msg}" - elsif !@config.set_last_update() - puts "#{I18n.t('display.error')}: #{@config.error_msg}" - else - return true - end + if !@config.sync_host.nil? && !@config.sync_port.nil? + if !@sync.connect(@config.sync_host, @config.sync_user, @config.sync_pwd, @config.sync_path, @config.sync_port) + puts "#{I18n.t('display.error')}: #{@sync.error_msg}" end - rescue Exception => e - puts "#{I18n.t('display.error')}: #{e}" end + if @sync.enable + if !@mpw.sync(@sync.get(@passwd), @config.last_update) + puts "#{I18n.t('display.error')}: #{@sync.error_msg}" + elsif !@sync.update(File.open(@config.file_gpg).read) + puts "#{I18n.t('display.error')}: #{@sync.error_msg}" + elsif !@config.set_last_update + puts "#{I18n.t('display.error')}: #{@config.error_msg}" + else + return true + end + end + rescue Exception => e + puts "#{I18n.t('display.error')}: #{e}" + else return false end @@ -96,7 +101,7 @@ class Cli end # Request the GPG password and decrypt the file - def decrypt() + def decrypt if !defined?(@mpw) @mpw = MPW::MPW.new(@config.file_gpg, @config.key) end From 1f5b37ed3c0a217aede1223f7b9a4f1929c9dedf Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sat, 1 Feb 2014 00:09:22 +0100 Subject: [PATCH 055/531] change array.new --- MPW/MPW.rb | 10 +++++----- MPW/UI/Cli.rb | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/MPW/MPW.rb b/MPW/MPW.rb index c57b696..6d851d6 100644 --- a/MPW/MPW.rb +++ b/MPW/MPW.rb @@ -78,7 +78,7 @@ module MPW # protocol -> the connection protocol (ssh, web, other) # @rtrn: a list with the resultat of the search def search(search='', group=nil, protocol=nil) - result = Array.new() + result = [] if !search.nil? search = search.downcase @@ -110,7 +110,7 @@ module MPW end end - return Array.new() + return [] end # Update an item @@ -125,7 +125,7 @@ module MPW # comment -> a comment # @rtrn: true if the item has been updated def update(name, group, server, protocol, login, passwd, port, comment, id=nil) - row = Array.new() + row = [] update = false i = 0 @@ -142,7 +142,7 @@ module MPW port = nil end - row_update = Array.new() + row_update = [] row_update[DATE] = Time.now.to_i row_update[ID] = id.nil? || id.empty? ? MPW.password(16) : id @@ -238,7 +238,7 @@ module MPW # @args: file -> path to file import # @rtrn: an array with the items to import, if there is an error return false def import_preview(file) - result = Array.new() + result = [] id = 0 data = IO.read(file) diff --git a/MPW/UI/Cli.rb b/MPW/UI/Cli.rb index 1b0ce0b..8501f22 100644 --- a/MPW/UI/Cli.rb +++ b/MPW/UI/Cli.rb @@ -165,7 +165,7 @@ class Cli # Form to add a new item def add() - row = Array.new() + row = [] puts I18n.t('form.add.title') puts '--------------------' name = ask(I18n.t('form.add.name')).to_s From dbfe1184900047f7ed76b903c6288c95e018cf46 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sat, 1 Feb 2014 00:30:52 +0100 Subject: [PATCH 056/531] beautiful code --- lib/Server.rb | 106 +++++++++++++++++++++++--------------------------- mpw | 2 + 2 files changed, 51 insertions(+), 57 deletions(-) diff --git a/lib/Server.rb b/lib/Server.rb index 3baa22f..1821f5e 100644 --- a/lib/Server.rb +++ b/lib/Server.rb @@ -17,13 +17,8 @@ class Server # Start the server def start() - begin - server = TCPServer.open(@host, @port) - @log.info("The server is started on #{@host}:#{@port}") - rescue Exception => e - @log.error("Impossible to start the server: #{e}") - exit 2 - end + server = TCPServer.open(@host, @port) + @log.info("The server is started on #{@host}:#{@port}") loop do Thread.start(server.accept) do |client| @@ -68,6 +63,10 @@ class Server end end end + + rescue Exception => e + @log.error("Impossible to start the server: #{e}") + exit 2 end # Get a gpg file @@ -228,13 +227,11 @@ class Server # @args: client -> client connection # @rtrn: array of the json string, or false if isn't json message def get_client_msg(client) - begin - msg = client.gets - return JSON.parse(msg) - rescue - closeConnection(client) - return false - end + msg = client.gets + return JSON.parse(msg) + rescue + closeConnection(client) + return false end # Close the client connection @@ -248,46 +245,43 @@ class Server # @args: file_config -> the configuration file # @rtrn: true if the config file is correct def checkconfig(file_config) - begin - config = YAML::load_file(file_config) - @host = config['config']['host'] - @port = config['config']['port'].to_i - @data_dir = config['config']['data_dir'] - @log_file = config['config']['log_file'] - @timeout = config['config']['timeout'].to_i + config = YAML::load_file(file_config) + @host = config['config']['host'] + @port = config['config']['port'].to_i + @data_dir = config['config']['data_dir'] + @log_file = config['config']['log_file'] + @timeout = config['config']['timeout'].to_i - if @host.empty? || @port <= 0 || @data_dir.empty? - puts I18n.t('checkconfig.fail') - puts I18n.t('checkconfig.empty') - return false - end - - if !Dir.exist?(@data_dir) - puts I18n.t('checkconfig.fail') - puts I18n.t('checkconfig.datadir') - return false - end - - if @log_file.nil? || @log_file.empty? - puts I18n.t('checkconfig.fail') - puts I18n.t('checkconfig.log_file_empty') - return false - else - begin - @log = Logger.new(@log_file) - rescue - puts I18n.t('checkconfig.fail') - puts I18n.t('checkconfig.log_file_create') - return false - end - end - - rescue Exception => e - puts "#{I18n.t('checkconfig.fail')}\n#{e}" + if @host.empty? || @port <= 0 || @data_dir.empty? + puts I18n.t('checkconfig.fail') + puts I18n.t('checkconfig.empty') return false end + if !Dir.exist?(@data_dir) + puts I18n.t('checkconfig.fail') + puts I18n.t('checkconfig.datadir') + return false + end + + if @log_file.nil? || @log_file.empty? + puts I18n.t('checkconfig.fail') + puts I18n.t('checkconfig.log_file_empty') + return false + else + begin + @log = Logger.new(@log_file) + rescue + puts I18n.t('checkconfig.fail') + puts I18n.t('checkconfig.log_file_create') + return false + end + end + return true + rescue Exception => e + puts "#{I18n.t('checkconfig.fail')}\n#{e}" + return false end # Create a new config file @@ -308,16 +302,14 @@ class Server 'log_file' => log_file, 'timeout' => timeout}} - begin - File.open(file_config, 'w') do |file| - file << config.to_yaml - end - rescue Exception => e - puts "#{I18n.t('form.setup.not_valid')}\n#{e}" - return false + File.open(file_config, 'w') do |file| + file << config.to_yaml end - + return true + rescue Exception => e + puts "#{I18n.t('form.setup.not_valid')}\n#{e}" + return false end # Generate a random salt diff --git a/mpw b/mpw index ae59416..e5cf0a3 100755 --- a/mpw +++ b/mpw @@ -135,11 +135,13 @@ else begin cli.interactive() rescue SystemExit, Interrupt + cli.sync_close() cli = nil return 1 end end cli.sync_close() +cli = nil exit 0 From b71f98d2384fe1b51afa2e87ab0e75c223c322ba Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sat, 1 Feb 2014 13:52:50 +0100 Subject: [PATCH 057/531] clean code --- MPW/UI/Cli.rb | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/MPW/UI/Cli.rb b/MPW/UI/Cli.rb index 8501f22..20ba037 100644 --- a/MPW/UI/Cli.rb +++ b/MPW/UI/Cli.rb @@ -76,19 +76,16 @@ class Cli sync_host = ask(I18n.t('form.setup.sync_host')).to_s sync_port = ask(I18n.t('form.setup.sync_port')).to_s sync_pwd = ask(I18n.t('form.setup.sync_pwd')).to_s - sync_suffix = ask(I18n.t('form.setup.sync_suffix')).to_s + sync_path = ask(I18n.t('form.setup.sync_path')).to_s - if !File.exist?("#{APP_ROOT}/i18n/#{language}.yml") - language= 'en' - end I18n.locale = language.to_sym - sync_host = sync_host.empty? ? nil : sync_host - sync_port = sync_port.empty? ? nil : sync_port.to_i - sync_pwd = sync_pwd.empty? ? nil : sync_pwd - sync_suffix = sync_suffix.empty? ? nil : sync_suffix + sync_host = sync_host.empty? ? nil : sync_host + sync_port = sync_port.empty? ? nil : sync_port.to_i + sync_pwd = sync_pwd.empty? ? nil : sync_pwd + sync_path = sync_path.empty? ? nil : sync_path - if @config.setup(key, language, file_gpg, timeout_pwd, sync_host, sync_port, sync_pwd, sync_suffix) + if @config.setup(key, language, file_gpg, timeout_pwd, sync_host, sync_port, sync_pwd, sync_path) puts I18n.t('form.setup.valid') else puts "#{I18n.t('display.error')}: #{@config.error_msg}" From 1043b5c21c09af96801d7ca35f2895d60c250506 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sat, 1 Feb 2014 19:11:19 +0100 Subject: [PATCH 058/531] fix sync via ssh --- MPW/Sync/SSH.rb | 25 ++++++++++++++----------- MPW/UI/Cli.rb | 14 ++++++++++++-- 2 files changed, 26 insertions(+), 13 deletions(-) diff --git a/MPW/Sync/SSH.rb b/MPW/Sync/SSH.rb index bd92fc6..e69a6e2 100644 --- a/MPW/Sync/SSH.rb +++ b/MPW/Sync/SSH.rb @@ -9,8 +9,10 @@ module MPW require 'rubygems' require 'i18n' + require 'net/ssh' + require 'net/scp' - class MPW + class SSH attr_accessor :error_msg attr_accessor :enable @@ -33,11 +35,12 @@ module MPW @user = user @password = password @path = path - @port = port.nil? || port.empty? ? 22 : port.to_i + @port = port.instance_of?(Integer) ? 22 : port Net::SSH.start(@host, @user, :password => @password, :port => @port) do + @enable = true end - rescue + rescue Exception => e @error_msg = "#{I18n.t('error.sync.connection')}\n#{e}" @enable = false else @@ -53,14 +56,10 @@ module MPW end tmp_file = tmpfile - Net::SCP.start(@host, @user, :password => @password, :port => @port) do |ssh| - ssh.scp.download(@path, tmp_file) + Net::SCP.start(@host, @user, :password => @password, :port => @port) do |scp| + scp.download!(@path, tmp_file) end - File.open(tmp_file, 'w') do |file| - file << msg['data'] - end - mpw = MPW.new(tmp_file) if !mpw.decrypt(gpg_password) @error_msg = mpw.error_msg @@ -83,8 +82,12 @@ module MPW end tmp_file = tmpfile - Net::SCP.start(@host, @user, :password => @password, :port => @port) do |ssh| - ssh.scp.upload(tmp_file, @path) + File.open(tmp_file, "w") do |file| + file << data + end + + Net::SCP.start(@host, @user, :password => @password, :port => @port) do |scp| + scp.upload!(tmp_file, @path) end File.unlink(tmp_file) diff --git a/MPW/UI/Cli.rb b/MPW/UI/Cli.rb index 20ba037..1b5c017 100644 --- a/MPW/UI/Cli.rb +++ b/MPW/UI/Cli.rb @@ -12,6 +12,7 @@ require 'yaml' require "#{APP_ROOT}/MPW/MPW" require "#{APP_ROOT}/MPW/Sync/MPW" +require "#{APP_ROOT}/MPW/Sync/SSH" class Cli @@ -50,7 +51,9 @@ class Cli if @sync.enable if !@mpw.sync(@sync.get(@passwd), @config.last_update) puts "#{I18n.t('display.error')}: #{@sync.error_msg}" - elsif !@sync.update(File.open(@config.file_gpg).read) + end + + if !@sync.update(File.open(@config.file_gpg).read) puts "#{I18n.t('display.error')}: #{@sync.error_msg}" elsif !@config.set_last_update puts "#{I18n.t('display.error')}: #{@config.error_msg}" @@ -60,6 +63,9 @@ class Cli end rescue Exception => e puts "#{I18n.t('display.error')}: #{e}" + puts @sync.error_msg + puts @config.error_msg + puts @mpw.error_msg else return false end @@ -73,19 +79,23 @@ class Cli key = ask(I18n.t('form.setup.gpg_key')).to_s file_gpg = ask(I18n.t('form.setup.gpg_file', :home => Dir.home())).to_s timeout_pwd = ask(I18n.t('form.setup.timeout')).to_s + sync_type = ask(I18n.t('form.setup.sync_type')).to_s sync_host = ask(I18n.t('form.setup.sync_host')).to_s sync_port = ask(I18n.t('form.setup.sync_port')).to_s + sync_user = ask(I18n.t('form.setup.sync_user')).to_s sync_pwd = ask(I18n.t('form.setup.sync_pwd')).to_s sync_path = ask(I18n.t('form.setup.sync_path')).to_s I18n.locale = language.to_sym + sync_type = sync_type.empty? ? nil : sync_type sync_host = sync_host.empty? ? nil : sync_host sync_port = sync_port.empty? ? nil : sync_port.to_i + sync_user = sync_user.empty? ? nil : sync_user sync_pwd = sync_pwd.empty? ? nil : sync_pwd sync_path = sync_path.empty? ? nil : sync_path - if @config.setup(key, language, file_gpg, timeout_pwd, sync_host, sync_port, sync_pwd, sync_path) + if @config.setup(key, language, file_gpg, timeout_pwd, sync_type, sync_host, sync_port, sync_user, sync_pwd, sync_path) puts I18n.t('form.setup.valid') else puts "#{I18n.t('display.error')}: #{@config.error_msg}" From 63af86e7d43009aa54d612d686025eb0984f9ba6 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sat, 1 Feb 2014 19:29:56 +0100 Subject: [PATCH 059/531] add package for sync via ssh --- README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 277d937..b2eda64 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # Manage your passwords! MPW is a little software which stores your passwords in an GPG encrypted file. -MPW can sync your password with a MPW Server. +MPW can synchronize your password with a MPW Server or via SSH. # Installation @@ -12,5 +12,9 @@ This program work with ruby >= 1.9 * apt-get install ruby ruby-gpgme ruby-highline ruby-i18n ruby-locale +If you want to synchronize your password via SSH/SCP: +* apt-get install ruby-ssh ruby-scp + For mpw-ssh: * apt-get install sshpass + From b1c281f3186d32bd94fc21b0415c6366addcfd84 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sat, 1 Feb 2014 20:17:55 +0100 Subject: [PATCH 060/531] fix I18n.enforce_available_locales --- mpw | 16 ++++++++++++++++ mpw-server | 19 ++++++++++++++++++- mpw-ssh | 16 ++++++++++++++++ 3 files changed, 50 insertions(+), 1 deletion(-) diff --git a/mpw b/mpw index e5cf0a3..ebe9f2a 100755 --- a/mpw +++ b/mpw @@ -13,13 +13,25 @@ APP_ROOT = File.dirname(Pathname.new(__FILE__).realpath) require "#{APP_ROOT}/MPW/UI/Cli" require "#{APP_ROOT}/MPW/Config" +# --------------------------------------------------------- # +# Set local +# --------------------------------------------------------- # + lang = Locale::Tag.parse(ENV['LANG']).to_simple.to_s[0..1] +if defined? I18n.enforce_available_locales + I18n.enforce_available_locales = true +end + I18n::Backend::Simple.send(:include, I18n::Backend::Fallbacks) I18n.load_path = Dir["#{APP_ROOT}/i18n/cli/*.yml"] I18n.default_locale = :en I18n.locale = lang.to_sym +# --------------------------------------------------------- # +# Options +# --------------------------------------------------------- # + options = {} options[:force] = false options[:format] = false @@ -93,6 +105,10 @@ OptionParser.new do |opts| end end.parse! +# --------------------------------------------------------- # +# Main +# --------------------------------------------------------- # + config = MPW::Config.new(options[:config]) check_error = config.checkconfig() diff --git a/mpw-server b/mpw-server index 07b42f5..d1f5192 100755 --- a/mpw-server +++ b/mpw-server @@ -12,13 +12,25 @@ require 'i18n' APP_ROOT = File.dirname(Pathname.new(__FILE__).realpath) require "#{APP_ROOT}/lib/Server.rb" +# --------------------------------------------------------- # +# Set local +# --------------------------------------------------------- # + lang = Locale::Tag.parse(ENV['LANG']).to_simple.to_s[0..1] +if defined? I18n.enforce_available_locales + I18n.enforce_available_locales = true +end + I18n::Backend::Simple.send(:include, I18n::Backend::Fallbacks) I18n.load_path = Dir["#{APP_ROOT}/i18n/server/*.yml"] I18n.default_locale = :en I18n.locale = lang.to_sym +# --------------------------------------------------------- # +# Options +# --------------------------------------------------------- # + options = {} OptionParser.new do |opts| opts.banner = "#{I18n.t('option.usage')}: mpw-server -c CONFIG [options]" @@ -41,6 +53,10 @@ OptionParser.new do |opts| end end.parse! +# --------------------------------------------------------- # +# Main +# --------------------------------------------------------- # + if options[:config].nil? || options[:config].empty? puts "#{I18n.t('option.usage')}: mpw-server -c CONFIG [options]" exit 2 @@ -54,8 +70,9 @@ elsif options[:setup] server.setup(options[:config]) else if server.checkconfig(options[:config]) - server.start() + server.start end end +server = nil exit 0 diff --git a/mpw-ssh b/mpw-ssh index 9ba3791..f90cc81 100755 --- a/mpw-ssh +++ b/mpw-ssh @@ -15,11 +15,23 @@ require "#{APP_ROOT}/MPW/Config" lang = Locale::Tag.parse(ENV['LANG']).to_simple.to_s[0..1] +# --------------------------------------------------------- # +# Set local +# --------------------------------------------------------- # + +if defined? I18n.enforce_available_locales + I18n.enforce_available_locales = true +end + I18n::Backend::Simple.send(:include, I18n::Backend::Fallbacks) I18n.load_path = Dir["#{APP_ROOT}/i18n/cli/*.yml"] I18n.default_locale = :en I18n.locale = lang.to_sym +# --------------------------------------------------------- # +# Options +# --------------------------------------------------------- # + options = {} OptionParser.new do |opts| opts.banner = "#{I18n.t('ssh.option.usage')}: mpw-ssh SEARCH [options]" @@ -46,6 +58,10 @@ OptionParser.new do |opts| end end.parse! +# --------------------------------------------------------- # +# Main +# --------------------------------------------------------- # + config = MPW::Config.new(options[:config]) check_error = config.checkconfig() From 71fb489958e5002ec1fd0990b517c9342c990b94 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sun, 2 Feb 2014 10:16:10 +0100 Subject: [PATCH 061/531] delete sync close function --- MPW/Config.rb | 6 +++--- MPW/Sync/MPW.rb | 54 +++++++++++++++++++++++-------------------------- MPW/Sync/SSH.rb | 4 ---- MPW/UI/Cli.rb | 31 ++++++++++++---------------- lib/Server.rb | 6 +++--- mpw | 12 +++++------ mpw-ssh | 8 ++++---- 7 files changed, 53 insertions(+), 68 deletions(-) diff --git a/MPW/Config.rb b/MPW/Config.rb index 92a58fd..2919fcf 100644 --- a/MPW/Config.rb +++ b/MPW/Config.rb @@ -30,7 +30,7 @@ module MPW # @args: file_config -> the specify config file def initialize(file_config=nil) @error_msg = nil - @file_config = "#{Dir.home()}/.mpw.cfg" + @file_config = "#{Dir.home}/.mpw.cfg" if !file_config.nil? && !file_config.empty? @file_config = file_config @@ -57,7 +57,7 @@ module MPW end if file_gpg.empty? - file_gpg = "#{Dir.home()}/.mpw.gpg" + file_gpg = "#{Dir.home}/.mpw.gpg" end timeout_pwd = timeout_pwd.empty? ? 60 : timeout_pwd.to_i @@ -86,7 +86,7 @@ module MPW # Check the config file # @rtrn: true if the config file is correct - def checkconfig() + def checkconfig config = YAML::load_file(@file_config) @key = config['config']['key'] @lang = config['config']['lang'] diff --git a/MPW/Sync/MPW.rb b/MPW/Sync/MPW.rb index d0462a8..69fdd83 100644 --- a/MPW/Sync/MPW.rb +++ b/MPW/Sync/MPW.rb @@ -35,8 +35,9 @@ module MPW @password = password @suffix = path - @socket = TCPSocket.new(host, port.to_i) - @enable = true + TCPSocket.new(host, port.to_i) do + @enable = true + end rescue Exception => e @error_msg = "#{I18n.t('error.sync.connection')}\n#{e}" @enable = false @@ -51,17 +52,19 @@ module MPW if !@enable return nil end - - send_msg = {:action => 'get', - :gpg_key => @gpg_key, - :password => @password, - :suffix => @suffix} - @socket.puts send_msg.to_json - msg = JSON.parse(@socket.gets) - + TCPSocket.new(host, port.to_i) do |socket| + send_msg = {:action => 'get', + :gpg_key => @gpg_key, + :password => @password, + :suffix => @suffix} + + socket.puts send_msg.to_json + msg = JSON.parse(socket.gets) + end + if !defined?(msg['error']) - @error_msg = I18n.t('error.sync.communication') + error_msg = I18n.t('error.sync.communication') return nil elsif msg['error'].nil? tmp_file = tmpfile @@ -81,6 +84,7 @@ module MPW @error_msg = I18n.t(msg['error']) return nil end + end # Update the remote data @@ -91,14 +95,16 @@ module MPW return true end - send_msg = {:action => 'update', - :gpg_key => @gpg_key, - :password => @password, - :suffix => @suffix, - :data => data} - - @socket.puts send_msg.to_json - msg = JSON.parse(@socket.gets) + TCPSocket.new(host, port.to_i) do |socket| + send_msg = {:action => 'update', + :gpg_key => @gpg_key, + :password => @password, + :suffix => @suffix, + :data => data} + + socket.puts send_msg.to_json + msg = JSON.parse(socket.gets) + end if !defined?(msg['error']) @error_msg = I18n.t('error.sync.communication') @@ -111,16 +117,6 @@ module MPW end end - # Close the connection - def close - if !@enable - return - end - - send_msg = {:action => 'close'} - @socket.puts send_msg.to_json - end - # Generate a random string # @rtrn: a random string def tmpfile diff --git a/MPW/Sync/SSH.rb b/MPW/Sync/SSH.rb index e69a6e2..21c9c03 100644 --- a/MPW/Sync/SSH.rb +++ b/MPW/Sync/SSH.rb @@ -97,10 +97,6 @@ module MPW @error_msg = "#{I18n.t('error.sync.upload')}\n#{e}" return false end - - # Close the connection - def close - end # Generate a random string # @rtrn: a random string diff --git a/MPW/UI/Cli.rb b/MPW/UI/Cli.rb index 1b5c017..ead9701 100644 --- a/MPW/UI/Cli.rb +++ b/MPW/UI/Cli.rb @@ -23,11 +23,6 @@ class Cli @config = config end - # Close sync - def sync_close - @sync.close - end - # Sync the data with the server # @rtnr: true if the synchro is finish def sync @@ -77,7 +72,7 @@ class Cli puts '--------------------' language = ask(I18n.t('form.setup.lang', :lang => lang)).to_s key = ask(I18n.t('form.setup.gpg_key')).to_s - file_gpg = ask(I18n.t('form.setup.gpg_file', :home => Dir.home())).to_s + file_gpg = ask(I18n.t('form.setup.gpg_file', :home => Dir.home)).to_s timeout_pwd = ask(I18n.t('form.setup.timeout')).to_s sync_type = ask(I18n.t('form.setup.sync_type')).to_s sync_host = ask(I18n.t('form.setup.sync_host')).to_s @@ -101,7 +96,7 @@ class Cli puts "#{I18n.t('display.error')}: #{@config.error_msg}" end - if not @config.checkconfig() + if not @config.checkconfig puts "#{I18n.t('display.error')}: #{@config.error_msg}" exit 2 end @@ -171,7 +166,7 @@ class Cli end # Form to add a new item - def add() + def add row = [] puts I18n.t('form.add.title') puts '--------------------' @@ -185,8 +180,8 @@ class Cli comment = ask(I18n.t('form.add.comment')).to_s if @mpw.update(name, group, server, protocol, login, passwd, port, comment) - if @mpw.encrypt() - sync() + if @mpw.encrypt + sync puts I18n.t('form.add.valid') else puts "#{I18n.t('display.error')}: #{@mpw.error_msg}" @@ -214,8 +209,8 @@ class Cli comment = ask(I18n.t('form.update.comment' , :comment => row[MPW::MPW::COMMENT])).to_s if @mpw.update(name, group, server, protocol, login, passwd, port, comment, id) - if @mpw.encrypt() - sync() + if @mpw.encrypt + sync puts I18n.t('form.update.valid') else puts "#{I18n.t('display.error')}: #{@mpw.error_msg}" @@ -249,8 +244,8 @@ class Cli if force if @mpw.remove(id) - if @mpw.encrypt() - sync() + if @mpw.encrypt + sync puts I18n.t('form.delete.valid', :id => id) else puts "#{I18n.t('display.error')}: #{@mpw.error_msg}" @@ -294,8 +289,8 @@ class Cli end if force - if @mpw.import(file) && @mpw.encrypt() - sync() + if @mpw.import(file) && @mpw.encrypt + sync puts I18n.t('form.import.valid') else puts "#{I18n.t('display.error')}: #{@mpw.error_msg}" @@ -304,7 +299,7 @@ class Cli end # Interactive mode - def interactive() + def interactive group = nil last_access = Time.now.to_i @@ -331,7 +326,7 @@ class Cli display(command[1], group, command[2]) end when 'add', 'a' - add() + add when 'update', 'u' if !command[1].nil? && !command[1].empty? update(command[1]) diff --git a/lib/Server.rb b/lib/Server.rb index 1821f5e..85d8f98 100644 --- a/lib/Server.rb +++ b/lib/Server.rb @@ -11,12 +11,12 @@ class Server attr_accessor :error_msg # Constructor - def initialize() + def initialize YAML::ENGINE.yamler='syck' end # Start the server - def start() + def start server = TCPServer.open(@host, @port) @log.info("The server is started on #{@host}:#{@port}") @@ -134,7 +134,7 @@ class Server hash = gpg_data['gpg']['hash'] else - salt = salt() + salt = salt hash = Digest::SHA256.hexdigest(salt + msg['password']) end diff --git a/mpw b/mpw index ebe9f2a..c13baeb 100755 --- a/mpw +++ b/mpw @@ -110,7 +110,7 @@ end.parse! # --------------------------------------------------------- # config = MPW::Config.new(options[:config]) -check_error = config.checkconfig() +check_error = config.checkconfig cli = Cli.new(lang, config) @@ -119,8 +119,8 @@ if !check_error || !options[:setup].nil? cli.setup(lang) end -cli.decrypt() -cli.sync() +cli.decrypt +cli.sync # Display the item's informations if not options[:display].nil? @@ -136,7 +136,7 @@ elsif not options[:update].nil? # Add a new item elsif not options[:add].nil? - cli.add() + cli.add # Export elsif not options[:export].nil? @@ -149,15 +149,13 @@ elsif not options[:import].nil? # Interactive mode else begin - cli.interactive() + cli.interactive rescue SystemExit, Interrupt - cli.sync_close() cli = nil return 1 end end -cli.sync_close() cli = nil exit 0 diff --git a/mpw-ssh b/mpw-ssh index f90cc81..079771e 100755 --- a/mpw-ssh +++ b/mpw-ssh @@ -63,7 +63,7 @@ end.parse! # --------------------------------------------------------- # config = MPW::Config.new(options[:config]) -check_error = config.checkconfig() +check_error = config.checkconfig cli = CliSSH.new(lang, config) cli.login = options[:login] @@ -80,11 +80,11 @@ elsif ARGV.length < 1 puts "#{I18n.t('ssh.option.usage')}: mpw-ssh SEARCH [options]" exit 2 else - cli.decrypt() - cli.sync() + cli.decrypt + cli.sync cli.ssh(search) end -cli.sync_close() +cli = nil exit 0 From ae98d34135054bfa9fecc69b4cb31cf8acaca628 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sun, 2 Feb 2014 10:45:18 +0100 Subject: [PATCH 062/531] rename MPWSync --- MPW/Sync/{MPW.rb => MPWSync.rb} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename MPW/Sync/{MPW.rb => MPWSync.rb} (100%) diff --git a/MPW/Sync/MPW.rb b/MPW/Sync/MPWSync.rb similarity index 100% rename from MPW/Sync/MPW.rb rename to MPW/Sync/MPWSync.rb From f59a5584cf7fec87720c985828ca2ea7a31defa8 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sun, 2 Feb 2014 11:24:28 +0100 Subject: [PATCH 063/531] add sync via FTP --- MPW/Sync/FTP.rb | 115 ++++++++++++++++++++++++++++++++++++++++++++++++ MPW/UI/Cli.rb | 5 ++- 2 files changed, 119 insertions(+), 1 deletion(-) create mode 100644 MPW/Sync/FTP.rb diff --git a/MPW/Sync/FTP.rb b/MPW/Sync/FTP.rb new file mode 100644 index 0000000..6a6b236 --- /dev/null +++ b/MPW/Sync/FTP.rb @@ -0,0 +1,115 @@ +#!/usr/bin/ruby +# author: nishiki +# mail: nishiki@yaegashi.fr +# info: a simple script who manage your passwords + +module MPW + + module Sync + + require 'rubygems' + require 'i18n' + require 'net/ftp' + + class FTP + + attr_accessor :error_msg + attr_accessor :enable + + # Constructor + def initialize + @error_msg = nil + @enable = false + end + + # Connect to server + # @args: host -> the server host + # port -> ther connection port + # gpg_key -> the gpg key + # password -> the remote password + # suffix -> the suffix file + # @rtrn: false if the connection fail + def connect(host, user, password, path, port=nil) + @host = host + @user = user + @password = password + @path = path + @port = port.instance_of?(Integer) ? 21 : port + + Net::FTP.open(@host) do |ftp| + ftp.login(@user, @password) + @enable = true + end + rescue Exception => e + @error_msg = "#{I18n.t('error.sync.connection')}\n#{e}" + @enable = false + else + return @enable + end + + # Get data on server + # @args: gpg_password -> the gpg password + # @rtrn: nil if nothing data or error + def get(gpg_password) + if !@enable + return nil + end + + tmp_file = tmpfile + Net::FTP.open(@host) do |ftp| + ftp.login(@user, @password) + ftp.gettextfile(@path, tmp_file) + end + + mpw = MPW.new(tmp_file) + if !mpw.decrypt(gpg_password) + @error_msg = mpw.error_msg + return nil + end + + File.unlink(tmp_file) + return mpw.search + rescue Exception => e + @error_msg = "#{I18n.t('error.sync.download')}\n#{e}" + return nil + end + + # Update the remote data + # @args: data -> the data to send on server + # @rtrn: false if there is a problem + def update(data) + if !@enable + return true + end + + tmp_file = tmpfile + File.open(tmp_file, "w") do |file| + file << data + end + + Net::FTP.open(@host) do |ftp| + ftp.login(@user, @password) + ftp.puttextfile(tmp_file, @path) + end + + File.unlink(tmp_file) + return true + rescue Exception => e + @error_msg = "#{I18n.t('error.sync.upload')}\n#{e}" + return false + end + + # Generate a random string + # @rtrn: a random string + def tmpfile + result = '' + result << ([*('A'..'Z'),*('a'..'z'),*('0'..'9')]).sample(6).join + + return "/tmp/mpw-#{result}" + end + + end + + end + +end diff --git a/MPW/UI/Cli.rb b/MPW/UI/Cli.rb index ead9701..75adfa0 100644 --- a/MPW/UI/Cli.rb +++ b/MPW/UI/Cli.rb @@ -11,8 +11,9 @@ require 'i18n' require 'yaml' require "#{APP_ROOT}/MPW/MPW" -require "#{APP_ROOT}/MPW/Sync/MPW" +require "#{APP_ROOT}/MPW/Sync/MPWSync" require "#{APP_ROOT}/MPW/Sync/SSH" +require "#{APP_ROOT}/MPW/Sync/FTP" class Cli @@ -32,6 +33,8 @@ class Cli @sync = MPW::Sync::MPWSync.new when 'sftp', 'scp', 'ssh' @sync = MPW::Sync::SSH.new + when 'ftp' + @sync = MPW::Sync::FTP.new else return false end From 851ca63f90a31cf2d7cd348c047418ea5c094164 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sun, 2 Feb 2014 11:48:46 +0100 Subject: [PATCH 064/531] add translate --- i18n/cli/en.yml | 13 +++++++++++-- i18n/cli/fr.yml | 13 +++++++++++-- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/i18n/cli/en.yml b/i18n/cli/en.yml index bf8b9fc..88fce39 100644 --- a/i18n/cli/en.yml +++ b/i18n/cli/en.yml @@ -20,9 +20,11 @@ en: sync: connection: "Connection fail!" communication: "A communication problem with the server is appeared!" - no_data: "Nothing data!" + download: "Can't download the file!" not_authorized: "You haven't the access to remote file!" + upload: "Can't upload the file on the server!" unknown: "An unknown error is occured!" + option: usage: "Usage" show: "Search and show the items" @@ -40,6 +42,7 @@ en: format: "Change the display items format by an alternative format" generate_password: "Generate a random password (default 8 characters)" help: "Show this help message" + form: add: title: "Add a new item" @@ -66,10 +69,12 @@ en: gpg_key: "Enter the GPG key: " gpg_file: "Enter the path to encrypt file [default=%{home}/.mpw.gpg]: " timeout: "Enter the timeout (in seconde) to GPG password [default=60]: " + sync_type: "Synchronization type (mpw, ssh, ftp, or nil): " sync_host: "Synchronization server: " sync_port: "Port of the synchronization server: " + sync_user: "Username for the synchronization: " sync_pwd: "Password for the synchronization: " - sync_suffix: "Suffix for the synchronization (optionnal): " + sync_path: "File path for the synchronization : " valid: "The config file has been created!" update: title: "Update an item" @@ -82,6 +87,7 @@ en: port: "Enter the connection port [%{port}]: " comment: "Enter a comment [%{comment}]: " valid: "Item has been updated!" + interactive: ask_password: "Password GPG: " bad_password: "Bad password!" @@ -96,6 +102,7 @@ en: remove: "Remove an item" help: "Show this message" quit: "Quit the software" + display: comment: "Comment" error: "ERROR" @@ -108,6 +115,7 @@ en: port: "Port" protocol: "Protocol" server: "Server" + ssh: option: usage: "Usage" @@ -118,6 +126,7 @@ en: display: connect: "Connection to:" nothing: "Nothing result!" + formats: default: ! '%Y-%m-%d' long: ! '%B %d, %Y' diff --git a/i18n/cli/fr.yml b/i18n/cli/fr.yml index 0936cdb..17d01b8 100644 --- a/i18n/cli/fr.yml +++ b/i18n/cli/fr.yml @@ -20,9 +20,11 @@ fr: sync: connection: "La connexion n'a pu être établie!" communication: "Un problème de communication avec le serveur est apparu!" - no_data: "Aucune donnée!" + download: "Impossible de télécharger le fichier!" not_authorized: "Vous n'avez pas les autorisations d'accès au fichier distant!" + upload: "Impossible d'envoyer le fichier sur le serveur!" unknown: "Une erreur inconnue est survenue!" + option: usage: "Utilisation" show: "Recherche et affiche les éléments" @@ -40,6 +42,7 @@ fr: format: "Change le format d'affichage des éléments par un alternatif" generate_password: "Génére un mot de passe aléatoire (défaut 8 caractères)" help: "Affiche ce message d'aide" + form: add: title: "Ajout d'un nouvel élément" @@ -66,10 +69,12 @@ fr: gpg_key: "Entrez la clé GPG: " gpg_file: "Entrez le chemin du fichier qui sera chiffré [défaut=%{home}/.mpw.gpg]: " timeout: "Entrez le temps (en seconde) du mot de passe GPG [défaut=60]: " + sync_type: "Type de synchronisation (mpw, ssh, ftp, or nil): " sync_host: "Serveur de synchronisation: " sync_port: "Port du serveur de synchronisation: " + sync_user: "Utilisateur pour la synchronisation: " sync_pwd: "Mot de passe pour la synchronisation: " - sync_suffix: "Suffix pour la synchronisation (optionnel): " + sync_path: "Chemin du fichier pour la synchronisation: " valid: "Le fichier de configuration a bien été créé!" update: title: "Mis à jour d'un élément" @@ -82,6 +87,7 @@ fr: port: "Entrez un port de connexion [%{port}]: " comment: "Entrez un commentaire [%{comment}]: " valid: "L'élément a bien été mis à jour!" + interactive: ask_password: "Mot de passe GPG: " bad_password: "Mauvais mot de passe!" @@ -96,6 +102,7 @@ fr: remove: "Supprime un élément" help: "Affiche ce message d'aide" quit: "Quitte le programme" + display: comment: "Commentaire" error: "ERREUR" @@ -108,6 +115,7 @@ fr: port: "Port" protocol: "Protocol" server: "Serveur" + ssh: option: usage: "Utilisation" @@ -118,6 +126,7 @@ fr: display: connect: "Connexion à:" nothing: "Aucun résultat!" + formats: default: ! '%Y-%m-%d' long: ! '%B %d, %Y' From 076aedeb3ca868e2fba739ef3562f3f1f4eab675 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sun, 2 Feb 2014 14:20:24 +0100 Subject: [PATCH 065/531] add share_keys in config --- MPW/Config.rb | 16 +++++++++++++++- MPW/UI/Cli.rb | 35 ++++++++++++++++++++++------------- i18n/cli/en.yml | 1 + i18n/cli/fr.yml | 1 + 4 files changed, 39 insertions(+), 14 deletions(-) diff --git a/MPW/Config.rb b/MPW/Config.rb index 2919fcf..bd993bb 100644 --- a/MPW/Config.rb +++ b/MPW/Config.rb @@ -14,6 +14,7 @@ module MPW attr_accessor :error_msg attr_accessor :key + attr_accessor :share_keys attr_accessor :lang attr_accessor :file_gpg attr_accessor :timeout_pwd @@ -39,6 +40,7 @@ module MPW # Create a new config file # @args: key -> the gpg key to encrypt + # share_keys -> multiple keys to share the password with other people # lang -> the software language # file_gpg -> the file who is encrypted # timeout_pwd -> time to save the password @@ -49,12 +51,21 @@ module MPW # sync_pwd -> the password for synchronization # sync_suffix -> the suffix file (optionnal) # @rtrn: true if le config file is create - def setup(key, lang, file_gpg, timeout_pwd, sync_type=nil, sync_host=nil, sync_port=nil, sync_user=nil, sync_pwd=nil, sync_path=nil) + def setup(key, share_keys, lang, file_gpg, timeout_pwd, sync_type, sync_host, sync_port, sync_user, sync_pwd, sync_path) if not key =~ /[a-zA-Z0-9.-_]+\@[a-zA-Z0-9]+\.[a-zA-Z]+/ @error_msg = I18n.t('error.config.key_bad_format') return false end + + if !share_keys.nil? && !share_keys.empty? + share_keys.split.each do |k| + if not k =~ /[a-zA-Z0-9.-_]+\@[a-zA-Z0-9]+\.[a-zA-Z]+/ + @error_msg = I18n.t('error.config.key_bad_format') + return false + end + end + end if file_gpg.empty? file_gpg = "#{Dir.home}/.mpw.gpg" @@ -63,6 +74,7 @@ module MPW timeout_pwd = timeout_pwd.empty? ? 60 : timeout_pwd.to_i config = {'config' => {'key' => key, + 'share_keys' => share_keys, 'lang' => lang, 'file_gpg' => file_gpg, 'timeout_pwd' => timeout_pwd, @@ -89,6 +101,7 @@ module MPW def checkconfig config = YAML::load_file(@file_config) @key = config['config']['key'] + @share_keys = config['config']['share_keys'] @lang = config['config']['lang'] @file_gpg = config['config']['file_gpg'] @timeout_pwd = config['config']['timeout_pwd'].to_i @@ -117,6 +130,7 @@ module MPW # @rtrn: true is the file has been updated def set_last_update config = {'config' => {'key' => @key, + 'share_keys' => @share_keys, 'lang' => @lang, 'file_gpg' => @file_gpg, 'timeout_pwd' => @timeout_pwd, diff --git a/MPW/UI/Cli.rb b/MPW/UI/Cli.rb index 75adfa0..46d5a81 100644 --- a/MPW/UI/Cli.rb +++ b/MPW/UI/Cli.rb @@ -75,28 +75,37 @@ class Cli puts '--------------------' language = ask(I18n.t('form.setup.lang', :lang => lang)).to_s key = ask(I18n.t('form.setup.gpg_key')).to_s + share_keys = ask(I18n.t('form.setup.share_gpg_keys')).to_s file_gpg = ask(I18n.t('form.setup.gpg_file', :home => Dir.home)).to_s timeout_pwd = ask(I18n.t('form.setup.timeout')).to_s sync_type = ask(I18n.t('form.setup.sync_type')).to_s - sync_host = ask(I18n.t('form.setup.sync_host')).to_s - sync_port = ask(I18n.t('form.setup.sync_port')).to_s - sync_user = ask(I18n.t('form.setup.sync_user')).to_s - sync_pwd = ask(I18n.t('form.setup.sync_pwd')).to_s - sync_path = ask(I18n.t('form.setup.sync_path')).to_s + + if ['ssh', 'ftp', 'mpw'].include?(sync_type) + sync_host = ask(I18n.t('form.setup.sync_host')).to_s + sync_port = ask(I18n.t('form.setup.sync_port')).to_s + sync_user = ask(I18n.t('form.setup.sync_user')).to_s + sync_pwd = ask(I18n.t('form.setup.sync_pwd')).to_s + sync_path = ask(I18n.t('form.setup.sync_path')).to_s + end - I18n.locale = language.to_sym + if !language.nil? && !language.empty? + I18n.locale = language.to_sym + else + language = nil + end - sync_type = sync_type.empty? ? nil : sync_type - sync_host = sync_host.empty? ? nil : sync_host - sync_port = sync_port.empty? ? nil : sync_port.to_i - sync_user = sync_user.empty? ? nil : sync_user - sync_pwd = sync_pwd.empty? ? nil : sync_pwd - sync_path = sync_path.empty? ? nil : sync_path + sync_type = sync_type.nil? || sync_type.empty? ? nil : sync_type + sync_host = sync_host.nil? || sync_host.empty? ? nil : sync_host + sync_port = sync_port.nil? || sync_port.empty? ? nil : sync_port.to_i + sync_user = sync_user.nil? || sync_user.empty? ? nil : sync_user + sync_pwd = sync_pwd.nil? || sync_pwd.empty? ? nil : sync_pwd + sync_path = sync_path.nil? || sync_path.empty? ? nil : sync_path - if @config.setup(key, language, file_gpg, timeout_pwd, sync_type, sync_host, sync_port, sync_user, sync_pwd, sync_path) + if @config.setup(key, share_keys, language, file_gpg, timeout_pwd, sync_type, sync_host, sync_port, sync_user, sync_pwd, sync_path) puts I18n.t('form.setup.valid') else puts "#{I18n.t('display.error')}: #{@config.error_msg}" + exit 2 end if not @config.checkconfig diff --git a/i18n/cli/en.yml b/i18n/cli/en.yml index 88fce39..622dfe8 100644 --- a/i18n/cli/en.yml +++ b/i18n/cli/en.yml @@ -67,6 +67,7 @@ en: title: "Setup a new config file" lang: "Choose your language (en, fr, ...): " gpg_key: "Enter the GPG key: " + share_gpg_key: "Enter the GPG keys with who you want to share the passwords: " gpg_file: "Enter the path to encrypt file [default=%{home}/.mpw.gpg]: " timeout: "Enter the timeout (in seconde) to GPG password [default=60]: " sync_type: "Synchronization type (mpw, ssh, ftp, or nil): " diff --git a/i18n/cli/fr.yml b/i18n/cli/fr.yml index 17d01b8..1f2f7b2 100644 --- a/i18n/cli/fr.yml +++ b/i18n/cli/fr.yml @@ -67,6 +67,7 @@ fr: title: "Création d'un nouveau fichier de configuration" lang: "Choisissez votre langue (en, fr, ...) [défaut=%{lang}]: " gpg_key: "Entrez la clé GPG: " + share_gpg_key: "Entrez les clés GPG avec qui vous voulez partager les mots de passe: " gpg_file: "Entrez le chemin du fichier qui sera chiffré [défaut=%{home}/.mpw.gpg]: " timeout: "Entrez le temps (en seconde) du mot de passe GPG [défaut=60]: " sync_type: "Type de synchronisation (mpw, ssh, ftp, or nil): " From bed8cbb8b65ff8be7ddcd07edf1595f76ad7d529 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sun, 2 Feb 2014 17:34:05 +0100 Subject: [PATCH 066/531] add share_keys --- MPW/Config.rb | 3 ++- MPW/MPW.rb | 17 ++++++++++++----- MPW/Sync/MPWSync.rb | 10 +++++++--- MPW/UI/Cli.rb | 2 +- 4 files changed, 22 insertions(+), 10 deletions(-) diff --git a/MPW/Config.rb b/MPW/Config.rb index bd993bb..4ace575 100644 --- a/MPW/Config.rb +++ b/MPW/Config.rb @@ -58,7 +58,8 @@ module MPW return false end - if !share_keys.nil? && !share_keys.empty? + share_keys = share_keys.nil? ? '' : share_keys + if !share_keys.empty? share_keys.split.each do |k| if not k =~ /[a-zA-Z0-9.-_]+\@[a-zA-Z0-9]+\.[a-zA-Z]+/ @error_msg = I18n.t('error.config.key_bad_format') diff --git a/MPW/MPW.rb b/MPW/MPW.rb index 6d851d6..05da9cf 100644 --- a/MPW/MPW.rb +++ b/MPW/MPW.rb @@ -26,10 +26,11 @@ module MPW attr_accessor :error_msg # Constructor - def initialize(file_gpg, key=nil) - @error_msg = nil - @file_gpg = file_gpg - @key = key + def initialize(file_gpg, key=nil, share_keys='') + @error_msg = nil + @file_gpg = file_gpg + @key = key + @share_keys = share_keys end # Decrypt a gpg file @@ -64,7 +65,13 @@ module MPW data_to_encrypt << row.to_csv end - crypto.encrypt(data_to_encrypt, :recipients => @key, :output => file_gpg) + recipients = [] + recipients.push(@key) + if !@share_keys.nil? + @share_keys.split.each { |k| recipients.push(k) } + end + + crypto.encrypt(data_to_encrypt, :recipients => recipients, :output => file_gpg) file_gpg.close return true diff --git a/MPW/Sync/MPWSync.rb b/MPW/Sync/MPWSync.rb index 69fdd83..da62975 100644 --- a/MPW/Sync/MPWSync.rb +++ b/MPW/Sync/MPWSync.rb @@ -31,11 +31,13 @@ module MPW # suffix -> the suffix file # @rtrn: false if the connection fail def connect(host, user, password, path, port=nil) + @host = host + @port = !port.instance_of?(Integer) ? 2201 : port @gpg_key = user @password = password @suffix = path - TCPSocket.new(host, port.to_i) do + TCPSocket.open(@host, @port) do @enable = true end rescue Exception => e @@ -53,7 +55,8 @@ module MPW return nil end - TCPSocket.new(host, port.to_i) do |socket| + msg = nil + TCPSocket.open(@host, @port) do |socket| send_msg = {:action => 'get', :gpg_key => @gpg_key, :password => @password, @@ -95,7 +98,8 @@ module MPW return true end - TCPSocket.new(host, port.to_i) do |socket| + msg = nil + TCPSocket.open(@host, @port) do |socket| send_msg = {:action => 'update', :gpg_key => @gpg_key, :password => @password, diff --git a/MPW/UI/Cli.rb b/MPW/UI/Cli.rb index 46d5a81..708f3ec 100644 --- a/MPW/UI/Cli.rb +++ b/MPW/UI/Cli.rb @@ -117,7 +117,7 @@ class Cli # Request the GPG password and decrypt the file def decrypt if !defined?(@mpw) - @mpw = MPW::MPW.new(@config.file_gpg, @config.key) + @mpw = MPW::MPW.new(@config.file_gpg, @config.key, @config.share_keys) end @passwd = ask(I18n.t('display.gpg_password')) {|q| q.echo = false} From 684972e44086f9a8c1690fb1472d6d5dadd475fa Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Wed, 5 Feb 2014 22:47:20 +0100 Subject: [PATCH 067/531] clean old code --- lib/Server.rb | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/lib/Server.rb b/lib/Server.rb index 85d8f98..2d55de0 100644 --- a/lib/Server.rb +++ b/lib/Server.rb @@ -31,11 +31,6 @@ class Server next end - if !msg['action'].nil? && msg['action'] == 'close' - @log.info("#{client.peeraddr[3]} is disconnected") - close_connection(client) - end - if msg['gpg_key'].nil? || msg['gpg_key'].empty? || msg['password'].nil? || msg['password'].empty? @log.warning("#{client.peeraddr[3]} is disconnected because no password or no gpg_key") close_connection(client) @@ -65,6 +60,7 @@ class Server end rescue Exception => e + puts "Impossible to start the server: #{e}" @log.error("Impossible to start the server: #{e}") exit 2 end From ea9b2fb411c52a56e42b9c455ca7ea661c4c044d Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sun, 16 Mar 2014 14:44:26 +0100 Subject: [PATCH 068/531] fix error message when sync --- MPW/UI/Cli.rb | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/MPW/UI/Cli.rb b/MPW/UI/Cli.rb index 708f3ec..9753d09 100644 --- a/MPW/UI/Cli.rb +++ b/MPW/UI/Cli.rb @@ -48,22 +48,26 @@ class Cli if @sync.enable if !@mpw.sync(@sync.get(@passwd), @config.last_update) - puts "#{I18n.t('display.error')}: #{@sync.error_msg}" + puts "#{I18n.t('display.error')}: #{@mpw.error_msg}" if !@mpw.error_msg.nil? + puts "#{I18n.t('display.error')}: #{@sync.error_msg}" if !@sync.error_msg.nil? + return false end if !@sync.update(File.open(@config.file_gpg).read) puts "#{I18n.t('display.error')}: #{@sync.error_msg}" elsif !@config.set_last_update puts "#{I18n.t('display.error')}: #{@config.error_msg}" + elsif !@mpw.encrypt + puts "#{I18n.t('display.error')}: #{@mpw.error_msg}" else return true end end rescue Exception => e puts "#{I18n.t('display.error')}: #{e}" - puts @sync.error_msg - puts @config.error_msg - puts @mpw.error_msg + puts @sync.error_msg if @sync.error_msg.nil? + puts @config.error_msg if @config.error_msg.nil? + puts @mpw.error_msg if @mpw.error_msg.nil? else return false end From a0720672bd91ae7d4df8ea638bf37650b0250956 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sun, 16 Mar 2014 15:29:21 +0100 Subject: [PATCH 069/531] minor change --- MPW/UI/Cli.rb | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/MPW/UI/Cli.rb b/MPW/UI/Cli.rb index 9753d09..c3ea99f 100644 --- a/MPW/UI/Cli.rb +++ b/MPW/UI/Cli.rb @@ -50,10 +50,7 @@ class Cli if !@mpw.sync(@sync.get(@passwd), @config.last_update) puts "#{I18n.t('display.error')}: #{@mpw.error_msg}" if !@mpw.error_msg.nil? puts "#{I18n.t('display.error')}: #{@sync.error_msg}" if !@sync.error_msg.nil? - return false - end - - if !@sync.update(File.open(@config.file_gpg).read) + elsif !@sync.update(File.open(@config.file_gpg).read) puts "#{I18n.t('display.error')}: #{@sync.error_msg}" elsif !@config.set_last_update puts "#{I18n.t('display.error')}: #{@config.error_msg}" From f9f06f245caa4d8ebd12653ac460ef27d68eb529 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sun, 16 Mar 2014 21:28:23 +0100 Subject: [PATCH 070/531] add generate gpg key --- MPW/Config.rb | 46 +++++++++++++++++++++++++++++++++++++++++++++- MPW/UI/Cli.rb | 29 +++++++++++++++++++++++++---- i18n/cli/en.yml | 11 +++++++++++ i18n/cli/fr.yml | 11 +++++++++++ mpw | 2 ++ 5 files changed, 94 insertions(+), 5 deletions(-) diff --git a/MPW/Config.rb b/MPW/Config.rb index 4ace575..42a840d 100644 --- a/MPW/Config.rb +++ b/MPW/Config.rb @@ -6,6 +6,7 @@ module MPW require 'rubygems' + require 'gpgme' require 'yaml' require 'i18n' @@ -96,6 +97,38 @@ module MPW @error_msg = "#{I18n.t('error.config.write')}\n#{e}" return false end + + # Setup a new gpg key + def setup_gpg_key(password, name, length = 2048, expire = 0) + if name.nil? || name.empty? + @error_msg = "#{I18n.t('error.config.genkey_gpg.name')}" + return false + elsif password.nil? || password.empty? + @error_msg = "#{I18n.t('error.config.genkey_gpg.password')}" + return false + end + + param = '' + param << '<GnupgKeyParms format="internal">' + "\n" + param << "Key-Type: DSA\n" + param << "Key-Length: #{length}\n" + param << "Subkey-Type: ELG-E\n" + param << "Subkey-Length: #{length}\n" + param << "Name-Real: #{name}\n" + param << "Name-Comment: #{name}\n" + param << "Name-Email: #{@key}\n" + param << "Expire-Date: #{expire}\n" + param << "Passphrase: apc\n" + param << "</GnupgKeyParms>\n" + + ctx = GPGME::Ctx.new + ctx.genkey(param, nil, nil) + + return true + rescue Exception => e + @error_msg = "#{I18n.t('error.config.genkey_gpg.exception')}\n#{e}" + return false + end # Check the config file # @rtrn: true if the config file is correct @@ -118,14 +151,25 @@ module MPW @error_msg = I18n.t('error.config.check') return false end - I18n.locale = @lang.to_sym return true rescue Exception => e + puts e @error_msg = "#{I18n.t('error.config.check')}\n#{e}" return false end + + # Check if private key exist + # @rtrn: true if the key exist, else false + def check_gpg_key? + ctx = GPGME::Ctx.new + ctx.each_key(@key, true) do |key| + return true + end + + return false + end # Set the last update when there is a sync # @rtrn: true is the file has been updated diff --git a/MPW/UI/Cli.rb b/MPW/UI/Cli.rb index c3ea99f..050e0d4 100644 --- a/MPW/UI/Cli.rb +++ b/MPW/UI/Cli.rb @@ -89,11 +89,10 @@ class Cli sync_path = ask(I18n.t('form.setup.sync_path')).to_s end - if !language.nil? && !language.empty? - I18n.locale = language.to_sym - else - language = nil + if language.nil? || language.empty? + language = lang end + I18n.locale = language.to_sym sync_type = sync_type.nil? || sync_type.empty? ? nil : sync_type sync_host = sync_host.nil? || sync_host.empty? ? nil : sync_host @@ -115,6 +114,28 @@ class Cli end end + # Setup a new GPG key + def setup_gpg_key + puts I18n.t('form.setup_gpg_key.title') + puts '--------------------' + name = ask(I18n.t('form.setup_gpg_key.name')).to_s + password = ask(I18n.t('form.setup_gpg_key.password')).to_s + length = ask(I18n.t('form.setup_gpg_key.length')).to_s + expire = ask(I18n.t('form.setup_gpg_key.expire')).to_s + + length = length.nil? || length.empty? ? 2048 : length.to_i + expire = expire.nil? || expire.empty? ? 0 : expire.to_i + + puts I18n.t('form.setup_gpg_key.wait') + + if @config.setup_gpg_key(password, name, length, expire) + puts I18n.t('form.setup_gpg_key.valid') + else + puts "#{I18n.t('display.error')}: #{@config.error_msg}" + exit 2 + end + end + # Request the GPG password and decrypt the file def decrypt if !defined?(@mpw) diff --git a/i18n/cli/en.yml b/i18n/cli/en.yml index 622dfe8..dd58ab0 100644 --- a/i18n/cli/en.yml +++ b/i18n/cli/en.yml @@ -5,6 +5,10 @@ en: write: "Can't write the config file!" check: "Checkconfig failed!" key_bad_format: "The key string isn't in good format!" + genkey_gpg: + exception: "Can't create the GPG key!" + name: "You must define a name for your GPG key!" + password: "You must define a password for your GPG key!" delete: id_no_exist: "Can't delete the item %{id}, it doesn't exist!" export: @@ -77,6 +81,13 @@ en: sync_pwd: "Password for the synchronization: " sync_path: "File path for the synchronization : " valid: "The config file has been created!" + setup_gpg_key: + title: "Setup a GPG key" + name: "Your name and lastname: " + password: "A password for the GPG key: " + length: "Size of the GPG key [default=2048]: " + expire: "Expire time of the GPG key [default=0 (unlimited)]: " + wait: "Please waiting during the GPG key generate, this process can take few minutes." update: title: "Update an item" name: "Enter the name [%{name}]: " diff --git a/i18n/cli/fr.yml b/i18n/cli/fr.yml index 1f2f7b2..e38e00d 100644 --- a/i18n/cli/fr.yml +++ b/i18n/cli/fr.yml @@ -5,6 +5,10 @@ fr: write: "Impossible d'écrire le fichier de configuration!" check: "Le fichier de configuration est invalide!" key_bad_format: "La clé GPG est invalide!" + genkey_gpg: + exception: "La création de la clé GPG n'a pas pu aboutir!" + name: "Vous devez définir un nom pour votre clé GPG!" + password: "Vous devez définir un mot de passe pour votre clé GPG!" delete: id_no_exist: "Impossible de supprimer l'élément %{id}, car il n'existe pas!" export: @@ -77,6 +81,13 @@ fr: sync_pwd: "Mot de passe pour la synchronisation: " sync_path: "Chemin du fichier pour la synchronisation: " valid: "Le fichier de configuration a bien été créé!" + setup_gpg_key: + title: "Configuration d'une clé GPG" + name: "Votre nom et prénom: " + password: "Mot de passe de la clé GPG: " + length: "Taille de la clé GPG [défaut=2048]: " + expire: "Expiration de la clé GPG [défaut=0 (illimité)]: " + wait: "Veuillez patienter durant la génération de votre clé GPG, ce processus peut prendre quelques minutes." update: title: "Mis à jour d'un élément" name: "Entrez le nom [%{name}]: " diff --git a/mpw b/mpw index c13baeb..6db35f0 100755 --- a/mpw +++ b/mpw @@ -117,6 +117,8 @@ cli = Cli.new(lang, config) # Setup a new config if !check_error || !options[:setup].nil? cli.setup(lang) +elsif !config.check_gpg_key? + cli.setup_gpg_key end cli.decrypt From ba297c3d7db6046b7796397d45502b1bf2e4326d Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Tue, 18 Mar 2014 21:08:09 +0100 Subject: [PATCH 071/531] ask if you want create gpg key --- MPW/Config.rb | 5 +++++ MPW/UI/Cli.rb | 7 +++++++ i18n/cli/en.yml | 2 ++ i18n/cli/fr.yml | 2 ++ 4 files changed, 16 insertions(+) diff --git a/MPW/Config.rb b/MPW/Config.rb index 42a840d..fadfbff 100644 --- a/MPW/Config.rb +++ b/MPW/Config.rb @@ -99,6 +99,11 @@ module MPW end # Setup a new gpg key + # @args: password -> the GPG key password + # name -> the name of user + # length -> length of the GPG key + # expire -> the time of expire to GPG key + # @rtrn: true if the GPG key is create, else false def setup_gpg_key(password, name, length = 2048, expire = 0) if name.nil? || name.empty? @error_msg = "#{I18n.t('error.config.genkey_gpg.name')}" diff --git a/MPW/UI/Cli.rb b/MPW/UI/Cli.rb index 050e0d4..baf522e 100644 --- a/MPW/UI/Cli.rb +++ b/MPW/UI/Cli.rb @@ -118,6 +118,13 @@ class Cli def setup_gpg_key puts I18n.t('form.setup_gpg_key.title') puts '--------------------' + ask = ask(I18n.t('form.setup_gpg_key.ask')).to_s + + if !['Y', 'y', 'O', 'o'].include?(ask) + puts I18n.t('form.setup_gpg_key.no_create') + exit 2 + end + name = ask(I18n.t('form.setup_gpg_key.name')).to_s password = ask(I18n.t('form.setup_gpg_key.password')).to_s length = ask(I18n.t('form.setup_gpg_key.length')).to_s diff --git a/i18n/cli/en.yml b/i18n/cli/en.yml index dd58ab0..61df851 100644 --- a/i18n/cli/en.yml +++ b/i18n/cli/en.yml @@ -83,6 +83,8 @@ en: valid: "The config file has been created!" setup_gpg_key: title: "Setup a GPG key" + ask: "Do you want create your GPG key ? (Y/n)" + no_create: "You must create manually your GPG key or relaunch the software." name: "Your name and lastname: " password: "A password for the GPG key: " length: "Size of the GPG key [default=2048]: " diff --git a/i18n/cli/fr.yml b/i18n/cli/fr.yml index e38e00d..cc2a982 100644 --- a/i18n/cli/fr.yml +++ b/i18n/cli/fr.yml @@ -83,6 +83,8 @@ fr: valid: "Le fichier de configuration a bien été créé!" setup_gpg_key: title: "Configuration d'une clé GPG" + ask: "Voulez vous créer votre clé GPG ? (O/n)" + no_create: "Veuillez créer manuellement votre clé GPG ou relancer le logiciel." name: "Votre nom et prénom: " password: "Mot de passe de la clé GPG: " length: "Taille de la clé GPG [défaut=2048]: " From d477a8a939f6fd783d7dcb2399b38c7372e8fbc7 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Wed, 19 Mar 2014 20:50:12 +0100 Subject: [PATCH 072/531] check if we have the public share key --- MPW/Config.rb | 10 ++++++++-- i18n/cli/en.yml | 2 ++ i18n/cli/fr.yml | 2 ++ 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/MPW/Config.rb b/MPW/Config.rb index fadfbff..c2c7d8d 100644 --- a/MPW/Config.rb +++ b/MPW/Config.rb @@ -66,6 +66,11 @@ module MPW @error_msg = I18n.t('error.config.key_bad_format') return false end + + if !check_gpg_key?(k, false) + @error_msg = I18n.t('error.config.no_key_public', :key => k) + return false + end end end @@ -166,10 +171,11 @@ module MPW end # Check if private key exist + # @args: only_private -> search only private key # @rtrn: true if the key exist, else false - def check_gpg_key? + def check_gpg_key?(key = @key, only_private = true) ctx = GPGME::Ctx.new - ctx.each_key(@key, true) do |key| + ctx.each_key(key, only_private) do return true end diff --git a/i18n/cli/en.yml b/i18n/cli/en.yml index 61df851..1d29686 100644 --- a/i18n/cli/en.yml +++ b/i18n/cli/en.yml @@ -5,6 +5,7 @@ en: write: "Can't write the config file!" check: "Checkconfig failed!" key_bad_format: "The key string isn't in good format!" + no_key_public: "You haven't the public key of %{key}!" genkey_gpg: exception: "Can't create the GPG key!" name: "You must define a name for your GPG key!" @@ -90,6 +91,7 @@ en: length: "Size of the GPG key [default=2048]: " expire: "Expire time of the GPG key [default=0 (unlimited)]: " wait: "Please waiting during the GPG key generate, this process can take few minutes." + valid: "Your GPG key has been created ;-)" update: title: "Update an item" name: "Enter the name [%{name}]: " diff --git a/i18n/cli/fr.yml b/i18n/cli/fr.yml index cc2a982..1ea2e57 100644 --- a/i18n/cli/fr.yml +++ b/i18n/cli/fr.yml @@ -5,6 +5,7 @@ fr: write: "Impossible d'écrire le fichier de configuration!" check: "Le fichier de configuration est invalide!" key_bad_format: "La clé GPG est invalide!" + no_key_public: "Vous ne possédez pas la clé publique de %{key}!" genkey_gpg: exception: "La création de la clé GPG n'a pas pu aboutir!" name: "Vous devez définir un nom pour votre clé GPG!" @@ -90,6 +91,7 @@ fr: length: "Taille de la clé GPG [défaut=2048]: " expire: "Expiration de la clé GPG [défaut=0 (illimité)]: " wait: "Veuillez patienter durant la génération de votre clé GPG, ce processus peut prendre quelques minutes." + valid: "Votre clé GPG a bien été créée ;-)" update: title: "Mis à jour d'un élément" name: "Entrez le nom [%{name}]: " From f15b4e47bf7144f9fe32876df1555c9b75ff9ef6 Mon Sep 17 00:00:00 2001 From: adrien <adrien.waksberg@believedigital.com> Date: Fri, 4 Apr 2014 17:03:46 +0200 Subject: [PATCH 073/531] fix show GPG password in setup and add confirm password --- MPW/UI/Cli.rb | 10 +++++++++- i18n/cli/en.yml | 2 ++ i18n/cli/fr.yml | 2 ++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/MPW/UI/Cli.rb b/MPW/UI/Cli.rb index baf522e..d59519a 100644 --- a/MPW/UI/Cli.rb +++ b/MPW/UI/Cli.rb @@ -126,9 +126,17 @@ class Cli end name = ask(I18n.t('form.setup_gpg_key.name')).to_s - password = ask(I18n.t('form.setup_gpg_key.password')).to_s + password = ask(I18n.t('form.setup_gpg_key.password')) {|q| q.echo = false} + confirm = ask(I18n.t('form.setup_gpg_key.confirm_password')) {|q| q.echo = false} + + if password != confirm + puts I18n.t('form.setup_gpg_key.error_password') + exit 2 + end + length = ask(I18n.t('form.setup_gpg_key.length')).to_s expire = ask(I18n.t('form.setup_gpg_key.expire')).to_s + password = password.to_s length = length.nil? || length.empty? ? 2048 : length.to_i expire = expire.nil? || expire.empty? ? 0 : expire.to_i diff --git a/i18n/cli/en.yml b/i18n/cli/en.yml index 1d29686..082c2f1 100644 --- a/i18n/cli/en.yml +++ b/i18n/cli/en.yml @@ -88,6 +88,8 @@ en: no_create: "You must create manually your GPG key or relaunch the software." name: "Your name and lastname: " password: "A password for the GPG key: " + confirm_password: "Confirm your password: " + error_password: "Your passwords aren't identical!" length: "Size of the GPG key [default=2048]: " expire: "Expire time of the GPG key [default=0 (unlimited)]: " wait: "Please waiting during the GPG key generate, this process can take few minutes." diff --git a/i18n/cli/fr.yml b/i18n/cli/fr.yml index 1ea2e57..146ca02 100644 --- a/i18n/cli/fr.yml +++ b/i18n/cli/fr.yml @@ -88,6 +88,8 @@ fr: no_create: "Veuillez créer manuellement votre clé GPG ou relancer le logiciel." name: "Votre nom et prénom: " password: "Mot de passe de la clé GPG: " + confirm_password: "Retapez votre mot de passe: " + error_password: "Vos deux mots de passes ne sont pas identiques!" length: "Taille de la clé GPG [défaut=2048]: " expire: "Expiration de la clé GPG [défaut=0 (illimité)]: " wait: "Veuillez patienter durant la génération de votre clé GPG, ce processus peut prendre quelques minutes." From 57d1a700c65d5bd45dac3cb4e0d19b3be6a09d7c Mon Sep 17 00:00:00 2001 From: adrien <adrien.waksberg@believedigital.com> Date: Fri, 4 Apr 2014 17:04:51 +0200 Subject: [PATCH 074/531] fix missing and error translation --- i18n/cli/en.yml | 2 +- i18n/cli/fr.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/i18n/cli/en.yml b/i18n/cli/en.yml index 082c2f1..e8f7d16 100644 --- a/i18n/cli/en.yml +++ b/i18n/cli/en.yml @@ -72,7 +72,7 @@ en: title: "Setup a new config file" lang: "Choose your language (en, fr, ...): " gpg_key: "Enter the GPG key: " - share_gpg_key: "Enter the GPG keys with who you want to share the passwords: " + share_gpg_keys: "Enter the GPG keys with who you want to share the passwords: " gpg_file: "Enter the path to encrypt file [default=%{home}/.mpw.gpg]: " timeout: "Enter the timeout (in seconde) to GPG password [default=60]: " sync_type: "Synchronization type (mpw, ssh, ftp, or nil): " diff --git a/i18n/cli/fr.yml b/i18n/cli/fr.yml index 146ca02..bb5491d 100644 --- a/i18n/cli/fr.yml +++ b/i18n/cli/fr.yml @@ -53,7 +53,7 @@ fr: title: "Ajout d'un nouvel élément" name: "Entrez le nom: " group: "Entrez le groupe (optionnel): " - server: "Entrez the hostname or ip: " + server: "Entrez le nom de domaine ou l'ip: " protocol: "Entrez le protocole de connexion (ssh, http, other): " login: "Entrez l'identifiant de connexion: " password: "Entrez le mot de passe: " @@ -72,7 +72,7 @@ fr: title: "Création d'un nouveau fichier de configuration" lang: "Choisissez votre langue (en, fr, ...) [défaut=%{lang}]: " gpg_key: "Entrez la clé GPG: " - share_gpg_key: "Entrez les clés GPG avec qui vous voulez partager les mots de passe: " + share_gpg_keys: "Entrez les clés GPG avec qui vous voulez partager les mots de passe: " gpg_file: "Entrez le chemin du fichier qui sera chiffré [défaut=%{home}/.mpw.gpg]: " timeout: "Entrez le temps (en seconde) du mot de passe GPG [défaut=60]: " sync_type: "Type de synchronisation (mpw, ssh, ftp, or nil): " From 08fbd258462d600dccf963d033e7cfe124869cce Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Mon, 21 Apr 2014 22:30:41 +0200 Subject: [PATCH 075/531] fix the issue 3, bad password --- MPW/Config.rb | 48 +++++++++++++++++++++++++++++++----------------- 1 file changed, 31 insertions(+), 17 deletions(-) diff --git a/MPW/Config.rb b/MPW/Config.rb index c2c7d8d..4a3b6b1 100644 --- a/MPW/Config.rb +++ b/MPW/Config.rb @@ -59,19 +59,8 @@ module MPW return false end - share_keys = share_keys.nil? ? '' : share_keys - if !share_keys.empty? - share_keys.split.each do |k| - if not k =~ /[a-zA-Z0-9.-_]+\@[a-zA-Z0-9]+\.[a-zA-Z]+/ - @error_msg = I18n.t('error.config.key_bad_format') - return false - end - - if !check_gpg_key?(k, false) - @error_msg = I18n.t('error.config.no_key_public', :key => k) - return false - end - end + if !check_public_gpg_key(share_keys) + return false end if file_gpg.empty? @@ -128,7 +117,7 @@ module MPW param << "Name-Comment: #{name}\n" param << "Name-Email: #{@key}\n" param << "Expire-Date: #{expire}\n" - param << "Passphrase: apc\n" + param << "Passphrase: #{password}\n" param << "</GnupgKeyParms>\n" ctx = GPGME::Ctx.new @@ -171,16 +160,41 @@ module MPW end # Check if private key exist - # @args: only_private -> search only private key # @rtrn: true if the key exist, else false - def check_gpg_key?(key = @key, only_private = true) + def check_gpg_key? ctx = GPGME::Ctx.new - ctx.each_key(key, only_private) do + ctx.each_key(key, true) do return true end return false end + + # Check if private key exist + # @args: share_keys -> string with all public keys + # @rtrn: true if the key exist, else false + def check_public_gpg_key(share_keys = @share_keys) + ctx = GPGME::Ctx.new + + share_keys = share_keys.nil? ? '' : share_keys + if !share_keys.empty? + share_keys.split.each do |k| + if not k =~ /[a-zA-Z0-9.-_]+\@[a-zA-Z0-9]+\.[a-zA-Z]+/ + @error_msg = I18n.t('error.config.key_bad_format') + return false + end + + ctx.each_key(key, false) do + next + end + + @error_msg = I18n.t('error.config.no_key_public', :key => k) + return false + end + end + + return true + end # Set the last update when there is a sync # @rtrn: true is the file has been updated From 7305ecef0f3a3cf30f885950dca353ecc01ba2df Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sun, 27 Apr 2014 15:13:43 +0200 Subject: [PATCH 076/531] fix bug salt in mpw server --- lib/Server.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/Server.rb b/lib/Server.rb index 2d55de0..94ca075 100644 --- a/lib/Server.rb +++ b/lib/Server.rb @@ -130,7 +130,7 @@ class Server hash = gpg_data['gpg']['hash'] else - salt = salt + salt = generate_salt hash = Digest::SHA256.hexdigest(salt + msg['password']) end @@ -311,7 +311,7 @@ class Server # Generate a random salt # @args: length -> the length salt # @rtrn: a random string - def salt(length=4) + def generate_salt(length=4) if length.to_i <= 0 || length.to_i > 16 length = 4 else From 0739be1763426315ba47f9f0cd6589e40094a271 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sun, 27 Apr 2014 15:17:37 +0200 Subject: [PATCH 077/531] fix bug when the MPW server haven't data --- MPW/MPW.rb | 2 ++ MPW/Sync/MPWSync.rb | 13 +++++++------ 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/MPW/MPW.rb b/MPW/MPW.rb index 05da9cf..71e6f3d 100644 --- a/MPW/MPW.rb +++ b/MPW/MPW.rb @@ -273,6 +273,8 @@ module MPW def sync(data_remote, last_update) if !data_remote.instance_of?(Array) return false + else data_remote.nil? || data_remote.empty? + return true end @data.each do |l| diff --git a/MPW/Sync/MPWSync.rb b/MPW/Sync/MPWSync.rb index da62975..8e6c700 100644 --- a/MPW/Sync/MPWSync.rb +++ b/MPW/Sync/MPWSync.rb @@ -67,9 +67,14 @@ module MPW end if !defined?(msg['error']) - error_msg = I18n.t('error.sync.communication') + @error_msg = I18n.t('error.sync.communication') return nil - elsif msg['error'].nil? + elsif !msg['error'].nil? + @error_msg = I18n.t(msg['error']) + return nil + elsif msg['data'].nil? || msg['data'].empty? + return [] + else tmp_file = tmpfile File.open(tmp_file, 'w') do |file| file << msg['data'] @@ -83,11 +88,7 @@ module MPW File.unlink(tmp_file) return mpw.search - else - @error_msg = I18n.t(msg['error']) - return nil end - end # Update the remote data From fe973c2fac6937e59f5333e6c1aa7a8393207bea Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sun, 27 Apr 2014 18:10:21 +0200 Subject: [PATCH 078/531] fix bug sync when the gpg file doesn't exist --- MPW/MPW.rb | 42 ++++++++++++++++++++---------------------- 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/MPW/MPW.rb b/MPW/MPW.rb index 71e6f3d..f48bad4 100644 --- a/MPW/MPW.rb +++ b/MPW/MPW.rb @@ -273,30 +273,28 @@ module MPW def sync(data_remote, last_update) if !data_remote.instance_of?(Array) return false - else data_remote.nil? || data_remote.empty? - return true - end - - @data.each do |l| - j = 0 - update = false - - # Update item - data_remote.each do |r| - if l[ID] == r[ID] - if l[DATE].to_i < r[DATE].to_i - update(r[NAME], r[GROUP], r[SERVER], r[PROTOCOL], r[LOGIN], r[PASSWORD], r[PORT], r[COMMENT], l[ID]) + else !data_remote.nil? && !data_remote.empty? + @data.each do |l| + j = 0 + update = false + + # Update item + data_remote.each do |r| + if l[ID] == r[ID] + if l[DATE].to_i < r[DATE].to_i + update(r[NAME], r[GROUP], r[SERVER], r[PROTOCOL], r[LOGIN], r[PASSWORD], r[PORT], r[COMMENT], l[ID]) + end + update = true + data_remote.delete_at(j) + break end - update = true - data_remote.delete_at(j) - break + j += 1 + end + + # Delete an old item + if !update && l[DATE].to_i < last_update + remove(l[ID]) end - j += 1 - end - - # Delete an old item - if !update && l[DATE].to_i < last_update - remove(l[ID]) end end From 64c0e7766f12e874e8f30e0b17c5006c672c4e0c Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sun, 27 Apr 2014 18:16:42 +0200 Subject: [PATCH 079/531] fix bug, you can't install the ruby-net-scp --- MPW/UI/Cli.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/MPW/UI/Cli.rb b/MPW/UI/Cli.rb index d59519a..2ea57f1 100644 --- a/MPW/UI/Cli.rb +++ b/MPW/UI/Cli.rb @@ -11,9 +11,6 @@ require 'i18n' require 'yaml' require "#{APP_ROOT}/MPW/MPW" -require "#{APP_ROOT}/MPW/Sync/MPWSync" -require "#{APP_ROOT}/MPW/Sync/SSH" -require "#{APP_ROOT}/MPW/Sync/FTP" class Cli @@ -30,10 +27,13 @@ class Cli if !defined?(@sync) case @config.sync_type when 'mpw' + require "#{APP_ROOT}/MPW/Sync/MPWSync" @sync = MPW::Sync::MPWSync.new when 'sftp', 'scp', 'ssh' + require "#{APP_ROOT}/MPW/Sync/SSH" @sync = MPW::Sync::SSH.new when 'ftp' + require "#{APP_ROOT}/MPW/Sync/FTP" @sync = MPW::Sync::FTP.new else return false From e290352dceccb88854638c9c51bddc892830abf5 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sun, 27 Apr 2014 18:17:13 +0200 Subject: [PATCH 080/531] update readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b2eda64..7816d0d 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ This program work with ruby >= 1.9 * apt-get install ruby ruby-gpgme ruby-highline ruby-i18n ruby-locale If you want to synchronize your password via SSH/SCP: -* apt-get install ruby-ssh ruby-scp +* apt-get install ruby-net-ssh ruby-net-scp For mpw-ssh: * apt-get install sshpass From 3c272b3127c3a39d4654adf33967d68d11972a41 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sun, 27 Apr 2014 18:23:28 +0200 Subject: [PATCH 081/531] mv lib/Server.rb in MPW --- MPW/Server.rb | 329 ++++++++++++++++++++++++++++++++++++++++++++++++++ lib/Server.rb | 324 ------------------------------------------------- mpw-server | 4 +- 3 files changed, 331 insertions(+), 326 deletions(-) create mode 100644 MPW/Server.rb delete mode 100644 lib/Server.rb diff --git a/MPW/Server.rb b/MPW/Server.rb new file mode 100644 index 0000000..2a52994 --- /dev/null +++ b/MPW/Server.rb @@ -0,0 +1,329 @@ +#!/usr/bin/ruby + +module MPW + + require 'socket' + require 'json' + require 'highline/import' + require 'digest' + require 'logger' + + + class Server + + attr_accessor :error_msg + + # Constructor + def initialize + YAML::ENGINE.yamler='syck' + end + + # Start the server + def start + server = TCPServer.open(@host, @port) + @log.info("The server is started on #{@host}:#{@port}") + + loop do + Thread.start(server.accept) do |client| + @log.info("#{client.peeraddr[3]} is connected") + + while true do + msg = get_client_msg(client) + + if !msg + next + end + + if msg['gpg_key'].nil? || msg['gpg_key'].empty? || msg['password'].nil? || msg['password'].empty? + @log.warning("#{client.peeraddr[3]} is disconnected because no password or no gpg_key") + close_connection(client) + next + end + + case msg['action'] + when 'get' + @log.debug("#{client.peeraddr[3]} GET gpg_key=#{msg['gpg_key']} suffix=#{msg['suffix']}") + client.puts get_file(msg) + when 'update' + @log.debug("#{client.peeraddr[3]} UPDATE gpg_key=#{msg['gpg_key']} suffix=#{msg['suffix']}") + client.puts update_file(msg) + when 'delete' + @log.debug("#{client.peeraddr[3]} DELETE gpg_key=#{msg['gpg_key']} suffix=#{msg['suffix']}") + client.puts delete_file(msg) + else + @log.warning("#{client.peeraddr[3]} is disconnected because unkwnow command") + send_msg = {:action => 'unknown', + :gpg_key => msg['gpg_key'], + :error => 'server.error.client.unknown'} + client.puts send_msg + close_connection(client) + end + end + end + end + + rescue Exception => e + puts "Impossible to start the server: #{e}" + @log.error("Impossible to start the server: #{e}") + exit 2 + end + + # Get a gpg file + # @args: msg -> message puts by the client + # @rtrn: json message + def get_file(msg) + gpg_key = msg['gpg_key'].sub('@', '_') + + if msg['suffix'].nil? || msg['suffix'].empty? + file_gpg = "#{@data_dir}/#{gpg_key}.yml" + else + file_gpg = "#{@data_dir}/#{gpg_key}-#{msg['suffix']}.yml" + end + + if File.exist?(file_gpg) + gpg_data = YAML::load_file(file_gpg) + salt = gpg_data['gpg']['salt'] + hash = gpg_data['gpg']['hash'] + data = gpg_data['gpg']['data'] + + if is_authorized?(msg['password'], salt, hash) + send_msg = {:action => 'get', + :gpg_key => msg['gpg_key'], + :data => data, + :error => nil} + else + send_msg = {:action => 'get', + :gpg_key => msg['gpg_key'], + :error => 'server.error.client.no_authorized'} + end + else + send_msg = {:action => 'get', + :gpg_key => msg['gpg_key'], + :data => '', + :error => nil} + end + + return send_msg.to_json + end + + # Update a file + # @args: msg -> message puts by the client + # @rtrn: json message + def update_file(msg) + gpg_key = msg['gpg_key'].sub('@', '_') + data = msg['data'] + + if data.nil? || data.empty? + send_msg = {:action => 'update', + :gpg_key => msg['gpg_key'], + :error => 'server.error.client.no_data'} + + return send_msg.to_json + end + + if msg['suffix'].nil? || msg['suffix'].empty? + file_gpg = "#{@data_dir}/#{gpg_key}.yml" + else + file_gpg = "#{@data_dir}/#{gpg_key}-#{msg['suffix']}.yml" + end + + if File.exist?(file_gpg) + gpg_data = YAML::load_file(file_gpg) + salt = gpg_data['gpg']['salt'] + hash = gpg_data['gpg']['hash'] + + else + salt = generate_salt + hash = Digest::SHA256.hexdigest(salt + msg['password']) + end + + if is_authorized?(msg['password'], salt, hash) + begin + config = {'gpg' => {'salt' => salt, + 'hash' => hash, + 'data' => data}} + + File.open(file_gpg, 'w+') do |file| + file << config.to_yaml + end + + send_msg = {:action => 'update', + :gpg_key => msg['gpg_key'], + :error => nil} + rescue Exception => e + send_msg = {:action => 'update', + :gpg_key => msg['gpg_key'], + :error => 'server.error.client.unknown'} + end + else + send_msg = {:action => 'update', + :gpg_key => msg['gpg_key'], + :error => 'server.error.client.no_authorized'} + end + + return send_msg.to_json + end + + # Remove a gpg file + # @args: msg -> message puts by the client + # @rtrn: json message + def delete_file(msg) + gpg_key = msg['gpg_key'].sub('@', '_') + + if msg['suffix'].nil? || msg['suffix'].empty? + file_gpg = "#{@data_dir}/#{gpg_key}.yml" + else + file_gpg = "#{@data_dir}/#{gpg_key}-#{msg['suffix']}.yml" + end + + if !File.exist?(file_gpg) + send_msg = {:action => 'delete', + :gpg_key => msg['gpg_key'], + :error => nil} + + return send_msg.to_json + end + + gpg_data = YAML::load_file(file_gpg) + salt = gpg_data['gpg']['salt'] + hash = gpg_data['gpg']['hash'] + + if is_authorized?(msg['password'], salt, hash) + begin + File.unlink(file_gpg) + + send_msg = {:action => 'delete', + :gpg_key => msg['gpg_key'], + :error => nil} + rescue Exception => e + send_msg = {:action => 'delete', + :gpg_key => msg['gpg_key'], + :error => 'server.error.client.unknown'} + end + else + send_msg = {:action => 'delete', + :gpg_key => msg['gpg_key'], + :error => 'server.error.client.no_authorized'} + end + + return send_msg.to_json + end + + # Check is the hash equal the password with the salt + # @args: password -> the user password + # salt -> the salt + # hash -> the hash of the password with the salt + # @rtrn: true is is good, else false + def is_authorized?(password, salt, hash) + if hash == Digest::SHA256.hexdigest(salt + password) + return true + else + return false + end + end + + # Get message to client + # @args: client -> client connection + # @rtrn: array of the json string, or false if isn't json message + def get_client_msg(client) + msg = client.gets + return JSON.parse(msg) + rescue + closeConnection(client) + return false + end + + # Close the client connection + # @args: client -> client connection + def close_connection(client) + client.puts "Closing the connection. Bye!" + client.close + end + + # Check the config file + # @args: file_config -> the configuration file + # @rtrn: true if the config file is correct + def checkconfig(file_config) + config = YAML::load_file(file_config) + @host = config['config']['host'] + @port = config['config']['port'].to_i + @data_dir = config['config']['data_dir'] + @log_file = config['config']['log_file'] + @timeout = config['config']['timeout'].to_i + + if @host.empty? || @port <= 0 || @data_dir.empty? + puts I18n.t('checkconfig.fail') + puts I18n.t('checkconfig.empty') + return false + end + + if !Dir.exist?(@data_dir) + puts I18n.t('checkconfig.fail') + puts I18n.t('checkconfig.datadir') + return false + end + + if @log_file.nil? || @log_file.empty? + puts I18n.t('checkconfig.fail') + puts I18n.t('checkconfig.log_file_empty') + return false + else + begin + @log = Logger.new(@log_file) + rescue + puts I18n.t('checkconfig.fail') + puts I18n.t('checkconfig.log_file_create') + return false + end + end + + return true + rescue Exception => e + puts "#{I18n.t('checkconfig.fail')}\n#{e}" + return false + end + + # Create a new config file + # @args: file_config -> the configuration file + # @rtrn: true if le config file is create + def setup(file_config) + puts I18n.t('form.setup.title') + puts '--------------------' + host = ask(I18n.t('form.setup.host')).to_s + port = ask(I18n.t('form.setup.port')).to_s + data_dir = ask(I18n.t('form.setup.data_dir')).to_s + log_file = ask(I18n.t('form.setup.log_file')).to_s + timeout = ask(I18n.t('form.setup.timeout')).to_s + + config = {'config' => {'host' => host, + 'port' => port, + 'data_dir' => data_dir, + 'log_file' => log_file, + 'timeout' => timeout}} + + File.open(file_config, 'w') do |file| + file << config.to_yaml + end + + return true + rescue Exception => e + puts "#{I18n.t('form.setup.not_valid')}\n#{e}" + return false + end + + # Generate a random salt + # @args: length -> the length salt + # @rtrn: a random string + def generate_salt(length=4) + if length.to_i <= 0 || length.to_i > 16 + length = 4 + else + length = length.to_i + end + + return ([*('A'..'Z'),*('a'..'z'),*('0'..'9')]).sample(length).join + end + + end + +end diff --git a/lib/Server.rb b/lib/Server.rb deleted file mode 100644 index 94ca075..0000000 --- a/lib/Server.rb +++ /dev/null @@ -1,324 +0,0 @@ -#!/usr/bin/ruby - -require 'socket' -require 'json' -require 'highline/import' -require 'digest' -require 'logger' - -class Server - - attr_accessor :error_msg - - # Constructor - def initialize - YAML::ENGINE.yamler='syck' - end - - # Start the server - def start - server = TCPServer.open(@host, @port) - @log.info("The server is started on #{@host}:#{@port}") - - loop do - Thread.start(server.accept) do |client| - @log.info("#{client.peeraddr[3]} is connected") - - while true do - msg = get_client_msg(client) - - if !msg - next - end - - if msg['gpg_key'].nil? || msg['gpg_key'].empty? || msg['password'].nil? || msg['password'].empty? - @log.warning("#{client.peeraddr[3]} is disconnected because no password or no gpg_key") - close_connection(client) - next - end - - case msg['action'] - when 'get' - @log.debug("#{client.peeraddr[3]} GET gpg_key=#{msg['gpg_key']} suffix=#{msg['suffix']}") - client.puts get_file(msg) - when 'update' - @log.debug("#{client.peeraddr[3]} UPDATE gpg_key=#{msg['gpg_key']} suffix=#{msg['suffix']}") - client.puts update_file(msg) - when 'delete' - @log.debug("#{client.peeraddr[3]} DELETE gpg_key=#{msg['gpg_key']} suffix=#{msg['suffix']}") - client.puts delete_file(msg) - else - @log.warning("#{client.peeraddr[3]} is disconnected because unkwnow command") - send_msg = {:action => 'unknown', - :gpg_key => msg['gpg_key'], - :error => 'server.error.client.unknown'} - client.puts send_msg - close_connection(client) - end - end - end - end - - rescue Exception => e - puts "Impossible to start the server: #{e}" - @log.error("Impossible to start the server: #{e}") - exit 2 - end - - # Get a gpg file - # @args: msg -> message puts by the client - # @rtrn: json message - def get_file(msg) - gpg_key = msg['gpg_key'].sub('@', '_') - - if msg['suffix'].nil? || msg['suffix'].empty? - file_gpg = "#{@data_dir}/#{gpg_key}.yml" - else - file_gpg = "#{@data_dir}/#{gpg_key}-#{msg['suffix']}.yml" - end - - if File.exist?(file_gpg) - gpg_data = YAML::load_file(file_gpg) - salt = gpg_data['gpg']['salt'] - hash = gpg_data['gpg']['hash'] - data = gpg_data['gpg']['data'] - - if is_authorized?(msg['password'], salt, hash) - send_msg = {:action => 'get', - :gpg_key => msg['gpg_key'], - :data => data, - :error => nil} - else - send_msg = {:action => 'get', - :gpg_key => msg['gpg_key'], - :error => 'server.error.client.no_authorized'} - end - else - send_msg = {:action => 'get', - :gpg_key => msg['gpg_key'], - :data => '', - :error => nil} - end - - return send_msg.to_json - end - - # Update a file - # @args: msg -> message puts by the client - # @rtrn: json message - def update_file(msg) - gpg_key = msg['gpg_key'].sub('@', '_') - data = msg['data'] - - if data.nil? || data.empty? - send_msg = {:action => 'update', - :gpg_key => msg['gpg_key'], - :error => 'server.error.client.no_data'} - - return send_msg.to_json - end - - if msg['suffix'].nil? || msg['suffix'].empty? - file_gpg = "#{@data_dir}/#{gpg_key}.yml" - else - file_gpg = "#{@data_dir}/#{gpg_key}-#{msg['suffix']}.yml" - end - - if File.exist?(file_gpg) - gpg_data = YAML::load_file(file_gpg) - salt = gpg_data['gpg']['salt'] - hash = gpg_data['gpg']['hash'] - - else - salt = generate_salt - hash = Digest::SHA256.hexdigest(salt + msg['password']) - end - - if is_authorized?(msg['password'], salt, hash) - begin - config = {'gpg' => {'salt' => salt, - 'hash' => hash, - 'data' => data}} - - File.open(file_gpg, 'w+') do |file| - file << config.to_yaml - end - - send_msg = {:action => 'update', - :gpg_key => msg['gpg_key'], - :error => nil} - rescue Exception => e - send_msg = {:action => 'update', - :gpg_key => msg['gpg_key'], - :error => 'server.error.client.unknown'} - end - else - send_msg = {:action => 'update', - :gpg_key => msg['gpg_key'], - :error => 'server.error.client.no_authorized'} - end - - return send_msg.to_json - end - - # Remove a gpg file - # @args: msg -> message puts by the client - # @rtrn: json message - def delete_file(msg) - gpg_key = msg['gpg_key'].sub('@', '_') - - if msg['suffix'].nil? || msg['suffix'].empty? - file_gpg = "#{@data_dir}/#{gpg_key}.yml" - else - file_gpg = "#{@data_dir}/#{gpg_key}-#{msg['suffix']}.yml" - end - - if !File.exist?(file_gpg) - send_msg = {:action => 'delete', - :gpg_key => msg['gpg_key'], - :error => nil} - - return send_msg.to_json - end - - gpg_data = YAML::load_file(file_gpg) - salt = gpg_data['gpg']['salt'] - hash = gpg_data['gpg']['hash'] - - if is_authorized?(msg['password'], salt, hash) - begin - File.unlink(file_gpg) - - send_msg = {:action => 'delete', - :gpg_key => msg['gpg_key'], - :error => nil} - rescue Exception => e - send_msg = {:action => 'delete', - :gpg_key => msg['gpg_key'], - :error => 'server.error.client.unknown'} - end - else - send_msg = {:action => 'delete', - :gpg_key => msg['gpg_key'], - :error => 'server.error.client.no_authorized'} - end - - return send_msg.to_json - end - - # Check is the hash equal the password with the salt - # @args: password -> the user password - # salt -> the salt - # hash -> the hash of the password with the salt - # @rtrn: true is is good, else false - def is_authorized?(password, salt, hash) - if hash == Digest::SHA256.hexdigest(salt + password) - return true - else - return false - end - end - - # Get message to client - # @args: client -> client connection - # @rtrn: array of the json string, or false if isn't json message - def get_client_msg(client) - msg = client.gets - return JSON.parse(msg) - rescue - closeConnection(client) - return false - end - - # Close the client connection - # @args: client -> client connection - def close_connection(client) - client.puts "Closing the connection. Bye!" - client.close - end - - # Check the config file - # @args: file_config -> the configuration file - # @rtrn: true if the config file is correct - def checkconfig(file_config) - config = YAML::load_file(file_config) - @host = config['config']['host'] - @port = config['config']['port'].to_i - @data_dir = config['config']['data_dir'] - @log_file = config['config']['log_file'] - @timeout = config['config']['timeout'].to_i - - if @host.empty? || @port <= 0 || @data_dir.empty? - puts I18n.t('checkconfig.fail') - puts I18n.t('checkconfig.empty') - return false - end - - if !Dir.exist?(@data_dir) - puts I18n.t('checkconfig.fail') - puts I18n.t('checkconfig.datadir') - return false - end - - if @log_file.nil? || @log_file.empty? - puts I18n.t('checkconfig.fail') - puts I18n.t('checkconfig.log_file_empty') - return false - else - begin - @log = Logger.new(@log_file) - rescue - puts I18n.t('checkconfig.fail') - puts I18n.t('checkconfig.log_file_create') - return false - end - end - - return true - rescue Exception => e - puts "#{I18n.t('checkconfig.fail')}\n#{e}" - return false - end - - # Create a new config file - # @args: file_config -> the configuration file - # @rtrn: true if le config file is create - def setup(file_config) - puts I18n.t('form.setup.title') - puts '--------------------' - host = ask(I18n.t('form.setup.host')).to_s - port = ask(I18n.t('form.setup.port')).to_s - data_dir = ask(I18n.t('form.setup.data_dir')).to_s - log_file = ask(I18n.t('form.setup.log_file')).to_s - timeout = ask(I18n.t('form.setup.timeout')).to_s - - config = {'config' => {'host' => host, - 'port' => port, - 'data_dir' => data_dir, - 'log_file' => log_file, - 'timeout' => timeout}} - - File.open(file_config, 'w') do |file| - file << config.to_yaml - end - - return true - rescue Exception => e - puts "#{I18n.t('form.setup.not_valid')}\n#{e}" - return false - end - - # Generate a random salt - # @args: length -> the length salt - # @rtrn: a random string - def generate_salt(length=4) - if length.to_i <= 0 || length.to_i > 16 - length = 4 - else - length = length.to_i - end - - return ([*('A'..'Z'),*('a'..'z'),*('0'..'9')]).sample(length).join - end - -end diff --git a/mpw-server b/mpw-server index d1f5192..0c94289 100755 --- a/mpw-server +++ b/mpw-server @@ -10,7 +10,7 @@ require 'locale' require 'i18n' APP_ROOT = File.dirname(Pathname.new(__FILE__).realpath) -require "#{APP_ROOT}/lib/Server.rb" +require "#{APP_ROOT}/MPW/Server.rb" # --------------------------------------------------------- # # Set local @@ -62,7 +62,7 @@ if options[:config].nil? || options[:config].empty? exit 2 end -server = Server.new +server = MPW::Server.new if options[:checkconfig] server.checkconfig(options[:config]) From b52443f9f127888ff569b43c6e0664c1a8e9d521 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sun, 27 Apr 2014 18:31:50 +0200 Subject: [PATCH 082/531] add the numbering of errors --- MPW/UI/Cli.rb | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/MPW/UI/Cli.rb b/MPW/UI/Cli.rb index 2ea57f1..cb49464 100644 --- a/MPW/UI/Cli.rb +++ b/MPW/UI/Cli.rb @@ -42,26 +42,26 @@ class Cli if !@config.sync_host.nil? && !@config.sync_port.nil? if !@sync.connect(@config.sync_host, @config.sync_user, @config.sync_pwd, @config.sync_path, @config.sync_port) - puts "#{I18n.t('display.error')}: #{@sync.error_msg}" + puts "#{I18n.t('display.error')} #1: #{@sync.error_msg}" end end if @sync.enable if !@mpw.sync(@sync.get(@passwd), @config.last_update) - puts "#{I18n.t('display.error')}: #{@mpw.error_msg}" if !@mpw.error_msg.nil? - puts "#{I18n.t('display.error')}: #{@sync.error_msg}" if !@sync.error_msg.nil? + puts "#{I18n.t('display.error')} #2: #{@mpw.error_msg}" if !@mpw.error_msg.nil? + puts "#{I18n.t('display.error')} #3: #{@sync.error_msg}" if !@sync.error_msg.nil? elsif !@sync.update(File.open(@config.file_gpg).read) - puts "#{I18n.t('display.error')}: #{@sync.error_msg}" + puts "#{I18n.t('display.error')} #4: #{@sync.error_msg}" elsif !@config.set_last_update - puts "#{I18n.t('display.error')}: #{@config.error_msg}" + puts "#{I18n.t('display.error')} #5: #{@config.error_msg}" elsif !@mpw.encrypt - puts "#{I18n.t('display.error')}: #{@mpw.error_msg}" + puts "#{I18n.t('display.error')} #6: #{@mpw.error_msg}" else return true end end rescue Exception => e - puts "#{I18n.t('display.error')}: #{e}" + puts "#{I18n.t('display.error')} #7: #{e}" puts @sync.error_msg if @sync.error_msg.nil? puts @config.error_msg if @config.error_msg.nil? puts @mpw.error_msg if @mpw.error_msg.nil? @@ -104,12 +104,12 @@ class Cli if @config.setup(key, share_keys, language, file_gpg, timeout_pwd, sync_type, sync_host, sync_port, sync_user, sync_pwd, sync_path) puts I18n.t('form.setup.valid') else - puts "#{I18n.t('display.error')}: #{@config.error_msg}" + puts "#{I18n.t('display.error')} #8: #{@config.error_msg}" exit 2 end if not @config.checkconfig - puts "#{I18n.t('display.error')}: #{@config.error_msg}" + puts "#{I18n.t('display.error')} #9: #{@config.error_msg}" exit 2 end end @@ -146,7 +146,7 @@ class Cli if @config.setup_gpg_key(password, name, length, expire) puts I18n.t('form.setup_gpg_key.valid') else - puts "#{I18n.t('display.error')}: #{@config.error_msg}" + puts "#{I18n.t('display.error')} #10: #{@config.error_msg}" exit 2 end end @@ -159,7 +159,7 @@ class Cli @passwd = ask(I18n.t('display.gpg_password')) {|q| q.echo = false} if !@mpw.decrypt(@passwd) - puts "#{I18n.t('display.error')}: #{@mpw.error_msg}" + puts "#{I18n.t('display.error')} #11: #{@mpw.error_msg}" exit 2 end end @@ -233,10 +233,10 @@ class Cli sync puts I18n.t('form.add.valid') else - puts "#{I18n.t('display.error')}: #{@mpw.error_msg}" + puts "#{I18n.t('display.error')} #12: #{@mpw.error_msg}" end else - puts "#{I18n.t('display.error')}: #{@mpw.error_msg}" + puts "#{I18n.t('display.error')} #13: #{@mpw.error_msg}" end end @@ -262,10 +262,10 @@ class Cli sync puts I18n.t('form.update.valid') else - puts "#{I18n.t('display.error')}: #{@mpw.error_msg}" + puts "#{I18n.t('display.error')} #14: #{@mpw.error_msg}" end else - puts "#{I18n.t('display.error')}: #{@mpw.error_msg}" + puts "#{I18n.t('display.error')} #15: #{@mpw.error_msg}" end else puts I18n.t('display.nothing') @@ -297,7 +297,7 @@ class Cli sync puts I18n.t('form.delete.valid', :id => id) else - puts "#{I18n.t('display.error')}: #{@mpw.error_msg}" + puts "#{I18n.t('display.error')} #16: #{@mpw.error_msg}" end else puts I18n.t('form.delete.not_valid') @@ -311,7 +311,7 @@ class Cli if @mpw.export(file) puts "The export in #{file} is succesfull!" else - puts "#{I18n.t('display.error')}: #{@mpw.error_msg}" + puts "#{I18n.t('display.error')} #17: #{@mpw.error_msg}" end end @@ -342,7 +342,7 @@ class Cli sync puts I18n.t('form.import.valid') else - puts "#{I18n.t('display.error')}: #{@mpw.error_msg}" + puts "#{I18n.t('display.error')} #18: #{@mpw.error_msg}" end end end From d17a8b557eecfcecbbccd3132f06db122ca0061a Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sun, 27 Apr 2014 18:53:20 +0200 Subject: [PATCH 083/531] add a directory conf --- MPW/Config.rb | 19 +++++++++++++++---- MPW/UI/Cli.rb | 2 +- i18n/cli/en.yml | 2 +- i18n/cli/fr.yml | 2 +- 4 files changed, 18 insertions(+), 7 deletions(-) diff --git a/MPW/Config.rb b/MPW/Config.rb index 4a3b6b1..9f6d4a1 100644 --- a/MPW/Config.rb +++ b/MPW/Config.rb @@ -27,13 +27,22 @@ module MPW attr_accessor :sync_pwd attr_accessor :sync_path attr_accessor :last_update + attr_accessor :dir_config # Constructor # @args: file_config -> the specify config file def initialize(file_config=nil) - @error_msg = nil - @file_config = "#{Dir.home}/.mpw.cfg" - + @error_msg = nil + + if /darwin/ =~ RUBY_PLATFORM + @dir_config = "#{Dir.home}/Library/Preferences/mpw" + elsif /cygwin|mswin|mingw|bccwin|wince|emx/ =~ RUBY_PLATFORM + @dir_config = "#{Dir.home}/AppData/Local/mpw" + else + @dir_config = "#{Dir.home}/.config/mpw" + end + + @file_config = "#{@dir_config}/conf/default.cfg" if !file_config.nil? && !file_config.empty? @file_config = file_config end @@ -64,7 +73,7 @@ module MPW end if file_gpg.empty? - file_gpg = "#{Dir.home}/.mpw.gpg" + file_gpg = "#{@dir_config}/db/default.gpg" end timeout_pwd = timeout_pwd.empty? ? 60 : timeout_pwd.to_i @@ -82,6 +91,8 @@ module MPW 'sync_path' => sync_path, 'last_update' => 0 }} + Dir.mkdir("#{@config_dir}/conf", 700) + Dir.mkdir("#{@config_dir}/db", 700) File.open(@file_config, 'w') do |file| file << config.to_yaml end diff --git a/MPW/UI/Cli.rb b/MPW/UI/Cli.rb index cb49464..58fa371 100644 --- a/MPW/UI/Cli.rb +++ b/MPW/UI/Cli.rb @@ -77,7 +77,7 @@ class Cli language = ask(I18n.t('form.setup.lang', :lang => lang)).to_s key = ask(I18n.t('form.setup.gpg_key')).to_s share_keys = ask(I18n.t('form.setup.share_gpg_keys')).to_s - file_gpg = ask(I18n.t('form.setup.gpg_file', :home => Dir.home)).to_s + file_gpg = ask(I18n.t('form.setup.gpg_file', :home => @conf.dir_home)).to_s timeout_pwd = ask(I18n.t('form.setup.timeout')).to_s sync_type = ask(I18n.t('form.setup.sync_type')).to_s diff --git a/i18n/cli/en.yml b/i18n/cli/en.yml index e8f7d16..0a4c03a 100644 --- a/i18n/cli/en.yml +++ b/i18n/cli/en.yml @@ -73,7 +73,7 @@ en: lang: "Choose your language (en, fr, ...): " gpg_key: "Enter the GPG key: " share_gpg_keys: "Enter the GPG keys with who you want to share the passwords: " - gpg_file: "Enter the path to encrypt file [default=%{home}/.mpw.gpg]: " + gpg_file: "Enter the path to encrypt file [default=%{home}/db/default.gpg]: " timeout: "Enter the timeout (in seconde) to GPG password [default=60]: " sync_type: "Synchronization type (mpw, ssh, ftp, or nil): " sync_host: "Synchronization server: " diff --git a/i18n/cli/fr.yml b/i18n/cli/fr.yml index bb5491d..1640cb7 100644 --- a/i18n/cli/fr.yml +++ b/i18n/cli/fr.yml @@ -73,7 +73,7 @@ fr: lang: "Choisissez votre langue (en, fr, ...) [défaut=%{lang}]: " gpg_key: "Entrez la clé GPG: " share_gpg_keys: "Entrez les clés GPG avec qui vous voulez partager les mots de passe: " - gpg_file: "Entrez le chemin du fichier qui sera chiffré [défaut=%{home}/.mpw.gpg]: " + gpg_file: "Entrez le chemin du fichier qui sera chiffré [défaut=%{home}/db/default.gpg]: " timeout: "Entrez le temps (en seconde) du mot de passe GPG [défaut=60]: " sync_type: "Type de synchronisation (mpw, ssh, ftp, or nil): " sync_host: "Serveur de synchronisation: " From 3e9e5e18d5dd0bb7b1e26522a9ac5b16230c9e29 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Tue, 29 Apr 2014 23:24:05 +0200 Subject: [PATCH 084/531] fix bug: generate password --- mpw | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mpw b/mpw index 6db35f0..a9a784a 100755 --- a/mpw +++ b/mpw @@ -12,6 +12,7 @@ require 'i18n' APP_ROOT = File.dirname(Pathname.new(__FILE__).realpath) require "#{APP_ROOT}/MPW/UI/Cli" require "#{APP_ROOT}/MPW/Config" +require "#{APP_ROOT}/MPW/MPW" # --------------------------------------------------------- # # Set local @@ -95,7 +96,7 @@ OptionParser.new do |opts| end opts.on('-G', '--generate-password [LENGTH]', I18n.t('option.generate_password')) do |length| - puts MPW::password(length) + puts MPW::MPW::password(length) exit 0 end From fe51dafd1719c5f50230bc129ebdb0d39ec16f3b Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Tue, 29 Apr 2014 23:42:06 +0200 Subject: [PATCH 085/531] Add Makefile for install on system (/usr/local/mpw) --- Makefile | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 Makefile diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..336204a --- /dev/null +++ b/Makefile @@ -0,0 +1,21 @@ +all: + $(info 'Nothing todo!') + $(info 'Use make install or make uninstall') + + +install: + mkdir -p /usr/local/mpw + cp -rv ./MPW /usr/local/mpw/ + cp -rv ./i18n /usr/local/mpw/ + cp -v ./mpw /usr/local/mpw/ + ln -snvf /usr/local/mpw/mpw /usr/local/bin/ + cp -v ./mpw-server /usr/local/mpw/ + ln -snvf /usr/local/mpw/mpw-server /usr/local/bin/mpw-server + cp -v ./mpw-ssh /usr/local/mpw/ + ln -snvf /usr/local/mpw/mpw-ssh /usr/local/bin/mpw-ssh + +uninstall: + rm -v /usr/local/bin/mpw-server + rm -v /usr/local/bin/mpw + rm -v /usr/local/bin/mpw-ssh + rm -rf /usr/local/mpw From 07f7aa5b679add9507ab9406d7299b396a74d8bc Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sun, 11 May 2014 16:42:37 +0200 Subject: [PATCH 086/531] Install ubuntu package in makefile --- Makefile | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/Makefile b/Makefile index 336204a..1e06dd9 100644 --- a/Makefile +++ b/Makefile @@ -2,20 +2,22 @@ all: $(info 'Nothing todo!') $(info 'Use make install or make uninstall') +dep-ubuntu: + apt-get install ruby ruby-gpgme ruby-highline ruby-i18n ruby-locale install: mkdir -p /usr/local/mpw - cp -rv ./MPW /usr/local/mpw/ - cp -rv ./i18n /usr/local/mpw/ - cp -v ./mpw /usr/local/mpw/ - ln -snvf /usr/local/mpw/mpw /usr/local/bin/ - cp -v ./mpw-server /usr/local/mpw/ - ln -snvf /usr/local/mpw/mpw-server /usr/local/bin/mpw-server - cp -v ./mpw-ssh /usr/local/mpw/ - ln -snvf /usr/local/mpw/mpw-ssh /usr/local/bin/mpw-ssh + cp -r ./MPW /usr/local/mpw/ + cp -r ./i18n /usr/local/mpw/ + cp ./mpw /usr/local/mpw/ + ln -snf /usr/local/mpw/mpw /usr/local/bin/ + cp ./mpw-server /usr/local/mpw/ + ln -snf /usr/local/mpw/mpw-server /usr/local/bin/mpw-server + cp ./mpw-ssh /usr/local/mpw/ + ln -snf /usr/local/mpw/mpw-ssh /usr/local/bin/mpw-ssh uninstall: - rm -v /usr/local/bin/mpw-server - rm -v /usr/local/bin/mpw - rm -v /usr/local/bin/mpw-ssh + rm /usr/local/bin/mpw-server + rm /usr/local/bin/mpw + rm /usr/local/bin/mpw-ssh rm -rf /usr/local/mpw From 4a564dd07e46788218d4a0e51dd42db58f4055a4 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sun, 31 Aug 2014 10:58:34 +0200 Subject: [PATCH 087/531] new syntax --- MPW/Server.rb | 105 ++++++++++++++++++++++++++++---------------------- 1 file changed, 60 insertions(+), 45 deletions(-) diff --git a/MPW/Server.rb b/MPW/Server.rb index 2a52994..fe70cca 100644 --- a/MPW/Server.rb +++ b/MPW/Server.rb @@ -52,9 +52,10 @@ module MPW client.puts delete_file(msg) else @log.warning("#{client.peeraddr[3]} is disconnected because unkwnow command") - send_msg = {:action => 'unknown', - :gpg_key => msg['gpg_key'], - :error => 'server.error.client.unknown'} + send_msg = {action: 'unknown', + gpg_key: msg['gpg_key'], + error: 'server.error.client.unknown' + } client.puts send_msg close_connection(client) end @@ -87,20 +88,23 @@ module MPW data = gpg_data['gpg']['data'] if is_authorized?(msg['password'], salt, hash) - send_msg = {:action => 'get', - :gpg_key => msg['gpg_key'], - :data => data, - :error => nil} + send_msg = {action: 'get', + gpg_key: msg['gpg_key'], + data: data, + error: nil + } else - send_msg = {:action => 'get', - :gpg_key => msg['gpg_key'], - :error => 'server.error.client.no_authorized'} + send_msg = {action: 'get', + gpg_key: msg['gpg_key'], + error: 'server.error.client.no_authorized' + } end else - send_msg = {:action => 'get', - :gpg_key => msg['gpg_key'], - :data => '', - :error => nil} + send_msg = {action: 'get', + gpg_key: msg['gpg_key'], + data: '', + error: nil + } end return send_msg.to_json @@ -114,9 +118,10 @@ module MPW data = msg['data'] if data.nil? || data.empty? - send_msg = {:action => 'update', - :gpg_key => msg['gpg_key'], - :error => 'server.error.client.no_data'} + send_msg = {action: 'update', + gpg_key: msg['gpg_key'], + error: 'server.error.client.no_data' + } return send_msg.to_json end @@ -139,26 +144,31 @@ module MPW if is_authorized?(msg['password'], salt, hash) begin - config = {'gpg' => {'salt' => salt, - 'hash' => hash, - 'data' => data}} + config = {'gpg' => {'salt' => salt, + 'hash' => hash, + 'data' => data + } + } File.open(file_gpg, 'w+') do |file| file << config.to_yaml end - send_msg = {:action => 'update', - :gpg_key => msg['gpg_key'], - :error => nil} + send_msg = {action: 'update', + gpg_key: msg['gpg_key'], + error: nil + } rescue Exception => e - send_msg = {:action => 'update', - :gpg_key => msg['gpg_key'], - :error => 'server.error.client.unknown'} + send_msg = {action: 'update', + gpg_key: msg['gpg_key'], + error: 'server.error.client.unknown' + } end else - send_msg = {:action => 'update', - :gpg_key => msg['gpg_key'], - :error => 'server.error.client.no_authorized'} + send_msg = {action: 'update', + gpg_key: msg['gpg_key'], + error: 'server.error.client.no_authorized' + } end return send_msg.to_json @@ -184,26 +194,29 @@ module MPW return send_msg.to_json end - gpg_data = YAML::load_file(file_gpg) - salt = gpg_data['gpg']['salt'] - hash = gpg_data['gpg']['hash'] + gpg_data = YAML::load_file(file_gpg) + salt = gpg_data['gpg']['salt'] + hash = gpg_data['gpg']['hash'] if is_authorized?(msg['password'], salt, hash) begin File.unlink(file_gpg) - send_msg = {:action => 'delete', - :gpg_key => msg['gpg_key'], - :error => nil} + send_msg = {action: 'delete', + gpg_key: msg['gpg_key'], + error: nil + } rescue Exception => e - send_msg = {:action => 'delete', - :gpg_key => msg['gpg_key'], - :error => 'server.error.client.unknown'} + send_msg = {action: 'delete', + gpg_key: msg['gpg_key'], + error: 'server.error.client.unknown' + } end else - send_msg = {:action => 'delete', - :gpg_key => msg['gpg_key'], - :error => 'server.error.client.no_authorized'} + send_msg = {action: 'delete', + gpg_key: msg['gpg_key'], + error: 'server.error.client.no_authorized' + } end return send_msg.to_json @@ -296,10 +309,12 @@ module MPW timeout = ask(I18n.t('form.setup.timeout')).to_s config = {'config' => {'host' => host, - 'port' => port, - 'data_dir' => data_dir, - 'log_file' => log_file, - 'timeout' => timeout}} + 'port' => port, + 'data_dir' => data_dir, + 'log_file' => log_file, + 'timeout' => timeout + } + } File.open(file_config, 'w') do |file| file << config.to_yaml From 1390850e1808b27890f19d7454b666a58b1282c6 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sun, 31 Aug 2014 10:59:33 +0200 Subject: [PATCH 088/531] add timeout --- MPW/Sync/MPWSync.rb | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/MPW/Sync/MPWSync.rb b/MPW/Sync/MPWSync.rb index 8e6c700..cdb05bf 100644 --- a/MPW/Sync/MPWSync.rb +++ b/MPW/Sync/MPWSync.rb @@ -11,6 +11,7 @@ module MPW require 'i18n' require 'socket' require 'json' + require 'timeout' class MPWSync @@ -37,9 +38,20 @@ module MPW @password = password @suffix = path - TCPSocket.open(@host, @port) do - @enable = true + Timeout.timeout(10) do + begin + TCPSocket.open(@host, @port) do + puts 'testi2' + @enable = true + end + rescue Errno::ENETUNREACH + retry + end end + rescue Timeout::Error + puts 'timeout' + @error_msg = "#{I18n.t('error.timeout')}\n#{e}" + @enable = false rescue Exception => e @error_msg = "#{I18n.t('error.sync.connection')}\n#{e}" @enable = false @@ -58,9 +70,9 @@ module MPW msg = nil TCPSocket.open(@host, @port) do |socket| send_msg = {:action => 'get', - :gpg_key => @gpg_key, - :password => @password, - :suffix => @suffix} + :gpg_key => @gpg_key, + :password => @password, + :suffix => @suffix} socket.puts send_msg.to_json msg = JSON.parse(socket.gets) From be2fb0fd3f7466f00583feefcafd65e34316a10b Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sun, 31 Aug 2014 11:09:39 +0200 Subject: [PATCH 089/531] remove test --- MPW/Sync/MPWSync.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/MPW/Sync/MPWSync.rb b/MPW/Sync/MPWSync.rb index cdb05bf..16d314b 100644 --- a/MPW/Sync/MPWSync.rb +++ b/MPW/Sync/MPWSync.rb @@ -41,7 +41,6 @@ module MPW Timeout.timeout(10) do begin TCPSocket.open(@host, @port) do - puts 'testi2' @enable = true end rescue Errno::ENETUNREACH From f06059518c166deb518ea1db149154701aa7ed47 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sun, 31 Aug 2014 12:28:20 +0200 Subject: [PATCH 090/531] improve csv with symbole --- MPW/MPW.rb | 115 +++++++++++++++++++++++--------------------------- MPW/UI/Cli.rb | 44 +++++++++---------- 2 files changed, 75 insertions(+), 84 deletions(-) diff --git a/MPW/MPW.rb b/MPW/MPW.rb index f48bad4..9bdceb8 100644 --- a/MPW/MPW.rb +++ b/MPW/MPW.rb @@ -11,17 +11,6 @@ module MPW require 'i18n' class MPW - - ID = 0 - NAME = 1 - GROUP = 2 - PROTOCOL = 3 - SERVER = 4 - LOGIN = 5 - PASSWORD = 6 - PORT = 7 - COMMENT = 8 - DATE = 9 attr_accessor :error_msg @@ -37,15 +26,13 @@ module MPW # @args: password -> the GPG key password # @rtrn: true if data has been decrypted def decrypt(passwd=nil) - @data = [] + @data = {} if File.exist?(@file_gpg) - crypto = GPGME::Crypto.new(:armor => true) - data_decrypt = crypto.decrypt(IO.read(@file_gpg), :password => passwd).read + crypto = GPGME::Crypto.new(armor: true) + data_decrypt = crypto.decrypt(IO.read(@file_gpg), password: passwd).read - data_decrypt.lines do |line| - @data.push(line.parse_csv) - end + @data = CSV.parse(data_decrypt, {headers: true, header_converters: :symbol}) end return true @@ -57,21 +44,25 @@ module MPW # Encrypt a file # @rtrn: true if the file has been encrypted def encrypt - crypto = GPGME::Crypto.new(:armor => true) + crypto = GPGME::Crypto.new(armor: true) file_gpg = File.open(@file_gpg, 'w+') - data_to_encrypt = '' - @data.each do |row| - data_to_encrypt << row.to_csv + data_to_encrypt = CSV.generate(write_headers: true, + headers: ['id', 'name', 'group', 'protocol', 'host', 'login', 'password', 'port', 'comment', 'date']) do |csv| + @data.each do |r| + csv << [r[:id], r[:name], r[:group], r[:protocol], r[:host], r[:login], r[:password], r[:port], r[:comment], r[:date]] + end end + puts 'test' + puts data_to_encrypt recipients = [] recipients.push(@key) if !@share_keys.nil? @share_keys.split.each { |k| recipients.push(k) } end - crypto.encrypt(data_to_encrypt, :recipients => recipients, :output => file_gpg) + crypto.encrypt(data_to_encrypt, recipients: recipients, output: file_gpg) file_gpg.close return true @@ -93,12 +84,12 @@ module MPW search = search.force_encoding('ASCII-8BIT') @data.each do |row| - name = row[NAME].nil? ? nil : row[NAME].downcase - server = row[SERVER].nil? ? nil : row[SERVER].downcase - comment = row[COMMENT].nil? ? nil : row[COMMENT].downcase + name = row[:name].nil? ? nil : row[:name].downcase + server = row[:host].nil? ? nil : row[:host].downcase + comment = row[:comment].nil? ? nil : row[:comment].downcase if name =~ /^.*#{search}.*$/ || server =~ /^.*#{search}.*$/ || comment =~ /^.*#{search}.*$/ - if (protocol.nil? || protocol.eql?(row[PROTOCOL])) && (group.nil? || group.eql?(row[GROUP])) + if (protocol.nil? || protocol.eql?(row[:protocol])) && (group.nil? || group.eql?(row[:group])) result.push(row) end end @@ -112,7 +103,7 @@ module MPW # @rtrn: a row with the resultat of the search def search_by_id(id) @data.each do |row| - if row[ID] == id + if row[:id] == id return row end end @@ -132,12 +123,12 @@ module MPW # comment -> a comment # @rtrn: true if the item has been updated def update(name, group, server, protocol, login, passwd, port, comment, id=nil) - row = [] + row = {} update = false i = 0 @data.each do |r| - if r[ID] == id + if r[:id] == id row = r update = true break @@ -149,28 +140,28 @@ module MPW port = nil end - row_update = [] - row_update[DATE] = Time.now.to_i + row_update = {} + row_update[:date] = Time.now.to_i - row_update[ID] = id.nil? || id.empty? ? MPW.password(16) : id - row_update[NAME] = name.nil? || name.empty? ? row[NAME] : name - row_update[GROUP] = group.nil? || group.empty? ? row[GROUP] : group - row_update[SERVER] = server.nil? || server.empty? ? row[SERVER] : server - row_update[PROTOCOL] = protocol.nil? || protocol.empty? ? row[PROTOCOL] : protocol - row_update[LOGIN] = login.nil? || login.empty? ? row[LOGIN] : login - row_update[PASSWORD] = passwd.nil? || passwd.empty? ? row[PASSWORD] : passwd - row_update[PORT] = port.nil? || port.empty? ? row[PORT] : port - row_update[COMMENT] = comment.nil? || comment.empty? ? row[COMMENT] : comment + row_update[:id] = id.nil? || id.empty? ? MPW.password(16) : id + row_update[:name] = name.nil? || name.empty? ? row[:name] : name + row_update[:group] = group.nil? || group.empty? ? row[:group] : group + row_update[:host] = server.nil? || server.empty? ? row[:host] : server + row_update[:protocol] = protocol.nil? || protocol.empty? ? row[:protocol] : protocol + row_update[:login] = login.nil? || login.empty? ? row[:login] : login + row_update[:password] = passwd.nil? || passwd.empty? ? row[:password] : passwd + row_update[:port] = port.nil? || port.empty? ? row[:port] : port + row_update[:comment] = comment.nil? || comment.empty? ? row[:comment] : comment - row_update[NAME] = row_update[NAME].nil? ? nil : row_update[NAME].force_encoding('ASCII-8BIT') - row_update[GROUP] = row_update[GROUP].nil? ? nil : row_update[GROUP].force_encoding('ASCII-8BIT') - row_update[SERVER] = row_update[SERVER].nil? ? nil : row_update[SERVER].force_encoding('ASCII-8BIT') - row_update[PROTOCOL] = row_update[PROTOCOL].nil? ? nil : row_update[PROTOCOL].force_encoding('ASCII-8BIT') - row_update[LOGIN] = row_update[LOGIN].nil? ? nil : row_update[LOGIN].force_encoding('ASCII-8BIT') - row_update[PASSWORD] = row_update[PASSWORD].nil? ? nil : row_update[PASSWORD].force_encoding('ASCII-8BIT') - row_update[COMMENT] = row_update[COMMENT].nil? ? nil : row_update[COMMENT].force_encoding('ASCII-8BIT') + row_update[:name] = row_update[:name].nil? ? nil : row_update[:name].force_encoding('ASCII-8BIT') + row_update[:group] = row_update[:group].nil? ? nil : row_update[:group].force_encoding('ASCII-8BIT') + row_update[:host] = row_update[:host].nil? ? nil : row_update[:host].force_encoding('ASCII-8BIT') + row_update[:protocol] = row_update[:protocol].nil? ? nil : row_update[:protocol].force_encoding('ASCII-8BIT') + row_update[:login] = row_update[:login].nil? ? nil : row_update[:login].force_encoding('ASCII-8BIT') + row_update[:password] = row_update[:password].nil? ? nil : row_update[:password].force_encoding('ASCII-8BIT') + row_update[:comment] = row_update[:comment].nil? ? nil : row_update[:comment].force_encoding('ASCII-8BIT') - if row_update[NAME].nil? || row_update[NAME].empty? + if row_update[:name].nil? || row_update[:name].empty? @error_msg = I18n.t('error.update.name_empty') return false end @@ -190,14 +181,14 @@ module MPW def remove(id) i = 0 @data.each do |row| - if row[ID] == id + if row[:id] == id @data.delete_at(i) return true end i += 1 end - @error_msg = I18n.t('error.delete.id_no_exist', :id => id) + @error_msg = I18n.t('error.delete.id_no_exist', id: id) return false end @@ -207,14 +198,14 @@ module MPW def export(file) File.open(file, 'w+') do |file| @data.each do |row| - row.delete_at(ID).delete_at(DATE) + row.delete_at(:id).delete_at(:date) file << row.to_csv end end return true rescue Exception => e - @error_msg = "#{I18n.t('error.export.write', :file => file)}\n#{e}" + @error_msg = "#{I18n.t('error.export.write', file: file)}\n#{e}" return false end @@ -229,7 +220,7 @@ module MPW return false else row = line.parse_csv.unshift(0) - if not update(row[NAME], row[GROUP], row[SERVER], row[PROTOCOL], row[LOGIN], row[PASSWORD], row[PORT], row[COMMENT]) + if not update(row[:name], row[:group], row[:host], row[:protocol], row[:login], row[:password], row[:port], row[:comment]) return false end end @@ -237,7 +228,7 @@ module MPW return true rescue Exception => e - @error_msg = "#{I18n.t('error.import.read', :file => file)}\n#{e}" + @error_msg = "#{I18n.t('error.import.read', file: file)}\n#{e}" return false end @@ -262,7 +253,7 @@ module MPW return result rescue Exception => e - @error_msg = "#{I18n.t('error.import.read', :file => file)}\n#{e}" + @error_msg = "#{I18n.t('error.import.read', file: file)}\n#{e}" return false end @@ -280,9 +271,9 @@ module MPW # Update item data_remote.each do |r| - if l[ID] == r[ID] - if l[DATE].to_i < r[DATE].to_i - update(r[NAME], r[GROUP], r[SERVER], r[PROTOCOL], r[LOGIN], r[PASSWORD], r[PORT], r[COMMENT], l[ID]) + if l[:id] == r[:id] + if l[:date].to_i < r[:date].to_i + update(r[:name], r[:group], r[:host], r[:protocol], r[:login], r[:password], r[:port], r[:comment], l[:id]) end update = true data_remote.delete_at(j) @@ -292,16 +283,16 @@ module MPW end # Delete an old item - if !update && l[DATE].to_i < last_update - remove(l[ID]) + if !update && l[:date].to_i < last_update + remove(l[:id]) end end end # Add item data_remote.each do |r| - if r[DATE].to_i > last_update - update(r[NAME], r[GROUP], r[SERVER], r[PROTOCOL], r[LOGIN], r[PASSWORD], r[PORT], r[COMMENT], r[ID]) + if r[:date].to_i > last_update + update(r[:name], r[:group], r[:host], r[:protocol], r[:login], r[:password], r[:port], r[:comment], r[:id]) end end diff --git a/MPW/UI/Cli.rb b/MPW/UI/Cli.rb index 58fa371..410b11b 100644 --- a/MPW/UI/Cli.rb +++ b/MPW/UI/Cli.rb @@ -187,30 +187,30 @@ class Cli # @args: item -> an array with the item information def displayFormat(item) puts '--------------------' - puts "Id: #{item[MPW::MPW::ID]}" - puts "#{I18n.t('display.name')}: #{item[MPW::MPW::NAME]}" - puts "#{I18n.t('display.group')}: #{item[MPW::MPW::GROUP]}" - puts "#{I18n.t('display.server')}: #{item[MPW::MPW::SERVER]}" - puts "#{I18n.t('display.protocol')}: #{item[MPW::MPW::PROTOCOL]}" - puts "#{I18n.t('display.login')}: #{item[MPW::MPW::LOGIN]}" - puts "#{I18n.t('display.password')}: #{item[MPW::MPW::PASSWORD]}" - puts "#{I18n.t('display.port')}: #{item[MPW::MPW::PORT]}" - puts "#{I18n.t('display.comment')}: #{item[MPW::MPW::COMMENT]}" + puts "Id: #{item[:id]}" + puts "#{I18n.t('display.name')}: #{item[:name]}" + puts "#{I18n.t('display.group')}: #{item[:group]}" + puts "#{I18n.t('display.server')}: #{item[:host]}" + puts "#{I18n.t('display.protocol')}: #{item[:protocol]}" + puts "#{I18n.t('display.login')}: #{item[:login]}" + puts "#{I18n.t('display.password')}: #{item[:password]}" + puts "#{I18n.t('display.port')}: #{item[:port]}" + puts "#{I18n.t('display.comment')}: #{item[:comment]}" end # Display an item in the alternative format # @args: item -> an array with the item information def displayFormatAlt(item) - port = item[MPW::MPW::PORT].nil? ? '' : ":#{item[MPW::MPW::PORT]}" + port = item[:port].nil? ? '' : ":#{item[:port]}" - if item[MPW::MPW::PASSWORD].nil? || item[MPW::MPW::PASSWORD].empty? - if item[MPW::MPW::LOGIN].include('@') - puts "# #{item[MPW::MPW::ID]} #{item[MPW::MPW::PROTOCOL]}://#{item[MPW::MPW::LOGIN]}@#{item[MPW::MPW::SERVER]}#{port}" + if item[:password].nil? || item[:password].empty? + if item[:login].include('@') + puts "# #{item[:id]} #{item[:protocol]}://#{item[:login]}@#{item[:host]}#{port}" else - puts "# #{item[MPW::MPW::ID]} #{item[MPW::MPW::PROTOCOL]}://{#{item[MPW::MPW::LOGIN]}}@#{item[MPW::MPW::SERVER]}#{port}" + puts "# #{item[:id]} #{item[:protocol]}://{#{item[:login]}}@#{item[:host]}#{port}" end else - puts "# #{item[MPW::MPW::ID]} #{item[MPW::MPW::PROTOCOL]}://{#{item[MPW::MPW::LOGIN]}:#{item[MPW::MPW::PASSWORD]}}@#{item[MPW::MPW::SERVER]}#{port}" + puts "# #{item[:id]} #{item[:protocol]}://{#{item[:login]}:#{item[:password]}}@#{item[:host]}#{port}" end end @@ -248,14 +248,14 @@ class Cli if not row.empty? puts I18n.t('form.update.title') puts '--------------------' - name = ask(I18n.t('form.update.name' , :name => row[MPW::MPW::NAME])).to_s - group = ask(I18n.t('form.update.group' , :group => row[MPW::MPW::GROUP])).to_s - server = ask(I18n.t('form.update.server' , :server => row[MPW::MPW::SERVER])).to_s - protocol = ask(I18n.t('form.update.protocol', :protocol => row[MPW::MPW::PROTOCOL])).to_s - login = ask(I18n.t('form.update.login' , :login => row[MPW::MPW::LOGIN])).to_s + name = ask(I18n.t('form.update.name' , name: row[:name])).to_s + group = ask(I18n.t('form.update.group' , group: row[:group])).to_s + server = ask(I18n.t('form.update.server' , server: row[:host])).to_s + protocol = ask(I18n.t('form.update.protocol', protocol: row[:protocol])).to_s + login = ask(I18n.t('form.update.login' , login: row[:login])).to_s passwd = ask(I18n.t('form.update.password')).to_s - port = ask(I18n.t('form.update.port' , :port => row[MPW::MPW::PORT])).to_s - comment = ask(I18n.t('form.update.comment' , :comment => row[MPW::MPW::COMMENT])).to_s + port = ask(I18n.t('form.update.port' , port: row[:port])).to_s + comment = ask(I18n.t('form.update.comment' , comment: row[:comment])).to_s if @mpw.update(name, group, server, protocol, login, passwd, port, comment, id) if @mpw.encrypt From 33f92d9aae88f2130d02f195d7bdd2bdd47db744 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sun, 31 Aug 2014 12:29:57 +0200 Subject: [PATCH 091/531] new syntax for symbol --- MPW/UI/Cli.rb | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/MPW/UI/Cli.rb b/MPW/UI/Cli.rb index 410b11b..f364b9a 100644 --- a/MPW/UI/Cli.rb +++ b/MPW/UI/Cli.rb @@ -74,10 +74,10 @@ class Cli def setup(lang) puts I18n.t('form.setup.title') puts '--------------------' - language = ask(I18n.t('form.setup.lang', :lang => lang)).to_s + language = ask(I18n.t('form.setup.lang', lang: lang)).to_s key = ask(I18n.t('form.setup.gpg_key')).to_s share_keys = ask(I18n.t('form.setup.share_gpg_keys')).to_s - file_gpg = ask(I18n.t('form.setup.gpg_file', :home => @conf.dir_home)).to_s + file_gpg = ask(I18n.t('form.setup.gpg_file', home: @conf.dir_home)).to_s timeout_pwd = ask(I18n.t('form.setup.timeout')).to_s sync_type = ask(I18n.t('form.setup.sync_type')).to_s @@ -282,7 +282,7 @@ class Cli if result.length > 0 displayFormat(result) - confirm = ask("#{I18n.t('form.delete.ask', :id => id)} (y/N) ").to_s + confirm = ask("#{I18n.t('form.delete.ask', id: id)} (y/N) ").to_s if confirm =~ /^(y|yes|YES|Yes|Y)$/ force = true end @@ -295,7 +295,7 @@ class Cli if @mpw.remove(id) if @mpw.encrypt sync - puts I18n.t('form.delete.valid', :id => id) + puts I18n.t('form.delete.valid', id: id) else puts "#{I18n.t('display.error')} #16: #{@mpw.error_msg}" end @@ -328,7 +328,7 @@ class Cli displayFormat(r) end - confirm = ask("#{I18n.t('form.import.ask', :file => file)} (y/N) ").to_s + confirm = ask("#{I18n.t('form.import.ask', file: file)} (y/N) ").to_s if confirm =~ /^(y|yes|YES|Yes|Y)$/ force = true end From ce05c53c20b146d8de29d5a125de19da388b90b3 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sun, 31 Aug 2014 12:39:40 +0200 Subject: [PATCH 092/531] fix new syntax for csv --- MPW/UI/CliSSH.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/MPW/UI/CliSSH.rb b/MPW/UI/CliSSH.rb index 9292ca8..a5c0eb1 100644 --- a/MPW/UI/CliSSH.rb +++ b/MPW/UI/CliSSH.rb @@ -16,11 +16,11 @@ class CliSSH < Cli if result.length > 0 result.each do |r| - server = @server.nil? ? r[MPW::MPW::SERVER] : @server - port = @port.nil? ? r[MPW::MPW::PORT] : @port - login = @login.nil? ? r[MPW::MPW::LOGIN] : @login + server = @server.nil? ? r[:host] : @server + port = @port.nil? ? r[:port] : @port + login = @login.nil? ? r[:login] : @login - passwd = r[MPW::MPW::PASSWORD] + passwd = r[:password] if port.nil? || port.empty? port = 22 From 6c09c7f1b3ac234c45a770e17a4458babe55f97c Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sun, 31 Aug 2014 12:42:26 +0200 Subject: [PATCH 093/531] fix for new syntax --- MPW/Config.rb | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/MPW/Config.rb b/MPW/Config.rb index 9f6d4a1..8dbbc8b 100644 --- a/MPW/Config.rb +++ b/MPW/Config.rb @@ -89,7 +89,9 @@ module MPW 'sync_user' => sync_user, 'sync_pwd' => sync_pwd, 'sync_path' => sync_path, - 'last_update' => 0 }} + 'last_update' => 0 + } + } Dir.mkdir("#{@config_dir}/conf", 700) Dir.mkdir("#{@config_dir}/db", 700) @@ -199,7 +201,7 @@ module MPW next end - @error_msg = I18n.t('error.config.no_key_public', :key => k) + @error_msg = I18n.t('error.config.no_key_public', key: k) return false end end @@ -221,7 +223,9 @@ module MPW 'sync_user' => @sync_user, 'sync_pwd' => @sync_pwd, 'sync_path' => @sync_path, - 'last_update' => Time.now.to_i }} + 'last_update' => Time.now.to_i + } + } File.open(@file_config, 'w') do |file| file << config.to_yaml From 1d3b127df03929d3acb45a426075b45860f034cf Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sun, 31 Aug 2014 13:07:06 +0200 Subject: [PATCH 094/531] fix new syntax --- MPW/Sync/MPWSync.rb | 20 +++++++++++--------- MPW/Sync/SSH.rb | 6 +++--- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/MPW/Sync/MPWSync.rb b/MPW/Sync/MPWSync.rb index 16d314b..730d9fb 100644 --- a/MPW/Sync/MPWSync.rb +++ b/MPW/Sync/MPWSync.rb @@ -68,10 +68,11 @@ module MPW msg = nil TCPSocket.open(@host, @port) do |socket| - send_msg = {:action => 'get', - :gpg_key => @gpg_key, - :password => @password, - :suffix => @suffix} + send_msg = {action: 'get', + gpg_key: @gpg_key, + password: @password, + suffix: @suffix + } socket.puts send_msg.to_json msg = JSON.parse(socket.gets) @@ -112,11 +113,12 @@ module MPW msg = nil TCPSocket.open(@host, @port) do |socket| - send_msg = {:action => 'update', - :gpg_key => @gpg_key, - :password => @password, - :suffix => @suffix, - :data => data} + send_msg = {action: 'update', + gpg_key: @gpg_key, + password: @password, + suffix: @suffix, + data: data + } socket.puts send_msg.to_json msg = JSON.parse(socket.gets) diff --git a/MPW/Sync/SSH.rb b/MPW/Sync/SSH.rb index 21c9c03..4868a85 100644 --- a/MPW/Sync/SSH.rb +++ b/MPW/Sync/SSH.rb @@ -37,7 +37,7 @@ module MPW @path = path @port = port.instance_of?(Integer) ? 22 : port - Net::SSH.start(@host, @user, :password => @password, :port => @port) do + Net::SSH.start(@host, @user, password: @password, port: @port) do @enable = true end rescue Exception => e @@ -56,7 +56,7 @@ module MPW end tmp_file = tmpfile - Net::SCP.start(@host, @user, :password => @password, :port => @port) do |scp| + Net::SCP.start(@host, @user, password: @password, port: @port) do |scp| scp.download!(@path, tmp_file) end @@ -86,7 +86,7 @@ module MPW file << data end - Net::SCP.start(@host, @user, :password => @password, :port => @port) do |scp| + Net::SCP.start(@host, @user, password: @password, port: @port) do |scp| scp.upload!(tmp_file, @path) end From be00f04353dc549b4eeafa30d5ea1c8d21e814e3 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sun, 31 Aug 2014 17:40:37 +0200 Subject: [PATCH 095/531] fix import and export --- MPW/MPW.rb | 40 ++++++++++------------------------------ 1 file changed, 10 insertions(+), 30 deletions(-) diff --git a/MPW/MPW.rb b/MPW/MPW.rb index 9bdceb8..2f5f3e6 100644 --- a/MPW/MPW.rb +++ b/MPW/MPW.rb @@ -26,7 +26,7 @@ module MPW # @args: password -> the GPG key password # @rtrn: true if data has been decrypted def decrypt(passwd=nil) - @data = {} + @data = [] if File.exist?(@file_gpg) crypto = GPGME::Crypto.new(armor: true) @@ -54,9 +54,6 @@ module MPW end end - puts 'test' - puts data_to_encrypt - recipients = [] recipients.push(@key) if !@share_keys.nil? @share_keys.split.each { |k| recipients.push(k) } @@ -196,13 +193,13 @@ module MPW # @args: file -> a string to match # @rtrn: true if export work def export(file) - File.open(file, 'w+') do |file| - @data.each do |row| - row.delete_at(:id).delete_at(:date) - file << row.to_csv + CSV.open(file, 'w', write_headers: true, + headers: ['name', 'group', 'protocol', 'host', 'login', 'password', 'port', 'comment']) do |csv| + @data.each do |r| + csv << [r[:name], r[:group], r[:protocol], r[:host], r[:login], r[:password], r[:port], r[:comment]] end end - + return true rescue Exception => e @error_msg = "#{I18n.t('error.export.write', file: file)}\n#{e}" @@ -213,16 +210,9 @@ module MPW # @args: file -> path to file import # @rtrn: true if the import work def import(file) - data_new = IO.read(file) - data_new.lines do |line| - if not line =~ /(.*,){6}/ - @error_msg = I18n.t('error.import.bad_format') + CSV.foreach(file, {headers: true, header_converters: :symbol}) do |row| + if not update(row[:name], row[:group], row[:host], row[:protocol], row[:login], row[:password], row[:port], row[:comment]) return false - else - row = line.parse_csv.unshift(0) - if not update(row[:name], row[:group], row[:host], row[:protocol], row[:login], row[:password], row[:port], row[:comment]) - return false - end end end @@ -237,18 +227,8 @@ module MPW # @rtrn: an array with the items to import, if there is an error return false def import_preview(file) result = [] - id = 0 - - data = IO.read(file) - data.lines do |line| - if not line =~ /(.*,){6}/ - @error_msg = I18n.t('error.import.bad_format') - return false - else - result.push(line.parse_csv.unshift(id)) - end - - id += 1 + CSV.foreach(file, {headers: true, header_converters: :symbol}) do |row| + result << row end return result From bd7a3e5ecf0901a08b46a30ed627d45578e9fd8b Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sun, 31 Aug 2014 18:31:14 +0200 Subject: [PATCH 096/531] fix regression --- MPW/MPW.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/MPW/MPW.rb b/MPW/MPW.rb index 2f5f3e6..d8908c8 100644 --- a/MPW/MPW.rb +++ b/MPW/MPW.rb @@ -54,6 +54,7 @@ module MPW end end + recipients = [] recipients.push(@key) if !@share_keys.nil? @share_keys.split.each { |k| recipients.push(k) } From a055c7779e70897689f159d5ba5edc03d3e993a4 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Mon, 1 Sep 2014 19:24:24 +0200 Subject: [PATCH 097/531] improve backup when encrypt new file --- MPW/MPW.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/MPW/MPW.rb b/MPW/MPW.rb index d8908c8..8e88e03 100644 --- a/MPW/MPW.rb +++ b/MPW/MPW.rb @@ -44,6 +44,8 @@ module MPW # Encrypt a file # @rtrn: true if the file has been encrypted def encrypt + FileUtils.cp(@file_gpg, "#{@file_gpg}.bk") + crypto = GPGME::Crypto.new(armor: true) file_gpg = File.open(@file_gpg, 'w+') @@ -63,9 +65,11 @@ module MPW crypto.encrypt(data_to_encrypt, recipients: recipients, output: file_gpg) file_gpg.close + FileUtils.rm("#{@file_gpg}.bk") return true rescue Exception => e @error_msg = "#{I18n.t('error.gpg_file.encrypt')}\n#{e}" + FileUtils.mv("#{@file_gpg}.bk", @file_gpg) return false end From 3807c2866c8269bb8454e203186a8264f73f7329 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Mon, 1 Sep 2014 20:34:25 +0200 Subject: [PATCH 098/531] add require fileutils --- MPW/MPW.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/MPW/MPW.rb b/MPW/MPW.rb index 8e88e03..d38ffc8 100644 --- a/MPW/MPW.rb +++ b/MPW/MPW.rb @@ -9,6 +9,7 @@ module MPW require 'gpgme' require 'csv' require 'i18n' + require 'fileutils' class MPW From e8590912a2491afcf3e1e6f76fd4a2c5ca244801 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sun, 7 Sep 2014 10:00:46 +0200 Subject: [PATCH 099/531] clean construtor Cli --- MPW/UI/Cli.rb | 2 +- mpw | 2 +- mpw-ssh | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/MPW/UI/Cli.rb b/MPW/UI/Cli.rb index f364b9a..3a3502c 100644 --- a/MPW/UI/Cli.rb +++ b/MPW/UI/Cli.rb @@ -17,7 +17,7 @@ class Cli # Constructor # @args: lang -> the operating system language # config_file -> a specify config file - def initialize(lang, config) + def initialize(config) @config = config end diff --git a/mpw b/mpw index a9a784a..3c206de 100755 --- a/mpw +++ b/mpw @@ -113,7 +113,7 @@ end.parse! config = MPW::Config.new(options[:config]) check_error = config.checkconfig -cli = Cli.new(lang, config) +cli = Cli.new(config) # Setup a new config if !check_error || !options[:setup].nil? diff --git a/mpw-ssh b/mpw-ssh index 079771e..1af952d 100755 --- a/mpw-ssh +++ b/mpw-ssh @@ -65,7 +65,7 @@ end.parse! config = MPW::Config.new(options[:config]) check_error = config.checkconfig -cli = CliSSH.new(lang, config) +cli = CliSSH.new(config) cli.login = options[:login] cli.server = options[:server] cli.port = options[:port] From 5964044f7858dfa67764c6aaa7b42d689c3051f4 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Fri, 12 Sep 2014 08:41:27 +0200 Subject: [PATCH 100/531] rename folder MPW to lib --- {MPW => lib}/Config.rb | 0 {MPW => lib}/MPW.rb | 0 {MPW => lib}/Server.rb | 0 {MPW => lib}/Sync/FTP.rb | 0 {MPW => lib}/Sync/MPWSync.rb | 0 {MPW => lib}/Sync/SSH.rb | 0 {MPW => lib}/UI/Cli.rb | 8 ++++---- {MPW => lib}/UI/CliSSH.rb | 0 mpw | 6 +++--- mpw-server | 2 +- mpw-ssh | 4 ++-- 11 files changed, 10 insertions(+), 10 deletions(-) rename {MPW => lib}/Config.rb (100%) rename {MPW => lib}/MPW.rb (100%) rename {MPW => lib}/Server.rb (100%) rename {MPW => lib}/Sync/FTP.rb (100%) rename {MPW => lib}/Sync/MPWSync.rb (100%) rename {MPW => lib}/Sync/SSH.rb (100%) rename {MPW => lib}/UI/Cli.rb (98%) rename {MPW => lib}/UI/CliSSH.rb (100%) diff --git a/MPW/Config.rb b/lib/Config.rb similarity index 100% rename from MPW/Config.rb rename to lib/Config.rb diff --git a/MPW/MPW.rb b/lib/MPW.rb similarity index 100% rename from MPW/MPW.rb rename to lib/MPW.rb diff --git a/MPW/Server.rb b/lib/Server.rb similarity index 100% rename from MPW/Server.rb rename to lib/Server.rb diff --git a/MPW/Sync/FTP.rb b/lib/Sync/FTP.rb similarity index 100% rename from MPW/Sync/FTP.rb rename to lib/Sync/FTP.rb diff --git a/MPW/Sync/MPWSync.rb b/lib/Sync/MPWSync.rb similarity index 100% rename from MPW/Sync/MPWSync.rb rename to lib/Sync/MPWSync.rb diff --git a/MPW/Sync/SSH.rb b/lib/Sync/SSH.rb similarity index 100% rename from MPW/Sync/SSH.rb rename to lib/Sync/SSH.rb diff --git a/MPW/UI/Cli.rb b/lib/UI/Cli.rb similarity index 98% rename from MPW/UI/Cli.rb rename to lib/UI/Cli.rb index 3a3502c..c045885 100644 --- a/MPW/UI/Cli.rb +++ b/lib/UI/Cli.rb @@ -10,7 +10,7 @@ require 'readline' require 'i18n' require 'yaml' -require "#{APP_ROOT}/MPW/MPW" +require "#{APP_ROOT}/lib/MPW" class Cli @@ -27,13 +27,13 @@ class Cli if !defined?(@sync) case @config.sync_type when 'mpw' - require "#{APP_ROOT}/MPW/Sync/MPWSync" + require "#{APP_ROOT}/lib/Sync/MPWSync" @sync = MPW::Sync::MPWSync.new when 'sftp', 'scp', 'ssh' - require "#{APP_ROOT}/MPW/Sync/SSH" + require "#{APP_ROOT}/lib/Sync/SSH" @sync = MPW::Sync::SSH.new when 'ftp' - require "#{APP_ROOT}/MPW/Sync/FTP" + require "#{APP_ROOT}/lib/Sync/FTP" @sync = MPW::Sync::FTP.new else return false diff --git a/MPW/UI/CliSSH.rb b/lib/UI/CliSSH.rb similarity index 100% rename from MPW/UI/CliSSH.rb rename to lib/UI/CliSSH.rb diff --git a/mpw b/mpw index 3c206de..1250bba 100755 --- a/mpw +++ b/mpw @@ -10,9 +10,9 @@ require 'locale' require 'i18n' APP_ROOT = File.dirname(Pathname.new(__FILE__).realpath) -require "#{APP_ROOT}/MPW/UI/Cli" -require "#{APP_ROOT}/MPW/Config" -require "#{APP_ROOT}/MPW/MPW" +require "#{APP_ROOT}/lib/UI/Cli" +require "#{APP_ROOT}/lib/Config" +require "#{APP_ROOT}/lib/MPW" # --------------------------------------------------------- # # Set local diff --git a/mpw-server b/mpw-server index 0c94289..688973f 100755 --- a/mpw-server +++ b/mpw-server @@ -10,7 +10,7 @@ require 'locale' require 'i18n' APP_ROOT = File.dirname(Pathname.new(__FILE__).realpath) -require "#{APP_ROOT}/MPW/Server.rb" +require "#{APP_ROOT}/lib/Server.rb" # --------------------------------------------------------- # # Set local diff --git a/mpw-ssh b/mpw-ssh index 1af952d..5674b1e 100755 --- a/mpw-ssh +++ b/mpw-ssh @@ -10,8 +10,8 @@ require 'locale' require 'i18n' APP_ROOT = File.dirname(Pathname.new(__FILE__).realpath) -require "#{APP_ROOT}/MPW/UI/CliSSH" -require "#{APP_ROOT}/MPW/Config" +require "#{APP_ROOT}/lib/UI/CliSSH" +require "#{APP_ROOT}/lib/Config" lang = Locale::Tag.parse(ENV['LANG']).to_simple.to_s[0..1] From 0e9f235be8bdc8d7b587d8446d227015f53be73e Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Fri, 12 Sep 2014 08:42:29 +0200 Subject: [PATCH 101/531] update the makefile --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 1e06dd9..cb1fa7a 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ dep-ubuntu: install: mkdir -p /usr/local/mpw - cp -r ./MPW /usr/local/mpw/ + cp -r ./lib /usr/local/mpw/ cp -r ./i18n /usr/local/mpw/ cp ./mpw /usr/local/mpw/ ln -snf /usr/local/mpw/mpw /usr/local/bin/ From 60fa43aef88f68bfab01e9b0351f8d96d5f79e68 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Fri, 12 Sep 2014 08:55:08 +0200 Subject: [PATCH 102/531] add --- Gemfile | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 Gemfile diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000..600f694 --- /dev/null +++ b/Gemfile @@ -0,0 +1,10 @@ +source 'https://rubygems.org' +gem 'highline' +gem 'i18n' +gem 'locale' +gem 'gpgme' + +group :ssh do + gem 'net-ssh' + gem 'net-scp' +end From 901317ca6ad24d9efd22837f96b9c6dcd24b5cae Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Fri, 12 Sep 2014 09:01:01 +0200 Subject: [PATCH 103/531] update readme --- README.md | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 7816d0d..1fc4d7e 100644 --- a/README.md +++ b/README.md @@ -1,20 +1,27 @@ # Manage your passwords! MPW is a little software which stores your passwords in an GPG encrypted file. -MPW can synchronize your password with a MPW Server or via SSH. +MPW can synchronize your password with a MPW Server or via SSH or via FTP. # Installation You must generate a GPG Key with GPG or with Seahorse (GUI on linux). This program work with ruby >= 1.9 +* install ruby on your computer +* gem install bundler +* bundle install +or +* bundle install --without ssh # if you don't want synchronize your password via SSH + ## On Debian/Ubuntu: * apt-get install ruby ruby-gpgme ruby-highline ruby-i18n ruby-locale -If you want to synchronize your password via SSH/SCP: +If you want to synchronize your passwords via SSH/SCP: * apt-get install ruby-net-ssh ruby-net-scp For mpw-ssh: * apt-get install sshpass + From 7fcb0fbde6994fa9819dcf60ca96b9a4fc5a9b8c Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Fri, 12 Sep 2014 09:28:21 +0200 Subject: [PATCH 104/531] fix regression with new version of i18n --- mpw | 1 + mpw-server | 1 + mpw-ssh | 1 + 3 files changed, 3 insertions(+) diff --git a/mpw b/mpw index 1250bba..6353633 100755 --- a/mpw +++ b/mpw @@ -7,6 +7,7 @@ require 'rubygems' require 'optparse' require 'pathname' require 'locale' +require 'set' require 'i18n' APP_ROOT = File.dirname(Pathname.new(__FILE__).realpath) diff --git a/mpw-server b/mpw-server index 688973f..d5b8fa2 100755 --- a/mpw-server +++ b/mpw-server @@ -7,6 +7,7 @@ require 'rubygems' require 'optparse' require 'pathname' require 'locale' +require 'set' require 'i18n' APP_ROOT = File.dirname(Pathname.new(__FILE__).realpath) diff --git a/mpw-ssh b/mpw-ssh index 5674b1e..b3c5f70 100755 --- a/mpw-ssh +++ b/mpw-ssh @@ -7,6 +7,7 @@ require 'rubygems' require 'optparse' require 'pathname' require 'locale' +require 'set' require 'i18n' APP_ROOT = File.dirname(Pathname.new(__FILE__).realpath) From 5c20c7c361833a0812994cb01867d5e13232ac0c Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Fri, 12 Sep 2014 09:28:42 +0200 Subject: [PATCH 105/531] fix regression change folder MPW to lib --- lib/UI/CliSSH.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/UI/CliSSH.rb b/lib/UI/CliSSH.rb index a5c0eb1..c982a28 100644 --- a/lib/UI/CliSSH.rb +++ b/lib/UI/CliSSH.rb @@ -3,7 +3,7 @@ # mail: nishiki@yaegashi.fr # info: a simple script who manage your passwords -require "#{APP_ROOT}/MPW/UI/Cli" +require "#{APP_ROOT}/lib/UI/Cli" class CliSSH < Cli From 76ee0fe2b4aa9d9d3a1a65dd7d682a2a2fe544bf Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sun, 21 Sep 2014 18:44:44 +0200 Subject: [PATCH 106/531] fix version of gem i18n --- Gemfile | 2 +- mpw | 1 - mpw-server | 1 - mpw-ssh | 1 - 4 files changed, 1 insertion(+), 4 deletions(-) diff --git a/Gemfile b/Gemfile index 600f694..d005d66 100644 --- a/Gemfile +++ b/Gemfile @@ -1,6 +1,6 @@ source 'https://rubygems.org' gem 'highline' -gem 'i18n' +gem 'i18n', '0.6.9' gem 'locale' gem 'gpgme' diff --git a/mpw b/mpw index 6353633..1250bba 100755 --- a/mpw +++ b/mpw @@ -7,7 +7,6 @@ require 'rubygems' require 'optparse' require 'pathname' require 'locale' -require 'set' require 'i18n' APP_ROOT = File.dirname(Pathname.new(__FILE__).realpath) diff --git a/mpw-server b/mpw-server index d5b8fa2..688973f 100755 --- a/mpw-server +++ b/mpw-server @@ -7,7 +7,6 @@ require 'rubygems' require 'optparse' require 'pathname' require 'locale' -require 'set' require 'i18n' APP_ROOT = File.dirname(Pathname.new(__FILE__).realpath) diff --git a/mpw-ssh b/mpw-ssh index b3c5f70..5674b1e 100755 --- a/mpw-ssh +++ b/mpw-ssh @@ -7,7 +7,6 @@ require 'rubygems' require 'optparse' require 'pathname' require 'locale' -require 'set' require 'i18n' APP_ROOT = File.dirname(Pathname.new(__FILE__).realpath) From af04b8761df5e075d22318c7bb9ffa7a3cd8ef1f Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sat, 15 Nov 2014 19:14:42 +0100 Subject: [PATCH 107/531] add export to yaml --- i18n/cli/en.yml | 2 ++ i18n/cli/fr.yml | 2 ++ lib/MPW.rb | 39 ++++++++++++++++++++++++++++++++++----- lib/UI/Cli.rb | 4 ++-- mpw | 8 +++++++- 5 files changed, 47 insertions(+), 8 deletions(-) diff --git a/i18n/cli/en.yml b/i18n/cli/en.yml index 0a4c03a..dde1d7d 100644 --- a/i18n/cli/en.yml +++ b/i18n/cli/en.yml @@ -13,6 +13,7 @@ en: delete: id_no_exist: "Can't delete the item %{id}, it doesn't exist!" export: + unknown_type: "The data type %{type} is unknown!" write: "Can't export, unable to write in %{file}!" gpg_file: decrypt: "Can't decrypt file!" @@ -42,6 +43,7 @@ en: setup: "Create a new configuration file" protocol: "Select the items with the specified protocol" export: "Export all items in a CSV file" + type: "Data's type export file [csv|yaml]" import: "Import item since a CSV file" force: "Force an action" format: "Change the display items format by an alternative format" diff --git a/i18n/cli/fr.yml b/i18n/cli/fr.yml index 1640cb7..64e11ee 100644 --- a/i18n/cli/fr.yml +++ b/i18n/cli/fr.yml @@ -13,6 +13,7 @@ fr: delete: id_no_exist: "Impossible de supprimer l'élément %{id}, car il n'existe pas!" export: + unknown_type: "Le type de donnée %{type} est inconnu!" write: "Impossible d'exporter les données dans le fichier %{file}!" gpg_file: decrypt: "Impossible de déchiffrer le fichier GPG!" @@ -42,6 +43,7 @@ fr: setup: "Création d'un nouveau fichier de configuration" protocol: "Sélectionne les éléments ayant le protocole spécifié" export: "Exporte tous les éléments dans un fichier au format CSV" + type: "Format des données du fichier d'export [csv|yaml]" import: "Importe des éléments depuis un fichier au format CSV" force: "Force une action, l'action ne demandera pas de confirmation" format: "Change le format d'affichage des éléments par un alternatif" diff --git a/lib/MPW.rb b/lib/MPW.rb index d38ffc8..f262a9d 100644 --- a/lib/MPW.rb +++ b/lib/MPW.rb @@ -196,14 +196,43 @@ module MPW end # Export to csv - # @args: file -> a string to match + # @args: file -> file where you export the data + # type -> data type # @rtrn: true if export work - def export(file) - CSV.open(file, 'w', write_headers: true, - headers: ['name', 'group', 'protocol', 'host', 'login', 'password', 'port', 'comment']) do |csv| + def export(file, type=:csv) + case type + when :csv + CSV.open(file, 'w', write_headers: true, + headers: ['name', 'group', 'protocol', 'host', 'login', 'password', 'port', 'comment']) do |csv| + @data.each do |r| + csv << [r[:name], r[:group], r[:protocol], r[:host], r[:login], r[:password], r[:port], r[:comment]] + end + end + when :yaml + data = {} + + i = 0 @data.each do |r| - csv << [r[:name], r[:group], r[:protocol], r[:host], r[:login], r[:password], r[:port], r[:comment]] + data.merge!({i => {'id' => r[:id], + 'name' => r[:name], + 'group' => r[:group], + 'protocol' => r[:protocol], + 'host' => r[:host], + 'login' => r[:login], + 'password' => r[:password], + 'port' => r[:port], + 'comment' => r[:comment] + } + } + ) + + i += 1 end + + File.open(file, 'w') {|f| f << data.to_yaml} + else + @error_msg = "#{I18n.t('error.export.unknown_type', type: type)}" + return false end return true diff --git a/lib/UI/Cli.rb b/lib/UI/Cli.rb index c045885..c84df63 100644 --- a/lib/UI/Cli.rb +++ b/lib/UI/Cli.rb @@ -307,8 +307,8 @@ class Cli # Export the items in a CSV file # @args: file -> the destination file - def export(file) - if @mpw.export(file) + def export(file, type) + if @mpw.export(file, type) puts "The export in #{file} is succesfull!" else puts "#{I18n.t('display.error')} #17: #{@mpw.error_msg}" diff --git a/mpw b/mpw index 1250bba..9056610 100755 --- a/mpw +++ b/mpw @@ -7,6 +7,7 @@ require 'rubygems' require 'optparse' require 'pathname' require 'locale' +require 'set' require 'i18n' APP_ROOT = File.dirname(Pathname.new(__FILE__).realpath) @@ -81,6 +82,11 @@ OptionParser.new do |opts| opts.on('-e', '--export FILE', I18n.t('option.export')) do |file| options[:export] = file + options[:type] = :csv + end + + opts.on('-t', '--type TYPE', I18n.t('option.type')) do |type| + options[:type] = type.to_sym end opts.on('-i', '--import FILE', I18n.t('option.import')) do |file| @@ -143,7 +149,7 @@ elsif not options[:add].nil? # Export elsif not options[:export].nil? - cli.export(options[:export]) + cli.export(options[:export], options[:type]) # Add a new item elsif not options[:import].nil? From 4aa4a750cdade27c3fade04b8f1e6fca7cc04717 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sun, 16 Nov 2014 19:39:38 +0100 Subject: [PATCH 108/531] update syntax --- lib/Config.rb | 12 +++++------ lib/MPW.rb | 34 +++++++++++++++---------------- lib/UI/Cli.rb | 52 ++++++++++++++++++++++++------------------------ lib/UI/CliSSH.rb | 2 +- mpw | 10 +++++----- mpw-ssh | 8 ++++---- 6 files changed, 59 insertions(+), 59 deletions(-) diff --git a/lib/Config.rb b/lib/Config.rb index 8dbbc8b..aaab3ac 100644 --- a/lib/Config.rb +++ b/lib/Config.rb @@ -43,7 +43,7 @@ module MPW end @file_config = "#{@dir_config}/conf/default.cfg" - if !file_config.nil? && !file_config.empty? + if not file_config.nil? and not file_config.empty? @file_config = file_config end end @@ -68,7 +68,7 @@ module MPW return false end - if !check_public_gpg_key(share_keys) + if not check_public_gpg_key(share_keys) return false end @@ -112,10 +112,10 @@ module MPW # expire -> the time of expire to GPG key # @rtrn: true if the GPG key is create, else false def setup_gpg_key(password, name, length = 2048, expire = 0) - if name.nil? || name.empty? + if name.nil? or name.empty? @error_msg = "#{I18n.t('error.config.genkey_gpg.name')}" return false - elsif password.nil? || password.empty? + elsif password.nil? or password.empty? @error_msg = "#{I18n.t('error.config.genkey_gpg.password')}" return false end @@ -159,7 +159,7 @@ module MPW @sync_path = config['config']['sync_path'] @last_update = config['config']['last_update'].to_i - if @key.empty? || @file_gpg.empty? + if @key.empty? or @file_gpg.empty? @error_msg = I18n.t('error.config.check') return false end @@ -190,7 +190,7 @@ module MPW ctx = GPGME::Ctx.new share_keys = share_keys.nil? ? '' : share_keys - if !share_keys.empty? + if not share_keys.empty? share_keys.split.each do |k| if not k =~ /[a-zA-Z0-9.-_]+\@[a-zA-Z0-9]+\.[a-zA-Z]+/ @error_msg = I18n.t('error.config.key_bad_format') diff --git a/lib/MPW.rb b/lib/MPW.rb index f262a9d..0b0fafb 100644 --- a/lib/MPW.rb +++ b/lib/MPW.rb @@ -59,7 +59,7 @@ module MPW recipients = [] recipients.push(@key) - if !@share_keys.nil? + if not @share_keys.nil? @share_keys.split.each { |k| recipients.push(k) } end @@ -81,7 +81,7 @@ module MPW def search(search='', group=nil, protocol=nil) result = [] - if !search.nil? + if not search.nil? search = search.downcase end search = search.force_encoding('ASCII-8BIT') @@ -91,8 +91,8 @@ module MPW server = row[:host].nil? ? nil : row[:host].downcase comment = row[:comment].nil? ? nil : row[:comment].downcase - if name =~ /^.*#{search}.*$/ || server =~ /^.*#{search}.*$/ || comment =~ /^.*#{search}.*$/ - if (protocol.nil? || protocol.eql?(row[:protocol])) && (group.nil? || group.eql?(row[:group])) + if name =~ /^.*#{search}.*$/ or server =~ /^.*#{search}.*$/ or comment =~ /^.*#{search}.*$/ + if (protocol.nil? or protocol.eql?(row[:protocol])) and (group.nil? or group.eql?(row[:group])) result.push(row) end end @@ -146,15 +146,15 @@ module MPW row_update = {} row_update[:date] = Time.now.to_i - row_update[:id] = id.nil? || id.empty? ? MPW.password(16) : id - row_update[:name] = name.nil? || name.empty? ? row[:name] : name - row_update[:group] = group.nil? || group.empty? ? row[:group] : group - row_update[:host] = server.nil? || server.empty? ? row[:host] : server - row_update[:protocol] = protocol.nil? || protocol.empty? ? row[:protocol] : protocol - row_update[:login] = login.nil? || login.empty? ? row[:login] : login - row_update[:password] = passwd.nil? || passwd.empty? ? row[:password] : passwd - row_update[:port] = port.nil? || port.empty? ? row[:port] : port - row_update[:comment] = comment.nil? || comment.empty? ? row[:comment] : comment + row_update[:id] = id.nil? or id.empty? ? MPW.password(16) : id + row_update[:name] = name.nil? or name.empty? ? row[:name] : name + row_update[:group] = group.nil? or group.empty? ? row[:group] : group + row_update[:host] = server.nil? or server.empty? ? row[:host] : server + row_update[:protocol] = protocol.nil? or protocol.empty? ? row[:protocol] : protocol + row_update[:login] = login.nil? or login.empty? ? row[:login] : login + row_update[:password] = passwd.nil? or passwd.empty? ? row[:password] : passwd + row_update[:port] = port.nil? or port.empty? ? row[:port] : port + row_update[:comment] = comment.nil? or comment.empty? ? row[:comment] : comment row_update[:name] = row_update[:name].nil? ? nil : row_update[:name].force_encoding('ASCII-8BIT') row_update[:group] = row_update[:group].nil? ? nil : row_update[:group].force_encoding('ASCII-8BIT') @@ -164,7 +164,7 @@ module MPW row_update[:password] = row_update[:password].nil? ? nil : row_update[:password].force_encoding('ASCII-8BIT') row_update[:comment] = row_update[:comment].nil? ? nil : row_update[:comment].force_encoding('ASCII-8BIT') - if row_update[:name].nil? || row_update[:name].empty? + if row_update[:name].nil? or row_update[:name].empty? @error_msg = I18n.t('error.update.name_empty') return false end @@ -277,9 +277,9 @@ module MPW # last_update -> last update # @rtrn: false if data_remote is nil def sync(data_remote, last_update) - if !data_remote.instance_of?(Array) + if not data_remote.instance_of?(Array) return false - else !data_remote.nil? && !data_remote.empty? + else not data_remote.nil? and not data_remote.empty? @data.each do |l| j = 0 update = false @@ -298,7 +298,7 @@ module MPW end # Delete an old item - if !update && l[:date].to_i < last_update + if not update and l[:date].to_i < last_update remove(l[:id]) end end diff --git a/lib/UI/Cli.rb b/lib/UI/Cli.rb index c84df63..3b74105 100644 --- a/lib/UI/Cli.rb +++ b/lib/UI/Cli.rb @@ -24,7 +24,7 @@ class Cli # Sync the data with the server # @rtnr: true if the synchro is finish def sync - if !defined?(@sync) + if not defined?(@sync) case @config.sync_type when 'mpw' require "#{APP_ROOT}/lib/Sync/MPWSync" @@ -40,21 +40,21 @@ class Cli end end - if !@config.sync_host.nil? && !@config.sync_port.nil? - if !@sync.connect(@config.sync_host, @config.sync_user, @config.sync_pwd, @config.sync_path, @config.sync_port) + if not @config.sync_host.nil? and not @config.sync_port.nil? + if not @sync.connect(@config.sync_host, @config.sync_user, @config.sync_pwd, @config.sync_path, @config.sync_port) puts "#{I18n.t('display.error')} #1: #{@sync.error_msg}" end end if @sync.enable - if !@mpw.sync(@sync.get(@passwd), @config.last_update) + if not @mpw.sync(@sync.get(@passwd), @config.last_update) puts "#{I18n.t('display.error')} #2: #{@mpw.error_msg}" if !@mpw.error_msg.nil? puts "#{I18n.t('display.error')} #3: #{@sync.error_msg}" if !@sync.error_msg.nil? - elsif !@sync.update(File.open(@config.file_gpg).read) + elsif not @sync.update(File.open(@config.file_gpg).read) puts "#{I18n.t('display.error')} #4: #{@sync.error_msg}" - elsif !@config.set_last_update + elsif not @config.set_last_update puts "#{I18n.t('display.error')} #5: #{@config.error_msg}" - elsif !@mpw.encrypt + elsif not @mpw.encrypt puts "#{I18n.t('display.error')} #6: #{@mpw.error_msg}" else return true @@ -89,17 +89,17 @@ class Cli sync_path = ask(I18n.t('form.setup.sync_path')).to_s end - if language.nil? || language.empty? + if language.nil? or language.empty? language = lang end I18n.locale = language.to_sym - sync_type = sync_type.nil? || sync_type.empty? ? nil : sync_type - sync_host = sync_host.nil? || sync_host.empty? ? nil : sync_host - sync_port = sync_port.nil? || sync_port.empty? ? nil : sync_port.to_i - sync_user = sync_user.nil? || sync_user.empty? ? nil : sync_user - sync_pwd = sync_pwd.nil? || sync_pwd.empty? ? nil : sync_pwd - sync_path = sync_path.nil? || sync_path.empty? ? nil : sync_path + sync_type = sync_type.nil? or sync_type.empty? ? nil : sync_type + sync_host = sync_host.nil? or sync_host.empty? ? nil : sync_host + sync_port = sync_port.nil? or sync_port.empty? ? nil : sync_port.to_i + sync_user = sync_user.nil? or sync_user.empty? ? nil : sync_user + sync_pwd = sync_pwd.nil? or sync_pwd.empty? ? nil : sync_pwd + sync_path = sync_path.nil? or sync_path.empty? ? nil : sync_path if @config.setup(key, share_keys, language, file_gpg, timeout_pwd, sync_type, sync_host, sync_port, sync_user, sync_pwd, sync_path) puts I18n.t('form.setup.valid') @@ -120,7 +120,7 @@ class Cli puts '--------------------' ask = ask(I18n.t('form.setup_gpg_key.ask')).to_s - if !['Y', 'y', 'O', 'o'].include?(ask) + if not ['Y', 'y', 'O', 'o'].include?(ask) puts I18n.t('form.setup_gpg_key.no_create') exit 2 end @@ -138,8 +138,8 @@ class Cli expire = ask(I18n.t('form.setup_gpg_key.expire')).to_s password = password.to_s - length = length.nil? || length.empty? ? 2048 : length.to_i - expire = expire.nil? || expire.empty? ? 0 : expire.to_i + length = length.nil? or length.empty? ? 2048 : length.to_i + expire = expire.nil? or expire.empty? ? 0 : expire.to_i puts I18n.t('form.setup_gpg_key.wait') @@ -153,12 +153,12 @@ class Cli # Request the GPG password and decrypt the file def decrypt - if !defined?(@mpw) + if not defined?(@mpw) @mpw = MPW::MPW.new(@config.file_gpg, @config.key, @config.share_keys) end @passwd = ask(I18n.t('display.gpg_password')) {|q| q.echo = false} - if !@mpw.decrypt(@passwd) + if not @mpw.decrypt(@passwd) puts "#{I18n.t('display.error')} #11: #{@mpw.error_msg}" exit 2 end @@ -203,7 +203,7 @@ class Cli def displayFormatAlt(item) port = item[:port].nil? ? '' : ":#{item[:port]}" - if item[:password].nil? || item[:password].empty? + if item[:password].nil? or item[:password].empty? if item[:login].include('@') puts "# #{item[:id]} #{item[:protocol]}://#{item[:login]}@#{item[:host]}#{port}" else @@ -338,7 +338,7 @@ class Cli end if force - if @mpw.import(file) && @mpw.encrypt + if @mpw.import(file) and @mpw.encrypt sync puts I18n.t('form.import.valid') else @@ -371,21 +371,21 @@ class Cli case command[0] when 'display', 'show', 'd', 's' - if !command[1].nil? && !command[1].empty? + if not command[1].nil? and not command[1].empty? display(command[1], group, command[2]) end when 'add', 'a' add when 'update', 'u' - if !command[1].nil? && !command[1].empty? + if not command[1].nil? and not command[1].empty? update(command[1]) end when 'remove', 'delete', 'r', 'd' - if !command[1].nil? && !command[1].empty? + if not command[1].nil? and not command[1].empty? remove(command[1]) end when 'group', 'g' - if !command[1].nil? && !command[1].empty? + if not command[1].nil? and not command[1].empty? group = command[1] else group = nil @@ -404,7 +404,7 @@ class Cli puts I18n.t('interactive.goodbye') break else - if !command[0].nil? && !command[0].empty? + if not command[0].nil? and not command[0].empty? puts I18n.t('interactive.unknown_command') end end diff --git a/lib/UI/CliSSH.rb b/lib/UI/CliSSH.rb index c982a28..b32097e 100644 --- a/lib/UI/CliSSH.rb +++ b/lib/UI/CliSSH.rb @@ -22,7 +22,7 @@ class CliSSH < Cli passwd = r[:password] - if port.nil? || port.empty? + if port.nil? and port.empty? port = 22 end diff --git a/mpw b/mpw index 9056610..309f910 100755 --- a/mpw +++ b/mpw @@ -21,14 +21,14 @@ require "#{APP_ROOT}/lib/MPW" lang = Locale::Tag.parse(ENV['LANG']).to_simple.to_s[0..1] -if defined? I18n.enforce_available_locales +if defined?(I18n.enforce_available_locales) I18n.enforce_available_locales = true end I18n::Backend::Simple.send(:include, I18n::Backend::Fallbacks) -I18n.load_path = Dir["#{APP_ROOT}/i18n/cli/*.yml"] +I18n.load_path = Dir["#{APP_ROOT}/i18n/cli/*.yml"] I18n.default_locale = :en -I18n.locale = lang.to_sym +I18n.locale = lang.to_sym # --------------------------------------------------------- # # Options @@ -122,9 +122,9 @@ check_error = config.checkconfig cli = Cli.new(config) # Setup a new config -if !check_error || !options[:setup].nil? +if not check_error or not options[:setup].nil? cli.setup(lang) -elsif !config.check_gpg_key? +elsif not config.check_gpg_key? cli.setup_gpg_key end diff --git a/mpw-ssh b/mpw-ssh index 5674b1e..89a8c99 100755 --- a/mpw-ssh +++ b/mpw-ssh @@ -19,14 +19,14 @@ lang = Locale::Tag.parse(ENV['LANG']).to_simple.to_s[0..1] # Set local # --------------------------------------------------------- # -if defined? I18n.enforce_available_locales +if defined?(I18n.enforce_available_locales) I18n.enforce_available_locales = true end I18n::Backend::Simple.send(:include, I18n::Backend::Fallbacks) -I18n.load_path = Dir["#{APP_ROOT}/i18n/cli/*.yml"] +I18n.load_path = Dir["#{APP_ROOT}/i18n/cli/*.yml"] I18n.default_locale = :en -I18n.locale = lang.to_sym +I18n.locale = lang.to_sym # --------------------------------------------------------- # # Options @@ -73,7 +73,7 @@ cli.port = options[:port] search = ARGV[0] # Setup a new config -if !check_error +if not check_error cli.setup(lang) elsif ARGV.length < 1 From 3e2c8eef0ce858de8acba61854e56d133d674b9f Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sun, 16 Nov 2014 19:46:21 +0100 Subject: [PATCH 109/531] update syntax --- lib/Server.rb | 29 ++++++++++++++--------------- mpw-server | 4 ++-- 2 files changed, 16 insertions(+), 17 deletions(-) diff --git a/lib/Server.rb b/lib/Server.rb index fe70cca..415bb26 100644 --- a/lib/Server.rb +++ b/lib/Server.rb @@ -30,11 +30,9 @@ module MPW while true do msg = get_client_msg(client) - if !msg - next - end + next if not msg - if msg['gpg_key'].nil? || msg['gpg_key'].empty? || msg['password'].nil? || msg['password'].empty? + if msg['gpg_key'].nil? or msg['gpg_key'].empty? or msg['password'].nil? or msg['password'].empty? @log.warning("#{client.peeraddr[3]} is disconnected because no password or no gpg_key") close_connection(client) next @@ -75,7 +73,7 @@ module MPW def get_file(msg) gpg_key = msg['gpg_key'].sub('@', '_') - if msg['suffix'].nil? || msg['suffix'].empty? + if msg['suffix'].nil? or msg['suffix'].empty? file_gpg = "#{@data_dir}/#{gpg_key}.yml" else file_gpg = "#{@data_dir}/#{gpg_key}-#{msg['suffix']}.yml" @@ -117,7 +115,7 @@ module MPW gpg_key = msg['gpg_key'].sub('@', '_') data = msg['data'] - if data.nil? || data.empty? + if data.nil? or data.empty? send_msg = {action: 'update', gpg_key: msg['gpg_key'], error: 'server.error.client.no_data' @@ -126,7 +124,7 @@ module MPW return send_msg.to_json end - if msg['suffix'].nil? || msg['suffix'].empty? + if msg['suffix'].nil? or msg['suffix'].empty? file_gpg = "#{@data_dir}/#{gpg_key}.yml" else file_gpg = "#{@data_dir}/#{gpg_key}-#{msg['suffix']}.yml" @@ -180,16 +178,17 @@ module MPW def delete_file(msg) gpg_key = msg['gpg_key'].sub('@', '_') - if msg['suffix'].nil? || msg['suffix'].empty? + if msg['suffix'].nil? or msg['suffix'].empty? file_gpg = "#{@data_dir}/#{gpg_key}.yml" else file_gpg = "#{@data_dir}/#{gpg_key}-#{msg['suffix']}.yml" end - if !File.exist?(file_gpg) + if not File.exist?(file_gpg) send_msg = {:action => 'delete', - :gpg_key => msg['gpg_key'], - :error => nil} + :gpg_key => msg['gpg_key'], + :error => nil + } return send_msg.to_json end @@ -264,19 +263,19 @@ module MPW @log_file = config['config']['log_file'] @timeout = config['config']['timeout'].to_i - if @host.empty? || @port <= 0 || @data_dir.empty? + if @host.empty? or @port <= 0 or @data_dir.empty? puts I18n.t('checkconfig.fail') puts I18n.t('checkconfig.empty') return false end - if !Dir.exist?(@data_dir) + if not Dir.exist?(@data_dir) puts I18n.t('checkconfig.fail') puts I18n.t('checkconfig.datadir') return false end - if @log_file.nil? || @log_file.empty? + if @log_file.nil? or @log_file.empty? puts I18n.t('checkconfig.fail') puts I18n.t('checkconfig.log_file_empty') return false @@ -330,7 +329,7 @@ module MPW # @args: length -> the length salt # @rtrn: a random string def generate_salt(length=4) - if length.to_i <= 0 || length.to_i > 16 + if length.to_i <= 0 or length.to_i > 16 length = 4 else length = length.to_i diff --git a/mpw-server b/mpw-server index 688973f..30f6105 100755 --- a/mpw-server +++ b/mpw-server @@ -18,7 +18,7 @@ require "#{APP_ROOT}/lib/Server.rb" lang = Locale::Tag.parse(ENV['LANG']).to_simple.to_s[0..1] -if defined? I18n.enforce_available_locales +if defined?(I18n.enforce_available_locales) I18n.enforce_available_locales = true end @@ -57,7 +57,7 @@ end.parse! # Main # --------------------------------------------------------- # -if options[:config].nil? || options[:config].empty? +if options[:config].nil? or options[:config].empty? puts "#{I18n.t('option.usage')}: mpw-server -c CONFIG [options]" exit 2 end From d2eb57a5c42ccc27b459d2234e2d80777c864738 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sun, 16 Nov 2014 19:50:09 +0100 Subject: [PATCH 110/531] update syntax --- lib/Sync/FTP.rb | 10 +++------- lib/Sync/MPWSync.rb | 20 ++++++++------------ lib/Sync/SSH.rb | 10 +++------- 3 files changed, 14 insertions(+), 26 deletions(-) diff --git a/lib/Sync/FTP.rb b/lib/Sync/FTP.rb index 6a6b236..4b6ba33 100644 --- a/lib/Sync/FTP.rb +++ b/lib/Sync/FTP.rb @@ -51,9 +51,7 @@ module MPW # @args: gpg_password -> the gpg password # @rtrn: nil if nothing data or error def get(gpg_password) - if !@enable - return nil - end + return nil if not @enable tmp_file = tmpfile Net::FTP.open(@host) do |ftp| @@ -62,7 +60,7 @@ module MPW end mpw = MPW.new(tmp_file) - if !mpw.decrypt(gpg_password) + if not mpw.decrypt(gpg_password) @error_msg = mpw.error_msg return nil end @@ -78,9 +76,7 @@ module MPW # @args: data -> the data to send on server # @rtrn: false if there is a problem def update(data) - if !@enable - return true - end + return true if not @enable tmp_file = tmpfile File.open(tmp_file, "w") do |file| diff --git a/lib/Sync/MPWSync.rb b/lib/Sync/MPWSync.rb index 730d9fb..1a9f7b6 100644 --- a/lib/Sync/MPWSync.rb +++ b/lib/Sync/MPWSync.rb @@ -33,7 +33,7 @@ module MPW # @rtrn: false if the connection fail def connect(host, user, password, path, port=nil) @host = host - @port = !port.instance_of?(Integer) ? 2201 : port + @port = not port.instance_of?(Integer) ? 2201 : port @gpg_key = user @password = password @suffix = path @@ -62,9 +62,7 @@ module MPW # @args: gpg_password -> the gpg password # @rtrn: nil if nothing data or error def get(gpg_password) - if !@enable - return nil - end + return nil if not @enable msg = nil TCPSocket.open(@host, @port) do |socket| @@ -78,13 +76,13 @@ module MPW msg = JSON.parse(socket.gets) end - if !defined?(msg['error']) + if not defined?(msg['error']) @error_msg = I18n.t('error.sync.communication') return nil - elsif !msg['error'].nil? + elsif not msg['error'].nil? @error_msg = I18n.t(msg['error']) return nil - elsif msg['data'].nil? || msg['data'].empty? + elsif msg['data'].nil? or msg['data'].empty? return [] else tmp_file = tmpfile @@ -93,7 +91,7 @@ module MPW end mpw = MPW.new(tmp_file) - if !mpw.decrypt(gpg_password) + if not mpw.decrypt(gpg_password) @error_msg = mpw.error_msg return nil end @@ -107,9 +105,7 @@ module MPW # @args: data -> the data to send on server # @rtrn: false if there is a problem def update(data) - if !@enable - return true - end + return true if not @enable msg = nil TCPSocket.open(@host, @port) do |socket| @@ -124,7 +120,7 @@ module MPW msg = JSON.parse(socket.gets) end - if !defined?(msg['error']) + if not defined?(msg['error']) @error_msg = I18n.t('error.sync.communication') return false elsif msg['error'].nil? diff --git a/lib/Sync/SSH.rb b/lib/Sync/SSH.rb index 4868a85..d1f3801 100644 --- a/lib/Sync/SSH.rb +++ b/lib/Sync/SSH.rb @@ -51,9 +51,7 @@ module MPW # @args: gpg_password -> the gpg password # @rtrn: nil if nothing data or error def get(gpg_password) - if !@enable - return nil - end + return nil if not @enable tmp_file = tmpfile Net::SCP.start(@host, @user, password: @password, port: @port) do |scp| @@ -61,7 +59,7 @@ module MPW end mpw = MPW.new(tmp_file) - if !mpw.decrypt(gpg_password) + if not mpw.decrypt(gpg_password) @error_msg = mpw.error_msg return nil end @@ -77,9 +75,7 @@ module MPW # @args: data -> the data to send on server # @rtrn: false if there is a problem def update(data) - if !@enable - return true - end + return true if not @enable tmp_file = tmpfile File.open(tmp_file, "w") do |file| From 7ed067b1b75a1142e7e7b547dd11a9c3cd4b7db6 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sat, 6 Dec 2014 12:03:57 +0100 Subject: [PATCH 111/531] update VERSION file --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 4482064..5d32997 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.2.0 - dev +2.0.0 - dev From a0559258662f8f5e890d6e54b62c9dab099b0d54 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sat, 6 Dec 2014 16:24:40 +0100 Subject: [PATCH 112/531] change the data format csv to yaml --- lib/MPW.rb | 164 ++++++++++++++++++++++++-------------------------- lib/UI/Cli.rb | 22 +++---- 2 files changed, 90 insertions(+), 96 deletions(-) diff --git a/lib/MPW.rb b/lib/MPW.rb index 0b0fafb..44b74ee 100644 --- a/lib/MPW.rb +++ b/lib/MPW.rb @@ -31,9 +31,8 @@ module MPW if File.exist?(@file_gpg) crypto = GPGME::Crypto.new(armor: true) - data_decrypt = crypto.decrypt(IO.read(@file_gpg), password: passwd).read - - @data = CSV.parse(data_decrypt, {headers: true, header_converters: :symbol}) + data_decrypt = crypto.decrypt(IO.read(@file_gpg), password: passwd).read.force_encoding('utf-8') + @data = YAML.load(data_decrypt) end return true @@ -45,17 +44,9 @@ module MPW # Encrypt a file # @rtrn: true if the file has been encrypted def encrypt - FileUtils.cp(@file_gpg, "#{@file_gpg}.bk") - - crypto = GPGME::Crypto.new(armor: true) - file_gpg = File.open(@file_gpg, 'w+') + FileUtils.cp(@file_gpg, "#{@file_gpg}.bk") if File.exist?(@file_gpg) - data_to_encrypt = CSV.generate(write_headers: true, - headers: ['id', 'name', 'group', 'protocol', 'host', 'login', 'password', 'port', 'comment', 'date']) do |csv| - @data.each do |r| - csv << [r[:id], r[:name], r[:group], r[:protocol], r[:host], r[:login], r[:password], r[:port], r[:comment], r[:date]] - end - end + data_to_encrypt = @data.to_yaml recipients = [] recipients.push(@key) @@ -63,14 +54,16 @@ module MPW @share_keys.split.each { |k| recipients.push(k) } end + crypto = GPGME::Crypto.new(armor: true) + file_gpg = File.open(@file_gpg, 'w+') crypto.encrypt(data_to_encrypt, recipients: recipients, output: file_gpg) file_gpg.close - FileUtils.rm("#{@file_gpg}.bk") + FileUtils.rm("#{@file_gpg}.bk") if File.exist?("#{@file_gpg}.bk") return true rescue Exception => e @error_msg = "#{I18n.t('error.gpg_file.encrypt')}\n#{e}" - FileUtils.mv("#{@file_gpg}.bk", @file_gpg) + FileUtils.mv("#{@file_gpg}.bk", @file_gpg) if File.exist?("#{@file_gpg}.bk") return false end @@ -84,12 +77,11 @@ module MPW if not search.nil? search = search.downcase end - search = search.force_encoding('ASCII-8BIT') - @data.each do |row| - name = row[:name].nil? ? nil : row[:name].downcase - server = row[:host].nil? ? nil : row[:host].downcase - comment = row[:comment].nil? ? nil : row[:comment].downcase + @data.each do |id, row| + name = row['name'].nil? ? nil : row['name'].downcase + server = row['host'].nil? ? nil : row['host'].downcase + comment = row['comment'].nil? ? nil : row['comment'].downcase if name =~ /^.*#{search}.*$/ or server =~ /^.*#{search}.*$/ or comment =~ /^.*#{search}.*$/ if (protocol.nil? or protocol.eql?(row[:protocol])) and (group.nil? or group.eql?(row[:group])) @@ -102,13 +94,11 @@ module MPW end # Search in some csv data - # @args: id -> the id item + # @args: id_search -> the id item # @rtrn: a row with the resultat of the search - def search_by_id(id) - @data.each do |row| - if row[:id] == id - return row - end + def search_by_id(id_search) + @data.each do |id, row| + return row if id == id_search end return [] @@ -130,49 +120,35 @@ module MPW update = false i = 0 - @data.each do |r| - if r[:id] == id - row = r - update = true - break - end - i += 1 + if @data.has_key?(id) + row = @data[id] end if port.to_i <= 0 port = nil end - row_update = {} - row_update[:date] = Time.now.to_i + row_update = {} + row_update['id'] = id.to_s.empty? ? MPW.password(16) : id + row_update['name'] = name.to_s.empty? ? row['name'] : name + row_update['group'] = group.to_s.empty? ? row['group'] : group + row_update['host'] = server.to_s.empty? ? row['host'] : server + row_update['protocol'] = protocol.to_s.empty? ? row['protocol'] : protocol + row_update['login'] = login.to_s.empty? ? row['login'] : login + row_update['password'] = passwd.to_s.empty? ? row['password'] : passwd + row_update['port'] = port.to_s.empty? ? row['port'] : port + row_update['comment'] = comment.to_s.empty? ? row['comment'] : comment + row_update['date'] = Time.now.to_i - row_update[:id] = id.nil? or id.empty? ? MPW.password(16) : id - row_update[:name] = name.nil? or name.empty? ? row[:name] : name - row_update[:group] = group.nil? or group.empty? ? row[:group] : group - row_update[:host] = server.nil? or server.empty? ? row[:host] : server - row_update[:protocol] = protocol.nil? or protocol.empty? ? row[:protocol] : protocol - row_update[:login] = login.nil? or login.empty? ? row[:login] : login - row_update[:password] = passwd.nil? or passwd.empty? ? row[:password] : passwd - row_update[:port] = port.nil? or port.empty? ? row[:port] : port - row_update[:comment] = comment.nil? or comment.empty? ? row[:comment] : comment - - row_update[:name] = row_update[:name].nil? ? nil : row_update[:name].force_encoding('ASCII-8BIT') - row_update[:group] = row_update[:group].nil? ? nil : row_update[:group].force_encoding('ASCII-8BIT') - row_update[:host] = row_update[:host].nil? ? nil : row_update[:host].force_encoding('ASCII-8BIT') - row_update[:protocol] = row_update[:protocol].nil? ? nil : row_update[:protocol].force_encoding('ASCII-8BIT') - row_update[:login] = row_update[:login].nil? ? nil : row_update[:login].force_encoding('ASCII-8BIT') - row_update[:password] = row_update[:password].nil? ? nil : row_update[:password].force_encoding('ASCII-8BIT') - row_update[:comment] = row_update[:comment].nil? ? nil : row_update[:comment].force_encoding('ASCII-8BIT') - - if row_update[:name].nil? or row_update[:name].empty? + if row_update['name'].to_s.empty? @error_msg = I18n.t('error.update.name_empty') return false end if update - @data[i] = row_update + @data[id] = row_update else - @data.push(row_update) + @data[row_update['id']] = row_update end return true @@ -182,13 +158,11 @@ module MPW # @args: id -> the item's identifiant # @rtrn: true if the item has been deleted def remove(id) - i = 0 - @data.each do |row| - if row[:id] == id - @data.delete_at(i) + @data.each do |k, row| + if k == id + @data.delete(id) return true end - i += 1 end @error_msg = I18n.t('error.delete.id_no_exist', id: id) @@ -197,36 +171,33 @@ module MPW # Export to csv # @args: file -> file where you export the data - # type -> data type + # type -> udata type # @rtrn: true if export work def export(file, type=:csv) case type when :csv CSV.open(file, 'w', write_headers: true, headers: ['name', 'group', 'protocol', 'host', 'login', 'password', 'port', 'comment']) do |csv| - @data.each do |r| - csv << [r[:name], r[:group], r[:protocol], r[:host], r[:login], r[:password], r[:port], r[:comment]] + @data.each do |id, r| + csv << [r['name'], r['group'], r['protocol'], r['host'], r['login'], r['password'], r['port'], r['comment']] end end when :yaml data = {} - i = 0 - @data.each do |r| - data.merge!({i => {'id' => r[:id], - 'name' => r[:name], - 'group' => r[:group], - 'protocol' => r[:protocol], - 'host' => r[:host], - 'login' => r[:login], - 'password' => r[:password], - 'port' => r[:port], - 'comment' => r[:comment] - } + @data.each do |id, r| + data.merge!({id => {'id' => r['id'], + 'name' => r['name'], + 'group' => r['group'], + 'protocol' => r['protocol'], + 'host' => r['host'], + 'login' => r['login'], + 'password' => r['password'], + 'port' => r['port'], + 'comment' => r['comment'], + } } ) - - i += 1 end File.open(file, 'w') {|f| f << data.to_yaml} @@ -243,12 +214,25 @@ module MPW # Import to csv # @args: file -> path to file import + # type -> udata type # @rtrn: true if the import work - def import(file) - CSV.foreach(file, {headers: true, header_converters: :symbol}) do |row| - if not update(row[:name], row[:group], row[:host], row[:protocol], row[:login], row[:password], row[:port], row[:comment]) - return false + def import(file, type=:csv) + case type + when :csv + CSV.foreach(file, {headers: true, header_converters: :symbol}) do |row| + if not update(row[:name], row[:group], row[:host], row[:protocol], row[:login], row[:password], row[:port], row[:comment]) + return false + end end + when :yaml + YAML::load_file(file).each do |k, row| + if not update(row['name'], row['group'], row['host'], row['protocol'], row['login'], row['password'], row['port'], row['comment']) + return false + end + end + else + @error_msg = "#{I18n.t('error.export.unknown_type', type: type)}" + return false end return true @@ -260,10 +244,20 @@ module MPW # Return a preview import # @args: file -> path to file import # @rtrn: an array with the items to import, if there is an error return false - def import_preview(file) + def import_preview(file, type=:csv) result = [] - CSV.foreach(file, {headers: true, header_converters: :symbol}) do |row| - result << row + case type + when :csv + CSV.foreach(file, {headers: true}) do |row| + result << row + end + when :yaml + YAML::load_file(file).each do |k, row| + result << row + end + else + @error_msg = "#{I18n.t('error.export.unknown_type', type: type)}" + return false end return result diff --git a/lib/UI/Cli.rb b/lib/UI/Cli.rb index 3b74105..a8d165e 100644 --- a/lib/UI/Cli.rb +++ b/lib/UI/Cli.rb @@ -77,7 +77,7 @@ class Cli language = ask(I18n.t('form.setup.lang', lang: lang)).to_s key = ask(I18n.t('form.setup.gpg_key')).to_s share_keys = ask(I18n.t('form.setup.share_gpg_keys')).to_s - file_gpg = ask(I18n.t('form.setup.gpg_file', home: @conf.dir_home)).to_s + file_gpg = ask(I18n.t('form.setup.gpg_file', home: @conf.dir_config)).to_s timeout_pwd = ask(I18n.t('form.setup.timeout')).to_s sync_type = ask(I18n.t('form.setup.sync_type')).to_s @@ -187,15 +187,15 @@ class Cli # @args: item -> an array with the item information def displayFormat(item) puts '--------------------' - puts "Id: #{item[:id]}" - puts "#{I18n.t('display.name')}: #{item[:name]}" - puts "#{I18n.t('display.group')}: #{item[:group]}" - puts "#{I18n.t('display.server')}: #{item[:host]}" - puts "#{I18n.t('display.protocol')}: #{item[:protocol]}" - puts "#{I18n.t('display.login')}: #{item[:login]}" - puts "#{I18n.t('display.password')}: #{item[:password]}" - puts "#{I18n.t('display.port')}: #{item[:port]}" - puts "#{I18n.t('display.comment')}: #{item[:comment]}" + puts "Id: #{item['id']}" + puts "#{I18n.t('display.name')}: #{item['name']}" + puts "#{I18n.t('display.group')}: #{item['group']}" + puts "#{I18n.t('display.server')}: #{item['host']}" + puts "#{I18n.t('display.protocol')}: #{item['protocol']}" + puts "#{I18n.t('display.login')}: #{item['login']}" + puts "#{I18n.t('display.password')}: #{item['password']}" + puts "#{I18n.t('display.port')}: #{item['port']}" + puts "#{I18n.t('display.comment')}: #{item['comment']}" end # Display an item in the alternative format @@ -320,9 +320,9 @@ class Cli # @args: file -> the import file # force -> no resquest a validation def import(file, force=false) - result = @mpw.import_preview(file) if not force + result = @mpw.import_preview(file) if result.is_a?(Array) && !result.empty? result.each do |r| displayFormat(r) From c3d484a85efd1f76bc11cc07e1acd23584a1efd0 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sat, 6 Dec 2014 16:25:03 +0100 Subject: [PATCH 113/531] fix a bug --- lib/Sync/MPWSync.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Sync/MPWSync.rb b/lib/Sync/MPWSync.rb index 1a9f7b6..ee0d6cb 100644 --- a/lib/Sync/MPWSync.rb +++ b/lib/Sync/MPWSync.rb @@ -33,7 +33,7 @@ module MPW # @rtrn: false if the connection fail def connect(host, user, password, path, port=nil) @host = host - @port = not port.instance_of?(Integer) ? 2201 : port + @port = !port.instance_of?(Integer) ? 2201 : port @gpg_key = user @password = password @suffix = path From 291d68a1f753e6dc595ef668c21772821004ae98 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sat, 6 Dec 2014 18:20:43 +0100 Subject: [PATCH 114/531] code factoring --- lib/MPW.rb | 68 ++++++++++++++++++++++-------------------------------- 1 file changed, 28 insertions(+), 40 deletions(-) diff --git a/lib/MPW.rb b/lib/MPW.rb index 44b74ee..938b616 100644 --- a/lib/MPW.rb +++ b/lib/MPW.rb @@ -3,14 +3,13 @@ # mail: nishiki@yaegashi.fr # info: a simple script who manage your passwords -module MPW - - require 'rubygems' - require 'gpgme' - require 'csv' - require 'i18n' - require 'fileutils' +require 'rubygems' +require 'gpgme' +require 'csv' +require 'i18n' +require 'fileutils' +module MPW class MPW attr_accessor :error_msg @@ -182,25 +181,10 @@ module MPW csv << [r['name'], r['group'], r['protocol'], r['host'], r['login'], r['password'], r['port'], r['comment']] end end + when :yaml - data = {} + File.open(file, 'w') {|f| f << @data.to_yaml} - @data.each do |id, r| - data.merge!({id => {'id' => r['id'], - 'name' => r['name'], - 'group' => r['group'], - 'protocol' => r['protocol'], - 'host' => r['host'], - 'login' => r['login'], - 'password' => r['password'], - 'port' => r['port'], - 'comment' => r['comment'], - } - } - ) - end - - File.open(file, 'w') {|f| f << data.to_yaml} else @error_msg = "#{I18n.t('error.export.unknown_type', type: type)}" return false @@ -219,17 +203,19 @@ module MPW def import(file, type=:csv) case type when :csv - CSV.foreach(file, {headers: true, header_converters: :symbol}) do |row| - if not update(row[:name], row[:group], row[:host], row[:protocol], row[:login], row[:password], row[:port], row[:comment]) + CSV.foreach(file, {headers: true}) do |row| + if not update(row['name'], row['group'], row['host'], row['protocol'], row['login'], row['password'], row['port'], row['comment']) return false end end + when :yaml YAML::load_file(file).each do |k, row| if not update(row['name'], row['group'], row['host'], row['protocol'], row['login'], row['password'], row['port'], row['comment']) return false end end + else @error_msg = "#{I18n.t('error.export.unknown_type', type: type)}" return false @@ -271,37 +257,39 @@ module MPW # last_update -> last update # @rtrn: false if data_remote is nil def sync(data_remote, last_update) - if not data_remote.instance_of?(Array) + if not data_remote.instance_of?(Hash) + @error_msg = I18n.t('error.sync.hash') return false - else not data_remote.nil? and not data_remote.empty? - @data.each do |l| + + else not data_remote.to_s.empty? + @data.each do |lk, l| j = 0 update = false # Update item - data_remote.each do |r| - if l[:id] == r[:id] - if l[:date].to_i < r[:date].to_i - update(r[:name], r[:group], r[:host], r[:protocol], r[:login], r[:password], r[:port], r[:comment], l[:id]) + data_remote.each do |rk, r| + if l['id'] == r['id'] + if l['date'].to_i < r['date'].to_i + update(r['name'], r['group'], r['host'], r['protocol'], r['login'], r['password'], r['port'], r['comment'], l['id']) end update = true - data_remote.delete_at(j) + data_remote.delete(rk) break end j += 1 end # Delete an old item - if not update and l[:date].to_i < last_update - remove(l[:id]) + if not update and l['date'].to_i < last_update + remove(l['id']) end end end # Add item - data_remote.each do |r| - if r[:date].to_i > last_update - update(r[:name], r[:group], r[:host], r[:protocol], r[:login], r[:password], r[:port], r[:comment], r[:id]) + data_remote.each do |rk, r| + if r['date'].to_i > last_update + update(r['name'], r['group'], r['host'], r['protocol'], r['login'], r['password'], r['port'], r['comment'], r['id']) end end @@ -327,6 +315,6 @@ module MPW return result end - end + end end From 568a8514cfe8c2a2a08232608bf3b6c6b491731f Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sat, 6 Dec 2014 21:37:18 +0100 Subject: [PATCH 115/531] fix sync with new data format --- lib/MPW.rb | 19 +++++++++---------- lib/Sync/MPWSync.rb | 6 +++--- lib/UI/Cli.rb | 12 ++++++------ 3 files changed, 18 insertions(+), 19 deletions(-) diff --git a/lib/MPW.rb b/lib/MPW.rb index 938b616..791dd3a 100644 --- a/lib/MPW.rb +++ b/lib/MPW.rb @@ -26,12 +26,12 @@ module MPW # @args: password -> the GPG key password # @rtrn: true if data has been decrypted def decrypt(passwd=nil) - @data = [] + @data = {} if File.exist?(@file_gpg) crypto = GPGME::Crypto.new(armor: true) data_decrypt = crypto.decrypt(IO.read(@file_gpg), password: passwd).read.force_encoding('utf-8') - @data = YAML.load(data_decrypt) + @data = YAML.load(data_decrypt) if not data_decrypt.to_s.empty? end return true @@ -119,7 +119,7 @@ module MPW update = false i = 0 - if @data.has_key?(id) + if @data.instance_of?(Hash) and @data.has_key?(id) row = @data[id] end @@ -229,7 +229,7 @@ module MPW # Return a preview import # @args: file -> path to file import - # @rtrn: an array with the items to import, if there is an error return false + # @rtrn: a hash with the items to import, if there is an error return false def import_preview(file, type=:csv) result = [] case type @@ -257,23 +257,22 @@ module MPW # last_update -> last update # @rtrn: false if data_remote is nil def sync(data_remote, last_update) - if not data_remote.instance_of?(Hash) - @error_msg = I18n.t('error.sync.hash') + if not data_remote.instance_of?(Array) + @error_msg = I18n.t('error.sync.array') return false - else not data_remote.to_s.empty? @data.each do |lk, l| j = 0 update = false # Update item - data_remote.each do |rk, r| + data_remote.each do |r| if l['id'] == r['id'] if l['date'].to_i < r['date'].to_i update(r['name'], r['group'], r['host'], r['protocol'], r['login'], r['password'], r['port'], r['comment'], l['id']) end update = true - data_remote.delete(rk) + data_remote.delete(r['id']) break end j += 1 @@ -287,7 +286,7 @@ module MPW end # Add item - data_remote.each do |rk, r| + data_remote.each do |r| if r['date'].to_i > last_update update(r['name'], r['group'], r['host'], r['protocol'], r['login'], r['password'], r['port'], r['comment'], r['id']) end diff --git a/lib/Sync/MPWSync.rb b/lib/Sync/MPWSync.rb index ee0d6cb..ae0c466 100644 --- a/lib/Sync/MPWSync.rb +++ b/lib/Sync/MPWSync.rb @@ -63,7 +63,7 @@ module MPW # @rtrn: nil if nothing data or error def get(gpg_password) return nil if not @enable - + msg = nil TCPSocket.open(@host, @port) do |socket| send_msg = {action: 'get', @@ -75,7 +75,7 @@ module MPW socket.puts send_msg.to_json msg = JSON.parse(socket.gets) end - + if not defined?(msg['error']) @error_msg = I18n.t('error.sync.communication') return nil @@ -83,7 +83,7 @@ module MPW @error_msg = I18n.t(msg['error']) return nil elsif msg['data'].nil? or msg['data'].empty? - return [] + return {} else tmp_file = tmpfile File.open(tmp_file, 'w') do |file| diff --git a/lib/UI/Cli.rb b/lib/UI/Cli.rb index a8d165e..59edc54 100644 --- a/lib/UI/Cli.rb +++ b/lib/UI/Cli.rb @@ -48,8 +48,8 @@ class Cli if @sync.enable if not @mpw.sync(@sync.get(@passwd), @config.last_update) - puts "#{I18n.t('display.error')} #2: #{@mpw.error_msg}" if !@mpw.error_msg.nil? - puts "#{I18n.t('display.error')} #3: #{@sync.error_msg}" if !@sync.error_msg.nil? + puts "#{I18n.t('display.error')} #2: #{@mpw.error_msg}" if not @mpw.error_msg.nil? + puts "#{I18n.t('display.error')} #3: #{@sync.error_msg}" if not @sync.error_msg.nil? elsif not @sync.update(File.open(@config.file_gpg).read) puts "#{I18n.t('display.error')} #4: #{@sync.error_msg}" elsif not @config.set_last_update @@ -62,9 +62,9 @@ class Cli end rescue Exception => e puts "#{I18n.t('display.error')} #7: #{e}" - puts @sync.error_msg if @sync.error_msg.nil? - puts @config.error_msg if @config.error_msg.nil? - puts @mpw.error_msg if @mpw.error_msg.nil? + puts @sync.error_msg if not @sync.error_msg.nil? + puts @config.error_msg if not @config.error_msg.nil? + puts @mpw.error_msg if not @mpw.error_msg.nil? else return false end @@ -323,7 +323,7 @@ class Cli if not force result = @mpw.import_preview(file) - if result.is_a?(Array) && !result.empty? + if result.is_a?(Array) and not result.empty? result.each do |r| displayFormat(r) end From 30f52dfe92f7b05c15d6aac1a7dd66ce87af5d78 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sat, 6 Dec 2014 23:32:09 +0100 Subject: [PATCH 116/531] fix import and export to yaml --- lib/MPW.rb | 4 ++-- lib/UI/Cli.rb | 8 ++++---- mpw | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/MPW.rb b/lib/MPW.rb index 791dd3a..f0971cb 100644 --- a/lib/MPW.rb +++ b/lib/MPW.rb @@ -172,7 +172,7 @@ module MPW # @args: file -> file where you export the data # type -> udata type # @rtrn: true if export work - def export(file, type=:csv) + def export(file, type=:yaml) case type when :csv CSV.open(file, 'w', write_headers: true, @@ -200,7 +200,7 @@ module MPW # @args: file -> path to file import # type -> udata type # @rtrn: true if the import work - def import(file, type=:csv) + def import(file, type=:yaml) case type when :csv CSV.foreach(file, {headers: true}) do |row| diff --git a/lib/UI/Cli.rb b/lib/UI/Cli.rb index 59edc54..14b2e97 100644 --- a/lib/UI/Cli.rb +++ b/lib/UI/Cli.rb @@ -307,7 +307,7 @@ class Cli # Export the items in a CSV file # @args: file -> the destination file - def export(file, type) + def export(file, type=:yaml) if @mpw.export(file, type) puts "The export in #{file} is succesfull!" else @@ -319,10 +319,10 @@ class Cli # Import items from a CSV file # @args: file -> the import file # force -> no resquest a validation - def import(file, force=false) + def import(file, type=:yaml, force=false) if not force - result = @mpw.import_preview(file) + result = @mpw.import_preview(file, type) if result.is_a?(Array) and not result.empty? result.each do |r| displayFormat(r) @@ -338,7 +338,7 @@ class Cli end if force - if @mpw.import(file) and @mpw.encrypt + if @mpw.import(file, type) and @mpw.encrypt sync puts I18n.t('form.import.valid') else diff --git a/mpw b/mpw index 309f910..f4092d3 100755 --- a/mpw +++ b/mpw @@ -153,7 +153,7 @@ elsif not options[:export].nil? # Add a new item elsif not options[:import].nil? - cli.import(options[:import], options[:force]) + cli.import(options[:import], options[:type], options[:force]) # Interactive mode else From ac07b629929bcea420f39478395a197ee0209275 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sat, 6 Dec 2014 23:33:48 +0100 Subject: [PATCH 117/531] add .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b844b14 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +Gemfile.lock From 6290bfb3bbfd602bb85acbb6583e709b4ba6894a Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sat, 6 Dec 2014 23:40:09 +0100 Subject: [PATCH 118/531] remove interactive mode --- lib/Config.rb | 9 +------ lib/UI/Cli.rb | 68 +-------------------------------------------------- mpw | 7 ------ 3 files changed, 2 insertions(+), 82 deletions(-) diff --git a/lib/Config.rb b/lib/Config.rb index aaab3ac..c1cc17e 100644 --- a/lib/Config.rb +++ b/lib/Config.rb @@ -18,7 +18,6 @@ module MPW attr_accessor :share_keys attr_accessor :lang attr_accessor :file_gpg - attr_accessor :timeout_pwd attr_accessor :last_update attr_accessor :sync_type attr_accessor :sync_host @@ -53,7 +52,6 @@ module MPW # share_keys -> multiple keys to share the password with other people # lang -> the software language # file_gpg -> the file who is encrypted - # timeout_pwd -> time to save the password # sync_type -> the type to synchronization # sync_host -> the server host for synchronization # sync_port -> the server port for synchronization @@ -61,7 +59,7 @@ module MPW # sync_pwd -> the password for synchronization # sync_suffix -> the suffix file (optionnal) # @rtrn: true if le config file is create - def setup(key, share_keys, lang, file_gpg, timeout_pwd, sync_type, sync_host, sync_port, sync_user, sync_pwd, sync_path) + def setup(key, share_keys, lang, file_gpg, sync_type, sync_host, sync_port, sync_user, sync_pwd, sync_path) if not key =~ /[a-zA-Z0-9.-_]+\@[a-zA-Z0-9]+\.[a-zA-Z]+/ @error_msg = I18n.t('error.config.key_bad_format') @@ -76,13 +74,10 @@ module MPW file_gpg = "#{@dir_config}/db/default.gpg" end - timeout_pwd = timeout_pwd.empty? ? 60 : timeout_pwd.to_i - config = {'config' => {'key' => key, 'share_keys' => share_keys, 'lang' => lang, 'file_gpg' => file_gpg, - 'timeout_pwd' => timeout_pwd, 'sync_type' => sync_type, 'sync_host' => sync_host, 'sync_port' => sync_port, @@ -150,7 +145,6 @@ module MPW @share_keys = config['config']['share_keys'] @lang = config['config']['lang'] @file_gpg = config['config']['file_gpg'] - @timeout_pwd = config['config']['timeout_pwd'].to_i @sync_type = config['config']['sync_type'] @sync_host = config['config']['sync_host'] @sync_port = config['config']['sync_port'] @@ -216,7 +210,6 @@ module MPW 'share_keys' => @share_keys, 'lang' => @lang, 'file_gpg' => @file_gpg, - 'timeout_pwd' => @timeout_pwd, 'sync_type' => @sync_type, 'sync_host' => @sync_host, 'sync_port' => @sync_port, diff --git a/lib/UI/Cli.rb b/lib/UI/Cli.rb index 14b2e97..765039d 100644 --- a/lib/UI/Cli.rb +++ b/lib/UI/Cli.rb @@ -78,7 +78,6 @@ class Cli key = ask(I18n.t('form.setup.gpg_key')).to_s share_keys = ask(I18n.t('form.setup.share_gpg_keys')).to_s file_gpg = ask(I18n.t('form.setup.gpg_file', home: @conf.dir_config)).to_s - timeout_pwd = ask(I18n.t('form.setup.timeout')).to_s sync_type = ask(I18n.t('form.setup.sync_type')).to_s if ['ssh', 'ftp', 'mpw'].include?(sync_type) @@ -101,7 +100,7 @@ class Cli sync_pwd = sync_pwd.nil? or sync_pwd.empty? ? nil : sync_pwd sync_path = sync_path.nil? or sync_path.empty? ? nil : sync_path - if @config.setup(key, share_keys, language, file_gpg, timeout_pwd, sync_type, sync_host, sync_port, sync_user, sync_pwd, sync_path) + if @config.setup(key, share_keys, language, file_gpg, sync_type, sync_host, sync_port, sync_user, sync_pwd, sync_path) puts I18n.t('form.setup.valid') else puts "#{I18n.t('display.error')} #8: #{@config.error_msg}" @@ -347,69 +346,4 @@ class Cli end end - # Interactive mode - def interactive - group = nil - last_access = Time.now.to_i - - while buf = Readline.readline('<mpw> ', true) - - if @config.timeout_pwd < Time.now.to_i - last_access - passwd_confirm = ask(I18n.t('interactive.ask_password')) {|q| q.echo = false} - - if @passwd.eql?(passwd_confirm) - last_access = Time.now.to_i - else - puts I18n.t('interactive.bad_password') - next - end - else - last_access = Time.now.to_i - end - - command = buf.split(' ') - - case command[0] - when 'display', 'show', 'd', 's' - if not command[1].nil? and not command[1].empty? - display(command[1], group, command[2]) - end - when 'add', 'a' - add - when 'update', 'u' - if not command[1].nil? and not command[1].empty? - update(command[1]) - end - when 'remove', 'delete', 'r', 'd' - if not command[1].nil? and not command[1].empty? - remove(command[1]) - end - when 'group', 'g' - if not command[1].nil? and not command[1].empty? - group = command[1] - else - group = nil - end - when 'help', 'h', '?' - puts I18n.t('interactive.option.title') - puts '--------------------' - puts "display, show, d, s SEARCH #{I18n.t('interactive.option.show')}" - puts "group, g #{I18n.t('interactive.option.group')}" - puts "add, a #{I18n.t('interactive.option.add')}" - puts "update, u ID #{I18n.t('interactive.option.update')}" - puts "remove, delete, r, d ID #{I18n.t('interactive.option.remove')}" - puts "help, h, ? #{I18n.t('interactive.option.help')}" - puts "quit, exit, q #{I18n.t('interactive.option.quit')}" - when 'quit', 'exit', 'q' - puts I18n.t('interactive.goodbye') - break - else - if not command[0].nil? and not command[0].empty? - puts I18n.t('interactive.unknown_command') - end - end - - end - - end end diff --git a/mpw b/mpw index f4092d3..0e2a171 100755 --- a/mpw +++ b/mpw @@ -156,13 +156,6 @@ elsif not options[:import].nil? cli.import(options[:import], options[:type], options[:force]) # Interactive mode -else - begin - cli.interactive - rescue SystemExit, Interrupt - cli = nil - return 1 - end end cli = nil From ccb0e71edc1648e60be307d3f3b9816444cce0ff Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sat, 6 Dec 2014 23:53:03 +0100 Subject: [PATCH 119/531] add text color --- Gemfile | 1 + i18n/cli/en.yml | 21 ++++---------------- i18n/cli/fr.yml | 21 ++++---------------- lib/UI/Cli.rb | 52 ++++++++++++++++++++++++------------------------- 4 files changed, 35 insertions(+), 60 deletions(-) diff --git a/Gemfile b/Gemfile index d005d66..7046265 100644 --- a/Gemfile +++ b/Gemfile @@ -3,6 +3,7 @@ gem 'highline' gem 'i18n', '0.6.9' gem 'locale' gem 'gpgme' +gem 'colorize' group :ssh do gem 'net-ssh' diff --git a/i18n/cli/en.yml b/i18n/cli/en.yml index dde1d7d..646671c 100644 --- a/i18n/cli/en.yml +++ b/i18n/cli/en.yml @@ -42,9 +42,9 @@ en: config: "Specify the configuration file to use" setup: "Create a new configuration file" protocol: "Select the items with the specified protocol" - export: "Export all items in a CSV file" + export: "Export all items in a file" type: "Data's type export file [csv|yaml]" - import: "Import item since a CSV file" + import: "Import item since a yaml or csv file" force: "Force an action" format: "Change the display items format by an alternative format" generate_password: "Generate a random password (default 8 characters)" @@ -107,21 +107,8 @@ en: port: "Enter the connection port [%{port}]: " comment: "Enter a comment [%{comment}]: " valid: "Item has been updated!" - - interactive: - ask_password: "Password GPG: " - bad_password: "Bad password!" - goodbye: "Goodbye!" - unknown_command: "Unknown command!" - option: - title: "Help" - show: "Search and show the results" - group: "Change the group for the search" - add: "Add an item" - update: "Update an item" - remove: "Remove an item" - help: "Show this message" - quit: "Quit the software" + export: + valid: "The export in %{file} is succesfull!" display: comment: "Comment" diff --git a/i18n/cli/fr.yml b/i18n/cli/fr.yml index 64e11ee..18f78af 100644 --- a/i18n/cli/fr.yml +++ b/i18n/cli/fr.yml @@ -42,9 +42,9 @@ fr: config: "Spécifie le fichier de configuration à utiliser" setup: "Création d'un nouveau fichier de configuration" protocol: "Sélectionne les éléments ayant le protocole spécifié" - export: "Exporte tous les éléments dans un fichier au format CSV" + export: "Exporte tous les éléments dans un fichier" type: "Format des données du fichier d'export [csv|yaml]" - import: "Importe des éléments depuis un fichier au format CSV" + import: "Importe des éléments depuis un fichier yaml ou csv" force: "Force une action, l'action ne demandera pas de confirmation" format: "Change le format d'affichage des éléments par un alternatif" generate_password: "Génére un mot de passe aléatoire (défaut 8 caractères)" @@ -107,21 +107,8 @@ fr: port: "Entrez un port de connexion [%{port}]: " comment: "Entrez un commentaire [%{comment}]: " valid: "L'élément a bien été mis à jour!" - - interactive: - ask_password: "Mot de passe GPG: " - bad_password: "Mauvais mot de passe!" - goodbye: "Au revoir!" - unknown_command: "Commande inconnue!" - option: - title: "Aide" - show: "Cherche et affiche les résulats" - group: "Change de groupe pour la recherche" - add: "Ajout un élément" - update: "Met à jour un élément" - remove: "Supprime un élément" - help: "Affiche ce message d'aide" - quit: "Quitte le programme" + export: + valid: "L'export dans %{file} est un succès!" display: comment: "Commentaire" diff --git a/lib/UI/Cli.rb b/lib/UI/Cli.rb index 765039d..af8719f 100644 --- a/lib/UI/Cli.rb +++ b/lib/UI/Cli.rb @@ -8,7 +8,7 @@ require 'highline/import' require 'pathname' require 'readline' require 'i18n' -require 'yaml' +require 'colorize' require "#{APP_ROOT}/lib/MPW" @@ -42,26 +42,26 @@ class Cli if not @config.sync_host.nil? and not @config.sync_port.nil? if not @sync.connect(@config.sync_host, @config.sync_user, @config.sync_pwd, @config.sync_path, @config.sync_port) - puts "#{I18n.t('display.error')} #1: #{@sync.error_msg}" + puts "#{I18n.t('display.error')} #1: #{@sync.error_msg}".red end end if @sync.enable if not @mpw.sync(@sync.get(@passwd), @config.last_update) - puts "#{I18n.t('display.error')} #2: #{@mpw.error_msg}" if not @mpw.error_msg.nil? - puts "#{I18n.t('display.error')} #3: #{@sync.error_msg}" if not @sync.error_msg.nil? + puts "#{I18n.t('display.error')} #2: #{@mpw.error_msg}".red if not @mpw.error_msg.nil? + puts "#{I18n.t('display.error')} #3: #{@sync.error_msg}".red if not @sync.error_msg.nil? elsif not @sync.update(File.open(@config.file_gpg).read) - puts "#{I18n.t('display.error')} #4: #{@sync.error_msg}" + puts "#{I18n.t('display.error')} #4: #{@sync.error_msg}".red elsif not @config.set_last_update - puts "#{I18n.t('display.error')} #5: #{@config.error_msg}" + puts "#{I18n.t('display.error')} #5: #{@config.error_msg}".red elsif not @mpw.encrypt - puts "#{I18n.t('display.error')} #6: #{@mpw.error_msg}" + puts "#{I18n.t('display.error')} #6: #{@mpw.error_msg}".red else return true end end rescue Exception => e - puts "#{I18n.t('display.error')} #7: #{e}" + puts "#{I18n.t('display.error')} #7: #{e}".red puts @sync.error_msg if not @sync.error_msg.nil? puts @config.error_msg if not @config.error_msg.nil? puts @mpw.error_msg if not @mpw.error_msg.nil? @@ -101,14 +101,14 @@ class Cli sync_path = sync_path.nil? or sync_path.empty? ? nil : sync_path if @config.setup(key, share_keys, language, file_gpg, sync_type, sync_host, sync_port, sync_user, sync_pwd, sync_path) - puts I18n.t('form.setup.valid') + puts "#{I18n.t('form.setup.valid')}".green else - puts "#{I18n.t('display.error')} #8: #{@config.error_msg}" + puts "#{I18n.t('display.error')} #8: #{@config.error_msg}".red exit 2 end if not @config.checkconfig - puts "#{I18n.t('display.error')} #9: #{@config.error_msg}" + puts "#{I18n.t('display.error')} #9: #{@config.error_msg}".red exit 2 end end @@ -143,9 +143,9 @@ class Cli puts I18n.t('form.setup_gpg_key.wait') if @config.setup_gpg_key(password, name, length, expire) - puts I18n.t('form.setup_gpg_key.valid') + puts "#{I18n.t('form.setup_gpg_key.valid')}".green else - puts "#{I18n.t('display.error')} #10: #{@config.error_msg}" + puts "#{I18n.t('display.error')} #10: #{@config.error_msg}".red exit 2 end end @@ -158,7 +158,7 @@ class Cli @passwd = ask(I18n.t('display.gpg_password')) {|q| q.echo = false} if not @mpw.decrypt(@passwd) - puts "#{I18n.t('display.error')} #11: #{@mpw.error_msg}" + puts "#{I18n.t('display.error')} #11: #{@mpw.error_msg}".red exit 2 end end @@ -230,12 +230,12 @@ class Cli if @mpw.update(name, group, server, protocol, login, passwd, port, comment) if @mpw.encrypt sync - puts I18n.t('form.add.valid') + puts "#{I18n.t('form.add.valid')}".green else - puts "#{I18n.t('display.error')} #12: #{@mpw.error_msg}" + puts "#{I18n.t('display.error')} #12: #{@mpw.error_msg}".red end else - puts "#{I18n.t('display.error')} #13: #{@mpw.error_msg}" + puts "#{I18n.t('display.error')} #13: #{@mpw.error_msg}".red end end @@ -259,12 +259,12 @@ class Cli if @mpw.update(name, group, server, protocol, login, passwd, port, comment, id) if @mpw.encrypt sync - puts I18n.t('form.update.valid') + puts "#{I18n.t('form.update.valid')}".green else - puts "#{I18n.t('display.error')} #14: #{@mpw.error_msg}" + puts "#{I18n.t('display.error')} #14: #{@mpw.error_msg}".red end else - puts "#{I18n.t('display.error')} #15: #{@mpw.error_msg}" + puts "#{I18n.t('display.error')} #15: #{@mpw.error_msg}".red end else puts I18n.t('display.nothing') @@ -294,9 +294,9 @@ class Cli if @mpw.remove(id) if @mpw.encrypt sync - puts I18n.t('form.delete.valid', id: id) + puts "#{I18n.t('form.delete.valid', id: id)}".green else - puts "#{I18n.t('display.error')} #16: #{@mpw.error_msg}" + puts "#{I18n.t('display.error')} #16: #{@mpw.error_msg}".red end else puts I18n.t('form.delete.not_valid') @@ -308,9 +308,9 @@ class Cli # @args: file -> the destination file def export(file, type=:yaml) if @mpw.export(file, type) - puts "The export in #{file} is succesfull!" + puts "#{I18n.t('export.valid', file)}".green else - puts "#{I18n.t('display.error')} #17: #{@mpw.error_msg}" + puts "#{I18n.t('display.error')} #17: #{@mpw.error_msg}".red end end @@ -339,9 +339,9 @@ class Cli if force if @mpw.import(file, type) and @mpw.encrypt sync - puts I18n.t('form.import.valid') + puts "#{I18n.t('form.import.valid')}".green else - puts "#{I18n.t('display.error')} #18: #{@mpw.error_msg}" + puts "#{I18n.t('display.error')} #18: #{@mpw.error_msg}".red end end end From d7a7dfbe10645855781da2fbb0905f2320bf0ffd Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sun, 7 Dec 2014 10:32:33 +0100 Subject: [PATCH 120/531] fix minor bugs --- lib/MPW.rb | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/MPW.rb b/lib/MPW.rb index f0971cb..812a24a 100644 --- a/lib/MPW.rb +++ b/lib/MPW.rb @@ -20,20 +20,20 @@ module MPW @file_gpg = file_gpg @key = key @share_keys = share_keys + @data = {} end # Decrypt a gpg file # @args: password -> the GPG key password # @rtrn: true if data has been decrypted def decrypt(passwd=nil) - @data = {} - if File.exist?(@file_gpg) crypto = GPGME::Crypto.new(armor: true) data_decrypt = crypto.decrypt(IO.read(@file_gpg), password: passwd).read.force_encoding('utf-8') @data = YAML.load(data_decrypt) if not data_decrypt.to_s.empty? end + puts @data.class return true rescue Exception => e @error_msg = "#{I18n.t('error.gpg_file.decrypt')}\n#{e}" @@ -135,7 +135,7 @@ module MPW row_update['protocol'] = protocol.to_s.empty? ? row['protocol'] : protocol row_update['login'] = login.to_s.empty? ? row['login'] : login row_update['password'] = passwd.to_s.empty? ? row['password'] : passwd - row_update['port'] = port.to_s.empty? ? row['port'] : port + row_update['port'] = port.to_s.empty? ? row['port'] : port.to_i row_update['comment'] = comment.to_s.empty? ? row['comment'] : comment row_update['date'] = Time.now.to_i @@ -147,7 +147,8 @@ module MPW if update @data[id] = row_update else - @data[row_update['id']] = row_update + id = row_update['id'] + @data[id] = row_update end return true From e5529e6a7b8c00410721abc4df9978b71404c5be Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sun, 7 Dec 2014 10:35:05 +0100 Subject: [PATCH 121/531] add unit tests --- test/test.cfg | 13 +++++++++++++ test/test.rb | 45 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+) create mode 100644 test/test.cfg create mode 100644 test/test.rb diff --git a/test/test.cfg b/test/test.cfg new file mode 100644 index 0000000..c0ace9e --- /dev/null +++ b/test/test.cfg @@ -0,0 +1,13 @@ +--- +config: + key: test@test-mpw.org + share_keys: + lang: en + file_gpg: "test.gpg" + sync_type: mpw + sync_host: + sync_port: + sync_user: + sync_pwd: + sync_path: + last_update: diff --git a/test/test.rb b/test/test.rb new file mode 100644 index 0000000..0f03d1b --- /dev/null +++ b/test/test.rb @@ -0,0 +1,45 @@ +# File: tc_simple_number.rb + +require_relative "../lib/MPW" +require "test/unit" + +class TestMPW < Test::Unit::TestCase + + + def test_initialize + File.delete('test.gpg') if File.exist?('test.gpg') + end + + def test_load_empty_file + mpw = MPW::MPW.new('test.cfg') + mpw.decrypt + + assert_equal(0, mpw.search.length) + end + + def test_add + mpw = MPW::MPW.new('test.cfg') + + name = 'test_name' + group = 'test_group' + host = 'test_host' + protocol = 'test_protocol' + login = 'test_login' + password = 'test_password' + port = '42' + comment = 'test_comment' + + mpw.update(name, group, host, protocol, login, password, port, comment) + + assert_equal(1, mpw.search.length) + assert_equal('test_name', mpw.search[0]['name']) + assert_equal('test_group', mpw.search[0]['group']) + assert_equal('test_host', mpw.search[0]['host']) + assert_equal('test_protocol', mpw.search[0]['protocol']) + assert_equal('test_login', mpw.search[0]['login']) + assert_equal('test_password', mpw.search[0]['password']) + assert_equal(42, mpw.search[0]['port']) + assert_equal('test_comment', mpw.search[0]['comment']) + end + +end From 140819dbb56d4965ef06f00b0229733b56765a39 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sun, 7 Dec 2014 16:24:31 +0100 Subject: [PATCH 122/531] add new unit test --- lib/MPW.rb | 4 +- test/test.rb | 45 -------------------- test/test_mpw.rb | 105 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 107 insertions(+), 47 deletions(-) delete mode 100644 test/test.rb create mode 100644 test/test_mpw.rb diff --git a/lib/MPW.rb b/lib/MPW.rb index 812a24a..a4c5a1d 100644 --- a/lib/MPW.rb +++ b/lib/MPW.rb @@ -8,6 +8,7 @@ require 'gpgme' require 'csv' require 'i18n' require 'fileutils' +require 'yaml' module MPW class MPW @@ -15,7 +16,7 @@ module MPW attr_accessor :error_msg # Constructor - def initialize(file_gpg, key=nil, share_keys='') + def initialize(file_gpg, key, share_keys='') @error_msg = nil @file_gpg = file_gpg @key = key @@ -33,7 +34,6 @@ module MPW @data = YAML.load(data_decrypt) if not data_decrypt.to_s.empty? end - puts @data.class return true rescue Exception => e @error_msg = "#{I18n.t('error.gpg_file.decrypt')}\n#{e}" diff --git a/test/test.rb b/test/test.rb deleted file mode 100644 index 0f03d1b..0000000 --- a/test/test.rb +++ /dev/null @@ -1,45 +0,0 @@ -# File: tc_simple_number.rb - -require_relative "../lib/MPW" -require "test/unit" - -class TestMPW < Test::Unit::TestCase - - - def test_initialize - File.delete('test.gpg') if File.exist?('test.gpg') - end - - def test_load_empty_file - mpw = MPW::MPW.new('test.cfg') - mpw.decrypt - - assert_equal(0, mpw.search.length) - end - - def test_add - mpw = MPW::MPW.new('test.cfg') - - name = 'test_name' - group = 'test_group' - host = 'test_host' - protocol = 'test_protocol' - login = 'test_login' - password = 'test_password' - port = '42' - comment = 'test_comment' - - mpw.update(name, group, host, protocol, login, password, port, comment) - - assert_equal(1, mpw.search.length) - assert_equal('test_name', mpw.search[0]['name']) - assert_equal('test_group', mpw.search[0]['group']) - assert_equal('test_host', mpw.search[0]['host']) - assert_equal('test_protocol', mpw.search[0]['protocol']) - assert_equal('test_login', mpw.search[0]['login']) - assert_equal('test_password', mpw.search[0]['password']) - assert_equal(42, mpw.search[0]['port']) - assert_equal('test_comment', mpw.search[0]['comment']) - end - -end diff --git a/test/test_mpw.rb b/test/test_mpw.rb new file mode 100644 index 0000000..bfed5d0 --- /dev/null +++ b/test/test_mpw.rb @@ -0,0 +1,105 @@ +# File: tc_simple_number.rb + +require_relative "../lib/MPW" +require "test/unit" + +class TestMPW < Test::Unit::TestCase + + def setup + @file_gpg = 'test.gpg' + @key = 'test-mpw@test-mpw.local' + + if defined?(I18n.enforce_available_locales) + I18n.enforce_available_locales = false + end + + File.delete(@file_gpg) if File.exist?(@file_gpg) + @mpw = MPW::MPW.new(@file_gpg, @key) + end + + def test_load_empty_file + assert(@mpw.decrypt) + assert_equal(0, @mpw.search.length) + end + + def test_add + name = 'test_name' + group = 'test_group' + host = 'test_host' + protocol = 'test_protocol' + login = 'test_login' + password = 'test_password' + port = '42' + comment = 'test_comment' + + assert(@mpw.update(name, group, host, protocol, login, password, port, comment)) + + assert_equal(1, @mpw.search.length) + + result = @mpw.search[0] + assert_equal('test_name', result['name']) + assert_equal('test_group', result['group']) + assert_equal('test_host', result['host']) + assert_equal('test_protocol', result['protocol']) + assert_equal('test_login', result['login']) + assert_equal('test_password', result['password']) + assert_equal(42, result['port']) + assert_equal('test_comment', result['comment']) + + assert(@mpw.update(name, group, host, protocol, login, password, port, comment)) + + assert_equal(2, @mpw.search.length) + end + + def test_add_empty_name + name = '' + group = 'test_group' + host = 'test_host' + protocol = 'test_protocol' + login = 'test_login' + password = 'test_password' + port = '42' + comment = 'test_comment' + + assert(!@mpw.update(name, group, host, protocol, login, password, port, comment)) + + assert_equal(0, @mpw.search.length) + end + + def test_update + name = 'test_name' + group = 'test_group' + host = 'test_host' + protocol = 'test_protocol' + login = 'test_login' + password = 'test_password' + port = '42' + comment = 'test_comment' + + assert(@mpw.update(name, group, host, protocol, login, password, port, comment)) + + id = @mpw.search[0]['id'] + name = 'test_name_update' + group = 'test_group_update' + host = 'test_host_update' + protocol = 'test_protocol_update' + login = 'test_login_update' + password = 'test_password_update' + port = '43' + comment = 'test_comment_update' + + assert(@mpw.update(name, group, host, protocol, login, password, port, comment, id)) + assert_equal(1, @mpw.search.length) + + result = @mpw.search_by_id(id) + assert_equal('test_name_update', result['name']) + assert_equal('test_group_update', result['group']) + assert_equal('test_host_update', result['host']) + assert_equal('test_protocol_update', result['protocol']) + assert_equal('test_login_update', result['login']) + assert_equal('test_password_update', result['password']) + assert_equal(43, result['port']) + assert_equal('test_comment_update', result['comment']) + end + +end From f443485ee0da995b6bf410901754e72192ec005f Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Tue, 9 Dec 2014 22:53:49 +0100 Subject: [PATCH 123/531] add unit test import + fixture --- test/fixtures.yml | 19 +++++++++ test/test_mpw.rb | 100 +++++++++++++++++++++++++--------------------- 2 files changed, 73 insertions(+), 46 deletions(-) create mode 100644 test/fixtures.yml diff --git a/test/fixtures.yml b/test/fixtures.yml new file mode 100644 index 0000000..7cd5520 --- /dev/null +++ b/test/fixtures.yml @@ -0,0 +1,19 @@ +add: + name: 'test_name' + group: 'test_group' + host: 'test_host' + protocol: 'test_protocol' + login: 'test_login' + password: 'test_password' + port: '42' + comment: 'test_comment' +update: + name: 'test_name_update' + group: 'test_group_update' + host: 'test_host_update' + protocol: 'test_protocol_update' + login: 'test_login_update' + password: 'test_password_update' + port: '43' + comment: 'test_comment_update' + diff --git a/test/test_mpw.rb b/test/test_mpw.rb index bfed5d0..431f05c 100644 --- a/test/test_mpw.rb +++ b/test/test_mpw.rb @@ -1,20 +1,23 @@ # File: tc_simple_number.rb -require_relative "../lib/MPW" -require "test/unit" +require_relative '../lib/MPW' +require 'test/unit' +require 'yaml' class TestMPW < Test::Unit::TestCase + #@@mpw = MPW::MPW.new('test.gpg', 'a.waksberg@yaegashi.fr') def setup - @file_gpg = 'test.gpg' - @key = 'test-mpw@test-mpw.local' + file_gpg = 'test.gpg' + key = 'test-mpw@test-mpw.local' if defined?(I18n.enforce_available_locales) I18n.enforce_available_locales = false end - File.delete(@file_gpg) if File.exist?(@file_gpg) - @mpw = MPW::MPW.new(@file_gpg, @key) + File.delete(file_gpg) if File.exist?(file_gpg) + @mpw = MPW::MPW.new(file_gpg, key) + @fixtures = YAML.load_file('fixtures.yml') end def test_load_empty_file @@ -23,16 +26,14 @@ class TestMPW < Test::Unit::TestCase end def test_add - name = 'test_name' - group = 'test_group' - host = 'test_host' - protocol = 'test_protocol' - login = 'test_login' - password = 'test_password' - port = '42' - comment = 'test_comment' - - assert(@mpw.update(name, group, host, protocol, login, password, port, comment)) + assert(@mpw.update(@fixtures['add']['name'], + @fixtures['add']['group'], + @fixtures['add']['host'], + @fixtures['add']['protocol'], + @fixtures['add']['login'], + @fixtures['add']['password'], + @fixtures['add']['port'], + @fixtures['add']['comment'])) assert_equal(1, @mpw.search.length) @@ -46,49 +47,54 @@ class TestMPW < Test::Unit::TestCase assert_equal(42, result['port']) assert_equal('test_comment', result['comment']) - assert(@mpw.update(name, group, host, protocol, login, password, port, comment)) + assert(@mpw.update(@fixtures['add']['name'], + @fixtures['add']['group'], + @fixtures['add']['host'], + @fixtures['add']['protocol'], + @fixtures['add']['login'], + @fixtures['add']['password'], + @fixtures['add']['port'], + @fixtures['add']['comment'])) + assert_equal(2, @mpw.search.length) end def test_add_empty_name - name = '' - group = 'test_group' - host = 'test_host' - protocol = 'test_protocol' - login = 'test_login' - password = 'test_password' - port = '42' - comment = 'test_comment' - - assert(!@mpw.update(name, group, host, protocol, login, password, port, comment)) + assert(!@mpw.update('', + @fixtures['add']['group'], + @fixtures['add']['host'], + @fixtures['add']['protocol'], + @fixtures['add']['login'], + @fixtures['add']['password'], + @fixtures['add']['port'], + @fixtures['add']['comment'])) assert_equal(0, @mpw.search.length) end def test_update - name = 'test_name' - group = 'test_group' - host = 'test_host' - protocol = 'test_protocol' - login = 'test_login' - password = 'test_password' - port = '42' - comment = 'test_comment' + assert(@mpw.update(@fixtures['add']['name'], + @fixtures['add']['group'], + @fixtures['add']['host'], + @fixtures['add']['protocol'], + @fixtures['add']['login'], + @fixtures['add']['password'], + @fixtures['add']['port'], + @fixtures['add']['comment'])) - assert(@mpw.update(name, group, host, protocol, login, password, port, comment)) + id = @mpw.search[0]['id'] - id = @mpw.search[0]['id'] - name = 'test_name_update' - group = 'test_group_update' - host = 'test_host_update' - protocol = 'test_protocol_update' - login = 'test_login_update' - password = 'test_password_update' - port = '43' - comment = 'test_comment_update' + assert(@mpw.update(@fixtures['update']['name'], + @fixtures['update']['group'], + @fixtures['update']['host'], + @fixtures['update']['protocol'], + @fixtures['update']['login'], + @fixtures['update']['password'], + @fixtures['update']['port'], + @fixtures['update']['comment'], + id)) - assert(@mpw.update(name, group, host, protocol, login, password, port, comment, id)) assert_equal(1, @mpw.search.length) result = @mpw.search_by_id(id) @@ -102,4 +108,6 @@ class TestMPW < Test::Unit::TestCase assert_equal('test_comment_update', result['comment']) end + def test_import + end end From 8bbddd1656cd3d65c2a5c5d619a5479c63aab626 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Wed, 10 Dec 2014 21:44:20 +0100 Subject: [PATCH 124/531] add test import --- test/test_mpw.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/test_mpw.rb b/test/test_mpw.rb index 431f05c..5697a7b 100644 --- a/test/test_mpw.rb +++ b/test/test_mpw.rb @@ -109,5 +109,7 @@ class TestMPW < Test::Unit::TestCase end def test_import + assert(@mpw.import('fixtures.yml')) + assert_equal(2, @mpw.search.length) end end From 2cc4ed75bd4f7306fb6dfd17d037affe884f7c16 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sun, 28 Dec 2014 18:18:45 +0100 Subject: [PATCH 125/531] add export test --- test/test_mpw.rb | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/test/test_mpw.rb b/test/test_mpw.rb index 5697a7b..870a66d 100644 --- a/test/test_mpw.rb +++ b/test/test_mpw.rb @@ -3,6 +3,7 @@ require_relative '../lib/MPW' require 'test/unit' require 'yaml' +require 'csv' class TestMPW < Test::Unit::TestCase @@ -112,4 +113,21 @@ class TestMPW < Test::Unit::TestCase assert(@mpw.import('fixtures.yml')) assert_equal(2, @mpw.search.length) end + + def test_export_yaml + assert(@mpw.import('fixtures.yml')) + assert_equal(2, @mpw.search.length) + assert(@mpw.export('export.yml', :yaml)) + export = YAML::load_file('export.yml') + assert_equal(2, export.length) + end + + def test_export_csv + assert(@mpw.import('fixtures.yml')) + assert_equal(2, @mpw.search.length) + assert(@mpw.export('export.yml', :csv)) + export = CSV.parse(File.read('export.yml'), headers: true) + assert_equal(2, export.length) + + end end From 4d1da879885d318aff7068f00574f2013bb40aa5 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sun, 28 Dec 2014 18:26:30 +0100 Subject: [PATCH 126/531] add import csv --- test/test_mpw.rb | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/test/test_mpw.rb b/test/test_mpw.rb index 870a66d..dd348d7 100644 --- a/test/test_mpw.rb +++ b/test/test_mpw.rb @@ -109,8 +109,8 @@ class TestMPW < Test::Unit::TestCase assert_equal('test_comment_update', result['comment']) end - def test_import - assert(@mpw.import('fixtures.yml')) + def test_import_yaml + assert(@mpw.import('fixtures.yml', :yaml)) assert_equal(2, @mpw.search.length) end @@ -125,9 +125,16 @@ class TestMPW < Test::Unit::TestCase def test_export_csv assert(@mpw.import('fixtures.yml')) assert_equal(2, @mpw.search.length) - assert(@mpw.export('export.yml', :csv)) - export = CSV.parse(File.read('export.yml'), headers: true) + assert(@mpw.export('export.csv', :csv)) + export = CSV.parse(File.read('export.csv'), headers: true) assert_equal(2, export.length) + end + def test_import_csv + assert(@mpw.import('fixtures.yml')) + assert_equal(2, @mpw.search.length) + assert(@mpw.export('export.csv', :csv)) + assert(@mpw.import('export.csv', :csv)) + assert_equal(4, @mpw.search.length) end end From 178010ab913876106cb72d994344f4f92d83948f Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sun, 28 Dec 2014 18:48:37 +0100 Subject: [PATCH 127/531] add empty update test --- test/test_mpw.rb | 74 +++++++++++++++++++++++++++++------------------- 1 file changed, 45 insertions(+), 29 deletions(-) diff --git a/test/test_mpw.rb b/test/test_mpw.rb index dd348d7..cade965 100644 --- a/test/test_mpw.rb +++ b/test/test_mpw.rb @@ -7,8 +7,9 @@ require 'csv' class TestMPW < Test::Unit::TestCase - #@@mpw = MPW::MPW.new('test.gpg', 'a.waksberg@yaegashi.fr') def setup + @fixture_file = 'fixtures.yml' + file_gpg = 'test.gpg' key = 'test-mpw@test-mpw.local' @@ -18,7 +19,7 @@ class TestMPW < Test::Unit::TestCase File.delete(file_gpg) if File.exist?(file_gpg) @mpw = MPW::MPW.new(file_gpg, key) - @fixtures = YAML.load_file('fixtures.yml') + @fixtures = YAML.load_file(@fixture_file) end def test_load_empty_file @@ -39,14 +40,14 @@ class TestMPW < Test::Unit::TestCase assert_equal(1, @mpw.search.length) result = @mpw.search[0] - assert_equal('test_name', result['name']) - assert_equal('test_group', result['group']) - assert_equal('test_host', result['host']) - assert_equal('test_protocol', result['protocol']) - assert_equal('test_login', result['login']) - assert_equal('test_password', result['password']) - assert_equal(42, result['port']) - assert_equal('test_comment', result['comment']) + assert_equal(@fixtures['add']['name'], result['name']) + assert_equal(@fixtures['add']['group'], result['group']) + assert_equal(@fixtures['add']['host'], result['host']) + assert_equal(@fixtures['add']['protocol'], result['protocol']) + assert_equal(@fixtures['add']['login'], result['login']) + assert_equal(@fixtures['add']['password'], result['password']) + assert_equal(@fixtures['add']['port'].to_i, result['port']) + assert_equal(@fixtures['add']['comment'], result['comment']) assert(@mpw.update(@fixtures['add']['name'], @fixtures['add']['group'], @@ -63,13 +64,13 @@ class TestMPW < Test::Unit::TestCase def test_add_empty_name assert(!@mpw.update('', - @fixtures['add']['group'], - @fixtures['add']['host'], - @fixtures['add']['protocol'], - @fixtures['add']['login'], - @fixtures['add']['password'], - @fixtures['add']['port'], - @fixtures['add']['comment'])) + @fixtures['add']['group'], + @fixtures['add']['host'], + @fixtures['add']['protocol'], + @fixtures['add']['login'], + @fixtures['add']['password'], + @fixtures['add']['port'], + @fixtures['add']['comment'])) assert_equal(0, @mpw.search.length) end @@ -86,6 +87,21 @@ class TestMPW < Test::Unit::TestCase id = @mpw.search[0]['id'] + # Test empty update + assert(@mpw.update('','', '','','','','', '', id)) + + result = @mpw.search_by_id(id) + assert_equal(@fixtures['add']['name'], result['name']) + assert_equal(@fixtures['add']['group'], result['group']) + assert_equal(@fixtures['add']['host'], result['host']) + assert_equal(@fixtures['add']['protocol'], result['protocol']) + assert_equal(@fixtures['add']['login'], result['login']) + assert_equal(@fixtures['add']['password'], result['password']) + assert_equal(@fixtures['add']['port'].to_i, result['port']) + assert_equal(@fixtures['add']['comment'], result['comment']) + + + # Test real update assert(@mpw.update(@fixtures['update']['name'], @fixtures['update']['group'], @fixtures['update']['host'], @@ -99,23 +115,23 @@ class TestMPW < Test::Unit::TestCase assert_equal(1, @mpw.search.length) result = @mpw.search_by_id(id) - assert_equal('test_name_update', result['name']) - assert_equal('test_group_update', result['group']) - assert_equal('test_host_update', result['host']) - assert_equal('test_protocol_update', result['protocol']) - assert_equal('test_login_update', result['login']) - assert_equal('test_password_update', result['password']) - assert_equal(43, result['port']) - assert_equal('test_comment_update', result['comment']) + assert_equal(@fixtures['update']['name'], result['name']) + assert_equal(@fixtures['update']['group'], result['group']) + assert_equal(@fixtures['update']['host'], result['host']) + assert_equal(@fixtures['update']['protocol'], result['protocol']) + assert_equal(@fixtures['update']['login'], result['login']) + assert_equal(@fixtures['update']['password'], result['password']) + assert_equal(@fixtures['update']['port'].to_i, result['port']) + assert_equal(@fixtures['update']['comment'], result['comment']) end def test_import_yaml - assert(@mpw.import('fixtures.yml', :yaml)) + assert(@mpw.import(@fixture_file, :yaml)) assert_equal(2, @mpw.search.length) end def test_export_yaml - assert(@mpw.import('fixtures.yml')) + assert(@mpw.import(@fixture_file)) assert_equal(2, @mpw.search.length) assert(@mpw.export('export.yml', :yaml)) export = YAML::load_file('export.yml') @@ -123,7 +139,7 @@ class TestMPW < Test::Unit::TestCase end def test_export_csv - assert(@mpw.import('fixtures.yml')) + assert(@mpw.import(@fixture_file)) assert_equal(2, @mpw.search.length) assert(@mpw.export('export.csv', :csv)) export = CSV.parse(File.read('export.csv'), headers: true) @@ -131,7 +147,7 @@ class TestMPW < Test::Unit::TestCase end def test_import_csv - assert(@mpw.import('fixtures.yml')) + assert(@mpw.import(@fixture_file)) assert_equal(2, @mpw.search.length) assert(@mpw.export('export.csv', :csv)) assert(@mpw.import('export.csv', :csv)) From 9aca9da49b603891328905b042d556dec6aed505 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sun, 28 Dec 2014 19:35:51 +0100 Subject: [PATCH 128/531] unittest: fix export and import test --- test/test_mpw.rb | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/test/test_mpw.rb b/test/test_mpw.rb index cade965..2208c6c 100644 --- a/test/test_mpw.rb +++ b/test/test_mpw.rb @@ -128,6 +128,16 @@ class TestMPW < Test::Unit::TestCase def test_import_yaml assert(@mpw.import(@fixture_file, :yaml)) assert_equal(2, @mpw.search.length) + + result = @mpw.search[0] + assert_equal(@fixtures['add']['name'], result['name']) + assert_equal(@fixtures['add']['group'], result['group']) + assert_equal(@fixtures['add']['host'], result['host']) + assert_equal(@fixtures['add']['protocol'], result['protocol']) + assert_equal(@fixtures['add']['login'], result['login']) + assert_equal(@fixtures['add']['password'], result['password']) + assert_equal(@fixtures['add']['port'].to_i, result['port']) + assert_equal(@fixtures['add']['comment'], result['comment']) end def test_export_yaml @@ -136,6 +146,16 @@ class TestMPW < Test::Unit::TestCase assert(@mpw.export('export.yml', :yaml)) export = YAML::load_file('export.yml') assert_equal(2, export.length) + + result = export.values[0] + assert_equal(@fixtures['add']['name'], result['name']) + assert_equal(@fixtures['add']['group'], result['group']) + assert_equal(@fixtures['add']['host'], result['host']) + assert_equal(@fixtures['add']['protocol'], result['protocol']) + assert_equal(@fixtures['add']['login'], result['login']) + assert_equal(@fixtures['add']['password'], result['password']) + assert_equal(@fixtures['add']['port'].to_i, result['port']) + assert_equal(@fixtures['add']['comment'], result['comment']) end def test_export_csv @@ -144,6 +164,17 @@ class TestMPW < Test::Unit::TestCase assert(@mpw.export('export.csv', :csv)) export = CSV.parse(File.read('export.csv'), headers: true) assert_equal(2, export.length) + + result = export[0] + assert_equal(@fixtures['add']['name'], result['name']) + assert_equal(@fixtures['add']['group'], result['group']) + assert_equal(@fixtures['add']['host'], result['host']) + assert_equal(@fixtures['add']['protocol'], result['protocol']) + assert_equal(@fixtures['add']['login'], result['login']) + assert_equal(@fixtures['add']['password'], result['password']) + assert_equal(@fixtures['add']['port'], result['port']) + assert_equal(@fixtures['add']['comment'], result['comment']) + end def test_import_csv @@ -152,5 +183,16 @@ class TestMPW < Test::Unit::TestCase assert(@mpw.export('export.csv', :csv)) assert(@mpw.import('export.csv', :csv)) assert_equal(4, @mpw.search.length) + + result = @mpw.search[2] + assert_equal(@fixtures['add']['name'], result['name']) + assert_equal(@fixtures['add']['group'], result['group']) + assert_equal(@fixtures['add']['host'], result['host']) + assert_equal(@fixtures['add']['protocol'], result['protocol']) + assert_equal(@fixtures['add']['login'], result['login']) + assert_equal(@fixtures['add']['password'], result['password']) + assert_equal(@fixtures['add']['port'].to_i, result['port']) + assert_equal(@fixtures['add']['comment'], result['comment']) + end end From 1c4e54582fcdc09f453203b98ed23ad1c43fe9c8 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sun, 28 Dec 2014 19:43:13 +0100 Subject: [PATCH 129/531] fix import preview default yaml --- lib/MPW.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/MPW.rb b/lib/MPW.rb index a4c5a1d..61d9661 100644 --- a/lib/MPW.rb +++ b/lib/MPW.rb @@ -231,7 +231,7 @@ module MPW # Return a preview import # @args: file -> path to file import # @rtrn: a hash with the items to import, if there is an error return false - def import_preview(file, type=:csv) + def import_preview(file, type=:yaml) result = [] case type when :csv From 3d9367189053bd9e9dc19f5390b5bdc70ab53009 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Mon, 29 Dec 2014 13:59:17 +0100 Subject: [PATCH 130/531] fix minor bug --- lib/Config.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Config.rb b/lib/Config.rb index c1cc17e..92abad8 100644 --- a/lib/Config.rb +++ b/lib/Config.rb @@ -170,7 +170,7 @@ module MPW # @rtrn: true if the key exist, else false def check_gpg_key? ctx = GPGME::Ctx.new - ctx.each_key(key, true) do + ctx.each_key(@key, true) do return true end From 60d7e9ef8e36b1067f35671deb878f96c27ded1e Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Mon, 29 Dec 2014 15:36:06 +0100 Subject: [PATCH 131/531] improve unittest --- test/test_import.csv | 3 + test/test_import.yml | 23 ++++++ test/test_mpw.rb | 172 ++++++++++++++++++++++--------------------- 3 files changed, 115 insertions(+), 83 deletions(-) create mode 100644 test/test_import.csv create mode 100644 test/test_import.yml diff --git a/test/test_import.csv b/test/test_import.csv new file mode 100644 index 0000000..1452c07 --- /dev/null +++ b/test/test_import.csv @@ -0,0 +1,3 @@ +name,group,protocol,host,login,password,port,comment +test_name_csv,test_group_csv,test_protocol_csv,test_host_csv,test_login_csv,test_password_csv,44,test_comment_csv +test_name_update_csv,test_group_update_csv,test_protocol_update_csv,test_host_update_csv,test_login_update_csv,test_password_update_csv,45,test_comment_update_csv diff --git a/test/test_import.yml b/test/test_import.yml new file mode 100644 index 0000000..e7fef00 --- /dev/null +++ b/test/test_import.yml @@ -0,0 +1,23 @@ +--- +XWas7vpy0HerhOYd: + id: XWas7vpy0HerhOYd + name: test_name + group: test_group + host: test_host + protocol: test_protocol + login: test_login + password: test_password + port: 42 + comment: test_comment + date: 1419858983 +D7URyJENLa91jt0b: + id: D7URyJENLa91jt0b + name: test_name_update + group: test_group_update + host: test_host_update + protocol: test_protocol_update + login: test_login_update + password: test_password_update + port: 43 + comment: test_comment_update + date: 1419858983 diff --git a/test/test_mpw.rb b/test/test_mpw.rb index 2208c6c..9c5b87f 100644 --- a/test/test_mpw.rb +++ b/test/test_mpw.rb @@ -26,6 +26,85 @@ class TestMPW < Test::Unit::TestCase assert(@mpw.decrypt) assert_equal(0, @mpw.search.length) end + + def test_import_yaml + import_file = 'test_import.yml' + + assert(@mpw.import(import_file, :yaml)) + assert_equal(2, @mpw.search.length) + + result = @mpw.search[0] + assert_equal(@fixtures['add']['name'], result['name']) + assert_equal(@fixtures['add']['group'], result['group']) + assert_equal(@fixtures['add']['host'], result['host']) + assert_equal(@fixtures['add']['protocol'], result['protocol']) + assert_equal(@fixtures['add']['login'], result['login']) + assert_equal(@fixtures['add']['password'], result['password']) + assert_equal(@fixtures['add']['port'].to_i, result['port']) + assert_equal(@fixtures['add']['comment'], result['comment']) + end + + def test_export_yaml + export_file = 'test_export.yml' + + assert(@mpw.import(@fixture_file)) + assert_equal(2, @mpw.search.length) + assert(@mpw.export(export_file, :yaml)) + export = YAML::load_file(export_file) + assert_equal(2, export.length) + + result = export.values[0] + assert_equal(@fixtures['add']['name'], result['name']) + assert_equal(@fixtures['add']['group'], result['group']) + assert_equal(@fixtures['add']['host'], result['host']) + assert_equal(@fixtures['add']['protocol'], result['protocol']) + assert_equal(@fixtures['add']['login'], result['login']) + assert_equal(@fixtures['add']['password'], result['password']) + assert_equal(@fixtures['add']['port'].to_i, result['port']) + assert_equal(@fixtures['add']['comment'], result['comment']) + + File.unlink(export_file) + end + + def test_import_csv + import_file = 'test_import.csv' + + assert(@mpw.import(import_file, :csv)) + assert_equal(2, @mpw.search.length) + + import = CSV.parse(File.read(import_file), headers: true) + + result = @mpw.search[0] + assert_equal(import[0]['name'], result['name']) + assert_equal(import[0]['group'], result['group']) + assert_equal(import[0]['host'], result['host']) + assert_equal(import[0]['protocol'], result['protocol']) + assert_equal(import[0]['login'], result['login']) + assert_equal(import[0]['password'], result['password']) + assert_equal(import[0]['port'].to_i, result['port']) + assert_equal(import[0]['comment'], result['comment']) + end + + def test_export_csv + export_file = 'test_export.csv' + assert(@mpw.import(@fixture_file)) + assert_equal(2, @mpw.search.length) + assert(@mpw.export(export_file, :csv)) + export = CSV.parse(File.read(export_file), headers: true) + assert_equal(2, export.length) + + result = export[0] + assert_equal(@fixtures['add']['name'], result['name']) + assert_equal(@fixtures['add']['group'], result['group']) + assert_equal(@fixtures['add']['host'], result['host']) + assert_equal(@fixtures['add']['protocol'], result['protocol']) + assert_equal(@fixtures['add']['login'], result['login']) + assert_equal(@fixtures['add']['password'], result['password']) + assert_equal(@fixtures['add']['port'], result['port']) + assert_equal(@fixtures['add']['comment'], result['comment']) + + File.unlink(export_file) + end def test_add assert(@mpw.update(@fixtures['add']['name'], @@ -75,19 +154,12 @@ class TestMPW < Test::Unit::TestCase assert_equal(0, @mpw.search.length) end - def test_update - assert(@mpw.update(@fixtures['add']['name'], - @fixtures['add']['group'], - @fixtures['add']['host'], - @fixtures['add']['protocol'], - @fixtures['add']['login'], - @fixtures['add']['password'], - @fixtures['add']['port'], - @fixtures['add']['comment'])) + def test_update_empty + assert(@mpw.import(@fixture_file, :yaml)) + assert_equal(2, @mpw.search.length) id = @mpw.search[0]['id'] - # Test empty update assert(@mpw.update('','', '','','','','', '', id)) result = @mpw.search_by_id(id) @@ -99,9 +171,14 @@ class TestMPW < Test::Unit::TestCase assert_equal(@fixtures['add']['password'], result['password']) assert_equal(@fixtures['add']['port'].to_i, result['port']) assert_equal(@fixtures['add']['comment'], result['comment']) + end + def test_update + assert(@mpw.import(@fixture_file, :yaml)) + assert_equal(2, @mpw.search.length) + + id = @mpw.search[0]['id'] - # Test real update assert(@mpw.update(@fixtures['update']['name'], @fixtures['update']['group'], @fixtures['update']['host'], @@ -112,7 +189,7 @@ class TestMPW < Test::Unit::TestCase @fixtures['update']['comment'], id)) - assert_equal(1, @mpw.search.length) + assert_equal(2, @mpw.search.length) result = @mpw.search_by_id(id) assert_equal(@fixtures['update']['name'], result['name']) @@ -124,75 +201,4 @@ class TestMPW < Test::Unit::TestCase assert_equal(@fixtures['update']['port'].to_i, result['port']) assert_equal(@fixtures['update']['comment'], result['comment']) end - - def test_import_yaml - assert(@mpw.import(@fixture_file, :yaml)) - assert_equal(2, @mpw.search.length) - - result = @mpw.search[0] - assert_equal(@fixtures['add']['name'], result['name']) - assert_equal(@fixtures['add']['group'], result['group']) - assert_equal(@fixtures['add']['host'], result['host']) - assert_equal(@fixtures['add']['protocol'], result['protocol']) - assert_equal(@fixtures['add']['login'], result['login']) - assert_equal(@fixtures['add']['password'], result['password']) - assert_equal(@fixtures['add']['port'].to_i, result['port']) - assert_equal(@fixtures['add']['comment'], result['comment']) - end - - def test_export_yaml - assert(@mpw.import(@fixture_file)) - assert_equal(2, @mpw.search.length) - assert(@mpw.export('export.yml', :yaml)) - export = YAML::load_file('export.yml') - assert_equal(2, export.length) - - result = export.values[0] - assert_equal(@fixtures['add']['name'], result['name']) - assert_equal(@fixtures['add']['group'], result['group']) - assert_equal(@fixtures['add']['host'], result['host']) - assert_equal(@fixtures['add']['protocol'], result['protocol']) - assert_equal(@fixtures['add']['login'], result['login']) - assert_equal(@fixtures['add']['password'], result['password']) - assert_equal(@fixtures['add']['port'].to_i, result['port']) - assert_equal(@fixtures['add']['comment'], result['comment']) - end - - def test_export_csv - assert(@mpw.import(@fixture_file)) - assert_equal(2, @mpw.search.length) - assert(@mpw.export('export.csv', :csv)) - export = CSV.parse(File.read('export.csv'), headers: true) - assert_equal(2, export.length) - - result = export[0] - assert_equal(@fixtures['add']['name'], result['name']) - assert_equal(@fixtures['add']['group'], result['group']) - assert_equal(@fixtures['add']['host'], result['host']) - assert_equal(@fixtures['add']['protocol'], result['protocol']) - assert_equal(@fixtures['add']['login'], result['login']) - assert_equal(@fixtures['add']['password'], result['password']) - assert_equal(@fixtures['add']['port'], result['port']) - assert_equal(@fixtures['add']['comment'], result['comment']) - - end - - def test_import_csv - assert(@mpw.import(@fixture_file)) - assert_equal(2, @mpw.search.length) - assert(@mpw.export('export.csv', :csv)) - assert(@mpw.import('export.csv', :csv)) - assert_equal(4, @mpw.search.length) - - result = @mpw.search[2] - assert_equal(@fixtures['add']['name'], result['name']) - assert_equal(@fixtures['add']['group'], result['group']) - assert_equal(@fixtures['add']['host'], result['host']) - assert_equal(@fixtures['add']['protocol'], result['protocol']) - assert_equal(@fixtures['add']['login'], result['login']) - assert_equal(@fixtures['add']['password'], result['password']) - assert_equal(@fixtures['add']['port'].to_i, result['port']) - assert_equal(@fixtures['add']['comment'], result['comment']) - - end end From e7c03269a606cbca2c66b93bafc21e62da9ae49c Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Mon, 29 Dec 2014 15:45:25 +0100 Subject: [PATCH 132/531] unittest: add remove tests --- test/test_mpw.rb | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/test/test_mpw.rb b/test/test_mpw.rb index 9c5b87f..46760db 100644 --- a/test/test_mpw.rb +++ b/test/test_mpw.rb @@ -1,4 +1,4 @@ -# File: tc_simple_number.rb +#!/usr/bin/ruby require_relative '../lib/MPW' require 'test/unit' @@ -201,4 +201,23 @@ class TestMPW < Test::Unit::TestCase assert_equal(@fixtures['update']['port'].to_i, result['port']) assert_equal(@fixtures['update']['comment'], result['comment']) end + + def test_remove + assert(@mpw.import(@fixture_file, :yaml)) + assert_equal(2, @mpw.search.length) + + id = @mpw.search[0]['id'] + assert(@mpw.remove(id)) + + assert_equal(1, @mpw.search.length) + end + + def test_remove_noexistent + assert(@mpw.import(@fixture_file, :yaml)) + assert_equal(2, @mpw.search.length) + + assert(!@mpw.remove('TEST_NOEXISTENT_ID')) + + assert_equal(2, @mpw.search.length) + end end From c04fa3af94eefadf95d0938ecfefcd9f41788a85 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Mon, 29 Dec 2014 22:32:36 +0100 Subject: [PATCH 133/531] fix indent --- lib/MPW.rb | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/MPW.rb b/lib/MPW.rb index 61d9661..ea9ac2f 100644 --- a/lib/MPW.rb +++ b/lib/MPW.rb @@ -176,12 +176,12 @@ module MPW def export(file, type=:yaml) case type when :csv - CSV.open(file, 'w', write_headers: true, - headers: ['name', 'group', 'protocol', 'host', 'login', 'password', 'port', 'comment']) do |csv| - @data.each do |id, r| - csv << [r['name'], r['group'], r['protocol'], r['host'], r['login'], r['password'], r['port'], r['comment']] - end + CSV.open(file, 'w', write_headers: true, + headers: ['name', 'group', 'protocol', 'host', 'login', 'password', 'port', 'comment']) do |csv| + @data.each do |id, r| + csv << [r['name'], r['group'], r['protocol'], r['host'], r['login'], r['password'], r['port'], r['comment']] end + end when :yaml File.open(file, 'w') {|f| f << @data.to_yaml} From cad292b3f95d1415fb999989aa1bdd27ced55245 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Tue, 30 Dec 2014 08:57:45 +0100 Subject: [PATCH 134/531] unittest: move files --- test/{ => files}/fixtures.yml | 0 test/{ => files}/test_import.csv | 0 test/{ => files}/test_import.yml | 0 test/test_mpw.rb | 6 +++--- 4 files changed, 3 insertions(+), 3 deletions(-) rename test/{ => files}/fixtures.yml (100%) rename test/{ => files}/test_import.csv (100%) rename test/{ => files}/test_import.yml (100%) diff --git a/test/fixtures.yml b/test/files/fixtures.yml similarity index 100% rename from test/fixtures.yml rename to test/files/fixtures.yml diff --git a/test/test_import.csv b/test/files/test_import.csv similarity index 100% rename from test/test_import.csv rename to test/files/test_import.csv diff --git a/test/test_import.yml b/test/files/test_import.yml similarity index 100% rename from test/test_import.yml rename to test/files/test_import.yml diff --git a/test/test_mpw.rb b/test/test_mpw.rb index 46760db..1874cb6 100644 --- a/test/test_mpw.rb +++ b/test/test_mpw.rb @@ -8,7 +8,7 @@ require 'csv' class TestMPW < Test::Unit::TestCase def setup - @fixture_file = 'fixtures.yml' + @fixture_file = 'files/fixtures.yml' file_gpg = 'test.gpg' key = 'test-mpw@test-mpw.local' @@ -28,7 +28,7 @@ class TestMPW < Test::Unit::TestCase end def test_import_yaml - import_file = 'test_import.yml' + import_file = 'files/test_import.yml' assert(@mpw.import(import_file, :yaml)) assert_equal(2, @mpw.search.length) @@ -67,7 +67,7 @@ class TestMPW < Test::Unit::TestCase end def test_import_csv - import_file = 'test_import.csv' + import_file = 'files/test_import.csv' assert(@mpw.import(import_file, :csv)) assert_equal(2, @mpw.search.length) From 087320e52b9b81b264f0998909307c7a6b7f3aac Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Tue, 30 Dec 2014 09:22:41 +0100 Subject: [PATCH 135/531] unittest: add encrypt tests --- test/test.cfg | 13 ---------- test/test_mpw.rb | 66 +++++++++++++++++++++++++++++++++++------------- 2 files changed, 49 insertions(+), 30 deletions(-) delete mode 100644 test/test.cfg diff --git a/test/test.cfg b/test/test.cfg deleted file mode 100644 index c0ace9e..0000000 --- a/test/test.cfg +++ /dev/null @@ -1,13 +0,0 @@ ---- -config: - key: test@test-mpw.org - share_keys: - lang: en - file_gpg: "test.gpg" - sync_type: mpw - sync_host: - sync_port: - sync_user: - sync_pwd: - sync_path: - last_update: diff --git a/test/test_mpw.rb b/test/test_mpw.rb index 1874cb6..9a9bbda 100644 --- a/test/test_mpw.rb +++ b/test/test_mpw.rb @@ -6,12 +6,13 @@ require 'yaml' require 'csv' class TestMPW < Test::Unit::TestCase - def setup @fixture_file = 'files/fixtures.yml' file_gpg = 'test.gpg' - key = 'test-mpw@test-mpw.local' + key = 'a.waksberg@yaegashi.fr' + + puts if defined?(I18n.enforce_available_locales) I18n.enforce_available_locales = false @@ -21,13 +22,8 @@ class TestMPW < Test::Unit::TestCase @mpw = MPW::MPW.new(file_gpg, key) @fixtures = YAML.load_file(@fixture_file) end - - def test_load_empty_file - assert(@mpw.decrypt) - assert_equal(0, @mpw.search.length) - end - def test_import_yaml + def test_01_import_yaml import_file = 'files/test_import.yml' assert(@mpw.import(import_file, :yaml)) @@ -44,7 +40,7 @@ class TestMPW < Test::Unit::TestCase assert_equal(@fixtures['add']['comment'], result['comment']) end - def test_export_yaml + def test_02_export_yaml export_file = 'test_export.yml' assert(@mpw.import(@fixture_file)) @@ -66,7 +62,7 @@ class TestMPW < Test::Unit::TestCase File.unlink(export_file) end - def test_import_csv + def test_03_import_csv import_file = 'files/test_import.csv' assert(@mpw.import(import_file, :csv)) @@ -85,7 +81,7 @@ class TestMPW < Test::Unit::TestCase assert_equal(import[0]['comment'], result['comment']) end - def test_export_csv + def test_04_export_csv export_file = 'test_export.csv' assert(@mpw.import(@fixture_file)) assert_equal(2, @mpw.search.length) @@ -106,7 +102,7 @@ class TestMPW < Test::Unit::TestCase File.unlink(export_file) end - def test_add + def test_05_add assert(@mpw.update(@fixtures['add']['name'], @fixtures['add']['group'], @fixtures['add']['host'], @@ -141,7 +137,7 @@ class TestMPW < Test::Unit::TestCase assert_equal(2, @mpw.search.length) end - def test_add_empty_name + def test_06_add_empty_name assert(!@mpw.update('', @fixtures['add']['group'], @fixtures['add']['host'], @@ -154,7 +150,7 @@ class TestMPW < Test::Unit::TestCase assert_equal(0, @mpw.search.length) end - def test_update_empty + def test_07_update_empty assert(@mpw.import(@fixture_file, :yaml)) assert_equal(2, @mpw.search.length) @@ -173,7 +169,7 @@ class TestMPW < Test::Unit::TestCase assert_equal(@fixtures['add']['comment'], result['comment']) end - def test_update + def test_08_update assert(@mpw.import(@fixture_file, :yaml)) assert_equal(2, @mpw.search.length) @@ -202,7 +198,7 @@ class TestMPW < Test::Unit::TestCase assert_equal(@fixtures['update']['comment'], result['comment']) end - def test_remove + def test_09_remove assert(@mpw.import(@fixture_file, :yaml)) assert_equal(2, @mpw.search.length) @@ -212,7 +208,7 @@ class TestMPW < Test::Unit::TestCase assert_equal(1, @mpw.search.length) end - def test_remove_noexistent + def test_10_remove_noexistent assert(@mpw.import(@fixture_file, :yaml)) assert_equal(2, @mpw.search.length) @@ -220,4 +216,40 @@ class TestMPW < Test::Unit::TestCase assert_equal(2, @mpw.search.length) end + + def test_11_encrypt_empty_file + assert(@mpw.encrypt) + end + + def test_12_encrypt + assert(@mpw.import(@fixture_file, :yaml)) + assert_equal(2, @mpw.search.length) + + assert(@mpw.encrypt) + end + + def test_13_decrypt_empty_file + assert(@mpw.decrypt) + assert_equal(0, @mpw.search.length) + end + + def test_14_decrypt + assert(@mpw.import(@fixture_file, :yaml)) + assert_equal(2, @mpw.search.length) + + assert(@mpw.encrypt) + + assert(@mpw.decrypt) + assert_equal(2, @mpw.search.length) + + result = @mpw.search[0] + assert_equal(@fixtures['add']['name'], result['name']) + assert_equal(@fixtures['add']['group'], result['group']) + assert_equal(@fixtures['add']['host'], result['host']) + assert_equal(@fixtures['add']['protocol'], result['protocol']) + assert_equal(@fixtures['add']['login'], result['login']) + assert_equal(@fixtures['add']['password'], result['password']) + assert_equal(@fixtures['add']['port'].to_i, result['port']) + assert_equal(@fixtures['add']['comment'], result['comment']) + end end From 04a4173f1609ba0a529ec5250fafccccbf7dabe2 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Tue, 30 Dec 2014 09:32:14 +0100 Subject: [PATCH 136/531] unittest: add env for key white a real key --- test/test_mpw.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_mpw.rb b/test/test_mpw.rb index 9a9bbda..a670e10 100644 --- a/test/test_mpw.rb +++ b/test/test_mpw.rb @@ -10,7 +10,7 @@ class TestMPW < Test::Unit::TestCase @fixture_file = 'files/fixtures.yml' file_gpg = 'test.gpg' - key = 'a.waksberg@yaegashi.fr' + key = ENV['MPW_TEST_KEY'] puts From 3ac63c0c8a4b764e04a10a59674d5b365bc4d661 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Tue, 30 Dec 2014 09:55:31 +0100 Subject: [PATCH 137/531] unittest: add firsts sync tests --- test/test_mpw.rb | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/test/test_mpw.rb b/test/test_mpw.rb index a670e10..b3ca25d 100644 --- a/test/test_mpw.rb +++ b/test/test_mpw.rb @@ -252,4 +252,37 @@ class TestMPW < Test::Unit::TestCase assert_equal(@fixtures['add']['port'].to_i, result['port']) assert_equal(@fixtures['add']['comment'], result['comment']) end + + def test_15_sync_local_empty + import_file = 'files/test_import.yml' + + data = [] + YAML.load_file(import_file).each_value { |v| data.push(v) } + + @mpw.sync(data, 0) + + result = @mpw.search[0] + assert_equal(@fixtures['add']['name'], result['name']) + assert_equal(@fixtures['add']['group'], result['group']) + assert_equal(@fixtures['add']['host'], result['host']) + assert_equal(@fixtures['add']['protocol'], result['protocol']) + assert_equal(@fixtures['add']['login'], result['login']) + assert_equal(@fixtures['add']['password'], result['password']) + assert_equal(@fixtures['add']['port'].to_i, result['port']) + assert_equal(@fixtures['add']['comment'], result['comment']) + + assert_equal(2, @mpw.search.length) + end + + def test_16_sync_remote_outdated_and_local_empty + import_file = 'files/test_import.yml' + + data = [] + YAML.load_file(import_file).each_value { |v| data.push(v) } + + @mpw.sync(data, Time.now.to_i) + + assert_equal(0, @mpw.search.length) + end + end From 4e4efb8979bdb6a8367eacbcaa3733aa0df4b4c7 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Wed, 31 Dec 2014 11:30:30 +0100 Subject: [PATCH 138/531] unittest: add sync empty data test --- test/test_mpw.rb | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/test/test_mpw.rb b/test/test_mpw.rb index b3ca25d..94bbfa3 100644 --- a/test/test_mpw.rb +++ b/test/test_mpw.rb @@ -280,9 +280,17 @@ class TestMPW < Test::Unit::TestCase data = [] YAML.load_file(import_file).each_value { |v| data.push(v) } - @mpw.sync(data, Time.now.to_i) + assert(@mpw.sync(data, Time.now.to_i)) assert_equal(0, @mpw.search.length) end + def test_17_sync_empty_data + assert(@mpw.import(@fixture_file, :yaml)) + assert_equal(2, @mpw.search.length) + + assert(@mpw.sync([], 0)) + + assert_equal(2, @mpw.search.length) + end end From 1eac4001d92836cb8df33cdb9505c00067edf269 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Wed, 31 Dec 2014 11:31:28 +0100 Subject: [PATCH 139/531] minor fix for the syntax --- lib/MPW.rb | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/lib/MPW.rb b/lib/MPW.rb index ea9ac2f..f6d58e9 100644 --- a/lib/MPW.rb +++ b/lib/MPW.rb @@ -77,7 +77,7 @@ module MPW search = search.downcase end - @data.each do |id, row| + @data.each_value do |row| name = row['name'].nil? ? nil : row['name'].downcase server = row['host'].nil? ? nil : row['host'].downcase comment = row['comment'].nil? ? nil : row['comment'].downcase @@ -93,11 +93,11 @@ module MPW end # Search in some csv data - # @args: id_search -> the id item + # @args: id -> the id item # @rtrn: a row with the resultat of the search - def search_by_id(id_search) - @data.each do |id, row| - return row if id == id_search + def search_by_id(id) + @data.each_value do |row| + return row if row['id'] == id end return [] @@ -158,8 +158,8 @@ module MPW # @args: id -> the item's identifiant # @rtrn: true if the item has been deleted def remove(id) - @data.each do |k, row| - if k == id + @data.each_value do |row| + if row['id'] == id @data.delete(id) return true end @@ -211,7 +211,7 @@ module MPW end when :yaml - YAML::load_file(file).each do |k, row| + YAML::load_file(file).each_value do |row| if not update(row['name'], row['group'], row['host'], row['protocol'], row['login'], row['password'], row['port'], row['comment']) return false end @@ -262,7 +262,7 @@ module MPW @error_msg = I18n.t('error.sync.array') return false else not data_remote.to_s.empty? - @data.each do |lk, l| + @data.each_value do |l| j = 0 update = false From 40291632eb4812cc663cf78a5b157444de63c02b Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Fri, 16 Jan 2015 23:11:10 +0100 Subject: [PATCH 140/531] remove alternative format --- lib/UI/Cli.rb | 28 ++++------------------------ 1 file changed, 4 insertions(+), 24 deletions(-) diff --git a/lib/UI/Cli.rb b/lib/UI/Cli.rb index af8719f..40938b6 100644 --- a/lib/UI/Cli.rb +++ b/lib/UI/Cli.rb @@ -171,11 +171,7 @@ class Cli if not result.empty? result.each do |r| - if format.nil? || !format - displayFormat(r) - else - displayFormatAlt(r) - end + display_item(r) end else puts I18n.t('display.nothing') @@ -184,7 +180,7 @@ class Cli # Display an item in the default format # @args: item -> an array with the item information - def displayFormat(item) + def diplay_item(item) puts '--------------------' puts "Id: #{item['id']}" puts "#{I18n.t('display.name')}: #{item['name']}" @@ -197,22 +193,6 @@ class Cli puts "#{I18n.t('display.comment')}: #{item['comment']}" end - # Display an item in the alternative format - # @args: item -> an array with the item information - def displayFormatAlt(item) - port = item[:port].nil? ? '' : ":#{item[:port]}" - - if item[:password].nil? or item[:password].empty? - if item[:login].include('@') - puts "# #{item[:id]} #{item[:protocol]}://#{item[:login]}@#{item[:host]}#{port}" - else - puts "# #{item[:id]} #{item[:protocol]}://{#{item[:login]}}@#{item[:host]}#{port}" - end - else - puts "# #{item[:id]} #{item[:protocol]}://{#{item[:login]}:#{item[:password]}}@#{item[:host]}#{port}" - end - end - # Form to add a new item def add row = [] @@ -279,7 +259,7 @@ class Cli result = @mpw.search_by_id(id) if result.length > 0 - displayFormat(result) + display_item(result) confirm = ask("#{I18n.t('form.delete.ask', id: id)} (y/N) ").to_s if confirm =~ /^(y|yes|YES|Yes|Y)$/ @@ -324,7 +304,7 @@ class Cli result = @mpw.import_preview(file, type) if result.is_a?(Array) and not result.empty? result.each do |r| - displayFormat(r) + display_item(r) end confirm = ask("#{I18n.t('form.import.ask', file: file)} (y/N) ").to_s From f5b98de4c1d678224f1e2e1f42ce3879e9a072c6 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sat, 17 Jan 2015 00:05:40 +0100 Subject: [PATCH 141/531] add select form when multiple result --- i18n/cli/en.yml | 5 +++++ i18n/cli/fr.yml | 5 +++++ lib/Sync/MPWSync.rb | 2 +- lib/UI/Cli.rb | 33 +++++++++++++++++++++++++-------- mpw | 2 +- 5 files changed, 37 insertions(+), 10 deletions(-) diff --git a/i18n/cli/en.yml b/i18n/cli/en.yml index 646671c..b8c1bd7 100644 --- a/i18n/cli/en.yml +++ b/i18n/cli/en.yml @@ -31,6 +31,9 @@ en: upload: "Can't upload the file on the server!" unknown: "An unknown error is occured!" + warning: + select: 'Your choice is not a valid element!' + option: usage: "Usage" show: "Search and show the items" @@ -51,6 +54,7 @@ en: help: "Show this help message" form: + select: "Select the item: " add: title: "Add a new item" name: "Enter the name: " @@ -122,6 +126,7 @@ en: port: "Port" protocol: "Protocol" server: "Server" + warning: "Warning" ssh: option: diff --git a/i18n/cli/fr.yml b/i18n/cli/fr.yml index 18f78af..ea9b9f0 100644 --- a/i18n/cli/fr.yml +++ b/i18n/cli/fr.yml @@ -31,6 +31,9 @@ fr: upload: "Impossible d'envoyer le fichier sur le serveur!" unknown: "Une erreur inconnue est survenue!" + warning: + select: "Votre choix n'est pas un élément valide!" + option: usage: "Utilisation" show: "Recherche et affiche les éléments" @@ -51,6 +54,7 @@ fr: help: "Affiche ce message d'aide" form: + select: "Sélectionner l'élément: " add: title: "Ajout d'un nouvel élément" name: "Entrez le nom: " @@ -122,6 +126,7 @@ fr: port: "Port" protocol: "Protocol" server: "Serveur" + warning: "Warning" ssh: option: diff --git a/lib/Sync/MPWSync.rb b/lib/Sync/MPWSync.rb index ae0c466..df8066f 100644 --- a/lib/Sync/MPWSync.rb +++ b/lib/Sync/MPWSync.rb @@ -90,7 +90,7 @@ module MPW file << msg['data'] end - mpw = MPW.new(tmp_file) + mpw = MPW.new(tmp_file, @gpg_key) if not mpw.decrypt(gpg_password) @error_msg = mpw.error_msg return nil diff --git a/lib/UI/Cli.rb b/lib/UI/Cli.rb index 40938b6..b1b4cda 100644 --- a/lib/UI/Cli.rb +++ b/lib/UI/Cli.rb @@ -39,7 +39,7 @@ class Cli return false end end - + if not @config.sync_host.nil? and not @config.sync_port.nil? if not @sync.connect(@config.sync_host, @config.sync_user, @config.sync_pwd, @config.sync_path, @config.sync_port) puts "#{I18n.t('display.error')} #1: #{@sync.error_msg}".red @@ -166,21 +166,37 @@ class Cli # Display the query's result # @args: search -> the string to search # protocol -> search from a particular protocol - def display(search, protocol=nil, group=nil, format=nil) + def display(search, protocol=nil, group=nil) result = @mpw.search(search, group, protocol) - if not result.empty? - result.each do |r| - display_item(r) - end - else + case result.length + when 0 puts I18n.t('display.nothing') + when 1 + display_item(result.first) + else + i = 1 + result.each do |r| + print "#{i}: ".cyan + print r['name'] + print " -> #{r['comment']}".magenta if not r['comment'].to_s.empty? + print "\n" + + i += 1 + end + choice = ask(I18n.t('form.select')).to_i + + if choice >= 1 and choice < i + display_item(result[choice-1]) + else + puts "#{I18n.t('display.warning')}: #{I18n.t('warning.select')}".yellow + end end end # Display an item in the default format # @args: item -> an array with the item information - def diplay_item(item) + def display_item(item) puts '--------------------' puts "Id: #{item['id']}" puts "#{I18n.t('display.name')}: #{item['name']}" @@ -193,6 +209,7 @@ class Cli puts "#{I18n.t('display.comment')}: #{item['comment']}" end + # Form to add a new item def add row = [] diff --git a/mpw b/mpw index 0e2a171..d18eaf5 100755 --- a/mpw +++ b/mpw @@ -133,7 +133,7 @@ cli.sync # Display the item's informations if not options[:display].nil? - cli.display(options[:display], options[:group], options[:type], options[:format]) + cli.display(options[:display], options[:group], options[:type]) # Remove an item elsif not options[:remove].nil? From 298a020e351e952ef94eb4be71ec57b60c5a5c39 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sat, 17 Jan 2015 00:12:01 +0100 Subject: [PATCH 142/531] add color when display an item --- lib/UI/Cli.rb | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/lib/UI/Cli.rb b/lib/UI/Cli.rb index b1b4cda..95f6f5f 100644 --- a/lib/UI/Cli.rb +++ b/lib/UI/Cli.rb @@ -197,19 +197,27 @@ class Cli # Display an item in the default format # @args: item -> an array with the item information def display_item(item) - puts '--------------------' - puts "Id: #{item['id']}" - puts "#{I18n.t('display.name')}: #{item['name']}" - puts "#{I18n.t('display.group')}: #{item['group']}" - puts "#{I18n.t('display.server')}: #{item['host']}" - puts "#{I18n.t('display.protocol')}: #{item['protocol']}" - puts "#{I18n.t('display.login')}: #{item['login']}" - puts "#{I18n.t('display.password')}: #{item['password']}" - puts "#{I18n.t('display.port')}: #{item['port']}" - puts "#{I18n.t('display.comment')}: #{item['comment']}" + puts '--------------------'.cyan + print 'Id: '.cyan + puts item['id'] + print "#{I18n.t('display.name')}: ".cyan + puts item['name'] + print "#{I18n.t('display.group')}: ".cyan + puts item['group'] + print "#{I18n.t('display.server')}: ".cyan + puts item['host'] + print "#{I18n.t('display.protocol')}: ".cyan + puts item['protocol'] + print "#{I18n.t('display.login')}: ".cyan + puts item['login'] + print "#{I18n.t('display.password')}: ".cyan + puts item['password'] + print "#{I18n.t('display.port')}: ".cyan + puts item['port'] + print "#{I18n.t('display.comment')}: ".cyan + puts item['comment'] end - # Form to add a new item def add row = [] From a49c975f19331f7462fa3c4199440f2f30ca9783 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sat, 17 Jan 2015 12:01:37 +0100 Subject: [PATCH 143/531] fix sync ftp and ssh --- lib/Sync/FTP.rb | 4 ++-- lib/Sync/MPWSync.rb | 4 ++-- lib/Sync/SSH.rb | 4 ++-- lib/UI/Cli.rb | 6 +++++- 4 files changed, 11 insertions(+), 7 deletions(-) diff --git a/lib/Sync/FTP.rb b/lib/Sync/FTP.rb index 4b6ba33..1bb2a55 100644 --- a/lib/Sync/FTP.rb +++ b/lib/Sync/FTP.rb @@ -50,7 +50,7 @@ module MPW # Get data on server # @args: gpg_password -> the gpg password # @rtrn: nil if nothing data or error - def get(gpg_password) + def get(gpg_key, gpg_password) return nil if not @enable tmp_file = tmpfile @@ -59,7 +59,7 @@ module MPW ftp.gettextfile(@path, tmp_file) end - mpw = MPW.new(tmp_file) + mpw = MPW.new(tmp_file, gpg_key) if not mpw.decrypt(gpg_password) @error_msg = mpw.error_msg return nil diff --git a/lib/Sync/MPWSync.rb b/lib/Sync/MPWSync.rb index df8066f..9bb6572 100644 --- a/lib/Sync/MPWSync.rb +++ b/lib/Sync/MPWSync.rb @@ -61,7 +61,7 @@ module MPW # Get data on server # @args: gpg_password -> the gpg password # @rtrn: nil if nothing data or error - def get(gpg_password) + def get(gpg_key, gpg_password) return nil if not @enable msg = nil @@ -90,7 +90,7 @@ module MPW file << msg['data'] end - mpw = MPW.new(tmp_file, @gpg_key) + mpw = MPW.new(tmp_file, gpg_key) if not mpw.decrypt(gpg_password) @error_msg = mpw.error_msg return nil diff --git a/lib/Sync/SSH.rb b/lib/Sync/SSH.rb index d1f3801..9ebca2d 100644 --- a/lib/Sync/SSH.rb +++ b/lib/Sync/SSH.rb @@ -50,7 +50,7 @@ module MPW # Get data on server # @args: gpg_password -> the gpg password # @rtrn: nil if nothing data or error - def get(gpg_password) + def get(gpg_key, gpg_password) return nil if not @enable tmp_file = tmpfile @@ -58,7 +58,7 @@ module MPW scp.download!(@path, tmp_file) end - mpw = MPW.new(tmp_file) + mpw = MPW.new(tmp_file, gpg_key) if not mpw.decrypt(gpg_password) @error_msg = mpw.error_msg return nil diff --git a/lib/UI/Cli.rb b/lib/UI/Cli.rb index 95f6f5f..2dc3bd7 100644 --- a/lib/UI/Cli.rb +++ b/lib/UI/Cli.rb @@ -47,15 +47,19 @@ class Cli end if @sync.enable - if not @mpw.sync(@sync.get(@passwd), @config.last_update) + if not @mpw.sync(@sync.get(@config.key, @passwd), @config.last_update) puts "#{I18n.t('display.error')} #2: #{@mpw.error_msg}".red if not @mpw.error_msg.nil? puts "#{I18n.t('display.error')} #3: #{@sync.error_msg}".red if not @sync.error_msg.nil? + elsif not @sync.update(File.open(@config.file_gpg).read) puts "#{I18n.t('display.error')} #4: #{@sync.error_msg}".red + elsif not @config.set_last_update puts "#{I18n.t('display.error')} #5: #{@config.error_msg}".red + elsif not @mpw.encrypt puts "#{I18n.t('display.error')} #6: #{@mpw.error_msg}".red + else return true end From 271138ae809214f227c44b6ea22dcc927d42df4c Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <adrien.waksberg@believedigital.com> Date: Tue, 27 Jan 2015 09:37:53 +0100 Subject: [PATCH 144/531] fix bug' --- lib/UI/Cli.rb | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/UI/Cli.rb b/lib/UI/Cli.rb index 2dc3bd7..2142b65 100644 --- a/lib/UI/Cli.rb +++ b/lib/UI/Cli.rb @@ -256,14 +256,14 @@ class Cli if not row.empty? puts I18n.t('form.update.title') puts '--------------------' - name = ask(I18n.t('form.update.name' , name: row[:name])).to_s - group = ask(I18n.t('form.update.group' , group: row[:group])).to_s - server = ask(I18n.t('form.update.server' , server: row[:host])).to_s - protocol = ask(I18n.t('form.update.protocol', protocol: row[:protocol])).to_s - login = ask(I18n.t('form.update.login' , login: row[:login])).to_s + name = ask(I18n.t('form.update.name' , name: row['name'])).to_s + group = ask(I18n.t('form.update.group' , group: row['group'])).to_s + server = ask(I18n.t('form.update.server' , server: row['host'])).to_s + protocol = ask(I18n.t('form.update.protocol', protocol: row['protocol'])).to_s + login = ask(I18n.t('form.update.login' , login: row['login'])).to_s passwd = ask(I18n.t('form.update.password')).to_s - port = ask(I18n.t('form.update.port' , port: row[:port])).to_s - comment = ask(I18n.t('form.update.comment' , comment: row[:comment])).to_s + port = ask(I18n.t('form.update.port' , port: row['port'])).to_s + comment = ask(I18n.t('form.update.comment' , comment: row['comment'])).to_s if @mpw.update(name, group, server, protocol, login, passwd, port, comment, id) if @mpw.encrypt From 7e546b65d27c30eca4efde416cae2ee18850d089 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Tue, 27 Jan 2015 23:17:16 +0100 Subject: [PATCH 145/531] unstable: new class item --- lib/Item.rb | 80 ++++++++++++++++++++++++++++++++++++++++ lib/MPW.rb | 103 +++++++++++++++++----------------------------------- 2 files changed, 113 insertions(+), 70 deletions(-) create mode 100644 lib/Item.rb diff --git a/lib/Item.rb b/lib/Item.rb new file mode 100644 index 0000000..df36916 --- /dev/null +++ b/lib/Item.rb @@ -0,0 +1,80 @@ +#!/usr/bin/ruby +# author: nishiki +# mail: nishiki@yaegashi.fr +# info: a simple script who manage your passwords + +require 'rubygems' +require 'i18n' + +module MPW + class Item + + attr_accessor :error_msg + + attr_accessor :id + attr_accessor :name + attr_accessor :group + attr_accessor :host + attr_accessor :protocol + attr_accessor :user + attr_accessor :password + attr_accessor :port + attr_accessor :comment + attr_accessor :last_edit + attr_accessor :created + + def initialize(options={}) + if not defined?(options[:id]) or not options[:id].to_s.empty? or + not defined?(options[:created]) or not options[:created].to_s.empty? + @id = generate_id + @created = Time.now.to_i + else + @id = options[:id] + @created = options[:created] + end + + update(options) + end + + def update(options={}) + if defined?(options[:name]) and options[:name].to_s.empty? + @error_msg = I18n.t('error.update.name_empty') + return false + end + + @name = options[:name] if defined?(options[:name]) + @group = options[:group] if defined?(options[:group]) + @host = options[:host] if defined?(options[:host]) + @protocol = options[:protocol] if defined?(options[:protocol]) + @user = options[:user] if defined?(options[:user]) + @password = options[:password] if defined?(options[:password]) + @port = options[:port].to_i if defined?(options[:port]) + @comment = options[:comment] if defined?(options[:comment]) + @last_edit = Time.now.to_i + + return true + end + + def empty? + return @name.to_s.empty? + end + + def nil? + return false + end + + private + def set_name(name) + if name.to_s.empty? + return false + + @name = name + return true + end + + private + def generate_id + return ([*('A'..'Z'),*('a'..'z'),*('0'..'9')]).sample(16).join + end + end +end diff --git a/lib/MPW.rb b/lib/MPW.rb index f6d58e9..11dc5fe 100644 --- a/lib/MPW.rb +++ b/lib/MPW.rb @@ -9,6 +9,7 @@ require 'csv' require 'i18n' require 'fileutils' require 'yaml' +require "#{APP_ROOT}/lib/Item" module MPW class MPW @@ -21,17 +22,31 @@ module MPW @file_gpg = file_gpg @key = key @share_keys = share_keys - @data = {} + @data = [] end # Decrypt a gpg file # @args: password -> the GPG key password # @rtrn: true if data has been decrypted - def decrypt(passwd=nil) + def decrypt(password=nil) if File.exist?(@file_gpg) - crypto = GPGME::Crypto.new(armor: true) - data_decrypt = crypto.decrypt(IO.read(@file_gpg), password: passwd).read.force_encoding('utf-8') - @data = YAML.load(data_decrypt) if not data_decrypt.to_s.empty? + crypto = GPGME::Crypto.new(armor: true) + data_decrypt = crypto.decrypt(IO.read(@file_gpg), password: password).read.force_encoding('utf-8') + if not data_decrypt.to_s.empty? + YAML.load(data_decrypt).each do |d| + @data.push(MPW::Item.new(id: d['id'], + name: d['name'], + group: d['group'], + host: d['host'], + protocol: d['protocol'], + user: d['login'], + password: d['password'], + port: d['port'], + comment: d['comment'], + last_edit: d['last_edit'], + created: d['created'], + ) + end end return true @@ -70,21 +85,20 @@ module MPW # @args: search -> the string to search # protocol -> the connection protocol (ssh, web, other) # @rtrn: a list with the resultat of the search - def search(search='', group=nil, protocol=nil) + def list(options={}) result = [] - if not search.nil? - search = search.downcase - end + search = defined?(options[:search]) ? options[:search].downcase : '' - @data.each_value do |row| - name = row['name'].nil? ? nil : row['name'].downcase - server = row['host'].nil? ? nil : row['host'].downcase - comment = row['comment'].nil? ? nil : row['comment'].downcase + @data.each do |item| + name = item.name.nil? ? nil : item.name.downcase + host = item.host.nil? ? nil : item.host.downcase + comment = item.comment.nil? ? nil : item.comment.downcase - if name =~ /^.*#{search}.*$/ or server =~ /^.*#{search}.*$/ or comment =~ /^.*#{search}.*$/ - if (protocol.nil? or protocol.eql?(row[:protocol])) and (group.nil? or group.eql?(row[:group])) - result.push(row) + if name =~ /^.*#{search}.*$/ or host =~ /^.*#{search}.*$/ or comment =~ /^.*#{search}.*$/ + if (not defined?(options[:protocol] or options[:protocol].eql?(item.protocol)) and + (group.nil? or options[:group].eql?(item.group)) + result.push(item) end end end @@ -96,62 +110,11 @@ module MPW # @args: id -> the id item # @rtrn: a row with the resultat of the search def search_by_id(id) - @data.each_value do |row| - return row if row['id'] == id + @data.each do |item| + return item if item.id == id end - return [] - end - - # Update an item - # @args: id -> the item's identifiant - # name -> the item name - # group -> the item group - # server -> the ip or hostname - # protocol -> the protocol - # login -> the login - # passwd -> the password - # port -> the port - # comment -> a comment - # @rtrn: true if the item has been updated - def update(name, group, server, protocol, login, passwd, port, comment, id=nil) - row = {} - update = false - - i = 0 - if @data.instance_of?(Hash) and @data.has_key?(id) - row = @data[id] - end - - if port.to_i <= 0 - port = nil - end - - row_update = {} - row_update['id'] = id.to_s.empty? ? MPW.password(16) : id - row_update['name'] = name.to_s.empty? ? row['name'] : name - row_update['group'] = group.to_s.empty? ? row['group'] : group - row_update['host'] = server.to_s.empty? ? row['host'] : server - row_update['protocol'] = protocol.to_s.empty? ? row['protocol'] : protocol - row_update['login'] = login.to_s.empty? ? row['login'] : login - row_update['password'] = passwd.to_s.empty? ? row['password'] : passwd - row_update['port'] = port.to_s.empty? ? row['port'] : port.to_i - row_update['comment'] = comment.to_s.empty? ? row['comment'] : comment - row_update['date'] = Time.now.to_i - - if row_update['name'].to_s.empty? - @error_msg = I18n.t('error.update.name_empty') - return false - end - - if update - @data[id] = row_update - else - id = row_update['id'] - @data[id] = row_update - end - - return true + return nil end # Remove an item From 16fd5d6c24a68ee87b6c5c12df9fff1f75c019d5 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Wed, 28 Jan 2015 23:08:25 +0100 Subject: [PATCH 146/531] unstable: work in progress to Item class --- lib/Item.rb | 1 + lib/MPW.rb | 96 ++++++++++++++++++++++++++++++--------------------- lib/UI/Cli.rb | 42 +++++++++++----------- 3 files changed, 79 insertions(+), 60 deletions(-) diff --git a/lib/Item.rb b/lib/Item.rb index df36916..b6964be 100644 --- a/lib/Item.rb +++ b/lib/Item.rb @@ -67,6 +67,7 @@ module MPW def set_name(name) if name.to_s.empty? return false + end @name = name return true diff --git a/lib/MPW.rb b/lib/MPW.rb index 11dc5fe..875a8e4 100644 --- a/lib/MPW.rb +++ b/lib/MPW.rb @@ -33,20 +33,22 @@ module MPW crypto = GPGME::Crypto.new(armor: true) data_decrypt = crypto.decrypt(IO.read(@file_gpg), password: password).read.force_encoding('utf-8') if not data_decrypt.to_s.empty? - YAML.load(data_decrypt).each do |d| - @data.push(MPW::Item.new(id: d['id'], - name: d['name'], - group: d['group'], - host: d['host'], - protocol: d['protocol'], - user: d['login'], - password: d['password'], - port: d['port'], - comment: d['comment'], - last_edit: d['last_edit'], - created: d['created'], - ) + YAML.load(data_decrypt).each_value do |d| + @data.push(Item.new(id: d['id'], + name: d['name'], + group: d['group'], + host: d['host'], + protocol: d['protocol'], + user: d['login'], + password: d['password'], + port: d['port'], + comment: d['comment'], + last_edit: d['last_edit'], + created: d['created'], + ) + ) end + end end return true @@ -60,7 +62,21 @@ module MPW def encrypt FileUtils.cp(@file_gpg, "#{@file_gpg}.bk") if File.exist?(@file_gpg) - data_to_encrypt = @data.to_yaml + data_to_encrypt = {} + @data.each do |item| + data_to_encrypt.merge!({'id' => item.id, + 'name' => item.name, + 'group' => item.group, + 'host' => item.host, + 'protocol' => item.protocol, + 'user' => item.user, + 'password' => item.password, + 'port' => item.port, + 'comment' => item.comment, + 'last_edit' => item.last_edit, + 'created' => item.created, + }) + end recipients = [] recipients.push(@key) @@ -70,7 +86,7 @@ module MPW crypto = GPGME::Crypto.new(armor: true) file_gpg = File.open(@file_gpg, 'w+') - crypto.encrypt(data_to_encrypt, recipients: recipients, output: file_gpg) + crypto.encrypt(data_to_encrypt.to_yaml, recipients: recipients, output: file_gpg) file_gpg.close FileUtils.rm("#{@file_gpg}.bk") if File.exist?("#{@file_gpg}.bk") @@ -88,7 +104,11 @@ module MPW def list(options={}) result = [] - search = defined?(options[:search]) ? options[:search].downcase : '' + if not defined?(options[:search]) or options[:search].nil? + search = '' + else + search = options[:search].downcase + end @data.each do |item| name = item.name.nil? ? nil : item.name.downcase @@ -96,10 +116,7 @@ module MPW comment = item.comment.nil? ? nil : item.comment.downcase if name =~ /^.*#{search}.*$/ or host =~ /^.*#{search}.*$/ or comment =~ /^.*#{search}.*$/ - if (not defined?(options[:protocol] or options[:protocol].eql?(item.protocol)) and - (group.nil? or options[:group].eql?(item.group)) - result.push(item) - end + result.push(item) end end @@ -117,21 +134,6 @@ module MPW return nil end - # Remove an item - # @args: id -> the item's identifiant - # @rtrn: true if the item has been deleted - def remove(id) - @data.each_value do |row| - if row['id'] == id - @data.delete(id) - return true - end - end - - @error_msg = I18n.t('error.delete.id_no_exist', id: id) - return false - end - # Export to csv # @args: file -> file where you export the data # type -> udata type @@ -140,14 +142,30 @@ module MPW case type when :csv CSV.open(file, 'w', write_headers: true, - headers: ['name', 'group', 'protocol', 'host', 'login', 'password', 'port', 'comment']) do |csv| - @data.each do |id, r| - csv << [r['name'], r['group'], r['protocol'], r['host'], r['login'], r['password'], r['port'], r['comment']] + headers: ['name', 'group', 'protocol', 'host', 'user', 'password', 'port', 'comment']) do |csv| + @data.each do |item| + csv << [item.id, item.group, item.protocol, item.host, item.user, item.password, item.port, item.comment] end end when :yaml - File.open(file, 'w') {|f| f << @data.to_yaml} + data = {} + @data.each do |item| + data.merge!({'id' => item.id, + 'name' => item.name, + 'group' => item.group, + 'host' => item.host, + 'protocol' => item.protocol, + 'user' => item.user, + 'password' => item.password, + 'port' => item.port, + 'comment' => item.comment, + 'last_edit' => item.last_edit, + 'created' => item.created, + }) + end + + File.open(file, 'w') {|f| f << data.to_yaml} else @error_msg = "#{I18n.t('error.export.unknown_type', type: type)}" diff --git a/lib/UI/Cli.rb b/lib/UI/Cli.rb index 2142b65..6a3e8ff 100644 --- a/lib/UI/Cli.rb +++ b/lib/UI/Cli.rb @@ -171,7 +171,7 @@ class Cli # @args: search -> the string to search # protocol -> search from a particular protocol def display(search, protocol=nil, group=nil) - result = @mpw.search(search, group, protocol) + result = @mpw.list(search: search) case result.length when 0 @@ -180,10 +180,10 @@ class Cli display_item(result.first) else i = 1 - result.each do |r| + result.each do |item| print "#{i}: ".cyan - print r['name'] - print " -> #{r['comment']}".magenta if not r['comment'].to_s.empty? + print item.name + print " -> #{item.comment}".magenta if not item.comment.to_s.empty? print "\n" i += 1 @@ -203,23 +203,23 @@ class Cli def display_item(item) puts '--------------------'.cyan print 'Id: '.cyan - puts item['id'] + puts item.id print "#{I18n.t('display.name')}: ".cyan - puts item['name'] + puts item.name print "#{I18n.t('display.group')}: ".cyan - puts item['group'] + puts item.group print "#{I18n.t('display.server')}: ".cyan - puts item['host'] + puts item.host print "#{I18n.t('display.protocol')}: ".cyan - puts item['protocol'] + puts item.protocol print "#{I18n.t('display.login')}: ".cyan - puts item['login'] + puts item.user print "#{I18n.t('display.password')}: ".cyan - puts item['password'] + puts item.password print "#{I18n.t('display.port')}: ".cyan - puts item['port'] + puts item.port print "#{I18n.t('display.comment')}: ".cyan - puts item['comment'] + puts item.comment end # Form to add a new item @@ -251,19 +251,19 @@ class Cli # Update an item # @args: id -> the item's id def update(id) - row = @mpw.search_by_id(id) + item = @mpw.search_by_id(id) if not row.empty? puts I18n.t('form.update.title') puts '--------------------' - name = ask(I18n.t('form.update.name' , name: row['name'])).to_s - group = ask(I18n.t('form.update.group' , group: row['group'])).to_s - server = ask(I18n.t('form.update.server' , server: row['host'])).to_s - protocol = ask(I18n.t('form.update.protocol', protocol: row['protocol'])).to_s - login = ask(I18n.t('form.update.login' , login: row['login'])).to_s + name = ask(I18n.t('form.update.name' , name: item.name)).to_s + group = ask(I18n.t('form.update.group' , group: item.group)).to_s + server = ask(I18n.t('form.update.server' , server: item.host)).to_s + protocol = ask(I18n.t('form.update.protocol', protocol: item.protocol)).to_s + login = ask(I18n.t('form.update.login' , login: item.user)).to_s passwd = ask(I18n.t('form.update.password')).to_s - port = ask(I18n.t('form.update.port' , port: row['port'])).to_s - comment = ask(I18n.t('form.update.comment' , comment: row['comment'])).to_s + port = ask(I18n.t('form.update.port' , port: item.port)).to_s + comment = ask(I18n.t('form.update.comment' , comment: item.comment)).to_s if @mpw.update(name, group, server, protocol, login, passwd, port, comment, id) if @mpw.encrypt From 7f7d8c862d0c39acbe4978469a3e7732679a55b1 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Thu, 29 Jan 2015 21:48:56 +0100 Subject: [PATCH 147/531] fix bug encrypt + export yaml --- lib/MPW.rb | 53 +++++++++++++++++++++++++++++------------------------ mpw | 2 +- 2 files changed, 30 insertions(+), 25 deletions(-) diff --git a/lib/MPW.rb b/lib/MPW.rb index 875a8e4..e8fc983 100644 --- a/lib/MPW.rb +++ b/lib/MPW.rb @@ -32,6 +32,7 @@ module MPW if File.exist?(@file_gpg) crypto = GPGME::Crypto.new(armor: true) data_decrypt = crypto.decrypt(IO.read(@file_gpg), password: password).read.force_encoding('utf-8') + if not data_decrypt.to_s.empty? YAML.load(data_decrypt).each_value do |d| @data.push(Item.new(id: d['id'], @@ -64,18 +65,21 @@ module MPW data_to_encrypt = {} @data.each do |item| - data_to_encrypt.merge!({'id' => item.id, - 'name' => item.name, - 'group' => item.group, - 'host' => item.host, - 'protocol' => item.protocol, - 'user' => item.user, - 'password' => item.password, - 'port' => item.port, - 'comment' => item.comment, - 'last_edit' => item.last_edit, - 'created' => item.created, - }) + next if item.empty? + + data_to_encrypt.merge!(item.id => {'id' => item.id, + 'name' => item.name, + 'group' => item.group, + 'host' => item.host, + 'protocol' => item.protocol, + 'user' => item.user, + 'password' => item.password, + 'port' => item.port, + 'comment' => item.comment, + 'last_edit' => item.last_edit, + 'created' => item.created, + } + ) end recipients = [] @@ -151,18 +155,19 @@ module MPW when :yaml data = {} @data.each do |item| - data.merge!({'id' => item.id, - 'name' => item.name, - 'group' => item.group, - 'host' => item.host, - 'protocol' => item.protocol, - 'user' => item.user, - 'password' => item.password, - 'port' => item.port, - 'comment' => item.comment, - 'last_edit' => item.last_edit, - 'created' => item.created, - }) + data.merge!(item.id => {'id' => item.id, + 'name' => item.name, + 'group' => item.group, + 'host' => item.host, + 'protocol' => item.protocol, + 'user' => item.user, + 'password' => item.password, + 'port' => item.port, + 'comment' => item.comment, + 'last_edit' => item.last_edit, + 'created' => item.created, + } + ) end File.open(file, 'w') {|f| f << data.to_yaml} diff --git a/mpw b/mpw index d18eaf5..c1791e2 100755 --- a/mpw +++ b/mpw @@ -82,7 +82,7 @@ OptionParser.new do |opts| opts.on('-e', '--export FILE', I18n.t('option.export')) do |file| options[:export] = file - options[:type] = :csv + options[:type] = :yaml end opts.on('-t', '--type TYPE', I18n.t('option.type')) do |type| From 25a84556582da7d5b914e1da1f5cd05dcf3f7d18 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Thu, 29 Jan 2015 22:09:42 +0100 Subject: [PATCH 148/531] fix import --- lib/MPW.rb | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/lib/MPW.rb b/lib/MPW.rb index e8fc983..c90bcd3 100644 --- a/lib/MPW.rb +++ b/lib/MPW.rb @@ -191,16 +191,36 @@ module MPW case type when :csv CSV.foreach(file, {headers: true}) do |row| - if not update(row['name'], row['group'], row['host'], row['protocol'], row['login'], row['password'], row['port'], row['comment']) - return false - end + item = Item.new(name: row['name'], + group: row['group'], + host: row['host'], + protocol: row['protocol'], + login: row['login'], + password: row['password'], + port: row['port'], + comment: row['comment'], + ) + + return false if item.empty? + + @data.push(item) end when :yaml YAML::load_file(file).each_value do |row| - if not update(row['name'], row['group'], row['host'], row['protocol'], row['login'], row['password'], row['port'], row['comment']) - return false - end + item = Item.new(name: row['name'], + group: row['group'], + host: row['host'], + protocol: row['protocol'], + login: row['login'], + password: row['password'], + port: row['port'], + comment: row['comment'], + ) + + return false if item.empty? + + @data.push(item) end else From 57b2ca5fca858afc82ce7d4ac535460cf64f0568 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sun, 1 Feb 2015 11:25:52 +0100 Subject: [PATCH 149/531] remove old option format --- mpw | 4 ---- 1 file changed, 4 deletions(-) diff --git a/mpw b/mpw index c1791e2..4ae1280 100755 --- a/mpw +++ b/mpw @@ -97,10 +97,6 @@ OptionParser.new do |opts| options[:force] = true end - opts.on('-F', '--format', I18n.t('option.format')) do - options[:format] = true - end - opts.on('-G', '--generate-password [LENGTH]', I18n.t('option.generate_password')) do |length| puts MPW::MPW::password(length) exit 0 From 9921d3057ff851f2097548905abcf0796300c66e Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sun, 1 Feb 2015 11:48:02 +0100 Subject: [PATCH 150/531] fix add item --- lib/MPW.rb | 18 +++++++++++++++++- lib/UI/Cli.rb | 22 ++++++++++++---------- 2 files changed, 29 insertions(+), 11 deletions(-) diff --git a/lib/MPW.rb b/lib/MPW.rb index c90bcd3..9401382 100644 --- a/lib/MPW.rb +++ b/lib/MPW.rb @@ -63,8 +63,8 @@ module MPW def encrypt FileUtils.cp(@file_gpg, "#{@file_gpg}.bk") if File.exist?(@file_gpg) - data_to_encrypt = {} @data.each do |item| + puts item.class next if item.empty? data_to_encrypt.merge!(item.id => {'id' => item.id, @@ -101,6 +101,22 @@ module MPW return false end + # Add a new item + # @args: item -> Object MPW::Item + # @rtrn: true if add item + def add(item) + if not item.instance_of?(Item) + @error_msg = I18n.t('error.bad_class') + return false + elsif item.empty? + @error_msg = I18n.t('error.add.empty') + return false + else + @data.push(item) + return true + end + end + # Search in some csv data # @args: search -> the string to search # protocol -> the connection protocol (ssh, web, other) diff --git a/lib/UI/Cli.rb b/lib/UI/Cli.rb index 6a3e8ff..4b468b0 100644 --- a/lib/UI/Cli.rb +++ b/lib/UI/Cli.rb @@ -224,19 +224,21 @@ class Cli # Form to add a new item def add - row = [] + options = {} + puts I18n.t('form.add.title') puts '--------------------' - name = ask(I18n.t('form.add.name')).to_s - group = ask(I18n.t('form.add.group')).to_s - server = ask(I18n.t('form.add.server')).to_s - protocol = ask(I18n.t('form.add.protocol')).to_s - login = ask(I18n.t('form.add.login')).to_s - passwd = ask(I18n.t('form.add.password')).to_s - port = ask(I18n.t('form.add.port')).to_s - comment = ask(I18n.t('form.add.comment')).to_s + options[:name] = ask(I18n.t('form.add.name')).to_s + options[:group] = ask(I18n.t('form.add.group')).to_s + options[:host] = ask(I18n.t('form.add.server')).to_s + options[:protocol] = ask(I18n.t('form.add.protocol')).to_s + options[:user] = ask(I18n.t('form.add.login')).to_s + options[:passwd] = ask(I18n.t('form.add.password')).to_s + options[:port] = ask(I18n.t('form.add.port')).to_s + options[:comment] = ask(I18n.t('form.add.comment')).to_s - if @mpw.update(name, group, server, protocol, login, passwd, port, comment) + item = MPW::Item.new(options) + if @mpw.add(item) if @mpw.encrypt sync puts "#{I18n.t('form.add.valid')}".green From 446faf704ed3d1ffe12296dbb6996d28fc9f385d Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sun, 1 Feb 2015 12:23:50 +0100 Subject: [PATCH 151/531] fix update --- lib/Item.rb | 31 ++++++++++--------------------- lib/MPW.rb | 5 +++-- lib/UI/Cli.rb | 30 +++++++++++++++++------------- 3 files changed, 30 insertions(+), 36 deletions(-) diff --git a/lib/Item.rb b/lib/Item.rb index b6964be..ffd5f93 100644 --- a/lib/Item.rb +++ b/lib/Item.rb @@ -24,8 +24,7 @@ module MPW attr_accessor :created def initialize(options={}) - if not defined?(options[:id]) or not options[:id].to_s.empty? or - not defined?(options[:created]) or not options[:created].to_s.empty? + if not options.has_key?(:id) or options[:id].to_s.empty? or not options.has_key?(:created) or options[:created].to_s.empty? @id = generate_id @created = Time.now.to_i else @@ -37,19 +36,19 @@ module MPW end def update(options={}) - if defined?(options[:name]) and options[:name].to_s.empty? + if options.has_key?(:name) and options[:name].to_s.empty? @error_msg = I18n.t('error.update.name_empty') return false end - @name = options[:name] if defined?(options[:name]) - @group = options[:group] if defined?(options[:group]) - @host = options[:host] if defined?(options[:host]) - @protocol = options[:protocol] if defined?(options[:protocol]) - @user = options[:user] if defined?(options[:user]) - @password = options[:password] if defined?(options[:password]) - @port = options[:port].to_i if defined?(options[:port]) - @comment = options[:comment] if defined?(options[:comment]) + @name = options[:name] if options.has_key?(:name) + @group = options[:group] if options.has_key?(:group) + @host = options[:host] if options.has_key?(:host) + @protocol = options[:protocol] if options.has_key?(:protocol) + @user = options[:user] if options.has_key?(:user) + @password = options[:password] if options.has_key?(:password) + @port = options[:port].to_i if options.has_key?(:port) and not options[:port].to_s.empty? + @comment = options[:comment] if options.has_key?(:comment) @last_edit = Time.now.to_i return true @@ -63,16 +62,6 @@ module MPW return false end - private - def set_name(name) - if name.to_s.empty? - return false - end - - @name = name - return true - end - private def generate_id return ([*('A'..'Z'),*('a'..'z'),*('0'..'9')]).sample(16).join diff --git a/lib/MPW.rb b/lib/MPW.rb index 9401382..9bb0e1a 100644 --- a/lib/MPW.rb +++ b/lib/MPW.rb @@ -40,7 +40,7 @@ module MPW group: d['group'], host: d['host'], protocol: d['protocol'], - user: d['login'], + user: d['user'], password: d['password'], port: d['port'], comment: d['comment'], @@ -62,9 +62,10 @@ module MPW # @rtrn: true if the file has been encrypted def encrypt FileUtils.cp(@file_gpg, "#{@file_gpg}.bk") if File.exist?(@file_gpg) + + data_to_encrypt = {} @data.each do |item| - puts item.class next if item.empty? data_to_encrypt.merge!(item.id => {'id' => item.id, diff --git a/lib/UI/Cli.rb b/lib/UI/Cli.rb index 4b468b0..8636c69 100644 --- a/lib/UI/Cli.rb +++ b/lib/UI/Cli.rb @@ -233,7 +233,7 @@ class Cli options[:host] = ask(I18n.t('form.add.server')).to_s options[:protocol] = ask(I18n.t('form.add.protocol')).to_s options[:user] = ask(I18n.t('form.add.login')).to_s - options[:passwd] = ask(I18n.t('form.add.password')).to_s + options[:password] = ask(I18n.t('form.add.password')).to_s options[:port] = ask(I18n.t('form.add.port')).to_s options[:comment] = ask(I18n.t('form.add.comment')).to_s @@ -246,7 +246,7 @@ class Cli puts "#{I18n.t('display.error')} #12: #{@mpw.error_msg}".red end else - puts "#{I18n.t('display.error')} #13: #{@mpw.error_msg}".red + puts "#{I18n.t('display.error')} #13: #{item.error_msg}".red end end @@ -255,19 +255,23 @@ class Cli def update(id) item = @mpw.search_by_id(id) - if not row.empty? + if not item.nil? + options = {} + puts I18n.t('form.update.title') puts '--------------------' - name = ask(I18n.t('form.update.name' , name: item.name)).to_s - group = ask(I18n.t('form.update.group' , group: item.group)).to_s - server = ask(I18n.t('form.update.server' , server: item.host)).to_s - protocol = ask(I18n.t('form.update.protocol', protocol: item.protocol)).to_s - login = ask(I18n.t('form.update.login' , login: item.user)).to_s - passwd = ask(I18n.t('form.update.password')).to_s - port = ask(I18n.t('form.update.port' , port: item.port)).to_s - comment = ask(I18n.t('form.update.comment' , comment: item.comment)).to_s + options[:name] = ask(I18n.t('form.update.name' , name: item.name)).to_s + options[:group] = ask(I18n.t('form.update.group' , group: item.group)).to_s + options[:host] = ask(I18n.t('form.update.server' , server: item.host)).to_s + options[:protocol] = ask(I18n.t('form.update.protocol', protocol: item.protocol)).to_s + options[:user] = ask(I18n.t('form.update.login' , login: item.user)).to_s + options[:password] = ask(I18n.t('form.update.password')).to_s + options[:port] = ask(I18n.t('form.update.port' , port: item.port)).to_s + options[:comment] = ask(I18n.t('form.update.comment' , comment: item.comment)).to_s + + options.delete_if { |k,v| v.empty? } - if @mpw.update(name, group, server, protocol, login, passwd, port, comment, id) + if item.update(options) if @mpw.encrypt sync puts "#{I18n.t('form.update.valid')}".green @@ -275,7 +279,7 @@ class Cli puts "#{I18n.t('display.error')} #14: #{@mpw.error_msg}".red end else - puts "#{I18n.t('display.error')} #15: #{@mpw.error_msg}".red + puts "#{I18n.t('display.error')} #15: #{item.error_msg}".red end else puts I18n.t('display.nothing') From 5ceb3cfbdb2feadb7d0b067c1f924bd2689eec88 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sun, 1 Feb 2015 12:35:42 +0100 Subject: [PATCH 152/531] fix delete item --- lib/Item.rb | 13 +++++++++++++ lib/UI/Cli.rb | 23 ++++++++++------------- mpw | 20 ++++++++++---------- 3 files changed, 33 insertions(+), 23 deletions(-) diff --git a/lib/Item.rb b/lib/Item.rb index ffd5f93..21312fe 100644 --- a/lib/Item.rb +++ b/lib/Item.rb @@ -54,6 +54,19 @@ module MPW return true end + def delete + @id = nil + @name = nil + @group = nil + @host = nil + @protocol = nil + @user = nil + @password = nil + @port = nil + @created = nil + @last_edit = nil + end + def empty? return @name.to_s.empty? end diff --git a/lib/UI/Cli.rb b/lib/UI/Cli.rb index 8636c69..c0d4f44 100644 --- a/lib/UI/Cli.rb +++ b/lib/UI/Cli.rb @@ -289,12 +289,12 @@ class Cli # Remove an item # @args: id -> the item's id # force -> no resquest a validation - def remove(id, force=false) + def delete(id, force=false) if not force - result = @mpw.search_by_id(id) + item = @mpw.search_by_id(id) - if result.length > 0 - display_item(result) + if not item.nil? + display_item(item) confirm = ask("#{I18n.t('form.delete.ask', id: id)} (y/N) ").to_s if confirm =~ /^(y|yes|YES|Yes|Y)$/ @@ -306,15 +306,13 @@ class Cli end if force - if @mpw.remove(id) - if @mpw.encrypt - sync - puts "#{I18n.t('form.delete.valid', id: id)}".green - else - puts "#{I18n.t('display.error')} #16: #{@mpw.error_msg}".red - end + item.delete + + if @mpw.encrypt + sync + puts "#{I18n.t('form.delete.valid', id: id)}".green else - puts I18n.t('form.delete.not_valid') + puts "#{I18n.t('display.error')} #16: #{@mpw.error_msg}".red end end end @@ -327,7 +325,6 @@ class Cli else puts "#{I18n.t('display.error')} #17: #{@mpw.error_msg}".red end - end # Import items from a CSV file diff --git a/mpw b/mpw index 4ae1280..6689ade 100755 --- a/mpw +++ b/mpw @@ -43,21 +43,21 @@ options[:config] = nil OptionParser.new do |opts| opts.banner = "#{I18n.t('option.usage')}: mpw [options]" - opts.on('-d', '--display [SEARCH]', I18n.t('option.show')) do |search| - search.nil? ? (options[:display] = '') : (options[:display] = search) + opts.on('-s', '--show [SEARCH]', I18n.t('option.show')) do |search| + search.nil? ? (options[:show] = '') : (options[:show] = search) end opts.on('-A', '--show-all', I18n.t('option.show_all')) do - options[:type] = nil - options[:display] = '' + options[:type] = nil + options[:show] = '' end opts.on('-u', '--update ID', I18n.t('option.update')) do |id| options[:update] = id end - opts.on('-r', '--remove ID', I18n.t('option.remove')) do |id| - options[:remove] = id + opts.on('-d', '--delete ID', I18n.t('option.remove')) do |id| + options[:delete] = id end opts.on('-g', '--group GROUP', I18n.t('option.group')) do |group| @@ -128,12 +128,12 @@ cli.decrypt cli.sync # Display the item's informations -if not options[:display].nil? - cli.display(options[:display], options[:group], options[:type]) +if not options[:show].nil? + cli.display(options[:show], options[:group], options[:type]) # Remove an item -elsif not options[:remove].nil? - cli.remove(options[:remove], options[:force]) +elsif not options[:delete].nil? + cli.delete(options[:delete], options[:force]) # Update an item elsif not options[:update].nil? From 40240934c555cbfefbe7b010be33366301207e44 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sat, 7 Feb 2015 00:10:39 +0100 Subject: [PATCH 153/531] unstable: new sync class --- lib/MPW.rb | 46 +----------- lib/Sync/SSH.rb | 191 +++++++++++++++++++++++------------------------- lib/UI/Cli.rb | 51 ++----------- 3 files changed, 98 insertions(+), 190 deletions(-) diff --git a/lib/MPW.rb b/lib/MPW.rb index 9bb0e1a..fae4e95 100644 --- a/lib/MPW.rb +++ b/lib/MPW.rb @@ -1,7 +1,6 @@ #!/usr/bin/ruby # author: nishiki # mail: nishiki@yaegashi.fr -# info: a simple script who manage your passwords require 'rubygems' require 'gpgme' @@ -276,50 +275,7 @@ module MPW return false end - # Sync remote data and local data - # @args: data_remote -> array with the data remote - # last_update -> last update - # @rtrn: false if data_remote is nil - def sync(data_remote, last_update) - if not data_remote.instance_of?(Array) - @error_msg = I18n.t('error.sync.array') - return false - else not data_remote.to_s.empty? - @data.each_value do |l| - j = 0 - update = false - - # Update item - data_remote.each do |r| - if l['id'] == r['id'] - if l['date'].to_i < r['date'].to_i - update(r['name'], r['group'], r['host'], r['protocol'], r['login'], r['password'], r['port'], r['comment'], l['id']) - end - update = true - data_remote.delete(r['id']) - break - end - j += 1 - end - - # Delete an old item - if not update and l['date'].to_i < last_update - remove(l['id']) - end - end - end - - # Add item - data_remote.each do |r| - if r['date'].to_i > last_update - update(r['name'], r['group'], r['host'], r['protocol'], r['login'], r['password'], r['port'], r['comment'], r['id']) - end - end - - return encrypt - end - - # Generate a random password + # Generate a random password # @args: length -> the length password # @rtrn: a random string def self.password(length=8) diff --git a/lib/Sync/SSH.rb b/lib/Sync/SSH.rb index 9ebca2d..d61531b 100644 --- a/lib/Sync/SSH.rb +++ b/lib/Sync/SSH.rb @@ -1,110 +1,99 @@ #!/usr/bin/ruby # author: nishiki # mail: nishiki@yaegashi.fr -# info: a simple script who manage your passwords -module MPW - - module Sync - - require 'rubygems' - require 'i18n' - require 'net/ssh' - require 'net/scp' - - class SSH - - attr_accessor :error_msg - attr_accessor :enable - - # Constructor - def initialize - @error_msg = nil - @enable = false - end - - # Connect to server - # @args: host -> the server host - # port -> ther connection port - # gpg_key -> the gpg key - # password -> the remote password - # suffix -> the suffix file - # @rtrn: false if the connection fail - def connect(host, user, password, path, port=nil) - @host = host - @user = user - @password = password - @path = path - @port = port.instance_of?(Integer) ? 22 : port - - Net::SSH.start(@host, @user, password: @password, port: @port) do - @enable = true - end - rescue Exception => e - @error_msg = "#{I18n.t('error.sync.connection')}\n#{e}" - @enable = false - else - return @enable - end - - # Get data on server - # @args: gpg_password -> the gpg password - # @rtrn: nil if nothing data or error - def get(gpg_key, gpg_password) - return nil if not @enable - - tmp_file = tmpfile - Net::SCP.start(@host, @user, password: @password, port: @port) do |scp| - scp.download!(@path, tmp_file) - end - - mpw = MPW.new(tmp_file, gpg_key) - if not mpw.decrypt(gpg_password) - @error_msg = mpw.error_msg - return nil - end - - File.unlink(tmp_file) - return mpw.search - rescue Exception => e - @error_msg = "#{I18n.t('error.sync.download')}\n#{e}" - return nil - end - - # Update the remote data - # @args: data -> the data to send on server - # @rtrn: false if there is a problem - def update(data) - return true if not @enable - - tmp_file = tmpfile - File.open(tmp_file, "w") do |file| - file << data - end - - Net::SCP.start(@host, @user, password: @password, port: @port) do |scp| - scp.upload!(tmp_file, @path) - end - - File.unlink(tmp_file) - - return true - rescue Exception => e - @error_msg = "#{I18n.t('error.sync.upload')}\n#{e}" - return false - end - - # Generate a random string - # @rtrn: a random string - def tmpfile - result = '' - result << ([*('A'..'Z'),*('a'..'z'),*('0'..'9')]).sample(6).join - - return "/tmp/mpw-#{result}" - end +require 'rubygems' +require 'i18n' +require 'yaml' +require 'tempfile' +require 'net/ssh' +require 'net/scp' +module MPW + class SyncSSH + + attr_accessor :error_msg + attr_accessor :enable + + # Constructor + # @args: host -> the server host + # port -> ther connection port + # gpg_key -> the gpg key + # password -> the remote password + def initialize(host, user, password, path, port=nil) + @error_msg = nil + @enable = false + + @host = host + @user = user + @password = password + @path = path + @port = port.instance_of?(Integer) ? 22 : port + end + + # Connect to server + # @rtrn: false if the connection fail + def connect + Net::SSH.start(@host, @user, password: @password, port: @port) do + @enable = true + end + rescue Exception => e + @error_msg = "#{I18n.t('error.sync.connection')}\n#{e}" + @enable = false + else + return @enable + end + + # Get data on server + # @args: gpg_password -> the gpg password + # @rtrn: nil if nothing data or error + def get(gpg_key, gpg_password) + return nil if not @enable + + file_tmp = Tempfile.new('mpw') + Net::SCP.start(@host, @user, password: @password, port: @port) do |scp| + scp.download!(@path, file_tmp.path) + end + + mpw = MPW.new(file_tmp, gpg_key) + raise mpw.error_msg if not mpw.decrypt(gpg_password) + + file_tmp.close(true) + + return mpw.list + rescue Exception => e + @error_msg = "#{I18n.t('error.sync.download')}\n#{e}" + file_tmp.close(true) + return nil + end + + # Update the remote data + # @args: items -> the data to send on server + # @rtrn: false if there is a problem + def update(items) + return true if not @enable + + file_tmp = Tempfile.new('mpw') + + mpw = MPW.new(file_tmp, gpg_key) + items.each do |item| + mpw.add(item) + end + + raise(mpw.error_msg) if not mpw.encrypt + + Net::SCP.start(@host, @user, password: @password, port: @port) do |scp| + scp.upload!(file_tmp, @path) + end + + file_tmp.close(true) + + return true + rescue Exception => e + @error_msg = "#{I18n.t('error.sync.upload')}\n#{e}" + file_tmp.close(true) + return false end end - end diff --git a/lib/UI/Cli.rb b/lib/UI/Cli.rb index c0d4f44..b31f426 100644 --- a/lib/UI/Cli.rb +++ b/lib/UI/Cli.rb @@ -11,6 +11,7 @@ require 'i18n' require 'colorize' require "#{APP_ROOT}/lib/MPW" +require "#{APP_ROOT}/lib/Sync" class Cli @@ -24,52 +25,14 @@ class Cli # Sync the data with the server # @rtnr: true if the synchro is finish def sync - if not defined?(@sync) - case @config.sync_type - when 'mpw' - require "#{APP_ROOT}/lib/Sync/MPWSync" - @sync = MPW::Sync::MPWSync.new - when 'sftp', 'scp', 'ssh' - require "#{APP_ROOT}/lib/Sync/SSH" - @sync = MPW::Sync::SSH.new - when 'ftp' - require "#{APP_ROOT}/lib/Sync/FTP" - @sync = MPW::Sync::FTP.new - else - return false - end - end + @sync = MPW::Sync.new(@config, @password, @mpw.list) - if not @config.sync_host.nil? and not @config.sync_port.nil? - if not @sync.connect(@config.sync_host, @config.sync_user, @config.sync_pwd, @config.sync_path, @config.sync_port) - puts "#{I18n.t('display.error')} #1: #{@sync.error_msg}".red - end - end + raise(@sync.error_msg) if not @sync.get_remote + raise(@sync.error_msg) if not @sync.sync - if @sync.enable - if not @mpw.sync(@sync.get(@config.key, @passwd), @config.last_update) - puts "#{I18n.t('display.error')} #2: #{@mpw.error_msg}".red if not @mpw.error_msg.nil? - puts "#{I18n.t('display.error')} #3: #{@sync.error_msg}".red if not @sync.error_msg.nil? - - elsif not @sync.update(File.open(@config.file_gpg).read) - puts "#{I18n.t('display.error')} #4: #{@sync.error_msg}".red - - elsif not @config.set_last_update - puts "#{I18n.t('display.error')} #5: #{@config.error_msg}".red - - elsif not @mpw.encrypt - puts "#{I18n.t('display.error')} #6: #{@mpw.error_msg}".red - - else - return true - end - end + return true rescue Exception => e puts "#{I18n.t('display.error')} #7: #{e}".red - puts @sync.error_msg if not @sync.error_msg.nil? - puts @config.error_msg if not @config.error_msg.nil? - puts @mpw.error_msg if not @mpw.error_msg.nil? - else return false end @@ -160,8 +123,8 @@ class Cli @mpw = MPW::MPW.new(@config.file_gpg, @config.key, @config.share_keys) end - @passwd = ask(I18n.t('display.gpg_password')) {|q| q.echo = false} - if not @mpw.decrypt(@passwd) + @password = ask(I18n.t('display.gpg_password')) {|q| q.echo = false} + if not @mpw.decrypt(@password) puts "#{I18n.t('display.error')} #11: #{@mpw.error_msg}".red exit 2 end From 75a8348086a8af5f006724e257d1b7b82cfcc174 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sun, 8 Feb 2015 20:56:39 +0100 Subject: [PATCH 154/531] unstable: fix sync via ssh --- lib/MPW.rb | 2 +- lib/Sync/MPWSync.rb | 147 -------------------------------------------- lib/Sync/SSH.rb | 48 +++++---------- lib/Sync/SyncMPW.rb | 132 +++++++++++++++++++++++++++++++++++++++ lib/UI/Cli.rb | 4 +- 5 files changed, 151 insertions(+), 182 deletions(-) delete mode 100644 lib/Sync/MPWSync.rb create mode 100644 lib/Sync/SyncMPW.rb diff --git a/lib/MPW.rb b/lib/MPW.rb index fae4e95..6817755 100644 --- a/lib/MPW.rb +++ b/lib/MPW.rb @@ -28,7 +28,7 @@ module MPW # @args: password -> the GPG key password # @rtrn: true if data has been decrypted def decrypt(password=nil) - if File.exist?(@file_gpg) + if File.exist?(@file_gpg) and not File.zero?(@file_gpg) crypto = GPGME::Crypto.new(armor: true) data_decrypt = crypto.decrypt(IO.read(@file_gpg), password: password).read.force_encoding('utf-8') diff --git a/lib/Sync/MPWSync.rb b/lib/Sync/MPWSync.rb deleted file mode 100644 index 9bb6572..0000000 --- a/lib/Sync/MPWSync.rb +++ /dev/null @@ -1,147 +0,0 @@ -#!/usr/bin/ruby -# author: nishiki -# mail: nishiki@yaegashi.fr -# info: a simple script who manage your passwords - -module MPW - - module Sync - - require 'rubygems' - require 'i18n' - require 'socket' - require 'json' - require 'timeout' - - class MPWSync - - attr_accessor :error_msg - attr_accessor :enable - - # Constructor - def initialize - @error_msg = nil - @enable = false - end - - # Connect to server - # @args: host -> the server host - # port -> ther connection port - # gpg_key -> the gpg key - # password -> the remote password - # suffix -> the suffix file - # @rtrn: false if the connection fail - def connect(host, user, password, path, port=nil) - @host = host - @port = !port.instance_of?(Integer) ? 2201 : port - @gpg_key = user - @password = password - @suffix = path - - Timeout.timeout(10) do - begin - TCPSocket.open(@host, @port) do - @enable = true - end - rescue Errno::ENETUNREACH - retry - end - end - rescue Timeout::Error - puts 'timeout' - @error_msg = "#{I18n.t('error.timeout')}\n#{e}" - @enable = false - rescue Exception => e - @error_msg = "#{I18n.t('error.sync.connection')}\n#{e}" - @enable = false - else - return @enable - end - - # Get data on server - # @args: gpg_password -> the gpg password - # @rtrn: nil if nothing data or error - def get(gpg_key, gpg_password) - return nil if not @enable - - msg = nil - TCPSocket.open(@host, @port) do |socket| - send_msg = {action: 'get', - gpg_key: @gpg_key, - password: @password, - suffix: @suffix - } - - socket.puts send_msg.to_json - msg = JSON.parse(socket.gets) - end - - if not defined?(msg['error']) - @error_msg = I18n.t('error.sync.communication') - return nil - elsif not msg['error'].nil? - @error_msg = I18n.t(msg['error']) - return nil - elsif msg['data'].nil? or msg['data'].empty? - return {} - else - tmp_file = tmpfile - File.open(tmp_file, 'w') do |file| - file << msg['data'] - end - - mpw = MPW.new(tmp_file, gpg_key) - if not mpw.decrypt(gpg_password) - @error_msg = mpw.error_msg - return nil - end - - File.unlink(tmp_file) - return mpw.search - end - end - - # Update the remote data - # @args: data -> the data to send on server - # @rtrn: false if there is a problem - def update(data) - return true if not @enable - - msg = nil - TCPSocket.open(@host, @port) do |socket| - send_msg = {action: 'update', - gpg_key: @gpg_key, - password: @password, - suffix: @suffix, - data: data - } - - socket.puts send_msg.to_json - msg = JSON.parse(socket.gets) - end - - if not defined?(msg['error']) - @error_msg = I18n.t('error.sync.communication') - return false - elsif msg['error'].nil? - return true - else - @error_msg = I18n.t(msg['error']) - return false - end - end - - # Generate a random string - # @rtrn: a random string - def tmpfile - result = '' - result << ([*('A'..'Z'),*('a'..'z'),*('0'..'9')]).sample(6).join - - return "/tmp/mpw-#{result}" - end - - end - - end - -end diff --git a/lib/Sync/SSH.rb b/lib/Sync/SSH.rb index d61531b..db721ca 100644 --- a/lib/Sync/SSH.rb +++ b/lib/Sync/SSH.rb @@ -4,10 +4,9 @@ require 'rubygems' require 'i18n' -require 'yaml' require 'tempfile' require 'net/ssh' -require 'net/scp' +require 'net/sftp' module MPW class SyncSSH @@ -34,7 +33,7 @@ module MPW # Connect to server # @rtrn: false if the connection fail def connect - Net::SSH.start(@host, @user, password: @password, port: @port) do + Net::SSH.start(@host, @user, password: @password, port: @port) do |ssh| @enable = true end rescue Exception => e @@ -47,51 +46,36 @@ module MPW # Get data on server # @args: gpg_password -> the gpg password # @rtrn: nil if nothing data or error - def get(gpg_key, gpg_password) - return nil if not @enable + def get(file_tmp) + return false if not @enable - file_tmp = Tempfile.new('mpw') - Net::SCP.start(@host, @user, password: @password, port: @port) do |scp| - scp.download!(@path, file_tmp.path) + puts @path + puts file_tmp + Net::SFTP.start(@host, @user, password: @password, port: @port) do |sftp| + sftp.lstat(@path) do |response| + sftp.download!(@path, file_tmp) if response.ok? + end end - - mpw = MPW.new(file_tmp, gpg_key) - raise mpw.error_msg if not mpw.decrypt(gpg_password) - - file_tmp.close(true) - return mpw.list + return true rescue Exception => e @error_msg = "#{I18n.t('error.sync.download')}\n#{e}" - file_tmp.close(true) - return nil + return false end # Update the remote data - # @args: items -> the data to send on server + # @args: file_gpg -> the data to send on server # @rtrn: false if there is a problem - def update(items) + def update(file_gpg) return true if not @enable - file_tmp = Tempfile.new('mpw') - - mpw = MPW.new(file_tmp, gpg_key) - items.each do |item| - mpw.add(item) + Net::SFTP.start(@host, @user, password: @password, port: @port) do |sftp| + sftp.upload!(file_gpg, @path) end - raise(mpw.error_msg) if not mpw.encrypt - - Net::SCP.start(@host, @user, password: @password, port: @port) do |scp| - scp.upload!(file_tmp, @path) - end - - file_tmp.close(true) - return true rescue Exception => e @error_msg = "#{I18n.t('error.sync.upload')}\n#{e}" - file_tmp.close(true) return false end diff --git a/lib/Sync/SyncMPW.rb b/lib/Sync/SyncMPW.rb new file mode 100644 index 0000000..0fc8068 --- /dev/null +++ b/lib/Sync/SyncMPW.rb @@ -0,0 +1,132 @@ +#!/usr/bin/ruby +# author: nishiki + +require 'rubygems' +require 'i18n' +require 'socket' +require 'json' +require 'timeout' + +module MPW + class SyncMPW + + attr_accessor :error_msg + attr_accessor :enable + + # Constructor + # @args: host -> the server host + # port -> ther connection port + # gpg_key -> the gpg key + # password -> the remote password + # suffix -> the suffix file + def initialize(host, user, password, suffix, port=nil) + @error_msg = nil + @enable = false + + @host = host + @port = !port.instance_of?(Integer) ? 2201 : port + @gpg_key = user + @password = password + @suffix = suffix + end + + # Connect to server + # @rtrn: false if the connection fail + def connect + Timeout.timeout(10) do + begin + TCPSocket.open(@host, @port) do + @enable = true + end + rescue Errno::ENETUNREACH + retry + end + end + rescue Timeout::Error + @error_msg = "#{I18n.t('error.timeout')}\n#{e}" + @enable = false + rescue Exception => e + @error_msg = "#{I18n.t('error.sync.connection')}\n#{e}" + @enable = false + else + return @enable + end + + # Get data on server + # @args: gpg_password -> the gpg password + # @rtrn: nil if nothing data or error + def get(gpg_key, gpg_password) + return nil if not @enable + + msg = nil + TCPSocket.open(@host, @port) do |socket| + send_msg = {action: 'get', + gpg_key: @gpg_key, + password: @password, + suffix: @suffix + } + + socket.puts send_msg.to_json + msg = JSON.parse(socket.gets) + end + + if not defined?(msg['error']) + @error_msg = I18n.t('error.sync.communication') + return nil + elsif not msg['error'].nil? + @error_msg = I18n.t(msg['error']) + return nil + elsif msg['data'].nil? or msg['data'].empty? + return {} + else + file_tmp = Tempfile.new('mpw-') + File.open(file_tmp, 'w') do |file| + file << msg['data'] + end + + mpw = MPW.new(file_tmp, gpg_key) + raise mpw.error_msg if not mpw.decrypt(gpg_password) + + file_tmp.close(true) + + puts 'test' + return mpw.list + end + rescue Exception => e + @error_msg = "#{I18n.t('error.sync.download')}\n#{e}" + file_tmp.close(true) + return nil + end + + # Update the remote data + # @args: data -> the data to send on server + # @rtrn: false if there is a problem + def update(data) + return true if not @enable + + msg = nil + TCPSocket.open(@host, @port) do |socket| + send_msg = {action: 'update', + gpg_key: @gpg_key, + password: @password, + suffix: @suffix, + data: data + } + + socket.puts send_msg.to_json + msg = JSON.parse(socket.gets) + end + + if not defined?(msg['error']) + @error_msg = I18n.t('error.sync.communication') + return false + elsif msg['error'].nil? + return true + else + @error_msg = I18n.t(msg['error']) + return false + end + end + + end +end diff --git a/lib/UI/Cli.rb b/lib/UI/Cli.rb index b31f426..b29ff91 100644 --- a/lib/UI/Cli.rb +++ b/lib/UI/Cli.rb @@ -25,13 +25,13 @@ class Cli # Sync the data with the server # @rtnr: true if the synchro is finish def sync - @sync = MPW::Sync.new(@config, @password, @mpw.list) + @sync = MPW::Sync.new(@config, @mpw, @password) raise(@sync.error_msg) if not @sync.get_remote raise(@sync.error_msg) if not @sync.sync return true - rescue Exception => e +# rescue Exception => e puts "#{I18n.t('display.error')} #7: #{e}".red return false end From 5da53efc0834b82b8019305776451ca14d14b423 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sun, 8 Feb 2015 21:15:06 +0100 Subject: [PATCH 155/531] fix missing file --- lib/Sync.rb | 112 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 lib/Sync.rb diff --git a/lib/Sync.rb b/lib/Sync.rb new file mode 100644 index 0000000..5426fab --- /dev/null +++ b/lib/Sync.rb @@ -0,0 +1,112 @@ +#!/usr/bin/ruby +# author: nishiki +# mail: nishiki@yaegashi.fr +# info: a simple script who manage your passwords + +require 'rubygems' +require 'i18n' +require 'yaml' +require "#{APP_ROOT}/lib/Item" +require "#{APP_ROOT}/lib/MPW" + +module MPW + class Sync + + attr_accessor :error_msg + + def initialize(config, local, password=nil) + @error_msg = nil + @config = config + @local = local + @password = password + + raise I18n.t('error.class') if not @local.instance_of?(MPW) + end + + def get_remote + case @config.sync_type + when 'mpw' + require "#{APP_ROOT}/lib/Sync/SyncMPW" + @sync = SyncMPW.new(@config.sync_host, @config.sync_user, @config.sync_pwd, @config.sync_path, @config.sync_port) + when 'sftp', 'scp', 'ssh' + require "#{APP_ROOT}/lib/Sync/SSH" + @sync = SyncSSH.new(@config.sync_host, @config.sync_user, @config.sync_pwd, @config.sync_path, @config.sync_port) + when 'ftp' + require "#{APP_ROOT}/lib/Sync/FTP" + @sync = SyncFTP.new + else + @error_msg = I18n.t('error.unknown_type') + return false + end + + if not @sync.connect + @error_msg = @sync.error_msg + return false + end + + + file_tmp = Tempfile.new('mpw-') + raise @sync.error_msg if not @sync.get(file_tmp.path) + + @remote = MPW.new(file_tmp.path, @config.key) + raise @remote.error_msg if not @remote.decrypt(@password) + + file_tmp.close(true) + return true + rescue Exception => e + @error_msg = "#{I18n.t('error.sync')} #{e}" + file_tmp.close(true) + return false + end + + # Sync remote data and local data + # @args: data_remote -> array with the data remote + # last_update -> last update + # @rtrn: false if data_remote is nil + def sync + if not @remote.to_s.empty? + @local.list.each do |item| + j = 0 + update = false + + # Update item + @remote.list.each do |r| + if item.id == r.id + if item.last_edit < r.last_edit + raise item.error_msg if not item.update(r.name, r.group, r.host, r.protocol, r.user, r.password, r.port, r.comment) + end + + update = true + data_remote.delete(j) + + break + end + + j += 1 + end + + # Delete an old item + if not update and item.last_edit < @config.last_update + item.delete + end + end + end + + # Add item + @remote.list.each do |r| + if r.last_edit > @config.last_update + item = Item.new(r.name, r.group, r.host, r.protocol, r.user, r.password, r.port, r.comment) + raise @local.error_msg if not @local.add(item) + end + end + + raise @sync.error_msg if not @sync.update(@config.file_gpg) + raise @mpw.error_msg if not @local.encrypt + + return true + rescue Exception => e + @error_msg = "#{I18n.t('error.sync')} #{e}" + return false + end + end +end From b7b56c306dac61e559f1419920234027a33be237 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sun, 8 Feb 2015 21:40:01 +0100 Subject: [PATCH 156/531] fix rescue --- lib/UI/Cli.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/UI/Cli.rb b/lib/UI/Cli.rb index b29ff91..98bcf70 100644 --- a/lib/UI/Cli.rb +++ b/lib/UI/Cli.rb @@ -31,7 +31,7 @@ class Cli raise(@sync.error_msg) if not @sync.sync return true -# rescue Exception => e + rescue Exception => e puts "#{I18n.t('display.error')} #7: #{e}".red return false end From cdf2de0fb43dc45cbee2c782fd82f53a555bc937 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sun, 8 Feb 2015 21:57:15 +0100 Subject: [PATCH 157/531] fix sync MPW --- lib/Sync.rb | 1 + lib/Sync/SyncMPW.rb | 36 ++++++++++++++---------------------- 2 files changed, 15 insertions(+), 22 deletions(-) diff --git a/lib/Sync.rb b/lib/Sync.rb index 5426fab..b71b136 100644 --- a/lib/Sync.rb +++ b/lib/Sync.rb @@ -6,6 +6,7 @@ require 'rubygems' require 'i18n' require 'yaml' +require 'tempfile' require "#{APP_ROOT}/lib/Item" require "#{APP_ROOT}/lib/MPW" diff --git a/lib/Sync/SyncMPW.rb b/lib/Sync/SyncMPW.rb index 0fc8068..596414d 100644 --- a/lib/Sync/SyncMPW.rb +++ b/lib/Sync/SyncMPW.rb @@ -55,8 +55,8 @@ module MPW # Get data on server # @args: gpg_password -> the gpg password # @rtrn: nil if nothing data or error - def get(gpg_key, gpg_password) - return nil if not @enable + def get(file_tmp) + return false if not @enable msg = nil TCPSocket.open(@host, @port) do |socket| @@ -72,38 +72,30 @@ module MPW if not defined?(msg['error']) @error_msg = I18n.t('error.sync.communication') - return nil + return false elsif not msg['error'].nil? @error_msg = I18n.t(msg['error']) - return nil - elsif msg['data'].nil? or msg['data'].empty? - return {} - else - file_tmp = Tempfile.new('mpw-') - File.open(file_tmp, 'w') do |file| - file << msg['data'] - end - - mpw = MPW.new(file_tmp, gpg_key) - raise mpw.error_msg if not mpw.decrypt(gpg_password) - - file_tmp.close(true) - - puts 'test' - return mpw.list + return false end + + File.open(file_tmp, 'w') do |file| + file << msg['data'] + end + + return true rescue Exception => e @error_msg = "#{I18n.t('error.sync.download')}\n#{e}" - file_tmp.close(true) - return nil + return false end # Update the remote data # @args: data -> the data to send on server # @rtrn: false if there is a problem - def update(data) + def update(file_gpg) return true if not @enable + data = File.open(file_gpg, 'r').read + msg = nil TCPSocket.open(@host, @port) do |socket| send_msg = {action: 'update', From 68062fe7287c154bb9d3d360718eb0ae6c3c604f Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sun, 8 Feb 2015 22:06:37 +0100 Subject: [PATCH 158/531] fix FTP sync --- lib/Sync/FTP.rb | 172 ++++++++++++++++++++---------------------------- lib/Sync/SSH.rb | 1 - 2 files changed, 71 insertions(+), 102 deletions(-) diff --git a/lib/Sync/FTP.rb b/lib/Sync/FTP.rb index 1bb2a55..0d324e7 100644 --- a/lib/Sync/FTP.rb +++ b/lib/Sync/FTP.rb @@ -1,111 +1,81 @@ #!/usr/bin/ruby # author: nishiki # mail: nishiki@yaegashi.fr -# info: a simple script who manage your passwords +require 'rubygems' +require 'i18n' +require 'net/ftp' + module MPW - - module Sync - - require 'rubygems' - require 'i18n' - require 'net/ftp' - - class FTP - - attr_accessor :error_msg - attr_accessor :enable - - # Constructor - def initialize - @error_msg = nil - @enable = false - end - - # Connect to server - # @args: host -> the server host - # port -> ther connection port - # gpg_key -> the gpg key - # password -> the remote password - # suffix -> the suffix file - # @rtrn: false if the connection fail - def connect(host, user, password, path, port=nil) - @host = host - @user = user - @password = password - @path = path - @port = port.instance_of?(Integer) ? 21 : port - - Net::FTP.open(@host) do |ftp| - ftp.login(@user, @password) - @enable = true - end - rescue Exception => e - @error_msg = "#{I18n.t('error.sync.connection')}\n#{e}" - @enable = false - else - return @enable - end - - # Get data on server - # @args: gpg_password -> the gpg password - # @rtrn: nil if nothing data or error - def get(gpg_key, gpg_password) - return nil if not @enable - - tmp_file = tmpfile - Net::FTP.open(@host) do |ftp| - ftp.login(@user, @password) - ftp.gettextfile(@path, tmp_file) - end - - mpw = MPW.new(tmp_file, gpg_key) - if not mpw.decrypt(gpg_password) - @error_msg = mpw.error_msg - return nil - end - - File.unlink(tmp_file) - return mpw.search - rescue Exception => e - @error_msg = "#{I18n.t('error.sync.download')}\n#{e}" - return nil - end - - # Update the remote data - # @args: data -> the data to send on server - # @rtrn: false if there is a problem - def update(data) - return true if not @enable - - tmp_file = tmpfile - File.open(tmp_file, "w") do |file| - file << data - end - - Net::FTP.open(@host) do |ftp| - ftp.login(@user, @password) - ftp.puttextfile(tmp_file, @path) - end - - File.unlink(tmp_file) - return true - rescue Exception => e - @error_msg = "#{I18n.t('error.sync.upload')}\n#{e}" - return false - end - - # Generate a random string - # @rtrn: a random string - def tmpfile - result = '' - result << ([*('A'..'Z'),*('a'..'z'),*('0'..'9')]).sample(6).join - - return "/tmp/mpw-#{result}" - end + class FTP + attr_accessor :error_msg + attr_accessor :enable + + # Constructor + # @args: host -> the server host + # port -> ther connection port + # gpg_key -> the gpg key + # password -> the remote password + # suffix -> the suffix file + def initialize(host, user, password, path, port=nil) + @error_msg = nil + @enable = false + + @host = host + @user = user + @password = password + @path = path + @port = port.instance_of?(Integer) ? 21 : port + end + + # Connect to server + # @rtrn: false if the connection fail + def connect + Net::FTP.open(@host) do |ftp| + ftp.login(@user, @password) + @enable = true + end + rescue Exception => e + @error_msg = "#{I18n.t('error.sync.connection')}\n#{e}" + @enable = false + else + return @enable + end + + # Get data on server + # @args: gpg_password -> the gpg password + # @rtrn: nil if nothing data or error + def get(file_tmp) + return false if not @enable + + Net::FTP.open(@host) do |ftp| + ftp.login(@user, @password) + ftp.gettextfile(@path, file_tmp) + end + + return true + rescue Exception => e + @error_msg = "#{I18n.t('error.sync.download')}\n#{e}" + return false + end + + # Update the remote data + # @args: data -> the data to send on server + # @rtrn: false if there is a problem + def update(file_gpg) + return true if not @enable + + Net::FTP.open(@host) do |ftp| + ftp.login(@user, @password) + ftp.puttextfile(file_gpg, @path) + end + + return true + rescue Exception => e + @error_msg = "#{I18n.t('error.sync.upload')}\n#{e}" + return false end end - end diff --git a/lib/Sync/SSH.rb b/lib/Sync/SSH.rb index db721ca..ddb00b5 100644 --- a/lib/Sync/SSH.rb +++ b/lib/Sync/SSH.rb @@ -4,7 +4,6 @@ require 'rubygems' require 'i18n' -require 'tempfile' require 'net/ssh' require 'net/sftp' From 59f9a5d40fdd8f322781d98ee39174ed3f1074da Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sun, 8 Feb 2015 22:43:35 +0100 Subject: [PATCH 159/531] fix sync --- lib/Sync.rb | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/lib/Sync.rb b/lib/Sync.rb index b71b136..afad14e 100644 --- a/lib/Sync.rb +++ b/lib/Sync.rb @@ -34,7 +34,7 @@ module MPW @sync = SyncSSH.new(@config.sync_host, @config.sync_user, @config.sync_pwd, @config.sync_path, @config.sync_port) when 'ftp' require "#{APP_ROOT}/lib/Sync/FTP" - @sync = SyncFTP.new + @sync = SyncFTP.new(@config.sync_host, @config.sync_user, @config.sync_pwd, @config.sync_path, @config.sync_port) else @error_msg = I18n.t('error.unknown_type') return false @@ -74,11 +74,19 @@ module MPW @remote.list.each do |r| if item.id == r.id if item.last_edit < r.last_edit - raise item.error_msg if not item.update(r.name, r.group, r.host, r.protocol, r.user, r.password, r.port, r.comment) + raise item.error_msg if not item.update(name: r.name, + group: r.group, + host: r.host, + protocol: r.protocol, + user: r.user, + password: r.password, + port: r.port, + comment: r.comment + ) end update = true - data_remote.delete(j) + item.delete break end @@ -96,7 +104,15 @@ module MPW # Add item @remote.list.each do |r| if r.last_edit > @config.last_update - item = Item.new(r.name, r.group, r.host, r.protocol, r.user, r.password, r.port, r.comment) + item = Item.new(name: r.name, + group: r.group, + host: r.host, + protocol: r.protocol, + user: r.user, + password: r.password, + port: r.port, + comment: r.comment + ) raise @local.error_msg if not @local.add(item) end end From 24949b2bde63c483672d81c7e4f56cf2ed7e1329 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sun, 8 Feb 2015 22:47:52 +0100 Subject: [PATCH 160/531] fix sync when add new item --- lib/Sync.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/Sync.rb b/lib/Sync.rb index afad14e..3f18f26 100644 --- a/lib/Sync.rb +++ b/lib/Sync.rb @@ -104,14 +104,16 @@ module MPW # Add item @remote.list.each do |r| if r.last_edit > @config.last_update - item = Item.new(name: r.name, + item = Item.new(id: r.id, + name: r.name, group: r.group, host: r.host, protocol: r.protocol, user: r.user, password: r.password, port: r.port, - comment: r.comment + comment: r.comment, + created: r.created ) raise @local.error_msg if not @local.add(item) end From 4569ad4d1c3451da23f8d19e1e155f2406e5977b Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sun, 8 Feb 2015 22:54:04 +0100 Subject: [PATCH 161/531] add require_relative --- lib/Config.rb | 13 +++++-------- lib/MPW.rb | 3 ++- lib/Sync.rb | 5 +++-- lib/UI/Cli.rb | 5 +++-- mpw | 9 +++++---- 5 files changed, 18 insertions(+), 17 deletions(-) diff --git a/lib/Config.rb b/lib/Config.rb index 92abad8..7663809 100644 --- a/lib/Config.rb +++ b/lib/Config.rb @@ -1,15 +1,13 @@ #!/usr/bin/ruby # author: nishiki # mail: nishiki@yaegashi.fr -# info: a simple script who manage your passwords -module MPW - - require 'rubygems' - require 'gpgme' - require 'yaml' - require 'i18n' +require 'rubygems' +require 'gpgme' +require 'yaml' +require 'i18n' +module MPW class Config attr_accessor :error_msg @@ -231,5 +229,4 @@ module MPW end end - end diff --git a/lib/MPW.rb b/lib/MPW.rb index 6817755..a29cff0 100644 --- a/lib/MPW.rb +++ b/lib/MPW.rb @@ -8,7 +8,8 @@ require 'csv' require 'i18n' require 'fileutils' require 'yaml' -require "#{APP_ROOT}/lib/Item" + +require_relative './Item' module MPW class MPW diff --git a/lib/Sync.rb b/lib/Sync.rb index 3f18f26..18dbad9 100644 --- a/lib/Sync.rb +++ b/lib/Sync.rb @@ -7,8 +7,9 @@ require 'rubygems' require 'i18n' require 'yaml' require 'tempfile' -require "#{APP_ROOT}/lib/Item" -require "#{APP_ROOT}/lib/MPW" + +require_relative './MPW' +require_relative './Item' module MPW class Sync diff --git a/lib/UI/Cli.rb b/lib/UI/Cli.rb index 98bcf70..eba7273 100644 --- a/lib/UI/Cli.rb +++ b/lib/UI/Cli.rb @@ -10,8 +10,9 @@ require 'readline' require 'i18n' require 'colorize' -require "#{APP_ROOT}/lib/MPW" -require "#{APP_ROOT}/lib/Sync" +require_relative '../Sync' +require_relative '../MPW' +require_relative '../Item' class Cli diff --git a/mpw b/mpw index 6689ade..bc63313 100755 --- a/mpw +++ b/mpw @@ -10,10 +10,9 @@ require 'locale' require 'set' require 'i18n' -APP_ROOT = File.dirname(Pathname.new(__FILE__).realpath) -require "#{APP_ROOT}/lib/UI/Cli" -require "#{APP_ROOT}/lib/Config" -require "#{APP_ROOT}/lib/MPW" +require_relative 'lib/UI/Cli' +require_relative 'lib/Config' +require_relative 'lib/MPW' # --------------------------------------------------------- # # Set local @@ -25,6 +24,8 @@ if defined?(I18n.enforce_available_locales) I18n.enforce_available_locales = true end +APP_ROOT = File.dirname(Pathname.new(__FILE__).realpath) + I18n::Backend::Simple.send(:include, I18n::Backend::Fallbacks) I18n.load_path = Dir["#{APP_ROOT}/i18n/cli/*.yml"] I18n.default_locale = :en From 43abe955790521abd29a8609249e8a3eb0877f36 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sun, 8 Feb 2015 22:58:18 +0100 Subject: [PATCH 162/531] update Gemfile --- Gemfile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Gemfile b/Gemfile index 7046265..1ccb9c5 100644 --- a/Gemfile +++ b/Gemfile @@ -6,6 +6,5 @@ gem 'gpgme' gem 'colorize' group :ssh do - gem 'net-ssh' - gem 'net-scp' + gem 'net-sftp' end From a119a954d39e59ff7a0e11baac34db245c38fc8b Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Mon, 9 Feb 2015 21:39:13 +0100 Subject: [PATCH 163/531] fix bug in error message --- lib/Sync.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/Sync.rb b/lib/Sync.rb index 18dbad9..984181d 100644 --- a/lib/Sync.rb +++ b/lib/Sync.rb @@ -56,7 +56,7 @@ module MPW file_tmp.close(true) return true rescue Exception => e - @error_msg = "#{I18n.t('error.sync')} #{e}" + @error_msg = "#{I18n.t('error.sync.download')} #{e}" file_tmp.close(true) return false end @@ -125,7 +125,7 @@ module MPW return true rescue Exception => e - @error_msg = "#{I18n.t('error.sync')} #{e}" + @error_msg = "#{I18n.t('error.sync.unknown')} #{e}" return false end end From 886595f31af8b12acffeedb82a408f66c4c8bed1 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Thu, 12 Feb 2015 18:01:58 +0100 Subject: [PATCH 164/531] add unittest for items --- lib/Item.rb | 4 +- test/files/fixtures.yml | 19 +++- test/test_item.rb | 210 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 229 insertions(+), 4 deletions(-) create mode 100644 test/test_item.rb diff --git a/lib/Item.rb b/lib/Item.rb index 21312fe..7841d8b 100644 --- a/lib/Item.rb +++ b/lib/Item.rb @@ -1,7 +1,6 @@ #!/usr/bin/ruby # author: nishiki # mail: nishiki@yaegashi.fr -# info: a simple script who manage your passwords require 'rubygems' require 'i18n' @@ -63,8 +62,11 @@ module MPW @user = nil @password = nil @port = nil + @comment = nil @created = nil @last_edit = nil + + return true end def empty? diff --git a/test/files/fixtures.yml b/test/files/fixtures.yml index 7cd5520..197e085 100644 --- a/test/files/fixtures.yml +++ b/test/files/fixtures.yml @@ -1,18 +1,31 @@ -add: +add_new: name: 'test_name' group: 'test_group' host: 'test_host' protocol: 'test_protocol' - login: 'test_login' + user: 'test_login' password: 'test_password' port: '42' comment: 'test_comment' + +add_existing: + id: 'TEST-ID-XXXXX' + name: 'test_name_existing' + group: 'test_group_existing' + host: 'test_host_existing' + protocol: 'test_protocol_existing' + user: 'test_user_existing' + password: 'test_password_existing' + port: '44' + comment: 'test_comment_existing' + created: 1386752948 + update: name: 'test_name_update' group: 'test_group_update' host: 'test_host_update' protocol: 'test_protocol_update' - login: 'test_login_update' + user: 'test_login_update' password: 'test_password_update' port: '43' comment: 'test_comment_update' diff --git a/test/test_item.rb b/test/test_item.rb new file mode 100644 index 0000000..277265d --- /dev/null +++ b/test/test_item.rb @@ -0,0 +1,210 @@ +#!/usr/bin/ruby + +require_relative '../lib/Item' +require 'test/unit' +require 'yaml' + +class TestItem < Test::Unit::TestCase + def setup + @fixture_file = 'files/fixtures.yml' + @fixtures = YAML.load_file(@fixture_file) + + if defined?(I18n.enforce_available_locales) + I18n.enforce_available_locales = false + end + + puts + end + + def test_01_add_new + data = {name: @fixtures['add_new']['name'], + group: @fixtures['add_new']['group'], + host: @fixtures['add_new']['host'], + protocol: @fixtures['add_new']['protocol'], + user: @fixtures['add_new']['user'], + password: @fixtures['add_new']['password'], + port: @fixtures['add_new']['port'], + comment: @fixtures['add_new']['comment'], + } + + item = MPW::Item.new(data) + + assert(!item.nil?) + assert(!item.empty?) + + assert_equal(@fixtures['add_new']['name'], item.name) + assert_equal(@fixtures['add_new']['group'], item.group) + assert_equal(@fixtures['add_new']['host'], item.host) + assert_equal(@fixtures['add_new']['protocol'], item.protocol) + assert_equal(@fixtures['add_new']['user'], item.user) + assert_equal(@fixtures['add_new']['password'], item.password) + assert_equal(@fixtures['add_new']['port'].to_i, item.port) + assert_equal(@fixtures['add_new']['comment'], item.comment) + end + + def test_02_add_existing + data = {id: @fixtures['add_existing']['id'], + name: @fixtures['add_existing']['name'], + group: @fixtures['add_existing']['group'], + host: @fixtures['add_existing']['host'], + protocol: @fixtures['add_existing']['protocol'], + user: @fixtures['add_existing']['user'], + password: @fixtures['add_existing']['password'], + port: @fixtures['add_existing']['port'], + comment: @fixtures['add_existing']['comment'], + created: @fixtures['add_existing']['created'], + } + + item = MPW::Item.new(data) + + assert(!item.nil?) + assert(!item.empty?) + + assert_equal(@fixtures['add_existing']['id'], item.id) + assert_equal(@fixtures['add_existing']['name'], item.name) + assert_equal(@fixtures['add_existing']['group'], item.group) + assert_equal(@fixtures['add_existing']['host'], item.host) + assert_equal(@fixtures['add_existing']['protocol'], item.protocol) + assert_equal(@fixtures['add_existing']['user'], item.user) + assert_equal(@fixtures['add_existing']['password'], item.password) + assert_equal(@fixtures['add_existing']['port'].to_i, item.port) + assert_equal(@fixtures['add_existing']['comment'], item.comment) + assert_equal(@fixtures['add_existing']['created'], item.created) + end + + def test_03_update + data = {name: @fixtures['add_new']['name'], + group: @fixtures['add_new']['group'], + host: @fixtures['add_new']['host'], + protocol: @fixtures['add_new']['protocol'], + user: @fixtures['add_new']['user'], + password: @fixtures['add_new']['password'], + port: @fixtures['add_new']['port'], + comment: @fixtures['add_new']['comment'], + } + + item = MPW::Item.new(data) + + assert(!item.nil?) + assert(!item.empty?) + + created = item.created + last_edit = item.last_edit + + data = {name: @fixtures['update']['name'], + group: @fixtures['update']['group'], + host: @fixtures['update']['host'], + protocol: @fixtures['update']['protocol'], + user: @fixtures['update']['user'], + password: @fixtures['update']['password'], + port: @fixtures['update']['port'], + comment: @fixtures['update']['comment'], + } + + sleep(1) + assert(item.update(data)) + + assert(!item.empty?) + + assert_equal(@fixtures['update']['name'], item.name) + assert_equal(@fixtures['update']['group'], item.group) + assert_equal(@fixtures['update']['host'], item.host) + assert_equal(@fixtures['update']['protocol'], item.protocol) + assert_equal(@fixtures['update']['user'], item.user) + assert_equal(@fixtures['update']['password'], item.password) + assert_equal(@fixtures['update']['port'].to_i, item.port) + assert_equal(@fixtures['update']['comment'], item.comment) + + assert_equal(created, item.created) + assert_not_equal(last_edit, item.last_edit) + end + + def test_04_update_with_empty_name + data = {name: @fixtures['add_new']['name'], + group: @fixtures['add_new']['group'], + host: @fixtures['add_new']['host'], + protocol: @fixtures['add_new']['protocol'], + user: @fixtures['add_new']['user'], + password: @fixtures['add_new']['password'], + port: @fixtures['add_new']['port'], + comment: @fixtures['add_new']['comment'], + } + + item = MPW::Item.new(data) + + assert(!item.nil?) + assert(!item.empty?) + + last_edit = item.last_edit + + sleep(1) + assert(!item.update({name: ''})) + + assert_equal(last_edit, item.last_edit) + end + + def test_05_update_one_element + data = {name: @fixtures['add_new']['name'], + group: @fixtures['add_new']['group'], + host: @fixtures['add_new']['host'], + protocol: @fixtures['add_new']['protocol'], + user: @fixtures['add_new']['user'], + password: @fixtures['add_new']['password'], + port: @fixtures['add_new']['port'], + comment: @fixtures['add_new']['comment'], + } + + item = MPW::Item.new(data) + + assert(!item.nil?) + assert(!item.empty?) + + last_edit = item.last_edit + + sleep(1) + assert(item.update({comment: @fixtures['update']['comment']})) + + assert_equal(@fixtures['add_new']['name'], item.name) + assert_equal(@fixtures['add_new']['group'], item.group) + assert_equal(@fixtures['add_new']['host'], item.host) + assert_equal(@fixtures['add_new']['protocol'], item.protocol) + assert_equal(@fixtures['add_new']['user'], item.user) + assert_equal(@fixtures['add_new']['password'], item.password) + assert_equal(@fixtures['add_new']['port'].to_i, item.port) + assert_equal(@fixtures['update']['comment'], item.comment) + + assert_not_equal(last_edit, item.last_edit) + end + + def test_04_delete + data = {name: @fixtures['add_new']['name'], + group: @fixtures['add_new']['group'], + host: @fixtures['add_new']['host'], + protocol: @fixtures['add_new']['protocol'], + user: @fixtures['add_new']['user'], + password: @fixtures['add_new']['password'], + port: @fixtures['add_new']['port'], + comment: @fixtures['add_new']['comment'], + } + + item = MPW::Item.new(data) + + assert(!item.nil?) + assert(!item.empty?) + + assert(item.delete) + assert(!item.nil?) + assert(item.empty?) + + assert_equal(nil, item.id) + assert_equal(nil, item.name) + assert_equal(nil, item.group) + assert_equal(nil, item.host) + assert_equal(nil, item.protocol) + assert_equal(nil, item.user) + assert_equal(nil, item.password) + assert_equal(nil, item.port) + assert_equal(nil, item.comment) + assert_equal(nil, item.created) + end +end From 21ef7659fcaf5eebd14f55a3a107bd1eb3d0dbc5 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Thu, 12 Feb 2015 23:02:09 +0100 Subject: [PATCH 165/531] unittest: update for item --- lib/Item.rb | 5 +++++ test/files/fixtures.yml | 4 ++-- test/test_item.rb | 10 +++++++++- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/lib/Item.rb b/lib/Item.rb index 7841d8b..33ab1bc 100644 --- a/lib/Item.rb +++ b/lib/Item.rb @@ -23,6 +23,11 @@ module MPW attr_accessor :created def initialize(options={}) + if not options.has_key?(:name) or options[:name].to_s.empty? + @error_msg = I18n.t('error.update.name_empty') + raise ExceptionMPW @error_msg + end + if not options.has_key?(:id) or options[:id].to_s.empty? or not options.has_key?(:created) or options[:created].to_s.empty? @id = generate_id @created = Time.now.to_i diff --git a/test/files/fixtures.yml b/test/files/fixtures.yml index 197e085..73eacf7 100644 --- a/test/files/fixtures.yml +++ b/test/files/fixtures.yml @@ -3,7 +3,7 @@ add_new: group: 'test_group' host: 'test_host' protocol: 'test_protocol' - user: 'test_login' + user: 'test_user' password: 'test_password' port: '42' comment: 'test_comment' @@ -25,7 +25,7 @@ update: group: 'test_group_update' host: 'test_host_update' protocol: 'test_protocol_update' - user: 'test_login_update' + user: 'test_user_update' password: 'test_password_update' port: '43' comment: 'test_comment_update' diff --git a/test/test_item.rb b/test/test_item.rb index 277265d..32d84f3 100644 --- a/test/test_item.rb +++ b/test/test_item.rb @@ -13,9 +13,17 @@ class TestItem < Test::Unit::TestCase I18n.enforce_available_locales = false end + I18n.load_path = Dir['../i18n/cli/*.yml'] + I18n.default_locale = :en + + puts end + def test_00_add_without_name + assert_raise {MPW::Item.new} + end + def test_01_add_new data = {name: @fixtures['add_new']['name'], group: @fixtures['add_new']['group'], @@ -176,7 +184,7 @@ class TestItem < Test::Unit::TestCase assert_not_equal(last_edit, item.last_edit) end - def test_04_delete + def test_05_delete data = {name: @fixtures['add_new']['name'], group: @fixtures['add_new']['group'], host: @fixtures['add_new']['host'], From 0708c3d4c05fdf5a403d194c317c12bd557d2672 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Thu, 12 Feb 2015 23:03:01 +0100 Subject: [PATCH 166/531] unittest: fix for mpw --- lib/MPW.rb | 8 +- test/files/test_import.csv | 6 +- test/files/test_import.yml | 4 +- test/test_mpw.rb | 300 ++++++++++++------------------------- 4 files changed, 102 insertions(+), 216 deletions(-) diff --git a/lib/MPW.rb b/lib/MPW.rb index a29cff0..1b1b81a 100644 --- a/lib/MPW.rb +++ b/lib/MPW.rb @@ -29,6 +29,8 @@ module MPW # @args: password -> the GPG key password # @rtrn: true if data has been decrypted def decrypt(password=nil) + @data = [] + if File.exist?(@file_gpg) and not File.zero?(@file_gpg) crypto = GPGME::Crypto.new(armor: true) data_decrypt = crypto.decrypt(IO.read(@file_gpg), password: password).read.force_encoding('utf-8') @@ -165,7 +167,7 @@ module MPW CSV.open(file, 'w', write_headers: true, headers: ['name', 'group', 'protocol', 'host', 'user', 'password', 'port', 'comment']) do |csv| @data.each do |item| - csv << [item.id, item.group, item.protocol, item.host, item.user, item.password, item.port, item.comment] + csv << [item.name, item.group, item.protocol, item.host, item.user, item.password, item.port, item.comment] end end @@ -212,7 +214,7 @@ module MPW group: row['group'], host: row['host'], protocol: row['protocol'], - login: row['login'], + user: row['user'], password: row['password'], port: row['port'], comment: row['comment'], @@ -229,7 +231,7 @@ module MPW group: row['group'], host: row['host'], protocol: row['protocol'], - login: row['login'], + user: row['user'], password: row['password'], port: row['port'], comment: row['comment'], diff --git a/test/files/test_import.csv b/test/files/test_import.csv index 1452c07..74c1844 100644 --- a/test/files/test_import.csv +++ b/test/files/test_import.csv @@ -1,3 +1,3 @@ -name,group,protocol,host,login,password,port,comment -test_name_csv,test_group_csv,test_protocol_csv,test_host_csv,test_login_csv,test_password_csv,44,test_comment_csv -test_name_update_csv,test_group_update_csv,test_protocol_update_csv,test_host_update_csv,test_login_update_csv,test_password_update_csv,45,test_comment_update_csv +name,group,protocol,host,user,password,port,comment +test_name,test_group,test_protocol,test_host,test_user,test_password,42,test_comment +test_name_update,test_group_update,test_protocol_update,test_host_update,test_user_update,test_password_update,43,test_comment_update diff --git a/test/files/test_import.yml b/test/files/test_import.yml index e7fef00..889a264 100644 --- a/test/files/test_import.yml +++ b/test/files/test_import.yml @@ -5,7 +5,7 @@ XWas7vpy0HerhOYd: group: test_group host: test_host protocol: test_protocol - login: test_login + user: test_user password: test_password port: 42 comment: test_comment @@ -16,7 +16,7 @@ D7URyJENLa91jt0b: group: test_group_update host: test_host_update protocol: test_protocol_update - login: test_login_update + user: test_user_update password: test_password_update port: 43 comment: test_comment_update diff --git a/test/test_mpw.rb b/test/test_mpw.rb index 94bbfa3..e8b51bf 100644 --- a/test/test_mpw.rb +++ b/test/test_mpw.rb @@ -1,13 +1,14 @@ #!/usr/bin/ruby require_relative '../lib/MPW' +require_relative '../lib/Item' require 'test/unit' require 'yaml' require 'csv' class TestMPW < Test::Unit::TestCase def setup - @fixture_file = 'files/fixtures.yml' + fixture_file = 'files/fixtures.yml' file_gpg = 'test.gpg' key = ENV['MPW_TEST_KEY'] @@ -19,45 +20,47 @@ class TestMPW < Test::Unit::TestCase end File.delete(file_gpg) if File.exist?(file_gpg) - @mpw = MPW::MPW.new(file_gpg, key) - @fixtures = YAML.load_file(@fixture_file) + + @mpw = MPW::MPW.new(file_gpg, key) + @fixtures = YAML.load_file(fixture_file) end def test_01_import_yaml import_file = 'files/test_import.yml' assert(@mpw.import(import_file, :yaml)) - assert_equal(2, @mpw.search.length) + assert_equal(2, @mpw.list.length) - result = @mpw.search[0] - assert_equal(@fixtures['add']['name'], result['name']) - assert_equal(@fixtures['add']['group'], result['group']) - assert_equal(@fixtures['add']['host'], result['host']) - assert_equal(@fixtures['add']['protocol'], result['protocol']) - assert_equal(@fixtures['add']['login'], result['login']) - assert_equal(@fixtures['add']['password'], result['password']) - assert_equal(@fixtures['add']['port'].to_i, result['port']) - assert_equal(@fixtures['add']['comment'], result['comment']) + item = @mpw.list[0] + assert_equal(@fixtures['add_new']['name'], item.name) + assert_equal(@fixtures['add_new']['group'], item.group) + assert_equal(@fixtures['add_new']['host'], item.host) + assert_equal(@fixtures['add_new']['protocol'], item.protocol) + assert_equal(@fixtures['add_new']['user'], item.user) + assert_equal(@fixtures['add_new']['password'], item.password) + assert_equal(@fixtures['add_new']['port'].to_i, item.port) + assert_equal(@fixtures['add_new']['comment'], item.comment) end def test_02_export_yaml + import_file = 'files/test_import.yml' export_file = 'test_export.yml' - assert(@mpw.import(@fixture_file)) - assert_equal(2, @mpw.search.length) + assert(@mpw.import(import_file)) + assert_equal(2, @mpw.list.length) assert(@mpw.export(export_file, :yaml)) export = YAML::load_file(export_file) assert_equal(2, export.length) result = export.values[0] - assert_equal(@fixtures['add']['name'], result['name']) - assert_equal(@fixtures['add']['group'], result['group']) - assert_equal(@fixtures['add']['host'], result['host']) - assert_equal(@fixtures['add']['protocol'], result['protocol']) - assert_equal(@fixtures['add']['login'], result['login']) - assert_equal(@fixtures['add']['password'], result['password']) - assert_equal(@fixtures['add']['port'].to_i, result['port']) - assert_equal(@fixtures['add']['comment'], result['comment']) + assert_equal(@fixtures['add_new']['name'], result['name']) + assert_equal(@fixtures['add_new']['group'], result['group']) + assert_equal(@fixtures['add_new']['host'], result['host']) + assert_equal(@fixtures['add_new']['protocol'], result['protocol']) + assert_equal(@fixtures['add_new']['user'], result['user']) + assert_equal(@fixtures['add_new']['password'], result['password']) + assert_equal(@fixtures['add_new']['port'].to_i, result['port']) + assert_equal(@fixtures['add_new']['comment'], result['comment']) File.unlink(export_file) end @@ -66,155 +69,73 @@ class TestMPW < Test::Unit::TestCase import_file = 'files/test_import.csv' assert(@mpw.import(import_file, :csv)) - assert_equal(2, @mpw.search.length) + assert_equal(2, @mpw.list.length) import = CSV.parse(File.read(import_file), headers: true) - result = @mpw.search[0] - assert_equal(import[0]['name'], result['name']) - assert_equal(import[0]['group'], result['group']) - assert_equal(import[0]['host'], result['host']) - assert_equal(import[0]['protocol'], result['protocol']) - assert_equal(import[0]['login'], result['login']) - assert_equal(import[0]['password'], result['password']) - assert_equal(import[0]['port'].to_i, result['port']) - assert_equal(import[0]['comment'], result['comment']) + item = @mpw.list[0] + assert_equal(import[0]['name'], item.name) + assert_equal(import[0]['group'], item.group) + assert_equal(import[0]['host'], item.host) + assert_equal(import[0]['protocol'], item.protocol) + assert_equal(import[0]['user'], item.user) + assert_equal(import[0]['password'], item.password) + assert_equal(import[0]['port'].to_i, item.port) + assert_equal(import[0]['comment'], item.comment) end def test_04_export_csv + import_file = 'files/test_import.csv' export_file = 'test_export.csv' - assert(@mpw.import(@fixture_file)) - assert_equal(2, @mpw.search.length) + + assert(@mpw.import(import_file, :csv)) + assert_equal(2, @mpw.list.length) assert(@mpw.export(export_file, :csv)) export = CSV.parse(File.read(export_file), headers: true) assert_equal(2, export.length) result = export[0] - assert_equal(@fixtures['add']['name'], result['name']) - assert_equal(@fixtures['add']['group'], result['group']) - assert_equal(@fixtures['add']['host'], result['host']) - assert_equal(@fixtures['add']['protocol'], result['protocol']) - assert_equal(@fixtures['add']['login'], result['login']) - assert_equal(@fixtures['add']['password'], result['password']) - assert_equal(@fixtures['add']['port'], result['port']) - assert_equal(@fixtures['add']['comment'], result['comment']) + assert_equal(@fixtures['add_new']['name'], result['name']) + assert_equal(@fixtures['add_new']['group'], result['group']) + assert_equal(@fixtures['add_new']['host'], result['host']) + assert_equal(@fixtures['add_new']['protocol'], result['protocol']) + assert_equal(@fixtures['add_new']['user'], result['user']) + assert_equal(@fixtures['add_new']['password'], result['password']) + assert_equal(@fixtures['add_new']['port'], result['port']) + assert_equal(@fixtures['add_new']['comment'], result['comment']) File.unlink(export_file) end - def test_05_add - assert(@mpw.update(@fixtures['add']['name'], - @fixtures['add']['group'], - @fixtures['add']['host'], - @fixtures['add']['protocol'], - @fixtures['add']['login'], - @fixtures['add']['password'], - @fixtures['add']['port'], - @fixtures['add']['comment'])) + def test_05_add_item + data = {name: @fixtures['add_new']['name'], + group: @fixtures['add_new']['group'], + host: @fixtures['add_new']['host'], + protocol: @fixtures['add_new']['protocol'], + user: @fixtures['add_new']['user'], + password: @fixtures['add_new']['password'], + port: @fixtures['add_new']['port'], + comment: @fixtures['add_new']['comment'], + } + + item = MPW::Item.new(data) - assert_equal(1, @mpw.search.length) + assert(!item.nil?) + assert(!item.empty?) - result = @mpw.search[0] - assert_equal(@fixtures['add']['name'], result['name']) - assert_equal(@fixtures['add']['group'], result['group']) - assert_equal(@fixtures['add']['host'], result['host']) - assert_equal(@fixtures['add']['protocol'], result['protocol']) - assert_equal(@fixtures['add']['login'], result['login']) - assert_equal(@fixtures['add']['password'], result['password']) - assert_equal(@fixtures['add']['port'].to_i, result['port']) - assert_equal(@fixtures['add']['comment'], result['comment']) + assert(@mpw.add(item)) - assert(@mpw.update(@fixtures['add']['name'], - @fixtures['add']['group'], - @fixtures['add']['host'], - @fixtures['add']['protocol'], - @fixtures['add']['login'], - @fixtures['add']['password'], - @fixtures['add']['port'], - @fixtures['add']['comment'])) + assert_equal(1, @mpw.list.length) - - assert_equal(2, @mpw.search.length) - end - - def test_06_add_empty_name - assert(!@mpw.update('', - @fixtures['add']['group'], - @fixtures['add']['host'], - @fixtures['add']['protocol'], - @fixtures['add']['login'], - @fixtures['add']['password'], - @fixtures['add']['port'], - @fixtures['add']['comment'])) - - assert_equal(0, @mpw.search.length) - end - - def test_07_update_empty - assert(@mpw.import(@fixture_file, :yaml)) - assert_equal(2, @mpw.search.length) - - id = @mpw.search[0]['id'] - - assert(@mpw.update('','', '','','','','', '', id)) - - result = @mpw.search_by_id(id) - assert_equal(@fixtures['add']['name'], result['name']) - assert_equal(@fixtures['add']['group'], result['group']) - assert_equal(@fixtures['add']['host'], result['host']) - assert_equal(@fixtures['add']['protocol'], result['protocol']) - assert_equal(@fixtures['add']['login'], result['login']) - assert_equal(@fixtures['add']['password'], result['password']) - assert_equal(@fixtures['add']['port'].to_i, result['port']) - assert_equal(@fixtures['add']['comment'], result['comment']) - end - - def test_08_update - assert(@mpw.import(@fixture_file, :yaml)) - assert_equal(2, @mpw.search.length) - - id = @mpw.search[0]['id'] - - assert(@mpw.update(@fixtures['update']['name'], - @fixtures['update']['group'], - @fixtures['update']['host'], - @fixtures['update']['protocol'], - @fixtures['update']['login'], - @fixtures['update']['password'], - @fixtures['update']['port'], - @fixtures['update']['comment'], - id)) - - assert_equal(2, @mpw.search.length) - - result = @mpw.search_by_id(id) - assert_equal(@fixtures['update']['name'], result['name']) - assert_equal(@fixtures['update']['group'], result['group']) - assert_equal(@fixtures['update']['host'], result['host']) - assert_equal(@fixtures['update']['protocol'], result['protocol']) - assert_equal(@fixtures['update']['login'], result['login']) - assert_equal(@fixtures['update']['password'], result['password']) - assert_equal(@fixtures['update']['port'].to_i, result['port']) - assert_equal(@fixtures['update']['comment'], result['comment']) - end - - def test_09_remove - assert(@mpw.import(@fixture_file, :yaml)) - assert_equal(2, @mpw.search.length) - - id = @mpw.search[0]['id'] - assert(@mpw.remove(id)) - - assert_equal(1, @mpw.search.length) - end - - def test_10_remove_noexistent - assert(@mpw.import(@fixture_file, :yaml)) - assert_equal(2, @mpw.search.length) - - assert(!@mpw.remove('TEST_NOEXISTENT_ID')) - - assert_equal(2, @mpw.search.length) + item = @mpw.list[0] + assert_equal(@fixtures['add_new']['name'], item.name) + assert_equal(@fixtures['add_new']['group'], item.group) + assert_equal(@fixtures['add_new']['host'], item.host) + assert_equal(@fixtures['add_new']['protocol'], item.protocol) + assert_equal(@fixtures['add_new']['user'], item.user) + assert_equal(@fixtures['add_new']['password'], item.password) + assert_equal(@fixtures['add_new']['port'].to_i, item.port) + assert_equal(@fixtures['add_new']['comment'], item.comment) end def test_11_encrypt_empty_file @@ -222,75 +143,38 @@ class TestMPW < Test::Unit::TestCase end def test_12_encrypt - assert(@mpw.import(@fixture_file, :yaml)) - assert_equal(2, @mpw.search.length) + import_file = 'files/test_import.yml' + + assert(@mpw.import(import_file, :yaml)) + assert_equal(2, @mpw.list.length) assert(@mpw.encrypt) end def test_13_decrypt_empty_file assert(@mpw.decrypt) - assert_equal(0, @mpw.search.length) + assert_equal(0, @mpw.list.length) end def test_14_decrypt - assert(@mpw.import(@fixture_file, :yaml)) - assert_equal(2, @mpw.search.length) + import_file = 'files/test_import.yml' + + assert(@mpw.import(import_file, :yaml)) + assert_equal(2, @mpw.list.length) assert(@mpw.encrypt) assert(@mpw.decrypt) - assert_equal(2, @mpw.search.length) + assert_equal(2, @mpw.list.length) - result = @mpw.search[0] - assert_equal(@fixtures['add']['name'], result['name']) - assert_equal(@fixtures['add']['group'], result['group']) - assert_equal(@fixtures['add']['host'], result['host']) - assert_equal(@fixtures['add']['protocol'], result['protocol']) - assert_equal(@fixtures['add']['login'], result['login']) - assert_equal(@fixtures['add']['password'], result['password']) - assert_equal(@fixtures['add']['port'].to_i, result['port']) - assert_equal(@fixtures['add']['comment'], result['comment']) - end - - def test_15_sync_local_empty - import_file = 'files/test_import.yml' - - data = [] - YAML.load_file(import_file).each_value { |v| data.push(v) } - - @mpw.sync(data, 0) - - result = @mpw.search[0] - assert_equal(@fixtures['add']['name'], result['name']) - assert_equal(@fixtures['add']['group'], result['group']) - assert_equal(@fixtures['add']['host'], result['host']) - assert_equal(@fixtures['add']['protocol'], result['protocol']) - assert_equal(@fixtures['add']['login'], result['login']) - assert_equal(@fixtures['add']['password'], result['password']) - assert_equal(@fixtures['add']['port'].to_i, result['port']) - assert_equal(@fixtures['add']['comment'], result['comment']) - - assert_equal(2, @mpw.search.length) - end - - def test_16_sync_remote_outdated_and_local_empty - import_file = 'files/test_import.yml' - - data = [] - YAML.load_file(import_file).each_value { |v| data.push(v) } - - assert(@mpw.sync(data, Time.now.to_i)) - - assert_equal(0, @mpw.search.length) - end - - def test_17_sync_empty_data - assert(@mpw.import(@fixture_file, :yaml)) - assert_equal(2, @mpw.search.length) - - assert(@mpw.sync([], 0)) - - assert_equal(2, @mpw.search.length) + item = @mpw.list[0] + assert_equal(@fixtures['add_new']['name'], item.name) + assert_equal(@fixtures['add_new']['group'], item.group) + assert_equal(@fixtures['add_new']['host'], item.host) + assert_equal(@fixtures['add_new']['protocol'], item.protocol) + assert_equal(@fixtures['add_new']['user'], item.user) + assert_equal(@fixtures['add_new']['password'], item.password) + assert_equal(@fixtures['add_new']['port'].to_i, item.port) + assert_equal(@fixtures['add_new']['comment'], item.comment) end end From 59c91bfb8fcab63703aa48dacb2dc0de254625d5 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Fri, 13 Feb 2015 19:28:51 +0100 Subject: [PATCH 167/531] add comment --- lib/Item.rb | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/lib/Item.rb b/lib/Item.rb index 33ab1bc..c14d0bd 100644 --- a/lib/Item.rb +++ b/lib/Item.rb @@ -22,10 +22,14 @@ module MPW attr_accessor :last_edit attr_accessor :created + # Constructor + # Create a new item + # @args: options -> a hash of parameter + # raise an error if the hash hasn't the key name def initialize(options={}) if not options.has_key?(:name) or options[:name].to_s.empty? @error_msg = I18n.t('error.update.name_empty') - raise ExceptionMPW @error_msg + raise @error_msg end if not options.has_key?(:id) or options[:id].to_s.empty? or not options.has_key?(:created) or options[:created].to_s.empty? @@ -39,6 +43,9 @@ module MPW update(options) end + # Update the item + # @args: options -> a hash of parameter + # @rtrn: true if the item is update def update(options={}) if options.has_key?(:name) and options[:name].to_s.empty? @error_msg = I18n.t('error.update.name_empty') @@ -58,6 +65,8 @@ module MPW return true end + # Delete all data + # @rtrn: true def delete @id = nil @name = nil @@ -82,6 +91,7 @@ module MPW return false end + # Generate an random id private def generate_id return ([*('A'..'Z'),*('a'..'z'),*('0'..'9')]).sample(16).join From bca86d4c0624c7a1df35b10a8a1e03535d70c10a Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Fri, 13 Feb 2015 19:28:59 +0100 Subject: [PATCH 168/531] add comment --- lib/Sync.rb | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/Sync.rb b/lib/Sync.rb index 984181d..35c516a 100644 --- a/lib/Sync.rb +++ b/lib/Sync.rb @@ -16,6 +16,8 @@ module MPW attr_accessor :error_msg + # Constructor + # raise an exception if there is a bad parameter def initialize(config, local, password=nil) @error_msg = nil @config = config @@ -25,6 +27,8 @@ module MPW raise I18n.t('error.class') if not @local.instance_of?(MPW) end + # Get the data on remote host + # @rtrn: true if get the date, else false def get_remote case @config.sync_type when 'mpw' @@ -62,9 +66,7 @@ module MPW end # Sync remote data and local data - # @args: data_remote -> array with the data remote - # last_update -> last update - # @rtrn: false if data_remote is nil + # raise an exception if there is a problem def sync if not @remote.to_s.empty? @local.list.each do |item| From 66405d0eb911b1fa1f7e19509abe933e6543ea63 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Fri, 13 Feb 2015 19:31:01 +0100 Subject: [PATCH 169/531] update comment --- lib/MPW.rb | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/lib/MPW.rb b/lib/MPW.rb index 1b1b81a..8d770d3 100644 --- a/lib/MPW.rb +++ b/lib/MPW.rb @@ -121,8 +121,7 @@ module MPW end # Search in some csv data - # @args: search -> the string to search - # protocol -> the connection protocol (ssh, web, other) + # @args: options -> a hash with paramaters # @rtrn: a list with the resultat of the search def list(options={}) result = [] @@ -148,7 +147,7 @@ module MPW # Search in some csv data # @args: id -> the id item - # @rtrn: a row with the resultat of the search + # @rtrn: a row with the result of the search def search_by_id(id) @data.each do |item| return item if item.id == id @@ -278,7 +277,7 @@ module MPW return false end - # Generate a random password + # Generate a random password # @args: length -> the length password # @rtrn: a random string def self.password(length=8) From ed2d7e624dee677b10f01d1e4723e89a4c04acfb Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Fri, 13 Feb 2015 23:55:14 +0100 Subject: [PATCH 170/531] fix test item --- test/test_item.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_item.rb b/test/test_item.rb index 32d84f3..923d7af 100644 --- a/test/test_item.rb +++ b/test/test_item.rb @@ -21,7 +21,7 @@ class TestItem < Test::Unit::TestCase end def test_00_add_without_name - assert_raise {MPW::Item.new} + assert_raise(RuntimeError){MPW::Item.new} end def test_01_add_new From 7f45037366650d4d1c076a39155a76eea9216b6e Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sat, 14 Feb 2015 10:42:03 +0100 Subject: [PATCH 171/531] improve search options --- lib/MPW.rb | 27 +++++++++++++++------------ lib/UI/Cli.rb | 4 ++-- mpw | 11 ++++++++--- 3 files changed, 25 insertions(+), 17 deletions(-) diff --git a/lib/MPW.rb b/lib/MPW.rb index 8d770d3..c948606 100644 --- a/lib/MPW.rb +++ b/lib/MPW.rb @@ -126,20 +126,23 @@ module MPW def list(options={}) result = [] - if not defined?(options[:search]) or options[:search].nil? - search = '' - else - search = options[:search].downcase - end - + search = options[:search].to_s.downcase + group = options[:group].to_s.downcase + protocol = options[:protocol].to_s.downcase + @data.each do |item| - name = item.name.nil? ? nil : item.name.downcase - host = item.host.nil? ? nil : item.host.downcase - comment = item.comment.nil? ? nil : item.comment.downcase - - if name =~ /^.*#{search}.*$/ or host =~ /^.*#{search}.*$/ or comment =~ /^.*#{search}.*$/ - result.push(item) + next if not group.empty? and not group.eql?(item.group.downcase) + next if not protocol.empty? and not protocol.eql?(item.protocol.downcase) + + name = item.name.to_s.downcase + host = item.host.to_s.downcase + comment = item.comment.to_s.downcase + + if not name =~ /^.*#{search}.*$/ and not host =~ /^.*#{search}.*$/ and not comment =~ /^.*#{search}.*$/ + next end + + result.push(item) end return result diff --git a/lib/UI/Cli.rb b/lib/UI/Cli.rb index eba7273..9352ed9 100644 --- a/lib/UI/Cli.rb +++ b/lib/UI/Cli.rb @@ -134,8 +134,8 @@ class Cli # Display the query's result # @args: search -> the string to search # protocol -> search from a particular protocol - def display(search, protocol=nil, group=nil) - result = @mpw.list(search: search) + def display(options={}) + result = @mpw.list(options) case result.length when 0 diff --git a/mpw b/mpw index bc63313..ad632b1 100755 --- a/mpw +++ b/mpw @@ -77,8 +77,8 @@ OptionParser.new do |opts| options[:setup] = true end - opts.on('-p', '--protocol PROTOCOL', I18n.t('option.protocol')) do |type| - options[:type] = type + opts.on('-p', '--protocol PROTOCOL', I18n.t('option.protocol')) do |protocol| + options[:protocol] = protocol end opts.on('-e', '--export FILE', I18n.t('option.export')) do |file| @@ -130,7 +130,12 @@ cli.sync # Display the item's informations if not options[:show].nil? - cli.display(options[:show], options[:group], options[:type]) + opts = {search: options[:show], + group: options[:group], + protocol: options[:protocol], + } + + cli.display(opts) # Remove an item elsif not options[:delete].nil? From 4cc134afb477c4b4ee63f2a1214fb1955f26e0a0 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Thu, 19 Mar 2015 22:52:33 +0100 Subject: [PATCH 172/531] fix bug in preview import --- lib/MPW.rb | 45 ++++++++++++++++++++++++++++++++++++--------- lib/UI/Cli.rb | 2 ++ 2 files changed, 38 insertions(+), 9 deletions(-) diff --git a/lib/MPW.rb b/lib/MPW.rb index c948606..45f355e 100644 --- a/lib/MPW.rb +++ b/lib/MPW.rb @@ -126,9 +126,9 @@ module MPW def list(options={}) result = [] - search = options[:search].to_s.downcase - group = options[:group].to_s.downcase - protocol = options[:protocol].to_s.downcase + search = options[:search].to_s.downcase + group = options[:group].to_s.downcase + protocol = options[:protocol].to_s.downcase @data.each do |item| next if not group.empty? and not group.eql?(item.group.downcase) @@ -259,22 +259,49 @@ module MPW # @args: file -> path to file import # @rtrn: a hash with the items to import, if there is an error return false def import_preview(file, type=:yaml) - result = [] + data = [] + case type when :csv CSV.foreach(file, {headers: true}) do |row| - result << row + item = Item.new(name: row['name'], + group: row['group'], + host: row['host'], + protocol: row['protocol'], + user: row['user'], + password: row['password'], + port: row['port'], + comment: row['comment'], + ) + + return false if item.empty? + + data.push(item) end + when :yaml - YAML::load_file(file).each do |k, row| - result << row + YAML::load_file(file).each_value do |row| + item = Item.new(name: row['name'], + group: row['group'], + host: row['host'], + protocol: row['protocol'], + user: row['user'], + password: row['password'], + port: row['port'], + comment: row['comment'], + ) + + return false if item.empty? + + data.push(item) end + else @error_msg = "#{I18n.t('error.export.unknown_type', type: type)}" return false end - - return result + + return data rescue Exception => e @error_msg = "#{I18n.t('error.import.read', file: file)}\n#{e}" return false diff --git a/lib/UI/Cli.rb b/lib/UI/Cli.rb index 9352ed9..35f3399 100644 --- a/lib/UI/Cli.rb +++ b/lib/UI/Cli.rb @@ -298,8 +298,10 @@ class Cli if not force result = @mpw.import_preview(file, type) + puts result if result.is_a?(Array) and not result.empty? result.each do |r| + puts r.class display_item(r) end From b5230f2cfe437ef6878dc6849d4da3e34c0b874b Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Thu, 19 Mar 2015 23:03:15 +0100 Subject: [PATCH 173/531] fix translation --- i18n/cli/en.yml | 1 + i18n/cli/fr.yml | 1 + 2 files changed, 2 insertions(+) diff --git a/i18n/cli/en.yml b/i18n/cli/en.yml index b8c1bd7..dfa5835 100644 --- a/i18n/cli/en.yml +++ b/i18n/cli/en.yml @@ -30,6 +30,7 @@ en: not_authorized: "You haven't the access to remote file!" upload: "Can't upload the file on the server!" unknown: "An unknown error is occured!" + unknown_type: "The sync type is unknown" warning: select: 'Your choice is not a valid element!' diff --git a/i18n/cli/fr.yml b/i18n/cli/fr.yml index ea9b9f0..b354e85 100644 --- a/i18n/cli/fr.yml +++ b/i18n/cli/fr.yml @@ -30,6 +30,7 @@ fr: not_authorized: "Vous n'avez pas les autorisations d'accès au fichier distant!" upload: "Impossible d'envoyer le fichier sur le serveur!" unknown: "Une erreur inconnue est survenue!" + unknown_type: "Le type de synchronisation est inconnu" warning: select: "Votre choix n'est pas un élément valide!" From 724fc1752af4661f978a0194fd03d6942bef8020 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Thu, 19 Mar 2015 23:17:01 +0100 Subject: [PATCH 174/531] lib/Sync.rb --- lib/Sync.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/Sync.rb b/lib/Sync.rb index 35c516a..e054330 100644 --- a/lib/Sync.rb +++ b/lib/Sync.rb @@ -121,9 +121,9 @@ module MPW raise @local.error_msg if not @local.add(item) end end - - raise @sync.error_msg if not @sync.update(@config.file_gpg) + raise @mpw.error_msg if not @local.encrypt + raise @sync.error_msg if not @sync.update(@config.file_gpg) return true rescue Exception => e From eb040310c34fb8a833c4ab29da75b807877ef55d Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Thu, 19 Mar 2015 23:17:40 +0100 Subject: [PATCH 175/531] update translation --- i18n/cli/en.yml | 2 ++ i18n/cli/fr.yml | 2 ++ 2 files changed, 4 insertions(+) diff --git a/i18n/cli/en.yml b/i18n/cli/en.yml index dfa5835..6ba6c08 100644 --- a/i18n/cli/en.yml +++ b/i18n/cli/en.yml @@ -1,6 +1,8 @@ --- en: error: + client: + no_authorized: "You aren't authorized." config: write: "Can't write the config file!" check: "Checkconfig failed!" diff --git a/i18n/cli/fr.yml b/i18n/cli/fr.yml index b354e85..1410993 100644 --- a/i18n/cli/fr.yml +++ b/i18n/cli/fr.yml @@ -1,6 +1,8 @@ --- fr: error: + client: + no_authorized: "Vous n'êtes pas autorisé!" config: write: "Impossible d'écrire le fichier de configuration!" check: "Le fichier de configuration est invalide!" From ddbc20f635d5019fb9c619654c43a1c60a5d87b3 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sun, 22 Mar 2015 22:38:35 +0100 Subject: [PATCH 176/531] no return empty result --- lib/MPW.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/MPW.rb b/lib/MPW.rb index 45f355e..0677af9 100644 --- a/lib/MPW.rb +++ b/lib/MPW.rb @@ -131,6 +131,8 @@ module MPW protocol = options[:protocol].to_s.downcase @data.each do |item| + next if item.empty? + next if not group.empty? and not group.eql?(item.group.downcase) next if not protocol.empty? and not protocol.eql?(item.protocol.downcase) From 465b60fd41138721096d600009fdccd29834ac60 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sun, 22 Mar 2015 22:43:18 +0100 Subject: [PATCH 177/531] fix multiple bug in sync --- lib/Item.rb | 8 +++++--- lib/Sync.rb | 30 ++++++++++++++++-------------- 2 files changed, 21 insertions(+), 17 deletions(-) diff --git a/lib/Item.rb b/lib/Item.rb index c14d0bd..ca4555e 100644 --- a/lib/Item.rb +++ b/lib/Item.rb @@ -36,8 +36,10 @@ module MPW @id = generate_id @created = Time.now.to_i else - @id = options[:id] - @created = options[:created] + @id = options[:id] + @created = options[:created] + @last_edit = options[:last_edit] + options[:no_update_last_edit] = true end update(options) @@ -60,7 +62,7 @@ module MPW @password = options[:password] if options.has_key?(:password) @port = options[:port].to_i if options.has_key?(:port) and not options[:port].to_s.empty? @comment = options[:comment] if options.has_key?(:comment) - @last_edit = Time.now.to_i + @last_edit = Time.now.to_i if not options.has_key?(:no_update_last_edit) return true end diff --git a/lib/Sync.rb b/lib/Sync.rb index e054330..beb7100 100644 --- a/lib/Sync.rb +++ b/lib/Sync.rb @@ -70,7 +70,6 @@ module MPW def sync if not @remote.to_s.empty? @local.list.each do |item| - j = 0 update = false # Update item @@ -89,12 +88,10 @@ module MPW end update = true - item.delete + r.delete break end - - j += 1 end # Delete an old item @@ -106,24 +103,29 @@ module MPW # Add item @remote.list.each do |r| + puts r.last_edit if r.last_edit > @config.last_update - item = Item.new(id: r.id, - name: r.name, - group: r.group, - host: r.host, - protocol: r.protocol, - user: r.user, - password: r.password, - port: r.port, - comment: r.comment, - created: r.created + item = Item.new(id: r.id, + name: r.name, + group: r.group, + host: r.host, + protocol: r.protocol, + user: r.user, + password: r.password, + port: r.port, + comment: r.comment, + created: r.created + last_edit: r.last_edit ) + puts item.last_edit raise @local.error_msg if not @local.add(item) end end raise @mpw.error_msg if not @local.encrypt raise @sync.error_msg if not @sync.update(@config.file_gpg) + + @config.set_last_update return true rescue Exception => e From 9225e360b9d65de903790020716ec45086befbc3 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sun, 22 Mar 2015 22:45:43 +0100 Subject: [PATCH 178/531] fix syntax error --- lib/Sync.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/Sync.rb b/lib/Sync.rb index beb7100..2c6db1b 100644 --- a/lib/Sync.rb +++ b/lib/Sync.rb @@ -103,7 +103,6 @@ module MPW # Add item @remote.list.each do |r| - puts r.last_edit if r.last_edit > @config.last_update item = Item.new(id: r.id, name: r.name, @@ -114,7 +113,7 @@ module MPW password: r.password, port: r.port, comment: r.comment, - created: r.created + created: r.created, last_edit: r.last_edit ) puts item.last_edit From 7a222798c5b0ee7cb02199ff88965b9a363f8695 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Mon, 11 May 2015 19:15:33 +0200 Subject: [PATCH 179/531] fix tests --- test/test_mpw.rb | 11 +++++++++++ test/tests.rb | 4 ++++ 2 files changed, 15 insertions(+) create mode 100644 test/tests.rb diff --git a/test/test_mpw.rb b/test/test_mpw.rb index e8b51bf..899b366 100644 --- a/test/test_mpw.rb +++ b/test/test_mpw.rb @@ -177,4 +177,15 @@ class TestMPW < Test::Unit::TestCase assert_equal(@fixtures['add_new']['port'].to_i, item.port) assert_equal(@fixtures['add_new']['comment'], item.comment) end + + def test_15_search + import_file = 'files/test_import.yml' + + assert(@mpw.import(import_file, :yaml)) + assert_equal(2, @mpw.list.length) + + assert_equal(1, @mpw.list(group: @fixtures['add_new']['group']).length) + assert_equal(1, @mpw.list(protocol: @fixtures['add_new']['protocol']).length) + assert_equal(2, @mpw.list(search: @fixtures['add_new']['name'][0..-2]).length) + end end diff --git a/test/tests.rb b/test/tests.rb new file mode 100644 index 0000000..d3735f5 --- /dev/null +++ b/test/tests.rb @@ -0,0 +1,4 @@ +#!/usr/bin/ruby + +require_relative 'test_mpw.rb' +require_relative 'test_item.rb' From 2d7dacb02c88c866726a19524b089efff1b87ec8 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Mon, 11 May 2015 19:17:12 +0200 Subject: [PATCH 180/531] fix bug sync when a device add an iten whitout sync --- lib/Config.rb | 30 +++++++++++++++--------------- lib/Item.rb | 7 +++++++ lib/Sync.rb | 37 +++++++++++++++++++------------------ 3 files changed, 41 insertions(+), 33 deletions(-) diff --git a/lib/Config.rb b/lib/Config.rb index 7663809..698efe1 100644 --- a/lib/Config.rb +++ b/lib/Config.rb @@ -23,7 +23,7 @@ module MPW attr_accessor :sync_user attr_accessor :sync_pwd attr_accessor :sync_path - attr_accessor :last_update + attr_accessor :last_sync attr_accessor :dir_config # Constructor @@ -82,7 +82,7 @@ module MPW 'sync_user' => sync_user, 'sync_pwd' => sync_pwd, 'sync_path' => sync_path, - 'last_update' => 0 + 'last_sync' => 0 } } @@ -139,17 +139,17 @@ module MPW # @rtrn: true if the config file is correct def checkconfig config = YAML::load_file(@file_config) - @key = config['config']['key'] - @share_keys = config['config']['share_keys'] - @lang = config['config']['lang'] - @file_gpg = config['config']['file_gpg'] - @sync_type = config['config']['sync_type'] - @sync_host = config['config']['sync_host'] - @sync_port = config['config']['sync_port'] - @sync_user = config['config']['sync_user'] - @sync_pwd = config['config']['sync_pwd'] - @sync_path = config['config']['sync_path'] - @last_update = config['config']['last_update'].to_i + @key = config['config']['key'] + @share_keys = config['config']['share_keys'] + @lang = config['config']['lang'] + @file_gpg = config['config']['file_gpg'] + @sync_type = config['config']['sync_type'] + @sync_host = config['config']['sync_host'] + @sync_port = config['config']['sync_port'] + @sync_user = config['config']['sync_user'] + @sync_pwd = config['config']['sync_pwd'] + @sync_path = config['config']['sync_path'] + @last_sync = config['config']['last_sync'].to_i if @key.empty? or @file_gpg.empty? @error_msg = I18n.t('error.config.check') @@ -203,7 +203,7 @@ module MPW # Set the last update when there is a sync # @rtrn: true is the file has been updated - def set_last_update + def set_last_sync config = {'config' => {'key' => @key, 'share_keys' => @share_keys, 'lang' => @lang, @@ -214,7 +214,7 @@ module MPW 'sync_user' => @sync_user, 'sync_pwd' => @sync_pwd, 'sync_path' => @sync_path, - 'last_update' => Time.now.to_i + 'last_sync' => Time.now.to_i } } diff --git a/lib/Item.rb b/lib/Item.rb index ca4555e..666d5b3 100644 --- a/lib/Item.rb +++ b/lib/Item.rb @@ -20,6 +20,7 @@ module MPW attr_accessor :port attr_accessor :comment attr_accessor :last_edit + attr_accessor :last_sync attr_accessor :created # Constructor @@ -67,6 +68,11 @@ module MPW return true end + # Update last_sync + def set_last_sync + @last_sync = Time.now.to_i + end + # Delete all data # @rtrn: true def delete @@ -81,6 +87,7 @@ module MPW @comment = nil @created = nil @last_edit = nil + @last_sync = nil return true end diff --git a/lib/Sync.rb b/lib/Sync.rb index 2c6db1b..ce98596 100644 --- a/lib/Sync.rb +++ b/lib/Sync.rb @@ -68,34 +68,32 @@ module MPW # Sync remote data and local data # raise an exception if there is a problem def sync + if not @remote.to_s.empty? @local.list.each do |item| - update = false - - # Update item @remote.list.each do |r| + + # Update item if item.id == r.id if item.last_edit < r.last_edit - raise item.error_msg if not item.update(name: r.name, - group: r.group, - host: r.host, - protocol: r.protocol, - user: r.user, - password: r.password, - port: r.port, - comment: r.comment + raise item.error_msg if not item.update(name: r.name, + group: r.group, + host: r.host, + protocol: r.protocol, + user: r.user, + password: r.password, + port: r.port, + comment: r.comment ) end - update = true r.delete - break end end - - # Delete an old item - if not update and item.last_edit < @config.last_update + + # Remove an old item + if item.last_sync < @config.last_sync item.delete end end @@ -116,15 +114,18 @@ module MPW created: r.created, last_edit: r.last_edit ) - puts item.last_edit raise @local.error_msg if not @local.add(item) end end + @local.list.each do |item| + item.set_last_sync + end + raise @mpw.error_msg if not @local.encrypt raise @sync.error_msg if not @sync.update(@config.file_gpg) - @config.set_last_update + @config.set_last_sync return true rescue Exception => e From b9ebe9de3f7f03429c30393f9f578d6975e459c4 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Mon, 11 May 2015 19:23:59 +0200 Subject: [PATCH 181/531] fix bug --- lib/Sync.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/Sync.rb b/lib/Sync.rb index ce98596..792de3d 100644 --- a/lib/Sync.rb +++ b/lib/Sync.rb @@ -93,7 +93,7 @@ module MPW end # Remove an old item - if item.last_sync < @config.last_sync + if item.last_sync.to_i < @config.last_sync item.delete end end @@ -128,7 +128,7 @@ module MPW @config.set_last_sync return true - rescue Exception => e +# rescue Exception => e @error_msg = "#{I18n.t('error.sync.unknown')} #{e}" return false end From 9bd5024fef459c6d984ddbf90c46b3f9eb43ddf8 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Mon, 11 May 2015 19:25:25 +0200 Subject: [PATCH 182/531] fix bug~ --- lib/Sync.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Sync.rb b/lib/Sync.rb index 792de3d..4bff9f0 100644 --- a/lib/Sync.rb +++ b/lib/Sync.rb @@ -101,7 +101,7 @@ module MPW # Add item @remote.list.each do |r| - if r.last_edit > @config.last_update + if r.last_edit > @config.last_sync item = Item.new(id: r.id, name: r.name, group: r.group, From 3da68967f977de56317a42cb06860180364ec5ea Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Mon, 11 May 2015 19:30:17 +0200 Subject: [PATCH 183/531] fix import default yaml --- lib/UI/Cli.rb | 4 +--- mpw | 1 + 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/UI/Cli.rb b/lib/UI/Cli.rb index 35f3399..7c5fc74 100644 --- a/lib/UI/Cli.rb +++ b/lib/UI/Cli.rb @@ -32,7 +32,7 @@ class Cli raise(@sync.error_msg) if not @sync.sync return true - rescue Exception => e +# rescue Exception => e puts "#{I18n.t('display.error')} #7: #{e}".red return false end @@ -298,10 +298,8 @@ class Cli if not force result = @mpw.import_preview(file, type) - puts result if result.is_a?(Array) and not result.empty? result.each do |r| - puts r.class display_item(r) end diff --git a/mpw b/mpw index ad632b1..bda314c 100755 --- a/mpw +++ b/mpw @@ -92,6 +92,7 @@ OptionParser.new do |opts| opts.on('-i', '--import FILE', I18n.t('option.import')) do |file| options[:import] = file + options[:type] = :yaml end opts.on('-f', '--force', I18n.t('option.force')) do From 59395ce7db68ddeb648edf516ecacbd1b69b1b87 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Mon, 11 May 2015 19:31:51 +0200 Subject: [PATCH 184/531] fix bug in sync --- lib/Sync.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Sync.rb b/lib/Sync.rb index 4bff9f0..bfb4d88 100644 --- a/lib/Sync.rb +++ b/lib/Sync.rb @@ -93,7 +93,7 @@ module MPW end # Remove an old item - if item.last_sync.to_i < @config.last_sync + if item.last_sync.to_i < @config.last_sync and item.last_edit < @config.last_sync item.delete end end From 6e9b4a50875bb08bc0cc7e9a1393ec90d174edd1 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Mon, 11 May 2015 20:12:23 +0200 Subject: [PATCH 185/531] fix bug in sync --- lib/Sync.rb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/Sync.rb b/lib/Sync.rb index bfb4d88..051a0c2 100644 --- a/lib/Sync.rb +++ b/lib/Sync.rb @@ -71,6 +71,7 @@ module MPW if not @remote.to_s.empty? @local.list.each do |item| + update = true @remote.list.each do |r| # Update item @@ -88,12 +89,14 @@ module MPW end r.delete + update = true + break end end # Remove an old item - if item.last_sync.to_i < @config.last_sync and item.last_edit < @config.last_sync + if not update and item.last_sync.to_i < @config.last_sync and item.last_edit < @config.last_sync item.delete end end From 1f4509597baf74e4f994e44ee8e145313cd75f18 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Mon, 11 May 2015 20:20:18 +0200 Subject: [PATCH 186/531] remove test --- lib/Sync.rb | 2 +- lib/UI/Cli.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/Sync.rb b/lib/Sync.rb index 051a0c2..78fcce8 100644 --- a/lib/Sync.rb +++ b/lib/Sync.rb @@ -131,7 +131,7 @@ module MPW @config.set_last_sync return true -# rescue Exception => e + rescue Exception => e @error_msg = "#{I18n.t('error.sync.unknown')} #{e}" return false end diff --git a/lib/UI/Cli.rb b/lib/UI/Cli.rb index 7c5fc74..9352ed9 100644 --- a/lib/UI/Cli.rb +++ b/lib/UI/Cli.rb @@ -32,7 +32,7 @@ class Cli raise(@sync.error_msg) if not @sync.sync return true -# rescue Exception => e + rescue Exception => e puts "#{I18n.t('display.error')} #7: #{e}".red return false end From e22ebecf36ef3c8f52311ffac2960f780c8126b9 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Mon, 11 May 2015 20:26:58 +0200 Subject: [PATCH 187/531] remove puts --- lib/Config.rb | 1 - lib/Sync/SSH.rb | 2 -- 2 files changed, 3 deletions(-) diff --git a/lib/Config.rb b/lib/Config.rb index 698efe1..d2b02a9 100644 --- a/lib/Config.rb +++ b/lib/Config.rb @@ -159,7 +159,6 @@ module MPW return true rescue Exception => e - puts e @error_msg = "#{I18n.t('error.config.check')}\n#{e}" return false end diff --git a/lib/Sync/SSH.rb b/lib/Sync/SSH.rb index ddb00b5..632e292 100644 --- a/lib/Sync/SSH.rb +++ b/lib/Sync/SSH.rb @@ -48,8 +48,6 @@ module MPW def get(file_tmp) return false if not @enable - puts @path - puts file_tmp Net::SFTP.start(@host, @user, password: @password, port: @port) do |sftp| sftp.lstat(@path) do |response| sftp.download!(@path, file_tmp) if response.ok? From 107e9047dd946c1fd03905398c6af1e13197b95b Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Mon, 11 May 2015 21:24:21 +0200 Subject: [PATCH 188/531] fix bug --- lib/Sync.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Sync.rb b/lib/Sync.rb index 78fcce8..22a289e 100644 --- a/lib/Sync.rb +++ b/lib/Sync.rb @@ -71,7 +71,7 @@ module MPW if not @remote.to_s.empty? @local.list.each do |item| - update = true + update = false @remote.list.each do |r| # Update item From ccd188bc2f5c6aa6c5df59efae7563e27e3bdfc2 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sun, 21 Jun 2015 23:45:25 +0200 Subject: [PATCH 189/531] add install with gem --- CHANGELOG | 6 ++++++ Makefile | 23 ----------------------- VERSION | 2 +- mpw => bin/mpw | 9 ++++----- mpw-server => bin/mpw-server | 4 ++-- mpw-ssh => bin/mpw-ssh | 13 ++++++------- lib/{Config.rb => mpw/config.rb} | 0 lib/{Item.rb => mpw/item.rb} | 0 lib/{MPW.rb => mpw/mpw.rb} | 3 +-- lib/{Server.rb => mpw/server.rb} | 0 lib/{Sync.rb => mpw/sync.rb} | 11 +++++------ lib/{Sync/FTP.rb => mpw/sync/ftp.rb} | 0 lib/{Sync/SyncMPW.rb => mpw/sync/mpw.rb} | 0 lib/{Sync/SSH.rb => mpw/sync/ssh.rb} | 0 lib/{UI/Cli.rb => mpw/ui/cli.rb} | 7 +++---- lib/{UI/CliSSH.rb => mpw/ui/clissh.rb} | 2 +- mpw.gemspec | 19 +++++++++++++++++++ 17 files changed, 48 insertions(+), 51 deletions(-) delete mode 100644 Makefile rename mpw => bin/mpw (96%) rename mpw-server => bin/mpw-server (95%) rename mpw-ssh => bin/mpw-ssh (94%) rename lib/{Config.rb => mpw/config.rb} (100%) rename lib/{Item.rb => mpw/item.rb} (100%) rename lib/{MPW.rb => mpw/mpw.rb} (99%) rename lib/{Server.rb => mpw/server.rb} (100%) rename lib/{Sync.rb => mpw/sync.rb} (95%) rename lib/{Sync/FTP.rb => mpw/sync/ftp.rb} (100%) rename lib/{Sync/SyncMPW.rb => mpw/sync/mpw.rb} (100%) rename lib/{Sync/SSH.rb => mpw/sync/ssh.rb} (100%) rename lib/{UI/Cli.rb => mpw/ui/cli.rb} (99%) rename lib/{UI/CliSSH.rb => mpw/ui/clissh.rb} (96%) create mode 100644 mpw.gemspec diff --git a/CHANGELOG b/CHANGELOG index 21cf7ae..1ce4809 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,4 +1,10 @@ = CHANGELOG = +== v2.0.0 == + +* change format csv to yaml +* easy install with gem +* add sync with ftp and ssh +* many improvement == v1.1.0 == diff --git a/Makefile b/Makefile deleted file mode 100644 index cb1fa7a..0000000 --- a/Makefile +++ /dev/null @@ -1,23 +0,0 @@ -all: - $(info 'Nothing todo!') - $(info 'Use make install or make uninstall') - -dep-ubuntu: - apt-get install ruby ruby-gpgme ruby-highline ruby-i18n ruby-locale - -install: - mkdir -p /usr/local/mpw - cp -r ./lib /usr/local/mpw/ - cp -r ./i18n /usr/local/mpw/ - cp ./mpw /usr/local/mpw/ - ln -snf /usr/local/mpw/mpw /usr/local/bin/ - cp ./mpw-server /usr/local/mpw/ - ln -snf /usr/local/mpw/mpw-server /usr/local/bin/mpw-server - cp ./mpw-ssh /usr/local/mpw/ - ln -snf /usr/local/mpw/mpw-ssh /usr/local/bin/mpw-ssh - -uninstall: - rm /usr/local/bin/mpw-server - rm /usr/local/bin/mpw - rm /usr/local/bin/mpw-ssh - rm -rf /usr/local/mpw diff --git a/VERSION b/VERSION index 5d32997..227cea2 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.0.0 - dev +2.0.0 diff --git a/mpw b/bin/mpw similarity index 96% rename from mpw rename to bin/mpw index bda314c..d8a76c7 100755 --- a/mpw +++ b/bin/mpw @@ -9,10 +9,9 @@ require 'pathname' require 'locale' require 'set' require 'i18n' - -require_relative 'lib/UI/Cli' -require_relative 'lib/Config' -require_relative 'lib/MPW' +require 'mpw/mpw' +require 'mpw/config' +require 'mpw/ui/cli' # --------------------------------------------------------- # # Set local @@ -27,7 +26,7 @@ end APP_ROOT = File.dirname(Pathname.new(__FILE__).realpath) I18n::Backend::Simple.send(:include, I18n::Backend::Fallbacks) -I18n.load_path = Dir["#{APP_ROOT}/i18n/cli/*.yml"] +I18n.load_path = Dir["#{APP_ROOT}/../i18n/cli/*.yml"] I18n.default_locale = :en I18n.locale = lang.to_sym diff --git a/mpw-server b/bin/mpw-server similarity index 95% rename from mpw-server rename to bin/mpw-server index 30f6105..3a7ce5a 100755 --- a/mpw-server +++ b/bin/mpw-server @@ -8,9 +8,9 @@ require 'optparse' require 'pathname' require 'locale' require 'i18n' +require 'mpw/server' APP_ROOT = File.dirname(Pathname.new(__FILE__).realpath) -require "#{APP_ROOT}/lib/Server.rb" # --------------------------------------------------------- # # Set local @@ -23,7 +23,7 @@ if defined?(I18n.enforce_available_locales) end I18n::Backend::Simple.send(:include, I18n::Backend::Fallbacks) -I18n.load_path = Dir["#{APP_ROOT}/i18n/server/*.yml"] +I18n.load_path = Dir["#{APP_ROOT}/../i18n/server/*.yml"] I18n.default_locale = :en I18n.locale = lang.to_sym diff --git a/mpw-ssh b/bin/mpw-ssh similarity index 94% rename from mpw-ssh rename to bin/mpw-ssh index 89a8c99..b5f1252 100755 --- a/mpw-ssh +++ b/bin/mpw-ssh @@ -8,23 +8,22 @@ require 'optparse' require 'pathname' require 'locale' require 'i18n' - -APP_ROOT = File.dirname(Pathname.new(__FILE__).realpath) -require "#{APP_ROOT}/lib/UI/CliSSH" -require "#{APP_ROOT}/lib/Config" - -lang = Locale::Tag.parse(ENV['LANG']).to_simple.to_s[0..1] +require 'mpw/ui/clissh' +require 'mpw/config' # --------------------------------------------------------- # # Set local # --------------------------------------------------------- # +APP_ROOT = File.dirname(Pathname.new(__FILE__).realpath) +lang = Locale::Tag.parse(ENV['LANG']).to_simple.to_s[0..1] + if defined?(I18n.enforce_available_locales) I18n.enforce_available_locales = true end I18n::Backend::Simple.send(:include, I18n::Backend::Fallbacks) -I18n.load_path = Dir["#{APP_ROOT}/i18n/cli/*.yml"] +I18n.load_path = Dir["#{APP_ROOT}/../i18n/cli/*.yml"] I18n.default_locale = :en I18n.locale = lang.to_sym diff --git a/lib/Config.rb b/lib/mpw/config.rb similarity index 100% rename from lib/Config.rb rename to lib/mpw/config.rb diff --git a/lib/Item.rb b/lib/mpw/item.rb similarity index 100% rename from lib/Item.rb rename to lib/mpw/item.rb diff --git a/lib/MPW.rb b/lib/mpw/mpw.rb similarity index 99% rename from lib/MPW.rb rename to lib/mpw/mpw.rb index 0677af9..57a6bce 100644 --- a/lib/MPW.rb +++ b/lib/mpw/mpw.rb @@ -8,8 +8,7 @@ require 'csv' require 'i18n' require 'fileutils' require 'yaml' - -require_relative './Item' +require 'mpw/item' module MPW class MPW diff --git a/lib/Server.rb b/lib/mpw/server.rb similarity index 100% rename from lib/Server.rb rename to lib/mpw/server.rb diff --git a/lib/Sync.rb b/lib/mpw/sync.rb similarity index 95% rename from lib/Sync.rb rename to lib/mpw/sync.rb index 22a289e..3e18d32 100644 --- a/lib/Sync.rb +++ b/lib/mpw/sync.rb @@ -7,9 +7,8 @@ require 'rubygems' require 'i18n' require 'yaml' require 'tempfile' - -require_relative './MPW' -require_relative './Item' +require 'mpw/mpw' +require 'mpw/item' module MPW class Sync @@ -32,13 +31,13 @@ module MPW def get_remote case @config.sync_type when 'mpw' - require "#{APP_ROOT}/lib/Sync/SyncMPW" + require 'mpw/sync/mpw' @sync = SyncMPW.new(@config.sync_host, @config.sync_user, @config.sync_pwd, @config.sync_path, @config.sync_port) when 'sftp', 'scp', 'ssh' - require "#{APP_ROOT}/lib/Sync/SSH" + require 'mpw/sync/ssh' @sync = SyncSSH.new(@config.sync_host, @config.sync_user, @config.sync_pwd, @config.sync_path, @config.sync_port) when 'ftp' - require "#{APP_ROOT}/lib/Sync/FTP" + require 'mpw/sync/ftp' @sync = SyncFTP.new(@config.sync_host, @config.sync_user, @config.sync_pwd, @config.sync_path, @config.sync_port) else @error_msg = I18n.t('error.unknown_type') diff --git a/lib/Sync/FTP.rb b/lib/mpw/sync/ftp.rb similarity index 100% rename from lib/Sync/FTP.rb rename to lib/mpw/sync/ftp.rb diff --git a/lib/Sync/SyncMPW.rb b/lib/mpw/sync/mpw.rb similarity index 100% rename from lib/Sync/SyncMPW.rb rename to lib/mpw/sync/mpw.rb diff --git a/lib/Sync/SSH.rb b/lib/mpw/sync/ssh.rb similarity index 100% rename from lib/Sync/SSH.rb rename to lib/mpw/sync/ssh.rb diff --git a/lib/UI/Cli.rb b/lib/mpw/ui/cli.rb similarity index 99% rename from lib/UI/Cli.rb rename to lib/mpw/ui/cli.rb index 9352ed9..3875be5 100644 --- a/lib/UI/Cli.rb +++ b/lib/mpw/ui/cli.rb @@ -9,10 +9,9 @@ require 'pathname' require 'readline' require 'i18n' require 'colorize' - -require_relative '../Sync' -require_relative '../MPW' -require_relative '../Item' +require 'mpw/sync' +require 'mpw/mpw' +require 'mpw/item' class Cli diff --git a/lib/UI/CliSSH.rb b/lib/mpw/ui/clissh.rb similarity index 96% rename from lib/UI/CliSSH.rb rename to lib/mpw/ui/clissh.rb index b32097e..83d1d3b 100644 --- a/lib/UI/CliSSH.rb +++ b/lib/mpw/ui/clissh.rb @@ -3,7 +3,7 @@ # mail: nishiki@yaegashi.fr # info: a simple script who manage your passwords -require "#{APP_ROOT}/lib/UI/Cli" +require 'mpw/ui/cli' class CliSSH < Cli diff --git a/mpw.gemspec b/mpw.gemspec new file mode 100644 index 0000000..b930a24 --- /dev/null +++ b/mpw.gemspec @@ -0,0 +1,19 @@ +# coding: utf-8 +lib = File.expand_path('../lib', __FILE__) +$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) + +Gem::Specification.new do |spec| + spec.name = 'mpw' + spec.version = File.open('VERSION').read + spec.authors = ['nishiki'] + spec.email = ['gems@yae.im'] + spec.summary = 'Manage your password' + spec.description = 'Save and read your password with gpg' + spec.homepage = 'https://github.com/nishiki/checkupdate' + spec.license = 'GPL' + + spec.files = `git ls-files -z`.split("\x0") + spec.executables = ['mpw', 'mpw-server'] + spec.test_files = spec.files.grep(%r{^(test|spec|features)/}) + spec.require_paths = ['lib'] +end From d367efe13d4fc215c0431f14ea84256bc67e5143 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sun, 21 Jun 2015 23:48:14 +0200 Subject: [PATCH 190/531] fix readme --- README.md | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 1fc4d7e..c5edca4 100644 --- a/README.md +++ b/README.md @@ -8,20 +8,7 @@ MPW can synchronize your password with a MPW Server or via SSH or via FTP. You must generate a GPG Key with GPG or with Seahorse (GUI on linux). This program work with ruby >= 1.9 -* install ruby on your computer -* gem install bundler -* bundle install -or -* bundle install --without ssh # if you don't want synchronize your password via SSH - -## On Debian/Ubuntu: - -* apt-get install ruby ruby-gpgme ruby-highline ruby-i18n ruby-locale - -If you want to synchronize your passwords via SSH/SCP: -* apt-get install ruby-net-ssh ruby-net-scp - -For mpw-ssh: -* apt-get install sshpass +* install ruby and rubygems on your computer +* gem install mpw From 7d71dded68fd2e2a69c191c70e58e627a5a5a81b Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Mon, 22 Jun 2015 20:46:43 +0200 Subject: [PATCH 191/531] fix homepage --- mpw.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mpw.gemspec b/mpw.gemspec index b930a24..21c33ed 100644 --- a/mpw.gemspec +++ b/mpw.gemspec @@ -9,7 +9,7 @@ Gem::Specification.new do |spec| spec.email = ['gems@yae.im'] spec.summary = 'Manage your password' spec.description = 'Save and read your password with gpg' - spec.homepage = 'https://github.com/nishiki/checkupdate' + spec.homepage = 'https://github.com/nishiki/manage-password' spec.license = 'GPL' spec.files = `git ls-files -z`.split("\x0") From eb0847b16bebf5a0f6e3cfc6af687d74edf87b55 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Tue, 23 Jun 2015 22:10:08 +0200 Subject: [PATCH 192/531] fix mpw-ssh --- README.md | 4 ++++ VERSION | 2 +- lib/mpw/ui/clissh.rb | 12 ++++++------ mpw.gemspec | 2 +- 4 files changed, 12 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index c5edca4..cbf6e64 100644 --- a/README.md +++ b/README.md @@ -11,4 +11,8 @@ This program work with ruby >= 1.9 * install ruby and rubygems on your computer * gem install mpw +If you want use mpw-ssh, you must install sshpass +# How to use + +mpw -h diff --git a/VERSION b/VERSION index 227cea2..38f77a6 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.0.0 +2.0.1 diff --git a/lib/mpw/ui/clissh.rb b/lib/mpw/ui/clissh.rb index 83d1d3b..0bf7bb0 100644 --- a/lib/mpw/ui/clissh.rb +++ b/lib/mpw/ui/clissh.rb @@ -12,15 +12,15 @@ class CliSSH < Cli # Connect to SSH # args: search -> string to search def ssh(search) - result = @mpw.search(search, nil, 'ssh') + result = @mpw.list(search: search, protocol: 'ssh') if result.length > 0 - result.each do |r| - server = @server.nil? ? r[:host] : @server - port = @port.nil? ? r[:port] : @port - login = @login.nil? ? r[:login] : @login + result.each do |item| + server = @server.nil? ? item.host : @server + port = @port.nil? ? item.port : @port + login = @login.nil? ? item.user : @login - passwd = r[:password] + passwd = item.password if port.nil? and port.empty? port = 22 diff --git a/mpw.gemspec b/mpw.gemspec index 21c33ed..aaf249a 100644 --- a/mpw.gemspec +++ b/mpw.gemspec @@ -13,7 +13,7 @@ Gem::Specification.new do |spec| spec.license = 'GPL' spec.files = `git ls-files -z`.split("\x0") - spec.executables = ['mpw', 'mpw-server'] + spec.executables = ['mpw', 'mpw-server', 'mpw-ssh'] spec.test_files = spec.files.grep(%r{^(test|spec|features)/}) spec.require_paths = ['lib'] end From 631f693d06d4e5821f98a2d0f3623fd6137095ca Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sun, 19 Jul 2015 21:51:05 +0200 Subject: [PATCH 193/531] fix dependancy --- VERSION | 2 +- mpw.gemspec | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 38f77a6..e9307ca 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.0.1 +2.0.2 diff --git a/mpw.gemspec b/mpw.gemspec index aaf249a..d004d34 100644 --- a/mpw.gemspec +++ b/mpw.gemspec @@ -16,4 +16,11 @@ Gem::Specification.new do |spec| spec.executables = ['mpw', 'mpw-server', 'mpw-ssh'] spec.test_files = spec.files.grep(%r{^(test|spec|features)/}) spec.require_paths = ['lib'] + + spec.add_dependency "i18n", "~> 0.6", ">= 0.6.9" + spec.add_dependency "gpgme" + spec.add_dependency "highline" + spec.add_dependency "locale" + spec.add_dependency "colorize" + spec.add_dependency "net-sftp" end From 6b14e8f881092fb5915759a43e9a06340ed59b3c Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <adrien.waksberg@believedigital.com> Date: Sun, 27 Sep 2015 09:13:43 +0200 Subject: [PATCH 194/531] add no-sync option --- bin/mpw | 7 ++++++- i18n/cli/en.yml | 1 + i18n/cli/fr.yml | 1 + lib/mpw/ui/cli.rb | 9 ++++++++- 4 files changed, 16 insertions(+), 2 deletions(-) diff --git a/bin/mpw b/bin/mpw index d8a76c7..c14c5af 100755 --- a/bin/mpw +++ b/bin/mpw @@ -37,6 +37,7 @@ I18n.locale = lang.to_sym options = {} options[:force] = false options[:format] = false +options[:sync] = true options[:group] = nil options[:config] = nil @@ -98,6 +99,10 @@ OptionParser.new do |opts| options[:force] = true end + opts.on('-N', '--no-sync', I18n.t('option.no_sync')) do + options[:sync] = false + end + opts.on('-G', '--generate-password [LENGTH]', I18n.t('option.generate_password')) do |length| puts MPW::MPW::password(length) exit 0 @@ -126,7 +131,7 @@ elsif not config.check_gpg_key? end cli.decrypt -cli.sync +cli.sync(options[:sync]) # Display the item's informations if not options[:show].nil? diff --git a/i18n/cli/en.yml b/i18n/cli/en.yml index 6ba6c08..bd84171 100644 --- a/i18n/cli/en.yml +++ b/i18n/cli/en.yml @@ -52,6 +52,7 @@ en: type: "Data's type export file [csv|yaml]" import: "Import item since a yaml or csv file" force: "Force an action" + no_sync: "Disable synchronization with the server" format: "Change the display items format by an alternative format" generate_password: "Generate a random password (default 8 characters)" help: "Show this help message" diff --git a/i18n/cli/fr.yml b/i18n/cli/fr.yml index 1410993..e9790c0 100644 --- a/i18n/cli/fr.yml +++ b/i18n/cli/fr.yml @@ -52,6 +52,7 @@ fr: type: "Format des données du fichier d'export [csv|yaml]" import: "Importe des éléments depuis un fichier yaml ou csv" force: "Force une action, l'action ne demandera pas de confirmation" + no_sync: "Désactive la synchronisation avec le serveur" format: "Change le format d'affichage des éléments par un alternatif" generate_password: "Génére un mot de passe aléatoire (défaut 8 caractères)" help: "Affiche ce message d'aide" diff --git a/lib/mpw/ui/cli.rb b/lib/mpw/ui/cli.rb index 3875be5..3bf9c51 100644 --- a/lib/mpw/ui/cli.rb +++ b/lib/mpw/ui/cli.rb @@ -23,8 +23,15 @@ class Cli end # Sync the data with the server + # @args: allow_sync -> allow or disable sync (boolean) # @rtnr: true if the synchro is finish - def sync + def sync(allow_sync=nil) + if not allow_sync.nil? + @allow_sync = allow_sync + end + + return true if not @allow_sync + @sync = MPW::Sync.new(@config, @mpw, @password) raise(@sync.error_msg) if not @sync.get_remote From 0268c604843d9c2f2798b98a8296ea6e14ee5f99 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <adrien.waksberg@believedigital.com> Date: Sun, 27 Sep 2015 09:16:56 +0200 Subject: [PATCH 195/531] add no-sync option --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index e9307ca..50ffc5a 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.0.2 +2.0.3 From 408ee95bcce7db8a9b0c8263e3f0623b9e886c86 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Thu, 5 May 2016 20:19:25 +0200 Subject: [PATCH 196/531] rewrite mpw for use a new file storage format --- bin/mpw | 22 +- lib/mpw/config.rb | 356 ++++++++++++----------------- lib/mpw/item.rb | 174 +++++++------- lib/mpw/mpw.rb | 569 +++++++++++++++++++++------------------------- lib/mpw/ui/cli.rb | 150 ++++-------- 5 files changed, 532 insertions(+), 739 deletions(-) diff --git a/bin/mpw b/bin/mpw index c14c5af..f36bc87 100755 --- a/bin/mpw +++ b/bin/mpw @@ -1,7 +1,6 @@ #!/usr/bin/ruby # author: nishiki # mail: nishiki@yaegashi.fr -# info: a simple script who manage your passwords require 'rubygems' require 'optparse' @@ -11,7 +10,7 @@ require 'set' require 'i18n' require 'mpw/mpw' require 'mpw/config' -require 'mpw/ui/cli' +require 'mpw/cli' # --------------------------------------------------------- # # Set local @@ -77,26 +76,12 @@ OptionParser.new do |opts| options[:setup] = true end - opts.on('-p', '--protocol PROTOCOL', I18n.t('option.protocol')) do |protocol| - options[:protocol] = protocol - end - opts.on('-e', '--export FILE', I18n.t('option.export')) do |file| options[:export] = file - options[:type] = :yaml - end - - opts.on('-t', '--type TYPE', I18n.t('option.type')) do |type| - options[:type] = type.to_sym end opts.on('-i', '--import FILE', I18n.t('option.import')) do |file| options[:import] = file - options[:type] = :yaml - end - - opts.on('-f', '--force', I18n.t('option.force')) do - options[:force] = true end opts.on('-N', '--no-sync', I18n.t('option.no_sync')) do @@ -131,7 +116,6 @@ elsif not config.check_gpg_key? end cli.decrypt -cli.sync(options[:sync]) # Display the item's informations if not options[:show].nil? @@ -156,11 +140,11 @@ elsif not options[:add].nil? # Export elsif not options[:export].nil? - cli.export(options[:export], options[:type]) + cli.export(options[:export]) # Add a new item elsif not options[:import].nil? - cli.import(options[:import], options[:type], options[:force]) + cli.import(options[:import]) # Interactive mode end diff --git a/lib/mpw/config.rb b/lib/mpw/config.rb index d2b02a9..dd797d2 100644 --- a/lib/mpw/config.rb +++ b/lib/mpw/config.rb @@ -2,230 +2,158 @@ # author: nishiki # mail: nishiki@yaegashi.fr -require 'rubygems' require 'gpgme' require 'yaml' require 'i18n' module MPW - class Config - - attr_accessor :error_msg +class Config - attr_accessor :key - attr_accessor :share_keys - attr_accessor :lang - attr_accessor :file_gpg - attr_accessor :last_update - attr_accessor :sync_type - attr_accessor :sync_host - attr_accessor :sync_port - attr_accessor :sync_user - attr_accessor :sync_pwd - attr_accessor :sync_path - attr_accessor :last_sync - attr_accessor :dir_config - - # Constructor - # @args: file_config -> the specify config file - def initialize(file_config=nil) - @error_msg = nil + attr_accessor :error_msg - if /darwin/ =~ RUBY_PLATFORM - @dir_config = "#{Dir.home}/Library/Preferences/mpw" - elsif /cygwin|mswin|mingw|bccwin|wince|emx/ =~ RUBY_PLATFORM - @dir_config = "#{Dir.home}/AppData/Local/mpw" - else - @dir_config = "#{Dir.home}/.config/mpw" - end - - @file_config = "#{@dir_config}/conf/default.cfg" - if not file_config.nil? and not file_config.empty? - @file_config = file_config - end - end - - # Create a new config file - # @args: key -> the gpg key to encrypt - # share_keys -> multiple keys to share the password with other people - # lang -> the software language - # file_gpg -> the file who is encrypted - # sync_type -> the type to synchronization - # sync_host -> the server host for synchronization - # sync_port -> the server port for synchronization - # sync_user -> the user for synchronization - # sync_pwd -> the password for synchronization - # sync_suffix -> the suffix file (optionnal) - # @rtrn: true if le config file is create - def setup(key, share_keys, lang, file_gpg, sync_type, sync_host, sync_port, sync_user, sync_pwd, sync_path) - - if not key =~ /[a-zA-Z0-9.-_]+\@[a-zA-Z0-9]+\.[a-zA-Z]+/ - @error_msg = I18n.t('error.config.key_bad_format') - return false - end + attr_accessor :key + attr_accessor :lang + attr_accessor :config_dir + attr_accessor :wallet_dir - if not check_public_gpg_key(share_keys) - return false - end - - if file_gpg.empty? - file_gpg = "#{@dir_config}/db/default.gpg" - end - - config = {'config' => {'key' => key, - 'share_keys' => share_keys, - 'lang' => lang, - 'file_gpg' => file_gpg, - 'sync_type' => sync_type, - 'sync_host' => sync_host, - 'sync_port' => sync_port, - 'sync_user' => sync_user, - 'sync_pwd' => sync_pwd, - 'sync_path' => sync_path, - 'last_sync' => 0 - } - } - - Dir.mkdir("#{@config_dir}/conf", 700) - Dir.mkdir("#{@config_dir}/db", 700) - File.open(@file_config, 'w') do |file| - file << config.to_yaml - end - - return true - rescue Exception => e - @error_msg = "#{I18n.t('error.config.write')}\n#{e}" - return false - end + # Constructor + # @args: config_file -> the specify config file + def initialize(config_file=nil) + @error_msg = nil + @config_file = config_file - # Setup a new gpg key - # @args: password -> the GPG key password - # name -> the name of user - # length -> length of the GPG key - # expire -> the time of expire to GPG key - # @rtrn: true if the GPG key is create, else false - def setup_gpg_key(password, name, length = 2048, expire = 0) - if name.nil? or name.empty? - @error_msg = "#{I18n.t('error.config.genkey_gpg.name')}" - return false - elsif password.nil? or password.empty? - @error_msg = "#{I18n.t('error.config.genkey_gpg.password')}" - return false - end - - param = '' - param << '<GnupgKeyParms format="internal">' + "\n" - param << "Key-Type: DSA\n" - param << "Key-Length: #{length}\n" - param << "Subkey-Type: ELG-E\n" - param << "Subkey-Length: #{length}\n" - param << "Name-Real: #{name}\n" - param << "Name-Comment: #{name}\n" - param << "Name-Email: #{@key}\n" - param << "Expire-Date: #{expire}\n" - param << "Passphrase: #{password}\n" - param << "</GnupgKeyParms>\n" - - ctx = GPGME::Ctx.new - ctx.genkey(param, nil, nil) - - return true - rescue Exception => e - @error_msg = "#{I18n.t('error.config.genkey_gpg.exception')}\n#{e}" - return false - end - - # Check the config file - # @rtrn: true if the config file is correct - def checkconfig - config = YAML::load_file(@file_config) - @key = config['config']['key'] - @share_keys = config['config']['share_keys'] - @lang = config['config']['lang'] - @file_gpg = config['config']['file_gpg'] - @sync_type = config['config']['sync_type'] - @sync_host = config['config']['sync_host'] - @sync_port = config['config']['sync_port'] - @sync_user = config['config']['sync_user'] - @sync_pwd = config['config']['sync_pwd'] - @sync_path = config['config']['sync_path'] - @last_sync = config['config']['last_sync'].to_i - - if @key.empty? or @file_gpg.empty? - @error_msg = I18n.t('error.config.check') - return false - end - I18n.locale = @lang.to_sym - - return true - rescue Exception => e - @error_msg = "#{I18n.t('error.config.check')}\n#{e}" - return false - end - - # Check if private key exist - # @rtrn: true if the key exist, else false - def check_gpg_key? - ctx = GPGME::Ctx.new - ctx.each_key(@key, true) do - return true - end - - return false - end - - # Check if private key exist - # @args: share_keys -> string with all public keys - # @rtrn: true if the key exist, else false - def check_public_gpg_key(share_keys = @share_keys) - ctx = GPGME::Ctx.new - - share_keys = share_keys.nil? ? '' : share_keys - if not share_keys.empty? - share_keys.split.each do |k| - if not k =~ /[a-zA-Z0-9.-_]+\@[a-zA-Z0-9]+\.[a-zA-Z]+/ - @error_msg = I18n.t('error.config.key_bad_format') - return false - end - - ctx.each_key(key, false) do - next - end - - @error_msg = I18n.t('error.config.no_key_public', key: k) - return false - end - end - - return true - end - - # Set the last update when there is a sync - # @rtrn: true is the file has been updated - def set_last_sync - config = {'config' => {'key' => @key, - 'share_keys' => @share_keys, - 'lang' => @lang, - 'file_gpg' => @file_gpg, - 'sync_type' => @sync_type, - 'sync_host' => @sync_host, - 'sync_port' => @sync_port, - 'sync_user' => @sync_user, - 'sync_pwd' => @sync_pwd, - 'sync_path' => @sync_path, - 'last_sync' => Time.now.to_i - } - } - - File.open(@file_config, 'w') do |file| - file << config.to_yaml - end - - return true - rescue Exception => e - @error_msg = "#{I18n.t('error.config.write')}\n#{e}" - return false + if /darwin/ =~ RUBY_PLATFORM + @config_dir = "#{Dir.home}/Library/Preferences/mpw" + elsif /cygwin|mswin|mingw|bccwin|wince|emx/ =~ RUBY_PLATFORM + @config_dir = "#{Dir.home}/AppData/Local/mpw" + else + @config_dir = "#{Dir.home}/.config/mpw" end + if @config_file.nil? or @config_file.empty? + @config_file = "#{@config_dir}/mpw.cfg" + end end + + # Create a new config file + # @args: key -> the gpg key to encrypt + # lang -> the software language + # wallet_dir -> the directory where are the wallets password + # @rtrn: true if le config file is create + def setup(key, lang, wallet_dir) + + if not key =~ /[a-zA-Z0-9.-_]+\@[a-zA-Z0-9]+\.[a-zA-Z]+/ + @error_msg = I18n.t('error.config.key_bad_format') + return false + end + + if wallet_dir.empty? + wallet_dir = "#{@config_dir}/wallets" + end + + config = {'config' => {'key' => key, + 'lang' => lang, + 'wallet_dir' => wallet_dir, + } + } + + Dir.mkdir(wallet_dir, 0700) + File.open(@config_file, 'w') do |file| + file << config.to_yaml + end + + return true + rescue Exception => e + @error_msg = "#{I18n.t('error.config.write')}\n#{e}" + return false + end + + # Setup a new gpg key + # @args: password -> the GPG key password + # name -> the name of user + # length -> length of the GPG key + # expire -> the time of expire to GPG key + # @rtrn: true if the GPG key is create, else false + def setup_gpg_key(password, name, length = 4096, expire = 0) + if name.nil? or name.empty? + @error_msg = "#{I18n.t('error.config.genkey_gpg.name')}" + return false + elsif password.nil? or password.empty? + @error_msg = "#{I18n.t('error.config.genkey_gpg.password')}" + return false + end + + param = '' + param << '<GnupgKeyParms format="internal">' + "\n" + param << "Key-Type: DSA\n" + param << "Key-Length: #{length}\n" + param << "Subkey-Type: ELG-E\n" + param << "Subkey-Length: #{length}\n" + param << "Name-Real: #{name}\n" + param << "Name-Comment: #{name}\n" + param << "Name-Email: #{@key}\n" + param << "Expire-Date: #{expire}\n" + param << "Passphrase: #{password}\n" + param << "</GnupgKeyParms>\n" + + ctx = GPGME::Ctx.new + ctx.genkey(param, nil, nil) + + return true + rescue Exception => e + @error_msg = "#{I18n.t('error.config.genkey_gpg.exception')}\n#{e}" + return false + end + + # Check the config file + # @rtrn: true if the config file is correct + def checkconfig + config = YAML::load_file(@config_file) + @key = config['config']['key'] + @lang = config['config']['lang'] + @wallet_dir = config['config']['wallet_dir'] + + if @key.empty? or @wallet_dir.empty? + @error_msg = I18n.t('error.config.check') + return false + end + I18n.locale = @lang.to_sym + + return true + rescue Exception => e + @error_msg = "#{I18n.t('error.config.check')}\n#{e}" + return false + end + + # Check if private key exist + # @rtrn: true if the key exist, else false + def check_gpg_key? + ctx = GPGME::Ctx.new + ctx.each_key(@key, true) do + return true + end + + return false + end + + # Set the last update when there is a sync + # @rtrn: true is the file has been updated + def set_last_sync + config = {'config' => {'key' => @key, + 'lang' => @lang, + 'wallet_dir' => @wallet_dir, + } + } + + File.open(@config_file, 'w') do |file| + file << config.to_yaml + end + + return true + rescue Exception => e + @error_msg = "#{I18n.t('error.config.write')}\n#{e}" + return false + end + +end end diff --git a/lib/mpw/item.rb b/lib/mpw/item.rb index 666d5b3..660f74a 100644 --- a/lib/mpw/item.rb +++ b/lib/mpw/item.rb @@ -2,108 +2,104 @@ # author: nishiki # mail: nishiki@yaegashi.fr -require 'rubygems' require 'i18n' module MPW - class Item +class Item - attr_accessor :error_msg + attr_accessor :error_msg - attr_accessor :id - attr_accessor :name - attr_accessor :group - attr_accessor :host - attr_accessor :protocol - attr_accessor :user - attr_accessor :password - attr_accessor :port - attr_accessor :comment - attr_accessor :last_edit - attr_accessor :last_sync - attr_accessor :created + attr_accessor :id + attr_accessor :name + attr_accessor :group + attr_accessor :host + attr_accessor :protocol + attr_accessor :user + attr_accessor :port + attr_accessor :comment + attr_accessor :last_edit + attr_accessor :last_sync + attr_accessor :created - # Constructor - # Create a new item - # @args: options -> a hash of parameter - # raise an error if the hash hasn't the key name - def initialize(options={}) - if not options.has_key?(:name) or options[:name].to_s.empty? - @error_msg = I18n.t('error.update.name_empty') - raise @error_msg - end - - if not options.has_key?(:id) or options[:id].to_s.empty? or not options.has_key?(:created) or options[:created].to_s.empty? - @id = generate_id - @created = Time.now.to_i - else - @id = options[:id] - @created = options[:created] - @last_edit = options[:last_edit] - options[:no_update_last_edit] = true - end - - update(options) + # Constructor + # Create a new item + # @args: options -> a hash of parameter + # raise an error if the hash hasn't the key name + def initialize(options={}) + if not options.has_key?(:name) or options[:name].to_s.empty? + @error_msg = I18n.t('error.update.name_empty') + raise @error_msg end - # Update the item - # @args: options -> a hash of parameter - # @rtrn: true if the item is update - def update(options={}) - if options.has_key?(:name) and options[:name].to_s.empty? - @error_msg = I18n.t('error.update.name_empty') - return false - end - - @name = options[:name] if options.has_key?(:name) - @group = options[:group] if options.has_key?(:group) - @host = options[:host] if options.has_key?(:host) - @protocol = options[:protocol] if options.has_key?(:protocol) - @user = options[:user] if options.has_key?(:user) - @password = options[:password] if options.has_key?(:password) - @port = options[:port].to_i if options.has_key?(:port) and not options[:port].to_s.empty? - @comment = options[:comment] if options.has_key?(:comment) - @last_edit = Time.now.to_i if not options.has_key?(:no_update_last_edit) - - return true + if not options.has_key?(:id) or options[:id].to_s.empty? or not options.has_key?(:created) or options[:created].to_s.empty? + @id = generate_id + @created = Time.now.to_i + else + @id = options[:id] + @created = options[:created] + @last_edit = options[:last_edit] + options[:no_update_last_edit] = true end - # Update last_sync - def set_last_sync - @last_sync = Time.now.to_i - end + update(options) + end - # Delete all data - # @rtrn: true - def delete - @id = nil - @name = nil - @group = nil - @host = nil - @protocol = nil - @user = nil - @password = nil - @port = nil - @comment = nil - @created = nil - @last_edit = nil - @last_sync = nil - - return true - end - - def empty? - return @name.to_s.empty? - end - - def nil? + # Update the item + # @args: options -> a hash of parameter + # @rtrn: true if the item is update + def update(options={}) + if options.has_key?(:name) and options[:name].to_s.empty? + @error_msg = I18n.t('error.update.name_empty') return false end - # Generate an random id - private - def generate_id - return ([*('A'..'Z'),*('a'..'z'),*('0'..'9')]).sample(16).join - end + @name = options[:name] if options.has_key?(:name) + @group = options[:group] if options.has_key?(:group) + @host = options[:host] if options.has_key?(:host) + @protocol = options[:protocol] if options.has_key?(:protocol) + @user = options[:user] if options.has_key?(:user) + @port = options[:port].to_i if options.has_key?(:port) and not options[:port].to_s.empty? + @comment = options[:comment] if options.has_key?(:comment) + @last_edit = Time.now.to_i if not options.has_key?(:no_update_last_edit) + + return true end + + # Update last_sync + def set_last_sync + @last_sync = Time.now.to_i + end + + # Delete all data + # @rtrn: true + def delete + @id = nil + @name = nil + @group = nil + @host = nil + @protocol = nil + @user = nil + @port = nil + @comment = nil + @created = nil + @last_edit = nil + @last_sync = nil + + return true + end + + def empty? + return @name.to_s.empty? + end + + def nil? + return false + end + + # Generate an random id + private + def generate_id + return ([*('A'..'Z'),*('a'..'z'),*('0'..'9')]).sample(16).join + end +end end diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index 57a6bce..9fad675 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -2,331 +2,288 @@ # author: nishiki # mail: nishiki@yaegashi.fr -require 'rubygems' +require 'rubygems/package' require 'gpgme' -require 'csv' require 'i18n' require 'fileutils' require 'yaml' require 'mpw/item' module MPW - class MPW - - attr_accessor :error_msg - - # Constructor - def initialize(file_gpg, key, share_keys='') - @error_msg = nil - @file_gpg = file_gpg - @key = key - @share_keys = share_keys - @data = [] - end - - # Decrypt a gpg file - # @args: password -> the GPG key password - # @rtrn: true if data has been decrypted - def decrypt(password=nil) - @data = [] +class MPW - if File.exist?(@file_gpg) and not File.zero?(@file_gpg) - crypto = GPGME::Crypto.new(armor: true) - data_decrypt = crypto.decrypt(IO.read(@file_gpg), password: password).read.force_encoding('utf-8') + attr_accessor :error_msg + + # Constructor + def initialize(key, wallet_file, gpg_pass=nil) + @error_msg = nil + @key = key + @gpg_pass = gpg_pass + @wallet_file = wallet_file + end - if not data_decrypt.to_s.empty? - YAML.load(data_decrypt).each_value do |d| - @data.push(Item.new(id: d['id'], - name: d['name'], - group: d['group'], - host: d['host'], - protocol: d['protocol'], - user: d['user'], - password: d['password'], - port: d['port'], - comment: d['comment'], - last_edit: d['last_edit'], - created: d['created'], - ) - ) - end + # Decrypt a gpg file + # @args: password -> the GPG key password + # @rtrn: true if data has been decrypted + def read_data + @config = nil + @keys = [] + @data = [] + @passwords = {} + + data = nil + + return if not File.exists?(@wallet_file) + + Gem::Package::TarReader.new(File.open(@wallet_file)) do |tar| + tar.each do |f| + case f.full_name + when 'wallet/config.yml' + @config = YAML.load(f.read) + check_config + + when 'wallet/meta.gpg' + data = decrypt(f.read) + + when /^wallet\/keys\/(?<key>.+)\.pub$/ + @keys[match['key']] = f.read + + when /^wallet\/passwords\/(?<id>[a-zA-Z0-9]+)\.gpg$/ + @passwords[Regexp.last_match('id')] = f.read + else + next end end - - return true - rescue Exception => e - @error_msg = "#{I18n.t('error.gpg_file.decrypt')}\n#{e}" - return false - end - - # Encrypt a file - # @rtrn: true if the file has been encrypted - def encrypt - FileUtils.cp(@file_gpg, "#{@file_gpg}.bk") if File.exist?(@file_gpg) - - data_to_encrypt = {} - - @data.each do |item| - next if item.empty? - - data_to_encrypt.merge!(item.id => {'id' => item.id, - 'name' => item.name, - 'group' => item.group, - 'host' => item.host, - 'protocol' => item.protocol, - 'user' => item.user, - 'password' => item.password, - 'port' => item.port, - 'comment' => item.comment, - 'last_edit' => item.last_edit, - 'created' => item.created, - } - ) - end - - recipients = [] - recipients.push(@key) - if not @share_keys.nil? - @share_keys.split.each { |k| recipients.push(k) } - end - - crypto = GPGME::Crypto.new(armor: true) - file_gpg = File.open(@file_gpg, 'w+') - crypto.encrypt(data_to_encrypt.to_yaml, recipients: recipients, output: file_gpg) - file_gpg.close - - FileUtils.rm("#{@file_gpg}.bk") if File.exist?("#{@file_gpg}.bk") - return true - rescue Exception => e - @error_msg = "#{I18n.t('error.gpg_file.encrypt')}\n#{e}" - FileUtils.mv("#{@file_gpg}.bk", @file_gpg) if File.exist?("#{@file_gpg}.bk") - return false - end - - # Add a new item - # @args: item -> Object MPW::Item - # @rtrn: true if add item - def add(item) - if not item.instance_of?(Item) - @error_msg = I18n.t('error.bad_class') - return false - elsif item.empty? - @error_msg = I18n.t('error.add.empty') - return false - else - @data.push(item) - return true - end end - # Search in some csv data - # @args: options -> a hash with paramaters - # @rtrn: a list with the resultat of the search - def list(options={}) - result = [] - - search = options[:search].to_s.downcase - group = options[:group].to_s.downcase - protocol = options[:protocol].to_s.downcase + if not data.nil? and not data.empty? + YAML.load(data).each_value do |d| + @data.push(Item.new(id: d['id'], + name: d['name'], + group: d['group'], + host: d['host'], + protocol: d['protocol'], + user: d['user'], + port: d['port'], + comment: d['comment'], + last_edit: d['last_edit'], + created: d['created'], + ) + ) + end + end + end - @data.each do |item| - next if item.empty? + # Encrypt a file + # @rtrn: true if the file has been encrypted + # TODO export key pub + def write_data + data = {} - next if not group.empty? and not group.eql?(item.group.downcase) - next if not protocol.empty? and not protocol.eql?(item.protocol.downcase) - - name = item.name.to_s.downcase - host = item.host.to_s.downcase - comment = item.comment.to_s.downcase + @data.each do |item| + next if item.empty? - if not name =~ /^.*#{search}.*$/ and not host =~ /^.*#{search}.*$/ and not comment =~ /^.*#{search}.*$/ - next + data.merge!(item.id => {'id' => item.id, + 'name' => item.name, + 'group' => item.group, + 'host' => item.host, + 'protocol' => item.protocol, + 'user' => item.user, + 'port' => item.port, + 'comment' => item.comment, + 'last_edit' => item.last_edit, + 'created' => item.created, + } + ) + end + + + + Gem::Package::TarWriter.new(File.open(@wallet_file, 'w+')) do |tar| + data_encrypt = encrypt(YAML::dump(data)) + tar.add_file_simple('wallet/meta.gpg', 0400, data_encrypt.length) do |io| + io.write(data_encrypt) + end + + @passwords.each do |id, password| + tar.add_file_simple("wallet/passwords/#{id}.gpg", 0400, password.length) do |io| + io.write(password) end - - result.push(item) end - - return result - end - - # Search in some csv data - # @args: id -> the id item - # @rtrn: a row with the result of the search - def search_by_id(id) - @data.each do |item| - return item if item.id == id - end - - return nil - end - - # Export to csv - # @args: file -> file where you export the data - # type -> udata type - # @rtrn: true if export work - def export(file, type=:yaml) - case type - when :csv - CSV.open(file, 'w', write_headers: true, - headers: ['name', 'group', 'protocol', 'host', 'user', 'password', 'port', 'comment']) do |csv| - @data.each do |item| - csv << [item.name, item.group, item.protocol, item.host, item.user, item.password, item.port, item.comment] - end - end - - when :yaml - data = {} - @data.each do |item| - data.merge!(item.id => {'id' => item.id, - 'name' => item.name, - 'group' => item.group, - 'host' => item.host, - 'protocol' => item.protocol, - 'user' => item.user, - 'password' => item.password, - 'port' => item.port, - 'comment' => item.comment, - 'last_edit' => item.last_edit, - 'created' => item.created, - } - ) - end - - File.open(file, 'w') {|f| f << data.to_yaml} - - else - @error_msg = "#{I18n.t('error.export.unknown_type', type: type)}" - return false - end - - return true - rescue Exception => e - @error_msg = "#{I18n.t('error.export.write', file: file)}\n#{e}" - return false - end - - # Import to csv - # @args: file -> path to file import - # type -> udata type - # @rtrn: true if the import work - def import(file, type=:yaml) - case type - when :csv - CSV.foreach(file, {headers: true}) do |row| - item = Item.new(name: row['name'], - group: row['group'], - host: row['host'], - protocol: row['protocol'], - user: row['user'], - password: row['password'], - port: row['port'], - comment: row['comment'], - ) - - return false if item.empty? - - @data.push(item) - end - - when :yaml - YAML::load_file(file).each_value do |row| - item = Item.new(name: row['name'], - group: row['group'], - host: row['host'], - protocol: row['protocol'], - user: row['user'], - password: row['password'], - port: row['port'], - comment: row['comment'], - ) - - return false if item.empty? - - @data.push(item) - end - - else - @error_msg = "#{I18n.t('error.export.unknown_type', type: type)}" - return false - end - - return true - rescue Exception => e - @error_msg = "#{I18n.t('error.import.read', file: file)}\n#{e}" - return false - end - - # Return a preview import - # @args: file -> path to file import - # @rtrn: a hash with the items to import, if there is an error return false - def import_preview(file, type=:yaml) - data = [] - - case type - when :csv - CSV.foreach(file, {headers: true}) do |row| - item = Item.new(name: row['name'], - group: row['group'], - host: row['host'], - protocol: row['protocol'], - user: row['user'], - password: row['password'], - port: row['port'], - comment: row['comment'], - ) - - return false if item.empty? - - data.push(item) - end - - when :yaml - YAML::load_file(file).each_value do |row| - item = Item.new(name: row['name'], - group: row['group'], - host: row['host'], - protocol: row['protocol'], - user: row['user'], - password: row['password'], - port: row['port'], - comment: row['comment'], - ) - - return false if item.empty? - - data.push(item) - end - - else - @error_msg = "#{I18n.t('error.export.unknown_type', type: type)}" - return false - end - - return data - rescue Exception => e - @error_msg = "#{I18n.t('error.import.read', file: file)}\n#{e}" - return false - end - - # Generate a random password - # @args: length -> the length password - # @rtrn: a random string - def self.password(length=8) - if length.to_i <= 0 - length = 8 - else - length = length.to_i - end - - result = '' - while length > 62 do - result << ([*('A'..'Z'),*('a'..'z'),*('0'..'9')]).sample(62).join - length -= 62 - end - result << ([*('A'..'Z'),*('a'..'z'),*('0'..'9')]).sample(length).join - - return result end end + + # TODO comment + def get_password(id) + return decrypt(@passwords[id]) + end + + # TODO comment + def set_password(id, password) + @passwords[id] = encrypt(password) + end + + # TODO + def check_config + if false + raise 'ERROR' + end + end + + # Add a new item + # @args: item -> Object MPW::Item + # @rtrn: true if add item + # TODO add password + def add(item) + if not item.instance_of?(Item) + raise I18n.t('error.bad_class') + elsif item.empty? + raise I18n.t('error.add.empty') + else + @data.push(item) + end + end + + + # Search in some csv data + # @args: options -> a hash with paramaters + # @rtrn: a list with the resultat of the search + def list(options={}) + result = [] + + search = options[:search].to_s.downcase + group = options[:group].to_s.downcase + protocol = options[:protocol].to_s.downcase + + @data.each do |item| + next if item.empty? + + next if not group.empty? and not group.eql?(item.group.downcase) + next if not protocol.empty? and not protocol.eql?(item.protocol.downcase) + + name = item.name.to_s.downcase + host = item.host.to_s.downcase + comment = item.comment.to_s.downcase + + if not name =~ /^.*#{search}.*$/ and not host =~ /^.*#{search}.*$/ and not comment =~ /^.*#{search}.*$/ + next + end + + result.push(item) + end + + return result + end + + # Search in some csv data + # @args: id -> the id item + # @rtrn: a row with the result of the search + def search_by_id(id) + @data.each do |item| + return item if item.id == id + end + + return nil + end + + # Export to csv + # @args: file -> file where you export the data + def export(file) + data = {} + @data.each do |item| + data.merge!(item.id => {'id' => item.id, + 'name' => item.name, + 'group' => item.group, + 'host' => item.host, + 'protocol' => item.protocol, + 'user' => item.user, + 'password' => get_password(item.id), + 'port' => item.port, + 'comment' => item.comment, + 'last_edit' => item.last_edit, + 'created' => item.created, + } + ) + end + + File.open(file, 'w') {|f| f << data.to_yaml} + rescue Exception => e + raise "#{I18n.t('error.export.write', file: file)}\n#{e}" + end + + # Import to yaml + # @args: file -> path to file import + # TODO raise + def import(file) + YAML::load_file(file).each_value do |row| + item = Item.new(name: row['name'], + group: row['group'], + host: row['host'], + protocol: row['protocol'], + user: row['user'], + port: row['port'], + comment: row['comment'], + ) + + raise 'Item is empty' if item.empty? + + @data.push(item) + set_password(item.id, row['password']) + end + rescue Exception => e + raise "#{I18n.t('error.import.read', file: file)}\n#{e}" + end + + # Generate a random password + # @args: length -> the length password + # @rtrn: a random string + def self.password(length=8) + if length.to_i <= 0 + length = 8 + else + length = length.to_i + end + + result = '' + while length > 62 do + result << ([*('A'..'Z'),*('a'..'z'),*('0'..'9')]).sample(62).join + length -= 62 + end + result << ([*('A'..'Z'),*('a'..'z'),*('0'..'9')]).sample(length).join + + return result + end + + # Decrypt a gpg file + # @args: password -> the GPG key password + # @rtrn: true if data has been decrypted + private + def decrypt(data) + crypto = GPGME::Crypto.new(armor: true) + + return crypto.decrypt(data, password: @gpg_pass).read.force_encoding('utf-8') + rescue Exception => e + raise "#{I18n.t('error.gpg_file.decrypt')}\n#{e}" + end + + # Encrypt a file + # @rtrn: true if the file has been encrypted + private + def encrypt(data) + recipients = [] + crypto = GPGME::Crypto.new(armor: true) + +# @config['keys'].each do |key| +# recipients.push(key) +# end + + recipients.push(@key) + + return crypto.encrypt(data, recipients: recipients).read + rescue Exception => e + raise "#{I18n.t('error.gpg_file.encrypt')}\n#{e}" + end + +end end diff --git a/lib/mpw/ui/cli.rb b/lib/mpw/ui/cli.rb index 3bf9c51..bb6768e 100644 --- a/lib/mpw/ui/cli.rb +++ b/lib/mpw/ui/cli.rb @@ -1,15 +1,11 @@ #!/usr/bin/ruby # author: nishiki # mail: nishiki@yaegashi.fr -# info: a simple script who m your passwords -require 'rubygems' -require 'highline/import' -require 'pathname' require 'readline' require 'i18n' require 'colorize' -require 'mpw/sync' +require 'highline/import' require 'mpw/mpw' require 'mpw/item' @@ -18,29 +14,10 @@ class Cli # Constructor # @args: lang -> the operating system language # config_file -> a specify config file + # TODO def initialize(config) @config = config - end - - # Sync the data with the server - # @args: allow_sync -> allow or disable sync (boolean) - # @rtnr: true if the synchro is finish - def sync(allow_sync=nil) - if not allow_sync.nil? - @allow_sync = allow_sync - end - - return true if not @allow_sync - - @sync = MPW::Sync.new(@config, @mpw, @password) - - raise(@sync.error_msg) if not @sync.get_remote - raise(@sync.error_msg) if not @sync.sync - - return true - rescue Exception => e - puts "#{I18n.t('display.error')} #7: #{e}".red - return false + @wallet_file = "#{@config.wallet_dir}/test.mpw" end # Create a new config file @@ -48,33 +25,16 @@ class Cli def setup(lang) puts I18n.t('form.setup.title') puts '--------------------' - language = ask(I18n.t('form.setup.lang', lang: lang)).to_s - key = ask(I18n.t('form.setup.gpg_key')).to_s - share_keys = ask(I18n.t('form.setup.share_gpg_keys')).to_s - file_gpg = ask(I18n.t('form.setup.gpg_file', home: @conf.dir_config)).to_s - sync_type = ask(I18n.t('form.setup.sync_type')).to_s + language = ask(I18n.t('form.setup.lang', lang: lang)).to_s + key = ask(I18n.t('form.setup.gpg_key')).to_s + wallet_dir = ask(I18n.t('form.setup.wallet_dir')).to_s - if ['ssh', 'ftp', 'mpw'].include?(sync_type) - sync_host = ask(I18n.t('form.setup.sync_host')).to_s - sync_port = ask(I18n.t('form.setup.sync_port')).to_s - sync_user = ask(I18n.t('form.setup.sync_user')).to_s - sync_pwd = ask(I18n.t('form.setup.sync_pwd')).to_s - sync_path = ask(I18n.t('form.setup.sync_path')).to_s - end - if language.nil? or language.empty? language = lang end I18n.locale = language.to_sym - sync_type = sync_type.nil? or sync_type.empty? ? nil : sync_type - sync_host = sync_host.nil? or sync_host.empty? ? nil : sync_host - sync_port = sync_port.nil? or sync_port.empty? ? nil : sync_port.to_i - sync_user = sync_user.nil? or sync_user.empty? ? nil : sync_user - sync_pwd = sync_pwd.nil? or sync_pwd.empty? ? nil : sync_pwd - sync_path = sync_path.nil? or sync_path.empty? ? nil : sync_path - - if @config.setup(key, share_keys, language, file_gpg, sync_type, sync_host, sync_port, sync_user, sync_pwd, sync_path) + if @config.setup(key, lang, wallet_dir) puts "#{I18n.t('form.setup.valid')}".green else puts "#{I18n.t('display.error')} #8: #{@config.error_msg}".red @@ -86,7 +46,7 @@ class Cli exit 2 end end - + # Setup a new GPG key def setup_gpg_key puts I18n.t('form.setup_gpg_key.title') @@ -124,17 +84,15 @@ class Cli end end + # Request the GPG password and decrypt the file def decrypt if not defined?(@mpw) - @mpw = MPW::MPW.new(@config.file_gpg, @config.key, @config.share_keys) + @password = ask(I18n.t('display.gpg_password')) {|q| q.echo = false} + @mpw = MPW::MPW.new(@config.key, @wallet_file, @password) end - @password = ask(I18n.t('display.gpg_password')) {|q| q.echo = false} - if not @mpw.decrypt(@password) - puts "#{I18n.t('display.error')} #11: #{@mpw.error_msg}".red - exit 2 - end + @mpw.read_data end # Display the query's result @@ -185,7 +143,7 @@ class Cli print "#{I18n.t('display.login')}: ".cyan puts item.user print "#{I18n.t('display.password')}: ".cyan - puts item.password + puts @mpw.get_password(item.id) print "#{I18n.t('display.port')}: ".cyan puts item.port print "#{I18n.t('display.comment')}: ".cyan @@ -203,21 +161,17 @@ class Cli options[:host] = ask(I18n.t('form.add.server')).to_s options[:protocol] = ask(I18n.t('form.add.protocol')).to_s options[:user] = ask(I18n.t('form.add.login')).to_s - options[:password] = ask(I18n.t('form.add.password')).to_s + password = ask(I18n.t('form.add.password')).to_s options[:port] = ask(I18n.t('form.add.port')).to_s options[:comment] = ask(I18n.t('form.add.comment')).to_s item = MPW::Item.new(options) - if @mpw.add(item) - if @mpw.encrypt - sync - puts "#{I18n.t('form.add.valid')}".green - else - puts "#{I18n.t('display.error')} #12: #{@mpw.error_msg}".red - end - else - puts "#{I18n.t('display.error')} #13: #{item.error_msg}".red - end + + @mpw.add(item) + @mpw.set_password(item.id, password) + @mpw.write_data + + puts "#{I18n.t('form.add.valid')}".green end # Update an item @@ -235,22 +189,17 @@ class Cli options[:host] = ask(I18n.t('form.update.server' , server: item.host)).to_s options[:protocol] = ask(I18n.t('form.update.protocol', protocol: item.protocol)).to_s options[:user] = ask(I18n.t('form.update.login' , login: item.user)).to_s - options[:password] = ask(I18n.t('form.update.password')).to_s + password = ask(I18n.t('form.update.password')).to_s options[:port] = ask(I18n.t('form.update.port' , port: item.port)).to_s options[:comment] = ask(I18n.t('form.update.comment' , comment: item.comment)).to_s options.delete_if { |k,v| v.empty? } - if item.update(options) - if @mpw.encrypt - sync - puts "#{I18n.t('form.update.valid')}".green - else - puts "#{I18n.t('display.error')} #14: #{@mpw.error_msg}".red - end - else - puts "#{I18n.t('display.error')} #15: #{item.error_msg}".red - end + item.update(options) + @mpw.encrypt + @mpw.write_data + + puts "#{I18n.t('form.update.valid')}".green else puts I18n.t('display.nothing') end @@ -289,43 +238,22 @@ class Cli # Export the items in a CSV file # @args: file -> the destination file - def export(file, type=:yaml) - if @mpw.export(file, type) - puts "#{I18n.t('export.valid', file)}".green - else - puts "#{I18n.t('display.error')} #17: #{@mpw.error_msg}".red - end + def export(file) + @mpw.export(file) + + puts "#{I18n.t('export.valid', file)}".green + rescue Exception => e + puts "#{I18n.t('display.error')} #17: #{e}".red end - # Import items from a CSV file + # Import items from a YAML file # @args: file -> the import file - # force -> no resquest a validation - def import(file, type=:yaml, force=false) + def import(file) + @mpw.import(file) + @mpw.write_data - if not force - result = @mpw.import_preview(file, type) - if result.is_a?(Array) and not result.empty? - result.each do |r| - display_item(r) - end - - confirm = ask("#{I18n.t('form.import.ask', file: file)} (y/N) ").to_s - if confirm =~ /^(y|yes|YES|Yes|Y)$/ - force = true - end - else - puts I18n.t('form.import.not_valid') - end - end - - if force - if @mpw.import(file, type) and @mpw.encrypt - sync - puts "#{I18n.t('form.import.valid')}".green - else - puts "#{I18n.t('display.error')} #18: #{@mpw.error_msg}".red - end - end + puts "#{I18n.t('form.import.valid')}".green + rescue Exception => e + puts "#{I18n.t('display.error')} #18: #{e}".red end - end From b86e095a603059a1bf53b26c3a8dfb629b1a51ea Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Thu, 5 May 2016 23:07:37 +0200 Subject: [PATCH 197/531] add relative path for development and test --- bin/mpw | 8 +++++--- lib/mpw/mpw.rb | 4 +++- lib/mpw/ui/cli.rb | 6 ++++-- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/bin/mpw b/bin/mpw index f36bc87..f385cb7 100755 --- a/bin/mpw +++ b/bin/mpw @@ -8,9 +8,6 @@ require 'pathname' require 'locale' require 'set' require 'i18n' -require 'mpw/mpw' -require 'mpw/config' -require 'mpw/cli' # --------------------------------------------------------- # # Set local @@ -24,6 +21,11 @@ end APP_ROOT = File.dirname(Pathname.new(__FILE__).realpath) +# TODO +require "#{APP_ROOT}/../lib/mpw/mpw.rb" +require "#{APP_ROOT}/../lib/mpw/config.rb" +require "#{APP_ROOT}/../lib/mpw/ui/cli.rb" + I18n::Backend::Simple.send(:include, I18n::Backend::Fallbacks) I18n.load_path = Dir["#{APP_ROOT}/../i18n/cli/*.yml"] I18n.default_locale = :en diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index 9fad675..654cd25 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -7,7 +7,9 @@ require 'gpgme' require 'i18n' require 'fileutils' require 'yaml' -require 'mpw/item' + +#TODO +require "#{APP_ROOT}/../lib/mpw/item.rb" module MPW class MPW diff --git a/lib/mpw/ui/cli.rb b/lib/mpw/ui/cli.rb index bb6768e..1d05c8b 100644 --- a/lib/mpw/ui/cli.rb +++ b/lib/mpw/ui/cli.rb @@ -6,8 +6,10 @@ require 'readline' require 'i18n' require 'colorize' require 'highline/import' -require 'mpw/mpw' -require 'mpw/item' + +#TODO +require "#{APP_ROOT}/../lib/mpw/item.rb" +require "#{APP_ROOT}/../lib/mpw/mpw.rb" class Cli From 38beb7ad5357f5343cf554d8540a064a17f2b82f Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Thu, 5 May 2016 23:14:28 +0200 Subject: [PATCH 198/531] cli: fix update function --- lib/mpw/ui/cli.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/mpw/ui/cli.rb b/lib/mpw/ui/cli.rb index 1d05c8b..cfa731c 100644 --- a/lib/mpw/ui/cli.rb +++ b/lib/mpw/ui/cli.rb @@ -198,13 +198,15 @@ class Cli options.delete_if { |k,v| v.empty? } item.update(options) - @mpw.encrypt + @mpw.set_password(item.id, password) if not password.empty? @mpw.write_data puts "#{I18n.t('form.update.valid')}".green else puts I18n.t('display.nothing') end + rescue Exception => e + puts "#{I18n.t('display.error')} #14: #{e}".red end # Remove an item From 163ef46076bb79f401e3b5caa296f8268a6907a8 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Thu, 5 May 2016 23:24:08 +0200 Subject: [PATCH 199/531] cli: fix delete function --- lib/mpw/ui/cli.rb | 35 ++++++++++++++++------------------- 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/lib/mpw/ui/cli.rb b/lib/mpw/ui/cli.rb index cfa731c..95e7326 100644 --- a/lib/mpw/ui/cli.rb +++ b/lib/mpw/ui/cli.rb @@ -213,31 +213,28 @@ class Cli # @args: id -> the item's id # force -> no resquest a validation def delete(id, force=false) + item = @mpw.search_by_id(id) + + if item.nil? + puts I18n.t('display.nothing') + return + end + if not force - item = @mpw.search_by_id(id) + display_item(item) - if not item.nil? - display_item(item) - - confirm = ask("#{I18n.t('form.delete.ask', id: id)} (y/N) ").to_s - if confirm =~ /^(y|yes|YES|Yes|Y)$/ - force = true - end - else - puts I18n.t('display.nothing') + confirm = ask("#{I18n.t('form.delete.ask', id: id)} (y/N) ").to_s + if not confirm =~ /^(y|yes|YES|Yes|Y)$/ + return end end - if force - item.delete + item.delete + @mpw.write_data - if @mpw.encrypt - sync - puts "#{I18n.t('form.delete.valid', id: id)}".green - else - puts "#{I18n.t('display.error')} #16: #{@mpw.error_msg}".red - end - end + puts "#{I18n.t('form.delete.valid', id: id)}".green + rescue + puts "#{I18n.t('display.error')} #16: #{@mpw.error_msg}".red end # Export the items in a CSV file From afb197aff5a7df1db3d80bc32ba48011081eb3be Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Thu, 5 May 2016 23:43:34 +0200 Subject: [PATCH 200/531] add option for choice the wallet --- bin/mpw | 7 ++++++- lib/mpw/ui/cli.rb | 4 ++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/bin/mpw b/bin/mpw index f385cb7..e0f5f16 100755 --- a/bin/mpw +++ b/bin/mpw @@ -41,6 +41,7 @@ options[:format] = false options[:sync] = true options[:group] = nil options[:config] = nil +options[:wallet] = nil OptionParser.new do |opts| opts.banner = "#{I18n.t('option.usage')}: mpw [options]" @@ -90,6 +91,10 @@ OptionParser.new do |opts| options[:sync] = false end + opts.on('-w', '--wallet WALLET', I18n.t('option.wallet')) do |wallet| + options[:wallet] = wallet + end + opts.on('-G', '--generate-password [LENGTH]', I18n.t('option.generate_password')) do |length| puts MPW::MPW::password(length) exit 0 @@ -108,7 +113,7 @@ end.parse! config = MPW::Config.new(options[:config]) check_error = config.checkconfig -cli = Cli.new(config) +cli = Cli.new(config, options[:wallet]) # Setup a new config if not check_error or not options[:setup].nil? diff --git a/lib/mpw/ui/cli.rb b/lib/mpw/ui/cli.rb index 95e7326..f4aba00 100644 --- a/lib/mpw/ui/cli.rb +++ b/lib/mpw/ui/cli.rb @@ -17,9 +17,9 @@ class Cli # @args: lang -> the operating system language # config_file -> a specify config file # TODO - def initialize(config) + def initialize(config, wallet) @config = config - @wallet_file = "#{@config.wallet_dir}/test.mpw" + @wallet_file = "#{@config.wallet_dir}/#{wallet}.mpw" end # Create a new config file From 797efa2b93e5434759ce43b080ca15c1041ca9cb Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Thu, 5 May 2016 23:46:48 +0200 Subject: [PATCH 201/531] cli: catch exception in decrypt --- lib/mpw/ui/cli.rb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/mpw/ui/cli.rb b/lib/mpw/ui/cli.rb index f4aba00..868ccfe 100644 --- a/lib/mpw/ui/cli.rb +++ b/lib/mpw/ui/cli.rb @@ -95,6 +95,9 @@ class Cli end @mpw.read_data + rescue Exception => e + puts "#{I18n.t('display.error')} #11: #{e}".red + exit 2 end # Display the query's result From c1cab93dce65fa3091bd2e786bab4c6b79b25a96 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Fri, 6 May 2016 10:53:32 +0200 Subject: [PATCH 202/531] write pub key in tarball --- lib/mpw/mpw.rb | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index 654cd25..d022849 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -99,8 +99,6 @@ class MPW ) end - - Gem::Package::TarWriter.new(File.open(@wallet_file, 'w+')) do |tar| data_encrypt = encrypt(YAML::dump(data)) tar.add_file_simple('wallet/meta.gpg', 0400, data_encrypt.length) do |io| @@ -112,8 +110,13 @@ class MPW io.write(password) end end - end + @keys.each do |id, key| + tar.add_file_simple("wallet/keys/#{id}.pub", 0400, key.length) do |io| + io.write(password) + end + end + end end # TODO comment From f724f09957d7e707ed24891c522860cffb072347 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sat, 7 May 2016 09:40:39 +0200 Subject: [PATCH 203/531] mpw: add raise for read data --- lib/mpw/mpw.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index d022849..669df3c 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -24,9 +24,7 @@ class MPW @wallet_file = wallet_file end - # Decrypt a gpg file - # @args: password -> the GPG key password - # @rtrn: true if data has been decrypted + # Read mpw file def read_data @config = nil @keys = [] @@ -74,6 +72,8 @@ class MPW ) end end + rescue Exception => e + raise "#{I18n.t('error.mpw_file.read_data')}\n#{e}" end # Encrypt a file From 6a1d3a8921388aa371732b6750e9ddfd1f2318d7 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sat, 7 May 2016 10:04:07 +0200 Subject: [PATCH 204/531] add choice wallet --- bin/mpw | 3 ++- lib/mpw/ui/cli.rb | 41 ++++++++++++++++++++++++++++++++++++----- 2 files changed, 38 insertions(+), 6 deletions(-) diff --git a/bin/mpw b/bin/mpw index e0f5f16..088f173 100755 --- a/bin/mpw +++ b/bin/mpw @@ -113,7 +113,7 @@ end.parse! config = MPW::Config.new(options[:config]) check_error = config.checkconfig -cli = Cli.new(config, options[:wallet]) +cli = Cli.new(config) # Setup a new config if not check_error or not options[:setup].nil? @@ -122,6 +122,7 @@ elsif not config.check_gpg_key? cli.setup_gpg_key end +cli.get_wallet(options[:wallet]) cli.decrypt # Display the item's informations diff --git a/lib/mpw/ui/cli.rb b/lib/mpw/ui/cli.rb index 868ccfe..57063de 100644 --- a/lib/mpw/ui/cli.rb +++ b/lib/mpw/ui/cli.rb @@ -14,12 +14,9 @@ require "#{APP_ROOT}/../lib/mpw/mpw.rb" class Cli # Constructor - # @args: lang -> the operating system language - # config_file -> a specify config file - # TODO - def initialize(config, wallet) + # @args: config_file -> a specify config file + def initialize(config) @config = config - @wallet_file = "#{@config.wallet_dir}/#{wallet}.mpw" end # Create a new config file @@ -155,6 +152,40 @@ class Cli puts item.comment end + # Display the wallet + # @args: wallet -> the wallet name + def get_wallet(wallet=nil) + if wallet.to_s.empty? + wallets = Dir.glob("#{@config.wallet_dir}/*.mpw") + puts wallets + + case wallets.length + when 0 + puts I18n.t('display.nothing') + when 1 + @wallet_file = wallets[0] + else + i = 1 + wallets.each do |wallet| + print "#{i}: ".cyan + puts File.basename(wallet, '.mpw') + + i += 1 + end + + choice = ask(I18n.t('form.select')).to_i + + if choice >= 1 and choice < i + @wallet_file = wallets[choice-1] + else + puts "#{I18n.t('display.warning')}: #{I18n.t('warning.select')}".yellow + end + end + else + @wallet_file = "#{@config.wallet_dir}/#{wallet}.mpw" + end + end + # Form to add a new item def add options = {} From 09f53a3c85883c0c3cf4559f2ce92535237490c2 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sat, 7 May 2016 12:00:19 +0200 Subject: [PATCH 205/531] add multiple key for encrypt --- lib/mpw/mpw.rb | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index 669df3c..799bf5b 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -27,8 +27,8 @@ class MPW # Read mpw file def read_data @config = nil - @keys = [] @data = [] + @keys = {} @passwords = {} data = nil @@ -46,7 +46,7 @@ class MPW data = decrypt(f.read) when /^wallet\/keys\/(?<key>.+)\.pub$/ - @keys[match['key']] = f.read + @keys[Regexp.last_match('key')] = f.read when /^wallet\/passwords\/(?<id>[a-zA-Z0-9]+)\.gpg$/ @passwords[Regexp.last_match('id')] = f.read @@ -279,11 +279,11 @@ class MPW recipients = [] crypto = GPGME::Crypto.new(armor: true) -# @config['keys'].each do |key| -# recipients.push(key) -# end + @keys.each_key do |key| + recipients.push(key) + end - recipients.push(@key) + recipients.push(@key) if not recipients.index(@key).nil? return crypto.encrypt(data, recipients: recipients).read rescue Exception => e From d56ab48797cddd462d2333ec42ce10e8c9445eed Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sat, 7 May 2016 12:03:55 +0200 Subject: [PATCH 206/531] fix indent for export function --- lib/mpw/mpw.rb | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index 799bf5b..0d1af7a 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -195,24 +195,24 @@ class MPW # Export to csv # @args: file -> file where you export the data def export(file) - data = {} - @data.each do |item| - data.merge!(item.id => {'id' => item.id, - 'name' => item.name, - 'group' => item.group, - 'host' => item.host, - 'protocol' => item.protocol, - 'user' => item.user, - 'password' => get_password(item.id), - 'port' => item.port, - 'comment' => item.comment, - 'last_edit' => item.last_edit, - 'created' => item.created, - } - ) - end + data = {} + @data.each do |item| + data.merge!(item.id => {'id' => item.id, + 'name' => item.name, + 'group' => item.group, + 'host' => item.host, + 'protocol' => item.protocol, + 'user' => item.user, + 'password' => get_password(item.id), + 'port' => item.port, + 'comment' => item.comment, + 'last_edit' => item.last_edit, + 'created' => item.created, + } + ) + end - File.open(file, 'w') {|f| f << data.to_yaml} + File.open(file, 'w') {|f| f << data.to_yaml} rescue Exception => e raise "#{I18n.t('error.export.write', file: file)}\n#{e}" end From 8f29eb8d58b629e6668667ad86cf6559bb248e61 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sat, 7 May 2016 12:08:36 +0200 Subject: [PATCH 207/531] fix comments --- lib/mpw/mpw.rb | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index 0d1af7a..230ff53 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -77,8 +77,7 @@ class MPW end # Encrypt a file - # @rtrn: true if the file has been encrypted - # TODO export key pub + # TODO backup and restore file with raise def write_data data = {} @@ -119,12 +118,15 @@ class MPW end end - # TODO comment + # Get a password + # args: id -> the item id def get_password(id) return decrypt(@passwords[id]) end - # TODO comment + # Set a password + # args: id -> the item id + # password -> the new password def set_password(id, password) @passwords[id] = encrypt(password) end @@ -138,8 +140,6 @@ class MPW # Add a new item # @args: item -> Object MPW::Item - # @rtrn: true if add item - # TODO add password def add(item) if not item.instance_of?(Item) raise I18n.t('error.bad_class') @@ -192,7 +192,7 @@ class MPW return nil end - # Export to csv + # Export to yaml # @args: file -> file where you export the data def export(file) data = {} @@ -261,8 +261,7 @@ class MPW end # Decrypt a gpg file - # @args: password -> the GPG key password - # @rtrn: true if data has been decrypted + # @args: data -> string to decrypt private def decrypt(data) crypto = GPGME::Crypto.new(armor: true) @@ -273,7 +272,7 @@ class MPW end # Encrypt a file - # @rtrn: true if the file has been encrypted + # args: data -> string to encrypt private def encrypt(data) recipients = [] From 2d35e19fd0e0e65112ba5be8b5acdcd07342e496 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sat, 7 May 2016 12:20:46 +0200 Subject: [PATCH 208/531] fix alphabetic order for options --- bin/mpw | 61 ++++++++++++++++++++++++++++++--------------------------- 1 file changed, 32 insertions(+), 29 deletions(-) diff --git a/bin/mpw b/bin/mpw index 088f173..ee201ba 100755 --- a/bin/mpw +++ b/bin/mpw @@ -37,7 +37,6 @@ I18n.locale = lang.to_sym options = {} options[:force] = false -options[:format] = false options[:sync] = true options[:group] = nil options[:config] = nil @@ -46,8 +45,8 @@ options[:wallet] = nil OptionParser.new do |opts| opts.banner = "#{I18n.t('option.usage')}: mpw [options]" - opts.on('-s', '--show [SEARCH]', I18n.t('option.show')) do |search| - search.nil? ? (options[:show] = '') : (options[:show] = search) + opts.on('-a', '--add', I18n.t('option.add')) do + options[:add] = true end opts.on('-A', '--show-all', I18n.t('option.show_all')) do @@ -55,44 +54,24 @@ OptionParser.new do |opts| options[:show] = '' end - opts.on('-u', '--update ID', I18n.t('option.update')) do |id| - options[:update] = id + opts.on('-c', '--config CONFIG', I18n.t('option.config')) do |config| + options[:config] = config end opts.on('-d', '--delete ID', I18n.t('option.remove')) do |id| options[:delete] = id end - opts.on('-g', '--group GROUP', I18n.t('option.group')) do |group| - options[:group] = group - end - - opts.on('-a', '--add', I18n.t('option.add')) do - options[:add] = true - end - - opts.on('-c', '--config CONFIG', I18n.t('option.config')) do |config| - options[:config] = config - end - - opts.on('-S', '--setup', I18n.t('option.setup')) do - options[:setup] = true - end - opts.on('-e', '--export FILE', I18n.t('option.export')) do |file| options[:export] = file end - opts.on('-i', '--import FILE', I18n.t('option.import')) do |file| - options[:import] = file + opts.on('-f', '--force', I18n.t('option.force')) do + options[:force] = true end - opts.on('-N', '--no-sync', I18n.t('option.no_sync')) do - options[:sync] = false - end - - opts.on('-w', '--wallet WALLET', I18n.t('option.wallet')) do |wallet| - options[:wallet] = wallet + opts.on('-g', '--group GROUP', I18n.t('option.group')) do |group| + options[:group] = group end opts.on('-G', '--generate-password [LENGTH]', I18n.t('option.generate_password')) do |length| @@ -104,6 +83,30 @@ OptionParser.new do |opts| puts opts exit 0 end + + opts.on('-i', '--import FILE', I18n.t('option.import')) do |file| + options[:import] = file + end + + opts.on('-N', '--no-sync', I18n.t('option.no_sync')) do + options[:sync] = false + end + + opts.on('-s', '--show [SEARCH]', I18n.t('option.show')) do |search| + search.nil? ? (options[:show] = '') : (options[:show] = search) + end + + opts.on('-S', '--setup', I18n.t('option.setup')) do + options[:setup] = true + end + + opts.on('-u', '--update ID', I18n.t('option.update')) do |id| + options[:update] = id + end + + opts.on('-w', '--wallet WALLET', I18n.t('option.wallet')) do |wallet| + options[:wallet] = wallet + end end.parse! # --------------------------------------------------------- # From 27c4162aa959f0da73781bc96e5259d84f1b0c1a Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sat, 7 May 2016 13:03:23 +0200 Subject: [PATCH 209/531] add options id --- bin/mpw | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/bin/mpw b/bin/mpw index ee201ba..6d92958 100755 --- a/bin/mpw +++ b/bin/mpw @@ -58,8 +58,8 @@ OptionParser.new do |opts| options[:config] = config end - opts.on('-d', '--delete ID', I18n.t('option.remove')) do |id| - options[:delete] = id + opts.on('-d', '--delete', I18n.t('option.remove')) do + options[:delete] = true end opts.on('-e', '--export FILE', I18n.t('option.export')) do |file| @@ -84,7 +84,11 @@ OptionParser.new do |opts| exit 0 end - opts.on('-i', '--import FILE', I18n.t('option.import')) do |file| + opts.on('-i', '--id ID', I18n.t('option.id')) do |id| + options[:id] = id + end + + opts.on('-I', '--import FILE', I18n.t('option.import')) do |file| options[:import] = file end @@ -100,8 +104,8 @@ OptionParser.new do |opts| options[:setup] = true end - opts.on('-u', '--update ID', I18n.t('option.update')) do |id| - options[:update] = id + opts.on('-u', '--update', I18n.t('option.update')) do + options[:update] = true end opts.on('-w', '--wallet WALLET', I18n.t('option.wallet')) do |wallet| @@ -138,12 +142,12 @@ if not options[:show].nil? cli.display(opts) # Remove an item -elsif not options[:delete].nil? - cli.delete(options[:delete], options[:force]) +elsif not options[:delete].nil? and not options[:id].nil? + cli.delete(options[:id], options[:force]) # Update an item -elsif not options[:update].nil? - cli.update(options[:update]) +elsif not options[:update].nil? and not options[:id].nil? + cli.update(options[:id]) # Add a new item elsif not options[:add].nil? From 22676a8b79b8480b8c32798378d94befdbb698c9 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sat, 7 May 2016 14:36:57 +0200 Subject: [PATCH 210/531] add public key in wallet --- bin/mpw | 10 +++++++++- lib/mpw/mpw.rb | 15 +++++++++++++-- lib/mpw/ui/cli.rb | 9 ++++++++- 3 files changed, 30 insertions(+), 4 deletions(-) diff --git a/bin/mpw b/bin/mpw index 6d92958..0663c6a 100755 --- a/bin/mpw +++ b/bin/mpw @@ -92,6 +92,10 @@ OptionParser.new do |opts| options[:import] = file end + opts.on('-k', '--key KEY', I18n.t('option.import')) do |key| + options[:key] = key + end + opts.on('-N', '--no-sync', I18n.t('option.no_sync')) do options[:sync] = false end @@ -150,9 +154,13 @@ elsif not options[:update].nil? and not options[:id].nil? cli.update(options[:id]) # Add a new item -elsif not options[:add].nil? +elsif not options[:add].nil? and options[:key].nil? cli.add +# Add a new public key in wallet +elsif not options[:add].nil? and not options[:key].nil? + cli.add_key(options[:key]) + # Export elsif not options[:export].nil? cli.export(options[:export]) diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index 230ff53..127da7f 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -112,7 +112,7 @@ class MPW @keys.each do |id, key| tar.add_file_simple("wallet/keys/#{id}.pub", 0400, key.length) do |io| - io.write(password) + io.write(key) end end end @@ -131,6 +131,18 @@ class MPW @passwords[id] = encrypt(password) end + # Add public key + # args: key -> new public key + def add_key(key) + data = GPGME::Key.export(key).read + + if data.to_s.empty? + raise I18n.t('error.export_key') + end + + @keys[key] = data + end + # TODO def check_config if false @@ -150,7 +162,6 @@ class MPW end end - # Search in some csv data # @args: options -> a hash with paramaters # @rtrn: a list with the resultat of the search diff --git a/lib/mpw/ui/cli.rb b/lib/mpw/ui/cli.rb index 57063de..4d36cd8 100644 --- a/lib/mpw/ui/cli.rb +++ b/lib/mpw/ui/cli.rb @@ -157,7 +157,6 @@ class Cli def get_wallet(wallet=nil) if wallet.to_s.empty? wallets = Dir.glob("#{@config.wallet_dir}/*.mpw") - puts wallets case wallets.length when 0 @@ -186,6 +185,14 @@ class Cli end end + # Add new public key + def add_key(key) + @mpw.add_key(key) + @mpw.write_data + rescue Exception => e + puts "#{I18n.t('display.error')} #13: #{e}".red + end + # Form to add a new item def add options = {} From 812a02d60e5aa1e5a23fc853f30907d0856b7246 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sat, 7 May 2016 14:53:37 +0200 Subject: [PATCH 211/531] add backup when write data --- lib/mpw/mpw.rb | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index 127da7f..29f8bb6 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -77,9 +77,9 @@ class MPW end # Encrypt a file - # TODO backup and restore file with raise def write_data - data = {} + data = {} + tmp_file = "#{@wallet_file}.tmp" @data.each do |item| next if item.empty? @@ -98,7 +98,7 @@ class MPW ) end - Gem::Package::TarWriter.new(File.open(@wallet_file, 'w+')) do |tar| + Gem::Package::TarWriter.new(File.open(tmp_file, 'w+')) do |tar| data_encrypt = encrypt(YAML::dump(data)) tar.add_file_simple('wallet/meta.gpg', 0400, data_encrypt.length) do |io| io.write(data_encrypt) @@ -116,6 +116,12 @@ class MPW end end end + + File.rename(tmp_file, @wallet_file) + rescue Exception => e + File.unlink(tmp_file) + + raise "#{I18n.t('error.mpw_file.write_data')}\n#{e}" end # Get a password From ad1713edcbe2c9fc5058b27859c76be321a8b3a9 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sat, 7 May 2016 15:05:14 +0200 Subject: [PATCH 212/531] add class cli in module mpw --- bin/mpw | 2 +- lib/mpw/ui/cli.rb | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/bin/mpw b/bin/mpw index 0663c6a..669a0f0 100755 --- a/bin/mpw +++ b/bin/mpw @@ -124,7 +124,7 @@ end.parse! config = MPW::Config.new(options[:config]) check_error = config.checkconfig -cli = Cli.new(config) +cli = MPW::Cli.new(config) # Setup a new config if not check_error or not options[:setup].nil? diff --git a/lib/mpw/ui/cli.rb b/lib/mpw/ui/cli.rb index 4d36cd8..3dd85a1 100644 --- a/lib/mpw/ui/cli.rb +++ b/lib/mpw/ui/cli.rb @@ -11,6 +11,7 @@ require 'highline/import' require "#{APP_ROOT}/../lib/mpw/item.rb" require "#{APP_ROOT}/../lib/mpw/mpw.rb" +module MPW class Cli # Constructor @@ -88,7 +89,7 @@ class Cli def decrypt if not defined?(@mpw) @password = ask(I18n.t('display.gpg_password')) {|q| q.echo = false} - @mpw = MPW::MPW.new(@config.key, @wallet_file, @password) + @mpw = MPW.new(@config.key, @wallet_file, @password) end @mpw.read_data @@ -208,7 +209,7 @@ class Cli options[:port] = ask(I18n.t('form.add.port')).to_s options[:comment] = ask(I18n.t('form.add.comment')).to_s - item = MPW::Item.new(options) + item = Item.new(options) @mpw.add(item) @mpw.set_password(item.id, password) @@ -299,3 +300,4 @@ class Cli puts "#{I18n.t('display.error')} #18: #{e}".red end end +end From 7759c3e1ebfa435357df641b6f9c6e177a970065 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sat, 7 May 2016 16:27:55 +0200 Subject: [PATCH 213/531] minor fix for add key pub --- lib/mpw/mpw.rb | 2 +- lib/mpw/ui/cli.rb | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index 29f8bb6..9d9d14f 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -140,7 +140,7 @@ class MPW # Add public key # args: key -> new public key def add_key(key) - data = GPGME::Key.export(key).read + data = GPGME::Key.export(key, armor: true).read if data.to_s.empty? raise I18n.t('error.export_key') diff --git a/lib/mpw/ui/cli.rb b/lib/mpw/ui/cli.rb index 3dd85a1..378c290 100644 --- a/lib/mpw/ui/cli.rb +++ b/lib/mpw/ui/cli.rb @@ -190,6 +190,8 @@ class Cli def add_key(key) @mpw.add_key(key) @mpw.write_data + + puts "#{I18n.t('key.add.valid')}".green rescue Exception => e puts "#{I18n.t('display.error')} #13: #{e}".red end From 22239c5db456805c4e214a36f24704360f1d7e79 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sat, 7 May 2016 17:47:24 +0200 Subject: [PATCH 214/531] remove a pub key --- bin/mpw | 5 ++++- lib/mpw/mpw.rb | 8 +++++++- lib/mpw/ui/cli.rb | 14 +++++++++++++- 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/bin/mpw b/bin/mpw index 669a0f0..d74f20a 100755 --- a/bin/mpw +++ b/bin/mpw @@ -161,6 +161,10 @@ elsif not options[:add].nil? and options[:key].nil? elsif not options[:add].nil? and not options[:key].nil? cli.add_key(options[:key]) +# Delete a public key in wallet +elsif not options[:delete].nil? and not options[:key].nil? + cli.delete_key(options[:key]) + # Export elsif not options[:export].nil? cli.export(options[:export]) @@ -169,7 +173,6 @@ elsif not options[:export].nil? elsif not options[:import].nil? cli.import(options[:import]) -# Interactive mode end cli = nil diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index 9d9d14f..f5dc2a2 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -137,7 +137,7 @@ class MPW @passwords[id] = encrypt(password) end - # Add public key + # Add a public key # args: key -> new public key def add_key(key) data = GPGME::Key.export(key, armor: true).read @@ -149,6 +149,12 @@ class MPW @keys[key] = data end + # Delete a public key + # args: key -> public key to delete + def delete_key(key) + @keys.delete(key) + end + # TODO def check_config if false diff --git a/lib/mpw/ui/cli.rb b/lib/mpw/ui/cli.rb index 378c290..682747f 100644 --- a/lib/mpw/ui/cli.rb +++ b/lib/mpw/ui/cli.rb @@ -186,7 +186,8 @@ class Cli end end - # Add new public key + # Add a new public key + # args: key -> the key name to add def add_key(key) @mpw.add_key(key) @mpw.write_data @@ -196,6 +197,17 @@ class Cli puts "#{I18n.t('display.error')} #13: #{e}".red end + # Add new public key + # args: key -> the key name to delete + def delete_key(key) + @mpw.delete_key(key) + @mpw.write_data + + puts "#{I18n.t('key.delete.valid')}".green + rescue Exception => e + puts "#{I18n.t('display.error')} #15: #{e}".red + end + # Form to add a new item def add options = {} From 731017e223cf47d353ceeb9cb8187e2d02d333ec Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sat, 7 May 2016 18:47:21 +0200 Subject: [PATCH 215/531] remove unused lib --- lib/mpw/mpw.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index f5dc2a2..c66fa3b 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -5,7 +5,6 @@ require 'rubygems/package' require 'gpgme' require 'i18n' -require 'fileutils' require 'yaml' #TODO From 0878155bcf18e981727a4ca9316f24f8568e322f Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sun, 8 May 2016 09:35:02 +0200 Subject: [PATCH 216/531] add option -f for file --- bin/mpw | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/bin/mpw b/bin/mpw index d74f20a..cb3bdf4 100755 --- a/bin/mpw +++ b/bin/mpw @@ -62,11 +62,15 @@ OptionParser.new do |opts| options[:delete] = true end - opts.on('-e', '--export FILE', I18n.t('option.export')) do |file| - options[:export] = file + opts.on('-e', '--export', I18n.t('option.export')) do + options[:export] = true end - opts.on('-f', '--force', I18n.t('option.force')) do + opts.on('-f', '--file', I18n.t('option.file')) do |file| + options[:file] = file + end + + opts.on('-F', '--force', I18n.t('option.force')) do options[:force] = true end @@ -88,11 +92,11 @@ OptionParser.new do |opts| options[:id] = id end - opts.on('-I', '--import FILE', I18n.t('option.import')) do |file| - options[:import] = file + opts.on('-I', '--import', I18n.t('option.import')) do + options[:import] = true end - opts.on('-k', '--key KEY', I18n.t('option.import')) do |key| + opts.on('-k', '--key KEY', I18n.t('option.key')) do |key| options[:key] = key end @@ -166,12 +170,12 @@ elsif not options[:delete].nil? and not options[:key].nil? cli.delete_key(options[:key]) # Export -elsif not options[:export].nil? - cli.export(options[:export]) +elsif not options[:export].nil? and not options[:file].nil? + cli.export(options[:file]) # Add a new item -elsif not options[:import].nil? - cli.import(options[:import]) +elsif not options[:import].nil? and not options[:file].nil? + cli.import(options[:file]) end From 0bf8d4e4ba498e4992da48894409d268296d8963 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sun, 8 May 2016 10:13:25 +0200 Subject: [PATCH 217/531] add import gpg file --- bin/mpw | 4 ++-- lib/mpw/mpw.rb | 13 ++++++++++--- lib/mpw/ui/cli.rb | 5 +++-- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/bin/mpw b/bin/mpw index cb3bdf4..a185b49 100755 --- a/bin/mpw +++ b/bin/mpw @@ -66,7 +66,7 @@ OptionParser.new do |opts| options[:export] = true end - opts.on('-f', '--file', I18n.t('option.file')) do |file| + opts.on('-f', '--file FILE', I18n.t('option.file')) do |file| options[:file] = file end @@ -163,7 +163,7 @@ elsif not options[:add].nil? and options[:key].nil? # Add a new public key in wallet elsif not options[:add].nil? and not options[:key].nil? - cli.add_key(options[:key]) + cli.add_key(options[:key], options[:file]) # Delete a public key in wallet elsif not options[:delete].nil? and not options[:key].nil? diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index c66fa3b..2c988c5 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -138,8 +138,15 @@ class MPW # Add a public key # args: key -> new public key - def add_key(key) - data = GPGME::Key.export(key, armor: true).read + # file -> public gpg file to import + def add_key(key, file=nil) + if not file.nil? and File.exists?(file) + data = File.open(file).read + GPGME::Key.import(data, armor: true) + puts GPGME::Key.find(key)[0].trust + else + data = GPGME::Key.export(key, armor: true).read + end if data.to_s.empty? raise I18n.t('error.export_key') @@ -298,7 +305,7 @@ class MPW private def encrypt(data) recipients = [] - crypto = GPGME::Crypto.new(armor: true) + crypto = GPGME::Crypto.new(armor: true, always_trust: true) @keys.each_key do |key| recipients.push(key) diff --git a/lib/mpw/ui/cli.rb b/lib/mpw/ui/cli.rb index 682747f..a3b846b 100644 --- a/lib/mpw/ui/cli.rb +++ b/lib/mpw/ui/cli.rb @@ -188,8 +188,9 @@ class Cli # Add a new public key # args: key -> the key name to add - def add_key(key) - @mpw.add_key(key) + # file -> gpg public file to import + def add_key(key, file=nil) + @mpw.add_key(key, file) @mpw.write_data puts "#{I18n.t('key.add.valid')}".green From 855640c93252dfef8ce69790fb8f4468d0fc6f20 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sun, 8 May 2016 10:25:16 +0200 Subject: [PATCH 218/531] auto import public key in mpw file --- lib/mpw/mpw.rb | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index 2c988c5..f99153b 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -45,7 +45,13 @@ class MPW data = decrypt(f.read) when /^wallet\/keys\/(?<key>.+)\.pub$/ - @keys[Regexp.last_match('key')] = f.read + key = Regexp.last_match('key') + + if GPGME::Key.find(:public, key).length == 0 + GPGME::Key.import(f.read, armor: true) + end + + @keys[key] = f.read when /^wallet\/passwords\/(?<id>[a-zA-Z0-9]+)\.gpg$/ @passwords[Regexp.last_match('id')] = f.read @@ -143,7 +149,6 @@ class MPW if not file.nil? and File.exists?(file) data = File.open(file).read GPGME::Key.import(data, armor: true) - puts GPGME::Key.find(key)[0].trust else data = GPGME::Key.export(key, armor: true).read end From dd0e236fc56922cb71fed89e70d602da3ac01009 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sun, 8 May 2016 11:22:08 +0200 Subject: [PATCH 219/531] remove mpw server protocol --- bin/mpw-server | 78 ---------------------------- lib/mpw/sync.rb | 3 -- lib/mpw/sync/mpw.rb | 124 -------------------------------------------- 3 files changed, 205 deletions(-) delete mode 100755 bin/mpw-server delete mode 100644 lib/mpw/sync/mpw.rb diff --git a/bin/mpw-server b/bin/mpw-server deleted file mode 100755 index 3a7ce5a..0000000 --- a/bin/mpw-server +++ /dev/null @@ -1,78 +0,0 @@ -#!/usr/bin/ruby -# author: nishiki -# mail: nishiki@yaegashi.fr -# info: a simple script who manage your passwords - -require 'rubygems' -require 'optparse' -require 'pathname' -require 'locale' -require 'i18n' -require 'mpw/server' - -APP_ROOT = File.dirname(Pathname.new(__FILE__).realpath) - -# --------------------------------------------------------- # -# Set local -# --------------------------------------------------------- # - -lang = Locale::Tag.parse(ENV['LANG']).to_simple.to_s[0..1] - -if defined?(I18n.enforce_available_locales) - I18n.enforce_available_locales = true -end - -I18n::Backend::Simple.send(:include, I18n::Backend::Fallbacks) -I18n.load_path = Dir["#{APP_ROOT}/../i18n/server/*.yml"] -I18n.default_locale = :en -I18n.locale = lang.to_sym - -# --------------------------------------------------------- # -# Options -# --------------------------------------------------------- # - -options = {} -OptionParser.new do |opts| - opts.banner = "#{I18n.t('option.usage')}: mpw-server -c CONFIG [options]" - - opts.on("-c", "--config CONFIG", I18n.t('option.config')) do |config| - options[:config] = config - end - - opts.on("-t", "--checkconfig", I18n.t('option.checkconfig')) do |b| - options[:checkconfig] = b - end - - opts.on("-s", "--setup", I18n.t('option.setup')) do |b| - options[:setup] = b - end - - opts.on("-h", "--help", I18n.t('option.help')) do |b| - puts opts - exit 0 - end -end.parse! - -# --------------------------------------------------------- # -# Main -# --------------------------------------------------------- # - -if options[:config].nil? or options[:config].empty? - puts "#{I18n.t('option.usage')}: mpw-server -c CONFIG [options]" - exit 2 -end - -server = MPW::Server.new - -if options[:checkconfig] - server.checkconfig(options[:config]) -elsif options[:setup] - server.setup(options[:config]) -else - if server.checkconfig(options[:config]) - server.start - end -end - -server = nil -exit 0 diff --git a/lib/mpw/sync.rb b/lib/mpw/sync.rb index 3e18d32..f271d79 100644 --- a/lib/mpw/sync.rb +++ b/lib/mpw/sync.rb @@ -30,9 +30,6 @@ module MPW # @rtrn: true if get the date, else false def get_remote case @config.sync_type - when 'mpw' - require 'mpw/sync/mpw' - @sync = SyncMPW.new(@config.sync_host, @config.sync_user, @config.sync_pwd, @config.sync_path, @config.sync_port) when 'sftp', 'scp', 'ssh' require 'mpw/sync/ssh' @sync = SyncSSH.new(@config.sync_host, @config.sync_user, @config.sync_pwd, @config.sync_path, @config.sync_port) diff --git a/lib/mpw/sync/mpw.rb b/lib/mpw/sync/mpw.rb deleted file mode 100644 index 596414d..0000000 --- a/lib/mpw/sync/mpw.rb +++ /dev/null @@ -1,124 +0,0 @@ -#!/usr/bin/ruby -# author: nishiki - -require 'rubygems' -require 'i18n' -require 'socket' -require 'json' -require 'timeout' - -module MPW - class SyncMPW - - attr_accessor :error_msg - attr_accessor :enable - - # Constructor - # @args: host -> the server host - # port -> ther connection port - # gpg_key -> the gpg key - # password -> the remote password - # suffix -> the suffix file - def initialize(host, user, password, suffix, port=nil) - @error_msg = nil - @enable = false - - @host = host - @port = !port.instance_of?(Integer) ? 2201 : port - @gpg_key = user - @password = password - @suffix = suffix - end - - # Connect to server - # @rtrn: false if the connection fail - def connect - Timeout.timeout(10) do - begin - TCPSocket.open(@host, @port) do - @enable = true - end - rescue Errno::ENETUNREACH - retry - end - end - rescue Timeout::Error - @error_msg = "#{I18n.t('error.timeout')}\n#{e}" - @enable = false - rescue Exception => e - @error_msg = "#{I18n.t('error.sync.connection')}\n#{e}" - @enable = false - else - return @enable - end - - # Get data on server - # @args: gpg_password -> the gpg password - # @rtrn: nil if nothing data or error - def get(file_tmp) - return false if not @enable - - msg = nil - TCPSocket.open(@host, @port) do |socket| - send_msg = {action: 'get', - gpg_key: @gpg_key, - password: @password, - suffix: @suffix - } - - socket.puts send_msg.to_json - msg = JSON.parse(socket.gets) - end - - if not defined?(msg['error']) - @error_msg = I18n.t('error.sync.communication') - return false - elsif not msg['error'].nil? - @error_msg = I18n.t(msg['error']) - return false - end - - File.open(file_tmp, 'w') do |file| - file << msg['data'] - end - - return true - rescue Exception => e - @error_msg = "#{I18n.t('error.sync.download')}\n#{e}" - return false - end - - # Update the remote data - # @args: data -> the data to send on server - # @rtrn: false if there is a problem - def update(file_gpg) - return true if not @enable - - data = File.open(file_gpg, 'r').read - - msg = nil - TCPSocket.open(@host, @port) do |socket| - send_msg = {action: 'update', - gpg_key: @gpg_key, - password: @password, - suffix: @suffix, - data: data - } - - socket.puts send_msg.to_json - msg = JSON.parse(socket.gets) - end - - if not defined?(msg['error']) - @error_msg = I18n.t('error.sync.communication') - return false - elsif msg['error'].nil? - return true - else - @error_msg = I18n.t(msg['error']) - return false - end - end - - end -end From 85c034b8b3a0ca193ffa45bc76437841328a5cd1 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sun, 8 May 2016 11:34:29 +0200 Subject: [PATCH 220/531] remove mpw-ssh --- bin/mpw-ssh | 89 -------------------------------------------- lib/mpw/ui/clissh.rb | 42 --------------------- 2 files changed, 131 deletions(-) delete mode 100755 bin/mpw-ssh delete mode 100644 lib/mpw/ui/clissh.rb diff --git a/bin/mpw-ssh b/bin/mpw-ssh deleted file mode 100755 index b5f1252..0000000 --- a/bin/mpw-ssh +++ /dev/null @@ -1,89 +0,0 @@ -#!/usr/bin/ruby -# author: nishiki -# mail: nishiki@yaegashi.fr -# info: a simple script who manage your passwords - -require 'rubygems' -require 'optparse' -require 'pathname' -require 'locale' -require 'i18n' -require 'mpw/ui/clissh' -require 'mpw/config' - -# --------------------------------------------------------- # -# Set local -# --------------------------------------------------------- # - -APP_ROOT = File.dirname(Pathname.new(__FILE__).realpath) -lang = Locale::Tag.parse(ENV['LANG']).to_simple.to_s[0..1] - -if defined?(I18n.enforce_available_locales) - I18n.enforce_available_locales = true -end - -I18n::Backend::Simple.send(:include, I18n::Backend::Fallbacks) -I18n.load_path = Dir["#{APP_ROOT}/../i18n/cli/*.yml"] -I18n.default_locale = :en -I18n.locale = lang.to_sym - -# --------------------------------------------------------- # -# Options -# --------------------------------------------------------- # - -options = {} -OptionParser.new do |opts| - opts.banner = "#{I18n.t('ssh.option.usage')}: mpw-ssh SEARCH [options]" - - opts.on("-l", "--login LOGIN", I18n.t('ssh.option.login')) do |login| - options[:login] = login - end - - opts.on("-s", "--server SERVER", I18n.t('ssh.option.server')) do |server| - options[:server] = server - end - - opts.on("-p", "--port PORT", I18n.t('ssh.option.port')) do |port| - options[:port] = port - end - - opts.on('-c', '--config CONFIG', I18n.t('cli.option.config')) do |config| - options[:config] = config - end - - opts.on("-h", "--help", I18n.t('ssh.option.help')) do - puts opts - exit 0 - end -end.parse! - -# --------------------------------------------------------- # -# Main -# --------------------------------------------------------- # - -config = MPW::Config.new(options[:config]) -check_error = config.checkconfig - -cli = CliSSH.new(config) -cli.login = options[:login] -cli.server = options[:server] -cli.port = options[:port] - -search = ARGV[0] - -# Setup a new config -if not check_error - cli.setup(lang) - -elsif ARGV.length < 1 - puts "#{I18n.t('ssh.option.usage')}: mpw-ssh SEARCH [options]" - exit 2 -else - cli.decrypt - cli.sync - cli.ssh(search) -end - -cli = nil - -exit 0 diff --git a/lib/mpw/ui/clissh.rb b/lib/mpw/ui/clissh.rb deleted file mode 100644 index 0bf7bb0..0000000 --- a/lib/mpw/ui/clissh.rb +++ /dev/null @@ -1,42 +0,0 @@ -#!/usr/bin/ruby -# author: nishiki -# mail: nishiki@yaegashi.fr -# info: a simple script who manage your passwords - -require 'mpw/ui/cli' - -class CliSSH < Cli - - attr_accessor :server, :port, :login - - # Connect to SSH - # args: search -> string to search - def ssh(search) - result = @mpw.list(search: search, protocol: 'ssh') - - if result.length > 0 - result.each do |item| - server = @server.nil? ? item.host : @server - port = @port.nil? ? item.port : @port - login = @login.nil? ? item.user : @login - - passwd = item.password - - if port.nil? and port.empty? - port = 22 - end - - puts "#{I18n.t('ssh.display.connect')} ssh #{login}@#{server} -p #{port}" - if passwd.empty? - system("ssh #{login}@#{server} -p #{port}") - else - system("sshpass -p '#{passwd}' ssh #{login}@#{server} -p #{port}") - end - end - - else - puts I18n.t('ssh.display.nothing') - end - end -end - From 923977ba04e4acccaffc13b2bcbb1f9e5c01129c Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sun, 8 May 2016 12:06:06 +0200 Subject: [PATCH 221/531] add salt for password --- lib/mpw/mpw.rb | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index f99153b..1dde6f4 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -132,13 +132,22 @@ class MPW # Get a password # args: id -> the item id def get_password(id) - return decrypt(@passwords[id]) + password = decrypt(@passwords[id]) + + if /^\$[a-zA-Z0-9]{4,9}::(?<password>.+)$/ =~ password + return Regexp.last_match('password') + else + return password + end end # Set a password # args: id -> the item id # password -> the new password def set_password(id, password) + salt = MPW::password(Random.rand(4..9)) + password = "$#{salt}::#{password}" + @passwords[id] = encrypt(password) end From b6fb5cd486f35d61cf3ec2987f03f12b3dc2c88e Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sun, 8 May 2016 22:06:25 +0200 Subject: [PATCH 222/531] encrypt config wallet --- lib/mpw/mpw.rb | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index 1dde6f4..f9d8fa6 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -37,8 +37,8 @@ class MPW Gem::Package::TarReader.new(File.open(@wallet_file)) do |tar| tar.each do |f| case f.full_name - when 'wallet/config.yml' - @config = YAML.load(f.read) + when 'wallet/config.gpg' + @config = YAML.load(decrypt(f.read)) check_config when 'wallet/meta.gpg' @@ -109,6 +109,11 @@ class MPW io.write(data_encrypt) end + config = @config.to_yaml + tar.add_file_simple('wallet/config.gpg', 0400, config.length) do |io| + io.write(config) + end + @passwords.each do |id, password| tar.add_file_simple("wallet/passwords/#{id}.gpg", 0400, password.length) do |io| io.write(password) From 0a56019794e645cff3670ba1d5d2cab5b6d5da36 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sun, 8 May 2016 22:24:39 +0200 Subject: [PATCH 223/531] remove error_msg --- lib/mpw/mpw.rb | 3 --- 1 file changed, 3 deletions(-) diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index f9d8fa6..4b1bddc 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -13,11 +13,8 @@ require "#{APP_ROOT}/../lib/mpw/item.rb" module MPW class MPW - attr_accessor :error_msg - # Constructor def initialize(key, wallet_file, gpg_pass=nil) - @error_msg = nil @key = key @gpg_pass = gpg_pass @wallet_file = wallet_file From b85d5109a1316e57c05c2f92b3779e3d6d350084 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Thu, 12 May 2016 16:48:57 +0200 Subject: [PATCH 224/531] add function get_last_sync --- lib/mpw/mpw.rb | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index 4b1bddc..850be44 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -285,6 +285,13 @@ class MPW raise "#{I18n.t('error.import.read', file: file)}\n#{e}" end + # Get last sync + def get_last_sync + return @config['sync']['last_sync'].to_i + rescue + return 0 + end + # Generate a random password # @args: length -> the length password # @rtrn: a random string From 9b853a371a8436b0e82eaba27a5437e0d4773e66 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Thu, 12 May 2016 22:42:20 +0200 Subject: [PATCH 225/531] fix write config --- lib/mpw/mpw.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index 850be44..2c671a8 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -101,12 +101,12 @@ class MPW end Gem::Package::TarWriter.new(File.open(tmp_file, 'w+')) do |tar| - data_encrypt = encrypt(YAML::dump(data)) + data_encrypt = encrypt(data.to_yaml) tar.add_file_simple('wallet/meta.gpg', 0400, data_encrypt.length) do |io| io.write(data_encrypt) end - config = @config.to_yaml + config = encrypt(@config.to_yaml) tar.add_file_simple('wallet/config.gpg', 0400, config.length) do |io| io.write(config) end From ec982ce4d80cb164350b1b45c8c1a0b2f0c899a3 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Thu, 12 May 2016 22:43:57 +0200 Subject: [PATCH 226/531] add function for setup wallet config --- bin/mpw | 9 ++++++++- lib/mpw/mpw.rb | 6 ++++++ lib/mpw/ui/cli.rb | 20 ++++++++++++++++++++ 3 files changed, 34 insertions(+), 1 deletion(-) diff --git a/bin/mpw b/bin/mpw index a185b49..830b2c2 100755 --- a/bin/mpw +++ b/bin/mpw @@ -2,7 +2,6 @@ # author: nishiki # mail: nishiki@yaegashi.fr -require 'rubygems' require 'optparse' require 'pathname' require 'locale' @@ -119,6 +118,10 @@ OptionParser.new do |opts| opts.on('-w', '--wallet WALLET', I18n.t('option.wallet')) do |wallet| options[:wallet] = wallet end + + opts.on('-W', '--setup-wallet', I18n.t('option.setup_wallet')) do + options[:setup_wallet] = true + end end.parse! # --------------------------------------------------------- # @@ -177,6 +180,10 @@ elsif not options[:export].nil? and not options[:file].nil? elsif not options[:import].nil? and not options[:file].nil? cli.import(options[:file]) +# Setup wallet config +elsif not options[:setup_wallet].nil? + cli.setup_wallet_config + end cli = nil diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index 2c671a8..9ae896e 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -184,6 +184,12 @@ class MPW end end + # Set config + # args: config -> a hash with config options + def set_config(config) + @config = config + end + # Add a new item # @args: item -> Object MPW::Item def add(item) diff --git a/lib/mpw/ui/cli.rb b/lib/mpw/ui/cli.rb index a3b846b..ec99a7c 100644 --- a/lib/mpw/ui/cli.rb +++ b/lib/mpw/ui/cli.rb @@ -84,6 +84,26 @@ class Cli end end + # Setup wallet config for sync + def setup_wallet_config + config = {} + config['sync'] = {} + + puts I18n.t('form.setup.title') + puts '--------------------' + config['sync']['type'] = ask(I18n.t('form.setup.sync_type')).to_s + config['sync']['host'] = ask(I18n.t('form.setup.sync_host')).to_s + config['sync']['port'] = ask(I18n.t('form.setup.sync_port')).to_s + config['sync']['user'] = ask(I18n.t('form.setup.sync_user')).to_s + config['sync']['pwd'] = ask(I18n.t('form.setup.sync_pwd')).to_s + config['sync']['path'] = ask(I18n.t('form.setup.sync_path')).to_s + + @mpw.set_config(config) + @mpw.write_data + rescue Exception => e + puts "#{I18n.t('display.error')} #10: #{e}".red + exit 2 + end # Request the GPG password and decrypt the file def decrypt From e1de7b7704cd77ae002a19fb4749e0e4e7067f26 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Thu, 12 May 2016 22:44:57 +0200 Subject: [PATCH 227/531] rewrite class sync ssh --- lib/mpw/sync/ssh.rb | 113 ++++++++++++++++++-------------------------- 1 file changed, 45 insertions(+), 68 deletions(-) diff --git a/lib/mpw/sync/ssh.rb b/lib/mpw/sync/ssh.rb index 632e292..89a7fd5 100644 --- a/lib/mpw/sync/ssh.rb +++ b/lib/mpw/sync/ssh.rb @@ -2,79 +2,56 @@ # author: nishiki # mail: nishiki@yaegashi.fr -require 'rubygems' require 'i18n' require 'net/ssh' require 'net/sftp' module MPW - class SyncSSH - - attr_accessor :error_msg - attr_accessor :enable - - # Constructor - # @args: host -> the server host - # port -> ther connection port - # gpg_key -> the gpg key - # password -> the remote password - def initialize(host, user, password, path, port=nil) - @error_msg = nil - @enable = false - - @host = host - @user = user - @password = password - @path = path - @port = port.instance_of?(Integer) ? 22 : port - end - - # Connect to server - # @rtrn: false if the connection fail - def connect - Net::SSH.start(@host, @user, password: @password, port: @port) do |ssh| - @enable = true - end - rescue Exception => e - @error_msg = "#{I18n.t('error.sync.connection')}\n#{e}" - @enable = false - else - return @enable - end - - # Get data on server - # @args: gpg_password -> the gpg password - # @rtrn: nil if nothing data or error - def get(file_tmp) - return false if not @enable - - Net::SFTP.start(@host, @user, password: @password, port: @port) do |sftp| - sftp.lstat(@path) do |response| - sftp.download!(@path, file_tmp) if response.ok? - end - end - - return true - rescue Exception => e - @error_msg = "#{I18n.t('error.sync.download')}\n#{e}" - return false - end - - # Update the remote data - # @args: file_gpg -> the data to send on server - # @rtrn: false if there is a problem - def update(file_gpg) - return true if not @enable - - Net::SFTP.start(@host, @user, password: @password, port: @port) do |sftp| - sftp.upload!(file_gpg, @path) - end - - return true - rescue Exception => e - @error_msg = "#{I18n.t('error.sync.upload')}\n#{e}" - return false - end +class SyncSSH + # Constructor + # @args: config -> the config + def initialize(config) + @host = config['host'] + @user = config['user'] + @password = config['password'] + @path = config['path'] + @port = config['port'].instance_of?(Integer) ? 22 : config['port'] end + + # Connect to server + # @rtrn: false if the connection fail + def connect + Net::SSH.start(@host, @user, password: @password, port: @port) do + break + end + rescue Exception => e + raise "#{I18n.t('error.sync.connection')}\n#{e}" + end + + # Get data on server + # @args: gpg_password -> the gpg password + # @rtrn: nil if nothing data or error + def get(file_tmp) + Net::SFTP.start(@host, @user, password: @password, port: @port) do |sftp| + sftp.lstat(@path) do |response| + sftp.download!(@path, file_tmp) if response.ok? + end + end + rescue Exception => e + raise "#{I18n.t('error.sync.download')}\n#{e}" + end + + # Update the remote data + # @args: file_gpg -> the data to send on server + # @rtrn: false if there is a problem + def update(file_gpg) + Net::SFTP.start(@host, @user, password: @password, port: @port) do |sftp| + sftp.upload!(file_gpg, @path) + end + rescue Exception => e + raise "#{I18n.t('error.sync.upload')}\n#{e}" + end + +end end From 50422e07390f7b926b076c44e8bdf2ada7f28a20 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Thu, 12 May 2016 22:47:02 +0200 Subject: [PATCH 228/531] rewrite sync --- lib/mpw/mpw.rb | 95 ++++++++++++++++++++++++++++++++ lib/mpw/sync.rb | 135 ---------------------------------------------- lib/mpw/ui/cli.rb | 1 + 3 files changed, 96 insertions(+), 135 deletions(-) delete mode 100644 lib/mpw/sync.rb diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index 9ae896e..e488805 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -298,6 +298,101 @@ class MPW return 0 end + # Sync data with remote file + def sync + return if @config['sync'].nil? + + tmp_file = "#{@wallet_file}.sync" + last_sync = @config['last_sync'].to_i + + case @config['sync']['type'] + when 'sftp', 'scp', 'ssh' + require "#{APP_ROOT}/../lib/mpw/sync/ssh.rb" + sync = SyncSSH.new(@config['sync']) + when 'ftp' + require 'mpw/sync/ftp' + sync = SyncFTP.new(@config['sync']) + else + raise I18n.t('error.unknown_type') + end + + sync.connect + sync.get(tmp_file) + + remote = MPW.new(@key, @wallet_file, @gpg_pass) + remote.read_data + + File.unlink(tmp_file) if File.exist?(tmp_file) + + if not remote.to_s.empty? + @data.each do |item| + update = false + + remote.list.each do |r| + next if item.id != r.id + + # Update item + if item.last_edit < r.last_edit + item.update(name: r.name, + group: r.group, + host: r.host, + protocol: r.protocol, + user: r.user, + port: r.port, + comment: r.comment + ) + set_password(item.id, r.get_password(item.id)) + end + + r.delete + update = true + + break + end + + # Remove an old item + if not update and item.last_sync.to_i < last_sync and item.last_edit < last_sync + item.delete + end + end + end + + # Add item + remote.list.each do |r| + next if r.last_edit <= last_sync + + item = Item.new(id: r.id, + name: r.name, + group: r.group, + host: r.host, + protocol: r.protocol, + user: r.user, + port: r.port, + comment: r.comment, + created: r.created, + last_edit: r.last_edit + ) + + set_password(item.id, r.get_password(item.id)) + add(item) + end + + remote = nil + + @data.each do |item| + item.set_last_sync + end + + @config['sync']['last_sync'] = Time.now.to_i + + write_data + sync.update(@wallet_file) + rescue Exception => e + File.unlink(tmp_file) if File.exist?(tmp_file) + + raise "#{I18n.t('error.sync.unknown')}\n#{e}" + end + # Generate a random password # @args: length -> the length password # @rtrn: a random string diff --git a/lib/mpw/sync.rb b/lib/mpw/sync.rb deleted file mode 100644 index f271d79..0000000 --- a/lib/mpw/sync.rb +++ /dev/null @@ -1,135 +0,0 @@ -#!/usr/bin/ruby -# author: nishiki -# mail: nishiki@yaegashi.fr -# info: a simple script who manage your passwords - -require 'rubygems' -require 'i18n' -require 'yaml' -require 'tempfile' -require 'mpw/mpw' -require 'mpw/item' - -module MPW - class Sync - - attr_accessor :error_msg - - # Constructor - # raise an exception if there is a bad parameter - def initialize(config, local, password=nil) - @error_msg = nil - @config = config - @local = local - @password = password - - raise I18n.t('error.class') if not @local.instance_of?(MPW) - end - - # Get the data on remote host - # @rtrn: true if get the date, else false - def get_remote - case @config.sync_type - when 'sftp', 'scp', 'ssh' - require 'mpw/sync/ssh' - @sync = SyncSSH.new(@config.sync_host, @config.sync_user, @config.sync_pwd, @config.sync_path, @config.sync_port) - when 'ftp' - require 'mpw/sync/ftp' - @sync = SyncFTP.new(@config.sync_host, @config.sync_user, @config.sync_pwd, @config.sync_path, @config.sync_port) - else - @error_msg = I18n.t('error.unknown_type') - return false - end - - if not @sync.connect - @error_msg = @sync.error_msg - return false - end - - - file_tmp = Tempfile.new('mpw-') - raise @sync.error_msg if not @sync.get(file_tmp.path) - - @remote = MPW.new(file_tmp.path, @config.key) - raise @remote.error_msg if not @remote.decrypt(@password) - - file_tmp.close(true) - return true - rescue Exception => e - @error_msg = "#{I18n.t('error.sync.download')} #{e}" - file_tmp.close(true) - return false - end - - # Sync remote data and local data - # raise an exception if there is a problem - def sync - - if not @remote.to_s.empty? - @local.list.each do |item| - update = false - @remote.list.each do |r| - - # Update item - if item.id == r.id - if item.last_edit < r.last_edit - raise item.error_msg if not item.update(name: r.name, - group: r.group, - host: r.host, - protocol: r.protocol, - user: r.user, - password: r.password, - port: r.port, - comment: r.comment - ) - end - - r.delete - update = true - - break - end - end - - # Remove an old item - if not update and item.last_sync.to_i < @config.last_sync and item.last_edit < @config.last_sync - item.delete - end - end - end - - # Add item - @remote.list.each do |r| - if r.last_edit > @config.last_sync - item = Item.new(id: r.id, - name: r.name, - group: r.group, - host: r.host, - protocol: r.protocol, - user: r.user, - password: r.password, - port: r.port, - comment: r.comment, - created: r.created, - last_edit: r.last_edit - ) - raise @local.error_msg if not @local.add(item) - end - end - - @local.list.each do |item| - item.set_last_sync - end - - raise @mpw.error_msg if not @local.encrypt - raise @sync.error_msg if not @sync.update(@config.file_gpg) - - @config.set_last_sync - - return true - rescue Exception => e - @error_msg = "#{I18n.t('error.sync.unknown')} #{e}" - return false - end - end -end diff --git a/lib/mpw/ui/cli.rb b/lib/mpw/ui/cli.rb index ec99a7c..59da85b 100644 --- a/lib/mpw/ui/cli.rb +++ b/lib/mpw/ui/cli.rb @@ -113,6 +113,7 @@ class Cli end @mpw.read_data + @mpw.sync rescue Exception => e puts "#{I18n.t('display.error')} #11: #{e}".red exit 2 From 684e0e32f038497ee1f8acd950383d6bda14771f Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Thu, 12 May 2016 23:39:50 +0200 Subject: [PATCH 229/531] fix password for wallet config --- lib/mpw/ui/cli.rb | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/mpw/ui/cli.rb b/lib/mpw/ui/cli.rb index 59da85b..686e897 100644 --- a/lib/mpw/ui/cli.rb +++ b/lib/mpw/ui/cli.rb @@ -91,12 +91,12 @@ class Cli puts I18n.t('form.setup.title') puts '--------------------' - config['sync']['type'] = ask(I18n.t('form.setup.sync_type')).to_s - config['sync']['host'] = ask(I18n.t('form.setup.sync_host')).to_s - config['sync']['port'] = ask(I18n.t('form.setup.sync_port')).to_s - config['sync']['user'] = ask(I18n.t('form.setup.sync_user')).to_s - config['sync']['pwd'] = ask(I18n.t('form.setup.sync_pwd')).to_s - config['sync']['path'] = ask(I18n.t('form.setup.sync_path')).to_s + config['sync']['type'] = ask(I18n.t('form.setup.sync_type')).to_s + config['sync']['host'] = ask(I18n.t('form.setup.sync_host')).to_s + config['sync']['port'] = ask(I18n.t('form.setup.sync_port')).to_s + config['sync']['user'] = ask(I18n.t('form.setup.sync_user')).to_s + config['sync']['password'] = ask(I18n.t('form.setup.sync_pwd')).to_s + config['sync']['path'] = ask(I18n.t('form.setup.sync_path')).to_s @mpw.set_config(config) @mpw.write_data From 31751455c59c34e44b202793b6a29aafe3761e49 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Fri, 13 May 2016 15:51:17 +0200 Subject: [PATCH 230/531] secure the wallet config --- lib/mpw/mpw.rb | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index e488805..2408515 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -22,7 +22,7 @@ class MPW # Read mpw file def read_data - @config = nil + @config = {} @data = [] @keys = {} @passwords = {} @@ -187,7 +187,15 @@ class MPW # Set config # args: config -> a hash with config options def set_config(config) - @config = config + @config['sync'] = {} if @config['sync'].nil? + + @config['sync']['type'] = config['sync']['type'] + @config['sync']['host'] = config['sync']['host'] + @config['sync']['port'] = config['sync']['port'] + @config['sync']['user'] = config['sync']['user'] + @config['sync']['password'] = config['sync']['password'] + @config['sync']['path'] = config['sync']['path'] + @config['sync']['last_sync'] = @config['sync']['last_sync'].nil? ? 0 : @config['sync']['last_sync'] end # Add a new item @@ -300,7 +308,7 @@ class MPW # Sync data with remote file def sync - return if @config['sync'].nil? + return if @config.empty? or @config['sync'].nil? tmp_file = "#{@wallet_file}.sync" last_sync = @config['last_sync'].to_i From 1399a17c8e23a3dff8f53c9feab8571927104a5f Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Fri, 13 May 2016 15:51:49 +0200 Subject: [PATCH 231/531] mutliple fixes for sync --- lib/mpw/mpw.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index 2408515..9197307 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -327,7 +327,7 @@ class MPW sync.connect sync.get(tmp_file) - remote = MPW.new(@key, @wallet_file, @gpg_pass) + remote = MPW.new(@key, tmp_file, @gpg_pass) remote.read_data File.unlink(tmp_file) if File.exist?(tmp_file) @@ -349,7 +349,7 @@ class MPW port: r.port, comment: r.comment ) - set_password(item.id, r.get_password(item.id)) + set_password(item.id, remote.get_password(item.id)) end r.delete @@ -381,7 +381,7 @@ class MPW last_edit: r.last_edit ) - set_password(item.id, r.get_password(item.id)) + set_password(item.id, remote.get_password(item.id)) add(item) end From b51144758dd1f9a3a8bbd3c4262ae1c910b29555 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Fri, 13 May 2016 16:05:09 +0200 Subject: [PATCH 232/531] automaticly add our public key in wallet --- lib/mpw/mpw.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index 9197307..b8f315c 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -74,6 +74,8 @@ class MPW ) end end + + add_key(@key) if @keys[@key].nil? rescue Exception => e raise "#{I18n.t('error.mpw_file.read_data')}\n#{e}" end From 460450ce082464ef3914698799c1cd2c3121c0d3 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Fri, 13 May 2016 16:13:14 +0200 Subject: [PATCH 233/531] add sync after add, update or delete action --- lib/mpw/ui/cli.rb | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/mpw/ui/cli.rb b/lib/mpw/ui/cli.rb index 686e897..6e301f4 100644 --- a/lib/mpw/ui/cli.rb +++ b/lib/mpw/ui/cli.rb @@ -213,6 +213,7 @@ class Cli def add_key(key, file=nil) @mpw.add_key(key, file) @mpw.write_data + @mpw.sync puts "#{I18n.t('key.add.valid')}".green rescue Exception => e @@ -224,6 +225,7 @@ class Cli def delete_key(key) @mpw.delete_key(key) @mpw.write_data + @mpw.sync puts "#{I18n.t('key.delete.valid')}".green rescue Exception => e @@ -250,6 +252,7 @@ class Cli @mpw.add(item) @mpw.set_password(item.id, password) @mpw.write_data + @mpw.sync puts "#{I18n.t('form.add.valid')}".green end @@ -278,6 +281,7 @@ class Cli item.update(options) @mpw.set_password(item.id, password) if not password.empty? @mpw.write_data + @mpw.sync puts "#{I18n.t('form.update.valid')}".green else @@ -309,6 +313,7 @@ class Cli item.delete @mpw.write_data + @mpw.sync puts "#{I18n.t('form.delete.valid', id: id)}".green rescue From 81da0407d02193a16a9acc96875eb799f5b904d8 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sat, 14 May 2016 12:10:24 +0200 Subject: [PATCH 234/531] remove search with protocol --- bin/mpw | 1 - lib/mpw/mpw.rb | 3 --- 2 files changed, 4 deletions(-) diff --git a/bin/mpw b/bin/mpw index 830b2c2..97b846d 100755 --- a/bin/mpw +++ b/bin/mpw @@ -147,7 +147,6 @@ cli.decrypt if not options[:show].nil? opts = {search: options[:show], group: options[:group], - protocol: options[:protocol], } cli.display(opts) diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index b8f315c..767522a 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -220,13 +220,10 @@ class MPW search = options[:search].to_s.downcase group = options[:group].to_s.downcase - protocol = options[:protocol].to_s.downcase @data.each do |item| next if item.empty? - next if not group.empty? and not group.eql?(item.group.downcase) - next if not protocol.empty? and not protocol.eql?(item.protocol.downcase) name = item.name.to_s.downcase host = item.host.to_s.downcase From e29346cbb3a316e3ffb461e93417e5cd0182ca99 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sat, 14 May 2016 12:13:04 +0200 Subject: [PATCH 235/531] translation fr option --- i18n/cli/fr.yml | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/i18n/cli/fr.yml b/i18n/cli/fr.yml index e9790c0..38a39d4 100644 --- a/i18n/cli/fr.yml +++ b/i18n/cli/fr.yml @@ -38,24 +38,26 @@ fr: select: "Votre choix n'est pas un élément valide!" option: - usage: "Utilisation" + add: "Ajoute un élément ou une clé" + config: "Spécifie le fichier de configuration à utiliser" + export: "Exporte un portefeuille dans un fichier yaml" + file: "Spécifie un fichier, à utiliser avec les options [--import | --export | --add]" + force: "Ne demande pas de confirmation pour la supprésion d'un élément" + generate_password: "Génére un mot de passe aléatoire (défaut 8 caractères)" + group: "Recherche les éléments appartenant au groupe spécifié" + help: "Affiche ce message d'aide" + id: "Spécifie un identifiant, à utiliser avec les options [--delete | --update]" + import: "Importe des éléments depuis un fichier yaml" + key: "Spécifie le nom d'une clé, à utiliser avec les options [--add | --delete | --update]" + no_sync: "Désactive la synchronisation avec le serveur" + setup: "Création d'un nouveau fichier de configuration" + setup_wallet: "Création d'un nouveau fichier de configuration pour un portefeuille" show: "Recherche et affiche les éléments" show_all: "Affiche tous les éléments" - update: "Met à jour un élément" remove: "Supprime un élément" - group: "Recherche les éléments appartenant au groupe spécifié" - add: "Ajoute un élément" - config: "Spécifie le fichier de configuration à utiliser" - setup: "Création d'un nouveau fichier de configuration" - protocol: "Sélectionne les éléments ayant le protocole spécifié" - export: "Exporte tous les éléments dans un fichier" - type: "Format des données du fichier d'export [csv|yaml]" - import: "Importe des éléments depuis un fichier yaml ou csv" - force: "Force une action, l'action ne demandera pas de confirmation" - no_sync: "Désactive la synchronisation avec le serveur" - format: "Change le format d'affichage des éléments par un alternatif" - generate_password: "Génére un mot de passe aléatoire (défaut 8 caractères)" - help: "Affiche ce message d'aide" + update: "Met à jour un élément" + usage: "Utilisation" + wallet: "Spécifie le portefeuille à utiliser" form: select: "Sélectionner l'élément: " From ea4c657036667be3262c0a963fd7908807e701fb Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sat, 14 May 2016 13:19:50 +0200 Subject: [PATCH 236/531] translation en option --- i18n/cli/en.yml | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/i18n/cli/en.yml b/i18n/cli/en.yml index bd84171..52d00cf 100644 --- a/i18n/cli/en.yml +++ b/i18n/cli/en.yml @@ -38,24 +38,28 @@ en: select: 'Your choice is not a valid element!' option: - usage: "Usage" + add: "Add an item or key" + config: "Specify the configuration file to use" + export: "Export a wallet in an yaml file" + file: "Specify a file, to use with the options [--import | --export | --add]" + force: "No ask to confirm when you delete an item" + generate_password: "Generate a random password (default 8 characters)" + group: "Search the items with specified group" + help: "Affiche ce message d'aide" + id: "Specify an id, to use with the options [--delete | --update]" + import: "Import item since a yaml file" + key: "Specify the key name, to use with the options [--add | --delete | --update]" + no_sync: "Disable synchronization with the server" + setup: "Create a new configuration file" + setup_wallet: "Create a new configuration file for a wallet" show: "Search and show the items" show_all: "Show all items" - update: "Update an item" remove: "Delete an item" - group: "Search the items with specified group" - add: "Add an item" - config: "Specify the configuration file to use" - setup: "Create a new configuration file" - protocol: "Select the items with the specified protocol" - export: "Export all items in a file" - type: "Data's type export file [csv|yaml]" - import: "Import item since a yaml or csv file" - force: "Force an action" - no_sync: "Disable synchronization with the server" - format: "Change the display items format by an alternative format" - generate_password: "Generate a random password (default 8 characters)" - help: "Show this help message" + update: "Update an item" + usage: "Usage" + wallet: "Specify a wallet to use" + + help: "Show this help message" form: select: "Select the item: " From 122f2e3393dac3e5ab4a7e20bcfb9507f057014c Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sat, 14 May 2016 17:01:44 +0200 Subject: [PATCH 237/531] new name for translation in cli --- lib/mpw/ui/cli.rb | 82 ++++++++++++++++++++++++----------------------- 1 file changed, 42 insertions(+), 40 deletions(-) diff --git a/lib/mpw/ui/cli.rb b/lib/mpw/ui/cli.rb index 6e301f4..9167c4d 100644 --- a/lib/mpw/ui/cli.rb +++ b/lib/mpw/ui/cli.rb @@ -23,11 +23,11 @@ class Cli # Create a new config file # @args: lang -> the software language def setup(lang) - puts I18n.t('form.setup.title') + puts I18n.t('form.setup_config.title') puts '--------------------' - language = ask(I18n.t('form.setup.lang', lang: lang)).to_s - key = ask(I18n.t('form.setup.gpg_key')).to_s - wallet_dir = ask(I18n.t('form.setup.wallet_dir')).to_s + language = ask(I18n.t('form.setup_config.lang', lang: lang)).to_s + key = ask(I18n.t('form.setup_config.gpg_key')).to_s + wallet_dir = ask(I18n.t('form.setup_config.wallet_dir', home: "#{@config.config_dir}")).to_s if language.nil? or language.empty? language = lang @@ -35,7 +35,7 @@ class Cli I18n.locale = language.to_sym if @config.setup(key, lang, wallet_dir) - puts "#{I18n.t('form.setup.valid')}".green + puts "#{I18n.t('form.setup_config.valid')}".green else puts "#{I18n.t('display.error')} #8: #{@config.error_msg}".red exit 2 @@ -89,17 +89,19 @@ class Cli config = {} config['sync'] = {} - puts I18n.t('form.setup.title') + puts I18n.t('form.setup_wallet.title') puts '--------------------' - config['sync']['type'] = ask(I18n.t('form.setup.sync_type')).to_s - config['sync']['host'] = ask(I18n.t('form.setup.sync_host')).to_s - config['sync']['port'] = ask(I18n.t('form.setup.sync_port')).to_s - config['sync']['user'] = ask(I18n.t('form.setup.sync_user')).to_s - config['sync']['password'] = ask(I18n.t('form.setup.sync_pwd')).to_s - config['sync']['path'] = ask(I18n.t('form.setup.sync_path')).to_s + config['sync']['type'] = ask(I18n.t('form.setup_wallet.sync_type')).to_s + config['sync']['host'] = ask(I18n.t('form.setup_wallet.sync_host')).to_s + config['sync']['port'] = ask(I18n.t('form.setup_wallet.sync_port')).to_s + config['sync']['user'] = ask(I18n.t('form.setup_wallet.sync_user')).to_s + config['sync']['password'] = ask(I18n.t('form.setup_wallet.sync_pwd')).to_s + config['sync']['path'] = ask(I18n.t('form.setup_wallet.sync_path')).to_s @mpw.set_config(config) @mpw.write_data + + puts "#{I18n.t('form.setup_wallet.valid')}".green rescue Exception => e puts "#{I18n.t('display.error')} #10: #{e}".red exit 2 @@ -215,7 +217,7 @@ class Cli @mpw.write_data @mpw.sync - puts "#{I18n.t('key.add.valid')}".green + puts "#{I18n.t('form.add_key.valid')}".green rescue Exception => e puts "#{I18n.t('display.error')} #13: #{e}".red end @@ -227,7 +229,7 @@ class Cli @mpw.write_data @mpw.sync - puts "#{I18n.t('key.delete.valid')}".green + puts "#{I18n.t('form.delete_key.valid')}".green rescue Exception => e puts "#{I18n.t('display.error')} #15: #{e}".red end @@ -236,16 +238,16 @@ class Cli def add options = {} - puts I18n.t('form.add.title') + puts I18n.t('form.add_item.title') puts '--------------------' - options[:name] = ask(I18n.t('form.add.name')).to_s - options[:group] = ask(I18n.t('form.add.group')).to_s - options[:host] = ask(I18n.t('form.add.server')).to_s - options[:protocol] = ask(I18n.t('form.add.protocol')).to_s - options[:user] = ask(I18n.t('form.add.login')).to_s - password = ask(I18n.t('form.add.password')).to_s - options[:port] = ask(I18n.t('form.add.port')).to_s - options[:comment] = ask(I18n.t('form.add.comment')).to_s + options[:name] = ask(I18n.t('form.add_item.name')).to_s + options[:group] = ask(I18n.t('form.add_item.group')).to_s + options[:host] = ask(I18n.t('form.add_item.server')).to_s + options[:protocol] = ask(I18n.t('form.add_item.protocol')).to_s + options[:user] = ask(I18n.t('form.add_item.login')).to_s + password = ask(I18n.t('form.add_item.password')).to_s + options[:port] = ask(I18n.t('form.add_item.port')).to_s + options[:comment] = ask(I18n.t('form.add_item.comment')).to_s item = Item.new(options) @@ -254,7 +256,7 @@ class Cli @mpw.write_data @mpw.sync - puts "#{I18n.t('form.add.valid')}".green + puts "#{I18n.t('form.add_item.valid')}".green end # Update an item @@ -265,16 +267,16 @@ class Cli if not item.nil? options = {} - puts I18n.t('form.update.title') + puts I18n.t('form.update_item.title') puts '--------------------' - options[:name] = ask(I18n.t('form.update.name' , name: item.name)).to_s - options[:group] = ask(I18n.t('form.update.group' , group: item.group)).to_s - options[:host] = ask(I18n.t('form.update.server' , server: item.host)).to_s - options[:protocol] = ask(I18n.t('form.update.protocol', protocol: item.protocol)).to_s - options[:user] = ask(I18n.t('form.update.login' , login: item.user)).to_s - password = ask(I18n.t('form.update.password')).to_s - options[:port] = ask(I18n.t('form.update.port' , port: item.port)).to_s - options[:comment] = ask(I18n.t('form.update.comment' , comment: item.comment)).to_s + options[:name] = ask(I18n.t('form.update_item.name' , name: item.name)).to_s + options[:group] = ask(I18n.t('form.update_item.group' , group: item.group)).to_s + options[:host] = ask(I18n.t('form.update_item.server' , server: item.host)).to_s + options[:protocol] = ask(I18n.t('form.update_item.protocol', protocol: item.protocol)).to_s + options[:user] = ask(I18n.t('form.update_item.login' , login: item.user)).to_s + password = ask(I18n.t('form.update_item.password')).to_s + options[:port] = ask(I18n.t('form.update_item.port' , port: item.port)).to_s + options[:comment] = ask(I18n.t('form.update_item.comment' , comment: item.comment)).to_s options.delete_if { |k,v| v.empty? } @@ -283,7 +285,7 @@ class Cli @mpw.write_data @mpw.sync - puts "#{I18n.t('form.update.valid')}".green + puts "#{I18n.t('form.update_item.valid')}".green else puts I18n.t('display.nothing') end @@ -298,14 +300,14 @@ class Cli item = @mpw.search_by_id(id) if item.nil? - puts I18n.t('display.nothing') + puts I18n.t('form.delete_item.not_valid', id: id) return end if not force display_item(item) - confirm = ask("#{I18n.t('form.delete.ask', id: id)} (y/N) ").to_s + confirm = ask("#{I18n.t('form.delete_item.ask', id: id)} (y/N) ").to_s if not confirm =~ /^(y|yes|YES|Yes|Y)$/ return end @@ -315,9 +317,9 @@ class Cli @mpw.write_data @mpw.sync - puts "#{I18n.t('form.delete.valid', id: id)}".green - rescue - puts "#{I18n.t('display.error')} #16: #{@mpw.error_msg}".red + puts "#{I18n.t('form.delete_item.valid', id: id)}".green + rescue Exception => e + puts "#{I18n.t('display.error')} #16: #{e}".red end # Export the items in a CSV file @@ -327,7 +329,7 @@ class Cli puts "#{I18n.t('export.valid', file)}".green rescue Exception => e - puts "#{I18n.t('display.error')} #17: #{e}".red + puts "#{I18n.t('display.error')} #17: #{e}".red end # Import items from a YAML file From 83d96bf26cfe70f67e91182740c3e503a0c6ed49 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sat, 14 May 2016 17:02:37 +0200 Subject: [PATCH 238/531] fix translate with new name --- i18n/cli/fr.yml | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/i18n/cli/fr.yml b/i18n/cli/fr.yml index 38a39d4..5564be4 100644 --- a/i18n/cli/fr.yml +++ b/i18n/cli/fr.yml @@ -61,7 +61,9 @@ fr: form: select: "Sélectionner l'élément: " - add: + add_key: + valid: "La clé a bien été ajoutée!" + add_item: title: "Ajout d'un nouvel élément" name: "Entrez le nom: " group: "Entrez le groupe (optionnel): " @@ -72,7 +74,9 @@ fr: port: "Entrez le port de connexion (optionnel): " comment: "Entrez un commentaire (optionnel): " valid: "L'élément a bien été ajouté!" - delete: + delete_key: + valid: "La clé a bien été supprimée!" + delete_item: ask: "Êtes vous sûre de vouloir supprimer l'élément %{id} ?" valid: "L'élément %{id} a bien été supprimé!" not_valid: "L'élément %{id} n'a pu être supprimé, car il n'existe pas!" @@ -80,22 +84,23 @@ fr: ask: "Êtes vous sûre de vouloir importer le fichier %{file} ?" valid: "L'import est un succès!" not_valid: "Aucune donnée à importer!" - setup: + setup_config: title: "Création d'un nouveau fichier de configuration" lang: "Choisissez votre langue (en, fr, ...) [défaut=%{lang}]: " gpg_key: "Entrez la clé GPG: " - share_gpg_keys: "Entrez les clés GPG avec qui vous voulez partager les mots de passe: " - gpg_file: "Entrez le chemin du fichier qui sera chiffré [défaut=%{home}/db/default.gpg]: " - timeout: "Entrez le temps (en seconde) du mot de passe GPG [défaut=60]: " - sync_type: "Type de synchronisation (mpw, ssh, ftp, or nil): " - sync_host: "Serveur de synchronisation: " - sync_port: "Port du serveur de synchronisation: " - sync_user: "Utilisateur pour la synchronisation: " - sync_pwd: "Mot de passe pour la synchronisation: " - sync_path: "Chemin du fichier pour la synchronisation: " + wallet_dir: "Entrez le chemin du répertoire qui contiendra les porte-feuilles de mot de passe [défaut=%{home}/wallets]: " valid: "Le fichier de configuration a bien été créé!" + setup_wallet: + title: "Configuration du porte-feuille" + sync_type: "Type de synchronisation (ssh, ftp): " + sync_host: "Serveur: " + sync_port: "Port: " + sync_user: "Utilisateur: " + sync_pwd: "Mot de passe: " + sync_path: "Chemin du fichier: " + valid: "Le fichier de configuration du porte-feuille a bien été créé!" setup_gpg_key: - title: "Configuration d'une clé GPG" + title: "Configuration d'une nouvelle clé GPG" ask: "Voulez vous créer votre clé GPG ? (O/n)" no_create: "Veuillez créer manuellement votre clé GPG ou relancer le logiciel." name: "Votre nom et prénom: " @@ -106,7 +111,7 @@ fr: expire: "Expiration de la clé GPG [défaut=0 (illimité)]: " wait: "Veuillez patienter durant la génération de votre clé GPG, ce processus peut prendre quelques minutes." valid: "Votre clé GPG a bien été créée ;-)" - update: + update_item: title: "Mis à jour d'un élément" name: "Entrez le nom [%{name}]: " group: "Entrez le groupe [%{group}]: " From 7e630954479e4b85e8b3b3e9d2e7ca84eb16182b Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sat, 14 May 2016 17:03:36 +0200 Subject: [PATCH 239/531] remove mpw server code --- i18n/server/en.yml | 26 ---- i18n/server/fr.yml | 26 ---- lib/mpw/server.rb | 343 --------------------------------------------- 3 files changed, 395 deletions(-) delete mode 100644 i18n/server/en.yml delete mode 100644 i18n/server/fr.yml delete mode 100644 lib/mpw/server.rb diff --git a/i18n/server/en.yml b/i18n/server/en.yml deleted file mode 100644 index df88dfe..0000000 --- a/i18n/server/en.yml +++ /dev/null @@ -1,26 +0,0 @@ ---- -en: - option: - usage: "Usage" - config: "Specifie the configuration file" - checkconfig: "Check the configuration" - setup: "Setup a new configuration file" - help: "Show this message help" - checkconfig: - fail: "Checkconfig failed:!" - empty: "ERROR: an importe option is missing!" - datadir: "ERROR: le data directory doesn't exist!" - form: - setup: - title: "Serveur configuration" - host: "IP listen: " - port: "Port listen: " - data_dir: "Data directory: " - timeout: "Timeout to second: " - log_file: "Log file path: " - not_valid: "ERROR: Impossible to write the configuration file!" - formats: - default: ! '%Y-%m-%d' - long: ! '%B %d, %Y' - short: ! '%b %d' - custom: ! '%A, %M %B, %Y @ %l:%M%P' diff --git a/i18n/server/fr.yml b/i18n/server/fr.yml deleted file mode 100644 index 667757c..0000000 --- a/i18n/server/fr.yml +++ /dev/null @@ -1,26 +0,0 @@ ---- -fr: - option: - usage: "Utilisation" - config: "Spécifie le fichier de configuration" - checkconfig: "Vérifie le fichier de configuration" - setup: "Permet de générer un nouveau fichier de configuration" - help: "Affiche ce message d'aide" - checkconfig: - fail: "Le fichier de configuration est invalide!" - empty: "ERREUR: Une option importante est manquante!" - datadir: "ERREUR: Le répertoire des données n'existe pas!" - form: - setup: - title: "Configuration du serveur" - host: "IP d'écoute: " - port: "Port d'écoute: " - data_dir: "Répertoire des données: " - log_file: "Chemin du ficier de log: " - timeout: "Timeout en seconde: " - not_valid: "ERREUR: Impossible d'écire le fichier de configuration!" - formats: - default: ! '%Y-%m-%d' - long: ! '%B %d, %Y' - short: ! '%b %d' - custom: ! '%A, %M %B, %Y @ %l:%M%P' diff --git a/lib/mpw/server.rb b/lib/mpw/server.rb deleted file mode 100644 index 415bb26..0000000 --- a/lib/mpw/server.rb +++ /dev/null @@ -1,343 +0,0 @@ -#!/usr/bin/ruby - -module MPW - - require 'socket' - require 'json' - require 'highline/import' - require 'digest' - require 'logger' - - - class Server - - attr_accessor :error_msg - - # Constructor - def initialize - YAML::ENGINE.yamler='syck' - end - - # Start the server - def start - server = TCPServer.open(@host, @port) - @log.info("The server is started on #{@host}:#{@port}") - - loop do - Thread.start(server.accept) do |client| - @log.info("#{client.peeraddr[3]} is connected") - - while true do - msg = get_client_msg(client) - - next if not msg - - if msg['gpg_key'].nil? or msg['gpg_key'].empty? or msg['password'].nil? or msg['password'].empty? - @log.warning("#{client.peeraddr[3]} is disconnected because no password or no gpg_key") - close_connection(client) - next - end - - case msg['action'] - when 'get' - @log.debug("#{client.peeraddr[3]} GET gpg_key=#{msg['gpg_key']} suffix=#{msg['suffix']}") - client.puts get_file(msg) - when 'update' - @log.debug("#{client.peeraddr[3]} UPDATE gpg_key=#{msg['gpg_key']} suffix=#{msg['suffix']}") - client.puts update_file(msg) - when 'delete' - @log.debug("#{client.peeraddr[3]} DELETE gpg_key=#{msg['gpg_key']} suffix=#{msg['suffix']}") - client.puts delete_file(msg) - else - @log.warning("#{client.peeraddr[3]} is disconnected because unkwnow command") - send_msg = {action: 'unknown', - gpg_key: msg['gpg_key'], - error: 'server.error.client.unknown' - } - client.puts send_msg - close_connection(client) - end - end - end - end - - rescue Exception => e - puts "Impossible to start the server: #{e}" - @log.error("Impossible to start the server: #{e}") - exit 2 - end - - # Get a gpg file - # @args: msg -> message puts by the client - # @rtrn: json message - def get_file(msg) - gpg_key = msg['gpg_key'].sub('@', '_') - - if msg['suffix'].nil? or msg['suffix'].empty? - file_gpg = "#{@data_dir}/#{gpg_key}.yml" - else - file_gpg = "#{@data_dir}/#{gpg_key}-#{msg['suffix']}.yml" - end - - if File.exist?(file_gpg) - gpg_data = YAML::load_file(file_gpg) - salt = gpg_data['gpg']['salt'] - hash = gpg_data['gpg']['hash'] - data = gpg_data['gpg']['data'] - - if is_authorized?(msg['password'], salt, hash) - send_msg = {action: 'get', - gpg_key: msg['gpg_key'], - data: data, - error: nil - } - else - send_msg = {action: 'get', - gpg_key: msg['gpg_key'], - error: 'server.error.client.no_authorized' - } - end - else - send_msg = {action: 'get', - gpg_key: msg['gpg_key'], - data: '', - error: nil - } - end - - return send_msg.to_json - end - - # Update a file - # @args: msg -> message puts by the client - # @rtrn: json message - def update_file(msg) - gpg_key = msg['gpg_key'].sub('@', '_') - data = msg['data'] - - if data.nil? or data.empty? - send_msg = {action: 'update', - gpg_key: msg['gpg_key'], - error: 'server.error.client.no_data' - } - - return send_msg.to_json - end - - if msg['suffix'].nil? or msg['suffix'].empty? - file_gpg = "#{@data_dir}/#{gpg_key}.yml" - else - file_gpg = "#{@data_dir}/#{gpg_key}-#{msg['suffix']}.yml" - end - - if File.exist?(file_gpg) - gpg_data = YAML::load_file(file_gpg) - salt = gpg_data['gpg']['salt'] - hash = gpg_data['gpg']['hash'] - - else - salt = generate_salt - hash = Digest::SHA256.hexdigest(salt + msg['password']) - end - - if is_authorized?(msg['password'], salt, hash) - begin - config = {'gpg' => {'salt' => salt, - 'hash' => hash, - 'data' => data - } - } - - File.open(file_gpg, 'w+') do |file| - file << config.to_yaml - end - - send_msg = {action: 'update', - gpg_key: msg['gpg_key'], - error: nil - } - rescue Exception => e - send_msg = {action: 'update', - gpg_key: msg['gpg_key'], - error: 'server.error.client.unknown' - } - end - else - send_msg = {action: 'update', - gpg_key: msg['gpg_key'], - error: 'server.error.client.no_authorized' - } - end - - return send_msg.to_json - end - - # Remove a gpg file - # @args: msg -> message puts by the client - # @rtrn: json message - def delete_file(msg) - gpg_key = msg['gpg_key'].sub('@', '_') - - if msg['suffix'].nil? or msg['suffix'].empty? - file_gpg = "#{@data_dir}/#{gpg_key}.yml" - else - file_gpg = "#{@data_dir}/#{gpg_key}-#{msg['suffix']}.yml" - end - - if not File.exist?(file_gpg) - send_msg = {:action => 'delete', - :gpg_key => msg['gpg_key'], - :error => nil - } - - return send_msg.to_json - end - - gpg_data = YAML::load_file(file_gpg) - salt = gpg_data['gpg']['salt'] - hash = gpg_data['gpg']['hash'] - - if is_authorized?(msg['password'], salt, hash) - begin - File.unlink(file_gpg) - - send_msg = {action: 'delete', - gpg_key: msg['gpg_key'], - error: nil - } - rescue Exception => e - send_msg = {action: 'delete', - gpg_key: msg['gpg_key'], - error: 'server.error.client.unknown' - } - end - else - send_msg = {action: 'delete', - gpg_key: msg['gpg_key'], - error: 'server.error.client.no_authorized' - } - end - - return send_msg.to_json - end - - # Check is the hash equal the password with the salt - # @args: password -> the user password - # salt -> the salt - # hash -> the hash of the password with the salt - # @rtrn: true is is good, else false - def is_authorized?(password, salt, hash) - if hash == Digest::SHA256.hexdigest(salt + password) - return true - else - return false - end - end - - # Get message to client - # @args: client -> client connection - # @rtrn: array of the json string, or false if isn't json message - def get_client_msg(client) - msg = client.gets - return JSON.parse(msg) - rescue - closeConnection(client) - return false - end - - # Close the client connection - # @args: client -> client connection - def close_connection(client) - client.puts "Closing the connection. Bye!" - client.close - end - - # Check the config file - # @args: file_config -> the configuration file - # @rtrn: true if the config file is correct - def checkconfig(file_config) - config = YAML::load_file(file_config) - @host = config['config']['host'] - @port = config['config']['port'].to_i - @data_dir = config['config']['data_dir'] - @log_file = config['config']['log_file'] - @timeout = config['config']['timeout'].to_i - - if @host.empty? or @port <= 0 or @data_dir.empty? - puts I18n.t('checkconfig.fail') - puts I18n.t('checkconfig.empty') - return false - end - - if not Dir.exist?(@data_dir) - puts I18n.t('checkconfig.fail') - puts I18n.t('checkconfig.datadir') - return false - end - - if @log_file.nil? or @log_file.empty? - puts I18n.t('checkconfig.fail') - puts I18n.t('checkconfig.log_file_empty') - return false - else - begin - @log = Logger.new(@log_file) - rescue - puts I18n.t('checkconfig.fail') - puts I18n.t('checkconfig.log_file_create') - return false - end - end - - return true - rescue Exception => e - puts "#{I18n.t('checkconfig.fail')}\n#{e}" - return false - end - - # Create a new config file - # @args: file_config -> the configuration file - # @rtrn: true if le config file is create - def setup(file_config) - puts I18n.t('form.setup.title') - puts '--------------------' - host = ask(I18n.t('form.setup.host')).to_s - port = ask(I18n.t('form.setup.port')).to_s - data_dir = ask(I18n.t('form.setup.data_dir')).to_s - log_file = ask(I18n.t('form.setup.log_file')).to_s - timeout = ask(I18n.t('form.setup.timeout')).to_s - - config = {'config' => {'host' => host, - 'port' => port, - 'data_dir' => data_dir, - 'log_file' => log_file, - 'timeout' => timeout - } - } - - File.open(file_config, 'w') do |file| - file << config.to_yaml - end - - return true - rescue Exception => e - puts "#{I18n.t('form.setup.not_valid')}\n#{e}" - return false - end - - # Generate a random salt - # @args: length -> the length salt - # @rtrn: a random string - def generate_salt(length=4) - if length.to_i <= 0 or length.to_i > 16 - length = 4 - else - length = length.to_i - end - - return ([*('A'..'Z'),*('a'..'z'),*('0'..'9')]).sample(length).join - end - - end - -end From 25214873edecc63369353ddacc82b5d1a4b88be3 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sat, 14 May 2016 17:05:17 +0200 Subject: [PATCH 240/531] remove folder cli in folder i18n --- bin/mpw | 2 +- i18n/{cli => }/en.yml | 0 i18n/{cli => }/fr.yml | 0 3 files changed, 1 insertion(+), 1 deletion(-) rename i18n/{cli => }/en.yml (100%) rename i18n/{cli => }/fr.yml (100%) diff --git a/bin/mpw b/bin/mpw index 97b846d..63868ed 100755 --- a/bin/mpw +++ b/bin/mpw @@ -26,7 +26,7 @@ require "#{APP_ROOT}/../lib/mpw/config.rb" require "#{APP_ROOT}/../lib/mpw/ui/cli.rb" I18n::Backend::Simple.send(:include, I18n::Backend::Fallbacks) -I18n.load_path = Dir["#{APP_ROOT}/../i18n/cli/*.yml"] +I18n.load_path = Dir["#{APP_ROOT}/../i18n/*.yml"] I18n.default_locale = :en I18n.locale = lang.to_sym diff --git a/i18n/cli/en.yml b/i18n/en.yml similarity index 100% rename from i18n/cli/en.yml rename to i18n/en.yml diff --git a/i18n/cli/fr.yml b/i18n/fr.yml similarity index 100% rename from i18n/cli/fr.yml rename to i18n/fr.yml From 68a0fddde8c8475891c723400a028f6eb8800172 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sat, 14 May 2016 17:13:47 +0200 Subject: [PATCH 241/531] fix en translate with new name --- i18n/en.yml | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/i18n/en.yml b/i18n/en.yml index 52d00cf..6576691 100644 --- a/i18n/en.yml +++ b/i18n/en.yml @@ -45,7 +45,7 @@ en: force: "No ask to confirm when you delete an item" generate_password: "Generate a random password (default 8 characters)" group: "Search the items with specified group" - help: "Affiche ce message d'aide" + help: "Show this help message" id: "Specify an id, to use with the options [--delete | --update]" import: "Import item since a yaml file" key: "Specify the key name, to use with the options [--add | --delete | --update]" @@ -59,11 +59,11 @@ en: usage: "Usage" wallet: "Specify a wallet to use" - help: "Show this help message" - form: select: "Select the item: " - add: + add_key: + valid: "Key has been added!" + add_item: title: "Add a new item" name: "Enter the name: " group: "Enter the group (optional): " @@ -74,7 +74,9 @@ en: port: "Enter the connection port (optional): " comment: "Enter a comment (optional): " valid: "Item has been added!" - delete: + delete_key: + valid: "Key has been deleted!" + delete_item: ask: "Are you sure you want to remove the item %{id} ?" valid: "The item %{id} has been removed!" not_valid: "The item %{id} hasn't been removed, because it doesn't exist!" @@ -82,20 +84,21 @@ en: ask: "Are you sure you want to import this file %{file} ?" valid: "The import is succesfull!" not_valid: "No data to import!" - setup: + setup_config: title: "Setup a new config file" lang: "Choose your language (en, fr, ...): " gpg_key: "Enter the GPG key: " - share_gpg_keys: "Enter the GPG keys with who you want to share the passwords: " - gpg_file: "Enter the path to encrypt file [default=%{home}/db/default.gpg]: " - timeout: "Enter the timeout (in seconde) to GPG password [default=60]: " + wallet_dir: "Enter the wallets's folder path [défaut=%{home}/wallets]: " + valid: "The config file has been created!" + setup_wallet: + title: "Wallet setup" sync_type: "Synchronization type (mpw, ssh, ftp, or nil): " sync_host: "Synchronization server: " sync_port: "Port of the synchronization server: " sync_user: "Username for the synchronization: " sync_pwd: "Password for the synchronization: " sync_path: "File path for the synchronization : " - valid: "The config file has been created!" + valid: "The wallet config file has been created!" setup_gpg_key: title: "Setup a GPG key" ask: "Do you want create your GPG key ? (Y/n)" @@ -108,7 +111,7 @@ en: expire: "Expire time of the GPG key [default=0 (unlimited)]: " wait: "Please waiting during the GPG key generate, this process can take few minutes." valid: "Your GPG key has been created ;-)" - update: + updatei_item: title: "Update an item" name: "Enter the name [%{name}]: " group: "Enter the group [%{group}]: " From a4fe06370322188b3e0abaad58ff8542d884cbf0 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sun, 15 May 2016 18:30:33 +0200 Subject: [PATCH 242/531] remove error_msg in config class --- lib/mpw/config.rb | 34 +++++++++------------------------- lib/mpw/ui/cli.rb | 34 ++++++++++++++-------------------- 2 files changed, 23 insertions(+), 45 deletions(-) diff --git a/lib/mpw/config.rb b/lib/mpw/config.rb index dd797d2..11f1e5c 100644 --- a/lib/mpw/config.rb +++ b/lib/mpw/config.rb @@ -19,7 +19,6 @@ class Config # Constructor # @args: config_file -> the specify config file def initialize(config_file=nil) - @error_msg = nil @config_file = config_file if /darwin/ =~ RUBY_PLATFORM @@ -43,8 +42,7 @@ class Config def setup(key, lang, wallet_dir) if not key =~ /[a-zA-Z0-9.-_]+\@[a-zA-Z0-9]+\.[a-zA-Z]+/ - @error_msg = I18n.t('error.config.key_bad_format') - return false + raise I18n.t('error.config.key_bad_format') end if wallet_dir.empty? @@ -62,10 +60,8 @@ class Config file << config.to_yaml end - return true rescue Exception => e - @error_msg = "#{I18n.t('error.config.write')}\n#{e}" - return false + raise "#{I18n.t('error.config.write')}\n#{e}" end # Setup a new gpg key @@ -76,11 +72,9 @@ class Config # @rtrn: true if the GPG key is create, else false def setup_gpg_key(password, name, length = 4096, expire = 0) if name.nil? or name.empty? - @error_msg = "#{I18n.t('error.config.genkey_gpg.name')}" - return false + raise "#{I18n.t('error.config.genkey_gpg.name')}" elsif password.nil? or password.empty? - @error_msg = "#{I18n.t('error.config.genkey_gpg.password')}" - return false + raise "#{I18n.t('error.config.genkey_gpg.password')}" end param = '' @@ -98,31 +92,24 @@ class Config ctx = GPGME::Ctx.new ctx.genkey(param, nil, nil) - - return true rescue Exception => e - @error_msg = "#{I18n.t('error.config.genkey_gpg.exception')}\n#{e}" - return false + raise "#{I18n.t('error.config.genkey_gpg.exception')}\n#{e}" end # Check the config file # @rtrn: true if the config file is correct def checkconfig - config = YAML::load_file(@config_file) + config = YAML::load_file(@config_file) @key = config['config']['key'] @lang = config['config']['lang'] @wallet_dir = config['config']['wallet_dir'] if @key.empty? or @wallet_dir.empty? - @error_msg = I18n.t('error.config.check') - return false + raise I18n.t('error.config.check') end I18n.locale = @lang.to_sym - - return true rescue Exception => e - @error_msg = "#{I18n.t('error.config.check')}\n#{e}" - return false + raise "#{I18n.t('error.config.check')}\n#{e}" end # Check if private key exist @@ -148,11 +135,8 @@ class Config File.open(@config_file, 'w') do |file| file << config.to_yaml end - - return true rescue Exception => e - @error_msg = "#{I18n.t('error.config.write')}\n#{e}" - return false + raise "#{I18n.t('error.config.write')}\n#{e}" end end diff --git a/lib/mpw/ui/cli.rb b/lib/mpw/ui/cli.rb index 9167c4d..957005b 100644 --- a/lib/mpw/ui/cli.rb +++ b/lib/mpw/ui/cli.rb @@ -34,17 +34,13 @@ class Cli end I18n.locale = language.to_sym - if @config.setup(key, lang, wallet_dir) - puts "#{I18n.t('form.setup_config.valid')}".green - else - puts "#{I18n.t('display.error')} #8: #{@config.error_msg}".red - exit 2 - end + @config.setup(key, lang, wallet_dir) + @config.checkconfig - if not @config.checkconfig - puts "#{I18n.t('display.error')} #9: #{@config.error_msg}".red - exit 2 - end + puts "#{I18n.t('form.setup_config.valid')}".green + rescue Exception => e + puts "#{I18n.t('display.error')} #8: #{e}".red + exit 2 end # Setup a new GPG key @@ -54,8 +50,7 @@ class Cli ask = ask(I18n.t('form.setup_gpg_key.ask')).to_s if not ['Y', 'y', 'O', 'o'].include?(ask) - puts I18n.t('form.setup_gpg_key.no_create') - exit 2 + raise I18n.t('form.setup_gpg_key.no_create') end name = ask(I18n.t('form.setup_gpg_key.name')).to_s @@ -63,8 +58,7 @@ class Cli confirm = ask(I18n.t('form.setup_gpg_key.confirm_password')) {|q| q.echo = false} if password != confirm - puts I18n.t('form.setup_gpg_key.error_password') - exit 2 + raise I18n.t('form.setup_gpg_key.error_password') end length = ask(I18n.t('form.setup_gpg_key.length')).to_s @@ -76,12 +70,12 @@ class Cli puts I18n.t('form.setup_gpg_key.wait') - if @config.setup_gpg_key(password, name, length, expire) - puts "#{I18n.t('form.setup_gpg_key.valid')}".green - else - puts "#{I18n.t('display.error')} #10: #{@config.error_msg}".red - exit 2 - end + @config.setup_gpg_key(password, name, length, expire) + + puts "#{I18n.t('form.setup_gpg_key.valid')}".green + rescue Exception => e + puts "#{I18n.t('display.error')} #8: #{e}".red + exit 2 end # Setup wallet config for sync From 4060e2b105e446dfc09f49f801d13dc39a8581ee Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sun, 15 May 2016 18:31:56 +0200 Subject: [PATCH 243/531] remove set_last_sync function in config because it is obsolete --- lib/mpw/config.rb | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/lib/mpw/config.rb b/lib/mpw/config.rb index 11f1e5c..951f400 100644 --- a/lib/mpw/config.rb +++ b/lib/mpw/config.rb @@ -122,22 +122,5 @@ class Config return false end - - # Set the last update when there is a sync - # @rtrn: true is the file has been updated - def set_last_sync - config = {'config' => {'key' => @key, - 'lang' => @lang, - 'wallet_dir' => @wallet_dir, - } - } - - File.open(@config_file, 'w') do |file| - file << config.to_yaml - end - rescue Exception => e - raise "#{I18n.t('error.config.write')}\n#{e}" - end - end end From 84ff0e8ae26679fb9559fbb590446356e07957c7 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sun, 15 May 2016 23:22:55 +0200 Subject: [PATCH 244/531] fix comments --- lib/mpw/sync/ssh.rb | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/lib/mpw/sync/ssh.rb b/lib/mpw/sync/ssh.rb index 89a7fd5..45dae3a 100644 --- a/lib/mpw/sync/ssh.rb +++ b/lib/mpw/sync/ssh.rb @@ -20,7 +20,6 @@ class SyncSSH end # Connect to server - # @rtrn: false if the connection fail def connect Net::SSH.start(@host, @user, password: @password, port: @port) do break @@ -30,8 +29,7 @@ class SyncSSH end # Get data on server - # @args: gpg_password -> the gpg password - # @rtrn: nil if nothing data or error + # @args: file_tmp -> the path where download the file def get(file_tmp) Net::SFTP.start(@host, @user, password: @password, port: @port) do |sftp| sftp.lstat(@path) do |response| @@ -44,7 +42,6 @@ class SyncSSH # Update the remote data # @args: file_gpg -> the data to send on server - # @rtrn: false if there is a problem def update(file_gpg) Net::SFTP.start(@host, @user, password: @password, port: @port) do |sftp| sftp.upload!(file_gpg, @path) @@ -52,6 +49,5 @@ class SyncSSH rescue Exception => e raise "#{I18n.t('error.sync.upload')}\n#{e}" end - end end From 47430ce611eb83fe0ba157d85ccdab73ea07e29d Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sun, 15 May 2016 23:23:26 +0200 Subject: [PATCH 245/531] fix ftp sync for mpw 3.0 --- lib/mpw/sync/ftp.rb | 109 +++++++++++++++++--------------------------- 1 file changed, 41 insertions(+), 68 deletions(-) diff --git a/lib/mpw/sync/ftp.rb b/lib/mpw/sync/ftp.rb index 0d324e7..71d1624 100644 --- a/lib/mpw/sync/ftp.rb +++ b/lib/mpw/sync/ftp.rb @@ -2,80 +2,53 @@ # author: nishiki # mail: nishiki@yaegashi.fr -require 'rubygems' require 'i18n' require 'net/ftp' module MPW - class FTP - - attr_accessor :error_msg - attr_accessor :enable - - # Constructor - # @args: host -> the server host - # port -> ther connection port - # gpg_key -> the gpg key - # password -> the remote password - # suffix -> the suffix file - def initialize(host, user, password, path, port=nil) - @error_msg = nil - @enable = false +class FTP - @host = host - @user = user - @password = password - @path = path - @port = port.instance_of?(Integer) ? 21 : port - end - - # Connect to server - # @rtrn: false if the connection fail - def connect - Net::FTP.open(@host) do |ftp| - ftp.login(@user, @password) - @enable = true - end - rescue Exception => e - @error_msg = "#{I18n.t('error.sync.connection')}\n#{e}" - @enable = false - else - return @enable - end - - # Get data on server - # @args: gpg_password -> the gpg password - # @rtrn: nil if nothing data or error - def get(file_tmp) - return false if not @enable - - Net::FTP.open(@host) do |ftp| - ftp.login(@user, @password) - ftp.gettextfile(@path, file_tmp) - end - - return true - rescue Exception => e - @error_msg = "#{I18n.t('error.sync.download')}\n#{e}" - return false - end - - # Update the remote data - # @args: data -> the data to send on server - # @rtrn: false if there is a problem - def update(file_gpg) - return true if not @enable - - Net::FTP.open(@host) do |ftp| - ftp.login(@user, @password) - ftp.puttextfile(file_gpg, @path) - end + # Constructor + # @args: config -> the config + def initialize(config) + @host = config['host'] + @user = config['user'] + @password = config['password'] + @path = config['path'] + @port = config['port'].instance_of?(Integer) ? 22 : config['port'] + end - return true - rescue Exception => e - @error_msg = "#{I18n.t('error.sync.upload')}\n#{e}" - return false - end + # Connect to server + def connect + Net::FTP.open(@host) do |ftp| + ftp.login(@user, @password) + break + end + rescue Exception => e + raise "#{I18n.t('error.sync.connection')}\n#{e}" + end + + # Get data on server + # @args: file_tmp -> the path where download the file + def get(file_tmp) + Net::FTP.open(@host) do |ftp| + ftp.login(@user, @password) + ftp.gettextfile(@path, file_tmp) + end + rescue Exception => e + raise "#{I18n.t('error.sync.download')}\n#{e}" + end + + # Update the remote data + # @args: file_gpg -> the data to send on server + def update(file_gpg) + Net::FTP.open(@host) do |ftp| + ftp.login(@user, @password) + ftp.puttextfile(file_gpg, @path) + end + rescue Exception => e + raise "#{I18n.t('error.sync.upload')}\n#{e}" end end +end From 7ea4f19698817d9566e7eb1ba0cb71674ffbf896 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sun, 15 May 2016 23:37:57 +0200 Subject: [PATCH 246/531] remove useless function check_config --- lib/mpw/mpw.rb | 8 -------- 1 file changed, 8 deletions(-) diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index 767522a..64e7972 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -179,13 +179,6 @@ class MPW @keys.delete(key) end - # TODO - def check_config - if false - raise 'ERROR' - end - end - # Set config # args: config -> a hash with config options def set_config(config) @@ -277,7 +270,6 @@ class MPW # Import to yaml # @args: file -> path to file import - # TODO raise def import(file) YAML::load_file(file).each_value do |row| item = Item.new(name: row['name'], From 4108f397d872da7cbc783813fb236d89633cf62b Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sun, 15 May 2016 23:52:12 +0200 Subject: [PATCH 247/531] remove translate client ssh --- i18n/en.yml | 11 ----------- i18n/fr.yml | 11 ----------- 2 files changed, 22 deletions(-) diff --git a/i18n/en.yml b/i18n/en.yml index 6576691..c6298aa 100644 --- a/i18n/en.yml +++ b/i18n/en.yml @@ -139,17 +139,6 @@ en: server: "Server" warning: "Warning" - ssh: - option: - usage: "Usage" - login: "Change the login" - server: "Change the host or the ip" - port: "Change the port" - help: "Show this help message" - display: - connect: "Connection to:" - nothing: "Nothing result!" - formats: default: ! '%Y-%m-%d' long: ! '%B %d, %Y' diff --git a/i18n/fr.yml b/i18n/fr.yml index 5564be4..11dde2b 100644 --- a/i18n/fr.yml +++ b/i18n/fr.yml @@ -139,17 +139,6 @@ fr: server: "Serveur" warning: "Warning" - ssh: - option: - usage: "Utilisation" - login: "Change l'identifiant de connexion" - server: "Change le nom de domaine ou l'ip du serveur" - port: "Change le port de connexion" - help: "Affiche ce message d'aide" - display: - connect: "Connexion à:" - nothing: "Aucun résultat!" - formats: default: ! '%Y-%m-%d' long: ! '%B %d, %Y' From f423774c2ca7ea9abc6235f32c127dc990b8938c Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sun, 15 May 2016 23:55:01 +0200 Subject: [PATCH 248/531] fix translate for class mpw --- i18n/en.yml | 20 +++++++++----------- i18n/fr.yml | 18 ++++++++---------- lib/mpw/mpw.rb | 8 ++++---- 3 files changed, 21 insertions(+), 25 deletions(-) diff --git a/i18n/en.yml b/i18n/en.yml index c6298aa..a81fced 100644 --- a/i18n/en.yml +++ b/i18n/en.yml @@ -1,8 +1,6 @@ --- en: error: - client: - no_authorized: "You aren't authorized." config: write: "Can't write the config file!" check: "Checkconfig failed!" @@ -14,25 +12,25 @@ en: password: "You must define a password for your GPG key!" delete: id_no_exist: "Can't delete the item %{id}, it doesn't exist!" - export: - unknown_type: "The data type %{type} is unknown!" - write: "Can't export, unable to write in %{file}!" + export: "Can't export, unable to write in %{file}!" gpg_file: decrypt: "Can't decrypt file!" encrypt: "Can't encrypt the GPG file!" - import: - bad_format: "Can't import, the file is badly formated!" - read: "Can't import, unable to read %{file}!" + mpw_file: + read_data: "Can't to read the MPW file!" + write_data: "Can't to write the MPW file!" + import: "Can't import, unable to read %{file}!" update: name_empty: "You must define a name!" sync: + general: "An error is appeared durint the sync" connection: "Connection fail!" communication: "A communication problem with the server is appeared!" download: "Can't download the file!" not_authorized: "You haven't the access to remote file!" upload: "Can't upload the file on the server!" - unknown: "An unknown error is occured!" - unknown_type: "The sync type is unknown" + unknown: "An unknown error is occured!" + unknown_type: "The sync type is unknown" warning: select: 'Your choice is not a valid element!' @@ -111,7 +109,7 @@ en: expire: "Expire time of the GPG key [default=0 (unlimited)]: " wait: "Please waiting during the GPG key generate, this process can take few minutes." valid: "Your GPG key has been created ;-)" - updatei_item: + update_item: title: "Update an item" name: "Enter the name [%{name}]: " group: "Enter the group [%{group}]: " diff --git a/i18n/fr.yml b/i18n/fr.yml index 11dde2b..a6172ea 100644 --- a/i18n/fr.yml +++ b/i18n/fr.yml @@ -1,8 +1,6 @@ --- fr: error: - client: - no_authorized: "Vous n'êtes pas autorisé!" config: write: "Impossible d'écrire le fichier de configuration!" check: "Le fichier de configuration est invalide!" @@ -14,25 +12,25 @@ fr: password: "Vous devez définir un mot de passe pour votre clé GPG!" delete: id_no_exist: "Impossible de supprimer l'élément %{id}, car il n'existe pas!" - export: - unknown_type: "Le type de donnée %{type} est inconnu!" - write: "Impossible d'exporter les données dans le fichier %{file}!" + export: "Impossible d'exporter les données dans le fichier %{file}!" gpg_file: decrypt: "Impossible de déchiffrer le fichier GPG!" encrypt: "Impossible de chiffrer le fichier GPG!" - import: - bad_format: "Impossible d'importer le fichier car son format est incorrect!" - read: "Impossible d'importer le fichier %{file}, car il n'est pas lisible!" + mpw_file: + read_data: "Impossible de lire le fichier MPW!" + write_data: "Impossible d'écrire le fichier MPW!" + import: "Impossible d'importer le fichier %{file}, car il n'est pas lisible!" update: name_empty: "Vous devez définir un nom!" sync: + general: "Une erreur est survenue durant la synchronisation" connection: "La connexion n'a pu être établie!" communication: "Un problème de communication avec le serveur est apparu!" download: "Impossible de télécharger le fichier!" not_authorized: "Vous n'avez pas les autorisations d'accès au fichier distant!" upload: "Impossible d'envoyer le fichier sur le serveur!" - unknown: "Une erreur inconnue est survenue!" - unknown_type: "Le type de synchronisation est inconnu" + unknown: "Une erreur inconnue est survenue!" + unknown_type: "Le type de synchronisation est inconnu" warning: select: "Votre choix n'est pas un élément valide!" diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index 64e7972..011bf3e 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -265,7 +265,7 @@ class MPW File.open(file, 'w') {|f| f << data.to_yaml} rescue Exception => e - raise "#{I18n.t('error.export.write', file: file)}\n#{e}" + raise "#{I18n.t('error.export', file: file)}\n#{e}" end # Import to yaml @@ -287,7 +287,7 @@ class MPW set_password(item.id, row['password']) end rescue Exception => e - raise "#{I18n.t('error.import.read', file: file)}\n#{e}" + raise "#{I18n.t('error.import', file: file)}\n#{e}" end # Get last sync @@ -312,7 +312,7 @@ class MPW require 'mpw/sync/ftp' sync = SyncFTP.new(@config['sync']) else - raise I18n.t('error.unknown_type') + raise I18n.t('error.sync.unknown_type') end sync.connect @@ -389,7 +389,7 @@ class MPW rescue Exception => e File.unlink(tmp_file) if File.exist?(tmp_file) - raise "#{I18n.t('error.sync.unknown')}\n#{e}" + raise "#{I18n.t('error.sync.general')}\n#{e}" end # Generate a random password From 47e84eb451a1b4c0e131ff9b1742638d4714e998 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Mon, 16 May 2016 19:51:59 +0200 Subject: [PATCH 249/531] minot fix spelling --- i18n/fr.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/fr.yml b/i18n/fr.yml index a6172ea..22309f9 100644 --- a/i18n/fr.yml +++ b/i18n/fr.yml @@ -40,7 +40,7 @@ fr: config: "Spécifie le fichier de configuration à utiliser" export: "Exporte un portefeuille dans un fichier yaml" file: "Spécifie un fichier, à utiliser avec les options [--import | --export | --add]" - force: "Ne demande pas de confirmation pour la supprésion d'un élément" + force: "Ne demande pas de confirmation pour la suppression d'un élément" generate_password: "Génére un mot de passe aléatoire (défaut 8 caractères)" group: "Recherche les éléments appartenant au groupe spécifié" help: "Affiche ce message d'aide" From 5f7e1ff8004c15d7d7d7643005f84ab8aca0a329 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Mon, 16 May 2016 19:55:25 +0200 Subject: [PATCH 250/531] update Gemfile --- Gemfile | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/Gemfile b/Gemfile index 1ccb9c5..14a22b1 100644 --- a/Gemfile +++ b/Gemfile @@ -1,10 +1,7 @@ source 'https://rubygems.org' gem 'highline' -gem 'i18n', '0.6.9' +gem 'i18n' gem 'locale' gem 'gpgme' gem 'colorize' - -group :ssh do - gem 'net-sftp' -end +gem 'net-sftp' From f842bd63ee05dd4fc11ad04524b8c7a98de16b88 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Mon, 16 May 2016 20:14:03 +0200 Subject: [PATCH 251/531] remove check_config in read_data --- lib/mpw/mpw.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index 011bf3e..cb7e57d 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -36,7 +36,6 @@ class MPW case f.full_name when 'wallet/config.gpg' @config = YAML.load(decrypt(f.read)) - check_config when 'wallet/meta.gpg' data = decrypt(f.read) From 2a0decd21578634e96cf4e0df2e383c833951c1e Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Mon, 16 May 2016 20:15:42 +0200 Subject: [PATCH 252/531] rename function checkconfig to is_valid? --- bin/mpw | 8 +++----- lib/mpw/config.rb | 13 +++++++------ lib/mpw/ui/cli.rb | 3 ++- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/bin/mpw b/bin/mpw index 63868ed..1b8d552 100755 --- a/bin/mpw +++ b/bin/mpw @@ -128,13 +128,11 @@ end.parse! # Main # --------------------------------------------------------- # -config = MPW::Config.new(options[:config]) -check_error = config.checkconfig - -cli = MPW::Cli.new(config) +config = MPW::Config.new(options[:config]) +cli = MPW::Cli.new(config) # Setup a new config -if not check_error or not options[:setup].nil? +if not config.is_valid? or not options[:setup].nil? cli.setup(lang) elsif not config.check_gpg_key? cli.setup_gpg_key diff --git a/lib/mpw/config.rb b/lib/mpw/config.rb index 951f400..1eaaa0e 100644 --- a/lib/mpw/config.rb +++ b/lib/mpw/config.rb @@ -98,18 +98,19 @@ class Config # Check the config file # @rtrn: true if the config file is correct - def checkconfig + def is_valid? config = YAML::load_file(@config_file) @key = config['config']['key'] @lang = config['config']['lang'] @wallet_dir = config['config']['wallet_dir'] - if @key.empty? or @wallet_dir.empty? - raise I18n.t('error.config.check') - end + raise if @key.empty? or @wallet_dir.empty? + I18n.locale = @lang.to_sym - rescue Exception => e - raise "#{I18n.t('error.config.check')}\n#{e}" + + return true + rescue + return false end # Check if private key exist diff --git a/lib/mpw/ui/cli.rb b/lib/mpw/ui/cli.rb index 957005b..a41657f 100644 --- a/lib/mpw/ui/cli.rb +++ b/lib/mpw/ui/cli.rb @@ -35,7 +35,8 @@ class Cli I18n.locale = language.to_sym @config.setup(key, lang, wallet_dir) - @config.checkconfig + + raise I18n.t('error.config.check') if not @config.is_valid? puts "#{I18n.t('form.setup_config.valid')}".green rescue Exception => e From 95675ce3ff21e7923a86e07871ddade5a0cad202 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Mon, 16 May 2016 20:41:51 +0200 Subject: [PATCH 253/531] update readme --- README.md | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 75 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index cbf6e64..cad2fc2 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,87 @@ # Manage your passwords! MPW is a little software which stores your passwords in an GPG encrypted file. -MPW can synchronize your password with a MPW Server or via SSH or via FTP. +MPW can synchronize your password with via SSH or FTP. # Installation -You must generate a GPG Key with GPG or with Seahorse (GUI on linux). -This program work with ruby >= 1.9 +This program work with ruby >= 2.0 * install ruby and rubygems on your computer * gem install mpw -If you want use mpw-ssh, you must install sshpass - # How to use -mpw -h +* Show help +mpw --help + +* Setup a new config file +mpw --setup +mpw --setup --config /path/conf/file.cfg + +* Create and setup a new wallet +mpw --setup-wallet --wallet new_wallet_name +mpw --setup-wallet --wallet new_wallet_name --config /path/conf/file.cfg + +* Add a new item in wallet +mpw --add +mpw --add --config /path/conf/file.cfg +mpw --add --wallet wallet_name +mpw --add --config /path/conf/file.cfg --wallet wallet_name + +* Update an item +mpw --update --id uniq_id +mpw --update --id uniq_id --config /path/conf/file.cfg +mpw --update --id uniq_id --wallet wallet_name +mpw --update --id uniq_id --config /path/conf/file.cfg --wallet wallet_name + +* Delete an item +mpw --delete --id uniq_id +mpw --delete --id uniq_id --config /path/conf/file.cfg +mpw --delete --id uniq_id --wallet wallet_name +mpw --delete --id uniq_id --config /path/conf/file.cfg --wallet wallet_name + +* Show an item +mpw --show 'string to search' +mpw --show 'string to search' --config /path/conf/file.cfg +mpw --show 'string to search' --wallet wallet_name +mpw --show 'string to search' --config /path/conf/file.cfg --wallet wallet_name +mpw --show 'string to search' --group group_name +mpw --show 'string to search' --group group_name --config /path/conf/file.cfg +mpw --show 'string to search' --group group_name --wallet wallet_name +mpw --show 'string to search' --group group_name --config /path/conf/file.cfg --wallet wallet_name + +* Export data in YAML file +mpw --export --file /path/file/to/export.yml +mpw --export --file /path/file/to/export.yml --config /path/conf/file.cfg +mpw --export --file /path/file/to/export.yml --wallet wallet_name +mpw --export --file /path/file/to/export.yml --config /path/conf/file.cfg --wallet wallet_name + +* Import data from YAML file +mpw --import --file /path/file/to/export.yml +mpw --import --file /path/file/to/export.yml --config /path/conf/file.cfg +mpw --import --file /path/file/to/export.yml --wallet wallet_name +mpw --import --file /path/file/to/export.yml --config /path/conf/file.cfg --wallet wallet_name + +Format file to import: + +1: + name: Website perso + group: Perso + host: localhost.local + protocol: ftp + user: test + password: letoortue + port: 21 + comment: Mysuper website +2: + name: Linuxfr + group: Pro + host: Linuxfr.org + protocol: https + user: test + password: coucou + port: + comment: + + From f1814c518ed5b851bbd1fe61bc8e696d898e1035 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Mon, 16 May 2016 20:47:44 +0200 Subject: [PATCH 254/531] update readme --- README.md | 104 ++++++++++++++++++++++++++---------------------------- 1 file changed, 51 insertions(+), 53 deletions(-) diff --git a/README.md b/README.md index cad2fc2..5d79fb1 100644 --- a/README.md +++ b/README.md @@ -13,75 +13,73 @@ This program work with ruby >= 2.0 # How to use * Show help -mpw --help + mpw --help * Setup a new config file -mpw --setup -mpw --setup --config /path/conf/file.cfg + mpw --setup + mpw --setup --config /path/conf/file.cfg * Create and setup a new wallet -mpw --setup-wallet --wallet new_wallet_name -mpw --setup-wallet --wallet new_wallet_name --config /path/conf/file.cfg + mpw --setup-wallet --wallet new_wallet_name + mpw --setup-wallet --wallet new_wallet_name --config /path/conf/file.cfg * Add a new item in wallet -mpw --add -mpw --add --config /path/conf/file.cfg -mpw --add --wallet wallet_name -mpw --add --config /path/conf/file.cfg --wallet wallet_name + mpw --add + mpw --add --config /path/conf/file.cfg + mpw --add --wallet wallet_name + mpw --add --config /path/conf/file.cfg --wallet wallet_name * Update an item -mpw --update --id uniq_id -mpw --update --id uniq_id --config /path/conf/file.cfg -mpw --update --id uniq_id --wallet wallet_name -mpw --update --id uniq_id --config /path/conf/file.cfg --wallet wallet_name + mpw --update --id uniq_id + mpw --update --id uniq_id --config /path/conf/file.cfg + mpw --update --id uniq_id --wallet wallet_name + mpw --update --id uniq_id --config /path/conf/file.cfg --wallet wallet_name * Delete an item -mpw --delete --id uniq_id -mpw --delete --id uniq_id --config /path/conf/file.cfg -mpw --delete --id uniq_id --wallet wallet_name -mpw --delete --id uniq_id --config /path/conf/file.cfg --wallet wallet_name + mpw --delete --id uniq_id + mpw --delete --id uniq_id --config /path/conf/file.cfg + mpw --delete --id uniq_id --wallet wallet_name + mpw --delete --id uniq_id --config /path/conf/file.cfg --wallet wallet_name * Show an item -mpw --show 'string to search' -mpw --show 'string to search' --config /path/conf/file.cfg -mpw --show 'string to search' --wallet wallet_name -mpw --show 'string to search' --config /path/conf/file.cfg --wallet wallet_name -mpw --show 'string to search' --group group_name -mpw --show 'string to search' --group group_name --config /path/conf/file.cfg -mpw --show 'string to search' --group group_name --wallet wallet_name -mpw --show 'string to search' --group group_name --config /path/conf/file.cfg --wallet wallet_name + mpw --show 'string to search' + mpw --show 'string to search' --config /path/conf/file.cfg + mpw --show 'string to search' --wallet wallet_name + mpw --show 'string to search' --config /path/conf/file.cfg --wallet wallet_name + mpw --show 'string to search' --group group_name + mpw --show 'string to search' --group group_name --config /path/conf/file.cfg + mpw --show 'string to search' --group group_name --wallet wallet_name + mpw --show 'string to search' --group group_name --config /path/conf/file.cfg --wallet wallet_name * Export data in YAML file -mpw --export --file /path/file/to/export.yml -mpw --export --file /path/file/to/export.yml --config /path/conf/file.cfg -mpw --export --file /path/file/to/export.yml --wallet wallet_name -mpw --export --file /path/file/to/export.yml --config /path/conf/file.cfg --wallet wallet_name + mpw --export --file /path/file/to/export.yml + mpw --export --file /path/file/to/export.yml --config /path/conf/file.cfg + mpw --export --file /path/file/to/export.yml --wallet wallet_name + mpw --export --file /path/file/to/export.yml --config /path/conf/file.cfg --wallet wallet_name * Import data from YAML file -mpw --import --file /path/file/to/export.yml -mpw --import --file /path/file/to/export.yml --config /path/conf/file.cfg -mpw --import --file /path/file/to/export.yml --wallet wallet_name -mpw --import --file /path/file/to/export.yml --config /path/conf/file.cfg --wallet wallet_name + mpw --import --file /path/file/to/export.yml + mpw --import --file /path/file/to/export.yml --config /path/conf/file.cfg + mpw --import --file /path/file/to/export.yml --wallet wallet_name + mpw --import --file /path/file/to/export.yml --config /path/conf/file.cfg --wallet wallet_name Format file to import: -1: - name: Website perso - group: Perso - host: localhost.local - protocol: ftp - user: test - password: letoortue - port: 21 - comment: Mysuper website -2: - name: Linuxfr - group: Pro - host: Linuxfr.org - protocol: https - user: test - password: coucou - port: - comment: - - + 1: + name: Website perso + group: Perso + host: localhost.local + protocol: ftp + user: test + password: letoortue + port: 21 + comment: Mysuper website + 2: + name: Linuxfr + group: Pro + host: Linuxfr.org + protocol: https + user: test + password: coucou + port: + comment: From 56eaae86b745feb93653d898bbf73737be2af3a8 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Mon, 16 May 2016 20:48:57 +0200 Subject: [PATCH 255/531] update readme --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index 5d79fb1..74bf554 100644 --- a/README.md +++ b/README.md @@ -16,32 +16,38 @@ This program work with ruby >= 2.0 mpw --help * Setup a new config file + mpw --setup mpw --setup --config /path/conf/file.cfg * Create and setup a new wallet + mpw --setup-wallet --wallet new_wallet_name mpw --setup-wallet --wallet new_wallet_name --config /path/conf/file.cfg * Add a new item in wallet + mpw --add mpw --add --config /path/conf/file.cfg mpw --add --wallet wallet_name mpw --add --config /path/conf/file.cfg --wallet wallet_name * Update an item + mpw --update --id uniq_id mpw --update --id uniq_id --config /path/conf/file.cfg mpw --update --id uniq_id --wallet wallet_name mpw --update --id uniq_id --config /path/conf/file.cfg --wallet wallet_name * Delete an item + mpw --delete --id uniq_id mpw --delete --id uniq_id --config /path/conf/file.cfg mpw --delete --id uniq_id --wallet wallet_name mpw --delete --id uniq_id --config /path/conf/file.cfg --wallet wallet_name * Show an item + mpw --show 'string to search' mpw --show 'string to search' --config /path/conf/file.cfg mpw --show 'string to search' --wallet wallet_name @@ -52,12 +58,14 @@ This program work with ruby >= 2.0 mpw --show 'string to search' --group group_name --config /path/conf/file.cfg --wallet wallet_name * Export data in YAML file + mpw --export --file /path/file/to/export.yml mpw --export --file /path/file/to/export.yml --config /path/conf/file.cfg mpw --export --file /path/file/to/export.yml --wallet wallet_name mpw --export --file /path/file/to/export.yml --config /path/conf/file.cfg --wallet wallet_name * Import data from YAML file + mpw --import --file /path/file/to/export.yml mpw --import --file /path/file/to/export.yml --config /path/conf/file.cfg mpw --import --file /path/file/to/export.yml --wallet wallet_name From 32ba65a558e3f0dc932e45d7a0987327fe35062a Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Mon, 16 May 2016 20:51:11 +0200 Subject: [PATCH 256/531] update readme --- README.md | 102 +++++++++++++++++++++++++++--------------------------- 1 file changed, 51 insertions(+), 51 deletions(-) diff --git a/README.md b/README.md index 74bf554..c75f0dc 100644 --- a/README.md +++ b/README.md @@ -13,81 +13,81 @@ This program work with ruby >= 2.0 # How to use * Show help - mpw --help + mpw --help * Setup a new config file - mpw --setup - mpw --setup --config /path/conf/file.cfg + mpw --setup + mpw --setup --config /path/conf/file.cfg * Create and setup a new wallet - mpw --setup-wallet --wallet new_wallet_name - mpw --setup-wallet --wallet new_wallet_name --config /path/conf/file.cfg + mpw --setup-wallet --wallet new_wallet_name + mpw --setup-wallet --wallet new_wallet_name --config /path/conf/file.cfg * Add a new item in wallet - mpw --add - mpw --add --config /path/conf/file.cfg - mpw --add --wallet wallet_name - mpw --add --config /path/conf/file.cfg --wallet wallet_name + mpw --add + mpw --add --config /path/conf/file.cfg + mpw --add --wallet wallet_name + mpw --add --config /path/conf/file.cfg --wallet wallet_name * Update an item - mpw --update --id uniq_id - mpw --update --id uniq_id --config /path/conf/file.cfg - mpw --update --id uniq_id --wallet wallet_name - mpw --update --id uniq_id --config /path/conf/file.cfg --wallet wallet_name + mpw --update --id uniq_id + mpw --update --id uniq_id --config /path/conf/file.cfg + mpw --update --id uniq_id --wallet wallet_name + mpw --update --id uniq_id --config /path/conf/file.cfg --wallet wallet_name * Delete an item - mpw --delete --id uniq_id - mpw --delete --id uniq_id --config /path/conf/file.cfg - mpw --delete --id uniq_id --wallet wallet_name - mpw --delete --id uniq_id --config /path/conf/file.cfg --wallet wallet_name + mpw --delete --id uniq_id + mpw --delete --id uniq_id --config /path/conf/file.cfg + mpw --delete --id uniq_id --wallet wallet_name + mpw --delete --id uniq_id --config /path/conf/file.cfg --wallet wallet_name * Show an item - mpw --show 'string to search' - mpw --show 'string to search' --config /path/conf/file.cfg - mpw --show 'string to search' --wallet wallet_name - mpw --show 'string to search' --config /path/conf/file.cfg --wallet wallet_name - mpw --show 'string to search' --group group_name - mpw --show 'string to search' --group group_name --config /path/conf/file.cfg - mpw --show 'string to search' --group group_name --wallet wallet_name - mpw --show 'string to search' --group group_name --config /path/conf/file.cfg --wallet wallet_name + mpw --show 'string to search' + mpw --show 'string to search' --config /path/conf/file.cfg + mpw --show 'string to search' --wallet wallet_name + mpw --show 'string to search' --config /path/conf/file.cfg --wallet wallet_name + mpw --show 'string to search' --group group_name + mpw --show 'string to search' --group group_name --config /path/conf/file.cfg + mpw --show 'string to search' --group group_name --wallet wallet_name + mpw --show 'string to search' --group group_name --config /path/conf/file.cfg --wallet wallet_name * Export data in YAML file - mpw --export --file /path/file/to/export.yml - mpw --export --file /path/file/to/export.yml --config /path/conf/file.cfg - mpw --export --file /path/file/to/export.yml --wallet wallet_name - mpw --export --file /path/file/to/export.yml --config /path/conf/file.cfg --wallet wallet_name + mpw --export --file /path/file/to/export.yml + mpw --export --file /path/file/to/export.yml --config /path/conf/file.cfg + mpw --export --file /path/file/to/export.yml --wallet wallet_name + mpw --export --file /path/file/to/export.yml --config /path/conf/file.cfg --wallet wallet_name * Import data from YAML file - mpw --import --file /path/file/to/export.yml - mpw --import --file /path/file/to/export.yml --config /path/conf/file.cfg - mpw --import --file /path/file/to/export.yml --wallet wallet_name - mpw --import --file /path/file/to/export.yml --config /path/conf/file.cfg --wallet wallet_name + mpw --import --file /path/file/to/export.yml + mpw --import --file /path/file/to/export.yml --config /path/conf/file.cfg + mpw --import --file /path/file/to/export.yml --wallet wallet_name + mpw --import --file /path/file/to/export.yml --config /path/conf/file.cfg --wallet wallet_name Format file to import: - 1: - name: Website perso - group: Perso - host: localhost.local - protocol: ftp - user: test - password: letoortue - port: 21 - comment: Mysuper website - 2: - name: Linuxfr - group: Pro - host: Linuxfr.org - protocol: https - user: test - password: coucou - port: - comment: + 1: + name: Website perso + group: Perso + host: localhost.local + protocol: ftp + user: test + password: letoortue + port: 21 + comment: Mysuper website + 2: + name: Linuxfr + group: Pro + host: Linuxfr.org + protocol: https + user: test + password: coucou + port: + comment: From d7c8aa314299004d7c8a9f7109fd20963e04d5f3 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Mon, 16 May 2016 21:04:49 +0200 Subject: [PATCH 257/531] update readme --- README.md | 102 +++++++++++++++++++++++++++--------------------------- 1 file changed, 51 insertions(+), 51 deletions(-) diff --git a/README.md b/README.md index c75f0dc..b3c9942 100644 --- a/README.md +++ b/README.md @@ -13,81 +13,81 @@ This program work with ruby >= 2.0 # How to use * Show help - mpw --help +> mpw --help * Setup a new config file - mpw --setup - mpw --setup --config /path/conf/file.cfg +> mpw --setup +> mpw --setup --config /path/conf/file.cfg * Create and setup a new wallet - mpw --setup-wallet --wallet new_wallet_name - mpw --setup-wallet --wallet new_wallet_name --config /path/conf/file.cfg +> mpw --setup-wallet --wallet new_wallet_name +> mpw --setup-wallet --wallet new_wallet_name --config /path/conf/file.cfg * Add a new item in wallet - mpw --add - mpw --add --config /path/conf/file.cfg - mpw --add --wallet wallet_name - mpw --add --config /path/conf/file.cfg --wallet wallet_name +> mpw --add +> mpw --add --config /path/conf/file.cfg +> mpw --add --wallet wallet_name +> mpw --add --config /path/conf/file.cfg --wallet wallet_name * Update an item - mpw --update --id uniq_id - mpw --update --id uniq_id --config /path/conf/file.cfg - mpw --update --id uniq_id --wallet wallet_name - mpw --update --id uniq_id --config /path/conf/file.cfg --wallet wallet_name +> mpw --update --id uniq_id +> mpw --update --id uniq_id --config /path/conf/file.cfg +> mpw --update --id uniq_id --wallet wallet_name +> mpw --update --id uniq_id --config /path/conf/file.cfg --wallet wallet_name * Delete an item - mpw --delete --id uniq_id - mpw --delete --id uniq_id --config /path/conf/file.cfg - mpw --delete --id uniq_id --wallet wallet_name - mpw --delete --id uniq_id --config /path/conf/file.cfg --wallet wallet_name +> mpw --delete --id uniq_id +> mpw --delete --id uniq_id --config /path/conf/file.cfg +> mpw --delete --id uniq_id --wallet wallet_name +> mpw --delete --id uniq_id --config /path/conf/file.cfg --wallet wallet_name * Show an item - mpw --show 'string to search' - mpw --show 'string to search' --config /path/conf/file.cfg - mpw --show 'string to search' --wallet wallet_name - mpw --show 'string to search' --config /path/conf/file.cfg --wallet wallet_name - mpw --show 'string to search' --group group_name - mpw --show 'string to search' --group group_name --config /path/conf/file.cfg - mpw --show 'string to search' --group group_name --wallet wallet_name - mpw --show 'string to search' --group group_name --config /path/conf/file.cfg --wallet wallet_name +> mpw --show 'string to search' +> mpw --show 'string to search' --config /path/conf/file.cfg +> mpw --show 'string to search' --wallet wallet_name +> mpw --show 'string to search' --config /path/conf/file.cfg --wallet wallet_name +> mpw --show 'string to search' --group group_name +> mpw --show 'string to search' --group group_name --config /path/conf/file.cfg +> mpw --show 'string to search' --group group_name --wallet wallet_name +> mpw --show 'string to search' --group group_name --config /path/conf/file.cfg --wallet wallet_name * Export data in YAML file - mpw --export --file /path/file/to/export.yml - mpw --export --file /path/file/to/export.yml --config /path/conf/file.cfg - mpw --export --file /path/file/to/export.yml --wallet wallet_name - mpw --export --file /path/file/to/export.yml --config /path/conf/file.cfg --wallet wallet_name +> mpw --export --file /path/file/to/export.yml +> mpw --export --file /path/file/to/export.yml --config /path/conf/file.cfg +> mpw --export --file /path/file/to/export.yml --wallet wallet_name +> mpw --export --file /path/file/to/export.yml --config /path/conf/file.cfg --wallet wallet_name * Import data from YAML file - mpw --import --file /path/file/to/export.yml - mpw --import --file /path/file/to/export.yml --config /path/conf/file.cfg - mpw --import --file /path/file/to/export.yml --wallet wallet_name - mpw --import --file /path/file/to/export.yml --config /path/conf/file.cfg --wallet wallet_name +> mpw --import --file /path/file/to/export.yml +> mpw --import --file /path/file/to/export.yml --config /path/conf/file.cfg +> mpw --import --file /path/file/to/export.yml --wallet wallet_name +> mpw --import --file /path/file/to/export.yml --config /path/conf/file.cfg --wallet wallet_name Format file to import: - 1: - name: Website perso - group: Perso - host: localhost.local - protocol: ftp - user: test - password: letoortue - port: 21 - comment: Mysuper website - 2: - name: Linuxfr - group: Pro - host: Linuxfr.org - protocol: https - user: test - password: coucou - port: - comment: +> 1: +> name: Website perso +> group: Perso +> host: localhost.local +> protocol: ftp +> user: test +> password: letoortue +> port: 21 +> comment: Mysuper website +> 2: +> name: Linuxfr +> group: Pro +> host: Linuxfr.org +> protocol: https +> user: test +> password: coucou +> port: +> comment: From 6ca9e8bffe982b415e33b034fe9c05646501a417 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Mon, 16 May 2016 21:39:05 +0200 Subject: [PATCH 258/531] update readme --- README.md | 123 +++++++++++++++++++++++++++++------------------------- 1 file changed, 65 insertions(+), 58 deletions(-) diff --git a/README.md b/README.md index b3c9942..7958e71 100644 --- a/README.md +++ b/README.md @@ -13,81 +13,88 @@ This program work with ruby >= 2.0 # How to use * Show help -> mpw --help +mpw --help * Setup a new config file -> mpw --setup -> mpw --setup --config /path/conf/file.cfg +mpw --setup +mpw --setup --config /path/conf/file.cfg * Create and setup a new wallet -> mpw --setup-wallet --wallet new_wallet_name -> mpw --setup-wallet --wallet new_wallet_name --config /path/conf/file.cfg +mpw --setup-wallet --wallet new_wallet_name +mpw --setup-wallet --wallet new_wallet_name --config /path/conf/file.cfg * Add a new item in wallet - -> mpw --add -> mpw --add --config /path/conf/file.cfg -> mpw --add --wallet wallet_name -> mpw --add --config /path/conf/file.cfg --wallet wallet_name +``` +mpw --add +mpw --add --config /path/conf/file.cfg +mpw --add --wallet wallet_name +mpw --add --config /path/conf/file.cfg --wallet wallet_name +``` * Update an item - -> mpw --update --id uniq_id -> mpw --update --id uniq_id --config /path/conf/file.cfg -> mpw --update --id uniq_id --wallet wallet_name -> mpw --update --id uniq_id --config /path/conf/file.cfg --wallet wallet_name +``` +mpw --update --id uniq_id +mpw --update --id uniq_id --config /path/conf/file.cfg +mpw --update --id uniq_id --wallet wallet_name +mpw --update --id uniq_id --config /path/conf/file.cfg --wallet wallet_name +``` * Delete an item - -> mpw --delete --id uniq_id -> mpw --delete --id uniq_id --config /path/conf/file.cfg -> mpw --delete --id uniq_id --wallet wallet_name -> mpw --delete --id uniq_id --config /path/conf/file.cfg --wallet wallet_name +``` +mpw --delete --id uniq_id +mpw --delete --id uniq_id --config /path/conf/file.cfg +mpw --delete --id uniq_id --wallet wallet_name +mpw --delete --id uniq_id --config /path/conf/file.cfg --wallet wallet_name +``` * Show an item - -> mpw --show 'string to search' -> mpw --show 'string to search' --config /path/conf/file.cfg -> mpw --show 'string to search' --wallet wallet_name -> mpw --show 'string to search' --config /path/conf/file.cfg --wallet wallet_name -> mpw --show 'string to search' --group group_name -> mpw --show 'string to search' --group group_name --config /path/conf/file.cfg -> mpw --show 'string to search' --group group_name --wallet wallet_name -> mpw --show 'string to search' --group group_name --config /path/conf/file.cfg --wallet wallet_name +``` +mpw --show 'string to search' +mpw --show 'string to search' --config /path/conf/file.cfg +mpw --show 'string to search' --wallet wallet_name +mpw --show 'string to search' --config /path/conf/file.cfg --wallet wallet_name +mpw --show 'string to search' --group group_name +mpw --show 'string to search' --group group_name --config /path/conf/file.cfg +mpw --show 'string to search' --group group_name --wallet wallet_name +mpw --show 'string to search' --group group_name --config /path/conf/file.cfg --wallet wallet_name +``` * Export data in YAML file - -> mpw --export --file /path/file/to/export.yml -> mpw --export --file /path/file/to/export.yml --config /path/conf/file.cfg -> mpw --export --file /path/file/to/export.yml --wallet wallet_name -> mpw --export --file /path/file/to/export.yml --config /path/conf/file.cfg --wallet wallet_name +``` +mpw --export --file /path/file/to/export.yml +mpw --export --file /path/file/to/export.yml --config /path/conf/file.cfg +mpw --export --file /path/file/to/export.yml --wallet wallet_name +mpw --export --file /path/file/to/export.yml --config /path/conf/file.cfg --wallet wallet_name +``` * Import data from YAML file - -> mpw --import --file /path/file/to/export.yml -> mpw --import --file /path/file/to/export.yml --config /path/conf/file.cfg -> mpw --import --file /path/file/to/export.yml --wallet wallet_name -> mpw --import --file /path/file/to/export.yml --config /path/conf/file.cfg --wallet wallet_name +``` +mpw --import --file /path/file/to/export.yml +mpw --import --file /path/file/to/export.yml --config /path/conf/file.cfg +mpw --import --file /path/file/to/export.yml --wallet wallet_name +mpw --import --file /path/file/to/export.yml --config /path/conf/file.cfg --wallet wallet_name +``` Format file to import: - -> 1: -> name: Website perso -> group: Perso -> host: localhost.local -> protocol: ftp -> user: test -> password: letoortue -> port: 21 -> comment: Mysuper website -> 2: -> name: Linuxfr -> group: Pro -> host: Linuxfr.org -> protocol: https -> user: test -> password: coucou -> port: -> comment: +``` +1: + name: Website perso + group: Perso + host: localhost.local + protocol: ftp + user: test + password: letoortue + port: 21 + comment: Mysuper website +2: + name: Linuxfr + group: Pro + host: Linuxfr.org + protocol: https + user: test + password: coucou + port: + comment: +``` From 240af672abb052bdd1c210fda0805cfe3da07738 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Mon, 16 May 2016 21:53:24 +0200 Subject: [PATCH 259/531] update readme --- README.md | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 7958e71..a6b4dee 100644 --- a/README.md +++ b/README.md @@ -13,17 +13,44 @@ This program work with ruby >= 2.0 # How to use * Show help +``` mpw --help +``` * Setup a new config file - +``` mpw --setup mpw --setup --config /path/conf/file.cfg +``` * Create and setup a new wallet - +``` mpw --setup-wallet --wallet new_wallet_name mpw --setup-wallet --wallet new_wallet_name --config /path/conf/file.cfg +``` + +* Add a GPG key in wallet +``` +mpw --add --key root@localhost.local +mpw --add --key root@localhost.local --config /path/conf/file.cfg +mpw --add --key root@localhost.local --wallet wallet_name +mpw --add --key root@localhost.local --config /path/conf/file.cfg --wallet wallet_name +``` + +* Add a new GPG key in wallet +``` +mpw --add --key root@localhost.local --file /path/gpg/file.pub +mpw --add --key root@localhost.local --file /path/gpg/file.pub --config /path/conf/file.cfg +mpw --add --key root@localhost.local --file /path/gpg/file.pub --wallet wallet_name +mpw --add --key root@localhost.local --file /path/gpg/file.pub --config /path/conf/file.cfg --wallet wallet_name +``` + +* Delete a GPG key in wallet +``` +mpw --delete --key root@localhost.local +mpw --delete --key root@localhost.local --wallet wallet_name +mpw --delete --key root@localhost.local --wallet wallet_name --config /path/conf/file.cfg +``` * Add a new item in wallet ``` From 53cb745eb4b2568a521a07d2fe88404e793e9b77 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Tue, 17 May 2016 19:25:30 +0200 Subject: [PATCH 260/531] fix bug when create recursive config folder --- lib/mpw/config.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/mpw/config.rb b/lib/mpw/config.rb index 1eaaa0e..85b863b 100644 --- a/lib/mpw/config.rb +++ b/lib/mpw/config.rb @@ -5,6 +5,7 @@ require 'gpgme' require 'yaml' require 'i18n' +require 'fileutils' module MPW class Config @@ -55,7 +56,7 @@ class Config } } - Dir.mkdir(wallet_dir, 0700) + FileUtils.mkdir_p(wallet_dir, mode: 0700) File.open(@config_file, 'w') do |file| file << config.to_yaml end From 8a89339691fe66ec7e36f7a32920da9b32102b1a Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Tue, 17 May 2016 19:34:05 +0200 Subject: [PATCH 261/531] fix translate --- i18n/en.yml | 12 ++++++------ i18n/fr.yml | 2 +- lib/mpw/ui/cli.rb | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/i18n/en.yml b/i18n/en.yml index a81fced..5c36344 100644 --- a/i18n/en.yml +++ b/i18n/en.yml @@ -84,13 +84,13 @@ en: not_valid: "No data to import!" setup_config: title: "Setup a new config file" - lang: "Choose your language (en, fr, ...): " - gpg_key: "Enter the GPG key: " - wallet_dir: "Enter the wallets's folder path [défaut=%{home}/wallets]: " + lang: "Choose your language (en, fr, ...) [default=%{lang}]: " + gpg_key: "Enter the GPG key [ex: test@host.local]: " + wallet_dir: "Enter the wallets's folder path [default=%{home}/wallets]: " valid: "The config file has been created!" setup_wallet: title: "Wallet setup" - sync_type: "Synchronization type (mpw, ssh, ftp, or nil): " + sync_type: "Synchronization type (ssh, ftp, or nil): " sync_host: "Synchronization server: " sync_port: "Port of the synchronization server: " sync_user: "Username for the synchronization: " @@ -126,11 +126,11 @@ en: display: comment: "Comment" error: "ERROR" - gpg_password: "Password GPG: " + gpg_password: "GPG passphrase: " group: "Group" login: "Login" name: "Name" - nothing: "Nothing result!" + nothing: "No matches!" password: "Password" port: "Port" protocol: "Protocol" diff --git a/i18n/fr.yml b/i18n/fr.yml index 22309f9..f273aff 100644 --- a/i18n/fr.yml +++ b/i18n/fr.yml @@ -85,7 +85,7 @@ fr: setup_config: title: "Création d'un nouveau fichier de configuration" lang: "Choisissez votre langue (en, fr, ...) [défaut=%{lang}]: " - gpg_key: "Entrez la clé GPG: " + gpg_key: "Entrez la clé GPG [ex: test@host.local]: " wallet_dir: "Entrez le chemin du répertoire qui contiendra les porte-feuilles de mot de passe [défaut=%{home}/wallets]: " valid: "Le fichier de configuration a bien été créé!" setup_wallet: diff --git a/lib/mpw/ui/cli.rb b/lib/mpw/ui/cli.rb index a41657f..a0d5b29 100644 --- a/lib/mpw/ui/cli.rb +++ b/lib/mpw/ui/cli.rb @@ -322,7 +322,7 @@ class Cli def export(file) @mpw.export(file) - puts "#{I18n.t('export.valid', file)}".green + puts "#{I18n.t('export.export.valid', file)}".green rescue Exception => e puts "#{I18n.t('display.error')} #17: #{e}".red end From 5287c4f122d82b7a36c8b034f3e895674ec45fa5 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Thu, 30 Jun 2016 22:02:04 +0200 Subject: [PATCH 262/531] fix Gemfile --- Gemfile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Gemfile b/Gemfile index 14a22b1..ef153b8 100644 --- a/Gemfile +++ b/Gemfile @@ -4,4 +4,5 @@ gem 'i18n' gem 'locale' gem 'gpgme' gem 'colorize' -gem 'net-sftp' +gem 'net-ssh' +gem 'net-scp' From 4ea4376149fd784896daa0a1e4d7a95bac7582d5 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Thu, 30 Jun 2016 22:02:45 +0200 Subject: [PATCH 263/531] add license in source file --- bin/mpw | 18 ++++++++++++++++-- lib/mpw/config.rb | 18 ++++++++++++++++-- lib/mpw/item.rb | 18 ++++++++++++++++-- lib/mpw/mpw.rb | 18 ++++++++++++++++-- lib/mpw/sync/ftp.rb | 18 ++++++++++++++++-- lib/mpw/sync/ssh.rb | 18 ++++++++++++++++-- lib/mpw/ui/cli.rb | 18 ++++++++++++++++-- 7 files changed, 112 insertions(+), 14 deletions(-) diff --git a/bin/mpw b/bin/mpw index 1b8d552..245c8ab 100755 --- a/bin/mpw +++ b/bin/mpw @@ -1,6 +1,20 @@ #!/usr/bin/ruby -# author: nishiki -# mail: nishiki@yaegashi.fr +# MPW is a software to crypt and manage your passwords +# Copyright (C) 2016 Adrien Waksberg <mpw@yae.im> +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. require 'optparse' require 'pathname' diff --git a/lib/mpw/config.rb b/lib/mpw/config.rb index 85b863b..49345d7 100644 --- a/lib/mpw/config.rb +++ b/lib/mpw/config.rb @@ -1,6 +1,20 @@ #!/usr/bin/ruby -# author: nishiki -# mail: nishiki@yaegashi.fr +# MPW is a software to crypt and manage your passwords +# Copyright (C) 2016 Adrien Waksberg <mpw@yae.im> +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. require 'gpgme' require 'yaml' diff --git a/lib/mpw/item.rb b/lib/mpw/item.rb index 660f74a..7f0459a 100644 --- a/lib/mpw/item.rb +++ b/lib/mpw/item.rb @@ -1,6 +1,20 @@ #!/usr/bin/ruby -# author: nishiki -# mail: nishiki@yaegashi.fr +# MPW is a software to crypt and manage your passwords +# Copyright (C) 2016 Adrien Waksberg <mpw@yae.im> +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. require 'i18n' diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index cb7e57d..14f7ab8 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -1,6 +1,20 @@ #!/usr/bin/ruby -# author: nishiki -# mail: nishiki@yaegashi.fr +# MPW is a software to crypt and manage your passwords +# Copyright (C) 2016 Adrien Waksberg <mpw@yae.im> +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. require 'rubygems/package' require 'gpgme' diff --git a/lib/mpw/sync/ftp.rb b/lib/mpw/sync/ftp.rb index 71d1624..d64e629 100644 --- a/lib/mpw/sync/ftp.rb +++ b/lib/mpw/sync/ftp.rb @@ -1,6 +1,20 @@ #!/usr/bin/ruby -# author: nishiki -# mail: nishiki@yaegashi.fr +# MPW is a software to crypt and manage your passwords +# Copyright (C) 2016 Adrien Waksberg <mpw@yae.im> +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. require 'i18n' require 'net/ftp' diff --git a/lib/mpw/sync/ssh.rb b/lib/mpw/sync/ssh.rb index 45dae3a..4471949 100644 --- a/lib/mpw/sync/ssh.rb +++ b/lib/mpw/sync/ssh.rb @@ -1,6 +1,20 @@ #!/usr/bin/ruby -# author: nishiki -# mail: nishiki@yaegashi.fr +# MPW is a software to crypt and manage your passwords +# Copyright (C) 2016 Adrien Waksberg <mpw@yae.im> +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. require 'i18n' require 'net/ssh' diff --git a/lib/mpw/ui/cli.rb b/lib/mpw/ui/cli.rb index a0d5b29..bccb9be 100644 --- a/lib/mpw/ui/cli.rb +++ b/lib/mpw/ui/cli.rb @@ -1,6 +1,20 @@ #!/usr/bin/ruby -# author: nishiki -# mail: nishiki@yaegashi.fr +# MPW is a software to crypt and manage your passwords +# Copyright (C) 2016 Adrien Waksberg <mpw@yae.im> +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. require 'readline' require 'i18n' From 8d73f9cf474f47eaeec791a646d65c3906ded55e Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Thu, 30 Jun 2016 22:24:51 +0200 Subject: [PATCH 264/531] update gemspec file --- mpw.gemspec | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/mpw.gemspec b/mpw.gemspec index d004d34..5024cd1 100644 --- a/mpw.gemspec +++ b/mpw.gemspec @@ -5,22 +5,23 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) Gem::Specification.new do |spec| spec.name = 'mpw' spec.version = File.open('VERSION').read - spec.authors = ['nishiki'] - spec.email = ['gems@yae.im'] - spec.summary = 'Manage your password' - spec.description = 'Save and read your password with gpg' + spec.authors = ['Adrien Waksberg'] + spec.email = ['mpw@yae.im'] + spec.summary = 'MPW is a software to crypt and manage your passwords' + spec.description = 'Manage your passwords in all security with MPW, we use GPG to crypt your passwords' spec.homepage = 'https://github.com/nishiki/manage-password' - spec.license = 'GPL' + spec.license = 'GPL-2.0' spec.files = `git ls-files -z`.split("\x0") - spec.executables = ['mpw', 'mpw-server', 'mpw-ssh'] + spec.executables = ['mpw'] spec.test_files = spec.files.grep(%r{^(test|spec|features)/}) spec.require_paths = ['lib'] - spec.add_dependency "i18n", "~> 0.6", ">= 0.6.9" + spec.add_dependency "i18n" spec.add_dependency "gpgme" spec.add_dependency "highline" spec.add_dependency "locale" spec.add_dependency "colorize" - spec.add_dependency "net-sftp" + spec.add_dependency "net-ssh" + spec.add_dependency "net-scp" end From 19d0f749c82ca00e1c7c1ef0ce9110638f2e5430 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Thu, 30 Jun 2016 22:25:20 +0200 Subject: [PATCH 265/531] change version for 3.0-beta --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 50ffc5a..0f982ff 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.0.3 +3.0.0-beta From 0238e75d36c611ff3f0f00918d02d91236587b8a Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Fri, 1 Jul 2016 09:15:39 +0200 Subject: [PATCH 266/531] no sync if last_sync == remote.last_sync --- lib/mpw/mpw.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index 14f7ab8..a07061c 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -336,6 +336,8 @@ class MPW File.unlink(tmp_file) if File.exist?(tmp_file) + return if remote.get_last_sync == get_last_sync + if not remote.to_s.empty? @data.each do |item| update = false From e12b701c4b200713c72903f7571cf7648371e2d9 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Fri, 1 Jul 2016 09:22:28 +0200 Subject: [PATCH 267/531] add option no sync --- bin/mpw | 2 +- lib/mpw/ui/cli.rb | 18 ++++++++++-------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/bin/mpw b/bin/mpw index 245c8ab..080c58a 100755 --- a/bin/mpw +++ b/bin/mpw @@ -143,7 +143,7 @@ end.parse! # --------------------------------------------------------- # config = MPW::Config.new(options[:config]) -cli = MPW::Cli.new(config) +cli = MPW::Cli.new(config, options[:sync]) # Setup a new config if not config.is_valid? or not options[:setup].nil? diff --git a/lib/mpw/ui/cli.rb b/lib/mpw/ui/cli.rb index bccb9be..5965dfb 100644 --- a/lib/mpw/ui/cli.rb +++ b/lib/mpw/ui/cli.rb @@ -29,9 +29,11 @@ module MPW class Cli # Constructor - # @args: config_file -> a specify config file - def initialize(config) + # @args: config -> the config + # sync -> boolean for sync or not + def initialize(config, sync=true) @config = config + @sync = sync end # Create a new config file @@ -124,7 +126,7 @@ class Cli end @mpw.read_data - @mpw.sync + @mpw.sync if @sync rescue Exception => e puts "#{I18n.t('display.error')} #11: #{e}".red exit 2 @@ -224,7 +226,7 @@ class Cli def add_key(key, file=nil) @mpw.add_key(key, file) @mpw.write_data - @mpw.sync + @mpw.sync if @sync puts "#{I18n.t('form.add_key.valid')}".green rescue Exception => e @@ -236,7 +238,7 @@ class Cli def delete_key(key) @mpw.delete_key(key) @mpw.write_data - @mpw.sync + @mpw.sync if @sync puts "#{I18n.t('form.delete_key.valid')}".green rescue Exception => e @@ -263,7 +265,7 @@ class Cli @mpw.add(item) @mpw.set_password(item.id, password) @mpw.write_data - @mpw.sync + @mpw.sync if @sync puts "#{I18n.t('form.add_item.valid')}".green end @@ -292,7 +294,7 @@ class Cli item.update(options) @mpw.set_password(item.id, password) if not password.empty? @mpw.write_data - @mpw.sync + @mpw.sync if @sync puts "#{I18n.t('form.update_item.valid')}".green else @@ -324,7 +326,7 @@ class Cli item.delete @mpw.write_data - @mpw.sync + @mpw.sync if @sync puts "#{I18n.t('form.delete_item.valid', id: id)}".green rescue Exception => e From 0733bdbd123ef7299254e0d98a94ca041f8c74a7 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Fri, 1 Jul 2016 09:28:56 +0200 Subject: [PATCH 268/531] minor syntax fix --- lib/mpw/ui/cli.rb | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/mpw/ui/cli.rb b/lib/mpw/ui/cli.rb index 5965dfb..3bfe30a 100644 --- a/lib/mpw/ui/cli.rb +++ b/lib/mpw/ui/cli.rb @@ -102,12 +102,12 @@ class Cli puts I18n.t('form.setup_wallet.title') puts '--------------------' - config['sync']['type'] = ask(I18n.t('form.setup_wallet.sync_type')).to_s - config['sync']['host'] = ask(I18n.t('form.setup_wallet.sync_host')).to_s - config['sync']['port'] = ask(I18n.t('form.setup_wallet.sync_port')).to_s - config['sync']['user'] = ask(I18n.t('form.setup_wallet.sync_user')).to_s - config['sync']['password'] = ask(I18n.t('form.setup_wallet.sync_pwd')).to_s - config['sync']['path'] = ask(I18n.t('form.setup_wallet.sync_path')).to_s + config['sync']['type'] = ask(I18n.t('form.setup_wallet.sync_type')).to_s + config['sync']['host'] = ask(I18n.t('form.setup_wallet.sync_host')).to_s + config['sync']['port'] = ask(I18n.t('form.setup_wallet.sync_port')).to_s + config['sync']['user'] = ask(I18n.t('form.setup_wallet.sync_user')).to_s + config['sync']['password'] = ask(I18n.t('form.setup_wallet.sync_pwd')).to_s + config['sync']['path'] = ask(I18n.t('form.setup_wallet.sync_path')).to_s @mpw.set_config(config) @mpw.write_data From 8d01c21806a82c09dff5644929fe33a11a0833f3 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Tue, 5 Jul 2016 13:44:04 +0200 Subject: [PATCH 269/531] release version 3.0 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 0f982ff..4a36342 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3.0.0-beta +3.0.0 From e9eb9b0909051f283badd51f75d795a289acf3ae Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Tue, 5 Jul 2016 13:59:54 +0200 Subject: [PATCH 270/531] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a6b4dee..6532a53 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # Manage your passwords! MPW is a little software which stores your passwords in an GPG encrypted file. -MPW can synchronize your password with via SSH or FTP. +MPW can synchronize your password with SSH or FTP. # Installation From ac3b7b1dde1fa421c73b2fd56985c02baeec3f16 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Tue, 5 Jul 2016 14:35:10 +0200 Subject: [PATCH 271/531] Update mpw.gemspec --- mpw.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mpw.gemspec b/mpw.gemspec index 5024cd1..31b851f 100644 --- a/mpw.gemspec +++ b/mpw.gemspec @@ -8,7 +8,7 @@ Gem::Specification.new do |spec| spec.authors = ['Adrien Waksberg'] spec.email = ['mpw@yae.im'] spec.summary = 'MPW is a software to crypt and manage your passwords' - spec.description = 'Manage your passwords in all security with MPW, we use GPG to crypt your passwords' + spec.description = 'Manage your passwords in all security with MPW, we use GPG to encrypt your passwords' spec.homepage = 'https://github.com/nishiki/manage-password' spec.license = 'GPL-2.0' From 8e4027c82216e304f11a4f60b43ade4fe0b54a53 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Tue, 5 Jul 2016 22:03:55 +0200 Subject: [PATCH 272/531] switch gpg2 to gpg1 --- i18n/en.yml | 1 + i18n/fr.yml | 1 + lib/mpw/config.rb | 6 +++++- lib/mpw/mpw.rb | 9 +++++++-- lib/mpw/ui/cli.rb | 5 +++-- 5 files changed, 17 insertions(+), 5 deletions(-) diff --git a/i18n/en.yml b/i18n/en.yml index 5c36344..9121813 100644 --- a/i18n/en.yml +++ b/i18n/en.yml @@ -86,6 +86,7 @@ en: title: "Setup a new config file" lang: "Choose your language (en, fr, ...) [default=%{lang}]: " gpg_key: "Enter the GPG key [ex: test@host.local]: " + gpg_exe: "Enter the executable GPG path (optional): " wallet_dir: "Enter the wallets's folder path [default=%{home}/wallets]: " valid: "The config file has been created!" setup_wallet: diff --git a/i18n/fr.yml b/i18n/fr.yml index f273aff..155a177 100644 --- a/i18n/fr.yml +++ b/i18n/fr.yml @@ -86,6 +86,7 @@ fr: title: "Création d'un nouveau fichier de configuration" lang: "Choisissez votre langue (en, fr, ...) [défaut=%{lang}]: " gpg_key: "Entrez la clé GPG [ex: test@host.local]: " + gpg_exe: "Entrez le chemin de l'exécutable GPG (optionnel): " wallet_dir: "Entrez le chemin du répertoire qui contiendra les porte-feuilles de mot de passe [défaut=%{home}/wallets]: " valid: "Le fichier de configuration a bien été créé!" setup_wallet: diff --git a/lib/mpw/config.rb b/lib/mpw/config.rb index 49345d7..90df409 100644 --- a/lib/mpw/config.rb +++ b/lib/mpw/config.rb @@ -30,6 +30,7 @@ class Config attr_accessor :lang attr_accessor :config_dir attr_accessor :wallet_dir + attr_accessor :gpg_exe # Constructor # @args: config_file -> the specify config file @@ -53,8 +54,9 @@ class Config # @args: key -> the gpg key to encrypt # lang -> the software language # wallet_dir -> the directory where are the wallets password + # gpg_exe -> the path of gpg executable # @rtrn: true if le config file is create - def setup(key, lang, wallet_dir) + def setup(key, lang, wallet_dir, gpg_exe) if not key =~ /[a-zA-Z0-9.-_]+\@[a-zA-Z0-9]+\.[a-zA-Z]+/ raise I18n.t('error.config.key_bad_format') @@ -67,6 +69,7 @@ class Config config = {'config' => {'key' => key, 'lang' => lang, 'wallet_dir' => wallet_dir, + 'gpg_exe' => gpg_exe, } } @@ -118,6 +121,7 @@ class Config @key = config['config']['key'] @lang = config['config']['lang'] @wallet_dir = config['config']['wallet_dir'] + @gpg_exe = config['config']['gpg_exe'] raise if @key.empty? or @wallet_dir.empty? diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index a07061c..f2b2ddc 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -28,10 +28,15 @@ module MPW class MPW # Constructor - def initialize(key, wallet_file, gpg_pass=nil) + def initialize(key, wallet_file, gpg_pass=nil, gpg_exe=nil) @key = key @gpg_pass = gpg_pass + @gpg_exe = gpg_exe @wallet_file = wallet_file + + if @gpg_exe + GPGME::Engine.set_info(GPGME::PROTOCOL_OpenPGP, @gpg_exe, "#{Dir.home}/.gnupg") + end end # Read mpw file @@ -331,7 +336,7 @@ class MPW sync.connect sync.get(tmp_file) - remote = MPW.new(@key, tmp_file, @gpg_pass) + remote = MPW.new(@key, tmp_file, @gpg_pass, @gpg_exe) remote.read_data File.unlink(tmp_file) if File.exist?(tmp_file) diff --git a/lib/mpw/ui/cli.rb b/lib/mpw/ui/cli.rb index 3bfe30a..d72d597 100644 --- a/lib/mpw/ui/cli.rb +++ b/lib/mpw/ui/cli.rb @@ -44,13 +44,14 @@ class Cli language = ask(I18n.t('form.setup_config.lang', lang: lang)).to_s key = ask(I18n.t('form.setup_config.gpg_key')).to_s wallet_dir = ask(I18n.t('form.setup_config.wallet_dir', home: "#{@config.config_dir}")).to_s + gpg_exe = ask(I18n.t('form.setup_config.gpg_exe')).to_s if language.nil? or language.empty? language = lang end I18n.locale = language.to_sym - @config.setup(key, lang, wallet_dir) + @config.setup(key, lang, wallet_dir, gpg_exe) raise I18n.t('error.config.check') if not @config.is_valid? @@ -122,7 +123,7 @@ class Cli def decrypt if not defined?(@mpw) @password = ask(I18n.t('display.gpg_password')) {|q| q.echo = false} - @mpw = MPW.new(@config.key, @wallet_file, @password) + @mpw = MPW.new(@config.key, @wallet_file, @password, @config.gpg_exe) end @mpw.read_data From 91242936074bd36fdff67b5e29beaf55afbd68ed Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Tue, 5 Jul 2016 22:39:10 +0200 Subject: [PATCH 273/531] fix translate --- i18n/en.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/en.yml b/i18n/en.yml index 9121813..6e20e46 100644 --- a/i18n/en.yml +++ b/i18n/en.yml @@ -23,7 +23,7 @@ en: update: name_empty: "You must define a name!" sync: - general: "An error is appeared durint the sync" + general: "An error is appeared during the sync" connection: "Connection fail!" communication: "A communication problem with the server is appeared!" download: "Can't download the file!" From 25a64d0303fdbdc4cdb823ff755fcbe1859fea28 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Tue, 5 Jul 2016 22:47:35 +0200 Subject: [PATCH 274/531] fix bug try sync but sync is nil --- lib/mpw/mpw.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index f2b2ddc..4ee0b8c 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -317,7 +317,7 @@ class MPW # Sync data with remote file def sync - return if @config.empty? or @config['sync'].nil? + return if @config.empty? or @config['sync']['type'].to_s.empty? tmp_file = "#{@wallet_file}.sync" last_sync = @config['last_sync'].to_i From 9565d40668f859ce0cf4a3173e2ab1dcd8e93f6f Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Tue, 5 Jul 2016 22:48:21 +0200 Subject: [PATCH 275/531] fix translate --- i18n/en.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/en.yml b/i18n/en.yml index 6e20e46..d18ecee 100644 --- a/i18n/en.yml +++ b/i18n/en.yml @@ -91,7 +91,7 @@ en: valid: "The config file has been created!" setup_wallet: title: "Wallet setup" - sync_type: "Synchronization type (ssh, ftp, or nil): " + sync_type: "Synchronization type (ssh, ftp): " sync_host: "Synchronization server: " sync_port: "Port of the synchronization server: " sync_user: "Username for the synchronization: " From 6bbee4d2cee37417944e7dcc217981be27673b99 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Tue, 5 Jul 2016 22:59:52 +0200 Subject: [PATCH 276/531] ui: no show wallet setup form if sync is nil --- lib/mpw/ui/cli.rb | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/lib/mpw/ui/cli.rb b/lib/mpw/ui/cli.rb index d72d597..433df6f 100644 --- a/lib/mpw/ui/cli.rb +++ b/lib/mpw/ui/cli.rb @@ -104,11 +104,14 @@ class Cli puts I18n.t('form.setup_wallet.title') puts '--------------------' config['sync']['type'] = ask(I18n.t('form.setup_wallet.sync_type')).to_s - config['sync']['host'] = ask(I18n.t('form.setup_wallet.sync_host')).to_s - config['sync']['port'] = ask(I18n.t('form.setup_wallet.sync_port')).to_s - config['sync']['user'] = ask(I18n.t('form.setup_wallet.sync_user')).to_s - config['sync']['password'] = ask(I18n.t('form.setup_wallet.sync_pwd')).to_s - config['sync']['path'] = ask(I18n.t('form.setup_wallet.sync_path')).to_s + + if ['ftp', 'ssh'].include?(config['sync']['type'].downcase) + config['sync']['host'] = ask(I18n.t('form.setup_wallet.sync_host')).to_s + config['sync']['port'] = ask(I18n.t('form.setup_wallet.sync_port')).to_s + config['sync']['user'] = ask(I18n.t('form.setup_wallet.sync_user')).to_s + config['sync']['password'] = ask(I18n.t('form.setup_wallet.sync_pwd')).to_s + config['sync']['path'] = ask(I18n.t('form.setup_wallet.sync_path')).to_s + end @mpw.set_config(config) @mpw.write_data From 50ea811b612c2cb07a669e75cc37edc139514cc7 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Tue, 5 Jul 2016 23:01:27 +0200 Subject: [PATCH 277/531] fix translate --- i18n/en.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/en.yml b/i18n/en.yml index d18ecee..e6b7a78 100644 --- a/i18n/en.yml +++ b/i18n/en.yml @@ -23,7 +23,7 @@ en: update: name_empty: "You must define a name!" sync: - general: "An error is appeared during the sync" + general: "An error has appeared during the sync" connection: "Connection fail!" communication: "A communication problem with the server is appeared!" download: "Can't download the file!" From 4502c43424c5ebd4f8bc8d0a5d739307088ff811 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Tue, 5 Jul 2016 23:14:12 +0200 Subject: [PATCH 278/531] catch backstrace when interrupt --- bin/mpw | 117 +++++++++++++++++++++++++++++--------------------------- 1 file changed, 61 insertions(+), 56 deletions(-) diff --git a/bin/mpw b/bin/mpw index 080c58a..8e72668 100755 --- a/bin/mpw +++ b/bin/mpw @@ -142,61 +142,66 @@ end.parse! # Main # --------------------------------------------------------- # -config = MPW::Config.new(options[:config]) -cli = MPW::Cli.new(config, options[:sync]) +begin + config = MPW::Config.new(options[:config]) + cli = MPW::Cli.new(config, options[:sync]) + + # Setup a new config + if not config.is_valid? or not options[:setup].nil? + cli.setup(lang) + elsif not config.check_gpg_key? + cli.setup_gpg_key + end -# Setup a new config -if not config.is_valid? or not options[:setup].nil? - cli.setup(lang) -elsif not config.check_gpg_key? - cli.setup_gpg_key + cli.get_wallet(options[:wallet]) + cli.decrypt + + # Display the item's informations + if not options[:show].nil? + opts = {search: options[:show], + group: options[:group], + } + + cli.display(opts) + + # Remove an item + elsif not options[:delete].nil? and not options[:id].nil? + cli.delete(options[:id], options[:force]) + + # Update an item + elsif not options[:update].nil? and not options[:id].nil? + cli.update(options[:id]) + + # Add a new item + elsif not options[:add].nil? and options[:key].nil? + cli.add + + # Add a new public key in wallet + elsif not options[:add].nil? and not options[:key].nil? + cli.add_key(options[:key], options[:file]) + + # Delete a public key in wallet + elsif not options[:delete].nil? and not options[:key].nil? + cli.delete_key(options[:key]) + + # Export + elsif not options[:export].nil? and not options[:file].nil? + cli.export(options[:file]) + + # Add a new item + elsif not options[:import].nil? and not options[:file].nil? + cli.import(options[:file]) + + # Setup wallet config + elsif not options[:setup_wallet].nil? + cli.setup_wallet_config + + end + + cli = nil + + exit 0 + +rescue SystemExit, Interrupt + exit 3 end - -cli.get_wallet(options[:wallet]) -cli.decrypt - -# Display the item's informations -if not options[:show].nil? - opts = {search: options[:show], - group: options[:group], - } - - cli.display(opts) - -# Remove an item -elsif not options[:delete].nil? and not options[:id].nil? - cli.delete(options[:id], options[:force]) - -# Update an item -elsif not options[:update].nil? and not options[:id].nil? - cli.update(options[:id]) - -# Add a new item -elsif not options[:add].nil? and options[:key].nil? - cli.add - -# Add a new public key in wallet -elsif not options[:add].nil? and not options[:key].nil? - cli.add_key(options[:key], options[:file]) - -# Delete a public key in wallet -elsif not options[:delete].nil? and not options[:key].nil? - cli.delete_key(options[:key]) - -# Export -elsif not options[:export].nil? and not options[:file].nil? - cli.export(options[:file]) - -# Add a new item -elsif not options[:import].nil? and not options[:file].nil? - cli.import(options[:file]) - -# Setup wallet config -elsif not options[:setup_wallet].nil? - cli.setup_wallet_config - -end - -cli = nil - -exit 0 From 8bfcb29bdf817154d9413b871970c5facebff031 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Wed, 6 Jul 2016 21:40:51 +0200 Subject: [PATCH 279/531] no error after config --- bin/mpw | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/bin/mpw b/bin/mpw index 8e72668..ce73305 100755 --- a/bin/mpw +++ b/bin/mpw @@ -147,11 +147,13 @@ begin cli = MPW::Cli.new(config, options[:sync]) # Setup a new config - if not config.is_valid? or not options[:setup].nil? + if not options[:setup].nil? cli.setup(lang) - elsif not config.check_gpg_key? - cli.setup_gpg_key + exit 0 end + + cli.setup(lang) if not config.is_valid? + cli.setup_gpg_key if not config.check_gpg_key? cli.get_wallet(options[:wallet]) cli.decrypt From 10363047274447fe0c799b51c5da4632b3131e8c Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Wed, 6 Jul 2016 21:48:49 +0200 Subject: [PATCH 280/531] no sync if last sync < 5min --- lib/mpw/mpw.rb | 9 +++++---- lib/mpw/ui/cli.rb | 10 +++++----- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index 4ee0b8c..69a4938 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -316,12 +316,13 @@ class MPW end # Sync data with remote file - def sync + # @args: force -> force the sync + def sync(force=false) return if @config.empty? or @config['sync']['type'].to_s.empty? + return if get_last_sync < Time.now.to_i + 300 and not force tmp_file = "#{@wallet_file}.sync" - last_sync = @config['last_sync'].to_i - + case @config['sync']['type'] when 'sftp', 'scp', 'ssh' require "#{APP_ROOT}/../lib/mpw/sync/ssh.rb" @@ -370,7 +371,7 @@ class MPW end # Remove an old item - if not update and item.last_sync.to_i < last_sync and item.last_edit < last_sync + if not update and item.last_sync.to_i < get_last_sync and item.last_edit < get_last_sync item.delete end end diff --git a/lib/mpw/ui/cli.rb b/lib/mpw/ui/cli.rb index 433df6f..bed2d31 100644 --- a/lib/mpw/ui/cli.rb +++ b/lib/mpw/ui/cli.rb @@ -230,7 +230,7 @@ class Cli def add_key(key, file=nil) @mpw.add_key(key, file) @mpw.write_data - @mpw.sync if @sync + @mpw.sync(true) if @sync puts "#{I18n.t('form.add_key.valid')}".green rescue Exception => e @@ -242,7 +242,7 @@ class Cli def delete_key(key) @mpw.delete_key(key) @mpw.write_data - @mpw.sync if @sync + @mpw.sync(true) if @sync puts "#{I18n.t('form.delete_key.valid')}".green rescue Exception => e @@ -269,7 +269,7 @@ class Cli @mpw.add(item) @mpw.set_password(item.id, password) @mpw.write_data - @mpw.sync if @sync + @mpw.sync(true) if @sync puts "#{I18n.t('form.add_item.valid')}".green end @@ -298,7 +298,7 @@ class Cli item.update(options) @mpw.set_password(item.id, password) if not password.empty? @mpw.write_data - @mpw.sync if @sync + @mpw.sync(true) if @sync puts "#{I18n.t('form.update_item.valid')}".green else @@ -330,7 +330,7 @@ class Cli item.delete @mpw.write_data - @mpw.sync if @sync + @mpw.sync(true) if @sync puts "#{I18n.t('form.delete_item.valid', id: id)}".green rescue Exception => e From bbeeb680653e9fbaab6c1c64fb0a118f350f09c4 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Wed, 6 Jul 2016 22:04:37 +0200 Subject: [PATCH 281/531] change version to 3.1.0 beta --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 4a36342..b6919fe 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3.0.0 +3.1.0-beta From e068a2758c867e7e634fe21a67887bf5279592bd Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sat, 9 Jul 2016 14:06:49 +0200 Subject: [PATCH 282/531] add login and password in clipboard --- Gemfile | 1 + README.md | 1 + bin/mpw | 19 ++++++++++++------- i18n/en.yml | 5 +++++ i18n/fr.yml | 5 +++++ lib/mpw/ui/cli.rb | 33 +++++++++++++++++++++++++++++---- mpw.gemspec | 1 + 7 files changed, 54 insertions(+), 11 deletions(-) diff --git a/Gemfile b/Gemfile index ef153b8..b897ea2 100644 --- a/Gemfile +++ b/Gemfile @@ -6,3 +6,4 @@ gem 'gpgme' gem 'colorize' gem 'net-ssh' gem 'net-scp' +gem 'clipboard' diff --git a/README.md b/README.md index 6532a53..e3ca84c 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,7 @@ MPW can synchronize your password with SSH or FTP. This program work with ruby >= 2.0 * install ruby and rubygems on your computer +* install xclip * gem install mpw # How to use diff --git a/bin/mpw b/bin/mpw index ce73305..52033a3 100755 --- a/bin/mpw +++ b/bin/mpw @@ -48,12 +48,13 @@ I18n.locale = lang.to_sym # Options # --------------------------------------------------------- # -options = {} -options[:force] = false -options[:sync] = true -options[:group] = nil -options[:config] = nil -options[:wallet] = nil +options = {} +options[:force] = false +options[:sync] = true +options[:clipboard] = true +options[:group] = nil +options[:config] = nil +options[:wallet] = nil OptionParser.new do |opts| opts.banner = "#{I18n.t('option.usage')}: mpw [options]" @@ -71,6 +72,10 @@ OptionParser.new do |opts| options[:config] = config end + opts.on('-C', '--no-clipboard', I18n.t('option.clipboard')) do + options[:clipboard] = false + end + opts.on('-d', '--delete', I18n.t('option.remove')) do options[:delete] = true end @@ -144,7 +149,7 @@ end.parse! begin config = MPW::Config.new(options[:config]) - cli = MPW::Cli.new(config, options[:sync]) + cli = MPW::Cli.new(config, options[:clipboard], options[:sync]) # Setup a new config if not options[:setup].nil? diff --git a/i18n/en.yml b/i18n/en.yml index e6b7a78..5426128 100644 --- a/i18n/en.yml +++ b/i18n/en.yml @@ -38,6 +38,7 @@ en: option: add: "Add an item or key" config: "Specify the configuration file to use" + clipboard: "Disable the clipboard feature" export: "Export a wallet in an yaml file" file: "Specify a file, to use with the options [--import | --export | --add]" force: "No ask to confirm when you delete an item" @@ -72,6 +73,10 @@ en: port: "Enter the connection port (optional): " comment: "Enter a comment (optional): " valid: "Item has been added!" + clipboard: + clean: "The clipboard has been cleaned." + login: "The login has been copied in clipboard, press any key to continue." + password: "The password has been copied in clipboard for 30s!" delete_key: valid: "Key has been deleted!" delete_item: diff --git a/i18n/fr.yml b/i18n/fr.yml index 155a177..f371eef 100644 --- a/i18n/fr.yml +++ b/i18n/fr.yml @@ -38,6 +38,7 @@ fr: option: add: "Ajoute un élément ou une clé" config: "Spécifie le fichier de configuration à utiliser" + clipboard: "Désactive la fonction presse papier" export: "Exporte un portefeuille dans un fichier yaml" file: "Spécifie un fichier, à utiliser avec les options [--import | --export | --add]" force: "Ne demande pas de confirmation pour la suppression d'un élément" @@ -72,6 +73,10 @@ fr: port: "Entrez le port de connexion (optionnel): " comment: "Entrez un commentaire (optionnel): " valid: "L'élément a bien été ajouté!" + clipboard: + clean: "Le presse papier a été nettoyé." + login: "L'identifiant a été copié dans le presse papier, pressez n'importe quelle touche pour continuer." + password: "Le mot de passe a été copié dans le presse papier pour 30s!" delete_key: valid: "La clé a bien été supprimée!" delete_item: diff --git a/lib/mpw/ui/cli.rb b/lib/mpw/ui/cli.rb index bed2d31..d2980cf 100644 --- a/lib/mpw/ui/cli.rb +++ b/lib/mpw/ui/cli.rb @@ -20,6 +20,7 @@ require 'readline' require 'i18n' require 'colorize' require 'highline/import' +require 'clipboard' #TODO require "#{APP_ROOT}/../lib/mpw/item.rb" @@ -31,9 +32,10 @@ class Cli # Constructor # @args: config -> the config # sync -> boolean for sync or not - def initialize(config, sync=true) - @config = config - @sync = sync + def initialize(config, clipboard=true, sync=true) + @config = config + @clipboard = clipboard + @sync = sync end # Create a new config file @@ -184,11 +186,34 @@ class Cli print "#{I18n.t('display.login')}: ".cyan puts item.user print "#{I18n.t('display.password')}: ".cyan - puts @mpw.get_password(item.id) + if @clipboard + puts '***********' + else + puts @mpw.get_password(item.id) + end print "#{I18n.t('display.port')}: ".cyan puts item.port print "#{I18n.t('display.comment')}: ".cyan puts item.comment + + clipboard(item) if @clipboard + end + + # Copy in clipboard the login and password + def clipboard(item) + Clipboard.copy(item.user) + print "\n#{I18n.t('form.clipboard.login')}".green + gets + + Clipboard.copy(@mpw.get_password(item.id)) + puts I18n.t('form.clipboard.password').yellow + + sleep(30) + + Clipboard.clear + puts I18n.t('form.clipboard.clean').green + rescue SystemExit, Interrupt + Clipboard.clear end # Display the wallet diff --git a/mpw.gemspec b/mpw.gemspec index 31b851f..bf6f3db 100644 --- a/mpw.gemspec +++ b/mpw.gemspec @@ -24,4 +24,5 @@ Gem::Specification.new do |spec| spec.add_dependency "colorize" spec.add_dependency "net-ssh" spec.add_dependency "net-scp" + spec.add_dependency "clipboard" end From 2ff967cded5dec7364037329859a845d8affba33 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sat, 9 Jul 2016 17:11:18 +0200 Subject: [PATCH 283/531] minor change when list items --- lib/mpw/ui/cli.rb | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/lib/mpw/ui/cli.rb b/lib/mpw/ui/cli.rb index d2980cf..3c8e5a5 100644 --- a/lib/mpw/ui/cli.rb +++ b/lib/mpw/ui/cli.rb @@ -147,11 +147,23 @@ class Cli case result.length when 0 puts I18n.t('display.nothing') + when 1 display_item(result.first) + else - i = 1 + group = nil + i = 1 + + result.sort! { |a,b| a.group.downcase <=> b.group.downcase } + result.each do |item| + if group != item.group + group = item.group + puts "#{I18n.t('display.group')}: #{group}".yellow + end + + print " |_ ".yellow print "#{i}: ".cyan print item.name print " -> #{item.comment}".magenta if not item.comment.to_s.empty? From 2883c0d51c170c5dab10765caa965ca6fec2708c Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sat, 9 Jul 2016 17:12:10 +0200 Subject: [PATCH 284/531] fix translate --- i18n/en.yml | 2 +- i18n/fr.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/i18n/en.yml b/i18n/en.yml index 5426128..42b6f37 100644 --- a/i18n/en.yml +++ b/i18n/en.yml @@ -52,7 +52,7 @@ en: setup: "Create a new configuration file" setup_wallet: "Create a new configuration file for a wallet" show: "Search and show the items" - show_all: "Show all items" + show_all: "List all items" remove: "Delete an item" update: "Update an item" usage: "Usage" diff --git a/i18n/fr.yml b/i18n/fr.yml index f371eef..882a123 100644 --- a/i18n/fr.yml +++ b/i18n/fr.yml @@ -52,7 +52,7 @@ fr: setup: "Création d'un nouveau fichier de configuration" setup_wallet: "Création d'un nouveau fichier de configuration pour un portefeuille" show: "Recherche et affiche les éléments" - show_all: "Affiche tous les éléments" + show_all: "Liste tous les éléments" remove: "Supprime un élément" update: "Met à jour un élément" usage: "Utilisation" From b233186e20919beeb58c598c1abdcfdfbd7befb8 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sat, 9 Jul 2016 17:15:03 +0200 Subject: [PATCH 285/531] update version 3.1.0 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index b6919fe..fd2a018 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3.1.0-beta +3.1.0 From 7cde7de1ed426a20f335b1cb15db6658ce03c7bd Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sun, 10 Jul 2016 11:00:04 +0200 Subject: [PATCH 286/531] update version 3.2.0-beta --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index fd2a018..db8f8da 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3.1.0 +3.2.0-beta From 712ac9d99829ec91339a031d95fa5522f715a763 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sun, 10 Jul 2016 11:00:53 +0200 Subject: [PATCH 287/531] new password generator with special chars --- bin/mpw | 22 ++++++++++++++++++++-- i18n/en.yml | 4 ++++ i18n/fr.yml | 4 ++++ lib/mpw/mpw.rb | 18 ++++++++++++------ 4 files changed, 40 insertions(+), 8 deletions(-) diff --git a/bin/mpw b/bin/mpw index 52033a3..60b0a07 100755 --- a/bin/mpw +++ b/bin/mpw @@ -48,6 +48,7 @@ I18n.locale = lang.to_sym # Options # --------------------------------------------------------- # +options_password = {} options = {} options[:force] = false options[:sync] = true @@ -97,8 +98,7 @@ OptionParser.new do |opts| end opts.on('-G', '--generate-password [LENGTH]', I18n.t('option.generate_password')) do |length| - puts MPW::MPW::password(length) - exit 0 + options_password[:length] = length end opts.on('-h', '--help', I18n.t('option.help')) do @@ -118,6 +118,10 @@ OptionParser.new do |opts| options[:key] = key end + opts.on('-n', '--numeric', I18n.t('option.numeric')) do + options_password[:numeric] = true + end + opts.on('-N', '--no-sync', I18n.t('option.no_sync')) do options[:sync] = false end @@ -141,12 +145,26 @@ OptionParser.new do |opts| opts.on('-W', '--setup-wallet', I18n.t('option.setup_wallet')) do options[:setup_wallet] = true end + + opts.on('-x', '--special-chars', I18n.t('option.special_chars')) do + options_password[:special] = true + end + + opts.on('-y', '--alpha', I18n.t('option.alpha')) do + options_password[:alpha] = true + end end.parse! # --------------------------------------------------------- # # Main # --------------------------------------------------------- # +# Generate password +if not options_password.empty? + puts MPW::MPW::password(options_password) + exit 0 +end + begin config = MPW::Config.new(options[:config]) cli = MPW::Cli.new(config, options[:clipboard], options[:sync]) diff --git a/i18n/en.yml b/i18n/en.yml index 42b6f37..2f1f476 100644 --- a/i18n/en.yml +++ b/i18n/en.yml @@ -37,6 +37,7 @@ en: option: add: "Add an item or key" + alpha: "Use letter to generate a password" config: "Specify the configuration file to use" clipboard: "Disable the clipboard feature" export: "Export a wallet in an yaml file" @@ -49,8 +50,10 @@ en: import: "Import item since a yaml file" key: "Specify the key name, to use with the options [--add | --delete | --update]" no_sync: "Disable synchronization with the server" + numeric: "Use number to generate a password" setup: "Create a new configuration file" setup_wallet: "Create a new configuration file for a wallet" + special_chars: "Use special char to generate a password" show: "Search and show the items" show_all: "List all items" remove: "Delete an item" @@ -136,6 +139,7 @@ en: group: "Group" login: "Login" name: "Name" + no_group: "Without group" nothing: "No matches!" password: "Password" port: "Port" diff --git a/i18n/fr.yml b/i18n/fr.yml index 882a123..da91af0 100644 --- a/i18n/fr.yml +++ b/i18n/fr.yml @@ -37,6 +37,7 @@ fr: option: add: "Ajoute un élément ou une clé" + alpha: "Utilise des lettres dans la génération d'un mot de passe" config: "Spécifie le fichier de configuration à utiliser" clipboard: "Désactive la fonction presse papier" export: "Exporte un portefeuille dans un fichier yaml" @@ -49,8 +50,10 @@ fr: import: "Importe des éléments depuis un fichier yaml" key: "Spécifie le nom d'une clé, à utiliser avec les options [--add | --delete | --update]" no_sync: "Désactive la synchronisation avec le serveur" + numeric: "Utilise des chiffre dans la génération d'un mot de passe" setup: "Création d'un nouveau fichier de configuration" setup_wallet: "Création d'un nouveau fichier de configuration pour un portefeuille" + special_chars: "Utilise des charactères speciaux dans la génération d'un mot de passe" show: "Recherche et affiche les éléments" show_all: "Liste tous les éléments" remove: "Supprime un élément" @@ -136,6 +139,7 @@ fr: group: "Groupe" login: "Identifiant" name: "Nom" + no_group: "Sans groupe" nothing: "Aucun résultat!" password: "Mot de passe" port: "Port" diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index 69a4938..ab2c1ce 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -414,21 +414,27 @@ class MPW end # Generate a random password - # @args: length -> the length password + # @args: options -> :length, :special, :alpha, :numeric # @rtrn: a random string - def self.password(length=8) - if length.to_i <= 0 + def self.password(options={}) + if not options.include?(:length) or options[:length].to_i <= 0 length = 8 else - length = length.to_i + length = options[:length].to_i end + chars = [] + chars += [*('!'..'?')] - [*('0'..'9')] if options.include?(:special) + chars += [*('A'..'Z'),*('a'..'z')] if options.include?(:alpha) + chars += [*('0'..'9')] if options.include?(:numeric) + chars = [*('A'..'Z'),*('a'..'z'),*('0'..'9')] if chars.empty? + result = '' while length > 62 do - result << ([*('A'..'Z'),*('a'..'z'),*('0'..'9')]).sample(62).join + result << chars.sample(62).join length -= 62 end - result << ([*('A'..'Z'),*('a'..'z'),*('0'..'9')]).sample(length).join + result << chars.sample(length).join return result end From 55342597ac4538799db25b41bd49296c91cdf153 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sun, 10 Jul 2016 11:01:11 +0200 Subject: [PATCH 288/531] improve list interface --- lib/mpw/ui/cli.rb | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/mpw/ui/cli.rb b/lib/mpw/ui/cli.rb index 3c8e5a5..5a0eb8e 100644 --- a/lib/mpw/ui/cli.rb +++ b/lib/mpw/ui/cli.rb @@ -160,7 +160,12 @@ class Cli result.each do |item| if group != item.group group = item.group - puts "#{I18n.t('display.group')}: #{group}".yellow + + if group.empty? + puts I18n.t('display.no_group').yellow + else + puts "\n#{group}".yellow + end end print " |_ ".yellow @@ -171,6 +176,8 @@ class Cli i += 1 end + + print "\n" choice = ask(I18n.t('form.select')).to_i if choice >= 1 and choice < i From 13b025df2ba915ee738b69a28310ef6ea84ed81c Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sun, 10 Jul 2016 18:55:18 +0200 Subject: [PATCH 289/531] fix path for require lib --- bin/mpw | 15 ++++++--------- lib/mpw/{ui => }/cli.rb | 6 ++---- lib/mpw/mpw.rb | 6 ++---- 3 files changed, 10 insertions(+), 17 deletions(-) rename lib/mpw/{ui => }/cli.rb (99%) diff --git a/bin/mpw b/bin/mpw index 60b0a07..cbc6e4d 100755 --- a/bin/mpw +++ b/bin/mpw @@ -16,11 +16,15 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +$: << File.expand_path('../../lib', __FILE__) + require 'optparse' -require 'pathname' require 'locale' require 'set' require 'i18n' +require 'mpw/mpw' +require 'mpw/config' +require 'mpw/cli' # --------------------------------------------------------- # # Set local @@ -32,15 +36,8 @@ if defined?(I18n.enforce_available_locales) I18n.enforce_available_locales = true end -APP_ROOT = File.dirname(Pathname.new(__FILE__).realpath) - -# TODO -require "#{APP_ROOT}/../lib/mpw/mpw.rb" -require "#{APP_ROOT}/../lib/mpw/config.rb" -require "#{APP_ROOT}/../lib/mpw/ui/cli.rb" - I18n::Backend::Simple.send(:include, I18n::Backend::Fallbacks) -I18n.load_path = Dir["#{APP_ROOT}/../i18n/*.yml"] +I18n.load_path = Dir["#{File.expand_path('../../i18n', __FILE__)}/*.yml"] I18n.default_locale = :en I18n.locale = lang.to_sym diff --git a/lib/mpw/ui/cli.rb b/lib/mpw/cli.rb similarity index 99% rename from lib/mpw/ui/cli.rb rename to lib/mpw/cli.rb index 5a0eb8e..0b06724 100644 --- a/lib/mpw/ui/cli.rb +++ b/lib/mpw/cli.rb @@ -21,10 +21,8 @@ require 'i18n' require 'colorize' require 'highline/import' require 'clipboard' - -#TODO -require "#{APP_ROOT}/../lib/mpw/item.rb" -require "#{APP_ROOT}/../lib/mpw/mpw.rb" +require 'mpw/item' +require 'mpw/mpw' module MPW class Cli diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index ab2c1ce..fc4e5da 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -20,9 +20,7 @@ require 'rubygems/package' require 'gpgme' require 'i18n' require 'yaml' - -#TODO -require "#{APP_ROOT}/../lib/mpw/item.rb" +require 'mpw/item' module MPW class MPW @@ -325,7 +323,7 @@ class MPW case @config['sync']['type'] when 'sftp', 'scp', 'ssh' - require "#{APP_ROOT}/../lib/mpw/sync/ssh.rb" + require "mpw/sync/ssh" sync = SyncSSH.new(@config['sync']) when 'ftp' require 'mpw/sync/ftp' From f68882181d6f86e9a8d55df7aede7f7b330adff2 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sun, 10 Jul 2016 19:04:34 +0200 Subject: [PATCH 290/531] minor clean code --- lib/mpw/item.rb | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/lib/mpw/item.rb b/lib/mpw/item.rb index 7f0459a..ef1309e 100644 --- a/lib/mpw/item.rb +++ b/lib/mpw/item.rb @@ -21,8 +21,6 @@ require 'i18n' module MPW class Item - attr_accessor :error_msg - attr_accessor :id attr_accessor :name attr_accessor :group @@ -41,8 +39,7 @@ class Item # raise an error if the hash hasn't the key name def initialize(options={}) if not options.has_key?(:name) or options[:name].to_s.empty? - @error_msg = I18n.t('error.update.name_empty') - raise @error_msg + raise I18n.t('error.update.name_empty') end if not options.has_key?(:id) or options[:id].to_s.empty? or not options.has_key?(:created) or options[:created].to_s.empty? @@ -60,11 +57,9 @@ class Item # Update the item # @args: options -> a hash of parameter - # @rtrn: true if the item is update def update(options={}) if options.has_key?(:name) and options[:name].to_s.empty? - @error_msg = I18n.t('error.update.name_empty') - return false + raise I18n.t('error.update.name_empty') end @name = options[:name] if options.has_key?(:name) @@ -75,8 +70,6 @@ class Item @port = options[:port].to_i if options.has_key?(:port) and not options[:port].to_s.empty? @comment = options[:comment] if options.has_key?(:comment) @last_edit = Time.now.to_i if not options.has_key?(:no_update_last_edit) - - return true end # Update last_sync @@ -85,7 +78,6 @@ class Item end # Delete all data - # @rtrn: true def delete @id = nil @name = nil @@ -98,8 +90,6 @@ class Item @created = nil @last_edit = nil @last_sync = nil - - return true end def empty? From 8a1003f1bdac9d2b20351cbd79382d8b5c7f58f3 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sun, 10 Jul 2016 19:25:21 +0200 Subject: [PATCH 291/531] fix max length to 32768 for a password --- lib/mpw/mpw.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index fc4e5da..68a2292 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -417,6 +417,8 @@ class MPW def self.password(options={}) if not options.include?(:length) or options[:length].to_i <= 0 length = 8 + elsif options[:length].to_i >= 32768 + length = 32768 else length = options[:length].to_i end From d55291cc147ce7239f9e7c9b16d474c176e4f8b4 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Mon, 11 Jul 2016 23:56:58 +0200 Subject: [PATCH 292/531] dynamic menu for clipboard --- i18n/en.yml | 3 ++- i18n/fr.yml | 3 ++- lib/mpw/cli.rb | 62 +++++++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 60 insertions(+), 8 deletions(-) diff --git a/i18n/en.yml b/i18n/en.yml index 2f1f476..c97ac5c 100644 --- a/i18n/en.yml +++ b/i18n/en.yml @@ -77,8 +77,9 @@ en: comment: "Enter a comment (optional): " valid: "Item has been added!" clipboard: + choice: "What do you want to copy ? [q = quit, p = password, l = login]: " clean: "The clipboard has been cleaned." - login: "The login has been copied in clipboard, press any key to continue." + login: "The login has been copied in clipboard." password: "The password has been copied in clipboard for 30s!" delete_key: valid: "Key has been deleted!" diff --git a/i18n/fr.yml b/i18n/fr.yml index da91af0..993a809 100644 --- a/i18n/fr.yml +++ b/i18n/fr.yml @@ -77,8 +77,9 @@ fr: comment: "Entrez un commentaire (optionnel): " valid: "L'élément a bien été ajouté!" clipboard: + choice: "Que voulez-vous copier ? [q = quitter, p = mot de passe, l = identifiant]: " clean: "Le presse papier a été nettoyé." - login: "L'identifiant a été copié dans le presse papier, pressez n'importe quelle touche pour continuer." + login: "L'identifiant a été copié dans le presse papier" password: "Le mot de passe a été copié dans le presse papier pour 30s!" delete_key: valid: "La clé a bien été supprimée!" diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index 0b06724..ce1b9ec 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -217,20 +217,69 @@ class Cli end # Copy in clipboard the login and password + # @args: item -> the item def clipboard(item) - Clipboard.copy(item.user) - print "\n#{I18n.t('form.clipboard.login')}".green - gets + pid = nil - Clipboard.copy(@mpw.get_password(item.id)) - puts I18n.t('form.clipboard.password').yellow + # Security: force quit after 90s + pid_s = Process.fork do + begin + sleep 90 + Process.kill(3, Process.ppid) + rescue Interrupt + exit + end + end + + while true + choice = ask(I18n.t('form.clipboard.choice')).to_s + + if not pid.nil? + Clipboard.clear + Process.kill(9, pid) - sleep(30) + pid = nil + end + + case choice + when 'q', 'quit' + break + + when 'l', 'login' + Clipboard.copy(item.user) + puts I18n.t('form.clipboard.login').green + + when 'p', 'password' + Clipboard.copy(@mpw.get_password(item.id)) + puts I18n.t('form.clipboard.password').yellow + + pid = Process.fork do + begin + sleep 30 + + Clipboard.clear + puts I18n.t('form.clipboard.clean').green + rescue Interrupt + exit + end + end + + else + puts I18n.t('warning.select').yellow + next + end + end Clipboard.clear puts I18n.t('form.clipboard.clean').green + rescue SystemExit, Interrupt Clipboard.clear + puts I18n.t('form.clipboard.clean').green + + ensure + Process.kill('HUP', pid) if not pid.nil? + Process.kill('HUP', pid_s) end # Display the wallet @@ -259,6 +308,7 @@ class Cli @wallet_file = wallets[choice-1] else puts "#{I18n.t('display.warning')}: #{I18n.t('warning.select')}".yellow + exit 2 end end else From 05dbba4da612e90bda4ae5aa1a746a1f6dbb6c63 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Tue, 12 Jul 2016 20:31:49 +0200 Subject: [PATCH 293/531] fix sync bug --- lib/mpw/mpw.rb | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index 68a2292..d906359 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -118,6 +118,8 @@ class MPW ) end + @config['last_update'] = Time.now.to_i + Gem::Package::TarWriter.new(File.open(tmp_file, 'w+')) do |tar| data_encrypt = encrypt(data.to_yaml) tar.add_file_simple('wallet/meta.gpg', 0400, data_encrypt.length) do |io| @@ -317,8 +319,8 @@ class MPW # @args: force -> force the sync def sync(force=false) return if @config.empty? or @config['sync']['type'].to_s.empty? - return if get_last_sync < Time.now.to_i + 300 and not force - + return if get_last_sync + 300 > Time.now.to_i and not force + tmp_file = "#{@wallet_file}.sync" case @config['sync']['type'] @@ -340,7 +342,7 @@ class MPW File.unlink(tmp_file) if File.exist?(tmp_file) - return if remote.get_last_sync == get_last_sync + return if remote.get_last_sync == @config['last_update'] if not remote.to_s.empty? @data.each do |item| From a18793d8d67e00b82a62c30ca15aeb9c30ab48e4 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Tue, 12 Jul 2016 20:32:21 +0200 Subject: [PATCH 294/531] fix salt for password --- lib/mpw/mpw.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index d906359..b15f95c 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -167,7 +167,7 @@ class MPW # args: id -> the item id # password -> the new password def set_password(id, password) - salt = MPW::password(Random.rand(4..9)) + salt = MPW::password(length: Random.rand(4..9)) password = "$#{salt}::#{password}" @passwords[id] = encrypt(password) From 4d783e88a4d9128d0c880ad27cf696ce919e3b48 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Tue, 12 Jul 2016 20:34:54 +0200 Subject: [PATCH 295/531] clipboard: remove clean text --- lib/mpw/cli.rb | 3 --- 1 file changed, 3 deletions(-) diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index ce1b9ec..ca2ee53 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -258,7 +258,6 @@ class Cli sleep 30 Clipboard.clear - puts I18n.t('form.clipboard.clean').green rescue Interrupt exit end @@ -271,11 +270,9 @@ class Cli end Clipboard.clear - puts I18n.t('form.clipboard.clean').green rescue SystemExit, Interrupt Clipboard.clear - puts I18n.t('form.clipboard.clean').green ensure Process.kill('HUP', pid) if not pid.nil? From 1edb10ae49bcfa2f59e299a552f19cdfa5143fc5 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Thu, 14 Jul 2016 00:12:21 +0200 Subject: [PATCH 296/531] replace fork to thread --- lib/mpw/cli.rb | 32 ++++++-------------------------- 1 file changed, 6 insertions(+), 26 deletions(-) diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index ca2ee53..430c671 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -222,25 +222,14 @@ class Cli pid = nil # Security: force quit after 90s - pid_s = Process.fork do - begin - sleep 90 - Process.kill(3, Process.ppid) - rescue Interrupt - exit - end + Thread.new do + sleep 90 + exit end while true choice = ask(I18n.t('form.clipboard.choice')).to_s - if not pid.nil? - Clipboard.clear - Process.kill(9, pid) - - pid = nil - end - case choice when 'q', 'quit' break @@ -253,14 +242,10 @@ class Cli Clipboard.copy(@mpw.get_password(item.id)) puts I18n.t('form.clipboard.password').yellow - pid = Process.fork do - begin - sleep 30 + Thread.new do + sleep 30 - Clipboard.clear - rescue Interrupt - exit - end + Clipboard.clear end else @@ -270,13 +255,8 @@ class Cli end Clipboard.clear - rescue SystemExit, Interrupt Clipboard.clear - - ensure - Process.kill('HUP', pid) if not pid.nil? - Process.kill('HUP', pid_s) end # Display the wallet From 8bcbffec66f60ad0ba2147841b0a298ce2858560 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Tue, 2 Aug 2016 21:59:05 +0200 Subject: [PATCH 297/531] add option for otp --- bin/mpw | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/bin/mpw b/bin/mpw index cbc6e4d..f5e717b 100755 --- a/bin/mpw +++ b/bin/mpw @@ -48,6 +48,7 @@ I18n.locale = lang.to_sym options_password = {} options = {} options[:force] = false +options[:otp] = false options[:sync] = true options[:clipboard] = true options[:group] = nil @@ -123,6 +124,10 @@ OptionParser.new do |opts| options[:sync] = false end + opts.on('-O', '--otp', I18n.t('option.otp')) do + options[:otp] = true + end + opts.on('-s', '--show [SEARCH]', I18n.t('option.show')) do |search| search.nil? ? (options[:show] = '') : (options[:show] = search) end @@ -164,7 +169,7 @@ end begin config = MPW::Config.new(options[:config]) - cli = MPW::Cli.new(config, options[:clipboard], options[:sync]) + cli = MPW::Cli.new(config, options[:clipboard], options[:sync], options[:otp]) # Setup a new config if not options[:setup].nil? From cd0dd2d0aab50f5ce72dac3d3c6e4670c3d1df68 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Tue, 2 Aug 2016 21:59:22 +0200 Subject: [PATCH 298/531] add translate for otp --- i18n/en.yml | 8 ++++++++ i18n/fr.yml | 10 +++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/i18n/en.yml b/i18n/en.yml index c97ac5c..79cf4b2 100644 --- a/i18n/en.yml +++ b/i18n/en.yml @@ -75,12 +75,19 @@ en: password: "Enter the the password: " port: "Enter the connection port (optional): " comment: "Enter a comment (optional): " + otp_key: "Enter the otp secret (base32 secret key): " valid: "Item has been added!" clipboard: choice: "What do you want to copy ? [q = quit, p = password, l = login]: " clean: "The clipboard has been cleaned." login: "The login has been copied in clipboard." password: "The password has been copied in clipboard for 30s!" + otp: "The OTP code has been copied for %{time}s!" + help: + name: "Help" + login: "Press <l> to copy the login" + password: "Press <p> to copy the password" + otp_code: "Press <o> to copy the otp code" delete_key: valid: "Key has been deleted!" delete_item: @@ -129,6 +136,7 @@ en: password: "Enter the the password: " port: "Enter the connection port [%{port}]: " comment: "Enter a comment [%{comment}]: " + otp_key: "Enter the otp secret (base32 secret key): " valid: "Item has been updated!" export: valid: "The export in %{file} is succesfull!" diff --git a/i18n/fr.yml b/i18n/fr.yml index 993a809..caf1e05 100644 --- a/i18n/fr.yml +++ b/i18n/fr.yml @@ -75,12 +75,19 @@ fr: password: "Entrez le mot de passe: " port: "Entrez le port de connexion (optionnel): " comment: "Entrez un commentaire (optionnel): " + otp_key: "Entrez le secret OTP: " valid: "L'élément a bien été ajouté!" clipboard: - choice: "Que voulez-vous copier ? [q = quitter, p = mot de passe, l = identifiant]: " + choice: "Que voulez-vous copier ? : " clean: "Le presse papier a été nettoyé." login: "L'identifiant a été copié dans le presse papier" password: "Le mot de passe a été copié dans le presse papier pour 30s!" + otp: "Le code OTP a été copié dans le presse papier il est valable %{time}s!" + help: + name: "Aide" + login: "Pressez <l> pour copier l'identifiant" + password: "Pressez <p> pour copier le mot de passe" + otp_code: "Pressez <o> pour copier le code OTP" delete_key: valid: "La clé a bien été supprimée!" delete_item: @@ -129,6 +136,7 @@ fr: password: "Entrez le mot de passe: " port: "Entrez un port de connexion [%{port}]: " comment: "Entrez un commentaire [%{comment}]: " + otp_key: "Entrez le secret OTP: " valid: "L'élément a bien été mis à jour!" export: valid: "L'export dans %{file} est un succès!" From b200b564695da09f581d1102b55f6982ad6f9183 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Tue, 2 Aug 2016 21:59:46 +0200 Subject: [PATCH 299/531] add manage otp code --- lib/mpw/cli.rb | 28 +++++++++++++++++++++++++--- lib/mpw/mpw.rb | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 3 deletions(-) diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index 430c671..03224e5 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -30,10 +30,13 @@ class Cli # Constructor # @args: config -> the config # sync -> boolean for sync or not - def initialize(config, clipboard=true, sync=true) + # clipboard -> enable clopboard + # otp -> enable otp + def initialize(config, clipboard=true, sync=true, otp=false) @config = config @clipboard = clipboard @sync = sync + @otp = otp end # Create a new config file @@ -203,11 +206,13 @@ class Cli print "#{I18n.t('display.login')}: ".cyan puts item.user print "#{I18n.t('display.password')}: ".cyan + if @clipboard puts '***********' else puts @mpw.get_password(item.id) end + print "#{I18n.t('display.port')}: ".cyan puts item.port print "#{I18n.t('display.comment')}: ".cyan @@ -248,8 +253,15 @@ class Cli Clipboard.clear end + when 'o', 'otp' + Clipboard.copy(@mpw.get_otp_code(item.id)) + puts I18n.t('form.clipboard.otp', time: @mpw.get_otp_remaining_time).yellow + else - puts I18n.t('warning.select').yellow + puts "----- #{I18n.t('form.clipboard.help.name')} -----".cyan + puts I18n.t('form.clipboard.help.login') + puts I18n.t('form.clipboard.help.password') + puts I18n.t('form.clipboard.help.otp_code') next end end @@ -333,10 +345,15 @@ class Cli options[:port] = ask(I18n.t('form.add_item.port')).to_s options[:comment] = ask(I18n.t('form.add_item.comment')).to_s + if @otp + otp_key = ask(I18n.t('form.add_item.otp_key')).to_s + end + item = Item.new(options) @mpw.add(item) @mpw.set_password(item.id, password) + @mpw.set_otp_key(item.id, otp_key) @mpw.write_data @mpw.sync(true) if @sync @@ -362,10 +379,15 @@ class Cli options[:port] = ask(I18n.t('form.update_item.port' , port: item.port)).to_s options[:comment] = ask(I18n.t('form.update_item.comment' , comment: item.comment)).to_s + if @otp + otp_key = ask(I18n.t('form.update_item.otp_key')).to_s + end + options.delete_if { |k,v| v.empty? } - + item.update(options) @mpw.set_password(item.id, password) if not password.empty? + @mpw.set_otp_key(item.id, otp_key) if not otp_key.empty? @mpw.write_data @mpw.sync(true) if @sync diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index b15f95c..c4c34ef 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -20,6 +20,7 @@ require 'rubygems/package' require 'gpgme' require 'i18n' require 'yaml' +require 'rotp' require 'mpw/item' module MPW @@ -43,6 +44,7 @@ class MPW @data = [] @keys = {} @passwords = {} + @otp_keys = {} data = nil @@ -68,6 +70,10 @@ class MPW when /^wallet\/passwords\/(?<id>[a-zA-Z0-9]+)\.gpg$/ @passwords[Regexp.last_match('id')] = f.read + + when /^wallet\/otp_keys\/(?<id>[a-zA-Z0-9]+)\.gpg$/ + @otp_keys[Regexp.last_match('id')] = f.read + else next end @@ -137,6 +143,12 @@ class MPW end end + @otp_keys.each do |id, key| + tar.add_file_simple("wallet/otp_keys/#{id}.gpg", 0400, key.length) do |io| + io.write(key) + end + end + @keys.each do |id, key| tar.add_file_simple("wallet/keys/#{id}.pub", 0400, key.length) do |io| io.write(key) @@ -413,6 +425,30 @@ class MPW raise "#{I18n.t('error.sync.general')}\n#{e}" end + # Set an opt key + # args: id -> the item id + # key -> the new key + def set_otp_key(id, key) + @otp_keys[id] = encrypt(key) + end + + # Get an otp code + # @args: id -> the item id + # @rtrn: an otp code + def get_otp_code(id) + if not @otp_keys.has_key?(id) + return 0 + else + return ROTP::TOTP.new(decrypt(@otp_keys[id])).now + end + end + + # Get remaining time before expire otp code + # @rtrn: return time in seconde + def get_otp_remaining_time + return (Time.now.utc.to_i / 30 + 1) * 30 - Time.now.utc.to_i + end + # Generate a random password # @args: options -> :length, :special, :alpha, :numeric # @rtrn: a random string From e8b572ae2e04757585d9294dac2ab4e1ca77895d Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Tue, 2 Aug 2016 22:03:09 +0200 Subject: [PATCH 300/531] add dep rotp --- Gemfile | 1 + mpw.gemspec | 1 + 2 files changed, 2 insertions(+) diff --git a/Gemfile b/Gemfile index b897ea2..557dec5 100644 --- a/Gemfile +++ b/Gemfile @@ -7,3 +7,4 @@ gem 'colorize' gem 'net-ssh' gem 'net-scp' gem 'clipboard' +gem 'rotp' diff --git a/mpw.gemspec b/mpw.gemspec index bf6f3db..fa4afc7 100644 --- a/mpw.gemspec +++ b/mpw.gemspec @@ -25,4 +25,5 @@ Gem::Specification.new do |spec| spec.add_dependency "net-ssh" spec.add_dependency "net-scp" spec.add_dependency "clipboard" + spec.add_dependency "rotp" end From 2dcff8d9ef3b7a44eb0a1cc4401ca41f036b9da8 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Tue, 2 Aug 2016 22:10:50 +0200 Subject: [PATCH 301/531] fix bug when otp is empty --- lib/mpw/cli.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index 03224e5..53ebe89 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -387,7 +387,7 @@ class Cli item.update(options) @mpw.set_password(item.id, password) if not password.empty? - @mpw.set_otp_key(item.id, otp_key) if not otp_key.empty? + @mpw.set_otp_key(item.id, otp_key) if not otp_key.to_s.empty? @mpw.write_data @mpw.sync(true) if @sync From d51c4733c052b15f808406982f042dc69b14ad03 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Wed, 3 Aug 2016 21:26:04 +0200 Subject: [PATCH 302/531] show otp code whitout clipboard --- i18n/en.yml | 1 + i18n/fr.yml | 1 + lib/mpw/cli.rb | 5 ++++- 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/i18n/en.yml b/i18n/en.yml index 79cf4b2..c704849 100644 --- a/i18n/en.yml +++ b/i18n/en.yml @@ -150,6 +150,7 @@ en: name: "Name" no_group: "Without group" nothing: "No matches!" + otp_code: "OTP code" password: "Password" port: "Port" protocol: "Protocol" diff --git a/i18n/fr.yml b/i18n/fr.yml index caf1e05..41cac4d 100644 --- a/i18n/fr.yml +++ b/i18n/fr.yml @@ -150,6 +150,7 @@ fr: name: "Nom" no_group: "Sans groupe" nothing: "Aucun résultat!" + otp_code: "Code OTP" password: "Mot de passe" port: "Port" protocol: "Protocol" diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index 53ebe89..b0e413d 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -205,12 +205,15 @@ class Cli puts item.protocol print "#{I18n.t('display.login')}: ".cyan puts item.user - print "#{I18n.t('display.password')}: ".cyan if @clipboard + print "#{I18n.t('display.password')}: ".cyan puts '***********' else + print "#{I18n.t('display.password')}: ".cyan puts @mpw.get_password(item.id) + print "#{I18n.t('display.otp_code')}: ".cyan + puts "#{@mpw.get_otp_code(item.id)} (#{@mpw.get_otp_remaining_time}s)" end print "#{I18n.t('display.port')}: ".cyan From 1104706692ad02c2187366c43d15999ca07f20ed Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Wed, 3 Aug 2016 21:26:36 +0200 Subject: [PATCH 303/531] update version --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index db8f8da..944880f 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3.2.0-beta +3.2.0 From fbc291c177087e3d00d54cb7681eb8db4fea4e7b Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Wed, 3 Aug 2016 21:37:49 +0200 Subject: [PATCH 304/531] no show otp code field if otp code is nil --- lib/mpw/cli.rb | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index b0e413d..144ed38 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -212,8 +212,11 @@ class Cli else print "#{I18n.t('display.password')}: ".cyan puts @mpw.get_password(item.id) - print "#{I18n.t('display.otp_code')}: ".cyan - puts "#{@mpw.get_otp_code(item.id)} (#{@mpw.get_otp_remaining_time}s)" + + if @mpw.get_otp_code(item.id) > 0 + print "#{I18n.t('display.otp_code')}: ".cyan + puts "#{@mpw.get_otp_code(item.id)} (#{@mpw.get_otp_remaining_time}s)" + end end print "#{I18n.t('display.port')}: ".cyan From b64514c55762cf081c81fabbb3a9578fb4195f6a Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Thu, 4 Aug 2016 22:20:12 +0200 Subject: [PATCH 305/531] if delete disable clipboard --- lib/mpw/cli.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index 144ed38..392e7bd 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -409,7 +409,8 @@ class Cli # @args: id -> the item's id # force -> no resquest a validation def delete(id, force=false) - item = @mpw.search_by_id(id) + @clipboard = false + item = @mpw.search_by_id(id) if item.nil? puts I18n.t('form.delete_item.not_valid', id: id) From 110cbe151042afa9553dac01b87373edb45d3ae9 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Thu, 4 Aug 2016 22:20:32 +0200 Subject: [PATCH 306/531] fix bug sync --- lib/mpw/mpw.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index c4c34ef..baa83f5 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -391,7 +391,7 @@ class MPW # Add item remote.list.each do |r| - next if r.last_edit <= last_sync + next if r.last_edit <= get_last_sync item = Item.new(id: r.id, name: r.name, From 08d72e8d44e0c1b5653833c6cef9e78d7503bf65 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Sat, 6 Aug 2016 23:35:54 +0200 Subject: [PATCH 307/531] update Version --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 944880f..e4604e3 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3.2.0 +3.2.1 From 2f627f271c9ae398018069caa35f70fcb2ccdf64 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Tue, 9 Aug 2016 22:06:47 +0200 Subject: [PATCH 308/531] add and update with vim editor --- bin/mpw | 22 +------- i18n/en.yml | 6 -- i18n/fr.yml | 6 -- lib/mpw/cli.rb | 114 ++++++++++++++++---------------------- templates/add_form.erb | 10 ++++ templates/update_form.erb | 10 ++++ 6 files changed, 70 insertions(+), 98 deletions(-) create mode 100644 templates/add_form.erb create mode 100644 templates/update_form.erb diff --git a/bin/mpw b/bin/mpw index f5e717b..5f0d64d 100755 --- a/bin/mpw +++ b/bin/mpw @@ -75,10 +75,6 @@ OptionParser.new do |opts| options[:clipboard] = false end - opts.on('-d', '--delete', I18n.t('option.remove')) do - options[:delete] = true - end - opts.on('-e', '--export', I18n.t('option.export')) do options[:export] = true end @@ -104,10 +100,6 @@ OptionParser.new do |opts| exit 0 end - opts.on('-i', '--id ID', I18n.t('option.id')) do |id| - options[:id] = id - end - opts.on('-I', '--import', I18n.t('option.import')) do options[:import] = true end @@ -136,10 +128,6 @@ OptionParser.new do |opts| options[:setup] = true end - opts.on('-u', '--update', I18n.t('option.update')) do - options[:update] = true - end - opts.on('-w', '--wallet WALLET', I18n.t('option.wallet')) do |wallet| options[:wallet] = wallet end @@ -191,14 +179,6 @@ begin cli.display(opts) - # Remove an item - elsif not options[:delete].nil? and not options[:id].nil? - cli.delete(options[:id], options[:force]) - - # Update an item - elsif not options[:update].nil? and not options[:id].nil? - cli.update(options[:id]) - # Add a new item elsif not options[:add].nil? and options[:key].nil? cli.add @@ -215,7 +195,7 @@ begin elsif not options[:export].nil? and not options[:file].nil? cli.export(options[:file]) - # Add a new item + # Import elsif not options[:import].nil? and not options[:file].nil? cli.import(options[:file]) diff --git a/i18n/en.yml b/i18n/en.yml index c704849..52fbf67 100644 --- a/i18n/en.yml +++ b/i18n/en.yml @@ -10,8 +10,6 @@ en: exception: "Can't create the GPG key!" name: "You must define a name for your GPG key!" password: "You must define a password for your GPG key!" - delete: - id_no_exist: "Can't delete the item %{id}, it doesn't exist!" export: "Can't export, unable to write in %{file}!" gpg_file: decrypt: "Can't decrypt file!" @@ -46,7 +44,6 @@ en: generate_password: "Generate a random password (default 8 characters)" group: "Search the items with specified group" help: "Show this help message" - id: "Specify an id, to use with the options [--delete | --update]" import: "Import item since a yaml file" key: "Specify the key name, to use with the options [--add | --delete | --update]" no_sync: "Disable synchronization with the server" @@ -56,8 +53,6 @@ en: special_chars: "Use special char to generate a password" show: "Search and show the items" show_all: "List all items" - remove: "Delete an item" - update: "Update an item" usage: "Usage" wallet: "Specify a wallet to use" @@ -93,7 +88,6 @@ en: delete_item: ask: "Are you sure you want to remove the item %{id} ?" valid: "The item %{id} has been removed!" - not_valid: "The item %{id} hasn't been removed, because it doesn't exist!" import: ask: "Are you sure you want to import this file %{file} ?" valid: "The import is succesfull!" diff --git a/i18n/fr.yml b/i18n/fr.yml index 41cac4d..b07a9e2 100644 --- a/i18n/fr.yml +++ b/i18n/fr.yml @@ -10,8 +10,6 @@ fr: exception: "La création de la clé GPG n'a pas pu aboutir!" name: "Vous devez définir un nom pour votre clé GPG!" password: "Vous devez définir un mot de passe pour votre clé GPG!" - delete: - id_no_exist: "Impossible de supprimer l'élément %{id}, car il n'existe pas!" export: "Impossible d'exporter les données dans le fichier %{file}!" gpg_file: decrypt: "Impossible de déchiffrer le fichier GPG!" @@ -46,7 +44,6 @@ fr: generate_password: "Génére un mot de passe aléatoire (défaut 8 caractères)" group: "Recherche les éléments appartenant au groupe spécifié" help: "Affiche ce message d'aide" - id: "Spécifie un identifiant, à utiliser avec les options [--delete | --update]" import: "Importe des éléments depuis un fichier yaml" key: "Spécifie le nom d'une clé, à utiliser avec les options [--add | --delete | --update]" no_sync: "Désactive la synchronisation avec le serveur" @@ -56,8 +53,6 @@ fr: special_chars: "Utilise des charactères speciaux dans la génération d'un mot de passe" show: "Recherche et affiche les éléments" show_all: "Liste tous les éléments" - remove: "Supprime un élément" - update: "Met à jour un élément" usage: "Utilisation" wallet: "Spécifie le portefeuille à utiliser" @@ -93,7 +88,6 @@ fr: delete_item: ask: "Êtes vous sûre de vouloir supprimer l'élément %{id} ?" valid: "L'élément %{id} a bien été supprimé!" - not_valid: "L'élément %{id} n'a pu être supprimé, car il n'existe pas!" import: ask: "Êtes vous sûre de vouloir importer le fichier %{file} ?" valid: "L'import est un succès!" diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index 392e7bd..50fad4d 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -21,6 +21,7 @@ require 'i18n' require 'colorize' require 'highline/import' require 'clipboard' +require 'tmpdir' require 'mpw/item' require 'mpw/mpw' @@ -156,7 +157,7 @@ class Cli group = nil i = 1 - result.sort! { |a,b| a.group.downcase <=> b.group.downcase } + result.sort! { |a,b| a.group.to_s.downcase <=> b.group.to_s.downcase } result.each do |item| if group != item.group @@ -263,6 +264,12 @@ class Cli Clipboard.copy(@mpw.get_otp_code(item.id)) puts I18n.t('form.clipboard.otp', time: @mpw.get_otp_remaining_time).yellow + when 'd', 'delete' + delete(item) + + when 'u', 'update', 'e', 'edit' + update(item) + else puts "----- #{I18n.t('form.clipboard.help.name')} -----".cyan puts I18n.t('form.clipboard.help.login') @@ -336,30 +343,41 @@ class Cli puts "#{I18n.t('display.error')} #15: #{e}".red end - # Form to add a new item - def add - options = {} + def text_editor(template_name, item=nil) + options = {} + opts = {} + template_file = "#{File.expand_path('../../../templates', __FILE__)}/#{template_name}.erb" + template = ERB.new(IO.read(template_file)) - puts I18n.t('form.add_item.title') - puts '--------------------' - options[:name] = ask(I18n.t('form.add_item.name')).to_s - options[:group] = ask(I18n.t('form.add_item.group')).to_s - options[:host] = ask(I18n.t('form.add_item.server')).to_s - options[:protocol] = ask(I18n.t('form.add_item.protocol')).to_s - options[:user] = ask(I18n.t('form.add_item.login')).to_s - password = ask(I18n.t('form.add_item.password')).to_s - options[:port] = ask(I18n.t('form.add_item.port')).to_s - options[:comment] = ask(I18n.t('form.add_item.comment')).to_s + Dir.mktmpdir do |dir| + tmp_file = "#{dir}/#{template_name}.yml" - if @otp - otp_key = ask(I18n.t('form.add_item.otp_key')).to_s + File.open(tmp_file, 'w') do |f| + f << template.result(binding) + end + + system("vim #{tmp_file}") + + opts = YAML::load_file(tmp_file) end - item = Item.new(options) + opts.delete_if { |k,v| v.to_s.empty? } + + opts.each do |k,v| + options[k.to_sym] = v + end + + return options + end + + # Form to add a new item + def add + options = text_editor('add_form') + item = Item.new(options) @mpw.add(item) - @mpw.set_password(item.id, password) - @mpw.set_otp_key(item.id, otp_key) + @mpw.set_password(item.id, options[:password]) if options.has_key?(:password) + @mpw.set_otp_key(item.id, options[:otp_key]) if options.has_key?(:otp_key) @mpw.write_data @mpw.sync(true) if @sync @@ -368,39 +386,16 @@ class Cli # Update an item # @args: id -> the item's id - def update(id) - item = @mpw.search_by_id(id) + def update(item) + options = text_editor('update_form', item) - if not item.nil? - options = {} + item.update(options) + @mpw.set_password(item.id, options[:password]) if options.has_key?(:password) + @mpw.set_otp_key(item.id, options[:otp_key]) if options.has_key?(:otp_key) + @mpw.write_data + @mpw.sync(true) if @sync - puts I18n.t('form.update_item.title') - puts '--------------------' - options[:name] = ask(I18n.t('form.update_item.name' , name: item.name)).to_s - options[:group] = ask(I18n.t('form.update_item.group' , group: item.group)).to_s - options[:host] = ask(I18n.t('form.update_item.server' , server: item.host)).to_s - options[:protocol] = ask(I18n.t('form.update_item.protocol', protocol: item.protocol)).to_s - options[:user] = ask(I18n.t('form.update_item.login' , login: item.user)).to_s - password = ask(I18n.t('form.update_item.password')).to_s - options[:port] = ask(I18n.t('form.update_item.port' , port: item.port)).to_s - options[:comment] = ask(I18n.t('form.update_item.comment' , comment: item.comment)).to_s - - if @otp - otp_key = ask(I18n.t('form.update_item.otp_key')).to_s - end - - options.delete_if { |k,v| v.empty? } - - item.update(options) - @mpw.set_password(item.id, password) if not password.empty? - @mpw.set_otp_key(item.id, otp_key) if not otp_key.to_s.empty? - @mpw.write_data - @mpw.sync(true) if @sync - - puts "#{I18n.t('form.update_item.valid')}".green - else - puts I18n.t('display.nothing') - end + puts "#{I18n.t('form.update_item.valid')}".green rescue Exception => e puts "#{I18n.t('display.error')} #14: #{e}".red end @@ -408,29 +403,18 @@ class Cli # Remove an item # @args: id -> the item's id # force -> no resquest a validation - def delete(id, force=false) - @clipboard = false - item = @mpw.search_by_id(id) + def delete(item) + confirm = ask("#{I18n.t('form.delete_item.ask')} (y/N) ").to_s - if item.nil? - puts I18n.t('form.delete_item.not_valid', id: id) + if not confirm =~ /^(y|yes|YES|Yes|Y)$/ return end - if not force - display_item(item) - - confirm = ask("#{I18n.t('form.delete_item.ask', id: id)} (y/N) ").to_s - if not confirm =~ /^(y|yes|YES|Yes|Y)$/ - return - end - end - item.delete @mpw.write_data @mpw.sync(true) if @sync - puts "#{I18n.t('form.delete_item.valid', id: id)}".green + puts "#{I18n.t('form.delete_item.valid')}".green rescue Exception => e puts "#{I18n.t('display.error')} #16: #{e}".red end diff --git a/templates/add_form.erb b/templates/add_form.erb new file mode 100644 index 0000000..9cb9d1a --- /dev/null +++ b/templates/add_form.erb @@ -0,0 +1,10 @@ +--- +name: +group: +host: +protocol: +user: +password: +port: +comment: +otp_secret: diff --git a/templates/update_form.erb b/templates/update_form.erb new file mode 100644 index 0000000..13ce1d6 --- /dev/null +++ b/templates/update_form.erb @@ -0,0 +1,10 @@ +--- +name: <%= item.name %> +group: <%= item.group %> +host: <%= item.host %> +protocol: <%= item.protocol %> +user: <%= item.user %> +password: +port: <%= item.port %> +comment: <%= item.comment %> +otp_secret: From 4b8c87c17f0ecdb0a30b4cda305bde4aa5afbfd3 Mon Sep 17 00:00:00 2001 From: nishiki <nishiki@yaegashi.fr> Date: Tue, 9 Aug 2016 22:34:59 +0200 Subject: [PATCH 309/531] change editor with var EDITOR --- lib/mpw/cli.rb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index 50fad4d..3319168 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -344,6 +344,7 @@ class Cli end def text_editor(template_name, item=nil) + editor = ENV['EDITOR'] || 'nano' options = {} opts = {} template_file = "#{File.expand_path('../../../templates', __FILE__)}/#{template_name}.erb" @@ -356,7 +357,7 @@ class Cli f << template.result(binding) end - system("vim #{tmp_file}") + system("#{editor} #{tmp_file}") opts = YAML::load_file(tmp_file) end @@ -382,6 +383,8 @@ class Cli @mpw.sync(true) if @sync puts "#{I18n.t('form.add_item.valid')}".green + rescue Exception => e + puts "#{I18n.t('display.error')} #13: #{e}".red end # Update an item From 166d1f141accf93ff810011dfdba2e03e617a7dc Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Sat, 20 Aug 2016 09:18:32 +0200 Subject: [PATCH 310/531] fix translate for add template --- i18n/en.yml | 19 +++++++++---------- i18n/fr.yml | 19 +++++++++---------- templates/add_form.erb | 18 +++++++++--------- 3 files changed, 27 insertions(+), 29 deletions(-) diff --git a/i18n/en.yml b/i18n/en.yml index 52fbf67..f226203 100644 --- a/i18n/en.yml +++ b/i18n/en.yml @@ -61,16 +61,15 @@ en: add_key: valid: "Key has been added!" add_item: - title: "Add a new item" - name: "Enter the name: " - group: "Enter the group (optional): " - server: "Enter the hostname or ip: " - protocol: "Enter the protocol of the connection (ssh, http, other): " - login: "Enter the login connection: " - password: "Enter the the password: " - port: "Enter the connection port (optional): " - comment: "Enter a comment (optional): " - otp_key: "Enter the otp secret (base32 secret key): " + name: "The item's name (mandatory" + group: "The group's name" + host: "The hostname or ip" + protocol: "The protocol of the connection (ssh, http, ...)" + login: "The login of connection" + password: "The password" + port: "The connection port" + comment: "A comment" + otp_key: "The OTP secret" valid: "Item has been added!" clipboard: choice: "What do you want to copy ? [q = quit, p = password, l = login]: " diff --git a/i18n/fr.yml b/i18n/fr.yml index b07a9e2..54da62b 100644 --- a/i18n/fr.yml +++ b/i18n/fr.yml @@ -61,16 +61,15 @@ fr: add_key: valid: "La clé a bien été ajoutée!" add_item: - title: "Ajout d'un nouvel élément" - name: "Entrez le nom: " - group: "Entrez le groupe (optionnel): " - server: "Entrez le nom de domaine ou l'ip: " - protocol: "Entrez le protocole de connexion (ssh, http, other): " - login: "Entrez l'identifiant de connexion: " - password: "Entrez le mot de passe: " - port: "Entrez le port de connexion (optionnel): " - comment: "Entrez un commentaire (optionnel): " - otp_key: "Entrez le secret OTP: " + name: "Le nom de l'élément (obligatoire)" + group: "Le nom du groupe" + host: "Le nom de domaine ou l'ip" + protocol: "Le protocole de connexion (ssh, http, ...)" + login: "L'identifiant de connexion" + password: "Le mot de passe" + port: "Le port de connexion" + comment: "Un commentaire" + otp_key: "Le secret OTP" valid: "L'élément a bien été ajouté!" clipboard: choice: "Que voulez-vous copier ? : " diff --git a/templates/add_form.erb b/templates/add_form.erb index 9cb9d1a..53c0333 100644 --- a/templates/add_form.erb +++ b/templates/add_form.erb @@ -1,10 +1,10 @@ --- -name: -group: -host: -protocol: -user: -password: -port: -comment: -otp_secret: +name: # <%= I18n.t('form.add_item.name') %> +group: # <%= I18n.t('form.add_item.group') %> +host: # <%= I18n.t('form.add_item.host') %> +protocol: # <%= I18n.t('form.add_item.protocol') %> +user: # <%= I18n.t('form.add_item.login') %> +password: # <%= I18n.t('form.add_item.password') %> +port: # <%= I18n.t('form.add_item.port') %> +comment: # <%= I18n.t('form.add_item.comment') %> +otp_secret: # <%= I18n.t('form.add_item.otp_key') %> From 2a89d8718c7a0add94503d16f6a01ad1f86830ac Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Sat, 20 Aug 2016 09:19:02 +0200 Subject: [PATCH 311/531] add missing gem net-sftp --- mpw.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mpw.gemspec b/mpw.gemspec index fa4afc7..09fe6d9 100644 --- a/mpw.gemspec +++ b/mpw.gemspec @@ -23,7 +23,7 @@ Gem::Specification.new do |spec| spec.add_dependency "locale" spec.add_dependency "colorize" spec.add_dependency "net-ssh" - spec.add_dependency "net-scp" + spec.add_dependency "net-sftp" spec.add_dependency "clipboard" spec.add_dependency "rotp" end From 973f36248580b9485291da1468fb1361de461414 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Sat, 20 Aug 2016 10:03:12 +0200 Subject: [PATCH 312/531] fix translate for update template --- i18n/en.yml | 19 +++++++++---------- i18n/fr.yml | 19 +++++++++---------- templates/update_form.erb | 13 +++++++++++-- 3 files changed, 29 insertions(+), 22 deletions(-) diff --git a/i18n/en.yml b/i18n/en.yml index f226203..c9b26eb 100644 --- a/i18n/en.yml +++ b/i18n/en.yml @@ -120,16 +120,15 @@ en: wait: "Please waiting during the GPG key generate, this process can take few minutes." valid: "Your GPG key has been created ;-)" update_item: - title: "Update an item" - name: "Enter the name [%{name}]: " - group: "Enter the group [%{group}]: " - server: "Enter the hostname or ip [%{server}]: " - protocol: "Enter the protocol of the connection [%{protocol}]: " - login: "Enter the login connection [%{login}]: " - password: "Enter the the password: " - port: "Enter the connection port [%{port}]: " - comment: "Enter a comment [%{comment}]: " - otp_key: "Enter the otp secret (base32 secret key): " + name: "The item's name (mandatory" + group: "The group's name" + host: "The hostname or ip" + protocol: "The protocol of the connection (ssh, http, ...)" + login: "The login of connection" + password: "The password (leave empty if you don't want change)" + port: "The connection port" + comment: "A comment" + otp_key: "The OTP secret (leave empty if you don't want change" valid: "Item has been updated!" export: valid: "The export in %{file} is succesfull!" diff --git a/i18n/fr.yml b/i18n/fr.yml index 54da62b..5715fe2 100644 --- a/i18n/fr.yml +++ b/i18n/fr.yml @@ -120,16 +120,15 @@ fr: wait: "Veuillez patienter durant la génération de votre clé GPG, ce processus peut prendre quelques minutes." valid: "Votre clé GPG a bien été créée ;-)" update_item: - title: "Mis à jour d'un élément" - name: "Entrez le nom [%{name}]: " - group: "Entrez le groupe [%{group}]: " - server: "Entrez le nom de domaine ou l'ip du serveur [%{server}]: " - protocol: "Entrez le protocole de connexion [%{protocol}]: " - login: "Entrez votre identifiant de connexion [%{login}]: " - password: "Entrez le mot de passe: " - port: "Entrez un port de connexion [%{port}]: " - comment: "Entrez un commentaire [%{comment}]: " - otp_key: "Entrez le secret OTP: " + name: "Le nom de l'élément (obligatoire)" + group: "Le nom du groupe" + host: "Le nom de domaine ou l'ip" + protocol: "Le protocole de connexion (ssh, http, ...)" + login: "L'identifiant de connexion" + password: "Le mot de passe (laissez vide si vous ne voulez pas le changer)" + port: "Le port de connexion" + comment: "Un commentaire" + otp_key: "Le secret OTP (laissez vide si vous ne voulez pas le changer)" valid: "L'élément a bien été mis à jour!" export: valid: "L'export dans %{file} est un succès!" diff --git a/templates/update_form.erb b/templates/update_form.erb index 13ce1d6..57178cc 100644 --- a/templates/update_form.erb +++ b/templates/update_form.erb @@ -1,10 +1,19 @@ --- -name: <%= item.name %> +# <%= I18n.t('form.update_item.name') %> +name: <%= item.name %> +# <%= I18n.t('form.update_item.group') %> group: <%= item.group %> +# <%= I18n.t('form.update_item.host') %> host: <%= item.host %> +# <%= I18n.t('form.update_item.protocol') %> protocol: <%= item.protocol %> +# <%= I18n.t('form.update_item.login') %> user: <%= item.user %> +# <%= I18n.t('form.update_item.password') %> password: +# <%= I18n.t('form.update_item.port') %> port: <%= item.port %> +# <%= I18n.t('form.update_item.comment') %> comment: <%= item.comment %> -otp_secret: +# <%= I18n.t('form.update_item.otp_key') %> +opt_code: From 126b896c24a80e452751b230eb360f90c4301246 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Sat, 20 Aug 2016 16:09:34 +0200 Subject: [PATCH 313/531] add otp_key for import and export --- lib/mpw/mpw.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index baa83f5..6c3fc00 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -287,6 +287,7 @@ class MPW 'password' => get_password(item.id), 'port' => item.port, 'comment' => item.comment, + 'otp_key' => get_otp_code(item.id), 'last_edit' => item.last_edit, 'created' => item.created, } @@ -314,7 +315,8 @@ class MPW raise 'Item is empty' if item.empty? @data.push(item) - set_password(item.id, row['password']) + set_password(item.id, row['password']) if not row['password'].to_s.empty? + set_otp_code(item.id, row['otp_key']) if not row['otp_key'].to_s.empty? end rescue Exception => e raise "#{I18n.t('error.import', file: file)}\n#{e}" @@ -435,7 +437,7 @@ class MPW # Get an otp code # @args: id -> the item id # @rtrn: an otp code - def get_otp_code(id) + def get_otp_code(id) if not @otp_keys.has_key?(id) return 0 else From dd9f2853ce330375a923f0b0daaac9aac84dc690 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Mon, 26 Sep 2016 21:53:17 +0200 Subject: [PATCH 314/531] fix translate --- i18n/en.yml | 6 ++++-- i18n/fr.yml | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/i18n/en.yml b/i18n/en.yml index c9b26eb..7c7bcc5 100644 --- a/i18n/en.yml +++ b/i18n/en.yml @@ -82,11 +82,13 @@ en: login: "Press <l> to copy the login" password: "Press <p> to copy the password" otp_code: "Press <o> to copy the otp code" + update: "Press <u> to update the item" + delete: "Press <d> to delete the item" delete_key: valid: "Key has been deleted!" delete_item: - ask: "Are you sure you want to remove the item %{id} ?" - valid: "The item %{id} has been removed!" + ask: "Are you sure you want to remove the item ?" + valid: "The item has been removed!" import: ask: "Are you sure you want to import this file %{file} ?" valid: "The import is succesfull!" diff --git a/i18n/fr.yml b/i18n/fr.yml index 5715fe2..a5d7aff 100644 --- a/i18n/fr.yml +++ b/i18n/fr.yml @@ -82,11 +82,13 @@ fr: login: "Pressez <l> pour copier l'identifiant" password: "Pressez <p> pour copier le mot de passe" otp_code: "Pressez <o> pour copier le code OTP" + update: "Pressez <u> pour mettre à jour l'élément" + delete: "Pressez <d> pour supprimer l'élément" delete_key: valid: "La clé a bien été supprimée!" delete_item: - ask: "Êtes vous sûre de vouloir supprimer l'élément %{id} ?" - valid: "L'élément %{id} a bien été supprimé!" + ask: "Êtes vous sûre de vouloir supprimer l'élément ?" + valid: "L'élément a bien été supprimé!" import: ask: "Êtes vous sûre de vouloir importer le fichier %{file} ?" valid: "L'import est un succès!" From e7956b20068ff503cd6eddc0eece7b0d65efebeb Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Mon, 26 Sep 2016 21:55:38 +0200 Subject: [PATCH 315/531] new setup form --- lib/mpw/cli.rb | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index 3319168..337b95e 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -41,21 +41,16 @@ class Cli end # Create a new config file - # @args: lang -> the software language - def setup(lang) - puts I18n.t('form.setup_config.title') - puts '--------------------' - language = ask(I18n.t('form.setup_config.lang', lang: lang)).to_s - key = ask(I18n.t('form.setup_config.gpg_key')).to_s - wallet_dir = ask(I18n.t('form.setup_config.wallet_dir', home: "#{@config.config_dir}")).to_s - gpg_exe = ask(I18n.t('form.setup_config.gpg_exe')).to_s + # @args: language -> the software language + def setup(language) + @config.is_valid? + + options = text_editor('setup_form', language) + language = options[:language] || language - if language.nil? or language.empty? - language = lang - end I18n.locale = language.to_sym - @config.setup(key, lang, wallet_dir, gpg_exe) + @config.setup(options[:gpg_key], language, options[:wallet_dir], options[:gpg_exe]) raise I18n.t('error.config.check') if not @config.is_valid? From a8a083250b2d0fa00e4b6635249738373b0d215e Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Mon, 26 Sep 2016 21:56:00 +0200 Subject: [PATCH 316/531] quit if delete item --- lib/mpw/cli.rb | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index 337b95e..cb061c7 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -260,7 +260,7 @@ class Cli puts I18n.t('form.clipboard.otp', time: @mpw.get_otp_remaining_time).yellow when 'd', 'delete' - delete(item) + break if delete(item) when 'u', 'update', 'e', 'edit' update(item) @@ -270,6 +270,8 @@ class Cli puts I18n.t('form.clipboard.help.login') puts I18n.t('form.clipboard.help.password') puts I18n.t('form.clipboard.help.otp_code') + puts I18n.t('form.clipboard.help.update') + puts I18n.t('form.clipboard.help.delete') next end end @@ -405,7 +407,7 @@ class Cli confirm = ask("#{I18n.t('form.delete_item.ask')} (y/N) ").to_s if not confirm =~ /^(y|yes|YES|Yes|Y)$/ - return + return false end item.delete @@ -413,8 +415,11 @@ class Cli @mpw.sync(true) if @sync puts "#{I18n.t('form.delete_item.valid')}".green + + return true rescue Exception => e puts "#{I18n.t('display.error')} #16: #{e}".red + return false end # Export the items in a CSV file From 4b36fa9081733cfe36b285e3929d8d5727166a20 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Mon, 26 Sep 2016 22:13:11 +0200 Subject: [PATCH 317/531] add template setup form --- templates/setup_form.erb | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 templates/setup_form.erb diff --git a/templates/setup_form.erb b/templates/setup_form.erb new file mode 100644 index 0000000..f7e6d7b --- /dev/null +++ b/templates/setup_form.erb @@ -0,0 +1,9 @@ +--- +# <%= I18n.t('form.setup_config.lang') %> +language: <%= @config.lang %> +# <%= I18n.t('form.setup_config.gpg_key') %> +gpg_key: <%= @config.key %> +# <%= I18n.t('form.setup_config.wallet_dir') %> +wallet_dir: <%= @config.config_dir %> +# <%= I18n.t('form.setup_config.gpg_exe') %> +gpg_exe: <%= @config.gpg_exe %> From d8ac5ed35a0723c35ab40019030f9081c8ca5db4 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Wed, 12 Oct 2016 23:23:03 +0200 Subject: [PATCH 318/531] first cut binary --- bin/mpw | 173 +-------------------------------------- bin/mpw-old | 214 +++++++++++++++++++++++++++++++++++++++++++++++++ bin/mpw-passwd | 50 ++++++++++++ 3 files changed, 268 insertions(+), 169 deletions(-) create mode 100755 bin/mpw-old create mode 100644 bin/mpw-passwd diff --git a/bin/mpw b/bin/mpw index 5f0d64d..2d32700 100755 --- a/bin/mpw +++ b/bin/mpw @@ -18,13 +18,9 @@ $: << File.expand_path('../../lib', __FILE__) -require 'optparse' require 'locale' require 'set' require 'i18n' -require 'mpw/mpw' -require 'mpw/config' -require 'mpw/cli' # --------------------------------------------------------- # # Set local @@ -45,170 +41,9 @@ I18n.locale = lang.to_sym # Options # --------------------------------------------------------- # -options_password = {} -options = {} -options[:force] = false -options[:otp] = false -options[:sync] = true -options[:clipboard] = true -options[:group] = nil -options[:config] = nil -options[:wallet] = nil +bin_dir = File.dirname(__FILE__) +command = "#{bin_dir}/mpw-#{ARGV[0]}" -OptionParser.new do |opts| - opts.banner = "#{I18n.t('option.usage')}: mpw [options]" - - opts.on('-a', '--add', I18n.t('option.add')) do - options[:add] = true - end - - opts.on('-A', '--show-all', I18n.t('option.show_all')) do - options[:type] = nil - options[:show] = '' - end - - opts.on('-c', '--config CONFIG', I18n.t('option.config')) do |config| - options[:config] = config - end - - opts.on('-C', '--no-clipboard', I18n.t('option.clipboard')) do - options[:clipboard] = false - end - - opts.on('-e', '--export', I18n.t('option.export')) do - options[:export] = true - end - - opts.on('-f', '--file FILE', I18n.t('option.file')) do |file| - options[:file] = file - end - - opts.on('-F', '--force', I18n.t('option.force')) do - options[:force] = true - end - - opts.on('-g', '--group GROUP', I18n.t('option.group')) do |group| - options[:group] = group - end - - opts.on('-G', '--generate-password [LENGTH]', I18n.t('option.generate_password')) do |length| - options_password[:length] = length - end - - opts.on('-h', '--help', I18n.t('option.help')) do - puts opts - exit 0 - end - - opts.on('-I', '--import', I18n.t('option.import')) do - options[:import] = true - end - - opts.on('-k', '--key KEY', I18n.t('option.key')) do |key| - options[:key] = key - end - - opts.on('-n', '--numeric', I18n.t('option.numeric')) do - options_password[:numeric] = true - end - - opts.on('-N', '--no-sync', I18n.t('option.no_sync')) do - options[:sync] = false - end - - opts.on('-O', '--otp', I18n.t('option.otp')) do - options[:otp] = true - end - - opts.on('-s', '--show [SEARCH]', I18n.t('option.show')) do |search| - search.nil? ? (options[:show] = '') : (options[:show] = search) - end - - opts.on('-S', '--setup', I18n.t('option.setup')) do - options[:setup] = true - end - - opts.on('-w', '--wallet WALLET', I18n.t('option.wallet')) do |wallet| - options[:wallet] = wallet - end - - opts.on('-W', '--setup-wallet', I18n.t('option.setup_wallet')) do - options[:setup_wallet] = true - end - - opts.on('-x', '--special-chars', I18n.t('option.special_chars')) do - options_password[:special] = true - end - - opts.on('-y', '--alpha', I18n.t('option.alpha')) do - options_password[:alpha] = true - end -end.parse! - -# --------------------------------------------------------- # -# Main -# --------------------------------------------------------- # - -# Generate password -if not options_password.empty? - puts MPW::MPW::password(options_password) - exit 0 -end - -begin - config = MPW::Config.new(options[:config]) - cli = MPW::Cli.new(config, options[:clipboard], options[:sync], options[:otp]) - - # Setup a new config - if not options[:setup].nil? - cli.setup(lang) - exit 0 - end - - cli.setup(lang) if not config.is_valid? - cli.setup_gpg_key if not config.check_gpg_key? - - cli.get_wallet(options[:wallet]) - cli.decrypt - - # Display the item's informations - if not options[:show].nil? - opts = {search: options[:show], - group: options[:group], - } - - cli.display(opts) - - # Add a new item - elsif not options[:add].nil? and options[:key].nil? - cli.add - - # Add a new public key in wallet - elsif not options[:add].nil? and not options[:key].nil? - cli.add_key(options[:key], options[:file]) - - # Delete a public key in wallet - elsif not options[:delete].nil? and not options[:key].nil? - cli.delete_key(options[:key]) - - # Export - elsif not options[:export].nil? and not options[:file].nil? - cli.export(options[:file]) - - # Import - elsif not options[:import].nil? and not options[:file].nil? - cli.import(options[:file]) - - # Setup wallet config - elsif not options[:setup_wallet].nil? - cli.setup_wallet_config - - end - - cli = nil - - exit 0 - -rescue SystemExit, Interrupt - exit 3 +if Dir.glob("#{bin_dir}/mpw-*").include?("#{command}") + Kernel.load(command) end diff --git a/bin/mpw-old b/bin/mpw-old new file mode 100755 index 0000000..5f0d64d --- /dev/null +++ b/bin/mpw-old @@ -0,0 +1,214 @@ +#!/usr/bin/ruby +# MPW is a software to crypt and manage your passwords +# Copyright (C) 2016 Adrien Waksberg <mpw@yae.im> +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +$: << File.expand_path('../../lib', __FILE__) + +require 'optparse' +require 'locale' +require 'set' +require 'i18n' +require 'mpw/mpw' +require 'mpw/config' +require 'mpw/cli' + +# --------------------------------------------------------- # +# Set local +# --------------------------------------------------------- # + +lang = Locale::Tag.parse(ENV['LANG']).to_simple.to_s[0..1] + +if defined?(I18n.enforce_available_locales) + I18n.enforce_available_locales = true +end + +I18n::Backend::Simple.send(:include, I18n::Backend::Fallbacks) +I18n.load_path = Dir["#{File.expand_path('../../i18n', __FILE__)}/*.yml"] +I18n.default_locale = :en +I18n.locale = lang.to_sym + +# --------------------------------------------------------- # +# Options +# --------------------------------------------------------- # + +options_password = {} +options = {} +options[:force] = false +options[:otp] = false +options[:sync] = true +options[:clipboard] = true +options[:group] = nil +options[:config] = nil +options[:wallet] = nil + +OptionParser.new do |opts| + opts.banner = "#{I18n.t('option.usage')}: mpw [options]" + + opts.on('-a', '--add', I18n.t('option.add')) do + options[:add] = true + end + + opts.on('-A', '--show-all', I18n.t('option.show_all')) do + options[:type] = nil + options[:show] = '' + end + + opts.on('-c', '--config CONFIG', I18n.t('option.config')) do |config| + options[:config] = config + end + + opts.on('-C', '--no-clipboard', I18n.t('option.clipboard')) do + options[:clipboard] = false + end + + opts.on('-e', '--export', I18n.t('option.export')) do + options[:export] = true + end + + opts.on('-f', '--file FILE', I18n.t('option.file')) do |file| + options[:file] = file + end + + opts.on('-F', '--force', I18n.t('option.force')) do + options[:force] = true + end + + opts.on('-g', '--group GROUP', I18n.t('option.group')) do |group| + options[:group] = group + end + + opts.on('-G', '--generate-password [LENGTH]', I18n.t('option.generate_password')) do |length| + options_password[:length] = length + end + + opts.on('-h', '--help', I18n.t('option.help')) do + puts opts + exit 0 + end + + opts.on('-I', '--import', I18n.t('option.import')) do + options[:import] = true + end + + opts.on('-k', '--key KEY', I18n.t('option.key')) do |key| + options[:key] = key + end + + opts.on('-n', '--numeric', I18n.t('option.numeric')) do + options_password[:numeric] = true + end + + opts.on('-N', '--no-sync', I18n.t('option.no_sync')) do + options[:sync] = false + end + + opts.on('-O', '--otp', I18n.t('option.otp')) do + options[:otp] = true + end + + opts.on('-s', '--show [SEARCH]', I18n.t('option.show')) do |search| + search.nil? ? (options[:show] = '') : (options[:show] = search) + end + + opts.on('-S', '--setup', I18n.t('option.setup')) do + options[:setup] = true + end + + opts.on('-w', '--wallet WALLET', I18n.t('option.wallet')) do |wallet| + options[:wallet] = wallet + end + + opts.on('-W', '--setup-wallet', I18n.t('option.setup_wallet')) do + options[:setup_wallet] = true + end + + opts.on('-x', '--special-chars', I18n.t('option.special_chars')) do + options_password[:special] = true + end + + opts.on('-y', '--alpha', I18n.t('option.alpha')) do + options_password[:alpha] = true + end +end.parse! + +# --------------------------------------------------------- # +# Main +# --------------------------------------------------------- # + +# Generate password +if not options_password.empty? + puts MPW::MPW::password(options_password) + exit 0 +end + +begin + config = MPW::Config.new(options[:config]) + cli = MPW::Cli.new(config, options[:clipboard], options[:sync], options[:otp]) + + # Setup a new config + if not options[:setup].nil? + cli.setup(lang) + exit 0 + end + + cli.setup(lang) if not config.is_valid? + cli.setup_gpg_key if not config.check_gpg_key? + + cli.get_wallet(options[:wallet]) + cli.decrypt + + # Display the item's informations + if not options[:show].nil? + opts = {search: options[:show], + group: options[:group], + } + + cli.display(opts) + + # Add a new item + elsif not options[:add].nil? and options[:key].nil? + cli.add + + # Add a new public key in wallet + elsif not options[:add].nil? and not options[:key].nil? + cli.add_key(options[:key], options[:file]) + + # Delete a public key in wallet + elsif not options[:delete].nil? and not options[:key].nil? + cli.delete_key(options[:key]) + + # Export + elsif not options[:export].nil? and not options[:file].nil? + cli.export(options[:file]) + + # Import + elsif not options[:import].nil? and not options[:file].nil? + cli.import(options[:file]) + + # Setup wallet config + elsif not options[:setup_wallet].nil? + cli.setup_wallet_config + + end + + cli = nil + + exit 0 + +rescue SystemExit, Interrupt + exit 3 +end diff --git a/bin/mpw-passwd b/bin/mpw-passwd new file mode 100644 index 0000000..c99d002 --- /dev/null +++ b/bin/mpw-passwd @@ -0,0 +1,50 @@ +#!/usr/bin/ruby +# MPW is a software to crypt and manage your passwords +# Copyright (C) 2016 Adrien Waksberg <mpw@yae.im> +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +require 'optparse' +require 'mpw/mpw' + +options = {} + +OptionParser.new do |opts| + opts.banner = "#{I18n.t('option.usage')}: mpw-passwd [options]" + + opts.on('-h', '--help', I18n.t('option.help')) do + puts opts + exit 0 + end + + opts.on('-l', '--length NUMBER', I18n.t('option.length')) do |length| + options[:length] = length.to_i + end + + opts.on('-n', '--numeric', I18n.t('option.numeric')) do + options[:numeric] = true + end + + opts.on('-s', '--special-chars', I18n.t('option.special_chars')) do + options[:special] = true + end + + opts.on('-a', '--alpha', I18n.t('option.alpha')) do + options[:alpha] = true + end +end.parse! + +puts MPW::MPW::password(options) +exit 0 From 4085d43f973d7b48d3c5480ed5878c32c3dd1746 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Thu, 13 Oct 2016 18:26:56 +0200 Subject: [PATCH 319/531] rename mpw-passwd to mpw-genpwd --- bin/{mpw-passwd => mpw-genpwd} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename bin/{mpw-passwd => mpw-genpwd} (100%) diff --git a/bin/mpw-passwd b/bin/mpw-genpwd similarity index 100% rename from bin/mpw-passwd rename to bin/mpw-genpwd From 3d99ac80deb10dcd836f0a9c3c3b1bc35c8a8d46 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Thu, 13 Oct 2016 21:59:51 +0200 Subject: [PATCH 320/531] new binary for config --- bin/mpw-config | 91 +++++++++++++++++++++++++++++++++++++++++++++++ lib/mpw/cli.rb | 44 ++++++++++++----------- lib/mpw/config.rb | 3 +- 3 files changed, 116 insertions(+), 22 deletions(-) create mode 100644 bin/mpw-config diff --git a/bin/mpw-config b/bin/mpw-config new file mode 100644 index 0000000..ebde9e2 --- /dev/null +++ b/bin/mpw-config @@ -0,0 +1,91 @@ +#!/usr/bin/ruby +# MPW is a software to crypt and manage your passwords +# Copyright (C) 2016 Adrien Waksberg <mpw@yae.im> +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +$: << File.expand_path('../../lib', __FILE__) + +require 'optparse' +require 'locale' +require 'set' +require 'i18n' +require 'mpw/config' +require 'mpw/cli' + +# --------------------------------------------------------- # +# Set local +# --------------------------------------------------------- # + +lang = Locale::Tag.parse(ENV['LANG']).to_simple.to_s[0..1] + +if defined?(I18n.enforce_available_locales) + I18n.enforce_available_locales = true +end + +I18n::Backend::Simple.send(:include, I18n::Backend::Fallbacks) +I18n.load_path = Dir["#{File.expand_path('../../i18n', __FILE__)}/*.yml"] +I18n.default_locale = :en +I18n.locale = lang.to_sym + +# --------------------------------------------------------- # +# Options +# --------------------------------------------------------- # + +options = {} + +OptionParser.new do |opts| + opts.banner = "#{I18n.t('option.usage')}: mpw [options]" + + opts.on('-c', '--config CONFIG', I18n.t('option.config')) do |config| + options[:config] = config + end + + opts.on('-g', '--gpg-exe PATH', I18n.t('option.lang')) do |gpg_exe| + options[:gpg_exe] = gpg_exe + end + + opts.on('-h', '--help', I18n.t('option.help')) do + puts opts + exit 0 + end + + opts.on('--init', I18n.t('option.init')) do + options[:init] = true + end + + opts.on('-k', '--key GPG_KEY', I18n.t('option.lang')) do |gpg_key| + options[:gpg_key] = gpg_key + end + + opts.on('-l', '--lang LANG', I18n.t('option.lang')) do |lang| + options[:lang] = lang + end + + opts.on('-w', '--wallet-dir LANG', I18n.t('option.lang')) do |wallet_dir| + options[:wallet_dir] = wallet_dir + end +end.parse! + +config = MPW::Config.new(options[:config]) +cli = MPW::Cli.new(config, options[:clipboard], options[:sync], options[:otp]) + +if not options[:init].nil? + cli.setup(options) + cli.setup_gpg_key(options[:gpg_key]) if not config.check_gpg_key? + exit 0 +end + +cli.set_config(options) diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index cb061c7..0547ac4 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -17,6 +17,7 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. require 'readline' +require 'locale' require 'i18n' require 'colorize' require 'highline/import' @@ -40,17 +41,32 @@ class Cli @otp = otp end + # Change a parameter int the config after init + # @args: options -> param to change + def set_config(options) + raise I18n.t('error.config.check') if not @config.is_valid? + + gpg_key = options[:gpg_key] || @config.key + lang = options[:lang] || @config.lang + wallet_dir = options[:wallet_dir] || @config.wallet_dir + gpg_exe = options[:gpg_exe] || @config.gpg_exe + + @config.setup(gpg_key, lang, wallet_dir, gpg_exe) + rescue Exception => e + puts "#{I18n.t('display.error')} #15: #{e}".red + exit 2 + end + # Create a new config file # @args: language -> the software language - def setup(language) + def setup(options) @config.is_valid? - options = text_editor('setup_form', language) - language = options[:language] || language + lang = options[:lang] || Locale::Tag.parse(ENV['LANG']).to_simple.to_s[0..1] - I18n.locale = language.to_sym + I18n.locale = lang.to_sym - @config.setup(options[:gpg_key], language, options[:wallet_dir], options[:gpg_exe]) + @config.setup(options[:gpg_key], lang, options[:wallet_dir], options[:gpg_exe]) raise I18n.t('error.config.check') if not @config.is_valid? @@ -61,16 +77,11 @@ class Cli end # Setup a new GPG key - def setup_gpg_key + # @args: gpg_key -> the key name + def setup_gpg_key(gpg_key) puts I18n.t('form.setup_gpg_key.title') puts '--------------------' ask = ask(I18n.t('form.setup_gpg_key.ask')).to_s - - if not ['Y', 'y', 'O', 'o'].include?(ask) - raise I18n.t('form.setup_gpg_key.no_create') - end - - name = ask(I18n.t('form.setup_gpg_key.name')).to_s password = ask(I18n.t('form.setup_gpg_key.password')) {|q| q.echo = false} confirm = ask(I18n.t('form.setup_gpg_key.confirm_password')) {|q| q.echo = false} @@ -78,16 +89,9 @@ class Cli raise I18n.t('form.setup_gpg_key.error_password') end - length = ask(I18n.t('form.setup_gpg_key.length')).to_s - expire = ask(I18n.t('form.setup_gpg_key.expire')).to_s - password = password.to_s - - length = length.nil? or length.empty? ? 2048 : length.to_i - expire = expire.nil? or expire.empty? ? 0 : expire.to_i - puts I18n.t('form.setup_gpg_key.wait') - @config.setup_gpg_key(password, name, length, expire) + @config.setup_gpg_key(password.to_s, gpg_key) puts "#{I18n.t('form.setup_gpg_key.valid')}".green rescue Exception => e diff --git a/lib/mpw/config.rb b/lib/mpw/config.rb index 90df409..b504c2a 100644 --- a/lib/mpw/config.rb +++ b/lib/mpw/config.rb @@ -57,12 +57,11 @@ class Config # gpg_exe -> the path of gpg executable # @rtrn: true if le config file is create def setup(key, lang, wallet_dir, gpg_exe) - if not key =~ /[a-zA-Z0-9.-_]+\@[a-zA-Z0-9]+\.[a-zA-Z]+/ raise I18n.t('error.config.key_bad_format') end - if wallet_dir.empty? + if wallet_dir.to_s.empty? wallet_dir = "#{@config_dir}/wallets" end From 422dacd29d805ec397c877933c3c34c65e99cb8e Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Fri, 14 Oct 2016 18:43:19 +0200 Subject: [PATCH 321/531] remove unused code --- bin/mpw-config | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/bin/mpw-config b/bin/mpw-config index ebde9e2..41223c6 100644 --- a/bin/mpw-config +++ b/bin/mpw-config @@ -16,30 +16,10 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -$: << File.expand_path('../../lib', __FILE__) - require 'optparse' -require 'locale' -require 'set' -require 'i18n' require 'mpw/config' require 'mpw/cli' -# --------------------------------------------------------- # -# Set local -# --------------------------------------------------------- # - -lang = Locale::Tag.parse(ENV['LANG']).to_simple.to_s[0..1] - -if defined?(I18n.enforce_available_locales) - I18n.enforce_available_locales = true -end - -I18n::Backend::Simple.send(:include, I18n::Backend::Fallbacks) -I18n.load_path = Dir["#{File.expand_path('../../i18n', __FILE__)}/*.yml"] -I18n.default_locale = :en -I18n.locale = lang.to_sym - # --------------------------------------------------------- # # Options # --------------------------------------------------------- # From 3fd70721f339b64ef97b5e6a9c9e18436e220c91 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Fri, 14 Oct 2016 21:48:23 +0200 Subject: [PATCH 322/531] new binary for add --- bin/mpw-add | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 bin/mpw-add diff --git a/bin/mpw-add b/bin/mpw-add new file mode 100644 index 0000000..d959c19 --- /dev/null +++ b/bin/mpw-add @@ -0,0 +1,48 @@ +#!/usr/bin/ruby +# MPW is a software to crypt and manage your passwords +# Copyright (C) 2016 Adrien Waksberg <mpw@yae.im> +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +require 'optparse' +require 'mpw/config' +require 'mpw/cli' + +# --------------------------------------------------------- # +# Options +# --------------------------------------------------------- # + +options = {} + +OptionParser.new do |opts| + opts.banner = "#{I18n.t('option.usage')}: mpw [options]" + + opts.on('-c', '--config CONFIG', I18n.t('option.config')) do |config| + options[:config] = config + end + + opts.on('-h', '--help', I18n.t('option.help')) do + puts opts + exit 0 + end + + opts.on('-w', '--wallet WALLET', I18n.t('option.wallet')) do |wallet| + options[:wallet] = wallet + end +end.parse! + +config = MPW::Config.new(options[:config]) +cli = MPW::Cli.new(config, nil, options[:sync], nil) +cli.add From e45c528a3fd8a0b0c279885776e57dbf7c2e57ca Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Fri, 14 Oct 2016 23:20:55 +0200 Subject: [PATCH 323/531] init: iniatilize a default wallet --- bin/mpw-config | 3 ++- lib/mpw/cli.rb | 38 ++++++++++++++++++++++---------------- lib/mpw/mpw.rb | 9 ++++++--- 3 files changed, 30 insertions(+), 20 deletions(-) diff --git a/bin/mpw-config b/bin/mpw-config index 41223c6..d29a93c 100644 --- a/bin/mpw-config +++ b/bin/mpw-config @@ -60,11 +60,12 @@ OptionParser.new do |opts| end.parse! config = MPW::Config.new(options[:config]) -cli = MPW::Cli.new(config, options[:clipboard], options[:sync], options[:otp]) +cli = MPW::Cli.new(config, nil, nil, nil) if not options[:init].nil? cli.setup(options) cli.setup_gpg_key(options[:gpg_key]) if not config.check_gpg_key? + cli.setup_wallet_config exit 0 end diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index 0547ac4..2f9ad31 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -89,9 +89,11 @@ class Cli raise I18n.t('form.setup_gpg_key.error_password') end + @password = password.to_s + puts I18n.t('form.setup_gpg_key.wait') - @config.setup_gpg_key(password.to_s, gpg_key) + @config.setup_gpg_key(@password, gpg_key) puts "#{I18n.t('form.setup_gpg_key.valid')}".green rescue Exception => e @@ -100,23 +102,27 @@ class Cli end # Setup wallet config for sync - def setup_wallet_config - config = {} - config['sync'] = {} + # @args: wallet -> the wallet name + def setup_wallet_config(wallet = nil) + #config = {} + #config['sync'] = {} - puts I18n.t('form.setup_wallet.title') - puts '--------------------' - config['sync']['type'] = ask(I18n.t('form.setup_wallet.sync_type')).to_s + #puts '--------------------' + #config['sync']['type'] = ask(I18n.t('form.setup_wallet.sync_type')).to_s - if ['ftp', 'ssh'].include?(config['sync']['type'].downcase) - config['sync']['host'] = ask(I18n.t('form.setup_wallet.sync_host')).to_s - config['sync']['port'] = ask(I18n.t('form.setup_wallet.sync_port')).to_s - config['sync']['user'] = ask(I18n.t('form.setup_wallet.sync_user')).to_s - config['sync']['password'] = ask(I18n.t('form.setup_wallet.sync_pwd')).to_s - config['sync']['path'] = ask(I18n.t('form.setup_wallet.sync_path')).to_s - end + #if ['ftp', 'ssh'].include?(config['sync']['type'].downcase) + # config['sync']['host'] = ask(I18n.t('form.setup_wallet.sync_host')).to_s + # config['sync']['port'] = ask(I18n.t('form.setup_wallet.sync_port')).to_s + # config['sync']['user'] = ask(I18n.t('form.setup_wallet.sync_user')).to_s + # config['sync']['password'] = ask(I18n.t('form.setup_wallet.sync_pwd')).to_s + # config['sync']['path'] = ask(I18n.t('form.setup_wallet.sync_path')).to_s + #end - @mpw.set_config(config) + wallet_file = wallet.nil? ? "#{@config.wallet_dir}/default.mpw" : "#{@config.wallet_dir}/#{wallet}.mpw" + + @mpw = MPW.new(@config.key, wallet_file, @password, @config.gpg_exe) + @mpw.read_data + @mpw.set_config @mpw.write_data puts "#{I18n.t('form.setup_wallet.valid')}".green @@ -384,7 +390,7 @@ class Cli @mpw.sync(true) if @sync puts "#{I18n.t('form.add_item.valid')}".green - rescue Exception => e + #rescue Exception => e puts "#{I18n.t('display.error')} #13: #{e}".red end diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index 6c3fc00..f4e8ce3 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -112,7 +112,7 @@ class MPW data.merge!(item.id => {'id' => item.id, 'name' => item.name, - 'group' => item.group, + 'group' => item.group, 'host' => item.host, 'protocol' => item.protocol, 'user' => item.user, @@ -158,7 +158,7 @@ class MPW File.rename(tmp_file, @wallet_file) rescue Exception => e - File.unlink(tmp_file) + File.unlink(tmp_file) if File.exist?(tmp_file) raise "#{I18n.t('error.mpw_file.write_data')}\n#{e}" end @@ -211,9 +211,12 @@ class MPW # Set config # args: config -> a hash with config options - def set_config(config) + def set_config(config=nil) + @config = {} if @config.nil? @config['sync'] = {} if @config['sync'].nil? + return if config.to_s.empty? + @config['sync']['type'] = config['sync']['type'] @config['sync']['host'] = config['sync']['host'] @config['sync']['port'] = config['sync']['port'] From 1681db0edb10e4391332a60c97eaf4266ddf6e4a Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Sat, 15 Oct 2016 09:30:41 +0200 Subject: [PATCH 324/531] fix recipients for encrypt --- lib/mpw/cli.rb | 7 +++---- lib/mpw/mpw.rb | 4 ++-- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index 2f9ad31..c3a953f 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -79,9 +79,6 @@ class Cli # Setup a new GPG key # @args: gpg_key -> the key name def setup_gpg_key(gpg_key) - puts I18n.t('form.setup_gpg_key.title') - puts '--------------------' - ask = ask(I18n.t('form.setup_gpg_key.ask')).to_s password = ask(I18n.t('form.setup_gpg_key.password')) {|q| q.echo = false} confirm = ask(I18n.t('form.setup_gpg_key.confirm_password')) {|q| q.echo = false} @@ -294,6 +291,8 @@ class Cli # Display the wallet # @args: wallet -> the wallet name def get_wallet(wallet=nil) + @config.is_valid? + if wallet.to_s.empty? wallets = Dir.glob("#{@config.wallet_dir}/*.mpw") @@ -390,7 +389,7 @@ class Cli @mpw.sync(true) if @sync puts "#{I18n.t('form.add_item.valid')}".green - #rescue Exception => e + rescue Exception => e puts "#{I18n.t('display.error')} #13: #{e}".red end diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index f4e8ce3..11c1293 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -500,12 +500,12 @@ class MPW recipients = [] crypto = GPGME::Crypto.new(armor: true, always_trust: true) + recipients.push(@key) @keys.each_key do |key| + next if key == @key recipients.push(key) end - recipients.push(@key) if not recipients.index(@key).nil? - return crypto.encrypt(data, recipients: recipients).read rescue Exception => e raise "#{I18n.t('error.gpg_file.encrypt')}\n#{e}" From ca2225ce711a4cc5fd68c0ef0df99074ac4a1728 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Sat, 15 Oct 2016 09:31:20 +0200 Subject: [PATCH 325/531] mpw-add: fix problem with get wallet --- bin/mpw-add | 3 +++ 1 file changed, 3 insertions(+) diff --git a/bin/mpw-add b/bin/mpw-add index d959c19..52537c0 100644 --- a/bin/mpw-add +++ b/bin/mpw-add @@ -45,4 +45,7 @@ end.parse! config = MPW::Config.new(options[:config]) cli = MPW::Cli.new(config, nil, options[:sync], nil) + +cli.get_wallet(options[:wallet]) +cli.decrypt cli.add From 77a8a7695a20f59923f534fbfd2cffbea297a349 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Sat, 15 Oct 2016 13:28:48 +0200 Subject: [PATCH 326/531] no try to decrypt if data is empty --- lib/mpw/mpw.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index 11c1293..5adeb0c 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -486,6 +486,8 @@ class MPW # @args: data -> string to decrypt private def decrypt(data) + return nil if data.to_s.empty? + crypto = GPGME::Crypto.new(armor: true) return crypto.decrypt(data, password: @gpg_pass).read.force_encoding('utf-8') From d5d4091bc23a83c47950af08d4d80c062c415a0b Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Sat, 15 Oct 2016 17:40:03 +0200 Subject: [PATCH 327/531] remove id and name for an item --- lib/mpw/item.rb | 19 +++---------- lib/mpw/mpw.rb | 61 +++++++++++++++++------------------------- templates/add_form.erb | 5 ++-- 3 files changed, 30 insertions(+), 55 deletions(-) diff --git a/lib/mpw/item.rb b/lib/mpw/item.rb index ef1309e..626db72 100644 --- a/lib/mpw/item.rb +++ b/lib/mpw/item.rb @@ -21,8 +21,6 @@ require 'i18n' module MPW class Item - attr_accessor :id - attr_accessor :name attr_accessor :group attr_accessor :host attr_accessor :protocol @@ -38,15 +36,13 @@ class Item # @args: options -> a hash of parameter # raise an error if the hash hasn't the key name def initialize(options={}) - if not options.has_key?(:name) or options[:name].to_s.empty? + if not options.has_key?(:host) or options[:host].to_s.empty? raise I18n.t('error.update.name_empty') end if not options.has_key?(:id) or options[:id].to_s.empty? or not options.has_key?(:created) or options[:created].to_s.empty? - @id = generate_id @created = Time.now.to_i else - @id = options[:id] @created = options[:created] @last_edit = options[:last_edit] options[:no_update_last_edit] = true @@ -58,11 +54,10 @@ class Item # Update the item # @args: options -> a hash of parameter def update(options={}) - if options.has_key?(:name) and options[:name].to_s.empty? + if options.has_key?(:host) and options[:host].to_s.empty? raise I18n.t('error.update.name_empty') end - @name = options[:name] if options.has_key?(:name) @group = options[:group] if options.has_key?(:group) @host = options[:host] if options.has_key?(:host) @protocol = options[:protocol] if options.has_key?(:protocol) @@ -79,8 +74,6 @@ class Item # Delete all data def delete - @id = nil - @name = nil @group = nil @host = nil @protocol = nil @@ -93,17 +86,11 @@ class Item end def empty? - return @name.to_s.empty? + return @host.to_s.empty? end def nil? return false end - - # Generate an random id - private - def generate_id - return ([*('A'..'Z'),*('a'..'z'),*('0'..'9')]).sample(16).join - end end end diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index 5adeb0c..fe80f40 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -82,9 +82,7 @@ class MPW if not data.nil? and not data.empty? YAML.load(data).each_value do |d| - @data.push(Item.new(id: d['id'], - name: d['name'], - group: d['group'], + @data.push(Item.new(group: d['group'], host: d['host'], protocol: d['protocol'], user: d['user'], @@ -110,17 +108,15 @@ class MPW @data.each do |item| next if item.empty? - data.merge!(item.id => {'id' => item.id, - 'name' => item.name, - 'group' => item.group, - 'host' => item.host, - 'protocol' => item.protocol, - 'user' => item.user, - 'port' => item.port, - 'comment' => item.comment, - 'last_edit' => item.last_edit, - 'created' => item.created, - } + data.merge!("#{item.user}@#{item.host}" => {'group' => item.group, + 'host' => item.host, + 'protocol' => item.protocol, + 'user' => item.user, + 'port' => item.port, + 'comment' => item.comment, + 'last_edit' => item.last_edit, + 'created' => item.created, + } ) end @@ -251,11 +247,10 @@ class MPW next if item.empty? next if not group.empty? and not group.eql?(item.group.downcase) - name = item.name.to_s.downcase host = item.host.to_s.downcase comment = item.comment.to_s.downcase - if not name =~ /^.*#{search}.*$/ and not host =~ /^.*#{search}.*$/ and not comment =~ /^.*#{search}.*$/ + if not host =~ /^.*#{search}.*$/ and not comment =~ /^.*#{search}.*$/ next end @@ -281,19 +276,17 @@ class MPW def export(file) data = {} @data.each do |item| - data.merge!(item.id => {'id' => item.id, - 'name' => item.name, - 'group' => item.group, - 'host' => item.host, - 'protocol' => item.protocol, - 'user' => item.user, - 'password' => get_password(item.id), - 'port' => item.port, - 'comment' => item.comment, - 'otp_key' => get_otp_code(item.id), - 'last_edit' => item.last_edit, - 'created' => item.created, - } + data.merge!("#{item.login}@#{item.host}" => {'group' => item.group, + 'host' => item.host, + 'protocol' => item.protocol, + 'user' => item.user, + 'password' => get_password(item.id), + 'port' => item.port, + 'comment' => item.comment, + 'otp_key' => get_otp_code(item.id), + 'last_edit' => item.last_edit, + 'created' => item.created, + } ) end @@ -306,8 +299,7 @@ class MPW # @args: file -> path to file import def import(file) YAML::load_file(file).each_value do |row| - item = Item.new(name: row['name'], - group: row['group'], + item = Item.new(group: row['group'], host: row['host'], protocol: row['protocol'], user: row['user'], @@ -370,8 +362,7 @@ class MPW # Update item if item.last_edit < r.last_edit - item.update(name: r.name, - group: r.group, + item.update(group: r.group, host: r.host, protocol: r.protocol, user: r.user, @@ -398,9 +389,7 @@ class MPW remote.list.each do |r| next if r.last_edit <= get_last_sync - item = Item.new(id: r.id, - name: r.name, - group: r.group, + item = Item.new(group: r.group, host: r.host, protocol: r.protocol, user: r.user, diff --git a/templates/add_form.erb b/templates/add_form.erb index 53c0333..447788e 100644 --- a/templates/add_form.erb +++ b/templates/add_form.erb @@ -1,9 +1,8 @@ --- -name: # <%= I18n.t('form.add_item.name') %> -group: # <%= I18n.t('form.add_item.group') %> host: # <%= I18n.t('form.add_item.host') %> -protocol: # <%= I18n.t('form.add_item.protocol') %> user: # <%= I18n.t('form.add_item.login') %> +group: # <%= I18n.t('form.add_item.group') %> +protocol: # <%= I18n.t('form.add_item.protocol') %> password: # <%= I18n.t('form.add_item.password') %> port: # <%= I18n.t('form.add_item.port') %> comment: # <%= I18n.t('form.add_item.comment') %> From dc8a8d76fc639a0d074085cb021aa287b6066d0f Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Sat, 15 Oct 2016 17:40:35 +0200 Subject: [PATCH 328/531] new binary for list --- bin/mpw-list | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++ lib/mpw/cli.rb | 32 +++++++++++++++++++++++++ 2 files changed, 95 insertions(+) create mode 100644 bin/mpw-list diff --git a/bin/mpw-list b/bin/mpw-list new file mode 100644 index 0000000..9bde1ff --- /dev/null +++ b/bin/mpw-list @@ -0,0 +1,63 @@ +#!/usr/bin/ruby +# MPW is a software to crypt and manage your passwords +# Copyright (C) 2016 Adrien Waksberg <mpw@yae.im> +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +require 'optparse' +require 'mpw/config' +require 'mpw/cli' + +# --------------------------------------------------------- # +# Options +# --------------------------------------------------------- # + +options = {} + +OptionParser.new do |opts| + opts.banner = "#{I18n.t('option.usage')}: mpw list [options]" + + opts.on('-c', '--config CONFIG', I18n.t('option.config')) do |config| + options[:config] = config + end + + opts.on('-g', '--group GROUP', I18n.t('option.config')) do |group| + options[:group] = group + end + + opts.on('-h', '--help', I18n.t('option.help')) do + puts opts + exit 0 + end + + opts.on('-p', '--pattern PATTERN', I18n.t('option.config')) do |pattern| + options[:pattern] = pattern + end + + opts.on('-w', '--wallet WALLET', I18n.t('option.wallet')) do |wallet| + options[:wallet] = wallet + end +end.parse! + +config = MPW::Config.new(options[:config]) +cli = MPW::Cli.new(config, nil, options[:sync], nil) + +opts = { search: options[:pattern], + group: options[:group], + } + +cli.get_wallet(options[:wallet]) +cli.decrypt +cli.list(opts) diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index c3a953f..f2bf72a 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -142,6 +142,38 @@ class Cli exit 2 end + # Display the query's result + # @args: options -> the option to search + def list(options={}) + result = @mpw.list(options) + + if result.length == 0 + puts I18n.t('display.nothing') + + else + group = '.' + + result.sort! { |a,b| a.group.to_s.downcase <=> b.group.to_s.downcase } + + result.each do |item| + if group != item.group + group = item.group + + if group.to_s.empty? + puts I18n.t('display.no_group').yellow + else + puts "\n#{group}".yellow + end + end + + print " |_ ".yellow + print "#{item.user}@#{item.host}" + print " -> #{item.comment}".magenta if not item.comment.to_s.empty? + print "\n" + end + end + end + # Display the query's result # @args: search -> the string to search # protocol -> search from a particular protocol From fbac3df19341042212116ef2162cae6dbba2dacf Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Sun, 16 Oct 2016 09:41:13 +0200 Subject: [PATCH 329/531] re add id for item --- lib/mpw/item.rb | 16 +++++++++++++--- lib/mpw/mpw.rb | 9 ++++++--- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/lib/mpw/item.rb b/lib/mpw/item.rb index 626db72..2e2459b 100644 --- a/lib/mpw/item.rb +++ b/lib/mpw/item.rb @@ -21,6 +21,7 @@ require 'i18n' module MPW class Item + attr_accessor :id attr_accessor :group attr_accessor :host attr_accessor :protocol @@ -40,9 +41,11 @@ class Item raise I18n.t('error.update.name_empty') end - if not options.has_key?(:id) or options[:id].to_s.empty? or not options.has_key?(:created) or options[:created].to_s.empty? + if not options.has_key?(:id) or options[:id].to_s.empty? or not options.has_key?(:created) or options[:created].to_s.empty? + @id = generate_id @created = Time.now.to_i else + @id = options[:id] @created = options[:created] @last_edit = options[:last_edit] options[:no_update_last_edit] = true @@ -74,6 +77,7 @@ class Item # Delete all data def delete + @id = nil @group = nil @host = nil @protocol = nil @@ -86,11 +90,17 @@ class Item end def empty? - return @host.to_s.empty? + return @id.to_s.empty? end def nil? return false end + + # Generate an random id + private + def generate_id + return ([*('A'..'Z'),*('a'..'z'),*('0'..'9')]).sample(16).join + end +end end -end diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index fe80f40..0c1609e 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -82,7 +82,8 @@ class MPW if not data.nil? and not data.empty? YAML.load(data).each_value do |d| - @data.push(Item.new(group: d['group'], + @data.push(Item.new(id: d['id'], + group: d['group'], host: d['host'], protocol: d['protocol'], user: d['user'], @@ -108,7 +109,8 @@ class MPW @data.each do |item| next if item.empty? - data.merge!("#{item.user}@#{item.host}" => {'group' => item.group, + data.merge!("#{item.user}@#{item.host}" => {'id' => item.id, + 'group' => item.group, 'host' => item.host, 'protocol' => item.protocol, 'user' => item.user, @@ -389,7 +391,8 @@ class MPW remote.list.each do |r| next if r.last_edit <= get_last_sync - item = Item.new(group: r.group, + item = Item.new(id: r.id, + group: r.group, host: r.host, protocol: r.protocol, user: r.user, From 4c9c4e21f67fc48c4039e2ee1cdd34d5eac6c760 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Mon, 17 Oct 2016 00:06:27 +0200 Subject: [PATCH 330/531] list under table format --- lib/mpw/cli.rb | 49 +++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 43 insertions(+), 6 deletions(-) diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index f2bf72a..1575a06 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -154,23 +154,60 @@ class Cli group = '.' result.sort! { |a,b| a.group.to_s.downcase <=> b.group.to_s.downcase } + size = {host: 10, + user: 8, + comment: 15, + otp: 5, + } + + result.sort! { |a,b| a.group.to_s.downcase <=> b.group.to_s.downcase } + + result.each do |item| + size[:host] = item.host.length + 3 if item.host.to_s.length > size[:host] + size[:user] = item.user.length + 3 if item.user.to_s.length > size[:user] + size[:comment] = item.comment.length + 3 if item.comment.to_s.length > size[:comment] + end + size[:max] = size[:host] + size[:user] + size[:comment] + size[:otp] result.each do |item| if group != item.group group = item.group if group.to_s.empty? - puts I18n.t('display.no_group').yellow + puts I18n.t('display.no_group').red else - puts "\n#{group}".yellow + puts "\n#{group}".red end + + (size[:max] + 8).times { print '=' } + print "\n" + print '| Host' + (size[:host] - 'Host'.length).times { print ' ' } + print '| User' + (size[:user] - 'User'.length).times { print ' ' } + print '| OTP ' + print '| Comment' + (size[:comment] - 'Comment'.length).times { print ' ' } + print "|\n" + (size[:max] + 8).times { print '=' } + print "\n" end - print " |_ ".yellow - print "#{item.user}@#{item.host}" - print " -> #{item.comment}".magenta if not item.comment.to_s.empty? - print "\n" + print '| ' + print "#{item.host}".yellow + (size[:host] - item.host.to_s.length).times { print ' ' } + print '| ' + print "#{item.user}".green + (size[:user] - item.user.to_s.length).times { print ' ' } + print '| ' + 4.times { print ' ' } + print '| ' + print "#{item.comment}".magenta + (size[:comment] - item.comment.to_s.length).times { print ' ' } + print "|\n" end + + print "\n" end end From fc8e5e71151c4aee3027071b8e09449328e5436a Mon Sep 17 00:00:00 2001 From: nishiki <git@yae.im> Date: Mon, 17 Oct 2016 18:32:34 +0200 Subject: [PATCH 331/531] fix bug in search with group option --- lib/mpw/mpw.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index 0c1609e..872c1aa 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -242,12 +242,12 @@ class MPW def list(options={}) result = [] - search = options[:search].to_s.downcase - group = options[:group].to_s.downcase + search = options[:search].to_s.downcase + group = options[:group].to_s.downcase @data.each do |item| next if item.empty? - next if not group.empty? and not group.eql?(item.group.downcase) + next if not group.empty? and not group.eql?(item.group.to_s.downcase) host = item.host.to_s.downcase comment = item.comment.to_s.downcase From aeae6e861c539329a8eca5022384c30112ade8e9 Mon Sep 17 00:00:00 2001 From: nishiki <git@yae.im> Date: Mon, 17 Oct 2016 18:34:43 +0200 Subject: [PATCH 332/531] add attribute otp in item --- lib/mpw/item.rb | 3 +++ lib/mpw/mpw.rb | 27 ++++++++++++++++----------- 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/lib/mpw/item.rb b/lib/mpw/item.rb index 2e2459b..4beb49f 100644 --- a/lib/mpw/item.rb +++ b/lib/mpw/item.rb @@ -27,6 +27,7 @@ class Item attr_accessor :protocol attr_accessor :user attr_accessor :port + attr_accessor :otp attr_accessor :comment attr_accessor :last_edit attr_accessor :last_sync @@ -66,6 +67,7 @@ class Item @protocol = options[:protocol] if options.has_key?(:protocol) @user = options[:user] if options.has_key?(:user) @port = options[:port].to_i if options.has_key?(:port) and not options[:port].to_s.empty? + @otp = options[:otp] if options.has_key?(:otp) @comment = options[:comment] if options.has_key?(:comment) @last_edit = Time.now.to_i if not options.has_key?(:no_update_last_edit) end @@ -83,6 +85,7 @@ class Item @protocol = nil @user = nil @port = nil + @otp = nil @comment = nil @created = nil @last_edit = nil diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index 872c1aa..1572923 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -88,6 +88,7 @@ class MPW protocol: d['protocol'], user: d['user'], port: d['port'], + otp: @otp_keys.has_key?(d['id']), comment: d['comment'], last_edit: d['last_edit'], created: d['created'], @@ -277,19 +278,23 @@ class MPW # @args: file -> file where you export the data def export(file) data = {} + i = 1 + @data.each do |item| - data.merge!("#{item.login}@#{item.host}" => {'group' => item.group, - 'host' => item.host, - 'protocol' => item.protocol, - 'user' => item.user, - 'password' => get_password(item.id), - 'port' => item.port, - 'comment' => item.comment, - 'otp_key' => get_otp_code(item.id), - 'last_edit' => item.last_edit, - 'created' => item.created, - } + data.merge!(i => { 'group' => item.group, + 'host' => item.host, + 'protocol' => item.protocol, + 'user' => item.user, + 'password' => get_password(item.id), + 'port' => item.port, + 'comment' => item.comment, + 'otp_key' => get_otp_code(item.id), + 'last_edit' => item.last_edit, + 'created' => item.created, + } ) + + i += 1 end File.open(file, 'w') {|f| f << data.to_yaml} From 2ffaa5114b3bef5c12c117ba54cb8da3ed7bc8ba Mon Sep 17 00:00:00 2001 From: nishiki <git@yae.im> Date: Mon, 17 Oct 2016 18:35:13 +0200 Subject: [PATCH 333/531] fix template for otp --- templates/add_form.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/add_form.erb b/templates/add_form.erb index 447788e..f4f8cae 100644 --- a/templates/add_form.erb +++ b/templates/add_form.erb @@ -6,4 +6,4 @@ protocol: # <%= I18n.t('form.add_item.protocol') %> password: # <%= I18n.t('form.add_item.password') %> port: # <%= I18n.t('form.add_item.port') %> comment: # <%= I18n.t('form.add_item.comment') %> -otp_secret: # <%= I18n.t('form.add_item.otp_key') %> +otp_key: # <%= I18n.t('form.add_item.otp_key') %> From cc339bbe98cd22ab554bddeb95d500a2a21e9061 Mon Sep 17 00:00:00 2001 From: nishiki <git@yae.im> Date: Mon, 17 Oct 2016 18:35:30 +0200 Subject: [PATCH 334/531] minor fix id --- lib/mpw/mpw.rb | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index 1572923..f1ae35e 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -110,16 +110,16 @@ class MPW @data.each do |item| next if item.empty? - data.merge!("#{item.user}@#{item.host}" => {'id' => item.id, - 'group' => item.group, - 'host' => item.host, - 'protocol' => item.protocol, - 'user' => item.user, - 'port' => item.port, - 'comment' => item.comment, - 'last_edit' => item.last_edit, - 'created' => item.created, - } + data.merge!(item.id => { 'id' => item.id, + 'group' => item.group, + 'host' => item.host, + 'protocol' => item.protocol, + 'user' => item.user, + 'port' => item.port, + 'comment' => item.comment, + 'last_edit' => item.last_edit, + 'created' => item.created, + } ) end From d49b305f697dd7ea7b5aca4a14493e639010e93d Mon Sep 17 00:00:00 2001 From: nishiki <git@yae.im> Date: Mon, 17 Oct 2016 18:35:57 +0200 Subject: [PATCH 335/531] cli: add table function --- lib/mpw/cli.rb | 131 ++++++++++++++++++++++++++++--------------------- 1 file changed, 74 insertions(+), 57 deletions(-) diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index 1575a06..5f356ad 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -142,6 +142,79 @@ class Cli exit 2 end + # Format items on a table + def table(items=[]) + group = '.' + i = 1 + length_total = 10 + length = { id: 3, + host: 10, + user: 8, + comment: 15, + otp: 5, + } + + items.each do |item| + length[:host] = item.host.length + 3 if item.host.to_s.length > length[:host] + length[:user] = item.user.length + 3 if item.user.to_s.length > length[:user] + length[:comment] = item.comment.length + 3 if item.comment.to_s.length > length[:comment] + end + length[:id] = items.length.to_s.length + 2 if items.length.to_s.length > length[:id] + + length.each_value { |v| length_total += v } + items.sort! { |a,b| a.group.to_s.downcase <=> b.group.to_s.downcase } + + items.each do |item| + if group != item.group + group = item.group + + if group.to_s.empty? + puts "\n#{I18n.t('display.no_group')}".red + else + puts "\n#{group}".red + end + + print ' ' + length_total.times { print '=' } + print "\n " + print ' ID ' + print '| Host' + (length[:host] - 'Host'.length).times { print ' ' } + print '| User' + (length[:user] - 'User'.length).times { print ' ' } + print '| OTP ' + print '| Comment' + (length[:comment] - 'Comment'.length).times { print ' ' } + print "\n " + length_total.times { print '=' } + print "\n" + end + + print " #{i}".cyan + (length[:id] - i.to_s.length).times { print ' ' } + print '| ' + print "#{item.host}".yellow + (length[:host] - item.host.to_s.length).times { print ' ' } + print '| ' + print "#{item.user}".green + (length[:user] - item.user.to_s.length).times { print ' ' } + print '| ' + if item.otp + print ' X ' + else + 4.times { print ' ' } + end + print '| ' + print "#{item.comment}".magenta + (length[:comment] - item.comment.to_s.length).times { print ' ' } + print "\n" + + i += 1 + end + + print "\n" + end + # Display the query's result # @args: options -> the option to search def list(options={}) @@ -151,63 +224,7 @@ class Cli puts I18n.t('display.nothing') else - group = '.' - - result.sort! { |a,b| a.group.to_s.downcase <=> b.group.to_s.downcase } - size = {host: 10, - user: 8, - comment: 15, - otp: 5, - } - - result.sort! { |a,b| a.group.to_s.downcase <=> b.group.to_s.downcase } - - result.each do |item| - size[:host] = item.host.length + 3 if item.host.to_s.length > size[:host] - size[:user] = item.user.length + 3 if item.user.to_s.length > size[:user] - size[:comment] = item.comment.length + 3 if item.comment.to_s.length > size[:comment] - end - size[:max] = size[:host] + size[:user] + size[:comment] + size[:otp] - - result.each do |item| - if group != item.group - group = item.group - - if group.to_s.empty? - puts I18n.t('display.no_group').red - else - puts "\n#{group}".red - end - - (size[:max] + 8).times { print '=' } - print "\n" - print '| Host' - (size[:host] - 'Host'.length).times { print ' ' } - print '| User' - (size[:user] - 'User'.length).times { print ' ' } - print '| OTP ' - print '| Comment' - (size[:comment] - 'Comment'.length).times { print ' ' } - print "|\n" - (size[:max] + 8).times { print '=' } - print "\n" - end - - print '| ' - print "#{item.host}".yellow - (size[:host] - item.host.to_s.length).times { print ' ' } - print '| ' - print "#{item.user}".green - (size[:user] - item.user.to_s.length).times { print ' ' } - print '| ' - 4.times { print ' ' } - print '| ' - print "#{item.comment}".magenta - (size[:comment] - item.comment.to_s.length).times { print ' ' } - print "|\n" - end - - print "\n" + table(result) end end From c75f169b0ca7d28691ac73e7db30d47a3c3347e9 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Mon, 17 Oct 2016 20:48:20 +0200 Subject: [PATCH 336/531] new binary for update --- bin/mpw-update | 63 ++++++++++++++++++++++++++++++ lib/mpw/cli.rb | 81 ++++++++++++++------------------------- templates/update_form.erb | 14 +++---- 3 files changed, 97 insertions(+), 61 deletions(-) create mode 100644 bin/mpw-update diff --git a/bin/mpw-update b/bin/mpw-update new file mode 100644 index 0000000..e521ffc --- /dev/null +++ b/bin/mpw-update @@ -0,0 +1,63 @@ +#!/usr/bin/ruby +# MPW is a software to crypt and manage your passwords +# Copyright (C) 2016 Adrien Waksberg <mpw@yae.im> +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +require 'optparse' +require 'mpw/config' +require 'mpw/cli' + +# --------------------------------------------------------- # +# Options +# --------------------------------------------------------- # + +options = {} + +OptionParser.new do |opts| + opts.banner = "#{I18n.t('option.usage')}: mpw [options]" + + opts.on('-c', '--config CONFIG', I18n.t('option.config')) do |config| + options[:config] = config + end + + opts.on('-g', '--group GROUP', I18n.t('option.config')) do |group| + options[:group] = group + end + + opts.on('-h', '--help', I18n.t('option.help')) do + puts opts + exit 0 + end + + opts.on('-p', '--pattern PATTERN', I18n.t('option.config')) do |pattern| + options[:pattern] = pattern + end + + opts.on('-w', '--wallet WALLET', I18n.t('option.wallet')) do |wallet| + options[:wallet] = wallet + end +end.parse! + +config = MPW::Config.new(options[:config]) +cli = MPW::Cli.new(config, nil, options[:sync], nil) + +opts = { search: options[:pattern], + group: options[:group], + } + +cli.get_wallet(options[:wallet]) +cli.decrypt +cli.update(opts) diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index 5f356ad..67bf9a2 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -228,53 +228,19 @@ class Cli end end - # Display the query's result - # @args: search -> the string to search - # protocol -> search from a particular protocol - def display(options={}) - result = @mpw.list(options) + # Get an item when multiple choice + # @args: items -> array of items + # @rtrn: item + def get_item(items) + return items[0] if items.length == 1 - case result.length - when 0 - puts I18n.t('display.nothing') - - when 1 - display_item(result.first) + items.sort! { |a,b| a.group.to_s.downcase <=> b.group.to_s.downcase } + choice = ask(I18n.t('form.select')).to_i + if choice >= 1 and choice <= items.length + return items[choice-1] else - group = nil - i = 1 - - result.sort! { |a,b| a.group.to_s.downcase <=> b.group.to_s.downcase } - - result.each do |item| - if group != item.group - group = item.group - - if group.empty? - puts I18n.t('display.no_group').yellow - else - puts "\n#{group}".yellow - end - end - - print " |_ ".yellow - print "#{i}: ".cyan - print item.name - print " -> #{item.comment}".magenta if not item.comment.to_s.empty? - print "\n" - - i += 1 - end - - print "\n" - choice = ask(I18n.t('form.select')).to_i - - if choice >= 1 and choice < i - display_item(result[choice-1]) - else - puts "#{I18n.t('display.warning')}: #{I18n.t('warning.select')}".yellow - end + return nil end end @@ -480,17 +446,26 @@ class Cli end # Update an item - # @args: id -> the item's id - def update(item) - options = text_editor('update_form', item) + # @args: options -> the option to search + def update(options={}) + items = @mpw.list(options) + + if items.length == 0 + puts "#{I18n.t('display.warning')}: #{I18n.t('warning.select')}".yellow + else + table(items) if items.length > 1 - item.update(options) - @mpw.set_password(item.id, options[:password]) if options.has_key?(:password) - @mpw.set_otp_key(item.id, options[:otp_key]) if options.has_key?(:otp_key) - @mpw.write_data - @mpw.sync(true) if @sync + item = get_item(items) + options = text_editor('update_form', item) - puts "#{I18n.t('form.update_item.valid')}".green + item.update(options) + @mpw.set_password(item.id, options[:password]) if options.has_key?(:password) + @mpw.set_otp_key(item.id, options[:otp_key]) if options.has_key?(:otp_key) + @mpw.write_data + @mpw.sync(true) if @sync + + puts "#{I18n.t('form.update_item.valid')}".green + end rescue Exception => e puts "#{I18n.t('display.error')} #14: #{e}".red end diff --git a/templates/update_form.erb b/templates/update_form.erb index 57178cc..f4a380b 100644 --- a/templates/update_form.erb +++ b/templates/update_form.erb @@ -1,19 +1,17 @@ --- -# <%= I18n.t('form.update_item.name') %> -name: <%= item.name %> -# <%= I18n.t('form.update_item.group') %> -group: <%= item.group %> # <%= I18n.t('form.update_item.host') %> host: <%= item.host %> -# <%= I18n.t('form.update_item.protocol') %> -protocol: <%= item.protocol %> # <%= I18n.t('form.update_item.login') %> user: <%= item.user %> # <%= I18n.t('form.update_item.password') %> password: +# <%= I18n.t('form.update_item.group') %> +group: <%= item.group %> +# <%= I18n.t('form.update_item.protocol') %> +protocol: <%= item.protocol %> # <%= I18n.t('form.update_item.port') %> port: <%= item.port %> +# <%= I18n.t('form.update_item.otp_key') %> +opt_key: # <%= I18n.t('form.update_item.comment') %> comment: <%= item.comment %> -# <%= I18n.t('form.update_item.otp_key') %> -opt_code: From e196cbf93d4a57768abe69393b635214a4dc547e Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Mon, 17 Oct 2016 21:17:15 +0200 Subject: [PATCH 337/531] new binary for delete --- bin/mpw-delete | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++ lib/mpw/cli.rb | 35 ++++++++++++++++------------ 2 files changed, 83 insertions(+), 15 deletions(-) create mode 100644 bin/mpw-delete diff --git a/bin/mpw-delete b/bin/mpw-delete new file mode 100644 index 0000000..a7e95e8 --- /dev/null +++ b/bin/mpw-delete @@ -0,0 +1,63 @@ +#!/usr/bin/ruby +# MPW is a software to crypt and manage your passwords +# Copyright (C) 2016 Adrien Waksberg <mpw@yae.im> +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +require 'optparse' +require 'mpw/config' +require 'mpw/cli' + +# --------------------------------------------------------- # +# Options +# --------------------------------------------------------- # + +options = {} + +OptionParser.new do |opts| + opts.banner = "#{I18n.t('option.usage')}: mpw delete [options]" + + opts.on('-c', '--config CONFIG', I18n.t('option.config')) do |config| + options[:config] = config + end + + opts.on('-g', '--group GROUP', I18n.t('option.config')) do |group| + options[:group] = group + end + + opts.on('-h', '--help', I18n.t('option.help')) do + puts opts + exit 0 + end + + opts.on('-p', '--pattern PATTERN', I18n.t('option.config')) do |pattern| + options[:pattern] = pattern + end + + opts.on('-w', '--wallet WALLET', I18n.t('option.wallet')) do |wallet| + options[:wallet] = wallet + end +end.parse! + +config = MPW::Config.new(options[:config]) +cli = MPW::Cli.new(config, nil, options[:sync], nil) + +opts = { search: options[:pattern], + group: options[:group], + } + +cli.get_wallet(options[:wallet]) +cli.decrypt +cli.delete(opts) diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index 67bf9a2..749007a 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -471,25 +471,30 @@ class Cli end # Remove an item - # @args: id -> the item's id - # force -> no resquest a validation - def delete(item) - confirm = ask("#{I18n.t('form.delete_item.ask')} (y/N) ").to_s + # @args: options -> the option to search + def delete(options={}) + items = @mpw.list(options) + + if items.length == 0 + puts "#{I18n.t('display.warning')}: #{I18n.t('warning.select')}".yellow + else + table(items) - if not confirm =~ /^(y|yes|YES|Yes|Y)$/ - return false + item = get_item(items) + confirm = ask("#{I18n.t('form.delete_item.ask')} (y/N) ").to_s + + if not confirm =~ /^(y|yes|YES|Yes|Y)$/ + return false + end + + item.delete + @mpw.write_data + @mpw.sync(true) if @sync + + puts "#{I18n.t('form.delete_item.valid')}".green end - - item.delete - @mpw.write_data - @mpw.sync(true) if @sync - - puts "#{I18n.t('form.delete_item.valid')}".green - - return true rescue Exception => e puts "#{I18n.t('display.error')} #16: #{e}".red - return false end # Export the items in a CSV file From 985de310fb4f11f4f00c92a196e9a7e2632c07c7 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Wed, 19 Oct 2016 12:56:55 +0200 Subject: [PATCH 338/531] new binary for wallet --- bin/mpw-wallet | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ lib/mpw/cli.rb | 28 ++++++++++++---------------- 2 files changed, 61 insertions(+), 16 deletions(-) create mode 100644 bin/mpw-wallet diff --git a/bin/mpw-wallet b/bin/mpw-wallet new file mode 100644 index 0000000..c5fdc7a --- /dev/null +++ b/bin/mpw-wallet @@ -0,0 +1,49 @@ +#!/usr/bin/ruby +# MPW is a software to crypt and manage your passwords +# Copyright (C) 2016 Adrien Waksberg <mpw@yae.im> +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +require 'optparse' +require 'mpw/config' +require 'mpw/cli' + +# --------------------------------------------------------- # +# Options +# --------------------------------------------------------- # + +options = {} + +OptionParser.new do |opts| + opts.banner = "#{I18n.t('option.usage')}: mpw wallet [options]" + + opts.on('-c', '--config CONFIG', I18n.t('option.config')) do |config| + options[:config] = config + end + + opts.on('-h', '--help', I18n.t('option.help')) do + puts opts + exit 0 + end + + opts.on('-w', '--wallet WALLET', I18n.t('option.wallet')) do |wallet| + options[:wallet] = wallet + end +end.parse! + +config = MPW::Config.new(options[:config]) +cli = MPW::Cli.new(config, nil, options[:sync], nil) + +cli.list_wallet diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index 749007a..b92d5fb 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -340,6 +340,17 @@ class Cli Clipboard.clear end + # List all wallets + def list_wallet + @config.is_valid? + + wallets = Dir.glob("#{@config.wallet_dir}/*.mpw") + + wallets.each do |wallet| + puts File.basename(wallet, '.mpw') + end + end + # Display the wallet # @args: wallet -> the wallet name def get_wallet(wallet=nil) @@ -354,22 +365,7 @@ class Cli when 1 @wallet_file = wallets[0] else - i = 1 - wallets.each do |wallet| - print "#{i}: ".cyan - puts File.basename(wallet, '.mpw') - - i += 1 - end - - choice = ask(I18n.t('form.select')).to_i - - if choice >= 1 and choice < i - @wallet_file = wallets[choice-1] - else - puts "#{I18n.t('display.warning')}: #{I18n.t('warning.select')}".yellow - exit 2 - end + @wallet_file = "#{@config.wallet_dir}/default.mpw" end else @wallet_file = "#{@config.wallet_dir}/#{wallet}.mpw" From 2f686ca1631219ff4aea958bb6969377241e9160 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Wed, 19 Oct 2016 15:08:08 +0200 Subject: [PATCH 339/531] new binary for export --- bin/mpw-export | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++ lib/mpw/cli.rb | 27 ++++++++++++++++++-- lib/mpw/mpw.rb | 28 --------------------- 3 files changed, 92 insertions(+), 30 deletions(-) create mode 100644 bin/mpw-export diff --git a/bin/mpw-export b/bin/mpw-export new file mode 100644 index 0000000..700d067 --- /dev/null +++ b/bin/mpw-export @@ -0,0 +1,67 @@ +#!/usr/bin/ruby +# MPW is a software to crypt and manage your passwords +# Copyright (C) 2016 Adrien Waksberg <mpw@yae.im> +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +require 'optparse' +require 'mpw/config' +require 'mpw/cli' + +# --------------------------------------------------------- # +# Options +# --------------------------------------------------------- # + +options = {} + +OptionParser.new do |opts| + opts.banner = "#{I18n.t('option.usage')}: mpw wallet [options]" + + opts.on('-c', '--config PATH', I18n.t('option.config')) do |config| + options[:config] = config + end + + opts.on('-f', '--file PATH', I18n.t('option.file')) do |file| + options[:file] = file + end + + opts.on('-g', '--group GROUP', I18n.t('option.config')) do |group| + options[:group] = group + end + + opts.on('-h', '--help', I18n.t('option.help')) do + puts opts + exit 0 + end + + opts.on('-p', '--pattern PATTERN', I18n.t('option.config')) do |pattern| + options[:pattern] = pattern + end + + opts.on('-w', '--wallet WALLET', I18n.t('option.wallet')) do |wallet| + options[:wallet] = wallet + end +end.parse! + +config = MPW::Config.new(options[:config]) +cli = MPW::Cli.new(config, nil, options[:sync], nil) + +opts = { search: options[:pattern], + group: options[:group], + } + +cli.get_wallet(options[:wallet]) +cli.decrypt +cli.export(options[:file], opts) diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index b92d5fb..daf8543 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -495,8 +495,31 @@ class Cli # Export the items in a CSV file # @args: file -> the destination file - def export(file) - @mpw.export(file) + # options -> option to search + def export(file, options) + file = 'export-mpw.yml' if file.to_s.empty? + items = @mpw.list(options) + data = {} + i = 1 + + items.each do |item| + data.merge!(i => { 'host' => item.host, + 'user' => item.user, + 'group' => item.group, + 'password' => @mpw.get_password(item.id), + 'protocol' => item.protocol, + 'port' => item.port, + 'otp_key' => @mpw.get_otp_code(item.id), + 'comment' => item.comment, + 'last_edit' => item.last_edit, + 'created' => item.created, + } + ) + + i += 1 + end + + File.open(file, 'w') {|f| f << data.to_yaml} puts "#{I18n.t('export.export.valid', file)}".green rescue Exception => e diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index f1ae35e..10c57d0 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -274,34 +274,6 @@ class MPW return nil end - # Export to yaml - # @args: file -> file where you export the data - def export(file) - data = {} - i = 1 - - @data.each do |item| - data.merge!(i => { 'group' => item.group, - 'host' => item.host, - 'protocol' => item.protocol, - 'user' => item.user, - 'password' => get_password(item.id), - 'port' => item.port, - 'comment' => item.comment, - 'otp_key' => get_otp_code(item.id), - 'last_edit' => item.last_edit, - 'created' => item.created, - } - ) - - i += 1 - end - - File.open(file, 'w') {|f| f << data.to_yaml} - rescue Exception => e - raise "#{I18n.t('error.export', file: file)}\n#{e}" - end - # Import to yaml # @args: file -> path to file import def import(file) From 7c24853e5e1f43bc31c4ef85bea090138bb6a8c5 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Wed, 19 Oct 2016 16:11:50 +0200 Subject: [PATCH 340/531] fix export otp_key --- lib/mpw/cli.rb | 4 ++-- lib/mpw/mpw.rb | 16 +++++++++++++++- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index daf8543..8e95297 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -509,7 +509,7 @@ class Cli 'password' => @mpw.get_password(item.id), 'protocol' => item.protocol, 'port' => item.port, - 'otp_key' => @mpw.get_otp_code(item.id), + 'otp_key' => @mpw.get_otp_key(item.id), 'comment' => item.comment, 'last_edit' => item.last_edit, 'created' => item.created, @@ -521,7 +521,7 @@ class Cli File.open(file, 'w') {|f| f << data.to_yaml} - puts "#{I18n.t('export.export.valid', file)}".green + puts "#{I18n.t('export.valid', file)}".green rescue Exception => e puts "#{I18n.t('display.error')} #17: #{e}".red end diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index 10c57d0..c2befb1 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -403,9 +403,23 @@ class MPW # args: id -> the item id # key -> the new key def set_otp_key(id, key) - @otp_keys[id] = encrypt(key) + if not key.to_s.empty? + @otp_keys[id] = encrypt(key.to_s) + end end + # Get an opt key + # args: id -> the item id + # key -> the new key + def get_otp_key(id) + if @otp_keys.has_key?(id) + return decrypt(@otp_keys[id]) + else + return nil + end + end + + # Get an otp code # @args: id -> the item id # @rtrn: an otp code From 92168dd654dfc55b9ec5380f8d8a4fbb15e2c5f3 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Wed, 19 Oct 2016 16:12:13 +0200 Subject: [PATCH 341/531] new binary for import --- bin/mpw-import | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++ lib/mpw/cli.rb | 21 +++++++++++++++++- lib/mpw/mpw.rb | 22 ------------------- 3 files changed, 79 insertions(+), 23 deletions(-) create mode 100644 bin/mpw-import diff --git a/bin/mpw-import b/bin/mpw-import new file mode 100644 index 0000000..61b5d8c --- /dev/null +++ b/bin/mpw-import @@ -0,0 +1,59 @@ +#!/usr/bin/ruby +# MPW is a software to crypt and manage your passwords +# Copyright (C) 2016 Adrien Waksberg <mpw@yae.im> +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +require 'optparse' +require 'mpw/config' +require 'mpw/cli' + +# --------------------------------------------------------- # +# Options +# --------------------------------------------------------- # + +options = {} + +OptionParser.new do |opts| + opts.banner = "#{I18n.t('option.usage')}: mpw wallet [options]" + + opts.on('-c', '--config PATH', I18n.t('option.config')) do |config| + options[:config] = config + end + + opts.on('-f', '--file PATH', I18n.t('option.file')) do |file| + options[:file] = file + end + + opts.on('-h', '--help', I18n.t('option.help')) do + puts opts + exit 0 + end + + opts.on('-w', '--wallet WALLET', I18n.t('option.wallet')) do |wallet| + options[:wallet] = wallet + end +end.parse! + +config = MPW::Config.new(options[:config]) +cli = MPW::Cli.new(config, nil, options[:sync], nil) + +opts = { search: options[:pattern], + group: options[:group], + } + +cli.get_wallet(options[:wallet]) +cli.decrypt +cli.import(options[:file]) diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index 8e95297..8fc109b 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -529,7 +529,26 @@ class Cli # Import items from a YAML file # @args: file -> the import file def import(file) - @mpw.import(file) + raise I18n.t('import.file_empty') if file.to_s.empty? + raise I18n.t('import.file_not_exist') if not File.exist?(file) + + YAML::load_file(file).each_value do |row| + + item = Item.new(group: row['group'], + host: row['host'], + protocol: row['protocol'], + user: row['user'], + port: row['port'], + comment: row['comment'], + ) + + next if item.empty? + + @mpw.add(item) + @mpw.set_password(item.id, row['password']) if not row['password'].to_s.empty? + @mpw.set_otp_key(item.id, row['otp_key']) if not row['otp_key'].to_s.empty? + end + @mpw.write_data puts "#{I18n.t('form.import.valid')}".green diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index c2befb1..a0c4c6e 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -274,28 +274,6 @@ class MPW return nil end - # Import to yaml - # @args: file -> path to file import - def import(file) - YAML::load_file(file).each_value do |row| - item = Item.new(group: row['group'], - host: row['host'], - protocol: row['protocol'], - user: row['user'], - port: row['port'], - comment: row['comment'], - ) - - raise 'Item is empty' if item.empty? - - @data.push(item) - set_password(item.id, row['password']) if not row['password'].to_s.empty? - set_otp_code(item.id, row['otp_key']) if not row['otp_key'].to_s.empty? - end - rescue Exception => e - raise "#{I18n.t('error.import', file: file)}\n#{e}" - end - # Get last sync def get_last_sync return @config['sync']['last_sync'].to_i From 38b5b5ada5fec453ddd9a9d2c99c7e6a9fc09442 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Thu, 20 Oct 2016 08:32:26 +0200 Subject: [PATCH 342/531] fix translation options --- bin/mpw-add | 6 +++--- bin/mpw-config | 21 ++++++++++----------- bin/mpw-delete | 8 ++++---- bin/mpw-export | 8 ++++---- bin/mpw-genpwd | 2 +- bin/mpw-import | 6 +++--- bin/mpw-list | 8 ++++---- bin/mpw-update | 10 +++++----- bin/mpw-wallet | 4 ++-- i18n/en.yml | 11 +++++++++-- i18n/fr.yml | 11 +++++++++-- 11 files changed, 54 insertions(+), 41 deletions(-) diff --git a/bin/mpw-add b/bin/mpw-add index 52537c0..883f75d 100644 --- a/bin/mpw-add +++ b/bin/mpw-add @@ -27,9 +27,9 @@ require 'mpw/cli' options = {} OptionParser.new do |opts| - opts.banner = "#{I18n.t('option.usage')}: mpw [options]" + opts.banner = "#{I18n.t('option.usage')}: mpw add [options]" - opts.on('-c', '--config CONFIG', I18n.t('option.config')) do |config| + opts.on('-c', '--config PATH', I18n.t('option.config')) do |config| options[:config] = config end @@ -38,7 +38,7 @@ OptionParser.new do |opts| exit 0 end - opts.on('-w', '--wallet WALLET', I18n.t('option.wallet')) do |wallet| + opts.on('-w', '--wallet NAME', I18n.t('option.wallet')) do |wallet| options[:wallet] = wallet end end.parse! diff --git a/bin/mpw-config b/bin/mpw-config index d29a93c..a215150 100644 --- a/bin/mpw-config +++ b/bin/mpw-config @@ -27,13 +27,13 @@ require 'mpw/cli' options = {} OptionParser.new do |opts| - opts.banner = "#{I18n.t('option.usage')}: mpw [options]" + opts.banner = "#{I18n.t('option.usage')}: mpw config [options]" - opts.on('-c', '--config CONFIG', I18n.t('option.config')) do |config| + opts.on('-c', '--config PATH', I18n.t('option.config')) do |config| options[:config] = config end - opts.on('-g', '--gpg-exe PATH', I18n.t('option.lang')) do |gpg_exe| + opts.on('-g', '--gpg-exe PATH', I18n.t('option.gpg_exe')) do |gpg_exe| options[:gpg_exe] = gpg_exe end @@ -42,11 +42,11 @@ OptionParser.new do |opts| exit 0 end - opts.on('--init', I18n.t('option.init')) do - options[:init] = true + opts.on('-i', '--init GPG_KEY', I18n.t('option.init')) do |gpg_key| + options[:init] = gpg_key end - opts.on('-k', '--key GPG_KEY', I18n.t('option.lang')) do |gpg_key| + opts.on('-k', '--key GPG_KEY', I18n.t('option.gpg_key')) do |gpg_key| options[:gpg_key] = gpg_key end @@ -54,7 +54,7 @@ OptionParser.new do |opts| options[:lang] = lang end - opts.on('-w', '--wallet-dir LANG', I18n.t('option.lang')) do |wallet_dir| + opts.on('-w', '--wallet-dir PATH', I18n.t('option.wallet_dir')) do |wallet_dir| options[:wallet_dir] = wallet_dir end end.parse! @@ -64,9 +64,8 @@ cli = MPW::Cli.new(config, nil, nil, nil) if not options[:init].nil? cli.setup(options) - cli.setup_gpg_key(options[:gpg_key]) if not config.check_gpg_key? + cli.setup_gpg_key(options[:init]) cli.setup_wallet_config - exit 0 +else + cli.set_config(options) end - -cli.set_config(options) diff --git a/bin/mpw-delete b/bin/mpw-delete index a7e95e8..7974ff6 100644 --- a/bin/mpw-delete +++ b/bin/mpw-delete @@ -29,11 +29,11 @@ options = {} OptionParser.new do |opts| opts.banner = "#{I18n.t('option.usage')}: mpw delete [options]" - opts.on('-c', '--config CONFIG', I18n.t('option.config')) do |config| + opts.on('-c', '--config PATH', I18n.t('option.config')) do |config| options[:config] = config end - opts.on('-g', '--group GROUP', I18n.t('option.config')) do |group| + opts.on('-g', '--group NAME', I18n.t('option.group')) do |group| options[:group] = group end @@ -42,11 +42,11 @@ OptionParser.new do |opts| exit 0 end - opts.on('-p', '--pattern PATTERN', I18n.t('option.config')) do |pattern| + opts.on('-p', '--pattern PATTERN', I18n.t('option.pattern')) do |pattern| options[:pattern] = pattern end - opts.on('-w', '--wallet WALLET', I18n.t('option.wallet')) do |wallet| + opts.on('-w', '--wallet NAME', I18n.t('option.wallet')) do |wallet| options[:wallet] = wallet end end.parse! diff --git a/bin/mpw-export b/bin/mpw-export index 700d067..15a9f9b 100644 --- a/bin/mpw-export +++ b/bin/mpw-export @@ -33,11 +33,11 @@ OptionParser.new do |opts| options[:config] = config end - opts.on('-f', '--file PATH', I18n.t('option.file')) do |file| + opts.on('-f', '--file PATH', I18n.t('option.file_export')) do |file| options[:file] = file end - opts.on('-g', '--group GROUP', I18n.t('option.config')) do |group| + opts.on('-g', '--group GROUP', I18n.t('option.group')) do |group| options[:group] = group end @@ -46,11 +46,11 @@ OptionParser.new do |opts| exit 0 end - opts.on('-p', '--pattern PATTERN', I18n.t('option.config')) do |pattern| + opts.on('-p', '--pattern PATTERN', I18n.t('option.pattern')) do |pattern| options[:pattern] = pattern end - opts.on('-w', '--wallet WALLET', I18n.t('option.wallet')) do |wallet| + opts.on('-w', '--wallet NAME', I18n.t('option.wallet')) do |wallet| options[:wallet] = wallet end end.parse! diff --git a/bin/mpw-genpwd b/bin/mpw-genpwd index c99d002..8af4290 100644 --- a/bin/mpw-genpwd +++ b/bin/mpw-genpwd @@ -22,7 +22,7 @@ require 'mpw/mpw' options = {} OptionParser.new do |opts| - opts.banner = "#{I18n.t('option.usage')}: mpw-passwd [options]" + opts.banner = "#{I18n.t('option.usage')}: mpw passwd [options]" opts.on('-h', '--help', I18n.t('option.help')) do puts opts diff --git a/bin/mpw-import b/bin/mpw-import index 61b5d8c..335ebf4 100644 --- a/bin/mpw-import +++ b/bin/mpw-import @@ -27,13 +27,13 @@ require 'mpw/cli' options = {} OptionParser.new do |opts| - opts.banner = "#{I18n.t('option.usage')}: mpw wallet [options]" + opts.banner = "#{I18n.t('option.usage')}: mpw import [options]" opts.on('-c', '--config PATH', I18n.t('option.config')) do |config| options[:config] = config end - opts.on('-f', '--file PATH', I18n.t('option.file')) do |file| + opts.on('-f', '--file PATH', I18n.t('option.file_import')) do |file| options[:file] = file end @@ -42,7 +42,7 @@ OptionParser.new do |opts| exit 0 end - opts.on('-w', '--wallet WALLET', I18n.t('option.wallet')) do |wallet| + opts.on('-w', '--wallet NAME', I18n.t('option.wallet')) do |wallet| options[:wallet] = wallet end end.parse! diff --git a/bin/mpw-list b/bin/mpw-list index 9bde1ff..984a3b0 100644 --- a/bin/mpw-list +++ b/bin/mpw-list @@ -29,11 +29,11 @@ options = {} OptionParser.new do |opts| opts.banner = "#{I18n.t('option.usage')}: mpw list [options]" - opts.on('-c', '--config CONFIG', I18n.t('option.config')) do |config| + opts.on('-c', '--config PATH', I18n.t('option.config')) do |config| options[:config] = config end - opts.on('-g', '--group GROUP', I18n.t('option.config')) do |group| + opts.on('-g', '--group NAME', I18n.t('option.group')) do |group| options[:group] = group end @@ -42,11 +42,11 @@ OptionParser.new do |opts| exit 0 end - opts.on('-p', '--pattern PATTERN', I18n.t('option.config')) do |pattern| + opts.on('-p', '--pattern PATTERN', I18n.t('option.pattern')) do |pattern| options[:pattern] = pattern end - opts.on('-w', '--wallet WALLET', I18n.t('option.wallet')) do |wallet| + opts.on('-w', '--wallet NAME', I18n.t('option.wallet')) do |wallet| options[:wallet] = wallet end end.parse! diff --git a/bin/mpw-update b/bin/mpw-update index e521ffc..cab7cbf 100644 --- a/bin/mpw-update +++ b/bin/mpw-update @@ -27,13 +27,13 @@ require 'mpw/cli' options = {} OptionParser.new do |opts| - opts.banner = "#{I18n.t('option.usage')}: mpw [options]" + opts.banner = "#{I18n.t('option.usage')}: mpw update [options]" - opts.on('-c', '--config CONFIG', I18n.t('option.config')) do |config| + opts.on('-c', '--config PATH', I18n.t('option.config')) do |config| options[:config] = config end - opts.on('-g', '--group GROUP', I18n.t('option.config')) do |group| + opts.on('-g', '--group NAME', I18n.t('option.group')) do |group| options[:group] = group end @@ -42,11 +42,11 @@ OptionParser.new do |opts| exit 0 end - opts.on('-p', '--pattern PATTERN', I18n.t('option.config')) do |pattern| + opts.on('-p', '--pattern PATTERN', I18n.t('option.pattern')) do |pattern| options[:pattern] = pattern end - opts.on('-w', '--wallet WALLET', I18n.t('option.wallet')) do |wallet| + opts.on('-w', '--wallet NAME', I18n.t('option.wallet')) do |wallet| options[:wallet] = wallet end end.parse! diff --git a/bin/mpw-wallet b/bin/mpw-wallet index c5fdc7a..7c52f1b 100644 --- a/bin/mpw-wallet +++ b/bin/mpw-wallet @@ -29,7 +29,7 @@ options = {} OptionParser.new do |opts| opts.banner = "#{I18n.t('option.usage')}: mpw wallet [options]" - opts.on('-c', '--config CONFIG', I18n.t('option.config')) do |config| + opts.on('-c', '--config PATH', I18n.t('option.config')) do |config| options[:config] = config end @@ -38,7 +38,7 @@ OptionParser.new do |opts| exit 0 end - opts.on('-w', '--wallet WALLET', I18n.t('option.wallet')) do |wallet| + opts.on('-w', '--wallet NAME', I18n.t('option.wallet')) do |wallet| options[:wallet] = wallet end end.parse! diff --git a/i18n/en.yml b/i18n/en.yml index 7c7bcc5..b4d2b15 100644 --- a/i18n/en.yml +++ b/i18n/en.yml @@ -39,15 +39,21 @@ en: config: "Specify the configuration file to use" clipboard: "Disable the clipboard feature" export: "Export a wallet in an yaml file" - file: "Specify a file, to use with the options [--import | --export | --add]" + file_export: "Specify the file where export data" + file_import: "Specify the file to import" force: "No ask to confirm when you delete an item" generate_password: "Generate a random password (default 8 characters)" + gpg_exe: "Set the gpg binary path to use" + gpg_key: "Specify a GPG key (ex: user@example.com)" group: "Search the items with specified group" help: "Show this help message" + init: "Initialize mpw" import: "Import item since a yaml file" - key: "Specify the key name, to use with the options [--add | --delete | --update]" + key: "Specify the key name" + lang: "Set the software language" no_sync: "Disable synchronization with the server" numeric: "Use number to generate a password" + pattern: "Given search pattern" setup: "Create a new configuration file" setup_wallet: "Create a new configuration file for a wallet" special_chars: "Use special char to generate a password" @@ -55,6 +61,7 @@ en: show_all: "List all items" usage: "Usage" wallet: "Specify a wallet to use" + wallet_dir: "Set the wallets folder" form: select: "Select the item: " diff --git a/i18n/fr.yml b/i18n/fr.yml index a5d7aff..f7233af 100644 --- a/i18n/fr.yml +++ b/i18n/fr.yml @@ -39,15 +39,21 @@ fr: config: "Spécifie le fichier de configuration à utiliser" clipboard: "Désactive la fonction presse papier" export: "Exporte un portefeuille dans un fichier yaml" - file: "Spécifie un fichier, à utiliser avec les options [--import | --export | --add]" + file_export: "Spécifie le fichier où exporter les données" + file_import: "Spécifie le fichier à importer" force: "Ne demande pas de confirmation pour la suppression d'un élément" generate_password: "Génére un mot de passe aléatoire (défaut 8 caractères)" + gpg_exe: "Spécifie le chemin du binaire gpg à utiliser" + gpg_key: "Spécifie une clé GPG (ex: user@example.com)" group: "Recherche les éléments appartenant au groupe spécifié" help: "Affiche ce message d'aide" import: "Importe des éléments depuis un fichier yaml" - key: "Spécifie le nom d'une clé, à utiliser avec les options [--add | --delete | --update]" + init: "Initialise mpw" + key: "Spécifie le nom d'une clé" + lang: "Spécifie la langue du logiciel (ex: fr)" no_sync: "Désactive la synchronisation avec le serveur" numeric: "Utilise des chiffre dans la génération d'un mot de passe" + pattern: "Motif de donnée à chercher" setup: "Création d'un nouveau fichier de configuration" setup_wallet: "Création d'un nouveau fichier de configuration pour un portefeuille" special_chars: "Utilise des charactères speciaux dans la génération d'un mot de passe" @@ -55,6 +61,7 @@ fr: show_all: "Liste tous les éléments" usage: "Utilisation" wallet: "Spécifie le portefeuille à utiliser" + wallet_dir: "Spécifie le répertoire des portefeuilles" form: select: "Sélectionner l'élément: " From 1745585fb8aa17f61b297c5e1da63ad52ac83c40 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Thu, 20 Oct 2016 08:51:59 +0200 Subject: [PATCH 343/531] remove unused contructor variables --- bin/mpw-add | 2 +- bin/mpw-config | 2 +- bin/mpw-delete | 2 +- bin/mpw-export | 2 +- bin/mpw-import | 2 +- bin/mpw-list | 2 +- bin/mpw-update | 2 +- bin/mpw-wallet | 2 +- lib/mpw/cli.rb | 6 +----- 9 files changed, 9 insertions(+), 13 deletions(-) diff --git a/bin/mpw-add b/bin/mpw-add index 883f75d..1e09e07 100644 --- a/bin/mpw-add +++ b/bin/mpw-add @@ -44,7 +44,7 @@ OptionParser.new do |opts| end.parse! config = MPW::Config.new(options[:config]) -cli = MPW::Cli.new(config, nil, options[:sync], nil) +cli = MPW::Cli.new(config, options[:sync]) cli.get_wallet(options[:wallet]) cli.decrypt diff --git a/bin/mpw-config b/bin/mpw-config index a215150..a1b0743 100644 --- a/bin/mpw-config +++ b/bin/mpw-config @@ -60,7 +60,7 @@ OptionParser.new do |opts| end.parse! config = MPW::Config.new(options[:config]) -cli = MPW::Cli.new(config, nil, nil, nil) +cli = MPW::Cli.new(config, nil) if not options[:init].nil? cli.setup(options) diff --git a/bin/mpw-delete b/bin/mpw-delete index 7974ff6..3dc0cd7 100644 --- a/bin/mpw-delete +++ b/bin/mpw-delete @@ -52,7 +52,7 @@ OptionParser.new do |opts| end.parse! config = MPW::Config.new(options[:config]) -cli = MPW::Cli.new(config, nil, options[:sync], nil) +cli = MPW::Cli.new(config, options[:sync]) opts = { search: options[:pattern], group: options[:group], diff --git a/bin/mpw-export b/bin/mpw-export index 15a9f9b..4a174aa 100644 --- a/bin/mpw-export +++ b/bin/mpw-export @@ -56,7 +56,7 @@ OptionParser.new do |opts| end.parse! config = MPW::Config.new(options[:config]) -cli = MPW::Cli.new(config, nil, options[:sync], nil) +cli = MPW::Cli.new(config, options[:sync]) opts = { search: options[:pattern], group: options[:group], diff --git a/bin/mpw-import b/bin/mpw-import index 335ebf4..8881441 100644 --- a/bin/mpw-import +++ b/bin/mpw-import @@ -48,7 +48,7 @@ OptionParser.new do |opts| end.parse! config = MPW::Config.new(options[:config]) -cli = MPW::Cli.new(config, nil, options[:sync], nil) +cli = MPW::Cli.new(config, options[:sync]) opts = { search: options[:pattern], group: options[:group], diff --git a/bin/mpw-list b/bin/mpw-list index 984a3b0..2b503cf 100644 --- a/bin/mpw-list +++ b/bin/mpw-list @@ -52,7 +52,7 @@ OptionParser.new do |opts| end.parse! config = MPW::Config.new(options[:config]) -cli = MPW::Cli.new(config, nil, options[:sync], nil) +cli = MPW::Cli.new(config, options[:sync]) opts = { search: options[:pattern], group: options[:group], diff --git a/bin/mpw-update b/bin/mpw-update index cab7cbf..7e6519d 100644 --- a/bin/mpw-update +++ b/bin/mpw-update @@ -52,7 +52,7 @@ OptionParser.new do |opts| end.parse! config = MPW::Config.new(options[:config]) -cli = MPW::Cli.new(config, nil, options[:sync], nil) +cli = MPW::Cli.new(config, options[:sync]) opts = { search: options[:pattern], group: options[:group], diff --git a/bin/mpw-wallet b/bin/mpw-wallet index 7c52f1b..790509f 100644 --- a/bin/mpw-wallet +++ b/bin/mpw-wallet @@ -44,6 +44,6 @@ OptionParser.new do |opts| end.parse! config = MPW::Config.new(options[:config]) -cli = MPW::Cli.new(config, nil, options[:sync], nil) +cli = MPW::Cli.new(config, options[:sync]) cli.list_wallet diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index 8fc109b..e7764f2 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -32,13 +32,9 @@ class Cli # Constructor # @args: config -> the config # sync -> boolean for sync or not - # clipboard -> enable clopboard - # otp -> enable otp - def initialize(config, clipboard=true, sync=true, otp=false) + def initialize(config,sync=true) @config = config - @clipboard = clipboard @sync = sync - @otp = otp end # Change a parameter int the config after init From fdc1a6f3ec0115867bac58249210b19e8519f2c0 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Thu, 20 Oct 2016 09:23:26 +0200 Subject: [PATCH 344/531] new binary for copy --- bin/mpw-copy | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++ i18n/en.yml | 3 +-- i18n/fr.yml | 3 +-- lib/mpw/cli.rb | 26 ++++++++++++++------- 4 files changed, 83 insertions(+), 12 deletions(-) create mode 100644 bin/mpw-copy diff --git a/bin/mpw-copy b/bin/mpw-copy new file mode 100644 index 0000000..c49d361 --- /dev/null +++ b/bin/mpw-copy @@ -0,0 +1,63 @@ +#!/usr/bin/ruby +# MPW is a software to crypt and manage your passwords +# Copyright (C) 2016 Adrien Waksberg <mpw@yae.im> +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +require 'optparse' +require 'mpw/config' +require 'mpw/cli' + +# --------------------------------------------------------- # +# Options +# --------------------------------------------------------- # + +options = {} + +OptionParser.new do |opts| + opts.banner = "#{I18n.t('option.usage')}: mpw copy [options]" + + opts.on('-c', '--config PATH', I18n.t('option.config')) do |config| + options[:config] = config + end + + opts.on('-g', '--group NAME', I18n.t('option.group')) do |group| + options[:group] = group + end + + opts.on('-h', '--help', I18n.t('option.help')) do + puts opts + exit 0 + end + + opts.on('-p', '--pattern PATTERN', I18n.t('option.pattern')) do |pattern| + options[:pattern] = pattern + end + + opts.on('-w', '--wallet NAME', I18n.t('option.wallet')) do |wallet| + options[:wallet] = wallet + end +end.parse! + +config = MPW::Config.new(options[:config]) +cli = MPW::Cli.new(config, options[:sync]) + +opts = { search: options[:pattern], + group: options[:group], + } + +cli.get_wallet(options[:wallet]) +cli.decrypt +cli.copy(opts) diff --git a/i18n/en.yml b/i18n/en.yml index b4d2b15..cf10200 100644 --- a/i18n/en.yml +++ b/i18n/en.yml @@ -89,8 +89,7 @@ en: login: "Press <l> to copy the login" password: "Press <p> to copy the password" otp_code: "Press <o> to copy the otp code" - update: "Press <u> to update the item" - delete: "Press <d> to delete the item" + quit: "Press <q> to quit" delete_key: valid: "Key has been deleted!" delete_item: diff --git a/i18n/fr.yml b/i18n/fr.yml index f7233af..8e878a1 100644 --- a/i18n/fr.yml +++ b/i18n/fr.yml @@ -89,8 +89,7 @@ fr: login: "Pressez <l> pour copier l'identifiant" password: "Pressez <p> pour copier le mot de passe" otp_code: "Pressez <o> pour copier le code OTP" - update: "Pressez <u> pour mettre à jour l'élément" - delete: "Pressez <d> pour supprimer l'élément" + quit: "Pressez <q> pour quitter" delete_key: valid: "La clé a bien été supprimée!" delete_item: diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index e7764f2..8bfa7bd 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -314,19 +314,12 @@ class Cli Clipboard.copy(@mpw.get_otp_code(item.id)) puts I18n.t('form.clipboard.otp', time: @mpw.get_otp_remaining_time).yellow - when 'd', 'delete' - break if delete(item) - - when 'u', 'update', 'e', 'edit' - update(item) - else puts "----- #{I18n.t('form.clipboard.help.name')} -----".cyan puts I18n.t('form.clipboard.help.login') puts I18n.t('form.clipboard.help.password') puts I18n.t('form.clipboard.help.otp_code') - puts I18n.t('form.clipboard.help.update') - puts I18n.t('form.clipboard.help.delete') + puts I18n.t('form.clipboard.help.quit') next end end @@ -489,6 +482,23 @@ class Cli puts "#{I18n.t('display.error')} #16: #{e}".red end + # Copy a password, otp, login + # @args: options -> the option to search + def copy(options={}) + items = @mpw.list(options) + + if items.length == 0 + puts "#{I18n.t('display.warning')}: #{I18n.t('warning.select')}".yellow + else + table(items) + + item = get_item(items) + clipboard(item) + end + rescue Exception => e + puts "#{I18n.t('display.error')} #14: #{e}".red + end + # Export the items in a CSV file # @args: file -> the destination file # options -> option to search From f5746d6af66fdd17e152cee4cb543da9080040ee Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Thu, 20 Oct 2016 10:24:04 +0200 Subject: [PATCH 345/531] improve table --- lib/mpw/cli.rb | 77 +++++++++++++++++++++++++++----------------------- 1 file changed, 42 insertions(+), 35 deletions(-) diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index 8bfa7bd..3779148 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -143,22 +143,26 @@ class Cli group = '.' i = 1 length_total = 10 - length = { id: 3, - host: 10, - user: 8, - comment: 15, - otp: 5, + data = { id: { length: 3, color: 'cyan' }, + host: { length: 9, color: 'yellow' }, + user: { length: 7, color: 'green' }, + protocol: { length: 9, color: 'white' }, + port: { length: 5, color: 'white' }, + otp: { length: 4, color: 'white' }, + comment: { length: 14, color: 'magenta' }, } items.each do |item| - length[:host] = item.host.length + 3 if item.host.to_s.length > length[:host] - length[:user] = item.user.length + 3 if item.user.to_s.length > length[:user] - length[:comment] = item.comment.length + 3 if item.comment.to_s.length > length[:comment] + data.each do |k, v| + next if k == :id or k == :otp + + v[:length] = item.send(k.to_s).length + 3 if item.send(k.to_s).to_s.length > v[:length] + end end - length[:id] = items.length.to_s.length + 2 if items.length.to_s.length > length[:id] + data[:id][:length] = items.length.to_s.length + 2 if items.length.to_s.length > data[:id][:length] - length.each_value { |v| length_total += v } - items.sort! { |a,b| a.group.to_s.downcase <=> b.group.to_s.downcase } + data.each_value { |v| length_total += v[:length] } + items.sort! { |a, b| a.group.to_s.downcase <=> b.group.to_s.downcase } items.each do |item| if group != item.group @@ -173,36 +177,39 @@ class Cli print ' ' length_total.times { print '=' } print "\n " - print ' ID ' - print '| Host' - (length[:host] - 'Host'.length).times { print ' ' } - print '| User' - (length[:user] - 'User'.length).times { print ' ' } - print '| OTP ' - print '| Comment' - (length[:comment] - 'Comment'.length).times { print ' ' } + data.each do |k, v| + case k + when :id + print ' ID' + when :otp + print '| OTP' + else + print "| #{k.to_s.capitalize}" + end + + (v[:length] - k.to_s.length).times { print ' ' } + end print "\n " length_total.times { print '=' } print "\n" end - print " #{i}".cyan - (length[:id] - i.to_s.length).times { print ' ' } - print '| ' - print "#{item.host}".yellow - (length[:host] - item.host.to_s.length).times { print ' ' } - print '| ' - print "#{item.user}".green - (length[:user] - item.user.to_s.length).times { print ' ' } - print '| ' - if item.otp - print ' X ' - else - 4.times { print ' ' } + print " #{i}".send(data[:id][:color]) + (data[:id][:length] - i.to_s.length).times { print ' ' } + data.each do |k, v| + next if k == :id + + if k == :otp + print '| ' + if item.otp; print ' X ' else 4.times { print ' ' } end + + next + end + + print '| ' + print "#{item.send(k.to_s)}".send(v[:color]) + (v[:length] - item.send(k.to_s).to_s.length).times { print ' ' } end - print '| ' - print "#{item.comment}".magenta - (length[:comment] - item.comment.to_s.length).times { print ' ' } print "\n" i += 1 From 73312b933ffaf182a66a0176e1643099679f5208 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Thu, 20 Oct 2016 13:49:17 +0200 Subject: [PATCH 346/531] copy: disable clipboard option --- bin/mpw-copy | 7 ++++++- lib/mpw/cli.rb | 38 ++++++++++++++++++++++++++------------ 2 files changed, 32 insertions(+), 13 deletions(-) diff --git a/bin/mpw-copy b/bin/mpw-copy index c49d361..b4d770c 100644 --- a/bin/mpw-copy +++ b/bin/mpw-copy @@ -25,6 +25,7 @@ require 'mpw/cli' # --------------------------------------------------------- # options = {} +options[:clipboard] = true OptionParser.new do |opts| opts.banner = "#{I18n.t('option.usage')}: mpw copy [options]" @@ -33,6 +34,10 @@ OptionParser.new do |opts| options[:config] = config end + opts.on('-d', '--disable-clipboard', I18n.t('option.clipboard')) do + options[:clipboard] = false + end + opts.on('-g', '--group NAME', I18n.t('option.group')) do |group| options[:group] = group end @@ -60,4 +65,4 @@ opts = { search: options[:pattern], cli.get_wallet(options[:wallet]) cli.decrypt -cli.copy(opts) +cli.copy(options[:clipboard], opts) diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index 3779148..617b58d 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -287,7 +287,8 @@ class Cli # Copy in clipboard the login and password # @args: item -> the item - def clipboard(item) + # clipboard -> enable clipboard + def clipboard(item, clipboard=true) pid = nil # Security: force quit after 90s @@ -304,21 +305,33 @@ class Cli break when 'l', 'login' - Clipboard.copy(item.user) - puts I18n.t('form.clipboard.login').green + if clipboard + Clipboard.copy(item.user) + puts I18n.t('form.clipboard.login').green + else + puts item.user + end when 'p', 'password' - Clipboard.copy(@mpw.get_password(item.id)) - puts I18n.t('form.clipboard.password').yellow + if clipboard + Clipboard.copy(@mpw.get_password(item.id)) + puts I18n.t('form.clipboard.password').yellow - Thread.new do - sleep 30 + Thread.new do + sleep 30 - Clipboard.clear + Clipboard.clear + end + else + puts @mpw.get_password(item.id) end when 'o', 'otp' - Clipboard.copy(@mpw.get_otp_code(item.id)) + if clipboard + Clipboard.copy(@mpw.get_otp_code(item.id)) + else + puts @mpw.get_otp_code(item.id) + end puts I18n.t('form.clipboard.otp', time: @mpw.get_otp_remaining_time).yellow else @@ -490,8 +503,9 @@ class Cli end # Copy a password, otp, login - # @args: options -> the option to search - def copy(options={}) + # @args: clipboard -> enable clipboard + # options -> the option to search + def copy(clipboard=true, options={}) items = @mpw.list(options) if items.length == 0 @@ -500,7 +514,7 @@ class Cli table(items) item = get_item(items) - clipboard(item) + clipboard(item, clipboard) end rescue Exception => e puts "#{I18n.t('display.error')} #14: #{e}".red From 2e32b223b0e97fa6b87204d56cb80252b2d06565 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Thu, 20 Oct 2016 14:25:42 +0200 Subject: [PATCH 347/531] remove old function display --- lib/mpw/cli.rb | 38 -------------------------------------- 1 file changed, 38 deletions(-) diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index 617b58d..3420bc1 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -247,44 +247,6 @@ class Cli end end - # Display an item in the default format - # @args: item -> an array with the item information - def display_item(item) - puts '--------------------'.cyan - print 'Id: '.cyan - puts item.id - print "#{I18n.t('display.name')}: ".cyan - puts item.name - print "#{I18n.t('display.group')}: ".cyan - puts item.group - print "#{I18n.t('display.server')}: ".cyan - puts item.host - print "#{I18n.t('display.protocol')}: ".cyan - puts item.protocol - print "#{I18n.t('display.login')}: ".cyan - puts item.user - - if @clipboard - print "#{I18n.t('display.password')}: ".cyan - puts '***********' - else - print "#{I18n.t('display.password')}: ".cyan - puts @mpw.get_password(item.id) - - if @mpw.get_otp_code(item.id) > 0 - print "#{I18n.t('display.otp_code')}: ".cyan - puts "#{@mpw.get_otp_code(item.id)} (#{@mpw.get_otp_remaining_time}s)" - end - end - - print "#{I18n.t('display.port')}: ".cyan - puts item.port - print "#{I18n.t('display.comment')}: ".cyan - puts item.comment - - clipboard(item) if @clipboard - end - # Copy in clipboard the login and password # @args: item -> the item # clipboard -> enable clipboard From 580c5b419388d1cd7cdb169e4d050ecf8e8e036f Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Thu, 20 Oct 2016 14:31:25 +0200 Subject: [PATCH 348/531] add random password when create new item --- bin/mpw-add | 6 +++++- lib/mpw/cli.rb | 15 ++++++++++++--- templates/add_form.erb | 4 ++-- 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/bin/mpw-add b/bin/mpw-add index 1e09e07..542b884 100644 --- a/bin/mpw-add +++ b/bin/mpw-add @@ -38,6 +38,10 @@ OptionParser.new do |opts| exit 0 end + opts.on('-r', '--random', I18n.t('option.random_password')) do + options[:password] = true + end + opts.on('-w', '--wallet NAME', I18n.t('option.wallet')) do |wallet| options[:wallet] = wallet end @@ -48,4 +52,4 @@ cli = MPW::Cli.new(config, options[:sync]) cli.get_wallet(options[:wallet]) cli.decrypt -cli.add +cli.add(options[:password]) diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index 3420bc1..b52a63b 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -368,7 +368,11 @@ class Cli puts "#{I18n.t('display.error')} #15: #{e}".red end - def text_editor(template_name, item=nil) + # Text editor interface + # @args: template -> template name + # item -> the item to edit + # password -> disable field password + def text_editor(template_name, item=nil, password=false) editor = ENV['EDITOR'] || 'nano' options = {} opts = {} @@ -397,10 +401,15 @@ class Cli end # Form to add a new item - def add - options = text_editor('add_form') + # @args: password -> generate a random password + def add(password=false) + options = text_editor('add_form', nil, password) item = Item.new(options) + if password + options[:password] = MPW::password(length: 24) + end + @mpw.add(item) @mpw.set_password(item.id, options[:password]) if options.has_key?(:password) @mpw.set_otp_key(item.id, options[:otp_key]) if options.has_key?(:otp_key) diff --git a/templates/add_form.erb b/templates/add_form.erb index f4f8cae..c2d6d73 100644 --- a/templates/add_form.erb +++ b/templates/add_form.erb @@ -2,8 +2,8 @@ host: # <%= I18n.t('form.add_item.host') %> user: # <%= I18n.t('form.add_item.login') %> group: # <%= I18n.t('form.add_item.group') %> -protocol: # <%= I18n.t('form.add_item.protocol') %> -password: # <%= I18n.t('form.add_item.password') %> +protocol: # <%= I18n.t('form.add_item.protocol') %><% if not password %> +password: # <%= I18n.t('form.add_item.password') %><% end %> port: # <%= I18n.t('form.add_item.port') %> comment: # <%= I18n.t('form.add_item.comment') %> otp_key: # <%= I18n.t('form.add_item.otp_key') %> From 337f1e2314e147319fef2fe03858c59e73e69af6 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Thu, 20 Oct 2016 18:25:30 +0200 Subject: [PATCH 349/531] set wallet config --- bin/mpw-wallet | 37 ++++++++++++++++++++++++++++++++++++- i18n/en.yml | 7 +++++++ i18n/fr.yml | 7 +++++++ lib/mpw/cli.rb | 26 ++++++++------------------ lib/mpw/mpw.rb | 29 +++++++++++++---------------- 5 files changed, 71 insertions(+), 35 deletions(-) diff --git a/bin/mpw-wallet b/bin/mpw-wallet index 790509f..0184d85 100644 --- a/bin/mpw-wallet +++ b/bin/mpw-wallet @@ -25,6 +25,7 @@ require 'mpw/cli' # --------------------------------------------------------- # options = {} +values = {} OptionParser.new do |opts| opts.banner = "#{I18n.t('option.usage')}: mpw wallet [options]" @@ -38,6 +39,34 @@ OptionParser.new do |opts| exit 0 end + opts.on('--host NAME', I18n.t('option.host')) do |host| + values[:host] = host + end + + opts.on('-l', '--list', I18n.t('option.list')) do |list| + options[:list] = true + end + + opts.on('--password', I18n.t('option.password')) do + values[:password] = true + end + + opts.on('--path PATH', I18n.t('option.path')) do |path| + values[:path] = path + end + + opts.on('--port NUMBER', I18n.t('option.port')) do |port| + values[:port] = port + end + + opts.on('--protocol NAME', I18n.t('option.protocol')) do |protocol| + values[:protocol] = protocol + end + + opts.on('--user NAME', I18n.t('option.user')) do |user| + values[:user] = user + end + opts.on('-w', '--wallet NAME', I18n.t('option.wallet')) do |wallet| options[:wallet] = wallet end @@ -46,4 +75,10 @@ end.parse! config = MPW::Config.new(options[:config]) cli = MPW::Cli.new(config, options[:sync]) -cli.list_wallet +if not options[:list].nil? + cli.list_wallet +else + cli.get_wallet(options[:wallet]) + cli.decrypt + cli.setup_wallet_config(values) +end diff --git a/i18n/en.yml b/i18n/en.yml index cf10200..e88f360 100644 --- a/i18n/en.yml +++ b/i18n/en.yml @@ -47,19 +47,26 @@ en: gpg_key: "Specify a GPG key (ex: user@example.com)" group: "Search the items with specified group" help: "Show this help message" + host: "Specify the server for the synchronization" init: "Initialize mpw" import: "Import item since a yaml file" key: "Specify the key name" lang: "Set the software language" + list: "List the wallets" no_sync: "Disable synchronization with the server" numeric: "Use number to generate a password" + password: "Change the password for the synchronization" + path: "Specify the remote path" pattern: "Given search pattern" + port: "Specify the connection port" + protocol: "Specify the protocol for the connection" setup: "Create a new configuration file" setup_wallet: "Create a new configuration file for a wallet" special_chars: "Use special char to generate a password" show: "Search and show the items" show_all: "List all items" usage: "Usage" + user: "Specify the user for the connection" wallet: "Specify a wallet to use" wallet_dir: "Set the wallets folder" diff --git a/i18n/fr.yml b/i18n/fr.yml index 8e878a1..903cba6 100644 --- a/i18n/fr.yml +++ b/i18n/fr.yml @@ -47,19 +47,26 @@ fr: gpg_key: "Spécifie une clé GPG (ex: user@example.com)" group: "Recherche les éléments appartenant au groupe spécifié" help: "Affiche ce message d'aide" + host: "Spécifie le serveur pour la synchronisation" import: "Importe des éléments depuis un fichier yaml" init: "Initialise mpw" key: "Spécifie le nom d'une clé" lang: "Spécifie la langue du logiciel (ex: fr)" + list: "Liste les portefeuilles" no_sync: "Désactive la synchronisation avec le serveur" numeric: "Utilise des chiffre dans la génération d'un mot de passe" + password: "Changer le mot de passe de connexion" + path: "Spécifie le chemin distant" pattern: "Motif de donnée à chercher" + port: "Spécifie le port de connexion" + protocol: "Spécifie le protocol utilisé pour la connexion" setup: "Création d'un nouveau fichier de configuration" setup_wallet: "Création d'un nouveau fichier de configuration pour un portefeuille" special_chars: "Utilise des charactères speciaux dans la génération d'un mot de passe" show: "Recherche et affiche les éléments" show_all: "Liste tous les éléments" usage: "Utilisation" + user: "Spécifie l'identifiant de connection" wallet: "Spécifie le portefeuille à utiliser" wallet_dir: "Spécifie le répertoire des portefeuilles" diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index b52a63b..464d098 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -95,27 +95,17 @@ class Cli end # Setup wallet config for sync - # @args: wallet -> the wallet name - def setup_wallet_config(wallet = nil) - #config = {} - #config['sync'] = {} + # @args: options -> value to change + def setup_wallet_config(options={}) + if not options[:password].nil? + options[:password] = ask(I18n.t('form.setup_wallet.password')) {|q| q.echo = false} + end - #puts '--------------------' - #config['sync']['type'] = ask(I18n.t('form.setup_wallet.sync_type')).to_s + #wallet_file = wallet.nil? ? "#{@config.wallet_dir}/default.mpw" : "#{@config.wallet_dir}/#{wallet}.mpw" - #if ['ftp', 'ssh'].include?(config['sync']['type'].downcase) - # config['sync']['host'] = ask(I18n.t('form.setup_wallet.sync_host')).to_s - # config['sync']['port'] = ask(I18n.t('form.setup_wallet.sync_port')).to_s - # config['sync']['user'] = ask(I18n.t('form.setup_wallet.sync_user')).to_s - # config['sync']['password'] = ask(I18n.t('form.setup_wallet.sync_pwd')).to_s - # config['sync']['path'] = ask(I18n.t('form.setup_wallet.sync_path')).to_s - #end - - wallet_file = wallet.nil? ? "#{@config.wallet_dir}/default.mpw" : "#{@config.wallet_dir}/#{wallet}.mpw" - - @mpw = MPW.new(@config.key, wallet_file, @password, @config.gpg_exe) + @mpw = MPW.new(@config.key, @wallet_file, @password, @config.gpg_exe) @mpw.read_data - @mpw.set_config + @mpw.set_config(options) @mpw.write_data puts "#{I18n.t('form.setup_wallet.valid')}".green diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index a0c4c6e..0727636 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -210,19 +210,16 @@ class MPW # Set config # args: config -> a hash with config options - def set_config(config=nil) - @config = {} if @config.nil? - @config['sync'] = {} if @config['sync'].nil? + def set_config(options={}) + @config = {} if @config.nil? - return if config.to_s.empty? - - @config['sync']['type'] = config['sync']['type'] - @config['sync']['host'] = config['sync']['host'] - @config['sync']['port'] = config['sync']['port'] - @config['sync']['user'] = config['sync']['user'] - @config['sync']['password'] = config['sync']['password'] - @config['sync']['path'] = config['sync']['path'] - @config['sync']['last_sync'] = @config['sync']['last_sync'].nil? ? 0 : @config['sync']['last_sync'] + @config['protocol'] = options[:protocol] if options.has_key?(:protocol) + @config['host'] = options[:host] if options.has_key?(:host) + @config['port'] = options[:port] if options.has_key?(:port) + @config['user'] = options[:user] if options.has_key?(:user) + @config['password'] = options[:password] if options.has_key?(:password) + @config['path'] = options[:path] if options.has_key?(:path) + @config['last_sync'] = @config['last_sync'].nil? ? 0 : @config['last_sync'] end # Add a new item @@ -276,7 +273,7 @@ class MPW # Get last sync def get_last_sync - return @config['sync']['last_sync'].to_i + return @config['last_sync'].to_i rescue return 0 end @@ -284,12 +281,12 @@ class MPW # Sync data with remote file # @args: force -> force the sync def sync(force=false) - return if @config.empty? or @config['sync']['type'].to_s.empty? + return if @config.empty? or @config['protocol'].to_s.empty? return if get_last_sync + 300 > Time.now.to_i and not force tmp_file = "#{@wallet_file}.sync" - case @config['sync']['type'] + case @config['protocol'] when 'sftp', 'scp', 'ssh' require "mpw/sync/ssh" sync = SyncSSH.new(@config['sync']) @@ -367,7 +364,7 @@ class MPW item.set_last_sync end - @config['sync']['last_sync'] = Time.now.to_i + @config['last_sync'] = Time.now.to_i write_data sync.update(@wallet_file) From 7b301519b64213b9765c1e7e7bbefaeefc680e67 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Thu, 20 Oct 2016 21:25:43 +0200 Subject: [PATCH 350/531] config: fix init with existing gpg key --- bin/mpw-config | 17 ++++++++++------- lib/mpw/cli.rb | 11 +++++------ 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/bin/mpw-config b/bin/mpw-config index a1b0743..b0a1863 100644 --- a/bin/mpw-config +++ b/bin/mpw-config @@ -25,6 +25,7 @@ require 'mpw/cli' # --------------------------------------------------------- # options = {} +values = {} OptionParser.new do |opts| opts.banner = "#{I18n.t('option.usage')}: mpw config [options]" @@ -34,7 +35,7 @@ OptionParser.new do |opts| end opts.on('-g', '--gpg-exe PATH', I18n.t('option.gpg_exe')) do |gpg_exe| - options[:gpg_exe] = gpg_exe + values[:gpg_exe] = gpg_exe end opts.on('-h', '--help', I18n.t('option.help')) do @@ -43,19 +44,20 @@ OptionParser.new do |opts| end opts.on('-i', '--init GPG_KEY', I18n.t('option.init')) do |gpg_key| - options[:init] = gpg_key + options[:init] = true + values[:gpg_key] = gpg_key end opts.on('-k', '--key GPG_KEY', I18n.t('option.gpg_key')) do |gpg_key| - options[:gpg_key] = gpg_key + values[:gpg_key] = gpg_key end opts.on('-l', '--lang LANG', I18n.t('option.lang')) do |lang| - options[:lang] = lang + values[:lang] = lang end opts.on('-w', '--wallet-dir PATH', I18n.t('option.wallet_dir')) do |wallet_dir| - options[:wallet_dir] = wallet_dir + values[:wallet_dir] = wallet_dir end end.parse! @@ -63,9 +65,10 @@ config = MPW::Config.new(options[:config]) cli = MPW::Cli.new(config, nil) if not options[:init].nil? - cli.setup(options) + cli.get_wallet + cli.setup(values) cli.setup_gpg_key(options[:init]) cli.setup_wallet_config else - cli.set_config(options) + cli.set_config(values) end diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index 464d098..b0161a1 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -32,7 +32,7 @@ class Cli # Constructor # @args: config -> the config # sync -> boolean for sync or not - def initialize(config,sync=true) + def initialize(config, sync=true) @config = config @sync = sync end @@ -54,7 +54,7 @@ class Cli end # Create a new config file - # @args: language -> the software language + # @args: options -> set param def setup(options) @config.is_valid? @@ -75,6 +75,8 @@ class Cli # Setup a new GPG key # @args: gpg_key -> the key name def setup_gpg_key(gpg_key) + return if @config.check_gpg_key? + password = ask(I18n.t('form.setup_gpg_key.password')) {|q| q.echo = false} confirm = ask(I18n.t('form.setup_gpg_key.confirm_password')) {|q| q.echo = false} @@ -320,10 +322,7 @@ class Cli if wallet.to_s.empty? wallets = Dir.glob("#{@config.wallet_dir}/*.mpw") - case wallets.length - when 0 - puts I18n.t('display.nothing') - when 1 + if wallets.length == 1 @wallet_file = wallets[0] else @wallet_file = "#{@config.wallet_dir}/default.mpw" From e4c03619b380725e19fd0e2767450970b709ef1e Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Thu, 20 Oct 2016 21:25:58 +0200 Subject: [PATCH 351/531] minor fix --- lib/mpw/config.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/mpw/config.rb b/lib/mpw/config.rb index b504c2a..148ecf1 100644 --- a/lib/mpw/config.rb +++ b/lib/mpw/config.rb @@ -88,9 +88,9 @@ class Config # expire -> the time of expire to GPG key # @rtrn: true if the GPG key is create, else false def setup_gpg_key(password, name, length = 4096, expire = 0) - if name.nil? or name.empty? + if name.to_s.empty? raise "#{I18n.t('error.config.genkey_gpg.name')}" - elsif password.nil? or password.empty? + elsif password.to_s.empty? raise "#{I18n.t('error.config.genkey_gpg.password')}" end From 6d2a45217c8aeda5594065daaf1d36d6c1bb52dc Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Sun, 23 Oct 2016 21:54:46 +0200 Subject: [PATCH 352/531] fix load config --- bin/mpw-add | 1 + bin/mpw-config | 1 + bin/mpw-copy | 1 + bin/mpw-delete | 1 + bin/mpw-export | 1 + bin/mpw-import | 1 + bin/mpw-list | 1 + bin/mpw-update | 1 + bin/mpw-wallet | 2 ++ i18n/en.yml | 2 +- i18n/fr.yml | 2 +- lib/mpw/cli.rb | 19 ++++++++++--------- lib/mpw/config.rb | 27 ++++++++++++--------------- 13 files changed, 34 insertions(+), 26 deletions(-) diff --git a/bin/mpw-add b/bin/mpw-add index 542b884..a0e450f 100644 --- a/bin/mpw-add +++ b/bin/mpw-add @@ -50,6 +50,7 @@ end.parse! config = MPW::Config.new(options[:config]) cli = MPW::Cli.new(config, options[:sync]) +cli.load_config cli.get_wallet(options[:wallet]) cli.decrypt cli.add(options[:password]) diff --git a/bin/mpw-config b/bin/mpw-config index b0a1863..133f3c4 100644 --- a/bin/mpw-config +++ b/bin/mpw-config @@ -65,6 +65,7 @@ config = MPW::Config.new(options[:config]) cli = MPW::Cli.new(config, nil) if not options[:init].nil? + cli.load_config cli.get_wallet cli.setup(values) cli.setup_gpg_key(options[:init]) diff --git a/bin/mpw-copy b/bin/mpw-copy index b4d770c..e9ae66b 100644 --- a/bin/mpw-copy +++ b/bin/mpw-copy @@ -63,6 +63,7 @@ opts = { search: options[:pattern], group: options[:group], } +cli.load_config cli.get_wallet(options[:wallet]) cli.decrypt cli.copy(options[:clipboard], opts) diff --git a/bin/mpw-delete b/bin/mpw-delete index 3dc0cd7..e2d1195 100644 --- a/bin/mpw-delete +++ b/bin/mpw-delete @@ -58,6 +58,7 @@ opts = { search: options[:pattern], group: options[:group], } +cli.load_config cli.get_wallet(options[:wallet]) cli.decrypt cli.delete(opts) diff --git a/bin/mpw-export b/bin/mpw-export index 4a174aa..be15bb5 100644 --- a/bin/mpw-export +++ b/bin/mpw-export @@ -62,6 +62,7 @@ opts = { search: options[:pattern], group: options[:group], } +cli.load_config cli.get_wallet(options[:wallet]) cli.decrypt cli.export(options[:file], opts) diff --git a/bin/mpw-import b/bin/mpw-import index 8881441..ad52f57 100644 --- a/bin/mpw-import +++ b/bin/mpw-import @@ -54,6 +54,7 @@ opts = { search: options[:pattern], group: options[:group], } +cli.load_config cli.get_wallet(options[:wallet]) cli.decrypt cli.import(options[:file]) diff --git a/bin/mpw-list b/bin/mpw-list index 2b503cf..1c729cc 100644 --- a/bin/mpw-list +++ b/bin/mpw-list @@ -58,6 +58,7 @@ opts = { search: options[:pattern], group: options[:group], } +cli.load_config cli.get_wallet(options[:wallet]) cli.decrypt cli.list(opts) diff --git a/bin/mpw-update b/bin/mpw-update index 7e6519d..cdd3af1 100644 --- a/bin/mpw-update +++ b/bin/mpw-update @@ -58,6 +58,7 @@ opts = { search: options[:pattern], group: options[:group], } +cli.load_config cli.get_wallet(options[:wallet]) cli.decrypt cli.update(opts) diff --git a/bin/mpw-wallet b/bin/mpw-wallet index 0184d85..8e33426 100644 --- a/bin/mpw-wallet +++ b/bin/mpw-wallet @@ -75,6 +75,8 @@ end.parse! config = MPW::Config.new(options[:config]) cli = MPW::Cli.new(config, options[:sync]) +cli.load_config + if not options[:list].nil? cli.list_wallet else diff --git a/i18n/en.yml b/i18n/en.yml index e88f360..9a964d2 100644 --- a/i18n/en.yml +++ b/i18n/en.yml @@ -3,7 +3,7 @@ en: error: config: write: "Can't write the config file!" - check: "Checkconfig failed!" + load: "Checkconfig failed!" key_bad_format: "The key string isn't in good format!" no_key_public: "You haven't the public key of %{key}!" genkey_gpg: diff --git a/i18n/fr.yml b/i18n/fr.yml index 903cba6..d2cae5b 100644 --- a/i18n/fr.yml +++ b/i18n/fr.yml @@ -3,7 +3,7 @@ fr: error: config: write: "Impossible d'écrire le fichier de configuration!" - check: "Le fichier de configuration est invalide!" + load: "Le fichier de configuration est invalide!" key_bad_format: "La clé GPG est invalide!" no_key_public: "Vous ne possédez pas la clé publique de %{key}!" genkey_gpg: diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index b0161a1..b25cd18 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -40,8 +40,6 @@ class Cli # Change a parameter int the config after init # @args: options -> param to change def set_config(options) - raise I18n.t('error.config.check') if not @config.is_valid? - gpg_key = options[:gpg_key] || @config.key lang = options[:lang] || @config.lang wallet_dir = options[:wallet_dir] || @config.wallet_dir @@ -56,15 +54,13 @@ class Cli # Create a new config file # @args: options -> set param def setup(options) - @config.is_valid? - lang = options[:lang] || Locale::Tag.parse(ENV['LANG']).to_simple.to_s[0..1] I18n.locale = lang.to_sym @config.setup(options[:gpg_key], lang, options[:wallet_dir], options[:gpg_exe]) - raise I18n.t('error.config.check') if not @config.is_valid? + load_config puts "#{I18n.t('form.setup_config.valid')}".green rescue Exception => e @@ -116,6 +112,15 @@ class Cli exit 2 end + # Load config + def load_config + @config.load_config + + rescue Exception => e + puts "#{I18n.t('display.error')} #10: #{e}".red + exit 2 + end + # Request the GPG password and decrypt the file def decrypt if not defined?(@mpw) @@ -305,8 +310,6 @@ class Cli # List all wallets def list_wallet - @config.is_valid? - wallets = Dir.glob("#{@config.wallet_dir}/*.mpw") wallets.each do |wallet| @@ -317,8 +320,6 @@ class Cli # Display the wallet # @args: wallet -> the wallet name def get_wallet(wallet=nil) - @config.is_valid? - if wallet.to_s.empty? wallets = Dir.glob("#{@config.wallet_dir}/*.mpw") diff --git a/lib/mpw/config.rb b/lib/mpw/config.rb index 148ecf1..2c1c496 100644 --- a/lib/mpw/config.rb +++ b/lib/mpw/config.rb @@ -65,11 +65,10 @@ class Config wallet_dir = "#{@config_dir}/wallets" end - config = {'config' => {'key' => key, - 'lang' => lang, - 'wallet_dir' => wallet_dir, - 'gpg_exe' => gpg_exe, - } + config = { 'key' => key, + 'lang' => lang, + 'wallet_dir' => wallet_dir, + 'gpg_exe' => gpg_exe, } FileUtils.mkdir_p(wallet_dir, mode: 0700) @@ -113,22 +112,20 @@ class Config raise "#{I18n.t('error.config.genkey_gpg.exception')}\n#{e}" end - # Check the config file - # @rtrn: true if the config file is correct - def is_valid? + # Load the config file + def load_config config = YAML::load_file(@config_file) - @key = config['config']['key'] - @lang = config['config']['lang'] - @wallet_dir = config['config']['wallet_dir'] - @gpg_exe = config['config']['gpg_exe'] + @key = config['key'] + @lang = config['lang'] + @wallet_dir = config['wallet_dir'] + @gpg_exe = config['gpg_exe'] raise if @key.empty? or @wallet_dir.empty? I18n.locale = @lang.to_sym - return true - rescue - return false + rescue Exception => e + raise "#{I18n.t('error.config.load')}\n#{e}" end # Check if private key exist From f1f92d5658db11a79bf20b6fe091da13ad915980 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Sun, 23 Oct 2016 22:10:58 +0200 Subject: [PATCH 353/531] replace opts by value for options to search --- bin/mpw-delete | 11 ++++------- bin/mpw-export | 11 ++++------- bin/mpw-list | 11 ++++------- bin/mpw-update | 11 ++++------- lib/mpw/mpw.rb | 2 +- 5 files changed, 17 insertions(+), 29 deletions(-) diff --git a/bin/mpw-delete b/bin/mpw-delete index e2d1195..d0e76d5 100644 --- a/bin/mpw-delete +++ b/bin/mpw-delete @@ -25,6 +25,7 @@ require 'mpw/cli' # --------------------------------------------------------- # options = {} +values = {} OptionParser.new do |opts| opts.banner = "#{I18n.t('option.usage')}: mpw delete [options]" @@ -34,7 +35,7 @@ OptionParser.new do |opts| end opts.on('-g', '--group NAME', I18n.t('option.group')) do |group| - options[:group] = group + values[:group] = group end opts.on('-h', '--help', I18n.t('option.help')) do @@ -43,7 +44,7 @@ OptionParser.new do |opts| end opts.on('-p', '--pattern PATTERN', I18n.t('option.pattern')) do |pattern| - options[:pattern] = pattern + values[:pattern] = pattern end opts.on('-w', '--wallet NAME', I18n.t('option.wallet')) do |wallet| @@ -54,11 +55,7 @@ end.parse! config = MPW::Config.new(options[:config]) cli = MPW::Cli.new(config, options[:sync]) -opts = { search: options[:pattern], - group: options[:group], - } - cli.load_config cli.get_wallet(options[:wallet]) cli.decrypt -cli.delete(opts) +cli.delete(values) diff --git a/bin/mpw-export b/bin/mpw-export index be15bb5..f5a2145 100644 --- a/bin/mpw-export +++ b/bin/mpw-export @@ -25,6 +25,7 @@ require 'mpw/cli' # --------------------------------------------------------- # options = {} +values = {} OptionParser.new do |opts| opts.banner = "#{I18n.t('option.usage')}: mpw wallet [options]" @@ -38,7 +39,7 @@ OptionParser.new do |opts| end opts.on('-g', '--group GROUP', I18n.t('option.group')) do |group| - options[:group] = group + values[:group] = group end opts.on('-h', '--help', I18n.t('option.help')) do @@ -47,7 +48,7 @@ OptionParser.new do |opts| end opts.on('-p', '--pattern PATTERN', I18n.t('option.pattern')) do |pattern| - options[:pattern] = pattern + values[:pattern] = pattern end opts.on('-w', '--wallet NAME', I18n.t('option.wallet')) do |wallet| @@ -58,11 +59,7 @@ end.parse! config = MPW::Config.new(options[:config]) cli = MPW::Cli.new(config, options[:sync]) -opts = { search: options[:pattern], - group: options[:group], - } - cli.load_config cli.get_wallet(options[:wallet]) cli.decrypt -cli.export(options[:file], opts) +cli.export(options[:file], values) diff --git a/bin/mpw-list b/bin/mpw-list index 1c729cc..839e00f 100644 --- a/bin/mpw-list +++ b/bin/mpw-list @@ -25,6 +25,7 @@ require 'mpw/cli' # --------------------------------------------------------- # options = {} +values = {} OptionParser.new do |opts| opts.banner = "#{I18n.t('option.usage')}: mpw list [options]" @@ -34,7 +35,7 @@ OptionParser.new do |opts| end opts.on('-g', '--group NAME', I18n.t('option.group')) do |group| - options[:group] = group + values[:group] = group end opts.on('-h', '--help', I18n.t('option.help')) do @@ -43,7 +44,7 @@ OptionParser.new do |opts| end opts.on('-p', '--pattern PATTERN', I18n.t('option.pattern')) do |pattern| - options[:pattern] = pattern + values[:pattern] = pattern end opts.on('-w', '--wallet NAME', I18n.t('option.wallet')) do |wallet| @@ -54,11 +55,7 @@ end.parse! config = MPW::Config.new(options[:config]) cli = MPW::Cli.new(config, options[:sync]) -opts = { search: options[:pattern], - group: options[:group], - } - cli.load_config cli.get_wallet(options[:wallet]) cli.decrypt -cli.list(opts) +cli.list(values) diff --git a/bin/mpw-update b/bin/mpw-update index cdd3af1..598920b 100644 --- a/bin/mpw-update +++ b/bin/mpw-update @@ -25,6 +25,7 @@ require 'mpw/cli' # --------------------------------------------------------- # options = {} +values = {} OptionParser.new do |opts| opts.banner = "#{I18n.t('option.usage')}: mpw update [options]" @@ -34,7 +35,7 @@ OptionParser.new do |opts| end opts.on('-g', '--group NAME', I18n.t('option.group')) do |group| - options[:group] = group + values[:group] = group end opts.on('-h', '--help', I18n.t('option.help')) do @@ -43,7 +44,7 @@ OptionParser.new do |opts| end opts.on('-p', '--pattern PATTERN', I18n.t('option.pattern')) do |pattern| - options[:pattern] = pattern + values[:pattern] = pattern end opts.on('-w', '--wallet NAME', I18n.t('option.wallet')) do |wallet| @@ -54,11 +55,7 @@ end.parse! config = MPW::Config.new(options[:config]) cli = MPW::Cli.new(config, options[:sync]) -opts = { search: options[:pattern], - group: options[:group], - } - cli.load_config cli.get_wallet(options[:wallet]) cli.decrypt -cli.update(opts) +cli.update(values) diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index 0727636..884f752 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -240,7 +240,7 @@ class MPW def list(options={}) result = [] - search = options[:search].to_s.downcase + search = options[:pattern].to_s.downcase group = options[:group].to_s.downcase @data.each do |item| From 90e8b658bf96dd4b7befa6f7f194005abf94b0eb Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Sun, 23 Oct 2016 22:36:50 +0200 Subject: [PATCH 354/531] replace opts by value for options to search --- bin/mpw-copy | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/bin/mpw-copy b/bin/mpw-copy index e9ae66b..aa42c9a 100644 --- a/bin/mpw-copy +++ b/bin/mpw-copy @@ -26,6 +26,7 @@ require 'mpw/cli' options = {} options[:clipboard] = true +values = {} OptionParser.new do |opts| opts.banner = "#{I18n.t('option.usage')}: mpw copy [options]" @@ -39,7 +40,7 @@ OptionParser.new do |opts| end opts.on('-g', '--group NAME', I18n.t('option.group')) do |group| - options[:group] = group + values[:group] = group end opts.on('-h', '--help', I18n.t('option.help')) do @@ -47,8 +48,12 @@ OptionParser.new do |opts| exit 0 end + opts.on('-n', '--no-sync', I18n.t('option.no_sync')) do + options[:sync] = false + end + opts.on('-p', '--pattern PATTERN', I18n.t('option.pattern')) do |pattern| - options[:pattern] = pattern + values[:pattern] = pattern end opts.on('-w', '--wallet NAME', I18n.t('option.wallet')) do |wallet| @@ -59,11 +64,7 @@ end.parse! config = MPW::Config.new(options[:config]) cli = MPW::Cli.new(config, options[:sync]) -opts = { search: options[:pattern], - group: options[:group], - } - cli.load_config cli.get_wallet(options[:wallet]) cli.decrypt -cli.copy(options[:clipboard], opts) +cli.copy(options[:clipboard], values) From 5bcf26d25193799ba8835006cb1ccae8cd31ebd6 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Sun, 23 Oct 2016 22:39:22 +0200 Subject: [PATCH 355/531] enable sync --- bin/mpw-add | 7 ++++++- bin/mpw-config | 2 +- bin/mpw-copy | 3 ++- bin/mpw-delete | 9 +++++++-- bin/mpw-export | 9 +++++++-- bin/mpw-import | 11 ++++++----- bin/mpw-list | 9 +++++++-- bin/mpw-update | 9 +++++++-- bin/mpw-wallet | 9 +++++++-- lib/mpw/mpw.rb | 4 ++-- 10 files changed, 52 insertions(+), 20 deletions(-) diff --git a/bin/mpw-add b/bin/mpw-add index a0e450f..5322cc1 100644 --- a/bin/mpw-add +++ b/bin/mpw-add @@ -24,7 +24,8 @@ require 'mpw/cli' # Options # --------------------------------------------------------- # -options = {} +options = {} +options[:sync] = true OptionParser.new do |opts| opts.banner = "#{I18n.t('option.usage')}: mpw add [options]" @@ -38,6 +39,10 @@ OptionParser.new do |opts| exit 0 end + opts.on('-n', '--no-sync', I18n.t('option.no_sync')) do + options[:sync] = false + end + opts.on('-r', '--random', I18n.t('option.random_password')) do options[:password] = true end diff --git a/bin/mpw-config b/bin/mpw-config index 133f3c4..120da5b 100644 --- a/bin/mpw-config +++ b/bin/mpw-config @@ -65,9 +65,9 @@ config = MPW::Config.new(options[:config]) cli = MPW::Cli.new(config, nil) if not options[:init].nil? + cli.setup(values) cli.load_config cli.get_wallet - cli.setup(values) cli.setup_gpg_key(options[:init]) cli.setup_wallet_config else diff --git a/bin/mpw-copy b/bin/mpw-copy index aa42c9a..0a14ed7 100644 --- a/bin/mpw-copy +++ b/bin/mpw-copy @@ -24,7 +24,8 @@ require 'mpw/cli' # Options # --------------------------------------------------------- # -options = {} +options = {} +options[:sync] = true options[:clipboard] = true values = {} diff --git a/bin/mpw-delete b/bin/mpw-delete index d0e76d5..2d79e6a 100644 --- a/bin/mpw-delete +++ b/bin/mpw-delete @@ -24,8 +24,9 @@ require 'mpw/cli' # Options # --------------------------------------------------------- # -options = {} -values = {} +options = {} +options[:sync] = true +values = {} OptionParser.new do |opts| opts.banner = "#{I18n.t('option.usage')}: mpw delete [options]" @@ -43,6 +44,10 @@ OptionParser.new do |opts| exit 0 end + opts.on('-n', '--no-sync', I18n.t('option.no_sync')) do + options[:sync] = false + end + opts.on('-p', '--pattern PATTERN', I18n.t('option.pattern')) do |pattern| values[:pattern] = pattern end diff --git a/bin/mpw-export b/bin/mpw-export index f5a2145..f891873 100644 --- a/bin/mpw-export +++ b/bin/mpw-export @@ -24,8 +24,9 @@ require 'mpw/cli' # Options # --------------------------------------------------------- # -options = {} -values = {} +options = {} +options[:sync] = true +values = {} OptionParser.new do |opts| opts.banner = "#{I18n.t('option.usage')}: mpw wallet [options]" @@ -47,6 +48,10 @@ OptionParser.new do |opts| exit 0 end + opts.on('-n', '--no-sync', I18n.t('option.no_sync')) do + options[:sync] = false + end + opts.on('-p', '--pattern PATTERN', I18n.t('option.pattern')) do |pattern| values[:pattern] = pattern end diff --git a/bin/mpw-import b/bin/mpw-import index ad52f57..c740252 100644 --- a/bin/mpw-import +++ b/bin/mpw-import @@ -24,7 +24,8 @@ require 'mpw/cli' # Options # --------------------------------------------------------- # -options = {} +options = {} +options[:sync] = true OptionParser.new do |opts| opts.banner = "#{I18n.t('option.usage')}: mpw import [options]" @@ -42,6 +43,10 @@ OptionParser.new do |opts| exit 0 end + opts.on('-n', '--no-sync', I18n.t('option.no_sync')) do + options[:sync] = false + end + opts.on('-w', '--wallet NAME', I18n.t('option.wallet')) do |wallet| options[:wallet] = wallet end @@ -50,10 +55,6 @@ end.parse! config = MPW::Config.new(options[:config]) cli = MPW::Cli.new(config, options[:sync]) -opts = { search: options[:pattern], - group: options[:group], - } - cli.load_config cli.get_wallet(options[:wallet]) cli.decrypt diff --git a/bin/mpw-list b/bin/mpw-list index 839e00f..9d18b0d 100644 --- a/bin/mpw-list +++ b/bin/mpw-list @@ -24,8 +24,9 @@ require 'mpw/cli' # Options # --------------------------------------------------------- # -options = {} -values = {} +options = {} +options[:sync] = true +values = {} OptionParser.new do |opts| opts.banner = "#{I18n.t('option.usage')}: mpw list [options]" @@ -47,6 +48,10 @@ OptionParser.new do |opts| values[:pattern] = pattern end + opts.on('-n', '--no-sync', I18n.t('option.no_sync')) do + options[:sync] = false + end + opts.on('-w', '--wallet NAME', I18n.t('option.wallet')) do |wallet| options[:wallet] = wallet end diff --git a/bin/mpw-update b/bin/mpw-update index 598920b..301b876 100644 --- a/bin/mpw-update +++ b/bin/mpw-update @@ -24,8 +24,9 @@ require 'mpw/cli' # Options # --------------------------------------------------------- # -options = {} -values = {} +options = {} +options[:sync] = true +values = {} OptionParser.new do |opts| opts.banner = "#{I18n.t('option.usage')}: mpw update [options]" @@ -43,6 +44,10 @@ OptionParser.new do |opts| exit 0 end + opts.on('-n', '--no-sync', I18n.t('option.no_sync')) do + options[:sync] = false + end + opts.on('-p', '--pattern PATTERN', I18n.t('option.pattern')) do |pattern| values[:pattern] = pattern end diff --git a/bin/mpw-wallet b/bin/mpw-wallet index 8e33426..b81e6b2 100644 --- a/bin/mpw-wallet +++ b/bin/mpw-wallet @@ -24,8 +24,9 @@ require 'mpw/cli' # Options # --------------------------------------------------------- # -options = {} -values = {} +options = {} +options[:sync] = {} +values = {} OptionParser.new do |opts| opts.banner = "#{I18n.t('option.usage')}: mpw wallet [options]" @@ -47,6 +48,10 @@ OptionParser.new do |opts| options[:list] = true end + opts.on('-n', '--no-sync', I18n.t('option.no_sync')) do + options[:sync] = false + end + opts.on('--password', I18n.t('option.password')) do values[:password] = true end diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index 884f752..0215a70 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -289,10 +289,10 @@ class MPW case @config['protocol'] when 'sftp', 'scp', 'ssh' require "mpw/sync/ssh" - sync = SyncSSH.new(@config['sync']) + sync = SyncSSH.new(@config) when 'ftp' require 'mpw/sync/ftp' - sync = SyncFTP.new(@config['sync']) + sync = SyncFTP.new(@config) else raise I18n.t('error.sync.unknown_type') end From fb64bfbbdf0397949febd0ef8335e6ca6d72751a Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Sun, 23 Oct 2016 22:39:52 +0200 Subject: [PATCH 356/531] remove olw mpw binary --- bin/mpw-old | 214 ---------------------------------------------------- 1 file changed, 214 deletions(-) delete mode 100755 bin/mpw-old diff --git a/bin/mpw-old b/bin/mpw-old deleted file mode 100755 index 5f0d64d..0000000 --- a/bin/mpw-old +++ /dev/null @@ -1,214 +0,0 @@ -#!/usr/bin/ruby -# MPW is a software to crypt and manage your passwords -# Copyright (C) 2016 Adrien Waksberg <mpw@yae.im> -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - -$: << File.expand_path('../../lib', __FILE__) - -require 'optparse' -require 'locale' -require 'set' -require 'i18n' -require 'mpw/mpw' -require 'mpw/config' -require 'mpw/cli' - -# --------------------------------------------------------- # -# Set local -# --------------------------------------------------------- # - -lang = Locale::Tag.parse(ENV['LANG']).to_simple.to_s[0..1] - -if defined?(I18n.enforce_available_locales) - I18n.enforce_available_locales = true -end - -I18n::Backend::Simple.send(:include, I18n::Backend::Fallbacks) -I18n.load_path = Dir["#{File.expand_path('../../i18n', __FILE__)}/*.yml"] -I18n.default_locale = :en -I18n.locale = lang.to_sym - -# --------------------------------------------------------- # -# Options -# --------------------------------------------------------- # - -options_password = {} -options = {} -options[:force] = false -options[:otp] = false -options[:sync] = true -options[:clipboard] = true -options[:group] = nil -options[:config] = nil -options[:wallet] = nil - -OptionParser.new do |opts| - opts.banner = "#{I18n.t('option.usage')}: mpw [options]" - - opts.on('-a', '--add', I18n.t('option.add')) do - options[:add] = true - end - - opts.on('-A', '--show-all', I18n.t('option.show_all')) do - options[:type] = nil - options[:show] = '' - end - - opts.on('-c', '--config CONFIG', I18n.t('option.config')) do |config| - options[:config] = config - end - - opts.on('-C', '--no-clipboard', I18n.t('option.clipboard')) do - options[:clipboard] = false - end - - opts.on('-e', '--export', I18n.t('option.export')) do - options[:export] = true - end - - opts.on('-f', '--file FILE', I18n.t('option.file')) do |file| - options[:file] = file - end - - opts.on('-F', '--force', I18n.t('option.force')) do - options[:force] = true - end - - opts.on('-g', '--group GROUP', I18n.t('option.group')) do |group| - options[:group] = group - end - - opts.on('-G', '--generate-password [LENGTH]', I18n.t('option.generate_password')) do |length| - options_password[:length] = length - end - - opts.on('-h', '--help', I18n.t('option.help')) do - puts opts - exit 0 - end - - opts.on('-I', '--import', I18n.t('option.import')) do - options[:import] = true - end - - opts.on('-k', '--key KEY', I18n.t('option.key')) do |key| - options[:key] = key - end - - opts.on('-n', '--numeric', I18n.t('option.numeric')) do - options_password[:numeric] = true - end - - opts.on('-N', '--no-sync', I18n.t('option.no_sync')) do - options[:sync] = false - end - - opts.on('-O', '--otp', I18n.t('option.otp')) do - options[:otp] = true - end - - opts.on('-s', '--show [SEARCH]', I18n.t('option.show')) do |search| - search.nil? ? (options[:show] = '') : (options[:show] = search) - end - - opts.on('-S', '--setup', I18n.t('option.setup')) do - options[:setup] = true - end - - opts.on('-w', '--wallet WALLET', I18n.t('option.wallet')) do |wallet| - options[:wallet] = wallet - end - - opts.on('-W', '--setup-wallet', I18n.t('option.setup_wallet')) do - options[:setup_wallet] = true - end - - opts.on('-x', '--special-chars', I18n.t('option.special_chars')) do - options_password[:special] = true - end - - opts.on('-y', '--alpha', I18n.t('option.alpha')) do - options_password[:alpha] = true - end -end.parse! - -# --------------------------------------------------------- # -# Main -# --------------------------------------------------------- # - -# Generate password -if not options_password.empty? - puts MPW::MPW::password(options_password) - exit 0 -end - -begin - config = MPW::Config.new(options[:config]) - cli = MPW::Cli.new(config, options[:clipboard], options[:sync], options[:otp]) - - # Setup a new config - if not options[:setup].nil? - cli.setup(lang) - exit 0 - end - - cli.setup(lang) if not config.is_valid? - cli.setup_gpg_key if not config.check_gpg_key? - - cli.get_wallet(options[:wallet]) - cli.decrypt - - # Display the item's informations - if not options[:show].nil? - opts = {search: options[:show], - group: options[:group], - } - - cli.display(opts) - - # Add a new item - elsif not options[:add].nil? and options[:key].nil? - cli.add - - # Add a new public key in wallet - elsif not options[:add].nil? and not options[:key].nil? - cli.add_key(options[:key], options[:file]) - - # Delete a public key in wallet - elsif not options[:delete].nil? and not options[:key].nil? - cli.delete_key(options[:key]) - - # Export - elsif not options[:export].nil? and not options[:file].nil? - cli.export(options[:file]) - - # Import - elsif not options[:import].nil? and not options[:file].nil? - cli.import(options[:file]) - - # Setup wallet config - elsif not options[:setup_wallet].nil? - cli.setup_wallet_config - - end - - cli = nil - - exit 0 - -rescue SystemExit, Interrupt - exit 3 -end From c25b31201375287a38ca7db2d9719ed64ecec0f3 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Sun, 23 Oct 2016 22:54:36 +0200 Subject: [PATCH 357/531] update version file: 4.0.0-beta --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 944880f..c0de572 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3.2.0 +4.0.0-beta From 94f6e4e61eea74671271153b6d13c2bcd429f56e Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Tue, 25 Oct 2016 23:17:04 +0200 Subject: [PATCH 358/531] fix bug when gpg path is empty --- lib/mpw/mpw.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index 0215a70..533077e 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -33,7 +33,7 @@ class MPW @gpg_exe = gpg_exe @wallet_file = wallet_file - if @gpg_exe + if not @gpg_exe.to_s.empty? GPGME::Engine.set_info(GPGME::PROTOCOL_OpenPGP, @gpg_exe, "#{Dir.home}/.gnupg") end end From f775146ffd3aef0c705e15fb50f70fff79ff0bc2 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Sat, 5 Nov 2016 10:13:33 +0100 Subject: [PATCH 359/531] new readme --- README.md | 128 ----------------------------------------------------- README.rst | 53 ++++++++++++++++++++++ 2 files changed, 53 insertions(+), 128 deletions(-) delete mode 100644 README.md create mode 100644 README.rst diff --git a/README.md b/README.md deleted file mode 100644 index e3ca84c..0000000 --- a/README.md +++ /dev/null @@ -1,128 +0,0 @@ -# Manage your passwords! - -MPW is a little software which stores your passwords in an GPG encrypted file. -MPW can synchronize your password with SSH or FTP. - -# Installation - -This program work with ruby >= 2.0 - -* install ruby and rubygems on your computer -* install xclip -* gem install mpw - -# How to use - -* Show help -``` -mpw --help -``` - -* Setup a new config file -``` -mpw --setup -mpw --setup --config /path/conf/file.cfg -``` - -* Create and setup a new wallet -``` -mpw --setup-wallet --wallet new_wallet_name -mpw --setup-wallet --wallet new_wallet_name --config /path/conf/file.cfg -``` - -* Add a GPG key in wallet -``` -mpw --add --key root@localhost.local -mpw --add --key root@localhost.local --config /path/conf/file.cfg -mpw --add --key root@localhost.local --wallet wallet_name -mpw --add --key root@localhost.local --config /path/conf/file.cfg --wallet wallet_name -``` - -* Add a new GPG key in wallet -``` -mpw --add --key root@localhost.local --file /path/gpg/file.pub -mpw --add --key root@localhost.local --file /path/gpg/file.pub --config /path/conf/file.cfg -mpw --add --key root@localhost.local --file /path/gpg/file.pub --wallet wallet_name -mpw --add --key root@localhost.local --file /path/gpg/file.pub --config /path/conf/file.cfg --wallet wallet_name -``` - -* Delete a GPG key in wallet -``` -mpw --delete --key root@localhost.local -mpw --delete --key root@localhost.local --wallet wallet_name -mpw --delete --key root@localhost.local --wallet wallet_name --config /path/conf/file.cfg -``` - -* Add a new item in wallet -``` -mpw --add -mpw --add --config /path/conf/file.cfg -mpw --add --wallet wallet_name -mpw --add --config /path/conf/file.cfg --wallet wallet_name -``` - -* Update an item -``` -mpw --update --id uniq_id -mpw --update --id uniq_id --config /path/conf/file.cfg -mpw --update --id uniq_id --wallet wallet_name -mpw --update --id uniq_id --config /path/conf/file.cfg --wallet wallet_name -``` - -* Delete an item -``` -mpw --delete --id uniq_id -mpw --delete --id uniq_id --config /path/conf/file.cfg -mpw --delete --id uniq_id --wallet wallet_name -mpw --delete --id uniq_id --config /path/conf/file.cfg --wallet wallet_name -``` - -* Show an item -``` -mpw --show 'string to search' -mpw --show 'string to search' --config /path/conf/file.cfg -mpw --show 'string to search' --wallet wallet_name -mpw --show 'string to search' --config /path/conf/file.cfg --wallet wallet_name -mpw --show 'string to search' --group group_name -mpw --show 'string to search' --group group_name --config /path/conf/file.cfg -mpw --show 'string to search' --group group_name --wallet wallet_name -mpw --show 'string to search' --group group_name --config /path/conf/file.cfg --wallet wallet_name -``` - -* Export data in YAML file -``` -mpw --export --file /path/file/to/export.yml -mpw --export --file /path/file/to/export.yml --config /path/conf/file.cfg -mpw --export --file /path/file/to/export.yml --wallet wallet_name -mpw --export --file /path/file/to/export.yml --config /path/conf/file.cfg --wallet wallet_name -``` - -* Import data from YAML file -``` -mpw --import --file /path/file/to/export.yml -mpw --import --file /path/file/to/export.yml --config /path/conf/file.cfg -mpw --import --file /path/file/to/export.yml --wallet wallet_name -mpw --import --file /path/file/to/export.yml --config /path/conf/file.cfg --wallet wallet_name -``` - -Format file to import: -``` -1: - name: Website perso - group: Perso - host: localhost.local - protocol: ftp - user: test - password: letoortue - port: 21 - comment: Mysuper website -2: - name: Linuxfr - group: Pro - host: Linuxfr.org - protocol: https - user: test - password: coucou - port: - comment: -``` diff --git a/README.rst b/README.rst new file mode 100644 index 0000000..a62c1e2 --- /dev/null +++ b/README.rst @@ -0,0 +1,53 @@ +MPW: Manage your passwords! +******************************************************* + +mpw is a little software which stores your passwords in `GnuPG <http://www.gnupg.org/>` encrypted files. + +Features +======== + +* generate OTP code +* synchronize your passwords with SSH or FTP. +* copy your login, password or otp in clipboard + +Install +======= + +On debian or ubuntu:: + + apt install ruby ruby-dev xclip + gem install mpw + + +How to use +========== + +A simple mpw usage:: + + mpw config --init user@host.com + mpw add + mpw copy + mpw add + mpw list + +Output:: + + Bank + ============================================================================== + ID | Host | User | Protocol | Port | OTP | Comment + ============================================================================== + 1 | bank.com | 1234456 | https | | X | + + Linux + ============================================================================== + ID | Host | User | Protocol | Port | OTP | Comment + ============================================================================== + 2 | linuxfr.org | example | https | | | Da Linux French Site + + +Licence |License| +================= + +Full license here: `LICENSE <https://github.com/nishiki/manage-password/blob/master/LICENSE>` + +.. |License| image:: https://img.shields.io/badge/license-GPL--2.0-blue.svg From 56b01bcc8633abbad6f55019a521bbf880e14b34 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Sat, 5 Nov 2016 10:14:08 +0100 Subject: [PATCH 360/531] minor fix in table format --- lib/mpw/cli.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index b25cd18..722b16d 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -141,7 +141,7 @@ class Cli i = 1 length_total = 10 data = { id: { length: 3, color: 'cyan' }, - host: { length: 9, color: 'yellow' }, + host: { length: 9, color: 'yellow' }, user: { length: 7, color: 'green' }, protocol: { length: 9, color: 'white' }, port: { length: 5, color: 'white' }, @@ -153,7 +153,7 @@ class Cli data.each do |k, v| next if k == :id or k == :otp - v[:length] = item.send(k.to_s).length + 3 if item.send(k.to_s).to_s.length > v[:length] + v[:length] = item.send(k.to_s).length + 3 if item.send(k.to_s).to_s.length >= v[:length] end end data[:id][:length] = items.length.to_s.length + 2 if items.length.to_s.length > data[:id][:length] From 167123d7111db4029aba4856905484125756abaf Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Sat, 5 Nov 2016 10:27:19 +0100 Subject: [PATCH 361/531] update changelog --- CHANGELOG | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index 1ce4809..261d083 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,4 +1,34 @@ = CHANGELOG = +== v4.0.0 (beta) == + +* new interface with a table +* new command line interface +* use text editor for add or update an item +* several bugs fix + +== v3.2.1 == + +* fix bug when add a new item + +== v3.2.0 == + +* add support OTP +* fix bug in synchronize +* improve interface + +== v3.1.0 == + +* add clipboard +* can change gpg version +* minor change in interface +* several bugs fix + +== v3.0.0 == + +* new storage format +* new share system +* remove MPW server + == v2.0.0 == * change format csv to yaml From 3d48ff95b90470accdc04b35cd675c24a8ae29ed Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Sat, 5 Nov 2016 10:50:10 +0100 Subject: [PATCH 362/531] fix dependency version --- Gemfile | 18 +++++++++--------- mpw.gemspec | 18 +++++++++--------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/Gemfile b/Gemfile index 557dec5..a588d17 100644 --- a/Gemfile +++ b/Gemfile @@ -1,10 +1,10 @@ source 'https://rubygems.org' -gem 'highline' -gem 'i18n' -gem 'locale' -gem 'gpgme' -gem 'colorize' -gem 'net-ssh' -gem 'net-scp' -gem 'clipboard' -gem 'rotp' +gem "i18n", "~> 0.7", ">= 0.7.0" +gem "gpgme", "~> 2.0", ">= 2.0.12" +gem "highline", "~> 1.7", ">= 1.7.8" +gem "locale", "~> 2.1", ">= 2.1.2" +gem "colorize", "~> 0.8", ">= 0.8.1" +gem "net-ssh", "~> 3.2", ">= 3.2.0" +gem "net-sftp", "~> 2.1", ">= 2.1.2" +gem "clipboard", "~> 1.1", ">= 1.1.1" +gem "rotp", "~> 3.1", ">= 3.1.0" diff --git a/mpw.gemspec b/mpw.gemspec index 09fe6d9..80d9344 100644 --- a/mpw.gemspec +++ b/mpw.gemspec @@ -17,13 +17,13 @@ Gem::Specification.new do |spec| spec.test_files = spec.files.grep(%r{^(test|spec|features)/}) spec.require_paths = ['lib'] - spec.add_dependency "i18n" - spec.add_dependency "gpgme" - spec.add_dependency "highline" - spec.add_dependency "locale" - spec.add_dependency "colorize" - spec.add_dependency "net-ssh" - spec.add_dependency "net-sftp" - spec.add_dependency "clipboard" - spec.add_dependency "rotp" + spec.add_dependency "i18n", "~> 0.7", ">= 0.7.0" + spec.add_dependency "gpgme", "~> 2.0", ">= 2.0.12" + spec.add_dependency "highline", "~> 1.7", ">= 1.7.8" + spec.add_dependency "locale", "~> 2.1", ">= 2.1.2" + spec.add_dependency "colorize", "~> 0.8", ">= 0.8.1" + spec.add_dependency "net-ssh", "~> 3.2", ">= 3.2.0" + spec.add_dependency "net-sftp", "~> 2.1", ">= 2.1.2" + spec.add_dependency "clipboard", "~> 1.1", ">= 1.1.1" + spec.add_dependency "rotp", "~> 3.1", ">= 3.1.0" end From 0e86be546150b48ca60d8a6a5179a061630e4d31 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Sat, 5 Nov 2016 15:34:11 +0100 Subject: [PATCH 363/531] add help command --- bin/mpw | 15 +++++++++++++++ i18n/en.yml | 12 ++++++++++++ i18n/fr.yml | 12 ++++++++++++ 3 files changed, 39 insertions(+) diff --git a/bin/mpw b/bin/mpw index 2d32700..8e578f8 100755 --- a/bin/mpw +++ b/bin/mpw @@ -46,4 +46,19 @@ command = "#{bin_dir}/mpw-#{ARGV[0]}" if Dir.glob("#{bin_dir}/mpw-*").include?("#{command}") Kernel.load(command) +else + puts "#{I18n.t('option.usage')}: mpw COMMAND [options]\n\n" + puts 'Commands:' + puts " add #{I18n.t('command.add')}" + puts " config #{I18n.t('command.config')}" + puts " copy #{I18n.t('command.copy')}" + puts " delete #{I18n.t('command.delete')}" + puts " export #{I18n.t('command.export')}" + puts " genpwd #{I18n.t('command.genpwd')}" + puts " import #{I18n.t('command.import')}" + puts " list #{I18n.t('command.list')}" + puts " update #{I18n.t('command.update')}" + puts " wallet #{I18n.t('command.wallet')}" + + exit 3 end diff --git a/i18n/en.yml b/i18n/en.yml index 9a964d2..93955d5 100644 --- a/i18n/en.yml +++ b/i18n/en.yml @@ -33,6 +33,18 @@ en: warning: select: 'Your choice is not a valid element!' + command: + add: "Add a new item" + config: "Manage the general config" + copy: "Copy a login, password or OTP code" + delete: "Delete an item" + export: "Export the data in plain text" + genpwd: "Generate a password" + import: "Import data from a file" + list: "Print the items" + update: "Update an item" + wallet: "Manage the wallet config" + option: add: "Add an item or key" alpha: "Use letter to generate a password" diff --git a/i18n/fr.yml b/i18n/fr.yml index d2cae5b..4f8b7ac 100644 --- a/i18n/fr.yml +++ b/i18n/fr.yml @@ -33,6 +33,18 @@ fr: warning: select: "Votre choix n'est pas un élément valide!" + command: + add: "Ajoute un nouvel élément" + config: "Gère la configuration générale" + copy: "Copie un identifiant, un mot de passe ou un code OTP" + delete: "Supprimer un élément d'un portefeuille" + export: "Exporte les données" + genpwd: "Génére un mot de passe" + import: "Importe des données" + list: "Liste les éléments d'un portefeuille" + update: "Met à jour un élément" + wallet: "Gére la configuration d'un portefeuille" + option: add: "Ajoute un élément ou une clé" alpha: "Utilise des lettres dans la génération d'un mot de passe" From 0c93fd9eeaee4fad2ed0042d056cb1cc7f0f3056 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Sun, 6 Nov 2016 10:30:37 +0100 Subject: [PATCH 364/531] fix create config folder --- lib/mpw/config.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/mpw/config.rb b/lib/mpw/config.rb index 2c1c496..e8911fa 100644 --- a/lib/mpw/config.rb +++ b/lib/mpw/config.rb @@ -71,7 +71,9 @@ class Config 'gpg_exe' => gpg_exe, } - FileUtils.mkdir_p(wallet_dir, mode: 0700) + FileUtils.mkdir_p(@config_dir, mode: 0700) + FileUtils.mkdir_p(wallet_dir, mode: 0700) + File.open(@config_file, 'w') do |file| file << config.to_yaml end From 59e850cfeb4c7bcd36ccbbc08d665524d34c16bf Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Thu, 10 Nov 2016 23:57:16 +0100 Subject: [PATCH 365/531] add test with travis --- .travis.yml | 13 +++ README.rst | 7 +- test/files/fixtures.yml | 4 - test/files/test_import.csv | 3 - test/files/test_import.yml | 23 ---- test/test.sh | 1 + test/test2.rb | 11 ++ test/test_config.rb | 40 +++++++ test/test_item.rb | 130 +++++++-------------- test/test_mpw.rb | 226 +++++++++++++------------------------ test/tests.rb | 3 +- 11 files changed, 192 insertions(+), 269 deletions(-) create mode 100644 .travis.yml delete mode 100644 test/files/test_import.csv delete mode 100644 test/files/test_import.yml create mode 100644 test/test.sh create mode 100644 test/test2.rb create mode 100644 test/test_config.rb diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..141eab1 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,13 @@ +language: ruby +rvm: + - 2.3.1 + - 2.2.5 + - 2.1.10 +install: + - bundle install + - gem install 'test-unit' + - echo 9999 > VERSION + - gem build mpw.gemspec + - gem install mpw-9999.gem +script: + - ruby ./test/tests.rb diff --git a/README.rst b/README.rst index a62c1e2..432b4d8 100644 --- a/README.rst +++ b/README.rst @@ -1,7 +1,8 @@ MPW: Manage your passwords! ******************************************************* +|Build Status| |License| -mpw is a little software which stores your passwords in `GnuPG <http://www.gnupg.org/>` encrypted files. +mpw is a little software which stores your passwords in `GnuPG <http://www.gnupg.org/>`_ encrypted files. Features ======== @@ -48,6 +49,8 @@ Output:: Licence |License| ================= -Full license here: `LICENSE <https://github.com/nishiki/manage-password/blob/master/LICENSE>` +Full license here: `LICENSE <https://github.com/nishiki/manage-password/blob/master/LICENSE>`_ .. |License| image:: https://img.shields.io/badge/license-GPL--2.0-blue.svg +.. |Build Status| image:: https://travis-ci.org/nishiki/manage-password.svg?branch=master + :target: https://travis-ci.org/nishiki/manage-password diff --git a/test/files/fixtures.yml b/test/files/fixtures.yml index 73eacf7..5651911 100644 --- a/test/files/fixtures.yml +++ b/test/files/fixtures.yml @@ -1,5 +1,4 @@ add_new: - name: 'test_name' group: 'test_group' host: 'test_host' protocol: 'test_protocol' @@ -10,7 +9,6 @@ add_new: add_existing: id: 'TEST-ID-XXXXX' - name: 'test_name_existing' group: 'test_group_existing' host: 'test_host_existing' protocol: 'test_protocol_existing' @@ -21,7 +19,6 @@ add_existing: created: 1386752948 update: - name: 'test_name_update' group: 'test_group_update' host: 'test_host_update' protocol: 'test_protocol_update' @@ -29,4 +26,3 @@ update: password: 'test_password_update' port: '43' comment: 'test_comment_update' - diff --git a/test/files/test_import.csv b/test/files/test_import.csv deleted file mode 100644 index 74c1844..0000000 --- a/test/files/test_import.csv +++ /dev/null @@ -1,3 +0,0 @@ -name,group,protocol,host,user,password,port,comment -test_name,test_group,test_protocol,test_host,test_user,test_password,42,test_comment -test_name_update,test_group_update,test_protocol_update,test_host_update,test_user_update,test_password_update,43,test_comment_update diff --git a/test/files/test_import.yml b/test/files/test_import.yml deleted file mode 100644 index 889a264..0000000 --- a/test/files/test_import.yml +++ /dev/null @@ -1,23 +0,0 @@ ---- -XWas7vpy0HerhOYd: - id: XWas7vpy0HerhOYd - name: test_name - group: test_group - host: test_host - protocol: test_protocol - user: test_user - password: test_password - port: 42 - comment: test_comment - date: 1419858983 -D7URyJENLa91jt0b: - id: D7URyJENLa91jt0b - name: test_name_update - group: test_group_update - host: test_host_update - protocol: test_protocol_update - user: test_user_update - password: test_password_update - port: 43 - comment: test_comment_update - date: 1419858983 diff --git a/test/test.sh b/test/test.sh new file mode 100644 index 0000000..ab37885 --- /dev/null +++ b/test/test.sh @@ -0,0 +1 @@ +echo "test\ntest\n" | ruby ./bin/mpw config --init test@test.com diff --git a/test/test2.rb b/test/test2.rb new file mode 100644 index 0000000..17af2da --- /dev/null +++ b/test/test2.rb @@ -0,0 +1,11 @@ +require 'open3' + +Open3.popen3("./bin/mpw config --init test@test.com") do |stdin, stdout, stderr, thread| + stdin.puts 'test' + stdin.puts 'test' +end + +Open3.popen3("./bin/mpw list") do |stdin, stdout, stderr, thread| + stdin.puts 'test' + puts stdout +end diff --git a/test/test_config.rb b/test/test_config.rb new file mode 100644 index 0000000..3de438c --- /dev/null +++ b/test/test_config.rb @@ -0,0 +1,40 @@ +#!/usr/bin/ruby + +require 'mpw/config' +require 'test/unit' +require 'locale' +require 'i18n' + +class TestConfig < Test::Unit::TestCase + def setup + lang = Locale::Tag.parse(ENV['LANG']).to_simple.to_s[0..1] + + if defined?(I18n.enforce_available_locales) + I18n.enforce_available_locales = true + end + + I18n::Backend::Simple.send(:include, I18n::Backend::Fallbacks) + I18n.load_path = Dir["#{File.expand_path('../../i18n', __FILE__)}/*.yml"] + I18n.default_locale = :en + I18n.locale = lang.to_sym + end + + def test_00_config + data = { key: 'test@example.com', + lang: 'en', + wallet_dir: '/tmp/test', + gpg_exe: '', + } + + @config = MPW::Config.new + @config.setup(data[:key], data[:lang], data[:wallet_dir], data[:gpg_exe]) + @config.load_config + + data.each do |k,v| + assert_equal(v, @config.send(k)) + end + + @config.setup_gpg_key('password', 'test@example.com', 2048) + assert(@config.check_gpg_key?) + end +end diff --git a/test/test_item.rb b/test/test_item.rb index 923d7af..b9f5961 100644 --- a/test/test_item.rb +++ b/test/test_item.rb @@ -1,19 +1,19 @@ #!/usr/bin/ruby -require_relative '../lib/Item' +require 'mpw/item' require 'test/unit' require 'yaml' class TestItem < Test::Unit::TestCase def setup - @fixture_file = 'files/fixtures.yml' + @fixture_file = 'test/files/fixtures.yml' @fixtures = YAML.load_file(@fixture_file) if defined?(I18n.enforce_available_locales) I18n.enforce_available_locales = false end - I18n.load_path = Dir['../i18n/cli/*.yml'] + I18n.load_path = Dir['./i18n/cli/*.yml'] I18n.default_locale = :en @@ -25,14 +25,12 @@ class TestItem < Test::Unit::TestCase end def test_01_add_new - data = {name: @fixtures['add_new']['name'], - group: @fixtures['add_new']['group'], - host: @fixtures['add_new']['host'], - protocol: @fixtures['add_new']['protocol'], - user: @fixtures['add_new']['user'], - password: @fixtures['add_new']['password'], - port: @fixtures['add_new']['port'], - comment: @fixtures['add_new']['comment'], + data = { group: @fixtures['add_new']['group'], + host: @fixtures['add_new']['host'], + protocol: @fixtures['add_new']['protocol'], + user: @fixtures['add_new']['user'], + port: @fixtures['add_new']['port'], + comment: @fixtures['add_new']['comment'], } item = MPW::Item.new(data) @@ -40,27 +38,23 @@ class TestItem < Test::Unit::TestCase assert(!item.nil?) assert(!item.empty?) - assert_equal(@fixtures['add_new']['name'], item.name) assert_equal(@fixtures['add_new']['group'], item.group) assert_equal(@fixtures['add_new']['host'], item.host) assert_equal(@fixtures['add_new']['protocol'], item.protocol) assert_equal(@fixtures['add_new']['user'], item.user) - assert_equal(@fixtures['add_new']['password'], item.password) assert_equal(@fixtures['add_new']['port'].to_i, item.port) assert_equal(@fixtures['add_new']['comment'], item.comment) end def test_02_add_existing - data = {id: @fixtures['add_existing']['id'], - name: @fixtures['add_existing']['name'], - group: @fixtures['add_existing']['group'], - host: @fixtures['add_existing']['host'], - protocol: @fixtures['add_existing']['protocol'], - user: @fixtures['add_existing']['user'], - password: @fixtures['add_existing']['password'], - port: @fixtures['add_existing']['port'], - comment: @fixtures['add_existing']['comment'], - created: @fixtures['add_existing']['created'], + data = { id: @fixtures['add_existing']['id'], + group: @fixtures['add_existing']['group'], + host: @fixtures['add_existing']['host'], + protocol: @fixtures['add_existing']['protocol'], + user: @fixtures['add_existing']['user'], + port: @fixtures['add_existing']['port'], + comment: @fixtures['add_existing']['comment'], + created: @fixtures['add_existing']['created'], } item = MPW::Item.new(data) @@ -69,26 +63,22 @@ class TestItem < Test::Unit::TestCase assert(!item.empty?) assert_equal(@fixtures['add_existing']['id'], item.id) - assert_equal(@fixtures['add_existing']['name'], item.name) assert_equal(@fixtures['add_existing']['group'], item.group) assert_equal(@fixtures['add_existing']['host'], item.host) assert_equal(@fixtures['add_existing']['protocol'], item.protocol) assert_equal(@fixtures['add_existing']['user'], item.user) - assert_equal(@fixtures['add_existing']['password'], item.password) assert_equal(@fixtures['add_existing']['port'].to_i, item.port) assert_equal(@fixtures['add_existing']['comment'], item.comment) assert_equal(@fixtures['add_existing']['created'], item.created) end def test_03_update - data = {name: @fixtures['add_new']['name'], - group: @fixtures['add_new']['group'], - host: @fixtures['add_new']['host'], - protocol: @fixtures['add_new']['protocol'], - user: @fixtures['add_new']['user'], - password: @fixtures['add_new']['password'], - port: @fixtures['add_new']['port'], - comment: @fixtures['add_new']['comment'], + data = { group: @fixtures['add_new']['group'], + host: @fixtures['add_new']['host'], + protocol: @fixtures['add_new']['protocol'], + user: @fixtures['add_new']['user'], + port: @fixtures['add_new']['port'], + comment: @fixtures['add_new']['comment'], } item = MPW::Item.new(data) @@ -99,14 +89,12 @@ class TestItem < Test::Unit::TestCase created = item.created last_edit = item.last_edit - data = {name: @fixtures['update']['name'], - group: @fixtures['update']['group'], - host: @fixtures['update']['host'], - protocol: @fixtures['update']['protocol'], - user: @fixtures['update']['user'], - password: @fixtures['update']['password'], - port: @fixtures['update']['port'], - comment: @fixtures['update']['comment'], + data = { group: @fixtures['update']['group'], + host: @fixtures['update']['host'], + protocol: @fixtures['update']['protocol'], + user: @fixtures['update']['user'], + port: @fixtures['update']['port'], + comment: @fixtures['update']['comment'], } sleep(1) @@ -114,12 +102,10 @@ class TestItem < Test::Unit::TestCase assert(!item.empty?) - assert_equal(@fixtures['update']['name'], item.name) assert_equal(@fixtures['update']['group'], item.group) assert_equal(@fixtures['update']['host'], item.host) assert_equal(@fixtures['update']['protocol'], item.protocol) assert_equal(@fixtures['update']['user'], item.user) - assert_equal(@fixtures['update']['password'], item.password) assert_equal(@fixtures['update']['port'].to_i, item.port) assert_equal(@fixtures['update']['comment'], item.comment) @@ -127,39 +113,13 @@ class TestItem < Test::Unit::TestCase assert_not_equal(last_edit, item.last_edit) end - def test_04_update_with_empty_name - data = {name: @fixtures['add_new']['name'], - group: @fixtures['add_new']['group'], - host: @fixtures['add_new']['host'], - protocol: @fixtures['add_new']['protocol'], - user: @fixtures['add_new']['user'], - password: @fixtures['add_new']['password'], - port: @fixtures['add_new']['port'], - comment: @fixtures['add_new']['comment'], - } - - item = MPW::Item.new(data) - - assert(!item.nil?) - assert(!item.empty?) - - last_edit = item.last_edit - - sleep(1) - assert(!item.update({name: ''})) - - assert_equal(last_edit, item.last_edit) - end - def test_05_update_one_element - data = {name: @fixtures['add_new']['name'], - group: @fixtures['add_new']['group'], - host: @fixtures['add_new']['host'], - protocol: @fixtures['add_new']['protocol'], - user: @fixtures['add_new']['user'], - password: @fixtures['add_new']['password'], - port: @fixtures['add_new']['port'], - comment: @fixtures['add_new']['comment'], + data = { group: @fixtures['add_new']['group'], + host: @fixtures['add_new']['host'], + protocol: @fixtures['add_new']['protocol'], + user: @fixtures['add_new']['user'], + port: @fixtures['add_new']['port'], + comment: @fixtures['add_new']['comment'], } item = MPW::Item.new(data) @@ -172,12 +132,10 @@ class TestItem < Test::Unit::TestCase sleep(1) assert(item.update({comment: @fixtures['update']['comment']})) - assert_equal(@fixtures['add_new']['name'], item.name) assert_equal(@fixtures['add_new']['group'], item.group) assert_equal(@fixtures['add_new']['host'], item.host) assert_equal(@fixtures['add_new']['protocol'], item.protocol) assert_equal(@fixtures['add_new']['user'], item.user) - assert_equal(@fixtures['add_new']['password'], item.password) assert_equal(@fixtures['add_new']['port'].to_i, item.port) assert_equal(@fixtures['update']['comment'], item.comment) @@ -185,14 +143,12 @@ class TestItem < Test::Unit::TestCase end def test_05_delete - data = {name: @fixtures['add_new']['name'], - group: @fixtures['add_new']['group'], - host: @fixtures['add_new']['host'], - protocol: @fixtures['add_new']['protocol'], - user: @fixtures['add_new']['user'], - password: @fixtures['add_new']['password'], - port: @fixtures['add_new']['port'], - comment: @fixtures['add_new']['comment'], + data = { group: @fixtures['add_new']['group'], + host: @fixtures['add_new']['host'], + protocol: @fixtures['add_new']['protocol'], + user: @fixtures['add_new']['user'], + port: @fixtures['add_new']['port'], + comment: @fixtures['add_new']['comment'], } item = MPW::Item.new(data) @@ -200,17 +156,15 @@ class TestItem < Test::Unit::TestCase assert(!item.nil?) assert(!item.empty?) - assert(item.delete) + item.delete assert(!item.nil?) assert(item.empty?) assert_equal(nil, item.id) - assert_equal(nil, item.name) assert_equal(nil, item.group) assert_equal(nil, item.host) assert_equal(nil, item.protocol) assert_equal(nil, item.user) - assert_equal(nil, item.password) assert_equal(nil, item.port) assert_equal(nil, item.comment) assert_equal(nil, item.created) diff --git a/test/test_mpw.rb b/test/test_mpw.rb index 899b366..0c6a25b 100644 --- a/test/test_mpw.rb +++ b/test/test_mpw.rb @@ -1,121 +1,44 @@ #!/usr/bin/ruby -require_relative '../lib/MPW' -require_relative '../lib/Item' +require 'mpw/mpw' +require 'mpw/item' require 'test/unit' require 'yaml' require 'csv' class TestMPW < Test::Unit::TestCase def setup - fixture_file = 'files/fixtures.yml' + fixture_file = './test/files/fixtures.yml' - file_gpg = 'test.gpg' - key = ENV['MPW_TEST_KEY'] - - puts + wallet_file = 'default.gpg' + key = 'test@example.com' + password = 'password' if defined?(I18n.enforce_available_locales) I18n.enforce_available_locales = false end - File.delete(file_gpg) if File.exist?(file_gpg) - - @mpw = MPW::MPW.new(file_gpg, key) + @mpw = MPW::MPW.new(key, wallet_file, password) @fixtures = YAML.load_file(fixture_file) end - def test_01_import_yaml - import_file = 'files/test_import.yml' - - assert(@mpw.import(import_file, :yaml)) - assert_equal(2, @mpw.list.length) - - item = @mpw.list[0] - assert_equal(@fixtures['add_new']['name'], item.name) - assert_equal(@fixtures['add_new']['group'], item.group) - assert_equal(@fixtures['add_new']['host'], item.host) - assert_equal(@fixtures['add_new']['protocol'], item.protocol) - assert_equal(@fixtures['add_new']['user'], item.user) - assert_equal(@fixtures['add_new']['password'], item.password) - assert_equal(@fixtures['add_new']['port'].to_i, item.port) - assert_equal(@fixtures['add_new']['comment'], item.comment) + def test_00_decrypt_empty_file + @mpw.read_data + assert_equal(0, @mpw.list.length) end - def test_02_export_yaml - import_file = 'files/test_import.yml' - export_file = 'test_export.yml' - - assert(@mpw.import(import_file)) - assert_equal(2, @mpw.list.length) - assert(@mpw.export(export_file, :yaml)) - export = YAML::load_file(export_file) - assert_equal(2, export.length) - - result = export.values[0] - assert_equal(@fixtures['add_new']['name'], result['name']) - assert_equal(@fixtures['add_new']['group'], result['group']) - assert_equal(@fixtures['add_new']['host'], result['host']) - assert_equal(@fixtures['add_new']['protocol'], result['protocol']) - assert_equal(@fixtures['add_new']['user'], result['user']) - assert_equal(@fixtures['add_new']['password'], result['password']) - assert_equal(@fixtures['add_new']['port'].to_i, result['port']) - assert_equal(@fixtures['add_new']['comment'], result['comment']) - - File.unlink(export_file) + def test_01_encrypt_empty_file + @mpw.read_data + @mpw.write_data end - def test_03_import_csv - import_file = 'files/test_import.csv' - - assert(@mpw.import(import_file, :csv)) - assert_equal(2, @mpw.list.length) - - import = CSV.parse(File.read(import_file), headers: true) - - item = @mpw.list[0] - assert_equal(import[0]['name'], item.name) - assert_equal(import[0]['group'], item.group) - assert_equal(import[0]['host'], item.host) - assert_equal(import[0]['protocol'], item.protocol) - assert_equal(import[0]['user'], item.user) - assert_equal(import[0]['password'], item.password) - assert_equal(import[0]['port'].to_i, item.port) - assert_equal(import[0]['comment'], item.comment) - end - - def test_04_export_csv - import_file = 'files/test_import.csv' - export_file = 'test_export.csv' - - assert(@mpw.import(import_file, :csv)) - assert_equal(2, @mpw.list.length) - assert(@mpw.export(export_file, :csv)) - export = CSV.parse(File.read(export_file), headers: true) - assert_equal(2, export.length) - - result = export[0] - assert_equal(@fixtures['add_new']['name'], result['name']) - assert_equal(@fixtures['add_new']['group'], result['group']) - assert_equal(@fixtures['add_new']['host'], result['host']) - assert_equal(@fixtures['add_new']['protocol'], result['protocol']) - assert_equal(@fixtures['add_new']['user'], result['user']) - assert_equal(@fixtures['add_new']['password'], result['password']) - assert_equal(@fixtures['add_new']['port'], result['port']) - assert_equal(@fixtures['add_new']['comment'], result['comment']) - - File.unlink(export_file) - end - - def test_05_add_item - data = {name: @fixtures['add_new']['name'], - group: @fixtures['add_new']['group'], - host: @fixtures['add_new']['host'], - protocol: @fixtures['add_new']['protocol'], - user: @fixtures['add_new']['user'], - password: @fixtures['add_new']['password'], - port: @fixtures['add_new']['port'], - comment: @fixtures['add_new']['comment'], + def test_02_add_item + data = { group: @fixtures['add_new']['group'], + host: @fixtures['add_new']['host'], + protocol: @fixtures['add_new']['protocol'], + user: @fixtures['add_new']['user'], + port: @fixtures['add_new']['port'], + comment: @fixtures['add_new']['comment'], } item = MPW::Item.new(data) @@ -123,69 +46,76 @@ class TestMPW < Test::Unit::TestCase assert(!item.nil?) assert(!item.empty?) - assert(@mpw.add(item)) + @mpw.read_data + @mpw.add(item) + @mpw.set_password(item.id, @fixtures['add_new']['password']) assert_equal(1, @mpw.list.length) item = @mpw.list[0] - assert_equal(@fixtures['add_new']['name'], item.name) - assert_equal(@fixtures['add_new']['group'], item.group) - assert_equal(@fixtures['add_new']['host'], item.host) - assert_equal(@fixtures['add_new']['protocol'], item.protocol) - assert_equal(@fixtures['add_new']['user'], item.user) - assert_equal(@fixtures['add_new']['password'], item.password) - assert_equal(@fixtures['add_new']['port'].to_i, item.port) - assert_equal(@fixtures['add_new']['comment'], item.comment) + @fixtures['add_new'].each do |k,v| + if k == 'password' + assert_equal(v, @mpw.get_password(item.id)) + else + assert_equal(v, item.send(k).to_s) + end + end + + @mpw.write_data end - def test_11_encrypt_empty_file - assert(@mpw.encrypt) - end - - def test_12_encrypt - import_file = 'files/test_import.yml' - - assert(@mpw.import(import_file, :yaml)) - assert_equal(2, @mpw.list.length) - - assert(@mpw.encrypt) - end - - def test_13_decrypt_empty_file - assert(@mpw.decrypt) - assert_equal(0, @mpw.list.length) - end - - def test_14_decrypt - import_file = 'files/test_import.yml' - - assert(@mpw.import(import_file, :yaml)) - assert_equal(2, @mpw.list.length) - - assert(@mpw.encrypt) - - assert(@mpw.decrypt) - assert_equal(2, @mpw.list.length) + def test_03_decrypt_file + @mpw.read_data + assert_equal(1, @mpw.list.length) item = @mpw.list[0] - assert_equal(@fixtures['add_new']['name'], item.name) - assert_equal(@fixtures['add_new']['group'], item.group) - assert_equal(@fixtures['add_new']['host'], item.host) - assert_equal(@fixtures['add_new']['protocol'], item.protocol) - assert_equal(@fixtures['add_new']['user'], item.user) - assert_equal(@fixtures['add_new']['password'], item.password) - assert_equal(@fixtures['add_new']['port'].to_i, item.port) - assert_equal(@fixtures['add_new']['comment'], item.comment) + @fixtures['add_new'].each do |k,v| + if k == 'password' + assert_equal(v, @mpw.get_password(item.id)) + else + assert_equal(v, item.send(k).to_s) + end + end end - def test_15_search - import_file = 'files/test_import.yml' + def test_04_delete_item + @mpw.read_data - assert(@mpw.import(import_file, :yaml)) - assert_equal(2, @mpw.list.length) + assert_equal(1, @mpw.list.length) + @mpw.list.each do |item| + item.delete + end + + assert_equal(0, @mpw.list.length) + + @mpw.write_data + end + + def test_05_search + @mpw.read_data + + @fixtures.each_value do |v| + data = { group: v['group'], + host: v['host'], + protocol: v['protocol'], + user: v['user'], + port: v['port'], + comment: v['comment'], + } + + item = MPW::Item.new(data) + + assert(!item.nil?) + assert(!item.empty?) + + @mpw.add(item) + @mpw.set_password(item.id, v['password']) + end + + assert_equal(3, @mpw.list.length) assert_equal(1, @mpw.list(group: @fixtures['add_new']['group']).length) - assert_equal(1, @mpw.list(protocol: @fixtures['add_new']['protocol']).length) - assert_equal(2, @mpw.list(search: @fixtures['add_new']['name'][0..-2]).length) + assert_equal(1, @mpw.list(pattern: 'existing').length) + assert_equal(2, @mpw.list(pattern: 'host_[eu]').length) end end diff --git a/test/tests.rb b/test/tests.rb index d3735f5..b85efc0 100644 --- a/test/tests.rb +++ b/test/tests.rb @@ -1,4 +1,5 @@ #!/usr/bin/ruby -require_relative 'test_mpw.rb' +require_relative 'test_config.rb' require_relative 'test_item.rb' +require_relative 'test_mpw.rb' From c01c795ecaa55a4fe91d94dffe9ebc07ccc7b951 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Fri, 11 Nov 2016 00:24:38 +0100 Subject: [PATCH 366/531] add version --- README.rst | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/README.rst b/README.rst index 432b4d8..17725d2 100644 --- a/README.rst +++ b/README.rst @@ -1,6 +1,6 @@ MPW: Manage your passwords! ******************************************************* -|Build Status| |License| +|Version| |Build Status| |License| mpw is a little software which stores your passwords in `GnuPG <http://www.gnupg.org/>`_ encrypted files. @@ -46,11 +46,9 @@ Output:: 2 | linuxfr.org | example | https | | | Da Linux French Site -Licence |License| -================= - -Full license here: `LICENSE <https://github.com/nishiki/manage-password/blob/master/LICENSE>`_ - +.. |Version| image:: https://img.shields.io/badge/latest_version-4.0.0--beta-yellow.svg + :target: https://github.com/nishiki/manage-password/releases .. |License| image:: https://img.shields.io/badge/license-GPL--2.0-blue.svg + :target: https://github.com/nishiki/manage-password/blob/master/LICENSE .. |Build Status| image:: https://travis-ci.org/nishiki/manage-password.svg?branch=master :target: https://travis-ci.org/nishiki/manage-password From 04e8a2cd0bc40d26a444e65ae5e02300db6e615e Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Sat, 12 Nov 2016 16:54:41 +0100 Subject: [PATCH 367/531] add test translate --- test/test_translate.rb | 31 +++++++++++++++++++++++++++++++ test/tests.rb | 1 + 2 files changed, 32 insertions(+) create mode 100644 test/test_translate.rb diff --git a/test/test_translate.rb b/test/test_translate.rb new file mode 100644 index 0000000..fe9a575 --- /dev/null +++ b/test/test_translate.rb @@ -0,0 +1,31 @@ +#!/usr/bin/ruby + +require 'yaml' +require 'test/unit' + +class TestTranslate < Test::Unit::TestCase + def test_00_check_translate + missing = 0 + + Dir.glob('i18n/*.yml').each do |yaml| + lang = File.basename(yaml, '.yml') + translate = YAML.load_file(yaml) + + `grep -r -o "I18n.t('.*')" bin/ lib/ | cut -d"'" -f2`.each_line do |line| + begin + t = translate[lang] + line.strip.split('.').each do |v| + t = t[v] + end + + assert(!t.to_s.empty?) + rescue + puts "#{lang}.#{line}" + missing = 1 + end + end + end + + assert_equal(0, missing) + end +end diff --git a/test/tests.rb b/test/tests.rb index b85efc0..e4efc5d 100644 --- a/test/tests.rb +++ b/test/tests.rb @@ -3,3 +3,4 @@ require_relative 'test_config.rb' require_relative 'test_item.rb' require_relative 'test_mpw.rb' +require_relative 'test_translate.rb' From d8339b53deb810ff24cdeb455cfd18dc0c240409 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Sat, 12 Nov 2016 17:16:57 +0100 Subject: [PATCH 368/531] fix missing translate --- i18n/en.yml | 8 ++++++++ i18n/fr.yml | 8 ++++++++ lib/mpw/cli.rb | 4 ++-- lib/mpw/mpw.rb | 2 +- 4 files changed, 19 insertions(+), 3 deletions(-) diff --git a/i18n/en.yml b/i18n/en.yml index 93955d5..e1ffcf7 100644 --- a/i18n/en.yml +++ b/i18n/en.yml @@ -1,6 +1,7 @@ --- en: error: + bad_class: "The object class isn't valid!" config: write: "Can't write the config file!" load: "Checkconfig failed!" @@ -10,7 +11,9 @@ en: exception: "Can't create the GPG key!" name: "You must define a name for your GPG key!" password: "You must define a password for your GPG key!" + empty: "The class is void" export: "Can't export, unable to write in %{file}!" + export_key: "Can't export the GPG key" gpg_file: decrypt: "Can't decrypt file!" encrypt: "Can't encrypt the GPG file!" @@ -64,6 +67,7 @@ en: import: "Import item since a yaml file" key: "Specify the key name" lang: "Set the software language" + length: "Size of the password" list: "List the wallets" no_sync: "Disable synchronization with the server" numeric: "Use number to generate a password" @@ -72,6 +76,7 @@ en: pattern: "Given search pattern" port: "Specify the connection port" protocol: "Specify the protocol for the connection" + random_password: "Generate a random password" setup: "Create a new configuration file" setup_wallet: "Create a new configuration file for a wallet" special_chars: "Use special char to generate a password" @@ -116,6 +121,8 @@ en: valid: "The item has been removed!" import: ask: "Are you sure you want to import this file %{file} ?" + file_empty: "The import file is empty!" + file_not_exist: "The import file doesn't exist!" valid: "The import is succesfull!" not_valid: "No data to import!" setup_config: @@ -126,6 +133,7 @@ en: wallet_dir: "Enter the wallets's folder path [default=%{home}/wallets]: " valid: "The config file has been created!" setup_wallet: + password: "Sync password: " title: "Wallet setup" sync_type: "Synchronization type (ssh, ftp): " sync_host: "Synchronization server: " diff --git a/i18n/fr.yml b/i18n/fr.yml index 4f8b7ac..82e5af3 100644 --- a/i18n/fr.yml +++ b/i18n/fr.yml @@ -1,6 +1,7 @@ --- fr: error: + bad_class: "La classe de l'objet n'est pas celle attendue!" config: write: "Impossible d'écrire le fichier de configuration!" load: "Le fichier de configuration est invalide!" @@ -10,7 +11,9 @@ fr: exception: "La création de la clé GPG n'a pas pu aboutir!" name: "Vous devez définir un nom pour votre clé GPG!" password: "Vous devez définir un mot de passe pour votre clé GPG!" + empty: "La classe est vide" export: "Impossible d'exporter les données dans le fichier %{file}!" + export_key: "Impossible d'exporter la clé GPG" gpg_file: decrypt: "Impossible de déchiffrer le fichier GPG!" encrypt: "Impossible de chiffrer le fichier GPG!" @@ -64,6 +67,7 @@ fr: init: "Initialise mpw" key: "Spécifie le nom d'une clé" lang: "Spécifie la langue du logiciel (ex: fr)" + length: "Taille du mot de passe" list: "Liste les portefeuilles" no_sync: "Désactive la synchronisation avec le serveur" numeric: "Utilise des chiffre dans la génération d'un mot de passe" @@ -72,6 +76,7 @@ fr: pattern: "Motif de donnée à chercher" port: "Spécifie le port de connexion" protocol: "Spécifie le protocol utilisé pour la connexion" + random_password: "Génére un mot de passe aléatoire" setup: "Création d'un nouveau fichier de configuration" setup_wallet: "Création d'un nouveau fichier de configuration pour un portefeuille" special_chars: "Utilise des charactères speciaux dans la génération d'un mot de passe" @@ -116,6 +121,8 @@ fr: valid: "L'élément a bien été supprimé!" import: ask: "Êtes vous sûre de vouloir importer le fichier %{file} ?" + file_empty: "Le fichier d'import est vide!" + file_not_exist: "Le fichier d'import n'existe pas" valid: "L'import est un succès!" not_valid: "Aucune donnée à importer!" setup_config: @@ -126,6 +133,7 @@ fr: wallet_dir: "Entrez le chemin du répertoire qui contiendra les porte-feuilles de mot de passe [défaut=%{home}/wallets]: " valid: "Le fichier de configuration a bien été créé!" setup_wallet: + password: "Mot de passe de synchronisation: " title: "Configuration du porte-feuille" sync_type: "Type de synchronisation (ssh, ftp): " sync_host: "Serveur: " diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index 722b16d..8cd700a 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -517,8 +517,8 @@ class Cli # Import items from a YAML file # @args: file -> the import file def import(file) - raise I18n.t('import.file_empty') if file.to_s.empty? - raise I18n.t('import.file_not_exist') if not File.exist?(file) + raise I18n.t('form.import.file_empty') if file.to_s.empty? + raise I18n.t('form.import.file_not_exist') if not File.exist?(file) YAML::load_file(file).each_value do |row| diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index 533077e..91bd04a 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -228,7 +228,7 @@ class MPW if not item.instance_of?(Item) raise I18n.t('error.bad_class') elsif item.empty? - raise I18n.t('error.add.empty') + raise I18n.t('error.empty') else @data.push(item) end From 36e0f83175e1bc440af907166430ccb095be5ecb Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Mon, 12 Dec 2016 22:15:09 +0100 Subject: [PATCH 369/531] fix gpg key name --- bin/mpw-config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/mpw-config b/bin/mpw-config index 120da5b..fb6b372 100644 --- a/bin/mpw-config +++ b/bin/mpw-config @@ -68,7 +68,7 @@ if not options[:init].nil? cli.setup(values) cli.load_config cli.get_wallet - cli.setup_gpg_key(options[:init]) + cli.setup_gpg_key(values[:gpg_key]) cli.setup_wallet_config else cli.set_config(values) From 3575cd9bd7095c09253492f314acff8f699d3a45 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Mon, 12 Dec 2016 23:09:52 +0100 Subject: [PATCH 370/531] feat change add key --- lib/mpw/cli.rb | 7 +++---- lib/mpw/mpw.rb | 12 ++++++------ 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index 8cd700a..43256d1 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -334,10 +334,9 @@ class Cli end # Add a new public key - # args: key -> the key name to add - # file -> gpg public file to import - def add_key(key, file=nil) - @mpw.add_key(key, file) + # args: key -> the key name or key file to add + def add_key(key) + @mpw.add_key(key) @mpw.write_data @mpw.sync(true) if @sync diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index 91bd04a..7e50547 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -185,12 +185,12 @@ class MPW end # Add a public key - # args: key -> new public key - # file -> public gpg file to import - def add_key(key, file=nil) - if not file.nil? and File.exists?(file) - data = File.open(file).read - GPGME::Key.import(data, armor: true) + # args: key -> new public key file or name + def add_key(key) + if File.exists?(key) + data = File.open(key).read + key_import = GPGME::Key.import(data, armor: true) + key = GPGME::Key.get(key_import.imports[0].fpr).uids[0].email else data = GPGME::Key.export(key, armor: true).read end From bf356f4d6f9dbcbab6ba150d898f99db0cdfa5fb Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Mon, 12 Dec 2016 23:13:32 +0100 Subject: [PATCH 371/531] add an option for add a share gpg key --- bin/mpw-wallet | 6 ++++++ i18n/en.yml | 1 + i18n/fr.yml | 1 + 3 files changed, 8 insertions(+) diff --git a/bin/mpw-wallet b/bin/mpw-wallet index b81e6b2..f6ea562 100644 --- a/bin/mpw-wallet +++ b/bin/mpw-wallet @@ -31,6 +31,10 @@ values = {} OptionParser.new do |opts| opts.banner = "#{I18n.t('option.usage')}: mpw wallet [options]" + opts.on('-a', '--add-gpg-key NAME', I18n.t('option.add_gpg_key')) do |gpg_key| + options[:gpg_key] = gpg_key + end + opts.on('-c', '--config PATH', I18n.t('option.config')) do |config| options[:config] = config end @@ -84,6 +88,8 @@ cli.load_config if not options[:list].nil? cli.list_wallet +elsif not options[:gpg_key].nil? + cli.add_key(options[:gpg_key]) else cli.get_wallet(options[:wallet]) cli.decrypt diff --git a/i18n/en.yml b/i18n/en.yml index e1ffcf7..eb45c86 100644 --- a/i18n/en.yml +++ b/i18n/en.yml @@ -50,6 +50,7 @@ en: option: add: "Add an item or key" + add_gpg_key: "Share the wallet with an other GPG key (name or file path)" alpha: "Use letter to generate a password" config: "Specify the configuration file to use" clipboard: "Disable the clipboard feature" diff --git a/i18n/fr.yml b/i18n/fr.yml index 82e5af3..5a0ebc0 100644 --- a/i18n/fr.yml +++ b/i18n/fr.yml @@ -50,6 +50,7 @@ fr: option: add: "Ajoute un élément ou une clé" + add_gpg_key: "Partage le portefeuille avec une autre clé GPG (nom ou fichier)" alpha: "Utilise des lettres dans la génération d'un mot de passe" config: "Spécifie le fichier de configuration à utiliser" clipboard: "Désactive la fonction presse papier" From cb409b1545bb3a2394c071f16a8a4e947c066ce3 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Tue, 24 Jan 2017 22:58:03 +0100 Subject: [PATCH 372/531] fix bug when port is > 4 number --- lib/mpw/cli.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index 8cd700a..47dfa04 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -153,7 +153,7 @@ class Cli data.each do |k, v| next if k == :id or k == :otp - v[:length] = item.send(k.to_s).length + 3 if item.send(k.to_s).to_s.length >= v[:length] + v[:length] = item.send(k.to_s).to_s.length + 3 if item.send(k.to_s).to_s.length >= v[:length] end end data[:id][:length] = items.length.to_s.length + 2 if items.length.to_s.length > data[:id][:length] From 50aa7713f47fd3cd7765190fe2c30eab843656ed Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Mon, 30 Jan 2017 20:29:42 +0100 Subject: [PATCH 373/531] fix error message when host is empty --- i18n/en.yml | 2 +- i18n/fr.yml | 2 +- lib/mpw/item.rb | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/i18n/en.yml b/i18n/en.yml index e1ffcf7..252efee 100644 --- a/i18n/en.yml +++ b/i18n/en.yml @@ -22,7 +22,7 @@ en: write_data: "Can't to write the MPW file!" import: "Can't import, unable to read %{file}!" update: - name_empty: "You must define a name!" + host_empty: "You must define a host!" sync: general: "An error has appeared during the sync" connection: "Connection fail!" diff --git a/i18n/fr.yml b/i18n/fr.yml index 82e5af3..16160cd 100644 --- a/i18n/fr.yml +++ b/i18n/fr.yml @@ -22,7 +22,7 @@ fr: write_data: "Impossible d'écrire le fichier MPW!" import: "Impossible d'importer le fichier %{file}, car il n'est pas lisible!" update: - name_empty: "Vous devez définir un nom!" + host_empty: "Vous devez définir un host!" sync: general: "Une erreur est survenue durant la synchronisation" connection: "La connexion n'a pu être établie!" diff --git a/lib/mpw/item.rb b/lib/mpw/item.rb index 4beb49f..d3783b9 100644 --- a/lib/mpw/item.rb +++ b/lib/mpw/item.rb @@ -39,7 +39,7 @@ class Item # raise an error if the hash hasn't the key name def initialize(options={}) if not options.has_key?(:host) or options[:host].to_s.empty? - raise I18n.t('error.update.name_empty') + raise I18n.t('error.update.host_empty') end if not options.has_key?(:id) or options[:id].to_s.empty? or not options.has_key?(:created) or options[:created].to_s.empty? @@ -59,7 +59,7 @@ class Item # @args: options -> a hash of parameter def update(options={}) if options.has_key?(:host) and options[:host].to_s.empty? - raise I18n.t('error.update.name_empty') + raise I18n.t('error.update.host_empty') end @group = options[:group] if options.has_key?(:group) From 8c5be6b795a784f5407e34268a39c15b151daac4 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Mon, 30 Jan 2017 22:10:56 +0100 Subject: [PATCH 374/531] wallet: add remove gpg key option --- bin/mpw-wallet | 18 ++++++++++++++---- i18n/en.yml | 3 ++- i18n/fr.yml | 3 ++- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/bin/mpw-wallet b/bin/mpw-wallet index f6ea562..8bdfb1c 100644 --- a/bin/mpw-wallet +++ b/bin/mpw-wallet @@ -24,9 +24,10 @@ require 'mpw/cli' # Options # --------------------------------------------------------- # -options = {} -options[:sync] = {} -values = {} +options = {} +options[:sync] = {} +options[:delete] = false +values = {} OptionParser.new do |opts| opts.banner = "#{I18n.t('option.usage')}: mpw wallet [options]" @@ -39,6 +40,11 @@ OptionParser.new do |opts| options[:config] = config end + opts.on('-d', '--delete-gpg-key NAME', I18n.t('option.delete_gpg_key')) do |gpg_key| + options[:gpg_key] = gpg_key + options[:delete] = true + end + opts.on('-h', '--help', I18n.t('option.help')) do puts opts exit 0 @@ -89,7 +95,11 @@ cli.load_config if not options[:list].nil? cli.list_wallet elsif not options[:gpg_key].nil? - cli.add_key(options[:gpg_key]) + if options[:delete] + cli.delete_key(options[:gpg_key]) + else + cli.add_key(options[:gpg_key]) + end else cli.get_wallet(options[:wallet]) cli.decrypt diff --git a/i18n/en.yml b/i18n/en.yml index eb45c86..6b1f23f 100644 --- a/i18n/en.yml +++ b/i18n/en.yml @@ -50,10 +50,11 @@ en: option: add: "Add an item or key" - add_gpg_key: "Share the wallet with an other GPG key (name or file path)" + add_gpg_key: "Share the wallet with an other GPG key" alpha: "Use letter to generate a password" config: "Specify the configuration file to use" clipboard: "Disable the clipboard feature" + add_gpg_key: "Delete the wallet's share with an other GPG key" export: "Export a wallet in an yaml file" file_export: "Specify the file where export data" file_import: "Specify the file to import" diff --git a/i18n/fr.yml b/i18n/fr.yml index 5a0ebc0..8dc6d21 100644 --- a/i18n/fr.yml +++ b/i18n/fr.yml @@ -50,10 +50,11 @@ fr: option: add: "Ajoute un élément ou une clé" - add_gpg_key: "Partage le portefeuille avec une autre clé GPG (nom ou fichier)" + add_gpg_key: "Partage le portefeuille avec une autre clé GPG" alpha: "Utilise des lettres dans la génération d'un mot de passe" config: "Spécifie le fichier de configuration à utiliser" clipboard: "Désactive la fonction presse papier" + delete_gpg_key: "Supprime le partage le portefeuille avec une autre clé GPG" export: "Exporte un portefeuille dans un fichier yaml" file_export: "Spécifie le fichier où exporter les données" file_import: "Spécifie le fichier à importer" From d6d7074341ad199eeca20fe31f6acc5c543adf26 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Mon, 30 Jan 2017 22:20:22 +0100 Subject: [PATCH 375/531] fix error message when there is a bad option --- bin/mpw | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/bin/mpw b/bin/mpw index 8e578f8..464980c 100755 --- a/bin/mpw +++ b/bin/mpw @@ -21,6 +21,7 @@ $: << File.expand_path('../../lib', __FILE__) require 'locale' require 'set' require 'i18n' +require 'colorize' # --------------------------------------------------------- # # Set local @@ -45,7 +46,11 @@ bin_dir = File.dirname(__FILE__) command = "#{bin_dir}/mpw-#{ARGV[0]}" if Dir.glob("#{bin_dir}/mpw-*").include?("#{command}") - Kernel.load(command) + begin + Kernel.load(command) + rescue Exception => e + puts "#{I18n.t('display.error')}: #{e}".red + end else puts "#{I18n.t('option.usage')}: mpw COMMAND [options]\n\n" puts 'Commands:' From 06c876861b7d246db798218bcf7ea555c2c96ad4 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Mon, 30 Jan 2017 22:26:18 +0100 Subject: [PATCH 376/531] fix english translation --- i18n/en.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/en.yml b/i18n/en.yml index 6b1f23f..6f3d4c8 100644 --- a/i18n/en.yml +++ b/i18n/en.yml @@ -54,7 +54,7 @@ en: alpha: "Use letter to generate a password" config: "Specify the configuration file to use" clipboard: "Disable the clipboard feature" - add_gpg_key: "Delete the wallet's share with an other GPG key" + delete_gpg_key: "Delete the wallet's share with an other GPG key" export: "Export a wallet in an yaml file" file_export: "Specify the file where export data" file_import: "Specify the file to import" From a1a21f96179f09107770e37e0d72fbc60eb56094 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Sat, 11 Feb 2017 11:24:12 +0100 Subject: [PATCH 377/531] mpw: add function list_keys --- lib/mpw/mpw.rb | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index 7e50547..c5023e6 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -184,6 +184,12 @@ class MPW @passwords[id] = encrypt(password) end + # Return the list of all gpg keys + # rtrn: an array with the gpg keys name + def list_keys + return @keys.keys + end + # Add a public key # args: key -> new public key file or name def add_key(key) From b287b719fee1f3b47d07ced3ef30ffb9d97ff02a Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Sat, 11 Feb 2017 11:24:49 +0100 Subject: [PATCH 378/531] add test to check add and delete gpg key --- test/test_mpw.rb | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/test/test_mpw.rb b/test/test_mpw.rb index 0c6a25b..b1c80c9 100644 --- a/test/test_mpw.rb +++ b/test/test_mpw.rb @@ -118,4 +118,26 @@ class TestMPW < Test::Unit::TestCase assert_equal(1, @mpw.list(pattern: 'existing').length) assert_equal(2, @mpw.list(pattern: 'host_[eu]').length) end + + def test_06_add_gpg_key + @config = MPW::Config.new + @config.setup_gpg_key('password', 'test2@example.com', 2048) + + @mpw.read_data + + @mpw.add_key('test2@example.com') + assert_equal(2, @mpw.keys.length) + + @mpw.write_data + end + + def test07_delete_gpg_key + @mpw.read_data + assert_equal(2, @mpw.keys.length) + + @mpw.delete_key('test2@example.com') + assert_equal(1, @mpw.keys.length) + + @mpw.write_data + end end From 4bd538fa7c4d6768094fb959924d8a33718fa237 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Sat, 11 Feb 2017 13:43:29 +0100 Subject: [PATCH 379/531] generate a gpg key for the test --- test/init.rb | 19 +++++++++++++++++++ test/test_mpw.rb | 5 +---- test/tests.rb | 1 + 3 files changed, 21 insertions(+), 4 deletions(-) create mode 100644 test/init.rb diff --git a/test/init.rb b/test/init.rb new file mode 100644 index 0000000..be7a73a --- /dev/null +++ b/test/init.rb @@ -0,0 +1,19 @@ +#!/usr/bin/ruby + +require 'gpgme' + +param = '' +param << '<GnupgKeyParms format="internal">' + "\n" +param << "Key-Type: RSA\n" +param << "Key-Length: 2048\n" +param << "Subkey-Type: ELG-E\n" +param << "Subkey-Length: 2048\n" +param << "Name-Real: test\n" +param << "Name-Comment: test\n" +param << "Name-Email: test2@example.com\n" +param << "Expire-Date: 0\n" +param << "Passphrase: password\n" +param << "</GnupgKeyParms>\n" + +ctx = GPGME::Ctx.new +ctx.genkey(param, nil, nil) diff --git a/test/test_mpw.rb b/test/test_mpw.rb index b1c80c9..d2de795 100644 --- a/test/test_mpw.rb +++ b/test/test_mpw.rb @@ -120,9 +120,6 @@ class TestMPW < Test::Unit::TestCase end def test_06_add_gpg_key - @config = MPW::Config.new - @config.setup_gpg_key('password', 'test2@example.com', 2048) - @mpw.read_data @mpw.add_key('test2@example.com') @@ -131,7 +128,7 @@ class TestMPW < Test::Unit::TestCase @mpw.write_data end - def test07_delete_gpg_key + def test_07_delete_gpg_key @mpw.read_data assert_equal(2, @mpw.keys.length) diff --git a/test/tests.rb b/test/tests.rb index e4efc5d..904f64e 100644 --- a/test/tests.rb +++ b/test/tests.rb @@ -1,5 +1,6 @@ #!/usr/bin/ruby +require_relative 'init.rb' require_relative 'test_config.rb' require_relative 'test_item.rb' require_relative 'test_mpw.rb' From e6238341cd6436cb4f12ed50996b3614f402ebef Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Sat, 11 Feb 2017 13:47:22 +0100 Subject: [PATCH 380/531] fix test --- test/test_mpw.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/test_mpw.rb b/test/test_mpw.rb index d2de795..c4748f6 100644 --- a/test/test_mpw.rb +++ b/test/test_mpw.rb @@ -123,17 +123,17 @@ class TestMPW < Test::Unit::TestCase @mpw.read_data @mpw.add_key('test2@example.com') - assert_equal(2, @mpw.keys.length) + assert_equal(2, @mpw.list_keys.length) @mpw.write_data end def test_07_delete_gpg_key @mpw.read_data - assert_equal(2, @mpw.keys.length) + assert_equal(2, @mpw.list_keys.length) @mpw.delete_key('test2@example.com') - assert_equal(1, @mpw.keys.length) + assert_equal(1, @mpw.list_keys.length) @mpw.write_data end From adf34a006c625d1b772414823819afe498416f56 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Sat, 11 Feb 2017 15:09:48 +0100 Subject: [PATCH 381/531] config: generate gpg key with rsa --- lib/mpw/config.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/mpw/config.rb b/lib/mpw/config.rb index e8911fa..867ff35 100644 --- a/lib/mpw/config.rb +++ b/lib/mpw/config.rb @@ -97,7 +97,7 @@ class Config param = '' param << '<GnupgKeyParms format="internal">' + "\n" - param << "Key-Type: DSA\n" + param << "Key-Type: RSA\n" param << "Key-Length: #{length}\n" param << "Subkey-Type: ELG-E\n" param << "Subkey-Length: #{length}\n" From 501ae5ab2e243d73720383e89e3afa74bcafb5e1 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Sat, 11 Feb 2017 15:11:08 +0100 Subject: [PATCH 382/531] remove unused test files --- test/test.sh | 1 - test/test2.rb | 11 ----------- 2 files changed, 12 deletions(-) delete mode 100644 test/test.sh delete mode 100644 test/test2.rb diff --git a/test/test.sh b/test/test.sh deleted file mode 100644 index ab37885..0000000 --- a/test/test.sh +++ /dev/null @@ -1 +0,0 @@ -echo "test\ntest\n" | ruby ./bin/mpw config --init test@test.com diff --git a/test/test2.rb b/test/test2.rb deleted file mode 100644 index 17af2da..0000000 --- a/test/test2.rb +++ /dev/null @@ -1,11 +0,0 @@ -require 'open3' - -Open3.popen3("./bin/mpw config --init test@test.com") do |stdin, stdout, stderr, thread| - stdin.puts 'test' - stdin.puts 'test' -end - -Open3.popen3("./bin/mpw list") do |stdin, stdout, stderr, thread| - stdin.puts 'test' - puts stdout -end From f251b2ebe098158fa6cad4180039fd2eda4be858 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Sat, 11 Feb 2017 19:08:26 +0100 Subject: [PATCH 383/531] test with ruby 2.4 --- .travis.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 141eab1..1a18023 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,8 @@ language: ruby rvm: - - 2.3.1 - - 2.2.5 + - 2.4.0 + - 2.3.3 + - 2.2.6 - 2.1.10 install: - bundle install From ec3abbe88a006757ab7ef3b9f7fd780b398a0b9f Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Tue, 14 Feb 2017 21:30:26 +0100 Subject: [PATCH 384/531] fix bug share key --- bin/mpw-wallet | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/bin/mpw-wallet b/bin/mpw-wallet index 8bdfb1c..5222d81 100644 --- a/bin/mpw-wallet +++ b/bin/mpw-wallet @@ -94,14 +94,17 @@ cli.load_config if not options[:list].nil? cli.list_wallet -elsif not options[:gpg_key].nil? - if options[:delete] - cli.delete_key(options[:gpg_key]) - else - cli.add_key(options[:gpg_key]) - end else cli.get_wallet(options[:wallet]) cli.decrypt - cli.setup_wallet_config(values) + + if not options[:gpg_key].nil? + if options[:delete] + cli.delete_key(options[:gpg_key]) + else + cli.add_key(options[:gpg_key]) + end + else + cli.setup_wallet_config(values) + end end From 362253c63b6f847d54a2627427e0888eaaee9f8e Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Thu, 16 Feb 2017 20:47:39 +0100 Subject: [PATCH 385/531] cli: add list gpg keys in wallet --- bin/mpw-wallet | 10 ++++++++-- i18n/en.yml | 2 ++ i18n/fr.yml | 2 ++ lib/mpw/cli.rb | 24 ++++++++++++++++++++++++ 4 files changed, 36 insertions(+), 2 deletions(-) diff --git a/bin/mpw-wallet b/bin/mpw-wallet index 5222d81..221bb38 100644 --- a/bin/mpw-wallet +++ b/bin/mpw-wallet @@ -54,10 +54,14 @@ OptionParser.new do |opts| values[:host] = host end - opts.on('-l', '--list', I18n.t('option.list')) do |list| + opts.on('-l', '--list', I18n.t('option.list')) do options[:list] = true end + opts.on('-L', '--list-keys', I18n.t('option.list_keys')) do + options[:list_keys] = true + end + opts.on('-n', '--no-sync', I18n.t('option.no_sync')) do options[:sync] = false end @@ -98,7 +102,9 @@ else cli.get_wallet(options[:wallet]) cli.decrypt - if not options[:gpg_key].nil? + if not options[:list_keys].nil? + cli.list_keys + elsif not options[:gpg_key].nil? if options[:delete] cli.delete_key(options[:gpg_key]) else diff --git a/i18n/en.yml b/i18n/en.yml index 16a8c69..abf32bd 100644 --- a/i18n/en.yml +++ b/i18n/en.yml @@ -71,6 +71,7 @@ en: lang: "Set the software language" length: "Size of the password" list: "List the wallets" + list_keys: "List the GPG keys in wallet" no_sync: "Disable synchronization with the server" numeric: "Use number to generate a password" password: "Change the password for the synchronization" @@ -173,6 +174,7 @@ en: display: comment: "Comment" error: "ERROR" + keys: "GPG keys" gpg_password: "GPG passphrase: " group: "Group" login: "Login" diff --git a/i18n/fr.yml b/i18n/fr.yml index 0e4e9f6..9b6a1ea 100644 --- a/i18n/fr.yml +++ b/i18n/fr.yml @@ -71,6 +71,7 @@ fr: lang: "Spécifie la langue du logiciel (ex: fr)" length: "Taille du mot de passe" list: "Liste les portefeuilles" + list_keys: "Liste les clés GPG dans le portefeuille" no_sync: "Désactive la synchronisation avec le serveur" numeric: "Utilise des chiffre dans la génération d'un mot de passe" password: "Changer le mot de passe de connexion" @@ -173,6 +174,7 @@ fr: display: comment: "Commentaire" error: "ERREUR" + keys: "Clés GPG" gpg_password: "Mot de passe GPG: " group: "Groupe" login: "Identifiant" diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index 09e3ebd..15915af 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -112,6 +112,30 @@ class Cli exit 2 end + # List gpg keys in wallet + def list_keys + i = 1 + length = 0 + + @mpw.list_keys.each do |key| + length = key.length if length < key.length + end + length += 7 + + puts "\n#{I18n.t('display.keys')}".red + length.times { print '=' } + print "\n" + + @mpw.list_keys.each do |key| + print " #{i}".cyan + (3 - i.to_s.length).times { print ' ' } + puts "| #{key}" + i += 1 + end + + print "\n" + end + # Load config def load_config @config.load_config From e17219c77210ec2dbd0ba6e9edb9f4a2b1238e31 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Thu, 16 Feb 2017 23:25:54 +0100 Subject: [PATCH 386/531] minor fix in list_keys interface --- lib/mpw/cli.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index 15915af..99f79e3 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -123,11 +123,12 @@ class Cli length += 7 puts "\n#{I18n.t('display.keys')}".red + print ' ' length.times { print '=' } print "\n" @mpw.list_keys.each do |key| - print " #{i}".cyan + print " #{i}".cyan (3 - i.to_s.length).times { print ' ' } puts "| #{key}" i += 1 From dbffea6b6e626e7a0778c890f15afab2f38e42ce Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Thu, 16 Feb 2017 23:32:24 +0100 Subject: [PATCH 387/531] upgrade version 4.0.0-beta1 --- README.rst | 2 +- VERSION | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.rst b/README.rst index 17725d2..f449383 100644 --- a/README.rst +++ b/README.rst @@ -46,7 +46,7 @@ Output:: 2 | linuxfr.org | example | https | | | Da Linux French Site -.. |Version| image:: https://img.shields.io/badge/latest_version-4.0.0--beta-yellow.svg +.. |Version| image:: https://img.shields.io/badge/latest_version-4.0.0--beta1-yellow.svg :target: https://github.com/nishiki/manage-password/releases .. |License| image:: https://img.shields.io/badge/license-GPL--2.0-blue.svg :target: https://github.com/nishiki/manage-password/blob/master/LICENSE diff --git a/VERSION b/VERSION index c0de572..817c97b 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -4.0.0-beta +4.0.0-beta1 From 795343b66980d4738b7e651730ecf4fd3dfc1ee0 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Thu, 16 Feb 2017 23:39:50 +0100 Subject: [PATCH 388/531] upgrade changelog for version 4.0.0-beta1 --- CHANGELOG | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index 261d083..e154a0c 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,10 +1,16 @@ = CHANGELOG = -== v4.0.0 (beta) == +== v4.0.0-beta1 == + +* add manage share key with new interface + +== v4.0.0-beta == * new interface with a table * new command line interface * use text editor for add or update an item +* fix generate gpg key with RSA * several bugs fix +* add unit tests == v3.2.1 == From a3dd83e63c5d23708d78c975bfb6f125319611e5 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Fri, 17 Feb 2017 00:04:25 +0100 Subject: [PATCH 389/531] fix update otp key --- templates/update_form.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/update_form.erb b/templates/update_form.erb index f4a380b..b942cf5 100644 --- a/templates/update_form.erb +++ b/templates/update_form.erb @@ -12,6 +12,6 @@ protocol: <%= item.protocol %> # <%= I18n.t('form.update_item.port') %> port: <%= item.port %> # <%= I18n.t('form.update_item.otp_key') %> -opt_key: +otp_key: # <%= I18n.t('form.update_item.comment') %> comment: <%= item.comment %> From afdbb05bc51c4ad2c277e6cfd08e8e7c2ef4d0be Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Mon, 20 Feb 2017 22:26:57 +0100 Subject: [PATCH 390/531] fix nothing item message in copy mode --- lib/mpw/cli.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index 99f79e3..331b250 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -247,7 +247,6 @@ class Cli if result.length == 0 puts I18n.t('display.nothing') - else table(result) end @@ -494,7 +493,7 @@ class Cli items = @mpw.list(options) if items.length == 0 - puts "#{I18n.t('display.warning')}: #{I18n.t('warning.select')}".yellow + puts I18n.t('display.nothing') else table(items) From 35a4cd47e4436f9fff27ebbf3d0bf2e92e91c018 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Tue, 21 Feb 2017 20:32:26 +0100 Subject: [PATCH 391/531] change readme syntax --- README.md | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ README.rst | 54 ------------------------------------------------------ 2 files changed, 49 insertions(+), 54 deletions(-) create mode 100644 README.md delete mode 100644 README.rst diff --git a/README.md b/README.md new file mode 100644 index 0000000..563c592 --- /dev/null +++ b/README.md @@ -0,0 +1,49 @@ +# MPW: Manage your passwords! +[](https://github.com/nishiki/manage-password/releases) +[](https://travis-ci.org/nishiki/manage-password) +[](https://github.com/nishiki/manage-password/blob/master/LICENSE) + + +mpw is a little software which stores your passwords in [GnuPG](http://www.gnupg.org/) encrypted files. + +## Features + + * generate OTP code + * synchronize your passwords with SSH or FTP. + * copy your login, password or otp in clipboard + +## Install + +On debian or ubuntu: +``` +apt install ruby ruby-dev xclip +gem install mpw +``` + + +# How to use + +A simple mpw usage: +``` +mpw config --init user@host.com +mpw add +mpw copy +mpw add +mpw list +``` + +Output: +``` +Bank + ============================================================================== + ID | Host | User | Protocol | Port | OTP | Comment + ============================================================================== + 1 | bank.com | 1234456 | https | | X | + +Linux + ============================================================================== + ID | Host | User | Protocol | Port | OTP | Comment + ============================================================================== + 2 | linuxfr.org | example | https | | | Da Linux French Site + +``` diff --git a/README.rst b/README.rst deleted file mode 100644 index f449383..0000000 --- a/README.rst +++ /dev/null @@ -1,54 +0,0 @@ -MPW: Manage your passwords! -******************************************************* -|Version| |Build Status| |License| - -mpw is a little software which stores your passwords in `GnuPG <http://www.gnupg.org/>`_ encrypted files. - -Features -======== - -* generate OTP code -* synchronize your passwords with SSH or FTP. -* copy your login, password or otp in clipboard - -Install -======= - -On debian or ubuntu:: - - apt install ruby ruby-dev xclip - gem install mpw - - -How to use -========== - -A simple mpw usage:: - - mpw config --init user@host.com - mpw add - mpw copy - mpw add - mpw list - -Output:: - - Bank - ============================================================================== - ID | Host | User | Protocol | Port | OTP | Comment - ============================================================================== - 1 | bank.com | 1234456 | https | | X | - - Linux - ============================================================================== - ID | Host | User | Protocol | Port | OTP | Comment - ============================================================================== - 2 | linuxfr.org | example | https | | | Da Linux French Site - - -.. |Version| image:: https://img.shields.io/badge/latest_version-4.0.0--beta1-yellow.svg - :target: https://github.com/nishiki/manage-password/releases -.. |License| image:: https://img.shields.io/badge/license-GPL--2.0-blue.svg - :target: https://github.com/nishiki/manage-password/blob/master/LICENSE -.. |Build Status| image:: https://travis-ci.org/nishiki/manage-password.svg?branch=master - :target: https://travis-ci.org/nishiki/manage-password From 4b6de3575a3643e1f8294eaf47b8c06c75971c73 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Tue, 21 Feb 2017 21:05:28 +0100 Subject: [PATCH 392/531] fix interface for wallets list --- i18n/en.yml | 1 + i18n/fr.yml | 1 + lib/mpw/cli.rb | 66 +++++++++++++++++++++++++++----------------------- 3 files changed, 38 insertions(+), 30 deletions(-) diff --git a/i18n/en.yml b/i18n/en.yml index abf32bd..536a5e4 100644 --- a/i18n/en.yml +++ b/i18n/en.yml @@ -186,6 +186,7 @@ en: port: "Port" protocol: "Protocol" server: "Server" + wallets: "Wallets" warning: "Warning" formats: diff --git a/i18n/fr.yml b/i18n/fr.yml index 9b6a1ea..09f060a 100644 --- a/i18n/fr.yml +++ b/i18n/fr.yml @@ -186,6 +186,7 @@ fr: port: "Port" protocol: "Protocol" server: "Serveur" + wallets: "Porte-feuilles" warning: "Warning" formats: diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index 331b250..cf0cc28 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -114,27 +114,7 @@ class Cli # List gpg keys in wallet def list_keys - i = 1 - length = 0 - - @mpw.list_keys.each do |key| - length = key.length if length < key.length - end - length += 7 - - puts "\n#{I18n.t('display.keys')}".red - print ' ' - length.times { print '=' } - print "\n" - - @mpw.list_keys.each do |key| - print " #{i}".cyan - (3 - i.to_s.length).times { print ' ' } - puts "| #{key}" - i += 1 - end - - print "\n" + table_list('keys', @mpw.list_keys) end # Load config @@ -160,8 +140,33 @@ class Cli exit 2 end + # Format list on a table + def table_list(title, list) + i = 1 + length = 0 + + list.each do |item| + length = item.length if length < item.length + end + length += 7 + + puts "\n#{I18n.t("display.#{title}")}".red + print ' ' + length.times { print '=' } + print "\n" + + list.each do |item| + print " #{i}".cyan + (3 - i.to_s.length).times { print ' ' } + puts "| #{item}" + i += 1 + end + + print "\n" + end + # Format items on a table - def table(items=[]) + def table_items(items=[]) group = '.' i = 1 length_total = 10 @@ -248,7 +253,7 @@ class Cli if result.length == 0 puts I18n.t('display.nothing') else - table(result) + table_items(result) end end @@ -334,11 +339,12 @@ class Cli # List all wallets def list_wallet - wallets = Dir.glob("#{@config.wallet_dir}/*.mpw") - - wallets.each do |wallet| - puts File.basename(wallet, '.mpw') + wallets = [] + Dir.glob("#{@config.wallet_dir}/*.mpw").each do |f| + wallets << File.basename(f, '.mpw') end + + table_list('wallets', wallets) end # Display the wallet @@ -442,7 +448,7 @@ class Cli if items.length == 0 puts "#{I18n.t('display.warning')}: #{I18n.t('warning.select')}".yellow else - table(items) if items.length > 1 + table_items(items) if items.length > 1 item = get_item(items) options = text_editor('update_form', item) @@ -467,7 +473,7 @@ class Cli if items.length == 0 puts "#{I18n.t('display.warning')}: #{I18n.t('warning.select')}".yellow else - table(items) + table_items(items) item = get_item(items) confirm = ask("#{I18n.t('form.delete_item.ask')} (y/N) ").to_s @@ -495,7 +501,7 @@ class Cli if items.length == 0 puts I18n.t('display.nothing') else - table(items) + table_items(items) item = get_item(items) clipboard(item, clipboard) From a117e8a6188251580ec5b8e36d8f8c320834b83c Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Tue, 21 Feb 2017 21:08:14 +0100 Subject: [PATCH 393/531] nothing to do if no values --- bin/mpw-wallet | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/mpw-wallet b/bin/mpw-wallet index 221bb38..fbf0389 100644 --- a/bin/mpw-wallet +++ b/bin/mpw-wallet @@ -110,7 +110,7 @@ else else cli.add_key(options[:gpg_key]) end - else + elsif not values.empty? cli.setup_wallet_config(values) end end From c63d91faccb2fb2e1a99c15340d464466df6234f Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Tue, 21 Feb 2017 22:38:55 +0100 Subject: [PATCH 394/531] fix bug when exit with help message --- bin/mpw | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/mpw b/bin/mpw index 464980c..a69b568 100755 --- a/bin/mpw +++ b/bin/mpw @@ -48,7 +48,7 @@ command = "#{bin_dir}/mpw-#{ARGV[0]}" if Dir.glob("#{bin_dir}/mpw-*").include?("#{command}") begin Kernel.load(command) - rescue Exception => e + rescue OptionParser::ParseError => e puts "#{I18n.t('display.error')}: #{e}".red end else From 50d88fc970b207b4f4aebc389d872e244091a0ab Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Wed, 22 Feb 2017 19:23:55 +0100 Subject: [PATCH 395/531] fix translation test --- lib/mpw/cli.rb | 2 +- test/test_translate.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index cf0cc28..94fa9c3 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -538,7 +538,7 @@ class Cli File.open(file, 'w') {|f| f << data.to_yaml} - puts "#{I18n.t('export.valid', file)}".green + puts "#{I18n.t('form.export.valid', file)}".green rescue Exception => e puts "#{I18n.t('display.error')} #17: #{e}".red end diff --git a/test/test_translate.rb b/test/test_translate.rb index fe9a575..55f09df 100644 --- a/test/test_translate.rb +++ b/test/test_translate.rb @@ -11,7 +11,7 @@ class TestTranslate < Test::Unit::TestCase lang = File.basename(yaml, '.yml') translate = YAML.load_file(yaml) - `grep -r -o "I18n.t('.*')" bin/ lib/ | cut -d"'" -f2`.each_line do |line| + `grep -r -o "I18n.t('.*)" bin/ lib/ | cut -d"'" -f2`.each_line do |line| begin t = translate[lang] line.strip.split('.').each do |v| From c841123ac0549f0ab6310da55623dd470a48944f Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Wed, 22 Feb 2017 21:51:06 +0100 Subject: [PATCH 396/531] feat: add option to set default wallet --- bin/mpw-config | 7 ++++++- i18n/en.yml | 3 +++ i18n/fr.yml | 3 +++ lib/mpw/cli.rb | 19 +++++++++++++------ lib/mpw/config.rb | 41 +++++++++++++++++++---------------------- 5 files changed, 44 insertions(+), 29 deletions(-) diff --git a/bin/mpw-config b/bin/mpw-config index fb6b372..74309ce 100644 --- a/bin/mpw-config +++ b/bin/mpw-config @@ -34,6 +34,10 @@ OptionParser.new do |opts| options[:config] = config end + opts.on('-d', '--default-wallet NAME', I18n.t('option.default_wallet')) do |default_wallet| + values[:default_wallet] = default_wallet + end + opts.on('-g', '--gpg-exe PATH', I18n.t('option.gpg_exe')) do |gpg_exe| values[:gpg_exe] = gpg_exe end @@ -64,12 +68,13 @@ end.parse! config = MPW::Config.new(options[:config]) cli = MPW::Cli.new(config, nil) -if not options[:init].nil? +if options.has_key?(:init) cli.setup(values) cli.load_config cli.get_wallet cli.setup_gpg_key(values[:gpg_key]) cli.setup_wallet_config else + cli.load_config cli.set_config(values) end diff --git a/i18n/en.yml b/i18n/en.yml index 536a5e4..6dafacf 100644 --- a/i18n/en.yml +++ b/i18n/en.yml @@ -54,6 +54,7 @@ en: alpha: "Use letter to generate a password" config: "Specify the configuration file to use" clipboard: "Disable the clipboard feature" + default_wallet: "Specify the default wallet to use" delete_gpg_key: "Delete the wallet's share with an other GPG key" export: "Export a wallet in an yaml file" file_export: "Specify the file where export data" @@ -128,6 +129,8 @@ en: file_not_exist: "The import file doesn't exist!" valid: "The import is succesfull!" not_valid: "No data to import!" + set_config: + valid: "The config file has been edited!" setup_config: title: "Setup a new config file" lang: "Choose your language (en, fr, ...) [default=%{lang}]: " diff --git a/i18n/fr.yml b/i18n/fr.yml index 09f060a..a20e58f 100644 --- a/i18n/fr.yml +++ b/i18n/fr.yml @@ -54,6 +54,7 @@ fr: alpha: "Utilise des lettres dans la génération d'un mot de passe" config: "Spécifie le fichier de configuration à utiliser" clipboard: "Désactive la fonction presse papier" + default_wallet: "Spécifie le porte-feuille à utiliser par défaut" delete_gpg_key: "Supprime le partage le portefeuille avec une autre clé GPG" export: "Exporte un portefeuille dans un fichier yaml" file_export: "Spécifie le fichier où exporter les données" @@ -128,6 +129,8 @@ fr: file_not_exist: "Le fichier d'import n'existe pas" valid: "L'import est un succès!" not_valid: "Aucune donnée à importer!" + set_config: + valid: "Le fichier de configuration a bien été modifié!" setup_config: title: "Création d'un nouveau fichier de configuration" lang: "Choisissez votre langue (en, fr, ...) [défaut=%{lang}]: " diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index 94fa9c3..0a5dcde 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -40,12 +40,15 @@ class Cli # Change a parameter int the config after init # @args: options -> param to change def set_config(options) - gpg_key = options[:gpg_key] || @config.key - lang = options[:lang] || @config.lang - wallet_dir = options[:wallet_dir] || @config.wallet_dir - gpg_exe = options[:gpg_exe] || @config.gpg_exe + gpg_key = options[:gpg_key] || @config.key + lang = options[:lang] || @config.lang + wallet_dir = options[:wallet_dir] || @config.wallet_dir + default_wallet = options[:default_wallet] || @config.default_wallet + gpg_exe = options[:gpg_exe] || @config.gpg_exe - @config.setup(gpg_key, lang, wallet_dir, gpg_exe) + @config.setup(gpg_key, lang, wallet_dir, default_wallet, gpg_exe) + + puts "#{I18n.t('form.set_config.valid')}".green rescue Exception => e puts "#{I18n.t('display.error')} #15: #{e}".red exit 2 @@ -341,7 +344,9 @@ class Cli def list_wallet wallets = [] Dir.glob("#{@config.wallet_dir}/*.mpw").each do |f| - wallets << File.basename(f, '.mpw') + wallet = File.basename(f, '.mpw') + wallet += ' *'.green if wallet == @config.default_wallet + wallets << wallet end table_list('wallets', wallets) @@ -355,6 +360,8 @@ class Cli if wallets.length == 1 @wallet_file = wallets[0] + elsif not @config.default_wallet.to_s.empty? + @wallet_file = "#{@config.wallet_dir}/#{@config.default_wallet}.mpw" else @wallet_file = "#{@config.wallet_dir}/default.mpw" end diff --git a/lib/mpw/config.rb b/lib/mpw/config.rb index 867ff35..c1e883c 100644 --- a/lib/mpw/config.rb +++ b/lib/mpw/config.rb @@ -29,6 +29,7 @@ class Config attr_accessor :key attr_accessor :lang attr_accessor :config_dir + attr_accessor :default_wallet attr_accessor :wallet_dir attr_accessor :gpg_exe @@ -45,31 +46,28 @@ class Config @config_dir = "#{Dir.home}/.config/mpw" end - if @config_file.nil? or @config_file.empty? - @config_file = "#{@config_dir}/mpw.cfg" - end + @config_file = "#{@config_dir}/mpw.cfg" if @config_file.nil? or @config_file.empty? end # Create a new config file # @args: key -> the gpg key to encrypt # lang -> the software language - # wallet_dir -> the directory where are the wallets password - # gpg_exe -> the path of gpg executable + # wallet_dir -> the directory where are the wallets password + # default_wallet -> the default wallet + # gpg_exe -> the path of gpg executable # @rtrn: true if le config file is create - def setup(key, lang, wallet_dir, gpg_exe) + def setup(key, lang, wallet_dir, default_wallet, gpg_exe) if not key =~ /[a-zA-Z0-9.-_]+\@[a-zA-Z0-9]+\.[a-zA-Z]+/ raise I18n.t('error.config.key_bad_format') end - if wallet_dir.to_s.empty? - wallet_dir = "#{@config_dir}/wallets" - end - - config = { 'key' => key, - 'lang' => lang, - 'wallet_dir' => wallet_dir, - 'gpg_exe' => gpg_exe, - } + wallet_dir = "#{@config_dir}/wallets" if wallet_dir.to_s.empty? + config = { 'key' => key, + 'lang' => lang, + 'wallet_dir' => wallet_dir, + 'default_wallet' => default_wallet, + 'gpg_exe' => gpg_exe, + } FileUtils.mkdir_p(@config_dir, mode: 0700) FileUtils.mkdir_p(wallet_dir, mode: 0700) @@ -77,7 +75,6 @@ class Config File.open(@config_file, 'w') do |file| file << config.to_yaml end - rescue Exception => e raise "#{I18n.t('error.config.write')}\n#{e}" end @@ -116,16 +113,16 @@ class Config # Load the config file def load_config - config = YAML::load_file(@config_file) - @key = config['key'] - @lang = config['lang'] - @wallet_dir = config['wallet_dir'] - @gpg_exe = config['gpg_exe'] + config = YAML::load_file(@config_file) + @key = config['key'] + @lang = config['lang'] + @wallet_dir = config['wallet_dir'] + @default_wallet = config['default_wallet'] + @gpg_exe = config['gpg_exe'] raise if @key.empty? or @wallet_dir.empty? I18n.locale = @lang.to_sym - rescue Exception => e raise "#{I18n.t('error.config.load')}\n#{e}" end From 31574751ffd58ffb048043b6bcde051f593e51c5 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Wed, 22 Feb 2017 21:59:49 +0100 Subject: [PATCH 397/531] fix bug after add default wallet --- lib/mpw/cli.rb | 2 +- test/test_config.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index 0a5dcde..12bbe22 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -61,7 +61,7 @@ class Cli I18n.locale = lang.to_sym - @config.setup(options[:gpg_key], lang, options[:wallet_dir], options[:gpg_exe]) + @config.setup(options[:gpg_key], lang, options[:wallet_dir], options[:default_wallet], options[:gpg_exe]) load_config diff --git a/test/test_config.rb b/test/test_config.rb index 3de438c..5e4e721 100644 --- a/test/test_config.rb +++ b/test/test_config.rb @@ -27,7 +27,7 @@ class TestConfig < Test::Unit::TestCase } @config = MPW::Config.new - @config.setup(data[:key], data[:lang], data[:wallet_dir], data[:gpg_exe]) + @config.setup(data[:key], data[:lang], data[:wallet_dir], nil, data[:gpg_exe]) @config.load_config data.each do |k,v| From 000bc3aaa55c807b5e34cf7594491eca10c9e678 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <adrien.waksberg@doctolib.fr> Date: Sat, 25 Feb 2017 18:43:30 +0100 Subject: [PATCH 398/531] add config option for password parameters --- bin/mpw-config | 30 +++++++++++++++++++++++++++++- i18n/en.yml | 3 +++ i18n/fr.yml | 3 +++ lib/mpw/cli.rb | 10 ++-------- lib/mpw/config.rb | 34 ++++++++++++++++++++++++++-------- lib/mpw/mpw.rb | 6 +++--- 6 files changed, 66 insertions(+), 20 deletions(-) diff --git a/bin/mpw-config b/bin/mpw-config index 74309ce..1034f04 100644 --- a/bin/mpw-config +++ b/bin/mpw-config @@ -56,13 +56,41 @@ OptionParser.new do |opts| values[:gpg_key] = gpg_key end - opts.on('-l', '--lang LANG', I18n.t('option.lang')) do |lang| + opts.on('-L', '--lang LANG', I18n.t('option.lang')) do |lang| values[:lang] = lang end opts.on('-w', '--wallet-dir PATH', I18n.t('option.wallet_dir')) do |wallet_dir| values[:wallet_dir] = wallet_dir end + + opts.on('-l', '--length NUMBER', I18n.t('option.length')) do |length| + values[:pwd_length] = length.to_i + end + + opts.on('-n', '--numeric', I18n.t('option.numeric')) do + values[:pwd_numeric] = true + end + + opts.on('-N', '--disable-numeric', I18n.t('option.disable_numeric')) do + values[:pwd_numeric] = false + end + + opts.on('-s', '--special-chars', I18n.t('option.special_chars')) do + values[:pwd_special] = true + end + + opts.on('-S', '--disable_special-chars', I18n.t('option.special_chars')) do + values[:pwd_special] = false + end + + opts.on('-a', '--alpha', I18n.t('option.alpha')) do + values[:pwd_alpha] = true + end + + opts.on('-A', '--disable-alpha', I18n.t('option.disable_alpha')) do + values[:pwd_alpha] = false + end end.parse! config = MPW::Config.new(options[:config]) diff --git a/i18n/en.yml b/i18n/en.yml index 6dafacf..5ee9868 100644 --- a/i18n/en.yml +++ b/i18n/en.yml @@ -56,6 +56,9 @@ en: clipboard: "Disable the clipboard feature" default_wallet: "Specify the default wallet to use" delete_gpg_key: "Delete the wallet's share with an other GPG key" + disable_alpha: "Don't use letter to generate a password" + disable_numeric: "Don't use number to generate a password" + disable_special_chars: "Don't use special char to generate a password" export: "Export a wallet in an yaml file" file_export: "Specify the file where export data" file_import: "Specify the file to import" diff --git a/i18n/fr.yml b/i18n/fr.yml index a20e58f..d9bd279 100644 --- a/i18n/fr.yml +++ b/i18n/fr.yml @@ -56,6 +56,9 @@ fr: clipboard: "Désactive la fonction presse papier" default_wallet: "Spécifie le porte-feuille à utiliser par défaut" delete_gpg_key: "Supprime le partage le portefeuille avec une autre clé GPG" + disable_alpha: "Désactive l'utilisation des lettres dans la génération d'un mot de passe" + disable_numeric: "Désactive l'utilisation des chiffre dans la génération d'un mot de passe" + disable_special_chars: "Désactive l'utilisation des charactères speciaux dans la génération d'un mot de passe" export: "Exporte un portefeuille dans un fichier yaml" file_export: "Spécifie le fichier où exporter les données" file_import: "Spécifie le fichier à importer" diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index 12bbe22..97e7e56 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -40,13 +40,7 @@ class Cli # Change a parameter int the config after init # @args: options -> param to change def set_config(options) - gpg_key = options[:gpg_key] || @config.key - lang = options[:lang] || @config.lang - wallet_dir = options[:wallet_dir] || @config.wallet_dir - default_wallet = options[:default_wallet] || @config.default_wallet - gpg_exe = options[:gpg_exe] || @config.gpg_exe - - @config.setup(gpg_key, lang, wallet_dir, default_wallet, gpg_exe) + @config.setup(options) puts "#{I18n.t('form.set_config.valid')}".green rescue Exception => e @@ -433,7 +427,7 @@ class Cli item = Item.new(options) if password - options[:password] = MPW::password(length: 24) + options[:password] = MPW::password(@config.password) end @mpw.add(item) diff --git a/lib/mpw/config.rb b/lib/mpw/config.rb index c1e883c..94b9eb8 100644 --- a/lib/mpw/config.rb +++ b/lib/mpw/config.rb @@ -32,6 +32,7 @@ class Config attr_accessor :default_wallet attr_accessor :wallet_dir attr_accessor :gpg_exe + attr_accessor :password # Constructor # @args: config_file -> the specify config file @@ -50,23 +51,39 @@ class Config end # Create a new config file - # @args: key -> the gpg key to encrypt - # lang -> the software language - # wallet_dir -> the directory where are the wallets password - # default_wallet -> the default wallet - # gpg_exe -> the path of gpg executable + # @args: options -> hash with values # @rtrn: true if le config file is create - def setup(key, lang, wallet_dir, default_wallet, gpg_exe) - if not key =~ /[a-zA-Z0-9.-_]+\@[a-zA-Z0-9]+\.[a-zA-Z]+/ + def setup(options) + gpg_key = options[:gpg_key] || @key + lang = options[:lang] || @lang + wallet_dir = options[:wallet_dir] || @wallet_dir + default_wallet = options[:default_wallet] || @default_wallet + gpg_exe = options[:gpg_exe] || @gpg_exe + password = { numeric: true, + alpha: true, + special: false, + length: 16, + } + + ['numeric', 'special', 'alpha', 'length'].each do |k| + if options.has_key?("pwd_#{k}".to_sym) + password[k.to_sym] = options["pwd_#{k}".to_sym] + elsif not @password.nil? and @password.has_key?(k.to_sym) + password[k.to_sym] = @password[k.to_sym] + end + end + + if not gpg_key =~ /[a-zA-Z0-9.-_]+\@[a-zA-Z0-9]+\.[a-zA-Z]+/ raise I18n.t('error.config.key_bad_format') end wallet_dir = "#{@config_dir}/wallets" if wallet_dir.to_s.empty? - config = { 'key' => key, + config = { 'key' => gpg_key, 'lang' => lang, 'wallet_dir' => wallet_dir, 'default_wallet' => default_wallet, 'gpg_exe' => gpg_exe, + 'password' => password, } FileUtils.mkdir_p(@config_dir, mode: 0700) @@ -119,6 +136,7 @@ class Config @wallet_dir = config['wallet_dir'] @default_wallet = config['default_wallet'] @gpg_exe = config['gpg_exe'] + @password = config['password'] raise if @key.empty? or @wallet_dir.empty? diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index c5023e6..761127c 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -431,9 +431,9 @@ class MPW end chars = [] - chars += [*('!'..'?')] - [*('0'..'9')] if options.include?(:special) - chars += [*('A'..'Z'),*('a'..'z')] if options.include?(:alpha) - chars += [*('0'..'9')] if options.include?(:numeric) + chars += [*('!'..'?')] - [*('0'..'9')] if options[:special] + chars += [*('A'..'Z'),*('a'..'z')] if options[:alpha] + chars += [*('0'..'9')] if options[:numeric] chars = [*('A'..'Z'),*('a'..'z'),*('0'..'9')] if chars.empty? result = '' From cedfe9cef72d94da87e556f1aadf69d46815553a Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <adrien.waksberg@doctolib.fr> Date: Sun, 26 Feb 2017 09:35:46 +0100 Subject: [PATCH 399/531] fix bug encrypt with share key --- lib/mpw/mpw.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index c5023e6..3f9986f 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -206,12 +206,16 @@ class MPW end @keys[key] = data + @password.each_keys { |id| set_password(id, get_password(id)) } + @otp_keys.each_keys { |id| set_otp_key(id, get_otp_key(id)) } end # Delete a public key # args: key -> public key to delete def delete_key(key) @keys.delete(key) + @password.each_keys { |id| set_password(id, get_password(id)) } + @otp_keys.each_keys { |id| set_otp_key(id, get_otp_key(id)) } end # Set config From a737ee94d1b1a1666235ea82628883a6b22e0b93 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <adrien.waksberg@doctolib.fr> Date: Sun, 26 Feb 2017 09:45:19 +0100 Subject: [PATCH 400/531] add unit test --- test/test_config.rb | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/test/test_config.rb b/test/test_config.rb index 5e4e721..9d4b930 100644 --- a/test/test_config.rb +++ b/test/test_config.rb @@ -27,7 +27,7 @@ class TestConfig < Test::Unit::TestCase } @config = MPW::Config.new - @config.setup(data[:key], data[:lang], data[:wallet_dir], nil, data[:gpg_exe]) + @config.setup(data) @config.load_config data.each do |k,v| @@ -37,4 +37,28 @@ class TestConfig < Test::Unit::TestCase @config.setup_gpg_key('password', 'test@example.com', 2048) assert(@config.check_gpg_key?) end + + def test_01_password + data = { password: { alpha: false, + numeric: false, + special: true, + length: 32, + } + } + + @config.load_config + + assert_equal(@config.password[:length], 16) + assert(@config.password[:alpha]) + assert(@config.password[:numeric]) + assert(!@config.password[:special]) + + @config.setup(data) + @config.load_config + + assert_equal(@config.password[:length], 32) + assert(!@config.password[:alpha]) + assert(!@config.password[:numeric]) + assert(@config.password[:special]) + end end From 980adacc2c861cfe8faf298f9aab15783df9d892 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <adrien.waksberg@doctolib.fr> Date: Sun, 26 Feb 2017 21:17:35 +0100 Subject: [PATCH 401/531] fix missing change --- lib/mpw/cli.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index 97e7e56..7bce420 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -51,11 +51,11 @@ class Cli # Create a new config file # @args: options -> set param def setup(options) - lang = options[:lang] || Locale::Tag.parse(ENV['LANG']).to_simple.to_s[0..1] + options[:lang] = options[:lang] || Locale::Tag.parse(ENV['LANG']).to_simple.to_s[0..1] I18n.locale = lang.to_sym - @config.setup(options[:gpg_key], lang, options[:wallet_dir], options[:default_wallet], options[:gpg_exe]) + @config.setup(options) load_config From e486be5ba853b90355f91ff080a08172e9034cfb Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <adrien.waksberg@doctolib.fr> Date: Sun, 26 Feb 2017 21:22:25 +0100 Subject: [PATCH 402/531] fix bug --- lib/mpw/cli.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index 7bce420..409bf5a 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -53,7 +53,7 @@ class Cli def setup(options) options[:lang] = options[:lang] || Locale::Tag.parse(ENV['LANG']).to_simple.to_s[0..1] - I18n.locale = lang.to_sym + I18n.locale = options[:lang].to_sym @config.setup(options) From d6f7c78eb16345a5ff72d9d2b1aeb5ad90dceaf5 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <adrien.waksberg@doctolib.fr> Date: Sun, 26 Feb 2017 21:26:23 +0100 Subject: [PATCH 403/531] fix test --- test/test_config.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_config.rb b/test/test_config.rb index 9d4b930..3dd0d92 100644 --- a/test/test_config.rb +++ b/test/test_config.rb @@ -20,7 +20,7 @@ class TestConfig < Test::Unit::TestCase end def test_00_config - data = { key: 'test@example.com', + data = { gpg_key: 'test@example.com', lang: 'en', wallet_dir: '/tmp/test', gpg_exe: '', From 5d267a486580ada4ec0da6581deda75e42e8f075 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <adrien.waksberg@doctolib.fr> Date: Sun, 26 Feb 2017 21:34:54 +0100 Subject: [PATCH 404/531] config: rename key to gpg_key --- lib/mpw/cli.rb | 4 ++-- lib/mpw/config.rb | 14 +++++++------- templates/setup_form.erb | 9 --------- 3 files changed, 9 insertions(+), 18 deletions(-) delete mode 100644 templates/setup_form.erb diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index 409bf5a..3ad32be 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -98,7 +98,7 @@ class Cli #wallet_file = wallet.nil? ? "#{@config.wallet_dir}/default.mpw" : "#{@config.wallet_dir}/#{wallet}.mpw" - @mpw = MPW.new(@config.key, @wallet_file, @password, @config.gpg_exe) + @mpw = MPW.new(@config.gpg_key, @wallet_file, @password, @config.gpg_exe) @mpw.read_data @mpw.set_config(options) @mpw.write_data @@ -127,7 +127,7 @@ class Cli def decrypt if not defined?(@mpw) @password = ask(I18n.t('display.gpg_password')) {|q| q.echo = false} - @mpw = MPW.new(@config.key, @wallet_file, @password, @config.gpg_exe) + @mpw = MPW.new(@config.gpg_key, @wallet_file, @password, @config.gpg_exe) end @mpw.read_data diff --git a/lib/mpw/config.rb b/lib/mpw/config.rb index 94b9eb8..2cf5481 100644 --- a/lib/mpw/config.rb +++ b/lib/mpw/config.rb @@ -26,7 +26,7 @@ class Config attr_accessor :error_msg - attr_accessor :key + attr_accessor :gpg_key attr_accessor :lang attr_accessor :config_dir attr_accessor :default_wallet @@ -54,7 +54,7 @@ class Config # @args: options -> hash with values # @rtrn: true if le config file is create def setup(options) - gpg_key = options[:gpg_key] || @key + gpg_key = options[:gpg_key] || @gpg_key lang = options[:lang] || @lang wallet_dir = options[:wallet_dir] || @wallet_dir default_wallet = options[:default_wallet] || @default_wallet @@ -78,7 +78,7 @@ class Config end wallet_dir = "#{@config_dir}/wallets" if wallet_dir.to_s.empty? - config = { 'key' => gpg_key, + config = { 'gpg_key' => gpg_key, 'lang' => lang, 'wallet_dir' => wallet_dir, 'default_wallet' => default_wallet, @@ -117,7 +117,7 @@ class Config param << "Subkey-Length: #{length}\n" param << "Name-Real: #{name}\n" param << "Name-Comment: #{name}\n" - param << "Name-Email: #{@key}\n" + param << "Name-Email: #{@gpg_key}\n" param << "Expire-Date: #{expire}\n" param << "Passphrase: #{password}\n" param << "</GnupgKeyParms>\n" @@ -131,14 +131,14 @@ class Config # Load the config file def load_config config = YAML::load_file(@config_file) - @key = config['key'] + @gpg_key = config['gpg_key'] @lang = config['lang'] @wallet_dir = config['wallet_dir'] @default_wallet = config['default_wallet'] @gpg_exe = config['gpg_exe'] @password = config['password'] - raise if @key.empty? or @wallet_dir.empty? + raise if @gpg_key.empty? or @wallet_dir.empty? I18n.locale = @lang.to_sym rescue Exception => e @@ -149,7 +149,7 @@ class Config # @rtrn: true if the key exist, else false def check_gpg_key? ctx = GPGME::Ctx.new - ctx.each_key(@key, true) do + ctx.each_key(@gpg_key, true) do return true end diff --git a/templates/setup_form.erb b/templates/setup_form.erb deleted file mode 100644 index f7e6d7b..0000000 --- a/templates/setup_form.erb +++ /dev/null @@ -1,9 +0,0 @@ ---- -# <%= I18n.t('form.setup_config.lang') %> -language: <%= @config.lang %> -# <%= I18n.t('form.setup_config.gpg_key') %> -gpg_key: <%= @config.key %> -# <%= I18n.t('form.setup_config.wallet_dir') %> -wallet_dir: <%= @config.config_dir %> -# <%= I18n.t('form.setup_config.gpg_exe') %> -gpg_exe: <%= @config.gpg_exe %> From 21c3732ad371f70db839bd188b8379c7ab9cb905 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <adrien.waksberg@doctolib.fr> Date: Sun, 26 Feb 2017 21:39:33 +0100 Subject: [PATCH 405/531] fix test --- test/test_config.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/test/test_config.rb b/test/test_config.rb index 3dd0d92..4d94fcd 100644 --- a/test/test_config.rb +++ b/test/test_config.rb @@ -46,6 +46,7 @@ class TestConfig < Test::Unit::TestCase } } + @config = MPW::Config.new @config.load_config assert_equal(@config.password[:length], 16) From cced11f6c4247b7779ae5b3126f6fbc823ab82e7 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <adrien.waksberg@doctolib.fr> Date: Sun, 26 Feb 2017 21:45:42 +0100 Subject: [PATCH 406/531] fix test --- test/test_config.rb | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/test/test_config.rb b/test/test_config.rb index 4d94fcd..143b3ed 100644 --- a/test/test_config.rb +++ b/test/test_config.rb @@ -39,11 +39,10 @@ class TestConfig < Test::Unit::TestCase end def test_01_password - data = { password: { alpha: false, - numeric: false, - special: true, - length: 32, - } + data = { pwd_alpha: false, + pwd_numeric: false, + pwd_special: true, + pwd_length: 32, } @config = MPW::Config.new @@ -57,7 +56,7 @@ class TestConfig < Test::Unit::TestCase @config.setup(data) @config.load_config - assert_equal(@config.password[:length], 32) + assert_equal(@config.password[:length], data[:pwd_length]) assert(!@config.password[:alpha]) assert(!@config.password[:numeric]) assert(@config.password[:special]) From e03614fb724481ce34cb72bf7de152973079cc83 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <adrien.waksberg@doctolib.fr> Date: Sun, 26 Feb 2017 09:35:46 +0100 Subject: [PATCH 407/531] fix bug encrypt with share key --- lib/mpw/mpw.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index 761127c..f8ab415 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -206,12 +206,16 @@ class MPW end @keys[key] = data + @password.each_keys { |id| set_password(id, get_password(id)) } + @otp_keys.each_keys { |id| set_otp_key(id, get_otp_key(id)) } end # Delete a public key # args: key -> public key to delete def delete_key(key) @keys.delete(key) + @password.each_keys { |id| set_password(id, get_password(id)) } + @otp_keys.each_keys { |id| set_otp_key(id, get_otp_key(id)) } end # Set config From da81f34e07cbe8dad6c9a683f37bb34977f61d11 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <adrien.waksberg@doctolib.fr> Date: Sun, 26 Feb 2017 22:07:18 +0100 Subject: [PATCH 408/531] fix add_key --- lib/mpw/mpw.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index f8ab415..bf03347 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -206,7 +206,7 @@ class MPW end @keys[key] = data - @password.each_keys { |id| set_password(id, get_password(id)) } + @passwords.each_keys { |id| set_password(id, get_password(id)) } @otp_keys.each_keys { |id| set_otp_key(id, get_otp_key(id)) } end From 52577425a6e16c4a60eb1e6662fc0ddb2a79215e Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <adrien.waksberg@doctolib.fr> Date: Sun, 26 Feb 2017 22:11:14 +0100 Subject: [PATCH 409/531] fix each_key --- lib/mpw/mpw.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index bf03347..1e86c08 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -206,16 +206,16 @@ class MPW end @keys[key] = data - @passwords.each_keys { |id| set_password(id, get_password(id)) } - @otp_keys.each_keys { |id| set_otp_key(id, get_otp_key(id)) } + @passwords.each_key { |id| set_password(id, get_password(id)) } + @otp_keys.each_key { |id| set_otp_key(id, get_otp_key(id)) } end # Delete a public key # args: key -> public key to delete def delete_key(key) @keys.delete(key) - @password.each_keys { |id| set_password(id, get_password(id)) } - @otp_keys.each_keys { |id| set_otp_key(id, get_otp_key(id)) } + @passwords.each_key { |id| set_password(id, get_password(id)) } + @otp_keys.each_key { |id| set_otp_key(id, get_otp_key(id)) } end # Set config From e4fb7800163f8643a8e64ec1a76fd79371d027a3 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Sun, 26 Feb 2017 23:11:07 +0100 Subject: [PATCH 410/531] fix minor bug when config password is empty --- lib/mpw/config.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/mpw/config.rb b/lib/mpw/config.rb index 2cf5481..7fbd778 100644 --- a/lib/mpw/config.rb +++ b/lib/mpw/config.rb @@ -136,7 +136,7 @@ class Config @wallet_dir = config['wallet_dir'] @default_wallet = config['default_wallet'] @gpg_exe = config['gpg_exe'] - @password = config['password'] + @password = config['password'] || {} raise if @gpg_key.empty? or @wallet_dir.empty? From 6b8dce2eff12bc4527fb2b4c2ff3242b947ec145 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Sun, 26 Feb 2017 23:12:49 +0100 Subject: [PATCH 411/531] add random password for update --- bin/mpw-update | 6 +++++- lib/mpw/cli.rb | 19 +++++++++---------- templates/update_form.erb | 4 ++-- 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/bin/mpw-update b/bin/mpw-update index 301b876..221c632 100644 --- a/bin/mpw-update +++ b/bin/mpw-update @@ -52,6 +52,10 @@ OptionParser.new do |opts| values[:pattern] = pattern end + opts.on('-r', '--random', I18n.t('option.random_password')) do + options[:password] = true + end + opts.on('-w', '--wallet NAME', I18n.t('option.wallet')) do |wallet| options[:wallet] = wallet end @@ -63,4 +67,4 @@ cli = MPW::Cli.new(config, options[:sync]) cli.load_config cli.get_wallet(options[:wallet]) cli.decrypt -cli.update(values) +cli.update(options[:password], values) diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index 3ad32be..9e8040e 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -423,12 +423,9 @@ class Cli # Form to add a new item # @args: password -> generate a random password def add(password=false) - options = text_editor('add_form', nil, password) - item = Item.new(options) - - if password - options[:password] = MPW::password(@config.password) - end + options = text_editor('add_form', nil, password) + item = Item.new(options) + options[:password] = MPW::password(@config.password) if password @mpw.add(item) @mpw.set_password(item.id, options[:password]) if options.has_key?(:password) @@ -442,8 +439,9 @@ class Cli end # Update an item - # @args: options -> the option to search - def update(options={}) + # @args: password -> generate a random password + # options -> the option to search + def update(password=false, options={}) items = @mpw.list(options) if items.length == 0 @@ -451,8 +449,9 @@ class Cli else table_items(items) if items.length > 1 - item = get_item(items) - options = text_editor('update_form', item) + item = get_item(items) + options = text_editor('update_form', item, password) + options[:password] = MPW::password(@config.password) if password item.update(options) @mpw.set_password(item.id, options[:password]) if options.has_key?(:password) diff --git a/templates/update_form.erb b/templates/update_form.erb index b942cf5..e5363f8 100644 --- a/templates/update_form.erb +++ b/templates/update_form.erb @@ -2,9 +2,9 @@ # <%= I18n.t('form.update_item.host') %> host: <%= item.host %> # <%= I18n.t('form.update_item.login') %> -user: <%= item.user %> +user: <%= item.user %><% if not password %> # <%= I18n.t('form.update_item.password') %> -password: +password: <% end %> # <%= I18n.t('form.update_item.group') %> group: <%= item.group %> # <%= I18n.t('form.update_item.protocol') %> From ba745ccc0c148da7902fb5ed4c4ea74f783bd74b Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Thu, 2 Mar 2017 23:43:19 +0100 Subject: [PATCH 412/531] update README --- README.md | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 67 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 563c592..fa81df6 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,6 @@ [](https://travis-ci.org/nishiki/manage-password) [](https://github.com/nishiki/manage-password/blob/master/LICENSE) - mpw is a little software which stores your passwords in [GnuPG](http://www.gnupg.org/) encrypted files. ## Features @@ -11,6 +10,8 @@ mpw is a little software which stores your passwords in [GnuPG](http://www.gnupg * generate OTP code * synchronize your passwords with SSH or FTP. * copy your login, password or otp in clipboard + * manage many wallets + * share a wallet with others GPG keys ## Install @@ -20,17 +21,28 @@ apt install ruby ruby-dev xclip gem install mpw ``` +## How to use +### First steps -# How to use - -A simple mpw usage: +Initialize your first wallet: ``` mpw config --init user@host.com +``` + +Add your first item: +``` mpw add -mpw copy -mpw add +``` + +And list your items: +``` mpw list ``` +or search an item with +``` +mpw list --pattern Da +mpw list --group bank +``` Output: ``` @@ -47,3 +59,52 @@ Linux 2 | linuxfr.org | example | https | | | Da Linux French Site ``` + +Copy a password, login or OTP code: +``` +mpw copy -p linuxfr +``` + +Update an item: +``` +mpw update -p linuxfr +``` + +Delete an item: +``` +mpw delete -p linuxfr +``` + +### Manage wallets + +List all available wallets: +``` +mpw wallet --list +``` + +Create an other wallet: +``` +mpw config --wallet work --init user@host.com +``` + +List all GPG keys in wallet: +``` +mpw wallet --list-keys [--wallet NAME] +``` + +Share with an other GPG key: +``` +mpw wallet --add-gpg-key test42@localhost.com + or +mpw wallet --add-gpg-key /path/to/file +``` + +Remove a GPG key: +``` +mpw wallet --delete-gpg-key test42@localhost.com +``` + +Add synchronize: +``` +mpw wallet --protocol ssh --host example.com --user test --path /remote/path --password +``` From 55e46e1afadfaca42fad2e39456ed0067a221856 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Thu, 2 Mar 2017 23:47:24 +0100 Subject: [PATCH 413/531] convert changelog to markdown --- CHANGELOG | 49 ------------------------------------------------- CHANGELOG.md | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 49 deletions(-) delete mode 100644 CHANGELOG create mode 100644 CHANGELOG.md diff --git a/CHANGELOG b/CHANGELOG deleted file mode 100644 index e154a0c..0000000 --- a/CHANGELOG +++ /dev/null @@ -1,49 +0,0 @@ -= CHANGELOG = -== v4.0.0-beta1 == - -* add manage share key with new interface - -== v4.0.0-beta == - -* new interface with a table -* new command line interface -* use text editor for add or update an item -* fix generate gpg key with RSA -* several bugs fix -* add unit tests - -== v3.2.1 == - -* fix bug when add a new item - -== v3.2.0 == - -* add support OTP -* fix bug in synchronize -* improve interface - -== v3.1.0 == - -* add clipboard -* can change gpg version -* minor change in interface -* several bugs fix - -== v3.0.0 == - -* new storage format -* new share system -* remove MPW server - -== v2.0.0 == - -* change format csv to yaml -* easy install with gem -* add sync with ftp and ssh -* many improvement - -== v1.1.0 == - -* Add sync with MPW Server -* Add MPW Server -* Fix minors bugs diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..f00a846 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,49 @@ +# CHANGELOG +## v4.0.0-beta1 + + * add manage share key with new interface + +## v4.0.0-beta + + * new interface with a table + * new command line interface + * use text editor for add or update an item + * fix generate gpg key with RSA + * several bugs fix + * add unit tests + +## v3.2.1 + + * fix bug when add a new item + +## v3.2.0 + + * add support OTP + * fix bug in synchronize + * improve interface + +## v3.1.0 + + * add clipboard + * can change gpg version + * minor change in interface + * several bugs fix + +## v3.0.0 + + * new storage format + * new share system + * remove MPW server + +## v2.0.0 + + * change format csv to yaml + * easy install with gem + * add sync with ftp and ssh + * many improvement + +## v1.1.0 + + * Add sync with MPW Server + * Add MPW Server + * Fix minors bugs From 8fb83bd3910f321ce34cbee6d4ed6e6ac9d59664 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <adrien.waksberg@doctolib.fr> Date: Fri, 3 Mar 2017 21:57:21 +0100 Subject: [PATCH 414/531] fix message in export function --- lib/mpw/cli.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index 9e8040e..1eb2b94 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -538,7 +538,7 @@ class Cli File.open(file, 'w') {|f| f << data.to_yaml} - puts "#{I18n.t('form.export.valid', file)}".green + puts "#{I18n.t('form.export.valid', file: file)}".green rescue Exception => e puts "#{I18n.t('display.error')} #17: #{e}".red end From de4beba3dbb2f487c62f98f4a8380d4ad51d04fc Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <adrien.waksberg@doctolib.fr> Date: Fri, 3 Mar 2017 22:00:15 +0100 Subject: [PATCH 415/531] export items with id --- lib/mpw/cli.rb | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index 1eb2b94..90fe00d 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -517,23 +517,20 @@ class Cli file = 'export-mpw.yml' if file.to_s.empty? items = @mpw.list(options) data = {} - i = 1 items.each do |item| - data.merge!(i => { 'host' => item.host, - 'user' => item.user, - 'group' => item.group, - 'password' => @mpw.get_password(item.id), - 'protocol' => item.protocol, - 'port' => item.port, - 'otp_key' => @mpw.get_otp_key(item.id), - 'comment' => item.comment, - 'last_edit' => item.last_edit, - 'created' => item.created, - } + data.merge!(item.id => { 'host' => item.host, + 'user' => item.user, + 'group' => item.group, + 'password' => @mpw.get_password(item.id), + 'protocol' => item.protocol, + 'port' => item.port, + 'otp_key' => @mpw.get_otp_key(item.id), + 'comment' => item.comment, + 'last_edit' => item.last_edit, + 'created' => item.created, + } ) - - i += 1 end File.open(file, 'w') {|f| f << data.to_yaml} @@ -550,7 +547,6 @@ class Cli raise I18n.t('form.import.file_not_exist') if not File.exist?(file) YAML::load_file(file).each_value do |row| - item = Item.new(group: row['group'], host: row['host'], protocol: row['protocol'], From 44c1c2b4764c87b6ff3513e47aadf9f59ccdd166 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <adrien.waksberg@doctolib.fr> Date: Fri, 3 Mar 2017 22:42:30 +0100 Subject: [PATCH 416/531] update readme --- README.md | 39 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index fa81df6..6b32418 100644 --- a/README.md +++ b/README.md @@ -7,10 +7,11 @@ mpw is a little software which stores your passwords in [GnuPG](http://www.gnupg ## Features + * generate random password * generate OTP code - * synchronize your passwords with SSH or FTP. * copy your login, password or otp in clipboard * manage many wallets + * synchronize your passwords with SSH or FTP. * share a wallet with others GPG keys ## Install @@ -108,3 +109,39 @@ Add synchronize: ``` mpw wallet --protocol ssh --host example.com --user test --path /remote/path --password ``` + +### Export and import data + +You can export your data in yaml file with your passwords in clear text: +``` +mpw export --file export.yml +``` + +Import data from an yaml file: +``` +mpw import --file import.yml +``` + +Example yaml file for mpw: + +``` +--- +1: + host: bank.com + user: 123456 + group: Bank + password: secret + protocol: https + port: + otp_key: 1afg34 + comment: +2: + host: linuxfr.org + user: example + group: + password: 'complex %- password' + protocol: https + port: + otp_key: + comment: Da Linux French Site +``` From 58215d4e01ab133e8324c21be9b5d0220e88ddf1 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <adrien.waksberg@doctolib.fr> Date: Fri, 3 Mar 2017 22:57:03 +0100 Subject: [PATCH 417/531] ignore *.gem --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index b844b14..7ae6fcf 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ Gemfile.lock +*.gem From ffedd5b88bae5ecd214d2a1a111cd2f2d7d782e4 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Wed, 8 Mar 2017 21:23:15 +0100 Subject: [PATCH 418/531] fix error when delete an item with sync --- lib/mpw/mpw.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index 1e86c08..fe46108 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -319,6 +319,8 @@ class MPW if not remote.to_s.empty? @data.each do |item| + next if item.empty? + update = false remote.list.each do |r| From 5a1e0f6aa8a1f07e0c5fb54be8d6d1760cacc190 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Thu, 9 Mar 2017 21:06:05 +0100 Subject: [PATCH 419/531] release version 4.0.0 --- CHANGELOG.md | 7 +++++++ README.md | 2 +- VERSION | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f00a846..452ac98 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,11 @@ # CHANGELOG +## v4.0.0 + + * feature: set default wallet + * add option for generate a random password when you update an item + * fix encryption when you share an existing wallet + * several bugs fix + ## v4.0.0-beta1 * add manage share key with new interface diff --git a/README.md b/README.md index 6b32418..7ac7d47 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # MPW: Manage your passwords! -[](https://github.com/nishiki/manage-password/releases) +[](https://github.com/nishiki/manage-password/releases) [](https://travis-ci.org/nishiki/manage-password) [](https://github.com/nishiki/manage-password/blob/master/LICENSE) diff --git a/VERSION b/VERSION index 817c97b..fcdb2e1 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -4.0.0-beta1 +4.0.0 From 2e6d111b69f2153afdf34c39503a15229a91ec30 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Mon, 27 Mar 2017 21:27:50 +0200 Subject: [PATCH 420/531] begind version 4.1.0 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index fcdb2e1..4aa925d 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -4.0.0 +4.1.0-dev From 871b1dcbed1490d47b8bab40cd22e12aae6eb879 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Mon, 27 Mar 2017 21:47:43 +0200 Subject: [PATCH 421/531] remove all sync --- README.md | 6 --- bin/mpw-add | 9 +--- bin/mpw-copy | 7 +-- bin/mpw-delete | 11 ++--- bin/mpw-export | 11 ++--- bin/mpw-import | 9 +--- bin/mpw-list | 11 ++--- bin/mpw-update | 11 ++--- bin/mpw-wallet | 34 +------------- i18n/en.yml | 26 ----------- i18n/fr.yml | 26 ----------- lib/mpw/cli.rb | 32 +------------ lib/mpw/item.rb | 7 --- lib/mpw/mpw.rb | 106 -------------------------------------------- lib/mpw/sync/ftp.rb | 68 ---------------------------- lib/mpw/sync/ssh.rb | 67 ---------------------------- 16 files changed, 20 insertions(+), 421 deletions(-) delete mode 100644 lib/mpw/sync/ftp.rb delete mode 100644 lib/mpw/sync/ssh.rb diff --git a/README.md b/README.md index 7ac7d47..fd2534a 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,6 @@ mpw is a little software which stores your passwords in [GnuPG](http://www.gnupg * generate OTP code * copy your login, password or otp in clipboard * manage many wallets - * synchronize your passwords with SSH or FTP. * share a wallet with others GPG keys ## Install @@ -105,11 +104,6 @@ Remove a GPG key: mpw wallet --delete-gpg-key test42@localhost.com ``` -Add synchronize: -``` -mpw wallet --protocol ssh --host example.com --user test --path /remote/path --password -``` - ### Export and import data You can export your data in yaml file with your passwords in clear text: diff --git a/bin/mpw-add b/bin/mpw-add index 5322cc1..fc688a4 100644 --- a/bin/mpw-add +++ b/bin/mpw-add @@ -24,8 +24,7 @@ require 'mpw/cli' # Options # --------------------------------------------------------- # -options = {} -options[:sync] = true +options = {} OptionParser.new do |opts| opts.banner = "#{I18n.t('option.usage')}: mpw add [options]" @@ -39,10 +38,6 @@ OptionParser.new do |opts| exit 0 end - opts.on('-n', '--no-sync', I18n.t('option.no_sync')) do - options[:sync] = false - end - opts.on('-r', '--random', I18n.t('option.random_password')) do options[:password] = true end @@ -53,7 +48,7 @@ OptionParser.new do |opts| end.parse! config = MPW::Config.new(options[:config]) -cli = MPW::Cli.new(config, options[:sync]) +cli = MPW::Cli.new(config) cli.load_config cli.get_wallet(options[:wallet]) diff --git a/bin/mpw-copy b/bin/mpw-copy index 0a14ed7..1e5804b 100644 --- a/bin/mpw-copy +++ b/bin/mpw-copy @@ -25,7 +25,6 @@ require 'mpw/cli' # --------------------------------------------------------- # options = {} -options[:sync] = true options[:clipboard] = true values = {} @@ -49,10 +48,6 @@ OptionParser.new do |opts| exit 0 end - opts.on('-n', '--no-sync', I18n.t('option.no_sync')) do - options[:sync] = false - end - opts.on('-p', '--pattern PATTERN', I18n.t('option.pattern')) do |pattern| values[:pattern] = pattern end @@ -63,7 +58,7 @@ OptionParser.new do |opts| end.parse! config = MPW::Config.new(options[:config]) -cli = MPW::Cli.new(config, options[:sync]) +cli = MPW::Cli.new(config) cli.load_config cli.get_wallet(options[:wallet]) diff --git a/bin/mpw-delete b/bin/mpw-delete index 2d79e6a..53c8074 100644 --- a/bin/mpw-delete +++ b/bin/mpw-delete @@ -24,9 +24,8 @@ require 'mpw/cli' # Options # --------------------------------------------------------- # -options = {} -options[:sync] = true -values = {} +options = {} +values = {} OptionParser.new do |opts| opts.banner = "#{I18n.t('option.usage')}: mpw delete [options]" @@ -44,10 +43,6 @@ OptionParser.new do |opts| exit 0 end - opts.on('-n', '--no-sync', I18n.t('option.no_sync')) do - options[:sync] = false - end - opts.on('-p', '--pattern PATTERN', I18n.t('option.pattern')) do |pattern| values[:pattern] = pattern end @@ -58,7 +53,7 @@ OptionParser.new do |opts| end.parse! config = MPW::Config.new(options[:config]) -cli = MPW::Cli.new(config, options[:sync]) +cli = MPW::Cli.new(config) cli.load_config cli.get_wallet(options[:wallet]) diff --git a/bin/mpw-export b/bin/mpw-export index f891873..7913040 100644 --- a/bin/mpw-export +++ b/bin/mpw-export @@ -24,9 +24,8 @@ require 'mpw/cli' # Options # --------------------------------------------------------- # -options = {} -options[:sync] = true -values = {} +options = {} +values = {} OptionParser.new do |opts| opts.banner = "#{I18n.t('option.usage')}: mpw wallet [options]" @@ -48,10 +47,6 @@ OptionParser.new do |opts| exit 0 end - opts.on('-n', '--no-sync', I18n.t('option.no_sync')) do - options[:sync] = false - end - opts.on('-p', '--pattern PATTERN', I18n.t('option.pattern')) do |pattern| values[:pattern] = pattern end @@ -62,7 +57,7 @@ OptionParser.new do |opts| end.parse! config = MPW::Config.new(options[:config]) -cli = MPW::Cli.new(config, options[:sync]) +cli = MPW::Cli.new(config) cli.load_config cli.get_wallet(options[:wallet]) diff --git a/bin/mpw-import b/bin/mpw-import index c740252..a827783 100644 --- a/bin/mpw-import +++ b/bin/mpw-import @@ -24,8 +24,7 @@ require 'mpw/cli' # Options # --------------------------------------------------------- # -options = {} -options[:sync] = true +options = {} OptionParser.new do |opts| opts.banner = "#{I18n.t('option.usage')}: mpw import [options]" @@ -43,17 +42,13 @@ OptionParser.new do |opts| exit 0 end - opts.on('-n', '--no-sync', I18n.t('option.no_sync')) do - options[:sync] = false - end - opts.on('-w', '--wallet NAME', I18n.t('option.wallet')) do |wallet| options[:wallet] = wallet end end.parse! config = MPW::Config.new(options[:config]) -cli = MPW::Cli.new(config, options[:sync]) +cli = MPW::Cli.new(config) cli.load_config cli.get_wallet(options[:wallet]) diff --git a/bin/mpw-list b/bin/mpw-list index 9d18b0d..3ebc2b8 100644 --- a/bin/mpw-list +++ b/bin/mpw-list @@ -24,9 +24,8 @@ require 'mpw/cli' # Options # --------------------------------------------------------- # -options = {} -options[:sync] = true -values = {} +options = {} +values = {} OptionParser.new do |opts| opts.banner = "#{I18n.t('option.usage')}: mpw list [options]" @@ -48,17 +47,13 @@ OptionParser.new do |opts| values[:pattern] = pattern end - opts.on('-n', '--no-sync', I18n.t('option.no_sync')) do - options[:sync] = false - end - opts.on('-w', '--wallet NAME', I18n.t('option.wallet')) do |wallet| options[:wallet] = wallet end end.parse! config = MPW::Config.new(options[:config]) -cli = MPW::Cli.new(config, options[:sync]) +cli = MPW::Cli.new(config) cli.load_config cli.get_wallet(options[:wallet]) diff --git a/bin/mpw-update b/bin/mpw-update index 221c632..fd207c5 100644 --- a/bin/mpw-update +++ b/bin/mpw-update @@ -24,9 +24,8 @@ require 'mpw/cli' # Options # --------------------------------------------------------- # -options = {} -options[:sync] = true -values = {} +options = {} +values = {} OptionParser.new do |opts| opts.banner = "#{I18n.t('option.usage')}: mpw update [options]" @@ -44,10 +43,6 @@ OptionParser.new do |opts| exit 0 end - opts.on('-n', '--no-sync', I18n.t('option.no_sync')) do - options[:sync] = false - end - opts.on('-p', '--pattern PATTERN', I18n.t('option.pattern')) do |pattern| values[:pattern] = pattern end @@ -62,7 +57,7 @@ OptionParser.new do |opts| end.parse! config = MPW::Config.new(options[:config]) -cli = MPW::Cli.new(config, options[:sync]) +cli = MPW::Cli.new(config) cli.load_config cli.get_wallet(options[:wallet]) diff --git a/bin/mpw-wallet b/bin/mpw-wallet index fbf0389..56e96ba 100644 --- a/bin/mpw-wallet +++ b/bin/mpw-wallet @@ -25,9 +25,7 @@ require 'mpw/cli' # --------------------------------------------------------- # options = {} -options[:sync] = {} options[:delete] = false -values = {} OptionParser.new do |opts| opts.banner = "#{I18n.t('option.usage')}: mpw wallet [options]" @@ -50,10 +48,6 @@ OptionParser.new do |opts| exit 0 end - opts.on('--host NAME', I18n.t('option.host')) do |host| - values[:host] = host - end - opts.on('-l', '--list', I18n.t('option.list')) do options[:list] = true end @@ -62,37 +56,13 @@ OptionParser.new do |opts| options[:list_keys] = true end - opts.on('-n', '--no-sync', I18n.t('option.no_sync')) do - options[:sync] = false - end - - opts.on('--password', I18n.t('option.password')) do - values[:password] = true - end - - opts.on('--path PATH', I18n.t('option.path')) do |path| - values[:path] = path - end - - opts.on('--port NUMBER', I18n.t('option.port')) do |port| - values[:port] = port - end - - opts.on('--protocol NAME', I18n.t('option.protocol')) do |protocol| - values[:protocol] = protocol - end - - opts.on('--user NAME', I18n.t('option.user')) do |user| - values[:user] = user - end - opts.on('-w', '--wallet NAME', I18n.t('option.wallet')) do |wallet| options[:wallet] = wallet end end.parse! config = MPW::Config.new(options[:config]) -cli = MPW::Cli.new(config, options[:sync]) +cli = MPW::Cli.new(config) cli.load_config @@ -110,7 +80,5 @@ else else cli.add_key(options[:gpg_key]) end - elsif not values.empty? - cli.setup_wallet_config(values) end end diff --git a/i18n/en.yml b/i18n/en.yml index 5ee9868..162f6b3 100644 --- a/i18n/en.yml +++ b/i18n/en.yml @@ -23,15 +23,6 @@ en: import: "Can't import, unable to read %{file}!" update: host_empty: "You must define a host!" - sync: - general: "An error has appeared during the sync" - connection: "Connection fail!" - communication: "A communication problem with the server is appeared!" - download: "Can't download the file!" - not_authorized: "You haven't the access to remote file!" - upload: "Can't upload the file on the server!" - unknown: "An unknown error is occured!" - unknown_type: "The sync type is unknown" warning: select: 'Your choice is not a valid element!' @@ -68,7 +59,6 @@ en: gpg_key: "Specify a GPG key (ex: user@example.com)" group: "Search the items with specified group" help: "Show this help message" - host: "Specify the server for the synchronization" init: "Initialize mpw" import: "Import item since a yaml file" key: "Specify the key name" @@ -76,13 +66,8 @@ en: length: "Size of the password" list: "List the wallets" list_keys: "List the GPG keys in wallet" - no_sync: "Disable synchronization with the server" numeric: "Use number to generate a password" - password: "Change the password for the synchronization" - path: "Specify the remote path" pattern: "Given search pattern" - port: "Specify the connection port" - protocol: "Specify the protocol for the connection" random_password: "Generate a random password" setup: "Create a new configuration file" setup_wallet: "Create a new configuration file for a wallet" @@ -90,7 +75,6 @@ en: show: "Search and show the items" show_all: "List all items" usage: "Usage" - user: "Specify the user for the connection" wallet: "Specify a wallet to use" wallet_dir: "Set the wallets folder" @@ -141,16 +125,6 @@ en: gpg_exe: "Enter the executable GPG path (optional): " wallet_dir: "Enter the wallets's folder path [default=%{home}/wallets]: " valid: "The config file has been created!" - setup_wallet: - password: "Sync password: " - title: "Wallet setup" - sync_type: "Synchronization type (ssh, ftp): " - sync_host: "Synchronization server: " - sync_port: "Port of the synchronization server: " - sync_user: "Username for the synchronization: " - sync_pwd: "Password for the synchronization: " - sync_path: "File path for the synchronization : " - valid: "The wallet config file has been created!" setup_gpg_key: title: "Setup a GPG key" ask: "Do you want create your GPG key ? (Y/n)" diff --git a/i18n/fr.yml b/i18n/fr.yml index d9bd279..b2e3db4 100644 --- a/i18n/fr.yml +++ b/i18n/fr.yml @@ -23,15 +23,6 @@ fr: import: "Impossible d'importer le fichier %{file}, car il n'est pas lisible!" update: host_empty: "Vous devez définir un host!" - sync: - general: "Une erreur est survenue durant la synchronisation" - connection: "La connexion n'a pu être établie!" - communication: "Un problème de communication avec le serveur est apparu!" - download: "Impossible de télécharger le fichier!" - not_authorized: "Vous n'avez pas les autorisations d'accès au fichier distant!" - upload: "Impossible d'envoyer le fichier sur le serveur!" - unknown: "Une erreur inconnue est survenue!" - unknown_type: "Le type de synchronisation est inconnu" warning: select: "Votre choix n'est pas un élément valide!" @@ -68,7 +59,6 @@ fr: gpg_key: "Spécifie une clé GPG (ex: user@example.com)" group: "Recherche les éléments appartenant au groupe spécifié" help: "Affiche ce message d'aide" - host: "Spécifie le serveur pour la synchronisation" import: "Importe des éléments depuis un fichier yaml" init: "Initialise mpw" key: "Spécifie le nom d'une clé" @@ -76,13 +66,8 @@ fr: length: "Taille du mot de passe" list: "Liste les portefeuilles" list_keys: "Liste les clés GPG dans le portefeuille" - no_sync: "Désactive la synchronisation avec le serveur" numeric: "Utilise des chiffre dans la génération d'un mot de passe" - password: "Changer le mot de passe de connexion" - path: "Spécifie le chemin distant" pattern: "Motif de donnée à chercher" - port: "Spécifie le port de connexion" - protocol: "Spécifie le protocol utilisé pour la connexion" random_password: "Génére un mot de passe aléatoire" setup: "Création d'un nouveau fichier de configuration" setup_wallet: "Création d'un nouveau fichier de configuration pour un portefeuille" @@ -90,7 +75,6 @@ fr: show: "Recherche et affiche les éléments" show_all: "Liste tous les éléments" usage: "Utilisation" - user: "Spécifie l'identifiant de connection" wallet: "Spécifie le portefeuille à utiliser" wallet_dir: "Spécifie le répertoire des portefeuilles" @@ -141,16 +125,6 @@ fr: gpg_exe: "Entrez le chemin de l'exécutable GPG (optionnel): " wallet_dir: "Entrez le chemin du répertoire qui contiendra les porte-feuilles de mot de passe [défaut=%{home}/wallets]: " valid: "Le fichier de configuration a bien été créé!" - setup_wallet: - password: "Mot de passe de synchronisation: " - title: "Configuration du porte-feuille" - sync_type: "Type de synchronisation (ssh, ftp): " - sync_host: "Serveur: " - sync_port: "Port: " - sync_user: "Utilisateur: " - sync_pwd: "Mot de passe: " - sync_path: "Chemin du fichier: " - valid: "Le fichier de configuration du porte-feuille a bien été créé!" setup_gpg_key: title: "Configuration d'une nouvelle clé GPG" ask: "Voulez vous créer votre clé GPG ? (O/n)" diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index 90fe00d..0eb294e 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -31,10 +31,8 @@ class Cli # Constructor # @args: config -> the config - # sync -> boolean for sync or not - def initialize(config, sync=true) - @config = config - @sync = sync + def initialize(config) + @config = config end # Change a parameter int the config after init @@ -89,26 +87,6 @@ class Cli exit 2 end - # Setup wallet config for sync - # @args: options -> value to change - def setup_wallet_config(options={}) - if not options[:password].nil? - options[:password] = ask(I18n.t('form.setup_wallet.password')) {|q| q.echo = false} - end - - #wallet_file = wallet.nil? ? "#{@config.wallet_dir}/default.mpw" : "#{@config.wallet_dir}/#{wallet}.mpw" - - @mpw = MPW.new(@config.gpg_key, @wallet_file, @password, @config.gpg_exe) - @mpw.read_data - @mpw.set_config(options) - @mpw.write_data - - puts "#{I18n.t('form.setup_wallet.valid')}".green - rescue Exception => e - puts "#{I18n.t('display.error')} #10: #{e}".red - exit 2 - end - # List gpg keys in wallet def list_keys table_list('keys', @mpw.list_keys) @@ -131,7 +109,6 @@ class Cli end @mpw.read_data - @mpw.sync if @sync rescue Exception => e puts "#{I18n.t('display.error')} #11: #{e}".red exit 2 @@ -369,7 +346,6 @@ class Cli def add_key(key) @mpw.add_key(key) @mpw.write_data - @mpw.sync(true) if @sync puts "#{I18n.t('form.add_key.valid')}".green rescue Exception => e @@ -381,7 +357,6 @@ class Cli def delete_key(key) @mpw.delete_key(key) @mpw.write_data - @mpw.sync(true) if @sync puts "#{I18n.t('form.delete_key.valid')}".green rescue Exception => e @@ -431,7 +406,6 @@ class Cli @mpw.set_password(item.id, options[:password]) if options.has_key?(:password) @mpw.set_otp_key(item.id, options[:otp_key]) if options.has_key?(:otp_key) @mpw.write_data - @mpw.sync(true) if @sync puts "#{I18n.t('form.add_item.valid')}".green rescue Exception => e @@ -457,7 +431,6 @@ class Cli @mpw.set_password(item.id, options[:password]) if options.has_key?(:password) @mpw.set_otp_key(item.id, options[:otp_key]) if options.has_key?(:otp_key) @mpw.write_data - @mpw.sync(true) if @sync puts "#{I18n.t('form.update_item.valid')}".green end @@ -484,7 +457,6 @@ class Cli item.delete @mpw.write_data - @mpw.sync(true) if @sync puts "#{I18n.t('form.delete_item.valid')}".green end diff --git a/lib/mpw/item.rb b/lib/mpw/item.rb index d3783b9..a4f730b 100644 --- a/lib/mpw/item.rb +++ b/lib/mpw/item.rb @@ -30,7 +30,6 @@ class Item attr_accessor :otp attr_accessor :comment attr_accessor :last_edit - attr_accessor :last_sync attr_accessor :created # Constructor @@ -72,11 +71,6 @@ class Item @last_edit = Time.now.to_i if not options.has_key?(:no_update_last_edit) end - # Update last_sync - def set_last_sync - @last_sync = Time.now.to_i - end - # Delete all data def delete @id = nil @@ -89,7 +83,6 @@ class Item @comment = nil @created = nil @last_edit = nil - @last_sync = nil end def empty? diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index fe46108..8f4b42e 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -229,7 +229,6 @@ class MPW @config['user'] = options[:user] if options.has_key?(:user) @config['password'] = options[:password] if options.has_key?(:password) @config['path'] = options[:path] if options.has_key?(:path) - @config['last_sync'] = @config['last_sync'].nil? ? 0 : @config['last_sync'] end # Add a new item @@ -281,111 +280,6 @@ class MPW return nil end - # Get last sync - def get_last_sync - return @config['last_sync'].to_i - rescue - return 0 - end - - # Sync data with remote file - # @args: force -> force the sync - def sync(force=false) - return if @config.empty? or @config['protocol'].to_s.empty? - return if get_last_sync + 300 > Time.now.to_i and not force - - tmp_file = "#{@wallet_file}.sync" - - case @config['protocol'] - when 'sftp', 'scp', 'ssh' - require "mpw/sync/ssh" - sync = SyncSSH.new(@config) - when 'ftp' - require 'mpw/sync/ftp' - sync = SyncFTP.new(@config) - else - raise I18n.t('error.sync.unknown_type') - end - - sync.connect - sync.get(tmp_file) - - remote = MPW.new(@key, tmp_file, @gpg_pass, @gpg_exe) - remote.read_data - - File.unlink(tmp_file) if File.exist?(tmp_file) - - return if remote.get_last_sync == @config['last_update'] - - if not remote.to_s.empty? - @data.each do |item| - next if item.empty? - - update = false - - remote.list.each do |r| - next if item.id != r.id - - # Update item - if item.last_edit < r.last_edit - item.update(group: r.group, - host: r.host, - protocol: r.protocol, - user: r.user, - port: r.port, - comment: r.comment - ) - set_password(item.id, remote.get_password(item.id)) - end - - r.delete - update = true - - break - end - - # Remove an old item - if not update and item.last_sync.to_i < get_last_sync and item.last_edit < get_last_sync - item.delete - end - end - end - - # Add item - remote.list.each do |r| - next if r.last_edit <= get_last_sync - - item = Item.new(id: r.id, - group: r.group, - host: r.host, - protocol: r.protocol, - user: r.user, - port: r.port, - comment: r.comment, - created: r.created, - last_edit: r.last_edit - ) - - set_password(item.id, remote.get_password(item.id)) - add(item) - end - - remote = nil - - @data.each do |item| - item.set_last_sync - end - - @config['last_sync'] = Time.now.to_i - - write_data - sync.update(@wallet_file) - rescue Exception => e - File.unlink(tmp_file) if File.exist?(tmp_file) - - raise "#{I18n.t('error.sync.general')}\n#{e}" - end - # Set an opt key # args: id -> the item id # key -> the new key diff --git a/lib/mpw/sync/ftp.rb b/lib/mpw/sync/ftp.rb deleted file mode 100644 index d64e629..0000000 --- a/lib/mpw/sync/ftp.rb +++ /dev/null @@ -1,68 +0,0 @@ -#!/usr/bin/ruby -# MPW is a software to crypt and manage your passwords -# Copyright (C) 2016 Adrien Waksberg <mpw@yae.im> -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - -require 'i18n' -require 'net/ftp' - -module MPW -class FTP - - # Constructor - # @args: config -> the config - def initialize(config) - @host = config['host'] - @user = config['user'] - @password = config['password'] - @path = config['path'] - @port = config['port'].instance_of?(Integer) ? 22 : config['port'] - end - - - # Connect to server - def connect - Net::FTP.open(@host) do |ftp| - ftp.login(@user, @password) - break - end - rescue Exception => e - raise "#{I18n.t('error.sync.connection')}\n#{e}" - end - - # Get data on server - # @args: file_tmp -> the path where download the file - def get(file_tmp) - Net::FTP.open(@host) do |ftp| - ftp.login(@user, @password) - ftp.gettextfile(@path, file_tmp) - end - rescue Exception => e - raise "#{I18n.t('error.sync.download')}\n#{e}" - end - - # Update the remote data - # @args: file_gpg -> the data to send on server - def update(file_gpg) - Net::FTP.open(@host) do |ftp| - ftp.login(@user, @password) - ftp.puttextfile(file_gpg, @path) - end - rescue Exception => e - raise "#{I18n.t('error.sync.upload')}\n#{e}" - end -end -end diff --git a/lib/mpw/sync/ssh.rb b/lib/mpw/sync/ssh.rb deleted file mode 100644 index 4471949..0000000 --- a/lib/mpw/sync/ssh.rb +++ /dev/null @@ -1,67 +0,0 @@ -#!/usr/bin/ruby -# MPW is a software to crypt and manage your passwords -# Copyright (C) 2016 Adrien Waksberg <mpw@yae.im> -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - -require 'i18n' -require 'net/ssh' -require 'net/sftp' - -module MPW -class SyncSSH - - # Constructor - # @args: config -> the config - def initialize(config) - @host = config['host'] - @user = config['user'] - @password = config['password'] - @path = config['path'] - @port = config['port'].instance_of?(Integer) ? 22 : config['port'] - end - - # Connect to server - def connect - Net::SSH.start(@host, @user, password: @password, port: @port) do - break - end - rescue Exception => e - raise "#{I18n.t('error.sync.connection')}\n#{e}" - end - - # Get data on server - # @args: file_tmp -> the path where download the file - def get(file_tmp) - Net::SFTP.start(@host, @user, password: @password, port: @port) do |sftp| - sftp.lstat(@path) do |response| - sftp.download!(@path, file_tmp) if response.ok? - end - end - rescue Exception => e - raise "#{I18n.t('error.sync.download')}\n#{e}" - end - - # Update the remote data - # @args: file_gpg -> the data to send on server - def update(file_gpg) - Net::SFTP.start(@host, @user, password: @password, port: @port) do |sftp| - sftp.upload!(file_gpg, @path) - end - rescue Exception => e - raise "#{I18n.t('error.sync.upload')}\n#{e}" - end -end -end From 7c72b2d90f7322bae290b71e91fb010743269a70 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Mon, 27 Mar 2017 22:18:17 +0200 Subject: [PATCH 422/531] change tab by 2 spaces change tab by 2 spaces --- bin/mpw | 44 +- bin/mpw-add | 34 +- bin/mpw-config | 116 ++--- bin/mpw-copy | 46 +- bin/mpw-delete | 40 +- bin/mpw-export | 46 +- bin/mpw-genpwd | 40 +- bin/mpw-import | 34 +- bin/mpw-list | 40 +- bin/mpw-update | 46 +- bin/mpw-wallet | 78 +-- lib/mpw/cli.rb | 1028 ++++++++++++++++++++-------------------- lib/mpw/config.rb | 240 +++++----- lib/mpw/item.rb | 144 +++--- lib/mpw/mpw.rb | 592 +++++++++++------------ test/test_config.rb | 92 ++-- test/test_item.rb | 280 +++++------ test/test_mpw.rb | 212 ++++----- test/test_translate.rb | 46 +- test/tests.rb | 2 +- 20 files changed, 1600 insertions(+), 1600 deletions(-) diff --git a/bin/mpw b/bin/mpw index a69b568..3eb9fd9 100755 --- a/bin/mpw +++ b/bin/mpw @@ -1,17 +1,17 @@ #!/usr/bin/ruby # MPW is a software to crypt and manage your passwords # Copyright (C) 2016 Adrien Waksberg <mpw@yae.im> -# +# # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. -# +# # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -# +# # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. @@ -30,7 +30,7 @@ require 'colorize' lang = Locale::Tag.parse(ENV['LANG']).to_simple.to_s[0..1] if defined?(I18n.enforce_available_locales) - I18n.enforce_available_locales = true + I18n.enforce_available_locales = true end I18n::Backend::Simple.send(:include, I18n::Backend::Fallbacks) @@ -46,24 +46,24 @@ bin_dir = File.dirname(__FILE__) command = "#{bin_dir}/mpw-#{ARGV[0]}" if Dir.glob("#{bin_dir}/mpw-*").include?("#{command}") - begin - Kernel.load(command) - rescue OptionParser::ParseError => e - puts "#{I18n.t('display.error')}: #{e}".red - end + begin + Kernel.load(command) + rescue OptionParser::ParseError => e + puts "#{I18n.t('display.error')}: #{e}".red + end else - puts "#{I18n.t('option.usage')}: mpw COMMAND [options]\n\n" - puts 'Commands:' - puts " add #{I18n.t('command.add')}" - puts " config #{I18n.t('command.config')}" - puts " copy #{I18n.t('command.copy')}" - puts " delete #{I18n.t('command.delete')}" - puts " export #{I18n.t('command.export')}" - puts " genpwd #{I18n.t('command.genpwd')}" - puts " import #{I18n.t('command.import')}" - puts " list #{I18n.t('command.list')}" - puts " update #{I18n.t('command.update')}" - puts " wallet #{I18n.t('command.wallet')}" + puts "#{I18n.t('option.usage')}: mpw COMMAND [options]\n\n" + puts 'Commands:' + puts " add #{I18n.t('command.add')}" + puts " config #{I18n.t('command.config')}" + puts " copy #{I18n.t('command.copy')}" + puts " delete #{I18n.t('command.delete')}" + puts " export #{I18n.t('command.export')}" + puts " genpwd #{I18n.t('command.genpwd')}" + puts " import #{I18n.t('command.import')}" + puts " list #{I18n.t('command.list')}" + puts " update #{I18n.t('command.update')}" + puts " wallet #{I18n.t('command.wallet')}" - exit 3 + exit 3 end diff --git a/bin/mpw-add b/bin/mpw-add index fc688a4..6376326 100644 --- a/bin/mpw-add +++ b/bin/mpw-add @@ -1,17 +1,17 @@ #!/usr/bin/ruby # MPW is a software to crypt and manage your passwords # Copyright (C) 2016 Adrien Waksberg <mpw@yae.im> -# +# # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. -# +# # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -# +# # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. @@ -27,24 +27,24 @@ require 'mpw/cli' options = {} OptionParser.new do |opts| - opts.banner = "#{I18n.t('option.usage')}: mpw add [options]" + opts.banner = "#{I18n.t('option.usage')}: mpw add [options]" - opts.on('-c', '--config PATH', I18n.t('option.config')) do |config| - options[:config] = config - end + opts.on('-c', '--config PATH', I18n.t('option.config')) do |config| + options[:config] = config + end - opts.on('-h', '--help', I18n.t('option.help')) do - puts opts - exit 0 - end + opts.on('-h', '--help', I18n.t('option.help')) do + puts opts + exit 0 + end - opts.on('-r', '--random', I18n.t('option.random_password')) do - options[:password] = true - end + opts.on('-r', '--random', I18n.t('option.random_password')) do + options[:password] = true + end - opts.on('-w', '--wallet NAME', I18n.t('option.wallet')) do |wallet| - options[:wallet] = wallet - end + opts.on('-w', '--wallet NAME', I18n.t('option.wallet')) do |wallet| + options[:wallet] = wallet + end end.parse! config = MPW::Config.new(options[:config]) diff --git a/bin/mpw-config b/bin/mpw-config index 1034f04..14387d9 100644 --- a/bin/mpw-config +++ b/bin/mpw-config @@ -1,17 +1,17 @@ #!/usr/bin/ruby # MPW is a software to crypt and manage your passwords # Copyright (C) 2016 Adrien Waksberg <mpw@yae.im> -# +# # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. -# +# # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -# +# # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. @@ -28,81 +28,81 @@ options = {} values = {} OptionParser.new do |opts| - opts.banner = "#{I18n.t('option.usage')}: mpw config [options]" + opts.banner = "#{I18n.t('option.usage')}: mpw config [options]" - opts.on('-c', '--config PATH', I18n.t('option.config')) do |config| - options[:config] = config - end + opts.on('-c', '--config PATH', I18n.t('option.config')) do |config| + options[:config] = config + end - opts.on('-d', '--default-wallet NAME', I18n.t('option.default_wallet')) do |default_wallet| - values[:default_wallet] = default_wallet - end + opts.on('-d', '--default-wallet NAME', I18n.t('option.default_wallet')) do |default_wallet| + values[:default_wallet] = default_wallet + end - opts.on('-g', '--gpg-exe PATH', I18n.t('option.gpg_exe')) do |gpg_exe| - values[:gpg_exe] = gpg_exe - end + opts.on('-g', '--gpg-exe PATH', I18n.t('option.gpg_exe')) do |gpg_exe| + values[:gpg_exe] = gpg_exe + end - opts.on('-h', '--help', I18n.t('option.help')) do - puts opts - exit 0 - end + opts.on('-h', '--help', I18n.t('option.help')) do + puts opts + exit 0 + end - opts.on('-i', '--init GPG_KEY', I18n.t('option.init')) do |gpg_key| - options[:init] = true - values[:gpg_key] = gpg_key - end + opts.on('-i', '--init GPG_KEY', I18n.t('option.init')) do |gpg_key| + options[:init] = true + values[:gpg_key] = gpg_key + end - opts.on('-k', '--key GPG_KEY', I18n.t('option.gpg_key')) do |gpg_key| - values[:gpg_key] = gpg_key - end + opts.on('-k', '--key GPG_KEY', I18n.t('option.gpg_key')) do |gpg_key| + values[:gpg_key] = gpg_key + end - opts.on('-L', '--lang LANG', I18n.t('option.lang')) do |lang| - values[:lang] = lang - end + opts.on('-L', '--lang LANG', I18n.t('option.lang')) do |lang| + values[:lang] = lang + end - opts.on('-w', '--wallet-dir PATH', I18n.t('option.wallet_dir')) do |wallet_dir| - values[:wallet_dir] = wallet_dir - end + opts.on('-w', '--wallet-dir PATH', I18n.t('option.wallet_dir')) do |wallet_dir| + values[:wallet_dir] = wallet_dir + end - opts.on('-l', '--length NUMBER', I18n.t('option.length')) do |length| - values[:pwd_length] = length.to_i - end + opts.on('-l', '--length NUMBER', I18n.t('option.length')) do |length| + values[:pwd_length] = length.to_i + end - opts.on('-n', '--numeric', I18n.t('option.numeric')) do - values[:pwd_numeric] = true - end + opts.on('-n', '--numeric', I18n.t('option.numeric')) do + values[:pwd_numeric] = true + end - opts.on('-N', '--disable-numeric', I18n.t('option.disable_numeric')) do - values[:pwd_numeric] = false - end + opts.on('-N', '--disable-numeric', I18n.t('option.disable_numeric')) do + values[:pwd_numeric] = false + end - opts.on('-s', '--special-chars', I18n.t('option.special_chars')) do - values[:pwd_special] = true - end + opts.on('-s', '--special-chars', I18n.t('option.special_chars')) do + values[:pwd_special] = true + end - opts.on('-S', '--disable_special-chars', I18n.t('option.special_chars')) do - values[:pwd_special] = false - end + opts.on('-S', '--disable_special-chars', I18n.t('option.special_chars')) do + values[:pwd_special] = false + end - opts.on('-a', '--alpha', I18n.t('option.alpha')) do - values[:pwd_alpha] = true - end + opts.on('-a', '--alpha', I18n.t('option.alpha')) do + values[:pwd_alpha] = true + end - opts.on('-A', '--disable-alpha', I18n.t('option.disable_alpha')) do - values[:pwd_alpha] = false - end + opts.on('-A', '--disable-alpha', I18n.t('option.disable_alpha')) do + values[:pwd_alpha] = false + end end.parse! config = MPW::Config.new(options[:config]) cli = MPW::Cli.new(config, nil) if options.has_key?(:init) - cli.setup(values) - cli.load_config - cli.get_wallet - cli.setup_gpg_key(values[:gpg_key]) - cli.setup_wallet_config + cli.setup(values) + cli.load_config + cli.get_wallet + cli.setup_gpg_key(values[:gpg_key]) + cli.setup_wallet_config else - cli.load_config - cli.set_config(values) + cli.load_config + cli.set_config(values) end diff --git a/bin/mpw-copy b/bin/mpw-copy index 1e5804b..9436a10 100644 --- a/bin/mpw-copy +++ b/bin/mpw-copy @@ -1,17 +1,17 @@ #!/usr/bin/ruby # MPW is a software to crypt and manage your passwords # Copyright (C) 2016 Adrien Waksberg <mpw@yae.im> -# +# # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. -# +# # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -# +# # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. @@ -29,32 +29,32 @@ options[:clipboard] = true values = {} OptionParser.new do |opts| - opts.banner = "#{I18n.t('option.usage')}: mpw copy [options]" + opts.banner = "#{I18n.t('option.usage')}: mpw copy [options]" - opts.on('-c', '--config PATH', I18n.t('option.config')) do |config| - options[:config] = config - end + opts.on('-c', '--config PATH', I18n.t('option.config')) do |config| + options[:config] = config + end - opts.on('-d', '--disable-clipboard', I18n.t('option.clipboard')) do - options[:clipboard] = false - end + opts.on('-d', '--disable-clipboard', I18n.t('option.clipboard')) do + options[:clipboard] = false + end - opts.on('-g', '--group NAME', I18n.t('option.group')) do |group| - values[:group] = group - end + opts.on('-g', '--group NAME', I18n.t('option.group')) do |group| + values[:group] = group + end - opts.on('-h', '--help', I18n.t('option.help')) do - puts opts - exit 0 - end + opts.on('-h', '--help', I18n.t('option.help')) do + puts opts + exit 0 + end - opts.on('-p', '--pattern PATTERN', I18n.t('option.pattern')) do |pattern| - values[:pattern] = pattern - end + opts.on('-p', '--pattern PATTERN', I18n.t('option.pattern')) do |pattern| + values[:pattern] = pattern + end - opts.on('-w', '--wallet NAME', I18n.t('option.wallet')) do |wallet| - options[:wallet] = wallet - end + opts.on('-w', '--wallet NAME', I18n.t('option.wallet')) do |wallet| + options[:wallet] = wallet + end end.parse! config = MPW::Config.new(options[:config]) diff --git a/bin/mpw-delete b/bin/mpw-delete index 53c8074..f276785 100644 --- a/bin/mpw-delete +++ b/bin/mpw-delete @@ -1,17 +1,17 @@ #!/usr/bin/ruby # MPW is a software to crypt and manage your passwords # Copyright (C) 2016 Adrien Waksberg <mpw@yae.im> -# +# # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. -# +# # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -# +# # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. @@ -28,28 +28,28 @@ options = {} values = {} OptionParser.new do |opts| - opts.banner = "#{I18n.t('option.usage')}: mpw delete [options]" + opts.banner = "#{I18n.t('option.usage')}: mpw delete [options]" - opts.on('-c', '--config PATH', I18n.t('option.config')) do |config| - options[:config] = config - end + opts.on('-c', '--config PATH', I18n.t('option.config')) do |config| + options[:config] = config + end - opts.on('-g', '--group NAME', I18n.t('option.group')) do |group| - values[:group] = group - end + opts.on('-g', '--group NAME', I18n.t('option.group')) do |group| + values[:group] = group + end - opts.on('-h', '--help', I18n.t('option.help')) do - puts opts - exit 0 - end + opts.on('-h', '--help', I18n.t('option.help')) do + puts opts + exit 0 + end - opts.on('-p', '--pattern PATTERN', I18n.t('option.pattern')) do |pattern| - values[:pattern] = pattern - end + opts.on('-p', '--pattern PATTERN', I18n.t('option.pattern')) do |pattern| + values[:pattern] = pattern + end - opts.on('-w', '--wallet NAME', I18n.t('option.wallet')) do |wallet| - options[:wallet] = wallet - end + opts.on('-w', '--wallet NAME', I18n.t('option.wallet')) do |wallet| + options[:wallet] = wallet + end end.parse! config = MPW::Config.new(options[:config]) diff --git a/bin/mpw-export b/bin/mpw-export index 7913040..982d1ad 100644 --- a/bin/mpw-export +++ b/bin/mpw-export @@ -1,17 +1,17 @@ #!/usr/bin/ruby # MPW is a software to crypt and manage your passwords # Copyright (C) 2016 Adrien Waksberg <mpw@yae.im> -# +# # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. -# +# # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -# +# # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. @@ -28,32 +28,32 @@ options = {} values = {} OptionParser.new do |opts| - opts.banner = "#{I18n.t('option.usage')}: mpw wallet [options]" + opts.banner = "#{I18n.t('option.usage')}: mpw wallet [options]" - opts.on('-c', '--config PATH', I18n.t('option.config')) do |config| - options[:config] = config - end + opts.on('-c', '--config PATH', I18n.t('option.config')) do |config| + options[:config] = config + end - opts.on('-f', '--file PATH', I18n.t('option.file_export')) do |file| - options[:file] = file - end + opts.on('-f', '--file PATH', I18n.t('option.file_export')) do |file| + options[:file] = file + end - opts.on('-g', '--group GROUP', I18n.t('option.group')) do |group| - values[:group] = group - end + opts.on('-g', '--group GROUP', I18n.t('option.group')) do |group| + values[:group] = group + end - opts.on('-h', '--help', I18n.t('option.help')) do - puts opts - exit 0 - end + opts.on('-h', '--help', I18n.t('option.help')) do + puts opts + exit 0 + end - opts.on('-p', '--pattern PATTERN', I18n.t('option.pattern')) do |pattern| - values[:pattern] = pattern - end + opts.on('-p', '--pattern PATTERN', I18n.t('option.pattern')) do |pattern| + values[:pattern] = pattern + end - opts.on('-w', '--wallet NAME', I18n.t('option.wallet')) do |wallet| - options[:wallet] = wallet - end + opts.on('-w', '--wallet NAME', I18n.t('option.wallet')) do |wallet| + options[:wallet] = wallet + end end.parse! config = MPW::Config.new(options[:config]) diff --git a/bin/mpw-genpwd b/bin/mpw-genpwd index 8af4290..0370732 100644 --- a/bin/mpw-genpwd +++ b/bin/mpw-genpwd @@ -1,17 +1,17 @@ #!/usr/bin/ruby # MPW is a software to crypt and manage your passwords # Copyright (C) 2016 Adrien Waksberg <mpw@yae.im> -# +# # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. -# +# # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -# +# # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. @@ -22,28 +22,28 @@ require 'mpw/mpw' options = {} OptionParser.new do |opts| - opts.banner = "#{I18n.t('option.usage')}: mpw passwd [options]" + opts.banner = "#{I18n.t('option.usage')}: mpw passwd [options]" - opts.on('-h', '--help', I18n.t('option.help')) do - puts opts - exit 0 - end + opts.on('-h', '--help', I18n.t('option.help')) do + puts opts + exit 0 + end - opts.on('-l', '--length NUMBER', I18n.t('option.length')) do |length| - options[:length] = length.to_i - end + opts.on('-l', '--length NUMBER', I18n.t('option.length')) do |length| + options[:length] = length.to_i + end - opts.on('-n', '--numeric', I18n.t('option.numeric')) do - options[:numeric] = true - end + opts.on('-n', '--numeric', I18n.t('option.numeric')) do + options[:numeric] = true + end - opts.on('-s', '--special-chars', I18n.t('option.special_chars')) do - options[:special] = true - end + opts.on('-s', '--special-chars', I18n.t('option.special_chars')) do + options[:special] = true + end - opts.on('-a', '--alpha', I18n.t('option.alpha')) do - options[:alpha] = true - end + opts.on('-a', '--alpha', I18n.t('option.alpha')) do + options[:alpha] = true + end end.parse! puts MPW::MPW::password(options) diff --git a/bin/mpw-import b/bin/mpw-import index a827783..d9c868d 100644 --- a/bin/mpw-import +++ b/bin/mpw-import @@ -1,17 +1,17 @@ #!/usr/bin/ruby # MPW is a software to crypt and manage your passwords # Copyright (C) 2016 Adrien Waksberg <mpw@yae.im> -# +# # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. -# +# # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -# +# # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. @@ -27,24 +27,24 @@ require 'mpw/cli' options = {} OptionParser.new do |opts| - opts.banner = "#{I18n.t('option.usage')}: mpw import [options]" + opts.banner = "#{I18n.t('option.usage')}: mpw import [options]" - opts.on('-c', '--config PATH', I18n.t('option.config')) do |config| - options[:config] = config - end + opts.on('-c', '--config PATH', I18n.t('option.config')) do |config| + options[:config] = config + end - opts.on('-f', '--file PATH', I18n.t('option.file_import')) do |file| - options[:file] = file - end + opts.on('-f', '--file PATH', I18n.t('option.file_import')) do |file| + options[:file] = file + end - opts.on('-h', '--help', I18n.t('option.help')) do - puts opts - exit 0 - end + opts.on('-h', '--help', I18n.t('option.help')) do + puts opts + exit 0 + end - opts.on('-w', '--wallet NAME', I18n.t('option.wallet')) do |wallet| - options[:wallet] = wallet - end + opts.on('-w', '--wallet NAME', I18n.t('option.wallet')) do |wallet| + options[:wallet] = wallet + end end.parse! config = MPW::Config.new(options[:config]) diff --git a/bin/mpw-list b/bin/mpw-list index 3ebc2b8..3571abc 100644 --- a/bin/mpw-list +++ b/bin/mpw-list @@ -1,17 +1,17 @@ #!/usr/bin/ruby # MPW is a software to crypt and manage your passwords # Copyright (C) 2016 Adrien Waksberg <mpw@yae.im> -# +# # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. -# +# # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -# +# # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. @@ -28,28 +28,28 @@ options = {} values = {} OptionParser.new do |opts| - opts.banner = "#{I18n.t('option.usage')}: mpw list [options]" + opts.banner = "#{I18n.t('option.usage')}: mpw list [options]" - opts.on('-c', '--config PATH', I18n.t('option.config')) do |config| - options[:config] = config - end + opts.on('-c', '--config PATH', I18n.t('option.config')) do |config| + options[:config] = config + end - opts.on('-g', '--group NAME', I18n.t('option.group')) do |group| - values[:group] = group - end + opts.on('-g', '--group NAME', I18n.t('option.group')) do |group| + values[:group] = group + end - opts.on('-h', '--help', I18n.t('option.help')) do - puts opts - exit 0 - end + opts.on('-h', '--help', I18n.t('option.help')) do + puts opts + exit 0 + end - opts.on('-p', '--pattern PATTERN', I18n.t('option.pattern')) do |pattern| - values[:pattern] = pattern - end + opts.on('-p', '--pattern PATTERN', I18n.t('option.pattern')) do |pattern| + values[:pattern] = pattern + end - opts.on('-w', '--wallet NAME', I18n.t('option.wallet')) do |wallet| - options[:wallet] = wallet - end + opts.on('-w', '--wallet NAME', I18n.t('option.wallet')) do |wallet| + options[:wallet] = wallet + end end.parse! config = MPW::Config.new(options[:config]) diff --git a/bin/mpw-update b/bin/mpw-update index fd207c5..c258330 100644 --- a/bin/mpw-update +++ b/bin/mpw-update @@ -1,17 +1,17 @@ #!/usr/bin/ruby # MPW is a software to crypt and manage your passwords # Copyright (C) 2016 Adrien Waksberg <mpw@yae.im> -# +# # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. -# +# # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -# +# # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. @@ -28,32 +28,32 @@ options = {} values = {} OptionParser.new do |opts| - opts.banner = "#{I18n.t('option.usage')}: mpw update [options]" + opts.banner = "#{I18n.t('option.usage')}: mpw update [options]" - opts.on('-c', '--config PATH', I18n.t('option.config')) do |config| - options[:config] = config - end + opts.on('-c', '--config PATH', I18n.t('option.config')) do |config| + options[:config] = config + end - opts.on('-g', '--group NAME', I18n.t('option.group')) do |group| - values[:group] = group - end + opts.on('-g', '--group NAME', I18n.t('option.group')) do |group| + values[:group] = group + end - opts.on('-h', '--help', I18n.t('option.help')) do - puts opts - exit 0 - end + opts.on('-h', '--help', I18n.t('option.help')) do + puts opts + exit 0 + end - opts.on('-p', '--pattern PATTERN', I18n.t('option.pattern')) do |pattern| - values[:pattern] = pattern - end + opts.on('-p', '--pattern PATTERN', I18n.t('option.pattern')) do |pattern| + values[:pattern] = pattern + end - opts.on('-r', '--random', I18n.t('option.random_password')) do - options[:password] = true - end + opts.on('-r', '--random', I18n.t('option.random_password')) do + options[:password] = true + end - opts.on('-w', '--wallet NAME', I18n.t('option.wallet')) do |wallet| - options[:wallet] = wallet - end + opts.on('-w', '--wallet NAME', I18n.t('option.wallet')) do |wallet| + options[:wallet] = wallet + end end.parse! config = MPW::Config.new(options[:config]) diff --git a/bin/mpw-wallet b/bin/mpw-wallet index 56e96ba..e575c0d 100644 --- a/bin/mpw-wallet +++ b/bin/mpw-wallet @@ -1,17 +1,17 @@ #!/usr/bin/ruby # MPW is a software to crypt and manage your passwords # Copyright (C) 2016 Adrien Waksberg <mpw@yae.im> -# +# # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. -# +# # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -# +# # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. @@ -28,37 +28,37 @@ options = {} options[:delete] = false OptionParser.new do |opts| - opts.banner = "#{I18n.t('option.usage')}: mpw wallet [options]" + opts.banner = "#{I18n.t('option.usage')}: mpw wallet [options]" - opts.on('-a', '--add-gpg-key NAME', I18n.t('option.add_gpg_key')) do |gpg_key| - options[:gpg_key] = gpg_key - end + opts.on('-a', '--add-gpg-key NAME', I18n.t('option.add_gpg_key')) do |gpg_key| + options[:gpg_key] = gpg_key + end - opts.on('-c', '--config PATH', I18n.t('option.config')) do |config| - options[:config] = config - end + opts.on('-c', '--config PATH', I18n.t('option.config')) do |config| + options[:config] = config + end - opts.on('-d', '--delete-gpg-key NAME', I18n.t('option.delete_gpg_key')) do |gpg_key| - options[:gpg_key] = gpg_key - options[:delete] = true - end + opts.on('-d', '--delete-gpg-key NAME', I18n.t('option.delete_gpg_key')) do |gpg_key| + options[:gpg_key] = gpg_key + options[:delete] = true + end - opts.on('-h', '--help', I18n.t('option.help')) do - puts opts - exit 0 - end + opts.on('-h', '--help', I18n.t('option.help')) do + puts opts + exit 0 + end - opts.on('-l', '--list', I18n.t('option.list')) do - options[:list] = true - end + opts.on('-l', '--list', I18n.t('option.list')) do + options[:list] = true + end - opts.on('-L', '--list-keys', I18n.t('option.list_keys')) do - options[:list_keys] = true - end + opts.on('-L', '--list-keys', I18n.t('option.list_keys')) do + options[:list_keys] = true + end - opts.on('-w', '--wallet NAME', I18n.t('option.wallet')) do |wallet| - options[:wallet] = wallet - end + opts.on('-w', '--wallet NAME', I18n.t('option.wallet')) do |wallet| + options[:wallet] = wallet + end end.parse! config = MPW::Config.new(options[:config]) @@ -67,18 +67,18 @@ cli = MPW::Cli.new(config) cli.load_config if not options[:list].nil? - cli.list_wallet + cli.list_wallet else - cli.get_wallet(options[:wallet]) - cli.decrypt + cli.get_wallet(options[:wallet]) + cli.decrypt - if not options[:list_keys].nil? - cli.list_keys - elsif not options[:gpg_key].nil? - if options[:delete] - cli.delete_key(options[:gpg_key]) - else - cli.add_key(options[:gpg_key]) - end - end + if not options[:list_keys].nil? + cli.list_keys + elsif not options[:gpg_key].nil? + if options[:delete] + cli.delete_key(options[:gpg_key]) + else + cli.add_key(options[:gpg_key]) + end + end end diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index 0eb294e..83b9af3 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -1,17 +1,17 @@ #!/usr/bin/ruby # MPW is a software to crypt and manage your passwords # Copyright (C) 2016 Adrien Waksberg <mpw@yae.im> -# +# # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. -# +# # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -# +# # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. @@ -29,516 +29,516 @@ require 'mpw/mpw' module MPW class Cli - # Constructor - # @args: config -> the config - def initialize(config) - @config = config - end - - # Change a parameter int the config after init - # @args: options -> param to change - def set_config(options) - @config.setup(options) - - puts "#{I18n.t('form.set_config.valid')}".green - rescue Exception => e - puts "#{I18n.t('display.error')} #15: #{e}".red - exit 2 - end - - # Create a new config file - # @args: options -> set param - def setup(options) - options[:lang] = options[:lang] || Locale::Tag.parse(ENV['LANG']).to_simple.to_s[0..1] - - I18n.locale = options[:lang].to_sym - - @config.setup(options) - - load_config - - puts "#{I18n.t('form.setup_config.valid')}".green - rescue Exception => e - puts "#{I18n.t('display.error')} #8: #{e}".red - exit 2 - end - - # Setup a new GPG key - # @args: gpg_key -> the key name - def setup_gpg_key(gpg_key) - return if @config.check_gpg_key? - - password = ask(I18n.t('form.setup_gpg_key.password')) {|q| q.echo = false} - confirm = ask(I18n.t('form.setup_gpg_key.confirm_password')) {|q| q.echo = false} - - if password != confirm - raise I18n.t('form.setup_gpg_key.error_password') - end - - @password = password.to_s - - puts I18n.t('form.setup_gpg_key.wait') - - @config.setup_gpg_key(@password, gpg_key) - - puts "#{I18n.t('form.setup_gpg_key.valid')}".green - rescue Exception => e - puts "#{I18n.t('display.error')} #8: #{e}".red - exit 2 - end - - # List gpg keys in wallet - def list_keys - table_list('keys', @mpw.list_keys) - end - - # Load config - def load_config - @config.load_config - - rescue Exception => e - puts "#{I18n.t('display.error')} #10: #{e}".red - exit 2 - end - - # Request the GPG password and decrypt the file - def decrypt - if not defined?(@mpw) - @password = ask(I18n.t('display.gpg_password')) {|q| q.echo = false} - @mpw = MPW.new(@config.gpg_key, @wallet_file, @password, @config.gpg_exe) - end - - @mpw.read_data - rescue Exception => e - puts "#{I18n.t('display.error')} #11: #{e}".red - exit 2 - end - - # Format list on a table - def table_list(title, list) - i = 1 - length = 0 - - list.each do |item| - length = item.length if length < item.length - end - length += 7 - - puts "\n#{I18n.t("display.#{title}")}".red - print ' ' - length.times { print '=' } - print "\n" - - list.each do |item| - print " #{i}".cyan - (3 - i.to_s.length).times { print ' ' } - puts "| #{item}" - i += 1 - end - - print "\n" - end - - # Format items on a table - def table_items(items=[]) - group = '.' - i = 1 - length_total = 10 - data = { id: { length: 3, color: 'cyan' }, - host: { length: 9, color: 'yellow' }, - user: { length: 7, color: 'green' }, - protocol: { length: 9, color: 'white' }, - port: { length: 5, color: 'white' }, - otp: { length: 4, color: 'white' }, - comment: { length: 14, color: 'magenta' }, - } - - items.each do |item| - data.each do |k, v| - next if k == :id or k == :otp - - v[:length] = item.send(k.to_s).to_s.length + 3 if item.send(k.to_s).to_s.length >= v[:length] - end - end - data[:id][:length] = items.length.to_s.length + 2 if items.length.to_s.length > data[:id][:length] - - data.each_value { |v| length_total += v[:length] } - items.sort! { |a, b| a.group.to_s.downcase <=> b.group.to_s.downcase } - - items.each do |item| - if group != item.group - group = item.group - - if group.to_s.empty? - puts "\n#{I18n.t('display.no_group')}".red - else - puts "\n#{group}".red - end - - print ' ' - length_total.times { print '=' } - print "\n " - data.each do |k, v| - case k - when :id - print ' ID' - when :otp - print '| OTP' - else - print "| #{k.to_s.capitalize}" - end - - (v[:length] - k.to_s.length).times { print ' ' } - end - print "\n " - length_total.times { print '=' } - print "\n" - end - - print " #{i}".send(data[:id][:color]) - (data[:id][:length] - i.to_s.length).times { print ' ' } - data.each do |k, v| - next if k == :id - - if k == :otp - print '| ' - if item.otp; print ' X ' else 4.times { print ' ' } end - - next - end - - print '| ' - print "#{item.send(k.to_s)}".send(v[:color]) - (v[:length] - item.send(k.to_s).to_s.length).times { print ' ' } - end - print "\n" - - i += 1 - end - - print "\n" - end - - # Display the query's result - # @args: options -> the option to search - def list(options={}) - result = @mpw.list(options) - - if result.length == 0 - puts I18n.t('display.nothing') - else - table_items(result) - end - end - - # Get an item when multiple choice - # @args: items -> array of items - # @rtrn: item - def get_item(items) - return items[0] if items.length == 1 - - items.sort! { |a,b| a.group.to_s.downcase <=> b.group.to_s.downcase } - choice = ask(I18n.t('form.select')).to_i - - if choice >= 1 and choice <= items.length - return items[choice-1] - else - return nil - end - end - - # Copy in clipboard the login and password - # @args: item -> the item - # clipboard -> enable clipboard - def clipboard(item, clipboard=true) - pid = nil - - # Security: force quit after 90s - Thread.new do - sleep 90 - exit - end - - while true - choice = ask(I18n.t('form.clipboard.choice')).to_s - - case choice - when 'q', 'quit' - break - - when 'l', 'login' - if clipboard - Clipboard.copy(item.user) - puts I18n.t('form.clipboard.login').green - else - puts item.user - end - - when 'p', 'password' - if clipboard - Clipboard.copy(@mpw.get_password(item.id)) - puts I18n.t('form.clipboard.password').yellow - - Thread.new do - sleep 30 - - Clipboard.clear - end - else - puts @mpw.get_password(item.id) - end - - when 'o', 'otp' - if clipboard - Clipboard.copy(@mpw.get_otp_code(item.id)) - else - puts @mpw.get_otp_code(item.id) - end - puts I18n.t('form.clipboard.otp', time: @mpw.get_otp_remaining_time).yellow - - else - puts "----- #{I18n.t('form.clipboard.help.name')} -----".cyan - puts I18n.t('form.clipboard.help.login') - puts I18n.t('form.clipboard.help.password') - puts I18n.t('form.clipboard.help.otp_code') - puts I18n.t('form.clipboard.help.quit') - next - end - end - - Clipboard.clear - rescue SystemExit, Interrupt - Clipboard.clear - end - - # List all wallets - def list_wallet - wallets = [] - Dir.glob("#{@config.wallet_dir}/*.mpw").each do |f| - wallet = File.basename(f, '.mpw') - wallet += ' *'.green if wallet == @config.default_wallet - wallets << wallet - end - - table_list('wallets', wallets) - end - - # Display the wallet - # @args: wallet -> the wallet name - def get_wallet(wallet=nil) - if wallet.to_s.empty? - wallets = Dir.glob("#{@config.wallet_dir}/*.mpw") - - if wallets.length == 1 - @wallet_file = wallets[0] - elsif not @config.default_wallet.to_s.empty? - @wallet_file = "#{@config.wallet_dir}/#{@config.default_wallet}.mpw" - else - @wallet_file = "#{@config.wallet_dir}/default.mpw" - end - else - @wallet_file = "#{@config.wallet_dir}/#{wallet}.mpw" - end - end - - # Add a new public key - # args: key -> the key name or key file to add - def add_key(key) - @mpw.add_key(key) - @mpw.write_data - - puts "#{I18n.t('form.add_key.valid')}".green - rescue Exception => e - puts "#{I18n.t('display.error')} #13: #{e}".red - end - - # Add new public key - # args: key -> the key name to delete - def delete_key(key) - @mpw.delete_key(key) - @mpw.write_data - - puts "#{I18n.t('form.delete_key.valid')}".green - rescue Exception => e - puts "#{I18n.t('display.error')} #15: #{e}".red - end - - # Text editor interface - # @args: template -> template name - # item -> the item to edit - # password -> disable field password - def text_editor(template_name, item=nil, password=false) - editor = ENV['EDITOR'] || 'nano' - options = {} - opts = {} - template_file = "#{File.expand_path('../../../templates', __FILE__)}/#{template_name}.erb" - template = ERB.new(IO.read(template_file)) - - Dir.mktmpdir do |dir| - tmp_file = "#{dir}/#{template_name}.yml" - - File.open(tmp_file, 'w') do |f| - f << template.result(binding) - end - - system("#{editor} #{tmp_file}") - - opts = YAML::load_file(tmp_file) - end - - opts.delete_if { |k,v| v.to_s.empty? } - - opts.each do |k,v| - options[k.to_sym] = v - end - - return options - end - - # Form to add a new item - # @args: password -> generate a random password - def add(password=false) - options = text_editor('add_form', nil, password) - item = Item.new(options) - options[:password] = MPW::password(@config.password) if password - - @mpw.add(item) - @mpw.set_password(item.id, options[:password]) if options.has_key?(:password) - @mpw.set_otp_key(item.id, options[:otp_key]) if options.has_key?(:otp_key) - @mpw.write_data - - puts "#{I18n.t('form.add_item.valid')}".green - rescue Exception => e - puts "#{I18n.t('display.error')} #13: #{e}".red - end - - # Update an item - # @args: password -> generate a random password - # options -> the option to search - def update(password=false, options={}) - items = @mpw.list(options) - - if items.length == 0 - puts "#{I18n.t('display.warning')}: #{I18n.t('warning.select')}".yellow - else - table_items(items) if items.length > 1 - - item = get_item(items) - options = text_editor('update_form', item, password) - options[:password] = MPW::password(@config.password) if password - - item.update(options) - @mpw.set_password(item.id, options[:password]) if options.has_key?(:password) - @mpw.set_otp_key(item.id, options[:otp_key]) if options.has_key?(:otp_key) - @mpw.write_data - - puts "#{I18n.t('form.update_item.valid')}".green - end - rescue Exception => e - puts "#{I18n.t('display.error')} #14: #{e}".red - end - - # Remove an item - # @args: options -> the option to search - def delete(options={}) - items = @mpw.list(options) - - if items.length == 0 - puts "#{I18n.t('display.warning')}: #{I18n.t('warning.select')}".yellow - else - table_items(items) - - item = get_item(items) - confirm = ask("#{I18n.t('form.delete_item.ask')} (y/N) ").to_s - - if not confirm =~ /^(y|yes|YES|Yes|Y)$/ - return false - end - - item.delete - @mpw.write_data - - puts "#{I18n.t('form.delete_item.valid')}".green - end - rescue Exception => e - puts "#{I18n.t('display.error')} #16: #{e}".red - end - - # Copy a password, otp, login - # @args: clipboard -> enable clipboard - # options -> the option to search - def copy(clipboard=true, options={}) - items = @mpw.list(options) - - if items.length == 0 - puts I18n.t('display.nothing') - else - table_items(items) - - item = get_item(items) - clipboard(item, clipboard) - end - rescue Exception => e - puts "#{I18n.t('display.error')} #14: #{e}".red - end - - # Export the items in a CSV file - # @args: file -> the destination file - # options -> option to search - def export(file, options) - file = 'export-mpw.yml' if file.to_s.empty? - items = @mpw.list(options) - data = {} - - items.each do |item| - data.merge!(item.id => { 'host' => item.host, - 'user' => item.user, - 'group' => item.group, - 'password' => @mpw.get_password(item.id), - 'protocol' => item.protocol, - 'port' => item.port, - 'otp_key' => @mpw.get_otp_key(item.id), - 'comment' => item.comment, - 'last_edit' => item.last_edit, - 'created' => item.created, - } - ) - end - - File.open(file, 'w') {|f| f << data.to_yaml} - - puts "#{I18n.t('form.export.valid', file: file)}".green - rescue Exception => e - puts "#{I18n.t('display.error')} #17: #{e}".red - end - - # Import items from a YAML file - # @args: file -> the import file - def import(file) - raise I18n.t('form.import.file_empty') if file.to_s.empty? - raise I18n.t('form.import.file_not_exist') if not File.exist?(file) - - YAML::load_file(file).each_value do |row| - item = Item.new(group: row['group'], - host: row['host'], - protocol: row['protocol'], - user: row['user'], - port: row['port'], - comment: row['comment'], - ) - - next if item.empty? - - @mpw.add(item) - @mpw.set_password(item.id, row['password']) if not row['password'].to_s.empty? - @mpw.set_otp_key(item.id, row['otp_key']) if not row['otp_key'].to_s.empty? - end - - @mpw.write_data - - puts "#{I18n.t('form.import.valid')}".green - rescue Exception => e - puts "#{I18n.t('display.error')} #18: #{e}".red - end + # Constructor + # @args: config -> the config + def initialize(config) + @config = config + end + + # Change a parameter int the config after init + # @args: options -> param to change + def set_config(options) + @config.setup(options) + + puts "#{I18n.t('form.set_config.valid')}".green + rescue Exception => e + puts "#{I18n.t('display.error')} #15: #{e}".red + exit 2 + end + + # Create a new config file + # @args: options -> set param + def setup(options) + options[:lang] = options[:lang] || Locale::Tag.parse(ENV['LANG']).to_simple.to_s[0..1] + + I18n.locale = options[:lang].to_sym + + @config.setup(options) + + load_config + + puts "#{I18n.t('form.setup_config.valid')}".green + rescue Exception => e + puts "#{I18n.t('display.error')} #8: #{e}".red + exit 2 + end + + # Setup a new GPG key + # @args: gpg_key -> the key name + def setup_gpg_key(gpg_key) + return if @config.check_gpg_key? + + password = ask(I18n.t('form.setup_gpg_key.password')) {|q| q.echo = false} + confirm = ask(I18n.t('form.setup_gpg_key.confirm_password')) {|q| q.echo = false} + + if password != confirm + raise I18n.t('form.setup_gpg_key.error_password') + end + + @password = password.to_s + + puts I18n.t('form.setup_gpg_key.wait') + + @config.setup_gpg_key(@password, gpg_key) + + puts "#{I18n.t('form.setup_gpg_key.valid')}".green + rescue Exception => e + puts "#{I18n.t('display.error')} #8: #{e}".red + exit 2 + end + + # List gpg keys in wallet + def list_keys + table_list('keys', @mpw.list_keys) + end + + # Load config + def load_config + @config.load_config + + rescue Exception => e + puts "#{I18n.t('display.error')} #10: #{e}".red + exit 2 + end + + # Request the GPG password and decrypt the file + def decrypt + if not defined?(@mpw) + @password = ask(I18n.t('display.gpg_password')) {|q| q.echo = false} + @mpw = MPW.new(@config.gpg_key, @wallet_file, @password, @config.gpg_exe) + end + + @mpw.read_data + rescue Exception => e + puts "#{I18n.t('display.error')} #11: #{e}".red + exit 2 + end + + # Format list on a table + def table_list(title, list) + i = 1 + length = 0 + + list.each do |item| + length = item.length if length < item.length + end + length += 7 + + puts "\n#{I18n.t("display.#{title}")}".red + print ' ' + length.times { print '=' } + print "\n" + + list.each do |item| + print " #{i}".cyan + (3 - i.to_s.length).times { print ' ' } + puts "| #{item}" + i += 1 + end + + print "\n" + end + + # Format items on a table + def table_items(items=[]) + group = '.' + i = 1 + length_total = 10 + data = { id: { length: 3, color: 'cyan' }, + host: { length: 9, color: 'yellow' }, + user: { length: 7, color: 'green' }, + protocol: { length: 9, color: 'white' }, + port: { length: 5, color: 'white' }, + otp: { length: 4, color: 'white' }, + comment: { length: 14, color: 'magenta' }, + } + + items.each do |item| + data.each do |k, v| + next if k == :id or k == :otp + + v[:length] = item.send(k.to_s).to_s.length + 3 if item.send(k.to_s).to_s.length >= v[:length] + end + end + data[:id][:length] = items.length.to_s.length + 2 if items.length.to_s.length > data[:id][:length] + + data.each_value { |v| length_total += v[:length] } + items.sort! { |a, b| a.group.to_s.downcase <=> b.group.to_s.downcase } + + items.each do |item| + if group != item.group + group = item.group + + if group.to_s.empty? + puts "\n#{I18n.t('display.no_group')}".red + else + puts "\n#{group}".red + end + + print ' ' + length_total.times { print '=' } + print "\n " + data.each do |k, v| + case k + when :id + print ' ID' + when :otp + print '| OTP' + else + print "| #{k.to_s.capitalize}" + end + + (v[:length] - k.to_s.length).times { print ' ' } + end + print "\n " + length_total.times { print '=' } + print "\n" + end + + print " #{i}".send(data[:id][:color]) + (data[:id][:length] - i.to_s.length).times { print ' ' } + data.each do |k, v| + next if k == :id + + if k == :otp + print '| ' + if item.otp; print ' X ' else 4.times { print ' ' } end + + next + end + + print '| ' + print "#{item.send(k.to_s)}".send(v[:color]) + (v[:length] - item.send(k.to_s).to_s.length).times { print ' ' } + end + print "\n" + + i += 1 + end + + print "\n" + end + + # Display the query's result + # @args: options -> the option to search + def list(options={}) + result = @mpw.list(options) + + if result.length == 0 + puts I18n.t('display.nothing') + else + table_items(result) + end + end + + # Get an item when multiple choice + # @args: items -> array of items + # @rtrn: item + def get_item(items) + return items[0] if items.length == 1 + + items.sort! { |a,b| a.group.to_s.downcase <=> b.group.to_s.downcase } + choice = ask(I18n.t('form.select')).to_i + + if choice >= 1 and choice <= items.length + return items[choice-1] + else + return nil + end + end + + # Copy in clipboard the login and password + # @args: item -> the item + # clipboard -> enable clipboard + def clipboard(item, clipboard=true) + pid = nil + + # Security: force quit after 90s + Thread.new do + sleep 90 + exit + end + + while true + choice = ask(I18n.t('form.clipboard.choice')).to_s + + case choice + when 'q', 'quit' + break + + when 'l', 'login' + if clipboard + Clipboard.copy(item.user) + puts I18n.t('form.clipboard.login').green + else + puts item.user + end + + when 'p', 'password' + if clipboard + Clipboard.copy(@mpw.get_password(item.id)) + puts I18n.t('form.clipboard.password').yellow + + Thread.new do + sleep 30 + + Clipboard.clear + end + else + puts @mpw.get_password(item.id) + end + + when 'o', 'otp' + if clipboard + Clipboard.copy(@mpw.get_otp_code(item.id)) + else + puts @mpw.get_otp_code(item.id) + end + puts I18n.t('form.clipboard.otp', time: @mpw.get_otp_remaining_time).yellow + + else + puts "----- #{I18n.t('form.clipboard.help.name')} -----".cyan + puts I18n.t('form.clipboard.help.login') + puts I18n.t('form.clipboard.help.password') + puts I18n.t('form.clipboard.help.otp_code') + puts I18n.t('form.clipboard.help.quit') + next + end + end + + Clipboard.clear + rescue SystemExit, Interrupt + Clipboard.clear + end + + # List all wallets + def list_wallet + wallets = [] + Dir.glob("#{@config.wallet_dir}/*.mpw").each do |f| + wallet = File.basename(f, '.mpw') + wallet += ' *'.green if wallet == @config.default_wallet + wallets << wallet + end + + table_list('wallets', wallets) + end + + # Display the wallet + # @args: wallet -> the wallet name + def get_wallet(wallet=nil) + if wallet.to_s.empty? + wallets = Dir.glob("#{@config.wallet_dir}/*.mpw") + + if wallets.length == 1 + @wallet_file = wallets[0] + elsif not @config.default_wallet.to_s.empty? + @wallet_file = "#{@config.wallet_dir}/#{@config.default_wallet}.mpw" + else + @wallet_file = "#{@config.wallet_dir}/default.mpw" + end + else + @wallet_file = "#{@config.wallet_dir}/#{wallet}.mpw" + end + end + + # Add a new public key + # args: key -> the key name or key file to add + def add_key(key) + @mpw.add_key(key) + @mpw.write_data + + puts "#{I18n.t('form.add_key.valid')}".green + rescue Exception => e + puts "#{I18n.t('display.error')} #13: #{e}".red + end + + # Add new public key + # args: key -> the key name to delete + def delete_key(key) + @mpw.delete_key(key) + @mpw.write_data + + puts "#{I18n.t('form.delete_key.valid')}".green + rescue Exception => e + puts "#{I18n.t('display.error')} #15: #{e}".red + end + + # Text editor interface + # @args: template -> template name + # item -> the item to edit + # password -> disable field password + def text_editor(template_name, item=nil, password=false) + editor = ENV['EDITOR'] || 'nano' + options = {} + opts = {} + template_file = "#{File.expand_path('../../../templates', __FILE__)}/#{template_name}.erb" + template = ERB.new(IO.read(template_file)) + + Dir.mktmpdir do |dir| + tmp_file = "#{dir}/#{template_name}.yml" + + File.open(tmp_file, 'w') do |f| + f << template.result(binding) + end + + system("#{editor} #{tmp_file}") + + opts = YAML::load_file(tmp_file) + end + + opts.delete_if { |k,v| v.to_s.empty? } + + opts.each do |k,v| + options[k.to_sym] = v + end + + return options + end + + # Form to add a new item + # @args: password -> generate a random password + def add(password=false) + options = text_editor('add_form', nil, password) + item = Item.new(options) + options[:password] = MPW::password(@config.password) if password + + @mpw.add(item) + @mpw.set_password(item.id, options[:password]) if options.has_key?(:password) + @mpw.set_otp_key(item.id, options[:otp_key]) if options.has_key?(:otp_key) + @mpw.write_data + + puts "#{I18n.t('form.add_item.valid')}".green + rescue Exception => e + puts "#{I18n.t('display.error')} #13: #{e}".red + end + + # Update an item + # @args: password -> generate a random password + # options -> the option to search + def update(password=false, options={}) + items = @mpw.list(options) + + if items.length == 0 + puts "#{I18n.t('display.warning')}: #{I18n.t('warning.select')}".yellow + else + table_items(items) if items.length > 1 + + item = get_item(items) + options = text_editor('update_form', item, password) + options[:password] = MPW::password(@config.password) if password + + item.update(options) + @mpw.set_password(item.id, options[:password]) if options.has_key?(:password) + @mpw.set_otp_key(item.id, options[:otp_key]) if options.has_key?(:otp_key) + @mpw.write_data + + puts "#{I18n.t('form.update_item.valid')}".green + end + rescue Exception => e + puts "#{I18n.t('display.error')} #14: #{e}".red + end + + # Remove an item + # @args: options -> the option to search + def delete(options={}) + items = @mpw.list(options) + + if items.length == 0 + puts "#{I18n.t('display.warning')}: #{I18n.t('warning.select')}".yellow + else + table_items(items) + + item = get_item(items) + confirm = ask("#{I18n.t('form.delete_item.ask')} (y/N) ").to_s + + if not confirm =~ /^(y|yes|YES|Yes|Y)$/ + return false + end + + item.delete + @mpw.write_data + + puts "#{I18n.t('form.delete_item.valid')}".green + end + rescue Exception => e + puts "#{I18n.t('display.error')} #16: #{e}".red + end + + # Copy a password, otp, login + # @args: clipboard -> enable clipboard + # options -> the option to search + def copy(clipboard=true, options={}) + items = @mpw.list(options) + + if items.length == 0 + puts I18n.t('display.nothing') + else + table_items(items) + + item = get_item(items) + clipboard(item, clipboard) + end + rescue Exception => e + puts "#{I18n.t('display.error')} #14: #{e}".red + end + + # Export the items in a CSV file + # @args: file -> the destination file + # options -> option to search + def export(file, options) + file = 'export-mpw.yml' if file.to_s.empty? + items = @mpw.list(options) + data = {} + + items.each do |item| + data.merge!(item.id => { 'host' => item.host, + 'user' => item.user, + 'group' => item.group, + 'password' => @mpw.get_password(item.id), + 'protocol' => item.protocol, + 'port' => item.port, + 'otp_key' => @mpw.get_otp_key(item.id), + 'comment' => item.comment, + 'last_edit' => item.last_edit, + 'created' => item.created, + } + ) + end + + File.open(file, 'w') {|f| f << data.to_yaml} + + puts "#{I18n.t('form.export.valid', file: file)}".green + rescue Exception => e + puts "#{I18n.t('display.error')} #17: #{e}".red + end + + # Import items from a YAML file + # @args: file -> the import file + def import(file) + raise I18n.t('form.import.file_empty') if file.to_s.empty? + raise I18n.t('form.import.file_not_exist') if not File.exist?(file) + + YAML::load_file(file).each_value do |row| + item = Item.new(group: row['group'], + host: row['host'], + protocol: row['protocol'], + user: row['user'], + port: row['port'], + comment: row['comment'], + ) + + next if item.empty? + + @mpw.add(item) + @mpw.set_password(item.id, row['password']) if not row['password'].to_s.empty? + @mpw.set_otp_key(item.id, row['otp_key']) if not row['otp_key'].to_s.empty? + end + + @mpw.write_data + + puts "#{I18n.t('form.import.valid')}".green + rescue Exception => e + puts "#{I18n.t('display.error')} #18: #{e}".red + end end end diff --git a/lib/mpw/config.rb b/lib/mpw/config.rb index 7fbd778..298ba61 100644 --- a/lib/mpw/config.rb +++ b/lib/mpw/config.rb @@ -1,17 +1,17 @@ #!/usr/bin/ruby # MPW is a software to crypt and manage your passwords # Copyright (C) 2016 Adrien Waksberg <mpw@yae.im> -# +# # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. -# +# # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -# +# # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. @@ -20,140 +20,140 @@ require 'gpgme' require 'yaml' require 'i18n' require 'fileutils' - + module MPW class Config - - attr_accessor :error_msg - attr_accessor :gpg_key - attr_accessor :lang - attr_accessor :config_dir - attr_accessor :default_wallet - attr_accessor :wallet_dir - attr_accessor :gpg_exe - attr_accessor :password + attr_accessor :error_msg - # Constructor - # @args: config_file -> the specify config file - def initialize(config_file=nil) - @config_file = config_file + attr_accessor :gpg_key + attr_accessor :lang + attr_accessor :config_dir + attr_accessor :default_wallet + attr_accessor :wallet_dir + attr_accessor :gpg_exe + attr_accessor :password - if /darwin/ =~ RUBY_PLATFORM - @config_dir = "#{Dir.home}/Library/Preferences/mpw" - elsif /cygwin|mswin|mingw|bccwin|wince|emx/ =~ RUBY_PLATFORM - @config_dir = "#{Dir.home}/AppData/Local/mpw" - else - @config_dir = "#{Dir.home}/.config/mpw" - end - - @config_file = "#{@config_dir}/mpw.cfg" if @config_file.nil? or @config_file.empty? - end + # Constructor + # @args: config_file -> the specify config file + def initialize(config_file=nil) + @config_file = config_file - # Create a new config file - # @args: options -> hash with values - # @rtrn: true if le config file is create - def setup(options) - gpg_key = options[:gpg_key] || @gpg_key - lang = options[:lang] || @lang - wallet_dir = options[:wallet_dir] || @wallet_dir - default_wallet = options[:default_wallet] || @default_wallet - gpg_exe = options[:gpg_exe] || @gpg_exe - password = { numeric: true, - alpha: true, - special: false, - length: 16, - } + if /darwin/ =~ RUBY_PLATFORM + @config_dir = "#{Dir.home}/Library/Preferences/mpw" + elsif /cygwin|mswin|mingw|bccwin|wince|emx/ =~ RUBY_PLATFORM + @config_dir = "#{Dir.home}/AppData/Local/mpw" + else + @config_dir = "#{Dir.home}/.config/mpw" + end - ['numeric', 'special', 'alpha', 'length'].each do |k| - if options.has_key?("pwd_#{k}".to_sym) - password[k.to_sym] = options["pwd_#{k}".to_sym] - elsif not @password.nil? and @password.has_key?(k.to_sym) - password[k.to_sym] = @password[k.to_sym] - end - end + @config_file = "#{@config_dir}/mpw.cfg" if @config_file.nil? or @config_file.empty? + end - if not gpg_key =~ /[a-zA-Z0-9.-_]+\@[a-zA-Z0-9]+\.[a-zA-Z]+/ - raise I18n.t('error.config.key_bad_format') - end + # Create a new config file + # @args: options -> hash with values + # @rtrn: true if le config file is create + def setup(options) + gpg_key = options[:gpg_key] || @gpg_key + lang = options[:lang] || @lang + wallet_dir = options[:wallet_dir] || @wallet_dir + default_wallet = options[:default_wallet] || @default_wallet + gpg_exe = options[:gpg_exe] || @gpg_exe + password = { numeric: true, + alpha: true, + special: false, + length: 16, + } - wallet_dir = "#{@config_dir}/wallets" if wallet_dir.to_s.empty? - config = { 'gpg_key' => gpg_key, - 'lang' => lang, - 'wallet_dir' => wallet_dir, - 'default_wallet' => default_wallet, - 'gpg_exe' => gpg_exe, - 'password' => password, - } + ['numeric', 'special', 'alpha', 'length'].each do |k| + if options.has_key?("pwd_#{k}".to_sym) + password[k.to_sym] = options["pwd_#{k}".to_sym] + elsif not @password.nil? and @password.has_key?(k.to_sym) + password[k.to_sym] = @password[k.to_sym] + end + end - FileUtils.mkdir_p(@config_dir, mode: 0700) - FileUtils.mkdir_p(wallet_dir, mode: 0700) + if not gpg_key =~ /[a-zA-Z0-9.-_]+\@[a-zA-Z0-9]+\.[a-zA-Z]+/ + raise I18n.t('error.config.key_bad_format') + end - File.open(@config_file, 'w') do |file| - file << config.to_yaml - end - rescue Exception => e - raise "#{I18n.t('error.config.write')}\n#{e}" - end + wallet_dir = "#{@config_dir}/wallets" if wallet_dir.to_s.empty? + config = { 'gpg_key' => gpg_key, + 'lang' => lang, + 'wallet_dir' => wallet_dir, + 'default_wallet' => default_wallet, + 'gpg_exe' => gpg_exe, + 'password' => password, + } - # Setup a new gpg key - # @args: password -> the GPG key password - # name -> the name of user - # length -> length of the GPG key - # expire -> the time of expire to GPG key - # @rtrn: true if the GPG key is create, else false - def setup_gpg_key(password, name, length = 4096, expire = 0) - if name.to_s.empty? - raise "#{I18n.t('error.config.genkey_gpg.name')}" - elsif password.to_s.empty? - raise "#{I18n.t('error.config.genkey_gpg.password')}" - end + FileUtils.mkdir_p(@config_dir, mode: 0700) + FileUtils.mkdir_p(wallet_dir, mode: 0700) - param = '' - param << '<GnupgKeyParms format="internal">' + "\n" - param << "Key-Type: RSA\n" - param << "Key-Length: #{length}\n" - param << "Subkey-Type: ELG-E\n" - param << "Subkey-Length: #{length}\n" - param << "Name-Real: #{name}\n" - param << "Name-Comment: #{name}\n" - param << "Name-Email: #{@gpg_key}\n" - param << "Expire-Date: #{expire}\n" - param << "Passphrase: #{password}\n" - param << "</GnupgKeyParms>\n" + File.open(@config_file, 'w') do |file| + file << config.to_yaml + end + rescue Exception => e + raise "#{I18n.t('error.config.write')}\n#{e}" + end - ctx = GPGME::Ctx.new - ctx.genkey(param, nil, nil) - rescue Exception => e - raise "#{I18n.t('error.config.genkey_gpg.exception')}\n#{e}" - end + # Setup a new gpg key + # @args: password -> the GPG key password + # name -> the name of user + # length -> length of the GPG key + # expire -> the time of expire to GPG key + # @rtrn: true if the GPG key is create, else false + def setup_gpg_key(password, name, length = 4096, expire = 0) + if name.to_s.empty? + raise "#{I18n.t('error.config.genkey_gpg.name')}" + elsif password.to_s.empty? + raise "#{I18n.t('error.config.genkey_gpg.password')}" + end - # Load the config file - def load_config - config = YAML::load_file(@config_file) - @gpg_key = config['gpg_key'] - @lang = config['lang'] - @wallet_dir = config['wallet_dir'] - @default_wallet = config['default_wallet'] - @gpg_exe = config['gpg_exe'] - @password = config['password'] || {} + param = '' + param << '<GnupgKeyParms format="internal">' + "\n" + param << "Key-Type: RSA\n" + param << "Key-Length: #{length}\n" + param << "Subkey-Type: ELG-E\n" + param << "Subkey-Length: #{length}\n" + param << "Name-Real: #{name}\n" + param << "Name-Comment: #{name}\n" + param << "Name-Email: #{@gpg_key}\n" + param << "Expire-Date: #{expire}\n" + param << "Passphrase: #{password}\n" + param << "</GnupgKeyParms>\n" - raise if @gpg_key.empty? or @wallet_dir.empty? - - I18n.locale = @lang.to_sym - rescue Exception => e - raise "#{I18n.t('error.config.load')}\n#{e}" - end + ctx = GPGME::Ctx.new + ctx.genkey(param, nil, nil) + rescue Exception => e + raise "#{I18n.t('error.config.genkey_gpg.exception')}\n#{e}" + end - # Check if private key exist - # @rtrn: true if the key exist, else false - def check_gpg_key? - ctx = GPGME::Ctx.new - ctx.each_key(@gpg_key, true) do - return true - end + # Load the config file + def load_config + config = YAML::load_file(@config_file) + @gpg_key = config['gpg_key'] + @lang = config['lang'] + @wallet_dir = config['wallet_dir'] + @default_wallet = config['default_wallet'] + @gpg_exe = config['gpg_exe'] + @password = config['password'] || {} - return false - end + raise if @gpg_key.empty? or @wallet_dir.empty? + + I18n.locale = @lang.to_sym + rescue Exception => e + raise "#{I18n.t('error.config.load')}\n#{e}" + end + + # Check if private key exist + # @rtrn: true if the key exist, else false + def check_gpg_key? + ctx = GPGME::Ctx.new + ctx.each_key(@gpg_key, true) do + return true + end + + return false + end end end diff --git a/lib/mpw/item.rb b/lib/mpw/item.rb index a4f730b..469af15 100644 --- a/lib/mpw/item.rb +++ b/lib/mpw/item.rb @@ -1,102 +1,102 @@ #!/usr/bin/ruby # MPW is a software to crypt and manage your passwords # Copyright (C) 2016 Adrien Waksberg <mpw@yae.im> -# +# # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. -# +# # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -# +# # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. require 'i18n' - + module MPW class Item - attr_accessor :id - attr_accessor :group - attr_accessor :host - attr_accessor :protocol - attr_accessor :user - attr_accessor :port - attr_accessor :otp - attr_accessor :comment - attr_accessor :last_edit - attr_accessor :created + attr_accessor :id + attr_accessor :group + attr_accessor :host + attr_accessor :protocol + attr_accessor :user + attr_accessor :port + attr_accessor :otp + attr_accessor :comment + attr_accessor :last_edit + attr_accessor :created - # Constructor - # Create a new item - # @args: options -> a hash of parameter - # raise an error if the hash hasn't the key name - def initialize(options={}) - if not options.has_key?(:host) or options[:host].to_s.empty? - raise I18n.t('error.update.host_empty') - end + # Constructor + # Create a new item + # @args: options -> a hash of parameter + # raise an error if the hash hasn't the key name + def initialize(options={}) + if not options.has_key?(:host) or options[:host].to_s.empty? + raise I18n.t('error.update.host_empty') + end - if not options.has_key?(:id) or options[:id].to_s.empty? or not options.has_key?(:created) or options[:created].to_s.empty? - @id = generate_id - @created = Time.now.to_i - else - @id = options[:id] - @created = options[:created] - @last_edit = options[:last_edit] - options[:no_update_last_edit] = true - end + if not options.has_key?(:id) or options[:id].to_s.empty? or not options.has_key?(:created) or options[:created].to_s.empty? + @id = generate_id + @created = Time.now.to_i + else + @id = options[:id] + @created = options[:created] + @last_edit = options[:last_edit] + options[:no_update_last_edit] = true + end - update(options) - end + update(options) + end - # Update the item - # @args: options -> a hash of parameter - def update(options={}) - if options.has_key?(:host) and options[:host].to_s.empty? - raise I18n.t('error.update.host_empty') - end + # Update the item + # @args: options -> a hash of parameter + def update(options={}) + if options.has_key?(:host) and options[:host].to_s.empty? + raise I18n.t('error.update.host_empty') + end - @group = options[:group] if options.has_key?(:group) - @host = options[:host] if options.has_key?(:host) - @protocol = options[:protocol] if options.has_key?(:protocol) - @user = options[:user] if options.has_key?(:user) - @port = options[:port].to_i if options.has_key?(:port) and not options[:port].to_s.empty? - @otp = options[:otp] if options.has_key?(:otp) - @comment = options[:comment] if options.has_key?(:comment) - @last_edit = Time.now.to_i if not options.has_key?(:no_update_last_edit) - end + @group = options[:group] if options.has_key?(:group) + @host = options[:host] if options.has_key?(:host) + @protocol = options[:protocol] if options.has_key?(:protocol) + @user = options[:user] if options.has_key?(:user) + @port = options[:port].to_i if options.has_key?(:port) and not options[:port].to_s.empty? + @otp = options[:otp] if options.has_key?(:otp) + @comment = options[:comment] if options.has_key?(:comment) + @last_edit = Time.now.to_i if not options.has_key?(:no_update_last_edit) + end - # Delete all data - def delete - @id = nil - @group = nil - @host = nil - @protocol = nil - @user = nil - @port = nil - @otp = nil - @comment = nil - @created = nil - @last_edit = nil - end + # Delete all data + def delete + @id = nil + @group = nil + @host = nil + @protocol = nil + @user = nil + @port = nil + @otp = nil + @comment = nil + @created = nil + @last_edit = nil + end - def empty? - return @id.to_s.empty? - end + def empty? + return @id.to_s.empty? + end - def nil? - return false - end + def nil? + return false + end - # Generate an random id - private - def generate_id - return ([*('A'..'Z'),*('a'..'z'),*('0'..'9')]).sample(16).join - end + # Generate an random id + private + def generate_id + return ([*('A'..'Z'),*('a'..'z'),*('0'..'9')]).sample(16).join + end end end diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index 8f4b42e..9147648 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -1,17 +1,17 @@ #!/usr/bin/ruby # MPW is a software to crypt and manage your passwords # Copyright (C) 2016 Adrien Waksberg <mpw@yae.im> -# +# # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. -# +# # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -# +# # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. @@ -22,360 +22,360 @@ require 'i18n' require 'yaml' require 'rotp' require 'mpw/item' - + module MPW class MPW - # Constructor - def initialize(key, wallet_file, gpg_pass=nil, gpg_exe=nil) - @key = key - @gpg_pass = gpg_pass - @gpg_exe = gpg_exe - @wallet_file = wallet_file + # Constructor + def initialize(key, wallet_file, gpg_pass=nil, gpg_exe=nil) + @key = key + @gpg_pass = gpg_pass + @gpg_exe = gpg_exe + @wallet_file = wallet_file - if not @gpg_exe.to_s.empty? - GPGME::Engine.set_info(GPGME::PROTOCOL_OpenPGP, @gpg_exe, "#{Dir.home}/.gnupg") - end - end + if not @gpg_exe.to_s.empty? + GPGME::Engine.set_info(GPGME::PROTOCOL_OpenPGP, @gpg_exe, "#{Dir.home}/.gnupg") + end + end - # Read mpw file - def read_data - @config = {} - @data = [] - @keys = {} - @passwords = {} - @otp_keys = {} + # Read mpw file + def read_data + @config = {} + @data = [] + @keys = {} + @passwords = {} + @otp_keys = {} - data = nil + data = nil - return if not File.exists?(@wallet_file) + return if not File.exists?(@wallet_file) - Gem::Package::TarReader.new(File.open(@wallet_file)) do |tar| - tar.each do |f| - case f.full_name - when 'wallet/config.gpg' - @config = YAML.load(decrypt(f.read)) + Gem::Package::TarReader.new(File.open(@wallet_file)) do |tar| + tar.each do |f| + case f.full_name + when 'wallet/config.gpg' + @config = YAML.load(decrypt(f.read)) - when 'wallet/meta.gpg' - data = decrypt(f.read) + when 'wallet/meta.gpg' + data = decrypt(f.read) - when /^wallet\/keys\/(?<key>.+)\.pub$/ - key = Regexp.last_match('key') + when /^wallet\/keys\/(?<key>.+)\.pub$/ + key = Regexp.last_match('key') - if GPGME::Key.find(:public, key).length == 0 - GPGME::Key.import(f.read, armor: true) - end + if GPGME::Key.find(:public, key).length == 0 + GPGME::Key.import(f.read, armor: true) + end - @keys[key] = f.read + @keys[key] = f.read - when /^wallet\/passwords\/(?<id>[a-zA-Z0-9]+)\.gpg$/ - @passwords[Regexp.last_match('id')] = f.read + when /^wallet\/passwords\/(?<id>[a-zA-Z0-9]+)\.gpg$/ + @passwords[Regexp.last_match('id')] = f.read - when /^wallet\/otp_keys\/(?<id>[a-zA-Z0-9]+)\.gpg$/ - @otp_keys[Regexp.last_match('id')] = f.read + when /^wallet\/otp_keys\/(?<id>[a-zA-Z0-9]+)\.gpg$/ + @otp_keys[Regexp.last_match('id')] = f.read - else - next - end - end - end + else + next + end + end + end - if not data.nil? and not data.empty? - YAML.load(data).each_value do |d| - @data.push(Item.new(id: d['id'], - group: d['group'], - host: d['host'], - protocol: d['protocol'], - user: d['user'], - port: d['port'], - otp: @otp_keys.has_key?(d['id']), - comment: d['comment'], - last_edit: d['last_edit'], - created: d['created'], - ) - ) - end - end + if not data.nil? and not data.empty? + YAML.load(data).each_value do |d| + @data.push(Item.new(id: d['id'], + group: d['group'], + host: d['host'], + protocol: d['protocol'], + user: d['user'], + port: d['port'], + otp: @otp_keys.has_key?(d['id']), + comment: d['comment'], + last_edit: d['last_edit'], + created: d['created'], + ) + ) + end + end - add_key(@key) if @keys[@key].nil? - rescue Exception => e - raise "#{I18n.t('error.mpw_file.read_data')}\n#{e}" - end + add_key(@key) if @keys[@key].nil? + rescue Exception => e + raise "#{I18n.t('error.mpw_file.read_data')}\n#{e}" + end - # Encrypt a file - def write_data - data = {} - tmp_file = "#{@wallet_file}.tmp" + # Encrypt a file + def write_data + data = {} + tmp_file = "#{@wallet_file}.tmp" - @data.each do |item| - next if item.empty? + @data.each do |item| + next if item.empty? - data.merge!(item.id => { 'id' => item.id, - 'group' => item.group, - 'host' => item.host, - 'protocol' => item.protocol, - 'user' => item.user, - 'port' => item.port, - 'comment' => item.comment, - 'last_edit' => item.last_edit, - 'created' => item.created, - } - ) - end + data.merge!(item.id => { 'id' => item.id, + 'group' => item.group, + 'host' => item.host, + 'protocol' => item.protocol, + 'user' => item.user, + 'port' => item.port, + 'comment' => item.comment, + 'last_edit' => item.last_edit, + 'created' => item.created, + } + ) + end - @config['last_update'] = Time.now.to_i + @config['last_update'] = Time.now.to_i - Gem::Package::TarWriter.new(File.open(tmp_file, 'w+')) do |tar| - data_encrypt = encrypt(data.to_yaml) - tar.add_file_simple('wallet/meta.gpg', 0400, data_encrypt.length) do |io| - io.write(data_encrypt) - end + Gem::Package::TarWriter.new(File.open(tmp_file, 'w+')) do |tar| + data_encrypt = encrypt(data.to_yaml) + tar.add_file_simple('wallet/meta.gpg', 0400, data_encrypt.length) do |io| + io.write(data_encrypt) + end - config = encrypt(@config.to_yaml) - tar.add_file_simple('wallet/config.gpg', 0400, config.length) do |io| - io.write(config) - end + config = encrypt(@config.to_yaml) + tar.add_file_simple('wallet/config.gpg', 0400, config.length) do |io| + io.write(config) + end - @passwords.each do |id, password| - tar.add_file_simple("wallet/passwords/#{id}.gpg", 0400, password.length) do |io| - io.write(password) - end - end + @passwords.each do |id, password| + tar.add_file_simple("wallet/passwords/#{id}.gpg", 0400, password.length) do |io| + io.write(password) + end + end - @otp_keys.each do |id, key| - tar.add_file_simple("wallet/otp_keys/#{id}.gpg", 0400, key.length) do |io| - io.write(key) - end - end + @otp_keys.each do |id, key| + tar.add_file_simple("wallet/otp_keys/#{id}.gpg", 0400, key.length) do |io| + io.write(key) + end + end - @keys.each do |id, key| - tar.add_file_simple("wallet/keys/#{id}.pub", 0400, key.length) do |io| - io.write(key) - end - end - end + @keys.each do |id, key| + tar.add_file_simple("wallet/keys/#{id}.pub", 0400, key.length) do |io| + io.write(key) + end + end + end - File.rename(tmp_file, @wallet_file) - rescue Exception => e - File.unlink(tmp_file) if File.exist?(tmp_file) + File.rename(tmp_file, @wallet_file) + rescue Exception => e + File.unlink(tmp_file) if File.exist?(tmp_file) - raise "#{I18n.t('error.mpw_file.write_data')}\n#{e}" - end + raise "#{I18n.t('error.mpw_file.write_data')}\n#{e}" + end - # Get a password - # args: id -> the item id - def get_password(id) - password = decrypt(@passwords[id]) - - if /^\$[a-zA-Z0-9]{4,9}::(?<password>.+)$/ =~ password - return Regexp.last_match('password') - else - return password - end - end + # Get a password + # args: id -> the item id + def get_password(id) + password = decrypt(@passwords[id]) - # Set a password - # args: id -> the item id - # password -> the new password - def set_password(id, password) - salt = MPW::password(length: Random.rand(4..9)) - password = "$#{salt}::#{password}" + if /^\$[a-zA-Z0-9]{4,9}::(?<password>.+)$/ =~ password + return Regexp.last_match('password') + else + return password + end + end - @passwords[id] = encrypt(password) - end + # Set a password + # args: id -> the item id + # password -> the new password + def set_password(id, password) + salt = MPW::password(length: Random.rand(4..9)) + password = "$#{salt}::#{password}" - # Return the list of all gpg keys - # rtrn: an array with the gpg keys name - def list_keys - return @keys.keys - end + @passwords[id] = encrypt(password) + end - # Add a public key - # args: key -> new public key file or name - def add_key(key) - if File.exists?(key) - data = File.open(key).read - key_import = GPGME::Key.import(data, armor: true) - key = GPGME::Key.get(key_import.imports[0].fpr).uids[0].email - else - data = GPGME::Key.export(key, armor: true).read - end + # Return the list of all gpg keys + # rtrn: an array with the gpg keys name + def list_keys + return @keys.keys + end - if data.to_s.empty? - raise I18n.t('error.export_key') - end + # Add a public key + # args: key -> new public key file or name + def add_key(key) + if File.exists?(key) + data = File.open(key).read + key_import = GPGME::Key.import(data, armor: true) + key = GPGME::Key.get(key_import.imports[0].fpr).uids[0].email + else + data = GPGME::Key.export(key, armor: true).read + end - @keys[key] = data - @passwords.each_key { |id| set_password(id, get_password(id)) } - @otp_keys.each_key { |id| set_otp_key(id, get_otp_key(id)) } - end + if data.to_s.empty? + raise I18n.t('error.export_key') + end - # Delete a public key - # args: key -> public key to delete - def delete_key(key) - @keys.delete(key) - @passwords.each_key { |id| set_password(id, get_password(id)) } - @otp_keys.each_key { |id| set_otp_key(id, get_otp_key(id)) } - end + @keys[key] = data + @passwords.each_key { |id| set_password(id, get_password(id)) } + @otp_keys.each_key { |id| set_otp_key(id, get_otp_key(id)) } + end - # Set config - # args: config -> a hash with config options - def set_config(options={}) - @config = {} if @config.nil? + # Delete a public key + # args: key -> public key to delete + def delete_key(key) + @keys.delete(key) + @passwords.each_key { |id| set_password(id, get_password(id)) } + @otp_keys.each_key { |id| set_otp_key(id, get_otp_key(id)) } + end - @config['protocol'] = options[:protocol] if options.has_key?(:protocol) - @config['host'] = options[:host] if options.has_key?(:host) - @config['port'] = options[:port] if options.has_key?(:port) - @config['user'] = options[:user] if options.has_key?(:user) - @config['password'] = options[:password] if options.has_key?(:password) - @config['path'] = options[:path] if options.has_key?(:path) - end + # Set config + # args: config -> a hash with config options + def set_config(options={}) + @config = {} if @config.nil? - # Add a new item - # @args: item -> Object MPW::Item - def add(item) - if not item.instance_of?(Item) - raise I18n.t('error.bad_class') - elsif item.empty? - raise I18n.t('error.empty') - else - @data.push(item) - end - end + @config['protocol'] = options[:protocol] if options.has_key?(:protocol) + @config['host'] = options[:host] if options.has_key?(:host) + @config['port'] = options[:port] if options.has_key?(:port) + @config['user'] = options[:user] if options.has_key?(:user) + @config['password'] = options[:password] if options.has_key?(:password) + @config['path'] = options[:path] if options.has_key?(:path) + end - # Search in some csv data - # @args: options -> a hash with paramaters - # @rtrn: a list with the resultat of the search - def list(options={}) - result = [] + # Add a new item + # @args: item -> Object MPW::Item + def add(item) + if not item.instance_of?(Item) + raise I18n.t('error.bad_class') + elsif item.empty? + raise I18n.t('error.empty') + else + @data.push(item) + end + end - search = options[:pattern].to_s.downcase - group = options[:group].to_s.downcase + # Search in some csv data + # @args: options -> a hash with paramaters + # @rtrn: a list with the resultat of the search + def list(options={}) + result = [] - @data.each do |item| - next if item.empty? - next if not group.empty? and not group.eql?(item.group.to_s.downcase) - - host = item.host.to_s.downcase - comment = item.comment.to_s.downcase + search = options[:pattern].to_s.downcase + group = options[:group].to_s.downcase - if not host =~ /^.*#{search}.*$/ and not comment =~ /^.*#{search}.*$/ - next - end + @data.each do |item| + next if item.empty? + next if not group.empty? and not group.eql?(item.group.to_s.downcase) - result.push(item) - end + host = item.host.to_s.downcase + comment = item.comment.to_s.downcase - return result - end + if not host =~ /^.*#{search}.*$/ and not comment =~ /^.*#{search}.*$/ + next + end - # Search in some csv data - # @args: id -> the id item - # @rtrn: a row with the result of the search - def search_by_id(id) - @data.each do |item| - return item if item.id == id - end + result.push(item) + end - return nil - end + return result + end - # Set an opt key - # args: id -> the item id - # key -> the new key - def set_otp_key(id, key) - if not key.to_s.empty? - @otp_keys[id] = encrypt(key.to_s) - end - end + # Search in some csv data + # @args: id -> the id item + # @rtrn: a row with the result of the search + def search_by_id(id) + @data.each do |item| + return item if item.id == id + end - # Get an opt key - # args: id -> the item id - # key -> the new key - def get_otp_key(id) - if @otp_keys.has_key?(id) - return decrypt(@otp_keys[id]) - else - return nil - end - end + return nil + end + + # Set an opt key + # args: id -> the item id + # key -> the new key + def set_otp_key(id, key) + if not key.to_s.empty? + @otp_keys[id] = encrypt(key.to_s) + end + end + + # Get an opt key + # args: id -> the item id + # key -> the new key + def get_otp_key(id) + if @otp_keys.has_key?(id) + return decrypt(@otp_keys[id]) + else + return nil + end + end - # Get an otp code - # @args: id -> the item id - # @rtrn: an otp code - def get_otp_code(id) - if not @otp_keys.has_key?(id) - return 0 - else - return ROTP::TOTP.new(decrypt(@otp_keys[id])).now - end - end + # Get an otp code + # @args: id -> the item id + # @rtrn: an otp code + def get_otp_code(id) + if not @otp_keys.has_key?(id) + return 0 + else + return ROTP::TOTP.new(decrypt(@otp_keys[id])).now + end + end - # Get remaining time before expire otp code - # @rtrn: return time in seconde - def get_otp_remaining_time - return (Time.now.utc.to_i / 30 + 1) * 30 - Time.now.utc.to_i - end + # Get remaining time before expire otp code + # @rtrn: return time in seconde + def get_otp_remaining_time + return (Time.now.utc.to_i / 30 + 1) * 30 - Time.now.utc.to_i + end - # Generate a random password - # @args: options -> :length, :special, :alpha, :numeric - # @rtrn: a random string - def self.password(options={}) - if not options.include?(:length) or options[:length].to_i <= 0 - length = 8 - elsif options[:length].to_i >= 32768 - length = 32768 - else - length = options[:length].to_i - end + # Generate a random password + # @args: options -> :length, :special, :alpha, :numeric + # @rtrn: a random string + def self.password(options={}) + if not options.include?(:length) or options[:length].to_i <= 0 + length = 8 + elsif options[:length].to_i >= 32768 + length = 32768 + else + length = options[:length].to_i + end - chars = [] - chars += [*('!'..'?')] - [*('0'..'9')] if options[:special] - chars += [*('A'..'Z'),*('a'..'z')] if options[:alpha] - chars += [*('0'..'9')] if options[:numeric] - chars = [*('A'..'Z'),*('a'..'z'),*('0'..'9')] if chars.empty? + chars = [] + chars += [*('!'..'?')] - [*('0'..'9')] if options[:special] + chars += [*('A'..'Z'),*('a'..'z')] if options[:alpha] + chars += [*('0'..'9')] if options[:numeric] + chars = [*('A'..'Z'),*('a'..'z'),*('0'..'9')] if chars.empty? - result = '' - while length > 62 do - result << chars.sample(62).join - length -= 62 - end - result << chars.sample(length).join + result = '' + while length > 62 do + result << chars.sample(62).join + length -= 62 + end + result << chars.sample(length).join - return result - end + return result + end - # Decrypt a gpg file - # @args: data -> string to decrypt - private - def decrypt(data) - return nil if data.to_s.empty? + # Decrypt a gpg file + # @args: data -> string to decrypt + private + def decrypt(data) + return nil if data.to_s.empty? - crypto = GPGME::Crypto.new(armor: true) - - return crypto.decrypt(data, password: @gpg_pass).read.force_encoding('utf-8') - rescue Exception => e - raise "#{I18n.t('error.gpg_file.decrypt')}\n#{e}" - end + crypto = GPGME::Crypto.new(armor: true) - # Encrypt a file - # args: data -> string to encrypt - private - def encrypt(data) - recipients = [] - crypto = GPGME::Crypto.new(armor: true, always_trust: true) + return crypto.decrypt(data, password: @gpg_pass).read.force_encoding('utf-8') + rescue Exception => e + raise "#{I18n.t('error.gpg_file.decrypt')}\n#{e}" + end - recipients.push(@key) - @keys.each_key do |key| - next if key == @key - recipients.push(key) - end + # Encrypt a file + # args: data -> string to encrypt + private + def encrypt(data) + recipients = [] + crypto = GPGME::Crypto.new(armor: true, always_trust: true) - return crypto.encrypt(data, recipients: recipients).read - rescue Exception => e - raise "#{I18n.t('error.gpg_file.encrypt')}\n#{e}" - end + recipients.push(@key) + @keys.each_key do |key| + next if key == @key + recipients.push(key) + end + + return crypto.encrypt(data, recipients: recipients).read + rescue Exception => e + raise "#{I18n.t('error.gpg_file.encrypt')}\n#{e}" + end end end diff --git a/test/test_config.rb b/test/test_config.rb index 143b3ed..2d1a51b 100644 --- a/test/test_config.rb +++ b/test/test_config.rb @@ -6,59 +6,59 @@ require 'locale' require 'i18n' class TestConfig < Test::Unit::TestCase - def setup - lang = Locale::Tag.parse(ENV['LANG']).to_simple.to_s[0..1] - - if defined?(I18n.enforce_available_locales) - I18n.enforce_available_locales = true - end - - I18n::Backend::Simple.send(:include, I18n::Backend::Fallbacks) - I18n.load_path = Dir["#{File.expand_path('../../i18n', __FILE__)}/*.yml"] - I18n.default_locale = :en - I18n.locale = lang.to_sym - end + def setup + lang = Locale::Tag.parse(ENV['LANG']).to_simple.to_s[0..1] - def test_00_config - data = { gpg_key: 'test@example.com', - lang: 'en', - wallet_dir: '/tmp/test', - gpg_exe: '', - } + if defined?(I18n.enforce_available_locales) + I18n.enforce_available_locales = true + end - @config = MPW::Config.new - @config.setup(data) - @config.load_config + I18n::Backend::Simple.send(:include, I18n::Backend::Fallbacks) + I18n.load_path = Dir["#{File.expand_path('../../i18n', __FILE__)}/*.yml"] + I18n.default_locale = :en + I18n.locale = lang.to_sym + end - data.each do |k,v| - assert_equal(v, @config.send(k)) - end + def test_00_config + data = { gpg_key: 'test@example.com', + lang: 'en', + wallet_dir: '/tmp/test', + gpg_exe: '', + } - @config.setup_gpg_key('password', 'test@example.com', 2048) - assert(@config.check_gpg_key?) - end + @config = MPW::Config.new + @config.setup(data) + @config.load_config - def test_01_password - data = { pwd_alpha: false, - pwd_numeric: false, - pwd_special: true, - pwd_length: 32, - } + data.each do |k,v| + assert_equal(v, @config.send(k)) + end - @config = MPW::Config.new - @config.load_config + @config.setup_gpg_key('password', 'test@example.com', 2048) + assert(@config.check_gpg_key?) + end - assert_equal(@config.password[:length], 16) - assert(@config.password[:alpha]) - assert(@config.password[:numeric]) - assert(!@config.password[:special]) + def test_01_password + data = { pwd_alpha: false, + pwd_numeric: false, + pwd_special: true, + pwd_length: 32, + } - @config.setup(data) - @config.load_config + @config = MPW::Config.new + @config.load_config - assert_equal(@config.password[:length], data[:pwd_length]) - assert(!@config.password[:alpha]) - assert(!@config.password[:numeric]) - assert(@config.password[:special]) - end + assert_equal(@config.password[:length], 16) + assert(@config.password[:alpha]) + assert(@config.password[:numeric]) + assert(!@config.password[:special]) + + @config.setup(data) + @config.load_config + + assert_equal(@config.password[:length], data[:pwd_length]) + assert(!@config.password[:alpha]) + assert(!@config.password[:numeric]) + assert(@config.password[:special]) + end end diff --git a/test/test_item.rb b/test/test_item.rb index b9f5961..751e1b0 100644 --- a/test/test_item.rb +++ b/test/test_item.rb @@ -1,172 +1,172 @@ #!/usr/bin/ruby - + require 'mpw/item' require 'test/unit' require 'yaml' - + class TestItem < Test::Unit::TestCase - def setup - @fixture_file = 'test/files/fixtures.yml' - @fixtures = YAML.load_file(@fixture_file) - - if defined?(I18n.enforce_available_locales) - I18n.enforce_available_locales = false - end + def setup + @fixture_file = 'test/files/fixtures.yml' + @fixtures = YAML.load_file(@fixture_file) - I18n.load_path = Dir['./i18n/cli/*.yml'] - I18n.default_locale = :en + if defined?(I18n.enforce_available_locales) + I18n.enforce_available_locales = false + end + + I18n.load_path = Dir['./i18n/cli/*.yml'] + I18n.default_locale = :en - puts - end + puts + end - def test_00_add_without_name - assert_raise(RuntimeError){MPW::Item.new} - end + def test_00_add_without_name + assert_raise(RuntimeError){MPW::Item.new} + end - def test_01_add_new - data = { group: @fixtures['add_new']['group'], - host: @fixtures['add_new']['host'], - protocol: @fixtures['add_new']['protocol'], - user: @fixtures['add_new']['user'], - port: @fixtures['add_new']['port'], - comment: @fixtures['add_new']['comment'], - } - - item = MPW::Item.new(data) + def test_01_add_new + data = { group: @fixtures['add_new']['group'], + host: @fixtures['add_new']['host'], + protocol: @fixtures['add_new']['protocol'], + user: @fixtures['add_new']['user'], + port: @fixtures['add_new']['port'], + comment: @fixtures['add_new']['comment'], + } - assert(!item.nil?) - assert(!item.empty?) + item = MPW::Item.new(data) - assert_equal(@fixtures['add_new']['group'], item.group) - assert_equal(@fixtures['add_new']['host'], item.host) - assert_equal(@fixtures['add_new']['protocol'], item.protocol) - assert_equal(@fixtures['add_new']['user'], item.user) - assert_equal(@fixtures['add_new']['port'].to_i, item.port) - assert_equal(@fixtures['add_new']['comment'], item.comment) - end + assert(!item.nil?) + assert(!item.empty?) - def test_02_add_existing - data = { id: @fixtures['add_existing']['id'], - group: @fixtures['add_existing']['group'], - host: @fixtures['add_existing']['host'], - protocol: @fixtures['add_existing']['protocol'], - user: @fixtures['add_existing']['user'], - port: @fixtures['add_existing']['port'], - comment: @fixtures['add_existing']['comment'], - created: @fixtures['add_existing']['created'], - } + assert_equal(@fixtures['add_new']['group'], item.group) + assert_equal(@fixtures['add_new']['host'], item.host) + assert_equal(@fixtures['add_new']['protocol'], item.protocol) + assert_equal(@fixtures['add_new']['user'], item.user) + assert_equal(@fixtures['add_new']['port'].to_i, item.port) + assert_equal(@fixtures['add_new']['comment'], item.comment) + end - item = MPW::Item.new(data) + def test_02_add_existing + data = { id: @fixtures['add_existing']['id'], + group: @fixtures['add_existing']['group'], + host: @fixtures['add_existing']['host'], + protocol: @fixtures['add_existing']['protocol'], + user: @fixtures['add_existing']['user'], + port: @fixtures['add_existing']['port'], + comment: @fixtures['add_existing']['comment'], + created: @fixtures['add_existing']['created'], + } - assert(!item.nil?) - assert(!item.empty?) + item = MPW::Item.new(data) - assert_equal(@fixtures['add_existing']['id'], item.id) - assert_equal(@fixtures['add_existing']['group'], item.group) - assert_equal(@fixtures['add_existing']['host'], item.host) - assert_equal(@fixtures['add_existing']['protocol'], item.protocol) - assert_equal(@fixtures['add_existing']['user'], item.user) - assert_equal(@fixtures['add_existing']['port'].to_i, item.port) - assert_equal(@fixtures['add_existing']['comment'], item.comment) - assert_equal(@fixtures['add_existing']['created'], item.created) - end + assert(!item.nil?) + assert(!item.empty?) - def test_03_update - data = { group: @fixtures['add_new']['group'], - host: @fixtures['add_new']['host'], - protocol: @fixtures['add_new']['protocol'], - user: @fixtures['add_new']['user'], - port: @fixtures['add_new']['port'], - comment: @fixtures['add_new']['comment'], - } - - item = MPW::Item.new(data) + assert_equal(@fixtures['add_existing']['id'], item.id) + assert_equal(@fixtures['add_existing']['group'], item.group) + assert_equal(@fixtures['add_existing']['host'], item.host) + assert_equal(@fixtures['add_existing']['protocol'], item.protocol) + assert_equal(@fixtures['add_existing']['user'], item.user) + assert_equal(@fixtures['add_existing']['port'].to_i, item.port) + assert_equal(@fixtures['add_existing']['comment'], item.comment) + assert_equal(@fixtures['add_existing']['created'], item.created) + end - assert(!item.nil?) - assert(!item.empty?) + def test_03_update + data = { group: @fixtures['add_new']['group'], + host: @fixtures['add_new']['host'], + protocol: @fixtures['add_new']['protocol'], + user: @fixtures['add_new']['user'], + port: @fixtures['add_new']['port'], + comment: @fixtures['add_new']['comment'], + } - created = item.created - last_edit = item.last_edit + item = MPW::Item.new(data) - data = { group: @fixtures['update']['group'], - host: @fixtures['update']['host'], - protocol: @fixtures['update']['protocol'], - user: @fixtures['update']['user'], - port: @fixtures['update']['port'], - comment: @fixtures['update']['comment'], - } - - sleep(1) - assert(item.update(data)) + assert(!item.nil?) + assert(!item.empty?) - assert(!item.empty?) + created = item.created + last_edit = item.last_edit - assert_equal(@fixtures['update']['group'], item.group) - assert_equal(@fixtures['update']['host'], item.host) - assert_equal(@fixtures['update']['protocol'], item.protocol) - assert_equal(@fixtures['update']['user'], item.user) - assert_equal(@fixtures['update']['port'].to_i, item.port) - assert_equal(@fixtures['update']['comment'], item.comment) + data = { group: @fixtures['update']['group'], + host: @fixtures['update']['host'], + protocol: @fixtures['update']['protocol'], + user: @fixtures['update']['user'], + port: @fixtures['update']['port'], + comment: @fixtures['update']['comment'], + } - assert_equal(created, item.created) - assert_not_equal(last_edit, item.last_edit) - end + sleep(1) + assert(item.update(data)) - def test_05_update_one_element - data = { group: @fixtures['add_new']['group'], - host: @fixtures['add_new']['host'], - protocol: @fixtures['add_new']['protocol'], - user: @fixtures['add_new']['user'], - port: @fixtures['add_new']['port'], - comment: @fixtures['add_new']['comment'], - } - - item = MPW::Item.new(data) + assert(!item.empty?) - assert(!item.nil?) - assert(!item.empty?) + assert_equal(@fixtures['update']['group'], item.group) + assert_equal(@fixtures['update']['host'], item.host) + assert_equal(@fixtures['update']['protocol'], item.protocol) + assert_equal(@fixtures['update']['user'], item.user) + assert_equal(@fixtures['update']['port'].to_i, item.port) + assert_equal(@fixtures['update']['comment'], item.comment) - last_edit = item.last_edit + assert_equal(created, item.created) + assert_not_equal(last_edit, item.last_edit) + end - sleep(1) - assert(item.update({comment: @fixtures['update']['comment']})) + def test_05_update_one_element + data = { group: @fixtures['add_new']['group'], + host: @fixtures['add_new']['host'], + protocol: @fixtures['add_new']['protocol'], + user: @fixtures['add_new']['user'], + port: @fixtures['add_new']['port'], + comment: @fixtures['add_new']['comment'], + } - assert_equal(@fixtures['add_new']['group'], item.group) - assert_equal(@fixtures['add_new']['host'], item.host) - assert_equal(@fixtures['add_new']['protocol'], item.protocol) - assert_equal(@fixtures['add_new']['user'], item.user) - assert_equal(@fixtures['add_new']['port'].to_i, item.port) - assert_equal(@fixtures['update']['comment'], item.comment) - - assert_not_equal(last_edit, item.last_edit) - end + item = MPW::Item.new(data) - def test_05_delete - data = { group: @fixtures['add_new']['group'], - host: @fixtures['add_new']['host'], - protocol: @fixtures['add_new']['protocol'], - user: @fixtures['add_new']['user'], - port: @fixtures['add_new']['port'], - comment: @fixtures['add_new']['comment'], - } - - item = MPW::Item.new(data) + assert(!item.nil?) + assert(!item.empty?) - assert(!item.nil?) - assert(!item.empty?) + last_edit = item.last_edit - item.delete - assert(!item.nil?) - assert(item.empty?) + sleep(1) + assert(item.update({comment: @fixtures['update']['comment']})) - assert_equal(nil, item.id) - assert_equal(nil, item.group) - assert_equal(nil, item.host) - assert_equal(nil, item.protocol) - assert_equal(nil, item.user) - assert_equal(nil, item.port) - assert_equal(nil, item.comment) - assert_equal(nil, item.created) - end -end + assert_equal(@fixtures['add_new']['group'], item.group) + assert_equal(@fixtures['add_new']['host'], item.host) + assert_equal(@fixtures['add_new']['protocol'], item.protocol) + assert_equal(@fixtures['add_new']['user'], item.user) + assert_equal(@fixtures['add_new']['port'].to_i, item.port) + assert_equal(@fixtures['update']['comment'], item.comment) + + assert_not_equal(last_edit, item.last_edit) + end + + def test_05_delete + data = { group: @fixtures['add_new']['group'], + host: @fixtures['add_new']['host'], + protocol: @fixtures['add_new']['protocol'], + user: @fixtures['add_new']['user'], + port: @fixtures['add_new']['port'], + comment: @fixtures['add_new']['comment'], + } + + item = MPW::Item.new(data) + + assert(!item.nil?) + assert(!item.empty?) + + item.delete + assert(!item.nil?) + assert(item.empty?) + + assert_equal(nil, item.id) + assert_equal(nil, item.group) + assert_equal(nil, item.host) + assert_equal(nil, item.protocol) + assert_equal(nil, item.user) + assert_equal(nil, item.port) + assert_equal(nil, item.comment) + assert_equal(nil, item.created) + end +end diff --git a/test/test_mpw.rb b/test/test_mpw.rb index c4748f6..30c9028 100644 --- a/test/test_mpw.rb +++ b/test/test_mpw.rb @@ -1,140 +1,140 @@ #!/usr/bin/ruby - + require 'mpw/mpw' require 'mpw/item' require 'test/unit' require 'yaml' require 'csv' - + class TestMPW < Test::Unit::TestCase - def setup - fixture_file = './test/files/fixtures.yml' + def setup + fixture_file = './test/files/fixtures.yml' - wallet_file = 'default.gpg' - key = 'test@example.com' - password = 'password' + wallet_file = 'default.gpg' + key = 'test@example.com' + password = 'password' - if defined?(I18n.enforce_available_locales) - I18n.enforce_available_locales = false - end + if defined?(I18n.enforce_available_locales) + I18n.enforce_available_locales = false + end - @mpw = MPW::MPW.new(key, wallet_file, password) - @fixtures = YAML.load_file(fixture_file) - end - - def test_00_decrypt_empty_file - @mpw.read_data - assert_equal(0, @mpw.list.length) - end + @mpw = MPW::MPW.new(key, wallet_file, password) + @fixtures = YAML.load_file(fixture_file) + end - def test_01_encrypt_empty_file - @mpw.read_data - @mpw.write_data - end + def test_00_decrypt_empty_file + @mpw.read_data + assert_equal(0, @mpw.list.length) + end - def test_02_add_item - data = { group: @fixtures['add_new']['group'], - host: @fixtures['add_new']['host'], - protocol: @fixtures['add_new']['protocol'], - user: @fixtures['add_new']['user'], - port: @fixtures['add_new']['port'], - comment: @fixtures['add_new']['comment'], - } - - item = MPW::Item.new(data) + def test_01_encrypt_empty_file + @mpw.read_data + @mpw.write_data + end - assert(!item.nil?) - assert(!item.empty?) + def test_02_add_item + data = { group: @fixtures['add_new']['group'], + host: @fixtures['add_new']['host'], + protocol: @fixtures['add_new']['protocol'], + user: @fixtures['add_new']['user'], + port: @fixtures['add_new']['port'], + comment: @fixtures['add_new']['comment'], + } - @mpw.read_data - @mpw.add(item) - @mpw.set_password(item.id, @fixtures['add_new']['password']) + item = MPW::Item.new(data) - assert_equal(1, @mpw.list.length) + assert(!item.nil?) + assert(!item.empty?) - item = @mpw.list[0] - @fixtures['add_new'].each do |k,v| - if k == 'password' - assert_equal(v, @mpw.get_password(item.id)) - else - assert_equal(v, item.send(k).to_s) - end - end + @mpw.read_data + @mpw.add(item) + @mpw.set_password(item.id, @fixtures['add_new']['password']) - @mpw.write_data - end + assert_equal(1, @mpw.list.length) - def test_03_decrypt_file - @mpw.read_data - assert_equal(1, @mpw.list.length) + item = @mpw.list[0] + @fixtures['add_new'].each do |k,v| + if k == 'password' + assert_equal(v, @mpw.get_password(item.id)) + else + assert_equal(v, item.send(k).to_s) + end + end - item = @mpw.list[0] - @fixtures['add_new'].each do |k,v| - if k == 'password' - assert_equal(v, @mpw.get_password(item.id)) - else - assert_equal(v, item.send(k).to_s) - end - end - end + @mpw.write_data + end - def test_04_delete_item - @mpw.read_data + def test_03_decrypt_file + @mpw.read_data + assert_equal(1, @mpw.list.length) - assert_equal(1, @mpw.list.length) + item = @mpw.list[0] + @fixtures['add_new'].each do |k,v| + if k == 'password' + assert_equal(v, @mpw.get_password(item.id)) + else + assert_equal(v, item.send(k).to_s) + end + end + end - @mpw.list.each do |item| - item.delete - end + def test_04_delete_item + @mpw.read_data - assert_equal(0, @mpw.list.length) + assert_equal(1, @mpw.list.length) - @mpw.write_data - end + @mpw.list.each do |item| + item.delete + end - def test_05_search - @mpw.read_data + assert_equal(0, @mpw.list.length) - @fixtures.each_value do |v| - data = { group: v['group'], - host: v['host'], - protocol: v['protocol'], - user: v['user'], - port: v['port'], - comment: v['comment'], - } - - item = MPW::Item.new(data) - - assert(!item.nil?) - assert(!item.empty?) - - @mpw.add(item) - @mpw.set_password(item.id, v['password']) - end + @mpw.write_data + end - assert_equal(3, @mpw.list.length) - assert_equal(1, @mpw.list(group: @fixtures['add_new']['group']).length) - assert_equal(1, @mpw.list(pattern: 'existing').length) - assert_equal(2, @mpw.list(pattern: 'host_[eu]').length) - end + def test_05_search + @mpw.read_data - def test_06_add_gpg_key - @mpw.read_data + @fixtures.each_value do |v| + data = { group: v['group'], + host: v['host'], + protocol: v['protocol'], + user: v['user'], + port: v['port'], + comment: v['comment'], + } - @mpw.add_key('test2@example.com') - assert_equal(2, @mpw.list_keys.length) + item = MPW::Item.new(data) - @mpw.write_data - end + assert(!item.nil?) + assert(!item.empty?) - def test_07_delete_gpg_key - @mpw.read_data - assert_equal(2, @mpw.list_keys.length) + @mpw.add(item) + @mpw.set_password(item.id, v['password']) + end - @mpw.delete_key('test2@example.com') - assert_equal(1, @mpw.list_keys.length) + assert_equal(3, @mpw.list.length) + assert_equal(1, @mpw.list(group: @fixtures['add_new']['group']).length) + assert_equal(1, @mpw.list(pattern: 'existing').length) + assert_equal(2, @mpw.list(pattern: 'host_[eu]').length) + end - @mpw.write_data - end + def test_06_add_gpg_key + @mpw.read_data + + @mpw.add_key('test2@example.com') + assert_equal(2, @mpw.list_keys.length) + + @mpw.write_data + end + + def test_07_delete_gpg_key + @mpw.read_data + assert_equal(2, @mpw.list_keys.length) + + @mpw.delete_key('test2@example.com') + assert_equal(1, @mpw.list_keys.length) + + @mpw.write_data + end end diff --git a/test/test_translate.rb b/test/test_translate.rb index 55f09df..6334a78 100644 --- a/test/test_translate.rb +++ b/test/test_translate.rb @@ -4,28 +4,28 @@ require 'yaml' require 'test/unit' class TestTranslate < Test::Unit::TestCase - def test_00_check_translate - missing = 0 - - Dir.glob('i18n/*.yml').each do |yaml| - lang = File.basename(yaml, '.yml') - translate = YAML.load_file(yaml) - - `grep -r -o "I18n.t('.*)" bin/ lib/ | cut -d"'" -f2`.each_line do |line| - begin - t = translate[lang] - line.strip.split('.').each do |v| - t = t[v] - end + def test_00_check_translate + missing = 0 - assert(!t.to_s.empty?) - rescue - puts "#{lang}.#{line}" - missing = 1 - end - end - end - - assert_equal(0, missing) - end + Dir.glob('i18n/*.yml').each do |yaml| + lang = File.basename(yaml, '.yml') + translate = YAML.load_file(yaml) + + `grep -r -o "I18n.t('.*)" bin/ lib/ | cut -d"'" -f2`.each_line do |line| + begin + t = translate[lang] + line.strip.split('.').each do |v| + t = t[v] + end + + assert(!t.to_s.empty?) + rescue + puts "#{lang}.#{line}" + missing = 1 + end + end + end + + assert_equal(0, missing) + end end diff --git a/test/tests.rb b/test/tests.rb index 904f64e..7f3fc7d 100644 --- a/test/tests.rb +++ b/test/tests.rb @@ -1,5 +1,5 @@ #!/usr/bin/ruby - + require_relative 'init.rb' require_relative 'test_config.rb' require_relative 'test_item.rb' From 178d0e6d1d3d32ad765fc4203cf1ee2e5575024f Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Mon, 27 Mar 2017 22:31:05 +0200 Subject: [PATCH 423/531] replace if not by unless --- bin/mpw-wallet | 2 +- lib/mpw/cli.rb | 12 +++++------- lib/mpw/config.rb | 2 +- lib/mpw/item.rb | 2 +- lib/mpw/mpw.rb | 18 +++++++----------- templates/add_form.erb | 2 +- templates/update_form.erb | 2 +- 7 files changed, 17 insertions(+), 23 deletions(-) diff --git a/bin/mpw-wallet b/bin/mpw-wallet index e575c0d..bcc3fc2 100644 --- a/bin/mpw-wallet +++ b/bin/mpw-wallet @@ -66,7 +66,7 @@ cli = MPW::Cli.new(config) cli.load_config -if not options[:list].nil? +if !options[:list].nil? cli.list_wallet else cli.get_wallet(options[:wallet]) diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index 83b9af3..9571fec 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -103,7 +103,7 @@ class Cli # Request the GPG password and decrypt the file def decrypt - if not defined?(@mpw) + unless defined?(@mpw) @password = ask(I18n.t('display.gpg_password')) {|q| q.echo = false} @mpw = MPW.new(@config.gpg_key, @wallet_file, @password, @config.gpg_exe) end @@ -451,9 +451,7 @@ class Cli item = get_item(items) confirm = ask("#{I18n.t('form.delete_item.ask')} (y/N) ").to_s - if not confirm =~ /^(y|yes|YES|Yes|Y)$/ - return false - end + return false unless confirm =~ /^(y|yes|YES|Yes|Y)$/ item.delete @mpw.write_data @@ -516,7 +514,7 @@ class Cli # @args: file -> the import file def import(file) raise I18n.t('form.import.file_empty') if file.to_s.empty? - raise I18n.t('form.import.file_not_exist') if not File.exist?(file) + raise I18n.t('form.import.file_not_exist') unless File.exist?(file) YAML::load_file(file).each_value do |row| item = Item.new(group: row['group'], @@ -530,8 +528,8 @@ class Cli next if item.empty? @mpw.add(item) - @mpw.set_password(item.id, row['password']) if not row['password'].to_s.empty? - @mpw.set_otp_key(item.id, row['otp_key']) if not row['otp_key'].to_s.empty? + @mpw.set_password(item.id, row['password']) unless row['password'].to_s.empty? + @mpw.set_otp_key(item.id, row['otp_key']) unless row['otp_key'].to_s.empty? end @mpw.write_data diff --git a/lib/mpw/config.rb b/lib/mpw/config.rb index 298ba61..8ec8e3a 100644 --- a/lib/mpw/config.rb +++ b/lib/mpw/config.rb @@ -73,7 +73,7 @@ class Config end end - if not gpg_key =~ /[a-zA-Z0-9.-_]+\@[a-zA-Z0-9]+\.[a-zA-Z]+/ + unless gpg_key =~ /[a-zA-Z0-9.-_]+\@[a-zA-Z0-9]+\.[a-zA-Z]+/ raise I18n.t('error.config.key_bad_format') end diff --git a/lib/mpw/item.rb b/lib/mpw/item.rb index 469af15..7c2547e 100644 --- a/lib/mpw/item.rb +++ b/lib/mpw/item.rb @@ -68,7 +68,7 @@ class Item @port = options[:port].to_i if options.has_key?(:port) and not options[:port].to_s.empty? @otp = options[:otp] if options.has_key?(:otp) @comment = options[:comment] if options.has_key?(:comment) - @last_edit = Time.now.to_i if not options.has_key?(:no_update_last_edit) + @last_edit = Time.now.to_i unless options.has_key?(:no_update_last_edit) end # Delete all data diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index 9147648..bb4e38b 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -33,7 +33,7 @@ class MPW @gpg_exe = gpg_exe @wallet_file = wallet_file - if not @gpg_exe.to_s.empty? + unless @gpg_exe.to_s.empty? GPGME::Engine.set_info(GPGME::PROTOCOL_OpenPGP, @gpg_exe, "#{Dir.home}/.gnupg") end end @@ -48,7 +48,7 @@ class MPW data = nil - return if not File.exists?(@wallet_file) + return unless File.exists?(@wallet_file) Gem::Package::TarReader.new(File.open(@wallet_file)) do |tar| tar.each do |f| @@ -80,7 +80,7 @@ class MPW end end - if not data.nil? and not data.empty? + unless data.to_s.empty? YAML.load(data).each_value do |d| @data.push(Item.new(id: d['id'], group: d['group'], @@ -254,14 +254,12 @@ class MPW @data.each do |item| next if item.empty? - next if not group.empty? and not group.eql?(item.group.to_s.downcase) + next unless group.empty? or group.eql?(item.group.to_s.downcase) host = item.host.to_s.downcase comment = item.comment.to_s.downcase - if not host =~ /^.*#{search}.*$/ and not comment =~ /^.*#{search}.*$/ - next - end + next unless host =~ /^.*#{search}.*$/ or comment =~ /^.*#{search}.*$/ result.push(item) end @@ -284,9 +282,7 @@ class MPW # args: id -> the item id # key -> the new key def set_otp_key(id, key) - if not key.to_s.empty? - @otp_keys[id] = encrypt(key.to_s) - end + @otp_keys[id] = encrypt(key.to_s) unless key.to_s.empty? end # Get an opt key @@ -305,7 +301,7 @@ class MPW # @args: id -> the item id # @rtrn: an otp code def get_otp_code(id) - if not @otp_keys.has_key?(id) + unless @otp_keys.has_key?(id) return 0 else return ROTP::TOTP.new(decrypt(@otp_keys[id])).now diff --git a/templates/add_form.erb b/templates/add_form.erb index c2d6d73..bb81787 100644 --- a/templates/add_form.erb +++ b/templates/add_form.erb @@ -2,7 +2,7 @@ host: # <%= I18n.t('form.add_item.host') %> user: # <%= I18n.t('form.add_item.login') %> group: # <%= I18n.t('form.add_item.group') %> -protocol: # <%= I18n.t('form.add_item.protocol') %><% if not password %> +protocol: # <%= I18n.t('form.add_item.protocol') %><% unless password %> password: # <%= I18n.t('form.add_item.password') %><% end %> port: # <%= I18n.t('form.add_item.port') %> comment: # <%= I18n.t('form.add_item.comment') %> diff --git a/templates/update_form.erb b/templates/update_form.erb index e5363f8..f27da0b 100644 --- a/templates/update_form.erb +++ b/templates/update_form.erb @@ -2,7 +2,7 @@ # <%= I18n.t('form.update_item.host') %> host: <%= item.host %> # <%= I18n.t('form.update_item.login') %> -user: <%= item.user %><% if not password %> +user: <%= item.user %><% unless password %> # <%= I18n.t('form.update_item.password') %> password: <% end %> # <%= I18n.t('form.update_item.group') %> From e71f8e2acf36e74c81ba624405fd29ab94da06e2 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Wed, 29 Mar 2017 22:49:46 +0200 Subject: [PATCH 424/531] replace if not by unless --- lib/mpw/mpw.rb | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index bb4e38b..724dcaf 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -234,13 +234,10 @@ class MPW # Add a new item # @args: item -> Object MPW::Item def add(item) - if not item.instance_of?(Item) - raise I18n.t('error.bad_class') - elsif item.empty? - raise I18n.t('error.empty') - else - @data.push(item) - end + raise I18n.t('error.bad_class') unless item.instance_of?(Item) + raise I18n.t('error.empty') if item.empty? + + return @data.push(item) end # Search in some csv data From 8ed90c2ddc7de2eac70d36c528869edd8cb846d5 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Wed, 29 Mar 2017 22:50:47 +0200 Subject: [PATCH 425/531] fix --- bin/mpw-wallet | 4 ++-- lib/mpw/cli.rb | 6 +++--- lib/mpw/config.rb | 6 +++--- lib/mpw/item.rb | 8 ++++---- lib/mpw/mpw.rb | 8 ++++---- 5 files changed, 16 insertions(+), 16 deletions(-) diff --git a/bin/mpw-wallet b/bin/mpw-wallet index bcc3fc2..fffeaac 100644 --- a/bin/mpw-wallet +++ b/bin/mpw-wallet @@ -72,9 +72,9 @@ else cli.get_wallet(options[:wallet]) cli.decrypt - if not options[:list_keys].nil? + if !options[:list_keys].nil? cli.list_keys - elsif not options[:gpg_key].nil? + elsif !options[:gpg_key].nil? if options[:delete] cli.delete_key(options[:gpg_key]) else diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index 9571fec..6b56c63 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -155,7 +155,7 @@ class Cli items.each do |item| data.each do |k, v| - next if k == :id or k == :otp + next if k == :id || k == :otp v[:length] = item.send(k.to_s).to_s.length + 3 if item.send(k.to_s).to_s.length >= v[:length] end @@ -240,7 +240,7 @@ class Cli items.sort! { |a,b| a.group.to_s.downcase <=> b.group.to_s.downcase } choice = ask(I18n.t('form.select')).to_i - if choice >= 1 and choice <= items.length + if choice >= 1 && choice <= items.length return items[choice-1] else return nil @@ -331,7 +331,7 @@ class Cli if wallets.length == 1 @wallet_file = wallets[0] - elsif not @config.default_wallet.to_s.empty? + elsif !@config.default_wallet.to_s.empty? @wallet_file = "#{@config.wallet_dir}/#{@config.default_wallet}.mpw" else @wallet_file = "#{@config.wallet_dir}/default.mpw" diff --git a/lib/mpw/config.rb b/lib/mpw/config.rb index 8ec8e3a..cd584b1 100644 --- a/lib/mpw/config.rb +++ b/lib/mpw/config.rb @@ -47,7 +47,7 @@ class Config @config_dir = "#{Dir.home}/.config/mpw" end - @config_file = "#{@config_dir}/mpw.cfg" if @config_file.nil? or @config_file.empty? + @config_file = "#{@config_dir}/mpw.cfg" if @config_file.nil? || @config_file.empty? end # Create a new config file @@ -68,7 +68,7 @@ class Config ['numeric', 'special', 'alpha', 'length'].each do |k| if options.has_key?("pwd_#{k}".to_sym) password[k.to_sym] = options["pwd_#{k}".to_sym] - elsif not @password.nil? and @password.has_key?(k.to_sym) + elsif !@password.nil? && @password.has_key?(k.to_sym) password[k.to_sym] = @password[k.to_sym] end end @@ -138,7 +138,7 @@ class Config @gpg_exe = config['gpg_exe'] @password = config['password'] || {} - raise if @gpg_key.empty? or @wallet_dir.empty? + raise if @gpg_key.empty? || @wallet_dir.empty? I18n.locale = @lang.to_sym rescue Exception => e diff --git a/lib/mpw/item.rb b/lib/mpw/item.rb index 7c2547e..c0ca11e 100644 --- a/lib/mpw/item.rb +++ b/lib/mpw/item.rb @@ -37,11 +37,11 @@ class Item # @args: options -> a hash of parameter # raise an error if the hash hasn't the key name def initialize(options={}) - if not options.has_key?(:host) or options[:host].to_s.empty? + if !options.has_key?(:host) || options[:host].to_s.empty? raise I18n.t('error.update.host_empty') end - if not options.has_key?(:id) or options[:id].to_s.empty? or not options.has_key?(:created) or options[:created].to_s.empty? + if !options.has_key?(:id) || options[:id].to_s.empty? || !options.has_key?(:created) || options[:created].to_s.empty? @id = generate_id @created = Time.now.to_i else @@ -57,7 +57,7 @@ class Item # Update the item # @args: options -> a hash of parameter def update(options={}) - if options.has_key?(:host) and options[:host].to_s.empty? + if options.has_key?(:host) && options[:host].to_s.empty? raise I18n.t('error.update.host_empty') end @@ -65,7 +65,7 @@ class Item @host = options[:host] if options.has_key?(:host) @protocol = options[:protocol] if options.has_key?(:protocol) @user = options[:user] if options.has_key?(:user) - @port = options[:port].to_i if options.has_key?(:port) and not options[:port].to_s.empty? + @port = options[:port].to_i if options.has_key?(:port) && !options[:port].to_s.empty? @otp = options[:otp] if options.has_key?(:otp) @comment = options[:comment] if options.has_key?(:comment) @last_edit = Time.now.to_i unless options.has_key?(:no_update_last_edit) diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index 724dcaf..183b888 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -237,7 +237,7 @@ class MPW raise I18n.t('error.bad_class') unless item.instance_of?(Item) raise I18n.t('error.empty') if item.empty? - return @data.push(item) + @data.push(item) end # Search in some csv data @@ -251,12 +251,12 @@ class MPW @data.each do |item| next if item.empty? - next unless group.empty? or group.eql?(item.group.to_s.downcase) + next unless group.empty? || group.eql?(item.group.to_s.downcase) host = item.host.to_s.downcase comment = item.comment.to_s.downcase - next unless host =~ /^.*#{search}.*$/ or comment =~ /^.*#{search}.*$/ + next unless host =~ /^.*#{search}.*$/ || comment =~ /^.*#{search}.*$/ result.push(item) end @@ -315,7 +315,7 @@ class MPW # @args: options -> :length, :special, :alpha, :numeric # @rtrn: a random string def self.password(options={}) - if not options.include?(:length) or options[:length].to_i <= 0 + if !options.include?(:length) || options[:length].to_i <= 0 length = 8 elsif options[:length].to_i >= 32768 length = 32768 From e7fff4bb87aa97ffac32d9ee5eac50aec813bc7b Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Tue, 28 Mar 2017 22:17:52 +0200 Subject: [PATCH 426/531] remove return if useless --- lib/mpw/cli.rb | 10 +++------- lib/mpw/config.rb | 2 +- lib/mpw/item.rb | 6 +++--- lib/mpw/mpw.rb | 32 +++++++++++--------------------- 4 files changed, 18 insertions(+), 32 deletions(-) diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index 6b56c63..ecd98e3 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -240,11 +240,7 @@ class Cli items.sort! { |a,b| a.group.to_s.downcase <=> b.group.to_s.downcase } choice = ask(I18n.t('form.select')).to_i - if choice >= 1 && choice <= items.length - return items[choice-1] - else - return nil - end + choice >= 1 && choice <= items.length ? items[choice-1] : nil end # Copy in clipboard the login and password @@ -392,7 +388,7 @@ class Cli options[k.to_sym] = v end - return options + options end # Form to add a new item @@ -451,7 +447,7 @@ class Cli item = get_item(items) confirm = ask("#{I18n.t('form.delete_item.ask')} (y/N) ").to_s - return false unless confirm =~ /^(y|yes|YES|Yes|Y)$/ + return unless confirm =~ /^(y|yes|YES|Yes|Y)$/ item.delete @mpw.write_data diff --git a/lib/mpw/config.rb b/lib/mpw/config.rb index cd584b1..b23842e 100644 --- a/lib/mpw/config.rb +++ b/lib/mpw/config.rb @@ -153,7 +153,7 @@ class Config return true end - return false + false end end end diff --git a/lib/mpw/item.rb b/lib/mpw/item.rb index c0ca11e..bd1445b 100644 --- a/lib/mpw/item.rb +++ b/lib/mpw/item.rb @@ -86,17 +86,17 @@ class Item end def empty? - return @id.to_s.empty? + @id.to_s.empty? end def nil? - return false + false end # Generate an random id private def generate_id - return ([*('A'..'Z'),*('a'..'z'),*('0'..'9')]).sample(16).join + ([*('A'..'Z'),*('a'..'z'),*('0'..'9')]).sample(16).join end end end diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index 183b888..de99440 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -168,9 +168,9 @@ class MPW password = decrypt(@passwords[id]) if /^\$[a-zA-Z0-9]{4,9}::(?<password>.+)$/ =~ password - return Regexp.last_match('password') + Regexp.last_match('password') else - return password + password end end @@ -187,7 +187,7 @@ class MPW # Return the list of all gpg keys # rtrn: an array with the gpg keys name def list_keys - return @keys.keys + @keys.keys end # Add a public key @@ -261,7 +261,7 @@ class MPW result.push(item) end - return result + result end # Search in some csv data @@ -272,7 +272,7 @@ class MPW return item if item.id == id end - return nil + nil end # Set an opt key @@ -286,29 +286,20 @@ class MPW # args: id -> the item id # key -> the new key def get_otp_key(id) - if @otp_keys.has_key?(id) - return decrypt(@otp_keys[id]) - else - return nil - end + @otp_keys.has_key?(id) ? decrypt(@otp_keys[id]) : nil end - # Get an otp code # @args: id -> the item id # @rtrn: an otp code def get_otp_code(id) - unless @otp_keys.has_key?(id) - return 0 - else - return ROTP::TOTP.new(decrypt(@otp_keys[id])).now - end + @otp_keys.has_key?(id) ? 0 : ROTP::TOTP.new(decrypt(@otp_keys[id])).now end # Get remaining time before expire otp code # @rtrn: return time in seconde def get_otp_remaining_time - return (Time.now.utc.to_i / 30 + 1) * 30 - Time.now.utc.to_i + (Time.now.utc.to_i / 30 + 1) * 30 - Time.now.utc.to_i end # Generate a random password @@ -336,7 +327,7 @@ class MPW end result << chars.sample(length).join - return result + result end # Decrypt a gpg file @@ -347,7 +338,7 @@ class MPW crypto = GPGME::Crypto.new(armor: true) - return crypto.decrypt(data, password: @gpg_pass).read.force_encoding('utf-8') + crypto.decrypt(data, password: @gpg_pass).read.force_encoding('utf-8') rescue Exception => e raise "#{I18n.t('error.gpg_file.decrypt')}\n#{e}" end @@ -365,10 +356,9 @@ class MPW recipients.push(key) end - return crypto.encrypt(data, recipients: recipients).read + crypto.encrypt(data, recipients: recipients).read rescue Exception => e raise "#{I18n.t('error.gpg_file.encrypt')}\n#{e}" end - end end From 31aba3b13c4a9d87cbfad1fee8aa16abdec4c0d9 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Tue, 28 Mar 2017 22:22:09 +0200 Subject: [PATCH 427/531] replace hash method has_key? by key? --- bin/mpw-config | 2 +- lib/mpw/cli.rb | 8 ++++---- lib/mpw/config.rb | 4 ++-- lib/mpw/item.rb | 22 +++++++++++----------- lib/mpw/mpw.rb | 18 +++++++++--------- 5 files changed, 27 insertions(+), 27 deletions(-) diff --git a/bin/mpw-config b/bin/mpw-config index 14387d9..4740ed1 100644 --- a/bin/mpw-config +++ b/bin/mpw-config @@ -96,7 +96,7 @@ end.parse! config = MPW::Config.new(options[:config]) cli = MPW::Cli.new(config, nil) -if options.has_key?(:init) +if options.key?(:init) cli.setup(values) cli.load_config cli.get_wallet diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index ecd98e3..90f7665 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -399,8 +399,8 @@ class Cli options[:password] = MPW::password(@config.password) if password @mpw.add(item) - @mpw.set_password(item.id, options[:password]) if options.has_key?(:password) - @mpw.set_otp_key(item.id, options[:otp_key]) if options.has_key?(:otp_key) + @mpw.set_password(item.id, options[:password]) if options.key?(:password) + @mpw.set_otp_key(item.id, options[:otp_key]) if options.key?(:otp_key) @mpw.write_data puts "#{I18n.t('form.add_item.valid')}".green @@ -424,8 +424,8 @@ class Cli options[:password] = MPW::password(@config.password) if password item.update(options) - @mpw.set_password(item.id, options[:password]) if options.has_key?(:password) - @mpw.set_otp_key(item.id, options[:otp_key]) if options.has_key?(:otp_key) + @mpw.set_password(item.id, options[:password]) if options.key?(:password) + @mpw.set_otp_key(item.id, options[:otp_key]) if options.key?(:otp_key) @mpw.write_data puts "#{I18n.t('form.update_item.valid')}".green diff --git a/lib/mpw/config.rb b/lib/mpw/config.rb index b23842e..b7cf5e8 100644 --- a/lib/mpw/config.rb +++ b/lib/mpw/config.rb @@ -66,9 +66,9 @@ class Config } ['numeric', 'special', 'alpha', 'length'].each do |k| - if options.has_key?("pwd_#{k}".to_sym) + if options.key?("pwd_#{k}".to_sym) password[k.to_sym] = options["pwd_#{k}".to_sym] - elsif !@password.nil? && @password.has_key?(k.to_sym) + elsif !@password.nil? && @password.key?(k.to_sym) password[k.to_sym] = @password[k.to_sym] end end diff --git a/lib/mpw/item.rb b/lib/mpw/item.rb index bd1445b..6e99f6a 100644 --- a/lib/mpw/item.rb +++ b/lib/mpw/item.rb @@ -37,11 +37,11 @@ class Item # @args: options -> a hash of parameter # raise an error if the hash hasn't the key name def initialize(options={}) - if !options.has_key?(:host) || options[:host].to_s.empty? + if !options.key?(:host) || options[:host].to_s.empty? raise I18n.t('error.update.host_empty') end - if !options.has_key?(:id) || options[:id].to_s.empty? || !options.has_key?(:created) || options[:created].to_s.empty? + if !options.key?(:id) || options[:id].to_s.empty? || !options.key?(:created) || options[:created].to_s.empty? @id = generate_id @created = Time.now.to_i else @@ -57,18 +57,18 @@ class Item # Update the item # @args: options -> a hash of parameter def update(options={}) - if options.has_key?(:host) && options[:host].to_s.empty? + if options.key?(:host) && options[:host].to_s.empty? raise I18n.t('error.update.host_empty') end - @group = options[:group] if options.has_key?(:group) - @host = options[:host] if options.has_key?(:host) - @protocol = options[:protocol] if options.has_key?(:protocol) - @user = options[:user] if options.has_key?(:user) - @port = options[:port].to_i if options.has_key?(:port) && !options[:port].to_s.empty? - @otp = options[:otp] if options.has_key?(:otp) - @comment = options[:comment] if options.has_key?(:comment) - @last_edit = Time.now.to_i unless options.has_key?(:no_update_last_edit) + @group = options[:group] if options.key?(:group) + @host = options[:host] if options.key?(:host) + @protocol = options[:protocol] if options.key?(:protocol) + @user = options[:user] if options.key?(:user) + @port = options[:port].to_i if options.key?(:port) && !options[:port].to_s.empty? + @otp = options[:otp] if options.key?(:otp) + @comment = options[:comment] if options.key?(:comment) + @last_edit = Time.now.to_i unless options.key?(:no_update_last_edit) end # Delete all data diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index de99440..a957ef0 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -88,7 +88,7 @@ class MPW protocol: d['protocol'], user: d['user'], port: d['port'], - otp: @otp_keys.has_key?(d['id']), + otp: @otp_keys.key?(d['id']), comment: d['comment'], last_edit: d['last_edit'], created: d['created'], @@ -223,12 +223,12 @@ class MPW def set_config(options={}) @config = {} if @config.nil? - @config['protocol'] = options[:protocol] if options.has_key?(:protocol) - @config['host'] = options[:host] if options.has_key?(:host) - @config['port'] = options[:port] if options.has_key?(:port) - @config['user'] = options[:user] if options.has_key?(:user) - @config['password'] = options[:password] if options.has_key?(:password) - @config['path'] = options[:path] if options.has_key?(:path) + @config['protocol'] = options[:protocol] if options.key?(:protocol) + @config['host'] = options[:host] if options.key?(:host) + @config['port'] = options[:port] if options.key?(:port) + @config['user'] = options[:user] if options.key?(:user) + @config['password'] = options[:password] if options.key?(:password) + @config['path'] = options[:path] if options.key?(:path) end # Add a new item @@ -286,14 +286,14 @@ class MPW # args: id -> the item id # key -> the new key def get_otp_key(id) - @otp_keys.has_key?(id) ? decrypt(@otp_keys[id]) : nil + @otp_keys.key?(id) ? decrypt(@otp_keys[id]) : nil end # Get an otp code # @args: id -> the item id # @rtrn: an otp code def get_otp_code(id) - @otp_keys.has_key?(id) ? 0 : ROTP::TOTP.new(decrypt(@otp_keys[id])).now + @otp_keys.key?(id) ? 0 : ROTP::TOTP.new(decrypt(@otp_keys[id])).now end # Get remaining time before expire otp code From 351499aef6c76b99f75f6789c2440b5c387bc39c Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Tue, 28 Mar 2017 22:56:23 +0200 Subject: [PATCH 428/531] replace MPW::password to MPW.password replace YAML::load_file to YAML.load_file replace YAML::load to YAML.safe_load --- bin/mpw-genpwd | 2 +- lib/mpw/cli.rb | 8 ++++---- lib/mpw/config.rb | 2 +- lib/mpw/mpw.rb | 6 +++--- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/bin/mpw-genpwd b/bin/mpw-genpwd index 0370732..1c09489 100644 --- a/bin/mpw-genpwd +++ b/bin/mpw-genpwd @@ -46,5 +46,5 @@ OptionParser.new do |opts| end end.parse! -puts MPW::MPW::password(options) +puts MPW::MPW.password(options) exit 0 diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index 90f7665..7f406b7 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -379,7 +379,7 @@ class Cli system("#{editor} #{tmp_file}") - opts = YAML::load_file(tmp_file) + opts = YAML.load_file(tmp_file) end opts.delete_if { |k,v| v.to_s.empty? } @@ -396,7 +396,7 @@ class Cli def add(password=false) options = text_editor('add_form', nil, password) item = Item.new(options) - options[:password] = MPW::password(@config.password) if password + options[:password] = MPW.password(@config.password) if password @mpw.add(item) @mpw.set_password(item.id, options[:password]) if options.key?(:password) @@ -421,7 +421,7 @@ class Cli item = get_item(items) options = text_editor('update_form', item, password) - options[:password] = MPW::password(@config.password) if password + options[:password] = MPW.password(@config.password) if password item.update(options) @mpw.set_password(item.id, options[:password]) if options.key?(:password) @@ -512,7 +512,7 @@ class Cli raise I18n.t('form.import.file_empty') if file.to_s.empty? raise I18n.t('form.import.file_not_exist') unless File.exist?(file) - YAML::load_file(file).each_value do |row| + YAML.load_file(file).each_value do |row| item = Item.new(group: row['group'], host: row['host'], protocol: row['protocol'], diff --git a/lib/mpw/config.rb b/lib/mpw/config.rb index b7cf5e8..6f3632c 100644 --- a/lib/mpw/config.rb +++ b/lib/mpw/config.rb @@ -130,7 +130,7 @@ class Config # Load the config file def load_config - config = YAML::load_file(@config_file) + config = YAML.load_file(@config_file) @gpg_key = config['gpg_key'] @lang = config['lang'] @wallet_dir = config['wallet_dir'] diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index a957ef0..70f3847 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -54,7 +54,7 @@ class MPW tar.each do |f| case f.full_name when 'wallet/config.gpg' - @config = YAML.load(decrypt(f.read)) + @config = YAML.safe_load(decrypt(f.read)) when 'wallet/meta.gpg' data = decrypt(f.read) @@ -81,7 +81,7 @@ class MPW end unless data.to_s.empty? - YAML.load(data).each_value do |d| + YAML.safe_load(data).each_value do |d| @data.push(Item.new(id: d['id'], group: d['group'], host: d['host'], @@ -178,7 +178,7 @@ class MPW # args: id -> the item id # password -> the new password def set_password(id, password) - salt = MPW::password(length: Random.rand(4..9)) + salt = MPW.password(length: Random.rand(4..9)) password = "$#{salt}::#{password}" @passwords[id] = encrypt(password) From db6bb2b0f6fef4cd97b0223b8bea07b552e5c84d Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Tue, 28 Mar 2017 23:04:54 +0200 Subject: [PATCH 429/531] replace "#{var}" by var.to_s --- lib/mpw/cli.rb | 22 +++++++++++----------- lib/mpw/config.rb | 4 ++-- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index 7f406b7..1807f75 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -40,7 +40,7 @@ class Cli def set_config(options) @config.setup(options) - puts "#{I18n.t('form.set_config.valid')}".green + puts I18n.t('form.set_config.valid').to_s.green rescue Exception => e puts "#{I18n.t('display.error')} #15: #{e}".red exit 2 @@ -57,7 +57,7 @@ class Cli load_config - puts "#{I18n.t('form.setup_config.valid')}".green + puts I18n.t('form.setup_config.valid').to_s.green rescue Exception => e puts "#{I18n.t('display.error')} #8: #{e}".red exit 2 @@ -81,7 +81,7 @@ class Cli @config.setup_gpg_key(@password, gpg_key) - puts "#{I18n.t('form.setup_gpg_key.valid')}".green + puts I18n.t('form.setup_gpg_key.valid').to_s.green rescue Exception => e puts "#{I18n.t('display.error')} #8: #{e}".red exit 2 @@ -208,7 +208,7 @@ class Cli end print '| ' - print "#{item.send(k.to_s)}".send(v[:color]) + print item.send(k.to_s).to_s.send(v[:color]) (v[:length] - item.send(k.to_s).to_s.length).times { print ' ' } end print "\n" @@ -343,7 +343,7 @@ class Cli @mpw.add_key(key) @mpw.write_data - puts "#{I18n.t('form.add_key.valid')}".green + puts I18n.t('form.add_key.valid').to_s.green rescue Exception => e puts "#{I18n.t('display.error')} #13: #{e}".red end @@ -354,7 +354,7 @@ class Cli @mpw.delete_key(key) @mpw.write_data - puts "#{I18n.t('form.delete_key.valid')}".green + puts I18n.t('form.delete_key.valid').to_s.green rescue Exception => e puts "#{I18n.t('display.error')} #15: #{e}".red end @@ -403,7 +403,7 @@ class Cli @mpw.set_otp_key(item.id, options[:otp_key]) if options.key?(:otp_key) @mpw.write_data - puts "#{I18n.t('form.add_item.valid')}".green + puts I18n.t('form.add_item.valid').to_s.green rescue Exception => e puts "#{I18n.t('display.error')} #13: #{e}".red end @@ -428,7 +428,7 @@ class Cli @mpw.set_otp_key(item.id, options[:otp_key]) if options.key?(:otp_key) @mpw.write_data - puts "#{I18n.t('form.update_item.valid')}".green + puts I18n.t('form.update_item.valid').to_s.green end rescue Exception => e puts "#{I18n.t('display.error')} #14: #{e}".red @@ -452,7 +452,7 @@ class Cli item.delete @mpw.write_data - puts "#{I18n.t('form.delete_item.valid')}".green + puts I18n.t('form.delete_item.valid').to_s.green end rescue Exception => e puts "#{I18n.t('display.error')} #16: #{e}".red @@ -501,7 +501,7 @@ class Cli File.open(file, 'w') {|f| f << data.to_yaml} - puts "#{I18n.t('form.export.valid', file: file)}".green + puts I18n.t('form.export.valid', file: file).to_s.green rescue Exception => e puts "#{I18n.t('display.error')} #17: #{e}".red end @@ -530,7 +530,7 @@ class Cli @mpw.write_data - puts "#{I18n.t('form.import.valid')}".green + puts I18n.t('form.import.valid').to_s.green rescue Exception => e puts "#{I18n.t('display.error')} #18: #{e}".red end diff --git a/lib/mpw/config.rb b/lib/mpw/config.rb index 6f3632c..be99f31 100644 --- a/lib/mpw/config.rb +++ b/lib/mpw/config.rb @@ -104,9 +104,9 @@ class Config # @rtrn: true if the GPG key is create, else false def setup_gpg_key(password, name, length = 4096, expire = 0) if name.to_s.empty? - raise "#{I18n.t('error.config.genkey_gpg.name')}" + raise I18n.t('error.config.genkey_gpg.name') elsif password.to_s.empty? - raise "#{I18n.t('error.config.genkey_gpg.password')}" + raise I18n.t('error.config.genkey_gpg.password') end param = '' From e99b18519db246afeccb990959f602e4e6b5b79b Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Tue, 28 Mar 2017 23:13:45 +0200 Subject: [PATCH 430/531] replace var.length == 0 by var.empty? --- lib/mpw/cli.rb | 8 ++++---- lib/mpw/mpw.rb | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index 1807f75..991388c 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -224,7 +224,7 @@ class Cli def list(options={}) result = @mpw.list(options) - if result.length == 0 + if result.empty? puts I18n.t('display.nothing') else table_items(result) @@ -414,7 +414,7 @@ class Cli def update(password=false, options={}) items = @mpw.list(options) - if items.length == 0 + if items.empty? puts "#{I18n.t('display.warning')}: #{I18n.t('warning.select')}".yellow else table_items(items) if items.length > 1 @@ -439,7 +439,7 @@ class Cli def delete(options={}) items = @mpw.list(options) - if items.length == 0 + if items.empty? puts "#{I18n.t('display.warning')}: #{I18n.t('warning.select')}".yellow else table_items(items) @@ -464,7 +464,7 @@ class Cli def copy(clipboard=true, options={}) items = @mpw.list(options) - if items.length == 0 + if items.empty? puts I18n.t('display.nothing') else table_items(items) diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index 70f3847..811a7a1 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -62,7 +62,7 @@ class MPW when /^wallet\/keys\/(?<key>.+)\.pub$/ key = Regexp.last_match('key') - if GPGME::Key.find(:public, key).length == 0 + if GPGME::Key.find(:public, key).empty? GPGME::Key.import(f.read, armor: true) end From 6a6120ca1448363f0fd21264c05ff2ad9fa9e44a Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Tue, 28 Mar 2017 23:24:22 +0200 Subject: [PATCH 431/531] use %w for words array --- lib/mpw/config.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/mpw/config.rb b/lib/mpw/config.rb index be99f31..915e603 100644 --- a/lib/mpw/config.rb +++ b/lib/mpw/config.rb @@ -65,7 +65,7 @@ class Config length: 16, } - ['numeric', 'special', 'alpha', 'length'].each do |k| + %w(numeric special alpha length).each do |k| if options.key?("pwd_#{k}".to_sym) password[k.to_sym] = options["pwd_#{k}".to_sym] elsif !@password.nil? && @password.key?(k.to_sym) From 7a831555f49fe0a2dbdb0d25edb6e64a4d36ed42 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Tue, 28 Mar 2017 23:29:33 +0200 Subject: [PATCH 432/531] fix spacing --- lib/mpw/cli.rb | 38 ++++++++++++++++++------------------- lib/mpw/config.rb | 2 +- lib/mpw/item.rb | 6 +++--- lib/mpw/mpw.rb | 48 +++++++++++++++++++++++------------------------ 4 files changed, 47 insertions(+), 47 deletions(-) diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index 991388c..300318a 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -68,8 +68,8 @@ class Cli def setup_gpg_key(gpg_key) return if @config.check_gpg_key? - password = ask(I18n.t('form.setup_gpg_key.password')) {|q| q.echo = false} - confirm = ask(I18n.t('form.setup_gpg_key.confirm_password')) {|q| q.echo = false} + password = ask(I18n.t('form.setup_gpg_key.password')) { |q| q.echo = false } + confirm = ask(I18n.t('form.setup_gpg_key.confirm_password')) { |q| q.echo = false } if password != confirm raise I18n.t('form.setup_gpg_key.error_password') @@ -104,7 +104,7 @@ class Cli # Request the GPG password and decrypt the file def decrypt unless defined?(@mpw) - @password = ask(I18n.t('display.gpg_password')) {|q| q.echo = false} + @password = ask(I18n.t('display.gpg_password')) { |q| q.echo = false } @mpw = MPW.new(@config.gpg_key, @wallet_file, @password, @config.gpg_exe) end @@ -140,7 +140,7 @@ class Cli end # Format items on a table - def table_items(items=[]) + def table_items(items = []) group = '.' i = 1 length_total = 10 @@ -160,7 +160,7 @@ class Cli v[:length] = item.send(k.to_s).to_s.length + 3 if item.send(k.to_s).to_s.length >= v[:length] end end - data[:id][:length] = items.length.to_s.length + 2 if items.length.to_s.length > data[:id][:length] + data[:id][:length] = items.length.to_s.length + 2 if items.length.to_s.length > data[:id][:length] data.each_value { |v| length_total += v[:length] } items.sort! { |a, b| a.group.to_s.downcase <=> b.group.to_s.downcase } @@ -221,7 +221,7 @@ class Cli # Display the query's result # @args: options -> the option to search - def list(options={}) + def list(options = {}) result = @mpw.list(options) if result.empty? @@ -237,16 +237,16 @@ class Cli def get_item(items) return items[0] if items.length == 1 - items.sort! { |a,b| a.group.to_s.downcase <=> b.group.to_s.downcase } + items.sort! { |a, b| a.group.to_s.downcase <=> b.group.to_s.downcase } choice = ask(I18n.t('form.select')).to_i - choice >= 1 && choice <= items.length ? items[choice-1] : nil + choice >= 1 && choice <= items.length ? items[choice - 1] : nil end # Copy in clipboard the login and password # @args: item -> the item # clipboard -> enable clipboard - def clipboard(item, clipboard=true) + def clipboard(item, clipboard = true) pid = nil # Security: force quit after 90s @@ -321,7 +321,7 @@ class Cli # Display the wallet # @args: wallet -> the wallet name - def get_wallet(wallet=nil) + def get_wallet(wallet = nil) if wallet.to_s.empty? wallets = Dir.glob("#{@config.wallet_dir}/*.mpw") @@ -363,7 +363,7 @@ class Cli # @args: template -> template name # item -> the item to edit # password -> disable field password - def text_editor(template_name, item=nil, password=false) + def text_editor(template_name, item = nil, password = false) editor = ENV['EDITOR'] || 'nano' options = {} opts = {} @@ -382,9 +382,9 @@ class Cli opts = YAML.load_file(tmp_file) end - opts.delete_if { |k,v| v.to_s.empty? } + opts.delete_if { |k, v| v.to_s.empty? } - opts.each do |k,v| + opts.each do |k, v| options[k.to_sym] = v end @@ -393,7 +393,7 @@ class Cli # Form to add a new item # @args: password -> generate a random password - def add(password=false) + def add(password = false) options = text_editor('add_form', nil, password) item = Item.new(options) options[:password] = MPW.password(@config.password) if password @@ -411,7 +411,7 @@ class Cli # Update an item # @args: password -> generate a random password # options -> the option to search - def update(password=false, options={}) + def update(password = false, options = {}) items = @mpw.list(options) if items.empty? @@ -421,7 +421,7 @@ class Cli item = get_item(items) options = text_editor('update_form', item, password) - options[:password] = MPW.password(@config.password) if password + options[:password] = MPW.password(@config.password) if password item.update(options) @mpw.set_password(item.id, options[:password]) if options.key?(:password) @@ -436,7 +436,7 @@ class Cli # Remove an item # @args: options -> the option to search - def delete(options={}) + def delete(options = {}) items = @mpw.list(options) if items.empty? @@ -461,7 +461,7 @@ class Cli # Copy a password, otp, login # @args: clipboard -> enable clipboard # options -> the option to search - def copy(clipboard=true, options={}) + def copy(clipboard = true, options = {}) items = @mpw.list(options) if items.empty? @@ -499,7 +499,7 @@ class Cli ) end - File.open(file, 'w') {|f| f << data.to_yaml} + File.open(file, 'w') { |f| f << data.to_yaml } puts I18n.t('form.export.valid', file: file).to_s.green rescue Exception => e diff --git a/lib/mpw/config.rb b/lib/mpw/config.rb index 915e603..c722c39 100644 --- a/lib/mpw/config.rb +++ b/lib/mpw/config.rb @@ -36,7 +36,7 @@ class Config # Constructor # @args: config_file -> the specify config file - def initialize(config_file=nil) + def initialize(config_file = nil) @config_file = config_file if /darwin/ =~ RUBY_PLATFORM diff --git a/lib/mpw/item.rb b/lib/mpw/item.rb index 6e99f6a..55e0061 100644 --- a/lib/mpw/item.rb +++ b/lib/mpw/item.rb @@ -36,7 +36,7 @@ class Item # Create a new item # @args: options -> a hash of parameter # raise an error if the hash hasn't the key name - def initialize(options={}) + def initialize(options = {}) if !options.key?(:host) || options[:host].to_s.empty? raise I18n.t('error.update.host_empty') end @@ -56,7 +56,7 @@ class Item # Update the item # @args: options -> a hash of parameter - def update(options={}) + def update(options = {}) if options.key?(:host) && options[:host].to_s.empty? raise I18n.t('error.update.host_empty') end @@ -96,7 +96,7 @@ class Item # Generate an random id private def generate_id - ([*('A'..'Z'),*('a'..'z'),*('0'..'9')]).sample(16).join + ([*('A'..'Z'), *('a'..'z'), *('0'..'9')]).sample(16).join end end end diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index 811a7a1..678987e 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -27,7 +27,7 @@ module MPW class MPW # Constructor - def initialize(key, wallet_file, gpg_pass=nil, gpg_exe=nil) + def initialize(key, wallet_file, gpg_pass = nil, gpg_exe = nil) @key = key @gpg_pass = gpg_pass @gpg_exe = gpg_exe @@ -53,29 +53,29 @@ class MPW Gem::Package::TarReader.new(File.open(@wallet_file)) do |tar| tar.each do |f| case f.full_name - when 'wallet/config.gpg' - @config = YAML.safe_load(decrypt(f.read)) + when 'wallet/config.gpg' + @config = YAML.safe_load(decrypt(f.read)) - when 'wallet/meta.gpg' - data = decrypt(f.read) + when 'wallet/meta.gpg' + data = decrypt(f.read) - when /^wallet\/keys\/(?<key>.+)\.pub$/ - key = Regexp.last_match('key') + when /^wallet\/keys\/(?<key>.+)\.pub$/ + key = Regexp.last_match('key') - if GPGME::Key.find(:public, key).empty? - GPGME::Key.import(f.read, armor: true) - end + if GPGME::Key.find(:public, key).empty? + GPGME::Key.import(f.read, armor: true) + end - @keys[key] = f.read + @keys[key] = f.read - when /^wallet\/passwords\/(?<id>[a-zA-Z0-9]+)\.gpg$/ - @passwords[Regexp.last_match('id')] = f.read + when /^wallet\/passwords\/(?<id>[a-zA-Z0-9]+)\.gpg$/ + @passwords[Regexp.last_match('id')] = f.read - when /^wallet\/otp_keys\/(?<id>[a-zA-Z0-9]+)\.gpg$/ - @otp_keys[Regexp.last_match('id')] = f.read + when /^wallet\/otp_keys\/(?<id>[a-zA-Z0-9]+)\.gpg$/ + @otp_keys[Regexp.last_match('id')] = f.read - else - next + else + next end end end @@ -220,7 +220,7 @@ class MPW # Set config # args: config -> a hash with config options - def set_config(options={}) + def set_config(options = {}) @config = {} if @config.nil? @config['protocol'] = options[:protocol] if options.key?(:protocol) @@ -243,7 +243,7 @@ class MPW # Search in some csv data # @args: options -> a hash with paramaters # @rtrn: a list with the resultat of the search - def list(options={}) + def list(options = {}) result = [] search = options[:pattern].to_s.downcase @@ -305,7 +305,7 @@ class MPW # Generate a random password # @args: options -> :length, :special, :alpha, :numeric # @rtrn: a random string - def self.password(options={}) + def self.password(options = {}) if !options.include?(:length) || options[:length].to_i <= 0 length = 8 elsif options[:length].to_i >= 32768 @@ -315,10 +315,10 @@ class MPW end chars = [] - chars += [*('!'..'?')] - [*('0'..'9')] if options[:special] - chars += [*('A'..'Z'),*('a'..'z')] if options[:alpha] - chars += [*('0'..'9')] if options[:numeric] - chars = [*('A'..'Z'),*('a'..'z'),*('0'..'9')] if chars.empty? + chars += [*('!'..'?')] - [*('0'..'9')] if options[:special] + chars += [*('A'..'Z'), *('a'..'z')] if options[:alpha] + chars += [*('0'..'9')] if options[:numeric] + chars = [*('A'..'Z'), *('a'..'z'), *('0'..'9')] if chars.empty? result = '' while length > 62 do From 043e378eab897e63cb0488ebcb1093ca5a23ff86 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Tue, 28 Mar 2017 23:34:24 +0200 Subject: [PATCH 433/531] replace File.exists? by File.exist? --- lib/mpw/mpw.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index 678987e..13c864f 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -48,7 +48,7 @@ class MPW data = nil - return unless File.exists?(@wallet_file) + return unless File.exist?(@wallet_file) Gem::Package::TarReader.new(File.open(@wallet_file)) do |tar| tar.each do |f| @@ -193,7 +193,7 @@ class MPW # Add a public key # args: key -> new public key file or name def add_key(key) - if File.exists?(key) + if File.exist?(key) data = File.open(key).read key_import = GPGME::Key.import(data, armor: true) key = GPGME::Key.get(key_import.imports[0].fpr).uids[0].email From 05c30200c3b2a2efa6373aa4d0cf72131e699b6f Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Wed, 29 Mar 2017 08:12:57 +0200 Subject: [PATCH 434/531] add rubocop file --- .rubocop.yml | 122 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 122 insertions(+) create mode 100644 .rubocop.yml diff --git a/.rubocop.yml b/.rubocop.yml new file mode 100644 index 0000000..8685f88 --- /dev/null +++ b/.rubocop.yml @@ -0,0 +1,122 @@ + +AllCops: + Exclude: + - db/**/* + - config/**/* + - test/* + - Vagrantfile + TargetRubyVersion: 2.3 + +Style/AccessorMethodName: + Enabled: false +Style/NumericLiteralPrefix: + Enabled: false +Style/TrailingCommaInArguments: + Enabled: false +Style/TrailingCommaInLiteral: + Enabled: false +Style/FrozenStringLiteralComment: + Enabled: false +Metrics/ParameterLists: + Max: 5 + CountKeywordArgs: false +Style/MutableConstant: + Enabled: false +Metrics/LineLength: + Max: 120 +Metrics/AbcSize: + Enabled: false +Metrics/MethodLength: + Enabled: false +Metrics/BlockLength: + Enabled: false +Metrics/CyclomaticComplexity: + Enabled: false +Metrics/PerceivedComplexity: + Enabled: false +Metrics/ClassLength: + Enabled: false +Style/SpaceInsideHashLiteralBraces: + Enabled: false +Style/AsciiComments: + Enabled: true +Style/Documentation: + Enabled: false +Style/SignalException: + Enabled: false +Style/OptionHash: + Enabled: true +Style/SymbolArray: + Enabled: true +Performance/Casecmp: + Enabled: false +Style/DoubleNegation: + Enabled: false +Style/Alias: + EnforcedStyle: prefer_alias_method +Style/MultilineMethodCallIndentation: + EnforcedStyle: indented +Style/RaiseArgs: + EnforcedStyle: exploded +Style/SpaceInLambdaLiteral: + Enabled: false +Lint/UnneededSplatExpansion: + Enabled: false + + +# Generated configuration +Style/HashSyntax: + Enabled: true + EnforcedStyle: ruby19 + UseHashRocketsWithSymbolValues: false +Style/MethodDefParentheses: + Enabled: true + EnforcedStyle: require_parentheses +Style/MultilineAssignmentLayout: + Enabled: true + EnforcedStyle: new_line +Style/IndentationConsistency: + Enabled: true + EnforcedStyle: normal +Style/AlignParameters: + Enabled: true + EnforcedStyle: with_fixed_indentation +Style/BlockDelimiters: + Enabled: true + EnforcedStyle: line_count_based +Style/AndOr: + Enabled: true +Style/DotPosition: + Enabled: true + EnforcedStyle: leading +Style/EmptyLinesAroundClassBody: + Enabled: true + EnforcedStyle: no_empty_lines +Style/EmptyLinesAroundModuleBody: + Enabled: true + EnforcedStyle: no_empty_lines +Style/NumericPredicate: + Enabled: true + EnforcedStyle: comparison +Style/EvenOdd: + Enabled: false +Style/CollectionMethods: + Enabled: true + PreferredMethods: + collect: map + collect!: map! + inject: reduce + detect: find + find_all: select +Style/EmptyLinesAroundAccessModifier: + Enabled: true +Style/CommandLiteral: + Enabled: true + EnforcedStyle: percent_x +Style/StringLiterals: + Enabled: true + EnforcedStyle: single_quotes +Style/SpaceInsideBlockBraces: + EnforcedStyle: space +Style/VariableNumber: + EnforcedStyle: snake_case From c1baf3e1d4f18e5dee5c93530905281d16624417 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Wed, 29 Mar 2017 22:00:21 +0200 Subject: [PATCH 435/531] remove unused variable --- lib/mpw/cli.rb | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index 300318a..8faab03 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -247,8 +247,6 @@ class Cli # @args: item -> the item # clipboard -> enable clipboard def clipboard(item, clipboard = true) - pid = nil - # Security: force quit after 90s Thread.new do sleep 90 From b32846ea5edb61842464f798b4b60b78cdab9583 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Wed, 29 Mar 2017 22:12:11 +0200 Subject: [PATCH 436/531] replace while true by Kernel.loop --- lib/mpw/cli.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index 8faab03..a334e61 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -253,7 +253,7 @@ class Cli exit end - while true + Kernel.loop do choice = ask(I18n.t('form.clipboard.choice')).to_s case choice From c29d2e92d23ea103c66e0107a237d73b60315f6e Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Wed, 29 Mar 2017 22:13:53 +0200 Subject: [PATCH 437/531] replace :? to --- bin/mpw | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/mpw b/bin/mpw index 3eb9fd9..8ee1305 100755 --- a/bin/mpw +++ b/bin/mpw @@ -16,7 +16,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -$: << File.expand_path('../../lib', __FILE__) +$LOAD_PATH << File.expand_path('../../lib', __FILE__) require 'locale' require 'set' From 74d08a7d5b9706561ab52b597eb999c3d3fa8ad1 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Wed, 29 Mar 2017 22:24:50 +0200 Subject: [PATCH 438/531] add to_s --- bin/mpw | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/mpw b/bin/mpw index 8ee1305..1bdf835 100755 --- a/bin/mpw +++ b/bin/mpw @@ -45,7 +45,7 @@ I18n.locale = lang.to_sym bin_dir = File.dirname(__FILE__) command = "#{bin_dir}/mpw-#{ARGV[0]}" -if Dir.glob("#{bin_dir}/mpw-*").include?("#{command}") +if Dir.glob("#{bin_dir}/mpw-*").include?(command.to_s) begin Kernel.load(command) rescue OptionParser::ParseError => e From da248460da2fe8d674ea4979a33facc249b07ae9 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Wed, 29 Mar 2017 22:31:04 +0200 Subject: [PATCH 439/531] use %r{} for regex --- lib/mpw/mpw.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index 13c864f..b3a733c 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -59,7 +59,7 @@ class MPW when 'wallet/meta.gpg' data = decrypt(f.read) - when /^wallet\/keys\/(?<key>.+)\.pub$/ + when %r{^wallet/keys/(?<key>.+)\.pub$} key = Regexp.last_match('key') if GPGME::Key.find(:public, key).empty? @@ -68,10 +68,10 @@ class MPW @keys[key] = f.read - when /^wallet\/passwords\/(?<id>[a-zA-Z0-9]+)\.gpg$/ + when %r{^wallet/passwords/(?<id>[a-zA-Z0-9]+)\.gpg$} @passwords[Regexp.last_match('id')] = f.read - when /^wallet\/otp_keys\/(?<id>[a-zA-Z0-9]+)\.gpg$/ + when %r{^wallet/otp_keys/(?<id>[a-zA-Z0-9]+)\.gpg$} @otp_keys[Regexp.last_match('id')] = f.read else From 8cd7b6e583fef8d355b559eeab5c19f2e631cfc0 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Wed, 29 Mar 2017 22:31:48 +0200 Subject: [PATCH 440/531] use iter form --- lib/mpw/cli.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index a334e61..7f1c2da 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -202,7 +202,7 @@ class Cli if k == :otp print '| ' - if item.otp; print ' X ' else 4.times { print ' ' } end + item.otp ? (print ' X ') : 4.times { print ' ' } next end From 18ba72e91bd9fc52381c2a27c42d12444617b121 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Wed, 29 Mar 2017 22:36:46 +0200 Subject: [PATCH 441/531] fix private style --- lib/mpw/item.rb | 3 ++- lib/mpw/mpw.rb | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/mpw/item.rb b/lib/mpw/item.rb index 55e0061..225a3d7 100644 --- a/lib/mpw/item.rb +++ b/lib/mpw/item.rb @@ -93,8 +93,9 @@ class Item false end - # Generate an random id private + + # Generate an random id def generate_id ([*('A'..'Z'), *('a'..'z'), *('0'..'9')]).sample(16).join end diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index b3a733c..d09e9bd 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -330,9 +330,10 @@ class MPW result end + private + # Decrypt a gpg file # @args: data -> string to decrypt - private def decrypt(data) return nil if data.to_s.empty? @@ -345,7 +346,6 @@ class MPW # Encrypt a file # args: data -> string to encrypt - private def encrypt(data) recipients = [] crypto = GPGME::Crypto.new(armor: true, always_trust: true) From 5db52db1a39c7c6c4ccfc2bd7d9e707c3cd53118 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Wed, 29 Mar 2017 22:38:16 +0200 Subject: [PATCH 442/531] remove do in while line --- lib/mpw/mpw.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index d09e9bd..ffdccff 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -321,7 +321,7 @@ class MPW chars = [*('A'..'Z'), *('a'..'z'), *('0'..'9')] if chars.empty? result = '' - while length > 62 do + while length > 62 result << chars.sample(62).join length -= 62 end From e04d00d3f477a08c1e69b76bfb27df883a0ec4e2 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Wed, 29 Mar 2017 22:45:39 +0200 Subject: [PATCH 443/531] use new form for module --- lib/mpw/cli.rb | 4 +--- lib/mpw/config.rb | 4 +--- lib/mpw/item.rb | 4 +--- lib/mpw/mpw.rb | 4 +--- 4 files changed, 4 insertions(+), 12 deletions(-) diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index 7f1c2da..d2dcd0b 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -26,8 +26,7 @@ require 'tmpdir' require 'mpw/item' require 'mpw/mpw' -module MPW -class Cli +class MPW::Cli # Constructor # @args: config -> the config @@ -533,4 +532,3 @@ class Cli puts "#{I18n.t('display.error')} #18: #{e}".red end end -end diff --git a/lib/mpw/config.rb b/lib/mpw/config.rb index c722c39..4c4e259 100644 --- a/lib/mpw/config.rb +++ b/lib/mpw/config.rb @@ -21,8 +21,7 @@ require 'yaml' require 'i18n' require 'fileutils' -module MPW -class Config +class MPW::Config attr_accessor :error_msg @@ -156,4 +155,3 @@ class Config false end end -end diff --git a/lib/mpw/item.rb b/lib/mpw/item.rb index 225a3d7..a5528a6 100644 --- a/lib/mpw/item.rb +++ b/lib/mpw/item.rb @@ -18,8 +18,7 @@ require 'i18n' -module MPW -class Item +class MPW::Item attr_accessor :id attr_accessor :group @@ -100,4 +99,3 @@ class Item ([*('A'..'Z'), *('a'..'z'), *('0'..'9')]).sample(16).join end end -end diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index ffdccff..0eac01c 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -23,8 +23,7 @@ require 'yaml' require 'rotp' require 'mpw/item' -module MPW -class MPW +class MPW::MPW # Constructor def initialize(key, wallet_file, gpg_pass = nil, gpg_exe = nil) @@ -361,4 +360,3 @@ class MPW raise "#{I18n.t('error.gpg_file.encrypt')}\n#{e}" end end -end From 782f3d8b5f88cc7acd16311157406a236c031352 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Wed, 29 Mar 2017 23:01:12 +0200 Subject: [PATCH 444/531] remove useless line --- lib/mpw/cli.rb | 1 - lib/mpw/config.rb | 1 - lib/mpw/item.rb | 1 - lib/mpw/mpw.rb | 1 - 4 files changed, 4 deletions(-) diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index d2dcd0b..3488b5a 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -27,7 +27,6 @@ require 'mpw/item' require 'mpw/mpw' class MPW::Cli - # Constructor # @args: config -> the config def initialize(config) diff --git a/lib/mpw/config.rb b/lib/mpw/config.rb index 4c4e259..4818104 100644 --- a/lib/mpw/config.rb +++ b/lib/mpw/config.rb @@ -22,7 +22,6 @@ require 'i18n' require 'fileutils' class MPW::Config - attr_accessor :error_msg attr_accessor :gpg_key diff --git a/lib/mpw/item.rb b/lib/mpw/item.rb index a5528a6..8c0db4c 100644 --- a/lib/mpw/item.rb +++ b/lib/mpw/item.rb @@ -19,7 +19,6 @@ require 'i18n' class MPW::Item - attr_accessor :id attr_accessor :group attr_accessor :host diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index 0eac01c..0aa9aea 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -24,7 +24,6 @@ require 'rotp' require 'mpw/item' class MPW::MPW - # Constructor def initialize(key, wallet_file, gpg_pass = nil, gpg_exe = nil) @key = key From b1fd013d921f12f71b93bc1db0a532bd6562f44b Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Wed, 29 Mar 2017 23:15:45 +0200 Subject: [PATCH 445/531] fix indentation for multiline method and hash --- lib/mpw/cli.rb | 32 +++++++++++++++--------------- lib/mpw/config.rb | 6 ++---- lib/mpw/mpw.rb | 50 +++++++++++++++++++++++++---------------------- 3 files changed, 45 insertions(+), 43 deletions(-) diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index 3488b5a..12f18af 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -148,8 +148,7 @@ class MPW::Cli protocol: { length: 9, color: 'white' }, port: { length: 5, color: 'white' }, otp: { length: 4, color: 'white' }, - comment: { length: 14, color: 'magenta' }, - } + comment: { length: 14, color: 'magenta' } } items.each do |item| data.each do |k, v| @@ -481,18 +480,20 @@ class MPW::Cli data = {} items.each do |item| - data.merge!(item.id => { 'host' => item.host, - 'user' => item.user, - 'group' => item.group, - 'password' => @mpw.get_password(item.id), - 'protocol' => item.protocol, - 'port' => item.port, - 'otp_key' => @mpw.get_otp_key(item.id), - 'comment' => item.comment, - 'last_edit' => item.last_edit, - 'created' => item.created, - } - ) + data.merge!( + item.id => { + 'host' => item.host, + 'user' => item.user, + 'group' => item.group, + 'password' => @mpw.get_password(item.id), + 'protocol' => item.protocol, + 'port' => item.port, + 'otp_key' => @mpw.get_otp_key(item.id), + 'comment' => item.comment, + 'last_edit' => item.last_edit, + 'created' => item.created, + } + ) end File.open(file, 'w') { |f| f << data.to_yaml } @@ -514,8 +515,7 @@ class MPW::Cli protocol: row['protocol'], user: row['user'], port: row['port'], - comment: row['comment'], - ) + comment: row['comment']) next if item.empty? diff --git a/lib/mpw/config.rb b/lib/mpw/config.rb index 4818104..f82fadb 100644 --- a/lib/mpw/config.rb +++ b/lib/mpw/config.rb @@ -60,8 +60,7 @@ class MPW::Config password = { numeric: true, alpha: true, special: false, - length: 16, - } + length: 16 } %w(numeric special alpha length).each do |k| if options.key?("pwd_#{k}".to_sym) @@ -81,8 +80,7 @@ class MPW::Config 'wallet_dir' => wallet_dir, 'default_wallet' => default_wallet, 'gpg_exe' => gpg_exe, - 'password' => password, - } + 'password' => password } FileUtils.mkdir_p(@config_dir, mode: 0700) FileUtils.mkdir_p(wallet_dir, mode: 0700) diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index 0aa9aea..1e385cb 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -80,18 +80,20 @@ class MPW::MPW unless data.to_s.empty? YAML.safe_load(data).each_value do |d| - @data.push(Item.new(id: d['id'], - group: d['group'], - host: d['host'], - protocol: d['protocol'], - user: d['user'], - port: d['port'], - otp: @otp_keys.key?(d['id']), - comment: d['comment'], - last_edit: d['last_edit'], - created: d['created'], - ) - ) + @data.push( + Item.new( + id: d['id'], + group: d['group'], + host: d['host'], + protocol: d['protocol'], + user: d['user'], + port: d['port'], + otp: @otp_keys.key?(d['id']), + comment: d['comment'], + last_edit: d['last_edit'], + created: d['created'], + ) + ) end end @@ -108,17 +110,19 @@ class MPW::MPW @data.each do |item| next if item.empty? - data.merge!(item.id => { 'id' => item.id, - 'group' => item.group, - 'host' => item.host, - 'protocol' => item.protocol, - 'user' => item.user, - 'port' => item.port, - 'comment' => item.comment, - 'last_edit' => item.last_edit, - 'created' => item.created, - } - ) + data.merge!( + item.id => { + 'id' => item.id, + 'group' => item.group, + 'host' => item.host, + 'protocol' => item.protocol, + 'user' => item.user, + 'port' => item.port, + 'comment' => item.comment, + 'last_edit' => item.last_edit, + 'created' => item.created, + } + ) end @config['last_update'] = Time.now.to_i From ac2732d116e56c68fa60873ac70b570bda122156 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Wed, 29 Mar 2017 23:24:54 +0200 Subject: [PATCH 446/531] revert new module form --- lib/mpw/cli.rb | 4 +++- lib/mpw/config.rb | 4 +++- lib/mpw/item.rb | 4 +++- lib/mpw/mpw.rb | 4 +++- 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index 12f18af..b44d770 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -26,7 +26,8 @@ require 'tmpdir' require 'mpw/item' require 'mpw/mpw' -class MPW::Cli +module MPW +class Cli # Constructor # @args: config -> the config def initialize(config) @@ -531,3 +532,4 @@ class MPW::Cli puts "#{I18n.t('display.error')} #18: #{e}".red end end +end diff --git a/lib/mpw/config.rb b/lib/mpw/config.rb index f82fadb..8e2cb6e 100644 --- a/lib/mpw/config.rb +++ b/lib/mpw/config.rb @@ -21,7 +21,8 @@ require 'yaml' require 'i18n' require 'fileutils' -class MPW::Config +module MPW +class Config attr_accessor :error_msg attr_accessor :gpg_key @@ -152,3 +153,4 @@ class MPW::Config false end end +end diff --git a/lib/mpw/item.rb b/lib/mpw/item.rb index 8c0db4c..f6d90ef 100644 --- a/lib/mpw/item.rb +++ b/lib/mpw/item.rb @@ -18,7 +18,8 @@ require 'i18n' -class MPW::Item +module MPW +class Item attr_accessor :id attr_accessor :group attr_accessor :host @@ -98,3 +99,4 @@ class MPW::Item ([*('A'..'Z'), *('a'..'z'), *('0'..'9')]).sample(16).join end end +end diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index 1e385cb..0c65435 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -23,7 +23,8 @@ require 'yaml' require 'rotp' require 'mpw/item' -class MPW::MPW +module MPW +class MPW # Constructor def initialize(key, wallet_file, gpg_pass = nil, gpg_exe = nil) @key = key @@ -363,3 +364,4 @@ class MPW::MPW raise "#{I18n.t('error.gpg_file.encrypt')}\n#{e}" end end +end From 002ec2175b427ba148dbf803d3fa34f39ca402bd Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <adrien.waksberg@doctolib.fr> Date: Thu, 30 Mar 2017 19:35:50 +0200 Subject: [PATCH 447/531] fix rescue --- lib/mpw/cli.rb | 27 +++++++++++++-------------- lib/mpw/config.rb | 6 +++--- lib/mpw/mpw.rb | 8 ++++---- 3 files changed, 20 insertions(+), 21 deletions(-) diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index b44d770..a1533b5 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -40,7 +40,7 @@ class Cli @config.setup(options) puts I18n.t('form.set_config.valid').to_s.green - rescue Exception => e + rescue => e puts "#{I18n.t('display.error')} #15: #{e}".red exit 2 end @@ -57,7 +57,7 @@ class Cli load_config puts I18n.t('form.setup_config.valid').to_s.green - rescue Exception => e + rescue => e puts "#{I18n.t('display.error')} #8: #{e}".red exit 2 end @@ -81,7 +81,7 @@ class Cli @config.setup_gpg_key(@password, gpg_key) puts I18n.t('form.setup_gpg_key.valid').to_s.green - rescue Exception => e + rescue => e puts "#{I18n.t('display.error')} #8: #{e}".red exit 2 end @@ -94,8 +94,7 @@ class Cli # Load config def load_config @config.load_config - - rescue Exception => e + rescue => e puts "#{I18n.t('display.error')} #10: #{e}".red exit 2 end @@ -108,7 +107,7 @@ class Cli end @mpw.read_data - rescue Exception => e + rescue => e puts "#{I18n.t('display.error')} #11: #{e}".red exit 2 end @@ -340,7 +339,7 @@ class Cli @mpw.write_data puts I18n.t('form.add_key.valid').to_s.green - rescue Exception => e + rescue => e puts "#{I18n.t('display.error')} #13: #{e}".red end @@ -351,7 +350,7 @@ class Cli @mpw.write_data puts I18n.t('form.delete_key.valid').to_s.green - rescue Exception => e + rescue => e puts "#{I18n.t('display.error')} #15: #{e}".red end @@ -400,7 +399,7 @@ class Cli @mpw.write_data puts I18n.t('form.add_item.valid').to_s.green - rescue Exception => e + rescue => e puts "#{I18n.t('display.error')} #13: #{e}".red end @@ -426,7 +425,7 @@ class Cli puts I18n.t('form.update_item.valid').to_s.green end - rescue Exception => e + rescue => e puts "#{I18n.t('display.error')} #14: #{e}".red end @@ -450,7 +449,7 @@ class Cli puts I18n.t('form.delete_item.valid').to_s.green end - rescue Exception => e + rescue => e puts "#{I18n.t('display.error')} #16: #{e}".red end @@ -468,7 +467,7 @@ class Cli item = get_item(items) clipboard(item, clipboard) end - rescue Exception => e + rescue => e puts "#{I18n.t('display.error')} #14: #{e}".red end @@ -500,7 +499,7 @@ class Cli File.open(file, 'w') { |f| f << data.to_yaml } puts I18n.t('form.export.valid', file: file).to_s.green - rescue Exception => e + rescue => e puts "#{I18n.t('display.error')} #17: #{e}".red end @@ -528,7 +527,7 @@ class Cli @mpw.write_data puts I18n.t('form.import.valid').to_s.green - rescue Exception => e + rescue => e puts "#{I18n.t('display.error')} #18: #{e}".red end end diff --git a/lib/mpw/config.rb b/lib/mpw/config.rb index 8e2cb6e..af746a2 100644 --- a/lib/mpw/config.rb +++ b/lib/mpw/config.rb @@ -89,7 +89,7 @@ class Config File.open(@config_file, 'w') do |file| file << config.to_yaml end - rescue Exception => e + rescue => e raise "#{I18n.t('error.config.write')}\n#{e}" end @@ -121,7 +121,7 @@ class Config ctx = GPGME::Ctx.new ctx.genkey(param, nil, nil) - rescue Exception => e + rescue => e raise "#{I18n.t('error.config.genkey_gpg.exception')}\n#{e}" end @@ -138,7 +138,7 @@ class Config raise if @gpg_key.empty? || @wallet_dir.empty? I18n.locale = @lang.to_sym - rescue Exception => e + rescue => e raise "#{I18n.t('error.config.load')}\n#{e}" end diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index 0c65435..069a123 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -99,7 +99,7 @@ class MPW end add_key(@key) if @keys[@key].nil? - rescue Exception => e + rescue => e raise "#{I18n.t('error.mpw_file.read_data')}\n#{e}" end @@ -159,7 +159,7 @@ class MPW end File.rename(tmp_file, @wallet_file) - rescue Exception => e + rescue => e File.unlink(tmp_file) if File.exist?(tmp_file) raise "#{I18n.t('error.mpw_file.write_data')}\n#{e}" @@ -343,7 +343,7 @@ class MPW crypto = GPGME::Crypto.new(armor: true) crypto.decrypt(data, password: @gpg_pass).read.force_encoding('utf-8') - rescue Exception => e + rescue => e raise "#{I18n.t('error.gpg_file.decrypt')}\n#{e}" end @@ -360,7 +360,7 @@ class MPW end crypto.encrypt(data, recipients: recipients).read - rescue Exception => e + rescue => e raise "#{I18n.t('error.gpg_file.encrypt')}\n#{e}" end end From 3c787371b36d0760a0a19645a657807047a084a7 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <adrien.waksberg@doctolib.fr> Date: Thu, 30 Mar 2017 19:40:04 +0200 Subject: [PATCH 448/531] fix syntax for options in method --- lib/mpw/cli.rb | 8 ++++---- lib/mpw/item.rb | 4 ++-- lib/mpw/mpw.rb | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index a1533b5..3f4d43d 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -218,7 +218,7 @@ class Cli # Display the query's result # @args: options -> the option to search - def list(options = {}) + def list(**options) result = @mpw.list(options) if result.empty? @@ -406,7 +406,7 @@ class Cli # Update an item # @args: password -> generate a random password # options -> the option to search - def update(password = false, options = {}) + def update(password = false, **options) items = @mpw.list(options) if items.empty? @@ -431,7 +431,7 @@ class Cli # Remove an item # @args: options -> the option to search - def delete(options = {}) + def delete(**options) items = @mpw.list(options) if items.empty? @@ -456,7 +456,7 @@ class Cli # Copy a password, otp, login # @args: clipboard -> enable clipboard # options -> the option to search - def copy(clipboard = true, options = {}) + def copy(clipboard = true, **options) items = @mpw.list(options) if items.empty? diff --git a/lib/mpw/item.rb b/lib/mpw/item.rb index f6d90ef..1534cc4 100644 --- a/lib/mpw/item.rb +++ b/lib/mpw/item.rb @@ -35,7 +35,7 @@ class Item # Create a new item # @args: options -> a hash of parameter # raise an error if the hash hasn't the key name - def initialize(options = {}) + def initialize(**options) if !options.key?(:host) || options[:host].to_s.empty? raise I18n.t('error.update.host_empty') end @@ -55,7 +55,7 @@ class Item # Update the item # @args: options -> a hash of parameter - def update(options = {}) + def update(**options) if options.key?(:host) && options[:host].to_s.empty? raise I18n.t('error.update.host_empty') end diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index 069a123..46355ec 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -223,7 +223,7 @@ class MPW # Set config # args: config -> a hash with config options - def set_config(options = {}) + def set_config(**options) @config = {} if @config.nil? @config['protocol'] = options[:protocol] if options.key?(:protocol) @@ -246,7 +246,7 @@ class MPW # Search in some csv data # @args: options -> a hash with paramaters # @rtrn: a list with the resultat of the search - def list(options = {}) + def list(**options) result = [] search = options[:pattern].to_s.downcase From 755df6c3425663e7bcfd3e07b6a8976e349c703d Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <adrien.waksberg@doctolib.fr> Date: Thu, 30 Mar 2017 19:41:00 +0200 Subject: [PATCH 449/531] fix syntax for variable with multiple conditional --- lib/mpw/cli.rb | 21 +++++++++++---------- lib/mpw/config.rb | 15 ++++++++------- lib/mpw/mpw.rb | 17 +++++++++-------- 3 files changed, 28 insertions(+), 25 deletions(-) diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index 3f4d43d..0536108 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -317,19 +317,20 @@ class Cli # Display the wallet # @args: wallet -> the wallet name def get_wallet(wallet = nil) - if wallet.to_s.empty? - wallets = Dir.glob("#{@config.wallet_dir}/*.mpw") + @wallet_file = + if wallet.to_s.empty? + wallets = Dir.glob("#{@config.wallet_dir}/*.mpw") - if wallets.length == 1 - @wallet_file = wallets[0] - elsif !@config.default_wallet.to_s.empty? - @wallet_file = "#{@config.wallet_dir}/#{@config.default_wallet}.mpw" + if wallets.length == 1 + wallets[0] + elsif !@config.default_wallet.to_s.empty? + "#{@config.wallet_dir}/#{@config.default_wallet}.mpw" + else + "#{@config.wallet_dir}/default.mpw" + end else - @wallet_file = "#{@config.wallet_dir}/default.mpw" + "#{@config.wallet_dir}/#{wallet}.mpw" end - else - @wallet_file = "#{@config.wallet_dir}/#{wallet}.mpw" - end end # Add a new public key diff --git a/lib/mpw/config.rb b/lib/mpw/config.rb index af746a2..a6c102e 100644 --- a/lib/mpw/config.rb +++ b/lib/mpw/config.rb @@ -38,13 +38,14 @@ class Config def initialize(config_file = nil) @config_file = config_file - if /darwin/ =~ RUBY_PLATFORM - @config_dir = "#{Dir.home}/Library/Preferences/mpw" - elsif /cygwin|mswin|mingw|bccwin|wince|emx/ =~ RUBY_PLATFORM - @config_dir = "#{Dir.home}/AppData/Local/mpw" - else - @config_dir = "#{Dir.home}/.config/mpw" - end + @config_dir = + if /darwin/ =~ RUBY_PLATFORM + "#{Dir.home}/Library/Preferences/mpw" + elsif /cygwin|mswin|mingw|bccwin|wince|emx/ =~ RUBY_PLATFORM + "#{Dir.home}/AppData/Local/mpw" + else + "#{Dir.home}/.config/mpw" + end @config_file = "#{@config_dir}/mpw.cfg" if @config_file.nil? || @config_file.empty? end diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index 46355ec..557d572 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -308,14 +308,15 @@ class MPW # Generate a random password # @args: options -> :length, :special, :alpha, :numeric # @rtrn: a random string - def self.password(options = {}) - if !options.include?(:length) || options[:length].to_i <= 0 - length = 8 - elsif options[:length].to_i >= 32768 - length = 32768 - else - length = options[:length].to_i - end + def self.password(**options) + length = + if !options.include?(:length) || options[:length].to_i <= 0 + 8 + elsif options[:length].to_i >= 32_768 + 32_768 + else + options[:length].to_i + end chars = [] chars += [*('!'..'?')] - [*('0'..'9')] if options[:special] From 0f7510b6e6b61dfb898328eb6c161b2583dbff83 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <adrien.waksberg@doctolib.fr> Date: Thu, 30 Mar 2017 19:44:32 +0200 Subject: [PATCH 450/531] multiple fix on syntax --- lib/mpw/cli.rb | 6 ++---- lib/mpw/config.rb | 7 ++----- lib/mpw/item.rb | 2 +- lib/mpw/mpw.rb | 8 ++------ 4 files changed, 7 insertions(+), 16 deletions(-) diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index 0536108..cc452cf 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -70,9 +70,7 @@ class Cli password = ask(I18n.t('form.setup_gpg_key.password')) { |q| q.echo = false } confirm = ask(I18n.t('form.setup_gpg_key.confirm_password')) { |q| q.echo = false } - if password != confirm - raise I18n.t('form.setup_gpg_key.error_password') - end + raise I18n.t('form.setup_gpg_key.error_password') if password != confirm @password = password.to_s @@ -378,7 +376,7 @@ class Cli opts = YAML.load_file(tmp_file) end - opts.delete_if { |k, v| v.to_s.empty? } + opts.delete_if { |_, v| v.to_s.empty? } opts.each do |k, v| options[k.to_sym] = v diff --git a/lib/mpw/config.rb b/lib/mpw/config.rb index a6c102e..d691559 100644 --- a/lib/mpw/config.rb +++ b/lib/mpw/config.rb @@ -101,11 +101,8 @@ class Config # expire -> the time of expire to GPG key # @rtrn: true if the GPG key is create, else false def setup_gpg_key(password, name, length = 4096, expire = 0) - if name.to_s.empty? - raise I18n.t('error.config.genkey_gpg.name') - elsif password.to_s.empty? - raise I18n.t('error.config.genkey_gpg.password') - end + raise I18n.t('error.config.genkey_gpg.name') if name.to_s.empty? + raise I18n.t('error.config.genkey_gpg.password') if password.to_s.empty? param = '' param << '<GnupgKeyParms format="internal">' + "\n" diff --git a/lib/mpw/item.rb b/lib/mpw/item.rb index 1534cc4..cd24168 100644 --- a/lib/mpw/item.rb +++ b/lib/mpw/item.rb @@ -96,7 +96,7 @@ class Item # Generate an random id def generate_id - ([*('A'..'Z'), *('a'..'z'), *('0'..'9')]).sample(16).join + [*('A'..'Z'), *('a'..'z'), *('0'..'9')].sample(16).join end end end diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index 557d572..daf04ff 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -32,9 +32,7 @@ class MPW @gpg_exe = gpg_exe @wallet_file = wallet_file - unless @gpg_exe.to_s.empty? - GPGME::Engine.set_info(GPGME::PROTOCOL_OpenPGP, @gpg_exe, "#{Dir.home}/.gnupg") - end + GPGME::Engine.set_info(GPGME::PROTOCOL_OpenPGP, @gpg_exe, "#{Dir.home}/.gnupg") unless @gpg_exe.to_s.empty? end # Read mpw file @@ -204,9 +202,7 @@ class MPW data = GPGME::Key.export(key, armor: true).read end - if data.to_s.empty? - raise I18n.t('error.export_key') - end + raise I18n.t('error.export_key') if data.to_s.empty? @keys[key] = data @passwords.each_key { |id| set_password(id, get_password(id)) } From 01745cac2d5ced7a5237b16087b9525974876634 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <adrien.waksberg@doctolib.fr> Date: Thu, 30 Mar 2017 20:04:20 +0200 Subject: [PATCH 451/531] indent class --- lib/mpw/cli.rb | 886 +++++++++++++++++++++++----------------------- lib/mpw/config.rb | 228 ++++++------ lib/mpw/item.rb | 138 ++++---- lib/mpw/mpw.rb | 622 ++++++++++++++++---------------- 4 files changed, 937 insertions(+), 937 deletions(-) diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index cc452cf..d4d4027 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -27,507 +27,507 @@ require 'mpw/item' require 'mpw/mpw' module MPW -class Cli - # Constructor - # @args: config -> the config - def initialize(config) - @config = config - end - - # Change a parameter int the config after init - # @args: options -> param to change - def set_config(options) - @config.setup(options) - - puts I18n.t('form.set_config.valid').to_s.green - rescue => e - puts "#{I18n.t('display.error')} #15: #{e}".red - exit 2 - end - - # Create a new config file - # @args: options -> set param - def setup(options) - options[:lang] = options[:lang] || Locale::Tag.parse(ENV['LANG']).to_simple.to_s[0..1] - - I18n.locale = options[:lang].to_sym - - @config.setup(options) - - load_config - - puts I18n.t('form.setup_config.valid').to_s.green - rescue => e - puts "#{I18n.t('display.error')} #8: #{e}".red - exit 2 - end - - # Setup a new GPG key - # @args: gpg_key -> the key name - def setup_gpg_key(gpg_key) - return if @config.check_gpg_key? - - password = ask(I18n.t('form.setup_gpg_key.password')) { |q| q.echo = false } - confirm = ask(I18n.t('form.setup_gpg_key.confirm_password')) { |q| q.echo = false } - - raise I18n.t('form.setup_gpg_key.error_password') if password != confirm - - @password = password.to_s - - puts I18n.t('form.setup_gpg_key.wait') - - @config.setup_gpg_key(@password, gpg_key) - - puts I18n.t('form.setup_gpg_key.valid').to_s.green - rescue => e - puts "#{I18n.t('display.error')} #8: #{e}".red - exit 2 - end - - # List gpg keys in wallet - def list_keys - table_list('keys', @mpw.list_keys) - end - - # Load config - def load_config - @config.load_config - rescue => e - puts "#{I18n.t('display.error')} #10: #{e}".red - exit 2 - end - - # Request the GPG password and decrypt the file - def decrypt - unless defined?(@mpw) - @password = ask(I18n.t('display.gpg_password')) { |q| q.echo = false } - @mpw = MPW.new(@config.gpg_key, @wallet_file, @password, @config.gpg_exe) + class Cli + # Constructor + # @args: config -> the config + def initialize(config) + @config = config end - @mpw.read_data - rescue => e - puts "#{I18n.t('display.error')} #11: #{e}".red - exit 2 - end + # Change a parameter int the config after init + # @args: options -> param to change + def set_config(options) + @config.setup(options) - # Format list on a table - def table_list(title, list) - i = 1 - length = 0 - - list.each do |item| - length = item.length if length < item.length - end - length += 7 - - puts "\n#{I18n.t("display.#{title}")}".red - print ' ' - length.times { print '=' } - print "\n" - - list.each do |item| - print " #{i}".cyan - (3 - i.to_s.length).times { print ' ' } - puts "| #{item}" - i += 1 + puts I18n.t('form.set_config.valid').to_s.green + rescue => e + puts "#{I18n.t('display.error')} #15: #{e}".red + exit 2 end - print "\n" - end + # Create a new config file + # @args: options -> set param + def setup(options) + options[:lang] = options[:lang] || Locale::Tag.parse(ENV['LANG']).to_simple.to_s[0..1] - # Format items on a table - def table_items(items = []) - group = '.' - i = 1 - length_total = 10 - data = { id: { length: 3, color: 'cyan' }, - host: { length: 9, color: 'yellow' }, - user: { length: 7, color: 'green' }, - protocol: { length: 9, color: 'white' }, - port: { length: 5, color: 'white' }, - otp: { length: 4, color: 'white' }, - comment: { length: 14, color: 'magenta' } } + I18n.locale = options[:lang].to_sym - items.each do |item| - data.each do |k, v| - next if k == :id || k == :otp + @config.setup(options) - v[:length] = item.send(k.to_s).to_s.length + 3 if item.send(k.to_s).to_s.length >= v[:length] - end + load_config + + puts I18n.t('form.setup_config.valid').to_s.green + rescue => e + puts "#{I18n.t('display.error')} #8: #{e}".red + exit 2 end - data[:id][:length] = items.length.to_s.length + 2 if items.length.to_s.length > data[:id][:length] - data.each_value { |v| length_total += v[:length] } - items.sort! { |a, b| a.group.to_s.downcase <=> b.group.to_s.downcase } + # Setup a new GPG key + # @args: gpg_key -> the key name + def setup_gpg_key(gpg_key) + return if @config.check_gpg_key? - items.each do |item| - if group != item.group - group = item.group + password = ask(I18n.t('form.setup_gpg_key.password')) { |q| q.echo = false } + confirm = ask(I18n.t('form.setup_gpg_key.confirm_password')) { |q| q.echo = false } - if group.to_s.empty? - puts "\n#{I18n.t('display.no_group')}".red - else - puts "\n#{group}".red - end + raise I18n.t('form.setup_gpg_key.error_password') if password != confirm - print ' ' - length_total.times { print '=' } - print "\n " - data.each do |k, v| - case k - when :id - print ' ID' - when :otp - print '| OTP' - else - print "| #{k.to_s.capitalize}" - end + @password = password.to_s - (v[:length] - k.to_s.length).times { print ' ' } - end - print "\n " - length_total.times { print '=' } - print "\n" + puts I18n.t('form.setup_gpg_key.wait') + + @config.setup_gpg_key(@password, gpg_key) + + puts I18n.t('form.setup_gpg_key.valid').to_s.green + rescue => e + puts "#{I18n.t('display.error')} #8: #{e}".red + exit 2 + end + + # List gpg keys in wallet + def list_keys + table_list('keys', @mpw.list_keys) + end + + # Load config + def load_config + @config.load_config + rescue => e + puts "#{I18n.t('display.error')} #10: #{e}".red + exit 2 + end + + # Request the GPG password and decrypt the file + def decrypt + unless defined?(@mpw) + @password = ask(I18n.t('display.gpg_password')) { |q| q.echo = false } + @mpw = MPW.new(@config.gpg_key, @wallet_file, @password, @config.gpg_exe) end - print " #{i}".send(data[:id][:color]) - (data[:id][:length] - i.to_s.length).times { print ' ' } - data.each do |k, v| - next if k == :id + @mpw.read_data + rescue => e + puts "#{I18n.t('display.error')} #11: #{e}".red + exit 2 + end - if k == :otp - print '| ' - item.otp ? (print ' X ') : 4.times { print ' ' } + # Format list on a table + def table_list(title, list) + i = 1 + length = 0 - next - end - - print '| ' - print item.send(k.to_s).to_s.send(v[:color]) - (v[:length] - item.send(k.to_s).to_s.length).times { print ' ' } + list.each do |item| + length = item.length if length < item.length end + length += 7 + + puts "\n#{I18n.t("display.#{title}")}".red + print ' ' + length.times { print '=' } print "\n" - i += 1 + list.each do |item| + print " #{i}".cyan + (3 - i.to_s.length).times { print ' ' } + puts "| #{item}" + i += 1 + end + + print "\n" end - print "\n" - end + # Format items on a table + def table_items(items = []) + group = '.' + i = 1 + length_total = 10 + data = { id: { length: 3, color: 'cyan' }, + host: { length: 9, color: 'yellow' }, + user: { length: 7, color: 'green' }, + protocol: { length: 9, color: 'white' }, + port: { length: 5, color: 'white' }, + otp: { length: 4, color: 'white' }, + comment: { length: 14, color: 'magenta' } } - # Display the query's result - # @args: options -> the option to search - def list(**options) - result = @mpw.list(options) + items.each do |item| + data.each do |k, v| + next if k == :id || k == :otp - if result.empty? - puts I18n.t('display.nothing') - else - table_items(result) - end - end + v[:length] = item.send(k.to_s).to_s.length + 3 if item.send(k.to_s).to_s.length >= v[:length] + end + end + data[:id][:length] = items.length.to_s.length + 2 if items.length.to_s.length > data[:id][:length] - # Get an item when multiple choice - # @args: items -> array of items - # @rtrn: item - def get_item(items) - return items[0] if items.length == 1 + data.each_value { |v| length_total += v[:length] } + items.sort! { |a, b| a.group.to_s.downcase <=> b.group.to_s.downcase } - items.sort! { |a, b| a.group.to_s.downcase <=> b.group.to_s.downcase } - choice = ask(I18n.t('form.select')).to_i + items.each do |item| + if group != item.group + group = item.group - choice >= 1 && choice <= items.length ? items[choice - 1] : nil - end + if group.to_s.empty? + puts "\n#{I18n.t('display.no_group')}".red + else + puts "\n#{group}".red + end - # Copy in clipboard the login and password - # @args: item -> the item - # clipboard -> enable clipboard - def clipboard(item, clipboard = true) - # Security: force quit after 90s - Thread.new do - sleep 90 - exit - end + print ' ' + length_total.times { print '=' } + print "\n " + data.each do |k, v| + case k + when :id + print ' ID' + when :otp + print '| OTP' + else + print "| #{k.to_s.capitalize}" + end - Kernel.loop do - choice = ask(I18n.t('form.clipboard.choice')).to_s - - case choice - when 'q', 'quit' - break - - when 'l', 'login' - if clipboard - Clipboard.copy(item.user) - puts I18n.t('form.clipboard.login').green - else - puts item.user + (v[:length] - k.to_s.length).times { print ' ' } + end + print "\n " + length_total.times { print '=' } + print "\n" end - when 'p', 'password' - if clipboard - Clipboard.copy(@mpw.get_password(item.id)) - puts I18n.t('form.clipboard.password').yellow + print " #{i}".send(data[:id][:color]) + (data[:id][:length] - i.to_s.length).times { print ' ' } + data.each do |k, v| + next if k == :id - Thread.new do - sleep 30 + if k == :otp + print '| ' + item.otp ? (print ' X ') : 4.times { print ' ' } - Clipboard.clear + next + end + + print '| ' + print item.send(k.to_s).to_s.send(v[:color]) + (v[:length] - item.send(k.to_s).to_s.length).times { print ' ' } + end + print "\n" + + i += 1 + end + + print "\n" + end + + # Display the query's result + # @args: options -> the option to search + def list(**options) + result = @mpw.list(options) + + if result.empty? + puts I18n.t('display.nothing') + else + table_items(result) + end + end + + # Get an item when multiple choice + # @args: items -> array of items + # @rtrn: item + def get_item(items) + return items[0] if items.length == 1 + + items.sort! { |a, b| a.group.to_s.downcase <=> b.group.to_s.downcase } + choice = ask(I18n.t('form.select')).to_i + + choice >= 1 && choice <= items.length ? items[choice - 1] : nil + end + + # Copy in clipboard the login and password + # @args: item -> the item + # clipboard -> enable clipboard + def clipboard(item, clipboard = true) + # Security: force quit after 90s + Thread.new do + sleep 90 + exit + end + + Kernel.loop do + choice = ask(I18n.t('form.clipboard.choice')).to_s + + case choice + when 'q', 'quit' + break + + when 'l', 'login' + if clipboard + Clipboard.copy(item.user) + puts I18n.t('form.clipboard.login').green + else + puts item.user + end + + when 'p', 'password' + if clipboard + Clipboard.copy(@mpw.get_password(item.id)) + puts I18n.t('form.clipboard.password').yellow + + Thread.new do + sleep 30 + + Clipboard.clear + end + else + puts @mpw.get_password(item.id) + end + + when 'o', 'otp' + if clipboard + Clipboard.copy(@mpw.get_otp_code(item.id)) + else + puts @mpw.get_otp_code(item.id) + end + puts I18n.t('form.clipboard.otp', time: @mpw.get_otp_remaining_time).yellow + + else + puts "----- #{I18n.t('form.clipboard.help.name')} -----".cyan + puts I18n.t('form.clipboard.help.login') + puts I18n.t('form.clipboard.help.password') + puts I18n.t('form.clipboard.help.otp_code') + puts I18n.t('form.clipboard.help.quit') + next + end + end + + Clipboard.clear + rescue SystemExit, Interrupt + Clipboard.clear + end + + # List all wallets + def list_wallet + wallets = [] + Dir.glob("#{@config.wallet_dir}/*.mpw").each do |f| + wallet = File.basename(f, '.mpw') + wallet += ' *'.green if wallet == @config.default_wallet + wallets << wallet + end + + table_list('wallets', wallets) + end + + # Display the wallet + # @args: wallet -> the wallet name + def get_wallet(wallet = nil) + @wallet_file = + if wallet.to_s.empty? + wallets = Dir.glob("#{@config.wallet_dir}/*.mpw") + + if wallets.length == 1 + wallets[0] + elsif !@config.default_wallet.to_s.empty? + "#{@config.wallet_dir}/#{@config.default_wallet}.mpw" + else + "#{@config.wallet_dir}/default.mpw" end else - puts @mpw.get_password(item.id) + "#{@config.wallet_dir}/#{wallet}.mpw" + end + end + + # Add a new public key + # args: key -> the key name or key file to add + def add_key(key) + @mpw.add_key(key) + @mpw.write_data + + puts I18n.t('form.add_key.valid').to_s.green + rescue => e + puts "#{I18n.t('display.error')} #13: #{e}".red + end + + # Add new public key + # args: key -> the key name to delete + def delete_key(key) + @mpw.delete_key(key) + @mpw.write_data + + puts I18n.t('form.delete_key.valid').to_s.green + rescue => e + puts "#{I18n.t('display.error')} #15: #{e}".red + end + + # Text editor interface + # @args: template -> template name + # item -> the item to edit + # password -> disable field password + def text_editor(template_name, item = nil, password = false) + editor = ENV['EDITOR'] || 'nano' + options = {} + opts = {} + template_file = "#{File.expand_path('../../../templates', __FILE__)}/#{template_name}.erb" + template = ERB.new(IO.read(template_file)) + + Dir.mktmpdir do |dir| + tmp_file = "#{dir}/#{template_name}.yml" + + File.open(tmp_file, 'w') do |f| + f << template.result(binding) end - when 'o', 'otp' - if clipboard - Clipboard.copy(@mpw.get_otp_code(item.id)) - else - puts @mpw.get_otp_code(item.id) - end - puts I18n.t('form.clipboard.otp', time: @mpw.get_otp_remaining_time).yellow + system("#{editor} #{tmp_file}") - else - puts "----- #{I18n.t('form.clipboard.help.name')} -----".cyan - puts I18n.t('form.clipboard.help.login') - puts I18n.t('form.clipboard.help.password') - puts I18n.t('form.clipboard.help.otp_code') - puts I18n.t('form.clipboard.help.quit') - next - end - end - - Clipboard.clear - rescue SystemExit, Interrupt - Clipboard.clear - end - - # List all wallets - def list_wallet - wallets = [] - Dir.glob("#{@config.wallet_dir}/*.mpw").each do |f| - wallet = File.basename(f, '.mpw') - wallet += ' *'.green if wallet == @config.default_wallet - wallets << wallet - end - - table_list('wallets', wallets) - end - - # Display the wallet - # @args: wallet -> the wallet name - def get_wallet(wallet = nil) - @wallet_file = - if wallet.to_s.empty? - wallets = Dir.glob("#{@config.wallet_dir}/*.mpw") - - if wallets.length == 1 - wallets[0] - elsif !@config.default_wallet.to_s.empty? - "#{@config.wallet_dir}/#{@config.default_wallet}.mpw" - else - "#{@config.wallet_dir}/default.mpw" - end - else - "#{@config.wallet_dir}/#{wallet}.mpw" - end - end - - # Add a new public key - # args: key -> the key name or key file to add - def add_key(key) - @mpw.add_key(key) - @mpw.write_data - - puts I18n.t('form.add_key.valid').to_s.green - rescue => e - puts "#{I18n.t('display.error')} #13: #{e}".red - end - - # Add new public key - # args: key -> the key name to delete - def delete_key(key) - @mpw.delete_key(key) - @mpw.write_data - - puts I18n.t('form.delete_key.valid').to_s.green - rescue => e - puts "#{I18n.t('display.error')} #15: #{e}".red - end - - # Text editor interface - # @args: template -> template name - # item -> the item to edit - # password -> disable field password - def text_editor(template_name, item = nil, password = false) - editor = ENV['EDITOR'] || 'nano' - options = {} - opts = {} - template_file = "#{File.expand_path('../../../templates', __FILE__)}/#{template_name}.erb" - template = ERB.new(IO.read(template_file)) - - Dir.mktmpdir do |dir| - tmp_file = "#{dir}/#{template_name}.yml" - - File.open(tmp_file, 'w') do |f| - f << template.result(binding) + opts = YAML.load_file(tmp_file) end - system("#{editor} #{tmp_file}") + opts.delete_if { |_, v| v.to_s.empty? } - opts = YAML.load_file(tmp_file) + opts.each do |k, v| + options[k.to_sym] = v + end + + options end - opts.delete_if { |_, v| v.to_s.empty? } - - opts.each do |k, v| - options[k.to_sym] = v - end - - options - end - - # Form to add a new item - # @args: password -> generate a random password - def add(password = false) - options = text_editor('add_form', nil, password) - item = Item.new(options) - options[:password] = MPW.password(@config.password) if password - - @mpw.add(item) - @mpw.set_password(item.id, options[:password]) if options.key?(:password) - @mpw.set_otp_key(item.id, options[:otp_key]) if options.key?(:otp_key) - @mpw.write_data - - puts I18n.t('form.add_item.valid').to_s.green - rescue => e - puts "#{I18n.t('display.error')} #13: #{e}".red - end - - # Update an item - # @args: password -> generate a random password - # options -> the option to search - def update(password = false, **options) - items = @mpw.list(options) - - if items.empty? - puts "#{I18n.t('display.warning')}: #{I18n.t('warning.select')}".yellow - else - table_items(items) if items.length > 1 - - item = get_item(items) - options = text_editor('update_form', item, password) + # Form to add a new item + # @args: password -> generate a random password + def add(password = false) + options = text_editor('add_form', nil, password) + item = Item.new(options) options[:password] = MPW.password(@config.password) if password - item.update(options) + @mpw.add(item) @mpw.set_password(item.id, options[:password]) if options.key?(:password) @mpw.set_otp_key(item.id, options[:otp_key]) if options.key?(:otp_key) @mpw.write_data - puts I18n.t('form.update_item.valid').to_s.green + puts I18n.t('form.add_item.valid').to_s.green + rescue => e + puts "#{I18n.t('display.error')} #13: #{e}".red end - rescue => e - puts "#{I18n.t('display.error')} #14: #{e}".red - end - # Remove an item - # @args: options -> the option to search - def delete(**options) - items = @mpw.list(options) + # Update an item + # @args: password -> generate a random password + # options -> the option to search + def update(password = false, **options) + items = @mpw.list(options) - if items.empty? - puts "#{I18n.t('display.warning')}: #{I18n.t('warning.select')}".yellow - else - table_items(items) + if items.empty? + puts "#{I18n.t('display.warning')}: #{I18n.t('warning.select')}".yellow + else + table_items(items) if items.length > 1 - item = get_item(items) - confirm = ask("#{I18n.t('form.delete_item.ask')} (y/N) ").to_s + item = get_item(items) + options = text_editor('update_form', item, password) + options[:password] = MPW.password(@config.password) if password - return unless confirm =~ /^(y|yes|YES|Yes|Y)$/ + item.update(options) + @mpw.set_password(item.id, options[:password]) if options.key?(:password) + @mpw.set_otp_key(item.id, options[:otp_key]) if options.key?(:otp_key) + @mpw.write_data + + puts I18n.t('form.update_item.valid').to_s.green + end + rescue => e + puts "#{I18n.t('display.error')} #14: #{e}".red + end + + # Remove an item + # @args: options -> the option to search + def delete(**options) + items = @mpw.list(options) + + if items.empty? + puts "#{I18n.t('display.warning')}: #{I18n.t('warning.select')}".yellow + else + table_items(items) + + item = get_item(items) + confirm = ask("#{I18n.t('form.delete_item.ask')} (y/N) ").to_s + + return unless confirm =~ /^(y|yes|YES|Yes|Y)$/ + + item.delete + @mpw.write_data + + puts I18n.t('form.delete_item.valid').to_s.green + end + rescue => e + puts "#{I18n.t('display.error')} #16: #{e}".red + end + + # Copy a password, otp, login + # @args: clipboard -> enable clipboard + # options -> the option to search + def copy(clipboard = true, **options) + items = @mpw.list(options) + + if items.empty? + puts I18n.t('display.nothing') + else + table_items(items) + + item = get_item(items) + clipboard(item, clipboard) + end + rescue => e + puts "#{I18n.t('display.error')} #14: #{e}".red + end + + # Export the items in a CSV file + # @args: file -> the destination file + # options -> option to search + def export(file, options) + file = 'export-mpw.yml' if file.to_s.empty? + items = @mpw.list(options) + data = {} + + items.each do |item| + data.merge!( + item.id => { + 'host' => item.host, + 'user' => item.user, + 'group' => item.group, + 'password' => @mpw.get_password(item.id), + 'protocol' => item.protocol, + 'port' => item.port, + 'otp_key' => @mpw.get_otp_key(item.id), + 'comment' => item.comment, + 'last_edit' => item.last_edit, + 'created' => item.created, + } + ) + end + + File.open(file, 'w') { |f| f << data.to_yaml } + + puts I18n.t('form.export.valid', file: file).to_s.green + rescue => e + puts "#{I18n.t('display.error')} #17: #{e}".red + end + + # Import items from a YAML file + # @args: file -> the import file + def import(file) + raise I18n.t('form.import.file_empty') if file.to_s.empty? + raise I18n.t('form.import.file_not_exist') unless File.exist?(file) + + YAML.load_file(file).each_value do |row| + item = Item.new(group: row['group'], + host: row['host'], + protocol: row['protocol'], + user: row['user'], + port: row['port'], + comment: row['comment']) + + next if item.empty? + + @mpw.add(item) + @mpw.set_password(item.id, row['password']) unless row['password'].to_s.empty? + @mpw.set_otp_key(item.id, row['otp_key']) unless row['otp_key'].to_s.empty? + end - item.delete @mpw.write_data - puts I18n.t('form.delete_item.valid').to_s.green + puts I18n.t('form.import.valid').to_s.green + rescue => e + puts "#{I18n.t('display.error')} #18: #{e}".red end - rescue => e - puts "#{I18n.t('display.error')} #16: #{e}".red - end - - # Copy a password, otp, login - # @args: clipboard -> enable clipboard - # options -> the option to search - def copy(clipboard = true, **options) - items = @mpw.list(options) - - if items.empty? - puts I18n.t('display.nothing') - else - table_items(items) - - item = get_item(items) - clipboard(item, clipboard) - end - rescue => e - puts "#{I18n.t('display.error')} #14: #{e}".red - end - - # Export the items in a CSV file - # @args: file -> the destination file - # options -> option to search - def export(file, options) - file = 'export-mpw.yml' if file.to_s.empty? - items = @mpw.list(options) - data = {} - - items.each do |item| - data.merge!( - item.id => { - 'host' => item.host, - 'user' => item.user, - 'group' => item.group, - 'password' => @mpw.get_password(item.id), - 'protocol' => item.protocol, - 'port' => item.port, - 'otp_key' => @mpw.get_otp_key(item.id), - 'comment' => item.comment, - 'last_edit' => item.last_edit, - 'created' => item.created, - } - ) - end - - File.open(file, 'w') { |f| f << data.to_yaml } - - puts I18n.t('form.export.valid', file: file).to_s.green - rescue => e - puts "#{I18n.t('display.error')} #17: #{e}".red - end - - # Import items from a YAML file - # @args: file -> the import file - def import(file) - raise I18n.t('form.import.file_empty') if file.to_s.empty? - raise I18n.t('form.import.file_not_exist') unless File.exist?(file) - - YAML.load_file(file).each_value do |row| - item = Item.new(group: row['group'], - host: row['host'], - protocol: row['protocol'], - user: row['user'], - port: row['port'], - comment: row['comment']) - - next if item.empty? - - @mpw.add(item) - @mpw.set_password(item.id, row['password']) unless row['password'].to_s.empty? - @mpw.set_otp_key(item.id, row['otp_key']) unless row['otp_key'].to_s.empty? - end - - @mpw.write_data - - puts I18n.t('form.import.valid').to_s.green - rescue => e - puts "#{I18n.t('display.error')} #18: #{e}".red end end -end diff --git a/lib/mpw/config.rb b/lib/mpw/config.rb index d691559..3b88b0a 100644 --- a/lib/mpw/config.rb +++ b/lib/mpw/config.rb @@ -22,133 +22,133 @@ require 'i18n' require 'fileutils' module MPW -class Config - attr_accessor :error_msg + class Config + attr_accessor :error_msg - attr_accessor :gpg_key - attr_accessor :lang - attr_accessor :config_dir - attr_accessor :default_wallet - attr_accessor :wallet_dir - attr_accessor :gpg_exe - attr_accessor :password + attr_accessor :gpg_key + attr_accessor :lang + attr_accessor :config_dir + attr_accessor :default_wallet + attr_accessor :wallet_dir + attr_accessor :gpg_exe + attr_accessor :password - # Constructor - # @args: config_file -> the specify config file - def initialize(config_file = nil) - @config_file = config_file + # Constructor + # @args: config_file -> the specify config file + def initialize(config_file = nil) + @config_file = config_file - @config_dir = - if /darwin/ =~ RUBY_PLATFORM - "#{Dir.home}/Library/Preferences/mpw" - elsif /cygwin|mswin|mingw|bccwin|wince|emx/ =~ RUBY_PLATFORM - "#{Dir.home}/AppData/Local/mpw" - else - "#{Dir.home}/.config/mpw" + @config_dir = + if /darwin/ =~ RUBY_PLATFORM + "#{Dir.home}/Library/Preferences/mpw" + elsif /cygwin|mswin|mingw|bccwin|wince|emx/ =~ RUBY_PLATFORM + "#{Dir.home}/AppData/Local/mpw" + else + "#{Dir.home}/.config/mpw" + end + + @config_file = "#{@config_dir}/mpw.cfg" if @config_file.nil? || @config_file.empty? + end + + # Create a new config file + # @args: options -> hash with values + # @rtrn: true if le config file is create + def setup(options) + gpg_key = options[:gpg_key] || @gpg_key + lang = options[:lang] || @lang + wallet_dir = options[:wallet_dir] || @wallet_dir + default_wallet = options[:default_wallet] || @default_wallet + gpg_exe = options[:gpg_exe] || @gpg_exe + password = { numeric: true, + alpha: true, + special: false, + length: 16 } + + %w(numeric special alpha length).each do |k| + if options.key?("pwd_#{k}".to_sym) + password[k.to_sym] = options["pwd_#{k}".to_sym] + elsif !@password.nil? && @password.key?(k.to_sym) + password[k.to_sym] = @password[k.to_sym] + end end - @config_file = "#{@config_dir}/mpw.cfg" if @config_file.nil? || @config_file.empty? - end - - # Create a new config file - # @args: options -> hash with values - # @rtrn: true if le config file is create - def setup(options) - gpg_key = options[:gpg_key] || @gpg_key - lang = options[:lang] || @lang - wallet_dir = options[:wallet_dir] || @wallet_dir - default_wallet = options[:default_wallet] || @default_wallet - gpg_exe = options[:gpg_exe] || @gpg_exe - password = { numeric: true, - alpha: true, - special: false, - length: 16 } - - %w(numeric special alpha length).each do |k| - if options.key?("pwd_#{k}".to_sym) - password[k.to_sym] = options["pwd_#{k}".to_sym] - elsif !@password.nil? && @password.key?(k.to_sym) - password[k.to_sym] = @password[k.to_sym] + unless gpg_key =~ /[a-zA-Z0-9.-_]+\@[a-zA-Z0-9]+\.[a-zA-Z]+/ + raise I18n.t('error.config.key_bad_format') end + + wallet_dir = "#{@config_dir}/wallets" if wallet_dir.to_s.empty? + config = { 'gpg_key' => gpg_key, + 'lang' => lang, + 'wallet_dir' => wallet_dir, + 'default_wallet' => default_wallet, + 'gpg_exe' => gpg_exe, + 'password' => password } + + FileUtils.mkdir_p(@config_dir, mode: 0700) + FileUtils.mkdir_p(wallet_dir, mode: 0700) + + File.open(@config_file, 'w') do |file| + file << config.to_yaml + end + rescue => e + raise "#{I18n.t('error.config.write')}\n#{e}" end - unless gpg_key =~ /[a-zA-Z0-9.-_]+\@[a-zA-Z0-9]+\.[a-zA-Z]+/ - raise I18n.t('error.config.key_bad_format') + # Setup a new gpg key + # @args: password -> the GPG key password + # name -> the name of user + # length -> length of the GPG key + # expire -> the time of expire to GPG key + # @rtrn: true if the GPG key is create, else false + def setup_gpg_key(password, name, length = 4096, expire = 0) + raise I18n.t('error.config.genkey_gpg.name') if name.to_s.empty? + raise I18n.t('error.config.genkey_gpg.password') if password.to_s.empty? + + param = '' + param << '<GnupgKeyParms format="internal">' + "\n" + param << "Key-Type: RSA\n" + param << "Key-Length: #{length}\n" + param << "Subkey-Type: ELG-E\n" + param << "Subkey-Length: #{length}\n" + param << "Name-Real: #{name}\n" + param << "Name-Comment: #{name}\n" + param << "Name-Email: #{@gpg_key}\n" + param << "Expire-Date: #{expire}\n" + param << "Passphrase: #{password}\n" + param << "</GnupgKeyParms>\n" + + ctx = GPGME::Ctx.new + ctx.genkey(param, nil, nil) + rescue => e + raise "#{I18n.t('error.config.genkey_gpg.exception')}\n#{e}" end - wallet_dir = "#{@config_dir}/wallets" if wallet_dir.to_s.empty? - config = { 'gpg_key' => gpg_key, - 'lang' => lang, - 'wallet_dir' => wallet_dir, - 'default_wallet' => default_wallet, - 'gpg_exe' => gpg_exe, - 'password' => password } + # Load the config file + def load_config + config = YAML.load_file(@config_file) + @gpg_key = config['gpg_key'] + @lang = config['lang'] + @wallet_dir = config['wallet_dir'] + @default_wallet = config['default_wallet'] + @gpg_exe = config['gpg_exe'] + @password = config['password'] || {} - FileUtils.mkdir_p(@config_dir, mode: 0700) - FileUtils.mkdir_p(wallet_dir, mode: 0700) + raise if @gpg_key.empty? || @wallet_dir.empty? - File.open(@config_file, 'w') do |file| - file << config.to_yaml - end - rescue => e - raise "#{I18n.t('error.config.write')}\n#{e}" - end - - # Setup a new gpg key - # @args: password -> the GPG key password - # name -> the name of user - # length -> length of the GPG key - # expire -> the time of expire to GPG key - # @rtrn: true if the GPG key is create, else false - def setup_gpg_key(password, name, length = 4096, expire = 0) - raise I18n.t('error.config.genkey_gpg.name') if name.to_s.empty? - raise I18n.t('error.config.genkey_gpg.password') if password.to_s.empty? - - param = '' - param << '<GnupgKeyParms format="internal">' + "\n" - param << "Key-Type: RSA\n" - param << "Key-Length: #{length}\n" - param << "Subkey-Type: ELG-E\n" - param << "Subkey-Length: #{length}\n" - param << "Name-Real: #{name}\n" - param << "Name-Comment: #{name}\n" - param << "Name-Email: #{@gpg_key}\n" - param << "Expire-Date: #{expire}\n" - param << "Passphrase: #{password}\n" - param << "</GnupgKeyParms>\n" - - ctx = GPGME::Ctx.new - ctx.genkey(param, nil, nil) - rescue => e - raise "#{I18n.t('error.config.genkey_gpg.exception')}\n#{e}" - end - - # Load the config file - def load_config - config = YAML.load_file(@config_file) - @gpg_key = config['gpg_key'] - @lang = config['lang'] - @wallet_dir = config['wallet_dir'] - @default_wallet = config['default_wallet'] - @gpg_exe = config['gpg_exe'] - @password = config['password'] || {} - - raise if @gpg_key.empty? || @wallet_dir.empty? - - I18n.locale = @lang.to_sym - rescue => e - raise "#{I18n.t('error.config.load')}\n#{e}" - end - - # Check if private key exist - # @rtrn: true if the key exist, else false - def check_gpg_key? - ctx = GPGME::Ctx.new - ctx.each_key(@gpg_key, true) do - return true + I18n.locale = @lang.to_sym + rescue => e + raise "#{I18n.t('error.config.load')}\n#{e}" end - false + # Check if private key exist + # @rtrn: true if the key exist, else false + def check_gpg_key? + ctx = GPGME::Ctx.new + ctx.each_key(@gpg_key, true) do + return true + end + + false + end end end -end diff --git a/lib/mpw/item.rb b/lib/mpw/item.rb index cd24168..8b4b867 100644 --- a/lib/mpw/item.rb +++ b/lib/mpw/item.rb @@ -19,84 +19,84 @@ require 'i18n' module MPW -class Item - attr_accessor :id - attr_accessor :group - attr_accessor :host - attr_accessor :protocol - attr_accessor :user - attr_accessor :port - attr_accessor :otp - attr_accessor :comment - attr_accessor :last_edit - attr_accessor :created + class Item + attr_accessor :id + attr_accessor :group + attr_accessor :host + attr_accessor :protocol + attr_accessor :user + attr_accessor :port + attr_accessor :otp + attr_accessor :comment + attr_accessor :last_edit + attr_accessor :created - # Constructor - # Create a new item - # @args: options -> a hash of parameter - # raise an error if the hash hasn't the key name - def initialize(**options) - if !options.key?(:host) || options[:host].to_s.empty? - raise I18n.t('error.update.host_empty') + # Constructor + # Create a new item + # @args: options -> a hash of parameter + # raise an error if the hash hasn't the key name + def initialize(**options) + if !options.key?(:host) || options[:host].to_s.empty? + raise I18n.t('error.update.host_empty') + end + + if !options.key?(:id) || options[:id].to_s.empty? || !options.key?(:created) || options[:created].to_s.empty? + @id = generate_id + @created = Time.now.to_i + else + @id = options[:id] + @created = options[:created] + @last_edit = options[:last_edit] + options[:no_update_last_edit] = true + end + + update(options) end - if !options.key?(:id) || options[:id].to_s.empty? || !options.key?(:created) || options[:created].to_s.empty? - @id = generate_id - @created = Time.now.to_i - else - @id = options[:id] - @created = options[:created] - @last_edit = options[:last_edit] - options[:no_update_last_edit] = true + # Update the item + # @args: options -> a hash of parameter + def update(**options) + if options.key?(:host) && options[:host].to_s.empty? + raise I18n.t('error.update.host_empty') + end + + @group = options[:group] if options.key?(:group) + @host = options[:host] if options.key?(:host) + @protocol = options[:protocol] if options.key?(:protocol) + @user = options[:user] if options.key?(:user) + @port = options[:port].to_i if options.key?(:port) && !options[:port].to_s.empty? + @otp = options[:otp] if options.key?(:otp) + @comment = options[:comment] if options.key?(:comment) + @last_edit = Time.now.to_i unless options.key?(:no_update_last_edit) end - update(options) - end - - # Update the item - # @args: options -> a hash of parameter - def update(**options) - if options.key?(:host) && options[:host].to_s.empty? - raise I18n.t('error.update.host_empty') + # Delete all data + def delete + @id = nil + @group = nil + @host = nil + @protocol = nil + @user = nil + @port = nil + @otp = nil + @comment = nil + @created = nil + @last_edit = nil end - @group = options[:group] if options.key?(:group) - @host = options[:host] if options.key?(:host) - @protocol = options[:protocol] if options.key?(:protocol) - @user = options[:user] if options.key?(:user) - @port = options[:port].to_i if options.key?(:port) && !options[:port].to_s.empty? - @otp = options[:otp] if options.key?(:otp) - @comment = options[:comment] if options.key?(:comment) - @last_edit = Time.now.to_i unless options.key?(:no_update_last_edit) - end + def empty? + @id.to_s.empty? + end - # Delete all data - def delete - @id = nil - @group = nil - @host = nil - @protocol = nil - @user = nil - @port = nil - @otp = nil - @comment = nil - @created = nil - @last_edit = nil - end + def nil? + false + end - def empty? - @id.to_s.empty? - end + private - def nil? - false - end - - private - - # Generate an random id - def generate_id - [*('A'..'Z'), *('a'..'z'), *('0'..'9')].sample(16).join + # Generate an random id + def generate_id + [*('A'..'Z'), *('a'..'z'), *('0'..'9')].sample(16).join + end end end -end diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index daf04ff..8389be9 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -24,341 +24,341 @@ require 'rotp' require 'mpw/item' module MPW -class MPW - # Constructor - def initialize(key, wallet_file, gpg_pass = nil, gpg_exe = nil) - @key = key - @gpg_pass = gpg_pass - @gpg_exe = gpg_exe - @wallet_file = wallet_file + class MPW + # Constructor + def initialize(key, wallet_file, gpg_pass = nil, gpg_exe = nil) + @key = key + @gpg_pass = gpg_pass + @gpg_exe = gpg_exe + @wallet_file = wallet_file - GPGME::Engine.set_info(GPGME::PROTOCOL_OpenPGP, @gpg_exe, "#{Dir.home}/.gnupg") unless @gpg_exe.to_s.empty? - end - - # Read mpw file - def read_data - @config = {} - @data = [] - @keys = {} - @passwords = {} - @otp_keys = {} - - data = nil - - return unless File.exist?(@wallet_file) - - Gem::Package::TarReader.new(File.open(@wallet_file)) do |tar| - tar.each do |f| - case f.full_name - when 'wallet/config.gpg' - @config = YAML.safe_load(decrypt(f.read)) - - when 'wallet/meta.gpg' - data = decrypt(f.read) - - when %r{^wallet/keys/(?<key>.+)\.pub$} - key = Regexp.last_match('key') - - if GPGME::Key.find(:public, key).empty? - GPGME::Key.import(f.read, armor: true) - end - - @keys[key] = f.read - - when %r{^wallet/passwords/(?<id>[a-zA-Z0-9]+)\.gpg$} - @passwords[Regexp.last_match('id')] = f.read - - when %r{^wallet/otp_keys/(?<id>[a-zA-Z0-9]+)\.gpg$} - @otp_keys[Regexp.last_match('id')] = f.read - - else - next - end - end + GPGME::Engine.set_info(GPGME::PROTOCOL_OpenPGP, @gpg_exe, "#{Dir.home}/.gnupg") unless @gpg_exe.to_s.empty? end - unless data.to_s.empty? - YAML.safe_load(data).each_value do |d| - @data.push( - Item.new( - id: d['id'], - group: d['group'], - host: d['host'], - protocol: d['protocol'], - user: d['user'], - port: d['port'], - otp: @otp_keys.key?(d['id']), - comment: d['comment'], - last_edit: d['last_edit'], - created: d['created'], + # Read mpw file + def read_data + @config = {} + @data = [] + @keys = {} + @passwords = {} + @otp_keys = {} + + data = nil + + return unless File.exist?(@wallet_file) + + Gem::Package::TarReader.new(File.open(@wallet_file)) do |tar| + tar.each do |f| + case f.full_name + when 'wallet/config.gpg' + @config = YAML.safe_load(decrypt(f.read)) + + when 'wallet/meta.gpg' + data = decrypt(f.read) + + when %r{^wallet/keys/(?<key>.+)\.pub$} + key = Regexp.last_match('key') + + if GPGME::Key.find(:public, key).empty? + GPGME::Key.import(f.read, armor: true) + end + + @keys[key] = f.read + + when %r{^wallet/passwords/(?<id>[a-zA-Z0-9]+)\.gpg$} + @passwords[Regexp.last_match('id')] = f.read + + when %r{^wallet/otp_keys/(?<id>[a-zA-Z0-9]+)\.gpg$} + @otp_keys[Regexp.last_match('id')] = f.read + + else + next + end + end + end + + unless data.to_s.empty? + YAML.safe_load(data).each_value do |d| + @data.push( + Item.new( + id: d['id'], + group: d['group'], + host: d['host'], + protocol: d['protocol'], + user: d['user'], + port: d['port'], + otp: @otp_keys.key?(d['id']), + comment: d['comment'], + last_edit: d['last_edit'], + created: d['created'], + ) ) + end + end + + add_key(@key) if @keys[@key].nil? + rescue => e + raise "#{I18n.t('error.mpw_file.read_data')}\n#{e}" + end + + # Encrypt a file + def write_data + data = {} + tmp_file = "#{@wallet_file}.tmp" + + @data.each do |item| + next if item.empty? + + data.merge!( + item.id => { + 'id' => item.id, + 'group' => item.group, + 'host' => item.host, + 'protocol' => item.protocol, + 'user' => item.user, + 'port' => item.port, + 'comment' => item.comment, + 'last_edit' => item.last_edit, + 'created' => item.created, + } ) end - end - add_key(@key) if @keys[@key].nil? - rescue => e - raise "#{I18n.t('error.mpw_file.read_data')}\n#{e}" - end + @config['last_update'] = Time.now.to_i - # Encrypt a file - def write_data - data = {} - tmp_file = "#{@wallet_file}.tmp" + Gem::Package::TarWriter.new(File.open(tmp_file, 'w+')) do |tar| + data_encrypt = encrypt(data.to_yaml) + tar.add_file_simple('wallet/meta.gpg', 0400, data_encrypt.length) do |io| + io.write(data_encrypt) + end - @data.each do |item| - next if item.empty? + config = encrypt(@config.to_yaml) + tar.add_file_simple('wallet/config.gpg', 0400, config.length) do |io| + io.write(config) + end - data.merge!( - item.id => { - 'id' => item.id, - 'group' => item.group, - 'host' => item.host, - 'protocol' => item.protocol, - 'user' => item.user, - 'port' => item.port, - 'comment' => item.comment, - 'last_edit' => item.last_edit, - 'created' => item.created, - } - ) - end + @passwords.each do |id, password| + tar.add_file_simple("wallet/passwords/#{id}.gpg", 0400, password.length) do |io| + io.write(password) + end + end - @config['last_update'] = Time.now.to_i + @otp_keys.each do |id, key| + tar.add_file_simple("wallet/otp_keys/#{id}.gpg", 0400, key.length) do |io| + io.write(key) + end + end - Gem::Package::TarWriter.new(File.open(tmp_file, 'w+')) do |tar| - data_encrypt = encrypt(data.to_yaml) - tar.add_file_simple('wallet/meta.gpg', 0400, data_encrypt.length) do |io| - io.write(data_encrypt) - end - - config = encrypt(@config.to_yaml) - tar.add_file_simple('wallet/config.gpg', 0400, config.length) do |io| - io.write(config) - end - - @passwords.each do |id, password| - tar.add_file_simple("wallet/passwords/#{id}.gpg", 0400, password.length) do |io| - io.write(password) + @keys.each do |id, key| + tar.add_file_simple("wallet/keys/#{id}.pub", 0400, key.length) do |io| + io.write(key) + end end end - @otp_keys.each do |id, key| - tar.add_file_simple("wallet/otp_keys/#{id}.gpg", 0400, key.length) do |io| - io.write(key) - end - end + File.rename(tmp_file, @wallet_file) + rescue => e + File.unlink(tmp_file) if File.exist?(tmp_file) - @keys.each do |id, key| - tar.add_file_simple("wallet/keys/#{id}.pub", 0400, key.length) do |io| - io.write(key) - end - end + raise "#{I18n.t('error.mpw_file.write_data')}\n#{e}" end - File.rename(tmp_file, @wallet_file) - rescue => e - File.unlink(tmp_file) if File.exist?(tmp_file) + # Get a password + # args: id -> the item id + def get_password(id) + password = decrypt(@passwords[id]) - raise "#{I18n.t('error.mpw_file.write_data')}\n#{e}" - end - - # Get a password - # args: id -> the item id - def get_password(id) - password = decrypt(@passwords[id]) - - if /^\$[a-zA-Z0-9]{4,9}::(?<password>.+)$/ =~ password - Regexp.last_match('password') - else - password - end - end - - # Set a password - # args: id -> the item id - # password -> the new password - def set_password(id, password) - salt = MPW.password(length: Random.rand(4..9)) - password = "$#{salt}::#{password}" - - @passwords[id] = encrypt(password) - end - - # Return the list of all gpg keys - # rtrn: an array with the gpg keys name - def list_keys - @keys.keys - end - - # Add a public key - # args: key -> new public key file or name - def add_key(key) - if File.exist?(key) - data = File.open(key).read - key_import = GPGME::Key.import(data, armor: true) - key = GPGME::Key.get(key_import.imports[0].fpr).uids[0].email - else - data = GPGME::Key.export(key, armor: true).read - end - - raise I18n.t('error.export_key') if data.to_s.empty? - - @keys[key] = data - @passwords.each_key { |id| set_password(id, get_password(id)) } - @otp_keys.each_key { |id| set_otp_key(id, get_otp_key(id)) } - end - - # Delete a public key - # args: key -> public key to delete - def delete_key(key) - @keys.delete(key) - @passwords.each_key { |id| set_password(id, get_password(id)) } - @otp_keys.each_key { |id| set_otp_key(id, get_otp_key(id)) } - end - - # Set config - # args: config -> a hash with config options - def set_config(**options) - @config = {} if @config.nil? - - @config['protocol'] = options[:protocol] if options.key?(:protocol) - @config['host'] = options[:host] if options.key?(:host) - @config['port'] = options[:port] if options.key?(:port) - @config['user'] = options[:user] if options.key?(:user) - @config['password'] = options[:password] if options.key?(:password) - @config['path'] = options[:path] if options.key?(:path) - end - - # Add a new item - # @args: item -> Object MPW::Item - def add(item) - raise I18n.t('error.bad_class') unless item.instance_of?(Item) - raise I18n.t('error.empty') if item.empty? - - @data.push(item) - end - - # Search in some csv data - # @args: options -> a hash with paramaters - # @rtrn: a list with the resultat of the search - def list(**options) - result = [] - - search = options[:pattern].to_s.downcase - group = options[:group].to_s.downcase - - @data.each do |item| - next if item.empty? - next unless group.empty? || group.eql?(item.group.to_s.downcase) - - host = item.host.to_s.downcase - comment = item.comment.to_s.downcase - - next unless host =~ /^.*#{search}.*$/ || comment =~ /^.*#{search}.*$/ - - result.push(item) - end - - result - end - - # Search in some csv data - # @args: id -> the id item - # @rtrn: a row with the result of the search - def search_by_id(id) - @data.each do |item| - return item if item.id == id - end - - nil - end - - # Set an opt key - # args: id -> the item id - # key -> the new key - def set_otp_key(id, key) - @otp_keys[id] = encrypt(key.to_s) unless key.to_s.empty? - end - - # Get an opt key - # args: id -> the item id - # key -> the new key - def get_otp_key(id) - @otp_keys.key?(id) ? decrypt(@otp_keys[id]) : nil - end - - # Get an otp code - # @args: id -> the item id - # @rtrn: an otp code - def get_otp_code(id) - @otp_keys.key?(id) ? 0 : ROTP::TOTP.new(decrypt(@otp_keys[id])).now - end - - # Get remaining time before expire otp code - # @rtrn: return time in seconde - def get_otp_remaining_time - (Time.now.utc.to_i / 30 + 1) * 30 - Time.now.utc.to_i - end - - # Generate a random password - # @args: options -> :length, :special, :alpha, :numeric - # @rtrn: a random string - def self.password(**options) - length = - if !options.include?(:length) || options[:length].to_i <= 0 - 8 - elsif options[:length].to_i >= 32_768 - 32_768 + if /^\$[a-zA-Z0-9]{4,9}::(?<password>.+)$/ =~ password + Regexp.last_match('password') else - options[:length].to_i + password + end + end + + # Set a password + # args: id -> the item id + # password -> the new password + def set_password(id, password) + salt = MPW.password(length: Random.rand(4..9)) + password = "$#{salt}::#{password}" + + @passwords[id] = encrypt(password) + end + + # Return the list of all gpg keys + # rtrn: an array with the gpg keys name + def list_keys + @keys.keys + end + + # Add a public key + # args: key -> new public key file or name + def add_key(key) + if File.exist?(key) + data = File.open(key).read + key_import = GPGME::Key.import(data, armor: true) + key = GPGME::Key.get(key_import.imports[0].fpr).uids[0].email + else + data = GPGME::Key.export(key, armor: true).read end - chars = [] - chars += [*('!'..'?')] - [*('0'..'9')] if options[:special] - chars += [*('A'..'Z'), *('a'..'z')] if options[:alpha] - chars += [*('0'..'9')] if options[:numeric] - chars = [*('A'..'Z'), *('a'..'z'), *('0'..'9')] if chars.empty? + raise I18n.t('error.export_key') if data.to_s.empty? - result = '' - while length > 62 - result << chars.sample(62).join - length -= 62 - end - result << chars.sample(length).join - - result - end - - private - - # Decrypt a gpg file - # @args: data -> string to decrypt - def decrypt(data) - return nil if data.to_s.empty? - - crypto = GPGME::Crypto.new(armor: true) - - crypto.decrypt(data, password: @gpg_pass).read.force_encoding('utf-8') - rescue => e - raise "#{I18n.t('error.gpg_file.decrypt')}\n#{e}" - end - - # Encrypt a file - # args: data -> string to encrypt - def encrypt(data) - recipients = [] - crypto = GPGME::Crypto.new(armor: true, always_trust: true) - - recipients.push(@key) - @keys.each_key do |key| - next if key == @key - recipients.push(key) + @keys[key] = data + @passwords.each_key { |id| set_password(id, get_password(id)) } + @otp_keys.each_key { |id| set_otp_key(id, get_otp_key(id)) } end - crypto.encrypt(data, recipients: recipients).read - rescue => e - raise "#{I18n.t('error.gpg_file.encrypt')}\n#{e}" + # Delete a public key + # args: key -> public key to delete + def delete_key(key) + @keys.delete(key) + @passwords.each_key { |id| set_password(id, get_password(id)) } + @otp_keys.each_key { |id| set_otp_key(id, get_otp_key(id)) } + end + + # Set config + # args: config -> a hash with config options + def set_config(**options) + @config = {} if @config.nil? + + @config['protocol'] = options[:protocol] if options.key?(:protocol) + @config['host'] = options[:host] if options.key?(:host) + @config['port'] = options[:port] if options.key?(:port) + @config['user'] = options[:user] if options.key?(:user) + @config['password'] = options[:password] if options.key?(:password) + @config['path'] = options[:path] if options.key?(:path) + end + + # Add a new item + # @args: item -> Object MPW::Item + def add(item) + raise I18n.t('error.bad_class') unless item.instance_of?(Item) + raise I18n.t('error.empty') if item.empty? + + @data.push(item) + end + + # Search in some csv data + # @args: options -> a hash with paramaters + # @rtrn: a list with the resultat of the search + def list(**options) + result = [] + + search = options[:pattern].to_s.downcase + group = options[:group].to_s.downcase + + @data.each do |item| + next if item.empty? + next unless group.empty? || group.eql?(item.group.to_s.downcase) + + host = item.host.to_s.downcase + comment = item.comment.to_s.downcase + + next unless host =~ /^.*#{search}.*$/ || comment =~ /^.*#{search}.*$/ + + result.push(item) + end + + result + end + + # Search in some csv data + # @args: id -> the id item + # @rtrn: a row with the result of the search + def search_by_id(id) + @data.each do |item| + return item if item.id == id + end + + nil + end + + # Set an opt key + # args: id -> the item id + # key -> the new key + def set_otp_key(id, key) + @otp_keys[id] = encrypt(key.to_s) unless key.to_s.empty? + end + + # Get an opt key + # args: id -> the item id + # key -> the new key + def get_otp_key(id) + @otp_keys.key?(id) ? decrypt(@otp_keys[id]) : nil + end + + # Get an otp code + # @args: id -> the item id + # @rtrn: an otp code + def get_otp_code(id) + @otp_keys.key?(id) ? 0 : ROTP::TOTP.new(decrypt(@otp_keys[id])).now + end + + # Get remaining time before expire otp code + # @rtrn: return time in seconde + def get_otp_remaining_time + (Time.now.utc.to_i / 30 + 1) * 30 - Time.now.utc.to_i + end + + # Generate a random password + # @args: options -> :length, :special, :alpha, :numeric + # @rtrn: a random string + def self.password(**options) + length = + if !options.include?(:length) || options[:length].to_i <= 0 + 8 + elsif options[:length].to_i >= 32_768 + 32_768 + else + options[:length].to_i + end + + chars = [] + chars += [*('!'..'?')] - [*('0'..'9')] if options[:special] + chars += [*('A'..'Z'), *('a'..'z')] if options[:alpha] + chars += [*('0'..'9')] if options[:numeric] + chars = [*('A'..'Z'), *('a'..'z'), *('0'..'9')] if chars.empty? + + result = '' + while length > 62 + result << chars.sample(62).join + length -= 62 + end + result << chars.sample(length).join + + result + end + + private + + # Decrypt a gpg file + # @args: data -> string to decrypt + def decrypt(data) + return nil if data.to_s.empty? + + crypto = GPGME::Crypto.new(armor: true) + + crypto.decrypt(data, password: @gpg_pass).read.force_encoding('utf-8') + rescue => e + raise "#{I18n.t('error.gpg_file.decrypt')}\n#{e}" + end + + # Encrypt a file + # args: data -> string to encrypt + def encrypt(data) + recipients = [] + crypto = GPGME::Crypto.new(armor: true, always_trust: true) + + recipients.push(@key) + @keys.each_key do |key| + next if key == @key + recipients.push(key) + end + + crypto.encrypt(data, recipients: recipients).read + rescue => e + raise "#{I18n.t('error.gpg_file.encrypt')}\n#{e}" + end end end -end From 7eb585726faf69eb02367f236ed524e903adf39c Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <adrien.waksberg@doctolib.fr> Date: Thu, 30 Mar 2017 20:07:47 +0200 Subject: [PATCH 452/531] fix syntax on Genfile and mpw.gemspec --- Gemfile | 18 +++++++++--------- mpw.gemspec | 21 +++++++++++---------- 2 files changed, 20 insertions(+), 19 deletions(-) diff --git a/Gemfile b/Gemfile index a588d17..7e2d83c 100644 --- a/Gemfile +++ b/Gemfile @@ -1,10 +1,10 @@ source 'https://rubygems.org' -gem "i18n", "~> 0.7", ">= 0.7.0" -gem "gpgme", "~> 2.0", ">= 2.0.12" -gem "highline", "~> 1.7", ">= 1.7.8" -gem "locale", "~> 2.1", ">= 2.1.2" -gem "colorize", "~> 0.8", ">= 0.8.1" -gem "net-ssh", "~> 3.2", ">= 3.2.0" -gem "net-sftp", "~> 2.1", ">= 2.1.2" -gem "clipboard", "~> 1.1", ">= 1.1.1" -gem "rotp", "~> 3.1", ">= 3.1.0" +gem 'clipboard', '~> 1.1', '>= 1.1.1' +gem 'colorize', '~> 0.8', '>= 0.8.1' +gem 'gpgme', '~> 2.0', '>= 2.0.12' +gem 'highline', '~> 1.7', '>= 1.7.8' +gem 'i18n', '~> 0.7', '>= 0.7.0' +gem 'locale', '~> 2.1', '>= 2.1.2' +gem 'net-sftp', '~> 2.1', '>= 2.1.2' +gem 'net-ssh', '~> 3.2', '>= 3.2.0' +gem 'rotp', '~> 3.1', '>= 3.1.0' diff --git a/mpw.gemspec b/mpw.gemspec index 80d9344..7f687ab 100644 --- a/mpw.gemspec +++ b/mpw.gemspec @@ -1,4 +1,5 @@ # coding: utf-8 + lib = File.expand_path('../lib', __FILE__) $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) @@ -12,18 +13,18 @@ Gem::Specification.new do |spec| spec.homepage = 'https://github.com/nishiki/manage-password' spec.license = 'GPL-2.0' - spec.files = `git ls-files -z`.split("\x0") + spec.files = %x(git ls-files -z).split("\x0") spec.executables = ['mpw'] spec.test_files = spec.files.grep(%r{^(test|spec|features)/}) spec.require_paths = ['lib'] - spec.add_dependency "i18n", "~> 0.7", ">= 0.7.0" - spec.add_dependency "gpgme", "~> 2.0", ">= 2.0.12" - spec.add_dependency "highline", "~> 1.7", ">= 1.7.8" - spec.add_dependency "locale", "~> 2.1", ">= 2.1.2" - spec.add_dependency "colorize", "~> 0.8", ">= 0.8.1" - spec.add_dependency "net-ssh", "~> 3.2", ">= 3.2.0" - spec.add_dependency "net-sftp", "~> 2.1", ">= 2.1.2" - spec.add_dependency "clipboard", "~> 1.1", ">= 1.1.1" - spec.add_dependency "rotp", "~> 3.1", ">= 3.1.0" + spec.add_dependency 'i18n', '~> 0.7', '>= 0.7.0' + spec.add_dependency 'gpgme', '~> 2.0', '>= 2.0.12' + spec.add_dependency 'highline', '~> 1.7', '>= 1.7.8' + spec.add_dependency 'locale', '~> 2.1', '>= 2.1.2' + spec.add_dependency 'colorize', '~> 0.8', '>= 0.8.1' + spec.add_dependency 'net-ssh', '~> 3.2', '>= 3.2.0' + spec.add_dependency 'net-sftp', '~> 2.1', '>= 2.1.2' + spec.add_dependency 'clipboard', '~> 1.1', '>= 1.1.1' + spec.add_dependency 'rotp', '~> 3.1', '>= 3.1.0' end From 2cb8ad4dbe4806bedb64b257cd1bc45d65d85c7a Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Thu, 30 Mar 2017 20:18:49 +0200 Subject: [PATCH 453/531] add rubocop test in travis --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index 1a18023..faa5c04 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,8 +7,10 @@ rvm: install: - bundle install - gem install 'test-unit' + - gem install rubocop - echo 9999 > VERSION - gem build mpw.gemspec - gem install mpw-9999.gem script: + - rubocop - ruby ./test/tests.rb From 1e688d191cd9c45e748ecaa3c7fd51f848dca727 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Thu, 30 Mar 2017 22:41:12 +0200 Subject: [PATCH 454/531] remove unused dependancies --- Gemfile | 2 -- mpw.gemspec | 2 -- 2 files changed, 4 deletions(-) diff --git a/Gemfile b/Gemfile index 7e2d83c..71d84d4 100644 --- a/Gemfile +++ b/Gemfile @@ -5,6 +5,4 @@ gem 'gpgme', '~> 2.0', '>= 2.0.12' gem 'highline', '~> 1.7', '>= 1.7.8' gem 'i18n', '~> 0.7', '>= 0.7.0' gem 'locale', '~> 2.1', '>= 2.1.2' -gem 'net-sftp', '~> 2.1', '>= 2.1.2' -gem 'net-ssh', '~> 3.2', '>= 3.2.0' gem 'rotp', '~> 3.1', '>= 3.1.0' diff --git a/mpw.gemspec b/mpw.gemspec index 7f687ab..9f27023 100644 --- a/mpw.gemspec +++ b/mpw.gemspec @@ -23,8 +23,6 @@ Gem::Specification.new do |spec| spec.add_dependency 'highline', '~> 1.7', '>= 1.7.8' spec.add_dependency 'locale', '~> 2.1', '>= 2.1.2' spec.add_dependency 'colorize', '~> 0.8', '>= 0.8.1' - spec.add_dependency 'net-ssh', '~> 3.2', '>= 3.2.0' - spec.add_dependency 'net-sftp', '~> 2.1', '>= 2.1.2' spec.add_dependency 'clipboard', '~> 1.1', '>= 1.1.1' spec.add_dependency 'rotp', '~> 3.1', '>= 3.1.0' end From 92cb89ad33083a917710cafe057d4303c8bc91eb Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <adrien.waksberg@doctolib.fr> Date: Sun, 2 Apr 2017 12:14:27 +0200 Subject: [PATCH 455/531] fix gpg password with pinentry --- lib/mpw/mpw.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index 8389be9..2444f12 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -339,7 +339,7 @@ module MPW crypto = GPGME::Crypto.new(armor: true) - crypto.decrypt(data, password: @gpg_pass).read.force_encoding('utf-8') + crypto.decrypt(data, password: @gpg_pass, pinentry_mode: GPGME::PINENTRY_MODE_LOOPBACK).read.force_encoding('utf-8') rescue => e raise "#{I18n.t('error.gpg_file.decrypt')}\n#{e}" end From 3543b0cf05cfc4fc177dc54a0407a21951747aac Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Sun, 2 Apr 2017 22:39:31 +0200 Subject: [PATCH 456/531] remove unused wallet config --- lib/mpw/mpw.rb | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index 8389be9..c52f8db 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -37,7 +37,6 @@ module MPW # Read mpw file def read_data - @config = {} @data = [] @keys = {} @passwords = {} @@ -50,9 +49,6 @@ module MPW Gem::Package::TarReader.new(File.open(@wallet_file)) do |tar| tar.each do |f| case f.full_name - when 'wallet/config.gpg' - @config = YAML.safe_load(decrypt(f.read)) - when 'wallet/meta.gpg' data = decrypt(f.read) @@ -124,19 +120,12 @@ module MPW ) end - @config['last_update'] = Time.now.to_i - Gem::Package::TarWriter.new(File.open(tmp_file, 'w+')) do |tar| data_encrypt = encrypt(data.to_yaml) tar.add_file_simple('wallet/meta.gpg', 0400, data_encrypt.length) do |io| io.write(data_encrypt) end - config = encrypt(@config.to_yaml) - tar.add_file_simple('wallet/config.gpg', 0400, config.length) do |io| - io.write(config) - end - @passwords.each do |id, password| tar.add_file_simple("wallet/passwords/#{id}.gpg", 0400, password.length) do |io| io.write(password) @@ -217,19 +206,6 @@ module MPW @otp_keys.each_key { |id| set_otp_key(id, get_otp_key(id)) } end - # Set config - # args: config -> a hash with config options - def set_config(**options) - @config = {} if @config.nil? - - @config['protocol'] = options[:protocol] if options.key?(:protocol) - @config['host'] = options[:host] if options.key?(:host) - @config['port'] = options[:port] if options.key?(:port) - @config['user'] = options[:user] if options.key?(:user) - @config['password'] = options[:password] if options.key?(:password) - @config['path'] = options[:path] if options.key?(:path) - end - # Add a new item # @args: item -> Object MPW::Item def add(item) From d1adfd24c10ab9a4fd80cb3c08ebbfbc069bc585 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Sun, 2 Apr 2017 23:44:36 +0200 Subject: [PATCH 457/531] fix pinentry mode with gpg 1.4 --- lib/mpw/mpw.rb | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index 2444f12..88cab5c 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -337,9 +337,18 @@ module MPW def decrypt(data) return nil if data.to_s.empty? - crypto = GPGME::Crypto.new(armor: true) + password = + if /^1\.[0-9.]+$/ =~ GPGME::Engine.info.first.version + { password: @gpg_pass } + else + { password: @gpg_pass, + pinentry_mode: GPGME::PINENTRY_MODE_LOOPBACK } + end - crypto.decrypt(data, password: @gpg_pass, pinentry_mode: GPGME::PINENTRY_MODE_LOOPBACK).read.force_encoding('utf-8') + crypto = GPGME::Crypto.new(armor: true) + crypto + .decrypt(data, password) + .read.force_encoding('utf-8') rescue => e raise "#{I18n.t('error.gpg_file.decrypt')}\n#{e}" end From 7ce4ba721bb039f30af6882dca9c55e748b58944 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Tue, 4 Apr 2017 23:45:03 +0200 Subject: [PATCH 458/531] add option to enable pinmode with gpg >= 2.1 --- bin/mpw-config | 6 +++++- lib/mpw/cli.rb | 2 +- lib/mpw/config.rb | 6 +++++- lib/mpw/mpw.rb | 5 +++-- 4 files changed, 14 insertions(+), 5 deletions(-) diff --git a/bin/mpw-config b/bin/mpw-config index 4740ed1..1e3480d 100644 --- a/bin/mpw-config +++ b/bin/mpw-config @@ -60,6 +60,10 @@ OptionParser.new do |opts| values[:lang] = lang end + opts.on('-P', '--pinmode', I18n.t('option.pinmode')) do + values[:pinmode] = true + end + opts.on('-w', '--wallet-dir PATH', I18n.t('option.wallet_dir')) do |wallet_dir| values[:wallet_dir] = wallet_dir end @@ -94,7 +98,7 @@ OptionParser.new do |opts| end.parse! config = MPW::Config.new(options[:config]) -cli = MPW::Cli.new(config, nil) +cli = MPW::Cli.new(config) if options.key?(:init) cli.setup(values) diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index d4d4027..56e77a1 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -101,7 +101,7 @@ module MPW def decrypt unless defined?(@mpw) @password = ask(I18n.t('display.gpg_password')) { |q| q.echo = false } - @mpw = MPW.new(@config.gpg_key, @wallet_file, @password, @config.gpg_exe) + @mpw = MPW.new(@config.gpg_key, @wallet_file, @password, @config.gpg_exe, @config.pinmode) end @mpw.read_data diff --git a/lib/mpw/config.rb b/lib/mpw/config.rb index 3b88b0a..829abc2 100644 --- a/lib/mpw/config.rb +++ b/lib/mpw/config.rb @@ -32,6 +32,7 @@ module MPW attr_accessor :wallet_dir attr_accessor :gpg_exe attr_accessor :password + attr_accessor :pinmode # Constructor # @args: config_file -> the specify config file @@ -59,6 +60,7 @@ module MPW wallet_dir = options[:wallet_dir] || @wallet_dir default_wallet = options[:default_wallet] || @default_wallet gpg_exe = options[:gpg_exe] || @gpg_exe + pinmode = options[:pinmode] || @pinmode password = { numeric: true, alpha: true, special: false, @@ -82,7 +84,8 @@ module MPW 'wallet_dir' => wallet_dir, 'default_wallet' => default_wallet, 'gpg_exe' => gpg_exe, - 'password' => password } + 'password' => password, + 'pinmode' => pinmode } FileUtils.mkdir_p(@config_dir, mode: 0700) FileUtils.mkdir_p(wallet_dir, mode: 0700) @@ -132,6 +135,7 @@ module MPW @default_wallet = config['default_wallet'] @gpg_exe = config['gpg_exe'] @password = config['password'] || {} + @pinmode = config['pinmode'] raise if @gpg_key.empty? || @wallet_dir.empty? diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index 88cab5c..7d15b52 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -26,11 +26,12 @@ require 'mpw/item' module MPW class MPW # Constructor - def initialize(key, wallet_file, gpg_pass = nil, gpg_exe = nil) + def initialize(key, wallet_file, gpg_pass = nil, gpg_exe = nil, pinmode = false) @key = key @gpg_pass = gpg_pass @gpg_exe = gpg_exe @wallet_file = wallet_file + @pinmode = pinmode GPGME::Engine.set_info(GPGME::PROTOCOL_OpenPGP, @gpg_exe, "#{Dir.home}/.gnupg") unless @gpg_exe.to_s.empty? end @@ -338,7 +339,7 @@ module MPW return nil if data.to_s.empty? password = - if /^1\.[0-9.]+$/ =~ GPGME::Engine.info.first.version + if /^1\.[0-9.]+$/ =~ GPGME::Engine.info.first.version || @pinmode { password: @gpg_pass } else { password: @gpg_pass, From d8df357993212cc6d43148eaeb3f907f7479fa5c Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Tue, 4 Apr 2017 23:50:38 +0200 Subject: [PATCH 459/531] not use pinmode if gpg version < 2.1 --- lib/mpw/mpw.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index 7d15b52..dd12ef6 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -339,7 +339,7 @@ module MPW return nil if data.to_s.empty? password = - if /^1\.[0-9.]+$/ =~ GPGME::Engine.info.first.version || @pinmode + if /^(1\.[0-9.]+|2\.0)(\.[0-9]+)?/ =~ GPGME::Engine.info.first.version || @pinmode { password: @gpg_pass } else { password: @gpg_pass, From 45ead1e24e13fda0161dab564198980ae2b57abd Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Tue, 4 Apr 2017 23:52:00 +0200 Subject: [PATCH 460/531] fix syntax for rubocop 0.48.1 --- lib/mpw/config.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/mpw/config.rb b/lib/mpw/config.rb index 829abc2..591b991 100644 --- a/lib/mpw/config.rb +++ b/lib/mpw/config.rb @@ -66,7 +66,7 @@ module MPW special: false, length: 16 } - %w(numeric special alpha length).each do |k| + %w[numeric special alpha length].each do |k| if options.key?("pwd_#{k}".to_sym) password[k.to_sym] = options["pwd_#{k}".to_sym] elsif !@password.nil? && @password.key?(k.to_sym) From 621819203f4025c9632f79971383c76b8c0415bf Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Wed, 5 Apr 2017 00:03:53 +0200 Subject: [PATCH 461/531] add option to disable pinmode --- bin/mpw-config | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/bin/mpw-config b/bin/mpw-config index 1e3480d..67ffc50 100644 --- a/bin/mpw-config +++ b/bin/mpw-config @@ -60,10 +60,14 @@ OptionParser.new do |opts| values[:lang] = lang end - opts.on('-P', '--pinmode', I18n.t('option.pinmode')) do + opts.on('-P', '--enable-pinmode', I18n.t('option.pinmode')) do values[:pinmode] = true end + opts.on('-p', '--disable-pinmode', I18n.t('option.disable_pinmode')) do + values[:pinmode] = false + end + opts.on('-w', '--wallet-dir PATH', I18n.t('option.wallet_dir')) do |wallet_dir| values[:wallet_dir] = wallet_dir end From 3b5bb48e6ba6cdcc9ae60783a62a85440e406761 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Wed, 5 Apr 2017 00:04:15 +0200 Subject: [PATCH 462/531] add translate for pinmode options --- i18n/en.yml | 2 ++ i18n/fr.yml | 2 ++ 2 files changed, 4 insertions(+) diff --git a/i18n/en.yml b/i18n/en.yml index 162f6b3..97f1928 100644 --- a/i18n/en.yml +++ b/i18n/en.yml @@ -49,6 +49,7 @@ en: delete_gpg_key: "Delete the wallet's share with an other GPG key" disable_alpha: "Don't use letter to generate a password" disable_numeric: "Don't use number to generate a password" + disable_pinmode: "Disable the pinentry mode" disable_special_chars: "Don't use special char to generate a password" export: "Export a wallet in an yaml file" file_export: "Specify the file where export data" @@ -68,6 +69,7 @@ en: list_keys: "List the GPG keys in wallet" numeric: "Use number to generate a password" pattern: "Given search pattern" + pinmode: "Enable pinentry mode (available with gpg >= 2.1)" random_password: "Generate a random password" setup: "Create a new configuration file" setup_wallet: "Create a new configuration file for a wallet" diff --git a/i18n/fr.yml b/i18n/fr.yml index b2e3db4..0c7319c 100644 --- a/i18n/fr.yml +++ b/i18n/fr.yml @@ -49,6 +49,7 @@ fr: delete_gpg_key: "Supprime le partage le portefeuille avec une autre clé GPG" disable_alpha: "Désactive l'utilisation des lettres dans la génération d'un mot de passe" disable_numeric: "Désactive l'utilisation des chiffre dans la génération d'un mot de passe" + disable_pinmode: "Désactive le mode pinentry" disable_special_chars: "Désactive l'utilisation des charactères speciaux dans la génération d'un mot de passe" export: "Exporte un portefeuille dans un fichier yaml" file_export: "Spécifie le fichier où exporter les données" @@ -68,6 +69,7 @@ fr: list_keys: "Liste les clés GPG dans le portefeuille" numeric: "Utilise des chiffre dans la génération d'un mot de passe" pattern: "Motif de donnée à chercher" + pinmode: "Active le mode pinentry (valable avec gpg >= 2.1)" random_password: "Génére un mot de passe aléatoire" setup: "Création d'un nouveau fichier de configuration" setup_wallet: "Création d'un nouveau fichier de configuration pour un portefeuille" From 55c07b90af363055bc2131f04030e500e2c56f72 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Sat, 8 Apr 2017 10:04:43 +0200 Subject: [PATCH 463/531] minor refacto --- bin/mpw-wallet | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/bin/mpw-wallet b/bin/mpw-wallet index fffeaac..8bbffcf 100644 --- a/bin/mpw-wallet +++ b/bin/mpw-wallet @@ -66,19 +66,15 @@ cli = MPW::Cli.new(config) cli.load_config -if !options[:list].nil? +if options.key?(:list) cli.list_wallet else cli.get_wallet(options[:wallet]) cli.decrypt - if !options[:list_keys].nil? + if options.key?(:list_keys) cli.list_keys - elsif !options[:gpg_key].nil? - if options[:delete] - cli.delete_key(options[:gpg_key]) - else - cli.add_key(options[:gpg_key]) - end + elsif options.key?(:gpg_key) + options[:delete] ? cli.delete_key(options[:gpg_key]) : cli.add_key(options[:gpg_key]) end end From 25baa260e33756fc0efeb17c525e2563470c75fa Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Sat, 8 Apr 2017 17:15:05 +0200 Subject: [PATCH 464/531] feat: add option to set a specific path for a wallet --- bin/mpw-wallet | 11 +++++++++++ i18n/en.yml | 4 ++++ i18n/fr.yml | 4 ++++ lib/mpw/cli.rb | 29 +++++++++++++++++++++++------ lib/mpw/config.rb | 38 ++++++++++++++++++++++++++++++++++---- 5 files changed, 76 insertions(+), 10 deletions(-) diff --git a/bin/mpw-wallet b/bin/mpw-wallet index 8bbffcf..5b3b7f9 100644 --- a/bin/mpw-wallet +++ b/bin/mpw-wallet @@ -56,6 +56,14 @@ OptionParser.new do |opts| options[:list_keys] = true end + opts.on('-p', '--path PATH', I18n.t('option.path')) do |path| + options[:path] = path + end + + opts.on('-P', '--default-path', I18n.t('option.default_path')) do + options[:path] = 'default' + end + opts.on('-w', '--wallet NAME', I18n.t('option.wallet')) do |wallet| options[:wallet] = wallet end @@ -68,6 +76,9 @@ cli.load_config if options.key?(:list) cli.list_wallet +elsif options.key?(:path) + cli.get_wallet(options[:wallet]) + cli.set_wallet_path(options[:path]) else cli.get_wallet(options[:wallet]) cli.decrypt diff --git a/i18n/en.yml b/i18n/en.yml index 97f1928..1fa2618 100644 --- a/i18n/en.yml +++ b/i18n/en.yml @@ -45,6 +45,7 @@ en: alpha: "Use letter to generate a password" config: "Specify the configuration file to use" clipboard: "Disable the clipboard feature" + default_path: "Move the wallet in default directory" default_wallet: "Specify the default wallet to use" delete_gpg_key: "Delete the wallet's share with an other GPG key" disable_alpha: "Don't use letter to generate a password" @@ -68,6 +69,7 @@ en: list: "List the wallets" list_keys: "List the GPG keys in wallet" numeric: "Use number to generate a password" + path: "Move the wallet in new specify directory" pattern: "Given search pattern" pinmode: "Enable pinentry mode (available with gpg >= 2.1)" random_password: "Generate a random password" @@ -120,6 +122,8 @@ en: not_valid: "No data to import!" set_config: valid: "The config file has been edited!" + set_wallet_path: + valid: "The wallet has well moved!" setup_config: title: "Setup a new config file" lang: "Choose your language (en, fr, ...) [default=%{lang}]: " diff --git a/i18n/fr.yml b/i18n/fr.yml index 0c7319c..76b07ef 100644 --- a/i18n/fr.yml +++ b/i18n/fr.yml @@ -45,6 +45,7 @@ fr: alpha: "Utilise des lettres dans la génération d'un mot de passe" config: "Spécifie le fichier de configuration à utiliser" clipboard: "Désactive la fonction presse papier" + default_path: "Déplace le portefeuille dans le dossier par défaut" default_wallet: "Spécifie le porte-feuille à utiliser par défaut" delete_gpg_key: "Supprime le partage le portefeuille avec une autre clé GPG" disable_alpha: "Désactive l'utilisation des lettres dans la génération d'un mot de passe" @@ -68,6 +69,7 @@ fr: list: "Liste les portefeuilles" list_keys: "Liste les clés GPG dans le portefeuille" numeric: "Utilise des chiffre dans la génération d'un mot de passe" + path: "Déplace le portefeuille dans un nouveau dossier" pattern: "Motif de donnée à chercher" pinmode: "Active le mode pinentry (valable avec gpg >= 2.1)" random_password: "Génére un mot de passe aléatoire" @@ -120,6 +122,8 @@ fr: not_valid: "Aucune donnée à importer!" set_config: valid: "Le fichier de configuration a bien été modifié!" + set_wallet_path: + valid: "Le portefeuille a bien été déplacé!" setup_config: title: "Création d'un nouveau fichier de configuration" lang: "Choisissez votre langue (en, fr, ...) [défaut=%{lang}]: " diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index 56e77a1..23114d1 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -45,6 +45,17 @@ module MPW exit 2 end + # Change the wallet path + # @args: path -> the new path + def set_wallet_path(path) + @config.set_wallet_path(path, @wallet) + + puts I18n.t('form.set_wallet_path.valid').to_s.green + rescue => e + puts "#{I18n.t('display.error')} #19: #{e}".red + exit 2 + end + # Create a new config file # @args: options -> set param def setup(options) @@ -315,19 +326,25 @@ module MPW # Display the wallet # @args: wallet -> the wallet name def get_wallet(wallet = nil) - @wallet_file = + @wallet = if wallet.to_s.empty? wallets = Dir.glob("#{@config.wallet_dir}/*.mpw") - if wallets.length == 1 - wallets[0] + File.basename(wallets[0], '.mpw') elsif !@config.default_wallet.to_s.empty? - "#{@config.wallet_dir}/#{@config.default_wallet}.mpw" + @config.default_wallet else - "#{@config.wallet_dir}/default.mpw" + 'default' end else - "#{@config.wallet_dir}/#{wallet}.mpw" + wallet + end + + @wallet_file = + if @config.wallet_paths.key?(@wallet) + "#{@config.wallet_paths[@wallet]}/#{@wallet}.mpw" + else + "#{@config.wallet_dir}/#{@wallet}.mpw" end end diff --git a/lib/mpw/config.rb b/lib/mpw/config.rb index 591b991..fd78cf8 100644 --- a/lib/mpw/config.rb +++ b/lib/mpw/config.rb @@ -30,6 +30,7 @@ module MPW attr_accessor :config_dir attr_accessor :default_wallet attr_accessor :wallet_dir + attr_accessor :wallet_paths attr_accessor :gpg_exe attr_accessor :password attr_accessor :pinmode @@ -38,8 +39,7 @@ module MPW # @args: config_file -> the specify config file def initialize(config_file = nil) @config_file = config_file - - @config_dir = + @config_dir = if /darwin/ =~ RUBY_PLATFORM "#{Dir.home}/Library/Preferences/mpw" elsif /cygwin|mswin|mingw|bccwin|wince|emx/ =~ RUBY_PLATFORM @@ -48,7 +48,7 @@ module MPW "#{Dir.home}/.config/mpw" end - @config_file = "#{@config_dir}/mpw.cfg" if @config_file.nil? || @config_file.empty? + @config_file = "#{@config_dir}/mpw.cfg" if @config_file.to_s.empty? end # Create a new config file @@ -85,7 +85,8 @@ module MPW 'default_wallet' => default_wallet, 'gpg_exe' => gpg_exe, 'password' => password, - 'pinmode' => pinmode } + 'pinmode' => pinmode, + 'wallet_paths' => @wallet_paths } FileUtils.mkdir_p(@config_dir, mode: 0700) FileUtils.mkdir_p(wallet_dir, mode: 0700) @@ -132,6 +133,7 @@ module MPW @gpg_key = config['gpg_key'] @lang = config['lang'] @wallet_dir = config['wallet_dir'] + @wallet_paths = config['wallet_paths'] || {} @default_wallet = config['default_wallet'] @gpg_exe = config['gpg_exe'] @password = config['password'] || {} @@ -154,5 +156,33 @@ module MPW false end + + # Change the path of one wallet + # @args: path -> the new directory path + # wallet -> the wallet name + def set_wallet_path(path, wallet) + path = @wallet_dir if path == 'default' + + return if path == @wallet_dir && File.exist?("#{@wallet_dir}/#{wallet}.mpw") + return if path == @wallet_paths[wallet] + + old_wallet_file = + if @wallet_paths.key?(wallet) + "#{@wallet_paths[wallet]}/#{wallet}.mpw" + else + "#{@wallet_dir}/#{wallet}.mpw" + end + + FileUtils.mkdir_p(path) unless Dir.exist?(path) + FileUtils.mv(old_wallet_file, "#{path}/#{wallet}.mpw") if File.exist?(old_wallet_file) + + if path == @wallet_dir + @wallet_paths.delete(wallet) + else + @wallet_paths[wallet] = path + end + + setup + end end end From 18ba8967d9b634eeb8cb5f65df6e9f3f92949df0 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Sat, 8 Apr 2017 17:27:56 +0200 Subject: [PATCH 465/531] add test for wallet_paths --- test/test_config.rb | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/test/test_config.rb b/test/test_config.rb index 2d1a51b..49af82c 100644 --- a/test/test_config.rb +++ b/test/test_config.rb @@ -61,4 +61,19 @@ class TestConfig < Test::Unit::TestCase assert(!@config.password[:numeric]) assert(@config.password[:special]) end + + def test_02_wallet_paths + new_path = '/tmp/mpw-test' + + @config = MPW::Config.new + @config.load_config + + assert(!@config.wallet_paths['default']) + + @config.set_wallet_path(new_path, 'default') + assert_equal(@config.wallet_paths['default'], new_path) + + @config.set_wallet_path('default', 'default') + assert(!@config.wallet_paths['default']) + end end From 388dc439b6baf9bfff10645a5dfad0191e5c36b5 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Sat, 8 Apr 2017 17:39:51 +0200 Subject: [PATCH 466/531] fix argument in config setup --- lib/mpw/config.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/mpw/config.rb b/lib/mpw/config.rb index fd78cf8..fa1a825 100644 --- a/lib/mpw/config.rb +++ b/lib/mpw/config.rb @@ -54,7 +54,7 @@ module MPW # Create a new config file # @args: options -> hash with values # @rtrn: true if le config file is create - def setup(options) + def setup(**options) gpg_key = options[:gpg_key] || @gpg_key lang = options[:lang] || @lang wallet_dir = options[:wallet_dir] || @wallet_dir From b65595d0b7eea175bf20a5bce731fb9732e35d9a Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Sun, 9 Apr 2017 08:47:07 +0200 Subject: [PATCH 467/531] minor refacto --- lib/mpw/mpw.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index c6a5cf0..896339c 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -93,7 +93,7 @@ module MPW end end - add_key(@key) if @keys[@key].nil? + add_key(@key) unless @keys.key?(@key) rescue => e raise "#{I18n.t('error.mpw_file.read_data')}\n#{e}" end From 3f9d7eff3368b2042311fe54b38f8e07d18ec2d8 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Sun, 9 Apr 2017 10:08:25 +0200 Subject: [PATCH 468/531] feat: add print configuration --- bin/mpw-config | 6 +++++- i18n/en.yml | 1 + i18n/fr.yml | 1 + lib/mpw/cli.rb | 46 +++++++++++++++++++++++++++++++++++----------- 4 files changed, 42 insertions(+), 12 deletions(-) diff --git a/bin/mpw-config b/bin/mpw-config index 67ffc50..04f960b 100644 --- a/bin/mpw-config +++ b/bin/mpw-config @@ -112,5 +112,9 @@ if options.key?(:init) cli.setup_wallet_config else cli.load_config - cli.set_config(values) + if values.empty? + cli.list_config + else + cli.set_config(values) + end end diff --git a/i18n/en.yml b/i18n/en.yml index 1fa2618..5ed50c7 100644 --- a/i18n/en.yml +++ b/i18n/en.yml @@ -159,6 +159,7 @@ en: display: comment: "Comment" + config: "Configuration" error: "ERROR" keys: "GPG keys" gpg_password: "GPG passphrase: " diff --git a/i18n/fr.yml b/i18n/fr.yml index 76b07ef..13829a2 100644 --- a/i18n/fr.yml +++ b/i18n/fr.yml @@ -159,6 +159,7 @@ fr: display: comment: "Commentaire" + config: "Configuration" error: "ERREUR" keys: "Clés GPG" gpg_password: "Mot de passe GPG: " diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index 23114d1..22b24cb 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -100,6 +100,21 @@ module MPW table_list('keys', @mpw.list_keys) end + # List config + def list_config + config = { + 'lang' => @config.lang, + 'gpg_key' => @config.gpg_key, + 'config_dir' => @config.config_dir, + 'pinmode' => @config.pinmode, + 'gpg_exe' => @config.gpg_exe + } + + @config.password.each { |k, v| config["password_#{k}"] = v } + + table_list('config', config) + end + # Load config def load_config @config.load_config @@ -122,31 +137,40 @@ module MPW end # Format list on a table + # @args: title -> the name of table + # list -> array or hash def table_list(title, list) - i = 1 - length = 0 + length = { k: 0, v: 0 } - list.each do |item| - length = item.length if length < item.length + if list.is_a?(Array) + i = 0 + list = list.map do |item| + i += 1 + [i, item] + end.to_h + end + + list.each do |k, v| + length[:k] = k.to_s.length if length[:k] < k.to_s.length + length[:v] = v.to_s.length if length[:v] < v.to_s.length end - length += 7 puts "\n#{I18n.t("display.#{title}")}".red print ' ' - length.times { print '=' } + (length[:k] + length[:v] + 5).times { print '=' } print "\n" - list.each do |item| - print " #{i}".cyan - (3 - i.to_s.length).times { print ' ' } - puts "| #{item}" - i += 1 + list.each do |k, v| + print " #{k}".cyan + (length[:k] - k.to_s.length + 1).times { print ' ' } + puts "| #{v}" end print "\n" end # Format items on a table + # @args: items -> an aray items def table_items(items = []) group = '.' i = 1 From 77bca426bca26c81dff1ccdaec9c51f247017a52 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Sun, 9 Apr 2017 11:02:07 +0200 Subject: [PATCH 469/531] add information in print config --- lib/mpw/cli.rb | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index 22b24cb..6fd257f 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -103,14 +103,16 @@ module MPW # List config def list_config config = { - 'lang' => @config.lang, - 'gpg_key' => @config.gpg_key, - 'config_dir' => @config.config_dir, - 'pinmode' => @config.pinmode, - 'gpg_exe' => @config.gpg_exe + 'lang' => @config.lang, + 'gpg_key' => @config.gpg_key, + 'default_wallet' => @config.default_wallet, + 'config_dir' => @config.config_dir, + 'pinmode' => @config.pinmode, + 'gpg_exe' => @config.gpg_exe } - @config.password.each { |k, v| config["password_#{k}"] = v } + @config.wallet_paths.each { |k, v| config["path_wallet_#{k}"] = "#{v}/#{k}.mpw" } + @config.password.each { |k, v| config["password_#{k}"] = v } table_list('config', config) end From 0fdefdf4332d33e88bcfc1027addd159e70e4c45 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Thu, 13 Apr 2017 22:35:57 +0200 Subject: [PATCH 470/531] feat: add options to edit or update an item --- bin/mpw-add | 38 +++++++++++++++++++++++++++++++++-- bin/mpw-update | 42 +++++++++++++++++++++++++++++++++++---- i18n/en.yml | 8 ++++++++ i18n/fr.yml | 8 ++++++++ lib/mpw/cli.rb | 26 ++++++++++++++---------- templates/add_form.erb | 16 +++++++-------- templates/update_form.erb | 14 ++++++------- 7 files changed, 120 insertions(+), 32 deletions(-) diff --git a/bin/mpw-add b/bin/mpw-add index 6376326..20eaf7b 100644 --- a/bin/mpw-add +++ b/bin/mpw-add @@ -24,7 +24,9 @@ require 'mpw/cli' # Options # --------------------------------------------------------- # -options = {} +values = {} +options = {} +options[:text_editor] = true OptionParser.new do |opts| opts.banner = "#{I18n.t('option.usage')}: mpw add [options]" @@ -33,15 +35,47 @@ OptionParser.new do |opts| options[:config] = config end + opts.on('-C', '--comment COMMENT', I18n.t('option.comment')) do |comment| + values[:comment] = comment + end + + opts.on('-G', '--group NAME', I18n.t('option.new_group')) do |group| + values[:group] = group + end + opts.on('-h', '--help', I18n.t('option.help')) do puts opts exit 0 end + opts.on('-H', '--host HOST', I18n.t('option.host')) do |host| + values[:host] = host + end + + opts.on('-o', '--otp-code CODE', I18n.t('option.otp_code')) do |otp| + values[:otp_key] = otp + end + + opts.on('-O', '--protocol PROTOCOL', I18n.t('option.protocol')) do |protocol| + values[:protocol] = protocol + end + + opts.on('-P', '--port NUMBER', I18n.t('option.port')) do |port| + values[:port] = port + end + opts.on('-r', '--random', I18n.t('option.random_password')) do options[:password] = true end + opts.on('-t', '--text-editor', I18n.t('option.text_editor')) do + options[:text_editor] = true + end + + opts.on('-u', '--user USER', I18n.t('option.user')) do |user| + values[:user] = user + end + opts.on('-w', '--wallet NAME', I18n.t('option.wallet')) do |wallet| options[:wallet] = wallet end @@ -53,4 +87,4 @@ cli = MPW::Cli.new(config) cli.load_config cli.get_wallet(options[:wallet]) cli.decrypt -cli.add(options[:password]) +cli.add(options[:password], options[:text_editor], values) diff --git a/bin/mpw-update b/bin/mpw-update index c258330..d887ce3 100644 --- a/bin/mpw-update +++ b/bin/mpw-update @@ -24,8 +24,10 @@ require 'mpw/cli' # Options # --------------------------------------------------------- # -options = {} -values = {} +values = {} +search = {} +options = {} +options[:text_editor] = false OptionParser.new do |opts| opts.banner = "#{I18n.t('option.usage')}: mpw update [options]" @@ -34,7 +36,15 @@ OptionParser.new do |opts| options[:config] = config end + opts.on('-C', '--comment COMMENT', I18n.t('option.comment')) do |comment| + values[:comment] = comment + end + opts.on('-g', '--group NAME', I18n.t('option.group')) do |group| + search[:group] = group + end + + opts.on('-G', '--new-group NAME', I18n.t('option.new_group')) do |group| values[:group] = group end @@ -43,14 +53,38 @@ OptionParser.new do |opts| exit 0 end + opts.on('-H', '--host HOST', I18n.t('option.host')) do |host| + values[:host] = host + end + + opts.on('-o', '--otp-code CODE', I18n.t('option.otp_code')) do |otp| + values[:otp_key] = otp + end + + opts.on('-O', '--protocol PROTOCOL', I18n.t('option.protocol')) do |protocol| + values[:protocol] = protocol + end + opts.on('-p', '--pattern PATTERN', I18n.t('option.pattern')) do |pattern| - values[:pattern] = pattern + search[:pattern] = pattern + end + + opts.on('-P', '--port NUMBER', I18n.t('option.port')) do |port| + values[:port] = port end opts.on('-r', '--random', I18n.t('option.random_password')) do options[:password] = true end + opts.on('-t', '--text-editor', I18n.t('option.text_editor')) do + options[:text_editor] = true + end + + opts.on('-u', '--user USER', I18n.t('option.user')) do |user| + values[:user] = user + end + opts.on('-w', '--wallet NAME', I18n.t('option.wallet')) do |wallet| options[:wallet] = wallet end @@ -62,4 +96,4 @@ cli = MPW::Cli.new(config) cli.load_config cli.get_wallet(options[:wallet]) cli.decrypt -cli.update(options[:password], values) +cli.update(options[:password], options[:text_editor], search, values) diff --git a/i18n/en.yml b/i18n/en.yml index 5ed50c7..402facd 100644 --- a/i18n/en.yml +++ b/i18n/en.yml @@ -43,6 +43,7 @@ en: add: "Add an item or key" add_gpg_key: "Share the wallet with an other GPG key" alpha: "Use letter to generate a password" + comment: "Specify a comment" config: "Specify the configuration file to use" clipboard: "Disable the clipboard feature" default_path: "Move the wallet in default directory" @@ -61,6 +62,7 @@ en: gpg_key: "Specify a GPG key (ex: user@example.com)" group: "Search the items with specified group" help: "Show this help message" + host: "Specify a host or ip" init: "Initialize mpw" import: "Import item since a yaml file" key: "Specify the key name" @@ -68,17 +70,23 @@ en: length: "Size of the password" list: "List the wallets" list_keys: "List the GPG keys in wallet" + new_group: "Specify the group for the item" numeric: "Use number to generate a password" + otp_code: "Set an otp key" path: "Move the wallet in new specify directory" pattern: "Given search pattern" pinmode: "Enable pinentry mode (available with gpg >= 2.1)" + port: "Set a port of connexion" + protocol: "Set a protocol of connexion" random_password: "Generate a random password" setup: "Create a new configuration file" setup_wallet: "Create a new configuration file for a wallet" special_chars: "Use special char to generate a password" show: "Search and show the items" show_all: "List all items" + text_editor: "Use text editor to edit the item" usage: "Usage" + user: "Set an user" wallet: "Specify a wallet to use" wallet_dir: "Set the wallets folder" diff --git a/i18n/fr.yml b/i18n/fr.yml index 13829a2..b1b4ecc 100644 --- a/i18n/fr.yml +++ b/i18n/fr.yml @@ -44,6 +44,7 @@ fr: add_gpg_key: "Partage le portefeuille avec une autre clé GPG" alpha: "Utilise des lettres dans la génération d'un mot de passe" config: "Spécifie le fichier de configuration à utiliser" + comment: "Spécifie un commentaire" clipboard: "Désactive la fonction presse papier" default_path: "Déplace le portefeuille dans le dossier par défaut" default_wallet: "Spécifie le porte-feuille à utiliser par défaut" @@ -61,6 +62,7 @@ fr: gpg_key: "Spécifie une clé GPG (ex: user@example.com)" group: "Recherche les éléments appartenant au groupe spécifié" help: "Affiche ce message d'aide" + host: "Spécifie le nom du serveur ou l'ip" import: "Importe des éléments depuis un fichier yaml" init: "Initialise mpw" key: "Spécifie le nom d'une clé" @@ -68,17 +70,23 @@ fr: length: "Taille du mot de passe" list: "Liste les portefeuilles" list_keys: "Liste les clés GPG dans le portefeuille" + new_group: "Spécifie le groupe de l'item" numeric: "Utilise des chiffre dans la génération d'un mot de passe" + otp_code: "Spécifie un code OTP" path: "Déplace le portefeuille dans un nouveau dossier" pattern: "Motif de donnée à chercher" pinmode: "Active le mode pinentry (valable avec gpg >= 2.1)" + port: "Spécifie un port de connexion" + protocol: "Spécifie un protocol de connexion" random_password: "Génére un mot de passe aléatoire" setup: "Création d'un nouveau fichier de configuration" setup_wallet: "Création d'un nouveau fichier de configuration pour un portefeuille" special_chars: "Utilise des charactères speciaux dans la génération d'un mot de passe" show: "Recherche et affiche les éléments" show_all: "Liste tous les éléments" + text_editor: "Active l'édition avec un éditeur de texte" usage: "Utilisation" + user: "Spécifie un utilisateur" wallet: "Spécifie le portefeuille à utiliser" wallet_dir: "Spécifie le répertoire des portefeuilles" diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index 6fd257f..7aad7f0 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -400,9 +400,9 @@ module MPW # @args: template -> template name # item -> the item to edit # password -> disable field password - def text_editor(template_name, item = nil, password = false) + # @rtrn: a hash with the value for an item + def text_editor(template_name, password = false, item = nil, **options) editor = ENV['EDITOR'] || 'nano' - options = {} opts = {} template_file = "#{File.expand_path('../../../templates', __FILE__)}/#{template_name}.erb" template = ERB.new(IO.read(template_file)) @@ -430,8 +430,10 @@ module MPW # Form to add a new item # @args: password -> generate a random password - def add(password = false) - options = text_editor('add_form', nil, password) + # text_editor -> enable text editor mode + # values -> hash with multiples value to set the item + def add(password = false, text_editor = false, **values) + options = text_editor('add_form', password, nil, values) if text_editor item = Item.new(options) options[:password] = MPW.password(@config.password) if password @@ -447,8 +449,10 @@ module MPW # Update an item # @args: password -> generate a random password + # text_editor -> enable text editor mode # options -> the option to search - def update(password = false, **options) + # values -> hash with multiples value to set the item + def update(password = false, text_editor = false, options = {}, **values) items = @mpw.list(options) if items.empty? @@ -456,13 +460,13 @@ module MPW else table_items(items) if items.length > 1 - item = get_item(items) - options = text_editor('update_form', item, password) - options[:password] = MPW.password(@config.password) if password + item = get_item(items) + values = text_editor('update_form', password, item, values) if text_editor + values[:password] = MPW.password(@config.password) if password - item.update(options) - @mpw.set_password(item.id, options[:password]) if options.key?(:password) - @mpw.set_otp_key(item.id, options[:otp_key]) if options.key?(:otp_key) + item.update(values) + @mpw.set_password(item.id, values[:password]) if values.key?(:password) + @mpw.set_otp_key(item.id, values[:otp_key]) if values.key?(:otp_key) @mpw.write_data puts I18n.t('form.update_item.valid').to_s.green diff --git a/templates/add_form.erb b/templates/add_form.erb index bb81787..d88874e 100644 --- a/templates/add_form.erb +++ b/templates/add_form.erb @@ -1,9 +1,9 @@ --- -host: # <%= I18n.t('form.add_item.host') %> -user: # <%= I18n.t('form.add_item.login') %> -group: # <%= I18n.t('form.add_item.group') %> -protocol: # <%= I18n.t('form.add_item.protocol') %><% unless password %> -password: # <%= I18n.t('form.add_item.password') %><% end %> -port: # <%= I18n.t('form.add_item.port') %> -comment: # <%= I18n.t('form.add_item.comment') %> -otp_key: # <%= I18n.t('form.add_item.otp_key') %> +host: <%= options[:host] %> # <%= I18n.t('form.add_item.host') %> +user: <%= options[:user] %> # <%= I18n.t('form.add_item.login') %> +group: <%= options[:group] %> # <%= I18n.t('form.add_item.group') %> +protocol: <%= options[:protocol] %> # <%= I18n.t('form.add_item.protocol') %><% unless password %> +password: # <%= I18n.t('form.add_item.password') %><% end %> +port: <%= options[:port] %> # <%= I18n.t('form.add_item.port') %> +comment: <%= options[:comment] %> # <%= I18n.t('form.add_item.comment') %> +otp_key: <%= options[:otp] %> # <%= I18n.t('form.add_item.otp_key') %> diff --git a/templates/update_form.erb b/templates/update_form.erb index f27da0b..5037568 100644 --- a/templates/update_form.erb +++ b/templates/update_form.erb @@ -1,17 +1,17 @@ --- # <%= I18n.t('form.update_item.host') %> -host: <%= item.host %> +host: <% if options[:host] %><%= options[:host] %><% else %><%= item.host %><% end %> # <%= I18n.t('form.update_item.login') %> -user: <%= item.user %><% unless password %> +user: <% if options[:user] %><%= options[:user] %><% else %><%= item.user %><% end %><% unless password %> # <%= I18n.t('form.update_item.password') %> password: <% end %> # <%= I18n.t('form.update_item.group') %> -group: <%= item.group %> +group: <% if options[:group] %><%= options[:group] %><% else %><%= item.group %><% end %> # <%= I18n.t('form.update_item.protocol') %> -protocol: <%= item.protocol %> +protocol: <% if options[:protocol] %><%= options[:protocol] %><% else %><%= item.protocol %><% end %> # <%= I18n.t('form.update_item.port') %> -port: <%= item.port %> +port: <% if options[:port] %><%= options[:port] %><% else %><%= item.port %><% end %> # <%= I18n.t('form.update_item.otp_key') %> -otp_key: +otp_key: <% if options[:otp_key] %><%= options[:otp_key] %><% end %> # <%= I18n.t('form.update_item.comment') %> -comment: <%= item.comment %> +comment: <% if options[:comment] %><%= options[:comment] %><% else %><%= item.comment %><% end %> From b2b94374312f570a79c2971a5361803171b579d9 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Thu, 20 Apr 2017 23:22:56 +0200 Subject: [PATCH 471/531] change copyright year --- bin/mpw | 2 +- bin/mpw-add | 2 +- bin/mpw-config | 2 +- bin/mpw-copy | 2 +- bin/mpw-delete | 2 +- bin/mpw-export | 2 +- bin/mpw-genpwd | 2 +- bin/mpw-import | 2 +- bin/mpw-list | 2 +- bin/mpw-update | 2 +- bin/mpw-wallet | 2 +- lib/mpw/cli.rb | 2 +- lib/mpw/config.rb | 2 +- lib/mpw/item.rb | 2 +- lib/mpw/mpw.rb | 2 +- 15 files changed, 15 insertions(+), 15 deletions(-) diff --git a/bin/mpw b/bin/mpw index 1bdf835..811322e 100755 --- a/bin/mpw +++ b/bin/mpw @@ -1,6 +1,6 @@ #!/usr/bin/ruby # MPW is a software to crypt and manage your passwords -# Copyright (C) 2016 Adrien Waksberg <mpw@yae.im> +# Copyright (C) 2017 Adrien Waksberg <mpw@yae.im> # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License diff --git a/bin/mpw-add b/bin/mpw-add index 20eaf7b..2c2e996 100644 --- a/bin/mpw-add +++ b/bin/mpw-add @@ -1,6 +1,6 @@ #!/usr/bin/ruby # MPW is a software to crypt and manage your passwords -# Copyright (C) 2016 Adrien Waksberg <mpw@yae.im> +# Copyright (C) 2017 Adrien Waksberg <mpw@yae.im> # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License diff --git a/bin/mpw-config b/bin/mpw-config index 04f960b..3f049fa 100644 --- a/bin/mpw-config +++ b/bin/mpw-config @@ -1,6 +1,6 @@ #!/usr/bin/ruby # MPW is a software to crypt and manage your passwords -# Copyright (C) 2016 Adrien Waksberg <mpw@yae.im> +# Copyright (C) 2017 Adrien Waksberg <mpw@yae.im> # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License diff --git a/bin/mpw-copy b/bin/mpw-copy index 9436a10..95c01d6 100644 --- a/bin/mpw-copy +++ b/bin/mpw-copy @@ -1,6 +1,6 @@ #!/usr/bin/ruby # MPW is a software to crypt and manage your passwords -# Copyright (C) 2016 Adrien Waksberg <mpw@yae.im> +# Copyright (C) 2017 Adrien Waksberg <mpw@yae.im> # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License diff --git a/bin/mpw-delete b/bin/mpw-delete index f276785..ea352c4 100644 --- a/bin/mpw-delete +++ b/bin/mpw-delete @@ -1,6 +1,6 @@ #!/usr/bin/ruby # MPW is a software to crypt and manage your passwords -# Copyright (C) 2016 Adrien Waksberg <mpw@yae.im> +# Copyright (C) 2017 Adrien Waksberg <mpw@yae.im> # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License diff --git a/bin/mpw-export b/bin/mpw-export index 982d1ad..83d35ae 100644 --- a/bin/mpw-export +++ b/bin/mpw-export @@ -1,6 +1,6 @@ #!/usr/bin/ruby # MPW is a software to crypt and manage your passwords -# Copyright (C) 2016 Adrien Waksberg <mpw@yae.im> +# Copyright (C) 2017 Adrien Waksberg <mpw@yae.im> # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License diff --git a/bin/mpw-genpwd b/bin/mpw-genpwd index 1c09489..051c5c4 100644 --- a/bin/mpw-genpwd +++ b/bin/mpw-genpwd @@ -1,6 +1,6 @@ #!/usr/bin/ruby # MPW is a software to crypt and manage your passwords -# Copyright (C) 2016 Adrien Waksberg <mpw@yae.im> +# Copyright (C) 2017 Adrien Waksberg <mpw@yae.im> # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License diff --git a/bin/mpw-import b/bin/mpw-import index d9c868d..0502b2b 100644 --- a/bin/mpw-import +++ b/bin/mpw-import @@ -1,6 +1,6 @@ #!/usr/bin/ruby # MPW is a software to crypt and manage your passwords -# Copyright (C) 2016 Adrien Waksberg <mpw@yae.im> +# Copyright (C) 2017 Adrien Waksberg <mpw@yae.im> # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License diff --git a/bin/mpw-list b/bin/mpw-list index 3571abc..434ea11 100644 --- a/bin/mpw-list +++ b/bin/mpw-list @@ -1,6 +1,6 @@ #!/usr/bin/ruby # MPW is a software to crypt and manage your passwords -# Copyright (C) 2016 Adrien Waksberg <mpw@yae.im> +# Copyright (C) 2017 Adrien Waksberg <mpw@yae.im> # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License diff --git a/bin/mpw-update b/bin/mpw-update index d887ce3..5e2c62d 100644 --- a/bin/mpw-update +++ b/bin/mpw-update @@ -1,6 +1,6 @@ #!/usr/bin/ruby # MPW is a software to crypt and manage your passwords -# Copyright (C) 2016 Adrien Waksberg <mpw@yae.im> +# Copyright (C) 2017 Adrien Waksberg <mpw@yae.im> # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License diff --git a/bin/mpw-wallet b/bin/mpw-wallet index 5b3b7f9..c23e1e2 100644 --- a/bin/mpw-wallet +++ b/bin/mpw-wallet @@ -1,6 +1,6 @@ #!/usr/bin/ruby # MPW is a software to crypt and manage your passwords -# Copyright (C) 2016 Adrien Waksberg <mpw@yae.im> +# Copyright (C) 2017 Adrien Waksberg <mpw@yae.im> # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index 7aad7f0..d622bff 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -1,6 +1,6 @@ #!/usr/bin/ruby # MPW is a software to crypt and manage your passwords -# Copyright (C) 2016 Adrien Waksberg <mpw@yae.im> +# Copyright (C) 2017 Adrien Waksberg <mpw@yae.im> # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License diff --git a/lib/mpw/config.rb b/lib/mpw/config.rb index fa1a825..72b732d 100644 --- a/lib/mpw/config.rb +++ b/lib/mpw/config.rb @@ -1,6 +1,6 @@ #!/usr/bin/ruby # MPW is a software to crypt and manage your passwords -# Copyright (C) 2016 Adrien Waksberg <mpw@yae.im> +# Copyright (C) 2017 Adrien Waksberg <mpw@yae.im> # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License diff --git a/lib/mpw/item.rb b/lib/mpw/item.rb index 8b4b867..b338998 100644 --- a/lib/mpw/item.rb +++ b/lib/mpw/item.rb @@ -1,6 +1,6 @@ #!/usr/bin/ruby # MPW is a software to crypt and manage your passwords -# Copyright (C) 2016 Adrien Waksberg <mpw@yae.im> +# Copyright (C) 2017 Adrien Waksberg <mpw@yae.im> # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index 896339c..71676c7 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -1,6 +1,6 @@ #!/usr/bin/ruby # MPW is a software to crypt and manage your passwords -# Copyright (C) 2016 Adrien Waksberg <mpw@yae.im> +# Copyright (C) 2017 Adrien Waksberg <mpw@yae.im> # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License From 02996b590419aa81e84fc5ff3ea0a3b24e46bfbd Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Thu, 20 Apr 2017 23:26:40 +0200 Subject: [PATCH 472/531] gemspec: add minimal ruby version --- mpw.gemspec | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mpw.gemspec b/mpw.gemspec index 9f27023..4afbe3b 100644 --- a/mpw.gemspec +++ b/mpw.gemspec @@ -18,6 +18,8 @@ Gem::Specification.new do |spec| spec.test_files = spec.files.grep(%r{^(test|spec|features)/}) spec.require_paths = ['lib'] + spec.required_ruby_version = '>= 2.1' + spec.add_dependency 'i18n', '~> 0.7', '>= 0.7.0' spec.add_dependency 'gpgme', '~> 2.0', '>= 2.0.12' spec.add_dependency 'highline', '~> 1.7', '>= 1.7.8' From 83fe41921c4c4ab55af4e9ef88d21f2b05f820de Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Sat, 22 Apr 2017 10:25:19 +0200 Subject: [PATCH 473/531] update version 4.1 --- CHANGELOG.md | 9 +++++++++ README.md | 33 +++++++++++++++++++++++++++------ VERSION | 2 +- 3 files changed, 37 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 452ac98..7f52b5f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,13 @@ # CHANGELOG +## v4.1.0 + + * feat: add options to update or add an item in command line + * feat: print config + * feat: add a specific path for a wallet + * feat: add rubocop to fix syntax + * fix: pinentry mode with gpg >= 2.1 + * remove SSH and FTP synchronization + ## v4.0.0 * feature: set default wallet diff --git a/README.md b/README.md index fd2534a..60a69d8 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # MPW: Manage your passwords! -[](https://github.com/nishiki/manage-password/releases) +[](https://github.com/nishiki/manage-password/releases) [](https://travis-ci.org/nishiki/manage-password) [](https://github.com/nishiki/manage-password/blob/master/LICENSE) @@ -82,11 +82,6 @@ List all available wallets: mpw wallet --list ``` -Create an other wallet: -``` -mpw config --wallet work --init user@host.com -``` - List all GPG keys in wallet: ``` mpw wallet --list-keys [--wallet NAME] @@ -139,3 +134,29 @@ Example yaml file for mpw: otp_key: comment: Da Linux French Site ``` + +### Config + +Print the current config +``` +mpw config +``` + +Output: + +``` +Configuration + ============================================== + lang | fr + gpg_key | mpw@yae.im + default_wallet | + config_dir | /home/mpw/.config/mpw + pinmode | true + gpg_exe | + path_wallet_test | /tmp/test.mpw + password_numeric | true + password_alpha | true + password_special | false + password_length | 16 + +``` diff --git a/VERSION b/VERSION index 4aa925d..ee74734 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -4.1.0-dev +4.1.0 From 9ad8eba901c97637d0cb0e1d2eb3a6c067f04b96 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Wed, 3 May 2017 19:54:21 +0200 Subject: [PATCH 474/531] fix: remove unused method --- bin/mpw-config | 1 - 1 file changed, 1 deletion(-) diff --git a/bin/mpw-config b/bin/mpw-config index 3f049fa..bec687d 100644 --- a/bin/mpw-config +++ b/bin/mpw-config @@ -109,7 +109,6 @@ if options.key?(:init) cli.load_config cli.get_wallet cli.setup_gpg_key(values[:gpg_key]) - cli.setup_wallet_config else cli.load_config if values.empty? From 96380d3d934eba25747713c2bbbbf068b060ed76 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Wed, 3 May 2017 20:39:32 +0200 Subject: [PATCH 475/531] update version 4.1.1 --- CHANGELOG.md | 4 ++++ README.md | 2 +- VERSION | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7f52b5f..1fb8d79 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,8 @@ # CHANGELOG +## v4.1.1 + + * fix bug in init + ## v4.1.0 * feat: add options to update or add an item in command line diff --git a/README.md b/README.md index 60a69d8..afb4ade 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # MPW: Manage your passwords! -[](https://github.com/nishiki/manage-password/releases) +[](https://github.com/nishiki/manage-password/releases) [](https://travis-ci.org/nishiki/manage-password) [](https://github.com/nishiki/manage-password/blob/master/LICENSE) diff --git a/VERSION b/VERSION index ee74734..627a3f4 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -4.1.0 +4.1.1 From a7a165bca9e401845fbc7d18b6349f2f423fdd88 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Wed, 3 May 2017 22:53:56 +0200 Subject: [PATCH 476/531] feat: comment the code with yard --- .gitignore | 2 ++ lib/mpw/cli.rb | 71 +++++++++++++++++++++++------------------------ lib/mpw/config.rb | 21 ++++++-------- lib/mpw/item.rb | 8 ++---- lib/mpw/mpw.rb | 59 +++++++++++++++++++++------------------ 5 files changed, 81 insertions(+), 80 deletions(-) diff --git a/.gitignore b/.gitignore index 7ae6fcf..afd83c3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ Gemfile.lock *.gem +.yardoc +doc diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index d622bff..e3cb85e 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -28,14 +28,13 @@ require 'mpw/mpw' module MPW class Cli - # Constructor - # @args: config -> the config + # @param config [Config] def initialize(config) @config = config end # Change a parameter int the config after init - # @args: options -> param to change + # @param options [Hash] param to change def set_config(options) @config.setup(options) @@ -46,7 +45,7 @@ module MPW end # Change the wallet path - # @args: path -> the new path + # @param path [String] new path def set_wallet_path(path) @config.set_wallet_path(path, @wallet) @@ -57,7 +56,7 @@ module MPW end # Create a new config file - # @args: options -> set param + # @param options [Hash] def setup(options) options[:lang] = options[:lang] || Locale::Tag.parse(ENV['LANG']).to_simple.to_s[0..1] @@ -74,7 +73,7 @@ module MPW end # Setup a new GPG key - # @args: gpg_key -> the key name + # @param gpg_key [String] gpg key name def setup_gpg_key(gpg_key) return if @config.check_gpg_key? @@ -139,8 +138,8 @@ module MPW end # Format list on a table - # @args: title -> the name of table - # list -> array or hash + # @param title [String] name of table + # @param list an array or hash def table_list(title, list) length = { k: 0, v: 0 } @@ -172,7 +171,7 @@ module MPW end # Format items on a table - # @args: items -> an aray items + # @param items [Array] def table_items(items = []) group = '.' i = 1 @@ -252,7 +251,7 @@ module MPW end # Display the query's result - # @args: options -> the option to search + # @param options [Hash] the options to search def list(**options) result = @mpw.list(options) @@ -264,8 +263,8 @@ module MPW end # Get an item when multiple choice - # @args: items -> array of items - # @rtrn: item + # @param items [Array] list of items + # @return item [Item] def get_item(items) return items[0] if items.length == 1 @@ -276,8 +275,8 @@ module MPW end # Copy in clipboard the login and password - # @args: item -> the item - # clipboard -> enable clipboard + # @param item [Item] + # @param clipboard [Boolean] enable clipboard def clipboard(item, clipboard = true) # Security: force quit after 90s Thread.new do @@ -350,7 +349,7 @@ module MPW end # Display the wallet - # @args: wallet -> the wallet name + # @param wallet [String] wallet name def get_wallet(wallet = nil) @wallet = if wallet.to_s.empty? @@ -375,7 +374,7 @@ module MPW end # Add a new public key - # args: key -> the key name or key file to add + # @param key [String] key name or key file to add def add_key(key) @mpw.add_key(key) @mpw.write_data @@ -386,7 +385,7 @@ module MPW end # Add new public key - # args: key -> the key name to delete + # @param key [String] key name to delete def delete_key(key) @mpw.delete_key(key) @mpw.write_data @@ -397,10 +396,10 @@ module MPW end # Text editor interface - # @args: template -> template name - # item -> the item to edit - # password -> disable field password - # @rtrn: a hash with the value for an item + # @param template [String] template name + # @param item [Item] the item to edit + # @param password [Boolean] disable field password + # @return [Hash] the values for an item def text_editor(template_name, password = false, item = nil, **options) editor = ENV['EDITOR'] || 'nano' opts = {} @@ -429,9 +428,9 @@ module MPW end # Form to add a new item - # @args: password -> generate a random password - # text_editor -> enable text editor mode - # values -> hash with multiples value to set the item + # @param password [Boolean] generate a random password + # @param text_editor [Boolean] enable text editor mode + # @param values [Hash] multiples value to set the item def add(password = false, text_editor = false, **values) options = text_editor('add_form', password, nil, values) if text_editor item = Item.new(options) @@ -448,10 +447,10 @@ module MPW end # Update an item - # @args: password -> generate a random password - # text_editor -> enable text editor mode - # options -> the option to search - # values -> hash with multiples value to set the item + # @param password [Boolean] generate a random password + # @param text_editor [Boolean] enable text editor mode + # @param options [Hash] the options to search + # @param values [Hash] multiples value to set the item def update(password = false, text_editor = false, options = {}, **values) items = @mpw.list(options) @@ -476,7 +475,7 @@ module MPW end # Remove an item - # @args: options -> the option to search + # @param options [Hash] the options to search def delete(**options) items = @mpw.list(options) @@ -500,8 +499,8 @@ module MPW end # Copy a password, otp, login - # @args: clipboard -> enable clipboard - # options -> the option to search + # @param clipboard [Boolean] enable clipboard + # @param options [Hash] the options to search def copy(clipboard = true, **options) items = @mpw.list(options) @@ -517,9 +516,9 @@ module MPW puts "#{I18n.t('display.error')} #14: #{e}".red end - # Export the items in a CSV file - # @args: file -> the destination file - # options -> option to search + # Export the items in an yaml file + # @param file [String] the path of destination file + # @param options [Hash] options to search def export(file, options) file = 'export-mpw.yml' if file.to_s.empty? items = @mpw.list(options) @@ -549,8 +548,8 @@ module MPW puts "#{I18n.t('display.error')} #17: #{e}".red end - # Import items from a YAML file - # @args: file -> the import file + # Import items from an yaml file + # @param file [String] path of import file def import(file) raise I18n.t('form.import.file_empty') if file.to_s.empty? raise I18n.t('form.import.file_not_exist') unless File.exist?(file) diff --git a/lib/mpw/config.rb b/lib/mpw/config.rb index 72b732d..bdcf394 100644 --- a/lib/mpw/config.rb +++ b/lib/mpw/config.rb @@ -35,8 +35,7 @@ module MPW attr_accessor :password attr_accessor :pinmode - # Constructor - # @args: config_file -> the specify config file + # @param config_file [String] path of config file def initialize(config_file = nil) @config_file = config_file @config_dir = @@ -52,8 +51,7 @@ module MPW end # Create a new config file - # @args: options -> hash with values - # @rtrn: true if le config file is create + # @param options [Hash] the value to set the config file def setup(**options) gpg_key = options[:gpg_key] || @gpg_key lang = options[:lang] || @lang @@ -99,11 +97,10 @@ module MPW end # Setup a new gpg key - # @args: password -> the GPG key password - # name -> the name of user - # length -> length of the GPG key - # expire -> the time of expire to GPG key - # @rtrn: true if the GPG key is create, else false + # @param password [String] gpg key password + # @param name [String] the name of user + # @param length [Integer] length of the gpg key + # @param expire [Integer] time of expire to gpg key def setup_gpg_key(password, name, length = 4096, expire = 0) raise I18n.t('error.config.genkey_gpg.name') if name.to_s.empty? raise I18n.t('error.config.genkey_gpg.password') if password.to_s.empty? @@ -147,7 +144,7 @@ module MPW end # Check if private key exist - # @rtrn: true if the key exist, else false + # @return [Boolean] true if the key exist, else false def check_gpg_key? ctx = GPGME::Ctx.new ctx.each_key(@gpg_key, true) do @@ -158,8 +155,8 @@ module MPW end # Change the path of one wallet - # @args: path -> the new directory path - # wallet -> the wallet name + # @param path [String]new directory path + # @param wallet [String] wallet name def set_wallet_path(path, wallet) path = @wallet_dir if path == 'default' diff --git a/lib/mpw/item.rb b/lib/mpw/item.rb index b338998..ba86b96 100644 --- a/lib/mpw/item.rb +++ b/lib/mpw/item.rb @@ -31,10 +31,7 @@ module MPW attr_accessor :last_edit attr_accessor :created - # Constructor - # Create a new item - # @args: options -> a hash of parameter - # raise an error if the hash hasn't the key name + # @param options [Hash] the option :host is required def initialize(**options) if !options.key?(:host) || options[:host].to_s.empty? raise I18n.t('error.update.host_empty') @@ -54,7 +51,7 @@ module MPW end # Update the item - # @args: options -> a hash of parameter + # @param options [Hash] def update(**options) if options.key?(:host) && options[:host].to_s.empty? raise I18n.t('error.update.host_empty') @@ -95,6 +92,7 @@ module MPW private # Generate an random id + # @return [String] random string def generate_id [*('A'..'Z'), *('a'..'z'), *('0'..'9')].sample(16).join end diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index 71676c7..fbca576 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -25,7 +25,11 @@ require 'mpw/item' module MPW class MPW - # Constructor + # @param key [String] gpg key name + # @param wallet_file [String] path of the wallet file + # @param gpg_pass [String] password of the gpg key + # @param gpg_exe [String] path of the gpg executable + # @param pinmode [Boolean] enable the gpg pinmode def initialize(key, wallet_file, gpg_pass = nil, gpg_exe = nil, pinmode = false) @key = key @gpg_pass = gpg_pass @@ -98,7 +102,7 @@ module MPW raise "#{I18n.t('error.mpw_file.read_data')}\n#{e}" end - # Encrypt a file + # Encrypt all data in tarball def write_data data = {} tmp_file = "#{@wallet_file}.tmp" @@ -154,7 +158,7 @@ module MPW end # Get a password - # args: id -> the item id + # @param id [String] the item id def get_password(id) password = decrypt(@passwords[id]) @@ -165,9 +169,9 @@ module MPW end end - # Set a password - # args: id -> the item id - # password -> the new password + # Set a new password for an item + # @param id [String] the item id + # @param password [String] the new password def set_password(id, password) salt = MPW.password(length: Random.rand(4..9)) password = "$#{salt}::#{password}" @@ -176,13 +180,13 @@ module MPW end # Return the list of all gpg keys - # rtrn: an array with the gpg keys name + # @return [Array] the gpg keys name def list_keys @keys.keys end # Add a public key - # args: key -> new public key file or name + # @param key [String] new public key file or name def add_key(key) if File.exist?(key) data = File.open(key).read @@ -200,7 +204,7 @@ module MPW end # Delete a public key - # args: key -> public key to delete + # @param key [String] public key to delete def delete_key(key) @keys.delete(key) @passwords.each_key { |id| set_password(id, get_password(id)) } @@ -208,7 +212,7 @@ module MPW end # Add a new item - # @args: item -> Object MPW::Item + # @param item [Item] def add(item) raise I18n.t('error.bad_class') unless item.instance_of?(Item) raise I18n.t('error.empty') if item.empty? @@ -217,8 +221,8 @@ module MPW end # Search in some csv data - # @args: options -> a hash with paramaters - # @rtrn: a list with the resultat of the search + # @params options [Hash] + # @return [Array] a list with the resultat of the search def list(**options) result = [] @@ -240,9 +244,9 @@ module MPW result end - # Search in some csv data - # @args: id -> the id item - # @rtrn: a row with the result of the search + # Search an item with an id + # @param id [String]the id item + # @return [Item] an item or nil def search_by_id(id) @data.each do |item| return item if item.id == id @@ -251,36 +255,35 @@ module MPW nil end - # Set an opt key - # args: id -> the item id - # key -> the new key + # Set a new opt key + # @param id [String] the item id + # @param key [String] the new key def set_otp_key(id, key) @otp_keys[id] = encrypt(key.to_s) unless key.to_s.empty? end # Get an opt key - # args: id -> the item id - # key -> the new key + # @param id [String] the item id def get_otp_key(id) @otp_keys.key?(id) ? decrypt(@otp_keys[id]) : nil end # Get an otp code - # @args: id -> the item id - # @rtrn: an otp code + # @param id [String] the item id + # @return [String] an otp code def get_otp_code(id) @otp_keys.key?(id) ? 0 : ROTP::TOTP.new(decrypt(@otp_keys[id])).now end # Get remaining time before expire otp code - # @rtrn: return time in seconde + # @return [Integer] time in seconde def get_otp_remaining_time (Time.now.utc.to_i / 30 + 1) * 30 - Time.now.utc.to_i end # Generate a random password - # @args: options -> :length, :special, :alpha, :numeric - # @rtrn: a random string + # @param options [Hash] :length, :special, :alpha, :numeric + # @return [String] a random string def self.password(**options) length = if !options.include?(:length) || options[:length].to_i <= 0 @@ -310,7 +313,8 @@ module MPW private # Decrypt a gpg file - # @args: data -> string to decrypt + # @param data [String] data to decrypt + # @return [String] data decrypted def decrypt(data) return nil if data.to_s.empty? @@ -331,7 +335,8 @@ module MPW end # Encrypt a file - # args: data -> string to encrypt + # @param data [String] data to encrypt + # @return [String] data encrypted def encrypt(data) recipients = [] crypto = GPGME::Crypto.new(armor: true, always_trust: true) From f91531b856e7b1299851331ec204c08c0da92200 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Sat, 6 May 2017 09:09:17 +0200 Subject: [PATCH 477/531] feat: replace host by url in table --- lib/mpw/cli.rb | 33 +++++++++++++++++++++------------ lib/mpw/item.rb | 11 +++++++++++ 2 files changed, 32 insertions(+), 12 deletions(-) diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index e3cb85e..023b9b2 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -179,16 +179,19 @@ module MPW data = { id: { length: 3, color: 'cyan' }, host: { length: 9, color: 'yellow' }, user: { length: 7, color: 'green' }, - protocol: { length: 9, color: 'white' }, - port: { length: 5, color: 'white' }, otp: { length: 4, color: 'white' }, comment: { length: 14, color: 'magenta' } } items.each do |item| data.each do |k, v| - next if k == :id || k == :otp - - v[:length] = item.send(k.to_s).to_s.length + 3 if item.send(k.to_s).to_s.length >= v[:length] + case k + when :id, :otp + next + when :host + v[:length] = item.url.length + 3 if item.url.length >= v[:length] + else + v[:length] = item.send(k.to_s).to_s.length + 3 if item.send(k.to_s).to_s.length >= v[:length] + end end end data[:id][:length] = items.length.to_s.length + 2 if items.length.to_s.length > data[:id][:length] @@ -231,16 +234,22 @@ module MPW data.each do |k, v| next if k == :id - if k == :otp - print '| ' + print '| ' + + case k + when :otp item.otp ? (print ' X ') : 4.times { print ' ' } - next - end + when :host + print "#{item.protocol}://" if item.protocol + print item.host.send(v[:color]) + print ":#{item.port}" if item.port + (v[:length] - item.url.to_s.length).times { print ' ' } - print '| ' - print item.send(k.to_s).to_s.send(v[:color]) - (v[:length] - item.send(k.to_s).to_s.length).times { print ' ' } + else + print item.send(k.to_s).to_s.send(v[:color]) + (v[:length] - item.send(k.to_s).to_s.length).times { print ' ' } + end end print "\n" diff --git a/lib/mpw/item.rb b/lib/mpw/item.rb index ba86b96..be03dba 100644 --- a/lib/mpw/item.rb +++ b/lib/mpw/item.rb @@ -81,6 +81,17 @@ module MPW @last_edit = nil end + # Return data on url format + # @return [String] an url + def url + url = '' + url += "#{@protocol}://" if @protocol + url += @host + url += ":#{@port}" if @port + + url + end + def empty? @id.to_s.empty? end From 6a3f2ca007823190e755154c5e0df48f6a38cae7 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Sun, 7 May 2017 17:11:42 +0200 Subject: [PATCH 478/531] add first tests for cli --- .travis.yml | 7 ++++++- test/test_cli.rb | 50 ++++++++++++++++++++++++++++++++++++++++++++++++ test/tests.rb | 7 ------- 3 files changed, 56 insertions(+), 8 deletions(-) create mode 100644 test/test_cli.rb delete mode 100644 test/tests.rb diff --git a/.travis.yml b/.travis.yml index faa5c04..89d29f0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,4 +13,9 @@ install: - gem install mpw-9999.gem script: - rubocop - - ruby ./test/tests.rb + - ruby ./test/init.rb + - ruby ./test/test_config.rb + - ruby ./test/test_item.rb + - ruby ./test/test_mpw.rb + - ruby ./test/test_translate.rb + - ruby ./test/test_cli.rb diff --git a/test/test_cli.rb b/test/test_cli.rb new file mode 100644 index 0000000..0db3ffa --- /dev/null +++ b/test/test_cli.rb @@ -0,0 +1,50 @@ +#!/usr/bin/ruby + +require 'fileutils' +require 'test/unit' + +class TestConfig < Test::Unit::TestCase + def setup + @password = 'password' + end + + def test_00_init_config + FileUtils.rm_rf("#{Dir.home}/.config/mpw") + FileUtils.rm_rf("#{Dir.home}/.gnupg") + + output = `echo "#{@password}\n#{@password}" | mpw config --init test@example.com` + assert_match('The config file has been created', output) + assert_match('Your GPG key has been created ;-)', output) + end + + def test_01_add_item + host = 'example.com' + + output = `echo #{@password} | mpw add --host #{host} -r` + assert_match('Item has been added!', output) + + output = `echo #{@password} | mpw list` + assert_match(host, output) + end + + def test_02_update_item + host_old = 'example.com' + host_new = 'example2.com' + + output = `echo #{@password} | mpw update -p #{host_old} --host #{host_new}` + assert_match('Item has been updated!', output) + + output = `echo #{@password} | mpw list` + assert_match(host_new, output) + end + + def test_03_delete_item + host = 'example2.com' + + output = `echo "#{@password}\ny" | mpw delete -p #{host}` + assert_match('The item has been removed!', output) + + output = `echo #{@password} | mpw list` + assert_no_match(/#{host}/, output) + end +end diff --git a/test/tests.rb b/test/tests.rb deleted file mode 100644 index 7f3fc7d..0000000 --- a/test/tests.rb +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/ruby - -require_relative 'init.rb' -require_relative 'test_config.rb' -require_relative 'test_item.rb' -require_relative 'test_mpw.rb' -require_relative 'test_translate.rb' From 646f096aac6f6efd9db6b4464b7d6a9b1de908f7 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Sun, 7 May 2017 19:29:22 +0200 Subject: [PATCH 479/531] update ruby version for test --- .travis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 89d29f0..f9db456 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,8 +1,8 @@ language: ruby rvm: - - 2.4.0 - - 2.3.3 - - 2.2.6 + - 2.4.1 + - 2.3.4 + - 2.2.7 - 2.1.10 install: - bundle install From a13fcd147fb53d05bb3df493111e155926dabc85 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Sat, 6 May 2017 09:09:17 +0200 Subject: [PATCH 480/531] feat: replace host by url in table --- lib/mpw/cli.rb | 33 +++++++++++++++++++++------------ lib/mpw/item.rb | 11 +++++++++++ 2 files changed, 32 insertions(+), 12 deletions(-) diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index e3cb85e..023b9b2 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -179,16 +179,19 @@ module MPW data = { id: { length: 3, color: 'cyan' }, host: { length: 9, color: 'yellow' }, user: { length: 7, color: 'green' }, - protocol: { length: 9, color: 'white' }, - port: { length: 5, color: 'white' }, otp: { length: 4, color: 'white' }, comment: { length: 14, color: 'magenta' } } items.each do |item| data.each do |k, v| - next if k == :id || k == :otp - - v[:length] = item.send(k.to_s).to_s.length + 3 if item.send(k.to_s).to_s.length >= v[:length] + case k + when :id, :otp + next + when :host + v[:length] = item.url.length + 3 if item.url.length >= v[:length] + else + v[:length] = item.send(k.to_s).to_s.length + 3 if item.send(k.to_s).to_s.length >= v[:length] + end end end data[:id][:length] = items.length.to_s.length + 2 if items.length.to_s.length > data[:id][:length] @@ -231,16 +234,22 @@ module MPW data.each do |k, v| next if k == :id - if k == :otp - print '| ' + print '| ' + + case k + when :otp item.otp ? (print ' X ') : 4.times { print ' ' } - next - end + when :host + print "#{item.protocol}://" if item.protocol + print item.host.send(v[:color]) + print ":#{item.port}" if item.port + (v[:length] - item.url.to_s.length).times { print ' ' } - print '| ' - print item.send(k.to_s).to_s.send(v[:color]) - (v[:length] - item.send(k.to_s).to_s.length).times { print ' ' } + else + print item.send(k.to_s).to_s.send(v[:color]) + (v[:length] - item.send(k.to_s).to_s.length).times { print ' ' } + end end print "\n" diff --git a/lib/mpw/item.rb b/lib/mpw/item.rb index ba86b96..be03dba 100644 --- a/lib/mpw/item.rb +++ b/lib/mpw/item.rb @@ -81,6 +81,17 @@ module MPW @last_edit = nil end + # Return data on url format + # @return [String] an url + def url + url = '' + url += "#{@protocol}://" if @protocol + url += @host + url += ":#{@port}" if @port + + url + end + def empty? @id.to_s.empty? end From 09e451bf3be5ac589fdaebf85c4768eec97b13a0 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <adrien.waksberg@doctolib.fr> Date: Tue, 9 May 2017 13:56:52 +0200 Subject: [PATCH 481/531] use ligth_black for port and protocol --- lib/mpw/cli.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index 023b9b2..4e2f240 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -241,9 +241,9 @@ module MPW item.otp ? (print ' X ') : 4.times { print ' ' } when :host - print "#{item.protocol}://" if item.protocol + print "#{item.protocol}://".light_black if item.protocol print item.host.send(v[:color]) - print ":#{item.port}" if item.port + print ":#{item.port}".light_black if item.port (v[:length] - item.url.to_s.length).times { print ' ' } else From 977266def846ec5794494e697d8dc8174c305391 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Wed, 10 May 2017 22:38:35 +0200 Subject: [PATCH 482/531] add new test --- test/test_cli.rb | 69 +++++++++++++++++++++++++++++++++++++----------- 1 file changed, 54 insertions(+), 15 deletions(-) diff --git a/test/test_cli.rb b/test/test_cli.rb index 0db3ffa..c3466e8 100644 --- a/test/test_cli.rb +++ b/test/test_cli.rb @@ -12,39 +12,78 @@ class TestConfig < Test::Unit::TestCase FileUtils.rm_rf("#{Dir.home}/.config/mpw") FileUtils.rm_rf("#{Dir.home}/.gnupg") - output = `echo "#{@password}\n#{@password}" | mpw config --init test@example.com` + output = %x(echo "#{@password}\n#{@password}" | mpw config --init test@example.com) assert_match('The config file has been created', output) assert_match('Your GPG key has been created ;-)', output) end def test_01_add_item - host = 'example.com' + host = 'example.com' + port = 1234 + proto = 'http' + user = 'root' + comment = 'the super website' + group = 'Bank' - output = `echo #{@password} | mpw add --host #{host} -r` + output = %x( + echo #{@password} | mpw add \ + --host #{host} \ + --port #{port} \ + --protocol #{proto} \ + --user #{user} \ + --comment '#{comment}' \ + --group #{group} \ + --random) + puts output assert_match('Item has been added!', output) - - output = `echo #{@password} | mpw list` - assert_match(host, output) + + output = %x(echo #{@password} | mpw list) + puts output + assert_match(%r{#{proto}://.+#{host}.+:#{port}}, output) + assert_match(user, output) + assert_match(comment, output) + assert_match(group, output) end def test_02_update_item - host_old = 'example.com' - host_new = 'example2.com' + host_old = 'example.com' + host_new = 'example2.com' + port_new = 4321 + proto_new = 'ssh' + user_new = 'tortue' + comment_new = 'my account' + group_new = 'Assurance' - output = `echo #{@password} | mpw update -p #{host_old} --host #{host_new}` + output = %x( + echo #{@password} | mpw update \ + -p #{host_old} \ + --host #{host_new} \ + --port #{port_new} \ + --protocol #{proto_new} \ + --user #{user_new} \ + --comment '#{comment_new}' \ + --new-group #{group_new} + ) + puts output assert_match('Item has been updated!', output) - - output = `echo #{@password} | mpw list` - assert_match(host_new, output) + + output = %x(echo #{@password} | mpw list) + puts output + assert_match(%r{#{proto_new}://.+#{host_new}.+:#{port_new}}, output) + assert_match(user_new, output) + assert_match(comment_new, output) + assert_match(group_new, output) end def test_03_delete_item host = 'example2.com' - output = `echo "#{@password}\ny" | mpw delete -p #{host}` + output = %x(echo "#{@password}\ny" | mpw delete -p #{host}) + puts output assert_match('The item has been removed!', output) - - output = `echo #{@password} | mpw list` + + output = %x(echo #{@password} | mpw list) + puts output assert_no_match(/#{host}/, output) end end From f150feec10240ec8b007283da5bc9ae900789b4e Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Thu, 11 May 2017 22:24:05 +0200 Subject: [PATCH 483/531] fix syntax for all tests --- .rubocop.yml | 1 - test/test_config.rb | 24 +++++----- test/test_item.rb | 99 ++++++++++++++++++++++-------------------- test/test_mpw.rb | 40 ++++++++--------- test/test_translate.rb | 2 +- 5 files changed, 85 insertions(+), 81 deletions(-) diff --git a/.rubocop.yml b/.rubocop.yml index 8685f88..ce1de33 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -3,7 +3,6 @@ AllCops: Exclude: - db/**/* - config/**/* - - test/* - Vagrantfile TargetRubyVersion: 2.3 diff --git a/test/test_config.rb b/test/test_config.rb index 49af82c..8ad7369 100644 --- a/test/test_config.rb +++ b/test/test_config.rb @@ -20,17 +20,18 @@ class TestConfig < Test::Unit::TestCase end def test_00_config - data = { gpg_key: 'test@example.com', - lang: 'en', - wallet_dir: '/tmp/test', - gpg_exe: '', - } + data = { + gpg_key: 'test@example.com', + lang: 'en', + wallet_dir: '/tmp/test', + gpg_exe: '' + } @config = MPW::Config.new @config.setup(data) @config.load_config - data.each do |k,v| + data.each do |k, v| assert_equal(v, @config.send(k)) end @@ -39,11 +40,12 @@ class TestConfig < Test::Unit::TestCase end def test_01_password - data = { pwd_alpha: false, - pwd_numeric: false, - pwd_special: true, - pwd_length: 32, - } + data = { + pwd_alpha: false, + pwd_numeric: false, + pwd_special: true, + pwd_length: 32 + } @config = MPW::Config.new @config.load_config diff --git a/test/test_item.rb b/test/test_item.rb index 751e1b0..961834e 100644 --- a/test/test_item.rb +++ b/test/test_item.rb @@ -16,22 +16,22 @@ class TestItem < Test::Unit::TestCase I18n.load_path = Dir['./i18n/cli/*.yml'] I18n.default_locale = :en - puts end def test_00_add_without_name - assert_raise(RuntimeError){MPW::Item.new} + assert_raise(RuntimeError) { MPW::Item.new } end def test_01_add_new - data = { group: @fixtures['add_new']['group'], - host: @fixtures['add_new']['host'], - protocol: @fixtures['add_new']['protocol'], - user: @fixtures['add_new']['user'], - port: @fixtures['add_new']['port'], - comment: @fixtures['add_new']['comment'], - } + data = { + group: @fixtures['add_new']['group'], + host: @fixtures['add_new']['host'], + protocol: @fixtures['add_new']['protocol'], + user: @fixtures['add_new']['user'], + port: @fixtures['add_new']['port'], + comment: @fixtures['add_new']['comment'] + } item = MPW::Item.new(data) @@ -47,15 +47,16 @@ class TestItem < Test::Unit::TestCase end def test_02_add_existing - data = { id: @fixtures['add_existing']['id'], - group: @fixtures['add_existing']['group'], - host: @fixtures['add_existing']['host'], - protocol: @fixtures['add_existing']['protocol'], - user: @fixtures['add_existing']['user'], - port: @fixtures['add_existing']['port'], - comment: @fixtures['add_existing']['comment'], - created: @fixtures['add_existing']['created'], - } + data = { + id: @fixtures['add_existing']['id'], + group: @fixtures['add_existing']['group'], + host: @fixtures['add_existing']['host'], + protocol: @fixtures['add_existing']['protocol'], + user: @fixtures['add_existing']['user'], + port: @fixtures['add_existing']['port'], + comment: @fixtures['add_existing']['comment'], + created: @fixtures['add_existing']['created'] + } item = MPW::Item.new(data) @@ -73,13 +74,14 @@ class TestItem < Test::Unit::TestCase end def test_03_update - data = { group: @fixtures['add_new']['group'], - host: @fixtures['add_new']['host'], - protocol: @fixtures['add_new']['protocol'], - user: @fixtures['add_new']['user'], - port: @fixtures['add_new']['port'], - comment: @fixtures['add_new']['comment'], - } + data = { + group: @fixtures['add_new']['group'], + host: @fixtures['add_new']['host'], + protocol: @fixtures['add_new']['protocol'], + user: @fixtures['add_new']['user'], + port: @fixtures['add_new']['port'], + comment: @fixtures['add_new']['comment'] + } item = MPW::Item.new(data) @@ -89,13 +91,14 @@ class TestItem < Test::Unit::TestCase created = item.created last_edit = item.last_edit - data = { group: @fixtures['update']['group'], - host: @fixtures['update']['host'], - protocol: @fixtures['update']['protocol'], - user: @fixtures['update']['user'], - port: @fixtures['update']['port'], - comment: @fixtures['update']['comment'], - } + data = { + group: @fixtures['update']['group'], + host: @fixtures['update']['host'], + protocol: @fixtures['update']['protocol'], + user: @fixtures['update']['user'], + port: @fixtures['update']['port'], + comment: @fixtures['update']['comment'] + } sleep(1) assert(item.update(data)) @@ -114,13 +117,14 @@ class TestItem < Test::Unit::TestCase end def test_05_update_one_element - data = { group: @fixtures['add_new']['group'], - host: @fixtures['add_new']['host'], - protocol: @fixtures['add_new']['protocol'], - user: @fixtures['add_new']['user'], - port: @fixtures['add_new']['port'], - comment: @fixtures['add_new']['comment'], - } + data = { + group: @fixtures['add_new']['group'], + host: @fixtures['add_new']['host'], + protocol: @fixtures['add_new']['protocol'], + user: @fixtures['add_new']['user'], + port: @fixtures['add_new']['port'], + comment: @fixtures['add_new']['comment'] + } item = MPW::Item.new(data) @@ -130,7 +134,7 @@ class TestItem < Test::Unit::TestCase last_edit = item.last_edit sleep(1) - assert(item.update({comment: @fixtures['update']['comment']})) + assert(item.update(comment: @fixtures['update']['comment'])) assert_equal(@fixtures['add_new']['group'], item.group) assert_equal(@fixtures['add_new']['host'], item.host) @@ -143,13 +147,14 @@ class TestItem < Test::Unit::TestCase end def test_05_delete - data = { group: @fixtures['add_new']['group'], - host: @fixtures['add_new']['host'], - protocol: @fixtures['add_new']['protocol'], - user: @fixtures['add_new']['user'], - port: @fixtures['add_new']['port'], - comment: @fixtures['add_new']['comment'], - } + data = { + group: @fixtures['add_new']['group'], + host: @fixtures['add_new']['host'], + protocol: @fixtures['add_new']['protocol'], + user: @fixtures['add_new']['user'], + port: @fixtures['add_new']['port'], + comment: @fixtures['add_new']['comment'] + } item = MPW::Item.new(data) diff --git a/test/test_mpw.rb b/test/test_mpw.rb index 30c9028..dd005ca 100644 --- a/test/test_mpw.rb +++ b/test/test_mpw.rb @@ -33,13 +33,14 @@ class TestMPW < Test::Unit::TestCase end def test_02_add_item - data = { group: @fixtures['add_new']['group'], - host: @fixtures['add_new']['host'], - protocol: @fixtures['add_new']['protocol'], - user: @fixtures['add_new']['user'], - port: @fixtures['add_new']['port'], - comment: @fixtures['add_new']['comment'], - } + data = { + group: @fixtures['add_new']['group'], + host: @fixtures['add_new']['host'], + protocol: @fixtures['add_new']['protocol'], + user: @fixtures['add_new']['user'], + port: @fixtures['add_new']['port'], + comment: @fixtures['add_new']['comment'] + } item = MPW::Item.new(data) @@ -53,7 +54,7 @@ class TestMPW < Test::Unit::TestCase assert_equal(1, @mpw.list.length) item = @mpw.list[0] - @fixtures['add_new'].each do |k,v| + @fixtures['add_new'].each do |k, v| if k == 'password' assert_equal(v, @mpw.get_password(item.id)) else @@ -69,7 +70,7 @@ class TestMPW < Test::Unit::TestCase assert_equal(1, @mpw.list.length) item = @mpw.list[0] - @fixtures['add_new'].each do |k,v| + @fixtures['add_new'].each do |k, v| if k == 'password' assert_equal(v, @mpw.get_password(item.id)) else @@ -80,13 +81,9 @@ class TestMPW < Test::Unit::TestCase def test_04_delete_item @mpw.read_data - assert_equal(1, @mpw.list.length) - @mpw.list.each do |item| - item.delete - end - + @mpw.list.each(&:delete) assert_equal(0, @mpw.list.length) @mpw.write_data @@ -96,13 +93,14 @@ class TestMPW < Test::Unit::TestCase @mpw.read_data @fixtures.each_value do |v| - data = { group: v['group'], - host: v['host'], - protocol: v['protocol'], - user: v['user'], - port: v['port'], - comment: v['comment'], - } + data = { + group: v['group'], + host: v['host'], + protocol: v['protocol'], + user: v['user'], + port: v['port'], + comment: v['comment'] + } item = MPW::Item.new(data) diff --git a/test/test_translate.rb b/test/test_translate.rb index 6334a78..d4bb002 100644 --- a/test/test_translate.rb +++ b/test/test_translate.rb @@ -11,7 +11,7 @@ class TestTranslate < Test::Unit::TestCase lang = File.basename(yaml, '.yml') translate = YAML.load_file(yaml) - `grep -r -o "I18n.t('.*)" bin/ lib/ | cut -d"'" -f2`.each_line do |line| + %x(grep -r -o "I18n.t('.*)" bin/ lib/ | cut -d"'" -f2).each_line do |line| begin t = translate[lang] line.strip.split('.').each do |v| From 72c213b7b7112727642fced0e04fe6964c8e96a8 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <adrien.waksberg@doctolib.fr> Date: Sat, 13 May 2017 01:04:56 +0200 Subject: [PATCH 484/531] test: use dynamic translation --- test/test_cli.rb | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/test/test_cli.rb b/test/test_cli.rb index c3466e8..375de4e 100644 --- a/test/test_cli.rb +++ b/test/test_cli.rb @@ -1,10 +1,19 @@ #!/usr/bin/ruby require 'fileutils' +require 'i18n' require 'test/unit' class TestConfig < Test::Unit::TestCase def setup + if defined?(I18n.enforce_available_locales) + I18n.enforce_available_locales = true + end + + I18n::Backend::Simple.send(:include, I18n::Backend::Fallbacks) + I18n.load_path = ["#{File.expand_path('../../i18n', __FILE__)}/en.yml"] + I18n.locale = :en + @password = 'password' end @@ -13,8 +22,8 @@ class TestConfig < Test::Unit::TestCase FileUtils.rm_rf("#{Dir.home}/.gnupg") output = %x(echo "#{@password}\n#{@password}" | mpw config --init test@example.com) - assert_match('The config file has been created', output) - assert_match('Your GPG key has been created ;-)', output) + assert_match(I18n.t('form.setup_config.valid'), output) + assert_match(I18n.t('form.setup_gpg_key.valid'), output) end def test_01_add_item @@ -35,7 +44,7 @@ class TestConfig < Test::Unit::TestCase --group #{group} \ --random) puts output - assert_match('Item has been added!', output) + assert_match(I18n.t('form.add_item.valid'), output) output = %x(echo #{@password} | mpw list) puts output @@ -65,7 +74,7 @@ class TestConfig < Test::Unit::TestCase --new-group #{group_new} ) puts output - assert_match('Item has been updated!', output) + assert_match(I18n.t('form.update_item.valid'), output) output = %x(echo #{@password} | mpw list) puts output @@ -80,7 +89,7 @@ class TestConfig < Test::Unit::TestCase output = %x(echo "#{@password}\ny" | mpw delete -p #{host}) puts output - assert_match('The item has been removed!', output) + assert_match(I18n.t('form.delete_item.valid'), output) output = %x(echo #{@password} | mpw list) puts output From f41a9e68d32f9ec3651a9690310a3552da679512 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Thu, 11 May 2017 22:24:05 +0200 Subject: [PATCH 485/531] fix syntax for all tests --- test/test_item.rb | 5 +---- test/test_mpw.rb | 4 +--- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/test/test_item.rb b/test/test_item.rb index 961834e..4b0cf1b 100644 --- a/test/test_item.rb +++ b/test/test_item.rb @@ -6,9 +6,6 @@ require 'yaml' class TestItem < Test::Unit::TestCase def setup - @fixture_file = 'test/files/fixtures.yml' - @fixtures = YAML.load_file(@fixture_file) - if defined?(I18n.enforce_available_locales) I18n.enforce_available_locales = false end @@ -16,7 +13,7 @@ class TestItem < Test::Unit::TestCase I18n.load_path = Dir['./i18n/cli/*.yml'] I18n.default_locale = :en - puts + @fixtures = YAML.load_file('./test/files/fixtures.yml') end def test_00_add_without_name diff --git a/test/test_mpw.rb b/test/test_mpw.rb index dd005ca..2877d19 100644 --- a/test/test_mpw.rb +++ b/test/test_mpw.rb @@ -8,8 +8,6 @@ require 'csv' class TestMPW < Test::Unit::TestCase def setup - fixture_file = './test/files/fixtures.yml' - wallet_file = 'default.gpg' key = 'test@example.com' password = 'password' @@ -19,7 +17,7 @@ class TestMPW < Test::Unit::TestCase end @mpw = MPW::MPW.new(key, wallet_file, password) - @fixtures = YAML.load_file(fixture_file) + @fixtures = YAML.load_file('./test/files/fixtures.yml') end def test_00_decrypt_empty_file From ca2e0d9e479cd21cc6139428bb7c3076bce02655 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <adrien.waksberg@doctolib.fr> Date: Sat, 13 May 2017 12:28:42 +0200 Subject: [PATCH 486/531] test: update fixture --- test/files/fixtures.yml | 46 ++++++++--------- test/test_cli.rb | 60 ++++++++++------------ test/test_item.rb | 108 ++++++++++++++++++++-------------------- test/test_mpw.rb | 24 ++++----- 4 files changed, 114 insertions(+), 124 deletions(-) diff --git a/test/files/fixtures.yml b/test/files/fixtures.yml index 5651911..765314e 100644 --- a/test/files/fixtures.yml +++ b/test/files/fixtures.yml @@ -1,28 +1,28 @@ -add_new: - group: 'test_group' - host: 'test_host' - protocol: 'test_protocol' - user: 'test_user' - password: 'test_password' - port: '42' - comment: 'test_comment' +add: + group: 'Bank' + host: 'example.com' + protocol: 'https' + user: 'admin' + password: 'VmfnCN6pPIqgRIbc' + port: '8080' + comment: 'the website' -add_existing: +import: id: 'TEST-ID-XXXXX' - group: 'test_group_existing' - host: 'test_host_existing' - protocol: 'test_protocol_existing' - user: 'test_user_existing' - password: 'test_password_existing' - port: '44' - comment: 'test_comment_existing' + group: 'Cloud' + host: 'gogole.com' + protocol: 'https' + user: 'gg-2304' + password: 'TITl0kV9CDDa9sVK' + port: '8081' + comment: 'My little servers' created: 1386752948 update: - group: 'test_group_update' - host: 'test_host_update' - protocol: 'test_protocol_update' - user: 'test_user_update' - password: 'test_password_update' - port: '43' - comment: 'test_comment_update' + group: 'Assurance' + host: 'example2.com' + protocol: 'ssh' + user: 'root' + password: 'kbSrbv4WlMaVxaZ7' + port: '2222' + comment: 'i love ssh' diff --git a/test/test_cli.rb b/test/test_cli.rb index 375de4e..d92e175 100644 --- a/test/test_cli.rb +++ b/test/test_cli.rb @@ -15,6 +15,7 @@ class TestConfig < Test::Unit::TestCase I18n.locale = :en @password = 'password' + @fixtures = YAML.load_file(fixture_file) end def test_00_init_config @@ -27,65 +28,54 @@ class TestConfig < Test::Unit::TestCase end def test_01_add_item - host = 'example.com' - port = 1234 - proto = 'http' - user = 'root' - comment = 'the super website' - group = 'Bank' + data = @fixtures['add'] output = %x( echo #{@password} | mpw add \ - --host #{host} \ - --port #{port} \ - --protocol #{proto} \ - --user #{user} \ - --comment '#{comment}' \ - --group #{group} \ + --host #{data['host']} \ + --port #{data['port']} \ + --protocol #{data['protocol']} \ + --user #{data['user']} \ + --comment '#{data['comment']}' \ + --group #{data['group']} \ --random) puts output assert_match(I18n.t('form.add_item.valid'), output) output = %x(echo #{@password} | mpw list) puts output - assert_match(%r{#{proto}://.+#{host}.+:#{port}}, output) - assert_match(user, output) - assert_match(comment, output) - assert_match(group, output) + assert_match(%r{#{data['protocol']}://.+#{data['host']}.+:#{data['port']}}, output) + assert_match(data['user'], output) + assert_match(data['comment'], output) + assert_match(data['group'], output) end def test_02_update_item - host_old = 'example.com' - host_new = 'example2.com' - port_new = 4321 - proto_new = 'ssh' - user_new = 'tortue' - comment_new = 'my account' - group_new = 'Assurance' + data = @fixtures['update'] output = %x( echo #{@password} | mpw update \ - -p #{host_old} \ - --host #{host_new} \ - --port #{port_new} \ - --protocol #{proto_new} \ - --user #{user_new} \ - --comment '#{comment_new}' \ - --new-group #{group_new} + -p #{@fixtures['add']['host']} \ + --host #{data['host']} \ + --port #{data['port']} \ + --protocol #{data['protocol']} \ + --user #{data['user']} \ + --comment '#{data['comment']}' \ + --new-group #{data['group']} ) puts output assert_match(I18n.t('form.update_item.valid'), output) output = %x(echo #{@password} | mpw list) puts output - assert_match(%r{#{proto_new}://.+#{host_new}.+:#{port_new}}, output) - assert_match(user_new, output) - assert_match(comment_new, output) - assert_match(group_new, output) + assert_match(%r{#{data['protocol']}://.+#{data['host']}.+:#{data['port']}}, output) + assert_match(data['user'], output) + assert_match(data['comment'], output) + assert_match(data['group'], output) end def test_03_delete_item - host = 'example2.com' + host = @fixtures['update']['host'] output = %x(echo "#{@password}\ny" | mpw delete -p #{host}) puts output diff --git a/test/test_item.rb b/test/test_item.rb index 4b0cf1b..c83cbc3 100644 --- a/test/test_item.rb +++ b/test/test_item.rb @@ -20,14 +20,14 @@ class TestItem < Test::Unit::TestCase assert_raise(RuntimeError) { MPW::Item.new } end - def test_01_add_new + def test_01_add data = { - group: @fixtures['add_new']['group'], - host: @fixtures['add_new']['host'], - protocol: @fixtures['add_new']['protocol'], - user: @fixtures['add_new']['user'], - port: @fixtures['add_new']['port'], - comment: @fixtures['add_new']['comment'] + group: @fixtures['add']['group'], + host: @fixtures['add']['host'], + protocol: @fixtures['add']['protocol'], + user: @fixtures['add']['user'], + port: @fixtures['add']['port'], + comment: @fixtures['add']['comment'] } item = MPW::Item.new(data) @@ -35,24 +35,24 @@ class TestItem < Test::Unit::TestCase assert(!item.nil?) assert(!item.empty?) - assert_equal(@fixtures['add_new']['group'], item.group) - assert_equal(@fixtures['add_new']['host'], item.host) - assert_equal(@fixtures['add_new']['protocol'], item.protocol) - assert_equal(@fixtures['add_new']['user'], item.user) - assert_equal(@fixtures['add_new']['port'].to_i, item.port) - assert_equal(@fixtures['add_new']['comment'], item.comment) + assert_equal(@fixtures['add']['group'], item.group) + assert_equal(@fixtures['add']['host'], item.host) + assert_equal(@fixtures['add']['protocol'], item.protocol) + assert_equal(@fixtures['add']['user'], item.user) + assert_equal(@fixtures['add']['port'].to_i, item.port) + assert_equal(@fixtures['add']['comment'], item.comment) end - def test_02_add_existing + def test_02_import data = { - id: @fixtures['add_existing']['id'], - group: @fixtures['add_existing']['group'], - host: @fixtures['add_existing']['host'], - protocol: @fixtures['add_existing']['protocol'], - user: @fixtures['add_existing']['user'], - port: @fixtures['add_existing']['port'], - comment: @fixtures['add_existing']['comment'], - created: @fixtures['add_existing']['created'] + id: @fixtures['import']['id'], + group: @fixtures['import']['group'], + host: @fixtures['import']['host'], + protocol: @fixtures['import']['protocol'], + user: @fixtures['import']['user'], + port: @fixtures['import']['port'], + comment: @fixtures['import']['comment'], + created: @fixtures['import']['created'] } item = MPW::Item.new(data) @@ -60,24 +60,24 @@ class TestItem < Test::Unit::TestCase assert(!item.nil?) assert(!item.empty?) - assert_equal(@fixtures['add_existing']['id'], item.id) - assert_equal(@fixtures['add_existing']['group'], item.group) - assert_equal(@fixtures['add_existing']['host'], item.host) - assert_equal(@fixtures['add_existing']['protocol'], item.protocol) - assert_equal(@fixtures['add_existing']['user'], item.user) - assert_equal(@fixtures['add_existing']['port'].to_i, item.port) - assert_equal(@fixtures['add_existing']['comment'], item.comment) - assert_equal(@fixtures['add_existing']['created'], item.created) + assert_equal(@fixtures['import']['id'], item.id) + assert_equal(@fixtures['import']['group'], item.group) + assert_equal(@fixtures['import']['host'], item.host) + assert_equal(@fixtures['import']['protocol'], item.protocol) + assert_equal(@fixtures['import']['user'], item.user) + assert_equal(@fixtures['import']['port'].to_i, item.port) + assert_equal(@fixtures['import']['comment'], item.comment) + assert_equal(@fixtures['import']['created'], item.created) end def test_03_update data = { - group: @fixtures['add_new']['group'], - host: @fixtures['add_new']['host'], - protocol: @fixtures['add_new']['protocol'], - user: @fixtures['add_new']['user'], - port: @fixtures['add_new']['port'], - comment: @fixtures['add_new']['comment'] + group: @fixtures['add']['group'], + host: @fixtures['add']['host'], + protocol: @fixtures['add']['protocol'], + user: @fixtures['add']['user'], + port: @fixtures['add']['port'], + comment: @fixtures['add']['comment'] } item = MPW::Item.new(data) @@ -115,12 +115,12 @@ class TestItem < Test::Unit::TestCase def test_05_update_one_element data = { - group: @fixtures['add_new']['group'], - host: @fixtures['add_new']['host'], - protocol: @fixtures['add_new']['protocol'], - user: @fixtures['add_new']['user'], - port: @fixtures['add_new']['port'], - comment: @fixtures['add_new']['comment'] + group: @fixtures['add']['group'], + host: @fixtures['add']['host'], + protocol: @fixtures['add']['protocol'], + user: @fixtures['add']['user'], + port: @fixtures['add']['port'], + comment: @fixtures['add']['comment'] } item = MPW::Item.new(data) @@ -133,24 +133,24 @@ class TestItem < Test::Unit::TestCase sleep(1) assert(item.update(comment: @fixtures['update']['comment'])) - assert_equal(@fixtures['add_new']['group'], item.group) - assert_equal(@fixtures['add_new']['host'], item.host) - assert_equal(@fixtures['add_new']['protocol'], item.protocol) - assert_equal(@fixtures['add_new']['user'], item.user) - assert_equal(@fixtures['add_new']['port'].to_i, item.port) - assert_equal(@fixtures['update']['comment'], item.comment) + assert_equal(@fixtures['add']['group'], item.group) + assert_equal(@fixtures['add']['host'], item.host) + assert_equal(@fixtures['add']['protocol'], item.protocol) + assert_equal(@fixtures['add']['user'], item.user) + assert_equal(@fixtures['add']['port'].to_i, item.port) + assert_equal(@fixtures['update']['comment'], item.comment) assert_not_equal(last_edit, item.last_edit) end def test_05_delete data = { - group: @fixtures['add_new']['group'], - host: @fixtures['add_new']['host'], - protocol: @fixtures['add_new']['protocol'], - user: @fixtures['add_new']['user'], - port: @fixtures['add_new']['port'], - comment: @fixtures['add_new']['comment'] + group: @fixtures['add']['group'], + host: @fixtures['add']['host'], + protocol: @fixtures['add']['protocol'], + user: @fixtures['add']['user'], + port: @fixtures['add']['port'], + comment: @fixtures['add']['comment'] } item = MPW::Item.new(data) diff --git a/test/test_mpw.rb b/test/test_mpw.rb index 2877d19..a783225 100644 --- a/test/test_mpw.rb +++ b/test/test_mpw.rb @@ -32,12 +32,12 @@ class TestMPW < Test::Unit::TestCase def test_02_add_item data = { - group: @fixtures['add_new']['group'], - host: @fixtures['add_new']['host'], - protocol: @fixtures['add_new']['protocol'], - user: @fixtures['add_new']['user'], - port: @fixtures['add_new']['port'], - comment: @fixtures['add_new']['comment'] + group: @fixtures['add']['group'], + host: @fixtures['add']['host'], + protocol: @fixtures['add']['protocol'], + user: @fixtures['add']['user'], + port: @fixtures['add']['port'], + comment: @fixtures['add']['comment'] } item = MPW::Item.new(data) @@ -47,12 +47,12 @@ class TestMPW < Test::Unit::TestCase @mpw.read_data @mpw.add(item) - @mpw.set_password(item.id, @fixtures['add_new']['password']) + @mpw.set_password(item.id, @fixtures['add']['password']) assert_equal(1, @mpw.list.length) item = @mpw.list[0] - @fixtures['add_new'].each do |k, v| + @fixtures['add'].each do |k, v| if k == 'password' assert_equal(v, @mpw.get_password(item.id)) else @@ -68,7 +68,7 @@ class TestMPW < Test::Unit::TestCase assert_equal(1, @mpw.list.length) item = @mpw.list[0] - @fixtures['add_new'].each do |k, v| + @fixtures['add'].each do |k, v| if k == 'password' assert_equal(v, @mpw.get_password(item.id)) else @@ -110,9 +110,9 @@ class TestMPW < Test::Unit::TestCase end assert_equal(3, @mpw.list.length) - assert_equal(1, @mpw.list(group: @fixtures['add_new']['group']).length) - assert_equal(1, @mpw.list(pattern: 'existing').length) - assert_equal(2, @mpw.list(pattern: 'host_[eu]').length) + assert_equal(1, @mpw.list(group: @fixtures['add']['group']).length) + assert_equal(1, @mpw.list(pattern: 'gogole').length) + assert_equal(2, @mpw.list(pattern: 'example[2\.]').length) end def test_06_add_gpg_key From 5f7cb6e0cc40b61c1eeaaf392bbf5b54ad733781 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <adrien.waksberg@doctolib.fr> Date: Sat, 13 May 2017 19:30:23 +0200 Subject: [PATCH 487/531] add search test in cli --- lib/mpw/cli.rb | 4 ++-- test/test_cli.rb | 31 ++++++++++++++++++++++++------- 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index 4e2f240..cc0ebf0 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -464,7 +464,7 @@ module MPW items = @mpw.list(options) if items.empty? - puts "#{I18n.t('display.warning')}: #{I18n.t('warning.select')}".yellow + puts I18n.t('display.nothing') else table_items(items) if items.length > 1 @@ -489,7 +489,7 @@ module MPW items = @mpw.list(options) if items.empty? - puts "#{I18n.t('display.warning')}: #{I18n.t('warning.select')}".yellow + puts I18n.t('display.nothing') else table_items(items) diff --git a/test/test_cli.rb b/test/test_cli.rb index d92e175..8944ce2 100644 --- a/test/test_cli.rb +++ b/test/test_cli.rb @@ -15,7 +15,7 @@ class TestConfig < Test::Unit::TestCase I18n.locale = :en @password = 'password' - @fixtures = YAML.load_file(fixture_file) + @fixtures = YAML.load_file('./test/files/fixtures.yml') end def test_00_init_config @@ -50,7 +50,26 @@ class TestConfig < Test::Unit::TestCase assert_match(data['group'], output) end - def test_02_update_item + def test_02_search + data = @fixtures['add'] + + output = %x(echo #{@password} | mpw list --group #{data['group']}) + assert_match(%r{#{data['protocol']}://.+#{data['host']}.+:#{data['port']}}, output) + + output = %x(echo #{@password} | mpw list --pattern #{data['host']}) + assert_match(%r{#{data['protocol']}://.+#{data['host']}.+:#{data['port']}}, output) + + output = %x(echo #{@password} | mpw list --pattern #{data['comment']}) + assert_match(%r{#{data['protocol']}://.+#{data['host']}.+:#{data['port']}}, output) + + output = %x(echo #{@password} | mpw list --group R1Pmfbp626TFpjlr) + assert_match(I18n.t('display.nothing'), output) + + output = %x(echo #{@password} | mpw list --pattern h1IfnKqamaGM9oEX) + assert_match(I18n.t('display.nothing'), output) + end + + def test_03_update_item data = @fixtures['update'] output = %x( @@ -74,15 +93,13 @@ class TestConfig < Test::Unit::TestCase assert_match(data['group'], output) end - def test_03_delete_item - host = @fixtures['update']['host'] - - output = %x(echo "#{@password}\ny" | mpw delete -p #{host}) + def test_04_delete_item + output = %x(echo "#{@password}\ny" | mpw delete -p #{@fixtures['update']['host']}) puts output assert_match(I18n.t('form.delete_item.valid'), output) output = %x(echo #{@password} | mpw list) puts output - assert_no_match(/#{host}/, output) + assert_match(I18n.t('display.nothing'), output) end end From 62318fe0778e8c1f17d74ddbcf57e5585330fd1e Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Thu, 18 May 2017 23:03:30 +0200 Subject: [PATCH 488/531] add test cli for config --- bin/mpw-config | 2 +- test/test_cli.rb | 59 ++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 58 insertions(+), 3 deletions(-) diff --git a/bin/mpw-config b/bin/mpw-config index bec687d..0af88bd 100644 --- a/bin/mpw-config +++ b/bin/mpw-config @@ -88,7 +88,7 @@ OptionParser.new do |opts| values[:pwd_special] = true end - opts.on('-S', '--disable_special-chars', I18n.t('option.special_chars')) do + opts.on('-S', '--disable-special-chars', I18n.t('option.special_chars')) do values[:pwd_special] = false end diff --git a/test/test_cli.rb b/test/test_cli.rb index 8944ce2..56326c2 100644 --- a/test/test_cli.rb +++ b/test/test_cli.rb @@ -16,13 +16,14 @@ class TestConfig < Test::Unit::TestCase @password = 'password' @fixtures = YAML.load_file('./test/files/fixtures.yml') + @gpg_key = 'test@example.com' end def test_00_init_config FileUtils.rm_rf("#{Dir.home}/.config/mpw") FileUtils.rm_rf("#{Dir.home}/.gnupg") - output = %x(echo "#{@password}\n#{@password}" | mpw config --init test@example.com) + output = %x(echo "#{@password}\n#{@password}" | mpw config --init #{@gpg_key}) assert_match(I18n.t('form.setup_config.valid'), output) assert_match(I18n.t('form.setup_gpg_key.valid'), output) end @@ -38,7 +39,8 @@ class TestConfig < Test::Unit::TestCase --user #{data['user']} \ --comment '#{data['comment']}' \ --group #{data['group']} \ - --random) + --random + ) puts output assert_match(I18n.t('form.add_item.valid'), output) @@ -102,4 +104,57 @@ class TestConfig < Test::Unit::TestCase puts output assert_match(I18n.t('display.nothing'), output) end + + def test_05_setup_config + gpg_key = 'user@example2.com' + gpg_exe = '/usr/bin/gpg2' + wallet_dir = '/tmp/mpw' + length = 24 + wallet = 'work' + + output = %x( + mpw config \ + --gpg-exe #{gpg_exe} \ + --enable-pinmode \ + --disable-alpha \ + --disable-special-chars \ + --disable-numeric \ + --length #{length} \ + --wallet-dir #{wallet_dir} \ + --default-wallet #{wallet} + ) + puts output + assert_match(I18n.t('form.set_config.valid'), output) + + output = %x(mpw config) + puts output + assert_match(/gpg_key.+\| #{@gpg_key}/, output) + assert_match(/gpg_exe.+\| #{gpg_exe}/, output) + assert_match(/pinmode.+\| true/, output) + assert_match(/default_wallet.+\| #{wallet}/, output) + assert_match(/wallet_dir.+\| #{wallet_dir}/, output) + assert_match(/password_length.+\| #{length}/, output) + %w[numeric alpha special].each do |k| + assert_match(/password_#{k}.+\| false/, output) + end + + output = %x( + mpw config \ + --key #{gpg_key} \ + --alpha \ + --special-chars \ + --numeric \ + --disable-pinmode + ) + puts output + assert_match(I18n.t('form.set_config.valid'), output) + + output = %x(mpw config) + puts output + assert_match(/gpg_key.+\| #{gpg_key}/, output) + assert_match(/pinmode.+\| false/, output) + %w[numeric alpha special].each do |k| + assert_match(/password_#{k}.+\| true/, output) + end + end end From 8e4fb1c91bf2701d8ded1a9ff9db36d0003d763a Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Thu, 18 May 2017 23:30:54 +0200 Subject: [PATCH 489/531] fix show config --- lib/mpw/cli.rb | 2 +- lib/mpw/config.rb | 14 ++++++++------ 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index cc0ebf0..d794434 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -105,7 +105,7 @@ module MPW 'lang' => @config.lang, 'gpg_key' => @config.gpg_key, 'default_wallet' => @config.default_wallet, - 'config_dir' => @config.config_dir, + 'wallet_dir' => @config.wallet_dir, 'pinmode' => @config.pinmode, 'gpg_exe' => @config.gpg_exe } diff --git a/lib/mpw/config.rb b/lib/mpw/config.rb index bdcf394..016c690 100644 --- a/lib/mpw/config.rb +++ b/lib/mpw/config.rb @@ -58,11 +58,13 @@ module MPW wallet_dir = options[:wallet_dir] || @wallet_dir default_wallet = options[:default_wallet] || @default_wallet gpg_exe = options[:gpg_exe] || @gpg_exe - pinmode = options[:pinmode] || @pinmode - password = { numeric: true, - alpha: true, - special: false, - length: 16 } + pinmode = options.key?(:pinmode) ? options[:pinmode] : @pinmode + password = { + numeric: true, + alpha: true, + special: false, + length: 16 + } %w[numeric special alpha length].each do |k| if options.key?("pwd_#{k}".to_sym) @@ -134,7 +136,7 @@ module MPW @default_wallet = config['default_wallet'] @gpg_exe = config['gpg_exe'] @password = config['password'] || {} - @pinmode = config['pinmode'] + @pinmode = config['pinmode'] || false raise if @gpg_key.empty? || @wallet_dir.empty? From 7c369861418c0b0f5a262476ceef7d515a2562ae Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Fri, 19 May 2017 22:28:15 +0200 Subject: [PATCH 490/531] feat: show wallet list by default --- bin/mpw-wallet | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/bin/mpw-wallet b/bin/mpw-wallet index c23e1e2..caee35d 100644 --- a/bin/mpw-wallet +++ b/bin/mpw-wallet @@ -74,12 +74,10 @@ cli = MPW::Cli.new(config) cli.load_config -if options.key?(:list) - cli.list_wallet -elsif options.key?(:path) +if options.key?(:path) cli.get_wallet(options[:wallet]) cli.set_wallet_path(options[:path]) -else +elsif options.key?(:list_keys) || options.key?(:gpg_key) cli.get_wallet(options[:wallet]) cli.decrypt @@ -88,4 +86,6 @@ else elsif options.key?(:gpg_key) options[:delete] ? cli.delete_key(options[:gpg_key]) : cli.add_key(options[:gpg_key]) end +else + cli.list_wallet end From 3b9ff8c15cb2bd0229fa31407da4e6a909b4ebb9 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Sat, 20 May 2017 08:06:50 +0200 Subject: [PATCH 491/531] add test cli for wallet options --- .travis.yml | 1 + test/init.rb | 8 ++++++-- test/test_cli.rb | 50 +++++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 52 insertions(+), 7 deletions(-) diff --git a/.travis.yml b/.travis.yml index f9db456..b640d4d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,4 +18,5 @@ script: - ruby ./test/test_item.rb - ruby ./test/test_mpw.rb - ruby ./test/test_translate.rb + - ruby ./test/init.rb - ruby ./test/test_cli.rb diff --git a/test/init.rb b/test/init.rb index be7a73a..6da9ecb 100644 --- a/test/init.rb +++ b/test/init.rb @@ -1,13 +1,17 @@ #!/usr/bin/ruby +require 'fileutils' require 'gpgme' +FileUtils.rm_rf("#{Dir.home}/.config/mpw") +FileUtils.rm_rf("#{Dir.home}/.gnupg") + param = '' param << '<GnupgKeyParms format="internal">' + "\n" param << "Key-Type: RSA\n" -param << "Key-Length: 2048\n" +param << "Key-Length: 512\n" param << "Subkey-Type: ELG-E\n" -param << "Subkey-Length: 2048\n" +param << "Subkey-Length: 512\n" param << "Name-Real: test\n" param << "Name-Comment: test\n" param << "Name-Email: test2@example.com\n" diff --git a/test/test_cli.rb b/test/test_cli.rb index 56326c2..3e97308 100644 --- a/test/test_cli.rb +++ b/test/test_cli.rb @@ -1,6 +1,5 @@ #!/usr/bin/ruby -require 'fileutils' require 'i18n' require 'test/unit' @@ -20,9 +19,6 @@ class TestConfig < Test::Unit::TestCase end def test_00_init_config - FileUtils.rm_rf("#{Dir.home}/.config/mpw") - FileUtils.rm_rf("#{Dir.home}/.gnupg") - output = %x(echo "#{@password}\n#{@password}" | mpw config --init #{@gpg_key}) assert_match(I18n.t('form.setup_config.valid'), output) assert_match(I18n.t('form.setup_gpg_key.valid'), output) @@ -105,7 +101,51 @@ class TestConfig < Test::Unit::TestCase assert_match(I18n.t('display.nothing'), output) end - def test_05_setup_config + def test_05_setup_wallet + path = '/tmp/' + gpg_key = 'test2@example.com' + + output = %x(echo #{@password} | mpw wallet --add-gpg-key #{gpg_key}) + puts output + assert_match(I18n.t('form.add_key.valid'), output) + + output = %x(echo #{@password} | mpw wallet --list-keys) + puts output + assert_match("| #{@gpg_key}", output) + assert_match("| #{gpg_key}", output) + + output = %x(echo #{@password} | mpw wallet --delete-gpg-key #{gpg_key}) + puts output + assert_match(I18n.t('form.delete_key.valid'), output) + + output = %x(echo #{@password} | mpw wallet --list-keys) + puts output + assert_match("| #{@gpg_key}", output) + assert_no_match(/\| #{gpg_key}/, output) + + output = %x(mpw wallet) + puts output + assert_match('| default', output) + + output = %x(mpw wallet --path #{path}) + puts output + assert_match(I18n.t('form.set_wallet_path.valid'), output) + + output = %x(mpw config) + puts output + assert_match(%r{path_wallet_default.+\| #{path}/default.mpw}, output) + assert(File.exist?("#{path}/default.mpw")) + + output = %x(mpw wallet --default-path) + puts output + assert_match(I18n.t('form.set_wallet_path.valid'), output) + + output = %x(mpw config) + puts output + assert_no_match(/path_wallet_default/, output) + end + + def test_06_setup_config gpg_key = 'user@example2.com' gpg_exe = '/usr/bin/gpg2' wallet_dir = '/tmp/mpw' From 01831c1f2b703bc2e99f84e9328f7b52874e52cd Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Sat, 20 May 2017 11:31:37 +0200 Subject: [PATCH 492/531] add test cli for genpwd --- test/test_cli.rb | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/test/test_cli.rb b/test/test_cli.rb index 3e97308..85d5a5a 100644 --- a/test/test_cli.rb +++ b/test/test_cli.rb @@ -197,4 +197,29 @@ class TestConfig < Test::Unit::TestCase assert_match(/password_#{k}.+\| true/, output) end end + + def test_07_generate_password + length = 24 + + output = %x( + mpw genpwd \ + --length #{length} \ + --alpha + ) + assert_match(/[a-zA-Z]{#{length}}/, output) + + output = %x( + mpw genpwd \ + --length #{length} \ + --numeric + ) + assert_match(/[0-9]{#{length}}/, output) + + output = %x( + mpw genpwd \ + --length #{length} \ + --special-chars + ) + assert_no_match(/[a-zA-Z0-9]/, output) + end end From 811c576aae1866978dfb62b9c04f8d1f53898f0b Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Sat, 20 May 2017 12:03:57 +0200 Subject: [PATCH 493/531] fix password generator --- lib/mpw/mpw.rb | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index fbca576..9917801 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -301,11 +301,9 @@ module MPW chars = [*('A'..'Z'), *('a'..'z'), *('0'..'9')] if chars.empty? result = '' - while length > 62 - result << chars.sample(62).join - length -= 62 + length.times do + result << chars.sample end - result << chars.sample(length).join result end From efff66b12e8c52bdb374cdac9b39c5c69d888cef Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Sat, 20 May 2017 13:26:12 +0200 Subject: [PATCH 494/531] add test cli for export and import --- test/files/fixtures-import.yml | 19 +++++++++++++++++++ test/test_cli.rb | 34 +++++++++++++++++++++++++++++++--- 2 files changed, 50 insertions(+), 3 deletions(-) create mode 100644 test/files/fixtures-import.yml diff --git a/test/files/fixtures-import.yml b/test/files/fixtures-import.yml new file mode 100644 index 0000000..f79ab0a --- /dev/null +++ b/test/files/fixtures-import.yml @@ -0,0 +1,19 @@ +--- +1: + host: fric.com + user: 230403 + group: Bank + password: 5XdiTQOubRDw9B0aJoMlcEyL + protocol: https + port: + otp_key: 330223432 + comment: I love my bank +2: + host: assurance.com + user: user_2132 + group: Assurance + password: DMyK6B3v4bWO52VzU7aTHIem + protocol: https + port: 443 + otp_key: + comment: diff --git a/test/test_cli.rb b/test/test_cli.rb index 85d5a5a..2dd411f 100644 --- a/test/test_cli.rb +++ b/test/test_cli.rb @@ -101,7 +101,35 @@ class TestConfig < Test::Unit::TestCase assert_match(I18n.t('display.nothing'), output) end - def test_05_setup_wallet + def test_05_import_export + file_import = './test/files/fixtures-import.yml' + file_export = '/tmp/test-mpw.yml' + + output = %x(echo #{@password} | mpw import --file #{file_import}) + assert_match(I18n.t('form.import.valid', file: file_import), output) + + output = %x(echo #{@password} | mpw export --file #{file_export}) + assert_match(I18n.t('form.export.valid', file: file_export), output) + assert(File.exist?(file_export)) + assert_equal(YAML.load_file(file_export).length, 2) + + YAML.load_file(file_import).each_value do |import| + error = true + + YAML.load_file(file_export).each_value do |export| + next if import['host'] != export['host'] + + %w[user group password protocol port otp_key comment].each do |key| + assert_equal(import[key].to_s, export[key].to_s) + end + + error = false + end + assert(!error) + end + end + + def test_06_setup_wallet path = '/tmp/' gpg_key = 'test2@example.com' @@ -145,7 +173,7 @@ class TestConfig < Test::Unit::TestCase assert_no_match(/path_wallet_default/, output) end - def test_06_setup_config + def test_07_setup_config gpg_key = 'user@example2.com' gpg_exe = '/usr/bin/gpg2' wallet_dir = '/tmp/mpw' @@ -198,7 +226,7 @@ class TestConfig < Test::Unit::TestCase end end - def test_07_generate_password + def test_08_generate_password length = 24 output = %x( From 6541931b792431fbe5181e145a76403ffb9ed4a4 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Sat, 20 May 2017 15:30:19 +0200 Subject: [PATCH 495/531] enable text editor if threre isn't nothing value who has been set --- bin/mpw-update | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bin/mpw-update b/bin/mpw-update index 5e2c62d..143e187 100644 --- a/bin/mpw-update +++ b/bin/mpw-update @@ -93,6 +93,8 @@ end.parse! config = MPW::Config.new(options[:config]) cli = MPW::Cli.new(config) +options[:text_editor] = true if values.empty? + cli.load_config cli.get_wallet(options[:wallet]) cli.decrypt From 90486d1e9338f57801f029622fde5b0d0cd4e96c Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Sat, 20 May 2017 15:42:28 +0200 Subject: [PATCH 496/531] update README --- README.md | 61 ++++++++++++++++++++++++++++--------------------------- 1 file changed, 31 insertions(+), 30 deletions(-) diff --git a/README.md b/README.md index afb4ade..c1abef6 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,9 @@ mpw config --init user@host.com Add your first item: ``` -mpw add +mpw add --host assurance.com --port 443 --user user_2132 --protocol https --random +mpw add --host fric.com --user 230403 --otp-code 23434113 --protocol https --comment 'I love my bank' --random + ``` And list your items: @@ -40,46 +42,45 @@ mpw list ``` or search an item with ``` -mpw list --pattern Da +mpw list --pattern love mpw list --group bank ``` Output: ``` +Assurance + ========================================================================== + ID | Host | User | OTP | Comment + ========================================================================== + 1 | https://assurance.com:443 | user_2132 | | + Bank - ============================================================================== - ID | Host | User | Protocol | Port | OTP | Comment - ============================================================================== - 1 | bank.com | 1234456 | https | | X | - -Linux - ============================================================================== - ID | Host | User | Protocol | Port | OTP | Comment - ============================================================================== - 2 | linuxfr.org | example | https | | | Da Linux French Site - + ========================================================================== + ID | Host | User | OTP | Comment + ========================================================================== + 3 | https://fric.com | 230403 | X | I love my bank ``` Copy a password, login or OTP code: ``` -mpw copy -p linuxfr +mpw copy -p assurance.com ``` Update an item: ``` -mpw update -p linuxfr +mpw update -p assurance.com ``` Delete an item: ``` -mpw delete -p linuxfr +mpw delete -p assurance.com ``` ### Manage wallets List all available wallets: ``` -mpw wallet --list +mpw wallet ``` List all GPG keys in wallet: @@ -116,23 +117,23 @@ Example yaml file for mpw: ``` --- 1: - host: bank.com - user: 123456 + host: fric.com + user: 230403 group: Bank - password: secret + password: 5XdiTQOubRDw9B0aJoMlcEyL protocol: https - port: - otp_key: 1afg34 - comment: + port: + otp_key: 330223432 + comment: I love my bank 2: - host: linuxfr.org - user: example - group: - password: 'complex %- password' + host: assurance.com + user: user_2132 + group: Assurance + password: DMyK6B3v4bWO52VzU7aTHIem protocol: https - port: - otp_key: - comment: Da Linux French Site + port: 443 + otp_key: + comment: ``` ### Config From 5f29f7b6e826c104dbd074650cc58d9342d9ee3b Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Sun, 21 May 2017 17:19:46 +0200 Subject: [PATCH 497/531] add test cli for copy mode --- test/test_cli.rb | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/test/test_cli.rb b/test/test_cli.rb index 2dd411f..8fb91ee 100644 --- a/test/test_cli.rb +++ b/test/test_cli.rb @@ -129,7 +129,19 @@ class TestConfig < Test::Unit::TestCase end end - def test_06_setup_wallet + def test_06_copy + data = YAML.load_file('./test/files/fixtures-import.yml')[1] + + output = %x( + echo "#{@password}\np\nq" | mpw copy \ + --disable-clipboard \ + -p #{data['host']} + ) + puts output + assert_match(data['password'], output) + end + + def test_07_setup_wallet path = '/tmp/' gpg_key = 'test2@example.com' @@ -173,7 +185,7 @@ class TestConfig < Test::Unit::TestCase assert_no_match(/path_wallet_default/, output) end - def test_07_setup_config + def test_08_setup_config gpg_key = 'user@example2.com' gpg_exe = '/usr/bin/gpg2' wallet_dir = '/tmp/mpw' @@ -226,7 +238,7 @@ class TestConfig < Test::Unit::TestCase end end - def test_08_generate_password + def test_09_generate_password length = 24 output = %x( From ab459f954d0867a69582783acd7f33e338a7b401 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Sun, 21 May 2017 18:00:43 +0200 Subject: [PATCH 498/531] feat: add copy url --- i18n/en.yml | 2 ++ i18n/fr.yml | 2 ++ lib/mpw/cli.rb | 9 +++++++++ 3 files changed, 13 insertions(+) diff --git a/i18n/en.yml b/i18n/en.yml index 402facd..cd78280 100644 --- a/i18n/en.yml +++ b/i18n/en.yml @@ -111,8 +111,10 @@ en: login: "The login has been copied in clipboard." password: "The password has been copied in clipboard for 30s!" otp: "The OTP code has been copied for %{time}s!" + url: "The URL has been copied in clipboard." help: name: "Help" + url: "Press <u> to copy URL" login: "Press <l> to copy the login" password: "Press <p> to copy the password" otp_code: "Press <o> to copy the otp code" diff --git a/i18n/fr.yml b/i18n/fr.yml index b1b4ecc..d529ee4 100644 --- a/i18n/fr.yml +++ b/i18n/fr.yml @@ -111,8 +111,10 @@ fr: login: "L'identifiant a été copié dans le presse papier" password: "Le mot de passe a été copié dans le presse papier pour 30s!" otp: "Le code OTP a été copié dans le presse papier il est valable %{time}s!" + url: "L'URL a été copié dans le presse papier" help: name: "Aide" + url: "Pressez <u> pour copier l'URL" login: "Pressez <l> pour copier l'identifiant" password: "Pressez <p> pour copier le mot de passe" otp_code: "Pressez <o> pour copier le code OTP" diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index d794434..ccf212c 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -300,6 +300,14 @@ module MPW when 'q', 'quit' break + when 'u', 'url' + if clipboard + Clipboard.copy(item.url) + puts I18n.t('form.clipboard.url').green + else + puts item.url + end + when 'l', 'login' if clipboard Clipboard.copy(item.user) @@ -332,6 +340,7 @@ module MPW else puts "----- #{I18n.t('form.clipboard.help.name')} -----".cyan + puts I18n.t('form.clipboard.help.url') puts I18n.t('form.clipboard.help.login') puts I18n.t('form.clipboard.help.password') puts I18n.t('form.clipboard.help.otp_code') From dcb286ec09b56588df5e959459fc3f60f358c678 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Mon, 22 May 2017 20:32:06 +0200 Subject: [PATCH 499/531] add gem for development --- Gemfile | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Gemfile b/Gemfile index 71d84d4..1fdac16 100644 --- a/Gemfile +++ b/Gemfile @@ -6,3 +6,8 @@ gem 'highline', '~> 1.7', '>= 1.7.8' gem 'i18n', '~> 0.7', '>= 0.7.0' gem 'locale', '~> 2.1', '>= 2.1.2' gem 'rotp', '~> 3.1', '>= 3.1.0' + +group :development do + gem 'rubocop' + gem 'yard' +end From 1fcac965e975ba9b11f47cebb3be3d106c165c1d Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Mon, 22 May 2017 20:32:27 +0200 Subject: [PATCH 500/531] fix comments --- lib/mpw/cli.rb | 4 ++-- lib/mpw/mpw.rb | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index ccf212c..02ede97 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -273,7 +273,7 @@ module MPW # Get an item when multiple choice # @param items [Array] list of items - # @return item [Item] + # @return [Item] an item def get_item(items) return items[0] if items.length == 1 @@ -414,7 +414,7 @@ module MPW end # Text editor interface - # @param template [String] template name + # @param template_name [String] template name # @param item [Item] the item to edit # @param password [Boolean] disable field password # @return [Hash] the values for an item diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index 9917801..5905492 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -221,7 +221,7 @@ module MPW end # Search in some csv data - # @params options [Hash] + # @param options [Hash] # @return [Array] a list with the resultat of the search def list(**options) result = [] From b83b27832e5d44e5c8cb726279b234529dcfa3ed Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Mon, 22 May 2017 21:25:56 +0200 Subject: [PATCH 501/531] feat: no ask password if not necessary --- lib/mpw/cli.rb | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index 02ede97..d92e4e4 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -126,12 +126,20 @@ module MPW # Request the GPG password and decrypt the file def decrypt - unless defined?(@mpw) - @password = ask(I18n.t('display.gpg_password')) { |q| q.echo = false } - @mpw = MPW.new(@config.gpg_key, @wallet_file, @password, @config.gpg_exe, @config.pinmode) - end + if defined?(@mpw) + @mpw.read_data + else + begin + @mpw = MPW.new(@config.gpg_key, @wallet_file, nil, @config.gpg_exe, @config.pinmode) - @mpw.read_data + @mpw.read_data + rescue + @password = ask(I18n.t('display.gpg_password')) { |q| q.echo = false } + @mpw = MPW.new(@config.gpg_key, @wallet_file, @password, @config.gpg_exe, @config.pinmode) + + @mpw.read_data + end + end rescue => e puts "#{I18n.t('display.error')} #11: #{e}".red exit 2 From a2c2711ddc1f5a60dc5fd4b62172e6f5b66a6d11 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Tue, 23 May 2017 19:33:05 +0200 Subject: [PATCH 502/531] add gem test-unit for development --- .travis.yml | 2 -- Gemfile | 1 + 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index b640d4d..525a9d0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,8 +6,6 @@ rvm: - 2.1.10 install: - bundle install - - gem install 'test-unit' - - gem install rubocop - echo 9999 > VERSION - gem build mpw.gemspec - gem install mpw-9999.gem diff --git a/Gemfile b/Gemfile index 1fdac16..56b6638 100644 --- a/Gemfile +++ b/Gemfile @@ -9,5 +9,6 @@ gem 'rotp', '~> 3.1', '>= 3.1.0' group :development do gem 'rubocop' + gem 'test-unit' gem 'yard' end From 6ea40e542025d9b186b0edce061da89423627533 Mon Sep 17 00:00:00 2001 From: fbonely <fanny.bonely@arte.tv> Date: Tue, 23 May 2017 19:49:20 +0200 Subject: [PATCH 503/531] Update translations EN --- i18n/en.yml | 96 ++++++++++++++++++++++++++--------------------------- 1 file changed, 48 insertions(+), 48 deletions(-) diff --git a/i18n/en.yml b/i18n/en.yml index cd78280..b50fd63 100644 --- a/i18n/en.yml +++ b/i18n/en.yml @@ -5,27 +5,27 @@ en: config: write: "Can't write the config file!" load: "Checkconfig failed!" - key_bad_format: "The key string isn't in good format!" - no_key_public: "You haven't the public key of %{key}!" + key_bad_format: "The key string isn't in the right format!" + no_key_public: "You haven't entered the public key of %{key}!" genkey_gpg: exception: "Can't create the GPG key!" name: "You must define a name for your GPG key!" password: "You must define a password for your GPG key!" - empty: "The class is void" + empty: "The class is empty" export: "Can't export, unable to write in %{file}!" export_key: "Can't export the GPG key" gpg_file: decrypt: "Can't decrypt file!" encrypt: "Can't encrypt the GPG file!" mpw_file: - read_data: "Can't to read the MPW file!" - write_data: "Can't to write the MPW file!" + read_data: "Can't read the MPW file!" + write_data: "Can't write the MPW file!" import: "Can't import, unable to read %{file}!" update: host_empty: "You must define a host!" warning: - select: 'Your choice is not a valid element!' + select: 'Your choice is not a valid item!' command: add: "Add a new item" @@ -41,37 +41,37 @@ en: option: add: "Add an item or key" - add_gpg_key: "Share the wallet with an other GPG key" - alpha: "Use letter to generate a password" + add_gpg_key: "Share the wallet with another GPG key" + alpha: "Use letter to create a password" comment: "Specify a comment" config: "Specify the configuration file to use" clipboard: "Disable the clipboard feature" - default_path: "Move the wallet in default directory" + default_path: "Move the wallet to the default directory" default_wallet: "Specify the default wallet to use" - delete_gpg_key: "Delete the wallet's share with an other GPG key" - disable_alpha: "Don't use letter to generate a password" - disable_numeric: "Don't use number to generate a password" + delete_gpg_key: "Delete wallet sharing with an other GPG key" + disable_alpha: "Don't use letters to create a password" + disable_numeric: "Don't use numbers to generate a password" disable_pinmode: "Disable the pinentry mode" - disable_special_chars: "Don't use special char to generate a password" + disable_special_chars: "Don't use special char to create a password" export: "Export a wallet in an yaml file" - file_export: "Specify the file where export data" + file_export: "Specify the file to export data" file_import: "Specify the file to import" - force: "No ask to confirm when you delete an item" - generate_password: "Generate a random password (default 8 characters)" + force: "Do not ask confirmation when deleting an item" + generate_password: "Create a random password (default 8 characters)" gpg_exe: "Set the gpg binary path to use" gpg_key: "Specify a GPG key (ex: user@example.com)" group: "Search the items with specified group" help: "Show this help message" host: "Specify a host or ip" init: "Initialize mpw" - import: "Import item since a yaml file" - key: "Specify the key name" + import: "Import item from an yaml file" + key: "Define the key name" lang: "Set the software language" length: "Size of the password" list: "List the wallets" list_keys: "List the GPG keys in wallet" - new_group: "Specify the group for the item" - numeric: "Use number to generate a password" + new_group: "Define a group for the item" + numeric: "Use number to create a password" otp_code: "Set an otp key" path: "Move the wallet in new specify directory" pattern: "Given search pattern" @@ -81,11 +81,11 @@ en: random_password: "Generate a random password" setup: "Create a new configuration file" setup_wallet: "Create a new configuration file for a wallet" - special_chars: "Use special char to generate a password" - show: "Search and show the items" - show_all: "List all items" + special_chars: "Use special char to create a password" + show: "Search and display the items" + show_all: "Listing all items" text_editor: "Use text editor to edit the item" - usage: "Usage" + usage: "Use" user: "Set an user" wallet: "Specify a wallet to use" wallet_dir: "Set the wallets folder" @@ -95,13 +95,13 @@ en: add_key: valid: "Key has been added!" add_item: - name: "The item's name (mandatory" - group: "The group's name" - host: "The hostname or ip" - protocol: "The protocol of the connection (ssh, http, ...)" - login: "The login of connection" - password: "The password" - port: "The connection port" + name: "Item name (mandatory)" + group: "Group name" + host: "Hostname or ip" + protocol: "Connection protocol (ssh, http, ...)" + login: "Connection ID" + password: "Password" + port: "Connection port" comment: "A comment" otp_key: "The OTP secret" valid: "Item has been added!" @@ -110,7 +110,7 @@ en: clean: "The clipboard has been cleaned." login: "The login has been copied in clipboard." password: "The password has been copied in clipboard for 30s!" - otp: "The OTP code has been copied for %{time}s!" + otp: "The OTP code has been copied %{time}s!" url: "The URL has been copied in clipboard." help: name: "Help" @@ -122,18 +122,18 @@ en: delete_key: valid: "Key has been deleted!" delete_item: - ask: "Are you sure you want to remove the item ?" + ask: "Are you sure you want to remove this item ?" valid: "The item has been removed!" import: ask: "Are you sure you want to import this file %{file} ?" file_empty: "The import file is empty!" file_not_exist: "The import file doesn't exist!" - valid: "The import is succesfull!" + valid: "The import is successful!" not_valid: "No data to import!" set_config: valid: "The config file has been edited!" set_wallet_path: - valid: "The wallet has well moved!" + valid: "The wallet has been moved!" setup_config: title: "Setup a new config file" lang: "Choose your language (en, fr, ...) [default=%{lang}]: " @@ -143,36 +143,36 @@ en: valid: "The config file has been created!" setup_gpg_key: title: "Setup a GPG key" - ask: "Do you want create your GPG key ? (Y/n)" - no_create: "You must create manually your GPG key or relaunch the software." + ask: "Do you want to create your GPG key ? (Y/n)" + no_create: "You must to create manually your GPG key or relaunch the software." name: "Your name and lastname: " password: "A password for the GPG key: " confirm_password: "Confirm your password: " error_password: "Your passwords aren't identical!" length: "Size of the GPG key [default=2048]: " expire: "Expire time of the GPG key [default=0 (unlimited)]: " - wait: "Please waiting during the GPG key generate, this process can take few minutes." + wait: "Please wait until GPG key is created, this process can take a few minutes." valid: "Your GPG key has been created ;-)" update_item: - name: "The item's name (mandatory" - group: "The group's name" - host: "The hostname or ip" - protocol: "The protocol of the connection (ssh, http, ...)" - login: "The login of connection" - password: "The password (leave empty if you don't want change)" - port: "The connection port" + name: "Item name (mandatory)" + group: "Group name" + host: "Hostname or ip" + protocol: "Connection protocol (ssh, http, ...)" + login: "Login id" + password: "Password (leave empty if you don't want to update it)" + port: "Connection port" comment: "A comment" - otp_key: "The OTP secret (leave empty if you don't want change" + otp_key: "Secret OTP (leave empty if you don't want to update it" valid: "Item has been updated!" export: - valid: "The export in %{file} is succesfull!" + valid: "The export in %{file} is successful!" display: comment: "Comment" config: "Configuration" error: "ERROR" keys: "GPG keys" - gpg_password: "GPG passphrase: " + gpg_password: "GPG password: " group: "Group" login: "Login" name: "Name" From 767343e36879dee6f9bed415119be93906b66329 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Tue, 6 Jun 2017 22:56:23 +0200 Subject: [PATCH 504/531] update version 4.2.0 --- CHANGELOG.md | 43 ++++++++++++++++++++++++++++++++----------- README.md | 2 +- VERSION | 2 +- 3 files changed, 34 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1fb8d79..2430516 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,9 +1,18 @@ # CHANGELOG -## v4.1.1 +## v4.2.0 (2017-06-06) + + * feat: improve the interface + * feat: add copy url + * feat: add unit tests for cli + * feat: comment the code with yarn syntax + * fix several bugs + * fix translations + +## v4.1.1 (2017-05-03) * fix bug in init -## v4.1.0 +## v4.1.0 (2017-04-22) * feat: add options to update or add an item in command line * feat: print config @@ -12,18 +21,18 @@ * fix: pinentry mode with gpg >= 2.1 * remove SSH and FTP synchronization -## v4.0.0 +## v4.0.0 (2017-03-09) * feature: set default wallet * add option for generate a random password when you update an item * fix encryption when you share an existing wallet * several bugs fix -## v4.0.0-beta1 +## v4.0.0-beta1 (2017-02-16) * add manage share key with new interface -## v4.0.0-beta +## v4.0.0-beta (2016-11-11) * new interface with a table * new command line interface @@ -32,38 +41,50 @@ * several bugs fix * add unit tests -## v3.2.1 +## v3.2.1 (2016-08-06) * fix bug when add a new item -## v3.2.0 +## v3.2.0 (2016-08-03) * add support OTP * fix bug in synchronize * improve interface -## v3.1.0 +## v3.1.0 (2016-07-09) * add clipboard * can change gpg version * minor change in interface * several bugs fix -## v3.0.0 +## v3.0.0 (2016-07-05) * new storage format * new share system * remove MPW server -## v2.0.0 +## v2.0.3 (2015-09-27) + + * add no-sync option + +## v2.0.1 (2015-06-23) + + * fix mpw-ssh + +## v2.0.0 (2015-06-22) * change format csv to yaml * easy install with gem * add sync with ftp and ssh * many improvement -## v1.1.0 +## v1.1.0 (2014-01-28) * Add sync with MPW Server * Add MPW Server * Fix minors bugs + +## v1.0.0 (2014-01-15) + + * first release diff --git a/README.md b/README.md index c1abef6..8a39d81 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # MPW: Manage your passwords! -[](https://github.com/nishiki/manage-password/releases) +[](https://github.com/nishiki/manage-password/releases) [](https://travis-ci.org/nishiki/manage-password) [](https://github.com/nishiki/manage-password/blob/master/LICENSE) diff --git a/VERSION b/VERSION index 627a3f4..6aba2b2 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -4.1.1 +4.2.0 From 11de55ccb76f6899071130a61ca7ebe0187ad9b9 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Tue, 6 Jun 2017 23:06:25 +0200 Subject: [PATCH 505/531] update Gemfile to fix rubocop version --- Gemfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile b/Gemfile index 56b6638..de2741f 100644 --- a/Gemfile +++ b/Gemfile @@ -8,7 +8,7 @@ gem 'locale', '~> 2.1', '>= 2.1.2' gem 'rotp', '~> 3.1', '>= 3.1.0' group :development do - gem 'rubocop' + gem 'rubocop', '0.48.1' gem 'test-unit' gem 'yard' end From d185509113bc11503d7fcdb788f597df7b81efe5 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Sun, 30 Jul 2017 22:30:15 +0200 Subject: [PATCH 506/531] fix bug in otp generator --- CHANGELOG.md | 4 ++++ README.md | 2 +- VERSION | 2 +- lib/mpw/mpw.rb | 2 +- 4 files changed, 7 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2430516..9367be4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,8 @@ # CHANGELOG +## v4.2.1 (2017-07-30) + + * fix bug in otp generator + ## v4.2.0 (2017-06-06) * feat: improve the interface diff --git a/README.md b/README.md index 8a39d81..e6a119f 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # MPW: Manage your passwords! -[](https://github.com/nishiki/manage-password/releases) +[](https://github.com/nishiki/manage-password/releases) [](https://travis-ci.org/nishiki/manage-password) [](https://github.com/nishiki/manage-password/blob/master/LICENSE) diff --git a/VERSION b/VERSION index 6aba2b2..fae6e3d 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -4.2.0 +4.2.1 diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index 5905492..81a0231 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -272,7 +272,7 @@ module MPW # @param id [String] the item id # @return [String] an otp code def get_otp_code(id) - @otp_keys.key?(id) ? 0 : ROTP::TOTP.new(decrypt(@otp_keys[id])).now + @otp_keys.key?(id) ? ROTP::TOTP.new(decrypt(@otp_keys[id])).now : 0 end # Get remaining time before expire otp code From 948db2e905e8801dfd8b7acf4545317865f3c5d9 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Thu, 10 Aug 2017 22:45:03 +0200 Subject: [PATCH 507/531] feat: minor improve clipboard interface --- lib/mpw/cli.rb | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index d92e4e4..33d4151 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -291,6 +291,17 @@ module MPW choice >= 1 && choice <= items.length ? items[choice - 1] : nil end + # Print help message for clipboard mode + # @param item [Item] + def clipboard_help(item) + puts "----- #{I18n.t('form.clipboard.help.name')} -----".cyan + puts I18n.t('form.clipboard.help.url') + puts I18n.t('form.clipboard.help.login') + puts I18n.t('form.clipboard.help.password') + puts I18n.t('form.clipboard.help.otp_code') if item.otp + puts I18n.t('form.clipboard.help.quit') + end + # Copy in clipboard the login and password # @param item [Item] # @param clipboard [Boolean] enable clipboard @@ -339,7 +350,10 @@ module MPW end when 'o', 'otp' - if clipboard + if !item.otp + clipboard_help(item) + next + elsif clipboard Clipboard.copy(@mpw.get_otp_code(item.id)) else puts @mpw.get_otp_code(item.id) @@ -347,13 +361,7 @@ module MPW puts I18n.t('form.clipboard.otp', time: @mpw.get_otp_remaining_time).yellow else - puts "----- #{I18n.t('form.clipboard.help.name')} -----".cyan - puts I18n.t('form.clipboard.help.url') - puts I18n.t('form.clipboard.help.login') - puts I18n.t('form.clipboard.help.password') - puts I18n.t('form.clipboard.help.otp_code') - puts I18n.t('form.clipboard.help.quit') - next + clipboard_help(item) end end From 65db261c00224f8d35f883e703d7a736d79d9f83 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Thu, 10 Aug 2017 23:23:06 +0200 Subject: [PATCH 508/531] feat: minor improve get_item interface --- i18n/en.yml | 4 +++- i18n/fr.yml | 4 +++- lib/mpw/cli.rb | 6 ++++-- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/i18n/en.yml b/i18n/en.yml index b50fd63..962b6ef 100644 --- a/i18n/en.yml +++ b/i18n/en.yml @@ -91,7 +91,9 @@ en: wallet_dir: "Set the wallets folder" form: - select: "Select the item: " + select: + choice: "Select the item: " + error: "No item selected" add_key: valid: "Key has been added!" add_item: diff --git a/i18n/fr.yml b/i18n/fr.yml index d529ee4..e117c1f 100644 --- a/i18n/fr.yml +++ b/i18n/fr.yml @@ -91,7 +91,9 @@ fr: wallet_dir: "Spécifie le répertoire des portefeuilles" form: - select: "Sélectionner l'élément: " + select: + choice: "Sélectionner l'élément: " + error: "Aucun élément sélectionné" add_key: valid: "La clé a bien été ajoutée!" add_item: diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index 33d4151..02d6eb9 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -286,9 +286,11 @@ module MPW return items[0] if items.length == 1 items.sort! { |a, b| a.group.to_s.downcase <=> b.group.to_s.downcase } - choice = ask(I18n.t('form.select')).to_i + choice = ask(I18n.t('form.select.choice')).to_i - choice >= 1 && choice <= items.length ? items[choice - 1] : nil + raise I18n.t('form.select.error') unless choice >= 1 && choice <= items.length + + items[choice - 1] end # Print help message for clipboard mode From 0195771c76a15b83b407c3ca420cd7b0a02530a9 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Thu, 10 Aug 2017 23:41:20 +0200 Subject: [PATCH 509/531] feat: minor improvement add_form interface --- templates/add_form.erb | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/templates/add_form.erb b/templates/add_form.erb index d88874e..89b750e 100644 --- a/templates/add_form.erb +++ b/templates/add_form.erb @@ -1,9 +1,17 @@ --- -host: <%= options[:host] %> # <%= I18n.t('form.add_item.host') %> -user: <%= options[:user] %> # <%= I18n.t('form.add_item.login') %> -group: <%= options[:group] %> # <%= I18n.t('form.add_item.group') %> -protocol: <%= options[:protocol] %> # <%= I18n.t('form.add_item.protocol') %><% unless password %> -password: # <%= I18n.t('form.add_item.password') %><% end %> -port: <%= options[:port] %> # <%= I18n.t('form.add_item.port') %> -comment: <%= options[:comment] %> # <%= I18n.t('form.add_item.comment') %> -otp_key: <%= options[:otp] %> # <%= I18n.t('form.add_item.otp_key') %> +# <%= I18n.t('form.add_item.host') %> +host: <%= options[:host] %> +# <%= I18n.t('form.add_item.login') %> +user: <%= options[:user] %> +# <%= I18n.t('form.add_item.group') %> +group: <%= options[:group] %> +# <%= I18n.t('form.add_item.protocol') %> +protocol: <%= options[:protocol] %><% unless password %> +# <%= I18n.t('form.add_item.password') %> +password:<% end %> +# <%= I18n.t('form.add_item.port') %> +port: <%= options[:port] %> +# <%= I18n.t('form.add_item.comment') %> +comment: <%= options[:comment] %> +# <%= I18n.t('form.add_item.otp_key') %> +otp_key: <%= options[:otp] %> From 8aeb7f5224ad165d657b4fe879c180a65021c0b6 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Sat, 12 Aug 2017 01:19:52 +0200 Subject: [PATCH 510/531] feat: alway use absolute path for wallet path --- lib/mpw/config.rb | 1 + test/test_cli.rb | 7 +++---- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/mpw/config.rb b/lib/mpw/config.rb index 016c690..95390a4 100644 --- a/lib/mpw/config.rb +++ b/lib/mpw/config.rb @@ -161,6 +161,7 @@ module MPW # @param wallet [String] wallet name def set_wallet_path(path, wallet) path = @wallet_dir if path == 'default' + path = File.absolute_path(path) return if path == @wallet_dir && File.exist?("#{@wallet_dir}/#{wallet}.mpw") return if path == @wallet_paths[wallet] diff --git a/test/test_cli.rb b/test/test_cli.rb index 8fb91ee..8f5d546 100644 --- a/test/test_cli.rb +++ b/test/test_cli.rb @@ -142,7 +142,6 @@ class TestConfig < Test::Unit::TestCase end def test_07_setup_wallet - path = '/tmp/' gpg_key = 'test2@example.com' output = %x(echo #{@password} | mpw wallet --add-gpg-key #{gpg_key}) @@ -167,14 +166,14 @@ class TestConfig < Test::Unit::TestCase puts output assert_match('| default', output) - output = %x(mpw wallet --path #{path}) + output = %x(mpw wallet --path '.') puts output assert_match(I18n.t('form.set_wallet_path.valid'), output) output = %x(mpw config) puts output - assert_match(%r{path_wallet_default.+\| #{path}/default.mpw}, output) - assert(File.exist?("#{path}/default.mpw")) + assert_match(%r{path_wallet_default.+\| #{Dir.pwd}/default.mpw}, output) + assert(File.exist?("#{Dir.pwd}/default.mpw")) output = %x(mpw wallet --default-path) puts output From b2a38ccd4eeeef088fe0d6bd690b778bd1e2b589 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Tue, 15 Aug 2017 21:13:34 +0200 Subject: [PATCH 511/531] update version to 4.2.2 --- CHANGELOG.md | 4 ++++ README.md | 2 +- VERSION | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9367be4..199b863 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,8 @@ # CHANGELOG +## v4.2.2 (2017-08-15) + + * minor improvements in the interface + ## v4.2.1 (2017-07-30) * fix bug in otp generator diff --git a/README.md b/README.md index e6a119f..9c2c5d6 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # MPW: Manage your passwords! -[](https://github.com/nishiki/manage-password/releases) +[](https://github.com/nishiki/manage-password/releases) [](https://travis-ci.org/nishiki/manage-password) [](https://github.com/nishiki/manage-password/blob/master/LICENSE) diff --git a/VERSION b/VERSION index fae6e3d..af8c8ec 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -4.2.1 +4.2.2 From e2b455798128c0bb58c5ff423491660cbaaf54cc Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Sun, 3 Sep 2017 02:37:17 +0200 Subject: [PATCH 512/531] feat: add import gorilla file --- bin/mpw-import | 14 ++++++++-- i18n/en.yml | 4 ++- i18n/fr.yml | 4 ++- lib/mpw/cli.rb | 25 +++++++++++------ lib/mpw/import/gorilla.rb | 57 +++++++++++++++++++++++++++++++++++++++ lib/mpw/import/mpw.rb | 29 ++++++++++++++++++++ lib/mpw/item.rb | 12 ++++----- 7 files changed, 126 insertions(+), 19 deletions(-) create mode 100644 lib/mpw/import/gorilla.rb create mode 100644 lib/mpw/import/mpw.rb diff --git a/bin/mpw-import b/bin/mpw-import index 0502b2b..76e163e 100644 --- a/bin/mpw-import +++ b/bin/mpw-import @@ -24,7 +24,13 @@ require 'mpw/cli' # Options # --------------------------------------------------------- # -options = {} +formats = + Dir["#{File.expand_path('../../lib/mpw/import', __FILE__)}/*.rb"] + .map { |v| File.basename(v, '.rb') } + .join(', ') +options = { + format: 'mpw' +} OptionParser.new do |opts| opts.banner = "#{I18n.t('option.usage')}: mpw import [options]" @@ -37,6 +43,10 @@ OptionParser.new do |opts| options[:file] = file end + opts.on('-F', '--format STRING', I18n.t('option.file_format', formats: formats)) do |format| + options[:format] = format + end + opts.on('-h', '--help', I18n.t('option.help')) do puts opts exit 0 @@ -53,4 +63,4 @@ cli = MPW::Cli.new(config) cli.load_config cli.get_wallet(options[:wallet]) cli.decrypt -cli.import(options[:file]) +cli.import(options[:file], options[:format]) diff --git a/i18n/en.yml b/i18n/en.yml index 962b6ef..2375084 100644 --- a/i18n/en.yml +++ b/i18n/en.yml @@ -22,7 +22,7 @@ en: write_data: "Can't write the MPW file!" import: "Can't import, unable to read %{file}!" update: - host_empty: "You must define a host!" + host_and_comment_empty: "You must define a host or a comment!" warning: select: 'Your choice is not a valid item!' @@ -55,6 +55,7 @@ en: disable_special_chars: "Don't use special char to create a password" export: "Export a wallet in an yaml file" file_export: "Specify the file to export data" + file_format: "Format of import file (default: mpw; available: %{formats})" file_import: "Specify the file to import" force: "Do not ask confirmation when deleting an item" generate_password: "Create a random password (default 8 characters)" @@ -130,6 +131,7 @@ en: ask: "Are you sure you want to import this file %{file} ?" file_empty: "The import file is empty!" file_not_exist: "The import file doesn't exist!" + format_unknown: "The import format '%{file_format} is unknown!" valid: "The import is successful!" not_valid: "No data to import!" set_config: diff --git a/i18n/fr.yml b/i18n/fr.yml index e117c1f..9ab2e58 100644 --- a/i18n/fr.yml +++ b/i18n/fr.yml @@ -22,7 +22,7 @@ fr: write_data: "Impossible d'écrire le fichier MPW!" import: "Impossible d'importer le fichier %{file}, car il n'est pas lisible!" update: - host_empty: "Vous devez définir un host!" + host_and_comment_empty: "Vous devez définir un host ou un commentaire!" warning: select: "Votre choix n'est pas un élément valide!" @@ -55,6 +55,7 @@ fr: disable_special_chars: "Désactive l'utilisation des charactères speciaux dans la génération d'un mot de passe" export: "Exporte un portefeuille dans un fichier yaml" file_export: "Spécifie le fichier où exporter les données" + file_format: "Format du fichier d'import (défault: mpw; disponible: %{formats})" file_import: "Spécifie le fichier à importer" force: "Ne demande pas de confirmation pour la suppression d'un élément" generate_password: "Génére un mot de passe aléatoire (défaut 8 caractères)" @@ -130,6 +131,7 @@ fr: ask: "Êtes vous sûre de vouloir importer le fichier %{file} ?" file_empty: "Le fichier d'import est vide!" file_not_exist: "Le fichier d'import n'existe pas" + format_unknown: "Le format d'import '%{file_format}' est inconnu!" valid: "L'import est un succès!" not_valid: "Aucune donnée à importer!" set_config: diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index 02d6eb9..17701b6 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -586,17 +586,26 @@ module MPW # Import items from an yaml file # @param file [String] path of import file - def import(file) + # @param format [String] the software import file format + def import(file, format = 'mpw') raise I18n.t('form.import.file_empty') if file.to_s.empty? raise I18n.t('form.import.file_not_exist') unless File.exist?(file) - YAML.load_file(file).each_value do |row| - item = Item.new(group: row['group'], - host: row['host'], - protocol: row['protocol'], - user: row['user'], - port: row['port'], - comment: row['comment']) + begin + require "mpw/import/#{format}" + rescue LoadError + raise I18n.t('form.import.format_unknown', file_format: format) + end + + Import.send(format, file).each_value do |row| + item = Item.new( + group: row['group'], + host: row['host'], + protocol: row['protocol'], + user: row['user'], + port: row['port'], + comment: row['comment'] + ) next if item.empty? diff --git a/lib/mpw/import/gorilla.rb b/lib/mpw/import/gorilla.rb new file mode 100644 index 0000000..0ab5dc3 --- /dev/null +++ b/lib/mpw/import/gorilla.rb @@ -0,0 +1,57 @@ +#!/usr/bin/ruby +# MPW is a software to crypt and manage your passwords +# Copyright (C) 2017 Adrien Waksberg <mpw@yae.im> +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +require 'csv' + +module MPW + module Import + # Import an export mpw file + # @param file [String] the file path to import + def self.gorilla(file) + data = {} + + CSV.foreach(file, headers: true) do |row| + id = row['uuid'] + comment = + if row['title'] && row['notes'] + "#{row['title']} #{row['notes']}" + elsif row['title'] + row['title'] + elsif row['notes'] + row['notes'] + end + + data[id] = { + 'group' => row['group'], + 'host' => row['url'], + 'user' => row['user'], + 'password' => row['password'], + 'comment' => comment + } + + if row['url'] =~ %r{^((?<protocol>[a-z]+)://)?(?<host>[a-zA-Z0-9_.-]+)(:(?<port>[0-9]{1,5}))?$} + data[id]['protocol'] = Regexp.last_match(:protocol) + data[id]['port'] = Regexp.last_match(:port) + data[id]['host'] = Regexp.last_match(:host) + end + end + + data + end + end +end diff --git a/lib/mpw/import/mpw.rb b/lib/mpw/import/mpw.rb new file mode 100644 index 0000000..8d6b1c4 --- /dev/null +++ b/lib/mpw/import/mpw.rb @@ -0,0 +1,29 @@ +#!/usr/bin/ruby +# MPW is a software to crypt and manage your passwords +# Copyright (C) 2017 Adrien Waksberg <mpw@yae.im> +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +require 'yaml' + +module MPW + module Import + # Import an export mpw file + # @param file [String] the file path to import + def self.mpw(file) + YAML.load_file(file) + end + end +end diff --git a/lib/mpw/item.rb b/lib/mpw/item.rb index be03dba..4e17912 100644 --- a/lib/mpw/item.rb +++ b/lib/mpw/item.rb @@ -33,9 +33,7 @@ module MPW # @param options [Hash] the option :host is required def initialize(**options) - if !options.key?(:host) || options[:host].to_s.empty? - raise I18n.t('error.update.host_empty') - end + @host = '' if !options.key?(:id) || options[:id].to_s.empty? || !options.key?(:created) || options[:created].to_s.empty? @id = generate_id @@ -53,12 +51,12 @@ module MPW # Update the item # @param options [Hash] def update(**options) - if options.key?(:host) && options[:host].to_s.empty? - raise I18n.t('error.update.host_empty') + unless options[:host] || options[:comment] + raise I18n.t('error.update.host_and_comment_empty') end @group = options[:group] if options.key?(:group) - @host = options[:host] if options.key?(:host) + @host = options[:host] if options.key?(:host) && !options[:host].nil? @protocol = options[:protocol] if options.key?(:protocol) @user = options[:user] if options.key?(:user) @port = options[:port].to_i if options.key?(:port) && !options[:port].to_s.empty? @@ -86,7 +84,7 @@ module MPW def url url = '' url += "#{@protocol}://" if @protocol - url += @host + url += @host if @host url += ":#{@port}" if @port url From 2a647afb10c205a1d62b75b91b6ca9a53133cae5 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Sun, 3 Sep 2017 10:23:44 +0200 Subject: [PATCH 513/531] fix: force system on travis --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 525a9d0..57c6924 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,5 @@ language: ruby +dist: precise rvm: - 2.4.1 - 2.3.4 From 42629c61b35da7bf7eb22e78e1f56839bcf35ecf Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Sun, 3 Sep 2017 15:10:01 +0200 Subject: [PATCH 514/531] feat: add test for import --- .travis.yml | 1 + test/files/import-gorilla.txt | 4 +++ test/test_cli.rb | 12 +++++---- test/test_import.rb | 46 +++++++++++++++++++++++++++++++++++ 4 files changed, 58 insertions(+), 5 deletions(-) create mode 100644 test/files/import-gorilla.txt create mode 100644 test/test_import.rb diff --git a/.travis.yml b/.travis.yml index 57c6924..e289bcf 100644 --- a/.travis.yml +++ b/.travis.yml @@ -19,3 +19,4 @@ script: - ruby ./test/test_translate.rb - ruby ./test/init.rb - ruby ./test/test_cli.rb + - ruby ./test/test_import.rb diff --git a/test/files/import-gorilla.txt b/test/files/import-gorilla.txt new file mode 100644 index 0000000..a5fc604 --- /dev/null +++ b/test/files/import-gorilla.txt @@ -0,0 +1,4 @@ +uuid,group,title,url,user,password,notes +49627979-e393-48c4-49ca-1cf66603238e,Bank,Fric,http://fric.com,12345,secret,money money +49627979-e393-48c4-49ca-1cf66603238f,,My little server,server.com,secret2, +49627979-e393-48c4-49ca-1cf66603238g,Cloud,,ssh://fric.com:4333,username,secret,bastion diff --git a/test/test_cli.rb b/test/test_cli.rb index 8f5d546..f4cf356 100644 --- a/test/test_cli.rb +++ b/test/test_cli.rb @@ -185,15 +185,16 @@ class TestConfig < Test::Unit::TestCase end def test_08_setup_config - gpg_key = 'user@example2.com' + gpg_key = 'test2@example.com' gpg_exe = '/usr/bin/gpg2' - wallet_dir = '/tmp/mpw' + wallet_dir = '/tmp' length = 24 wallet = 'work' output = %x( mpw config \ --gpg-exe #{gpg_exe} \ + --key #{gpg_key} \ --enable-pinmode \ --disable-alpha \ --disable-special-chars \ @@ -207,7 +208,7 @@ class TestConfig < Test::Unit::TestCase output = %x(mpw config) puts output - assert_match(/gpg_key.+\| #{@gpg_key}/, output) + assert_match(/gpg_key.+\| #{gpg_key}/, output) assert_match(/gpg_exe.+\| #{gpg_exe}/, output) assert_match(/pinmode.+\| true/, output) assert_match(/default_wallet.+\| #{wallet}/, output) @@ -219,7 +220,8 @@ class TestConfig < Test::Unit::TestCase output = %x( mpw config \ - --key #{gpg_key} \ + --gpg-exe '' \ + --key #{@gpg_key} \ --alpha \ --special-chars \ --numeric \ @@ -230,7 +232,7 @@ class TestConfig < Test::Unit::TestCase output = %x(mpw config) puts output - assert_match(/gpg_key.+\| #{gpg_key}/, output) + assert_match(/gpg_key.+\| #{@gpg_key}/, output) assert_match(/pinmode.+\| false/, output) %w[numeric alpha special].each do |k| assert_match(/password_#{k}.+\| true/, output) diff --git a/test/test_import.rb b/test/test_import.rb new file mode 100644 index 0000000..c27b58f --- /dev/null +++ b/test/test_import.rb @@ -0,0 +1,46 @@ +#!/usr/bin/ruby + +require 'i18n' +require 'test/unit' + +class TestImport < Test::Unit::TestCase + def setup + if defined?(I18n.enforce_available_locales) + I18n.enforce_available_locales = true + end + + I18n::Backend::Simple.send(:include, I18n::Backend::Fallbacks) + I18n.load_path = ["#{File.expand_path('../../i18n', __FILE__)}/en.yml"] + I18n.locale = :en + + @password = 'password' + end + + def test_00_import + Dir['./test/files/import-*.txt'].each do |file| + format = File.basename(file, '.txt').partition('-').last + + puts format + + output = %x( + mpw import \ + --file #{file} \ + --format #{format} \ + --wallet #{format} + ) + assert_match(I18n.t('form.import.valid'), output) + + output = %x(echo #{@password} | mpw list --group Bank --wallet #{format}) + puts output + assert_match(%r{http://.*fric\.com.*12345.*Fric money money}, output) + + output = %x(echo #{@password} | mpw list --group Cloud --wallet #{format}) + puts output + assert_match(%r{ssh://.*fric\.com.*:4333.*username.*bastion}, output) + + output = %x(echo #{@password} | mpw list --wallet #{format}) + puts output + assert_match(/server\.com.*My little server/, output) + end + end +end From cf5b7e014213d592ceb9bf975b137a4c57f03810 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Sun, 17 Sep 2017 16:25:05 +0200 Subject: [PATCH 515/531] fix travis tests --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index e289bcf..7f524d4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,6 +6,8 @@ rvm: - 2.2.7 - 2.1.10 install: + - sudo cp -a /dev/urandom /dev/random + - sudo apt-get purge -y gnupg-agent gnupg2 - bundle install - echo 9999 > VERSION - gem build mpw.gemspec From 8b5c7ae581e391b3c81b079816adb993217d43ec Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Tue, 5 Sep 2017 22:16:37 +0200 Subject: [PATCH 516/531] feat: major change the url storage --- bin/mpw-add | 18 +++------- bin/mpw-update | 18 +++------- i18n/en.yml | 4 +-- i18n/fr.yml | 4 +-- lib/mpw/cli.rb | 22 +++++------- lib/mpw/import/gorilla.rb | 12 ++----- lib/mpw/item.rb | 63 ++++++++++++++++------------------ lib/mpw/mpw.rb | 8 ++--- templates/add_form.erb | 10 ++---- templates/update_form.erb | 8 ++--- test/files/fixtures-import.yml | 9 ++--- test/files/fixtures.yml | 3 ++ test/test_cli.rb | 14 ++++---- test/test_item.rb | 31 +++++++---------- test/test_mpw.rb | 8 ++--- 15 files changed, 87 insertions(+), 145 deletions(-) diff --git a/bin/mpw-add b/bin/mpw-add index 2c2e996..1d0581a 100644 --- a/bin/mpw-add +++ b/bin/mpw-add @@ -48,22 +48,10 @@ OptionParser.new do |opts| exit 0 end - opts.on('-H', '--host HOST', I18n.t('option.host')) do |host| - values[:host] = host - end - opts.on('-o', '--otp-code CODE', I18n.t('option.otp_code')) do |otp| values[:otp_key] = otp end - opts.on('-O', '--protocol PROTOCOL', I18n.t('option.protocol')) do |protocol| - values[:protocol] = protocol - end - - opts.on('-P', '--port NUMBER', I18n.t('option.port')) do |port| - values[:port] = port - end - opts.on('-r', '--random', I18n.t('option.random_password')) do options[:password] = true end @@ -72,7 +60,11 @@ OptionParser.new do |opts| options[:text_editor] = true end - opts.on('-u', '--user USER', I18n.t('option.user')) do |user| + opts.on('-u', '--url URL', I18n.t('option.url')) do |url| + values[:url] = url + end + + opts.on('-U', '--user USER', I18n.t('option.user')) do |user| values[:user] = user end diff --git a/bin/mpw-update b/bin/mpw-update index 143e187..d15b8e7 100644 --- a/bin/mpw-update +++ b/bin/mpw-update @@ -53,26 +53,14 @@ OptionParser.new do |opts| exit 0 end - opts.on('-H', '--host HOST', I18n.t('option.host')) do |host| - values[:host] = host - end - opts.on('-o', '--otp-code CODE', I18n.t('option.otp_code')) do |otp| values[:otp_key] = otp end - opts.on('-O', '--protocol PROTOCOL', I18n.t('option.protocol')) do |protocol| - values[:protocol] = protocol - end - opts.on('-p', '--pattern PATTERN', I18n.t('option.pattern')) do |pattern| search[:pattern] = pattern end - opts.on('-P', '--port NUMBER', I18n.t('option.port')) do |port| - values[:port] = port - end - opts.on('-r', '--random', I18n.t('option.random_password')) do options[:password] = true end @@ -81,7 +69,11 @@ OptionParser.new do |opts| options[:text_editor] = true end - opts.on('-u', '--user USER', I18n.t('option.user')) do |user| + opts.on('-u', '--url URL', I18n.t('option.url')) do |url| + values[:url] = url + end + + opts.on('-U', '--user USER', I18n.t('option.user')) do |user| values[:user] = user end diff --git a/i18n/en.yml b/i18n/en.yml index 2375084..9df7bda 100644 --- a/i18n/en.yml +++ b/i18n/en.yml @@ -63,7 +63,6 @@ en: gpg_key: "Specify a GPG key (ex: user@example.com)" group: "Search the items with specified group" help: "Show this help message" - host: "Specify a host or ip" init: "Initialize mpw" import: "Import item from an yaml file" key: "Define the key name" @@ -77,8 +76,6 @@ en: path: "Move the wallet in new specify directory" pattern: "Given search pattern" pinmode: "Enable pinentry mode (available with gpg >= 2.1)" - port: "Set a port of connexion" - protocol: "Set a protocol of connexion" random_password: "Generate a random password" setup: "Create a new configuration file" setup_wallet: "Create a new configuration file for a wallet" @@ -87,6 +84,7 @@ en: show_all: "Listing all items" text_editor: "Use text editor to edit the item" usage: "Use" + url: "Set an url (ex: https://example.com/path)" user: "Set an user" wallet: "Specify a wallet to use" wallet_dir: "Set the wallets folder" diff --git a/i18n/fr.yml b/i18n/fr.yml index 9ab2e58..04583ad 100644 --- a/i18n/fr.yml +++ b/i18n/fr.yml @@ -63,7 +63,6 @@ fr: gpg_key: "Spécifie une clé GPG (ex: user@example.com)" group: "Recherche les éléments appartenant au groupe spécifié" help: "Affiche ce message d'aide" - host: "Spécifie le nom du serveur ou l'ip" import: "Importe des éléments depuis un fichier yaml" init: "Initialise mpw" key: "Spécifie le nom d'une clé" @@ -77,8 +76,6 @@ fr: path: "Déplace le portefeuille dans un nouveau dossier" pattern: "Motif de donnée à chercher" pinmode: "Active le mode pinentry (valable avec gpg >= 2.1)" - port: "Spécifie un port de connexion" - protocol: "Spécifie un protocol de connexion" random_password: "Génére un mot de passe aléatoire" setup: "Création d'un nouveau fichier de configuration" setup_wallet: "Création d'un nouveau fichier de configuration pour un portefeuille" @@ -87,6 +84,7 @@ fr: show_all: "Liste tous les éléments" text_editor: "Active l'édition avec un éditeur de texte" usage: "Utilisation" + url: "Spécifie l'url (ex: http://example.com/path)" user: "Spécifie un utilisateur" wallet: "Spécifie le portefeuille à utiliser" wallet_dir: "Spécifie le répertoire des portefeuilles" diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index 17701b6..d54b314 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -563,16 +563,14 @@ module MPW items.each do |item| data.merge!( item.id => { - 'host' => item.host, - 'user' => item.user, - 'group' => item.group, - 'password' => @mpw.get_password(item.id), - 'protocol' => item.protocol, - 'port' => item.port, - 'otp_key' => @mpw.get_otp_key(item.id), 'comment' => item.comment, - 'last_edit' => item.last_edit, 'created' => item.created, + 'group' => item.group, + 'last_edit' => item.last_edit, + 'otp_key' => @mpw.get_otp_key(item.id), + 'password' => @mpw.get_password(item.id), + 'url' => item.url, + 'user' => item.user } ) end @@ -599,12 +597,10 @@ module MPW Import.send(format, file).each_value do |row| item = Item.new( + comment: row['comment'], group: row['group'], - host: row['host'], - protocol: row['protocol'], - user: row['user'], - port: row['port'], - comment: row['comment'] + url: row['url'], + user: row['user'] ) next if item.empty? diff --git a/lib/mpw/import/gorilla.rb b/lib/mpw/import/gorilla.rb index 0ab5dc3..fd5d9f1 100644 --- a/lib/mpw/import/gorilla.rb +++ b/lib/mpw/import/gorilla.rb @@ -37,18 +37,12 @@ module MPW end data[id] = { + 'comment' => comment, 'group' => row['group'], - 'host' => row['url'], - 'user' => row['user'], 'password' => row['password'], - 'comment' => comment + 'url' => row['url'], + 'user' => row['user'] } - - if row['url'] =~ %r{^((?<protocol>[a-z]+)://)?(?<host>[a-zA-Z0-9_.-]+)(:(?<port>[0-9]{1,5}))?$} - data[id]['protocol'] = Regexp.last_match(:protocol) - data[id]['port'] = Regexp.last_match(:port) - data[id]['host'] = Regexp.last_match(:host) - end end data diff --git a/lib/mpw/item.rb b/lib/mpw/item.rb index 4e17912..ec8ab0e 100644 --- a/lib/mpw/item.rb +++ b/lib/mpw/item.rb @@ -17,25 +17,27 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. require 'i18n' +require 'uri' module MPW class Item - attr_accessor :id + attr_accessor :created + attr_accessor :comment attr_accessor :group attr_accessor :host - attr_accessor :protocol - attr_accessor :user - attr_accessor :port + attr_accessor :id attr_accessor :otp - attr_accessor :comment + attr_accessor :port + attr_accessor :protocol attr_accessor :last_edit - attr_accessor :created + attr_accessor :url + attr_accessor :user # @param options [Hash] the option :host is required def initialize(**options) @host = '' - if !options.key?(:id) || options[:id].to_s.empty? || !options.key?(:created) || options[:created].to_s.empty? + if !options[:id] || !options[:created] @id = generate_id @created = Time.now.to_i else @@ -51,43 +53,38 @@ module MPW # Update the item # @param options [Hash] def update(**options) - unless options[:host] || options[:comment] + unless options[:url] || options[:comment] raise I18n.t('error.update.host_and_comment_empty') end - @group = options[:group] if options.key?(:group) - @host = options[:host] if options.key?(:host) && !options[:host].nil? - @protocol = options[:protocol] if options.key?(:protocol) - @user = options[:user] if options.key?(:user) - @port = options[:port].to_i if options.key?(:port) && !options[:port].to_s.empty? - @otp = options[:otp] if options.key?(:otp) - @comment = options[:comment] if options.key?(:comment) - @last_edit = Time.now.to_i unless options.key?(:no_update_last_edit) + if options[:url] + uri = URI(options[:url]) + @host = uri.host || options[:url] + @port = uri.port || nil + @protocol = uri.scheme || nil + @url = options[:url] + end + + @comment = options[:comment] if options.key?(:comment) + @group = options[:group] if options.key?(:group) + @last_edit = Time.now.to_i unless options.key?(:no_update_last_edit) + @otp = options[:otp] if options.key?(:otp) + @user = options[:user] if options.key?(:user) end # Delete all data def delete @id = nil - @group = nil - @host = nil - @protocol = nil - @user = nil - @port = nil - @otp = nil @comment = nil @created = nil + @group = nil + @host = nil @last_edit = nil - end - - # Return data on url format - # @return [String] an url - def url - url = '' - url += "#{@protocol}://" if @protocol - url += @host if @host - url += ":#{@port}" if @port - - url + @otp = nil + @port = nil + @protocol = nil + @url = nil + @user = nil end def empty? diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index 81a0231..a5fc0ae 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -84,10 +84,8 @@ module MPW Item.new( id: d['id'], group: d['group'], - host: d['host'], - protocol: d['protocol'], user: d['user'], - port: d['port'], + url: d['url'], otp: @otp_keys.key?(d['id']), comment: d['comment'], last_edit: d['last_edit'], @@ -114,10 +112,8 @@ module MPW item.id => { 'id' => item.id, 'group' => item.group, - 'host' => item.host, - 'protocol' => item.protocol, 'user' => item.user, - 'port' => item.port, + 'url' => item.url, 'comment' => item.comment, 'last_edit' => item.last_edit, 'created' => item.created, diff --git a/templates/add_form.erb b/templates/add_form.erb index 89b750e..e2aea20 100644 --- a/templates/add_form.erb +++ b/templates/add_form.erb @@ -1,16 +1,12 @@ --- -# <%= I18n.t('form.add_item.host') %> -host: <%= options[:host] %> +# <%= I18n.t('form.add_item.url') %> +url: <%= options[:url] %> # <%= I18n.t('form.add_item.login') %> user: <%= options[:user] %> # <%= I18n.t('form.add_item.group') %> -group: <%= options[:group] %> -# <%= I18n.t('form.add_item.protocol') %> -protocol: <%= options[:protocol] %><% unless password %> +group: <%= options[:group] %><% unless password %> # <%= I18n.t('form.add_item.password') %> password:<% end %> -# <%= I18n.t('form.add_item.port') %> -port: <%= options[:port] %> # <%= I18n.t('form.add_item.comment') %> comment: <%= options[:comment] %> # <%= I18n.t('form.add_item.otp_key') %> diff --git a/templates/update_form.erb b/templates/update_form.erb index 5037568..eafeb1b 100644 --- a/templates/update_form.erb +++ b/templates/update_form.erb @@ -1,16 +1,12 @@ --- -# <%= I18n.t('form.update_item.host') %> -host: <% if options[:host] %><%= options[:host] %><% else %><%= item.host %><% end %> +# <%= I18n.t('form.update_item.url') %> +host: <% if options[:url] %><%= options[:url] %><% else %><%= item.url %><% end %> # <%= I18n.t('form.update_item.login') %> user: <% if options[:user] %><%= options[:user] %><% else %><%= item.user %><% end %><% unless password %> # <%= I18n.t('form.update_item.password') %> password: <% end %> # <%= I18n.t('form.update_item.group') %> group: <% if options[:group] %><%= options[:group] %><% else %><%= item.group %><% end %> -# <%= I18n.t('form.update_item.protocol') %> -protocol: <% if options[:protocol] %><%= options[:protocol] %><% else %><%= item.protocol %><% end %> -# <%= I18n.t('form.update_item.port') %> -port: <% if options[:port] %><%= options[:port] %><% else %><%= item.port %><% end %> # <%= I18n.t('form.update_item.otp_key') %> otp_key: <% if options[:otp_key] %><%= options[:otp_key] %><% end %> # <%= I18n.t('form.update_item.comment') %> diff --git a/test/files/fixtures-import.yml b/test/files/fixtures-import.yml index f79ab0a..8cb1ff4 100644 --- a/test/files/fixtures-import.yml +++ b/test/files/fixtures-import.yml @@ -1,19 +1,16 @@ --- 1: - host: fric.com + url: https://fric.com user: 230403 group: Bank password: 5XdiTQOubRDw9B0aJoMlcEyL - protocol: https - port: otp_key: 330223432 comment: I love my bank 2: - host: assurance.com + url: https://assurance.com:443 user: user_2132 + host: assurance.com group: Assurance password: DMyK6B3v4bWO52VzU7aTHIem - protocol: https - port: 443 otp_key: comment: diff --git a/test/files/fixtures.yml b/test/files/fixtures.yml index 765314e..d8927cb 100644 --- a/test/files/fixtures.yml +++ b/test/files/fixtures.yml @@ -1,4 +1,5 @@ add: + url: 'https://example.com:8080' group: 'Bank' host: 'example.com' protocol: 'https' @@ -9,6 +10,7 @@ add: import: id: 'TEST-ID-XXXXX' + url: 'https://gogole.com:8081/toto' group: 'Cloud' host: 'gogole.com' protocol: 'https' @@ -19,6 +21,7 @@ import: created: 1386752948 update: + url: 'ssh://example2.com:2222' group: 'Assurance' host: 'example2.com' protocol: 'ssh' diff --git a/test/test_cli.rb b/test/test_cli.rb index f4cf356..07c4273 100644 --- a/test/test_cli.rb +++ b/test/test_cli.rb @@ -29,9 +29,7 @@ class TestConfig < Test::Unit::TestCase output = %x( echo #{@password} | mpw add \ - --host #{data['host']} \ - --port #{data['port']} \ - --protocol #{data['protocol']} \ + --url #{data['url']} \ --user #{data['user']} \ --comment '#{data['comment']}' \ --group #{data['group']} \ @@ -73,9 +71,7 @@ class TestConfig < Test::Unit::TestCase output = %x( echo #{@password} | mpw update \ -p #{@fixtures['add']['host']} \ - --host #{data['host']} \ - --port #{data['port']} \ - --protocol #{data['protocol']} \ + --url #{data['url']} \ --user #{data['user']} \ --comment '#{data['comment']}' \ --new-group #{data['group']} @@ -117,20 +113,22 @@ class TestConfig < Test::Unit::TestCase error = true YAML.load_file(file_export).each_value do |export| - next if import['host'] != export['host'] + next if import['url'] != export['url'] %w[user group password protocol port otp_key comment].each do |key| assert_equal(import[key].to_s, export[key].to_s) end error = false + break end + assert(!error) end end def test_06_copy - data = YAML.load_file('./test/files/fixtures-import.yml')[1] + data = YAML.load_file('./test/files/fixtures-import.yml')[2] output = %x( echo "#{@password}\np\nq" | mpw copy \ diff --git a/test/test_item.rb b/test/test_item.rb index c83cbc3..80e39ff 100644 --- a/test/test_item.rb +++ b/test/test_item.rb @@ -23,10 +23,8 @@ class TestItem < Test::Unit::TestCase def test_01_add data = { group: @fixtures['add']['group'], - host: @fixtures['add']['host'], - protocol: @fixtures['add']['protocol'], user: @fixtures['add']['user'], - port: @fixtures['add']['port'], + url: @fixtures['add']['url'], comment: @fixtures['add']['comment'] } @@ -35,6 +33,7 @@ class TestItem < Test::Unit::TestCase assert(!item.nil?) assert(!item.empty?) + assert_equal(@fixtures['add']['url'], item.url) assert_equal(@fixtures['add']['group'], item.group) assert_equal(@fixtures['add']['host'], item.host) assert_equal(@fixtures['add']['protocol'], item.protocol) @@ -47,10 +46,8 @@ class TestItem < Test::Unit::TestCase data = { id: @fixtures['import']['id'], group: @fixtures['import']['group'], - host: @fixtures['import']['host'], - protocol: @fixtures['import']['protocol'], user: @fixtures['import']['user'], - port: @fixtures['import']['port'], + url: @fixtures['import']['url'], comment: @fixtures['import']['comment'], created: @fixtures['import']['created'] } @@ -61,6 +58,7 @@ class TestItem < Test::Unit::TestCase assert(!item.empty?) assert_equal(@fixtures['import']['id'], item.id) + assert_equal(@fixtures['import']['url'], item.url) assert_equal(@fixtures['import']['group'], item.group) assert_equal(@fixtures['import']['host'], item.host) assert_equal(@fixtures['import']['protocol'], item.protocol) @@ -73,10 +71,8 @@ class TestItem < Test::Unit::TestCase def test_03_update data = { group: @fixtures['add']['group'], - host: @fixtures['add']['host'], - protocol: @fixtures['add']['protocol'], user: @fixtures['add']['user'], - port: @fixtures['add']['port'], + url: @fixtures['add']['url'], comment: @fixtures['add']['comment'] } @@ -90,10 +86,8 @@ class TestItem < Test::Unit::TestCase data = { group: @fixtures['update']['group'], - host: @fixtures['update']['host'], - protocol: @fixtures['update']['protocol'], user: @fixtures['update']['user'], - port: @fixtures['update']['port'], + url: @fixtures['update']['url'], comment: @fixtures['update']['comment'] } @@ -102,6 +96,7 @@ class TestItem < Test::Unit::TestCase assert(!item.empty?) + assert_equal(@fixtures['update']['url'], item.url) assert_equal(@fixtures['update']['group'], item.group) assert_equal(@fixtures['update']['host'], item.host) assert_equal(@fixtures['update']['protocol'], item.protocol) @@ -116,10 +111,8 @@ class TestItem < Test::Unit::TestCase def test_05_update_one_element data = { group: @fixtures['add']['group'], - host: @fixtures['add']['host'], - protocol: @fixtures['add']['protocol'], user: @fixtures['add']['user'], - port: @fixtures['add']['port'], + url: @fixtures['add']['url'], comment: @fixtures['add']['comment'] } @@ -131,8 +124,9 @@ class TestItem < Test::Unit::TestCase last_edit = item.last_edit sleep(1) - assert(item.update(comment: @fixtures['update']['comment'])) + item.update(comment: @fixtures['update']['comment']) + assert_equal(@fixtures['add']['url'], item.url) assert_equal(@fixtures['add']['group'], item.group) assert_equal(@fixtures['add']['host'], item.host) assert_equal(@fixtures['add']['protocol'], item.protocol) @@ -146,10 +140,8 @@ class TestItem < Test::Unit::TestCase def test_05_delete data = { group: @fixtures['add']['group'], - host: @fixtures['add']['host'], - protocol: @fixtures['add']['protocol'], user: @fixtures['add']['user'], - port: @fixtures['add']['port'], + url: @fixtures['add']['url'], comment: @fixtures['add']['comment'] } @@ -163,6 +155,7 @@ class TestItem < Test::Unit::TestCase assert(item.empty?) assert_equal(nil, item.id) + assert_equal(nil, item.url) assert_equal(nil, item.group) assert_equal(nil, item.host) assert_equal(nil, item.protocol) diff --git a/test/test_mpw.rb b/test/test_mpw.rb index a783225..a1633ef 100644 --- a/test/test_mpw.rb +++ b/test/test_mpw.rb @@ -33,10 +33,8 @@ class TestMPW < Test::Unit::TestCase def test_02_add_item data = { group: @fixtures['add']['group'], - host: @fixtures['add']['host'], - protocol: @fixtures['add']['protocol'], user: @fixtures['add']['user'], - port: @fixtures['add']['port'], + url: @fixtures['add']['url'], comment: @fixtures['add']['comment'] } @@ -93,10 +91,8 @@ class TestMPW < Test::Unit::TestCase @fixtures.each_value do |v| data = { group: v['group'], - host: v['host'], - protocol: v['protocol'], user: v['user'], - port: v['port'], + url: v['url'], comment: v['comment'] } From dd02776baa297adca47dc344984723ab842ee1dd Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Sun, 17 Sep 2017 22:47:59 +0200 Subject: [PATCH 517/531] feat: add import old version of mpw --- lib/mpw/import/mpw_old.rb | 46 +++++++++++++++++++++++++++++++++++ test/files/import-mpw_old.txt | 35 ++++++++++++++++++++++++++ 2 files changed, 81 insertions(+) create mode 100644 lib/mpw/import/mpw_old.rb create mode 100644 test/files/import-mpw_old.txt diff --git a/lib/mpw/import/mpw_old.rb b/lib/mpw/import/mpw_old.rb new file mode 100644 index 0000000..f6957fe --- /dev/null +++ b/lib/mpw/import/mpw_old.rb @@ -0,0 +1,46 @@ +#!/usr/bin/ruby +# MPW is a software to crypt and manage your passwords +# Copyright (C) 2017 Adrien Waksberg <mpw@yae.im> +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +require 'yaml' + +module MPW + module Import + # Import an export mpw file + # @param file [String] the file path to import + def self.mpw_old(file) + data = {} + YAML.load_file(file).each do |id, item| + url = '' + url += "#{item['protocol']}://" if item['protocol'] + url += item['host'] + url += ":#{item['port']}" if item['port'] + + data[id] = { + 'comment' => item['comment'], + 'group' => item['group'], + 'otp' => item['otp'], + 'password' => item['password'], + 'url' => url, + 'user' => item['user'] + } + end + + data + end + end +end diff --git a/test/files/import-mpw_old.txt b/test/files/import-mpw_old.txt new file mode 100644 index 0000000..fd162aa --- /dev/null +++ b/test/files/import-mpw_old.txt @@ -0,0 +1,35 @@ +--- +1: + host: fric.com + user: 12345 + group: Bank + password: secret + protocol: http + port: + otp_key: + comment: Fric money money + last_edit: 1487623641 + created: 1485729356 +2: + host: server.com + user: sercret2 + group: + password: + protocol: + port: 4222 + otp_key: + comment: My little server + last_edit: 1487623641 + created: 1485729356 +3: + host: fric.com + user: username + group: Cloud + password: + protocol: ssh + port: 4333 + otp_key: + comment: bastion + last_edit: 1487623641 + created: 1485729356 + From ce02022ac758b8a4bf20a7a3e28827715df82c5d Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Sun, 24 Sep 2017 12:38:14 +0200 Subject: [PATCH 518/531] feat: update rubocop to 0.50.0 --- .rubocop.yml | 109 +++++--------------------------------- Gemfile | 2 +- bin/mpw-add | 1 - bin/mpw-config | 1 - bin/mpw-copy | 1 - bin/mpw-delete | 1 - bin/mpw-export | 1 - bin/mpw-genpwd | 1 - bin/mpw-import | 1 - bin/mpw-list | 1 - bin/mpw-update | 1 - bin/mpw-wallet | 1 - lib/mpw/cli.rb | 29 +++++----- lib/mpw/config.rb | 11 ++-- lib/mpw/import/gorilla.rb | 1 - lib/mpw/import/mpw.rb | 1 - lib/mpw/import/mpw_old.rb | 1 - lib/mpw/item.rb | 1 - lib/mpw/mpw.rb | 13 +++-- mpw.gemspec | 2 - test/init.rb | 2 - test/test_cli.rb | 2 - test/test_config.rb | 2 - test/test_import.rb | 2 - test/test_item.rb | 2 - test/test_mpw.rb | 2 - test/test_translate.rb | 2 - 27 files changed, 39 insertions(+), 155 deletions(-) diff --git a/.rubocop.yml b/.rubocop.yml index ce1de33..56d1540 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -6,116 +6,33 @@ AllCops: - Vagrantfile TargetRubyVersion: 2.3 -Style/AccessorMethodName: +Naming/AccessorMethodName: Enabled: false -Style/NumericLiteralPrefix: - Enabled: false -Style/TrailingCommaInArguments: - Enabled: false -Style/TrailingCommaInLiteral: - Enabled: false -Style/FrozenStringLiteralComment: - Enabled: false -Metrics/ParameterLists: - Max: 5 - CountKeywordArgs: false -Style/MutableConstant: + +Lint/RescueWithoutErrorClass: Enabled: false + Metrics/LineLength: Max: 120 -Metrics/AbcSize: +Metrics/CyclomaticComplexity: + Enabled: false +Metrics/PerceivedComplexity: Enabled: false Metrics/MethodLength: Enabled: false Metrics/BlockLength: Enabled: false -Metrics/CyclomaticComplexity: - Enabled: false -Metrics/PerceivedComplexity: - Enabled: false Metrics/ClassLength: Enabled: false -Style/SpaceInsideHashLiteralBraces: - Enabled: false -Style/AsciiComments: - Enabled: true -Style/Documentation: - Enabled: false -Style/SignalException: - Enabled: false -Style/OptionHash: - Enabled: true -Style/SymbolArray: - Enabled: true -Performance/Casecmp: - Enabled: false -Style/DoubleNegation: - Enabled: false -Style/Alias: - EnforcedStyle: prefer_alias_method -Style/MultilineMethodCallIndentation: - EnforcedStyle: indented -Style/RaiseArgs: - EnforcedStyle: exploded -Style/SpaceInLambdaLiteral: - Enabled: false -Lint/UnneededSplatExpansion: +Metrics/AbcSize: Enabled: false - -# Generated configuration -Style/HashSyntax: - Enabled: true - EnforcedStyle: ruby19 - UseHashRocketsWithSymbolValues: false -Style/MethodDefParentheses: - Enabled: true - EnforcedStyle: require_parentheses -Style/MultilineAssignmentLayout: - Enabled: true - EnforcedStyle: new_line -Style/IndentationConsistency: - Enabled: true - EnforcedStyle: normal -Style/AlignParameters: - Enabled: true - EnforcedStyle: with_fixed_indentation -Style/BlockDelimiters: - Enabled: true - EnforcedStyle: line_count_based -Style/AndOr: - Enabled: true -Style/DotPosition: - Enabled: true - EnforcedStyle: leading -Style/EmptyLinesAroundClassBody: - Enabled: true - EnforcedStyle: no_empty_lines -Style/EmptyLinesAroundModuleBody: - Enabled: true - EnforcedStyle: no_empty_lines -Style/NumericPredicate: - Enabled: true - EnforcedStyle: comparison -Style/EvenOdd: +Style/NumericLiteralPrefix: + Enabled: false +Style/FrozenStringLiteralComment: Enabled: false -Style/CollectionMethods: - Enabled: true - PreferredMethods: - collect: map - collect!: map! - inject: reduce - detect: find - find_all: select -Style/EmptyLinesAroundAccessModifier: - Enabled: true Style/CommandLiteral: Enabled: true EnforcedStyle: percent_x -Style/StringLiterals: - Enabled: true - EnforcedStyle: single_quotes -Style/SpaceInsideBlockBraces: - EnforcedStyle: space -Style/VariableNumber: - EnforcedStyle: snake_case +Style/Documentation: + Enabled: false diff --git a/Gemfile b/Gemfile index de2741f..405c4df 100644 --- a/Gemfile +++ b/Gemfile @@ -8,7 +8,7 @@ gem 'locale', '~> 2.1', '>= 2.1.2' gem 'rotp', '~> 3.1', '>= 3.1.0' group :development do - gem 'rubocop', '0.48.1' + gem 'rubocop', '0.50.0' gem 'test-unit' gem 'yard' end diff --git a/bin/mpw-add b/bin/mpw-add index 1d0581a..cdc23b0 100644 --- a/bin/mpw-add +++ b/bin/mpw-add @@ -1,4 +1,3 @@ -#!/usr/bin/ruby # MPW is a software to crypt and manage your passwords # Copyright (C) 2017 Adrien Waksberg <mpw@yae.im> # diff --git a/bin/mpw-config b/bin/mpw-config index 0af88bd..e36d2f8 100644 --- a/bin/mpw-config +++ b/bin/mpw-config @@ -1,4 +1,3 @@ -#!/usr/bin/ruby # MPW is a software to crypt and manage your passwords # Copyright (C) 2017 Adrien Waksberg <mpw@yae.im> # diff --git a/bin/mpw-copy b/bin/mpw-copy index 95c01d6..01b75aa 100644 --- a/bin/mpw-copy +++ b/bin/mpw-copy @@ -1,4 +1,3 @@ -#!/usr/bin/ruby # MPW is a software to crypt and manage your passwords # Copyright (C) 2017 Adrien Waksberg <mpw@yae.im> # diff --git a/bin/mpw-delete b/bin/mpw-delete index ea352c4..78dc340 100644 --- a/bin/mpw-delete +++ b/bin/mpw-delete @@ -1,4 +1,3 @@ -#!/usr/bin/ruby # MPW is a software to crypt and manage your passwords # Copyright (C) 2017 Adrien Waksberg <mpw@yae.im> # diff --git a/bin/mpw-export b/bin/mpw-export index 83d35ae..3ab0945 100644 --- a/bin/mpw-export +++ b/bin/mpw-export @@ -1,4 +1,3 @@ -#!/usr/bin/ruby # MPW is a software to crypt and manage your passwords # Copyright (C) 2017 Adrien Waksberg <mpw@yae.im> # diff --git a/bin/mpw-genpwd b/bin/mpw-genpwd index 051c5c4..de5628f 100644 --- a/bin/mpw-genpwd +++ b/bin/mpw-genpwd @@ -1,4 +1,3 @@ -#!/usr/bin/ruby # MPW is a software to crypt and manage your passwords # Copyright (C) 2017 Adrien Waksberg <mpw@yae.im> # diff --git a/bin/mpw-import b/bin/mpw-import index 76e163e..8213eb3 100644 --- a/bin/mpw-import +++ b/bin/mpw-import @@ -1,4 +1,3 @@ -#!/usr/bin/ruby # MPW is a software to crypt and manage your passwords # Copyright (C) 2017 Adrien Waksberg <mpw@yae.im> # diff --git a/bin/mpw-list b/bin/mpw-list index 434ea11..71e7b5a 100644 --- a/bin/mpw-list +++ b/bin/mpw-list @@ -1,4 +1,3 @@ -#!/usr/bin/ruby # MPW is a software to crypt and manage your passwords # Copyright (C) 2017 Adrien Waksberg <mpw@yae.im> # diff --git a/bin/mpw-update b/bin/mpw-update index d15b8e7..53ce5f8 100644 --- a/bin/mpw-update +++ b/bin/mpw-update @@ -1,4 +1,3 @@ -#!/usr/bin/ruby # MPW is a software to crypt and manage your passwords # Copyright (C) 2017 Adrien Waksberg <mpw@yae.im> # diff --git a/bin/mpw-wallet b/bin/mpw-wallet index caee35d..6f84afd 100644 --- a/bin/mpw-wallet +++ b/bin/mpw-wallet @@ -1,4 +1,3 @@ -#!/usr/bin/ruby # MPW is a software to crypt and manage your passwords # Copyright (C) 2017 Adrien Waksberg <mpw@yae.im> # diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index d54b314..7309024 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -1,4 +1,3 @@ -#!/usr/bin/ruby # MPW is a software to crypt and manage your passwords # Copyright (C) 2017 Adrien Waksberg <mpw@yae.im> # @@ -39,7 +38,7 @@ module MPW @config.setup(options) puts I18n.t('form.set_config.valid').to_s.green - rescue => e + rescue e puts "#{I18n.t('display.error')} #15: #{e}".red exit 2 end @@ -50,7 +49,7 @@ module MPW @config.set_wallet_path(path, @wallet) puts I18n.t('form.set_wallet_path.valid').to_s.green - rescue => e + rescue e puts "#{I18n.t('display.error')} #19: #{e}".red exit 2 end @@ -67,7 +66,7 @@ module MPW load_config puts I18n.t('form.setup_config.valid').to_s.green - rescue => e + rescue e puts "#{I18n.t('display.error')} #8: #{e}".red exit 2 end @@ -89,7 +88,7 @@ module MPW @config.setup_gpg_key(@password, gpg_key) puts I18n.t('form.setup_gpg_key.valid').to_s.green - rescue => e + rescue e puts "#{I18n.t('display.error')} #8: #{e}".red exit 2 end @@ -119,7 +118,7 @@ module MPW # Load config def load_config @config.load_config - rescue => e + rescue e puts "#{I18n.t('display.error')} #10: #{e}".red exit 2 end @@ -140,7 +139,7 @@ module MPW @mpw.read_data end end - rescue => e + rescue e puts "#{I18n.t('display.error')} #11: #{e}".red exit 2 end @@ -416,7 +415,7 @@ module MPW @mpw.write_data puts I18n.t('form.add_key.valid').to_s.green - rescue => e + rescue e puts "#{I18n.t('display.error')} #13: #{e}".red end @@ -427,7 +426,7 @@ module MPW @mpw.write_data puts I18n.t('form.delete_key.valid').to_s.green - rescue => e + rescue e puts "#{I18n.t('display.error')} #15: #{e}".red end @@ -478,7 +477,7 @@ module MPW @mpw.write_data puts I18n.t('form.add_item.valid').to_s.green - rescue => e + rescue e puts "#{I18n.t('display.error')} #13: #{e}".red end @@ -506,7 +505,7 @@ module MPW puts I18n.t('form.update_item.valid').to_s.green end - rescue => e + rescue e puts "#{I18n.t('display.error')} #14: #{e}".red end @@ -530,7 +529,7 @@ module MPW puts I18n.t('form.delete_item.valid').to_s.green end - rescue => e + rescue e puts "#{I18n.t('display.error')} #16: #{e}".red end @@ -548,7 +547,7 @@ module MPW item = get_item(items) clipboard(item, clipboard) end - rescue => e + rescue e puts "#{I18n.t('display.error')} #14: #{e}".red end @@ -578,7 +577,7 @@ module MPW File.open(file, 'w') { |f| f << data.to_yaml } puts I18n.t('form.export.valid', file: file).to_s.green - rescue => e + rescue e puts "#{I18n.t('display.error')} #17: #{e}".red end @@ -613,7 +612,7 @@ module MPW @mpw.write_data puts I18n.t('form.import.valid').to_s.green - rescue => e + rescue e puts "#{I18n.t('display.error')} #18: #{e}".red end end diff --git a/lib/mpw/config.rb b/lib/mpw/config.rb index 95390a4..47440ab 100644 --- a/lib/mpw/config.rb +++ b/lib/mpw/config.rb @@ -1,4 +1,3 @@ -#!/usr/bin/ruby # MPW is a software to crypt and manage your passwords # Copyright (C) 2017 Adrien Waksberg <mpw@yae.im> # @@ -39,9 +38,9 @@ module MPW def initialize(config_file = nil) @config_file = config_file @config_dir = - if /darwin/ =~ RUBY_PLATFORM + if RUBY_PLATFORM =~ /darwin/ "#{Dir.home}/Library/Preferences/mpw" - elsif /cygwin|mswin|mingw|bccwin|wince|emx/ =~ RUBY_PLATFORM + elsif RUBY_PLATFORM =~ /cygwin|mswin|mingw|bccwin|wince|emx/ "#{Dir.home}/AppData/Local/mpw" else "#{Dir.home}/.config/mpw" @@ -94,7 +93,7 @@ module MPW File.open(@config_file, 'w') do |file| file << config.to_yaml end - rescue => e + rescue e raise "#{I18n.t('error.config.write')}\n#{e}" end @@ -122,7 +121,7 @@ module MPW ctx = GPGME::Ctx.new ctx.genkey(param, nil, nil) - rescue => e + rescue e raise "#{I18n.t('error.config.genkey_gpg.exception')}\n#{e}" end @@ -141,7 +140,7 @@ module MPW raise if @gpg_key.empty? || @wallet_dir.empty? I18n.locale = @lang.to_sym - rescue => e + rescue e raise "#{I18n.t('error.config.load')}\n#{e}" end diff --git a/lib/mpw/import/gorilla.rb b/lib/mpw/import/gorilla.rb index fd5d9f1..a5a8fbe 100644 --- a/lib/mpw/import/gorilla.rb +++ b/lib/mpw/import/gorilla.rb @@ -1,4 +1,3 @@ -#!/usr/bin/ruby # MPW is a software to crypt and manage your passwords # Copyright (C) 2017 Adrien Waksberg <mpw@yae.im> # diff --git a/lib/mpw/import/mpw.rb b/lib/mpw/import/mpw.rb index 8d6b1c4..aca88aa 100644 --- a/lib/mpw/import/mpw.rb +++ b/lib/mpw/import/mpw.rb @@ -1,4 +1,3 @@ -#!/usr/bin/ruby # MPW is a software to crypt and manage your passwords # Copyright (C) 2017 Adrien Waksberg <mpw@yae.im> # diff --git a/lib/mpw/import/mpw_old.rb b/lib/mpw/import/mpw_old.rb index f6957fe..7f8c33e 100644 --- a/lib/mpw/import/mpw_old.rb +++ b/lib/mpw/import/mpw_old.rb @@ -1,4 +1,3 @@ -#!/usr/bin/ruby # MPW is a software to crypt and manage your passwords # Copyright (C) 2017 Adrien Waksberg <mpw@yae.im> # diff --git a/lib/mpw/item.rb b/lib/mpw/item.rb index ec8ab0e..ec4c50e 100644 --- a/lib/mpw/item.rb +++ b/lib/mpw/item.rb @@ -1,4 +1,3 @@ -#!/usr/bin/ruby # MPW is a software to crypt and manage your passwords # Copyright (C) 2017 Adrien Waksberg <mpw@yae.im> # diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index a5fc0ae..257d3bf 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -1,4 +1,3 @@ -#!/usr/bin/ruby # MPW is a software to crypt and manage your passwords # Copyright (C) 2017 Adrien Waksberg <mpw@yae.im> # @@ -89,14 +88,14 @@ module MPW otp: @otp_keys.key?(d['id']), comment: d['comment'], last_edit: d['last_edit'], - created: d['created'], + created: d['created'] ) ) end end add_key(@key) unless @keys.key?(@key) - rescue => e + rescue e raise "#{I18n.t('error.mpw_file.read_data')}\n#{e}" end @@ -116,7 +115,7 @@ module MPW 'url' => item.url, 'comment' => item.comment, 'last_edit' => item.last_edit, - 'created' => item.created, + 'created' => item.created } ) end @@ -147,7 +146,7 @@ module MPW end File.rename(tmp_file, @wallet_file) - rescue => e + rescue e File.unlink(tmp_file) if File.exist?(tmp_file) raise "#{I18n.t('error.mpw_file.write_data')}\n#{e}" @@ -324,7 +323,7 @@ module MPW crypto .decrypt(data, password) .read.force_encoding('utf-8') - rescue => e + rescue e raise "#{I18n.t('error.gpg_file.decrypt')}\n#{e}" end @@ -342,7 +341,7 @@ module MPW end crypto.encrypt(data, recipients: recipients).read - rescue => e + rescue e raise "#{I18n.t('error.gpg_file.encrypt')}\n#{e}" end end diff --git a/mpw.gemspec b/mpw.gemspec index 4afbe3b..dfb4825 100644 --- a/mpw.gemspec +++ b/mpw.gemspec @@ -1,5 +1,3 @@ -# coding: utf-8 - lib = File.expand_path('../lib', __FILE__) $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) diff --git a/test/init.rb b/test/init.rb index 6da9ecb..08ebbb8 100644 --- a/test/init.rb +++ b/test/init.rb @@ -1,5 +1,3 @@ -#!/usr/bin/ruby - require 'fileutils' require 'gpgme' diff --git a/test/test_cli.rb b/test/test_cli.rb index 07c4273..9cfe215 100644 --- a/test/test_cli.rb +++ b/test/test_cli.rb @@ -1,5 +1,3 @@ -#!/usr/bin/ruby - require 'i18n' require 'test/unit' diff --git a/test/test_config.rb b/test/test_config.rb index 8ad7369..2b88b54 100644 --- a/test/test_config.rb +++ b/test/test_config.rb @@ -1,5 +1,3 @@ -#!/usr/bin/ruby - require 'mpw/config' require 'test/unit' require 'locale' diff --git a/test/test_import.rb b/test/test_import.rb index c27b58f..101fd1a 100644 --- a/test/test_import.rb +++ b/test/test_import.rb @@ -1,5 +1,3 @@ -#!/usr/bin/ruby - require 'i18n' require 'test/unit' diff --git a/test/test_item.rb b/test/test_item.rb index 80e39ff..97503c0 100644 --- a/test/test_item.rb +++ b/test/test_item.rb @@ -1,5 +1,3 @@ -#!/usr/bin/ruby - require 'mpw/item' require 'test/unit' require 'yaml' diff --git a/test/test_mpw.rb b/test/test_mpw.rb index a1633ef..8fc544e 100644 --- a/test/test_mpw.rb +++ b/test/test_mpw.rb @@ -1,5 +1,3 @@ -#!/usr/bin/ruby - require 'mpw/mpw' require 'mpw/item' require 'test/unit' diff --git a/test/test_translate.rb b/test/test_translate.rb index d4bb002..d7cbceb 100644 --- a/test/test_translate.rb +++ b/test/test_translate.rb @@ -1,5 +1,3 @@ -#!/usr/bin/ruby - require 'yaml' require 'test/unit' From ef0a9081449d0b0fd65859bdca84c53179189485 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Mon, 18 Sep 2017 07:58:21 +0200 Subject: [PATCH 519/531] feat: add docker for local tests --- .docker-test | 32 ++++++++++++++++++++++++++++++++ Dockerfile | 20 ++++++++++++++++++++ README.md | 17 +++++++++++++++++ 3 files changed, 69 insertions(+) create mode 100644 .docker-test create mode 100644 Dockerfile diff --git a/.docker-test b/.docker-test new file mode 100644 index 0000000..d36fad8 --- /dev/null +++ b/.docker-test @@ -0,0 +1,32 @@ +#!/bin/bash + +ruby_version=${1:-2.4.2} + +if ! rvm use ruby-${ruby_version} &>/dev/null ; then + echo "The ruby version '${ruby_version}' doesn't exist!" + echo "Available versions are:" + rvm list rubies strings | cut -d '-' -f2 + exit 2 +fi + +echo '# ---------------------------------' +echo "# Use ruby version: ${ruby_version}" +echo '# ---------------------------------' + +cp -r /mpw ~/mpw +cd ~/mpw +gem install bundler --no-ri --no-rdoc +bundle install +gem build mpw.gemspec +gem install mpw-$(cat VERSION).gem +cp -a /dev/urandom /dev/random + +rubocop +ruby ./test/init.rb +ruby ./test/test_config.rb +ruby ./test/test_item.rb +ruby ./test/test_mpw.rb +ruby ./test/test_translate.rb +ruby ./test/init.rb +ruby ./test/test_cli.rb +ruby ./test/test_import.rb diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..d8995d0 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,20 @@ +FROM debian:stretch +MAINTAINER Adrien Waksberg "mpw@yae.im" + +RUN apt update +RUN apt dist-upgrade -y + +RUN apt install -y procps gnupg1 curl git +RUN ln -snvf /usr/bin/gpg1 /usr/bin/gpg +RUN gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB +RUN curl -sSL https://get.rvm.io | bash -s stable +RUN echo 'source "/usr/local/rvm/scripts/rvm"' >> /etc/bash.bashrc + +run apt install -y patch bzip2 gawk g++ gcc make libc6-dev patch zlib1g-dev libyaml-dev libsqlite3-dev \ + sqlite3 autoconf libgmp-dev libgdbm-dev libncurses5-dev automake libtool bison \ + pkg-config libffi-dev libgmp-dev libreadline-dev libssl-dev + +RUN /bin/bash -l -c "rvm install 2.4.2" +RUN /bin/bash -l -c "rvm install 2.3.5" +RUN /bin/bash -l -c "rvm install 2.2.8" +RUN /bin/bash -l -c "rvm install 2.1.10" diff --git a/README.md b/README.md index 9c2c5d6..162be49 100644 --- a/README.md +++ b/README.md @@ -161,3 +161,20 @@ Configuration password_length | 16 ``` + +## Development + +Don't run the tests on your local machine, you risk to lost your datas. + +### Test on local machine with docker + + * install [docker](https://docs.docker.com/engine/installation/) + * build the container +``` +docker build -t mpw/debian:stretch -f Dockerfile . +``` + * run the tests + +``` +docker run -v $(pwd):/mpw:ro -it mpw/debian:stretch /bin/bash -l /mpw/.docker-test +``` From 2abad3695f2883488f6b1f9796542ac262763c4a Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Sun, 1 Oct 2017 20:01:35 +0200 Subject: [PATCH 520/531] fix no show wallet in other folder --- lib/mpw/cli.rb | 3 ++- test/test_cli.rb | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index 7309024..711e91c 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -373,7 +373,8 @@ module MPW # List all wallets def list_wallet - wallets = [] + wallets = @config.wallet_paths.keys + Dir.glob("#{@config.wallet_dir}/*.mpw").each do |f| wallet = File.basename(f, '.mpw') wallet += ' *'.green if wallet == @config.default_wallet diff --git a/test/test_cli.rb b/test/test_cli.rb index 9cfe215..766aebd 100644 --- a/test/test_cli.rb +++ b/test/test_cli.rb @@ -171,6 +171,10 @@ class TestConfig < Test::Unit::TestCase assert_match(%r{path_wallet_default.+\| #{Dir.pwd}/default.mpw}, output) assert(File.exist?("#{Dir.pwd}/default.mpw")) + output = %x(mpw wallet) + puts output + assert_match('default', output) + output = %x(mpw wallet --default-path) puts output assert_match(I18n.t('form.set_wallet_path.valid'), output) From afd6585acc4fac66133a8264460a4751f1bcdd37 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Sun, 1 Oct 2017 20:31:43 +0200 Subject: [PATCH 521/531] fix: remove outputs in tests --- test/test_cli.rb | 70 +++++++++++++++++++++--------------------------- 1 file changed, 30 insertions(+), 40 deletions(-) diff --git a/test/test_cli.rb b/test/test_cli.rb index 766aebd..8bae4cc 100644 --- a/test/test_cli.rb +++ b/test/test_cli.rb @@ -17,7 +17,11 @@ class TestConfig < Test::Unit::TestCase end def test_00_init_config - output = %x(echo "#{@password}\n#{@password}" | mpw config --init #{@gpg_key}) + output = %x( + echo "#{@password}\n#{@password}" | mpw config \ + --init #{@gpg_key} \ + 2>/dev/null + ) assert_match(I18n.t('form.setup_config.valid'), output) assert_match(I18n.t('form.setup_gpg_key.valid'), output) end @@ -31,13 +35,12 @@ class TestConfig < Test::Unit::TestCase --user #{data['user']} \ --comment '#{data['comment']}' \ --group #{data['group']} \ - --random + --random \ + 2>/dev/null ) - puts output assert_match(I18n.t('form.add_item.valid'), output) - output = %x(echo #{@password} | mpw list) - puts output + output = %x(echo #{@password} | mpw list 2>/dev/null) assert_match(%r{#{data['protocol']}://.+#{data['host']}.+:#{data['port']}}, output) assert_match(data['user'], output) assert_match(data['comment'], output) @@ -47,19 +50,19 @@ class TestConfig < Test::Unit::TestCase def test_02_search data = @fixtures['add'] - output = %x(echo #{@password} | mpw list --group #{data['group']}) + output = %x(echo #{@password} | mpw list --group #{data['group']} 2>/dev/null) assert_match(%r{#{data['protocol']}://.+#{data['host']}.+:#{data['port']}}, output) - output = %x(echo #{@password} | mpw list --pattern #{data['host']}) + output = %x(echo #{@password} | mpw list --pattern #{data['host']} 2>/dev/null) assert_match(%r{#{data['protocol']}://.+#{data['host']}.+:#{data['port']}}, output) - output = %x(echo #{@password} | mpw list --pattern #{data['comment']}) + output = %x(echo #{@password} | mpw list --pattern #{data['comment']} 2>/dev/null) assert_match(%r{#{data['protocol']}://.+#{data['host']}.+:#{data['port']}}, output) - output = %x(echo #{@password} | mpw list --group R1Pmfbp626TFpjlr) + output = %x(echo #{@password} | mpw list --group R1Pmfbp626TFpjlr 2>/dev/null) assert_match(I18n.t('display.nothing'), output) - output = %x(echo #{@password} | mpw list --pattern h1IfnKqamaGM9oEX) + output = %x(echo #{@password} | mpw list --pattern h1IfnKqamaGM9oEX 2>/dev/null) assert_match(I18n.t('display.nothing'), output) end @@ -72,13 +75,12 @@ class TestConfig < Test::Unit::TestCase --url #{data['url']} \ --user #{data['user']} \ --comment '#{data['comment']}' \ - --new-group #{data['group']} + --new-group #{data['group']} \ + 2>/dev/null ) - puts output assert_match(I18n.t('form.update_item.valid'), output) - output = %x(echo #{@password} | mpw list) - puts output + output = %x(echo #{@password} | mpw list 2>/dev/null) assert_match(%r{#{data['protocol']}://.+#{data['host']}.+:#{data['port']}}, output) assert_match(data['user'], output) assert_match(data['comment'], output) @@ -86,12 +88,14 @@ class TestConfig < Test::Unit::TestCase end def test_04_delete_item - output = %x(echo "#{@password}\ny" | mpw delete -p #{@fixtures['update']['host']}) - puts output + output = %x( + echo "#{@password}\ny" | mpw delete \ + -p #{@fixtures['update']['host']} \ + 2>/dev/null + ) assert_match(I18n.t('form.delete_item.valid'), output) - output = %x(echo #{@password} | mpw list) - puts output + output = %x(echo #{@password} | mpw list 2>/dev/null) assert_match(I18n.t('display.nothing'), output) end @@ -99,10 +103,10 @@ class TestConfig < Test::Unit::TestCase file_import = './test/files/fixtures-import.yml' file_export = '/tmp/test-mpw.yml' - output = %x(echo #{@password} | mpw import --file #{file_import}) + output = %x(echo #{@password} | mpw import --file #{file_import} 2>/dev/null) assert_match(I18n.t('form.import.valid', file: file_import), output) - output = %x(echo #{@password} | mpw export --file #{file_export}) + output = %x(echo #{@password} | mpw export --file #{file_export} 2>/dev/null) assert_match(I18n.t('form.export.valid', file: file_export), output) assert(File.exist?(file_export)) assert_equal(YAML.load_file(file_export).length, 2) @@ -131,56 +135,46 @@ class TestConfig < Test::Unit::TestCase output = %x( echo "#{@password}\np\nq" | mpw copy \ --disable-clipboard \ - -p #{data['host']} + -p #{data['host']} \ + 2>/dev/null ) - puts output assert_match(data['password'], output) end def test_07_setup_wallet gpg_key = 'test2@example.com' - output = %x(echo #{@password} | mpw wallet --add-gpg-key #{gpg_key}) - puts output + output = %x(echo #{@password} | mpw wallet --add-gpg-key #{gpg_key} 2>/dev/null) assert_match(I18n.t('form.add_key.valid'), output) - output = %x(echo #{@password} | mpw wallet --list-keys) - puts output + output = %x(echo #{@password} | mpw wallet --list-keys 2>/dev/null) assert_match("| #{@gpg_key}", output) assert_match("| #{gpg_key}", output) - output = %x(echo #{@password} | mpw wallet --delete-gpg-key #{gpg_key}) - puts output + output = %x(echo #{@password} | mpw wallet --delete-gpg-key #{gpg_key} 2>/dev/null) assert_match(I18n.t('form.delete_key.valid'), output) - output = %x(echo #{@password} | mpw wallet --list-keys) - puts output + output = %x(echo #{@password} | mpw wallet --list-keys 2>/dev/null) assert_match("| #{@gpg_key}", output) assert_no_match(/\| #{gpg_key}/, output) output = %x(mpw wallet) - puts output assert_match('| default', output) output = %x(mpw wallet --path '.') - puts output assert_match(I18n.t('form.set_wallet_path.valid'), output) output = %x(mpw config) - puts output assert_match(%r{path_wallet_default.+\| #{Dir.pwd}/default.mpw}, output) assert(File.exist?("#{Dir.pwd}/default.mpw")) output = %x(mpw wallet) - puts output assert_match('default', output) output = %x(mpw wallet --default-path) - puts output assert_match(I18n.t('form.set_wallet_path.valid'), output) output = %x(mpw config) - puts output assert_no_match(/path_wallet_default/, output) end @@ -203,11 +197,9 @@ class TestConfig < Test::Unit::TestCase --wallet-dir #{wallet_dir} \ --default-wallet #{wallet} ) - puts output assert_match(I18n.t('form.set_config.valid'), output) output = %x(mpw config) - puts output assert_match(/gpg_key.+\| #{gpg_key}/, output) assert_match(/gpg_exe.+\| #{gpg_exe}/, output) assert_match(/pinmode.+\| true/, output) @@ -227,11 +219,9 @@ class TestConfig < Test::Unit::TestCase --numeric \ --disable-pinmode ) - puts output assert_match(I18n.t('form.set_config.valid'), output) output = %x(mpw config) - puts output assert_match(/gpg_key.+\| #{@gpg_key}/, output) assert_match(/pinmode.+\| false/, output) %w[numeric alpha special].each do |k| From 348db7cfd0ce14b8374c0573fc581289030cbb01 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Sun, 1 Oct 2017 20:32:56 +0200 Subject: [PATCH 522/531] feat: update travis.yml --- .travis.yml | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index 7f524d4..14d696a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,17 +1,16 @@ language: ruby dist: precise rvm: - - 2.4.1 - - 2.3.4 - - 2.2.7 + - 2.4.2 + - 2.3.5 + - 2.2.8 - 2.1.10 install: - sudo cp -a /dev/urandom /dev/random - sudo apt-get purge -y gnupg-agent gnupg2 - bundle install - - echo 9999 > VERSION - gem build mpw.gemspec - - gem install mpw-9999.gem + - gem install mpw-$(cat VERSION).gem script: - rubocop - ruby ./test/init.rb From 8fddbd01be1e5a10b24b1ba8ab49536b6f9145de Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Tue, 3 Oct 2017 13:07:53 +0200 Subject: [PATCH 523/531] fix: minor change in dockerfile --- Dockerfile | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Dockerfile b/Dockerfile index d8995d0..6654780 100644 --- a/Dockerfile +++ b/Dockerfile @@ -10,10 +10,6 @@ RUN gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A170311380 RUN curl -sSL https://get.rvm.io | bash -s stable RUN echo 'source "/usr/local/rvm/scripts/rvm"' >> /etc/bash.bashrc -run apt install -y patch bzip2 gawk g++ gcc make libc6-dev patch zlib1g-dev libyaml-dev libsqlite3-dev \ - sqlite3 autoconf libgmp-dev libgdbm-dev libncurses5-dev automake libtool bison \ - pkg-config libffi-dev libgmp-dev libreadline-dev libssl-dev - RUN /bin/bash -l -c "rvm install 2.4.2" RUN /bin/bash -l -c "rvm install 2.3.5" RUN /bin/bash -l -c "rvm install 2.2.8" From b0905f18f1f4d14d5b9f08f4379809cacc3cf27d Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Tue, 3 Oct 2017 13:09:27 +0200 Subject: [PATCH 524/531] fix: remove output for test_import --- test/test_import.rb | 3 --- 1 file changed, 3 deletions(-) diff --git a/test/test_import.rb b/test/test_import.rb index 101fd1a..ae53eef 100644 --- a/test/test_import.rb +++ b/test/test_import.rb @@ -29,15 +29,12 @@ class TestImport < Test::Unit::TestCase assert_match(I18n.t('form.import.valid'), output) output = %x(echo #{@password} | mpw list --group Bank --wallet #{format}) - puts output assert_match(%r{http://.*fric\.com.*12345.*Fric money money}, output) output = %x(echo #{@password} | mpw list --group Cloud --wallet #{format}) - puts output assert_match(%r{ssh://.*fric\.com.*:4333.*username.*bastion}, output) output = %x(echo #{@password} | mpw list --wallet #{format}) - puts output assert_match(/server\.com.*My little server/, output) end end From 2de66a4eaf9c4b6b7c8c4f7d8766039609f89aba Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Sun, 19 Nov 2017 13:49:42 +0100 Subject: [PATCH 525/531] fix syntax for all rescue --- lib/mpw/cli.rb | 28 ++++++++++++++-------------- lib/mpw/config.rb | 6 +++--- lib/mpw/mpw.rb | 8 ++++---- 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index 711e91c..db703a8 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -38,7 +38,7 @@ module MPW @config.setup(options) puts I18n.t('form.set_config.valid').to_s.green - rescue e + rescue => e puts "#{I18n.t('display.error')} #15: #{e}".red exit 2 end @@ -49,7 +49,7 @@ module MPW @config.set_wallet_path(path, @wallet) puts I18n.t('form.set_wallet_path.valid').to_s.green - rescue e + rescue => e puts "#{I18n.t('display.error')} #19: #{e}".red exit 2 end @@ -66,7 +66,7 @@ module MPW load_config puts I18n.t('form.setup_config.valid').to_s.green - rescue e + rescue => e puts "#{I18n.t('display.error')} #8: #{e}".red exit 2 end @@ -88,7 +88,7 @@ module MPW @config.setup_gpg_key(@password, gpg_key) puts I18n.t('form.setup_gpg_key.valid').to_s.green - rescue e + rescue => e puts "#{I18n.t('display.error')} #8: #{e}".red exit 2 end @@ -118,7 +118,7 @@ module MPW # Load config def load_config @config.load_config - rescue e + rescue => e puts "#{I18n.t('display.error')} #10: #{e}".red exit 2 end @@ -139,7 +139,7 @@ module MPW @mpw.read_data end end - rescue e + rescue => e puts "#{I18n.t('display.error')} #11: #{e}".red exit 2 end @@ -416,7 +416,7 @@ module MPW @mpw.write_data puts I18n.t('form.add_key.valid').to_s.green - rescue e + rescue => e puts "#{I18n.t('display.error')} #13: #{e}".red end @@ -427,7 +427,7 @@ module MPW @mpw.write_data puts I18n.t('form.delete_key.valid').to_s.green - rescue e + rescue => e puts "#{I18n.t('display.error')} #15: #{e}".red end @@ -478,7 +478,7 @@ module MPW @mpw.write_data puts I18n.t('form.add_item.valid').to_s.green - rescue e + rescue => e puts "#{I18n.t('display.error')} #13: #{e}".red end @@ -506,7 +506,7 @@ module MPW puts I18n.t('form.update_item.valid').to_s.green end - rescue e + rescue => e puts "#{I18n.t('display.error')} #14: #{e}".red end @@ -530,7 +530,7 @@ module MPW puts I18n.t('form.delete_item.valid').to_s.green end - rescue e + rescue => e puts "#{I18n.t('display.error')} #16: #{e}".red end @@ -548,7 +548,7 @@ module MPW item = get_item(items) clipboard(item, clipboard) end - rescue e + rescue => e puts "#{I18n.t('display.error')} #14: #{e}".red end @@ -578,7 +578,7 @@ module MPW File.open(file, 'w') { |f| f << data.to_yaml } puts I18n.t('form.export.valid', file: file).to_s.green - rescue e + rescue => e puts "#{I18n.t('display.error')} #17: #{e}".red end @@ -613,7 +613,7 @@ module MPW @mpw.write_data puts I18n.t('form.import.valid').to_s.green - rescue e + rescue => e puts "#{I18n.t('display.error')} #18: #{e}".red end end diff --git a/lib/mpw/config.rb b/lib/mpw/config.rb index 47440ab..a4d2142 100644 --- a/lib/mpw/config.rb +++ b/lib/mpw/config.rb @@ -93,7 +93,7 @@ module MPW File.open(@config_file, 'w') do |file| file << config.to_yaml end - rescue e + rescue => e raise "#{I18n.t('error.config.write')}\n#{e}" end @@ -121,7 +121,7 @@ module MPW ctx = GPGME::Ctx.new ctx.genkey(param, nil, nil) - rescue e + rescue => e raise "#{I18n.t('error.config.genkey_gpg.exception')}\n#{e}" end @@ -140,7 +140,7 @@ module MPW raise if @gpg_key.empty? || @wallet_dir.empty? I18n.locale = @lang.to_sym - rescue e + rescue => e raise "#{I18n.t('error.config.load')}\n#{e}" end diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index 257d3bf..a67f09d 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -95,7 +95,7 @@ module MPW end add_key(@key) unless @keys.key?(@key) - rescue e + rescue => e raise "#{I18n.t('error.mpw_file.read_data')}\n#{e}" end @@ -146,7 +146,7 @@ module MPW end File.rename(tmp_file, @wallet_file) - rescue e + rescue => e File.unlink(tmp_file) if File.exist?(tmp_file) raise "#{I18n.t('error.mpw_file.write_data')}\n#{e}" @@ -323,7 +323,7 @@ module MPW crypto .decrypt(data, password) .read.force_encoding('utf-8') - rescue e + rescue => e raise "#{I18n.t('error.gpg_file.decrypt')}\n#{e}" end @@ -341,7 +341,7 @@ module MPW end crypto.encrypt(data, recipients: recipients).read - rescue e + rescue => e raise "#{I18n.t('error.gpg_file.encrypt')}\n#{e}" end end From ed09f55ce282bd4b170b8ebc9abf615be633098a Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Sun, 19 Nov 2017 13:54:17 +0100 Subject: [PATCH 526/531] chore: update README --- README.md | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/README.md b/README.md index 162be49..4b0c0b0 100644 --- a/README.md +++ b/README.md @@ -169,12 +169,8 @@ Don't run the tests on your local machine, you risk to lost your datas. ### Test on local machine with docker * install [docker](https://docs.docker.com/engine/installation/) - * build the container -``` -docker build -t mpw/debian:stretch -f Dockerfile . -``` * run the tests ``` -docker run -v $(pwd):/mpw:ro -it mpw/debian:stretch /bin/bash -l /mpw/.docker-test +docker run -v $(pwd):/mpw:ro -it nishiki/ruby:stretch /bin/bash -l /mpw/.docker-test ``` From 30ca80f6db7b67bfd74c1a8b57e6eebaa859c1b6 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Sun, 19 Nov 2017 18:27:48 +0100 Subject: [PATCH 527/531] fix shebang --- bin/mpw | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/mpw b/bin/mpw index 811322e..384374a 100755 --- a/bin/mpw +++ b/bin/mpw @@ -1,4 +1,4 @@ -#!/usr/bin/ruby +#!/usr/bin/env ruby # MPW is a software to crypt and manage your passwords # Copyright (C) 2017 Adrien Waksberg <mpw@yae.im> # From 6a2d5da9fbf022ba90fc3ed594eae87616339001 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Sun, 19 Nov 2017 20:11:39 +0100 Subject: [PATCH 528/531] feat: update gem dependencies --- Gemfile | 6 +++--- mpw.gemspec | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Gemfile b/Gemfile index 405c4df..a76b2c1 100644 --- a/Gemfile +++ b/Gemfile @@ -1,11 +1,11 @@ source 'https://rubygems.org' gem 'clipboard', '~> 1.1', '>= 1.1.1' gem 'colorize', '~> 0.8', '>= 0.8.1' -gem 'gpgme', '~> 2.0', '>= 2.0.12' +gem 'gpgme', '~> 2.0', '>= 2.0.14' gem 'highline', '~> 1.7', '>= 1.7.8' -gem 'i18n', '~> 0.7', '>= 0.7.0' +gem 'i18n', '~> 0.9', '>= 0.9.1' gem 'locale', '~> 2.1', '>= 2.1.2' -gem 'rotp', '~> 3.1', '>= 3.1.0' +gem 'rotp', '~> 3.3', '>= 3.3.0' group :development do gem 'rubocop', '0.50.0' diff --git a/mpw.gemspec b/mpw.gemspec index dfb4825..abcb375 100644 --- a/mpw.gemspec +++ b/mpw.gemspec @@ -18,11 +18,11 @@ Gem::Specification.new do |spec| spec.required_ruby_version = '>= 2.1' - spec.add_dependency 'i18n', '~> 0.7', '>= 0.7.0' - spec.add_dependency 'gpgme', '~> 2.0', '>= 2.0.12' + spec.add_dependency 'i18n', '~> 0.9', '>= 0.9.1' + spec.add_dependency 'gpgme', '~> 2.0', '>= 2.0.14' spec.add_dependency 'highline', '~> 1.7', '>= 1.7.8' spec.add_dependency 'locale', '~> 2.1', '>= 2.1.2' spec.add_dependency 'colorize', '~> 0.8', '>= 0.8.1' spec.add_dependency 'clipboard', '~> 1.1', '>= 1.1.1' - spec.add_dependency 'rotp', '~> 3.1', '>= 3.1.0' + spec.add_dependency 'rotp', '~> 3.3', '>= 3.3.0' end From a11777cadead7dab24775538be9f171c50d6dbb6 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Sun, 19 Nov 2017 21:25:42 +0100 Subject: [PATCH 529/531] feat: add keepass --- lib/mpw/import/keepass.rb | 50 +++++++++++++++++++++++ test/files/import-keepass.txt | 3 ++ test/test_import.rb | 74 ++++++++++++++++++++++++++--------- 3 files changed, 109 insertions(+), 18 deletions(-) create mode 100644 lib/mpw/import/keepass.rb create mode 100644 test/files/import-keepass.txt diff --git a/lib/mpw/import/keepass.rb b/lib/mpw/import/keepass.rb new file mode 100644 index 0000000..b9d7852 --- /dev/null +++ b/lib/mpw/import/keepass.rb @@ -0,0 +1,50 @@ +# MPW is a software to crypt and manage your passwords +# Copyright (C) 2017 Adrien Waksberg <mpw@yae.im> +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +require 'csv' + +module MPW + module Import + # Import an keepass2 export csv file + # @param file [String] the file path to import + def self.keepass(file) + data = {} + + CSV.foreach(file, headers: true) do |row| + id = "#{row['Group']} #{row['Title']}" + comment = + if row['Title'] && row['Notes'] + "#{row['Title']} #{row['Notes']}" + elsif row['Title'] + row['Title'] + elsif row['Notes'] + row['Notes'] + end + + data[id] = { + 'comment' => comment, + 'group' => row['Group'], + 'password' => row['Password'], + 'url' => row['URL'], + 'user' => row['Username'] + } + end + + data + end + end +end diff --git a/test/files/import-keepass.txt b/test/files/import-keepass.txt new file mode 100644 index 0000000..61ce7ad --- /dev/null +++ b/test/files/import-keepass.txt @@ -0,0 +1,3 @@ +"Group","Title","Username","Password","URL","Notes" +"Racine","Bank","123456","ywcExJW8qmBVTSyi","http://bank.com/login","My little bank" +"Racine/Cloud","GAFAM","wesh","superpassword","localhost.local","" diff --git a/test/test_import.rb b/test/test_import.rb index ae53eef..f1a8727 100644 --- a/test/test_import.rb +++ b/test/test_import.rb @@ -14,28 +14,66 @@ class TestImport < Test::Unit::TestCase @password = 'password' end - def test_00_import - Dir['./test/files/import-*.txt'].each do |file| - format = File.basename(file, '.txt').partition('-').last + def test_00_import_mpw_old + file = './test/files/import-mpw_old.txt' + format = 'mpw_old' - puts format + output = %x( + mpw import \ + --file #{file} \ + --format #{format} \ + --wallet #{format} + ) + assert_match(I18n.t('form.import.valid'), output) - output = %x( - mpw import \ - --file #{file} \ - --format #{format} \ - --wallet #{format} - ) - assert_match(I18n.t('form.import.valid'), output) + output = %x(echo #{@password} | mpw list --group Bank --wallet #{format}) + assert_match(%r{http://.*fric\.com.*12345.*Fric money money}, output) - output = %x(echo #{@password} | mpw list --group Bank --wallet #{format}) - assert_match(%r{http://.*fric\.com.*12345.*Fric money money}, output) + output = %x(echo #{@password} | mpw list --group Cloud --wallet #{format}) + assert_match(%r{ssh://.*fric\.com.*:4333.*username.*bastion}, output) - output = %x(echo #{@password} | mpw list --group Cloud --wallet #{format}) - assert_match(%r{ssh://.*fric\.com.*:4333.*username.*bastion}, output) + output = %x(echo #{@password} | mpw list --wallet #{format}) + assert_match(/server\.com.*My little server/, output) + end - output = %x(echo #{@password} | mpw list --wallet #{format}) - assert_match(/server\.com.*My little server/, output) - end + def test_01_import_gorilla + file = './test/files/import-gorilla.txt' + format = 'gorilla' + + output = %x( + mpw import \ + --file #{file} \ + --format #{format} \ + --wallet #{format} + ) + assert_match(I18n.t('form.import.valid'), output) + + output = %x(echo #{@password} | mpw list --group Bank --wallet #{format}) + assert_match(%r{http://.*fric\.com.*12345.*Fric money money}, output) + + output = %x(echo #{@password} | mpw list --group Cloud --wallet #{format}) + assert_match(%r{ssh://.*fric\.com.*:4333.*username.*bastion}, output) + + output = %x(echo #{@password} | mpw list --wallet #{format}) + assert_match(/server\.com.*My little server/, output) + end + + def test_02_import_keepass + file = './test/files/import-keepass.txt' + format = 'keepass' + + output = %x( + mpw import \ + --file #{file} \ + --format #{format} \ + --wallet #{format} + ) + assert_match(I18n.t('form.import.valid'), output) + + output = %x(echo #{@password} | mpw list --group 'Racine/Cloud' --wallet #{format}) + assert_match(/localhost\.local.*wesh.*GAFAM/, output) + + output = %x(echo #{@password} | mpw list --wallet #{format}) + assert_match(%r{http://.*bank\.com.*123456.*Bank My little bank}, output) end end From fe7a03ba52e5b7a2ef0f3786cbdc474a53a83c4a Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Sun, 19 Nov 2017 23:03:16 +0100 Subject: [PATCH 530/531] feat: change license GPL2.0 to Apache2.0 --- LICENSE | 476 ++++++++++++++------------------------ README.md | 23 +- bin/mpw | 29 +-- bin/mpw-add | 29 +-- bin/mpw-config | 29 +-- bin/mpw-copy | 29 +-- bin/mpw-delete | 29 +-- bin/mpw-export | 28 +-- bin/mpw-genpwd | 28 +-- bin/mpw-import | 28 +-- bin/mpw-list | 28 +-- bin/mpw-update | 28 +-- bin/mpw-wallet | 28 +-- lib/mpw/cli.rb | 29 +-- lib/mpw/config.rb | 29 +-- lib/mpw/import/gorilla.rb | 29 +-- lib/mpw/import/keepass.rb | 29 +-- lib/mpw/import/mpw.rb | 29 +-- lib/mpw/import/mpw_old.rb | 29 +-- lib/mpw/item.rb | 29 +-- lib/mpw/mpw.rb | 29 +-- 21 files changed, 482 insertions(+), 562 deletions(-) diff --git a/LICENSE b/LICENSE index d159169..8dada3e 100644 --- a/LICENSE +++ b/LICENSE @@ -1,339 +1,201 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ - Copyright (C) 1989, 1991 Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - Preamble + 1. Definitions. - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Lesser General Public License instead.) You can apply it to -your programs, too. + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). - The precise terms and conditions for copying, distribution and -modification follow. + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) + END OF TERMS AND CONDITIONS -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. + APPENDIX: How to apply the Apache License to your work. -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. + Copyright {yyyy} {name of copyright owner} - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. + http://www.apache.org/licenses/LICENSE-2.0 - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - <one line to give the program's name and a brief idea of what it does.> - Copyright (C) <year> <name of author> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - <signature of Ty Coon>, 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/README.md b/README.md index 4b0c0b0..be9e7cb 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # MPW: Manage your passwords! [](https://github.com/nishiki/manage-password/releases) [](https://travis-ci.org/nishiki/manage-password) -[](https://github.com/nishiki/manage-password/blob/master/LICENSE) +[](https://github.com/nishiki/manage-password/blob/master/LICENSE) mpw is a little software which stores your passwords in [GnuPG](http://www.gnupg.org/) encrypted files. @@ -33,7 +33,6 @@ Add your first item: ``` mpw add --host assurance.com --port 443 --user user_2132 --protocol https --random mpw add --host fric.com --user 230403 --otp-code 23434113 --protocol https --comment 'I love my bank' --random - ``` And list your items: @@ -174,3 +173,23 @@ Don't run the tests on your local machine, you risk to lost your datas. ``` docker run -v $(pwd):/mpw:ro -it nishiki/ruby:stretch /bin/bash -l /mpw/.docker-test ``` + +## License + +``` +* Author:: Adrien Waksberg <mpw@yae.im> + +Copyright (c) 2013-2017 Adrien Waksberg + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +``` diff --git a/bin/mpw b/bin/mpw index 384374a..11bc726 100755 --- a/bin/mpw +++ b/bin/mpw @@ -1,20 +1,23 @@ #!/usr/bin/env ruby -# MPW is a software to crypt and manage your passwords -# Copyright (C) 2017 Adrien Waksberg <mpw@yae.im> # -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. +# Copyright:: 2013, Adrien Waksberg # -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at # -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. $LOAD_PATH << File.expand_path('../../lib', __FILE__) diff --git a/bin/mpw-add b/bin/mpw-add index cdc23b0..e08caae 100644 --- a/bin/mpw-add +++ b/bin/mpw-add @@ -1,19 +1,22 @@ -# MPW is a software to crypt and manage your passwords -# Copyright (C) 2017 Adrien Waksberg <mpw@yae.im> # -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. +# Copyright:: 2013, Adrien Waksberg # -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at # -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. require 'optparse' require 'mpw/config' diff --git a/bin/mpw-config b/bin/mpw-config index e36d2f8..2ac0f77 100644 --- a/bin/mpw-config +++ b/bin/mpw-config @@ -1,19 +1,22 @@ -# MPW is a software to crypt and manage your passwords -# Copyright (C) 2017 Adrien Waksberg <mpw@yae.im> # -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. +# Copyright:: 2013, Adrien Waksberg # -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at # -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. require 'optparse' require 'mpw/config' diff --git a/bin/mpw-copy b/bin/mpw-copy index 01b75aa..fc3b6e0 100644 --- a/bin/mpw-copy +++ b/bin/mpw-copy @@ -1,19 +1,22 @@ -# MPW is a software to crypt and manage your passwords -# Copyright (C) 2017 Adrien Waksberg <mpw@yae.im> # -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. +# Copyright:: 2013, Adrien Waksberg # -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at # -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. require 'optparse' require 'mpw/config' diff --git a/bin/mpw-delete b/bin/mpw-delete index 78dc340..48eb792 100644 --- a/bin/mpw-delete +++ b/bin/mpw-delete @@ -1,19 +1,22 @@ -# MPW is a software to crypt and manage your passwords -# Copyright (C) 2017 Adrien Waksberg <mpw@yae.im> # -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. +# Copyright:: 2013, Adrien Waksberg # -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at # -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. require 'optparse' require 'mpw/config' diff --git a/bin/mpw-export b/bin/mpw-export index 3ab0945..92eb7bd 100644 --- a/bin/mpw-export +++ b/bin/mpw-export @@ -1,19 +1,19 @@ -# MPW is a software to crypt and manage your passwords -# Copyright (C) 2017 Adrien Waksberg <mpw@yae.im> +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at # -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. +# http://www.apache.org/licenses/LICENSE-2.0 # -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. require 'optparse' require 'mpw/config' diff --git a/bin/mpw-genpwd b/bin/mpw-genpwd index de5628f..f6ca795 100644 --- a/bin/mpw-genpwd +++ b/bin/mpw-genpwd @@ -1,19 +1,19 @@ -# MPW is a software to crypt and manage your passwords -# Copyright (C) 2017 Adrien Waksberg <mpw@yae.im> +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at # -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. +# http://www.apache.org/licenses/LICENSE-2.0 # -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. require 'optparse' require 'mpw/mpw' diff --git a/bin/mpw-import b/bin/mpw-import index 8213eb3..d0deae9 100644 --- a/bin/mpw-import +++ b/bin/mpw-import @@ -1,19 +1,19 @@ -# MPW is a software to crypt and manage your passwords -# Copyright (C) 2017 Adrien Waksberg <mpw@yae.im> +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at # -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. +# http://www.apache.org/licenses/LICENSE-2.0 # -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. require 'optparse' require 'mpw/config' diff --git a/bin/mpw-list b/bin/mpw-list index 71e7b5a..fb7899c 100644 --- a/bin/mpw-list +++ b/bin/mpw-list @@ -1,19 +1,19 @@ -# MPW is a software to crypt and manage your passwords -# Copyright (C) 2017 Adrien Waksberg <mpw@yae.im> +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at # -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. +# http://www.apache.org/licenses/LICENSE-2.0 # -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. require 'optparse' require 'mpw/config' diff --git a/bin/mpw-update b/bin/mpw-update index 53ce5f8..26a55c9 100644 --- a/bin/mpw-update +++ b/bin/mpw-update @@ -1,19 +1,19 @@ -# MPW is a software to crypt and manage your passwords -# Copyright (C) 2017 Adrien Waksberg <mpw@yae.im> +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at # -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. +# http://www.apache.org/licenses/LICENSE-2.0 # -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. require 'optparse' require 'mpw/config' diff --git a/bin/mpw-wallet b/bin/mpw-wallet index 6f84afd..6518283 100644 --- a/bin/mpw-wallet +++ b/bin/mpw-wallet @@ -1,19 +1,19 @@ -# MPW is a software to crypt and manage your passwords -# Copyright (C) 2017 Adrien Waksberg <mpw@yae.im> +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at # -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. +# http://www.apache.org/licenses/LICENSE-2.0 # -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. require 'optparse' require 'mpw/config' diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb index db703a8..e64d27c 100644 --- a/lib/mpw/cli.rb +++ b/lib/mpw/cli.rb @@ -1,19 +1,22 @@ -# MPW is a software to crypt and manage your passwords -# Copyright (C) 2017 Adrien Waksberg <mpw@yae.im> # -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. +# Copyright:: 2013, Adrien Waksberg # -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at # -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. require 'readline' require 'locale' diff --git a/lib/mpw/config.rb b/lib/mpw/config.rb index a4d2142..f3974b5 100644 --- a/lib/mpw/config.rb +++ b/lib/mpw/config.rb @@ -1,19 +1,22 @@ -# MPW is a software to crypt and manage your passwords -# Copyright (C) 2017 Adrien Waksberg <mpw@yae.im> # -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. +# Copyright:: 2013, Adrien Waksberg # -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at # -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. require 'gpgme' require 'yaml' diff --git a/lib/mpw/import/gorilla.rb b/lib/mpw/import/gorilla.rb index a5a8fbe..feffce6 100644 --- a/lib/mpw/import/gorilla.rb +++ b/lib/mpw/import/gorilla.rb @@ -1,19 +1,22 @@ -# MPW is a software to crypt and manage your passwords -# Copyright (C) 2017 Adrien Waksberg <mpw@yae.im> # -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. +# Copyright:: 2013, Adrien Waksberg # -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at # -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. require 'csv' diff --git a/lib/mpw/import/keepass.rb b/lib/mpw/import/keepass.rb index b9d7852..0b961d4 100644 --- a/lib/mpw/import/keepass.rb +++ b/lib/mpw/import/keepass.rb @@ -1,19 +1,22 @@ -# MPW is a software to crypt and manage your passwords -# Copyright (C) 2017 Adrien Waksberg <mpw@yae.im> # -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. +# Copyright:: 2013, Adrien Waksberg # -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at # -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. require 'csv' diff --git a/lib/mpw/import/mpw.rb b/lib/mpw/import/mpw.rb index aca88aa..a287357 100644 --- a/lib/mpw/import/mpw.rb +++ b/lib/mpw/import/mpw.rb @@ -1,19 +1,22 @@ -# MPW is a software to crypt and manage your passwords -# Copyright (C) 2017 Adrien Waksberg <mpw@yae.im> # -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. +# Copyright:: 2013, Adrien Waksberg # -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at # -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. require 'yaml' diff --git a/lib/mpw/import/mpw_old.rb b/lib/mpw/import/mpw_old.rb index 7f8c33e..923bf16 100644 --- a/lib/mpw/import/mpw_old.rb +++ b/lib/mpw/import/mpw_old.rb @@ -1,19 +1,22 @@ -# MPW is a software to crypt and manage your passwords -# Copyright (C) 2017 Adrien Waksberg <mpw@yae.im> # -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. +# Copyright:: 2013, Adrien Waksberg # -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at # -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. require 'yaml' diff --git a/lib/mpw/item.rb b/lib/mpw/item.rb index ec4c50e..9da60b1 100644 --- a/lib/mpw/item.rb +++ b/lib/mpw/item.rb @@ -1,19 +1,22 @@ -# MPW is a software to crypt and manage your passwords -# Copyright (C) 2017 Adrien Waksberg <mpw@yae.im> # -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. +# Copyright:: 2013, Adrien Waksberg # -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at # -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. require 'i18n' require 'uri' diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb index a67f09d..191caae 100644 --- a/lib/mpw/mpw.rb +++ b/lib/mpw/mpw.rb @@ -1,19 +1,22 @@ -# MPW is a software to crypt and manage your passwords -# Copyright (C) 2017 Adrien Waksberg <mpw@yae.im> # -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. +# Copyright:: 2013, Adrien Waksberg # -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at # -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. require 'rubygems/package' require 'gpgme' From be526c297f09b68f312a1653898c6e6653cdd08e Mon Sep 17 00:00:00 2001 From: Adrien Waksberg <git@yae.im> Date: Thu, 7 Dec 2017 14:15:51 +0100 Subject: [PATCH 531/531] fix: update LICENSE with good copyright --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index 8dada3e..0c5ea8e 100644 --- a/LICENSE +++ b/LICENSE @@ -186,7 +186,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright {yyyy} {name of copyright owner} + Copyright 2017 Adrien Waksberg Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.