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
.txt extension in the central directory header, but with .exe in 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.
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
FileHeaderstruct.Instances in which a user might want to have access to the local header include:
.txtextension in the central directory header, but with.exein 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:
This would allow users to explicitly request a read of the local file header for a given
zip.File.