Update API documentation.

Mostly move things out of the public API by removing them from the docs,
but also add and correct docs where appropriate.
This commit is contained in:
Robert Haines 2024-03-02 14:52:24 +00:00
parent 9cfa01a479
commit e83bec471b
9 changed files with 113 additions and 63 deletions

View File

@ -57,9 +57,9 @@ module Zip
restore_ownership: false,
restore_permissions: true,
restore_times: true
}.freeze
}.freeze # :nodoc:
def reset!
def reset! # :nodoc:
@_ran_once = false
@unicode_names = false
@on_exists_proc = false
@ -73,6 +73,7 @@ module Zip
@validate_entry_sizes = true
end
# Set options for RubyZip in one block.
def setup
yield self unless @_ran_once
@_ran_once = true

View File

@ -1,6 +1,8 @@
# frozen_string_literal: true
module Zip
# :stopdoc:
RUNNING_ON_WINDOWS = RbConfig::CONFIG['host_os'] =~ /mswin|mingw|cygwin/i
CENTRAL_DIRECTORY_ENTRY_SIGNATURE = 0x02014b50
@ -116,4 +118,6 @@ module Zip
COMPRESSION_METHOD_PPMD => 'PPMd version I, Rev 1',
COMPRESSION_METHOD_AES => 'AES encryption'
}.freeze
# :startdoc:
end

View File

@ -9,16 +9,19 @@ module Zip
class Entry
include Dirtyable
# Constant used to specify that the entry is stored (i.e., not compressed).
STORED = ::Zip::COMPRESSION_METHOD_STORE
# Constant used to specify that the entry is deflated (i.e., compressed).
DEFLATED = ::Zip::COMPRESSION_METHOD_DEFLATE
# Language encoding flag (EFS) bit
EFS = 0b100000000000
EFS = 0b100000000000 # :nodoc:
# Compression level flags (used as part of the gp flags).
COMPRESSION_LEVEL_SUPERFAST_GPFLAG = 0b110
COMPRESSION_LEVEL_FAST_GPFLAG = 0b100
COMPRESSION_LEVEL_MAX_GPFLAG = 0b010
COMPRESSION_LEVEL_SUPERFAST_GPFLAG = 0b110 # :nodoc:
COMPRESSION_LEVEL_FAST_GPFLAG = 0b100 # :nodoc:
COMPRESSION_LEVEL_MAX_GPFLAG = 0b010 # :nodoc:
attr_accessor :comment, :compressed_size, :follow_symlinks, :name,
:restore_ownership, :restore_permissions, :restore_times,
@ -35,7 +38,7 @@ module Zip
:fstype=, :gp_flags=, :name=, :size=,
:unix_gid=, :unix_perms=, :unix_uid=
def set_default_vars_values
def set_default_vars_values # :nodoc:
@local_header_offset = 0
@local_header_size = nil # not known until local entry is created or read
@internal_file_attributes = 1
@ -63,11 +66,12 @@ module Zip
@unix_perms = nil
end
def check_name(name)
def check_name(name) # :nodoc:
raise EntryNameError, name if name.start_with?('/')
raise EntryNameError if name.length > 65_535
end
# Create a new Zip::Entry.
def initialize(
zipfile = '', name = '',
comment: '', size: nil, compressed_size: 0, crc: 0,
@ -103,18 +107,23 @@ module Zip
set_compression_level_flags
end
# Is this entry encrypted?
def encrypted?
gp_flags & 1 == 1
end
def incomplete?
def incomplete? # :nodoc:
gp_flags & 8 == 8
end
# The uncompressed size of the entry.
def size
@size || 0
end
# Get a timestamp component of this entry.
#
# Returns modification time by default.
def time(component: :mtime)
time =
if @extra['UniversalTime']
@ -130,14 +139,19 @@ module Zip
alias mtime time
# Get the last access time of this entry, if available.
def atime
time(component: :atime)
end
# Get the creation time of this entry, if available.
def ctime
time(component: :ctime)
end
# Set a timestamp component of this entry.
#
# Sets modification time by default.
def time=(value, component: :mtime)
@dirty = true
unless @extra.member?('UniversalTime') || @extra.member?('NTFS')
@ -152,30 +166,38 @@ module Zip
alias mtime= time=
# Set the last access time of this entry.
def atime=(value)
send(:time=, value, component: :atime)
end
# Set the creation time of this entry.
def ctime=(value)
send(:time=, value, component: :ctime)
end
# Return the compression method for this entry.
#
# Returns STORED if the entry is a directory or if the compression
# level is 0.
def compression_method
return STORED if ftype == :directory || @compression_level == 0
@compression_method
end
# Set the compression method for this entry.
def compression_method=(method)
@dirty = true
@compression_method = (ftype == :directory ? STORED : method)
end
# Does this entry use the ZIP64 extensions?
def zip64?
!@extra['Zip64'].nil?
end
def file_type_is?(type)
def file_type_is?(type) # :nodoc:
ftype == type
end
@ -190,14 +212,14 @@ module Zip
end
end
def name_is_directory? # :nodoc:all
def name_is_directory? # :nodoc:
@name.end_with?('/')
end
# Is the name a relative path, free of `..` patterns that could lead to
# path traversal attacks? This does NOT handle symlinks; if the path
# contains symlinks, this check is NOT enough to guarantee safety.
def name_safe?
def name_safe? # :nodoc:
cleanpath = Pathname.new(@name).cleanpath
return false unless cleanpath.relative?
@ -207,29 +229,29 @@ module Zip
::File.absolute_path(cleanpath.to_s, root).match?(/([A-Z]:)?#{naive}/i)
end
def local_entry_offset # :nodoc:all
def local_entry_offset # :nodoc:
local_header_offset + @local_header_size
end
def name_size
def name_size # :nodoc:
@name ? @name.bytesize : 0
end
def extra_size
def extra_size # :nodoc:
@extra ? @extra.local_size : 0
end
def comment_size
def comment_size # :nodoc:
@comment ? @comment.bytesize : 0
end
def calculate_local_header_size # :nodoc:all
def calculate_local_header_size # :nodoc:
LOCAL_ENTRY_STATIC_HEADER_LENGTH + name_size + extra_size
end
# check before rewriting an entry (after file sizes are known)
# that we didn't change the header size (and thus clobber file data or something)
def verify_local_header_size!
def verify_local_header_size! # :nodoc:
return if @local_header_size.nil?
new_size = calculate_local_header_size
@ -239,12 +261,12 @@ module Zip
"Local header size changed (#{@local_header_size} -> #{new_size})"
end
def cdir_header_size # :nodoc:all
def cdir_header_size # :nodoc:
CDIR_ENTRY_STATIC_HEADER_LENGTH + name_size +
(@extra ? @extra.c_dir_size : 0) + comment_size
end
def next_header_offset # :nodoc:all
def next_header_offset # :nodoc:
local_entry_offset + compressed_size
end
@ -270,12 +292,12 @@ module Zip
self
end
def to_s
def to_s # :nodoc:
@name
end
class << self
def read_c_dir_entry(io) # :nodoc:all
def read_c_dir_entry(io) # :nodoc:
path = if io.respond_to?(:path)
io.path
else
@ -288,7 +310,7 @@ module Zip
nil
end
def read_local_entry(io)
def read_local_entry(io) # :nodoc:
entry = new(io)
entry.read_local_entry(io)
entry
@ -299,7 +321,7 @@ module Zip
end
end
def unpack_local_entry(buf)
def unpack_local_entry(buf) # :nodoc:
@header_signature,
@version,
@fstype,
@ -314,7 +336,7 @@ module Zip
@extra_length = buf.unpack('VCCvvvvVVVvv')
end
def read_local_entry(io) # :nodoc:all
def read_local_entry(io) # :nodoc:
@dirty = false # No changes at this point.
@local_header_offset = io.tell
@ -356,7 +378,7 @@ module Zip
@local_header_size = calculate_local_header_size
end
def pack_local_entry
def pack_local_entry # :nodoc:
zip64 = @extra['Zip64']
[::Zip::LOCAL_ENTRY_SIGNATURE,
@version_needed_to_extract, # version needed to extract
@ -371,7 +393,7 @@ module Zip
@extra ? @extra.local_size : 0].pack('VvvvvvVVVvv')
end
def write_local_entry(io, rewrite: false) # :nodoc:all
def write_local_entry(io, rewrite: false) # :nodoc:
prep_local_zip64_extra
verify_local_header_size! if rewrite
@local_header_offset = io.tell
@ -383,7 +405,7 @@ module Zip
@local_header_size = io.tell - @local_header_offset
end
def unpack_c_dir_entry(buf)
def unpack_c_dir_entry(buf) # :nodoc:
@header_signature,
@version, # version of encoding software
@fstype, # filesystem type
@ -407,7 +429,7 @@ module Zip
@comment = buf.unpack('VCCvvvvvVVVvvvvvVV')
end
def set_ftype_from_c_dir_entry
def set_ftype_from_c_dir_entry # :nodoc:
@ftype = case @fstype
when ::Zip::FSTYPE_UNIX
@unix_perms = (@external_file_attributes >> 16) & 0o7777
@ -437,25 +459,25 @@ module Zip
end
end
def check_c_dir_entry_static_header_length(buf)
def check_c_dir_entry_static_header_length(buf) # :nodoc:
return unless buf.nil? || buf.bytesize != ::Zip::CDIR_ENTRY_STATIC_HEADER_LENGTH
raise Error, 'Premature end of file. Not enough data for zip cdir entry header'
end
def check_c_dir_entry_signature
def check_c_dir_entry_signature # :nodoc:
return if @header_signature == ::Zip::CENTRAL_DIRECTORY_ENTRY_SIGNATURE
raise Error, "Zip local header magic not found at location '#{local_header_offset}'"
end
def check_c_dir_entry_comment_size
def check_c_dir_entry_comment_size # :nodoc:
return if @comment && @comment.bytesize == @comment_length
raise ::Zip::Error, 'Truncated cdir zip entry header'
end
def read_extra_field(buf, local: false)
def read_extra_field(buf, local: false) # :nodoc:
if @extra.kind_of?(::Zip::ExtraField)
@extra.merge(buf, local: local) if buf
else
@ -463,7 +485,7 @@ module Zip
end
end
def read_c_dir_entry(io) # :nodoc:all
def read_c_dir_entry(io) # :nodoc:
@dirty = false # No changes at this point.
static_sized_fields_buf = io.read(::Zip::CDIR_ENTRY_STATIC_HEADER_LENGTH)
check_c_dir_entry_static_header_length(static_sized_fields_buf)
@ -503,7 +525,7 @@ module Zip
end
# rubocop:disable Style/GuardClause
def set_unix_attributes_on_path(dest_path)
def set_unix_attributes_on_path(dest_path) # :nodoc:
# Ignore setuid/setgid bits by default. Honour if @restore_ownership.
unix_perms_mask = (@restore_ownership ? 0o7777 : 0o1777)
if @restore_permissions && @unix_perms
@ -529,7 +551,7 @@ module Zip
::FileUtils.touch(dest_path, mtime: time) if @restore_times
end
def pack_c_dir_entry
def pack_c_dir_entry # :nodoc:
zip64 = @extra['Zip64']
[
@header_signature,
@ -556,7 +578,7 @@ module Zip
].pack('VCCvvvvvVVVvvvvvVV')
end
def write_c_dir_entry(io) # :nodoc:all
def write_c_dir_entry(io) # :nodoc:
prep_cdir_zip64_extra
case @fstype
@ -585,7 +607,7 @@ module Zip
io << @comment
end
def ==(other)
def ==(other) # :nodoc:
return false unless other.class == self.class
# Compares contents of local entry and exposed fields
@ -594,7 +616,7 @@ module Zip
end
end
def <=>(other)
def <=>(other) # :nodoc:
to_s <=> other.to_s
end
@ -661,7 +683,7 @@ module Zip
get_extra_attributes_from_path(@filepath)
end
def write_to_zip_output_stream(zip_output_stream) # :nodoc:all
def write_to_zip_output_stream(zip_output_stream) # :nodoc:
if ftype == :directory
zip_output_stream.put_next_entry(self)
elsif @filepath
@ -674,13 +696,13 @@ module Zip
end
end
def parent_as_string
def parent_as_string # :nodoc:
entry_name = name.chomp('/')
slash_index = entry_name.rindex('/')
slash_index ? entry_name.slice(0, slash_index + 1) : nil
end
def get_raw_input_stream(&block)
def get_raw_input_stream(&block) # :nodoc:
if @zipfile.respond_to?(:seek) && @zipfile.respond_to?(:read)
yield @zipfile
else
@ -688,7 +710,7 @@ module Zip
end
end
def clean_up
def clean_up # :nodoc:
@dirty = false # Any changes are written at this point.
end
@ -749,7 +771,7 @@ module Zip
# apply missing data from the zip64 extra information field, if present
# (required when file sizes exceed 2**32, but can be used for all files)
def parse_zip64_extra(for_local_header) # :nodoc:all
def parse_zip64_extra(for_local_header) # :nodoc:
return unless zip64?
if for_local_header

View File

@ -7,13 +7,17 @@ module Zip
# Error raised if an unsupported compression method is used.
class CompressionMethodError < Error
# The compression method that has caused this error.
attr_reader :compression_method
# Create a new CompressionMethodError with the specified incorrect
# compression method.
def initialize(method)
super()
@compression_method = method
end
# The message returned by this error.
def message
"Unsupported compression method: #{COMPRESSION_METHODS[@compression_method]}."
end
@ -21,13 +25,17 @@ module Zip
# Error raised if there is a problem while decompressing an archive entry.
class DecompressionError < Error
# The error from the underlying Zlib library that caused this error.
attr_reader :zlib_error
# Create a new DecompressionError with the specified underlying Zlib
# error.
def initialize(zlib_error)
super()
@zlib_error = zlib_error
end
# The message returned by this error.
def message
"Zlib error ('#{@zlib_error.message}') while inflating."
end
@ -36,11 +44,13 @@ module Zip
# Error raised when trying to extract an archive entry over an
# existing file.
class DestinationExistsError < Error
# Create a new DestinationExistsError with the clashing destination.
def initialize(destination)
super()
@destination = destination
end
# The message returned by this error.
def message
"Cannot create file or directory '#{@destination}'. " \
'A file already exists with that name.'
@ -50,12 +60,14 @@ module Zip
# Error raised when trying to add an entry to an archive where the
# entry name already exists.
class EntryExistsError < Error
# Create a new EntryExistsError with the specified source and name.
def initialize(source, name)
super()
@source = source
@name = name
end
# The message returned by this error.
def message
"'#{@source}' failed. Entry #{@name} already exists."
end
@ -63,11 +75,13 @@ module Zip
# Error raised when an entry name is invalid.
class EntryNameError < Error
# Create a new EntryNameError with the specified name.
def initialize(name = nil)
super()
@name = name
end
# The message returned by this error.
def message
if @name.nil?
'Illegal entry name. Names must have fewer than 65,536 characters.'
@ -80,13 +94,16 @@ module Zip
# Error raised if an entry is larger on extraction than it is advertised
# to be.
class EntrySizeError < Error
# The entry that has caused this error.
attr_reader :entry
# Create a new EntrySizeError with the specified entry.
def initialize(entry)
super()
@entry = entry
end
# The message returned by this error.
def message
"Entry '#{@entry.name}' should be #{@entry.size}B, but is larger when inflated."
end
@ -95,6 +112,7 @@ module Zip
# Error raised if a split archive is read. Rubyzip does not support reading
# split archives.
class SplitArchiveError < Error
# The message returned by this error.
def message
'Rubyzip cannot extract from split archives at this time.'
end
@ -102,13 +120,16 @@ module Zip
# Error raised if there is not enough metadata for the entry to be streamed.
class StreamingError < Error
# The entry that has caused this error.
attr_reader :entry
# Create a new StreamingError with the specified entry.
def initialize(entry)
super()
@entry = entry
end
# The message returned by this error.
def message
"The local header of this entry ('#{@entry.name}') does not contain " \
'the correct metadata for `Zip::InputStream` to be able to ' \

View File

@ -52,8 +52,9 @@ module Zip
extend Forwardable
extend FileSplit
IO_METHODS = [:tell, :seek, :read, :eof, :close].freeze
IO_METHODS = [:tell, :seek, :read, :eof, :close].freeze # :nodoc:
# The name of this zip archive.
attr_reader :name
# default -> false.

View File

@ -64,7 +64,7 @@ module Zip
end
end
class File
class File # :nodoc:
include FileSystem
end
end

View File

@ -1,5 +1,6 @@
# frozen_string_literal: true
##
module Zip
# InputStream is the basic class for reading zip entries in a
# zip file. It is possible to create a InputStream object directly,
@ -39,9 +40,8 @@ module Zip
#
# java.util.zip.ZipInputStream is the original inspiration for this
# class.
class InputStream
CHUNK_SIZE = 32_768
CHUNK_SIZE = 32_768 # :nodoc:
include ::Zip::IOExtras::AbstractInputStream
@ -60,6 +60,7 @@ module Zip
@complete_entry = nil
end
# Close this InputStream. All further IO will raise an IOError.
def close
@archive_io.close
end
@ -78,7 +79,7 @@ module Zip
open_entry
end
# Rewinds the stream to the beginning of the current entry
# Rewinds the stream to the beginning of the current entry.
def rewind
return if @current_entry.nil?
@ -115,7 +116,7 @@ module Zip
end
end
def open_buffer(filename_or_io, offset: 0)
def open_buffer(filename_or_io, offset: 0) # :nodoc:
warn 'open_buffer is deprecated!!! Use open instead!'
::Zip::InputStream.open(filename_or_io, offset: offset)
end
@ -123,7 +124,7 @@ module Zip
protected
def get_io(io_or_file, offset = 0)
def get_io(io_or_file, offset = 0) # :nodoc:
if io_or_file.respond_to?(:seek)
io = io_or_file.dup
io.seek(offset, ::IO::SEEK_SET)
@ -135,7 +136,7 @@ module Zip
end
end
def open_entry
def open_entry # :nodoc:
@current_entry = ::Zip::Entry.read_local_entry(@archive_io)
return if @current_entry.nil?
@ -154,14 +155,14 @@ module Zip
@current_entry
end
def get_decrypted_io
def get_decrypted_io # :nodoc:
header = @archive_io.read(@decrypter.header_bytesize)
@decrypter.reset!(header)
::Zip::DecryptedIo.new(@archive_io, @decrypter)
end
def get_decompressor
def get_decompressor # :nodoc:
return ::Zip::NullDecompressor if @current_entry.nil?
decompressed_size =
@ -182,11 +183,11 @@ module Zip
decompressor_class.new(@decrypted_io, decompressed_size)
end
def produce_input
def produce_input # :nodoc:
@decompressor.read(CHUNK_SIZE)
end
def input_finished?
def input_finished? # :nodoc:
@decompressor.eof
end
end

View File

@ -2,6 +2,7 @@
require 'forwardable'
##
module Zip
# ZipOutputStream is the basic class for writing zip files. It is
# possible to create a ZipOutputStream object directly, passing
@ -20,7 +21,6 @@ module Zip
#
# java.util.zip.ZipOutputStream is the original inspiration for this
# class.
class OutputStream
extend Forwardable
include ::Zip::IOExtras::AbstractOutputStream
@ -47,10 +47,10 @@ module Zip
@current_entry = nil
end
# Same as #initialize but if a block is passed the opened
# stream is passed to the block and closed when the block
# returns.
class << self
# Same as #initialize but if a block is passed the opened
# stream is passed to the block and closed when the block
# returns.
def open(file_name, encrypter: nil)
return new(file_name) unless block_given?
@ -114,7 +114,7 @@ module Zip
@current_entry = new_entry
end
def copy_raw_entry(entry)
def copy_raw_entry(entry) # :nodoc:
entry = entry.dup
raise Error, 'zip stream is closed' if @closed
raise Error, 'entry is not a ZipEntry' unless entry.kind_of?(Entry)
@ -185,7 +185,7 @@ module Zip
protected
def finish
def finish # :nodoc:
@compressor.finish
end

View File

@ -1,5 +1,5 @@
# frozen_string_literal: true
module Zip
VERSION = '3.0.0.alpha'
VERSION = '3.0.0.alpha' # :nodoc:
end