mirror of
https://github.com/nishiki/manage-password.git
synced 2025-02-17 08:30:04 +00:00
merge to server branch
This commit is contained in:
commit
a8b4ca29c9
10 changed files with 863 additions and 208 deletions
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
|||
1.0.0 - stable
|
||||
1.1.0 - dev
|
||||
|
|
30
i18n/en.yml
30
i18n/en.yml
|
@ -1,8 +1,6 @@
|
|||
---
|
||||
en:
|
||||
error:
|
||||
add:
|
||||
name_empty: "You must define a name!"
|
||||
config:
|
||||
write: "Can't write the config file!"
|
||||
check: "Checkconfig failed!"
|
||||
|
@ -18,7 +16,12 @@ en:
|
|||
bad_format: "Can't import, the file is badly formated!"
|
||||
read: "Can't import, unable to read %{file}!"
|
||||
update:
|
||||
id_no_exist: "Can't update the item, the item %{id} doesn't exist!"
|
||||
name_empty: "You must define a name!"
|
||||
sync:
|
||||
connection: "Connection fail!"
|
||||
no_data: "Nothing data!"
|
||||
not_authorized: "You haven't the access to remote file!"
|
||||
unknown: "An unknown error is occured!"
|
||||
cli:
|
||||
option:
|
||||
usage: "Usage"
|
||||
|
@ -101,6 +104,8 @@ en:
|
|||
port: "Port"
|
||||
protocol: "Protocol"
|
||||
server: "Server"
|
||||
sync:
|
||||
not_connect: "The server connection fail!"
|
||||
ssh:
|
||||
option:
|
||||
usage: "Usage"
|
||||
|
@ -111,6 +116,25 @@ en:
|
|||
display:
|
||||
connect: "Connection to:"
|
||||
nothing: "Nothing result!"
|
||||
server:
|
||||
option:
|
||||
usage: "Usage"
|
||||
config: "Specifie the configuration file"
|
||||
checkconfig: "Check the configuration"
|
||||
setup: "Setup a new configuration file"
|
||||
help: "Show this message help"
|
||||
checkconfig:
|
||||
fail: "Checkconfig failed:!"
|
||||
empty: "ERROR: an importe option is missing!"
|
||||
datadir: "ERROR: le data directory doesn't exist!"
|
||||
form:
|
||||
setup:
|
||||
title: "Serveur configuration"
|
||||
host: "IP listen: "
|
||||
port: "Port listen: "
|
||||
data_dir: "Data directory: "
|
||||
timeout: "Timeout to second: "
|
||||
not_valid: "ERROR: Impossible to write the configuration file!"
|
||||
formats:
|
||||
default: ! '%Y-%m-%d'
|
||||
long: ! '%B %d, %Y'
|
||||
|
|
30
i18n/fr.yml
30
i18n/fr.yml
|
@ -1,8 +1,6 @@
|
|||
---
|
||||
fr:
|
||||
error:
|
||||
add:
|
||||
name_empty: "Vous devez définir un nom!"
|
||||
config:
|
||||
write: "Impossible d'écrire le fichier de configuration!"
|
||||
check: "Le fichier de configuration est invalide!"
|
||||
|
@ -18,7 +16,12 @@ fr:
|
|||
bad_format: "Impossible d'importer le fichier car son format est incorrect!"
|
||||
read: "Impossible d'importer le fichier %{file}, car il n'est pas lisible!"
|
||||
update:
|
||||
id_no_exist: "Impossible de mettre à jour l'élément %{id}, car il n'existe pas!"
|
||||
name_empty: "Vous devez définir un nom!"
|
||||
sync:
|
||||
connection: "La connexion n'a pu être établie"
|
||||
no_data: "Aucune data!"
|
||||
not_authorized: "Vous n'avez pas les autorisations d'accès au fichier distant!"
|
||||
unknown: "Une erreur inconnue est survenue!"
|
||||
cli:
|
||||
option:
|
||||
usage: "Utilisation"
|
||||
|
@ -101,6 +104,8 @@ fr:
|
|||
port: "Port"
|
||||
protocol: "Protocol"
|
||||
server: "Serveur"
|
||||
sync:
|
||||
not_connect: "La connexion au serveur n'a pu être établie!"
|
||||
ssh:
|
||||
option:
|
||||
usage: "Utilisation"
|
||||
|
@ -111,6 +116,25 @@ fr:
|
|||
display:
|
||||
connect: "Connexion à:"
|
||||
nothing: "Aucun résultat!"
|
||||
server:
|
||||
option:
|
||||
usage: "Utilisation"
|
||||
config: "Spécifie le fichier de configuration"
|
||||
checkconfig: "Vérifie le fichier de configuration"
|
||||
setup: "Permet de générer un nouveau fichier de configuration"
|
||||
help: "Affiche ce message d'aide"
|
||||
checkconfig:
|
||||
fail: "Le fichier de configuration est invalide!"
|
||||
empty: "ERREUR: Une option importante est manquante!"
|
||||
datadir: "ERREUR: Le répertoire des données n'existe pas!"
|
||||
form:
|
||||
setup:
|
||||
title: "Configuration du serveur"
|
||||
host: "IP d'écoute: "
|
||||
port: "Port d'écoute: "
|
||||
data_dir: "Répertoire des données: "
|
||||
timeout: "Timeout en seconde: "
|
||||
not_valid: "ERREUR: Impossible d'écire le fichier de configuration!"
|
||||
formats:
|
||||
default: ! '%Y-%m-%d'
|
||||
long: ! '%B %d, %Y'
|
||||
|
|
103
lib/Cli.rb
103
lib/Cli.rb
|
@ -8,24 +8,47 @@ require 'highline/import'
|
|||
require 'pathname'
|
||||
require 'readline'
|
||||
require 'i18n'
|
||||
require 'yaml'
|
||||
|
||||
require "#{APP_ROOT}/lib/MPW.rb"
|
||||
require "#{APP_ROOT}/lib/MPWConfig.rb"
|
||||
require "#{APP_ROOT}/lib/Sync.rb"
|
||||
|
||||
class Cli
|
||||
|
||||
# Constructor
|
||||
# @args: lang -> the operating system language
|
||||
# config_file -> a specify config file
|
||||
def initialize(lang, config_file=nil)
|
||||
@m = MPW.new(config_file)
|
||||
|
||||
if not @m.checkconfig()
|
||||
self.setup(lang)
|
||||
def initialize(lang, config)
|
||||
@config = config
|
||||
|
||||
@mpw = MPW.new(@config.file_gpg, @config.key)
|
||||
if not decrypt()
|
||||
puts "#{I18n.t('cli.display.error')}: #{@mpw.error_msg}"
|
||||
exit 2
|
||||
end
|
||||
|
||||
if not self.decrypt()
|
||||
puts "#{I18n.t('cli.display.error')}: #{@m.error_msg}"
|
||||
exit 2
|
||||
@sync = Sync.new()
|
||||
if @config.sync_host.nil? || @config.sync_port.nil?
|
||||
@sync.disable()
|
||||
elsif !@sync.connect(@config.sync_host, @config.sync_port, @config.key, @config.sync_pwd, @config.sync_suffix)
|
||||
puts "#{I18n.t('cli.sync.not_connect')}:\n#{@sync.error_msg}"
|
||||
end
|
||||
end
|
||||
|
||||
# Destructor
|
||||
def finalize()
|
||||
@sync.close()
|
||||
end
|
||||
|
||||
# Sync the data with the server
|
||||
def sync()
|
||||
begin
|
||||
@mpw.sync(@sync.get(@passwd), @config.last_update)
|
||||
@sync.update(File.open(@config.file_gpg).read)
|
||||
@config.setLastUpdate()
|
||||
rescue Exception => e
|
||||
puts "#{I18n.t('cli.sync.error')}:\n#{e}"
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -44,35 +67,35 @@ class Cli
|
|||
end
|
||||
I18n.locale = language.to_sym
|
||||
|
||||
if @m.setup(key, language, file_gpg, timeout_pwd)
|
||||
if @config.setup(key, language, file_gpg, timeout_pwd)
|
||||
puts I18n.t('cli.form.setup.valid')
|
||||
else
|
||||
puts "#{I18n.t('cli.display.error')}: #{@m.error_msg}"
|
||||
puts "#{I18n.t('cli.display.error')}: #{@config.error_msg}"
|
||||
end
|
||||
|
||||
if not @m.checkconfig()
|
||||
puts "#{I18n.t('cli.display.error')}: #{@m.error_msg}"
|
||||
if not @config.checkconfig()
|
||||
puts "#{I18n.t('cli.display.error')}: #{@config.error_msg}"
|
||||
end
|
||||
end
|
||||
|
||||
# Request the GPG password and decrypt the file
|
||||
def decrypt()
|
||||
@passwd = ask(I18n.t('cli.display.gpg_password')) {|q| q.echo = false}
|
||||
return @m.decrypt(@passwd)
|
||||
return @mpw.decrypt(@passwd)
|
||||
end
|
||||
|
||||
# Display the query's result
|
||||
# @args: search -> the string to search
|
||||
# protocol -> search from a particular protocol
|
||||
def display(search, protocol=nil, group=nil, format=nil)
|
||||
result = @m.search(search, group, protocol)
|
||||
result = @mpw.search(search, group, protocol)
|
||||
|
||||
if not result.empty?
|
||||
result.each do |r|
|
||||
if format.nil? || !format
|
||||
self.displayFormat(r)
|
||||
displayFormat(r)
|
||||
else
|
||||
self.displayFormatAlt(r)
|
||||
displayFormatAlt(r)
|
||||
end
|
||||
end
|
||||
else
|
||||
|
@ -125,21 +148,21 @@ class Cli
|
|||
port = ask(I18n.t('cli.form.add.port')).to_s
|
||||
comment = ask(I18n.t('cli.form.add.comment')).to_s
|
||||
|
||||
if @m.add(name, group, server, protocol, login, passwd, port, comment)
|
||||
if @m.encrypt()
|
||||
if @mpw.update(name, group, server, protocol, login, passwd, port, comment)
|
||||
if @mpw.encrypt()
|
||||
puts I18n.t('cli.form.add.valid')
|
||||
else
|
||||
puts "#{I18n.t('cli.display.error')}: #{@m.error_msg}"
|
||||
puts "#{I18n.t('cli.display.error')}: #{@mpw.error_msg}"
|
||||
end
|
||||
else
|
||||
puts "#{I18n.t('cli.display.error')}: #{@m.error_msg}"
|
||||
puts "#{I18n.t('cli.display.error')}: #{@mpw.error_msg}"
|
||||
end
|
||||
end
|
||||
|
||||
# Update an item
|
||||
# @args: id -> the item's id
|
||||
def update(id)
|
||||
row = @m.searchById(id)
|
||||
row = @mpw.searchById(id)
|
||||
|
||||
if not row.empty?
|
||||
puts I18n.t('cli.form.update.title')
|
||||
|
@ -153,14 +176,14 @@ class Cli
|
|||
port = ask(I18n.t('cli.form.update.port' , :port => row[MPW::PORT])).to_s
|
||||
comment = ask(I18n.t('cli.form.update.comment' , :comment => row[MPW::COMMENT])).to_s
|
||||
|
||||
if @m.update(id, name, group, server, protocol, login, passwd, port, comment)
|
||||
if @m.encrypt()
|
||||
if @mpw.update(name, group, server, protocol, login, passwd, port, comment, id)
|
||||
if @mpw.encrypt()
|
||||
puts I18n.t('cli.form.update.valid')
|
||||
else
|
||||
puts "#{I18n.t('cli.display.error')}: #{@m.error_msg}"
|
||||
puts "#{I18n.t('cli.display.error')}: #{@mpw.error_msg}"
|
||||
end
|
||||
else
|
||||
puts "#{I18n.t('cli.display.error')}: #{@m.error_msg}"
|
||||
puts "#{I18n.t('cli.display.error')}: #{@mpw.error_msg}"
|
||||
end
|
||||
else
|
||||
puts I18n.t('cli.display.nothing')
|
||||
|
@ -172,10 +195,10 @@ class Cli
|
|||
# force -> no resquest a validation
|
||||
def remove(id, force=false)
|
||||
if not force
|
||||
result = @m.searchById(id)
|
||||
result = @mpw.searchById(id)
|
||||
|
||||
if result.length > 0
|
||||
self.displayFormat(result)
|
||||
displayFormat(result)
|
||||
|
||||
confirm = ask("#{I18n.t('cli.form.delete.ask', :id => id)} (y/N) ").to_s
|
||||
if confirm =~ /^(y|yes|YES|Yes|Y)$/
|
||||
|
@ -187,11 +210,11 @@ class Cli
|
|||
end
|
||||
|
||||
if force
|
||||
if @m.remove(id)
|
||||
if @m.encrypt()
|
||||
if @mpw.remove(id)
|
||||
if @mpw.encrypt()
|
||||
puts I18n.t('cli.form.delete.valid', :id => id)
|
||||
else
|
||||
puts "#{I18n.t('cli.display.error')}: #{@m.error_msg}"
|
||||
puts "#{I18n.t('cli.display.error')}: #{@mpw.error_msg}"
|
||||
end
|
||||
else
|
||||
puts I18n.t('cli.form.delete.not_valid')
|
||||
|
@ -202,10 +225,10 @@ class Cli
|
|||
# Export the items in a CSV file
|
||||
# @args: file -> the destination file
|
||||
def export(file)
|
||||
if @m.export(file)
|
||||
if @mpw.export(file)
|
||||
puts "The export in #{file} is succesfull!"
|
||||
else
|
||||
puts "#{I18n.t('cli.display.error')}: #{@m.error_msg}"
|
||||
puts "#{I18n.t('cli.display.error')}: #{@mpw.error_msg}"
|
||||
end
|
||||
|
||||
end
|
||||
|
@ -214,12 +237,12 @@ class Cli
|
|||
# @args: file -> the import file
|
||||
# force -> no resquest a validation
|
||||
def import(file, force=false)
|
||||
result = @m.importPreview(file)
|
||||
result = @mpw.importPreview(file)
|
||||
|
||||
if not force
|
||||
if result.is_a?(Array) && !result.empty?
|
||||
result.each do |r|
|
||||
self.displayFormat(r)
|
||||
displayFormat(r)
|
||||
end
|
||||
|
||||
confirm = ask("#{I18n.t('cli.form.import.ask', :file => file)} (y/N) ").to_s
|
||||
|
@ -232,10 +255,10 @@ class Cli
|
|||
end
|
||||
|
||||
if force
|
||||
if @m.import(file) && @m.encrypt()
|
||||
if @mpw.import(file) && @mpw.encrypt()
|
||||
puts I18n.t('cli.form.import.valid')
|
||||
else
|
||||
puts "#{I18n.t('cli.display.error')}: #{@m.error_msg}"
|
||||
puts "#{I18n.t('cli.display.error')}: #{@mpw.error_msg}"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -247,7 +270,7 @@ class Cli
|
|||
|
||||
while buf = Readline.readline('<mpw> ', true)
|
||||
|
||||
if @m.timeout_pwd < Time.now.to_i - last_access
|
||||
if @config.timeout_pwd < Time.now.to_i - last_access
|
||||
passwd_confirm = ask(I18n.t('cli.interactive.ask_password')) {|q| q.echo = false}
|
||||
|
||||
if @passwd.eql?(passwd_confirm)
|
||||
|
@ -265,17 +288,17 @@ class Cli
|
|||
case command[0]
|
||||
when 'display', 'show', 'd', 's'
|
||||
if !command[1].nil? && !command[1].empty?
|
||||
self.display(command[1], group, command[2])
|
||||
display(command[1], group, command[2])
|
||||
end
|
||||
when 'add', 'a'
|
||||
add()
|
||||
when 'update', 'u'
|
||||
if !command[1].nil? && !command[1].empty?
|
||||
self.update(command[1])
|
||||
update(command[1])
|
||||
end
|
||||
when 'remove', 'delete', 'r', 'd'
|
||||
if !command[1].nil? && !command[1].empty?
|
||||
self.remove(command[1])
|
||||
remove(command[1])
|
||||
end
|
||||
when 'group', 'g'
|
||||
if !command[1].nil? && !command[1].empty?
|
||||
|
|
265
lib/MPW.rb
265
lib/MPW.rb
|
@ -6,7 +6,6 @@
|
|||
require 'rubygems'
|
||||
require 'gpgme'
|
||||
require 'csv'
|
||||
require 'yaml'
|
||||
require 'i18n'
|
||||
|
||||
class MPW
|
||||
|
@ -20,80 +19,15 @@ class MPW
|
|||
PASSWORD = 6
|
||||
PORT = 7
|
||||
COMMENT = 8
|
||||
DATE = 9
|
||||
|
||||
attr_accessor :error_msg
|
||||
attr_accessor :timeout_pwd
|
||||
|
||||
|
||||
# Constructor
|
||||
# @args: file_config -> the specify config file
|
||||
def initialize(file_config=nil)
|
||||
@error_msg = nil
|
||||
@file_config = "#{Dir.home()}/.mpw.cfg"
|
||||
|
||||
if !file_config.nil? && !file_config.empty?
|
||||
@file_config = file_config
|
||||
end
|
||||
end
|
||||
|
||||
# Create a new config file
|
||||
# @args: key -> the gpg key to encrypt
|
||||
# lang -> the software language
|
||||
# file_gpg -> the file who is encrypted
|
||||
# timeout_pwd -> time to save the password
|
||||
# @rtrn: true if le config file is create
|
||||
def setup(key, lang, file_gpg, timeout_pwd)
|
||||
|
||||
if not key =~ /[a-zA-Z0-9.-_]+\@[a-zA-Z0-9]+\.[a-zA-Z]+/
|
||||
@error_msg = I18n.t('error.config.key_bad_format')
|
||||
return false
|
||||
end
|
||||
|
||||
if file_gpg.empty?
|
||||
file_gpg = "#{Dir.home()}/.mpw.gpg"
|
||||
end
|
||||
|
||||
timeout_pwd.empty? ? (timeout_pwd = 60) : (timeout_pwd = timeout_pwd.to_i)
|
||||
|
||||
config = {'config' => {'key' => key,
|
||||
'lang' => lang,
|
||||
'file_gpg' => file_gpg,
|
||||
'timeout_pwd' => timeout_pwd}}
|
||||
|
||||
begin
|
||||
File.open(@file_config, 'w') do |file|
|
||||
file << config.to_yaml
|
||||
end
|
||||
rescue Exception => e
|
||||
@error_msg = "#{I18n.t('error.config.write')}\n#{e}"
|
||||
return false
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
# Check the config file
|
||||
# @rtrn: true if the config file is correct
|
||||
def checkconfig()
|
||||
begin
|
||||
config = YAML::load_file(@file_config)
|
||||
@key = config['config']['key']
|
||||
@lang = config['config']['lang']
|
||||
@file_gpg = config['config']['file_gpg']
|
||||
@timeout_pwd = config['config']['timeout_pwd'].to_i
|
||||
|
||||
if @key.empty? || @file_gpg.empty?
|
||||
@error_msg = I18n.t('error.config.check')
|
||||
return false
|
||||
end
|
||||
|
||||
I18n.locale = @lang.to_sym
|
||||
|
||||
rescue Exception => e
|
||||
@error_msg = "#{I18n.t('error.config.check')}\n#{e}"
|
||||
return false
|
||||
end
|
||||
|
||||
return true
|
||||
def initialize(file_gpg, key=nil)
|
||||
@error_msg = nil
|
||||
@file_gpg = file_gpg
|
||||
@key = key
|
||||
end
|
||||
|
||||
# Decrypt a gpg file
|
||||
|
@ -107,10 +41,8 @@ class MPW
|
|||
crypto = GPGME::Crypto.new(:armor => true)
|
||||
data_decrypt = crypto.decrypt(IO.read(@file_gpg), :password => passwd).read
|
||||
|
||||
id = 0
|
||||
data_decrypt.lines do |line|
|
||||
@data[id] = line.parse_csv.unshift(id)
|
||||
id += 1;
|
||||
@data.push(line.parse_csv)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -130,7 +62,7 @@ class MPW
|
|||
|
||||
data_to_encrypt = ''
|
||||
@data.each do |row|
|
||||
data_to_encrypt << row.drop(1).to_csv
|
||||
data_to_encrypt << row.to_csv
|
||||
end
|
||||
|
||||
crypto.encrypt(data_to_encrypt, :recipients => @key, :output => file_gpg)
|
||||
|
@ -147,7 +79,7 @@ class MPW
|
|||
# @args: search -> the string to search
|
||||
# protocol -> the connection protocol (ssh, web, other)
|
||||
# @rtrn: a list with the resultat of the search
|
||||
def search(search, group=nil, protocol=nil)
|
||||
def search(search='', group=nil, protocol=nil)
|
||||
result = Array.new()
|
||||
|
||||
if !search.nil?
|
||||
|
@ -174,57 +106,15 @@ class MPW
|
|||
# @args: id -> the id item
|
||||
# @rtrn: a row with the resultat of the search
|
||||
def searchById(id)
|
||||
if not @data[id.to_i].nil?
|
||||
return @data[id.to_i]
|
||||
else
|
||||
return Array.new
|
||||
@data.each do |row|
|
||||
if row[ID] == id
|
||||
return row
|
||||
end
|
||||
end
|
||||
|
||||
return Array.new()
|
||||
end
|
||||
|
||||
# Add a new item
|
||||
# @args: name -> the item name
|
||||
# group -> the item group
|
||||
# server -> the ip or server
|
||||
# protocol -> the protocol
|
||||
# login -> the login
|
||||
# passwd -> the password
|
||||
# port -> the port
|
||||
# comment -> a comment
|
||||
# @rtrn: true if it works
|
||||
def add(name, group=nil, server=nil, protocol=nil, login=nil, passwd=nil, port=nil, comment=nil)
|
||||
row = Array.new()
|
||||
|
||||
if name.nil? || name.empty?
|
||||
@error_msg = I18n.t('error.add.name_empty')
|
||||
return false
|
||||
end
|
||||
|
||||
if port.to_i <= 0
|
||||
port = nil
|
||||
end
|
||||
|
||||
if not @data.last.nil?
|
||||
id = @data.last
|
||||
id = id[ID].to_i + 1
|
||||
else
|
||||
id = 0
|
||||
end
|
||||
|
||||
row[ID] = id
|
||||
row[PORT] = port
|
||||
row[NAME] = name.force_encoding('ASCII-8BIT')
|
||||
group.nil? || group.empty? ? (row[GROUP] = nil) : (row[GROUP] = group.force_encoding('ASCII-8BIT'))
|
||||
server.nil? || server.empty? ? (row[SERVER] = nil) : (row[SERVER] = server.force_encoding('ASCII-8BIT'))
|
||||
protocol.nil? || protocol.empty? ? (row[PROTOCOL] = nil) : (row[PROTOCOL] = protocol.force_encoding('ASCII-8BIT'))
|
||||
login.nil? || login.empty? ? (row[LOGIN] = nil) : (row[LOGIN] = login.force_encoding('ASCII-8BIT'))
|
||||
passwd.nil? || passwd.empty? ? (row[PASSWORD] = nil) : (row[PASSWORD] = passwd.force_encoding('ASCII-8BIT'))
|
||||
comment.nil? || comment.empty? ? (row[COMMENT] = nil) : (row[COMMENT] = comment.force_encoding('ASCII-8BIT'))
|
||||
|
||||
@data[id] = row
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
# Update an item
|
||||
# @args: id -> the item's identifiant
|
||||
# name -> the item name
|
||||
|
@ -236,46 +126,66 @@ class MPW
|
|||
# port -> the port
|
||||
# comment -> a comment
|
||||
# @rtrn: true if the item has been updated
|
||||
def update(id, name=nil, group=nil, server=nil, protocol=nil, login=nil, passwd=nil, port=nil, comment=nil)
|
||||
id = id.to_i
|
||||
def update(name, group, server, protocol, login, passwd, port, comment, id=nil)
|
||||
row = Array.new()
|
||||
update = false
|
||||
|
||||
if not @data[id].nil?
|
||||
|
||||
if port.to_i <= 0
|
||||
port = nil
|
||||
i = 0
|
||||
@data.each do |r|
|
||||
if r[ID] == id
|
||||
row = r
|
||||
update = true
|
||||
break
|
||||
end
|
||||
i += 1
|
||||
end
|
||||
|
||||
row = @data[id]
|
||||
row_update = Array.new()
|
||||
if port.to_i <= 0
|
||||
port = nil
|
||||
end
|
||||
|
||||
name.nil? || name.empty? ? (row_update[NAME] = row[NAME]) : (row_update[NAME] = name)
|
||||
group.nil? || group.empty? ? (row_update[GROUP] = row[GROUP]) : (row_update[GROUP] = group)
|
||||
server.nil? || server.empty? ? (row_update[SERVER] = row[SERVER]) : (row_update[SERVER] = server)
|
||||
protocol.nil? || protocol.empty? ? (row_update[PROTOCOL] = row[PROTOCOL]) : (row_update[PROTOCOL] = protocol)
|
||||
login.nil? || login.empty? ? (row_update[LOGIN] = row[LOGIN]) : (row_update[LOGIN] = login)
|
||||
passwd.nil? || passwd.empty? ? (row_update[PASSWORD] = row[PASSWORD]) : (row_update[PASSWORD] = passwd)
|
||||
port.nil? || port.empty? ? (row_update[PORT] = row[PORT]) : (row_update[PORT] = port)
|
||||
comment.nil? || comment.empty? ? (row_update[COMMENT] = row[COMMENT]) : (row_update[COMMENT] = comment)
|
||||
|
||||
@data[id] = row_update
|
||||
row_update = Array.new()
|
||||
row_update[DATE] = Time.now.to_i
|
||||
|
||||
return true
|
||||
else
|
||||
@error_msg = I18n.t('error.update.id_no_exist', :id => id)
|
||||
id.nil? || id.empty? ? (row_update[ID] = MPW.generatePassword(16)) : (row_update[ID] = row[ID])
|
||||
name.nil? || name.empty? ? (row_update[NAME] = row[NAME]) : (row_update[NAME] = name)
|
||||
group.nil? || group.empty? ? (row_update[GROUP] = row[GROUP]) : (row_update[GROUP] = group)
|
||||
server.nil? || server.empty? ? (row_update[SERVER] = row[SERVER]) : (row_update[SERVER] = server)
|
||||
protocol.nil? || protocol.empty? ? (row_update[PROTOCOL] = row[PROTOCOL]) : (row_update[PROTOCOL] = protocol)
|
||||
login.nil? || login.empty? ? (row_update[LOGIN] = row[LOGIN]) : (row_update[LOGIN] = login)
|
||||
passwd.nil? || passwd.empty? ? (row_update[PASSWORD] = row[PASSWORD]) : (row_update[PASSWORD] = passwd)
|
||||
port.nil? || port.empty? ? (row_update[PORT] = row[PORT]) : (row_update[PORT] = port)
|
||||
comment.nil? || comment.empty? ? (row_update[COMMENT] = row[COMMENT]) : (row_update[COMMENT] = comment)
|
||||
|
||||
if row_update[NAME].nil? || row_update[NAME].empty?
|
||||
@error_msg = I18n.t('error.update.name_empty')
|
||||
return false
|
||||
end
|
||||
|
||||
if update
|
||||
@data[i] = row_update
|
||||
else
|
||||
@data.push(row_update)
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
# Remove an item
|
||||
# @args: id -> the item's identifiant
|
||||
# @rtrn: true if the item has been deleted
|
||||
def remove(id)
|
||||
if not @data.delete_at(id.to_i).nil?
|
||||
return true
|
||||
else
|
||||
@error_msg = I18n.t('error.delete.id_no_exist', :id => id)
|
||||
return false
|
||||
i = 0
|
||||
@data.each do |row|
|
||||
if row[ID] == id
|
||||
@data.delete_at(i)
|
||||
return true
|
||||
end
|
||||
i += 1
|
||||
end
|
||||
|
||||
@error_msg = I18n.t('error.delete.id_no_exist', :id => id)
|
||||
return false
|
||||
end
|
||||
|
||||
# Export to csv
|
||||
|
@ -285,7 +195,7 @@ class MPW
|
|||
begin
|
||||
File.open(file, 'w+') do |file|
|
||||
@data.each do |row|
|
||||
row.delete_at(ID)
|
||||
row.delete_at(ID).delete_at(DATE)
|
||||
file << row.to_csv
|
||||
end
|
||||
end
|
||||
|
@ -309,7 +219,7 @@ class MPW
|
|||
return false
|
||||
else
|
||||
row = line.parse_csv.unshift(0)
|
||||
if not add(row[NAME], row[GROUP], row[SERVER], row[PROTOCOL], row[LOGIN], row[PASSWORD], row[PORT], row[COMMENT])
|
||||
if not update(row[NAME], row[GROUP], row[SERVER], row[PROTOCOL], row[LOGIN], row[PASSWORD], row[PORT], row[COMMENT])
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
@ -322,7 +232,7 @@ class MPW
|
|||
end
|
||||
end
|
||||
|
||||
# Return
|
||||
# Return a preview import
|
||||
# @args: file -> path to file import
|
||||
# @rtrn: an array with the items to import, if there is an error return false
|
||||
def importPreview(file)
|
||||
|
@ -349,6 +259,50 @@ class MPW
|
|||
end
|
||||
end
|
||||
|
||||
# Sync remote data and local data
|
||||
# @args: data_remote -> array with the data remote
|
||||
# last_update -> last update
|
||||
# @rtrn: false if data_remote is nil
|
||||
def sync(data_remote, last_update)
|
||||
if !data_remote.instance_of?(Array)
|
||||
return false
|
||||
end
|
||||
|
||||
@data.each do |l|
|
||||
j = 0
|
||||
update = false
|
||||
|
||||
# Update item
|
||||
data_remote.each do |r|
|
||||
if l[ID] == r[ID]
|
||||
if l[DATE].to_i < r[DATE].to_i
|
||||
update(r[NAME], r[GROUP], r[SERVER], r[PROTOCOL], r[LOGIN], r[PASSWORD], r[PORT], r[COMMENT], l[ID])
|
||||
end
|
||||
update = true
|
||||
data_remote.delete_at(j)
|
||||
break
|
||||
end
|
||||
j += 1
|
||||
end
|
||||
|
||||
# Delete an old item
|
||||
if !update && l[DATE].to_i < last_update
|
||||
remove(l[ID])
|
||||
end
|
||||
end
|
||||
|
||||
# Add item
|
||||
data_remote.each do |r|
|
||||
if r[DATE].to_i > last_update
|
||||
update(r[NAME], r[GROUP], r[SERVER], r[PROTOCOL], r[LOGIN], r[PASSWORD], r[PORT], r[COMMENT], r[ID])
|
||||
end
|
||||
end
|
||||
|
||||
encrypt()
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
# Generate a random password
|
||||
# @args: length -> the length password
|
||||
# @rtrn: a random string
|
||||
|
@ -367,7 +321,6 @@ class MPW
|
|||
result << ([*('A'..'Z'),*('a'..'z'),*('0'..'9')]).sample(length).join
|
||||
|
||||
return result
|
||||
#return ([*('A'..'Z'),*('a'..'z'),*('0'..'9')]-%w(0 1 I O l i o)).sample(length).join
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
|
130
lib/MPWConfig.rb
Normal file
130
lib/MPWConfig.rb
Normal file
|
@ -0,0 +1,130 @@
|
|||
#!/usr/bin/ruby
|
||||
# author: nishiki
|
||||
# mail: nishiki@yaegashi.fr
|
||||
# info: a simple script who manage your passwords
|
||||
|
||||
require 'rubygems'
|
||||
require 'yaml'
|
||||
require 'i18n'
|
||||
|
||||
class MPWConfig
|
||||
|
||||
attr_accessor :error_msg
|
||||
|
||||
attr_accessor :key
|
||||
attr_accessor :lang
|
||||
attr_accessor :file_gpg
|
||||
attr_accessor :timeout_pwd
|
||||
attr_accessor :last_update
|
||||
attr_accessor :sync_host
|
||||
attr_accessor :sync_port
|
||||
attr_accessor :sync_pwd
|
||||
attr_accessor :sync_suffix
|
||||
attr_accessor :last_update
|
||||
|
||||
# Constructor
|
||||
# @args: file_config -> the specify config file
|
||||
def initialize(file_config=nil)
|
||||
@error_msg = nil
|
||||
@file_config = "#{Dir.home()}/.mpw.cfg"
|
||||
|
||||
if !file_config.nil? && !file_config.empty?
|
||||
@file_config = file_config
|
||||
end
|
||||
end
|
||||
|
||||
# Create a new config file
|
||||
# @args: key -> the gpg key to encrypt
|
||||
# lang -> the software language
|
||||
# file_gpg -> the file who is encrypted
|
||||
# timeout_pwd -> time to save the password
|
||||
# @rtrn: true if le config file is create
|
||||
def setup(key, lang, file_gpg, timeout_pwd)
|
||||
|
||||
if not key =~ /[a-zA-Z0-9.-_]+\@[a-zA-Z0-9]+\.[a-zA-Z]+/
|
||||
@error_msg = I18n.t('error.config.key_bad_format')
|
||||
return false
|
||||
end
|
||||
|
||||
if file_gpg.empty?
|
||||
file_gpg = "#{Dir.home()}/.mpw.gpg"
|
||||
end
|
||||
|
||||
timeout_pwd.empty? ? (timeout_pwd = 60) : (timeout_pwd = timeout_pwd.to_i)
|
||||
|
||||
config = {'config' => {'key' => key,
|
||||
'lang' => lang,
|
||||
'file_gpg' => file_gpg,
|
||||
'timeout_pwd' => timeout_pwd,
|
||||
'sync_host' => host,
|
||||
'sync_port' => port,
|
||||
'sync_pwd' => password,
|
||||
'sync_suffix' => suffix,
|
||||
'last_update' => 0 }}
|
||||
|
||||
begin
|
||||
File.open(@file_config, 'w') do |file|
|
||||
file << config.to_yaml
|
||||
end
|
||||
rescue Exception => e
|
||||
@error_msg = "#{I18n.t('error.config.write')}\n#{e}"
|
||||
return false
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
# Check the config file
|
||||
# @rtrn: true if the config file is correct
|
||||
def checkconfig()
|
||||
begin
|
||||
config = YAML::load_file(@file_config)
|
||||
@key = config['config']['key']
|
||||
@lang = config['config']['lang']
|
||||
@file_gpg = config['config']['file_gpg']
|
||||
@timeout_pwd = config['config']['timeout_pwd'].to_i
|
||||
@sync_host = config['config']['sync_host']
|
||||
@sync_port = config['config']['sync_port']
|
||||
@sync_pwd = config['config']['sync_pwd']
|
||||
@sync_suffix = config['config']['sync_suffix']
|
||||
@last_update = config['config']['last_update'].to_i
|
||||
|
||||
if @key.empty? || @file_gpg.empty?
|
||||
@error_msg = I18n.t('error.config.check')
|
||||
return false
|
||||
end
|
||||
|
||||
I18n.locale = @lang.to_sym
|
||||
|
||||
rescue Exception => e
|
||||
@error_msg = "#{I18n.t('error.config.check')}\n#{e}"
|
||||
return false
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
def setLastUpdate()
|
||||
config = {'config' => {'key' => @key,
|
||||
'lang' => @lang,
|
||||
'file_gpg' => @file_gpg,
|
||||
'timeout_pwd' => @timeout_pwd,
|
||||
'sync_host' => @sync_host,
|
||||
'sync_port' => @sync_port,
|
||||
'sync_pwd' => @sync_pwd,
|
||||
'sync_suffix' => @sync_suffix,
|
||||
'last_update' => Time.now.to_i }}
|
||||
|
||||
begin
|
||||
File.open(@file_config, 'w') do |file|
|
||||
file << config.to_yaml
|
||||
end
|
||||
rescue Exception => e
|
||||
@error_msg = "#{I18n.t('error.config.write')}\n#{e}"
|
||||
return false
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
end
|
295
lib/Server.rb
Normal file
295
lib/Server.rb
Normal file
|
@ -0,0 +1,295 @@
|
|||
#!/usr/bin/ruby
|
||||
|
||||
require 'socket'
|
||||
require 'json'
|
||||
require 'highline/import'
|
||||
require 'digest'
|
||||
|
||||
require "#{APP_ROOT}/lib/MPW.rb"
|
||||
|
||||
class Server
|
||||
|
||||
attr_accessor :error_msg
|
||||
|
||||
# Constructor
|
||||
def initialize()
|
||||
YAML::ENGINE.yamler='syck'
|
||||
end
|
||||
|
||||
# Start the server
|
||||
def start()
|
||||
server = TCPServer.open(@host, @port)
|
||||
loop do
|
||||
Thread.start(server.accept) do |client|
|
||||
while true do
|
||||
msg = getClientMessage(client)
|
||||
|
||||
if !msg
|
||||
next
|
||||
end
|
||||
|
||||
if msg['gpg_key'].nil? || msg['gpg_key'].empty? || msg['password'].nil? || msg['password'].empty?
|
||||
closeConnection(client)
|
||||
next
|
||||
end
|
||||
|
||||
case msg['action']
|
||||
when 'get'
|
||||
client.puts getFile(msg)
|
||||
when 'update'
|
||||
client.puts updateFile(msg)
|
||||
when 'delete'
|
||||
client.puts deleteFile(msg)
|
||||
when 'close'
|
||||
closeConnection(client)
|
||||
else
|
||||
client.puts 'Unknown command'
|
||||
closeConnection(client)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Get a gpg file
|
||||
# @args: msg -> message puts by the client
|
||||
# @rtrn: json message
|
||||
def getFile(msg)
|
||||
gpg_key = msg['gpg_key'].sub('@', '_')
|
||||
|
||||
if msg['suffix'].nil? || msg['suffix'].empty?
|
||||
file_gpg = "#{@data_dir}/#{gpg_key}.yml"
|
||||
else
|
||||
file_gpg = "#{@data_dir}/#{gpg_key}-#{msg['suffix']}.yml"
|
||||
end
|
||||
|
||||
if File.exist?(file_gpg)
|
||||
gpg_data = YAML::load_file(file_gpg)
|
||||
salt = gpg_data['gpg']['salt']
|
||||
hash = gpg_data['gpg']['hash']
|
||||
data = gpg_data['gpg']['data']
|
||||
|
||||
if isAuthorized?(msg['password'], salt, hash)
|
||||
send_msg = {:action => 'get',
|
||||
:gpg_key => msg['gpg_key'],
|
||||
:msg => 'done',
|
||||
:data => data}
|
||||
else
|
||||
send_msg = {:action => 'get',
|
||||
:gpg_key => msg['gpg_key'],
|
||||
:msg => 'fail',
|
||||
:error => 'not_authorized'}
|
||||
end
|
||||
else
|
||||
send_msg = {:action => 'get',
|
||||
:gpg_key => msg['gpg_key'],
|
||||
:data => '',
|
||||
:msg => 'fail',
|
||||
:error => 'file_not_exist'}
|
||||
end
|
||||
|
||||
return send_msg.to_json
|
||||
end
|
||||
|
||||
# Update a file
|
||||
# @args: msg -> message puts by the client
|
||||
# @rtrn: json message
|
||||
def updateFile(msg)
|
||||
gpg_key = msg['gpg_key'].sub('@', '_')
|
||||
data = msg['data']
|
||||
|
||||
if data.nil? || data.empty?
|
||||
send_msg = {:action => 'update',
|
||||
:gpg_key => msg['gpg_key'],
|
||||
:msg => 'fail',
|
||||
:error => 'no_data'}
|
||||
|
||||
return send_msg.to_json
|
||||
end
|
||||
|
||||
if msg['suffix'].nil? || msg['suffix'].empty?
|
||||
file_gpg = "#{@data_dir}/#{gpg_key}.yml"
|
||||
else
|
||||
file_gpg = "#{@data_dir}/#{gpg_key}-#{msg['suffix']}.yml"
|
||||
end
|
||||
|
||||
if File.exist?(file_gpg)
|
||||
gpg_data = YAML::load_file(file_gpg)
|
||||
salt = gpg_data['gpg']['salt']
|
||||
hash = gpg_data['gpg']['hash']
|
||||
|
||||
else
|
||||
salt = MPW.generatePassword(4)
|
||||
hash = Digest::SHA256.hexdigest(salt + msg['password'])
|
||||
end
|
||||
|
||||
if isAuthorized?(msg['password'], salt, hash)
|
||||
begin
|
||||
config = {'gpg' => {'salt' => salt,
|
||||
'hash' => hash,
|
||||
'data' => data}}
|
||||
|
||||
File.open(file_gpg, 'w+') do |file|
|
||||
file << config.to_yaml
|
||||
end
|
||||
|
||||
send_msg = {:action => 'update',
|
||||
:gpg_key => msg['gpg_key'],
|
||||
:msg => 'done'}
|
||||
rescue Exception => e
|
||||
send_msg = {:action => 'update',
|
||||
:gpg_key => msg['gpg_key'],
|
||||
:msg => 'fail',
|
||||
:error => 'server_error'}
|
||||
end
|
||||
else
|
||||
send_msg = {:action => 'update',
|
||||
:gpg_key => msg['gpg_key'],
|
||||
:msg => 'fail',
|
||||
:error => 'not_autorized'}
|
||||
end
|
||||
|
||||
return send_msg.to_json
|
||||
end
|
||||
|
||||
# Remove a gpg file
|
||||
# @args: msg -> message puts by the client
|
||||
# @rtrn: json message
|
||||
def deleteFile(msg)
|
||||
gpg_key = msg['gpg_key'].sub('@', '_')
|
||||
|
||||
if msg['suffix'].nil? || msg['suffix'].empty?
|
||||
file_gpg = "#{@data_dir}/#{gpg_key}.yml"
|
||||
else
|
||||
file_gpg = "#{@data_dir}/#{gpg_key}-#{msg['suffix']}.yml"
|
||||
end
|
||||
|
||||
if !File.exist?(file_gpg)
|
||||
send_msg = {:action => 'delete',
|
||||
:gpg_key => msg['gpg_key'],
|
||||
:msg => 'delete_fail',
|
||||
:error => 'file_not_exist'}
|
||||
|
||||
return send_msg.to_json
|
||||
end
|
||||
|
||||
gpg_data = YAML::load_file(file_gpg)
|
||||
salt = gpg_data['gpg']['salt']
|
||||
hash = gpg_data['gpg']['hash']
|
||||
|
||||
if isAuthorized?(msg['password'], salt, hash)
|
||||
begin
|
||||
File.unlink(file_gpg)
|
||||
|
||||
send_msg = {:action => 'delete',
|
||||
:gpg_key => msg['gpg_key'],
|
||||
:msg => 'delete_done'}
|
||||
rescue Exception => e
|
||||
send_msg = {:action => 'delete',
|
||||
:gpg_key => msg['gpg_key'],
|
||||
:msg => 'delete_fail',
|
||||
:error => e}
|
||||
end
|
||||
else
|
||||
send_msg = {:action => 'delete',
|
||||
:gpg_key => msg['gpg_key'],
|
||||
:msg => 'delete_fail',
|
||||
:error => 'not_autorized'}
|
||||
end
|
||||
|
||||
return send_msg.to_json
|
||||
end
|
||||
|
||||
# Check is the hash equal the password with the salt
|
||||
# @args: password -> the user password
|
||||
# salt -> the salt
|
||||
# hash -> the hash of the password with the salt
|
||||
# @rtrn: true is is good, else false
|
||||
def isAuthorized?(password, salt, hash)
|
||||
if hash == Digest::SHA256.hexdigest(salt + password)
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
# Get message to client
|
||||
# @args: client -> client connection
|
||||
# @rtrn: array of the json string, or false if isn't json message
|
||||
def getClientMessage(client)
|
||||
begin
|
||||
msg = client.gets
|
||||
return JSON.parse(msg)
|
||||
rescue
|
||||
closeConnection(client)
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
# Close the client connection
|
||||
# @args: client -> client connection
|
||||
def closeConnection(client)
|
||||
client.puts "Closing the connection. Bye!"
|
||||
client.close
|
||||
end
|
||||
|
||||
# Check the config file
|
||||
# @args: file_config -> the configuration file
|
||||
# @rtrn: true if the config file is correct
|
||||
def checkconfig(file_config)
|
||||
begin
|
||||
config = YAML::load_file(file_config)
|
||||
@host = config['config']['host']
|
||||
@port = config['config']['port'].to_i
|
||||
@data_dir = config['config']['data_dir']
|
||||
@timeout = config['config']['timeout'].to_i
|
||||
|
||||
if @host.empty? || @port <= 0 || @data_dir.empty?
|
||||
puts I18n.t('server.checkconfig.fail')
|
||||
puts I18n.t('server.checkconfig.empty')
|
||||
return false
|
||||
end
|
||||
|
||||
if !Dir.exist?(@data_dir)
|
||||
puts I18n.t('server.checkconfig.fail')
|
||||
puts I18n.t('server.checkconfig.datadir')
|
||||
return false
|
||||
end
|
||||
|
||||
rescue Exception => e
|
||||
puts "#{I18n.t('server.checkconfig.fail')}\n#{e}"
|
||||
return false
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
# Create a new config file
|
||||
# @args: file_config -> the configuration file
|
||||
# @rtrn: true if le config file is create
|
||||
def setup(file_config)
|
||||
puts I18n.t('server.form.setup.title')
|
||||
puts '--------------------'
|
||||
host = ask(I18n.t('server.form.setup.host')).to_s
|
||||
port = ask(I18n.t('server.form.setup.port')).to_s
|
||||
data_dir = ask(I18n.t('server.form.setup.data_dir')).to_s
|
||||
timeout = ask(I18n.t('server.form.setup.timeout')).to_s
|
||||
|
||||
config = {'config' => {'host' => host,
|
||||
'port' => port,
|
||||
'data_dir' => data_dir,
|
||||
'timeout' => timeout}}
|
||||
|
||||
begin
|
||||
File.open(file_config, 'w') do |file|
|
||||
file << config.to_yaml
|
||||
end
|
||||
rescue Exception => e
|
||||
puts "#{I18n.t('server.formsetup.not_valid')}\n#{e}"
|
||||
return false
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
end
|
133
lib/Sync.rb
Normal file
133
lib/Sync.rb
Normal file
|
@ -0,0 +1,133 @@
|
|||
#!/usr/bin/ruby
|
||||
# author: nishiki
|
||||
# mail: nishiki@yaegashi.fr
|
||||
# info: a simple script who manage your passwords
|
||||
|
||||
require 'rubygems'
|
||||
require 'i18n'
|
||||
require 'socket'
|
||||
require 'json'
|
||||
|
||||
require "#{APP_ROOT}/lib/MPW.rb"
|
||||
|
||||
class Sync
|
||||
|
||||
attr_accessor :error_msg
|
||||
|
||||
# Constructor
|
||||
def initialize()
|
||||
@error_msg = nil
|
||||
end
|
||||
|
||||
# Disable the sync
|
||||
def disable()
|
||||
@sync = false
|
||||
end
|
||||
|
||||
# Connect to server
|
||||
# @args: host -> the server host
|
||||
# port -> ther connection port
|
||||
# gpg_key -> the gpg key
|
||||
# password -> the remote password
|
||||
# suffix -> the suffix file
|
||||
# @rtrn: false if the connection fail
|
||||
def connect(host, port, gpg_key, password, suffix=nil)
|
||||
@gpg_key = gpg_key
|
||||
@password = password
|
||||
@suffix = suffix
|
||||
|
||||
begin
|
||||
@socket= TCPSocket.new(host, port)
|
||||
@sync = true
|
||||
rescue Exception => e
|
||||
@error_msg = "#{I18n.t('error.sync.connection')}\n#{e}"
|
||||
@sync = false
|
||||
end
|
||||
|
||||
return @sync
|
||||
end
|
||||
|
||||
# Get data on server
|
||||
# @args: gpg_password -> the gpg password
|
||||
# @rtrn: nil if nothing data or error
|
||||
def get(gpg_password)
|
||||
if !@sync
|
||||
return nil
|
||||
end
|
||||
|
||||
send_msg = {:action => 'get',
|
||||
:gpg_key => @gpg_key,
|
||||
:password => @password,
|
||||
:suffix => @suffix}
|
||||
|
||||
@socket.puts send_msg.to_json
|
||||
msg = JSON.parse(@socket.gets)
|
||||
|
||||
case msg['error']
|
||||
when nil, 'file_not_exist'
|
||||
tmp_file = "/tmp/mpw-#{MPW.generatePassword()}.gpg"
|
||||
File.open(tmp_file, 'w') do |file|
|
||||
file << msg['data']
|
||||
end
|
||||
|
||||
@mpw = MPW.new(tmp_file)
|
||||
if !@mpw.decrypt(gpg_password)
|
||||
return nil
|
||||
end
|
||||
|
||||
File.unlink(tmp_file)
|
||||
|
||||
return @mpw.search()
|
||||
when 'not_authorized'
|
||||
@error_msg = "#{I18n.t('error.sync.not_authorized')}\n#{e}"
|
||||
else
|
||||
@error_msg = "#{I18n.t('error.sync.unknown')}\n#{e}"
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
# Update the remote data
|
||||
# @args: data -> the data to send on server
|
||||
# @rtrn: false if there is a problem
|
||||
def update(data)
|
||||
if !@sync
|
||||
return true
|
||||
end
|
||||
|
||||
send_msg = {:action => 'update',
|
||||
:gpg_key => @gpg_key,
|
||||
:password => @password,
|
||||
:suffix => @suffix,
|
||||
:data => data}
|
||||
|
||||
@socket.puts send_msg.to_json
|
||||
msg = JSON.parse(@socket.gets)
|
||||
|
||||
case msg['error']
|
||||
when nil
|
||||
return true
|
||||
when 'not_authorized'
|
||||
@error_msg = "#{I18n.t('error.sync.not_authorized')}\n#{e}"
|
||||
when 'no_data'
|
||||
@error_msg = "#{I18n.t('error.sync.no_data')}\n#{e}"
|
||||
else
|
||||
@error_msg = "#{I18n.t('error.sync.unknown')}\n#{e}"
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
def delete()
|
||||
end
|
||||
|
||||
# Close the connection
|
||||
def close()
|
||||
if !@sync
|
||||
return
|
||||
end
|
||||
|
||||
send_msg = {:action => 'close'}
|
||||
@socket.puts send_msg.to_json
|
||||
end
|
||||
end
|
23
mpw
23
mpw
|
@ -93,13 +93,17 @@ OptionParser.new do |opts|
|
|||
end
|
||||
end.parse!
|
||||
|
||||
config = MPWConfig.new(options[:config])
|
||||
check_error = config.checkconfig()
|
||||
|
||||
cli = Cli.new(lang, options[:config])
|
||||
cli = Cli.new(lang, config)
|
||||
cli.sync()
|
||||
|
||||
# Setup a new config
|
||||
if !check_error || !options[:setup].nil?
|
||||
cli.setup(lang)
|
||||
|
||||
# Display the item's informations
|
||||
if not options[:setup].nil?
|
||||
cli.setup()
|
||||
|
||||
elsif not options[:display].nil?
|
||||
cli.display(options[:display], options[:group], options[:type], options[:format])
|
||||
|
||||
|
@ -125,7 +129,16 @@ elsif not options[:import].nil?
|
|||
|
||||
# Interactive mode
|
||||
else
|
||||
cli.interactive
|
||||
begin
|
||||
cli.interactive()
|
||||
rescue SystemExit, Interrupt
|
||||
cli.sync()
|
||||
cli = nil
|
||||
return 1
|
||||
end
|
||||
end
|
||||
|
||||
cli.sync()
|
||||
cli = nil
|
||||
|
||||
exit 0
|
||||
|
|
60
mpw-server
Executable file
60
mpw-server
Executable file
|
@ -0,0 +1,60 @@
|
|||
#!/usr/bin/ruby
|
||||
# author: nishiki
|
||||
# mail: nishiki@yaegashi.fr
|
||||
# info: a simple script who manage your passwords
|
||||
|
||||
require 'rubygems'
|
||||
require 'optparse'
|
||||
require 'pathname'
|
||||
require 'locale'
|
||||
require 'i18n'
|
||||
|
||||
APP_ROOT = File.dirname(Pathname.new(__FILE__).realpath)
|
||||
require "#{APP_ROOT}/lib/Server.rb"
|
||||
|
||||
lang = Locale::Tag.parse(ENV['LANG']).to_simple.to_s[0..1]
|
||||
|
||||
I18n::Backend::Simple.send(:include, I18n::Backend::Fallbacks)
|
||||
I18n.load_path = Dir["#{APP_ROOT}/i18n/*.yml"]
|
||||
I18n.default_locale = :en
|
||||
I18n.locale = lang.to_sym
|
||||
|
||||
options = {}
|
||||
OptionParser.new do |opts|
|
||||
opts.banner = "#{I18n.t('server.option.usage')}: mpw-server -c CONFIG [options]"
|
||||
|
||||
opts.on("-c", "--config CONFIG", I18n.t('server.option.config')) do |config|
|
||||
options[:config] = config
|
||||
end
|
||||
|
||||
opts.on("-t", "--checkconfig", I18n.t('server.option.checkconfig')) do |b|
|
||||
options[:checkconfig] = b
|
||||
end
|
||||
|
||||
opts.on("-s", "--setup", I18n.t('server.option.setup')) do |b|
|
||||
options[:setup] = b
|
||||
end
|
||||
|
||||
opts.on("-h", "--help", I18n.t('server.option.help')) do |b|
|
||||
puts opts
|
||||
exit 0
|
||||
end
|
||||
end.parse!
|
||||
|
||||
if options[:config].nil? || options[:config].empty?
|
||||
puts "#{I18n.t('server.option.usage')}: mpw-server -c CONFIG [options]"
|
||||
exit 2
|
||||
end
|
||||
|
||||
server = Server.new
|
||||
|
||||
if options[:checkconfig]
|
||||
server.checkconfig(options[:config])
|
||||
elsif options[:setup]
|
||||
server.setup(options[:config])
|
||||
else
|
||||
server.checkconfig(options[:config])
|
||||
server.start()
|
||||
end
|
||||
|
||||
exit 0
|
Loading…
Add table
Reference in a new issue