<commit_before>#!/usr/bin/ruby
# author: nishiki
# mail: <EMAIL>
# 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 => <PASSWORD>).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|
			row[NAME].nil?    ? (name    = nil) : (name    = row[NAME].downcase)
			row[SERVER].nil?  ? (server  = nil) : (server  = row[SERVER].downcase)
			row[COMMENT].nil? ? (comment = nil) : (comment = row[COMMENT].downcase)

			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

		id.nil?	      || id.empty?       ? (row_update[ID]       = MPW.password(16)) : (row_update[ID]       = id)
		name.nil?     || name.empty?     ? (row_update[NAME]     = row[NAME])        : (row_update[NAME]     = name)
		group.nil?    || group.empty?    ? (row_update[GROUP]    = row[GROUP])       : (row_update[GROUP]    = group)
		server.nil?   || server.empty?   ? (row_update[SERVER]   = row[SERVER])      : (row_update[SERVER]   = server)
		protocol.nil? || protocol.empty? ? (row_update[PROTOCOL] = row[PROTOCOL])    : (row_update[PROTOCOL] = protocol)
		login.nil?    || login.empty?    ? (row_update[LOGIN]    = row[LOGIN])       : (row_update[LOGIN]    = login)
		passwd.nil?   || passwd.empty?   ? (row_update[PASSWORD] = row[PASSWORD])    : (row_update[PASSWORD] = passwd)
		port.nil?     || port.empty?     ? (row_update[PORT]     = row[PORT])        : (row_update[PORT]     = port)
		comment.nil?  || comment.empty?  ? (row_update[COMMENT]  = row[COMMENT])     : (row_update[COMMENT]  = comment)
		
		row_update[NAME].nil?     ? (row_update[NAME]     = row_update[NAME])     : (row_update[NAME]     = row_update[NAME].force_encoding('ASCII-8BIT'))
		row_update[GROUP].nil?    ? (row_update[GROUP]    = row_update[GROUP])    : (row_update[GROUP]    = row_update[GROUP].force_encoding('ASCII-8BIT'))
		row_update[SERVER].nil?   ? (row_update[SERVER]   = row_update[SERVER])   : (row_update[SERVER]   = row_update[SERVER].force_encoding('ASCII-8BIT'))
		row_update[PROTOCOL].nil? ? (row_update[PROTOCOL] = row_update[PROTOCOL]) : (row_update[PROTOCOL] = row_update[PROTOCOL].force_encoding('ASCII-8BIT'))
		row_update[LOGIN].nil?    ? (row_update[LOGIN]    = row_update[LOGIN])    : (row_update[LOGIN]    = row_update[LOGIN].force_encoding('ASCII-8BIT'))
		row_update[PASSWORD].nil? ? (row_update[PASSWORD] = row_update[PASSWORD]) : (row_update[PASSWORD] = row_update[PASSWORD].force_encoding('ASCII-<PASSWORD>'))
		row_update[COMMENT].nil?  ? (row_update[COMMENT]  = row_update[COMMENT])  : (row_update[COMMENT]  = row_update[COMMENT].force_encoding('ASCII-8BIT'))

		if row_update[NAME].nil? || row_update[NAME].empty?
			@error_msg = I18n.t('error.update.name_empty')
			return false
		end

		if update
			@data[i] = row_update
		else
			@data.push(row_update)
		end

		return true
	end
	<commit_msg>factorize the code<commit_after>#!/usr/bin/ruby
# author: nishiki
# mail: <EMAIL>
# 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=<PASSWORD>)
		@data = Array.new

		begin
			if File.exist?(@file_gpg)
				crypto = GPGME::Crypto.new(:armor => true)
				data_decrypt = crypto.decrypt(IO.read(@file_gpg), :password => <PASSWORD>).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
	
{'fraction_non_alphanumeric': 0.14515670864501468, 'fraction_numerical': 0.0057759681848309815, 'mean_word_length': 2.9104035542391706, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 49, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3126716', 'n_tokens_mistral': 4329, 'n_tokens_neox': 3921, 'n_words': 885}