LibreOffice Module package (master) 1
ZipPackage.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20#include <ZipPackage.hxx>
21#include "ZipPackageSink.hxx"
22#include <ZipEnumeration.hxx>
23#include <ZipPackageStream.hxx>
24#include <ZipPackageFolder.hxx>
25#include <ZipOutputEntry.hxx>
26#include <ZipOutputStream.hxx>
27#include <ZipPackageBuffer.hxx>
28#include <ZipFile.hxx>
29#include <PackageConstants.hxx>
30#include <com/sun/star/beans/PropertyValue.hpp>
31#include <com/sun/star/packages/zip/ZipConstants.hpp>
32#include <com/sun/star/packages/zip/ZipException.hpp>
33#include <com/sun/star/packages/zip/ZipIOException.hpp>
34#include <com/sun/star/packages/manifest/ManifestReader.hpp>
35#include <com/sun/star/packages/manifest/ManifestWriter.hpp>
36#include <com/sun/star/io/TempFile.hpp>
37#include <com/sun/star/io/XStream.hpp>
38#include <com/sun/star/io/XInputStream.hpp>
39#include <com/sun/star/io/XOutputStream.hpp>
40#include <com/sun/star/io/XTruncate.hpp>
41#include <com/sun/star/io/XSeekable.hpp>
42#include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
43#include <com/sun/star/container/XNameContainer.hpp>
46#include <ucbhelper/content.hxx>
48#include <com/sun/star/ucb/ContentCreationException.hpp>
49#include <com/sun/star/ucb/TransferInfo.hpp>
50#include <com/sun/star/ucb/NameClash.hpp>
51#include <com/sun/star/ucb/OpenCommandArgument2.hpp>
52#include <com/sun/star/ucb/OpenMode.hpp>
53#include <com/sun/star/ucb/SimpleFileAccess.hpp>
54#include <com/sun/star/io/XActiveDataStreamer.hpp>
55#include <com/sun/star/embed/UseBackupException.hpp>
56#include <com/sun/star/embed/StorageFormats.hpp>
57#include <com/sun/star/beans/NamedValue.hpp>
58#include <com/sun/star/xml/crypto/DigestID.hpp>
60#include <rtl/uri.hxx>
61#include <rtl/random.h>
62#include <o3tl/string_view.hxx>
63#include <osl/diagnose.h>
64#include <sal/log.hxx>
66#include <unotools/tempfile.hxx>
67#include <com/sun/star/io/XAsyncOutputMonitor.hpp>
68
69#include <string_view>
70
79#include <utility>
80
81using namespace osl;
82using namespace cppu;
83using namespace ucbhelper;
84using namespace com::sun::star;
85using namespace com::sun::star::io;
86using namespace com::sun::star::uno;
87using namespace com::sun::star::ucb;
88using namespace com::sun::star::util;
89using namespace com::sun::star::lang;
90using namespace com::sun::star::task;
91using namespace com::sun::star::beans;
92using namespace com::sun::star::packages;
93using namespace com::sun::star::container;
94using namespace com::sun::star::packages::zip;
95using namespace com::sun::star::packages::manifest;
96using namespace com::sun::star::packages::zip::ZipConstants;
97
98#if OSL_DEBUG_LEVEL > 0
99#define THROW_WHERE SAL_WHERE
100#else
101#define THROW_WHERE ""
102#endif
103
104namespace {
105
106class ActiveDataStreamer : public ::cppu::WeakImplHelper< XActiveDataStreamer >
107{
108 uno::Reference< XStream > mStream;
109public:
110
111 virtual uno::Reference< XStream > SAL_CALL getStream() override
112 { return mStream; }
113
114 virtual void SAL_CALL setStream( const uno::Reference< XStream >& stream ) override
115 { mStream = stream; }
116};
117
118class DummyInputStream : public ::cppu::WeakImplHelper< XInputStream >
119{
120 virtual sal_Int32 SAL_CALL readBytes( uno::Sequence< sal_Int8 >&, sal_Int32 ) override
121 { return 0; }
122
123 virtual sal_Int32 SAL_CALL readSomeBytes( uno::Sequence< sal_Int8 >&, sal_Int32 ) override
124 { return 0; }
125
126 virtual void SAL_CALL skipBytes( sal_Int32 ) override
127 {}
128
129 virtual sal_Int32 SAL_CALL available() override
130 { return 0; }
131
132 virtual void SAL_CALL closeInput() override
133 {}
134};
135
136}
137
138ZipPackage::ZipPackage ( uno::Reference < XComponentContext > xContext )
139: m_aMutexHolder( new comphelper::RefCountedMutex )
140, m_nStartKeyGenerationID( xml::crypto::DigestID::SHA1 )
141, m_nChecksumDigestID( xml::crypto::DigestID::SHA1_1K )
142, m_nCommonEncryptionID( xml::crypto::CipherID::BLOWFISH_CFB_8 )
143, m_bHasEncryptedEntries ( false )
144, m_bHasNonEncryptedEntries ( false )
145, m_bInconsistent ( false )
146, m_bForceRecovery ( false )
147, m_bMediaTypeFallbackUsed ( false )
148, m_nFormat( embed::StorageFormats::PACKAGE ) // package is the default format
149, m_bAllowRemoveOnInsert( true )
150, m_eMode ( e_IMode_None )
151, m_xContext(std::move( xContext ))
152{
154}
155
157{
158}
159
161{
163}
164
166{
167 if ( m_nFormat != embed::StorageFormats::PACKAGE )
168 return;
169
170 bool bManifestParsed = false;
171 static constexpr OUStringLiteral sMeta (u"META-INF");
172 if ( m_xRootFolder->hasByName( sMeta ) )
173 {
174 try {
175 static constexpr OUStringLiteral sManifest (u"manifest.xml");
176 Any aAny = m_xRootFolder->getByName( sMeta );
177 uno::Reference< XNameContainer > xMetaInfFolder;
178 aAny >>= xMetaInfFolder;
179 if ( xMetaInfFolder.is() && xMetaInfFolder->hasByName( sManifest ) )
180 {
181 uno::Reference < XActiveDataSink > xSink;
182 aAny = xMetaInfFolder->getByName( sManifest );
183 aAny >>= xSink;
184 if ( xSink.is() )
185 {
186 uno::Reference < XManifestReader > xReader = ManifestReader::create( m_xContext );
187
188 static constexpr OUStringLiteral sPropFullPath (u"FullPath");
189 static constexpr OUStringLiteral sPropVersion (u"Version");
190 static constexpr OUStringLiteral sPropMediaType (u"MediaType");
191 static constexpr OUStringLiteral sPropInitialisationVector (u"InitialisationVector");
192 static constexpr OUStringLiteral sPropSalt (u"Salt");
193 static constexpr OUStringLiteral sPropIterationCount (u"IterationCount");
194 static constexpr OUStringLiteral sPropSize (u"Size");
195 static constexpr OUStringLiteral sPropDigest (u"Digest");
196 static constexpr OUStringLiteral sPropDerivedKeySize (u"DerivedKeySize");
197 static constexpr OUStringLiteral sPropDigestAlgorithm (u"DigestAlgorithm");
198 static constexpr OUStringLiteral sPropEncryptionAlgorithm (u"EncryptionAlgorithm");
199 static constexpr OUStringLiteral sPropStartKeyAlgorithm (u"StartKeyAlgorithm");
200 static constexpr OUStringLiteral sKeyInfo (u"KeyInfo");
201
202 const uno::Sequence < uno::Sequence < PropertyValue > > aManifestSequence = xReader->readManifestSequence ( xSink->getInputStream() );
203 const Any *pKeyInfo = nullptr;
204
205 for ( const uno::Sequence<PropertyValue>& rSequence : aManifestSequence )
206 {
207 OUString sPath, sMediaType, sVersion;
208 const Any *pSalt = nullptr, *pVector = nullptr, *pCount = nullptr, *pSize = nullptr, *pDigest = nullptr, *pDigestAlg = nullptr, *pEncryptionAlg = nullptr, *pStartKeyAlg = nullptr, *pDerivedKeySize = nullptr;
209 for ( const PropertyValue& rValue : rSequence )
210 {
211 if ( rValue.Name == sPropFullPath )
212 rValue.Value >>= sPath;
213 else if ( rValue.Name == sPropVersion )
214 rValue.Value >>= sVersion;
215 else if ( rValue.Name == sPropMediaType )
216 rValue.Value >>= sMediaType;
217 else if ( rValue.Name == sPropSalt )
218 pSalt = &( rValue.Value );
219 else if ( rValue.Name == sPropInitialisationVector )
220 pVector = &( rValue.Value );
221 else if ( rValue.Name == sPropIterationCount )
222 pCount = &( rValue.Value );
223 else if ( rValue.Name == sPropSize )
224 pSize = &( rValue.Value );
225 else if ( rValue.Name == sPropDigest )
226 pDigest = &( rValue.Value );
227 else if ( rValue.Name == sPropDigestAlgorithm )
228 pDigestAlg = &( rValue.Value );
229 else if ( rValue.Name == sPropEncryptionAlgorithm )
230 pEncryptionAlg = &( rValue.Value );
231 else if ( rValue.Name == sPropStartKeyAlgorithm )
232 pStartKeyAlg = &( rValue.Value );
233 else if ( rValue.Name == sPropDerivedKeySize )
234 pDerivedKeySize = &( rValue.Value );
235 else if ( rValue.Name == sKeyInfo )
236 pKeyInfo = &( rValue.Value );
237 }
238
239 if ( !sPath.isEmpty() && hasByHierarchicalName ( sPath ) )
240 {
241 aAny = getByHierarchicalName( sPath );
242 uno::Reference < XInterface > xTmp;
243 aAny >>= xTmp;
244 if (auto pFolder = dynamic_cast<ZipPackageFolder*>(xTmp.get()))
245 {
246 pFolder->SetMediaType ( sMediaType );
247 pFolder->SetVersion ( sVersion );
248 }
249 else if (auto pStream = dynamic_cast<ZipPackageStream*>(xTmp.get()))
250 {
251 pStream->SetMediaType ( sMediaType );
252 pStream->SetFromManifest( true );
253
254 if ( pKeyInfo && pVector && pSize && pDigest && pDigestAlg && pEncryptionAlg )
255 {
256 uno::Sequence < sal_Int8 > aSequence;
257 sal_Int64 nSize = 0;
258 sal_Int32 nDigestAlg = 0, nEncryptionAlg = 0;
259
260 pStream->SetToBeEncrypted ( true );
261
262 *pVector >>= aSequence;
263 pStream->setInitialisationVector ( aSequence );
264
265 *pSize >>= nSize;
266 pStream->setSize ( nSize );
267
268 *pDigest >>= aSequence;
269 pStream->setDigest ( aSequence );
270
271 *pDigestAlg >>= nDigestAlg;
272 pStream->SetImportedChecksumAlgorithm( nDigestAlg );
273
274 *pEncryptionAlg >>= nEncryptionAlg;
275 pStream->SetImportedEncryptionAlgorithm( nEncryptionAlg );
276
277 *pKeyInfo >>= m_aGpgProps;
278
279 pStream->SetToBeCompressed ( true );
280 pStream->SetToBeEncrypted ( true );
281 pStream->SetIsEncrypted ( true );
282 pStream->setIterationCount(0);
283
284 // clamp to default SHA256 start key magic value,
285 // c.f. ZipPackageStream::GetEncryptionKey()
286 // trying to get key value from properties
287 const sal_Int32 nStartKeyAlg = xml::crypto::DigestID::SHA256;
288 pStream->SetImportedStartKeyAlgorithm( nStartKeyAlg );
289
290 if ( !m_bHasEncryptedEntries && pStream->getName() == "content.xml" )
291 {
293 m_nChecksumDigestID = nDigestAlg;
294 m_nCommonEncryptionID = nEncryptionAlg;
295 m_nStartKeyGenerationID = nStartKeyAlg;
296 }
297 }
298 else if ( pSalt && pVector && pCount && pSize && pDigest && pDigestAlg && pEncryptionAlg )
299 {
300 uno::Sequence < sal_Int8 > aSequence;
301 sal_Int64 nSize = 0;
302 sal_Int32 nCount = 0, nDigestAlg = 0, nEncryptionAlg = 0;
303 sal_Int32 nDerivedKeySize = 16, nStartKeyAlg = xml::crypto::DigestID::SHA1;
304
305 pStream->SetToBeEncrypted ( true );
306
307 *pSalt >>= aSequence;
308 pStream->setSalt ( aSequence );
309
310 *pVector >>= aSequence;
311 pStream->setInitialisationVector ( aSequence );
312
313 *pCount >>= nCount;
314 pStream->setIterationCount ( nCount );
315
316 *pSize >>= nSize;
317 pStream->setSize ( nSize );
318
319 *pDigest >>= aSequence;
320 pStream->setDigest ( aSequence );
321
322 *pDigestAlg >>= nDigestAlg;
323 pStream->SetImportedChecksumAlgorithm( nDigestAlg );
324
325 *pEncryptionAlg >>= nEncryptionAlg;
326 pStream->SetImportedEncryptionAlgorithm( nEncryptionAlg );
327
328 if ( pDerivedKeySize )
329 *pDerivedKeySize >>= nDerivedKeySize;
330 pStream->SetImportedDerivedKeySize( nDerivedKeySize );
331
332 if ( pStartKeyAlg )
333 *pStartKeyAlg >>= nStartKeyAlg;
334 pStream->SetImportedStartKeyAlgorithm( nStartKeyAlg );
335
336 pStream->SetToBeCompressed ( true );
337 pStream->SetToBeEncrypted ( true );
338 pStream->SetIsEncrypted ( true );
339 if ( !m_bHasEncryptedEntries && pStream->getName() == "content.xml" )
340 {
342 m_nStartKeyGenerationID = nStartKeyAlg;
343 m_nChecksumDigestID = nDigestAlg;
344 m_nCommonEncryptionID = nEncryptionAlg;
345 }
346 }
347 else
349 }
350 else
351 throw ZipIOException(THROW_WHERE "Wrong content");
352 }
353 }
354
355 bManifestParsed = true;
356 }
357
358 // now hide the manifest.xml file from user
359 xMetaInfFolder->removeByName( sManifest );
360 }
361 }
362 catch( Exception& )
363 {
364 if ( !m_bForceRecovery )
365 throw;
366 }
367 }
368
369 if ( !bManifestParsed && !m_bForceRecovery )
370 throw ZipIOException(
371 THROW_WHERE "Could not parse manifest.xml" );
372
373 static constexpr OUStringLiteral sMimetype (u"mimetype");
374 if ( m_xRootFolder->hasByName( sMimetype ) )
375 {
376 // get mediatype from the "mimetype" stream
377 OUString aPackageMediatype;
378 uno::Reference < io::XActiveDataSink > xMimeSink;
379 m_xRootFolder->getByName( sMimetype ) >>= xMimeSink;
380 if ( xMimeSink.is() )
381 {
382 uno::Reference< io::XInputStream > xMimeInStream = xMimeSink->getInputStream();
383 if ( xMimeInStream.is() )
384 {
385 // Mediatypes longer than 1024 symbols should not appear here
386 uno::Sequence< sal_Int8 > aData( 1024 );
387 sal_Int32 nRead = xMimeInStream->readBytes( aData, 1024 );
388 if ( nRead > aData.getLength() )
389 nRead = aData.getLength();
390
391 if ( nRead )
392 aPackageMediatype = OUString( reinterpret_cast<char const *>(aData.getConstArray()), nRead, RTL_TEXTENCODING_ASCII_US );
393 }
394 }
395
396 if ( !bManifestParsed )
397 {
398 // the manifest.xml could not be successfully parsed, this is an inconsistent package
399 if ( aPackageMediatype.startsWith("application/vnd.") )
400 {
401 // accept only types that look similar to own mediatypes
402 m_xRootFolder->SetMediaType( aPackageMediatype );
404 }
405 }
406 else if ( !m_bForceRecovery )
407 {
408 // the mimetype stream should contain the information from manifest.xml
409 if ( m_xRootFolder->GetMediaType() != aPackageMediatype )
410 throw ZipIOException(
412 "mimetype conflicts with manifest.xml, \""
413 + m_xRootFolder->GetMediaType() + "\" vs. \""
414 + aPackageMediatype + "\"" );
415 }
416
417 m_xRootFolder->removeByName( sMimetype );
418 }
419
420 m_bInconsistent = m_xRootFolder->LookForUnexpectedODF12Streams( std::u16string_view() );
421
422 bool bODF12AndNewer = ( m_xRootFolder->GetVersion().compareTo( ODFVER_012_TEXT ) >= 0 );
423 if ( !m_bForceRecovery && bODF12AndNewer )
424 {
425 if ( m_bInconsistent )
426 {
427 // this is an ODF1.2 document that contains streams not referred in the manifest.xml;
428 // in case of ODF1.2 documents without version in manifest.xml the property IsInconsistent
429 // should be checked later
430 throw ZipIOException(
431 THROW_WHERE "there are streams not referred in manifest.xml" );
432 }
433 // all the streams should be encrypted with the same StartKey in ODF1.2
434 // TODO/LATER: in future the exception should be thrown
435 // throw ZipIOException( THROW_WHERE "More than one Start Key Generation algorithm is specified!" );
436 }
437
438 // in case it is a correct ODF1.2 document, the version must be set
439 // and the META-INF folder is reserved for package format
440 if ( bODF12AndNewer )
441 m_xRootFolder->removeByName( sMeta );
442}
443
445{
446 if ( m_nFormat != embed::StorageFormats::OFOPXML )
447 return;
448
449 try {
450 static constexpr OUStringLiteral aContentTypes(u"[Content_Types].xml");
451 // the content type must exist in OFOPXML format!
452 if ( !m_xRootFolder->hasByName( aContentTypes ) )
453 throw io::IOException(THROW_WHERE "Wrong format!" );
454
455 uno::Reference < io::XActiveDataSink > xSink;
456 uno::Any aAny = m_xRootFolder->getByName( aContentTypes );
457 aAny >>= xSink;
458 if ( xSink.is() )
459 {
460 uno::Reference< io::XInputStream > xInStream = xSink->getInputStream();
461 if ( xInStream.is() )
462 {
463 // here aContentTypeInfo[0] - Defaults, and aContentTypeInfo[1] - Overrides
464 const uno::Sequence< uno::Sequence< beans::StringPair > > aContentTypeInfo =
465 ::comphelper::OFOPXMLHelper::ReadContentTypeSequence( xInStream, m_xContext );
466
467 if ( aContentTypeInfo.getLength() != 2 )
468 throw io::IOException(THROW_WHERE );
469
470 // set the implicit types first
471 for ( const auto& rPair : aContentTypeInfo[0] )
472 m_xRootFolder->setChildStreamsTypeByExtension( rPair );
473
474 // now set the explicit types
475 for ( const auto& rPair : aContentTypeInfo[1] )
476 {
477 OUString aPath;
478 if ( rPair.First.toChar() == '/' )
479 aPath = rPair.First.copy( 1 );
480 else
481 aPath = rPair.First;
482
483 if ( !aPath.isEmpty() && hasByHierarchicalName( aPath ) )
484 {
485 uno::Any aIterAny = getByHierarchicalName( aPath );
486 uno::Reference < XInterface > xIterTmp;
487 aIterAny >>= xIterTmp;
488 if (auto pStream = dynamic_cast<ZipPackageStream*>(xIterTmp.get()))
489 {
490 // this is a package stream, in OFOPXML format only streams can have mediatype
491 pStream->SetMediaType( rPair.Second );
492 }
493 }
494 }
495 }
496 }
497
498 m_xRootFolder->removeByName( aContentTypes );
499 }
500 catch( uno::Exception& )
501 {
502 if ( !m_bForceRecovery )
503 throw;
504 }
505}
506
508{
509 ZipEnumeration aEnum = m_pZipFile->entries();
510 OUString sTemp, sDirName;
511 sal_Int32 nOldIndex, nStreamIndex;
512 FolderHash::iterator aIter;
513
514 while (aEnum.hasMoreElements())
515 {
516 nOldIndex = 0;
517 ZipPackageFolder* pCurrent = m_xRootFolder.get();
518 const ZipEntry & rEntry = *aEnum.nextElement();
519 OUString rName = rEntry.sPath;
520
521 if ( m_bForceRecovery )
522 {
523 // the PKZIP Application note version 6.2 does not allows to use '\' as separator
524 // unfortunately it is used by some implementations, so we have to support it in recovery mode
525 rName = rName.replace( '\\', '/' );
526 }
527
528 nStreamIndex = rName.lastIndexOf ( '/' );
529 if ( nStreamIndex != -1 )
530 {
531 sDirName = rName.copy ( 0, nStreamIndex );
532 aIter = m_aRecent.find ( sDirName );
533 if ( aIter != m_aRecent.end() )
534 pCurrent = ( *aIter ).second;
535 }
536
537 if ( pCurrent == m_xRootFolder.get() )
538 {
539 sal_Int32 nIndex;
540 while ( ( nIndex = rName.indexOf( '/', nOldIndex ) ) != -1 )
541 {
542 sTemp = rName.copy ( nOldIndex, nIndex - nOldIndex );
543 if ( nIndex == nOldIndex )
544 break;
545 if ( !pCurrent->hasByName( sTemp ) )
546 {
548 pPkgFolder->setName( sTemp );
549 pPkgFolder->doSetParent( pCurrent );
550 pCurrent = pPkgFolder.get();
551 }
552 else
553 {
554 ZipContentInfo& rInfo = pCurrent->doGetByName(sTemp);
555 if (!rInfo.bFolder)
556 throw css::packages::zip::ZipIOException("Bad Zip File, stream as folder");
557 pCurrent = rInfo.pFolder;
558 }
559 nOldIndex = nIndex+1;
560 }
561 if ( nStreamIndex != -1 && !sDirName.isEmpty() )
562 m_aRecent [ sDirName ] = pCurrent;
563 }
564 if ( rName.getLength() -1 != nStreamIndex )
565 {
566 nStreamIndex++;
567 sTemp = rName.copy( nStreamIndex );
568
569 if (!pCurrent->hasByName(sTemp))
570 {
572 pPkgStream->SetPackageMember(true);
573 pPkgStream->setZipEntryOnLoading(rEntry);
574 pPkgStream->setName(sTemp);
575 pPkgStream->doSetParent(pCurrent);
576 }
577 }
578 }
579
580 if ( m_nFormat == embed::StorageFormats::PACKAGE )
582 else if ( m_nFormat == embed::StorageFormats::OFOPXML )
584}
585
586void SAL_CALL ZipPackage::initialize( const uno::Sequence< Any >& aArguments )
587{
588 beans::NamedValue aNamedValue;
589
590 if ( !aArguments.hasElements() )
591 return;
592
593 bool bHaveZipFile = true;
594
595 for( const auto& rArgument : aArguments )
596 {
597 OUString aParamUrl;
598 if ( rArgument >>= aParamUrl )
599 {
601 try
602 {
603 sal_Int32 nParam = aParamUrl.indexOf( '?' );
604 if ( nParam >= 0 )
605 {
606 m_aURL = aParamUrl.copy( 0, nParam );
607 std::u16string_view aParam = aParamUrl.subView( nParam + 1 );
608
609 sal_Int32 nIndex = 0;
610 do
611 {
612 std::u16string_view aCommand = o3tl::getToken(aParam, 0, '&', nIndex );
613 if ( aCommand == u"repairpackage" )
614 {
615 m_bForceRecovery = true;
616 break;
617 }
618 else if ( aCommand == u"purezip" )
619 {
620 m_nFormat = embed::StorageFormats::ZIP;
621 m_xRootFolder->setPackageFormat_Impl( m_nFormat );
622 break;
623 }
624 else if ( aCommand == u"ofopxml" )
625 {
626 m_nFormat = embed::StorageFormats::OFOPXML;
627 m_xRootFolder->setPackageFormat_Impl( m_nFormat );
628 break;
629 }
630 }
631 while ( nIndex >= 0 );
632 }
633 else
634 m_aURL = aParamUrl;
635
636 Content aContent(
637 m_aURL, uno::Reference< XCommandEnvironment >(),
638 m_xContext );
639 Any aAny = aContent.getPropertyValue("Size");
640 sal_uInt64 aSize = 0;
641 // kind of optimization: treat empty files as nonexistent files
642 // and write to such files directly. Note that "Size" property is optional.
643 bool bHasSizeProperty = aAny >>= aSize;
644 if( !bHasSizeProperty || aSize )
645 {
646 uno::Reference < XActiveDataSink > xSink = new ZipPackageSink;
647 if ( aContent.openStream ( xSink ) )
648 m_xContentStream = xSink->getInputStream();
649 }
650 else
651 bHaveZipFile = false;
652 }
653 catch ( css::uno::Exception& )
654 {
655 // Exception derived from uno::Exception thrown. This probably
656 // means the file doesn't exist...we'll create it at
657 // commitChanges time
658 bHaveZipFile = false;
659 }
660 }
661 else if ( rArgument >>= m_xStream )
662 {
663 // a writable stream can implement both XStream & XInputStream
665 m_xContentStream = m_xStream->getInputStream();
666 }
667 else if ( rArgument >>= m_xContentStream )
668 {
670 }
671 else if ( rArgument >>= aNamedValue )
672 {
673 if ( aNamedValue.Name == "RepairPackage" )
674 aNamedValue.Value >>= m_bForceRecovery;
675 else if ( aNamedValue.Name == "PackageFormat" )
676 {
677 // setting this argument to true means Package format
678 // setting it to false means plain Zip format
679
680 bool bPackFormat = true;
681 aNamedValue.Value >>= bPackFormat;
682 if ( !bPackFormat )
683 m_nFormat = embed::StorageFormats::ZIP;
684
685 m_xRootFolder->setPackageFormat_Impl( m_nFormat );
686 }
687 else if ( aNamedValue.Name == "StorageFormat" )
688 {
689 OUString aFormatName;
690 sal_Int32 nFormatID = 0;
691 if ( aNamedValue.Value >>= aFormatName )
692 {
693 if ( aFormatName == PACKAGE_STORAGE_FORMAT_STRING )
694 m_nFormat = embed::StorageFormats::PACKAGE;
695 else if ( aFormatName == ZIP_STORAGE_FORMAT_STRING )
696 m_nFormat = embed::StorageFormats::ZIP;
697 else if ( aFormatName == OFOPXML_STORAGE_FORMAT_STRING )
698 m_nFormat = embed::StorageFormats::OFOPXML;
699 else
700 throw lang::IllegalArgumentException(THROW_WHERE, uno::Reference< uno::XInterface >(), 1 );
701 }
702 else if ( aNamedValue.Value >>= nFormatID )
703 {
704 if (nFormatID != embed::StorageFormats::PACKAGE
705 && nFormatID != embed::StorageFormats::ZIP
706 && nFormatID != embed::StorageFormats::OFOPXML)
707 throw lang::IllegalArgumentException(THROW_WHERE, uno::Reference< uno::XInterface >(), 1 );
708
709 m_nFormat = nFormatID;
710 }
711 else
712 throw lang::IllegalArgumentException(THROW_WHERE, uno::Reference< uno::XInterface >(), 1 );
713
714 m_xRootFolder->setPackageFormat_Impl( m_nFormat );
715 }
716 else if ( aNamedValue.Name == "AllowRemoveOnInsert" )
717 {
718 aNamedValue.Value >>= m_bAllowRemoveOnInsert;
719 m_xRootFolder->setRemoveOnInsertMode_Impl( m_bAllowRemoveOnInsert );
720 }
721 else if (aNamedValue.Name == "NoFileSync")
722 aNamedValue.Value >>= m_bDisableFileSync;
723
724 // for now the progress handler is not used, probably it will never be
725 // if ( aNamedValue.Name == "ProgressHandler" )
726 }
727 else
728 {
729 // The URL is not acceptable
730 throw css::uno::Exception (THROW_WHERE "Bad arguments.",
731 getXWeak() );
732 }
733 }
734
735 try
736 {
737 if ( m_xContentStream.is() )
738 {
739 // the stream must be seekable, if it is not it will be wrapped
741 m_xContentSeek.set( m_xContentStream, UNO_QUERY_THROW );
742 if ( !m_xContentSeek->getLength() )
743 bHaveZipFile = false;
744 }
745 else
746 bHaveZipFile = false;
747 }
748 catch ( css::uno::Exception& )
749 {
750 // Exception derived from uno::Exception thrown. This probably
751 // means the file doesn't exist...we'll create it at
752 // commitChanges time
753 bHaveZipFile = false;
754 }
755 if ( !bHaveZipFile )
756 return;
757
758 bool bBadZipFile = false;
759 OUString message;
760 try
761 {
764 }
765 catch ( IOException & e )
766 {
767 bBadZipFile = true;
768 message = "IOException: " + e.Message;
769 }
770 catch ( ZipException & e )
771 {
772 bBadZipFile = true;
773 message = "ZipException: " + e.Message;
774 }
775 catch ( Exception & )
776 {
777 m_pZipFile.reset();
778 throw;
779 }
780
781 if ( bBadZipFile )
782 {
783 // clean up the memory, and tell the UCB about the error
784 m_pZipFile.reset();
785
786 throw css::packages::zip::ZipIOException (
787 THROW_WHERE "Bad Zip File, " + message,
788 getXWeak() );
789 }
790}
791
792Any SAL_CALL ZipPackage::getByHierarchicalName( const OUString& aName )
793{
794 OUString sTemp, sDirName;
795 sal_Int32 nOldIndex, nStreamIndex;
796 FolderHash::iterator aIter;
797
798 sal_Int32 nIndex = aName.getLength();
799
800 if (aName == "/")
801 // root directory.
802 return Any ( uno::Reference( cppu::getXWeak(m_xRootFolder.get()) ) );
803
804 nStreamIndex = aName.lastIndexOf ( '/' );
805 bool bFolder = nStreamIndex == nIndex-1; // last character is '/'.
806
807 if ( nStreamIndex != -1 )
808 {
809 // The name contains '/'.
810 sDirName = aName.copy ( 0, nStreamIndex );
811 aIter = m_aRecent.find ( sDirName );
812 if ( aIter != m_aRecent.end() )
813 {
814 // There is a cached entry for this name.
815
816 ZipPackageFolder* pFolder = aIter->second;
817
818 if ( bFolder )
819 {
820 // Determine the directory name.
821 sal_Int32 nDirIndex = aName.lastIndexOf ( '/', nStreamIndex );
822 sTemp = aName.copy ( nDirIndex == -1 ? 0 : nDirIndex+1, nStreamIndex-nDirIndex-1 );
823
824 if (pFolder && sTemp == pFolder->getName())
825 return Any(uno::Reference(cppu::getXWeak(pFolder)));
826 }
827 else
828 {
829 // Determine the file name.
830 sTemp = aName.copy ( nStreamIndex + 1 );
831
832 if (pFolder && pFolder->hasByName(sTemp))
833 return pFolder->getByName(sTemp);
834 }
835
836 m_aRecent.erase( aIter );
837 }
838 }
839 else if ( m_xRootFolder->hasByName ( aName ) )
840 // top-level element.
841 return m_xRootFolder->getByName ( aName );
842
843 // Not in the cache. Search normally.
844
845 nOldIndex = 0;
846 ZipPackageFolder * pCurrent = m_xRootFolder.get();
847 ZipPackageFolder * pPrevious = nullptr;
848
849 // Find the right directory for the given path.
850
851 while ( ( nIndex = aName.indexOf( '/', nOldIndex )) != -1 )
852 {
853 sTemp = aName.copy ( nOldIndex, nIndex - nOldIndex );
854 if ( nIndex == nOldIndex )
855 break;
856 if ( !pCurrent->hasByName( sTemp ) )
857 throw NoSuchElementException(THROW_WHERE );
858
859 pPrevious = pCurrent;
860 ZipContentInfo& rInfo = pCurrent->doGetByName(sTemp);
861 if (!rInfo.bFolder)
862 throw css::packages::zip::ZipIOException("Bad Zip File, stream as folder");
863 pCurrent = rInfo.pFolder;
864 nOldIndex = nIndex+1;
865 }
866
867 if ( bFolder )
868 {
869 if ( nStreamIndex != -1 )
870 m_aRecent[sDirName] = pPrevious; // cache it.
871 return Any ( uno::Reference( cppu::getXWeak(pCurrent) ) );
872 }
873
874 sTemp = aName.copy( nOldIndex );
875
876 if ( pCurrent->hasByName ( sTemp ) )
877 {
878 if ( nStreamIndex != -1 )
879 m_aRecent[sDirName] = pCurrent; // cache it.
880 return pCurrent->getByName( sTemp );
881 }
882
883 throw NoSuchElementException(THROW_WHERE);
884}
885
886sal_Bool SAL_CALL ZipPackage::hasByHierarchicalName( const OUString& aName )
887{
888 OUString sTemp;
889 sal_Int32 nOldIndex;
890 FolderHash::iterator aIter;
891
892 sal_Int32 nIndex = aName.getLength();
893
894 if (aName == "/")
895 // root directory
896 return true;
897
898 try
899 {
900 OUString sDirName;
901 sal_Int32 nStreamIndex;
902 nStreamIndex = aName.lastIndexOf ( '/' );
903 bool bFolder = nStreamIndex == nIndex-1;
904 if ( nStreamIndex != -1 )
905 {
906 sDirName = aName.copy ( 0, nStreamIndex );
907 aIter = m_aRecent.find ( sDirName );
908 if ( aIter != m_aRecent.end() )
909 {
910 if ( bFolder )
911 {
912 sal_Int32 nDirIndex = aName.lastIndexOf ( '/', nStreamIndex );
913 sTemp = aName.copy ( nDirIndex == -1 ? 0 : nDirIndex+1, nStreamIndex-nDirIndex-1 );
914 if ( sTemp == ( *aIter ).second->getName() )
915 return true;
916 else
917 m_aRecent.erase ( aIter );
918 }
919 else
920 {
921 sTemp = aName.copy ( nStreamIndex + 1 );
922 if ( ( *aIter ).second->hasByName( sTemp ) )
923 return true;
924 else
925 m_aRecent.erase( aIter );
926 }
927 }
928 }
929 else
930 {
931 if ( m_xRootFolder->hasByName ( aName ) )
932 return true;
933 }
934 ZipPackageFolder * pCurrent = m_xRootFolder.get();
935 ZipPackageFolder * pPrevious = nullptr;
936 nOldIndex = 0;
937 while ( ( nIndex = aName.indexOf( '/', nOldIndex )) != -1 )
938 {
939 sTemp = aName.copy ( nOldIndex, nIndex - nOldIndex );
940 if ( nIndex == nOldIndex )
941 break;
942 if ( pCurrent->hasByName( sTemp ) )
943 {
944 pPrevious = pCurrent;
945 ZipContentInfo& rInfo = pCurrent->doGetByName(sTemp);
946 if (!rInfo.bFolder)
947 throw css::packages::zip::ZipIOException("Bad Zip File, stream as folder");
948 pCurrent = rInfo.pFolder;
949 }
950 else
951 return false;
952 nOldIndex = nIndex+1;
953 }
954 if ( bFolder )
955 {
956 m_aRecent[sDirName] = pPrevious;
957 return true;
958 }
959 else
960 {
961 sTemp = aName.copy( nOldIndex );
962
963 if ( pCurrent->hasByName( sTemp ) )
964 {
965 m_aRecent[sDirName] = pCurrent;
966 return true;
967 }
968 }
969 }
970 catch (const uno::RuntimeException &)
971 {
972 throw;
973 }
974 catch (const uno::Exception&)
975 {
976 uno::Any e(::cppu::getCaughtException());
977 throw lang::WrappedTargetRuntimeException("ZipPackage::hasByHierarchicalName", nullptr, e);
978 }
979 return false;
980}
981
982uno::Reference< XInterface > SAL_CALL ZipPackage::createInstance()
983{
984 uno::Reference < XInterface > xRef = *( new ZipPackageStream( *this, m_xContext, m_nFormat, m_bAllowRemoveOnInsert ) );
985 return xRef;
986}
987
988uno::Reference< XInterface > SAL_CALL ZipPackage::createInstanceWithArguments( const uno::Sequence< Any >& aArguments )
989{
990 bool bArg = false;
991 uno::Reference < XInterface > xRef;
992 if ( aArguments.hasElements() )
993 aArguments[0] >>= bArg;
994 if ( bArg )
996 else
998
999 return xRef;
1000}
1001
1003{
1004 static constexpr OUStringLiteral sMime (u"mimetype");
1005 if ( m_xRootFolder->hasByName( sMime ) )
1006 m_xRootFolder->removeByName( sMime );
1007
1008 ZipEntry * pEntry = new ZipEntry;
1009 sal_Int32 nBufferLength = m_xRootFolder->GetMediaType().getLength();
1010 OString sMediaType = OUStringToOString( m_xRootFolder->GetMediaType(), RTL_TEXTENCODING_ASCII_US );
1011 const uno::Sequence< sal_Int8 > aType( reinterpret_cast<sal_Int8 const *>(sMediaType.getStr()),
1012 nBufferLength );
1013
1014 pEntry->sPath = sMime;
1015 pEntry->nMethod = STORED;
1016 pEntry->nSize = pEntry->nCompressedSize = nBufferLength;
1018
1019 CRC32 aCRC32;
1020 aCRC32.update( aType );
1021 pEntry->nCrc = aCRC32.getValue();
1022
1023 try
1024 {
1026 aZipOut.writeLOC(pEntry);
1027 aZipOut.rawWrite(aType);
1028 aZipOut.rawCloseEntry();
1029 }
1030 catch ( const css::io::IOException & )
1031 {
1032 css::uno::Any anyEx = cppu::getCaughtException();
1033 throw WrappedTargetException(
1034 THROW_WHERE "Error adding mimetype to the ZipOutputStream!",
1035 getXWeak(),
1036 anyEx );
1037 }
1038}
1039
1040void ZipPackage::WriteManifest( ZipOutputStream& aZipOut, const std::vector< uno::Sequence < PropertyValue > >& aManList )
1041{
1042 // Write the manifest
1043 uno::Reference < XManifestWriter > xWriter = ManifestWriter::create( m_xContext );
1044 ZipEntry * pEntry = new ZipEntry;
1046
1047 pEntry->sPath = "META-INF/manifest.xml";
1048 pEntry->nMethod = DEFLATED;
1049 pEntry->nCrc = -1;
1050 pEntry->nSize = pEntry->nCompressedSize = -1;
1052
1053 xWriter->writeManifestSequence ( pBuffer, comphelper::containerToSequence(aManList) );
1054
1055 sal_Int32 nBufferLength = static_cast < sal_Int32 > ( pBuffer->getPosition() );
1056 pBuffer->realloc( nBufferLength );
1057
1058 // the manifest.xml is never encrypted - so pass an empty reference
1060 aZipOut.writeLOC(pEntry);
1061 ZipOutputEntry aZipEntry(aZipOut.getStream(), m_xContext, *pEntry, nullptr, /*bEncrypt*/false);
1062 aZipEntry.write(pBuffer->getSequence());
1063 aZipEntry.closeEntry();
1064 aZipOut.rawCloseEntry();
1065}
1066
1067void ZipPackage::WriteContentTypes( ZipOutputStream& aZipOut, const std::vector< uno::Sequence < PropertyValue > >& aManList )
1068{
1069 ZipEntry* pEntry = new ZipEntry;
1071
1072 pEntry->sPath = "[Content_Types].xml";
1073 pEntry->nMethod = DEFLATED;
1074 pEntry->nCrc = -1;
1075 pEntry->nSize = pEntry->nCompressedSize = -1;
1077
1078 // Add default entries, the count must be updated manually when appending.
1079 // Add at least the standard default entries.
1080 uno::Sequence< beans::StringPair > aDefaultsSequence
1081 {
1082 { "xml", "application/xml" },
1083 { "rels", "application/vnd.openxmlformats-package.relationships+xml" },
1084 { "png", "image/png" },
1085 { "jpeg", "image/jpeg" }
1086 };
1087
1088 uno::Sequence< beans::StringPair > aOverridesSequence(aManList.size());
1089 auto aOverridesSequenceRange = asNonConstRange(aOverridesSequence);
1090 sal_Int32 nOverSeqLength = 0;
1091 for (const auto& rMan : aManList)
1092 {
1093 OUString aType;
1094 OSL_ENSURE( rMan[PKG_MNFST_MEDIATYPE].Name == "MediaType" && rMan[PKG_MNFST_FULLPATH].Name == "FullPath",
1095 "The mediatype sequence format is wrong!" );
1096 rMan[PKG_MNFST_MEDIATYPE].Value >>= aType;
1097 if ( !aType.isEmpty() )
1098 {
1099 OUString aPath;
1100 // only nonempty type makes sense here
1101 rMan[PKG_MNFST_FULLPATH].Value >>= aPath;
1102 //FIXME: For now we have no way of differentiating defaults from others.
1103 aOverridesSequenceRange[nOverSeqLength].First = "/" + aPath;
1104 aOverridesSequenceRange[nOverSeqLength].Second = aType;
1105 ++nOverSeqLength;
1106 }
1107 }
1108 aOverridesSequence.realloc(nOverSeqLength);
1109
1110 ::comphelper::OFOPXMLHelper::WriteContentSequence(
1111 pBuffer, aDefaultsSequence, aOverridesSequence, m_xContext );
1112
1113 sal_Int32 nBufferLength = static_cast < sal_Int32 > ( pBuffer->getPosition() );
1114 pBuffer->realloc( nBufferLength );
1115
1116 // there is no encryption in this format currently
1118 aZipOut.writeLOC(pEntry);
1119 ZipOutputEntry aZipEntry(aZipOut.getStream(), m_xContext, *pEntry, nullptr, /*bEncrypt*/false);
1120 aZipEntry.write(pBuffer->getSequence());
1121 aZipEntry.closeEntry();
1122 aZipOut.rawCloseEntry();
1123}
1124
1125void ZipPackage::ConnectTo( const uno::Reference< io::XInputStream >& xInStream )
1126{
1127 m_xContentSeek.set( xInStream, uno::UNO_QUERY_THROW );
1128 m_xContentStream = xInStream;
1129
1130 // seek back to the beginning of the temp file so we can read segments from it
1131 m_xContentSeek->seek( 0 );
1132 if ( m_pZipFile )
1133 m_pZipFile->setInputStream( m_xContentStream );
1134 else
1136}
1137
1138namespace
1139{
1140 class RandomPool
1141 {
1142 private:
1143 rtlRandomPool m_aRandomPool;
1144 public:
1145 RandomPool() : m_aRandomPool(rtl_random_createPool ())
1146 {
1147 }
1149 {
1150 return m_aRandomPool;
1151 }
1152 ~RandomPool()
1153 {
1154 // Clean up random pool memory
1155 rtl_random_destroyPool(m_aRandomPool);
1156 }
1157 };
1158}
1159
1160uno::Reference< io::XInputStream > ZipPackage::writeTempFile()
1161{
1162 // In case the target local file does not exist or empty
1163 // write directly to it otherwise create a temporary file to write to.
1164 // If a temporary file is created it is returned back by the method.
1165 // If the data written directly, xComponentStream will be switched here
1166
1167 bool bUseTemp = true;
1168 uno::Reference < io::XInputStream > xResult;
1169 uno::Reference < io::XInputStream > xTempIn;
1170
1171 uno::Reference < io::XOutputStream > xTempOut;
1172 uno::Reference< io::XActiveDataStreamer > xSink;
1173
1174 if ( m_eMode == e_IMode_URL && !m_pZipFile && isLocalFile() )
1175 {
1177 if( xSink.is() )
1178 {
1179 uno::Reference< io::XStream > xStr = xSink->getStream();
1180 if( xStr.is() )
1181 {
1182 xTempOut = xStr->getOutputStream();
1183 if( xTempOut.is() )
1184 bUseTemp = false;
1185 }
1186 }
1187 }
1188 else if ( m_eMode == e_IMode_XStream && !m_pZipFile )
1189 {
1190 // write directly to an empty stream
1191 xTempOut = m_xStream->getOutputStream();
1192 if( xTempOut.is() )
1193 bUseTemp = false;
1194 }
1195
1196 if( bUseTemp )
1197 {
1198 // create temporary file
1200 xTempOut.set( xTempFile );
1201 xTempIn.set( xTempFile );
1202 }
1203
1204 // Hand it to the ZipOutputStream:
1205 ZipOutputStream aZipOut( xTempOut );
1206 try
1207 {
1208 if ( m_nFormat == embed::StorageFormats::PACKAGE )
1209 {
1210 // Remove the old manifest.xml file as the
1211 // manifest will be re-generated and the
1212 // META-INF directory implicitly created if does not exist
1213 static constexpr OUStringLiteral sMeta (u"META-INF");
1214
1215 if ( m_xRootFolder->hasByName( sMeta ) )
1216 {
1217 static constexpr OUStringLiteral sManifest (u"manifest.xml");
1218
1219 uno::Reference< XNameContainer > xMetaInfFolder;
1220 Any aAny = m_xRootFolder->getByName( sMeta );
1221 aAny >>= xMetaInfFolder;
1222 if ( xMetaInfFolder.is() && xMetaInfFolder->hasByName( sManifest ) )
1223 xMetaInfFolder->removeByName( sManifest );
1224 }
1225
1226 // Write a magic file with mimetype
1227 WriteMimetypeMagicFile( aZipOut );
1228 }
1229 else if ( m_nFormat == embed::StorageFormats::OFOPXML )
1230 {
1231 // Remove the old [Content_Types].xml file as the
1232 // file will be re-generated
1233
1234 static constexpr OUStringLiteral aContentTypes(u"[Content_Types].xml");
1235
1236 if ( m_xRootFolder->hasByName( aContentTypes ) )
1237 m_xRootFolder->removeByName( aContentTypes );
1238 }
1239
1240 // Create a vector to store data for the manifest.xml file
1241 std::vector < uno::Sequence < PropertyValue > > aManList;
1242
1243 static constexpr OUStringLiteral sMediaType(u"MediaType");
1244 static constexpr OUStringLiteral sVersion(u"Version");
1245 static constexpr OUStringLiteral sFullPath(u"FullPath");
1246 const bool bIsGpgEncrypt = m_aGpgProps.hasElements();
1247
1248 if ( m_nFormat == embed::StorageFormats::PACKAGE )
1249 {
1250 uno::Sequence < PropertyValue > aPropSeq(
1251 bIsGpgEncrypt ? PKG_SIZE_NOENCR_MNFST+1 : PKG_SIZE_NOENCR_MNFST );
1252 auto pPropSeq = aPropSeq.getArray();
1253 pPropSeq [PKG_MNFST_MEDIATYPE].Name = sMediaType;
1254 pPropSeq [PKG_MNFST_MEDIATYPE].Value <<= m_xRootFolder->GetMediaType();
1255 pPropSeq [PKG_MNFST_VERSION].Name = sVersion;
1256 pPropSeq [PKG_MNFST_VERSION].Value <<= m_xRootFolder->GetVersion();
1257 pPropSeq [PKG_MNFST_FULLPATH].Name = sFullPath;
1258 pPropSeq [PKG_MNFST_FULLPATH].Value <<= OUString("/");
1259
1260 if( bIsGpgEncrypt )
1261 {
1262 pPropSeq[PKG_SIZE_NOENCR_MNFST].Name = "KeyInfo";
1263 pPropSeq[PKG_SIZE_NOENCR_MNFST].Value <<= m_aGpgProps;
1264 }
1265 aManList.push_back( aPropSeq );
1266 }
1267
1268 {
1269 // This will be used to generate random salt and initialisation vectors
1270 // for encrypted streams
1271 RandomPool aRandomPool;
1272
1273 sal_Int32 const nPBKDF2IterationCount = 100000;
1274
1275 // call saveContents ( it will recursively save sub-directories
1276 m_xRootFolder->saveContents("", aManList, aZipOut, GetEncryptionKey(), bIsGpgEncrypt ? 0 : nPBKDF2IterationCount, aRandomPool.get());
1277 }
1278
1279 if( m_nFormat == embed::StorageFormats::PACKAGE )
1280 {
1281 WriteManifest( aZipOut, aManList );
1282 }
1283 else if( m_nFormat == embed::StorageFormats::OFOPXML )
1284 {
1285 WriteContentTypes( aZipOut, aManList );
1286 }
1287
1288 aZipOut.finish();
1289
1290 if( bUseTemp )
1291 xResult = xTempIn;
1292
1293 // Update our References to point to the new temp file
1294 if( !bUseTemp )
1295 {
1296 // the case when the original contents were written directly
1297 xTempOut->flush();
1298
1299 // in case the stream is based on a file it will implement the following interface
1300 // the call should be used to be sure that the contents are written to the file system
1301 uno::Reference< io::XAsyncOutputMonitor > asyncOutputMonitor( xTempOut, uno::UNO_QUERY );
1302 if (asyncOutputMonitor.is() && !m_bDisableFileSync)
1303 asyncOutputMonitor->waitForCompletion();
1304
1305 // no need to postpone switching to the new stream since the target was written directly
1306 uno::Reference< io::XInputStream > xNewStream;
1307 if ( m_eMode == e_IMode_URL )
1308 xNewStream = xSink->getStream()->getInputStream();
1309 else if ( m_eMode == e_IMode_XStream && m_xStream.is() )
1310 xNewStream = m_xStream->getInputStream();
1311
1312 if ( xNewStream.is() )
1313 ConnectTo( xNewStream );
1314 }
1315 }
1316 catch ( uno::Exception& )
1317 {
1318 if( bUseTemp )
1319 {
1320 // no information loss appears, thus no special handling is required
1321 uno::Any aCaught( ::cppu::getCaughtException() );
1322
1323 // it is allowed to throw WrappedTargetException
1324 WrappedTargetException aException;
1325 if ( aCaught >>= aException )
1326 throw aException;
1327
1328 throw WrappedTargetException(
1329 THROW_WHERE "Problem writing the original content!",
1330 getXWeak(),
1331 aCaught );
1332 }
1333 else
1334 {
1335 // the document is written directly, although it was empty it is important to notify that the writing has failed
1336 // TODO/LATER: let the package be able to recover in this situation
1337 OUString aErrTxt(THROW_WHERE "This package is unusable!");
1338 embed::UseBackupException aException( aErrTxt, uno::Reference< uno::XInterface >(), OUString() );
1339 throw WrappedTargetException( aErrTxt,
1340 getXWeak(),
1341 Any ( aException ) );
1342 }
1343 }
1344
1345 return xResult;
1346}
1347
1348uno::Reference< XActiveDataStreamer > ZipPackage::openOriginalForOutput()
1349{
1350 // open and truncate the original file
1351 Content aOriginalContent(
1352 m_aURL, uno::Reference< XCommandEnvironment >(),
1353 m_xContext );
1354 uno::Reference< XActiveDataStreamer > xSink = new ActiveDataStreamer;
1355
1356 if ( m_eMode == e_IMode_URL )
1357 {
1358 try
1359 {
1360 bool bTruncSuccess = false;
1361
1362 try
1363 {
1364 Exception aDetect;
1365 Any aAny = aOriginalContent.setPropertyValue("Size", Any( sal_Int64(0) ) );
1366 if( !( aAny >>= aDetect ) )
1367 bTruncSuccess = true;
1368 }
1369 catch( Exception& )
1370 {
1371 }
1372
1373 if( !bTruncSuccess )
1374 {
1375 // the file is not accessible
1376 // just try to write an empty stream to it
1377
1378 uno::Reference< XInputStream > xTempIn = new DummyInputStream; //uno::Reference< XInputStream >( xTempOut, UNO_QUERY );
1379 aOriginalContent.writeStream( xTempIn , true );
1380 }
1381
1382 OpenCommandArgument2 aArg;
1383 aArg.Mode = OpenMode::DOCUMENT;
1384 aArg.Priority = 0; // unused
1385 aArg.Sink = xSink;
1386 aArg.Properties = uno::Sequence< Property >( 0 ); // unused
1387
1388 aOriginalContent.executeCommand("open", Any( aArg ) );
1389 }
1390 catch( Exception& )
1391 {
1392 // seems to be nonlocal file
1393 // temporary file mechanics should be used
1394 }
1395 }
1396
1397 return xSink;
1398}
1399
1401{
1402 // lock the component for the time of committing
1403 ::osl::MutexGuard aGuard( m_aMutexHolder->GetMutex() );
1404
1406 {
1407 IOException aException;
1408 throw WrappedTargetException(THROW_WHERE "This package is read only!",
1409 getXWeak(), Any ( aException ) );
1410 }
1411 // first the writeTempFile is called, if it returns a stream the stream should be written to the target
1412 // if no stream was returned, the file was written directly, nothing should be done
1413 uno::Reference< io::XInputStream > xTempInStream;
1414 try
1415 {
1416 xTempInStream = writeTempFile();
1417 }
1418 catch (const ucb::ContentCreationException&)
1419 {
1420 css::uno::Any anyEx = cppu::getCaughtException();
1421 throw WrappedTargetException(THROW_WHERE "Temporary file should be creatable!",
1422 getXWeak(), anyEx );
1423 }
1424 if ( xTempInStream.is() )
1425 {
1426 uno::Reference< io::XSeekable > xTempSeek( xTempInStream, uno::UNO_QUERY_THROW );
1427
1428 try
1429 {
1430 xTempSeek->seek( 0 );
1431 }
1432 catch( const uno::Exception& )
1433 {
1434 css::uno::Any anyEx = cppu::getCaughtException();
1435 throw WrappedTargetException(THROW_WHERE "Temporary file should be seekable!",
1436 getXWeak(), anyEx );
1437 }
1438
1439 try
1440 {
1441 // connect to the temporary stream
1442 ConnectTo( xTempInStream );
1443 }
1444 catch( const io::IOException& )
1445 {
1446 css::uno::Any anyEx = cppu::getCaughtException();
1447 throw WrappedTargetException(THROW_WHERE "Temporary file should be connectable!",
1448 getXWeak(), anyEx );
1449 }
1450
1451 if ( m_eMode == e_IMode_XStream )
1452 {
1453 // First truncate our output stream
1454 uno::Reference < XOutputStream > xOutputStream;
1455
1456 // preparation for copy step
1457 try
1458 {
1459 xOutputStream = m_xStream->getOutputStream();
1460
1461 // Make sure we avoid a situation where the current position is
1462 // not zero, but the underlying file is truncated in the
1463 // meantime.
1464 uno::Reference<io::XSeekable> xSeekable(xOutputStream, uno::UNO_QUERY);
1465 if (xSeekable.is())
1466 xSeekable->seek(0);
1467
1468 uno::Reference < XTruncate > xTruncate ( xOutputStream, UNO_QUERY_THROW );
1469
1470 // after successful truncation the original file contents are already lost
1471 xTruncate->truncate();
1472 }
1473 catch( const uno::Exception& )
1474 {
1475 css::uno::Any anyEx = cppu::getCaughtException();
1476 throw WrappedTargetException(THROW_WHERE "This package is read only!",
1477 getXWeak(), anyEx );
1478 }
1479
1480 try
1481 {
1482 // then copy the contents of the tempfile to our output stream
1483 ::comphelper::OStorageHelper::CopyInputToOutput( xTempInStream, xOutputStream );
1484 xOutputStream->flush();
1485 uno::Reference< io::XAsyncOutputMonitor > asyncOutputMonitor(
1486 xOutputStream, uno::UNO_QUERY );
1487 if ( asyncOutputMonitor.is() ) {
1488 asyncOutputMonitor->waitForCompletion();
1489 }
1490 }
1491 catch( uno::Exception& )
1492 {
1493 // if anything goes wrong in this block the target file becomes corrupted
1494 // so an exception should be thrown as a notification about it
1495 // and the package must disconnect from the stream
1497 }
1498 }
1499 else if ( m_eMode == e_IMode_URL )
1500 {
1501 uno::Reference< XOutputStream > aOrigFileStream;
1502 bool bCanBeCorrupted = false;
1503
1504 if( isLocalFile() )
1505 {
1506 // write directly in case of local file
1507 uno::Reference< css::ucb::XSimpleFileAccess3 > xSimpleAccess(
1508 SimpleFileAccess::create( m_xContext ) );
1509 OSL_ENSURE( xSimpleAccess.is(), "Can't instantiate SimpleFileAccess service!" );
1510 uno::Reference< io::XTruncate > xOrigTruncate;
1511 if ( xSimpleAccess.is() )
1512 {
1513 try
1514 {
1515 aOrigFileStream = xSimpleAccess->openFileWrite( m_aURL );
1516 xOrigTruncate.set( aOrigFileStream, uno::UNO_QUERY_THROW );
1517 // after successful truncation the file is already corrupted
1518 xOrigTruncate->truncate();
1519 }
1520 catch( uno::Exception& )
1521 {}
1522 }
1523
1524 if( xOrigTruncate.is() )
1525 {
1526 try
1527 {
1528 ::comphelper::OStorageHelper::CopyInputToOutput( xTempInStream, aOrigFileStream );
1529 aOrigFileStream->closeOutput();
1530 }
1531 catch( uno::Exception& )
1532 {
1533 try {
1534 aOrigFileStream->closeOutput();
1535 } catch ( uno::Exception& ) {}
1536
1537 aOrigFileStream.clear();
1538 // the original file can already be corrupted
1539 bCanBeCorrupted = true;
1540 }
1541 }
1542 }
1543
1544 if( !aOrigFileStream.is() )
1545 {
1546 try
1547 {
1548 uno::Reference < XPropertySet > xPropSet ( xTempInStream, UNO_QUERY_THROW );
1549
1550 OUString sTargetFolder = m_aURL.copy ( 0, m_aURL.lastIndexOf ( u'/' ) );
1551 Content aContent(
1552 sTargetFolder, uno::Reference< XCommandEnvironment >(),
1553 m_xContext );
1554
1555 OUString sTempURL;
1556 Any aAny = xPropSet->getPropertyValue ("Uri");
1557 aAny >>= sTempURL;
1558
1559 TransferInfo aInfo;
1560 aInfo.NameClash = NameClash::OVERWRITE;
1561 aInfo.MoveData = false;
1562 aInfo.SourceURL = sTempURL;
1563 aInfo.NewTitle = rtl::Uri::decode ( m_aURL.copy ( 1 + m_aURL.lastIndexOf ( u'/' ) ),
1564 rtl_UriDecodeWithCharset,
1565 RTL_TEXTENCODING_UTF8 );
1566 // if the file is still not corrupted, it can become after the next step
1567 aContent.executeCommand ("transfer", Any(aInfo) );
1568 }
1569 catch ( const css::uno::Exception& )
1570 {
1571 if ( bCanBeCorrupted )
1573
1574 css::uno::Any anyEx = cppu::getCaughtException();
1575 throw WrappedTargetException(
1576 THROW_WHERE "This package may be read only!",
1577 getXWeak(),
1578 anyEx );
1579 }
1580 }
1581 }
1582 }
1583
1584 // after successful storing it can be set to false
1586}
1587
1588void ZipPackage::DisconnectFromTargetAndThrowException_Impl( const uno::Reference< io::XInputStream >& xTempStream )
1589{
1590 m_xStream.set( xTempStream, uno::UNO_QUERY );
1591 if ( m_xStream.is() )
1593 else
1595
1596 OUString aTempURL;
1597 try {
1598 uno::Reference< beans::XPropertySet > xTempFile( xTempStream, uno::UNO_QUERY_THROW );
1599 uno::Any aUrl = xTempFile->getPropertyValue("Uri");
1600 aUrl >>= aTempURL;
1601 xTempFile->setPropertyValue("RemoveFile",
1602 uno::Any( false ) );
1603 }
1604 catch ( uno::Exception& )
1605 {
1606 OSL_FAIL( "These calls are pretty simple, they should not fail!" );
1607 }
1608
1609 OUString aErrTxt(THROW_WHERE "This package is read only!");
1610 embed::UseBackupException aException( aErrTxt, uno::Reference< uno::XInterface >(), aTempURL );
1611 throw WrappedTargetException( aErrTxt,
1612 getXWeak(),
1613 Any ( aException ) );
1614}
1615
1616uno::Sequence< sal_Int8 > ZipPackage::GetEncryptionKey()
1617{
1618 uno::Sequence< sal_Int8 > aResult;
1619
1620 if ( m_aStorageEncryptionKeys.hasElements() )
1621 {
1622 OUString aNameToFind;
1623 if ( m_nStartKeyGenerationID == xml::crypto::DigestID::SHA256 )
1625 else if ( m_nStartKeyGenerationID == xml::crypto::DigestID::SHA1 )
1627 else
1628 throw uno::RuntimeException(THROW_WHERE "No expected key is provided!" );
1629
1630 for ( const auto& rKey : std::as_const(m_aStorageEncryptionKeys) )
1631 if ( rKey.Name == aNameToFind )
1632 rKey.Value >>= aResult;
1633 }
1634 else
1635 aResult = m_aEncryptionKey;
1636
1637 return aResult;
1638}
1639
1641{
1642 return false;
1643}
1645{
1646 return uno::Sequence < ElementChange > ();
1647}
1648
1649
1651{
1652 return "com.sun.star.packages.comp.ZipPackage";
1653}
1654
1656{
1657 return { "com.sun.star.packages.Package" };
1658}
1659
1660sal_Bool SAL_CALL ZipPackage::supportsService( OUString const & rServiceName )
1661{
1662 return cppu::supportsService(this, rServiceName);
1663}
1664
1665uno::Reference< XPropertySetInfo > SAL_CALL ZipPackage::getPropertySetInfo()
1666{
1667 return uno::Reference < XPropertySetInfo > ();
1668}
1669
1670void SAL_CALL ZipPackage::setPropertyValue( const OUString& aPropertyName, const Any& aValue )
1671{
1672 if ( m_nFormat != embed::StorageFormats::PACKAGE )
1673 throw UnknownPropertyException(aPropertyName);
1674
1675 if (aPropertyName == HAS_ENCRYPTED_ENTRIES_PROPERTY
1676 ||aPropertyName == HAS_NONENCRYPTED_ENTRIES_PROPERTY
1677 ||aPropertyName == IS_INCONSISTENT_PROPERTY
1678 ||aPropertyName == MEDIATYPE_FALLBACK_USED_PROPERTY)
1679 throw PropertyVetoException(THROW_WHERE );
1680 else if ( aPropertyName == ENCRYPTION_KEY_PROPERTY )
1681 {
1682 if ( !( aValue >>= m_aEncryptionKey ) )
1683 throw IllegalArgumentException(THROW_WHERE, uno::Reference< uno::XInterface >(), 2 );
1684
1685 m_aStorageEncryptionKeys.realloc( 0 );
1686 }
1687 else if ( aPropertyName == STORAGE_ENCRYPTION_KEYS_PROPERTY )
1688 {
1689 // this property is only necessary to support raw passwords in storage API;
1690 // because of this support the storage has to operate with more than one key dependent on storage generation algorithm;
1691 // when this support is removed, the storage will get only one key from outside
1692 if ( !( aValue >>= m_aStorageEncryptionKeys ) )
1693 throw IllegalArgumentException(THROW_WHERE, uno::Reference< uno::XInterface >(), 2 );
1694
1695 m_aEncryptionKey.realloc( 0 );
1696 }
1697 else if ( aPropertyName == ENCRYPTION_ALGORITHMS_PROPERTY )
1698 {
1699 uno::Sequence< beans::NamedValue > aAlgorithms;
1700 if ( m_pZipFile || !( aValue >>= aAlgorithms ) || !aAlgorithms.hasElements() )
1701 {
1702 // the algorithms can not be changed if the file has a persistence based on the algorithms ( m_pZipFile )
1703 throw IllegalArgumentException(THROW_WHERE "unexpected algorithms list is provided.", uno::Reference< uno::XInterface >(), 2 );
1704 }
1705
1706 for ( const auto& rAlgorithm : std::as_const(aAlgorithms) )
1707 {
1708 if ( rAlgorithm.Name == "StartKeyGenerationAlgorithm" )
1709 {
1710 sal_Int32 nID = 0;
1711 if ( !( rAlgorithm.Value >>= nID )
1712 || ( nID != xml::crypto::DigestID::SHA256 && nID != xml::crypto::DigestID::SHA1 ) )
1713 throw IllegalArgumentException(THROW_WHERE "Unexpected start key generation algorithm is provided!", uno::Reference< uno::XInterface >(), 2 );
1714
1716 }
1717 else if ( rAlgorithm.Name == "EncryptionAlgorithm" )
1718 {
1719 sal_Int32 nID = 0;
1720 if ( !( rAlgorithm.Value >>= nID )
1721 || ( nID != xml::crypto::CipherID::AES_CBC_W3C_PADDING && nID != xml::crypto::CipherID::BLOWFISH_CFB_8 ) )
1722 throw IllegalArgumentException(THROW_WHERE "Unexpected start key generation algorithm is provided!", uno::Reference< uno::XInterface >(), 2 );
1723
1725 }
1726 else if ( rAlgorithm.Name == "ChecksumAlgorithm" )
1727 {
1728 sal_Int32 nID = 0;
1729 if ( !( rAlgorithm.Value >>= nID )
1730 || ( nID != xml::crypto::DigestID::SHA1_1K && nID != xml::crypto::DigestID::SHA256_1K ) )
1731 throw IllegalArgumentException(THROW_WHERE "Unexpected start key generation algorithm is provided!", uno::Reference< uno::XInterface >(), 2 );
1732
1733 m_nChecksumDigestID = nID;
1734 }
1735 else
1736 {
1737 OSL_ENSURE( false, "Unexpected encryption algorithm is provided!" );
1738 throw IllegalArgumentException(THROW_WHERE "unexpected algorithms list is provided.", uno::Reference< uno::XInterface >(), 2 );
1739 }
1740 }
1741 }
1742 else if ( aPropertyName == ENCRYPTION_GPG_PROPERTIES )
1743 {
1744 uno::Sequence< uno::Sequence< beans::NamedValue > > aGpgProps;
1745 if ( !( aValue >>= aGpgProps ) || !aGpgProps.hasElements() )
1746 {
1747 throw IllegalArgumentException(THROW_WHERE "unexpected Gpg properties are provided.", uno::Reference< uno::XInterface >(), 2 );
1748 }
1749
1750 m_aGpgProps = aGpgProps;
1751
1752 // override algorithm defaults (which are some legacy ODF
1753 // defaults) with reasonable values
1754 m_nStartKeyGenerationID = 0; // this is unused for PGP
1755 m_nCommonEncryptionID = xml::crypto::CipherID::AES_CBC_W3C_PADDING;
1756 m_nChecksumDigestID = xml::crypto::DigestID::SHA512_1K;
1757 }
1758 else
1759 throw UnknownPropertyException(aPropertyName);
1760}
1761
1762Any SAL_CALL ZipPackage::getPropertyValue( const OUString& PropertyName )
1763{
1764 // TODO/LATER: Activate the check when zip-ucp is ready
1765 // if ( m_nFormat != embed::StorageFormats::PACKAGE )
1766 // throw UnknownPropertyException(THROW_WHERE );
1767
1768 if ( PropertyName == ENCRYPTION_KEY_PROPERTY )
1769 {
1770 return Any(m_aEncryptionKey);
1771 }
1772 else if ( PropertyName == ENCRYPTION_ALGORITHMS_PROPERTY )
1773 {
1775 aAlgorithms["StartKeyGenerationAlgorithm"] <<= m_nStartKeyGenerationID;
1776 aAlgorithms["EncryptionAlgorithm"] <<= m_nCommonEncryptionID;
1777 aAlgorithms["ChecksumAlgorithm"] <<= m_nChecksumDigestID;
1778 return Any(aAlgorithms.getAsConstNamedValueList());
1779 }
1780 if ( PropertyName == STORAGE_ENCRYPTION_KEYS_PROPERTY )
1781 {
1783 }
1784 else if ( PropertyName == HAS_ENCRYPTED_ENTRIES_PROPERTY )
1785 {
1787 }
1788 else if ( PropertyName == ENCRYPTION_GPG_PROPERTIES )
1789 {
1790 return Any(m_aGpgProps);
1791 }
1792 else if ( PropertyName == HAS_NONENCRYPTED_ENTRIES_PROPERTY )
1793 {
1795 }
1796 else if ( PropertyName == IS_INCONSISTENT_PROPERTY )
1797 {
1798 return Any(m_bInconsistent);
1799 }
1800 else if ( PropertyName == MEDIATYPE_FALLBACK_USED_PROPERTY )
1801 {
1803 }
1804 throw UnknownPropertyException(PropertyName);
1805}
1806void SAL_CALL ZipPackage::addPropertyChangeListener( const OUString& /*aPropertyName*/, const uno::Reference< XPropertyChangeListener >& /*xListener*/ )
1807{
1808}
1809void SAL_CALL ZipPackage::removePropertyChangeListener( const OUString& /*aPropertyName*/, const uno::Reference< XPropertyChangeListener >& /*aListener*/ )
1810{
1811}
1812void SAL_CALL ZipPackage::addVetoableChangeListener( const OUString& /*PropertyName*/, const uno::Reference< XVetoableChangeListener >& /*aListener*/ )
1813{
1814}
1815void SAL_CALL ZipPackage::removeVetoableChangeListener( const OUString& /*PropertyName*/, const uno::Reference< XVetoableChangeListener >& /*aListener*/ )
1816{
1817}
1818
1819extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
1821 css::uno::XComponentContext* context , css::uno::Sequence<css::uno::Any> const&)
1822{
1823 return cppu::acquire(new ZipPackage(context));
1824}
1825
1826extern "C" bool TestImportZip(SvStream& rStream)
1827{
1828 // explicitly tests the "RepairPackage" recovery mode
1830 css::uno::Reference<css::io::XInputStream> xStream(new utl::OInputStreamWrapper(rStream));
1831 css::uno::Sequence<Any> aArgs{ Any(xStream), Any(NamedValue("RepairPackage", Any(true))) };
1832 xPackage->initialize(aArgs);
1833 return true;
1834}
1835
1836/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Reference< XComponentContext > m_xContext
constexpr OUStringLiteral ENCRYPTION_ALGORITHMS_PROPERTY
#define IS_INCONSISTENT_PROPERTY
#define HAS_NONENCRYPTED_ENTRIES_PROPERTY
constexpr OUStringLiteral MEDIATYPE_FALLBACK_USED_PROPERTY
#define PKG_SIZE_NOENCR_MNFST
#define PKG_MNFST_MEDIATYPE
constexpr OUStringLiteral STORAGE_ENCRYPTION_KEYS_PROPERTY
#define PKG_MNFST_VERSION
#define HAS_ENCRYPTED_ENTRIES_PROPERTY
#define PKG_MNFST_FULLPATH
constexpr OUStringLiteral ENCRYPTION_GPG_PROPERTIES
constexpr OUStringLiteral ENCRYPTION_KEY_PROPERTY
Reference< XInputStream > xStream
void * rtlRandomPool
bool TestImportZip(SvStream &rStream)
#define THROW_WHERE
Definition: ZipPackage.cxx:99
SAL_DLLPUBLIC_EXPORT css::uno::XInterface * package_ZipPackage_get_implementation(css::uno::XComponentContext *context, css::uno::Sequence< css::uno::Any > const &)
@ e_IMode_XInputStream
Definition: ZipPackage.hxx:56
@ e_IMode_XStream
Definition: ZipPackage.hxx:57
@ e_IMode_None
Definition: ZipPackage.hxx:54
@ e_IMode_URL
Definition: ZipPackage.hxx:55
constexpr OUStringLiteral sMediaType
Definition: CRC32.hxx:29
sal_Int32 getValue() const
Definition: CRC32.cxx:39
void update(const css::uno::Sequence< sal_Int8 > &b)
Update CRC32 with specified sequence of bytes.
Definition: CRC32.cxx:51
const ZipEntry * nextElement()
void write(const css::uno::Sequence< sal_Int8 > &rBuffer)
void writeLOC(ZipEntry *pEntry, bool bEncrypt=false)
void rawCloseEntry(bool bEncrypt=false)
const css::uno::Reference< css::io::XOutputStream > & getStream() const
void rawWrite(const css::uno::Sequence< sal_Int8 > &rBuffer)
static void setEntry(ZipEntry *pEntry)
static sal_uInt32 getCurrentDosTime()
virtual css::uno::Any SAL_CALL getByName(const OUString &aName) override
virtual sal_Bool SAL_CALL hasByName(const OUString &aName) override
ZipContentInfo & doGetByName(const OUString &aName)
bool m_bMediaTypeFallbackUsed
Definition: ZipPackage.hxx:88
virtual OUString SAL_CALL getImplementationName() override
virtual void SAL_CALL addVetoableChangeListener(const OUString &PropertyName, const css::uno::Reference< css::beans::XVetoableChangeListener > &aListener) override
virtual sal_Bool SAL_CALL supportsService(const OUString &ServiceName) override
std::optional< ZipFile > m_pZipFile
Definition: ZipPackage.hxx:100
virtual void SAL_CALL commitChanges() override
sal_Int32 m_nStartKeyGenerationID
Definition: ZipPackage.hxx:79
bool isLocalFile() const
Definition: ZipPackage.cxx:160
virtual ~ZipPackage() override
Definition: ZipPackage.cxx:156
void parseManifest()
Definition: ZipPackage.cxx:165
void DisconnectFromTargetAndThrowException_Impl(const css::uno::Reference< css::io::XInputStream > &xTempStream)
css::uno::Reference< css::io::XActiveDataStreamer > openOriginalForOutput()
css::uno::Sequence< sal_Int8 > m_aEncryptionKey
Definition: ZipPackage.hxx:73
const css::uno::Reference< css::uno::XComponentContext > m_xContext
Definition: ZipPackage.hxx:98
css::uno::Sequence< css::uno::Sequence< css::beans::NamedValue > > m_aGpgProps
Definition: ZipPackage.hxx:74
bool m_bAllowRemoveOnInsert
Definition: ZipPackage.hxx:90
virtual void SAL_CALL addPropertyChangeListener(const OUString &aPropertyName, const css::uno::Reference< css::beans::XPropertyChangeListener > &xListener) override
void WriteMimetypeMagicFile(ZipOutputStream &aZipOut)
bool m_bDisableFileSync
Definition: ZipPackage.hxx:101
virtual css::uno::Any SAL_CALL getByHierarchicalName(const OUString &aName) override
Definition: ZipPackage.cxx:792
bool m_bHasEncryptedEntries
Definition: ZipPackage.hxx:82
InitialisationMode m_eMode
Definition: ZipPackage.hxx:92
rtl::Reference< comphelper::RefCountedMutex > m_aMutexHolder
Definition: ZipPackage.hxx:70
void getZipFileContents()
Definition: ZipPackage.cxx:507
virtual css::uno::Any SAL_CALL getPropertyValue(const OUString &PropertyName) override
sal_Int32 m_nFormat
Definition: ZipPackage.hxx:89
virtual void SAL_CALL initialize(const css::uno::Sequence< css::uno::Any > &aArguments) override
Definition: ZipPackage.cxx:586
void ConnectTo(const css::uno::Reference< css::io::XInputStream > &xInStream)
sal_Int32 m_nCommonEncryptionID
Definition: ZipPackage.hxx:81
bool m_bHasNonEncryptedEntries
Definition: ZipPackage.hxx:83
virtual void SAL_CALL removeVetoableChangeListener(const OUString &PropertyName, const css::uno::Reference< css::beans::XVetoableChangeListener > &aListener) override
void WriteContentTypes(ZipOutputStream &aZipOut, const ::std::vector< css::uno::Sequence< css::beans::PropertyValue > > &aManList)
virtual sal_Bool SAL_CALL hasPendingChanges() override
virtual css::uno::Reference< css::uno::XInterface > SAL_CALL createInstanceWithArguments(const css::uno::Sequence< css::uno::Any > &aArguments) override
Definition: ZipPackage.cxx:988
css::uno::Reference< css::io::XStream > m_xStream
Definition: ZipPackage.hxx:95
virtual css::uno::Sequence< css::util::ElementChange > SAL_CALL getPendingChanges() override
rtl::Reference< ZipPackageFolder > m_xRootFolder
Definition: ZipPackage.hxx:94
bool m_bInconsistent
Definition: ZipPackage.hxx:85
bool m_bForceRecovery
Definition: ZipPackage.hxx:86
virtual void SAL_CALL removePropertyChangeListener(const OUString &aPropertyName, const css::uno::Reference< css::beans::XPropertyChangeListener > &aListener) override
void WriteManifest(ZipOutputStream &aZipOut, const ::std::vector< css::uno::Sequence< css::beans::PropertyValue > > &aManList)
sal_Int32 m_nChecksumDigestID
Definition: ZipPackage.hxx:80
virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override
void parseContentType()
Definition: ZipPackage.cxx:444
css::uno::Reference< css::io::XInputStream > writeTempFile()
FolderHash m_aRecent
Definition: ZipPackage.hxx:76
virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo() override
css::uno::Reference< css::io::XSeekable > m_xContentSeek
Definition: ZipPackage.hxx:97
virtual css::uno::Reference< css::uno::XInterface > SAL_CALL createInstance() override
Definition: ZipPackage.cxx:982
virtual void SAL_CALL setPropertyValue(const OUString &aPropertyName, const css::uno::Any &aValue) override
ZipPackage(css::uno::Reference< css::uno::XComponentContext > xContext)
Definition: ZipPackage.cxx:138
virtual sal_Bool SAL_CALL hasByHierarchicalName(const OUString &aName) override
Definition: ZipPackage.cxx:886
OUString m_aURL
Definition: ZipPackage.hxx:77
css::uno::Sequence< css::beans::NamedValue > m_aStorageEncryptionKeys
Definition: ZipPackage.hxx:72
css::uno::Sequence< sal_Int8 > GetEncryptionKey()
css::uno::Reference< css::io::XInputStream > m_xContentStream
Definition: ZipPackage.hxx:96
static css::uno::Reference< css::io::XInputStream > CheckSeekableCanWrap(const css::uno::Reference< css::io::XInputStream > &xInStream, const css::uno::Reference< css::uno::XComponentContext > &rxContext)
static void CopyInputToOutput(const css::uno::Reference< css::io::XInputStream > &xInput, const css::uno::Reference< css::io::XOutputStream > &xOutput)
css::uno::Sequence< css::beans::NamedValue > getAsConstNamedValueList() const
css::uno::Any setPropertyValue(const OUString &rPropertyName, const css::uno::Any &rValue)
css::uno::Any getPropertyValue(const OUString &rPropertyName)
css::uno::Any executeCommand(const OUString &rCommandName, const css::uno::Any &rCommandArgument)
css::uno::Reference< css::io::XInputStream > openStream()
void writeStream(const css::uno::Reference< css::io::XInputStream > &rStream, bool bReplaceExisting)
int nCount
Reference< XOutputStream > stream
constexpr OUStringLiteral ODFVER_012_TEXT
float u
Sequence< PropertyValue > aArguments
sal_Int32 nIndex
OUString aName
tools::SvRef< SvBaseLink > xSink
constexpr OUStringLiteral aData
@ Exception
COMPHELPER_DLLPUBLIC bool isFileUrl(std::u16string_view url)
css::uno::Sequence< DstElementType > containerToSequence(const SrcType &i_Container)
Reference< XComponentContext > getProcessComponentContext()
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
Any SAL_CALL getCaughtException()
std::basic_string_view< charT, traits > getToken(std::basic_string_view< charT, traits > sv, charT delimiter, std::size_t &position)
OString OUStringToOString(std::u16string_view str, ConnectionSettings const *settings)
css::uno::Reference< css::linguistic2::XProofreadingIterator > get(css::uno::Reference< css::uno::XComponentContext > const &context)
sal_uInt16 const m_nFormat
constexpr OUStringLiteral ZIP_STORAGE_FORMAT_STRING
constexpr OUStringLiteral PACKAGE_ENCRYPTIONDATA_SHA1CORRECT
constexpr OUStringLiteral OFOPXML_STORAGE_FORMAT_STRING
constexpr OUStringLiteral PACKAGE_ENCRYPTIONDATA_SHA256UTF8
constexpr OUStringLiteral PACKAGE_STORAGE_FORMAT_STRING
ZipPackageFolder * pFolder
sal_Int64 nCompressedSize
Definition: ZipEntry.hxx:31
sal_Int32 nCrc
Definition: ZipEntry.hxx:30
sal_Int64 nSize
Definition: ZipEntry.hxx:32
sal_Int32 nTime
Definition: ZipEntry.hxx:29
OUString sPath
Definition: ZipEntry.hxx:36
sal_Int16 nMethod
Definition: ZipEntry.hxx:28
OUString aCommand
OUString Name
unsigned char sal_Bool
signed char sal_Int8