xref: /trunk/main/package/source/xstor/owriteablestream.cxx (revision 91144cd0085a7583d2099b982122deb2184ab956)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_package.hxx"
26 #include <com/sun/star/ucb/XSimpleFileAccess.hpp>
27 #include <com/sun/star/ucb/XCommandEnvironment.hpp>
28 #include <com/sun/star/lang/DisposedException.hpp>
29 #include <com/sun/star/lang/XUnoTunnel.hpp>
30 #include <com/sun/star/lang/XTypeProvider.hpp>
31 #include <com/sun/star/io/XInputStream.hpp>
32 #include <com/sun/star/io/IOException.hpp>
33 #include <com/sun/star/embed/ElementModes.hpp>
34 #include <com/sun/star/embed/StorageFormats.hpp>
35 #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
36 #include <cppuhelper/typeprovider.hxx>
37 #include <cppuhelper/exc_hlp.hxx>
38 #include <osl/diagnose.h>
39 
40 #include <comphelper/processfactory.hxx>
41 #include <comphelper/componentcontext.hxx>
42 #include <comphelper/storagehelper.hxx>
43 #include <comphelper/ofopxmlhelper.hxx>
44 
45 #include <rtl/digest.h>
46 #include <rtl/logfile.hxx>
47 #include <rtl/instance.hxx>
48 
49 #include <PackageConstants.hxx>
50 #include <mutexholder.hxx>
51 
52 #include "selfterminatefilestream.hxx"
53 #include "owriteablestream.hxx"
54 #include "oseekinstream.hxx"
55 #include "xstorage.hxx"
56 
57 // since the copying uses 32000 blocks usually, it makes sense to have a smaller size
58 #define MAX_STORCACHE_SIZE 30000
59 
60 
61 using namespace ::com::sun::star;
62 
63 namespace package
64 {
65 //-----------------------------------------------
PackageEncryptionDatasEqual(const::comphelper::SequenceAsHashMap & aHash1,const::comphelper::SequenceAsHashMap & aHash2)66 bool PackageEncryptionDatasEqual( const ::comphelper::SequenceAsHashMap& aHash1, const ::comphelper::SequenceAsHashMap& aHash2 )
67 {
68     bool bResult = ( aHash1.size() && aHash1.size() == aHash2.size() );
69     for ( ::comphelper::SequenceAsHashMap::const_iterator aIter = aHash1.begin();
70           bResult && aIter != aHash1.end();
71           aIter++ )
72     {
73         uno::Sequence< sal_Int8 > aKey1;
74         bResult = ( ( aIter->second >>= aKey1 ) && aKey1.getLength() );
75         if ( bResult )
76         {
77             uno::Sequence< sal_Int8 > aKey2 = aHash2.getUnpackedValueOrDefault( aIter->first, uno::Sequence< sal_Int8 >() );
78             bResult = ( aKey1.getLength() == aKey2.getLength() );
79             for ( sal_Int32 nInd = 0; bResult && nInd < aKey1.getLength(); nInd++ )
80                 bResult = ( aKey1[nInd] == aKey2[nInd] );
81         }
82     }
83 
84     return bResult;
85 }
86 
87 //-----------------------------------------------
StaticAddLog(const::rtl::OUString & aMessage)88 void StaticAddLog( const ::rtl::OUString& aMessage )
89 {
90     try
91     {
92         ::comphelper::ComponentContext aContext( ::comphelper::getProcessServiceFactory() );
93         if ( aContext.is() )
94         {
95             uno::Reference< logging::XSimpleLogRing > xLogRing( aContext.getSingleton( "com.sun.star.logging.DocumentIOLogRing" ), uno::UNO_QUERY_THROW );
96             xLogRing->logString( aMessage );
97         }
98     }
99     catch( uno::Exception& )
100     {
101         // No log
102     }
103 }
104 } // namespace package
105 
106 // ================================================================
107 namespace
108 {
109 //-----------------------------------------------
SetEncryptionKeyProperty_Impl(const uno::Reference<beans::XPropertySet> & xPropertySet,const uno::Sequence<beans::NamedValue> & aKey)110 void SetEncryptionKeyProperty_Impl( const uno::Reference< beans::XPropertySet >& xPropertySet,
111                                     const uno::Sequence< beans::NamedValue >& aKey )
112 {
113     OSL_ENSURE( xPropertySet.is(), "No property set is provided!\n" );
114     if ( !xPropertySet.is() )
115         throw uno::RuntimeException();
116 
117     try {
118         xPropertySet->setPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( STORAGE_ENCRYPTION_KEYS_PROPERTY ) ), uno::makeAny( aKey ) );
119     }
120     catch ( uno::Exception& aException )
121     {
122         ::package::StaticAddLog( aException.Message );
123         ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Can't set encryption" ) ) );
124         OSL_ENSURE( sal_False, "Can't write encryption related properties!\n" );
125         throw io::IOException(); // TODO
126     }
127 }
128 
129 //-----------------------------------------------
GetEncryptionKeyProperty_Impl(const uno::Reference<beans::XPropertySet> & xPropertySet)130 uno::Any GetEncryptionKeyProperty_Impl( const uno::Reference< beans::XPropertySet >& xPropertySet )
131 {
132     OSL_ENSURE( xPropertySet.is(), "No property set is provided!\n" );
133     if ( !xPropertySet.is() )
134         throw uno::RuntimeException();
135 
136     try {
137         return xPropertySet->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( STORAGE_ENCRYPTION_KEYS_PROPERTY ) ) );
138     }
139     catch ( uno::Exception& aException )
140     {
141         ::package::StaticAddLog( aException.Message );
142         ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Can't get encryption property" ) ) );
143 
144         OSL_ENSURE( sal_False, "Can't get encryption related properties!\n" );
145         throw io::IOException(); // TODO
146     }
147 }
148 
149 //-----------------------------------------------
SequencesEqual(const uno::Sequence<sal_Int8> & aSequence1,const uno::Sequence<sal_Int8> & aSequence2)150 bool SequencesEqual( const uno::Sequence< sal_Int8 >& aSequence1, const uno::Sequence< sal_Int8 >& aSequence2 )
151 {
152     if ( aSequence1.getLength() != aSequence2.getLength() )
153         return false;
154 
155     for ( sal_Int32 nInd = 0; nInd < aSequence1.getLength(); nInd++ )
156         if ( aSequence1[nInd] != aSequence2[nInd] )
157             return false;
158 
159     return true;
160 }
161 
162 //-----------------------------------------------
SequencesEqual(const uno::Sequence<beans::NamedValue> & aSequence1,const uno::Sequence<beans::NamedValue> & aSequence2)163 bool SequencesEqual( const uno::Sequence< beans::NamedValue >& aSequence1, const uno::Sequence< beans::NamedValue >& aSequence2 )
164 {
165     if ( aSequence1.getLength() != aSequence2.getLength() )
166         return false;
167 
168     for ( sal_Int32 nInd = 0; nInd < aSequence1.getLength(); nInd++ )
169     {
170         bool bHasMember = false;
171         uno::Sequence< sal_Int8 > aMember1;
172         sal_Int32 nMember1 = 0;
173         if ( ( aSequence1[nInd].Value >>= aMember1 ) )
174         {
175             for ( sal_Int32 nInd2 = 0; nInd2 < aSequence2.getLength(); nInd2++ )
176             {
177                 if ( aSequence1[nInd].Name.equals( aSequence2[nInd2].Name ) )
178                 {
179                     bHasMember = true;
180 
181                     uno::Sequence< sal_Int8 > aMember2;
182                     if ( !( aSequence2[nInd2].Value >>= aMember2 ) || !SequencesEqual( aMember1, aMember2 ) )
183                         return false;
184                 }
185             }
186         }
187         else if ( ( aSequence1[nInd].Value >>= nMember1 ) )
188         {
189             for ( sal_Int32 nInd2 = 0; nInd2 < aSequence2.getLength(); nInd2++ )
190             {
191                 if ( aSequence1[nInd].Name.equals( aSequence2[nInd2].Name ) )
192                 {
193                     bHasMember = true;
194 
195                     sal_Int32 nMember2 = 0;
196                     if ( !( aSequence2[nInd2].Value >>= nMember2 ) || nMember1 != nMember2 )
197                         return false;
198                 }
199             }
200         }
201         else
202             return false;
203 
204         if ( !bHasMember )
205             return false;
206     }
207 
208     return true;
209 }
210 
211 //-----------------------------------------------
KillFile(const::rtl::OUString & aURL,const uno::Reference<lang::XMultiServiceFactory> & xFactory)212 sal_Bool KillFile( const ::rtl::OUString& aURL, const uno::Reference< lang::XMultiServiceFactory >& xFactory )
213 {
214     if ( !xFactory.is() )
215         return sal_False;
216 
217     sal_Bool bRet = sal_False;
218 
219     try
220     {
221         uno::Reference < ucb::XSimpleFileAccess > xAccess(
222                 xFactory->createInstance (
223                         ::rtl::OUString::createFromAscii( "com.sun.star.ucb.SimpleFileAccess" ) ),
224                 uno::UNO_QUERY );
225 
226         if ( xAccess.is() )
227         {
228             xAccess->kill( aURL );
229             bRet = sal_True;
230         }
231     }
232     catch( uno::Exception& aException )
233     {
234         ::package::StaticAddLog( aException.Message );
235         ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Quiet exception" ) ) );
236     }
237 
238     return bRet;
239 }
240 
241 const sal_Int32 n_ConstBufferSize = 32000;
242 
243 //-----------------------------------------------
GetNewTempFileURL(const uno::Reference<lang::XMultiServiceFactory> xFactory)244 ::rtl::OUString GetNewTempFileURL( const uno::Reference< lang::XMultiServiceFactory > xFactory )
245 {
246     ::rtl::OUString aTempURL;
247 
248     uno::Reference < beans::XPropertySet > xTempFile(
249             xFactory->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.io.TempFile" ) ),
250             uno::UNO_QUERY );
251 
252     if ( !xTempFile.is() )
253         throw uno::RuntimeException(); // TODO
254 
255     try {
256         xTempFile->setPropertyValue( ::rtl::OUString::createFromAscii( "RemoveFile" ), uno::makeAny( sal_False ) );
257         uno::Any aUrl = xTempFile->getPropertyValue( ::rtl::OUString::createFromAscii( "Uri" ) );
258         aUrl >>= aTempURL;
259     }
260     catch ( uno::Exception& aException )
261     {
262         ::package::StaticAddLog( aException.Message );
263         ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Quiet exception" ) ) );
264     }
265 
266     if ( !aTempURL.getLength() )
267         throw uno::RuntimeException(); // TODO: can not create tempfile
268 
269     return aTempURL;
270 }
271 
272 //-----------------------------------------------
CreateMemoryStream(const uno::Reference<lang::XMultiServiceFactory> & xFactory)273 uno::Reference< io::XStream > CreateMemoryStream( const uno::Reference< lang::XMultiServiceFactory >& xFactory )
274 {
275     if ( !xFactory.is() )
276         throw uno::RuntimeException();
277 
278     return uno::Reference< io::XStream >( xFactory->createInstance ( ::rtl::OUString::createFromAscii( "com.sun.star.comp.MemoryStream" ) ), uno::UNO_QUERY_THROW );
279 }
280 
281 } // anonymous namespace
282 // ================================================================
283 
284 //-----------------------------------------------
OWriteStream_Impl(OStorage_Impl * pParent,const uno::Reference<packages::XDataSinkEncrSupport> & xPackageStream,const uno::Reference<lang::XSingleServiceFactory> & xPackage,const uno::Reference<lang::XMultiServiceFactory> & xFactory,sal_Bool bForceEncrypted,sal_Int32 nStorageType,sal_Bool bDefaultCompress,const uno::Reference<io::XInputStream> & xRelInfoStream)285 OWriteStream_Impl::OWriteStream_Impl( OStorage_Impl* pParent,
286                                       const uno::Reference< packages::XDataSinkEncrSupport >& xPackageStream,
287                                       const uno::Reference< lang::XSingleServiceFactory >& xPackage,
288                                       const uno::Reference< lang::XMultiServiceFactory >& xFactory,
289                                       sal_Bool bForceEncrypted,
290                                       sal_Int32 nStorageType,
291                                       sal_Bool bDefaultCompress,
292                                       const uno::Reference< io::XInputStream >& xRelInfoStream )
293 : m_pAntiImpl( NULL )
294 , m_bHasDataToFlush( sal_False )
295 , m_bFlushed( sal_False )
296 , m_xPackageStream( xPackageStream )
297 , m_xFactory( xFactory )
298 , m_pParent( pParent )
299 , m_bForceEncrypted( bForceEncrypted )
300 , m_bUseCommonEncryption( !bForceEncrypted && nStorageType == embed::StorageFormats::PACKAGE )
301 , m_bHasCachedEncryptionData( sal_False )
302 , m_bCompressedSetExplicit( !bDefaultCompress )
303 , m_xPackage( xPackage )
304 , m_bHasInsertedStreamOptimization( sal_False )
305 , m_nStorageType( nStorageType )
306 , m_xOrigRelInfoStream( xRelInfoStream )
307 , m_bOrigRelInfoBroken( sal_False )
308 , m_nRelInfoStatus( RELINFO_NO_INIT )
309 , m_nRelId( 1 )
310 {
311     OSL_ENSURE( xPackageStream.is(), "No package stream is provided!\n" );
312     OSL_ENSURE( xPackage.is(), "No package component is provided!\n" );
313     OSL_ENSURE( m_xFactory.is(), "No package stream is provided!\n" );
314     OSL_ENSURE( pParent, "No parent storage is provided!\n" );
315     OSL_ENSURE( m_nStorageType == embed::StorageFormats::OFOPXML || !m_xOrigRelInfoStream.is(), "The Relations info makes sense only for OFOPXML format!\n" );
316 }
317 
318 //-----------------------------------------------
~OWriteStream_Impl()319 OWriteStream_Impl::~OWriteStream_Impl()
320 {
321     DisposeWrappers();
322 
323     if ( m_aTempURL.getLength() )
324     {
325         KillFile( m_aTempURL, GetServiceFactory() );
326         m_aTempURL = ::rtl::OUString();
327     }
328 
329     CleanCacheStream();
330 }
331 
332 //-----------------------------------------------
CleanCacheStream()333 void OWriteStream_Impl::CleanCacheStream()
334 {
335     if ( m_xCacheStream.is() )
336     {
337         try
338         {
339             uno::Reference< io::XInputStream > xInputCache = m_xCacheStream->getInputStream();
340             if ( xInputCache.is() )
341                 xInputCache->closeInput();
342         }
343         catch( uno::Exception& )
344         {}
345 
346         try
347         {
348             uno::Reference< io::XOutputStream > xOutputCache = m_xCacheStream->getOutputStream();
349             if ( xOutputCache.is() )
350                 xOutputCache->closeOutput();
351         }
352         catch( uno::Exception& )
353         {}
354 
355         m_xCacheStream = uno::Reference< io::XStream >();
356         m_xCacheSeek = uno::Reference< io::XSeekable >();
357     }
358 }
359 
360 //-----------------------------------------------
AddLog(const::rtl::OUString & aMessage)361 void OWriteStream_Impl::AddLog( const ::rtl::OUString& aMessage )
362 {
363     if ( !m_xLogRing.is() )
364     {
365         try
366         {
367             ::comphelper::ComponentContext aContext( ::comphelper::getProcessServiceFactory() );
368             if ( aContext.is() )
369                 m_xLogRing.set( aContext.getSingleton( "com.sun.star.logging.DocumentIOLogRing" ), uno::UNO_QUERY_THROW );
370         }
371         catch( uno::Exception& )
372         {
373             // No log
374         }
375     }
376 
377     if ( m_xLogRing.is() )
378         m_xLogRing->logString( aMessage );
379 }
380 
381 
382 //-----------------------------------------------
InsertIntoPackageFolder(const::rtl::OUString & aName,const uno::Reference<container::XNameContainer> & xParentPackageFolder)383 void OWriteStream_Impl::InsertIntoPackageFolder( const ::rtl::OUString& aName,
384                                                  const uno::Reference< container::XNameContainer >& xParentPackageFolder )
385 {
386     ::osl::MutexGuard aGuard( m_rMutexRef->GetMutex() );
387 
388     OSL_ENSURE( m_bFlushed, "This method must not be called for nonflushed streams!\n" );
389     if ( m_bFlushed )
390     {
391         OSL_ENSURE( m_xPackageStream.is(), "An inserted stream is incomplete!\n" );
392         uno::Reference< lang::XUnoTunnel > xTunnel( m_xPackageStream, uno::UNO_QUERY );
393         if ( !xTunnel.is() )
394             throw uno::RuntimeException(); // TODO
395 
396         xParentPackageFolder->insertByName( aName, uno::makeAny( xTunnel ) );
397 
398         m_bFlushed = sal_False;
399         m_bHasInsertedStreamOptimization = sal_False;
400     }
401 }
402 //-----------------------------------------------
IsEncrypted()403 sal_Bool OWriteStream_Impl::IsEncrypted()
404 {
405     if ( m_nStorageType != embed::StorageFormats::PACKAGE )
406         return sal_False;
407 
408     if ( m_bForceEncrypted || m_bHasCachedEncryptionData )
409         return sal_True;
410 
411     if ( m_aTempURL.getLength() || m_xCacheStream.is() )
412         return sal_False;
413 
414     GetStreamProperties();
415 
416     // the following value can not be cached since it can change after root commit
417     sal_Bool bWasEncr = sal_False;
418     uno::Reference< beans::XPropertySet > xPropSet( m_xPackageStream, uno::UNO_QUERY );
419     if ( xPropSet.is() )
420     {
421         uno::Any aValue = xPropSet->getPropertyValue( ::rtl::OUString::createFromAscii( "WasEncrypted" ) );
422         if ( !( aValue >>= bWasEncr ) )
423         {
424             OSL_ENSURE( sal_False, "The property WasEncrypted has wrong type!\n" );
425         }
426     }
427 
428     sal_Bool bToBeEncr = sal_False;
429     for ( sal_Int32 nInd = 0; nInd < m_aProps.getLength(); nInd++ )
430     {
431         if ( m_aProps[nInd].Name.equalsAscii( "Encrypted" ) )
432         {
433             if ( !( m_aProps[nInd].Value >>= bToBeEncr ) )
434             {
435                 OSL_ENSURE( sal_False, "The property has wrong type!\n" );
436             }
437         }
438     }
439 
440     // since a new key set to the package stream it should not be removed except the case when
441     // the stream becomes nonencrypted
442     uno::Sequence< beans::NamedValue > aKey;
443     if ( bToBeEncr )
444         GetEncryptionKeyProperty_Impl( xPropSet ) >>= aKey;
445 
446     // If the properties must be investigated the stream is either
447     // was never changed or was changed, the parent was committed
448     // and the stream was closed.
449     // That means that if it is intended to use common storage key
450     // it is already has no encryption but is marked to be stored
451     // encrypted and the key is empty.
452     if ( !bWasEncr && bToBeEncr && !aKey.getLength() )
453     {
454         // the stream is intended to use common storage password
455         m_bUseCommonEncryption = sal_True;
456         return sal_False;
457     }
458     else
459         return bToBeEncr;
460 }
461 
462 //-----------------------------------------------
SetDecrypted()463 void OWriteStream_Impl::SetDecrypted()
464 {
465     OSL_ENSURE( m_nStorageType == embed::StorageFormats::PACKAGE, "The encryption is supported only for package storages!\n" );
466     if ( m_nStorageType != embed::StorageFormats::PACKAGE )
467         throw uno::RuntimeException();
468 
469     GetStreamProperties();
470 
471     // let the stream be modified
472     FillTempGetFileName();
473     m_bHasDataToFlush = sal_True;
474 
475     // remove encryption
476     m_bForceEncrypted = sal_False;
477     m_bHasCachedEncryptionData = sal_False;
478     m_aEncryptionData.clear();
479 
480     for ( sal_Int32 nInd = 0; nInd < m_aProps.getLength(); nInd++ )
481     {
482         if ( m_aProps[nInd].Name.equalsAscii( "Encrypted" ) )
483             m_aProps[nInd].Value <<= sal_False;
484     }
485 }
486 
487 //-----------------------------------------------
SetEncrypted(const::comphelper::SequenceAsHashMap & aEncryptionData)488 void OWriteStream_Impl::SetEncrypted( const ::comphelper::SequenceAsHashMap& aEncryptionData )
489 {
490     OSL_ENSURE( m_nStorageType == embed::StorageFormats::PACKAGE, "The encryption is supported only for package storages!\n" );
491     if ( m_nStorageType != embed::StorageFormats::PACKAGE )
492         throw uno::RuntimeException();
493 
494     if ( !aEncryptionData.size() )
495         throw uno::RuntimeException();
496 
497     GetStreamProperties();
498 
499     // let the stream be modified
500     FillTempGetFileName();
501     m_bHasDataToFlush = sal_True;
502 
503     // introduce encryption info
504     for ( sal_Int32 nInd = 0; nInd < m_aProps.getLength(); nInd++ )
505     {
506         if ( m_aProps[nInd].Name.equalsAscii( "Encrypted" ) )
507             m_aProps[nInd].Value <<= sal_True;
508     }
509 
510     m_bUseCommonEncryption = sal_False; // very important to set it to false
511 
512     m_bHasCachedEncryptionData = sal_True;
513     m_aEncryptionData = aEncryptionData;
514 }
515 
516 //-----------------------------------------------
DisposeWrappers()517 void OWriteStream_Impl::DisposeWrappers()
518 {
519     ::osl::MutexGuard aGuard( m_rMutexRef->GetMutex() );
520     if ( m_pAntiImpl )
521     {
522         try {
523             m_pAntiImpl->dispose();
524         }
525         catch ( uno::RuntimeException& aRuntimeException )
526         {
527             AddLog( aRuntimeException.Message );
528             AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Quiet exception" ) ) );
529         }
530 
531         m_pAntiImpl = NULL;
532     }
533     m_pParent = NULL;
534 
535     if ( !m_aInputStreamsList.empty() )
536     {
537         for ( InputStreamsList_Impl::iterator pStreamIter = m_aInputStreamsList.begin();
538             pStreamIter != m_aInputStreamsList.end(); pStreamIter++ )
539         {
540             if ( (*pStreamIter) )
541             {
542                 (*pStreamIter)->InternalDispose();
543                 (*pStreamIter) = NULL;
544             }
545         }
546 
547         m_aInputStreamsList.clear();
548     }
549 }
550 
551 //-----------------------------------------------
GetServiceFactory()552 uno::Reference< lang::XMultiServiceFactory > OWriteStream_Impl::GetServiceFactory()
553 {
554     if ( m_xFactory.is() )
555         return m_xFactory;
556 
557     return ::comphelper::getProcessServiceFactory();
558 }
559 
560 //-----------------------------------------------
GetFilledTempFileIfNo(const uno::Reference<io::XInputStream> & xStream)561 ::rtl::OUString OWriteStream_Impl::GetFilledTempFileIfNo( const uno::Reference< io::XInputStream >& xStream )
562 {
563     if ( !m_aTempURL.getLength() )
564     {
565         ::rtl::OUString aTempURL = GetNewTempFileURL( GetServiceFactory() );
566 
567         try {
568             if ( !aTempURL.isEmpty() && xStream.is() )
569             {
570                 uno::Reference < ucb::XSimpleFileAccess > xTempAccess(
571                                 GetServiceFactory()->createInstance (
572                                         ::rtl::OUString::createFromAscii( "com.sun.star.ucb.SimpleFileAccess" ) ),
573                                 uno::UNO_QUERY );
574 
575                 if ( !xTempAccess.is() )
576                     throw uno::RuntimeException(); // TODO:
577 
578                 uno::Reference< io::XOutputStream > xTempOutStream = xTempAccess->openFileWrite( aTempURL );
579                 if ( xTempOutStream.is() )
580                 {
581                     // the current position of the original stream should be still OK, copy further
582                     ::comphelper::OStorageHelper::CopyInputToOutput( xStream, xTempOutStream );
583                     xTempOutStream->closeOutput();
584                     xTempOutStream = uno::Reference< io::XOutputStream >();
585                 }
586                 else
587                     throw io::IOException(); // TODO:
588             }
589         }
590         catch( packages::WrongPasswordException& aWrongPasswordException )
591         {
592             AddLog( aWrongPasswordException.Message );
593             AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Rethrow" ) ) );
594 
595             KillFile( aTempURL, GetServiceFactory() );
596             throw;
597         }
598         catch( uno::Exception& aException )
599         {
600             AddLog( aException.Message );
601             AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Rethrow" ) ) );
602 
603             KillFile( aTempURL, GetServiceFactory() );
604         throw;
605         }
606 
607         if ( aTempURL.getLength() )
608             CleanCacheStream();
609 
610         m_aTempURL = aTempURL;
611     }
612 
613     return m_aTempURL;
614 }
615 
616 //-----------------------------------------------
FillTempGetFileName()617 ::rtl::OUString OWriteStream_Impl::FillTempGetFileName()
618 {
619     // should try to create cache first, if the amount of contents is too big, the temp file should be taken
620     if ( !m_xCacheStream.is() && !m_aTempURL.getLength() )
621     {
622         uno::Reference< io::XInputStream > xOrigStream = m_xPackageStream->getDataStream();
623         if ( !xOrigStream.is() )
624         {
625             // in case of new inserted package stream it is possible that input stream still was not set
626             uno::Reference< io::XStream > xCacheStream = CreateMemoryStream( GetServiceFactory() );
627             OSL_ENSURE( xCacheStream.is(), "If the stream can not be created an exception must be thrown!\n" );
628             m_xCacheSeek.set( xCacheStream, uno::UNO_QUERY_THROW );
629             m_xCacheStream = xCacheStream;
630         }
631         else
632         {
633             sal_Int32 nRead = 0;
634             uno::Sequence< sal_Int8 > aData( MAX_STORCACHE_SIZE + 1 );
635             nRead = xOrigStream->readBytes( aData, MAX_STORCACHE_SIZE + 1 );
636             if ( aData.getLength() > nRead )
637                 aData.realloc( nRead );
638 
639             if ( nRead <= MAX_STORCACHE_SIZE )
640             {
641                 uno::Reference< io::XStream > xCacheStream = CreateMemoryStream( GetServiceFactory() );
642                 OSL_ENSURE( xCacheStream.is(), "If the stream can not be created an exception must be thrown!\n" );
643 
644                 if ( nRead )
645                 {
646                     uno::Reference< io::XOutputStream > xOutStream( xCacheStream->getOutputStream(), uno::UNO_SET_THROW );
647                     xOutStream->writeBytes( aData );
648                 }
649                 m_xCacheSeek.set( xCacheStream, uno::UNO_QUERY_THROW );
650                 m_xCacheStream = xCacheStream;
651                 m_xCacheSeek->seek( 0 );
652             }
653             else if ( !m_aTempURL.getLength() )
654             {
655                 m_aTempURL = GetNewTempFileURL( GetServiceFactory() );
656 
657                 try {
658                     if ( m_aTempURL.getLength() )
659                     {
660                         uno::Reference < ucb::XSimpleFileAccess > xTempAccess(
661                                         GetServiceFactory()->createInstance (
662                                                 ::rtl::OUString::createFromAscii( "com.sun.star.ucb.SimpleFileAccess" ) ),
663                                         uno::UNO_QUERY );
664 
665                         if ( !xTempAccess.is() )
666                             throw uno::RuntimeException(); // TODO:
667 
668 
669                         uno::Reference< io::XOutputStream > xTempOutStream = xTempAccess->openFileWrite( m_aTempURL );
670                         if ( xTempOutStream.is() )
671                         {
672                             // copy stream contents to the file
673                             xTempOutStream->writeBytes( aData );
674 
675                             // the current position of the original stream should be still OK, copy further
676                             ::comphelper::OStorageHelper::CopyInputToOutput( xOrigStream, xTempOutStream );
677                             xTempOutStream->closeOutput();
678                             xTempOutStream = uno::Reference< io::XOutputStream >();
679                         }
680                         else
681                             throw io::IOException(); // TODO:
682                     }
683                 }
684                 catch( packages::WrongPasswordException& )
685                 {
686                     KillFile( m_aTempURL, GetServiceFactory() );
687                     m_aTempURL = ::rtl::OUString();
688 
689                     throw;
690                 }
691                 catch( uno::Exception& )
692                 {
693                     KillFile( m_aTempURL, GetServiceFactory() );
694                     m_aTempURL = ::rtl::OUString();
695                 }
696             }
697         }
698     }
699 
700     return m_aTempURL;
701 }
702 
703 //-----------------------------------------------
GetTempFileAsStream()704 uno::Reference< io::XStream > OWriteStream_Impl::GetTempFileAsStream()
705 {
706     uno::Reference< io::XStream > xTempStream;
707 
708     if ( !m_xCacheStream.is() )
709     {
710         if ( !m_aTempURL.getLength() )
711             m_aTempURL = FillTempGetFileName();
712 
713         if ( m_aTempURL.getLength() )
714         {
715             // the temporary file is not used if the cache is used
716             uno::Reference < ucb::XSimpleFileAccess > xTempAccess(
717                             GetServiceFactory()->createInstance (
718                                     ::rtl::OUString::createFromAscii( "com.sun.star.ucb.SimpleFileAccess" ) ),
719                             uno::UNO_QUERY );
720 
721             if ( !xTempAccess.is() )
722                 throw uno::RuntimeException(); // TODO:
723 
724             try
725             {
726                 xTempStream = xTempAccess->openFileReadWrite( m_aTempURL );
727             }
728             catch( uno::Exception& aException )
729             {
730         AddLog( aException.Message );
731         AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Quiet exception" ) ) );
732             }
733         }
734     }
735 
736     if ( m_xCacheStream.is() )
737         xTempStream = m_xCacheStream;
738 
739     // the method must always return a stream
740     // in case the stream can not be open
741     // an exception should be thrown
742     if ( !xTempStream.is() )
743         throw io::IOException(); //TODO:
744 
745     return xTempStream;
746 }
747 
748 //-----------------------------------------------
GetTempFileAsInputStream()749 uno::Reference< io::XInputStream > OWriteStream_Impl::GetTempFileAsInputStream()
750 {
751     uno::Reference< io::XInputStream > xInputStream;
752 
753     if ( !m_xCacheStream.is() )
754     {
755         if ( !m_aTempURL.getLength() )
756             m_aTempURL = FillTempGetFileName();
757 
758         if ( m_aTempURL.getLength() )
759         {
760             // the temporary file is not used if the cache is used
761             uno::Reference < ucb::XSimpleFileAccess > xTempAccess(
762                             GetServiceFactory()->createInstance (
763                                     ::rtl::OUString::createFromAscii( "com.sun.star.ucb.SimpleFileAccess" ) ),
764                             uno::UNO_QUERY );
765 
766             if ( !xTempAccess.is() )
767                 throw uno::RuntimeException(); // TODO:
768 
769             try
770             {
771                 xInputStream = xTempAccess->openFileRead( m_aTempURL );
772             }
773             catch( uno::Exception& aException )
774             {
775                 AddLog( aException.Message );
776                 AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Quiet exception" ) ) );
777             }
778         }
779     }
780 
781     if ( m_xCacheStream.is() )
782         xInputStream = m_xCacheStream->getInputStream();
783 
784     // the method must always return a stream
785     // in case the stream can not be open
786     // an exception should be thrown
787     if ( !xInputStream.is() )
788         throw io::IOException(); // TODO:
789 
790     return xInputStream;
791 }
792 
793 // =================================================================================================
794 
795 //-----------------------------------------------
InsertStreamDirectly(const uno::Reference<io::XInputStream> & xInStream,const uno::Sequence<beans::PropertyValue> & aProps)796 void OWriteStream_Impl::InsertStreamDirectly( const uno::Reference< io::XInputStream >& xInStream,
797                                               const uno::Sequence< beans::PropertyValue >& aProps )
798 {
799     ::osl::MutexGuard aGuard( m_rMutexRef->GetMutex() ) ;
800 
801     // this call can be made only during parent storage commit
802     // the  parent storage is responsible for the correct handling
803     // of deleted and renamed contents
804 
805     OSL_ENSURE( m_xPackageStream.is(), "No package stream is set!\n" );
806 
807     if ( m_bHasDataToFlush )
808         throw io::IOException();
809 
810     OSL_ENSURE( !m_aTempURL.getLength() && !m_xCacheStream.is(), "The temporary must not exist!\n" );
811 
812     // use new file as current persistent representation
813     // the new file will be removed after it's stream is closed
814     m_xPackageStream->setDataStream( xInStream );
815 
816     // copy properties to the package stream
817     uno::Reference< beans::XPropertySet > xPropertySet( m_xPackageStream, uno::UNO_QUERY );
818     if ( !xPropertySet.is() )
819         throw uno::RuntimeException();
820 
821     // The storage-package communication has a problem
822     // the storage caches properties, thus if the package changes one of them itself
823     // the storage does not know about it
824 
825     // Depending from MediaType value the package can change the compressed property itself
826     // Thus if Compressed property is provided it must be set as the latest one
827     sal_Bool bCompressedIsSet = sal_False;
828     sal_Bool bCompressed = sal_False;
829     ::rtl::OUString aComprPropName( RTL_CONSTASCII_USTRINGPARAM( "Compressed" ) );
830     ::rtl::OUString aMedTypePropName( RTL_CONSTASCII_USTRINGPARAM( "MediaType" ) );
831     for ( sal_Int32 nInd = 0; nInd < aProps.getLength(); nInd++ )
832     {
833         if ( aProps[nInd].Name.equals( aComprPropName ) )
834         {
835             bCompressedIsSet = sal_True;
836             aProps[nInd].Value >>= bCompressed;
837         }
838         else if ( ( m_nStorageType == embed::StorageFormats::OFOPXML || m_nStorageType == embed::StorageFormats::PACKAGE )
839                && aProps[nInd].Name.equals( aMedTypePropName ) )
840         {
841             xPropertySet->setPropertyValue( aProps[nInd].Name, aProps[nInd].Value );
842         }
843         else if ( m_nStorageType == embed::StorageFormats::PACKAGE && aProps[nInd].Name.equalsAscii( "UseCommonStoragePasswordEncryption" ) )
844             aProps[nInd].Value >>= m_bUseCommonEncryption;
845         else
846             throw lang::IllegalArgumentException();
847 
848         // if there are cached properties update them
849         if ( aProps[nInd].Name.equals( aMedTypePropName ) || aProps[nInd].Name.equals( aComprPropName ) )
850             for ( sal_Int32 nMemInd = 0; nMemInd < m_aProps.getLength(); nMemInd++ )
851             {
852                 if ( aProps[nInd].Name.equals( m_aProps[nMemInd].Name ) )
853                     m_aProps[nMemInd].Value = aProps[nInd].Value;
854             }
855     }
856 
857     if ( bCompressedIsSet )
858     {
859         xPropertySet->setPropertyValue( aComprPropName, uno::makeAny( (sal_Bool)bCompressed ) );
860         m_bCompressedSetExplicit = sal_True;
861     }
862 
863     if ( m_bUseCommonEncryption )
864     {
865         if ( m_nStorageType != embed::StorageFormats::PACKAGE )
866             throw uno::RuntimeException();
867 
868         // set to be encrypted but do not use encryption key
869         xPropertySet->setPropertyValue( ::rtl::OUString::createFromAscii( STORAGE_ENCRYPTION_KEYS_PROPERTY ),
870                                         uno::makeAny( uno::Sequence< beans::NamedValue >() ) );
871         xPropertySet->setPropertyValue( ::rtl::OUString::createFromAscii( "Encrypted" ),
872                                         uno::makeAny( sal_True ) );
873     }
874 
875     // the stream should be free soon, after package is stored
876     m_bHasDataToFlush = sal_False;
877     m_bFlushed = sal_True; // will allow to use transaction on stream level if will need it
878     m_bHasInsertedStreamOptimization = sal_True;
879 }
880 
881 //-----------------------------------------------
Commit()882 void OWriteStream_Impl::Commit()
883 {
884     ::osl::MutexGuard aGuard( m_rMutexRef->GetMutex() ) ;
885 
886     OSL_ENSURE( m_xPackageStream.is(), "No package stream is set!\n" );
887 
888     if ( !m_bHasDataToFlush )
889         return;
890 
891     uno::Reference< packages::XDataSinkEncrSupport > xNewPackageStream;
892     uno::Sequence< uno::Any > aSeq( 1 );
893     aSeq[0] <<= sal_False;
894 
895     if ( m_xCacheStream.is() )
896     {
897         if ( m_pAntiImpl )
898             m_pAntiImpl->DeInit();
899 
900         uno::Reference< io::XInputStream > xInStream( m_xCacheStream->getInputStream(), uno::UNO_SET_THROW );
901 
902         xNewPackageStream = uno::Reference< packages::XDataSinkEncrSupport >(
903                                                         m_xPackage->createInstanceWithArguments( aSeq ),
904                                                         uno::UNO_QUERY_THROW );
905 
906         xNewPackageStream->setDataStream( xInStream );
907 
908         m_xCacheStream = uno::Reference< io::XStream >();
909         m_xCacheSeek = uno::Reference< io::XSeekable >();
910 
911     }
912     else if ( m_aTempURL.getLength() )
913     {
914         if ( m_pAntiImpl )
915             m_pAntiImpl->DeInit();
916 
917         uno::Reference< io::XInputStream > xInStream;
918         try
919         {
920             xInStream.set( static_cast< io::XInputStream* >( new OSelfTerminateFileStream( GetServiceFactory(), m_aTempURL ) ), uno::UNO_QUERY );
921         }
922         catch( uno::Exception& )
923         {
924         }
925 
926         if ( !xInStream.is() )
927             throw io::IOException();
928 
929         xNewPackageStream = uno::Reference< packages::XDataSinkEncrSupport >(
930                                                         m_xPackage->createInstanceWithArguments( aSeq ),
931                                                         uno::UNO_QUERY_THROW );
932 
933         // TODO/NEW: Let the temporary file be removed after commit
934         xNewPackageStream->setDataStream( xInStream );
935         m_aTempURL = ::rtl::OUString();
936     }
937     else // if ( m_bHasInsertedStreamOptimization )
938     {
939         // if the optimization is used the stream can be accessed directly
940         xNewPackageStream = m_xPackageStream;
941     }
942 
943     // copy properties to the package stream
944     uno::Reference< beans::XPropertySet > xPropertySet( xNewPackageStream, uno::UNO_QUERY );
945     if ( !xPropertySet.is() )
946         throw uno::RuntimeException();
947 
948     for ( sal_Int32 nInd = 0; nInd < m_aProps.getLength(); nInd++ )
949     {
950         if ( m_aProps[nInd].Name.equalsAscii( "Size" ) )
951         {
952             if ( m_pAntiImpl && !m_bHasInsertedStreamOptimization && m_pAntiImpl->m_xSeekable.is() )
953             {
954                 m_aProps[nInd].Value <<= ((sal_Int32)m_pAntiImpl->m_xSeekable->getLength());
955                 xPropertySet->setPropertyValue( m_aProps[nInd].Name, m_aProps[nInd].Value );
956             }
957         }
958         else
959             xPropertySet->setPropertyValue( m_aProps[nInd].Name, m_aProps[nInd].Value );
960     }
961 
962     if ( m_bUseCommonEncryption )
963     {
964         if ( m_nStorageType != embed::StorageFormats::PACKAGE )
965             throw uno::RuntimeException();
966 
967         // set to be encrypted but do not use encryption key
968         xPropertySet->setPropertyValue( ::rtl::OUString::createFromAscii( STORAGE_ENCRYPTION_KEYS_PROPERTY ),
969                                         uno::makeAny( uno::Sequence< beans::NamedValue >() ) );
970         xPropertySet->setPropertyValue( ::rtl::OUString::createFromAscii( "Encrypted" ),
971                                         uno::makeAny( sal_True ) );
972     }
973     else if ( m_bHasCachedEncryptionData )
974     {
975         if ( m_nStorageType != embed::StorageFormats::PACKAGE )
976             throw uno::RuntimeException();
977 
978         xPropertySet->setPropertyValue( ::rtl::OUString::createFromAscii( STORAGE_ENCRYPTION_KEYS_PROPERTY ),
979                                         uno::makeAny( m_aEncryptionData.getAsConstNamedValueList() ) );
980     }
981 
982     // the stream should be free soon, after package is stored
983     m_xPackageStream = xNewPackageStream;
984     m_bHasDataToFlush = sal_False;
985     m_bFlushed = sal_True; // will allow to use transaction on stream level if will need it
986 }
987 
988 //-----------------------------------------------
Revert()989 void OWriteStream_Impl::Revert()
990 {
991     // can be called only from parent storage
992     // means complete reload of the stream
993 
994     ::osl::MutexGuard aGuard( m_rMutexRef->GetMutex() ) ;
995 
996     if ( !m_bHasDataToFlush )
997         return; // nothing to do
998 
999     OSL_ENSURE( m_aTempURL.getLength() || m_xCacheStream.is(), "The temporary must exist!\n" );
1000 
1001     if ( m_xCacheStream.is() )
1002     {
1003         m_xCacheStream = uno::Reference< io::XStream >();
1004         m_xCacheSeek = uno::Reference< io::XSeekable >();
1005     }
1006 
1007     if ( m_aTempURL.getLength() )
1008     {
1009         KillFile( m_aTempURL, GetServiceFactory() );
1010         m_aTempURL = ::rtl::OUString();
1011     }
1012 
1013     m_aProps.realloc( 0 );
1014 
1015     m_bHasDataToFlush = sal_False;
1016 
1017     m_bUseCommonEncryption = sal_True;
1018     m_bHasCachedEncryptionData = sal_False;
1019     m_aEncryptionData.clear();
1020 
1021     if ( m_nStorageType == embed::StorageFormats::OFOPXML )
1022     {
1023         // currently the relations storage is changed only on commit
1024         m_xNewRelInfoStream = uno::Reference< io::XInputStream >();
1025         m_aNewRelInfo = uno::Sequence< uno::Sequence< beans::StringPair > >();
1026         if ( m_xOrigRelInfoStream.is() )
1027         {
1028             // the original stream is still here, that means that it was not parsed
1029             m_aOrigRelInfo = uno::Sequence< uno::Sequence< beans::StringPair > >();
1030             m_nRelInfoStatus = RELINFO_NO_INIT;
1031         }
1032         else
1033         {
1034             // the original stream was already parsed
1035             if ( !m_bOrigRelInfoBroken )
1036                 m_nRelInfoStatus = RELINFO_READ;
1037             else
1038                 m_nRelInfoStatus = RELINFO_BROKEN;
1039         }
1040     }
1041 }
1042 
1043 //-----------------------------------------------
GetStreamProperties()1044 uno::Sequence< beans::PropertyValue > OWriteStream_Impl::GetStreamProperties()
1045 {
1046     if ( !m_aProps.getLength() )
1047         m_aProps = ReadPackageStreamProperties();
1048 
1049     return m_aProps;
1050 }
1051 
1052 //-----------------------------------------------
InsertOwnProps(const uno::Sequence<beans::PropertyValue> & aProps,sal_Bool bUseCommonEncryption)1053 uno::Sequence< beans::PropertyValue > OWriteStream_Impl::InsertOwnProps(
1054                                                                     const uno::Sequence< beans::PropertyValue >& aProps,
1055                                                                     sal_Bool bUseCommonEncryption )
1056 {
1057     uno::Sequence< beans::PropertyValue > aResult( aProps );
1058     sal_Int32 nLen = aResult.getLength();
1059 
1060     if ( m_nStorageType == embed::StorageFormats::PACKAGE )
1061     {
1062         for ( sal_Int32 nInd = 0; nInd < nLen; nInd++ )
1063             if ( aResult[nInd].Name.equalsAscii( "UseCommonStoragePasswordEncryption" ) )
1064             {
1065                 aResult[nInd].Value <<= bUseCommonEncryption;
1066                 return aResult;
1067             }
1068 
1069         aResult.realloc( ++nLen );
1070         aResult[nLen - 1].Name = ::rtl::OUString::createFromAscii( "UseCommonStoragePasswordEncryption" );
1071         aResult[nLen - 1].Value <<= bUseCommonEncryption;
1072     }
1073     else if ( m_nStorageType == embed::StorageFormats::OFOPXML )
1074     {
1075         ReadRelInfoIfNecessary();
1076 
1077         uno::Any aValue;
1078         if ( m_nRelInfoStatus == RELINFO_READ )
1079             aValue <<= m_aOrigRelInfo;
1080         else if ( m_nRelInfoStatus == RELINFO_CHANGED_STREAM_READ || m_nRelInfoStatus == RELINFO_CHANGED )
1081             aValue <<= m_aNewRelInfo;
1082         else // m_nRelInfoStatus == RELINFO_CHANGED_BROKEN || m_nRelInfoStatus == RELINFO_BROKEN
1083             throw io::IOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Wrong relinfo stream!" ) ),
1084                                     uno::Reference< uno::XInterface >() );
1085 
1086         for ( sal_Int32 nInd = 0; nInd < nLen; nInd++ )
1087             if ( aResult[nInd].Name.equalsAscii( "RelationsInfo" ) )
1088             {
1089                 aResult[nInd].Value = aValue;
1090                 return aResult;
1091             }
1092 
1093         aResult.realloc( ++nLen );
1094         aResult[nLen - 1].Name = ::rtl::OUString::createFromAscii( "RelationsInfo" );
1095         aResult[nLen - 1].Value = aValue;
1096     }
1097 
1098     return aResult;
1099 }
1100 
1101 //-----------------------------------------------
IsTransacted()1102 sal_Bool OWriteStream_Impl::IsTransacted()
1103 {
1104     ::osl::MutexGuard aGuard( m_rMutexRef->GetMutex() ) ;
1105     return ( m_pAntiImpl && m_pAntiImpl->m_bTransacted );
1106 }
1107 
ReadRelInfoIfNecessary()1108 void OWriteStream_Impl::ReadRelInfoIfNecessary()
1109 {
1110     if ( m_nStorageType != embed::StorageFormats::OFOPXML )
1111         return;
1112 
1113     if ( m_nRelInfoStatus == RELINFO_NO_INIT )
1114     {
1115         try
1116         {
1117             // Init from original stream
1118             if ( m_xOrigRelInfoStream.is() )
1119                 m_aOrigRelInfo = ::comphelper::OFOPXMLHelper::ReadRelationsInfoSequence(
1120                                         m_xOrigRelInfoStream,
1121                                         ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "_rels/*.rels" ) ),
1122                                         m_xFactory );
1123 
1124             // in case of success the stream must be thrown away, that means that the OrigRelInfo is initialized
1125             // the reason for this is that the original stream might not be seekable ( at the same time the new
1126             // provided stream must be seekable ), so it must be read only once
1127             m_xOrigRelInfoStream = uno::Reference< io::XInputStream >();
1128             m_nRelInfoStatus = RELINFO_READ;
1129         }
1130         catch( uno::Exception& aException )
1131         {
1132             AddLog( aException.Message );
1133             AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Quiet exception" ) ) );
1134 
1135             m_nRelInfoStatus = RELINFO_BROKEN;
1136             m_bOrigRelInfoBroken = sal_True;
1137         }
1138     }
1139     else if ( m_nRelInfoStatus == RELINFO_CHANGED_STREAM )
1140     {
1141         // Init from the new stream
1142         try
1143         {
1144             if ( m_xNewRelInfoStream.is() )
1145                 m_aNewRelInfo = ::comphelper::OFOPXMLHelper::ReadRelationsInfoSequence(
1146                                         m_xNewRelInfoStream,
1147                                         ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "_rels/*.rels" ) ),
1148                                         m_xFactory );
1149 
1150             m_nRelInfoStatus = RELINFO_CHANGED_STREAM_READ;
1151         }
1152         catch( uno::Exception )
1153         {
1154             m_nRelInfoStatus = RELINFO_CHANGED_BROKEN;
1155         }
1156     }
1157 }
1158 
1159 //-----------------------------------------------
ReadPackageStreamProperties()1160 uno::Sequence< beans::PropertyValue > OWriteStream_Impl::ReadPackageStreamProperties()
1161 {
1162     sal_Int32 nPropNum = 0;
1163     if ( m_nStorageType == embed::StorageFormats::ZIP )
1164         nPropNum = 2;
1165     else if ( m_nStorageType == embed::StorageFormats::OFOPXML )
1166         nPropNum = 3;
1167     else if ( m_nStorageType == embed::StorageFormats::PACKAGE )
1168         nPropNum = 4;
1169     uno::Sequence< beans::PropertyValue > aResult( nPropNum );
1170 
1171     // The "Compressed" property must be set after "MediaType" property,
1172     // since the setting of the last one can change the value of the first one
1173 
1174     if ( m_nStorageType == embed::StorageFormats::OFOPXML || m_nStorageType == embed::StorageFormats::PACKAGE )
1175     {
1176         aResult[0].Name = ::rtl::OUString::createFromAscii("MediaType");
1177         aResult[1].Name = ::rtl::OUString::createFromAscii("Compressed");
1178         aResult[2].Name = ::rtl::OUString::createFromAscii("Size");
1179 
1180         if ( m_nStorageType == embed::StorageFormats::PACKAGE )
1181             aResult[3].Name = ::rtl::OUString::createFromAscii("Encrypted");
1182     }
1183     else
1184     {
1185         aResult[0].Name = ::rtl::OUString::createFromAscii("Compressed");
1186         aResult[1].Name = ::rtl::OUString::createFromAscii("Size");
1187 
1188     }
1189 
1190     // TODO: may be also raw stream should be marked
1191 
1192     uno::Reference< beans::XPropertySet > xPropSet( m_xPackageStream, uno::UNO_QUERY );
1193     if ( xPropSet.is() )
1194     {
1195         for ( sal_Int32 nInd = 0; nInd < aResult.getLength(); nInd++ )
1196         {
1197             try {
1198                 aResult[nInd].Value = xPropSet->getPropertyValue( aResult[nInd].Name );
1199             }
1200             catch( uno::Exception& aException )
1201             {
1202                 AddLog( aException.Message );
1203                 AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Quiet exception" ) ) );
1204 
1205                 OSL_ENSURE( sal_False, "A property can't be retrieved!\n" );
1206             }
1207         }
1208     }
1209     else
1210     {
1211         OSL_ENSURE( sal_False, "Can not get properties from a package stream!\n" );
1212         throw uno::RuntimeException();
1213     }
1214 
1215     return aResult;
1216 }
1217 
1218 //-----------------------------------------------
CopyInternallyTo_Impl(const uno::Reference<io::XStream> & xDestStream,const::comphelper::SequenceAsHashMap & aEncryptionData)1219 void OWriteStream_Impl::CopyInternallyTo_Impl( const uno::Reference< io::XStream >& xDestStream,
1220                                                 const ::comphelper::SequenceAsHashMap& aEncryptionData )
1221 {
1222     ::osl::MutexGuard aGuard( m_rMutexRef->GetMutex() ) ;
1223 
1224     OSL_ENSURE( !m_bUseCommonEncryption, "The stream can not be encrypted!" );
1225 
1226     if ( m_nStorageType != embed::StorageFormats::PACKAGE )
1227         throw packages::NoEncryptionException();
1228 
1229     if ( m_pAntiImpl )
1230     {
1231         m_pAntiImpl->CopyToStreamInternally_Impl( xDestStream );
1232     }
1233     else
1234     {
1235         uno::Reference< io::XStream > xOwnStream = GetStream( embed::ElementModes::READ, aEncryptionData, sal_False );
1236         if ( !xOwnStream.is() )
1237             throw io::IOException(); // TODO
1238 
1239         OStorage_Impl::completeStorageStreamCopy_Impl( xOwnStream, xDestStream, m_nStorageType, GetAllRelationshipsIfAny() );
1240     }
1241 
1242     uno::Reference< embed::XEncryptionProtectedSource2 > xEncr( xDestStream, uno::UNO_QUERY );
1243     if ( xEncr.is() )
1244         xEncr->setEncryptionData( aEncryptionData.getAsConstNamedValueList() );
1245 }
1246 
1247 //-----------------------------------------------
GetAllRelationshipsIfAny()1248 uno::Sequence< uno::Sequence< beans::StringPair > > OWriteStream_Impl::GetAllRelationshipsIfAny()
1249 {
1250     if ( m_nStorageType != embed::StorageFormats::OFOPXML )
1251         return uno::Sequence< uno::Sequence< beans::StringPair > >();
1252 
1253     ReadRelInfoIfNecessary();
1254 
1255     if ( m_nRelInfoStatus == RELINFO_READ )
1256         return m_aOrigRelInfo;
1257     else if ( m_nRelInfoStatus == RELINFO_CHANGED_STREAM_READ || m_nRelInfoStatus == RELINFO_CHANGED )
1258         return m_aNewRelInfo;
1259     else // m_nRelInfoStatus == RELINFO_CHANGED_BROKEN || m_nRelInfoStatus == RELINFO_BROKEN
1260             throw io::IOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Wrong relinfo stream!" ) ),
1261                                     uno::Reference< uno::XInterface >() );
1262 }
1263 
1264 //-----------------------------------------------
CopyInternallyTo_Impl(const uno::Reference<io::XStream> & xDestStream)1265 void OWriteStream_Impl::CopyInternallyTo_Impl( const uno::Reference< io::XStream >& xDestStream )
1266 {
1267     ::osl::MutexGuard aGuard( m_rMutexRef->GetMutex() ) ;
1268 
1269     if ( m_pAntiImpl )
1270     {
1271         m_pAntiImpl->CopyToStreamInternally_Impl( xDestStream );
1272     }
1273     else
1274     {
1275         uno::Reference< io::XStream > xOwnStream = GetStream( embed::ElementModes::READ, sal_False );
1276         if ( !xOwnStream.is() )
1277             throw io::IOException(); // TODO
1278 
1279         OStorage_Impl::completeStorageStreamCopy_Impl( xOwnStream, xDestStream, m_nStorageType, GetAllRelationshipsIfAny() );
1280     }
1281 }
1282 
1283 //-----------------------------------------------
GetStream(sal_Int32 nStreamMode,const::comphelper::SequenceAsHashMap & aEncryptionData,sal_Bool bHierarchyAccess)1284 uno::Reference< io::XStream > OWriteStream_Impl::GetStream( sal_Int32 nStreamMode, const ::comphelper::SequenceAsHashMap& aEncryptionData, sal_Bool bHierarchyAccess )
1285 {
1286     ::osl::MutexGuard aGuard( m_rMutexRef->GetMutex() ) ;
1287 
1288     OSL_ENSURE( m_xPackageStream.is(), "No package stream is set!\n" );
1289 
1290     if ( m_pAntiImpl )
1291         throw io::IOException(); // TODO:
1292 
1293     if ( !IsEncrypted() )
1294         throw packages::NoEncryptionException();
1295 
1296     uno::Reference< io::XStream > xResultStream;
1297 
1298     uno::Reference< beans::XPropertySet > xPropertySet( m_xPackageStream, uno::UNO_QUERY );
1299     if ( !xPropertySet.is() )
1300         throw uno::RuntimeException();
1301 
1302     if ( m_bHasCachedEncryptionData )
1303     {
1304         if ( !::package::PackageEncryptionDatasEqual( m_aEncryptionData, aEncryptionData ) )
1305             throw packages::WrongPasswordException();
1306 
1307         // the correct key must be set already
1308         xResultStream = GetStream_Impl( nStreamMode, bHierarchyAccess );
1309     }
1310     else
1311     {
1312         SetEncryptionKeyProperty_Impl( xPropertySet, aEncryptionData.getAsConstNamedValueList() );
1313 
1314         try {
1315             xResultStream = GetStream_Impl( nStreamMode, bHierarchyAccess );
1316 
1317             m_bUseCommonEncryption = sal_False; // very important to set it to false
1318             m_bHasCachedEncryptionData = sal_True;
1319             m_aEncryptionData = aEncryptionData;
1320         }
1321         catch( packages::WrongPasswordException& aWrongPasswordException )
1322         {
1323             SetEncryptionKeyProperty_Impl( xPropertySet, uno::Sequence< beans::NamedValue >() );
1324             AddLog( aWrongPasswordException.Message );
1325             AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Rethrow" ) ) );
1326             throw;
1327         }
1328         catch ( uno::Exception& aException )
1329         {
1330             AddLog( aException.Message );
1331             AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Quiet exception" ) ) );
1332 
1333             OSL_ENSURE( sal_False, "Can't write encryption related properties!\n" );
1334             SetEncryptionKeyProperty_Impl( xPropertySet, uno::Sequence< beans::NamedValue >() );
1335             throw io::IOException(); // TODO:
1336         }
1337     }
1338 
1339     OSL_ENSURE( xResultStream.is(), "In case stream can not be retrieved an exception must be thrown!\n" );
1340 
1341     return xResultStream;
1342 }
1343 
1344 //-----------------------------------------------
GetStream(sal_Int32 nStreamMode,sal_Bool bHierarchyAccess)1345 uno::Reference< io::XStream > OWriteStream_Impl::GetStream( sal_Int32 nStreamMode, sal_Bool bHierarchyAccess )
1346 {
1347     ::osl::MutexGuard aGuard( m_rMutexRef->GetMutex() ) ;
1348 
1349     OSL_ENSURE( m_xPackageStream.is(), "No package stream is set!\n" );
1350 
1351     if ( m_pAntiImpl )
1352         throw io::IOException(); // TODO:
1353 
1354     uno::Reference< io::XStream > xResultStream;
1355 
1356     if ( IsEncrypted() )
1357     {
1358         ::comphelper::SequenceAsHashMap aGlobalEncryptionData;
1359         try
1360         {
1361             aGlobalEncryptionData = GetCommonRootEncryptionData();
1362         }
1363         catch( packages::NoEncryptionException& aNoEncryptionException )
1364         {
1365             AddLog( aNoEncryptionException.Message );
1366             AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Rethrow" ) ) );
1367 
1368             throw packages::WrongPasswordException();
1369         }
1370 
1371         xResultStream = GetStream( nStreamMode, aGlobalEncryptionData, bHierarchyAccess );
1372     }
1373     else
1374         xResultStream = GetStream_Impl( nStreamMode, bHierarchyAccess );
1375 
1376     return xResultStream;
1377 }
1378 
1379 //-----------------------------------------------
GetStream_Impl(sal_Int32 nStreamMode,sal_Bool bHierarchyAccess)1380 uno::Reference< io::XStream > OWriteStream_Impl::GetStream_Impl( sal_Int32 nStreamMode, sal_Bool bHierarchyAccess )
1381 {
1382     // private method, no mutex is used
1383     GetStreamProperties();
1384 
1385     // TODO/LATER: this info might be read later, on demand in future
1386     ReadRelInfoIfNecessary();
1387 
1388     if ( ( nStreamMode & embed::ElementModes::READWRITE ) == embed::ElementModes::READ )
1389     {
1390         uno::Reference< io::XInputStream > xInStream;
1391         if ( m_xCacheStream.is() || m_aTempURL.getLength() )
1392             xInStream = GetTempFileAsInputStream(); //TODO:
1393         else
1394             xInStream = m_xPackageStream->getDataStream();
1395 
1396         // The stream does not exist in the storage
1397         if ( !xInStream.is() )
1398             throw io::IOException();
1399 
1400         OInputCompStream* pStream = new OInputCompStream( *this, xInStream, InsertOwnProps( m_aProps, m_bUseCommonEncryption ), m_nStorageType );
1401         uno::Reference< io::XStream > xCompStream(
1402                         static_cast< ::cppu::OWeakObject* >( pStream ),
1403                         uno::UNO_QUERY );
1404         OSL_ENSURE( xCompStream.is(),
1405                     "OInputCompStream MUST provide XStream interfaces!\n" );
1406 
1407         m_aInputStreamsList.push_back( pStream );
1408         return xCompStream;
1409     }
1410     else if ( ( nStreamMode & embed::ElementModes::READWRITE ) == embed::ElementModes::SEEKABLEREAD )
1411     {
1412         if ( !m_xCacheStream.is() && !m_aTempURL.getLength() && !( m_xPackageStream->getDataStream().is() ) )
1413         {
1414             // The stream does not exist in the storage
1415             throw io::IOException();
1416         }
1417 
1418         uno::Reference< io::XInputStream > xInStream;
1419 
1420         xInStream = GetTempFileAsInputStream(); //TODO:
1421 
1422         if ( !xInStream.is() )
1423             throw io::IOException();
1424 
1425         OInputSeekStream* pStream = new OInputSeekStream( *this, xInStream, InsertOwnProps( m_aProps, m_bUseCommonEncryption ), m_nStorageType );
1426         uno::Reference< io::XStream > xSeekStream(
1427                         static_cast< ::cppu::OWeakObject* >( pStream ),
1428                         uno::UNO_QUERY );
1429         OSL_ENSURE( xSeekStream.is(),
1430                     "OInputSeekStream MUST provide XStream interfaces!\n" );
1431 
1432         m_aInputStreamsList.push_back( pStream );
1433         return xSeekStream;
1434     }
1435     else if ( ( nStreamMode & embed::ElementModes::WRITE ) == embed::ElementModes::WRITE )
1436     {
1437         if ( !m_aInputStreamsList.empty() )
1438             throw io::IOException(); // TODO:
1439 
1440         uno::Reference< io::XStream > xStream;
1441         if ( ( nStreamMode & embed::ElementModes::TRUNCATE ) == embed::ElementModes::TRUNCATE )
1442         {
1443             if ( m_aTempURL.getLength() )
1444             {
1445                 KillFile( m_aTempURL, GetServiceFactory() );
1446                 m_aTempURL = ::rtl::OUString();
1447             }
1448             if ( m_xCacheStream.is() )
1449                 CleanCacheStream();
1450 
1451             m_bHasDataToFlush = sal_True;
1452 
1453             // this call is triggered by the parent and it will recognize the change of the state
1454             if ( m_pParent )
1455                 m_pParent->m_bIsModified = sal_True;
1456 
1457             xStream = CreateMemoryStream( GetServiceFactory() );
1458             m_xCacheSeek.set( xStream, uno::UNO_QUERY_THROW );
1459             m_xCacheStream = xStream;
1460         }
1461         else if ( !m_bHasInsertedStreamOptimization )
1462         {
1463             if ( !m_aTempURL.getLength() && !m_xCacheStream.is() && !( m_xPackageStream->getDataStream().is() ) )
1464             {
1465                 // The stream does not exist in the storage
1466                 m_bHasDataToFlush = sal_True;
1467 
1468                 // this call is triggered by the parent and it will recognize the change of the state
1469                 if ( m_pParent )
1470                     m_pParent->m_bIsModified = sal_True;
1471                 xStream = GetTempFileAsStream();
1472             }
1473 
1474             // if the stream exists the temporary file is created on demand
1475             // xStream = GetTempFileAsStream();
1476         }
1477 
1478         if ( !xStream.is() )
1479             m_pAntiImpl = new OWriteStream( this, bHierarchyAccess );
1480         else
1481             m_pAntiImpl = new OWriteStream( this, xStream, bHierarchyAccess );
1482 
1483         uno::Reference< io::XStream > xWriteStream =
1484                                 uno::Reference< io::XStream >( static_cast< ::cppu::OWeakObject* >( m_pAntiImpl ),
1485                                                                 uno::UNO_QUERY );
1486 
1487         OSL_ENSURE( xWriteStream.is(), "OWriteStream MUST implement XStream && XComponent interfaces!\n" );
1488 
1489         return xWriteStream;
1490     }
1491 
1492     throw lang::IllegalArgumentException(); // TODO
1493 }
1494 
1495 //-----------------------------------------------
GetPlainRawInStream()1496 uno::Reference< io::XInputStream > OWriteStream_Impl::GetPlainRawInStream()
1497 {
1498     ::osl::MutexGuard aGuard( m_rMutexRef->GetMutex() ) ;
1499 
1500     OSL_ENSURE( m_xPackageStream.is(), "No package stream is set!\n" );
1501 
1502     // this method is used only internally, this stream object should not go outside of this implementation
1503     // if ( m_pAntiImpl )
1504     //  throw io::IOException(); // TODO:
1505 
1506     return m_xPackageStream->getPlainRawStream();
1507 }
1508 
1509 //-----------------------------------------------
GetRawInStream()1510 uno::Reference< io::XInputStream > OWriteStream_Impl::GetRawInStream()
1511 {
1512     ::osl::MutexGuard aGuard( m_rMutexRef->GetMutex() ) ;
1513 
1514     OSL_ENSURE( m_xPackageStream.is(), "No package stream is set!\n" );
1515 
1516     if ( m_pAntiImpl )
1517         throw io::IOException(); // TODO:
1518 
1519     OSL_ENSURE( IsEncrypted(), "Impossible to get raw representation for nonencrypted stream!\n" );
1520     if ( !IsEncrypted() )
1521         throw packages::NoEncryptionException();
1522 
1523     return m_xPackageStream->getRawStream();
1524 }
1525 
1526 //-----------------------------------------------
GetCommonRootEncryptionData()1527 ::comphelper::SequenceAsHashMap OWriteStream_Impl::GetCommonRootEncryptionData()
1528 {
1529     ::osl::MutexGuard aGuard( m_rMutexRef->GetMutex() ) ;
1530 
1531     if ( m_nStorageType != embed::StorageFormats::PACKAGE || !m_pParent )
1532         throw packages::NoEncryptionException();
1533 
1534     return m_pParent->GetCommonRootEncryptionData();
1535 }
1536 
1537 //-----------------------------------------------
InputStreamDisposed(OInputCompStream * pStream)1538 void OWriteStream_Impl::InputStreamDisposed( OInputCompStream* pStream )
1539 {
1540     ::osl::MutexGuard aGuard( m_rMutexRef->GetMutex() );
1541     m_aInputStreamsList.remove( pStream );
1542 }
1543 
1544 //-----------------------------------------------
CreateReadonlyCopyBasedOnData(const uno::Reference<io::XInputStream> & xDataToCopy,const uno::Sequence<beans::PropertyValue> & aProps,sal_Bool,uno::Reference<io::XStream> & xTargetStream)1545 void OWriteStream_Impl::CreateReadonlyCopyBasedOnData( const uno::Reference< io::XInputStream >& xDataToCopy, const uno::Sequence< beans::PropertyValue >& aProps, sal_Bool, uno::Reference< io::XStream >& xTargetStream )
1546 {
1547     uno::Reference < io::XStream > xTempFile;
1548     if ( !xTargetStream.is() )
1549         xTempFile = uno::Reference < io::XStream >(
1550             m_xFactory->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.io.TempFile" ) ),
1551             uno::UNO_QUERY );
1552     else
1553         xTempFile = xTargetStream;
1554 
1555     uno::Reference < io::XSeekable > xTempSeek( xTempFile, uno::UNO_QUERY );
1556     if ( !xTempSeek.is() )
1557         throw uno::RuntimeException(); // TODO
1558 
1559     uno::Reference < io::XOutputStream > xTempOut = xTempFile->getOutputStream();
1560     if ( !xTempOut.is() )
1561         throw uno::RuntimeException();
1562 
1563     if ( xDataToCopy.is() )
1564         ::comphelper::OStorageHelper::CopyInputToOutput( xDataToCopy, xTempOut );
1565 
1566     xTempOut->closeOutput();
1567     xTempSeek->seek( 0 );
1568 
1569     uno::Reference< io::XInputStream > xInStream = xTempFile->getInputStream();
1570     if ( !xInStream.is() )
1571         throw io::IOException();
1572 
1573     // TODO: remember last state of m_bUseCommonEncryption
1574     if ( !xTargetStream.is() )
1575         xTargetStream = uno::Reference< io::XStream > (
1576             static_cast< ::cppu::OWeakObject* >(
1577                 new OInputSeekStream( xInStream, InsertOwnProps( aProps, m_bUseCommonEncryption ), m_nStorageType ) ),
1578             uno::UNO_QUERY_THROW );
1579 }
1580 
1581 //-----------------------------------------------
GetCopyOfLastCommit(uno::Reference<io::XStream> & xTargetStream)1582 void OWriteStream_Impl::GetCopyOfLastCommit( uno::Reference< io::XStream >& xTargetStream )
1583 {
1584     ::osl::MutexGuard aGuard( m_rMutexRef->GetMutex() );
1585 
1586     OSL_ENSURE( m_xPackageStream.is(), "The source stream for copying is incomplete!\n" );
1587     if ( !m_xPackageStream.is() )
1588         throw uno::RuntimeException();
1589 
1590     uno::Reference< io::XInputStream > xDataToCopy;
1591     if ( IsEncrypted() )
1592     {
1593         // an encrypted stream must contain input stream
1594         ::comphelper::SequenceAsHashMap aGlobalEncryptionData;
1595         try
1596         {
1597             aGlobalEncryptionData = GetCommonRootEncryptionData();
1598         }
1599         catch( packages::NoEncryptionException& aNoEncryptionException )
1600         {
1601             AddLog( aNoEncryptionException.Message );
1602             AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "No Element" ) ) );
1603 
1604             throw packages::WrongPasswordException();
1605         }
1606 
1607         GetCopyOfLastCommit( xTargetStream, aGlobalEncryptionData );
1608     }
1609     else
1610     {
1611         xDataToCopy = m_xPackageStream->getDataStream();
1612 
1613         // in case of new inserted package stream it is possible that input stream still was not set
1614         GetStreamProperties();
1615 
1616         CreateReadonlyCopyBasedOnData( xDataToCopy, m_aProps, m_bUseCommonEncryption, xTargetStream );
1617     }
1618 }
1619 
1620 //-----------------------------------------------
GetCopyOfLastCommit(uno::Reference<io::XStream> & xTargetStream,const::comphelper::SequenceAsHashMap & aEncryptionData)1621 void OWriteStream_Impl::GetCopyOfLastCommit( uno::Reference< io::XStream >& xTargetStream, const ::comphelper::SequenceAsHashMap& aEncryptionData )
1622 {
1623     ::osl::MutexGuard aGuard( m_rMutexRef->GetMutex() );
1624 
1625     OSL_ENSURE( m_xPackageStream.is(), "The source stream for copying is incomplete!\n" );
1626     if ( !m_xPackageStream.is() )
1627         throw uno::RuntimeException();
1628 
1629     if ( !IsEncrypted() )
1630         throw packages::NoEncryptionException();
1631 
1632     uno::Reference< io::XInputStream > xDataToCopy;
1633 
1634     if ( m_bHasCachedEncryptionData )
1635     {
1636         // TODO: introduce last committed cashed password information and use it here
1637         // that means "use common pass" also should be remembered on flash
1638         uno::Sequence< beans::NamedValue > aKey = aEncryptionData.getAsConstNamedValueList();
1639 
1640         uno::Reference< beans::XPropertySet > xProps( m_xPackageStream, uno::UNO_QUERY );
1641         if ( !xProps.is() )
1642             throw uno::RuntimeException();
1643 
1644         sal_Bool bEncr = sal_False;
1645         xProps->getPropertyValue( ::rtl::OUString::createFromAscii( "Encrypted" ) ) >>= bEncr;
1646         if ( !bEncr )
1647             throw packages::NoEncryptionException();
1648 
1649         uno::Sequence< beans::NamedValue > aPackKey;
1650         xProps->getPropertyValue( ::rtl::OUString::createFromAscii( STORAGE_ENCRYPTION_KEYS_PROPERTY ) ) >>= aPackKey;
1651         if ( !SequencesEqual( aKey, aPackKey ) )
1652             throw packages::WrongPasswordException();
1653 
1654         // the correct key must be set already
1655         xDataToCopy = m_xPackageStream->getDataStream();
1656     }
1657     else
1658     {
1659         uno::Reference< beans::XPropertySet > xPropertySet( m_xPackageStream, uno::UNO_QUERY );
1660         SetEncryptionKeyProperty_Impl( xPropertySet, aEncryptionData.getAsConstNamedValueList() );
1661 
1662         try {
1663             xDataToCopy = m_xPackageStream->getDataStream();
1664 
1665             if ( !xDataToCopy.is() )
1666             {
1667                 OSL_ENSURE( sal_False, "Encrypted ZipStream must already have input stream inside!\n" );
1668                 SetEncryptionKeyProperty_Impl( xPropertySet, uno::Sequence< beans::NamedValue >() );
1669             }
1670         }
1671         catch( uno::Exception& aException )
1672         {
1673             OSL_ENSURE( sal_False, "Can't open encrypted stream!\n" );
1674             SetEncryptionKeyProperty_Impl( xPropertySet, uno::Sequence< beans::NamedValue >() );
1675             AddLog( aException.Message );
1676             AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Rethrow" ) ) );
1677             throw;
1678         }
1679 
1680         SetEncryptionKeyProperty_Impl( xPropertySet, uno::Sequence< beans::NamedValue >() );
1681     }
1682 
1683     // in case of new inserted package stream it is possible that input stream still was not set
1684     GetStreamProperties();
1685 
1686     CreateReadonlyCopyBasedOnData( xDataToCopy, m_aProps, m_bUseCommonEncryption, xTargetStream );
1687 }
1688 
1689 //-----------------------------------------------
CommitStreamRelInfo(const uno::Reference<embed::XStorage> & xRelStorage,const::rtl::OUString & aOrigStreamName,const::rtl::OUString & aNewStreamName)1690 void OWriteStream_Impl::CommitStreamRelInfo( const uno::Reference< embed::XStorage >& xRelStorage, const ::rtl::OUString& aOrigStreamName, const ::rtl::OUString& aNewStreamName )
1691 {
1692     // at this point of time the old stream must be already cleaned
1693     OSL_ENSURE( m_nStorageType == embed::StorageFormats::OFOPXML, "The method should be used only with OFOPXML format!\n" );
1694 
1695     if ( m_nStorageType == embed::StorageFormats::OFOPXML )
1696     {
1697         OSL_ENSURE( aOrigStreamName.getLength() && aNewStreamName.getLength() && xRelStorage.is(),
1698                     "Wrong relation persistence information is provided!\n" );
1699 
1700         if ( !xRelStorage.is() || !aOrigStreamName.getLength() || !aNewStreamName.getLength() )
1701             throw uno::RuntimeException();
1702 
1703         if ( m_nRelInfoStatus == RELINFO_BROKEN || m_nRelInfoStatus == RELINFO_CHANGED_BROKEN )
1704             throw io::IOException(); // TODO:
1705 
1706         ::rtl::OUString aOrigRelStreamName = aOrigStreamName;
1707         aOrigRelStreamName += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".rels" ) );
1708 
1709         ::rtl::OUString aNewRelStreamName = aNewStreamName;
1710         aNewRelStreamName += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".rels" ) );
1711 
1712         sal_Bool bRenamed = !aOrigRelStreamName.equals( aNewRelStreamName );
1713         if ( m_nRelInfoStatus == RELINFO_CHANGED
1714           || m_nRelInfoStatus == RELINFO_CHANGED_STREAM_READ
1715           || m_nRelInfoStatus == RELINFO_CHANGED_STREAM )
1716         {
1717             if ( bRenamed && xRelStorage->hasByName( aOrigRelStreamName ) )
1718                 xRelStorage->removeElement( aOrigRelStreamName );
1719 
1720             if ( m_nRelInfoStatus == RELINFO_CHANGED )
1721             {
1722                 if ( m_aNewRelInfo.getLength() )
1723                 {
1724                     uno::Reference< io::XStream > xRelsStream =
1725                         xRelStorage->openStreamElement( aNewRelStreamName,
1726                                                           embed::ElementModes::TRUNCATE | embed::ElementModes::READWRITE );
1727 
1728                     uno::Reference< io::XOutputStream > xOutStream = xRelsStream->getOutputStream();
1729                     if ( !xOutStream.is() )
1730                         throw uno::RuntimeException();
1731 
1732                     ::comphelper::OFOPXMLHelper::WriteRelationsInfoSequence( xOutStream, m_aNewRelInfo, m_xFactory );
1733 
1734                     // set the mediatype
1735                     uno::Reference< beans::XPropertySet > xPropSet( xRelsStream, uno::UNO_QUERY_THROW );
1736                     xPropSet->setPropertyValue(
1737                         ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "MediaType" ) ),
1738                         uno::makeAny( ::rtl::OUString(
1739                             RTL_CONSTASCII_USTRINGPARAM( "application/vnd.openxmlformats-package.relationships+xml" ) ) ) );
1740 
1741                     m_nRelInfoStatus = RELINFO_READ;
1742                 }
1743             }
1744             else if ( m_nRelInfoStatus == RELINFO_CHANGED_STREAM_READ
1745                     || m_nRelInfoStatus == RELINFO_CHANGED_STREAM )
1746             {
1747                 uno::Reference< io::XStream > xRelsStream =
1748                     xRelStorage->openStreamElement( aNewRelStreamName,
1749                                                         embed::ElementModes::TRUNCATE | embed::ElementModes::READWRITE );
1750 
1751                 uno::Reference< io::XOutputStream > xOutputStream = xRelsStream->getOutputStream();
1752                 if ( !xOutputStream.is() )
1753                     throw uno::RuntimeException();
1754 
1755                 uno::Reference< io::XSeekable > xSeek( m_xNewRelInfoStream, uno::UNO_QUERY_THROW );
1756                 xSeek->seek( 0 );
1757                 ::comphelper::OStorageHelper::CopyInputToOutput( m_xNewRelInfoStream, xOutputStream );
1758                 xSeek->seek( 0 );
1759 
1760                 // set the mediatype
1761                 uno::Reference< beans::XPropertySet > xPropSet( xRelsStream, uno::UNO_QUERY_THROW );
1762                 xPropSet->setPropertyValue(
1763                     ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "MediaType" ) ),
1764                     uno::makeAny( ::rtl::OUString(
1765                         RTL_CONSTASCII_USTRINGPARAM( "application/vnd.openxmlformats-package.relationships+xml" ) ) ) );
1766 
1767                 if ( m_nRelInfoStatus == RELINFO_CHANGED_STREAM )
1768                     m_nRelInfoStatus = RELINFO_NO_INIT;
1769                 else
1770                 {
1771                     // the information is already parsed and the stream is stored, no need in temporary stream any more
1772                     m_xNewRelInfoStream = uno::Reference< io::XInputStream >();
1773                     m_nRelInfoStatus = RELINFO_READ;
1774                 }
1775             }
1776 
1777             // the original stream makes no sense after this step
1778             m_xOrigRelInfoStream = m_xNewRelInfoStream;
1779             m_aOrigRelInfo = m_aNewRelInfo;
1780             m_bOrigRelInfoBroken = sal_False;
1781             m_aNewRelInfo = uno::Sequence< uno::Sequence< beans::StringPair > >();
1782             m_xNewRelInfoStream = uno::Reference< io::XInputStream >();
1783         }
1784         else
1785         {
1786             // the stream is not changed but it might be renamed
1787             if ( bRenamed && xRelStorage->hasByName( aOrigRelStreamName ) )
1788                 xRelStorage->renameElement( aOrigRelStreamName, aNewRelStreamName );
1789         }
1790     }
1791 }
1792 
1793 //===============================================
1794 // OWriteStream implementation
1795 //===============================================
1796 
1797 //-----------------------------------------------
OWriteStream(OWriteStream_Impl * pImpl,sal_Bool bTransacted)1798 OWriteStream::OWriteStream( OWriteStream_Impl* pImpl, sal_Bool bTransacted )
1799 : m_pImpl( pImpl )
1800 , m_bInStreamDisconnected( sal_False )
1801 , m_bInitOnDemand( sal_True )
1802 , m_nInitPosition( 0 )
1803 , m_bTransacted( bTransacted )
1804 {
1805     OSL_ENSURE( pImpl, "No base implementation!\n" );
1806     OSL_ENSURE( m_pImpl->m_rMutexRef.Is(), "No mutex!\n" );
1807 
1808     if ( !m_pImpl || !m_pImpl->m_rMutexRef.Is() )
1809         throw uno::RuntimeException(); // just a disaster
1810 
1811     m_pData = new WSInternalData_Impl( pImpl->m_rMutexRef, m_pImpl->m_nStorageType );
1812 }
1813 
1814 //-----------------------------------------------
OWriteStream(OWriteStream_Impl * pImpl,uno::Reference<io::XStream> xStream,sal_Bool bTransacted)1815 OWriteStream::OWriteStream( OWriteStream_Impl* pImpl, uno::Reference< io::XStream > xStream, sal_Bool bTransacted )
1816 : m_pImpl( pImpl )
1817 , m_bInStreamDisconnected( sal_False )
1818 , m_bInitOnDemand( sal_False )
1819 , m_nInitPosition( 0 )
1820 , m_bTransacted( bTransacted )
1821 {
1822     OSL_ENSURE( pImpl && xStream.is(), "No base implementation!\n" );
1823     OSL_ENSURE( m_pImpl->m_rMutexRef.Is(), "No mutex!\n" );
1824 
1825     if ( !m_pImpl || !m_pImpl->m_rMutexRef.Is() )
1826         throw uno::RuntimeException(); // just a disaster
1827 
1828     m_pData = new WSInternalData_Impl( pImpl->m_rMutexRef, m_pImpl->m_nStorageType );
1829 
1830     if ( xStream.is() )
1831     {
1832         m_xInStream = xStream->getInputStream();
1833         m_xOutStream = xStream->getOutputStream();
1834         m_xSeekable = uno::Reference< io::XSeekable >( xStream, uno::UNO_QUERY );
1835         OSL_ENSURE( m_xInStream.is() && m_xOutStream.is() && m_xSeekable.is(), "Stream implementation is incomplete!\n" );
1836     }
1837 }
1838 
1839 //-----------------------------------------------
~OWriteStream()1840 OWriteStream::~OWriteStream()
1841 {
1842     {
1843         ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
1844         if ( m_pImpl )
1845         {
1846             m_refCount++;
1847             try {
1848                 dispose();
1849             }
1850             catch( uno::RuntimeException& aRuntimeException )
1851             {
1852                 m_pImpl->AddLog( aRuntimeException.Message );
1853                 m_pImpl->AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Quiet exception" ) ) );
1854             }
1855         }
1856     }
1857 
1858     if ( m_pData && m_pData->m_pTypeCollection )
1859         delete m_pData->m_pTypeCollection;
1860 
1861     if ( m_pData )
1862         delete m_pData;
1863 }
1864 
1865 //-----------------------------------------------
DeInit()1866 void OWriteStream::DeInit()
1867 {
1868     if ( !m_pImpl )
1869         return; // do nothing
1870 
1871     if ( m_xSeekable.is() )
1872         m_nInitPosition = m_xSeekable->getPosition();
1873 
1874     m_xInStream = uno::Reference< io::XInputStream >();
1875     m_xOutStream = uno::Reference< io::XOutputStream >();
1876     m_xSeekable = uno::Reference< io::XSeekable >();
1877     m_bInitOnDemand = sal_True;
1878 }
1879 
1880 //-----------------------------------------------
CheckInitOnDemand()1881 void OWriteStream::CheckInitOnDemand()
1882 {
1883     if ( !m_pImpl )
1884     {
1885         ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) );
1886         throw lang::DisposedException();
1887     }
1888 
1889     if ( m_bInitOnDemand )
1890     {
1891         RTL_LOGFILE_CONTEXT( aLog, "package (mv76033) OWriteStream::CheckInitOnDemand, initializing" );
1892         uno::Reference< io::XStream > xStream = m_pImpl->GetTempFileAsStream();
1893         if ( xStream.is() )
1894         {
1895             m_xInStream.set( xStream->getInputStream(), uno::UNO_SET_THROW );
1896             m_xOutStream.set( xStream->getOutputStream(), uno::UNO_SET_THROW );
1897             m_xSeekable.set( xStream, uno::UNO_QUERY_THROW );
1898             m_xSeekable->seek( m_nInitPosition );
1899 
1900             m_nInitPosition = 0;
1901             m_bInitOnDemand = sal_False;
1902         }
1903     }
1904 }
1905 
1906 //-----------------------------------------------
CopyToStreamInternally_Impl(const uno::Reference<io::XStream> & xDest)1907 void OWriteStream::CopyToStreamInternally_Impl( const uno::Reference< io::XStream >& xDest )
1908 {
1909     ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
1910 
1911     CheckInitOnDemand();
1912 
1913     if ( !m_xInStream.is() )
1914         throw uno::RuntimeException();
1915 
1916     if ( !m_xSeekable.is() )
1917         throw uno::RuntimeException();
1918 
1919     uno::Reference< beans::XPropertySet > xDestProps( xDest, uno::UNO_QUERY );
1920     if ( !xDestProps.is() )
1921         throw uno::RuntimeException(); //TODO
1922 
1923     uno::Reference< io::XOutputStream > xDestOutStream = xDest->getOutputStream();
1924     if ( !xDestOutStream.is() )
1925         throw io::IOException(); // TODO
1926 
1927     sal_Int64 nCurPos = m_xSeekable->getPosition();
1928     m_xSeekable->seek( 0 );
1929 
1930     uno::Exception eThrown;
1931     sal_Bool bThrown = sal_False;
1932     try {
1933         ::comphelper::OStorageHelper::CopyInputToOutput( m_xInStream, xDestOutStream );
1934     }
1935     catch ( uno::Exception& e )
1936     {
1937         eThrown = e;
1938         bThrown = sal_True;
1939     }
1940 
1941     // position-related section below is critical
1942     // if it fails the stream will become invalid
1943     try {
1944         m_xSeekable->seek( nCurPos );
1945     }
1946     catch ( uno::Exception& aException )
1947     {
1948         m_pImpl->AddLog( aException.Message );
1949         m_pImpl->AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Quiet exception" ) ) );
1950 
1951         // TODO: set the stoream in invalid state or dispose
1952         OSL_ENSURE( sal_False, "The stream became invalid during copying!\n" );
1953         throw uno::RuntimeException();
1954     }
1955 
1956     if ( bThrown )
1957         throw eThrown;
1958 
1959     // now the properties can be copied
1960     // the order of the properties setting is not important for StorageStream API
1961     ::rtl::OUString aPropName = ::rtl::OUString::createFromAscii( "Compressed" );
1962     xDestProps->setPropertyValue( aPropName, getPropertyValue( aPropName ) );
1963     if ( m_pData->m_nStorageType == embed::StorageFormats::PACKAGE || m_pData->m_nStorageType == embed::StorageFormats::OFOPXML )
1964     {
1965         aPropName = ::rtl::OUString::createFromAscii( "MediaType" );
1966         xDestProps->setPropertyValue( aPropName, getPropertyValue( aPropName ) );
1967 
1968         if ( m_pData->m_nStorageType == embed::StorageFormats::PACKAGE )
1969         {
1970             aPropName = ::rtl::OUString::createFromAscii( "UseCommonStoragePasswordEncryption" );
1971             xDestProps->setPropertyValue( aPropName, getPropertyValue( aPropName ) );
1972         }
1973     }
1974 }
1975 
1976 //-----------------------------------------------
ModifyParentUnlockMutex_Impl(::osl::ResettableMutexGuard & aGuard)1977 void OWriteStream::ModifyParentUnlockMutex_Impl( ::osl::ResettableMutexGuard& aGuard )
1978 {
1979     if ( m_pImpl->m_pParent )
1980     {
1981         if ( m_pImpl->m_pParent->m_pAntiImpl )
1982         {
1983             uno::Reference< util::XModifiable > xParentModif( (util::XModifiable*)(m_pImpl->m_pParent->m_pAntiImpl) );
1984             aGuard.clear();
1985             xParentModif->setModified( sal_True );
1986         }
1987         else
1988             m_pImpl->m_pParent->m_bIsModified = sal_True;
1989     }
1990 }
1991 
1992 //-----------------------------------------------
queryInterface(const uno::Type & rType)1993 uno::Any SAL_CALL OWriteStream::queryInterface( const uno::Type& rType )
1994 {
1995     uno::Any aReturn;
1996 
1997     // common interfaces
1998     aReturn <<= ::cppu::queryInterface
1999                 (   rType
2000                     ,   static_cast<lang::XTypeProvider*> ( this )
2001                     ,   static_cast<io::XInputStream*> ( this )
2002                     ,   static_cast<io::XOutputStream*> ( this )
2003                     ,   static_cast<io::XStream*> ( this )
2004                     ,   static_cast<embed::XExtendedStorageStream*> ( this )
2005                     ,   static_cast<io::XSeekable*> ( this )
2006                     ,   static_cast<io::XTruncate*> ( this )
2007                     ,   static_cast<lang::XComponent*> ( this )
2008                     ,   static_cast<beans::XPropertySet*> ( this ) );
2009 
2010     if ( aReturn.hasValue() == sal_True )
2011         return aReturn ;
2012 
2013     if ( m_pData->m_nStorageType == embed::StorageFormats::PACKAGE )
2014     {
2015         aReturn <<= ::cppu::queryInterface
2016                     (   rType
2017                         ,   static_cast<embed::XEncryptionProtectedSource2*> ( this )
2018                         ,   static_cast<embed::XEncryptionProtectedSource*> ( this ) );
2019     }
2020     else if ( m_pData->m_nStorageType == embed::StorageFormats::OFOPXML )
2021     {
2022         aReturn <<= ::cppu::queryInterface
2023                     (   rType
2024                         ,   static_cast<embed::XRelationshipAccess*> ( this ) );
2025     }
2026 
2027     if ( aReturn.hasValue() == sal_True )
2028         return aReturn ;
2029 
2030     if ( m_bTransacted )
2031     {
2032         aReturn <<= ::cppu::queryInterface
2033                     (   rType
2034                         ,   static_cast<embed::XTransactedObject*> ( this )
2035                         ,   static_cast<embed::XTransactionBroadcaster*> ( this ) );
2036 
2037         if ( aReturn.hasValue() == sal_True )
2038             return aReturn ;
2039     }
2040 
2041     return OWeakObject::queryInterface( rType );
2042 }
2043 
2044 //-----------------------------------------------
acquire()2045 void SAL_CALL OWriteStream::acquire() throw()
2046 {
2047     OWeakObject::acquire();
2048 }
2049 
2050 //-----------------------------------------------
release()2051 void SAL_CALL OWriteStream::release() throw()
2052 {
2053     OWeakObject::release();
2054 }
2055 
2056 //-----------------------------------------------
getTypes()2057 uno::Sequence< uno::Type > SAL_CALL OWriteStream::getTypes()
2058 {
2059     if ( m_pData->m_pTypeCollection == NULL )
2060     {
2061         ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
2062 
2063         if ( m_pData->m_pTypeCollection == NULL )
2064         {
2065             if ( m_bTransacted )
2066             {
2067                 if ( m_pData->m_nStorageType == embed::StorageFormats::PACKAGE )
2068                 {
2069                     ::cppu::OTypeCollection aTmpCollection
2070                                     (   ::getCppuType( ( const uno::Reference< lang::XTypeProvider >* )NULL )
2071                                     ,   ::getCppuType( ( const uno::Reference< io::XInputStream >* )NULL )
2072                                     ,   ::getCppuType( ( const uno::Reference< io::XOutputStream >* )NULL )
2073                                     ,   ::getCppuType( ( const uno::Reference< io::XStream >* )NULL )
2074                                     ,   ::getCppuType( ( const uno::Reference< io::XSeekable >* )NULL )
2075                                     ,   ::getCppuType( ( const uno::Reference< io::XTruncate >* )NULL )
2076                                     ,   ::getCppuType( ( const uno::Reference< lang::XComponent >* )NULL )
2077                                     ,   ::getCppuType( ( const uno::Reference< embed::XEncryptionProtectedSource2 >* )NULL )
2078                                     ,   ::getCppuType( ( const uno::Reference< embed::XEncryptionProtectedSource >* )NULL )
2079                                     ,   ::getCppuType( ( const uno::Reference< embed::XExtendedStorageStream >* )NULL )
2080                                     ,   ::getCppuType( ( const uno::Reference< embed::XTransactedObject >* )NULL )
2081                                     ,   ::getCppuType( ( const uno::Reference< embed::XTransactionBroadcaster >* )NULL ) );
2082 
2083                     m_pData->m_pTypeCollection = new ::cppu::OTypeCollection
2084                                     (   ::getCppuType( ( const uno::Reference< beans::XPropertySet >* )NULL )
2085                                     ,   aTmpCollection.getTypes() );
2086                 }
2087                 else if ( m_pData->m_nStorageType == embed::StorageFormats::OFOPXML )
2088                 {
2089                     m_pData->m_pTypeCollection = new ::cppu::OTypeCollection
2090                                     (   ::getCppuType( ( const uno::Reference< lang::XTypeProvider >* )NULL )
2091                                     ,   ::getCppuType( ( const uno::Reference< io::XInputStream >* )NULL )
2092                                     ,   ::getCppuType( ( const uno::Reference< io::XOutputStream >* )NULL )
2093                                     ,   ::getCppuType( ( const uno::Reference< io::XStream >* )NULL )
2094                                     ,   ::getCppuType( ( const uno::Reference< io::XSeekable >* )NULL )
2095                                     ,   ::getCppuType( ( const uno::Reference< io::XTruncate >* )NULL )
2096                                     ,   ::getCppuType( ( const uno::Reference< lang::XComponent >* )NULL )
2097                                     ,   ::getCppuType( ( const uno::Reference< embed::XRelationshipAccess >* )NULL )
2098                                     ,   ::getCppuType( ( const uno::Reference< embed::XExtendedStorageStream >* )NULL )
2099                                     ,   ::getCppuType( ( const uno::Reference< embed::XTransactedObject >* )NULL )
2100                                     ,   ::getCppuType( ( const uno::Reference< embed::XTransactionBroadcaster >* )NULL )
2101                                     ,   ::getCppuType( ( const uno::Reference< beans::XPropertySet >* )NULL ) );
2102                 }
2103                 else // if ( m_pData->m_nStorageType == embed::StorageFormats::ZIP )
2104                 {
2105                     m_pData->m_pTypeCollection = new ::cppu::OTypeCollection
2106                                     (   ::getCppuType( ( const uno::Reference< lang::XTypeProvider >* )NULL )
2107                                     ,   ::getCppuType( ( const uno::Reference< io::XInputStream >* )NULL )
2108                                     ,   ::getCppuType( ( const uno::Reference< io::XOutputStream >* )NULL )
2109                                     ,   ::getCppuType( ( const uno::Reference< io::XStream >* )NULL )
2110                                     ,   ::getCppuType( ( const uno::Reference< io::XSeekable >* )NULL )
2111                                     ,   ::getCppuType( ( const uno::Reference< io::XTruncate >* )NULL )
2112                                     ,   ::getCppuType( ( const uno::Reference< lang::XComponent >* )NULL )
2113                                     ,   ::getCppuType( ( const uno::Reference< embed::XExtendedStorageStream >* )NULL )
2114                                     ,   ::getCppuType( ( const uno::Reference< embed::XTransactedObject >* )NULL )
2115                                     ,   ::getCppuType( ( const uno::Reference< embed::XTransactionBroadcaster >* )NULL )
2116                                     ,   ::getCppuType( ( const uno::Reference< beans::XPropertySet >* )NULL ) );
2117                 }
2118             }
2119             else
2120             {
2121                 if ( m_pData->m_nStorageType == embed::StorageFormats::PACKAGE )
2122                 {
2123                     m_pData->m_pTypeCollection = new ::cppu::OTypeCollection
2124                                     (   ::getCppuType( ( const uno::Reference< lang::XTypeProvider >* )NULL )
2125                                     ,   ::getCppuType( ( const uno::Reference< io::XInputStream >* )NULL )
2126                                     ,   ::getCppuType( ( const uno::Reference< io::XOutputStream >* )NULL )
2127                                     ,   ::getCppuType( ( const uno::Reference< io::XStream >* )NULL )
2128                                     ,   ::getCppuType( ( const uno::Reference< io::XSeekable >* )NULL )
2129                                     ,   ::getCppuType( ( const uno::Reference< io::XTruncate >* )NULL )
2130                                     ,   ::getCppuType( ( const uno::Reference< lang::XComponent >* )NULL )
2131                                     ,   ::getCppuType( ( const uno::Reference< embed::XEncryptionProtectedSource2 >* )NULL )
2132                                     ,   ::getCppuType( ( const uno::Reference< embed::XEncryptionProtectedSource >* )NULL )
2133                                     ,   ::getCppuType( ( const uno::Reference< beans::XPropertySet >* )NULL ) );
2134                 }
2135                 else if ( m_pData->m_nStorageType == embed::StorageFormats::OFOPXML )
2136                 {
2137                     m_pData->m_pTypeCollection = new ::cppu::OTypeCollection
2138                                     (   ::getCppuType( ( const uno::Reference< lang::XTypeProvider >* )NULL )
2139                                     ,   ::getCppuType( ( const uno::Reference< io::XInputStream >* )NULL )
2140                                     ,   ::getCppuType( ( const uno::Reference< io::XOutputStream >* )NULL )
2141                                     ,   ::getCppuType( ( const uno::Reference< io::XStream >* )NULL )
2142                                     ,   ::getCppuType( ( const uno::Reference< io::XSeekable >* )NULL )
2143                                     ,   ::getCppuType( ( const uno::Reference< io::XTruncate >* )NULL )
2144                                     ,   ::getCppuType( ( const uno::Reference< lang::XComponent >* )NULL )
2145                                     ,   ::getCppuType( ( const uno::Reference< embed::XRelationshipAccess >* )NULL )
2146                                     ,   ::getCppuType( ( const uno::Reference< beans::XPropertySet >* )NULL ) );
2147                 }
2148                 else // if ( m_pData->m_nStorageType == embed::StorageFormats::ZIP )
2149                 {
2150                     m_pData->m_pTypeCollection = new ::cppu::OTypeCollection
2151                                     (   ::getCppuType( ( const uno::Reference< lang::XTypeProvider >* )NULL )
2152                                     ,   ::getCppuType( ( const uno::Reference< io::XInputStream >* )NULL )
2153                                     ,   ::getCppuType( ( const uno::Reference< io::XOutputStream >* )NULL )
2154                                     ,   ::getCppuType( ( const uno::Reference< io::XStream >* )NULL )
2155                                     ,   ::getCppuType( ( const uno::Reference< io::XSeekable >* )NULL )
2156                                     ,   ::getCppuType( ( const uno::Reference< io::XTruncate >* )NULL )
2157                                     ,   ::getCppuType( ( const uno::Reference< lang::XComponent >* )NULL )
2158                                     ,   ::getCppuType( ( const uno::Reference< beans::XPropertySet >* )NULL ) );
2159                 }
2160             }
2161         }
2162     }
2163 
2164     return m_pData->m_pTypeCollection->getTypes() ;
2165 }
2166 
2167 namespace { struct lcl_ImplId : public rtl::Static< ::cppu::OImplementationId, lcl_ImplId > {}; }
2168 
2169 //-----------------------------------------------
getImplementationId()2170 uno::Sequence< sal_Int8 > SAL_CALL OWriteStream::getImplementationId()
2171 {
2172     ::cppu::OImplementationId &rId = lcl_ImplId::get();
2173     return rId.getImplementationId();
2174 }
2175 
2176 //-----------------------------------------------
readBytes(uno::Sequence<sal_Int8> & aData,sal_Int32 nBytesToRead)2177 sal_Int32 SAL_CALL OWriteStream::readBytes( uno::Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead )
2178 {
2179     ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
2180 
2181     CheckInitOnDemand();
2182 
2183     if ( !m_pImpl )
2184     {
2185         ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) );
2186         throw lang::DisposedException();
2187     }
2188 
2189     if ( !m_xInStream.is() )
2190         throw io::NotConnectedException();
2191 
2192     return m_xInStream->readBytes( aData, nBytesToRead );
2193 }
2194 
2195 //-----------------------------------------------
readSomeBytes(uno::Sequence<sal_Int8> & aData,sal_Int32 nMaxBytesToRead)2196 sal_Int32 SAL_CALL OWriteStream::readSomeBytes( uno::Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead )
2197 {
2198     ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
2199 
2200     CheckInitOnDemand();
2201 
2202     if ( !m_pImpl )
2203     {
2204         ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) );
2205         throw lang::DisposedException();
2206     }
2207 
2208     if ( !m_xInStream.is() )
2209         throw io::NotConnectedException();
2210 
2211     return m_xInStream->readSomeBytes( aData, nMaxBytesToRead );
2212 }
2213 
2214 //-----------------------------------------------
skipBytes(sal_Int32 nBytesToSkip)2215 void SAL_CALL OWriteStream::skipBytes( sal_Int32 nBytesToSkip )
2216 {
2217     ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
2218 
2219     CheckInitOnDemand();
2220 
2221     if ( !m_pImpl )
2222     {
2223         ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) );
2224         throw lang::DisposedException();
2225     }
2226 
2227     if ( !m_xInStream.is() )
2228         throw io::NotConnectedException();
2229 
2230     m_xInStream->skipBytes( nBytesToSkip );
2231 }
2232 
2233 //-----------------------------------------------
available()2234 sal_Int32 SAL_CALL OWriteStream::available(  )
2235 {
2236     ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
2237 
2238     CheckInitOnDemand();
2239 
2240     if ( !m_pImpl )
2241     {
2242         ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) );
2243         throw lang::DisposedException();
2244     }
2245 
2246     if ( !m_xInStream.is() )
2247         throw io::NotConnectedException();
2248 
2249     return m_xInStream->available();
2250 
2251 }
2252 
2253 //-----------------------------------------------
closeInput()2254 void SAL_CALL OWriteStream::closeInput(  )
2255 {
2256     ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
2257 
2258     if ( !m_pImpl )
2259     {
2260         ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) );
2261         throw lang::DisposedException();
2262     }
2263 
2264     if ( !m_bInitOnDemand && ( m_bInStreamDisconnected || !m_xInStream.is() ) )
2265         throw io::NotConnectedException();
2266 
2267     // the input part of the stream stays open for internal purposes ( to allow reading during copying )
2268     // since it can not be reopened until output part is closed, it will be closed with output part.
2269     m_bInStreamDisconnected = sal_True;
2270     // m_xInStream->closeInput();
2271     // m_xInStream = uno::Reference< io::XInputStream >();
2272 
2273     if ( !m_xOutStream.is() )
2274         dispose();
2275 }
2276 
2277 //-----------------------------------------------
getInputStream()2278 uno::Reference< io::XInputStream > SAL_CALL OWriteStream::getInputStream()
2279 {
2280     ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
2281 
2282     if ( !m_pImpl )
2283     {
2284         ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) );
2285         throw lang::DisposedException();
2286     }
2287 
2288     if ( !m_bInitOnDemand && ( m_bInStreamDisconnected || !m_xInStream.is() ) )
2289         return uno::Reference< io::XInputStream >();
2290 
2291     return uno::Reference< io::XInputStream >( static_cast< io::XInputStream* >( this ), uno::UNO_QUERY );
2292 }
2293 
2294 //-----------------------------------------------
getOutputStream()2295 uno::Reference< io::XOutputStream > SAL_CALL OWriteStream::getOutputStream()
2296 {
2297     ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
2298 
2299     CheckInitOnDemand();
2300 
2301     if ( !m_pImpl )
2302     {
2303         ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) );
2304         throw lang::DisposedException();
2305     }
2306 
2307     if ( !m_xOutStream.is() )
2308         return uno::Reference< io::XOutputStream >();
2309 
2310     return uno::Reference< io::XOutputStream >( static_cast< io::XOutputStream* >( this ), uno::UNO_QUERY );
2311 }
2312 
2313 //-----------------------------------------------
writeBytes(const uno::Sequence<sal_Int8> & aData)2314 void SAL_CALL OWriteStream::writeBytes( const uno::Sequence< sal_Int8 >& aData )
2315 {
2316     ::osl::ResettableMutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
2317 
2318     // the write method makes initialization itself, since it depends from the aData length
2319     // NO CheckInitOnDemand()!
2320 
2321     if ( !m_pImpl )
2322     {
2323         ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) );
2324         throw lang::DisposedException();
2325     }
2326 
2327     if ( !m_bInitOnDemand )
2328     {
2329         if ( !m_xOutStream.is() || !m_xSeekable.is())
2330             throw io::NotConnectedException();
2331 
2332         if ( m_pImpl->m_xCacheStream.is() )
2333         {
2334             // check whether the cache should be turned off
2335             sal_Int64 nPos = m_xSeekable->getPosition();
2336             if ( nPos + aData.getLength() > MAX_STORCACHE_SIZE )
2337             {
2338                 // disconnect the cache and copy the data to the temporary file
2339                 m_xSeekable->seek( 0 );
2340 
2341                 // it is enough to copy the cached stream, the cache should already contain everything
2342                 if ( m_pImpl->GetFilledTempFileIfNo( m_xInStream ).getLength() )
2343                 {
2344                     DeInit();
2345                     // the last position is known and it is differs from the current stream position
2346                     m_nInitPosition = nPos;
2347                 }
2348             }
2349         }
2350     }
2351 
2352     if ( m_bInitOnDemand )
2353     {
2354         RTL_LOGFILE_CONTEXT( aLog, "package (mv76033) OWriteStream::CheckInitOnDemand, initializing" );
2355         uno::Reference< io::XStream > xStream = m_pImpl->GetTempFileAsStream();
2356         if ( xStream.is() )
2357         {
2358             m_xInStream.set( xStream->getInputStream(), uno::UNO_SET_THROW );
2359             m_xOutStream.set( xStream->getOutputStream(), uno::UNO_SET_THROW );
2360             m_xSeekable.set( xStream, uno::UNO_QUERY_THROW );
2361             m_xSeekable->seek( m_nInitPosition );
2362 
2363             m_nInitPosition = 0;
2364             m_bInitOnDemand = sal_False;
2365         }
2366     }
2367 
2368 
2369     if ( !m_xOutStream.is() )
2370         throw io::NotConnectedException();
2371 
2372     m_xOutStream->writeBytes( aData );
2373     m_pImpl->m_bHasDataToFlush = sal_True;
2374 
2375     ModifyParentUnlockMutex_Impl( aGuard );
2376 }
2377 
2378 //-----------------------------------------------
flush()2379 void SAL_CALL OWriteStream::flush()
2380 {
2381     // In case stream is flushed it's current version becomes visible
2382     // to the parent storage. Usually parent storage flushes the stream
2383     // during own commit but a user can explicitly flush the stream
2384     // so the changes will be available through cloning functionality.
2385 
2386     ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
2387 
2388     if ( !m_pImpl )
2389     {
2390         ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) );
2391         throw lang::DisposedException();
2392     }
2393 
2394     if ( !m_bInitOnDemand )
2395     {
2396         if ( !m_xOutStream.is() )
2397             throw io::NotConnectedException();
2398 
2399         m_xOutStream->flush();
2400         m_pImpl->Commit();
2401     }
2402 }
2403 
2404 //-----------------------------------------------
CloseOutput_Impl()2405 void OWriteStream::CloseOutput_Impl()
2406 {
2407     // all the checks must be done in calling method
2408 
2409     m_xOutStream->closeOutput();
2410     m_xOutStream = uno::Reference< io::XOutputStream >();
2411 
2412     if ( !m_bInitOnDemand )
2413     {
2414         // after the stream is disposed it can be committed
2415         // so transport correct size property
2416         if ( !m_xSeekable.is() )
2417             throw uno::RuntimeException();
2418 
2419         for ( sal_Int32 nInd = 0; nInd < m_pImpl->m_aProps.getLength(); nInd++ )
2420         {
2421             if ( m_pImpl->m_aProps[nInd].Name.equalsAscii( "Size" ) )
2422                 m_pImpl->m_aProps[nInd].Value <<= ((sal_Int32)m_xSeekable->getLength());
2423         }
2424     }
2425 }
2426 
2427 //-----------------------------------------------
closeOutput()2428 void SAL_CALL OWriteStream::closeOutput()
2429 {
2430     ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
2431 
2432     CheckInitOnDemand();
2433 
2434     if ( !m_pImpl )
2435     {
2436         ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) );
2437         throw lang::DisposedException();
2438     }
2439 
2440     if ( !m_xOutStream.is() )
2441         throw io::NotConnectedException();
2442 
2443     CloseOutput_Impl();
2444 
2445     if ( m_bInStreamDisconnected || !m_xInStream.is() )
2446         dispose();
2447 }
2448 
2449 //-----------------------------------------------
seek(sal_Int64 location)2450 void SAL_CALL OWriteStream::seek( sal_Int64 location )
2451 {
2452     ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
2453 
2454     CheckInitOnDemand();
2455 
2456     if ( !m_pImpl )
2457     {
2458         ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) );
2459         throw lang::DisposedException();
2460     }
2461 
2462     if ( !m_xSeekable.is() )
2463         throw uno::RuntimeException();
2464 
2465     m_xSeekable->seek( location );
2466 }
2467 
2468 //-----------------------------------------------
getPosition()2469 sal_Int64 SAL_CALL OWriteStream::getPosition()
2470 {
2471     ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
2472 
2473     CheckInitOnDemand();
2474 
2475     if ( !m_pImpl )
2476     {
2477         ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) );
2478         throw lang::DisposedException();
2479     }
2480 
2481     if ( !m_xSeekable.is() )
2482         throw uno::RuntimeException();
2483 
2484     return m_xSeekable->getPosition();
2485 }
2486 
2487 //-----------------------------------------------
getLength()2488 sal_Int64 SAL_CALL OWriteStream::getLength()
2489 {
2490     ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
2491 
2492     CheckInitOnDemand();
2493 
2494     if ( !m_pImpl )
2495     {
2496         ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) );
2497         throw lang::DisposedException();
2498     }
2499 
2500     if ( !m_xSeekable.is() )
2501         throw uno::RuntimeException();
2502 
2503     return m_xSeekable->getLength();
2504 }
2505 
2506 //-----------------------------------------------
truncate()2507 void SAL_CALL OWriteStream::truncate()
2508 {
2509     ::osl::ResettableMutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
2510 
2511     CheckInitOnDemand();
2512 
2513     if ( !m_pImpl )
2514     {
2515         ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) );
2516         throw lang::DisposedException();
2517     }
2518 
2519     if ( !m_xOutStream.is() )
2520         throw uno::RuntimeException();
2521 
2522     uno::Reference< io::XTruncate > xTruncate( m_xOutStream, uno::UNO_QUERY );
2523 
2524     if ( !xTruncate.is() )
2525     {
2526         OSL_ENSURE( sal_False, "The output stream must support XTruncate interface!\n" );
2527         throw uno::RuntimeException();
2528     }
2529 
2530     xTruncate->truncate();
2531 
2532     m_pImpl->m_bHasDataToFlush = sal_True;
2533 
2534     ModifyParentUnlockMutex_Impl( aGuard );
2535 }
2536 
2537 //-----------------------------------------------
dispose()2538 void SAL_CALL OWriteStream::dispose()
2539 {
2540     // should be an internal method since it can be called only from parent storage
2541     {
2542         ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
2543 
2544         if ( !m_pImpl )
2545         {
2546             ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) );
2547             throw lang::DisposedException();
2548         }
2549 
2550         if ( m_xOutStream.is() )
2551             CloseOutput_Impl();
2552 
2553         if ( m_xInStream.is() )
2554         {
2555             m_xInStream->closeInput();
2556             m_xInStream = uno::Reference< io::XInputStream >();
2557         }
2558 
2559         m_xSeekable = uno::Reference< io::XSeekable >();
2560 
2561         m_pImpl->m_pAntiImpl = NULL;
2562 
2563         if ( !m_bInitOnDemand )
2564         {
2565             try
2566             {
2567                 if ( !m_bTransacted )
2568                 {
2569                     m_pImpl->Commit();
2570                 }
2571                 else
2572                 {
2573                     // throw away all the changes
2574                     m_pImpl->Revert();
2575                 }
2576             }
2577             catch( uno::Exception& aException )
2578             {
2579                 m_pImpl->AddLog( aException.Message );
2580                 m_pImpl->AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Rethrow" ) ) );
2581 
2582                 uno::Any aCaught( ::cppu::getCaughtException() );
2583                 throw lang::WrappedTargetRuntimeException(
2584                                                 ::rtl::OUString::createFromAscii( "Can not commit/revert the storage!\n" ),
2585                                                 uno::Reference< uno::XInterface >(  static_cast< OWeakObject* >( this ),
2586                                                                                     uno::UNO_QUERY ),
2587                                                 aCaught );
2588             }
2589         }
2590 
2591         m_pImpl = NULL;
2592     }
2593 
2594     // the listener might try to get rid of parent storage, and the storage would delete this object;
2595     // for now the listener is just notified at the end of the method to workaround the problem
2596     // in future a more elegant way should be found
2597 
2598     lang::EventObject aSource( static_cast< ::cppu::OWeakObject* >(this) );
2599     m_pData->m_aListenersContainer.disposeAndClear( aSource );
2600 }
2601 
2602 //-----------------------------------------------
addEventListener(const uno::Reference<lang::XEventListener> & xListener)2603 void SAL_CALL OWriteStream::addEventListener(
2604             const uno::Reference< lang::XEventListener >& xListener )
2605 {
2606     ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
2607 
2608     if ( !m_pImpl )
2609     {
2610         ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) );
2611         throw lang::DisposedException();
2612     }
2613 
2614     m_pData->m_aListenersContainer.addInterface( ::getCppuType((const uno::Reference< lang::XEventListener >*)0),
2615                                                  xListener );
2616 }
2617 
2618 //-----------------------------------------------
removeEventListener(const uno::Reference<lang::XEventListener> & xListener)2619 void SAL_CALL OWriteStream::removeEventListener(
2620             const uno::Reference< lang::XEventListener >& xListener )
2621 {
2622     ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
2623 
2624     if ( !m_pImpl )
2625     {
2626         ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) );
2627         throw lang::DisposedException();
2628     }
2629 
2630     m_pData->m_aListenersContainer.removeInterface( ::getCppuType((const uno::Reference< lang::XEventListener >*)0),
2631                                                     xListener );
2632 }
2633 
2634 //-----------------------------------------------
setEncryptionPassword(const::rtl::OUString & aPass)2635 void SAL_CALL OWriteStream::setEncryptionPassword( const ::rtl::OUString& aPass )
2636 {
2637     ::osl::ResettableMutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
2638 
2639     CheckInitOnDemand();
2640 
2641     if ( !m_pImpl )
2642     {
2643         ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) );
2644         throw lang::DisposedException();
2645     }
2646 
2647     OSL_ENSURE( m_pImpl->m_xPackageStream.is(), "No package stream is set!\n" );
2648 
2649     m_pImpl->SetEncrypted( ::comphelper::OStorageHelper::CreatePackageEncryptionData( aPass ) );
2650 
2651     ModifyParentUnlockMutex_Impl( aGuard );
2652 }
2653 
2654 //-----------------------------------------------
removeEncryption()2655 void SAL_CALL OWriteStream::removeEncryption()
2656 {
2657     ::osl::ResettableMutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
2658 
2659     CheckInitOnDemand();
2660 
2661     if ( !m_pImpl )
2662     {
2663         ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) );
2664         throw lang::DisposedException();
2665     }
2666 
2667     OSL_ENSURE( m_pImpl->m_xPackageStream.is(), "No package stream is set!\n" );
2668 
2669     m_pImpl->SetDecrypted();
2670 
2671     ModifyParentUnlockMutex_Impl( aGuard );
2672 }
2673 
2674 //-----------------------------------------------
setEncryptionData(const uno::Sequence<beans::NamedValue> & aEncryptionData)2675 void SAL_CALL OWriteStream::setEncryptionData( const uno::Sequence< beans::NamedValue >& aEncryptionData )
2676 {
2677     ::osl::ResettableMutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
2678 
2679     CheckInitOnDemand();
2680 
2681     if ( !m_pImpl )
2682     {
2683         ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) );
2684         throw lang::DisposedException();
2685     }
2686 
2687     OSL_ENSURE( m_pImpl->m_xPackageStream.is(), "No package stream is set!\n" );
2688 
2689     m_pImpl->SetEncrypted( aEncryptionData );
2690 
2691     ModifyParentUnlockMutex_Impl( aGuard );
2692 }
2693 
2694 //-----------------------------------------------
hasByID(const::rtl::OUString & sID)2695 sal_Bool SAL_CALL OWriteStream::hasByID(  const ::rtl::OUString& sID )
2696 {
2697     ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
2698 
2699     if ( !m_pImpl )
2700     {
2701         ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) );
2702         throw lang::DisposedException();
2703     }
2704 
2705     if ( m_pData->m_nStorageType != embed::StorageFormats::OFOPXML )
2706         throw uno::RuntimeException();
2707 
2708     try
2709     {
2710         getRelationshipByID( sID );
2711         return sal_True;
2712     }
2713     catch( container::NoSuchElementException& aNoSuchElementException )
2714     {
2715         m_pImpl->AddLog( aNoSuchElementException.Message );
2716         m_pImpl->AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "No Element" ) ) );
2717     }
2718 
2719     return sal_False;
2720 }
2721 
2722 //-----------------------------------------------
getTargetByID(const::rtl::OUString & sID)2723 ::rtl::OUString SAL_CALL OWriteStream::getTargetByID(  const ::rtl::OUString& sID  )
2724 {
2725     ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
2726 
2727     if ( !m_pImpl )
2728     {
2729         ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) );
2730         throw lang::DisposedException();
2731     }
2732 
2733     if ( m_pData->m_nStorageType != embed::StorageFormats::OFOPXML )
2734         throw uno::RuntimeException();
2735 
2736     uno::Sequence< beans::StringPair > aSeq = getRelationshipByID( sID );
2737     for ( sal_Int32 nInd = 0; nInd < aSeq.getLength(); nInd++ )
2738         if ( aSeq[nInd].First.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Target" ) ) )
2739             return aSeq[nInd].Second;
2740 
2741     return ::rtl::OUString();
2742 }
2743 
2744 //-----------------------------------------------
getTypeByID(const::rtl::OUString & sID)2745 ::rtl::OUString SAL_CALL OWriteStream::getTypeByID(  const ::rtl::OUString& sID  )
2746 {
2747     ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
2748 
2749     if ( !m_pImpl )
2750     {
2751         ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) );
2752         throw lang::DisposedException();
2753     }
2754 
2755     if ( m_pData->m_nStorageType != embed::StorageFormats::OFOPXML )
2756         throw uno::RuntimeException();
2757 
2758     uno::Sequence< beans::StringPair > aSeq = getRelationshipByID( sID );
2759     for ( sal_Int32 nInd = 0; nInd < aSeq.getLength(); nInd++ )
2760         if ( aSeq[nInd].First.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Type" ) ) )
2761             return aSeq[nInd].Second;
2762 
2763     return ::rtl::OUString();
2764 }
2765 
2766 //-----------------------------------------------
getRelationshipByID(const::rtl::OUString & sID)2767 uno::Sequence< beans::StringPair > SAL_CALL OWriteStream::getRelationshipByID(  const ::rtl::OUString& sID  )
2768 {
2769     ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
2770 
2771     if ( !m_pImpl )
2772     {
2773         ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) );
2774         throw lang::DisposedException();
2775     }
2776 
2777     if ( m_pData->m_nStorageType != embed::StorageFormats::OFOPXML )
2778         throw uno::RuntimeException();
2779 
2780     // TODO/LATER: in future the unification of the ID could be checked
2781     uno::Sequence< uno::Sequence< beans::StringPair > > aSeq = getAllRelationships();
2782     for ( sal_Int32 nInd1 = 0; nInd1 < aSeq.getLength(); nInd1++ )
2783         for ( sal_Int32 nInd2 = 0; nInd2 < aSeq[nInd1].getLength(); nInd2++ )
2784             if ( aSeq[nInd1][nInd2].First.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Id" ) ) )
2785             {
2786                 if ( aSeq[nInd1][nInd2].Second.equals( sID ) )
2787                     return aSeq[nInd1];
2788                 break;
2789             }
2790 
2791     throw container::NoSuchElementException();
2792 }
2793 
2794 //-----------------------------------------------
getRelationshipsByType(const::rtl::OUString & sType)2795 uno::Sequence< uno::Sequence< beans::StringPair > > SAL_CALL OWriteStream::getRelationshipsByType(  const ::rtl::OUString& sType  )
2796 {
2797     ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
2798 
2799     if ( !m_pImpl )
2800     {
2801         ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) );
2802         throw lang::DisposedException();
2803     }
2804 
2805     if ( m_pData->m_nStorageType != embed::StorageFormats::OFOPXML )
2806         throw uno::RuntimeException();
2807 
2808     uno::Sequence< uno::Sequence< beans::StringPair > > aResult;
2809     sal_Int32 nEntriesNum = 0;
2810 
2811     // TODO/LATER: in future the unification of the ID could be checked
2812     uno::Sequence< uno::Sequence< beans::StringPair > > aSeq = getAllRelationships();
2813     for ( sal_Int32 nInd1 = 0; nInd1 < aSeq.getLength(); nInd1++ )
2814         for ( sal_Int32 nInd2 = 0; nInd2 < aSeq[nInd1].getLength(); nInd2++ )
2815             if ( aSeq[nInd1][nInd2].First.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Type" ) ) )
2816             {
2817                 if ( aSeq[nInd1][nInd2].Second.equals( sType ) )
2818                 {
2819                     aResult.realloc( nEntriesNum );
2820                     aResult[nEntriesNum-1] = aSeq[nInd1];
2821                 }
2822                 break;
2823             }
2824 
2825     return aResult;
2826 }
2827 
2828 //-----------------------------------------------
getAllRelationships()2829 uno::Sequence< uno::Sequence< beans::StringPair > > SAL_CALL OWriteStream::getAllRelationships()
2830 {
2831     ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
2832 
2833     if ( !m_pImpl )
2834     {
2835         ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) );
2836         throw lang::DisposedException();
2837     }
2838 
2839     if ( m_pData->m_nStorageType != embed::StorageFormats::OFOPXML )
2840         throw uno::RuntimeException();
2841 
2842     return m_pImpl->GetAllRelationshipsIfAny();
2843 }
2844 
2845 //-----------------------------------------------
insertRelationshipByID(const::rtl::OUString & sID,const uno::Sequence<beans::StringPair> & aEntry,::sal_Bool bReplace)2846 void SAL_CALL OWriteStream::insertRelationshipByID(  const ::rtl::OUString& sID, const uno::Sequence< beans::StringPair >& aEntry, ::sal_Bool bReplace  )
2847 {
2848     ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
2849 
2850     if ( !m_pImpl )
2851     {
2852         ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) );
2853         throw lang::DisposedException();
2854     }
2855 
2856     if ( m_pData->m_nStorageType != embed::StorageFormats::OFOPXML )
2857         throw uno::RuntimeException();
2858 
2859     ::rtl::OUString aIDTag( RTL_CONSTASCII_USTRINGPARAM( "Id" ) );
2860 
2861     sal_Int32 nIDInd = -1;
2862 
2863     // TODO/LATER: in future the unification of the ID could be checked
2864     uno::Sequence< uno::Sequence< beans::StringPair > > aSeq = getAllRelationships();
2865     for ( sal_Int32 nInd1 = 0; nInd1 < aSeq.getLength(); nInd1++ )
2866         for ( sal_Int32 nInd2 = 0; nInd2 < aSeq[nInd1].getLength(); nInd2++ )
2867             if ( aSeq[nInd1][nInd2].First.equals( aIDTag ) )
2868             {
2869                 if ( aSeq[nInd1][nInd2].Second.equals( sID ) )
2870                     nIDInd = nInd1;
2871 
2872                 break;
2873             }
2874 
2875     if ( nIDInd == -1 || bReplace )
2876     {
2877         if ( nIDInd == -1 )
2878         {
2879             nIDInd = aSeq.getLength();
2880             aSeq.realloc( nIDInd + 1 );
2881         }
2882 
2883         aSeq[nIDInd].realloc( aEntry.getLength() + 1 );
2884 
2885         aSeq[nIDInd][0].First = aIDTag;
2886         aSeq[nIDInd][0].Second = sID;
2887         sal_Int32 nIndTarget = 1;
2888         for ( sal_Int32 nIndOrig = 0;
2889               nIndOrig < aEntry.getLength();
2890               nIndOrig++ )
2891         {
2892             if ( !aEntry[nIndOrig].First.equals( aIDTag ) )
2893                 aSeq[nIDInd][nIndTarget++] = aEntry[nIndOrig];
2894         }
2895 
2896         aSeq[nIDInd].realloc( nIndTarget );
2897     }
2898     else
2899         throw container::ElementExistException(); // TODO
2900 
2901 
2902     m_pImpl->m_aNewRelInfo = aSeq;
2903     m_pImpl->m_xNewRelInfoStream = uno::Reference< io::XInputStream >();
2904     m_pImpl->m_nRelInfoStatus = RELINFO_CHANGED;
2905 }
2906 
2907 //-----------------------------------------------
removeRelationshipByID(const::rtl::OUString & sID)2908 void SAL_CALL OWriteStream::removeRelationshipByID(  const ::rtl::OUString& sID  )
2909 {
2910     ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
2911 
2912     if ( !m_pImpl )
2913     {
2914         ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) );
2915         throw lang::DisposedException();
2916     }
2917 
2918     if ( m_pData->m_nStorageType != embed::StorageFormats::OFOPXML )
2919         throw uno::RuntimeException();
2920 
2921     uno::Sequence< uno::Sequence< beans::StringPair > > aSeq = getAllRelationships();
2922     for ( sal_Int32 nInd1 = 0; nInd1 < aSeq.getLength(); nInd1++ )
2923         for ( sal_Int32 nInd2 = 0; nInd2 < aSeq[nInd1].getLength(); nInd2++ )
2924             if ( aSeq[nInd1][nInd2].First.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Id" ) ) )
2925             {
2926                 if ( aSeq[nInd1][nInd2].Second.equals( sID ) )
2927                 {
2928                     sal_Int32 nLength = aSeq.getLength();
2929                     aSeq[nInd1] = aSeq[nLength-1];
2930                     aSeq.realloc( nLength - 1 );
2931 
2932                     m_pImpl->m_aNewRelInfo = aSeq;
2933                     m_pImpl->m_xNewRelInfoStream = uno::Reference< io::XInputStream >();
2934                     m_pImpl->m_nRelInfoStatus = RELINFO_CHANGED;
2935 
2936                     // TODO/LATER: in future the unification of the ID could be checked
2937                     return;
2938                 }
2939 
2940                 break;
2941             }
2942 
2943     throw container::NoSuchElementException();
2944 }
2945 
2946 //-----------------------------------------------
insertRelationships(const uno::Sequence<uno::Sequence<beans::StringPair>> & aEntries,::sal_Bool bReplace)2947 void SAL_CALL OWriteStream::insertRelationships(  const uno::Sequence< uno::Sequence< beans::StringPair > >& aEntries, ::sal_Bool bReplace  )
2948 {
2949     ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
2950 
2951     if ( !m_pImpl )
2952     {
2953         ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) );
2954         throw lang::DisposedException();
2955     }
2956 
2957     if ( m_pData->m_nStorageType != embed::StorageFormats::OFOPXML )
2958         throw uno::RuntimeException();
2959 
2960     ::rtl::OUString aIDTag( RTL_CONSTASCII_USTRINGPARAM( "Id" ) );
2961     uno::Sequence< uno::Sequence< beans::StringPair > > aSeq = getAllRelationships();
2962     uno::Sequence< uno::Sequence< beans::StringPair > > aResultSeq( aSeq.getLength() + aEntries.getLength() );
2963     sal_Int32 nResultInd = 0;
2964 
2965     for ( sal_Int32 nIndTarget1 = 0; nIndTarget1 < aSeq.getLength(); nIndTarget1++ )
2966         for ( sal_Int32 nIndTarget2 = 0; nIndTarget2 < aSeq[nIndTarget1].getLength(); nIndTarget2++ )
2967             if ( aSeq[nIndTarget1][nIndTarget2].First.equals( aIDTag ) )
2968             {
2969                 sal_Int32 nIndSourceSame = -1;
2970 
2971                 for ( sal_Int32 nIndSource1 = 0; nIndSource1 < aEntries.getLength(); nIndSource1++ )
2972                     for ( sal_Int32 nIndSource2 = 0; nIndSource2 < aEntries[nIndSource1].getLength(); nIndSource2++ )
2973                     {
2974                         if ( aEntries[nIndSource1][nIndSource2].First.equals( aIDTag ) )
2975                         {
2976                             if ( aEntries[nIndSource1][nIndSource2].Second.equals( aSeq[nIndTarget1][nIndTarget2].Second ) )
2977                             {
2978                                 if ( !bReplace )
2979                                     throw container::ElementExistException();
2980 
2981                                 nIndSourceSame = nIndSource1;
2982                             }
2983 
2984                             break;
2985                         }
2986                     }
2987 
2988                 if ( nIndSourceSame == -1 )
2989                 {
2990                     // no such element in the provided sequence
2991                     aResultSeq[nResultInd++] = aSeq[nIndTarget1];
2992                 }
2993 
2994                 break;
2995             }
2996 
2997     for ( sal_Int32 nIndSource1 = 0; nIndSource1 < aEntries.getLength(); nIndSource1++ )
2998     {
2999         aResultSeq[nResultInd].realloc( aEntries[nIndSource1].getLength() );
3000         sal_Bool bHasID = sal_False;
3001         sal_Int32 nResInd2 = 1;
3002 
3003         for ( sal_Int32 nIndSource2 = 0; nIndSource2 < aEntries[nIndSource1].getLength(); nIndSource2++ )
3004             if ( aEntries[nIndSource1][nIndSource2].First.equals( aIDTag ) )
3005             {
3006                 aResultSeq[nResultInd][0] = aEntries[nIndSource1][nIndSource2];
3007                 bHasID = sal_True;
3008             }
3009             else if ( nResInd2 < aResultSeq[nResultInd].getLength() )
3010                 aResultSeq[nResultInd][nResInd2++] = aEntries[nIndSource1][nIndSource2];
3011             else
3012                 throw io::IOException(); // TODO: illegal relation ( no ID )
3013 
3014         if ( !bHasID )
3015             throw io::IOException(); // TODO: illegal relations
3016 
3017         nResultInd++;
3018     }
3019 
3020     aResultSeq.realloc( nResultInd );
3021     m_pImpl->m_aNewRelInfo = aResultSeq;
3022     m_pImpl->m_xNewRelInfoStream = uno::Reference< io::XInputStream >();
3023     m_pImpl->m_nRelInfoStatus = RELINFO_CHANGED;
3024 }
3025 
3026 //-----------------------------------------------
clearRelationships()3027 void SAL_CALL OWriteStream::clearRelationships()
3028 {
3029     ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
3030 
3031     if ( !m_pImpl )
3032     {
3033         ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) );
3034         throw lang::DisposedException();
3035     }
3036 
3037     if ( m_pData->m_nStorageType != embed::StorageFormats::OFOPXML )
3038         throw uno::RuntimeException();
3039 
3040     m_pImpl->m_aNewRelInfo.realloc( 0 );
3041     m_pImpl->m_xNewRelInfoStream = uno::Reference< io::XInputStream >();
3042     m_pImpl->m_nRelInfoStatus = RELINFO_CHANGED;
3043 }
3044 
3045 //-----------------------------------------------
getPropertySetInfo()3046 uno::Reference< beans::XPropertySetInfo > SAL_CALL OWriteStream::getPropertySetInfo()
3047 {
3048     ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
3049 
3050     //TODO:
3051     return uno::Reference< beans::XPropertySetInfo >();
3052 }
3053 
3054 //-----------------------------------------------
setPropertyValue(const::rtl::OUString & aPropertyName,const uno::Any & aValue)3055 void SAL_CALL OWriteStream::setPropertyValue( const ::rtl::OUString& aPropertyName, const uno::Any& aValue )
3056 {
3057     ::osl::ResettableMutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
3058 
3059     if ( !m_pImpl )
3060     {
3061         ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) );
3062         throw lang::DisposedException();
3063     }
3064 
3065     m_pImpl->GetStreamProperties();
3066     ::rtl::OUString aCompressedString( RTL_CONSTASCII_USTRINGPARAM( "Compressed" ) );
3067     ::rtl::OUString aMediaTypeString( RTL_CONSTASCII_USTRINGPARAM( "MediaType" ) );
3068     if ( m_pData->m_nStorageType == embed::StorageFormats::PACKAGE && aPropertyName.equals( aMediaTypeString ) )
3069     {
3070         // if the "Compressed" property is not set explicitly, the MediaType can change the default value
3071         sal_Bool bCompressedValueFromType = sal_True;
3072         ::rtl::OUString aType;
3073         aValue >>= aType;
3074 
3075         if ( !m_pImpl->m_bCompressedSetExplicit )
3076         {
3077             if ( aType.equals( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "image/jpeg" ) ) )
3078               || aType.equals( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "image/png" ) ) )
3079               || aType.equals( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "image/gif" ) ) ) )
3080                 bCompressedValueFromType = sal_False;
3081         }
3082 
3083         for ( sal_Int32 nInd = 0; nInd < m_pImpl->m_aProps.getLength(); nInd++ )
3084         {
3085             if ( aPropertyName.equals( m_pImpl->m_aProps[nInd].Name ) )
3086                 m_pImpl->m_aProps[nInd].Value = aValue;
3087             else if ( !m_pImpl->m_bCompressedSetExplicit && aCompressedString.equals( m_pImpl->m_aProps[nInd].Name ) )
3088                 m_pImpl->m_aProps[nInd].Value <<= bCompressedValueFromType;
3089         }
3090     }
3091     else if ( aPropertyName.equals( aCompressedString ) )
3092     {
3093         // if the "Compressed" property is not set explicitly, the MediaType can change the default value
3094         m_pImpl->m_bCompressedSetExplicit = sal_True;
3095         for ( sal_Int32 nInd = 0; nInd < m_pImpl->m_aProps.getLength(); nInd++ )
3096         {
3097             if ( aPropertyName.equals( m_pImpl->m_aProps[nInd].Name ) )
3098                 m_pImpl->m_aProps[nInd].Value = aValue;
3099         }
3100     }
3101     else if ( m_pData->m_nStorageType == embed::StorageFormats::PACKAGE
3102             && aPropertyName.equalsAscii( "UseCommonStoragePasswordEncryption" ) )
3103     {
3104         sal_Bool bUseCommonEncryption = sal_False;
3105         if ( aValue >>= bUseCommonEncryption )
3106         {
3107             if ( m_bInitOnDemand && m_pImpl->m_bHasInsertedStreamOptimization )
3108             {
3109                 // the data stream is provided to the packagestream directly
3110                 m_pImpl->m_bUseCommonEncryption = bUseCommonEncryption;
3111             }
3112             else if ( bUseCommonEncryption )
3113             {
3114                 if ( !m_pImpl->m_bUseCommonEncryption )
3115                 {
3116                     m_pImpl->SetDecrypted();
3117                     m_pImpl->m_bUseCommonEncryption = sal_True;
3118                 }
3119             }
3120             else
3121                 m_pImpl->m_bUseCommonEncryption = sal_False;
3122         }
3123         else
3124             throw lang::IllegalArgumentException(); //TODO
3125     }
3126     else if ( m_pData->m_nStorageType == embed::StorageFormats::OFOPXML && aPropertyName.equals( aMediaTypeString ) )
3127     {
3128         for ( sal_Int32 nInd = 0; nInd < m_pImpl->m_aProps.getLength(); nInd++ )
3129         {
3130             if ( aPropertyName.equals( m_pImpl->m_aProps[nInd].Name ) )
3131                 m_pImpl->m_aProps[nInd].Value = aValue;
3132         }
3133     }
3134     else if ( m_pData->m_nStorageType == embed::StorageFormats::OFOPXML && aPropertyName.equalsAscii( "RelationsInfoStream" ) )
3135     {
3136         uno::Reference< io::XInputStream > xInRelStream;
3137         if ( ( aValue >>= xInRelStream ) && xInRelStream.is() )
3138         {
3139             uno::Reference< io::XSeekable > xSeek( xInRelStream, uno::UNO_QUERY );
3140             if ( !xSeek.is() )
3141             {
3142                 // currently this is an internal property that is used for optimization
3143                 // and the stream must support XSeekable interface
3144                 // TODO/LATER: in future it can be changed if property is used from outside
3145                 throw lang::IllegalArgumentException(); // TODO
3146             }
3147 
3148             m_pImpl->m_xNewRelInfoStream = xInRelStream;
3149             m_pImpl->m_aNewRelInfo = uno::Sequence< uno::Sequence< beans::StringPair > >();
3150             m_pImpl->m_nRelInfoStatus = RELINFO_CHANGED_STREAM;
3151         }
3152         else
3153             throw lang::IllegalArgumentException(); // TODO
3154     }
3155     else if ( m_pData->m_nStorageType == embed::StorageFormats::OFOPXML && aPropertyName.equalsAscii( "RelationsInfo" ) )
3156     {
3157         if ( aValue >>= m_pImpl->m_aNewRelInfo )
3158         {
3159         }
3160         else
3161             throw lang::IllegalArgumentException(); // TODO
3162     }
3163     else if ( aPropertyName.equalsAscii( "Size" ) )
3164         throw beans::PropertyVetoException(); // TODO
3165     else if ( m_pData->m_nStorageType == embed::StorageFormats::PACKAGE
3166            && ( aPropertyName.equalsAscii( "IsEncrypted" ) || aPropertyName.equalsAscii( "Encrypted" ) ) )
3167         throw beans::PropertyVetoException(); // TODO
3168     else
3169         throw beans::UnknownPropertyException(); // TODO
3170 
3171     m_pImpl->m_bHasDataToFlush = sal_True;
3172     ModifyParentUnlockMutex_Impl( aGuard );
3173 }
3174 
3175 
3176 //-----------------------------------------------
getPropertyValue(const::rtl::OUString & aProp)3177 uno::Any SAL_CALL OWriteStream::getPropertyValue( const ::rtl::OUString& aProp )
3178 {
3179     ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
3180 
3181     if ( !m_pImpl )
3182     {
3183         ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) );
3184         throw lang::DisposedException();
3185     }
3186 
3187     if ( aProp.equalsAscii( "RelId" ) )
3188     {
3189         return uno::makeAny( m_pImpl->GetNewRelId() );
3190     }
3191 
3192     ::rtl::OUString aPropertyName;
3193     if ( aProp.equalsAscii( "IsEncrypted" ) )
3194         aPropertyName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Encrypted" ) );
3195     else
3196         aPropertyName = aProp;
3197 
3198     if ( ( ( m_pData->m_nStorageType == embed::StorageFormats::PACKAGE || m_pData->m_nStorageType == embed::StorageFormats::OFOPXML )
3199             && aPropertyName.equalsAscii( "MediaType" ) )
3200       || ( m_pData->m_nStorageType == embed::StorageFormats::PACKAGE && aPropertyName.equalsAscii( "Encrypted" ) )
3201       || aPropertyName.equalsAscii( "Compressed" ) )
3202     {
3203         m_pImpl->GetStreamProperties();
3204 
3205         for ( sal_Int32 nInd = 0; nInd < m_pImpl->m_aProps.getLength(); nInd++ )
3206         {
3207             if ( aPropertyName.equals( m_pImpl->m_aProps[nInd].Name ) )
3208                 return m_pImpl->m_aProps[nInd].Value;
3209         }
3210     }
3211     else if ( m_pData->m_nStorageType == embed::StorageFormats::PACKAGE
3212             && aPropertyName.equalsAscii( "UseCommonStoragePasswordEncryption" ) )
3213         return uno::makeAny( m_pImpl->m_bUseCommonEncryption );
3214     else if ( aPropertyName.equalsAscii( "Size" ) )
3215     {
3216         CheckInitOnDemand();
3217 
3218         if ( !m_xSeekable.is() )
3219             throw uno::RuntimeException();
3220 
3221         return uno::makeAny( (sal_Int32)m_xSeekable->getLength() );
3222     }
3223 
3224     throw beans::UnknownPropertyException(); // TODO
3225 }
3226 
3227 
3228 //-----------------------------------------------
addPropertyChangeListener(const::rtl::OUString &,const uno::Reference<beans::XPropertyChangeListener> &)3229 void SAL_CALL OWriteStream::addPropertyChangeListener(
3230     const ::rtl::OUString& /*aPropertyName*/,
3231     const uno::Reference< beans::XPropertyChangeListener >& /*xListener*/ )
3232 {
3233     ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
3234 
3235     if ( !m_pImpl )
3236     {
3237         ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) );
3238         throw lang::DisposedException();
3239     }
3240 
3241     //TODO:
3242 }
3243 
3244 
3245 //-----------------------------------------------
removePropertyChangeListener(const::rtl::OUString &,const uno::Reference<beans::XPropertyChangeListener> &)3246 void SAL_CALL OWriteStream::removePropertyChangeListener(
3247     const ::rtl::OUString& /*aPropertyName*/,
3248     const uno::Reference< beans::XPropertyChangeListener >& /*aListener*/ )
3249 {
3250     ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
3251 
3252     if ( !m_pImpl )
3253     {
3254         ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) );
3255         throw lang::DisposedException();
3256     }
3257 
3258     //TODO:
3259 }
3260 
3261 
3262 //-----------------------------------------------
addVetoableChangeListener(const::rtl::OUString &,const uno::Reference<beans::XVetoableChangeListener> &)3263 void SAL_CALL OWriteStream::addVetoableChangeListener(
3264     const ::rtl::OUString& /*PropertyName*/,
3265     const uno::Reference< beans::XVetoableChangeListener >& /*aListener*/ )
3266 {
3267     ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
3268 
3269     if ( !m_pImpl )
3270     {
3271         ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) );
3272         throw lang::DisposedException();
3273     }
3274 
3275     //TODO:
3276 }
3277 
3278 
3279 //-----------------------------------------------
removeVetoableChangeListener(const::rtl::OUString &,const uno::Reference<beans::XVetoableChangeListener> &)3280 void SAL_CALL OWriteStream::removeVetoableChangeListener(
3281     const ::rtl::OUString& /*PropertyName*/,
3282     const uno::Reference< beans::XVetoableChangeListener >& /*aListener*/ )
3283 {
3284     ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
3285 
3286     if ( !m_pImpl )
3287     {
3288         ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) );
3289         throw lang::DisposedException();
3290     }
3291 
3292     //TODO:
3293 }
3294 
3295 //____________________________________________________________________________________________________
3296 //  XTransactedObject
3297 //____________________________________________________________________________________________________
3298 
3299 //-----------------------------------------------
BroadcastTransaction(sal_Int8 nMessage)3300 void OWriteStream::BroadcastTransaction( sal_Int8 nMessage )
3301 /*
3302     1 - preCommit
3303     2 - committed
3304     3 - preRevert
3305     4 - reverted
3306 */
3307 {
3308     // no need to lock mutex here for the checking of m_pImpl, and m_pData is alive until the object is destructed
3309     if ( !m_pImpl )
3310     {
3311         ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) );
3312         throw lang::DisposedException();
3313     }
3314 
3315     lang::EventObject aSource( static_cast< ::cppu::OWeakObject* >(this) );
3316 
3317     ::cppu::OInterfaceContainerHelper* pContainer =
3318             m_pData->m_aListenersContainer.getContainer(
3319                 ::getCppuType( ( const uno::Reference< embed::XTransactionListener >*) NULL ) );
3320     if ( pContainer )
3321     {
3322         ::cppu::OInterfaceIteratorHelper pIterator( *pContainer );
3323         while ( pIterator.hasMoreElements( ) )
3324         {
3325             OSL_ENSURE( nMessage >= 1 && nMessage <= 4, "Wrong internal notification code is used!\n" );
3326 
3327             switch( nMessage )
3328             {
3329                 case STOR_MESS_PRECOMMIT:
3330                     ( ( embed::XTransactionListener* )pIterator.next( ) )->preCommit( aSource );
3331                     break;
3332                 case STOR_MESS_COMMITED:
3333                     ( ( embed::XTransactionListener* )pIterator.next( ) )->commited( aSource );
3334                     break;
3335                 case STOR_MESS_PREREVERT:
3336                     ( ( embed::XTransactionListener* )pIterator.next( ) )->preRevert( aSource );
3337                     break;
3338                 case STOR_MESS_REVERTED:
3339                     ( ( embed::XTransactionListener* )pIterator.next( ) )->reverted( aSource );
3340                     break;
3341             }
3342         }
3343     }
3344 }
3345 //-----------------------------------------------
commit()3346 void SAL_CALL OWriteStream::commit()
3347 {
3348     RTL_LOGFILE_CONTEXT( aLog, "package (mv76033) OWriteStream::commit" );
3349 
3350     if ( !m_pImpl )
3351     {
3352         ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) );
3353         throw lang::DisposedException();
3354     }
3355 
3356     if ( !m_bTransacted )
3357         throw uno::RuntimeException();
3358 
3359     try {
3360         BroadcastTransaction( STOR_MESS_PRECOMMIT );
3361 
3362         ::osl::ResettableMutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
3363 
3364         if ( !m_pImpl )
3365         {
3366             ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) );
3367             throw lang::DisposedException();
3368         }
3369 
3370         m_pImpl->Commit();
3371 
3372         // when the storage is committed the parent is modified
3373         ModifyParentUnlockMutex_Impl( aGuard );
3374     }
3375     catch( io::IOException& aIOException )
3376     {
3377         m_pImpl->AddLog( aIOException.Message );
3378         m_pImpl->AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Rethrow" ) ) );
3379         throw;
3380     }
3381     catch( embed::StorageWrappedTargetException& aStorageWrappedTargetException )
3382     {
3383         m_pImpl->AddLog( aStorageWrappedTargetException.Message );
3384         m_pImpl->AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Rethrow" ) ) );
3385         throw;
3386     }
3387     catch( uno::RuntimeException& aRuntimeException )
3388     {
3389         m_pImpl->AddLog( aRuntimeException.Message );
3390         m_pImpl->AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Rethrow" ) ) );
3391         throw;
3392     }
3393     catch( uno::Exception& aException )
3394     {
3395         m_pImpl->AddLog( aException.Message );
3396         m_pImpl->AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Rethrow" ) ) );
3397 
3398         uno::Any aCaught( ::cppu::getCaughtException() );
3399         throw embed::StorageWrappedTargetException( ::rtl::OUString::createFromAscii( "Problems on commit!" ),
3400                                   uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >( this ) ),
3401                                   aCaught );
3402     }
3403 
3404     BroadcastTransaction( STOR_MESS_COMMITED );
3405 }
3406 
3407 //-----------------------------------------------
revert()3408 void SAL_CALL OWriteStream::revert()
3409 {
3410     RTL_LOGFILE_CONTEXT( aLog, "package (mv76033) OWriteStream::revert" );
3411 
3412     // the method removes all the changes done after last commit
3413 
3414     if ( !m_pImpl )
3415     {
3416         ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) );
3417         throw lang::DisposedException();
3418     }
3419 
3420     if ( !m_bTransacted )
3421         throw uno::RuntimeException();
3422 
3423     BroadcastTransaction( STOR_MESS_PREREVERT );
3424 
3425     ::osl::ResettableMutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
3426 
3427     if ( !m_pImpl )
3428     {
3429         ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) );
3430         throw lang::DisposedException();
3431     }
3432 
3433     try {
3434         m_pImpl->Revert();
3435     }
3436     catch( io::IOException& aIOException )
3437     {
3438         m_pImpl->AddLog( aIOException.Message );
3439         m_pImpl->AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Rethrow" ) ) );
3440         throw;
3441     }
3442     catch( embed::StorageWrappedTargetException& aStorageWrappedTargetException )
3443     {
3444         m_pImpl->AddLog( aStorageWrappedTargetException.Message );
3445         m_pImpl->AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Rethrow" ) ) );
3446         throw;
3447     }
3448     catch( uno::RuntimeException& aRuntimeException )
3449     {
3450         m_pImpl->AddLog( aRuntimeException.Message );
3451         m_pImpl->AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Rethrow" ) ) );
3452         throw;
3453     }
3454     catch( uno::Exception& aException )
3455     {
3456         m_pImpl->AddLog( aException.Message );
3457         m_pImpl->AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Rethrow" ) ) );
3458 
3459         uno::Any aCaught( ::cppu::getCaughtException() );
3460         throw embed::StorageWrappedTargetException( ::rtl::OUString::createFromAscii( "Problems on revert!" ),
3461                                   uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >( this ) ),
3462                                   aCaught );
3463     }
3464 
3465     aGuard.clear();
3466 
3467     BroadcastTransaction( STOR_MESS_REVERTED );
3468 }
3469 
3470 //____________________________________________________________________________________________________
3471 //  XTransactionBroadcaster
3472 //____________________________________________________________________________________________________
3473 
3474 //-----------------------------------------------
addTransactionListener(const uno::Reference<embed::XTransactionListener> & aListener)3475 void SAL_CALL OWriteStream::addTransactionListener( const uno::Reference< embed::XTransactionListener >& aListener )
3476 {
3477     ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
3478 
3479     if ( !m_pImpl )
3480     {
3481         ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) );
3482         throw lang::DisposedException();
3483     }
3484 
3485     if ( !m_bTransacted )
3486         throw uno::RuntimeException();
3487 
3488     m_pData->m_aListenersContainer.addInterface( ::getCppuType((const uno::Reference< embed::XTransactionListener >*)0),
3489                                                 aListener );
3490 }
3491 
3492 //-----------------------------------------------
removeTransactionListener(const uno::Reference<embed::XTransactionListener> & aListener)3493 void SAL_CALL OWriteStream::removeTransactionListener( const uno::Reference< embed::XTransactionListener >& aListener )
3494 {
3495     ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
3496 
3497     if ( !m_pImpl )
3498     {
3499         ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) );
3500         throw lang::DisposedException();
3501     }
3502 
3503     if ( !m_bTransacted )
3504         throw uno::RuntimeException();
3505 
3506     m_pData->m_aListenersContainer.removeInterface( ::getCppuType((const uno::Reference< embed::XTransactionListener >*)0),
3507                                                     aListener );
3508 }
3509