1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20 #include <oox/helper/storagebase.hxx>
21
22 #include <com/sun/star/embed/XTransactedObject.hpp>
23 #include <com/sun/star/io/XStream.hpp>
24 #include <osl/diagnose.h>
25 #include <rtl/ustrbuf.hxx>
26 #include <oox/helper/binaryinputstream.hxx>
27 #include <oox/helper/binaryoutputstream.hxx>
28
29 namespace oox {
30
31 using namespace ::com::sun::star::embed;
32 using namespace ::com::sun::star::io;
33 using namespace ::com::sun::star::uno;
34
35 namespace {
36
lclSplitFirstElement(OUString & orElement,OUString & orRemainder,const OUString & _aFullName)37 void lclSplitFirstElement( OUString& orElement, OUString& orRemainder, const OUString& _aFullName )
38 {
39 OUString aFullName = _aFullName;
40 sal_Int32 nSlashPos = aFullName.indexOf( '/' );
41
42 // strip leading slashes
43 while( nSlashPos == 0 )
44 {
45 aFullName = aFullName.copy(1);
46 nSlashPos = aFullName.indexOf( '/' );
47 }
48
49 if( (0 <= nSlashPos) && (nSlashPos < aFullName.getLength()) )
50 {
51 orElement = aFullName.copy( 0, nSlashPos );
52 orRemainder = aFullName.copy( nSlashPos + 1 );
53 }
54 else
55 {
56 orElement = aFullName;
57 }
58 }
59
60 } // namespace
61
StorageBase(const Reference<XInputStream> & rxInStream,bool bBaseStreamAccess)62 StorageBase::StorageBase( const Reference< XInputStream >& rxInStream, bool bBaseStreamAccess ) :
63 mxInStream( rxInStream ),
64 mbBaseStreamAccess( bBaseStreamAccess ),
65 mbReadOnly( true )
66 {
67 OSL_ENSURE( mxInStream.is(), "StorageBase::StorageBase - missing base input stream" );
68 }
69
StorageBase(const Reference<XStream> & rxOutStream,bool bBaseStreamAccess)70 StorageBase::StorageBase( const Reference< XStream >& rxOutStream, bool bBaseStreamAccess ) :
71 mxOutStream( rxOutStream ),
72 mbBaseStreamAccess( bBaseStreamAccess ),
73 mbReadOnly( false )
74 {
75 OSL_ENSURE( mxOutStream.is(), "StorageBase::StorageBase - missing base output stream" );
76 }
77
StorageBase(const StorageBase & rParentStorage,const OUString & rStorageName,bool bReadOnly)78 StorageBase::StorageBase( const StorageBase& rParentStorage, const OUString& rStorageName, bool bReadOnly ) :
79 maParentPath( rParentStorage.getPath() ),
80 maStorageName( rStorageName ),
81 mbBaseStreamAccess( false ),
82 mbReadOnly( bReadOnly )
83 {
84 }
85
~StorageBase()86 StorageBase::~StorageBase()
87 {
88 }
89
isStorage() const90 bool StorageBase::isStorage() const
91 {
92 return implIsStorage();
93 }
94
isRootStorage() const95 bool StorageBase::isRootStorage() const
96 {
97 return implIsStorage() && maStorageName.isEmpty();
98 }
99
getXStorage() const100 Reference< XStorage > StorageBase::getXStorage() const
101 {
102 return implGetXStorage();
103 }
104
getPath() const105 OUString StorageBase::getPath() const
106 {
107 OUStringBuffer aBuffer( maParentPath );
108 if( !aBuffer.isEmpty() )
109 aBuffer.append( '/' );
110 aBuffer.append( maStorageName );
111 return aBuffer.makeStringAndClear();
112 }
113
getElementNames(::std::vector<OUString> & orElementNames) const114 void StorageBase::getElementNames( ::std::vector< OUString >& orElementNames ) const
115 {
116 orElementNames.clear();
117 implGetElementNames( orElementNames );
118 }
119
openSubStorage(const OUString & rStorageName,bool bCreateMissing)120 StorageRef StorageBase::openSubStorage( const OUString& rStorageName, bool bCreateMissing )
121 {
122 StorageRef xSubStorage;
123 OSL_ENSURE( !bCreateMissing || !mbReadOnly, "StorageBase::openSubStorage - cannot create substorage in read-only mode" );
124 if( !bCreateMissing || !mbReadOnly )
125 {
126 OUString aElement, aRemainder;
127 lclSplitFirstElement( aElement, aRemainder, rStorageName );
128 if( !aElement.isEmpty() )
129 xSubStorage = getSubStorage( aElement, bCreateMissing );
130 if( xSubStorage.get() && !aRemainder.isEmpty() )
131 xSubStorage = xSubStorage->openSubStorage( aRemainder, bCreateMissing );
132 }
133 return xSubStorage;
134 }
135
openInputStream(const OUString & rStreamName)136 Reference< XInputStream > StorageBase::openInputStream( const OUString& rStreamName )
137 {
138 Reference< XInputStream > xInStream;
139 OUString aElement, aRemainder;
140 lclSplitFirstElement( aElement, aRemainder, rStreamName );
141 if( !aElement.isEmpty() )
142 {
143 if( !aRemainder.isEmpty() )
144 {
145 StorageRef xSubStorage = getSubStorage( aElement, false );
146 if( xSubStorage.get() )
147 xInStream = xSubStorage->openInputStream( aRemainder );
148 }
149 else
150 {
151 xInStream = implOpenInputStream( aElement );
152 }
153 }
154 else if( mbBaseStreamAccess )
155 {
156 xInStream = mxInStream;
157 }
158 return xInStream;
159 }
160
openOutputStream(const OUString & rStreamName)161 Reference< XOutputStream > StorageBase::openOutputStream( const OUString& rStreamName )
162 {
163 Reference< XOutputStream > xOutStream;
164 OSL_ENSURE( !mbReadOnly, "StorageBase::openOutputStream - cannot create output stream in read-only mode" );
165 if( !mbReadOnly )
166 {
167 OUString aElement, aRemainder;
168 lclSplitFirstElement( aElement, aRemainder, rStreamName );
169 if( !aElement.isEmpty() )
170 {
171 if( !aRemainder.isEmpty() )
172 {
173 StorageRef xSubStorage = getSubStorage( aElement, true );
174 if( xSubStorage.get() )
175 xOutStream = xSubStorage->openOutputStream( aRemainder );
176 }
177 else
178 {
179 xOutStream = implOpenOutputStream( aElement );
180 }
181 }
182 else if( mbBaseStreamAccess )
183 {
184 xOutStream = mxOutStream->getOutputStream();
185 }
186 }
187 return xOutStream;
188 }
189
copyToStorage(StorageBase & rDestStrg,const OUString & rElementName)190 void StorageBase::copyToStorage( StorageBase& rDestStrg, const OUString& rElementName )
191 {
192 OSL_ENSURE( rDestStrg.isStorage() && !rDestStrg.isReadOnly(), "StorageBase::copyToStorage - invalid destination" );
193 OSL_ENSURE( !rElementName.isEmpty(), "StorageBase::copyToStorage - invalid element name" );
194 if( rDestStrg.isStorage() && !rDestStrg.isReadOnly() && !rElementName.isEmpty() )
195 {
196 StorageRef xSubStrg = openSubStorage( rElementName, false );
197 if( xSubStrg.get() )
198 {
199 StorageRef xDestSubStrg = rDestStrg.openSubStorage( rElementName, true );
200 if( xDestSubStrg.get() )
201 xSubStrg->copyStorageToStorage( *xDestSubStrg );
202 }
203 else
204 {
205 Reference< XInputStream > xInStrm = openInputStream( rElementName );
206 if( xInStrm.is() )
207 {
208 Reference< XOutputStream > xOutStrm = rDestStrg.openOutputStream( rElementName );
209 if( xOutStrm.is() )
210 {
211 BinaryXInputStream aInStrm( xInStrm, true );
212 BinaryXOutputStream aOutStrm( xOutStrm, true );
213 aInStrm.copyToStream( aOutStrm );
214 }
215 }
216 }
217 }
218 }
219
copyStorageToStorage(StorageBase & rDestStrg)220 void StorageBase::copyStorageToStorage( StorageBase& rDestStrg )
221 {
222 OSL_ENSURE( rDestStrg.isStorage() && !rDestStrg.isReadOnly(), "StorageBase::copyToStorage - invalid destination" );
223 if( rDestStrg.isStorage() && !rDestStrg.isReadOnly() )
224 {
225 ::std::vector< OUString > aElements;
226 getElementNames( aElements );
227 for (auto const& elem : aElements)
228 copyToStorage(rDestStrg, elem);
229 }
230 }
231
commit()232 void StorageBase::commit()
233 {
234 OSL_ENSURE( !mbReadOnly, "StorageBase::commit - cannot commit in read-only mode" );
235 if( !mbReadOnly )
236 {
237 // commit all open substorages
238 maSubStorages.forEachMem( &StorageBase::commit );
239 // commit this storage
240 implCommit();
241 }
242 }
243
244 // private --------------------------------------------------------------------
245
getSubStorage(const OUString & rElementName,bool bCreateMissing)246 StorageRef StorageBase::getSubStorage( const OUString& rElementName, bool bCreateMissing )
247 {
248 StorageRef& rxSubStrg = maSubStorages[ rElementName ];
249 if( !rxSubStrg )
250 rxSubStrg = implOpenSubStorage( rElementName, bCreateMissing );
251 return rxSubStrg;
252 }
253
254 } // namespace oox
255
256 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
257