From 40240934c555cbfefbe7b010be33366301207e44 Mon Sep 17 00:00:00 2001
From: nishiki <nishiki@yaegashi.fr>
Date: Sat, 7 Feb 2015 00:10:39 +0100
Subject: [PATCH] unstable: new sync class

---
 lib/MPW.rb      |  46 +-----------
 lib/Sync/SSH.rb | 191 +++++++++++++++++++++++-------------------------
 lib/UI/Cli.rb   |  51 ++-----------
 3 files changed, 98 insertions(+), 190 deletions(-)

diff --git a/lib/MPW.rb b/lib/MPW.rb
index 9bb0e1a..fae4e95 100644
--- a/lib/MPW.rb
+++ b/lib/MPW.rb
@@ -1,7 +1,6 @@
 #!/usr/bin/ruby
 # author: nishiki
 # mail: nishiki@yaegashi.fr
-# info: a simple script who manage your passwords
 
 require 'rubygems'
 require 'gpgme'
@@ -276,50 +275,7 @@ module MPW
 			return false
 		end
 	
-		# Sync remote data and local data
-		# @args: data_remote -> array with the data remote
-		#        last_update -> last update
-		# @rtrn: false if data_remote is nil
-		def sync(data_remote, last_update)
-			if not data_remote.instance_of?(Array)
-				@error_msg = I18n.t('error.sync.array')
-				return false
-			else not data_remote.to_s.empty?
-				@data.each_value do |l|
-					j = 0
-					update = false
-		
-					# Update item
-					data_remote.each do |r|
-						if l['id'] == r['id']
-							if l['date'].to_i < r['date'].to_i
-								update(r['name'], r['group'], r['host'], r['protocol'], r['login'], r['password'], r['port'], r['comment'], l['id'])
-							end
-							update = true
-							data_remote.delete(r['id'])
-							break
-						end
-						j += 1
-					end
-		
-					# Delete an old item
-					if not update and l['date'].to_i < last_update
-						remove(l['id'])
-					end
-				end
-			end
-	
-			# Add item
-			data_remote.each do |r|
-				if r['date'].to_i > last_update
-					update(r['name'], r['group'], r['host'], r['protocol'], r['login'], r['password'], r['port'], r['comment'], r['id'])
-				end
-			end
-	
-			return encrypt
-		end
-	
-		# Generate a random password
+	# Generate a random password
 		# @args: length -> the length password
 		# @rtrn: a random string
 		def self.password(length=8)
diff --git a/lib/Sync/SSH.rb b/lib/Sync/SSH.rb
index 9ebca2d..d61531b 100644
--- a/lib/Sync/SSH.rb
+++ b/lib/Sync/SSH.rb
@@ -1,110 +1,99 @@
 #!/usr/bin/ruby
 # author: nishiki
 # mail: nishiki@yaegashi.fr
-# info: a simple script who manage your passwords
 
-module MPW
-
-	module Sync
-
-		require 'rubygems'
-		require 'i18n'
-		require 'net/ssh'
-		require 'net/scp'
-		
-		class SSH
-		
-			attr_accessor :error_msg
-			attr_accessor :enable
-		
-			# Constructor
-			def initialize
-				@error_msg = nil
-				@enable    = false
-			end
-		
-			# Connect to server
-			# @args: host -> the server host
-			#        port -> ther connection port
-			#        gpg_key -> the gpg key
-			#        password -> the remote password
-			#        suffix -> the suffix file
-			# @rtrn: false if the connection fail
-			def connect(host, user, password, path, port=nil)
-				@host     = host
-				@user     = user
-				@password = password
-				@path     = path
-				@port     = port.instance_of?(Integer) ? 22 : port
-					
-				Net::SSH.start(@host, @user, password: @password, port: @port) do
-					@enable = true
-				end
-			rescue Exception => e
-				@error_msg = "#{I18n.t('error.sync.connection')}\n#{e}"
-				@enable    = false
-			else
-				return @enable
-			end
-		
-			# Get data on server
-			# @args: gpg_password -> the gpg password
-			# @rtrn: nil if nothing data or error
-			def get(gpg_key, gpg_password)
-				return nil if not @enable
-				
-				tmp_file = tmpfile
-				Net::SCP.start(@host, @user, password: @password, port: @port) do |scp|
-					scp.download!(@path, tmp_file)
-				end
-			
-				mpw = MPW.new(tmp_file, gpg_key)
-				if not mpw.decrypt(gpg_password)
-					@error_msg = mpw.error_msg
-					return nil
-				end
-		
-				File.unlink(tmp_file)
-				return mpw.search
-			rescue Exception => e
-				@error_msg = "#{I18n.t('error.sync.download')}\n#{e}"
-				return nil
-			end
-		
-			# Update the remote data
-			# @args: data -> the data to send on server
-			# @rtrn: false if there is a problem
-			def update(data)
-				return true if not @enable
-		
-				tmp_file = tmpfile
-				File.open(tmp_file, "w") do |file|
-					file << data
-				end
-
-				Net::SCP.start(@host, @user, password: @password, port: @port) do |scp|
-					scp.upload!(tmp_file, @path)
-				end
-
-				File.unlink(tmp_file)
-
-				return true
-			rescue Exception => e
-				@error_msg = "#{I18n.t('error.sync.upload')}\n#{e}"
-				return false
-			end
-
-			# Generate a random string
-			# @rtrn: a random string
-			def tmpfile
-				result = ''
-				result << ([*('A'..'Z'),*('a'..'z'),*('0'..'9')]).sample(6).join
-		
-				return "/tmp/mpw-#{result}"
-			end
+require 'rubygems'
+require 'i18n'
+require 'yaml'
+require 'tempfile'
+require 'net/ssh'
+require 'net/scp'
 	
+module MPW
+	class SyncSSH
+	
+		attr_accessor :error_msg
+		attr_accessor :enable
+	
+		# Constructor
+		# @args: host -> the server host
+		#        port -> ther connection port
+		#        gpg_key -> the gpg key
+		#        password -> the remote password
+		def initialize(host, user, password, path, port=nil)
+			@error_msg = nil
+			@enable    = false
+
+			@host      = host
+			@user      = user
+			@password  = password
+			@path      = path
+			@port      = port.instance_of?(Integer) ? 22 : port
+		end
+	
+		# Connect to server
+		# @rtrn: false if the connection fail
+		def connect
+			Net::SSH.start(@host, @user, password: @password, port: @port) do
+				@enable = true
+			end
+		rescue Exception => e
+			@error_msg = "#{I18n.t('error.sync.connection')}\n#{e}"
+			@enable    = false
+		else
+			return @enable
+		end
+	
+		# Get data on server
+		# @args: gpg_password -> the gpg password
+		# @rtrn: nil if nothing data or error
+		def get(gpg_key, gpg_password)
+			return nil if not @enable
+			
+			file_tmp = Tempfile.new('mpw')
+			Net::SCP.start(@host, @user, password: @password, port: @port) do |scp|
+				scp.download!(@path, file_tmp.path)
+			end
+		
+			mpw = MPW.new(file_tmp, gpg_key)
+			raise mpw.error_msg if not mpw.decrypt(gpg_password)
+	
+			file_tmp.close(true)
+
+			return mpw.list
+		rescue Exception => e
+			@error_msg = "#{I18n.t('error.sync.download')}\n#{e}"
+			file_tmp.close(true)
+			return nil
+		end
+	
+		# Update the remote data
+		# @args: items -> the data to send on server
+		# @rtrn: false if there is a problem
+		def update(items)
+			return true if not @enable
+	
+			file_tmp = Tempfile.new('mpw')
+
+			mpw = MPW.new(file_tmp, gpg_key)
+			items.each do |item|
+				mpw.add(item)
+			end
+
+			raise(mpw.error_msg) if not mpw.encrypt
+
+			Net::SCP.start(@host, @user, password: @password, port: @port) do |scp|
+				scp.upload!(file_tmp, @path)
+			end
+
+			file_tmp.close(true)
+
+			return true
+		rescue Exception => e
+			@error_msg = "#{I18n.t('error.sync.upload')}\n#{e}"
+			file_tmp.close(true)
+			return false
 		end
 
 	end
-
 end
diff --git a/lib/UI/Cli.rb b/lib/UI/Cli.rb
index c0d4f44..b31f426 100644
--- a/lib/UI/Cli.rb
+++ b/lib/UI/Cli.rb
@@ -11,6 +11,7 @@ require 'i18n'
 require 'colorize'
 
 require "#{APP_ROOT}/lib/MPW"
+require "#{APP_ROOT}/lib/Sync"
 
 class Cli
 
@@ -24,52 +25,14 @@ class Cli
 	# Sync the data with the server
 	# @rtnr: true if the synchro is finish
 	def sync
-		if not defined?(@sync)
-			case @config.sync_type
-			when 'mpw'
-				require "#{APP_ROOT}/lib/Sync/MPWSync"
-				@sync = MPW::Sync::MPWSync.new
-			when 'sftp', 'scp', 'ssh'
-				require "#{APP_ROOT}/lib/Sync/SSH"
-				@sync = MPW::Sync::SSH.new
-			when 'ftp'
-				require "#{APP_ROOT}/lib/Sync/FTP"
-				@sync = MPW::Sync::FTP.new
-			else
-				return false
-			end
-		end
+		@sync = MPW::Sync.new(@config, @password, @mpw.list) 
 
-		if  not @config.sync_host.nil? and not @config.sync_port.nil?
-			if not @sync.connect(@config.sync_host, @config.sync_user, @config.sync_pwd, @config.sync_path, @config.sync_port)
-				puts "#{I18n.t('display.error')} #1: #{@sync.error_msg}".red
-			end
-		end
+		raise(@sync.error_msg) if not @sync.get_remote
+		raise(@sync.error_msg) if not @sync.sync
 
-		if @sync.enable
-			if not @mpw.sync(@sync.get(@config.key, @passwd), @config.last_update)
-				puts "#{I18n.t('display.error')} #2: #{@mpw.error_msg}".red  if not @mpw.error_msg.nil?
-				puts "#{I18n.t('display.error')} #3: #{@sync.error_msg}".red if not @sync.error_msg.nil?
-
-			elsif not @sync.update(File.open(@config.file_gpg).read)
-				puts "#{I18n.t('display.error')} #4: #{@sync.error_msg}".red
-
-			elsif not @config.set_last_update
-				puts "#{I18n.t('display.error')} #5: #{@config.error_msg}".red
-
-			elsif not @mpw.encrypt
-				puts "#{I18n.t('display.error')} #6: #{@mpw.error_msg}".red
-
-			else
-				return true
-			end
-		end
+		return true
 	rescue Exception => e
 		puts "#{I18n.t('display.error')} #7: #{e}".red
-		puts @sync.error_msg   if not @sync.error_msg.nil?
-		puts @config.error_msg if not @config.error_msg.nil?
-		puts @mpw.error_msg    if not @mpw.error_msg.nil?
-	else
 		return false
 	end
 
@@ -160,8 +123,8 @@ class Cli
 			@mpw = MPW::MPW.new(@config.file_gpg, @config.key, @config.share_keys)
 		end
 
-		@passwd = ask(I18n.t('display.gpg_password')) {|q| q.echo = false}
-		if not @mpw.decrypt(@passwd)
+		@password = ask(I18n.t('display.gpg_password')) {|q| q.echo = false}
+		if not @mpw.decrypt(@password)
 			puts "#{I18n.t('display.error')} #11: #{@mpw.error_msg}".red
 			exit 2
 		end