A close reading of the ZIP spec insists that if bit 3 of the GP flags is set
then the archive cannot be read via `Zip::InputStream`. But in most cases
the correct information is present to be able to do so, both safely and
reliably, and v2.4 does allow this.
This commit ensures that behaviour is present in v3.0.
This method returns `true` if the time instance was created with accurate
timezone information. Ultimately, only those times parsed from binary
DOS format are missing accurate timezone information, but we need this
flag because ruby `Time` objects (from which `DOSTime` is decended) always
have a timezone set (usually whatever is local at the time).
This commit adds a parameter to the `File#extract` and `Entry#extract` methods
so that a base destination directory can be specified for extracting archives
in bulk to somewhere in the filesystem that isn't the current working
directory. This directory is `.` by default. It is combined with the entry
path - which shouldn't but could have relative directories (e.g. `..`) in it -
and tested for safety before extracting.
Resolves#540.
Previously the central directory Zip64 data was written even if it wasn't
strictly needed. The standard allows for entries to include Zip64 data
(say, if they are streamed and their size is unknown when writing the file
data) without needing any Zip64 data in the central directory. So now we
only write central directory Zip64 data if there are over 65535 files or
the file data is huge.
With Zip64 write support enabled by default, it's important that we
only store the extra data when we need to. This commit ensures that
the Zip64 extra data is included for an entry if its size is over
4GB, or if we don't know how big it will be at the point of writing
the local header data.
This commit also removes the need for the Zip64Placeholder extra
data field. Now we just use the Zip64 field itself and ensure it's
filled in correctly.
Previously if RubyZip attempted to create an archive with more than
64K entries, the central directory would truncate the count. `unzip`
and `zipinfo` would fail with an error message such as:
```
error: expected central file header signature not found (file #93272).
(please check that you have transferred or created the zipfile in the
appropriate BINARY mode and that you have compiled UnZip properly)
```
This generated a lot of confusion and a production issue since many
tools fail to decode a RubyZip-created archive if Zip64 is not enabled
for a large number of files. Since Zip64 support is now the norm,
enable this by default.
`GPFBit3Error` doesn't really mean anything to the general user, and
it's not descriptive of the issue at hand. This error is raised when a
zip file cannot be streamed via `InputStream`, so `StreamingError` makes
more sense.
Also standardize the error message while we're about it.
When reading an archive with `InputStream`, `Entry.ftype` was returning
`:file` for all entries, even if they were a directory. This is due to
various side-effects in many methods in `Entry`. This commit fixes the
behaviour, but not the side-effects.
Fixes#533.
Also, remove `Entry#extra=` as it makes no sense (and wasn't even being
tested).
And remove slightly odd test that was assuming an archive would not be
changed if its utime was changed - even if it was being changed back
immediately. This test was merely confirming that we weren't catching
timestamp changes correctly.
This also means that we no longer need to keep a copy of the original
set of `Entry`s or the central directory comment to test for changes.
For situations where a zip file has a lot of entries (e.g. #506) this
means we save a lot of memory, and a lot of time constructing the zip
file in memory.
Set it to true by default - because a new `Entry` is dirty by
definition, having not been written yet. Then make sure that an `Entry`
that is created by reading from a zip file is set as not dirty.