Class: Gem::Package::Old

Inherits:
Gem::Package show all
Defined in:
lib/rubygems/package/old.rb

Overview

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.

Instance Attribute Summary

Attributes inherited from Gem::Package

#build_time, #checksums, #data_mode, #dir_mode, #files, #gem, #prog_mode, #security_policy

Instance Method Summary collapse

Methods inherited from Gem::Package

#add_checksums, #add_contents, #add_files, #add_metadata, build, #build, #copy_stream, #copy_to, #digest, #extract_tar_gz, #file_mode, #gzip_to, #install_location, #limit_read, #load_spec, new, #normalize_path, #open_tar_gz, raw_spec, #read_checksums, #setup_signer, #verify_checksums, #verify_entry, #verify_files, #verify_gz

Methods included from UserInteraction

#alert, #alert_error, #alert_warning, #ask, #ask_for_password, #ask_yes_no, #choose_from_list, #say, #terminate_interaction, #verbose

Methods included from DefaultUserInteraction

ui, #ui, ui=, #ui=, use_ui, #use_ui

Methods included from Text

#clean_text, #format_text, #levenshtein_distance, #min3, #truncate_text

Constructor Details

#initialize(gem, security_policy) ⇒ Old

Creates a new old-format package reader for gem. Old-format packages cannot be written.



22
23
24
25
26
27
28
29
30
31
# File 'lib/rubygems/package/old.rb', line 22

def initialize(gem, security_policy)
  require "fileutils"
  require "zlib"
  Gem.load_yaml

  @contents        = nil
  @gem             = gem
  @security_policy = security_policy
  @spec            = nil
end

Instance Method Details

#contentsObject

A list of file names contained in this gem



36
37
38
39
40
41
42
43
44
45
46
47
# File 'lib/rubygems/package/old.rb', line 36

def contents
  verify

  return @contents if @contents

  @gem.with_read_io do |io|
    read_until_dashes io # spec
    header = file_list io

    @contents = header.map {|file| file["path"] }
  end
end

#extract_files(destination_dir) ⇒ Object

Extracts the files in this package into destination_dir



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
# File 'lib/rubygems/package/old.rb', line 52

def extract_files(destination_dir)
  verify

  errstr = "Error reading files from gem"

  @gem.with_read_io do |io|
    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

      file_data = String.new

      read_until_dashes io do |line|
        file_data << line
      end

      file_data = file_data.strip.unpack1("m")
      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), mode: dir_mode && 0o755

      File.open destination, "wb", file_mode(entry["mode"]) do |out|
        out.write file_data
      end

      verbose destination
    end
  end
rescue Zlib::DataError
  raise Gem::Exception, errstr
end

#file_list(io) ⇒ Object

Reads the file list section from the old-format gem io



97
98
99
100
101
102
103
104
105
# File 'lib/rubygems/package/old.rb', line 97

def file_list(io) # :nodoc:
  header = String.new

  read_until_dashes io do |line|
    header << line
  end

  Gem::SafeYAML.safe_load header
end

#read_until_dashes(io) ⇒ Object

Reads lines until a “—” separator is found



110
111
112
113
114
# File 'lib/rubygems/package/old.rb', line 110

def read_until_dashes(io) # :nodoc:
  while (line = io.gets) && line.chomp.strip != "---" do
    yield line if block_given?
  end
end

#skip_ruby(io) ⇒ Object

Skips the Ruby self-install header in io.

Raises:



119
120
121
122
123
124
125
126
127
128
# File 'lib/rubygems/package/old.rb', line 119

def skip_ruby(io) # :nodoc:
  loop do
    line = io.gets

    return if line.chomp == "__END__"
    break unless line
  end

  raise Gem::Exception, "Failed to find end of Ruby script while reading gem"
end

#specObject

The specification for this gem



133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
# File 'lib/rubygems/package/old.rb', line 133

def spec
  verify

  return @spec if @spec

  yaml = String.new

  @gem.with_read_io do |io|
    skip_ruby io
    read_until_dashes io do |line|
      yaml << line
    end
  end

  begin
    @spec = Gem::Specification.from_yaml yaml
  rescue Psych::SyntaxError
    raise Gem::Exception, "Failed to parse gem specification out of gem file"
  end
rescue ArgumentError
  raise Gem::Exception, "Failed to parse gem specification out of gem file"
end

#verifyObject

Raises an exception if a security policy that verifies data is active. Old format gems cannot be verified as signed.



160
161
162
163
164
165
166
167
168
# File 'lib/rubygems/package/old.rb', line 160

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