From 7c72b2d90f7322bae290b71e91fb010743269a70 Mon Sep 17 00:00:00 2001 From: Adrien Waksberg Date: Mon, 27 Mar 2017 22:18:17 +0200 Subject: [PATCH] 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 -# +# # 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 -# +# # 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 -# +# # 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 -# +# # 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 -# +# # 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 -# +# # 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 -# +# # 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 -# +# # 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 -# +# # 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 -# +# # 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 -# +# # 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 -# +# # 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 -# +# # 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 << '' + "\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 << "\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 << '' + "\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 << "\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 -# +# # 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 -# +# # 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\/(?.+)\.pub$/ - key = Regexp.last_match('key') + when /^wallet\/keys\/(?.+)\.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\/(?[a-zA-Z0-9]+)\.gpg$/ - @passwords[Regexp.last_match('id')] = f.read + when /^wallet\/passwords\/(?[a-zA-Z0-9]+)\.gpg$/ + @passwords[Regexp.last_match('id')] = f.read - when /^wallet\/otp_keys\/(?[a-zA-Z0-9]+)\.gpg$/ - @otp_keys[Regexp.last_match('id')] = f.read + when /^wallet\/otp_keys\/(?[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 - 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 + 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'