summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/source/zcodec/zcodec.cxx52
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_(