diff options
author | offtkp <parisoplop@gmail.com> | 2022-06-01 02:13:13 +0300 |
---|---|---|
committer | Tomaž Vajngerl <quikee@gmail.com> | 2022-06-12 09:29:53 +0200 |
commit | 932257c50c1dc9302b14862424e24e975f88bcc2 (patch) | |
tree | 3729b829e894462fd32aa2474b3dd2c2625614c8 /tools/source | |
parent | 988285410f8883ad49f32c4b804c4f5bd14569d0 (diff) |
Add compression support for GZ through ZCodec
ZCodec uses zlib to deflate. That file has code
to allow for compressing to GZ but it's wrapped in defines.
There's places in code where there's need for zlib headers
(ie. svx/source/gallery2/codec.cxx:71) and there will be need
for gz header compression when EMZ/WMZ/SVGZ export support
is added.
Made compression functions care about mbGzLib bool. Also added
a SetCompressionMetadata function to set metadata which are otherwise
impossible to know (such as filename, which is needed in the header)
Change-Id: Ic01050262b0b15e0632564b139c66656afac4611
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/135213
Tested-by: Jenkins
Reviewed-by: Tomaž Vajngerl <quikee@gmail.com>
Diffstat (limited to 'tools/source')
-rw-r--r-- | tools/source/zcodec/zcodec.cxx | 52 |
1 files changed, 45 insertions, 7 deletions
diff --git a/tools/source/zcodec/zcodec.cxx b/tools/source/zcodec/zcodec.cxx index 80daa1507a19..16248939f3d6 100644 --- a/tools/source/zcodec/zcodec.cxx +++ b/tools/source/zcodec/zcodec.cxx @@ -29,14 +29,15 @@ #include <tools/long.hxx> /* gzip flag byte */ -// GZ_ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */ -#define GZ_HEAD_CRC 0x02 /* bit 1 set: header CRC present */ -#define GZ_EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ -#define GZ_ORIG_NAME 0x08 /* bit 3 set: original file name present */ -#define GZ_COMMENT 0x10 /* bit 4 set: file comment present */ -#define GZ_RESERVED 0xE0 /* bits 5..7: reserved */ - +// GZ_ASCII_FLAG = 0x01; /* bit 0 set: file probably ascii text */ +constexpr sal_uInt8 GZ_HEAD_CRC = 0x02; /* bit 1 set: header CRC present */ +constexpr sal_uInt8 GZ_EXTRA_FIELD = 0x04; /* bit 2 set: extra field present */ +constexpr sal_uInt8 GZ_ORIG_NAME = 0x08; /* bit 3 set: original file name present */ +constexpr sal_uInt8 GZ_COMMENT = 0x10; /* bit 4 set: file comment present */ +constexpr sal_uInt8 GZ_RESERVED = 0xE0; /* bits 5..7: reserved */ constexpr sal_uInt16 GZ_MAGIC_BYTES_LE = 0x8B1F; /* gzip magic bytes, little endian */ +constexpr sal_uInt8 GZ_DEFLATE = 0x08; +constexpr sal_uInt8 GZ_FS_UNKNOWN = 0xFF; ZCodec::ZCodec( size_t nInBufSize, size_t nOutBufSize ) : meState(STATE_INIT) @@ -109,6 +110,25 @@ tools::Long ZCodec::EndCompression() retvalue = pStream->total_in; deflateEnd( pStream ); + if ( mbGzLib ) + { + // metadata must be set to compress as gz format + assert(!msFilename.isEmpty()); + // overwrite zlib checksum + mpOStm->Seek(STREAM_SEEK_TO_END); + mpOStm->SeekRel(-4); + mpOStm->WriteUInt32( mnInBufCRC32 ); // Uncompressed buffer CRC32 + mpOStm->WriteUInt32( mnUncompressedSize ); // Uncompressed size mod 2^32 + mpOStm->Seek( 0 ); + mpOStm->WriteUInt16( GZ_MAGIC_BYTES_LE ) // Magic bytes + .WriteUInt8( GZ_DEFLATE ) // Compression algorithm + .WriteUInt8( GZ_ORIG_NAME ) // Filename + .WriteUInt32( mnLastModifiedTime ) // Modification time + .WriteUInt8( 0 ) // Extra flags + .WriteUInt8( GZ_FS_UNKNOWN ) // Operating system + .WriteBytes( msFilename.pData->buffer, msFilename.pData->length ); + mpOStm->WriteUInt8( 0 ); // null terminate the filename string + } } else { @@ -122,10 +142,20 @@ tools::Long ZCodec::EndCompression() return mbStatus ? retvalue : -1; } +void ZCodec::SetCompressionMetadata( const OString& sFilename, sal_uInt32 nLastModifiedTime, sal_uInt32 nInBufCRC32 ) +{ + assert( mbGzLib ); + msFilename = sFilename; + mnLastModifiedTime = nLastModifiedTime; + mnInBufCRC32 = nInBufCRC32; +} + void ZCodec::Compress( SvStream& rIStm, SvStream& rOStm ) { assert(meState == STATE_INIT); mpOStm = &rOStm; + rIStm.Seek(0); + mnUncompressedSize = rIStm.TellEnd(); InitCompress(); mpInBuf.reset(new sal_uInt8[ mnInBufSize ]); auto pStream = static_cast<z_stream*>(mpsC_Stream); @@ -265,6 +295,14 @@ void ZCodec::ImplWriteBack() void ZCodec::InitCompress() { assert(meState == STATE_INIT); + if (mbGzLib) + { + // Seek just enough so that the zlib header is overwritten after compression + // with the gz header + // 10 header bytes + filename length + null terminator - 2 bytes for + // zlib header that gets overwritten + mpOStm->Seek(10 + msFilename.getLength() + 1 - 2); + } meState = STATE_COMPRESS; auto pStream = static_cast<z_stream*>(mpsC_Stream); mbStatus = deflateInit2_( |