Parent

Included Modules

Class Index [+]

Quicksearch

Gem::Package::TarInput

Attributes

metadata[R]

Public Class Methods

new(io, security_policy = nil) click to toggle source
     # File lib/rubygems/package/tar_input.rb, line 27
 27:   def initialize(io, security_policy = nil)
 28:     @io = io
 29:     @tarreader = Gem::Package::TarReader.new @io
 30:     has_meta = false
 31: 
 32:     data_sig, meta_sig, data_dgst, meta_dgst = nil, nil, nil, nil
 33:     dgst_algo = security_policy ? Gem::Security::OPT[:dgst_algo] : nil
 34: 
 35:     @tarreader.each do |entry|
 36:       case entry.full_name
 37:       when "metadata"
 38:         @metadata = load_gemspec entry.read
 39:         has_meta = true
 40:       when "metadata.gz"
 41:         begin
 42:           # if we have a security_policy, then pre-read the metadata file
 43:           # and calculate it's digest
 44:           sio = nil
 45:           if security_policy
 46:             Gem.ensure_ssl_available
 47:             sio = StringIO.new(entry.read)
 48:             meta_dgst = dgst_algo.digest(sio.string)
 49:             sio.rewind
 50:           end
 51: 
 52:           # Ruby 1.8 doesn't have encoding and YAML is UTF-8
 53:           args = [sio || entry]
 54:           args << { :external_encoding => Encoding::UTF_8 } if
 55:             Object.const_defined?(:Encoding)
 56: 
 57:           gzis = Zlib::GzipReader.new(*args)
 58: 
 59:           # YAML wants an instance of IO
 60:           @metadata = load_gemspec(gzis)
 61:           has_meta = true
 62:         ensure
 63:           gzis.close unless gzis.nil?
 64:         end
 65:       when 'metadata.gz.sig'
 66:         meta_sig = entry.read
 67:       when 'data.tar.gz.sig'
 68:         data_sig = entry.read
 69:       when 'data.tar.gz'
 70:         if security_policy
 71:           Gem.ensure_ssl_available
 72:           data_dgst = dgst_algo.digest(entry.read)
 73:         end
 74:       end
 75:     end
 76: 
 77:     if security_policy then
 78:       Gem.ensure_ssl_available
 79: 
 80:       # map trust policy from string to actual class (or a serialized YAML
 81:       # file, if that exists)
 82:       if String === security_policy then
 83:         if Gem::Security::Policies.key? security_policy then
 84:           # load one of the pre-defined security policies
 85:           security_policy = Gem::Security::Policies[security_policy]
 86:         elsif File.exist? security_policy then
 87:           # FIXME: this doesn't work yet
 88:           security_policy = YAML.load File.read(security_policy)
 89:         else
 90:           raise Gem::Exception, "Unknown trust policy '#{security_policy}'"
 91:         end
 92:       end
 93: 
 94:       if data_sig && data_dgst && meta_sig && meta_dgst then
 95:         # the user has a trust policy, and we have a signed gem
 96:         # file, so use the trust policy to verify the gem signature
 97: 
 98:         begin
 99:           security_policy.verify_gem(data_sig, data_dgst, @metadata.cert_chain)
100:         rescue Exception => e
101:           raise "Couldn't verify data signature: #{e}"
102:         end
103: 
104:         begin
105:           security_policy.verify_gem(meta_sig, meta_dgst, @metadata.cert_chain)
106:         rescue Exception => e
107:           raise "Couldn't verify metadata signature: #{e}"
108:         end
109:       elsif security_policy.only_signed
110:         raise Gem::Exception, "Unsigned gem"
111:       else
112:         # FIXME: should display warning here (trust policy, but
113:         # either unsigned or badly signed gem file)
114:       end
115:     end
116: 
117:     @tarreader.rewind
118: 
119:     unless has_meta then
120:       path = io.path if io.respond_to? :path
121:       error = Gem::Package::FormatError.new 'no metadata found', path
122:       raise error
123:     end
124:   end
open(io, security_policy = nil, &block) click to toggle source
    # File lib/rubygems/package/tar_input.rb, line 19
19:   def self.open(io, security_policy = nil,  &block)
20:     is = new io, security_policy
21: 
22:     yield is
23:   ensure
24:     is.close if is
25:   end

Public Instance Methods

close() click to toggle source
     # File lib/rubygems/package/tar_input.rb, line 126
126:   def close
127:     @io.close
128:     @tarreader.close
129:   end
each(&block) click to toggle source
     # File lib/rubygems/package/tar_input.rb, line 131
131:   def each(&block)
132:     @tarreader.each do |entry|
133:       next unless entry.full_name == "data.tar.gz"
134:       is = zipped_stream entry
135: 
136:       begin
137:         Gem::Package::TarReader.new is do |inner|
138:           inner.each(&block)
139:         end
140:       ensure
141:         is.close if is
142:       end
143:     end
144: 
145:     @tarreader.rewind
146:   end
extract_entry(destdir, entry, expected_md5sum = nil) click to toggle source
     # File lib/rubygems/package/tar_input.rb, line 148
148:   def extract_entry(destdir, entry, expected_md5sum = nil)
149:     if entry.directory? then
150:       dest = File.join destdir, entry.full_name
151: 
152:       if File.directory? dest then
153:         FileUtils.chmod entry.header.mode, dest, :verbose => false
154:       else
155:         FileUtils.mkdir_p dest, :mode => entry.header.mode, :verbose => false
156:       end
157: 
158:       fsync_dir dest
159:       fsync_dir File.join(dest, "..")
160: 
161:       return
162:     end
163: 
164:     # it's a file
165:     md5 = Digest::MD5.new if expected_md5sum
166:     destdir = File.join destdir, File.dirname(entry.full_name)
167:     FileUtils.mkdir_p destdir, :mode => 0755, :verbose => false
168:     destfile = File.join destdir, File.basename(entry.full_name)
169:     FileUtils.chmod 0600, destfile, :verbose => false rescue nil # Errno::ENOENT
170: 
171:     open destfile, "wb", entry.header.mode do |os|
172:       loop do
173:         data = entry.read 4096
174:         break unless data
175:         # HACK shouldn't we check the MD5 before writing to disk?
176:         md5 << data if expected_md5sum
177:         os.write(data)
178:       end
179: 
180:       os.fsync
181:     end
182: 
183:     FileUtils.chmod entry.header.mode, destfile, :verbose => false
184:     fsync_dir File.dirname(destfile)
185:     fsync_dir File.join(File.dirname(destfile), "..")
186: 
187:     if expected_md5sum && expected_md5sum != md5.hexdigest then
188:       raise Gem::Package::BadCheckSum
189:     end
190:   end
load_gemspec(io) click to toggle source

Attempt to YAML-load a gemspec from the given io parameter. Return nil if it fails.

     # File lib/rubygems/package/tar_input.rb, line 194
194:   def load_gemspec(io)
195:     Gem::Specification.from_yaml io
196:   rescue Gem::Exception
197:     nil
198:   end
zipped_stream(entry) click to toggle source

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.

     # File lib/rubygems/package/tar_input.rb, line 214
214:   def zipped_stream(entry)
215:     if defined? Rubinius or defined? Maglev then
216:       # these implementations have working Zlib
217:       zis = Zlib::GzipReader.new entry
218:       dis = zis.read
219:       is = StringIO.new(dis)
220:     else
221:       # This is Jamis Buck's Zlib workaround for some unknown issue
222:       entry.read(10) # skip the gzip header
223:       zis = Zlib::Inflate.new(-Zlib::MAX_WBITS)
224:       is = StringIO.new(zis.inflate(entry.read))
225:     end
226:   ensure
227:     zis.finish if zis
228:   end

Disabled; run with --debug to generate this.

[Validate]

Generated with the Darkfish Rdoc Generator 1.1.6.