Class: KeepassKpscript::Database

Inherits:
Object
  • Object
show all
Defined in:
lib/keepass_kpscript/database.rb

Overview

KPScript API handling a KeePass database

Instance Method Summary collapse

Constructor Details

#initialize(kpscript, database_file, password: nil, password_enc: nil, key_file: nil) ⇒ Database

Constructor At least 1 of password, password_enc or key_file is mandatory.

Parameters
  • kpscript (Kpscript): The KPScript instance handling this database

  • database_file (String): Database file path

  • password (String, SecretString or nil): Password opening the database, or nil if none [default: nil].

  • password_enc (String, SecretString or nil): Encrypted password opening the database, or nil if none [default: nil].

  • key_file (String, SecretString or nil): Key file path opening the database, or nil if none [default: nil].



21
22
23
24
25
26
27
28
# File 'lib/keepass_kpscript/database.rb', line 21

def initialize(kpscript, database_file, password: nil, password_enc: nil, key_file: nil)
  @kpscript = kpscript
  @database_file = database_file
  @password = password
  @password_enc = password_enc
  @key_file = key_file
  raise 'Please specify at least one of password, password_enc or key_file arguments' if @password.nil? && @password_enc.nil? && @key_file.nil?
end

Instance Method Details

#detach_bins(copy_to_dir: nil) ⇒ Object

Detach binaries.

Parameters
  • copy_to_dir (String or nil): Specify a directory in which binaries are extracted, or nil to extract next to the database file. [default: nil]

    If copy_to_dir is specified, then the directory will be created and a copy of the original database will be used to detach bins, leaving the original database untouched.
    


125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
# File 'lib/keepass_kpscript/database.rb', line 125

def detach_bins(copy_to_dir: nil)
  if copy_to_dir.nil?
    execute_kpscript('-c:DetachBins')
  else
    # Make a temporary copy of the database (as the KPScript extraction is destructive)
    FileUtils.mkdir_p copy_to_dir
    # Make a copy of the database in the directory first
    tmp_database = "#{copy_to_dir}/#{File.basename(@database_file)}.tmp.kdbx"
    FileUtils.cp @database_file, tmp_database
    begin
      @kpscript.open(tmp_database, password: @password, password_enc: @password_enc, key_file: @key_file).detach_bins
    ensure
      # Remove temporary database
      File.unlink tmp_database
    end
  end
end

#edit_entries(select, fields: {}, icon_idx: nil, custom_icon_idx: nil, expires: nil, expiry_time: nil, create_backup: false) ⇒ Object

Edit field values from entries.

Parameters
  • select (Select): The entries selector

  • fields (Hash<String or Symbol, String or SecretString>): Set of { field name => field value } to be set [default: {}]

  • icon_idx (Integer or nil): Set the icon index, or nil if none [default: nil]

  • custom_icon_idx (Integer or nil): Set the custom icon index, or nil if none [default: nil]

  • expires (Boolean or nil): Edit the expires flag, or nil to leave it untouched [default: nil]

  • expiry_time (Time or nil): Expiry time or nil to leave it untouched [default: nil]

  • create_backup (Boolean): Should we create backup of entries before modifying them? [default: false]



87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/keepass_kpscript/database.rb', line 87

def edit_entries(
  select,
  fields: {},
  icon_idx: nil,
  custom_icon_idx: nil,
  expires: nil,
  expiry_time: nil,
  create_backup: false
)
  args = [
    '-c:EditEntry',
    select.to_s
  ] + fields.map do |field_name, field_value|
    SecretString.new("-set-#{field_name}:\"#{field_value.to_unprotected}\"", silenced_str: "-set-#{field_name}:\"#{field_value}\"")
  end
  args << "-setx-Icon:#{icon_idx}" if icon_idx
  args << "-setx-CustomIcon:#{custom_icon_idx}" if custom_icon_idx
  args << "-setx-Expires:#{expires ? 'true' : 'false'}" unless expires.nil?
  args << "-setx-ExpiryTime:\"#{expiry_time.strftime('%FT%T')}\"" if expiry_time
  args << '-CreateBackup' if create_backup
  execute_kpscript(*args)
end

#entries_string(select, field, fail_if_not_exists: false, fail_if_no_entry: false, spr: false) ⇒ Object

Get field string values from entries.

Parameters
  • select (Select): The entries selector

  • field (String): Field to be selected

  • fail_if_not_exists (Boolean): Do we fail if the field does not exist? [default: false]

  • fail_if_no_entry (Boolean): Do we fail if no entry was found? [default: false]

  • spr (Boolean): So we Spr-compile the value of the retrieved field? [default: false]

Result
  • Array<String>: List of retrieved field values



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/keepass_kpscript/database.rb', line 59

def entries_string(
  select,
  field,
  fail_if_not_exists: false,
  fail_if_no_entry: false,
  spr: false
)
  args = [
    '-c:GetEntryString',
    select.to_s,
    "-Field:\"#{field}\""
  ]
  args << '-FailIfNotExists' if fail_if_not_exists
  args << '-FailIfNoEntry' if fail_if_no_entry
  args << '-Spr' if spr
  execute_kpscript(*args).split("\n")
end

#export(format, file, group_path: nil, xsl_file: nil) ⇒ Object

Export the database

Parameters
  • format (String): Format to export to (see the KeePass Export dialog for possible values).

  • file (String): File path to export to.

  • group_path (Array<String> or nil): Group path to export, or nil for all [default: nil]

  • xsl_file (String or nil): In case of transforming using XSL, this specifies the XSL file path to be used, or nil for none. [default: nil]



150
151
152
153
154
155
156
157
158
159
160
161
162
# File 'lib/keepass_kpscript/database.rb', line 150

def export(format, file, group_path: nil, xsl_file: nil)
  args = [
    '-c:Export',
    "-Format:\"#{format}\"",
    "-OutFile:\"#{file}\""
  ]
  args << "-GroupPath:\"#{group_path.join('/')}\"" if group_path
  args << "-XslFile:\"#{xsl_file}\"" if xsl_file
  case execute_kpscript(*args)
  when /E: Unknown format!/
    raise "Unknown format: #{format}"
  end
end

#password_for(title) ⇒ Object

Retrieve a password for a given entry title

Parameters
  • title (String): Entry title

Result
  • String: Corresponding password



116
117
118
# File 'lib/keepass_kpscript/database.rb', line 116

def password_for(title)
  entries_string(@kpscript.select.fields(Title: title), 'Password').first
end

#with_entries_string(*args, **kwargs) ⇒ Object

Securely select field values from entries. Using this will make sure the entries’ values are then erased from memory for security when exiting client code. Try to not clone or extrapolate those values in other String variables, or if you have to call SecretString.erase on those variables to also erase their content.

Parameters
  • Same parameters as #entries_string

  • Proc: Code called with the entries retrieved

    • Parameters
      • values (Array<String>)



39
40
41
42
43
44
45
46
47
# File 'lib/keepass_kpscript/database.rb', line 39

def with_entries_string(*args, **kwargs)
  values = []
  begin
    values = entries_string(*args, **kwargs).map { |str| SecretString.new(str) }
    yield values
  ensure
    values.each(&:erase)
  end
end