summaryrefslogtreecommitdiff
path: root/tools/source
diff options
context:
space:
mode:
authorofftkp <parisoplop@gmail.com>2022-06-01 02:13:13 +0300
committerTomaž Vajngerl <quikee@gmail.com>2022-06-12 09:29:53 +0200
commit932257c50c1dc9302b14862424e24e975f88bcc2 (patch)
tree3729b829e894462fd32aa2474b3dd2c2625614c8 /tools/source
parent988285410f8883ad49f32c4b804c4f5bd14569d0 (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.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_(