lib/io_streams/pgp/reader.rb in iostreams-0.19.0 vs lib/io_streams/pgp/reader.rb in iostreams-0.20.0
- old
+ new
@@ -12,34 +12,40 @@
# file_name_or_io: [String|IO]
# Name of file to read from
# Or, the IO stream to receive the decrypted contents
# passphrase: [String]
# Pass phrase for private key to decrypt the file with
- def self.open(file_name_or_io, passphrase: self.default_passphrase, binary: true)
+ def self.open(file_name_or_io, passphrase: self.default_passphrase, binary: true, &block)
raise(ArgumentError, 'Missing both passphrase and IOStreams::Pgp::Reader.default_passphrase') unless passphrase
- if IOStreams.reader_stream?(file_name_or_io)
- raise(NotImplementedError, 'Can only PGP Decrypt directly from a file name. Input streams are not yet supported.')
- else
- loopback = IOStreams::Pgp.pgp_version.to_f >= 2.1 ? '--pinentry-mode loopback' : ''
- command = "#{IOStreams::Pgp.executable} #{loopback} --batch --no-tty --yes --decrypt --passphrase-fd 0 #{file_name_or_io}"
- IOStreams::Pgp.logger.debug { "IOStreams::Pgp::Reader.open: #{command}" } if IOStreams::Pgp.logger
+ return read_file(file_name_or_io, passphrase: passphrase, binary: binary, &block) if file_name_or_io.is_a?(String)
- # Read decrypted contents from stdout
- Open3.popen3(command) do |stdin, stdout, stderr, waith_thr|
- stdin.puts(passphrase) if passphrase
- stdin.close
- result =
- begin
- stdout.binmode if binary
- yield(stdout)
- rescue Errno::EPIPE
- # Ignore broken pipe because gpg terminates early due to an error
- raise(Pgp::Failure, "GPG Failed reading from encrypted file: #{file_name_or_io}: #{stderr.read.chomp}")
- end
- raise(Pgp::Failure, "GPG Failed to decrypt file: #{file_name_or_io}: #{stderr.read.chomp}") unless waith_thr.value.success?
- result
- end
+ # PGP can only work against a file, not a stream, so create temp file.
+ IOStreams::File::Path.temp_file_name('iostreams_pgp') do |temp_file_name|
+ IOStreams.copy(file_name_or_io, temp_file_name, target_options: {streams: []})
+ read_file(temp_file_name, passphrase: passphrase, binary: binary, &block)
+ end
+ end
+
+ def self.read_file(file_name, passphrase: self.default_passphrase, binary: true)
+ loopback = IOStreams::Pgp.pgp_version.to_f >= 2.1 ? '--pinentry-mode loopback' : ''
+ command = "#{IOStreams::Pgp.executable} #{loopback} --batch --no-tty --yes --decrypt --passphrase-fd 0 #{file_name}"
+ IOStreams::Pgp.logger.debug { "IOStreams::Pgp::Reader.open: #{command}" } if IOStreams::Pgp.logger
+
+ # Read decrypted contents from stdout
+ Open3.popen3(command) do |stdin, stdout, stderr, waith_thr|
+ stdin.puts(passphrase) if passphrase
+ stdin.close
+ result =
+ begin
+ stdout.binmode if binary
+ yield(stdout)
+ rescue Errno::EPIPE
+ # Ignore broken pipe because gpg terminates early due to an error
+ raise(Pgp::Failure, "GPG Failed reading from encrypted file: #{file_name}: #{stderr.read.chomp}")
+ end
+ raise(Pgp::Failure, "GPG Failed to decrypt file: #{file_name}: #{stderr.read.chomp}") unless waith_thr.value.success?
+ result
end
end
private