Class: LibGems::Package::TarInput
- Inherits:
-
Object
- Object
- LibGems::Package::TarInput
- Includes:
- Enumerable, FSyncDir
- Defined in:
- lib/libgems/package/tar_input.rb
Instance Attribute Summary collapse
-
#metadata ⇒ Object
readonly
Returns the value of attribute metadata.
Class Method Summary collapse
Instance Method Summary collapse
- #close ⇒ Object
- #each(&block) ⇒ Object
- #extract_entry(destdir, entry, expected_md5sum = nil) ⇒ Object
-
#initialize(io, security_policy = nil) ⇒ TarInput
constructor
A new instance of TarInput.
-
#load_gemspec(io) ⇒ Object
Attempt to YAML-load a gemspec from the given io parameter.
-
#zipped_stream(entry) ⇒ Object
Return an IO stream for the zipped entry.
Constructor Details
#initialize(io, security_policy = nil) ⇒ TarInput
Returns a new instance of TarInput.
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 |
# File 'lib/libgems/package/tar_input.rb', line 27 def initialize(io, security_policy = nil) @io = io @tarreader = LibGems::Package::TarReader.new @io = false data_sig, , data_dgst, = nil, nil, nil, nil dgst_algo = security_policy ? LibGems::Security::OPT[:dgst_algo] : nil @tarreader.each do |entry| case entry.full_name when "metadata" @metadata = load_gemspec entry.read = 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 LibGems.ensure_ssl_available sio = StringIO.new(entry.read) = dgst_algo.digest(sio.string) sio.rewind end gzis = Zlib::GzipReader.new(sio || entry) # YAML wants an instance of IO @metadata = load_gemspec(gzis) = true ensure gzis.close unless gzis.nil? end when 'metadata.gz.sig' = entry.read when 'data.tar.gz.sig' data_sig = entry.read when 'data.tar.gz' if security_policy LibGems.ensure_ssl_available data_dgst = dgst_algo.digest(entry.read) end end end if security_policy then LibGems.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 LibGems::Security::Policies.key? security_policy then # load one of the pre-defined security policies security_policy = LibGems::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 LibGems::Exception, "Unknown trust policy '#{security_policy}'" end end if data_sig && data_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(, , @metadata.cert_chain) rescue Exception => e raise "Couldn't verify metadata signature: #{e}" end elsif security_policy.only_signed raise LibGems::Exception, "Unsigned gem" else # FIXME: should display warning here (trust policy, but # either unsigned or badly signed gem file) end end @tarreader.rewind @fileops = LibGems::FileOperations.new raise LibGems::Package::FormatError, "No metadata found!" unless end |
Instance Attribute Details
#metadata ⇒ Object (readonly)
Returns the value of attribute metadata.
15 16 17 |
# File 'lib/libgems/package/tar_input.rb', line 15 def @metadata end |
Class Method Details
.open(io, security_policy = nil, &block) ⇒ Object
19 20 21 22 23 24 25 |
# File 'lib/libgems/package/tar_input.rb', line 19 def self.open(io, security_policy = nil, &block) is = new io, security_policy yield is ensure is.close if is end |
Instance Method Details
#close ⇒ Object
117 118 119 120 |
# File 'lib/libgems/package/tar_input.rb', line 117 def close @io.close @tarreader.close end |
#each(&block) ⇒ Object
122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 |
# File 'lib/libgems/package/tar_input.rb', line 122 def each(&block) @tarreader.each do |entry| next unless entry.full_name == "data.tar.gz" is = zipped_stream entry begin LibGems::Package::TarReader.new is do |inner| inner.each(&block) end ensure is.close if is end end @tarreader.rewind end |
#extract_entry(destdir, entry, expected_md5sum = nil) ⇒ Object
139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 |
# File 'lib/libgems/package/tar_input.rb', line 139 def extract_entry(destdir, entry, expected_md5sum = nil) if entry.directory? then dest = File.join destdir, entry.full_name if File.directory? dest then @fileops.chmod entry.header.mode, dest, :verbose => false else @fileops.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) @fileops.mkdir_p destdir, :mode => 0755, :verbose => false destfile = File.join destdir, File.basename(entry.full_name) @fileops.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 @fileops.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 LibGems::Package::BadCheckSum end end |
#load_gemspec(io) ⇒ Object
Attempt to YAML-load a gemspec from the given io parameter. Return nil if it fails.
185 186 187 188 189 |
# File 'lib/libgems/package/tar_input.rb', line 185 def load_gemspec(io) LibGems::Specification.from_yaml io rescue LibGems::Exception nil end |
#zipped_stream(entry) ⇒ Object
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.
205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 |
# File 'lib/libgems/package/tar_input.rb', line 205 def zipped_stream(entry) if defined? Rubinius or defined? Maglev then # these implementations have working Zlib zis = Zlib::GzipReader.new entry dis = zis.read is = StringIO.new(dis) else # This is Jamis Buck's Zlib workaround for some unknown issue entry.read(10) # skip the gzip header zis = Zlib::Inflate.new(-Zlib::MAX_WBITS) is = StringIO.new(zis.inflate(entry.read)) end ensure zis.finish if zis end |