/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
/** This class is used to write Zip files
*/
ZipOutputStream::ZipOutputStream( const uno::Reference < io::XOutputStream > &xOStream )
: m_xStream(xOStream)
, mpThreadTaskTag( comphelper::ThreadPool::createThreadTaskTag() )
, m_aChucker(xOStream)
, m_pCurrentEntry(nullptr)
{
}
ZipOutputStream::~ZipOutputStream()
{
}
void ZipOutputStream::setEntry(ZipEntry& rEntry)
{ if (rEntry.nTime == -1)
rEntry.nTime = getCurrentDosTime(); if (rEntry.nMethod == -1)
rEntry.nMethod = DEFLATED;
rEntry.nVersion = 20;
rEntry.nFlag = 1 << 11; if (rEntry.nSize == -1 || rEntry.nCompressedSize == -1 ||
rEntry.nCrc == -1)
{ if (rEntry.nSize == -1)
{
assert(false); // how to get here
rEntry.nSize = 0;
}
rEntry.nCompressedSize = 0;
rEntry.nFlag |= 8;
}
}
if (bEncrypt)
{
m_pCurrentEntry->nMethod = STORED;
assert(m_pCurrentEntry->nSize == m_pCurrentEntry->nCompressedSize);
}
m_pCurrentEntry = nullptr;
}
void ZipOutputStream::consumeScheduledThreadTaskEntry(std::unique_ptr<ZipOutputEntryInThread> pCandidate)
{ //Any exceptions thrown in the threads were caught and stored for now const std::exception_ptr& rCaughtException(pCandidate->getParallelDeflateException()); if (rCaughtException)
{
m_aDeflateException = rCaughtException; // store it for later throwing // the exception handler in DeflateThreadTask should have cleaned temp file return;
}
void ZipOutputStream::writeCEN( const ZipEntry &rEntry )
{ if ( !::comphelper::OStorageHelper::IsValidZipEntryFileName( rEntry.sPath, true ) ) throw IOException(u"Unexpected character is used in file name."_ustr );
m_aChucker.WriteInt32( EXTSIG );
m_aChucker.WriteUInt32( rEntry.nCrc ); // For ZIP64(tm) format archives, the compressed and uncompressed sizes are 8 bytes each. // TODO: Not sure if this is the "when ZIP64(tm) format is used"
bWrite64Header = rEntry.nCompressedSize >= 0x100000000 || rEntry.nSize >= 0x100000000; if (!bWrite64Header)
{
m_aChucker.WriteUInt32( static_cast<sal_uInt32>(rEntry.nCompressedSize) );
m_aChucker.WriteUInt32( static_cast<sal_uInt32>(rEntry.nSize) );
} else
{
m_aChucker.WriteUInt64( rEntry.nCompressedSize );
m_aChucker.WriteUInt64( rEntry.nSize );
}
}
void ZipOutputStream::writeExtraFields(const ZipEntry& rEntry, boolconst isLOCWithDD)
{ //Could contain more fields, now we only save Zip64 extended information
m_aChucker.WriteInt16( 1 ); //id of Zip64 extended information extra field
m_aChucker.WriteInt16( 28 ); //data size of this field = 3*8+4 byte
m_aChucker.WriteUInt64(isLOCWithDD ? 0 : rEntry.nSize);
m_aChucker.WriteUInt64(isLOCWithDD ? 0 : rEntry.nCompressedSize);
m_aChucker.WriteUInt64( rEntry.nOffset );
m_aChucker.WriteInt32( 0 ); //Number of the disk on which this file starts
}
void ZipOutputStream::writeLOC(std::unique_ptr<ZipEntry>&& pEntry, bool bEncrypt)
{
assert(!m_pCurrentEntry && "Forgot to close an entry with rawCloseEntry()?");
m_aZipList.push_back(std::move(pEntry));
m_pCurrentEntry = m_aZipList.back().get(); const ZipEntry &rEntry = *m_pCurrentEntry;
if ( !::comphelper::OStorageHelper::IsValidZipEntryFileName( rEntry.sPath, true ) ) throw IOException(u"Unexpected character is used in file name."_ustr );
m_aChucker.WriteInt16( rEntry.nFlag ); // If it's an encrypted entry, we pretend its stored plain text if (bEncrypt)
m_aChucker.WriteInt16( STORED ); else
m_aChucker.WriteInt16( rEntry.nMethod );
bool bWrite64Header = false; // getTruncated must always be called to init bWrite64Header! autoconst nTruncCompressedSize{getTruncated(rEntry.nCompressedSize, &bWrite64Header)}; autoconst nTruncSize{getTruncated(rEntry.nSize, &bWrite64Header)};
// at year 2108, there is an overflow // -> some decision needs to be made // how to handle the ZIP file format (just overflow?)
// if the current system time is before 1980, // then the time traveller will have to make a decision // how to handle the ZIP file format before it is invented // (just underflow?)
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.