-
Notifications
You must be signed in to change notification settings - Fork 18.8k
Description
In a zip archive, file information is stored in two locations: the central directory header, and a local file header located prior to the file's data. In certain circumstances, a user might want to read information from the local file header as opposed to solely the central directory header. The current implementation relies solely on the central directory header to compute the FileHeader struct.
Instances in which a user might want to have access to the local header include:
- comparing the central and local file names to detect potential malicious activity (such as naming a file with a
.txtextension in the central directory header, but with.exein the local file header) - detecting potential archive corruption (such as when a file contains a trailing slash in the central directory header, but the correct character in the local file header)
Currently, if a user wanted to read the local file header, they would need to implement their own zip reader, as no export would allow them the raw access to the underlying reader necessary to read the local file header.
Ideally, the solution would not introduce additional unnecessary reads for users who don't care about the local file header. One potential solution would be the addition of the following function:
func (f *File) ReadLocalHeader() (FileHeader, error) {
var buf [fileHeaderLen]byte
if _, err := f.zipr.ReadAt(buf[:], f.headerOffset); err != nil {
return FileHeader{}, err
}
b := readBuf(buf[:])
if sig := b.uint32(); sig != fileHeaderSignature {
return FileHeader{}, ErrFormat
}
h := FileHeader{}
h.ReaderVersion = b.uint16()
h.Flags = b.uint16()
h.Method = b.uint16()
h.ModifiedTime = b.uint16()
h.ModifiedDate = b.uint16()
h.CRC32 = b.uint32()
h.CompressedSize = b.uint32()
h.UncompressedSize = b.uint32()
h.CompressedSize64 = uint64(h.CompressedSize)
h.UncompressedSize64 = uint64(h.UncompressedSize)
filenameLen := int(b.uint16())
d := make([]byte, filenameLen)
if _, err := f.zipr.ReadAt(d[:], f.headerOffset+fileHeaderLen); err != nil {
return FileHeader{}, err
}
h.Name = string(d[:filenameLen])
return h, nil
}This would allow users to explicitly request a read of the local file header for a given zip.File.
Metadata
Metadata
Assignees
Labels
Type
Projects
Status