diff options
Diffstat (limited to 'tools')
-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_( |