1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  *   Licensed to the Apache Software Foundation (ASF) under one or more
12  *   contributor license agreements. See the NOTICE file distributed
13  *   with this work for additional information regarding copyright
14  *   ownership. The ASF licenses this file to you under the Apache
15  *   License, Version 2.0 (the "License"); you may not use this file
16  *   except in compliance with the License. You may obtain a copy of
17  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #ifndef INCLUDED_PACKAGE_SOURCE_XSTOR_OWRITEABLESTREAM_HXX
21 #define INCLUDED_PACKAGE_SOURCE_XSTOR_OWRITEABLESTREAM_HXX
22 
23 #include <com/sun/star/io/XInputStream.hpp>
24 #include <com/sun/star/io/XOutputStream.hpp>
25 #include <com/sun/star/io/XStream.hpp>
26 #include <com/sun/star/io/XSeekable.hpp>
27 #include <com/sun/star/io/XTruncate.hpp>
28 #include <com/sun/star/packages/XDataSinkEncrSupport.hpp>
29 #include <com/sun/star/packages/NoEncryptionException.hpp>
30 #include <com/sun/star/lang/XEventListener.hpp>
31 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
32 #include <com/sun/star/lang/XComponent.hpp>
33 #include <com/sun/star/embed/XEncryptionProtectedSource2.hpp>
34 #include <com/sun/star/embed/XStorage.hpp>
35 #include <com/sun/star/embed/XRelationshipAccess.hpp>
36 #include <com/sun/star/embed/XExtendedStorageStream.hpp>
37 #include <com/sun/star/embed/XTransactedObject.hpp>
38 #include <com/sun/star/embed/XTransactionBroadcaster.hpp>
39 #include <com/sun/star/container/XNameContainer.hpp>
40 #include <com/sun/star/beans/StringPair.hpp>
41 
42 #include <cppuhelper/weak.hxx>
43 #include <cppuhelper/interfacecontainer.h>
44 
45 #include <comphelper/refcountedmutex.hxx>
46 #include <comphelper/sequenceashashmap.hxx>
47 
48 #include <vector>
49 #include <memory>
50 #include <string_view>
51 
52 #include "ocompinstream.hxx"
53 
54 namespace com::sun::star::uno {
55     class XComponentContext;
56 }
57 
58 namespace package {
59     // all data in aHash1 is contained in aHash2
60     bool PackageEncryptionDataLessOrEqual( const ::comphelper::SequenceAsHashMap& aHash1, const ::comphelper::SequenceAsHashMap& aHash2 );
61 }
62 
63 struct WSInternalData_Impl;
64 
65 struct OStorage_Impl;
66 class OWriteStream;
67 
68 struct OWriteStream_Impl
69 {
70     rtl::Reference<comphelper::RefCountedMutex> m_xMutex;
71 
72     friend struct OStorage_Impl;
73     friend class OWriteStream;
74     friend class OInputCompStream;
75 
76     OWriteStream*   m_pAntiImpl;
77     OUString m_aTempURL;
78 
79     css::uno::Reference< css::io::XStream > m_xCacheStream;
80     css::uno::Reference< css::io::XSeekable > m_xCacheSeek;
81 
82     std::vector< OInputCompStream* > m_aInputStreamsVector;
83 
84     bool                        m_bHasDataToFlush;    // only modified elements will be sent to the original content
85     bool                        m_bFlushed;      // sending the streams is coordinated by the root storage of the package
86 
87     css::uno::Reference< css::packages::XDataSinkEncrSupport > m_xPackageStream;
88 
89     css::uno::Reference< css::uno::XComponentContext > m_xContext;
90 
91     OStorage_Impl* m_pParent;
92 
93     css::uno::Sequence< css::beans::PropertyValue > m_aProps;
94 
95     bool m_bForceEncrypted;
96 
97     bool m_bUseCommonEncryption;
98     bool m_bHasCachedEncryptionData;
99     ::comphelper::SequenceAsHashMap m_aEncryptionData;
100 
101     bool m_bCompressedSetExplicit;
102 
103     css::uno::Reference< css::lang::XSingleServiceFactory > m_xPackage;
104 
105     bool m_bHasInsertedStreamOptimization;
106 
107     sal_Int32 m_nStorageType;
108 
109     // Relations info related data, stored in *.rels file in OFOPXML format
110     css::uno::Reference< css::io::XInputStream > m_xOrigRelInfoStream;
111     css::uno::Sequence< css::uno::Sequence< css::beans::StringPair > > m_aOrigRelInfo;
112     bool m_bOrigRelInfoBroken;
113 
114     css::uno::Sequence< css::uno::Sequence< css::beans::StringPair > > m_aNewRelInfo;
115     css::uno::Reference< css::io::XInputStream > m_xNewRelInfoStream;
116     sal_Int16 m_nRelInfoStatus;
117     sal_Int32 m_nRelId;
118 
119 private:
120     OUString const & GetFilledTempFileIfNo( const css::uno::Reference< css::io::XInputStream >& xStream );
121     OUString const & FillTempGetFileName();
122     css::uno::Reference< css::io::XStream >       GetTempFileAsStream();
123     css::uno::Reference< css::io::XInputStream >  GetTempFileAsInputStream();
124 
125     css::uno::Reference< css::io::XStream > GetStream_Impl( sal_Int32 nStreamMode,
126                                                                                         bool bHierarchyAccess );
127 
128     /// @throws css::packages::NoEncryptionException
129     ::comphelper::SequenceAsHashMap GetCommonRootEncryptionData();
130 
131     css::uno::Sequence< css::beans::PropertyValue > ReadPackageStreamProperties();
132     css::uno::Sequence< css::beans::PropertyValue > InsertOwnProps(
133                             const css::uno::Sequence< css::beans::PropertyValue >& aProps,
134                             bool bUseCommonEncryption );
135 
136 public:
137     OWriteStream_Impl(
138                 OStorage_Impl* pParent,
139                 const css::uno::Reference< css::packages::XDataSinkEncrSupport >& xPackageStream,
140                 const css::uno::Reference< css::lang::XSingleServiceFactory >& xPackage,
141                 const css::uno::Reference< css::uno::XComponentContext >& xContext,
142                 bool bForceEncrypted,
143                 sal_Int32 nStorageType,
144                 bool bDefaultCompress,
145                 const css::uno::Reference< css::io::XInputStream >& xRelInfoStream =
146                     css::uno::Reference< css::io::XInputStream >() );
147 
148     ~OWriteStream_Impl();
149 
150     void CleanCacheStream();
151 
UsesCommonEncryption_ImplOWriteStream_Impl152     bool UsesCommonEncryption_Impl() { return m_bUseCommonEncryption; }
HasTempFile_ImplOWriteStream_Impl153     bool HasTempFile_Impl() const { return ( m_aTempURL.getLength() != 0 ); }
154     bool IsTransacted();
155 
HasWriteOwner_ImplOWriteStream_Impl156     bool HasWriteOwner_Impl() const { return ( m_pAntiImpl != nullptr ); }
157 
158     void InsertIntoPackageFolder(
159             const OUString& aName,
160             const css::uno::Reference< css::container::XNameContainer >& xParentPackageFolder );
161 
SetToBeCommitedOWriteStream_Impl162     void SetToBeCommited() { m_bFlushed = true; }
163 
HasCachedEncryptionDataOWriteStream_Impl164     bool HasCachedEncryptionData() const { return m_bHasCachedEncryptionData; }
GetCachedEncryptionDataOWriteStream_Impl165     ::comphelper::SequenceAsHashMap& GetCachedEncryptionData() { return m_aEncryptionData; }
166 
IsModifiedOWriteStream_Impl167     bool IsModified() const { return m_bHasDataToFlush || m_bFlushed; }
168 
169     bool IsEncrypted();
170     void SetDecrypted();
171     void SetEncrypted( const ::comphelper::SequenceAsHashMap& aEncryptionData );
172 
173     void DisposeWrappers();
174 
175     void InsertStreamDirectly(
176             const css::uno::Reference< css::io::XInputStream >& xInStream,
177             const css::uno::Sequence< css::beans::PropertyValue >& aProps );
178 
179     void Commit();
180     void Revert();
181 
182     css::uno::Sequence< css::beans::PropertyValue > const & GetStreamProperties();
183 
184     css::uno::Sequence< css::uno::Sequence< css::beans::StringPair > > GetAllRelationshipsIfAny();
185 
186     void CopyInternallyTo_Impl( const css::uno::Reference< css::io::XStream >& xDestStream,
187                                 const ::comphelper::SequenceAsHashMap& aEncryptionData );
188     void CopyInternallyTo_Impl( const css::uno::Reference< css::io::XStream >& xDestStream );
189 
190     css::uno::Reference< css::io::XStream > GetStream(
191                         sal_Int32 nStreamMode,
192                         const ::comphelper::SequenceAsHashMap& aEncryptionData,
193                         bool bHierarchyAccess );
194 
195     css::uno::Reference< css::io::XStream > GetStream(
196                         sal_Int32 nStreamMode,
197                         bool bHierarchyAccess );
198 
199     css::uno::Reference< css::io::XInputStream > GetRawInStream();
200     css::uno::Reference< css::io::XInputStream > GetPlainRawInStream();
201 
202     void InputStreamDisposed( OInputCompStream* pStream );
203 
204     void CreateReadonlyCopyBasedOnData(
205                     const css::uno::Reference< css::io::XInputStream >& xDataToCopy,
206                     const css::uno::Sequence< css::beans::PropertyValue >& aProps,
207                     css::uno::Reference< css::io::XStream >& xTargetStream );
208 
209     void GetCopyOfLastCommit( css::uno::Reference< css::io::XStream >& xTargetStream );
210     void GetCopyOfLastCommit(
211                   css::uno::Reference< css::io::XStream >& xTargetStream,
212                             const ::comphelper::SequenceAsHashMap& aEncryptionData );
213 
214     void CommitStreamRelInfo(
215                     const css::uno::Reference< css::embed::XStorage >& xRelStorage,
216                     std::u16string_view aOrigStreamName,
217                     std::u16string_view aNewStreamName );
218 
219     void ReadRelInfoIfNecessary();
220 
GetNewRelIdOWriteStream_Impl221     sal_Int32 GetNewRelId() { return m_nRelId ++; }
222 };
223 
224 class OWriteStream : public css::lang::XTypeProvider
225             , public css::io::XInputStream
226             , public css::io::XOutputStream
227             , public css::embed::XExtendedStorageStream
228             , public css::io::XSeekable
229             , public css::io::XTruncate
230             , public css::embed::XEncryptionProtectedSource2
231             , public css::embed::XRelationshipAccess
232             , public css::embed::XTransactedObject
233             , public css::embed::XTransactionBroadcaster
234             , public css::beans::XPropertySet
235             , public ::cppu::OWeakObject
236 {
237     friend struct OWriteStream_Impl;
238 
239 protected:
240     css::uno::Reference < css::io::XInputStream > m_xInStream;
241     css::uno::Reference < css::io::XOutputStream > m_xOutStream;
242     css::uno::Reference < css::io::XSeekable > m_xSeekable;
243 
244     OWriteStream_Impl* m_pImpl;
245     std::unique_ptr<WSInternalData_Impl> m_pData;
246 
247     bool m_bInStreamDisconnected;
248     bool m_bInitOnDemand;
249     sal_Int64 m_nInitPosition;
250 
251     bool m_bTransacted;
252 
253     OWriteStream( OWriteStream_Impl* pImpl, bool bTransacted );
254     OWriteStream( OWriteStream_Impl* pImpl, css::uno::Reference< css::io::XStream > const & xStream, bool bTransacted );
255 
256     void CloseOutput_Impl();
257 
258     void CopyToStreamInternally_Impl( const css::uno::Reference< css::io::XStream >& xStream );
259 
260     void ModifyParentUnlockMutex_Impl(osl::ClearableMutexGuard& aGuard);
261 
262     void BroadcastTransaction( sal_Int8 nMessage );
263 
264 public:
265 
266     virtual ~OWriteStream() override;
267 
268     void CheckInitOnDemand();
269     void DeInit();
270 
271     // XInterface
272     virtual css::uno::Any SAL_CALL queryInterface( const css::uno::Type& rType ) override;
273     virtual void SAL_CALL acquire() noexcept override;
274     virtual void SAL_CALL release() noexcept override;
275 
276     //  XTypeProvider
277     virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes() override;
278     virtual css::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId() override;
279 
280     // XInputStream
281     virtual sal_Int32 SAL_CALL readBytes( css::uno::Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead ) override;
282     virtual sal_Int32 SAL_CALL readSomeBytes( css::uno::Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead ) override;
283     virtual void SAL_CALL skipBytes( sal_Int32 nBytesToSkip ) override;
284     virtual sal_Int32 SAL_CALL available(  ) override;
285     virtual void SAL_CALL closeInput(  ) override;
286 
287     // XOutputStream
288     virtual void SAL_CALL writeBytes( const css::uno::Sequence< sal_Int8 >& aData ) override;
289     virtual void SAL_CALL flush(  ) override;
290     virtual void SAL_CALL closeOutput(  ) override;
291 
292     //XSeekable
293     virtual void SAL_CALL seek( sal_Int64 location ) override;
294     virtual sal_Int64 SAL_CALL getPosition() override;
295     virtual sal_Int64 SAL_CALL getLength() override;
296 
297     //XStream
298     virtual css::uno::Reference< css::io::XInputStream > SAL_CALL getInputStream(  ) override;
299     virtual css::uno::Reference< css::io::XOutputStream > SAL_CALL getOutputStream(  ) override;
300 
301     // XTruncate
302     virtual void SAL_CALL truncate() override;
303 
304     //XComponent
305     virtual void SAL_CALL dispose() override;
306     virtual void SAL_CALL addEventListener( const css::uno::Reference< css::lang::XEventListener >& xListener ) override;
307     virtual void SAL_CALL removeEventListener( const css::uno::Reference< css::lang::XEventListener >& aListener ) override;
308 
309     //XEncryptionProtectedSource
310     virtual void SAL_CALL setEncryptionPassword( const OUString& aPass ) override;
311     virtual void SAL_CALL removeEncryption() override;
312 
313     //XEncryptionProtectedSource2
314     virtual void SAL_CALL setEncryptionData( const css::uno::Sequence< css::beans::NamedValue >& aEncryptionData ) override;
315     virtual sal_Bool SAL_CALL hasEncryptionData() override;
316 
317     //XRelationshipAccess
318     virtual sal_Bool SAL_CALL hasByID( const OUString& sID ) override;
319     virtual OUString SAL_CALL getTargetByID( const OUString& sID ) override;
320     virtual OUString SAL_CALL getTypeByID( const OUString& sID ) override;
321     virtual css::uno::Sequence< css::beans::StringPair > SAL_CALL getRelationshipByID( const OUString& sID ) override;
322     virtual css::uno::Sequence< css::uno::Sequence< css::beans::StringPair > > SAL_CALL getRelationshipsByType( const OUString& sType ) override;
323     virtual css::uno::Sequence< css::uno::Sequence< css::beans::StringPair > > SAL_CALL getAllRelationships(  ) override;
324     virtual void SAL_CALL insertRelationshipByID( const OUString& sID, const css::uno::Sequence< css::beans::StringPair >& aEntry, sal_Bool bReplace ) override;
325     virtual void SAL_CALL removeRelationshipByID( const OUString& sID ) override;
326     virtual void SAL_CALL insertRelationships( const css::uno::Sequence< css::uno::Sequence< css::beans::StringPair > >& aEntries, sal_Bool bReplace ) override;
327     virtual void SAL_CALL clearRelationships(  ) override;
328 
329     //XPropertySet
330     virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo() override;
331     virtual void SAL_CALL setPropertyValue( const OUString& aPropertyName, const css::uno::Any& aValue ) override;
332     virtual css::uno::Any SAL_CALL getPropertyValue( const OUString& PropertyName ) override;
333     virtual void SAL_CALL addPropertyChangeListener( const OUString& aPropertyName, const css::uno::Reference< css::beans::XPropertyChangeListener >& xListener ) override;
334     virtual void SAL_CALL removePropertyChangeListener( const OUString& aPropertyName, const css::uno::Reference< css::beans::XPropertyChangeListener >& aListener ) override;
335     virtual void SAL_CALL addVetoableChangeListener( const OUString& PropertyName, const css::uno::Reference< css::beans::XVetoableChangeListener >& aListener ) override;
336     virtual void SAL_CALL removeVetoableChangeListener( const OUString& PropertyName, const css::uno::Reference< css::beans::XVetoableChangeListener >& aListener ) override;
337 
338     // XTransactedObject
339     virtual void SAL_CALL commit() override;
340     virtual void SAL_CALL revert() override;
341 
342     // XTransactionBroadcaster
343     virtual void SAL_CALL addTransactionListener(
344             const css::uno::Reference< css::embed::XTransactionListener >& aListener ) override;
345     virtual void SAL_CALL removeTransactionListener(
346             const css::uno::Reference< css::embed::XTransactionListener >& aListener ) override;
347 
348 };
349 
350 #endif
351 
352 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
353