mirror of
https://github.com/nishiki/manage-password.git
synced 2024-11-27 07:33:05 +00:00
add module MPW
This commit is contained in:
parent
7a50c4cf1c
commit
96fe71e07d
10 changed files with 642 additions and 632 deletions
140
MPW/Config.rb
Normal file
140
MPW/Config.rb
Normal file
|
@ -0,0 +1,140 @@
|
|||
#!/usr/bin/ruby
|
||||
# author: nishiki
|
||||
# mail: nishiki@yaegashi.fr
|
||||
# info: a simple script who manage your passwords
|
||||
|
||||
module MPW
|
||||
|
||||
require 'rubygems'
|
||||
require 'yaml'
|
||||
require 'i18n'
|
||||
|
||||
class Config
|
||||
|
||||
attr_accessor :error_msg
|
||||
|
||||
attr_accessor :key
|
||||
attr_accessor :lang
|
||||
attr_accessor :file_gpg
|
||||
attr_accessor :timeout_pwd
|
||||
attr_accessor :last_update
|
||||
attr_accessor :sync_host
|
||||
attr_accessor :sync_port
|
||||
attr_accessor :sync_pwd
|
||||
attr_accessor :sync_suffix
|
||||
attr_accessor :last_update
|
||||
|
||||
# Constructor
|
||||
# @args: file_config -> the specify config file
|
||||
def initialize(file_config=nil)
|
||||
@error_msg = nil
|
||||
@file_config = "#{Dir.home()}/.mpw.cfg"
|
||||
|
||||
if !file_config.nil? && !file_config.empty?
|
||||
@file_config = file_config
|
||||
end
|
||||
end
|
||||
|
||||
# Create a new config file
|
||||
# @args: key -> the gpg key to encrypt
|
||||
# lang -> the software language
|
||||
# file_gpg -> the file who is encrypted
|
||||
# timeout_pwd -> time to save the password
|
||||
# sync_host -> the server host for synchronization
|
||||
# sync_port -> the server port for synchronization
|
||||
# sync_pwd -> the password for synchronization
|
||||
# sync_suffix -> the suffix file (optionnal)
|
||||
# @rtrn: true if le config file is create
|
||||
def setup(key, lang, file_gpg, timeout_pwd, sync_host=nil, sync_port=nil, sync_pwd=nil, sync_suffix=nil)
|
||||
|
||||
if not key =~ /[a-zA-Z0-9.-_]+\@[a-zA-Z0-9]+\.[a-zA-Z]+/
|
||||
@error_msg = I18n.t('error.config.key_bad_format')
|
||||
return false
|
||||
end
|
||||
|
||||
if file_gpg.empty?
|
||||
file_gpg = "#{Dir.home()}/.mpw.gpg"
|
||||
end
|
||||
|
||||
timeout_pwd = timeout_pwd.empty? ? 60 : timeout_pwd.to_i
|
||||
|
||||
config = {'config' => {'key' => key,
|
||||
'lang' => lang,
|
||||
'file_gpg' => file_gpg,
|
||||
'timeout_pwd' => timeout_pwd,
|
||||
'sync_host' => sync_host,
|
||||
'sync_port' => sync_port,
|
||||
'sync_pwd' => sync_pwd,
|
||||
'sync_suffix' => sync_suffix,
|
||||
'last_update' => 0 }}
|
||||
|
||||
begin
|
||||
File.open(@file_config, 'w') do |file|
|
||||
file << config.to_yaml
|
||||
end
|
||||
rescue Exception => e
|
||||
@error_msg = "#{I18n.t('error.config.write')}\n#{e}"
|
||||
return false
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
# Check the config file
|
||||
# @rtrn: true if the config file is correct
|
||||
def checkconfig()
|
||||
begin
|
||||
config = YAML::load_file(@file_config)
|
||||
@key = config['config']['key']
|
||||
@lang = config['config']['lang']
|
||||
@file_gpg = config['config']['file_gpg']
|
||||
@timeout_pwd = config['config']['timeout_pwd'].to_i
|
||||
@sync_host = config['config']['sync_host']
|
||||
@sync_port = config['config']['sync_port']
|
||||
@sync_pwd = config['config']['sync_pwd']
|
||||
@sync_suffix = config['config']['sync_suffix']
|
||||
@last_update = config['config']['last_update'].to_i
|
||||
|
||||
if @key.empty? || @file_gpg.empty?
|
||||
@error_msg = I18n.t('error.config.check')
|
||||
return false
|
||||
end
|
||||
|
||||
I18n.locale = @lang.to_sym
|
||||
|
||||
rescue Exception => e
|
||||
@error_msg = "#{I18n.t('error.config.check')}\n#{e}"
|
||||
return false
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
# Set the last update when there is a sync
|
||||
# @rtrn: true is the file has been updated
|
||||
def set_last_update()
|
||||
config = {'config' => {'key' => @key,
|
||||
'lang' => @lang,
|
||||
'file_gpg' => @file_gpg,
|
||||
'timeout_pwd' => @timeout_pwd,
|
||||
'sync_host' => @sync_host,
|
||||
'sync_port' => @sync_port,
|
||||
'sync_pwd' => @sync_pwd,
|
||||
'sync_suffix' => @sync_suffix,
|
||||
'last_update' => Time.now.to_i }}
|
||||
|
||||
begin
|
||||
File.open(@file_config, 'w') do |file|
|
||||
file << config.to_yaml
|
||||
end
|
||||
rescue Exception => e
|
||||
@error_msg = "#{I18n.t('error.config.write')}\n#{e}"
|
||||
return false
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
335
MPW/MPW.rb
Normal file
335
MPW/MPW.rb
Normal file
|
@ -0,0 +1,335 @@
|
|||
#!/usr/bin/ruby
|
||||
# author: nishiki
|
||||
# mail: nishiki@yaegashi.fr
|
||||
# info: a simple script who manage your passwords
|
||||
|
||||
module MPW
|
||||
|
||||
require 'rubygems'
|
||||
require 'gpgme'
|
||||
require 'csv'
|
||||
require 'i18n'
|
||||
|
||||
class MPW
|
||||
|
||||
ID = 0
|
||||
NAME = 1
|
||||
GROUP = 2
|
||||
PROTOCOL = 3
|
||||
SERVER = 4
|
||||
LOGIN = 5
|
||||
PASSWORD = 6
|
||||
PORT = 7
|
||||
COMMENT = 8
|
||||
DATE = 9
|
||||
|
||||
attr_accessor :error_msg
|
||||
|
||||
# Constructor
|
||||
def initialize(file_gpg, key=nil)
|
||||
@error_msg = nil
|
||||
@file_gpg = file_gpg
|
||||
@key = key
|
||||
end
|
||||
|
||||
# Decrypt a gpg file
|
||||
# @args: password -> the GPG key password
|
||||
# @rtrn: true if data has been decrypted
|
||||
def decrypt(passwd=nil)
|
||||
@data = Array.new
|
||||
|
||||
begin
|
||||
if File.exist?(@file_gpg)
|
||||
crypto = GPGME::Crypto.new(:armor => true)
|
||||
data_decrypt = crypto.decrypt(IO.read(@file_gpg), :password => passwd).read
|
||||
|
||||
data_decrypt.lines do |line|
|
||||
@data.push(line.parse_csv)
|
||||
end
|
||||
end
|
||||
|
||||
return true
|
||||
rescue Exception => e
|
||||
@error_msg = "#{I18n.t('error.gpg_file.decrypt')}\n#{e}"
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
# Encrypt a file
|
||||
# @rtrn: true if the file has been encrypted
|
||||
def encrypt()
|
||||
begin
|
||||
crypto = GPGME::Crypto.new(:armor => true)
|
||||
file_gpg = File.open(@file_gpg, 'w+')
|
||||
|
||||
data_to_encrypt = ''
|
||||
@data.each do |row|
|
||||
data_to_encrypt << row.to_csv
|
||||
end
|
||||
|
||||
crypto.encrypt(data_to_encrypt, :recipients => @key, :output => file_gpg)
|
||||
file_gpg.close
|
||||
|
||||
return true
|
||||
rescue Exception => e
|
||||
@error_msg = "#{I18n.t('error.gpg_file.encrypt')}\n#{e}"
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
# Search in some csv data
|
||||
# @args: search -> the string to search
|
||||
# protocol -> the connection protocol (ssh, web, other)
|
||||
# @rtrn: a list with the resultat of the search
|
||||
def search(search='', group=nil, protocol=nil)
|
||||
result = Array.new()
|
||||
|
||||
if !search.nil?
|
||||
search = search.downcase
|
||||
end
|
||||
search = search.force_encoding('ASCII-8BIT')
|
||||
|
||||
@data.each do |row|
|
||||
name = row[NAME].nil? ? nil : row[NAME].downcase
|
||||
server = row[SERVER].nil? ? nil : row[SERVER].downcase
|
||||
comment = row[COMMENT].nil? ? nil : row[COMMENT].downcase
|
||||
|
||||
if name =~ /^.*#{search}.*$/ || server =~ /^.*#{search}.*$/ || comment =~ /^.*#{search}.*$/
|
||||
if (protocol.nil? || protocol.eql?(row[PROTOCOL])) && (group.nil? || group.eql?(row[GROUP]))
|
||||
result.push(row)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return result
|
||||
end
|
||||
|
||||
# Search in some csv data
|
||||
# @args: id -> the id item
|
||||
# @rtrn: a row with the resultat of the search
|
||||
def search_by_id(id)
|
||||
@data.each do |row|
|
||||
if row[ID] == id
|
||||
return row
|
||||
end
|
||||
end
|
||||
|
||||
return Array.new()
|
||||
end
|
||||
|
||||
# Update an item
|
||||
# @args: id -> the item's identifiant
|
||||
# name -> the item name
|
||||
# group -> the item group
|
||||
# server -> the ip or hostname
|
||||
# protocol -> the protocol
|
||||
# login -> the login
|
||||
# passwd -> the password
|
||||
# port -> the port
|
||||
# comment -> a comment
|
||||
# @rtrn: true if the item has been updated
|
||||
def update(name, group, server, protocol, login, passwd, port, comment, id=nil)
|
||||
row = Array.new()
|
||||
update = false
|
||||
|
||||
i = 0
|
||||
@data.each do |r|
|
||||
if r[ID] == id
|
||||
row = r
|
||||
update = true
|
||||
break
|
||||
end
|
||||
i += 1
|
||||
end
|
||||
|
||||
if port.to_i <= 0
|
||||
port = nil
|
||||
end
|
||||
|
||||
row_update = Array.new()
|
||||
row_update[DATE] = Time.now.to_i
|
||||
|
||||
row_update[ID] = id.nil? || id.empty? ? MPW.password(16) : id
|
||||
row_update[NAME] = name.nil? || name.empty? ? row[NAME] : name
|
||||
row_update[GROUP] = group.nil? || group.empty? ? row[GROUP] : group
|
||||
row_update[SERVER] = server.nil? || server.empty? ? row[SERVER] : server
|
||||
row_update[PROTOCOL] = protocol.nil? || protocol.empty? ? row[PROTOCOL] : protocol
|
||||
row_update[LOGIN] = login.nil? || login.empty? ? row[LOGIN] : login
|
||||
row_update[PASSWORD] = passwd.nil? || passwd.empty? ? row[PASSWORD] : passwd
|
||||
row_update[PORT] = port.nil? || port.empty? ? row[PORT] : port
|
||||
row_update[COMMENT] = comment.nil? || comment.empty? ? row[COMMENT] : comment
|
||||
|
||||
row_update[] = row_update[NAME].nil? ? nil : row_update[NAME].force_encoding('ASCII-8BIT')
|
||||
row_update[] = row_update[GROUP].nil? ? nil : row_update[GROUP].force_encoding('ASCII-8BIT')
|
||||
row_update[] = row_update[SERVER].nil? ? nil : row_update[SERVER].force_encoding('ASCII-8BIT')
|
||||
row_update[] = row_update[PROTOCOL].nil? ? nil : row_update[PROTOCOL].force_encoding('ASCII-8BIT')
|
||||
row_update[] = row_update[LOGIN].nil? ? nil : row_update[LOGIN].force_encoding('ASCII-8BIT')
|
||||
row_update[] = row_update[PASSWORD].nil? ? nil : row_update[PASSWORD].force_encoding('ASCII-8BIT')
|
||||
row_update[] = row_update[COMMENT].nil? ? nil : row_update[COMMENT].force_encoding('ASCII-8BIT')
|
||||
|
||||
if row_update[NAME].nil? || row_update[NAME].empty?
|
||||
@error_msg = I18n.t('error.update.name_empty')
|
||||
return false
|
||||
end
|
||||
|
||||
if update
|
||||
@data[i] = row_update
|
||||
else
|
||||
@data.push(row_update)
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
# Remove an item
|
||||
# @args: id -> the item's identifiant
|
||||
# @rtrn: true if the item has been deleted
|
||||
def remove(id)
|
||||
i = 0
|
||||
@data.each do |row|
|
||||
if row[ID] == id
|
||||
@data.delete_at(i)
|
||||
return true
|
||||
end
|
||||
i += 1
|
||||
end
|
||||
|
||||
@error_msg = I18n.t('error.delete.id_no_exist', :id => id)
|
||||
return false
|
||||
end
|
||||
|
||||
# Export to csv
|
||||
# @args: file -> a string to match
|
||||
# @rtrn: true if export work
|
||||
def export(file)
|
||||
begin
|
||||
File.open(file, 'w+') do |file|
|
||||
@data.each do |row|
|
||||
row.delete_at(ID).delete_at(DATE)
|
||||
file << row.to_csv
|
||||
end
|
||||
end
|
||||
|
||||
return true
|
||||
rescue Exception => e
|
||||
@error_msg = "#{I18n.t('error.export.write', :file => file)}\n#{e}"
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
# Import to csv
|
||||
# @args: file -> path to file import
|
||||
# @rtrn: true if the import work
|
||||
def import(file)
|
||||
begin
|
||||
data_new = IO.read(file)
|
||||
data_new.lines do |line|
|
||||
if not line =~ /(.*,){6}/
|
||||
@error_msg = I18n.t('error.import.bad_format')
|
||||
return false
|
||||
else
|
||||
row = line.parse_csv.unshift(0)
|
||||
if not update(row[NAME], row[GROUP], row[SERVER], row[PROTOCOL], row[LOGIN], row[PASSWORD], row[PORT], row[COMMENT])
|
||||
return false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return true
|
||||
rescue Exception => e
|
||||
@error_msg = "#{I18n.t('error.import.read', :file => file)}\n#{e}"
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
# Return a preview import
|
||||
# @args: file -> path to file import
|
||||
# @rtrn: an array with the items to import, if there is an error return false
|
||||
def import_preview(file)
|
||||
begin
|
||||
result = Array.new()
|
||||
id = 0
|
||||
|
||||
data = IO.read(file)
|
||||
data.lines do |line|
|
||||
if not line =~ /(.*,){6}/
|
||||
@error_msg = I18n.t('error.import.bad_format')
|
||||
return false
|
||||
else
|
||||
result.push(line.parse_csv.unshift(id))
|
||||
end
|
||||
|
||||
id += 1
|
||||
end
|
||||
|
||||
return result
|
||||
rescue Exception => e
|
||||
@error_msg = "#{I18n.t('error.import.read', :file => file)}\n#{e}"
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
# Sync remote data and local data
|
||||
# @args: data_remote -> array with the data remote
|
||||
# last_update -> last update
|
||||
# @rtrn: false if data_remote is nil
|
||||
def sync(data_remote, last_update)
|
||||
if !data_remote.instance_of?(Array)
|
||||
return false
|
||||
end
|
||||
|
||||
@data.each do |l|
|
||||
j = 0
|
||||
update = false
|
||||
|
||||
# Update item
|
||||
data_remote.each do |r|
|
||||
if l[ID] == r[ID]
|
||||
if l[DATE].to_i < r[DATE].to_i
|
||||
update(r[NAME], r[GROUP], r[SERVER], r[PROTOCOL], r[LOGIN], r[PASSWORD], r[PORT], r[COMMENT], l[ID])
|
||||
end
|
||||
update = true
|
||||
data_remote.delete_at(j)
|
||||
break
|
||||
end
|
||||
j += 1
|
||||
end
|
||||
|
||||
# Delete an old item
|
||||
if !update && l[DATE].to_i < last_update
|
||||
remove(l[ID])
|
||||
end
|
||||
end
|
||||
|
||||
# Add item
|
||||
data_remote.each do |r|
|
||||
if r[DATE].to_i > last_update
|
||||
update(r[NAME], r[GROUP], r[SERVER], r[PROTOCOL], r[LOGIN], r[PASSWORD], r[PORT], r[COMMENT], r[ID])
|
||||
end
|
||||
end
|
||||
|
||||
return encrypt()
|
||||
end
|
||||
|
||||
# Generate a random password
|
||||
# @args: length -> the length password
|
||||
# @rtrn: a random string
|
||||
def self.password(length=8)
|
||||
if length.to_i <= 0
|
||||
length = 8
|
||||
else
|
||||
length = length.to_i
|
||||
end
|
||||
|
||||
result = ''
|
||||
while length > 62 do
|
||||
result << ([*('A'..'Z'),*('a'..'z'),*('0'..'9')]).sample(62).join
|
||||
length -= 62
|
||||
end
|
||||
result << ([*('A'..'Z'),*('a'..'z'),*('0'..'9')]).sample(length).join
|
||||
|
||||
return result
|
||||
end
|
||||
end
|
||||
|
||||
end
|
130
MPW/Sync/MPW.rb
Normal file
130
MPW/Sync/MPW.rb
Normal file
|
@ -0,0 +1,130 @@
|
|||
#!/usr/bin/ruby
|
||||
# author: nishiki
|
||||
# mail: nishiki@yaegashi.fr
|
||||
# info: a simple script who manage your passwords
|
||||
|
||||
module MPW
|
||||
|
||||
module Sync
|
||||
|
||||
require 'rubygems'
|
||||
require 'i18n'
|
||||
require 'socket'
|
||||
require 'json'
|
||||
|
||||
class MPW
|
||||
|
||||
attr_accessor :error_msg
|
||||
attr_accessor :enable
|
||||
|
||||
# Constructor
|
||||
def initialize()
|
||||
@error_msg = nil
|
||||
@enable = false
|
||||
end
|
||||
|
||||
# Connect to server
|
||||
# @args: host -> the server host
|
||||
# port -> ther connection port
|
||||
# gpg_key -> the gpg key
|
||||
# password -> the remote password
|
||||
# suffix -> the suffix file
|
||||
# @rtrn: false if the connection fail
|
||||
def connect(host, port, gpg_key, password, suffix=nil)
|
||||
@gpg_key = gpg_key
|
||||
@password = password
|
||||
@suffix = suffix
|
||||
|
||||
begin
|
||||
@socket = TCPSocket.new(host, port)
|
||||
@enable = true
|
||||
rescue Exception => e
|
||||
@error_msg = "#{I18n.t('error.sync.connection')}\n#{e}"
|
||||
@enable = false
|
||||
end
|
||||
|
||||
return @enable
|
||||
end
|
||||
|
||||
# Get data on server
|
||||
# @args: gpg_password -> the gpg password
|
||||
# @rtrn: nil if nothing data or error
|
||||
def get(gpg_password)
|
||||
if !@enable
|
||||
return nil
|
||||
end
|
||||
|
||||
send_msg = {:action => 'get',
|
||||
:gpg_key => @gpg_key,
|
||||
:password => @password,
|
||||
:suffix => @suffix}
|
||||
|
||||
@socket.puts send_msg.to_json
|
||||
msg = JSON.parse(@socket.gets)
|
||||
|
||||
if !defined?(msg['error'])
|
||||
@error_msg = I18n.t('error.sync.communication')
|
||||
return nil
|
||||
elsif msg['error'].nil?
|
||||
tmp_file = "/tmp/mpw-#{MPW.password()}.gpg"
|
||||
File.open(tmp_file, 'w') do |file|
|
||||
file << msg['data']
|
||||
end
|
||||
|
||||
@mpw = MPW.new(tmp_file)
|
||||
if !@mpw.decrypt(gpg_password)
|
||||
puts @mpw.error_msg
|
||||
return nil
|
||||
end
|
||||
|
||||
File.unlink(tmp_file)
|
||||
return @mpw.search()
|
||||
else
|
||||
@error_msg = I18n.t(msg['error'])
|
||||
return nil
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
# Update the remote data
|
||||
# @args: data -> the data to send on server
|
||||
# @rtrn: false if there is a problem
|
||||
def update(data)
|
||||
if !@enable
|
||||
return true
|
||||
end
|
||||
|
||||
send_msg = {:action => 'update',
|
||||
:gpg_key => @gpg_key,
|
||||
:password => @password,
|
||||
:suffix => @suffix,
|
||||
:data => data}
|
||||
|
||||
@socket.puts send_msg.to_json
|
||||
msg = JSON.parse(@socket.gets)
|
||||
|
||||
if !defined?(msg['error'])
|
||||
@error_msg = I18n.t('error.sync.communication')
|
||||
return false
|
||||
elsif msg['error'].nil?
|
||||
return true
|
||||
else
|
||||
@error_msg = I18n.t(msg['error'])
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
# Close the connection
|
||||
def close()
|
||||
if !@enable
|
||||
return
|
||||
end
|
||||
|
||||
send_msg = {:action => 'close'}
|
||||
@socket.puts send_msg.to_json
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
|
@ -10,9 +10,8 @@ require 'readline'
|
|||
require 'i18n'
|
||||
require 'yaml'
|
||||
|
||||
require "#{APP_ROOT}/lib/MPW.rb"
|
||||
require "#{APP_ROOT}/lib/MPWConfig.rb"
|
||||
require "#{APP_ROOT}/lib/Sync.rb"
|
||||
require "#{APP_ROOT}/MPW/MPW"
|
||||
require "#{APP_ROOT}/MPW/Sync/MPW"
|
||||
|
||||
class Cli
|
||||
|
||||
|
@ -32,7 +31,7 @@ class Cli
|
|||
# @rtnr: true if the synchro is finish
|
||||
def sync()
|
||||
if !defined?(@sync)
|
||||
@sync = Sync.new()
|
||||
@sync = MPW::Sync::MPW.new
|
||||
|
||||
if !@config.sync_host.nil? && !@config.sync_port.nil?
|
||||
if !@sync.connect(@config.sync_host, @config.sync_port, @config.key, @config.sync_pwd, @config.sync_suffix)
|
||||
|
@ -99,7 +98,7 @@ class Cli
|
|||
# Request the GPG password and decrypt the file
|
||||
def decrypt()
|
||||
if !defined?(@mpw)
|
||||
@mpw = MPW.new(@config.file_gpg, @config.key)
|
||||
@mpw = MPW::MPW.new(@config.file_gpg, @config.key)
|
||||
end
|
||||
|
||||
@passwd = ask(I18n.t('display.gpg_password')) {|q| q.echo = false}
|
||||
|
@ -132,30 +131,30 @@ class Cli
|
|||
# @args: item -> an array with the item information
|
||||
def displayFormat(item)
|
||||
puts '--------------------'
|
||||
puts "Id: #{item[MPW::ID]}"
|
||||
puts "#{I18n.t('display.name')}: #{item[MPW::NAME]}"
|
||||
puts "#{I18n.t('display.group')}: #{item[MPW::GROUP]}"
|
||||
puts "#{I18n.t('display.server')}: #{item[MPW::SERVER]}"
|
||||
puts "#{I18n.t('display.protocol')}: #{item[MPW::PROTOCOL]}"
|
||||
puts "#{I18n.t('display.login')}: #{item[MPW::LOGIN]}"
|
||||
puts "#{I18n.t('display.password')}: #{item[MPW::PASSWORD]}"
|
||||
puts "#{I18n.t('display.port')}: #{item[MPW::PORT]}"
|
||||
puts "#{I18n.t('display.comment')}: #{item[MPW::COMMENT]}"
|
||||
puts "Id: #{item[MPW::MPW::ID]}"
|
||||
puts "#{I18n.t('display.name')}: #{item[MPW::MPW::NAME]}"
|
||||
puts "#{I18n.t('display.group')}: #{item[MPW::MPW::GROUP]}"
|
||||
puts "#{I18n.t('display.server')}: #{item[MPW::MPW::SERVER]}"
|
||||
puts "#{I18n.t('display.protocol')}: #{item[MPW::MPW::PROTOCOL]}"
|
||||
puts "#{I18n.t('display.login')}: #{item[MPW::MPW::LOGIN]}"
|
||||
puts "#{I18n.t('display.password')}: #{item[MPW::MPW::PASSWORD]}"
|
||||
puts "#{I18n.t('display.port')}: #{item[MPW::MPW::PORT]}"
|
||||
puts "#{I18n.t('display.comment')}: #{item[MPW::MPW::COMMENT]}"
|
||||
end
|
||||
|
||||
# Display an item in the alternative format
|
||||
# @args: item -> an array with the item information
|
||||
def displayFormatAlt(item)
|
||||
port = item[MPW::PORT].nil? ? '' : ":#{item[MPW::PORT]}"
|
||||
port = item[MPW::MPW::PORT].nil? ? '' : ":#{item[MPW::MPW::PORT]}"
|
||||
|
||||
if item[MPW::PASSWORD].nil? || item[MPW::PASSWORD].empty?
|
||||
if item[MPW::LOGIN].include('@')
|
||||
puts "# #{item[MPW::ID]} #{item[MPW::PROTOCOL]}://#{item[MPW::LOGIN]}@#{item[MPW::SERVER]}#{port}"
|
||||
if item[MPW::MPW::PASSWORD].nil? || item[MPW::MPW::PASSWORD].empty?
|
||||
if item[MPW::MPW::LOGIN].include('@')
|
||||
puts "# #{item[MPW::MPW::ID]} #{item[MPW::MPW::PROTOCOL]}://#{item[MPW::MPW::LOGIN]}@#{item[MPW::MPW::SERVER]}#{port}"
|
||||
else
|
||||
puts "# #{item[MPW::ID]} #{item[MPW::PROTOCOL]}://{#{item[MPW::LOGIN]}}@#{item[MPW::SERVER]}#{port}"
|
||||
puts "# #{item[MPW::MPW::ID]} #{item[MPW::MPW::PROTOCOL]}://{#{item[MPW::MPW::LOGIN]}}@#{item[MPW::MPW::SERVER]}#{port}"
|
||||
end
|
||||
else
|
||||
puts "# #{item[MPW::ID]} #{item[MPW::PROTOCOL]}://{#{item[MPW::LOGIN]}:#{item[MPW::PASSWORD]}}@#{item[MPW::SERVER]}#{port}"
|
||||
puts "# #{item[MPW::MPW::ID]} #{item[MPW::MPW::PROTOCOL]}://{#{item[MPW::MPW::LOGIN]}:#{item[MPW::MPW::PASSWORD]}}@#{item[MPW::MPW::SERVER]}#{port}"
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -193,14 +192,14 @@ class Cli
|
|||
if not row.empty?
|
||||
puts I18n.t('form.update.title')
|
||||
puts '--------------------'
|
||||
name = ask(I18n.t('form.update.name' , :name => row[MPW::NAME])).to_s
|
||||
group = ask(I18n.t('form.update.group' , :group => row[MPW::GROUP])).to_s
|
||||
server = ask(I18n.t('form.update.server' , :server => row[MPW::SERVER])).to_s
|
||||
protocol = ask(I18n.t('form.update.protocol', :protocol => row[MPW::PROTOCOL])).to_s
|
||||
login = ask(I18n.t('form.update.login' , :login => row[MPW::LOGIN])).to_s
|
||||
name = ask(I18n.t('form.update.name' , :name => row[MPW::MPW::NAME])).to_s
|
||||
group = ask(I18n.t('form.update.group' , :group => row[MPW::MPW::GROUP])).to_s
|
||||
server = ask(I18n.t('form.update.server' , :server => row[MPW::MPW::SERVER])).to_s
|
||||
protocol = ask(I18n.t('form.update.protocol', :protocol => row[MPW::MPW::PROTOCOL])).to_s
|
||||
login = ask(I18n.t('form.update.login' , :login => row[MPW::MPW::LOGIN])).to_s
|
||||
passwd = ask(I18n.t('form.update.password')).to_s
|
||||
port = ask(I18n.t('form.update.port' , :port => row[MPW::PORT])).to_s
|
||||
comment = ask(I18n.t('form.update.comment' , :comment => row[MPW::COMMENT])).to_s
|
||||
port = ask(I18n.t('form.update.port' , :port => row[MPW::MPW::PORT])).to_s
|
||||
comment = ask(I18n.t('form.update.comment' , :comment => row[MPW::MPW::COMMENT])).to_s
|
||||
|
||||
if @mpw.update(name, group, server, protocol, login, passwd, port, comment, id)
|
||||
if @mpw.encrypt()
|
|
@ -3,7 +3,7 @@
|
|||
# mail: nishiki@yaegashi.fr
|
||||
# info: a simple script who manage your passwords
|
||||
|
||||
require "#{APP_ROOT}/lib/Cli.rb"
|
||||
require "#{APP_ROOT}/MPW/UI/Cli"
|
||||
|
||||
class CliSSH < Cli
|
||||
|
||||
|
@ -16,11 +16,11 @@ class CliSSH < Cli
|
|||
|
||||
if result.length > 0
|
||||
result.each do |r|
|
||||
server = @server.nil? ? r[MPW::SERVER] : @server
|
||||
port = @port.nil? ? r[MPW::PORT] : @port
|
||||
login = @login.nil? ? r[MPW::LOGIN] : @login
|
||||
server = @server.nil? ? r[MPW::MPW::SERVER] : @server
|
||||
port = @port.nil? ? r[MPW::MPW::PORT] : @port
|
||||
login = @login.nil? ? r[MPW::MPW::LOGIN] : @login
|
||||
|
||||
passwd = r[MPW::PASSWORD]
|
||||
passwd = r[MPW::MPW::PASSWORD]
|
||||
|
||||
if port.nil? || port.empty?
|
||||
port = 22
|
331
lib/MPW.rb
331
lib/MPW.rb
|
@ -1,331 +0,0 @@
|
|||
#!/usr/bin/ruby
|
||||
# author: nishiki
|
||||
# mail: nishiki@yaegashi.fr
|
||||
# info: a simple script who manage your passwords
|
||||
|
||||
require 'rubygems'
|
||||
require 'gpgme'
|
||||
require 'csv'
|
||||
require 'i18n'
|
||||
|
||||
class MPW
|
||||
|
||||
ID = 0
|
||||
NAME = 1
|
||||
GROUP = 2
|
||||
PROTOCOL = 3
|
||||
SERVER = 4
|
||||
LOGIN = 5
|
||||
PASSWORD = 6
|
||||
PORT = 7
|
||||
COMMENT = 8
|
||||
DATE = 9
|
||||
|
||||
attr_accessor :error_msg
|
||||
|
||||
# Constructor
|
||||
def initialize(file_gpg, key=nil)
|
||||
@error_msg = nil
|
||||
@file_gpg = file_gpg
|
||||
@key = key
|
||||
end
|
||||
|
||||
# Decrypt a gpg file
|
||||
# @args: password -> the GPG key password
|
||||
# @rtrn: true if data has been decrypted
|
||||
def decrypt(passwd=nil)
|
||||
@data = Array.new
|
||||
|
||||
begin
|
||||
if File.exist?(@file_gpg)
|
||||
crypto = GPGME::Crypto.new(:armor => true)
|
||||
data_decrypt = crypto.decrypt(IO.read(@file_gpg), :password => passwd).read
|
||||
|
||||
data_decrypt.lines do |line|
|
||||
@data.push(line.parse_csv)
|
||||
end
|
||||
end
|
||||
|
||||
return true
|
||||
rescue Exception => e
|
||||
@error_msg = "#{I18n.t('error.gpg_file.decrypt')}\n#{e}"
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
# Encrypt a file
|
||||
# @rtrn: true if the file has been encrypted
|
||||
def encrypt()
|
||||
begin
|
||||
crypto = GPGME::Crypto.new(:armor => true)
|
||||
file_gpg = File.open(@file_gpg, 'w+')
|
||||
|
||||
data_to_encrypt = ''
|
||||
@data.each do |row|
|
||||
data_to_encrypt << row.to_csv
|
||||
end
|
||||
|
||||
crypto.encrypt(data_to_encrypt, :recipients => @key, :output => file_gpg)
|
||||
file_gpg.close
|
||||
|
||||
return true
|
||||
rescue Exception => e
|
||||
@error_msg = "#{I18n.t('error.gpg_file.encrypt')}\n#{e}"
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
# Search in some csv data
|
||||
# @args: search -> the string to search
|
||||
# protocol -> the connection protocol (ssh, web, other)
|
||||
# @rtrn: a list with the resultat of the search
|
||||
def search(search='', group=nil, protocol=nil)
|
||||
result = Array.new()
|
||||
|
||||
if !search.nil?
|
||||
search = search.downcase
|
||||
end
|
||||
search = search.force_encoding('ASCII-8BIT')
|
||||
|
||||
@data.each do |row|
|
||||
name = row[NAME].nil? ? nil : row[NAME].downcase
|
||||
server = row[SERVER].nil? ? nil : row[SERVER].downcase
|
||||
comment = row[COMMENT].nil? ? nil : row[COMMENT].downcase
|
||||
|
||||
if name =~ /^.*#{search}.*$/ || server =~ /^.*#{search}.*$/ || comment =~ /^.*#{search}.*$/
|
||||
if (protocol.nil? || protocol.eql?(row[PROTOCOL])) && (group.nil? || group.eql?(row[GROUP]))
|
||||
result.push(row)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return result
|
||||
end
|
||||
|
||||
# Search in some csv data
|
||||
# @args: id -> the id item
|
||||
# @rtrn: a row with the resultat of the search
|
||||
def search_by_id(id)
|
||||
@data.each do |row|
|
||||
if row[ID] == id
|
||||
return row
|
||||
end
|
||||
end
|
||||
|
||||
return Array.new()
|
||||
end
|
||||
|
||||
# Update an item
|
||||
# @args: id -> the item's identifiant
|
||||
# name -> the item name
|
||||
# group -> the item group
|
||||
# server -> the ip or hostname
|
||||
# protocol -> the protocol
|
||||
# login -> the login
|
||||
# passwd -> the password
|
||||
# port -> the port
|
||||
# comment -> a comment
|
||||
# @rtrn: true if the item has been updated
|
||||
def update(name, group, server, protocol, login, passwd, port, comment, id=nil)
|
||||
row = Array.new()
|
||||
update = false
|
||||
|
||||
i = 0
|
||||
@data.each do |r|
|
||||
if r[ID] == id
|
||||
row = r
|
||||
update = true
|
||||
break
|
||||
end
|
||||
i += 1
|
||||
end
|
||||
|
||||
if port.to_i <= 0
|
||||
port = nil
|
||||
end
|
||||
|
||||
row_update = Array.new()
|
||||
row_update[DATE] = Time.now.to_i
|
||||
|
||||
row_update[ID] = id.nil? || id.empty? ? MPW.password(16) : id
|
||||
row_update[NAME] = name.nil? || name.empty? ? row[NAME] : name
|
||||
row_update[GROUP] = group.nil? || group.empty? ? row[GROUP] : group
|
||||
row_update[SERVER] = server.nil? || server.empty? ? row[SERVER] : server
|
||||
row_update[PROTOCOL] = protocol.nil? || protocol.empty? ? row[PROTOCOL] : protocol
|
||||
row_update[LOGIN] = login.nil? || login.empty? ? row[LOGIN] : login
|
||||
row_update[PASSWORD] = passwd.nil? || passwd.empty? ? row[PASSWORD] : passwd
|
||||
row_update[PORT] = port.nil? || port.empty? ? row[PORT] : port
|
||||
row_update[COMMENT] = comment.nil? || comment.empty? ? row[COMMENT] : comment
|
||||
|
||||
row_update[] = row_update[NAME].nil? ? nil : row_update[NAME].force_encoding('ASCII-8BIT')
|
||||
row_update[] = row_update[GROUP].nil? ? nil : row_update[GROUP].force_encoding('ASCII-8BIT')
|
||||
row_update[] = row_update[SERVER].nil? ? nil : row_update[SERVER].force_encoding('ASCII-8BIT')
|
||||
row_update[] = row_update[PROTOCOL].nil? ? nil : row_update[PROTOCOL].force_encoding('ASCII-8BIT')
|
||||
row_update[] = row_update[LOGIN].nil? ? nil : row_update[LOGIN].force_encoding('ASCII-8BIT')
|
||||
row_update[] = row_update[PASSWORD].nil? ? nil : row_update[PASSWORD].force_encoding('ASCII-8BIT')
|
||||
row_update[] = row_update[COMMENT].nil? ? nil : row_update[COMMENT].force_encoding('ASCII-8BIT')
|
||||
|
||||
if row_update[NAME].nil? || row_update[NAME].empty?
|
||||
@error_msg = I18n.t('error.update.name_empty')
|
||||
return false
|
||||
end
|
||||
|
||||
if update
|
||||
@data[i] = row_update
|
||||
else
|
||||
@data.push(row_update)
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
# Remove an item
|
||||
# @args: id -> the item's identifiant
|
||||
# @rtrn: true if the item has been deleted
|
||||
def remove(id)
|
||||
i = 0
|
||||
@data.each do |row|
|
||||
if row[ID] == id
|
||||
@data.delete_at(i)
|
||||
return true
|
||||
end
|
||||
i += 1
|
||||
end
|
||||
|
||||
@error_msg = I18n.t('error.delete.id_no_exist', :id => id)
|
||||
return false
|
||||
end
|
||||
|
||||
# Export to csv
|
||||
# @args: file -> a string to match
|
||||
# @rtrn: true if export work
|
||||
def export(file)
|
||||
begin
|
||||
File.open(file, 'w+') do |file|
|
||||
@data.each do |row|
|
||||
row.delete_at(ID).delete_at(DATE)
|
||||
file << row.to_csv
|
||||
end
|
||||
end
|
||||
|
||||
return true
|
||||
rescue Exception => e
|
||||
@error_msg = "#{I18n.t('error.export.write', :file => file)}\n#{e}"
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
# Import to csv
|
||||
# @args: file -> path to file import
|
||||
# @rtrn: true if the import work
|
||||
def import(file)
|
||||
begin
|
||||
data_new = IO.read(file)
|
||||
data_new.lines do |line|
|
||||
if not line =~ /(.*,){6}/
|
||||
@error_msg = I18n.t('error.import.bad_format')
|
||||
return false
|
||||
else
|
||||
row = line.parse_csv.unshift(0)
|
||||
if not update(row[NAME], row[GROUP], row[SERVER], row[PROTOCOL], row[LOGIN], row[PASSWORD], row[PORT], row[COMMENT])
|
||||
return false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return true
|
||||
rescue Exception => e
|
||||
@error_msg = "#{I18n.t('error.import.read', :file => file)}\n#{e}"
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
# Return a preview import
|
||||
# @args: file -> path to file import
|
||||
# @rtrn: an array with the items to import, if there is an error return false
|
||||
def import_preview(file)
|
||||
begin
|
||||
result = Array.new()
|
||||
id = 0
|
||||
|
||||
data = IO.read(file)
|
||||
data.lines do |line|
|
||||
if not line =~ /(.*,){6}/
|
||||
@error_msg = I18n.t('error.import.bad_format')
|
||||
return false
|
||||
else
|
||||
result.push(line.parse_csv.unshift(id))
|
||||
end
|
||||
|
||||
id += 1
|
||||
end
|
||||
|
||||
return result
|
||||
rescue Exception => e
|
||||
@error_msg = "#{I18n.t('error.import.read', :file => file)}\n#{e}"
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
# Sync remote data and local data
|
||||
# @args: data_remote -> array with the data remote
|
||||
# last_update -> last update
|
||||
# @rtrn: false if data_remote is nil
|
||||
def sync(data_remote, last_update)
|
||||
if !data_remote.instance_of?(Array)
|
||||
return false
|
||||
end
|
||||
|
||||
@data.each do |l|
|
||||
j = 0
|
||||
update = false
|
||||
|
||||
# Update item
|
||||
data_remote.each do |r|
|
||||
if l[ID] == r[ID]
|
||||
if l[DATE].to_i < r[DATE].to_i
|
||||
update(r[NAME], r[GROUP], r[SERVER], r[PROTOCOL], r[LOGIN], r[PASSWORD], r[PORT], r[COMMENT], l[ID])
|
||||
end
|
||||
update = true
|
||||
data_remote.delete_at(j)
|
||||
break
|
||||
end
|
||||
j += 1
|
||||
end
|
||||
|
||||
# Delete an old item
|
||||
if !update && l[DATE].to_i < last_update
|
||||
remove(l[ID])
|
||||
end
|
||||
end
|
||||
|
||||
# Add item
|
||||
data_remote.each do |r|
|
||||
if r[DATE].to_i > last_update
|
||||
update(r[NAME], r[GROUP], r[SERVER], r[PROTOCOL], r[LOGIN], r[PASSWORD], r[PORT], r[COMMENT], r[ID])
|
||||
end
|
||||
end
|
||||
|
||||
return encrypt()
|
||||
end
|
||||
|
||||
# Generate a random password
|
||||
# @args: length -> the length password
|
||||
# @rtrn: a random string
|
||||
def self.password(length=8)
|
||||
if length.to_i <= 0
|
||||
length = 8
|
||||
else
|
||||
length = length.to_i
|
||||
end
|
||||
|
||||
result = ''
|
||||
while length > 62 do
|
||||
result << ([*('A'..'Z'),*('a'..'z'),*('0'..'9')]).sample(62).join
|
||||
length -= 62
|
||||
end
|
||||
result << ([*('A'..'Z'),*('a'..'z'),*('0'..'9')]).sample(length).join
|
||||
|
||||
return result
|
||||
end
|
||||
end
|
136
lib/MPWConfig.rb
136
lib/MPWConfig.rb
|
@ -1,136 +0,0 @@
|
|||
#!/usr/bin/ruby
|
||||
# author: nishiki
|
||||
# mail: nishiki@yaegashi.fr
|
||||
# info: a simple script who manage your passwords
|
||||
|
||||
require 'rubygems'
|
||||
require 'yaml'
|
||||
require 'i18n'
|
||||
|
||||
class MPWConfig
|
||||
|
||||
attr_accessor :error_msg
|
||||
|
||||
attr_accessor :key
|
||||
attr_accessor :lang
|
||||
attr_accessor :file_gpg
|
||||
attr_accessor :timeout_pwd
|
||||
attr_accessor :last_update
|
||||
attr_accessor :sync_host
|
||||
attr_accessor :sync_port
|
||||
attr_accessor :sync_pwd
|
||||
attr_accessor :sync_suffix
|
||||
attr_accessor :last_update
|
||||
|
||||
# Constructor
|
||||
# @args: file_config -> the specify config file
|
||||
def initialize(file_config=nil)
|
||||
@error_msg = nil
|
||||
@file_config = "#{Dir.home()}/.mpw.cfg"
|
||||
|
||||
if !file_config.nil? && !file_config.empty?
|
||||
@file_config = file_config
|
||||
end
|
||||
end
|
||||
|
||||
# Create a new config file
|
||||
# @args: key -> the gpg key to encrypt
|
||||
# lang -> the software language
|
||||
# file_gpg -> the file who is encrypted
|
||||
# timeout_pwd -> time to save the password
|
||||
# sync_host -> the server host for synchronization
|
||||
# sync_port -> the server port for synchronization
|
||||
# sync_pwd -> the password for synchronization
|
||||
# sync_suffix -> the suffix file (optionnal)
|
||||
# @rtrn: true if le config file is create
|
||||
def setup(key, lang, file_gpg, timeout_pwd, sync_host=nil, sync_port=nil, sync_pwd=nil, sync_suffix=nil)
|
||||
|
||||
if not key =~ /[a-zA-Z0-9.-_]+\@[a-zA-Z0-9]+\.[a-zA-Z]+/
|
||||
@error_msg = I18n.t('error.config.key_bad_format')
|
||||
return false
|
||||
end
|
||||
|
||||
if file_gpg.empty?
|
||||
file_gpg = "#{Dir.home()}/.mpw.gpg"
|
||||
end
|
||||
|
||||
timeout_pwd = timeout_pwd.empty? ? 60 : timeout_pwd.to_i
|
||||
|
||||
config = {'config' => {'key' => key,
|
||||
'lang' => lang,
|
||||
'file_gpg' => file_gpg,
|
||||
'timeout_pwd' => timeout_pwd,
|
||||
'sync_host' => sync_host,
|
||||
'sync_port' => sync_port,
|
||||
'sync_pwd' => sync_pwd,
|
||||
'sync_suffix' => sync_suffix,
|
||||
'last_update' => 0 }}
|
||||
|
||||
begin
|
||||
File.open(@file_config, 'w') do |file|
|
||||
file << config.to_yaml
|
||||
end
|
||||
rescue Exception => e
|
||||
@error_msg = "#{I18n.t('error.config.write')}\n#{e}"
|
||||
return false
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
# Check the config file
|
||||
# @rtrn: true if the config file is correct
|
||||
def checkconfig()
|
||||
begin
|
||||
config = YAML::load_file(@file_config)
|
||||
@key = config['config']['key']
|
||||
@lang = config['config']['lang']
|
||||
@file_gpg = config['config']['file_gpg']
|
||||
@timeout_pwd = config['config']['timeout_pwd'].to_i
|
||||
@sync_host = config['config']['sync_host']
|
||||
@sync_port = config['config']['sync_port']
|
||||
@sync_pwd = config['config']['sync_pwd']
|
||||
@sync_suffix = config['config']['sync_suffix']
|
||||
@last_update = config['config']['last_update'].to_i
|
||||
|
||||
if @key.empty? || @file_gpg.empty?
|
||||
@error_msg = I18n.t('error.config.check')
|
||||
return false
|
||||
end
|
||||
|
||||
I18n.locale = @lang.to_sym
|
||||
|
||||
rescue Exception => e
|
||||
@error_msg = "#{I18n.t('error.config.check')}\n#{e}"
|
||||
return false
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
# Set the last update when there is a sync
|
||||
# @rtrn: true is the file has been updated
|
||||
def set_last_update()
|
||||
config = {'config' => {'key' => @key,
|
||||
'lang' => @lang,
|
||||
'file_gpg' => @file_gpg,
|
||||
'timeout_pwd' => @timeout_pwd,
|
||||
'sync_host' => @sync_host,
|
||||
'sync_port' => @sync_port,
|
||||
'sync_pwd' => @sync_pwd,
|
||||
'sync_suffix' => @sync_suffix,
|
||||
'last_update' => Time.now.to_i }}
|
||||
|
||||
begin
|
||||
File.open(@file_config, 'w') do |file|
|
||||
file << config.to_yaml
|
||||
end
|
||||
rescue Exception => e
|
||||
@error_msg = "#{I18n.t('error.config.write')}\n#{e}"
|
||||
return false
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
end
|
128
lib/Sync.rb
128
lib/Sync.rb
|
@ -1,128 +0,0 @@
|
|||
#!/usr/bin/ruby
|
||||
# author: nishiki
|
||||
# mail: nishiki@yaegashi.fr
|
||||
# info: a simple script who manage your passwords
|
||||
|
||||
require 'rubygems'
|
||||
require 'i18n'
|
||||
require 'socket'
|
||||
require 'json'
|
||||
|
||||
require "#{APP_ROOT}/lib/MPW.rb"
|
||||
|
||||
class Sync
|
||||
|
||||
attr_accessor :error_msg
|
||||
attr_accessor :enable
|
||||
|
||||
# Constructor
|
||||
def initialize()
|
||||
@error_msg = nil
|
||||
@enable = false
|
||||
end
|
||||
|
||||
# Connect to server
|
||||
# @args: host -> the server host
|
||||
# port -> ther connection port
|
||||
# gpg_key -> the gpg key
|
||||
# password -> the remote password
|
||||
# suffix -> the suffix file
|
||||
# @rtrn: false if the connection fail
|
||||
def connect(host, port, gpg_key, password, suffix=nil)
|
||||
@gpg_key = gpg_key
|
||||
@password = password
|
||||
@suffix = suffix
|
||||
|
||||
begin
|
||||
@socket = TCPSocket.new(host, port)
|
||||
@enable = true
|
||||
rescue Exception => e
|
||||
@error_msg = "#{I18n.t('error.sync.connection')}\n#{e}"
|
||||
@enable = false
|
||||
end
|
||||
|
||||
return @enable
|
||||
end
|
||||
|
||||
# Get data on server
|
||||
# @args: gpg_password -> the gpg password
|
||||
# @rtrn: nil if nothing data or error
|
||||
def get(gpg_password)
|
||||
if !@enable
|
||||
return nil
|
||||
end
|
||||
|
||||
send_msg = {:action => 'get',
|
||||
:gpg_key => @gpg_key,
|
||||
:password => @password,
|
||||
:suffix => @suffix}
|
||||
|
||||
@socket.puts send_msg.to_json
|
||||
msg = JSON.parse(@socket.gets)
|
||||
|
||||
if !defined?(msg['error'])
|
||||
@error_msg = I18n.t('error.sync.communication')
|
||||
return nil
|
||||
elsif msg['error'].nil?
|
||||
tmp_file = "/tmp/mpw-#{MPW.password()}.gpg"
|
||||
File.open(tmp_file, 'w') do |file|
|
||||
file << msg['data']
|
||||
end
|
||||
|
||||
@mpw = MPW.new(tmp_file)
|
||||
if !@mpw.decrypt(gpg_password)
|
||||
puts @mpw.error_msg
|
||||
return nil
|
||||
end
|
||||
|
||||
File.unlink(tmp_file)
|
||||
return @mpw.search()
|
||||
else
|
||||
@error_msg = I18n.t(msg['error'])
|
||||
return nil
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
# Update the remote data
|
||||
# @args: data -> the data to send on server
|
||||
# @rtrn: false if there is a problem
|
||||
def update(data)
|
||||
if !@enable
|
||||
return true
|
||||
end
|
||||
|
||||
send_msg = {:action => 'update',
|
||||
:gpg_key => @gpg_key,
|
||||
:password => @password,
|
||||
:suffix => @suffix,
|
||||
:data => data}
|
||||
|
||||
@socket.puts send_msg.to_json
|
||||
msg = JSON.parse(@socket.gets)
|
||||
|
||||
if !defined?(msg['error'])
|
||||
@error_msg = I18n.t('error.sync.communication')
|
||||
return false
|
||||
elsif msg['error'].nil?
|
||||
return true
|
||||
else
|
||||
@error_msg = I18n.t(msg['error'])
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
# TODO
|
||||
def delete()
|
||||
end
|
||||
|
||||
# Close the connection
|
||||
def close()
|
||||
if !@enable
|
||||
return
|
||||
end
|
||||
|
||||
send_msg = {:action => 'close'}
|
||||
@socket.puts send_msg.to_json
|
||||
end
|
||||
end
|
6
mpw
6
mpw
|
@ -10,8 +10,8 @@ require 'locale'
|
|||
require 'i18n'
|
||||
|
||||
APP_ROOT = File.dirname(Pathname.new(__FILE__).realpath)
|
||||
require "#{APP_ROOT}/lib/Cli.rb"
|
||||
require "#{APP_ROOT}/lib/MPW.rb"
|
||||
require "#{APP_ROOT}/MPW/UI/Cli"
|
||||
require "#{APP_ROOT}/MPW/Config"
|
||||
|
||||
lang = Locale::Tag.parse(ENV['LANG']).to_simple.to_s[0..1]
|
||||
|
||||
|
@ -93,7 +93,7 @@ OptionParser.new do |opts|
|
|||
end
|
||||
end.parse!
|
||||
|
||||
config = MPWConfig.new(options[:config])
|
||||
config = MPW::Config.new(options[:config])
|
||||
check_error = config.checkconfig()
|
||||
|
||||
cli = Cli.new(lang, config)
|
||||
|
|
5
mpw-ssh
5
mpw-ssh
|
@ -10,7 +10,8 @@ require 'locale'
|
|||
require 'i18n'
|
||||
|
||||
APP_ROOT = File.dirname(Pathname.new(__FILE__).realpath)
|
||||
require "#{APP_ROOT}/lib/CliSSH.rb"
|
||||
require "#{APP_ROOT}/MPW/UI/CliSSH"
|
||||
require "#{APP_ROOT}/MPW/Config"
|
||||
|
||||
lang = Locale::Tag.parse(ENV['LANG']).to_simple.to_s[0..1]
|
||||
|
||||
|
@ -45,7 +46,7 @@ OptionParser.new do |opts|
|
|||
end
|
||||
end.parse!
|
||||
|
||||
config = MPWConfig.new(options[:config])
|
||||
config = MPW::Config.new(options[:config])
|
||||
check_error = config.checkconfig()
|
||||
|
||||
cli = CliSSH.new(lang, config)
|
||||
|
|
Loading…
Reference in a new issue