diff options
Diffstat (limited to 'lib/rubygems/package/tar_input.rb')
-rw-r--r-- | lib/rubygems/package/tar_input.rb | 235 |
1 files changed, 0 insertions, 235 deletions
diff --git a/lib/rubygems/package/tar_input.rb b/lib/rubygems/package/tar_input.rb deleted file mode 100644 index 77b4d698da..0000000000 --- a/lib/rubygems/package/tar_input.rb +++ /dev/null @@ -1,235 +0,0 @@ -# -*- coding: iso-8859-1 -*- -#++ -# Copyright (C) 2004 Mauricio Julio Fernández Pradier -# See LICENSE.txt for additional licensing information. -#-- - -require 'zlib' -Gem.load_yaml - -class Gem::Package::TarInput - - include Gem::Package::FSyncDir - include Enumerable - - attr_reader :metadata - - private_class_method :new - - def self.open(io, security_policy = nil, &block) - is = new io, security_policy - - yield is - ensure - is.close if is - end - - def initialize(io, security_policy = nil) - @io = io - @tarreader = Gem::Package::TarReader.new @io - has_meta = false - - data_sig, meta_sig, data_dgst, meta_dgst = nil, nil, nil, nil - dgst_algo = security_policy ? Gem::Security::OPT[:dgst_algo] : nil - - @tarreader.each do |entry| - case entry.full_name - when "metadata" - @metadata = load_gemspec entry.read - has_meta = true - when "metadata.gz" - begin - # if we have a security_policy, then pre-read the metadata file - # and calculate it's digest - sio = nil - if security_policy - Gem.ensure_ssl_available - sio = StringIO.new(entry.read) - meta_dgst = dgst_algo.digest(sio.string) - sio.rewind - end - - # Ruby 1.8 doesn't have encoding and YAML is UTF-8 - args = [sio || entry] - args << { :external_encoding => Encoding::UTF_8 } if - Object.const_defined?(:Encoding) - - gzis = Zlib::GzipReader.new(*args) - - # YAML wants an instance of IO - @metadata = load_gemspec(gzis) - has_meta = true - ensure - gzis.close unless gzis.nil? - end - when 'metadata.gz.sig' - meta_sig = entry.read - when 'data.tar.gz.sig' - data_sig = entry.read - when 'data.tar.gz' - if security_policy - Gem.ensure_ssl_available - data_dgst = dgst_algo.digest(entry.read) - end - end - end - - if security_policy then - Gem.ensure_ssl_available - - # map trust policy from string to actual class (or a serialized YAML - # file, if that exists) - if String === security_policy then - if Gem::Security::Policies.key? security_policy then - # load one of the pre-defined security policies - security_policy = Gem::Security::Policies[security_policy] - elsif File.exist? security_policy then - # FIXME: this doesn't work yet - security_policy = YAML.load File.read(security_policy) - else - raise Gem::Exception, "Unknown trust policy '#{security_policy}'" - end - end - - if data_sig && data_dgst && meta_sig && meta_dgst then - # the user has a trust policy, and we have a signed gem - # file, so use the trust policy to verify the gem signature - - begin - security_policy.verify_gem(data_sig, data_dgst, @metadata.cert_chain) - rescue Exception => e - raise "Couldn't verify data signature: #{e}" - end - - begin - security_policy.verify_gem(meta_sig, meta_dgst, @metadata.cert_chain) - rescue Exception => e - raise "Couldn't verify metadata signature: #{e}" - end - elsif security_policy.only_signed - raise Gem::Exception, "Unsigned gem" - else - # FIXME: should display warning here (trust policy, but - # either unsigned or badly signed gem file) - end - end - - @tarreader.rewind - - unless has_meta then - path = io.path if io.respond_to? :path - error = Gem::Package::FormatError.new 'no metadata found', path - raise error - end - end - - def close - @io.close - @tarreader.close - end - - def each(&block) - @tarreader.each do |entry| - next unless entry.full_name == "data.tar.gz" - is = zipped_stream entry - - begin - Gem::Package::TarReader.new is do |inner| - inner.each(&block) - end - ensure - is.close if is - end - end - - @tarreader.rewind - end - - def extract_entry(destdir, entry, expected_md5sum = nil) - if entry.directory? then - dest = File.join destdir, entry.full_name - - if File.directory? dest then - FileUtils.chmod entry.header.mode, dest, :verbose => false - else - FileUtils.mkdir_p dest, :mode => entry.header.mode, :verbose => false - end - - fsync_dir dest - fsync_dir File.join(dest, "..") - - return - end - - # it's a file - md5 = Digest::MD5.new if expected_md5sum - destdir = File.join destdir, File.dirname(entry.full_name) - FileUtils.mkdir_p destdir, :mode => 0755, :verbose => false - destfile = File.join destdir, File.basename(entry.full_name) - FileUtils.chmod 0600, destfile, :verbose => false rescue nil # Errno::ENOENT - - open destfile, "wb", entry.header.mode do |os| - loop do - data = entry.read 4096 - break unless data - # HACK shouldn't we check the MD5 before writing to disk? - md5 << data if expected_md5sum - os.write(data) - end - - os.fsync - end - - FileUtils.chmod entry.header.mode, destfile, :verbose => false - fsync_dir File.dirname(destfile) - fsync_dir File.join(File.dirname(destfile), "..") - - if expected_md5sum && expected_md5sum != md5.hexdigest then - raise Gem::Package::BadCheckSum - end - end - - # Attempt to YAML-load a gemspec from the given _io_ parameter. Return - # nil if it fails. - def load_gemspec(io) - Gem::Specification.from_yaml io - rescue Gem::Exception - nil - end - - ## - # Return an IO stream for the zipped entry. - # - # NOTE: Originally this method used two approaches, Return a GZipReader - # directly, or read the GZipReader into a string and return a StringIO on - # the string. The string IO approach was used for versions of ZLib before - # 1.2.1 to avoid buffer errors on windows machines. Then we found that - # errors happened with 1.2.1 as well, so we changed the condition. Then - # we discovered errors occurred with versions as late as 1.2.3. At this - # point (after some benchmarking to show we weren't seriously crippling - # the unpacking speed) we threw our hands in the air and declared that - # this method would use the String IO approach on all platforms at all - # times. And that's the way it is. - # - # Revisited. Here's the beginning of the long story. - # http://osdir.com/ml/lang.ruby.gems.devel/2007-06/msg00045.html - # - # StringIO wraping has never worked as a workaround by definition. Skipping - # initial 10 bytes and passing -MAX_WBITS to Zlib::Inflate luckily works as - # gzip reader, but it only works if the GZip header is 10 bytes long (see - # below) and it does not check inflated stream consistency (CRC value in the - # Gzip trailer.) - # - # RubyGems generated Gzip Header: 10 bytes - # magic(2) + method(1) + flag(1) + mtime(4) + exflag(1) + os(1) + - # orig_name(0) + comment(0) - # - # Ideally, it must return a GZipReader without meaningless buffering. We - # have lots of CRuby committers around so let's fix windows build when we - # received an error. - def zipped_stream(entry) - Zlib::GzipReader.new entry - end - -end - |