2016-02-01 07:43:26 -05:00
|
|
|
# frozen_string_literal: true
|
2012-11-29 01:52:18 -05:00
|
|
|
#--
|
|
|
|
# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
|
|
|
|
# All rights reserved.
|
|
|
|
# See LICENSE.txt for permissions.
|
|
|
|
#++
|
|
|
|
|
|
|
|
##
|
|
|
|
# The format class knows the guts of the ancient .gem file format and provides
|
|
|
|
# the capability to read such ancient gems.
|
|
|
|
#
|
|
|
|
# Please pretend this doesn't exist.
|
|
|
|
|
|
|
|
class Gem::Package::Old < Gem::Package
|
|
|
|
|
|
|
|
undef_method :spec=
|
|
|
|
|
|
|
|
##
|
|
|
|
# Creates a new old-format package reader for +gem+. Old-format packages
|
|
|
|
# cannot be written.
|
|
|
|
|
2015-07-01 17:50:14 -04:00
|
|
|
def initialize gem, security_policy
|
2012-11-29 01:52:18 -05:00
|
|
|
require 'fileutils'
|
|
|
|
require 'zlib'
|
|
|
|
Gem.load_yaml
|
|
|
|
|
2013-02-08 19:24:55 -05:00
|
|
|
@contents = nil
|
|
|
|
@gem = gem
|
2015-07-01 17:50:14 -04:00
|
|
|
@security_policy = security_policy
|
2013-02-08 19:24:55 -05:00
|
|
|
@spec = nil
|
2012-11-29 01:52:18 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
##
|
|
|
|
# A list of file names contained in this gem
|
|
|
|
|
|
|
|
def contents
|
2013-02-07 17:48:35 -05:00
|
|
|
verify
|
|
|
|
|
2012-11-29 01:52:18 -05:00
|
|
|
return @contents if @contents
|
|
|
|
|
2014-09-13 23:30:02 -04:00
|
|
|
@gem.with_read_io do |io|
|
2012-11-29 01:52:18 -05:00
|
|
|
read_until_dashes io # spec
|
|
|
|
header = file_list io
|
|
|
|
|
|
|
|
@contents = header.map { |file| file['path'] }
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
##
|
|
|
|
# Extracts the files in this package into +destination_dir+
|
|
|
|
|
|
|
|
def extract_files destination_dir
|
2013-02-07 17:48:35 -05:00
|
|
|
verify
|
|
|
|
|
2012-11-29 01:52:18 -05:00
|
|
|
errstr = "Error reading files from gem"
|
|
|
|
|
2014-09-13 23:30:02 -04:00
|
|
|
@gem.with_read_io do |io|
|
2012-11-29 01:52:18 -05:00
|
|
|
read_until_dashes io # spec
|
|
|
|
header = file_list io
|
|
|
|
raise Gem::Exception, errstr unless header
|
|
|
|
|
|
|
|
header.each do |entry|
|
|
|
|
full_name = entry['path']
|
|
|
|
|
|
|
|
destination = install_location full_name, destination_dir
|
|
|
|
|
2016-02-01 07:43:26 -05:00
|
|
|
file_data = String.new
|
2012-11-29 01:52:18 -05:00
|
|
|
|
|
|
|
read_until_dashes io do |line|
|
|
|
|
file_data << line
|
|
|
|
end
|
|
|
|
|
|
|
|
file_data = file_data.strip.unpack("m")[0]
|
|
|
|
file_data = Zlib::Inflate.inflate file_data
|
|
|
|
|
|
|
|
raise Gem::Package::FormatError, "#{full_name} in #{@gem} is corrupt" if
|
|
|
|
file_data.length != entry['size'].to_i
|
|
|
|
|
|
|
|
FileUtils.rm_rf destination
|
|
|
|
|
|
|
|
FileUtils.mkdir_p File.dirname destination
|
|
|
|
|
|
|
|
open destination, 'wb', entry['mode'] do |out|
|
|
|
|
out.write file_data
|
|
|
|
end
|
|
|
|
|
2014-09-13 23:30:02 -04:00
|
|
|
verbose destination
|
2012-11-29 01:52:18 -05:00
|
|
|
end
|
|
|
|
end
|
|
|
|
rescue Zlib::DataError
|
|
|
|
raise Gem::Exception, errstr
|
|
|
|
end
|
|
|
|
|
|
|
|
##
|
|
|
|
# Reads the file list section from the old-format gem +io+
|
|
|
|
|
|
|
|
def file_list io # :nodoc:
|
2016-02-01 07:43:26 -05:00
|
|
|
header = String.new
|
2012-11-29 01:52:18 -05:00
|
|
|
|
|
|
|
read_until_dashes io do |line|
|
|
|
|
header << line
|
|
|
|
end
|
|
|
|
|
|
|
|
YAML.load header
|
|
|
|
end
|
|
|
|
|
|
|
|
##
|
|
|
|
# Reads lines until a "---" separator is found
|
|
|
|
|
|
|
|
def read_until_dashes io # :nodoc:
|
|
|
|
while (line = io.gets) && line.chomp.strip != "---" do
|
|
|
|
yield line if block_given?
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
##
|
|
|
|
# Skips the Ruby self-install header in +io+.
|
|
|
|
|
|
|
|
def skip_ruby io # :nodoc:
|
|
|
|
loop do
|
|
|
|
line = io.gets
|
|
|
|
|
|
|
|
return if line.chomp == '__END__'
|
|
|
|
break unless line
|
|
|
|
end
|
|
|
|
|
2017-10-07 21:32:18 -04:00
|
|
|
raise Gem::Exception, "Failed to find end of Ruby script while reading gem"
|
2012-11-29 01:52:18 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
##
|
|
|
|
# The specification for this gem
|
|
|
|
|
|
|
|
def spec
|
2013-02-07 17:48:35 -05:00
|
|
|
verify
|
|
|
|
|
2012-11-29 01:52:18 -05:00
|
|
|
return @spec if @spec
|
|
|
|
|
2016-02-01 07:43:26 -05:00
|
|
|
yaml = String.new
|
2012-11-29 01:52:18 -05:00
|
|
|
|
2014-09-13 23:30:02 -04:00
|
|
|
@gem.with_read_io do |io|
|
2012-11-29 01:52:18 -05:00
|
|
|
skip_ruby io
|
|
|
|
read_until_dashes io do |line|
|
|
|
|
yaml << line
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2013-02-08 19:24:55 -05:00
|
|
|
yaml_error = if RUBY_VERSION < '1.9' then
|
2013-02-07 18:58:42 -05:00
|
|
|
YAML::ParseError
|
2014-06-26 23:35:51 -04:00
|
|
|
elsif YAML.const_defined?(:ENGINE) && YAML::ENGINE.yamler == 'syck' then
|
2013-02-07 18:58:42 -05:00
|
|
|
YAML::ParseError
|
|
|
|
else
|
|
|
|
YAML::SyntaxError
|
|
|
|
end
|
|
|
|
|
|
|
|
begin
|
|
|
|
@spec = Gem::Specification.from_yaml yaml
|
2014-11-16 22:55:02 -05:00
|
|
|
rescue yaml_error
|
2013-02-07 18:58:42 -05:00
|
|
|
raise Gem::Exception, "Failed to parse gem specification out of gem file"
|
|
|
|
end
|
2014-11-16 22:55:02 -05:00
|
|
|
rescue ArgumentError
|
2012-11-29 01:52:18 -05:00
|
|
|
raise Gem::Exception, "Failed to parse gem specification out of gem file"
|
|
|
|
end
|
|
|
|
|
2013-02-07 17:48:35 -05:00
|
|
|
##
|
|
|
|
# Raises an exception if a security policy that verifies data is active.
|
|
|
|
# Old format gems cannot be verified as signed.
|
|
|
|
|
|
|
|
def verify
|
|
|
|
return true unless @security_policy
|
|
|
|
|
|
|
|
raise Gem::Security::Exception,
|
|
|
|
'old format gems do not contain signatures and cannot be verified' if
|
|
|
|
@security_policy.verify_data
|
|
|
|
|
|
|
|
true
|
|
|
|
end
|
|
|
|
|
2012-11-29 01:52:18 -05:00
|
|
|
end
|