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 // MARKER(update_precomp.py): autogen include statement, do not remove
23 //This file is about the conversion of the UOF v2.0 and ODF document format
24 #include "precompiled_filter.hxx"
25
26
27 #include "uof2storage.hxx"
28
29 #include <com/sun/star/io/XInputStream.hpp>
30 #include <com/sun/star/uno/Exception.hpp>
31 #include <rtl/ustrbuf.hxx>
32 #include <com/sun/star/io/XOutputStream.hpp>
33 #include <com/sun/star/io/XStream.hpp>
34 #include <comphelper/storagehelper.hxx>
35 #include <com/sun/star/container/NoSuchElementException.hpp>
36 #include <com/sun/star/embed/XTransactedObject.hpp>
37
38 namespace XSLT{
39
40 namespace{
41
lclSplitFirstElement(::rtl::OUString & orElement,::rtl::OUString & orRemainder,const::rtl::OUString & rFullName)42 void lclSplitFirstElement( ::rtl::OUString& orElement, ::rtl::OUString& orRemainder, const ::rtl::OUString& rFullName )
43 {
44 sal_Int32 nSlashPos = rFullName.indexOf('/');
45 if((0 <= nSlashPos ) && (nSlashPos < rFullName.getLength()))
46 {
47 orElement = rFullName.copy(0, nSlashPos);
48 orRemainder = rFullName.copy(nSlashPos+1);
49 }
50 else
51 {
52 orElement = rFullName;
53 }
54 }
55
56 }
57
StorageBase(const::com::sun::star::uno::Reference<::com::sun::star::io::XInputStream> & rxInStream,bool bBaseStreamAccess)58 StorageBase::StorageBase( const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& rxInStream,
59 bool bBaseStreamAccess )
60 : m_xInStream(rxInStream)
61 , m_bBaseStreamAccess(bBaseStreamAccess)
62 , m_bReadOnly(true)
63 {
64 OSL_ENSURE(m_xInStream.is(), "StorageBase::StorageBase - missing base input stream");
65 }
66
StorageBase(const::com::sun::star::uno::Reference<::com::sun::star::io::XStream> & rxOutStream,bool bBaseStreamAccess)67 StorageBase::StorageBase( const ::com::sun::star::uno::Reference< ::com::sun::star::io::XStream >& rxOutStream, bool bBaseStreamAccess )
68 : m_xOutStream(rxOutStream)
69 , m_bBaseStreamAccess(bBaseStreamAccess)
70 , m_bReadOnly(false)
71 {
72 OSL_ENSURE(m_xOutStream.is(), "StorageBase::StorageBase - missing base output stream");
73 }
74
StorageBase(const StorageBase & rParentStorage,const::rtl::OUString & rStorageName,bool bReadOnly)75 StorageBase::StorageBase( const StorageBase& rParentStorage, const ::rtl::OUString& rStorageName, bool bReadOnly )
76 : m_aParentPath(rParentStorage.getPath())
77 , m_aStorageName(rStorageName)
78 , m_bBaseStreamAccess(false)
79 , m_bReadOnly(bReadOnly)
80 {
81 }
82
~StorageBase()83 StorageBase::~StorageBase()
84 {
85 }
86
isStorage() const87 bool StorageBase::isStorage() const
88 {
89 return implIsStorage();
90 }
91
isRootStorage() const92 bool StorageBase::isRootStorage() const
93 {
94 return implIsStorage() && (m_aStorageName.getLength() == 0);
95 }
96
isReadOnly() const97 bool StorageBase::isReadOnly() const
98 {
99 return m_bReadOnly;
100 }
101
getXStorage() const102 ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage > StorageBase::getXStorage() const
103 {
104 return implGetXStorage();
105 }
106
getName() const107 const ::rtl::OUString& StorageBase::getName() const
108 {
109 return m_aStorageName;
110 }
111
getPath() const112 ::rtl::OUString StorageBase::getPath() const
113 {
114 ::rtl::OUStringBuffer aBuffer(m_aParentPath);
115 if(aBuffer.getLength() > 0)
116 {
117 aBuffer.append(sal_Unicode('/'));
118 }
119
120 aBuffer.append(m_aStorageName);
121 return aBuffer.makeStringAndClear();
122 }
123
getElementNames(::std::vector<::rtl::OUString> & orElementNames) const124 void StorageBase::getElementNames( ::std::vector< ::rtl::OUString >& orElementNames ) const
125 {
126 orElementNames.clear();
127 implGetElementNames(orElementNames);
128 }
129
openSubStorage(const::rtl::OUString & rStorageName,bool bCreatedMissing)130 XSLT::StorageRef StorageBase::openSubStorage( const ::rtl::OUString& rStorageName, bool bCreatedMissing )
131 {
132 StorageRef xSubStorage;
133 OSL_ENSURE(!bCreatedMissing || !m_bReadOnly, "StorageBase::openSubStorage - can not create substorage in read-only mode");
134 if(!bCreatedMissing || !m_bReadOnly)
135 {
136 ::rtl::OUString aElement, aRemainder;
137 lclSplitFirstElement(aElement, aRemainder, rStorageName);
138 if(aElement.getLength() > 0)
139 xSubStorage = getSubStorage(aElement, bCreatedMissing);
140 if(xSubStorage.get() && (aRemainder.getLength() > 0))
141 xSubStorage = xSubStorage->openSubStorage(aRemainder, bCreatedMissing);
142 }
143
144 return xSubStorage;
145 }
146
openInputStream(const::rtl::OUString & rStreamName)147 ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > StorageBase::openInputStream( const ::rtl::OUString& rStreamName )
148 {
149 ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > xInStream;
150 ::rtl::OUString aElement, aRemainder;
151 lclSplitFirstElement(aElement, aRemainder, rStreamName);
152 if(aElement.getLength() > 0)
153 {
154 if(aRemainder.getLength() > 0)
155 {
156 StorageRef xSubStorage = getSubStorage(aElement, false);
157 if(xSubStorage.get())
158 xInStream = xSubStorage->openInputStream(aRemainder);
159 }
160 else
161 {
162 xInStream = implOpenInputStream(aElement);
163 }
164 }
165 else if(m_bBaseStreamAccess)
166 {
167 xInStream = m_xInStream;
168 }
169
170 return xInStream;
171 }
172
openOutputStream(const::rtl::OUString & rStreamName)173 ::com::sun::star::uno::Reference< ::com::sun::star::io::XOutputStream > StorageBase::openOutputStream( const ::rtl::OUString& rStreamName )
174 {
175 ::com::sun::star::uno::Reference< ::com::sun::star::io::XOutputStream > xOutStream;
176 OSL_ENSURE(!m_bReadOnly, "StorageBase::openOutputStream - can not create output stream in read-only mode");
177 if(!m_bReadOnly)
178 {
179 ::rtl::OUString aElement, aRemainder;
180 lclSplitFirstElement(aElement, aRemainder, rStreamName);
181 if(aElement.getLength() > 0)
182 {
183 if(aRemainder.getLength() > 0)
184 {
185 StorageRef xSubStorage = getSubStorage(aElement, true);
186 if(xSubStorage.get())
187 xOutStream = xSubStorage->openOutputStream(aRemainder);
188 }
189 else
190 {
191 xOutStream = implOpenOutputStream(aElement);
192 }
193 }
194 else if(m_bBaseStreamAccess)
195 {
196 xOutStream = m_xOutStream->getOutputStream();
197 }
198 }
199
200 return xOutStream;
201 }
202
copyToStorage(StorageBase & rDestStrg,const::rtl::OUString & rElementName)203 void StorageBase::copyToStorage( StorageBase& rDestStrg, const ::rtl::OUString& rElementName )
204 {
205 OSL_ENSURE(rDestStrg.isStorage() && !rDestStrg.isReadOnly(), "StorageBase::copyToStorage - invalid destination");
206 OSL_ENSURE(rElementName.getLength() > 0, "StorageBase::copyToStorage - invalid element name");
207 if(rDestStrg.isStorage() && !rDestStrg.isReadOnly() && (rElementName.getLength() > 0))
208 {
209 StorageRef xSubStrg = openSubStorage(rElementName, false);
210 if(xSubStrg.get())
211 {
212 StorageRef xDestSubStrg = rDestStrg.openSubStorage(rElementName, true);
213 if(xDestSubStrg.get())
214 xSubStrg->copyStorageToStorage(*xDestSubStrg);
215 }
216 else
217 {
218 ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > xInStrm = openInputStream(rElementName);
219 if(xInStrm.get())
220 {
221 ::com::sun::star::uno::Reference< ::com::sun::star::io::XOutputStream > xOutStm = rDestStrg.openOutputStream(rElementName);
222 if(xOutStm.is())
223 {
224 /*BinaryXInputStream aInStrm(xInStrm, true);
225 BinaryXOutputStream aOutStrm(xOutStm, true);
226 aInStrm.copyToStream(aOutStrm);*/
227 }
228 }
229 }
230 }
231 }
232
copyStorageToStorage(StorageBase & rDestStrg)233 void StorageBase::copyStorageToStorage( StorageBase& rDestStrg )
234 {
235 OSL_ENSURE(rDestStrg.isStorage() && !rDestStrg.isReadOnly(), "StorageBase::copyStorageToStorage - invalid destination");
236 if(rDestStrg.isStorage() && !rDestStrg.isReadOnly())
237 {
238 ::std::vector< ::rtl::OUString > aElements;
239 getElementNames(aElements);
240 for( ::std::vector< ::rtl::OUString >::iterator aIter = aElements.begin();
241 aIter != aElements.end(); ++aIter)
242 copyToStorage(rDestStrg, *aIter);
243 }
244 }
245
commit()246 void StorageBase::commit()
247 {
248 OSL_ENSURE(!m_bReadOnly, "StorageBase::commit - can not commit in read-only mode");
249 if(!m_bReadOnly)
250 {
251 m_aSubStorages.forEachMem(&StorageBase::commit);
252 implCommit();
253 }
254 }
255
getSubStorage(const::rtl::OUString & rElementName,bool bCreateMissing)256 XSLT::StorageRef StorageBase::getSubStorage( const ::rtl::OUString& rElementName, bool bCreateMissing )
257 {
258 StorageRef& rxSubStrg = m_aSubStorages[rElementName];
259 if(!rxSubStrg)
260 rxSubStrg = implOpenSubStorage(rElementName, bCreateMissing);
261 return rxSubStrg;
262 }
263
ZipStorage(const::com::sun::star::uno::Reference<::com::sun::star::lang::XMultiServiceFactory> & rxFactory,const::com::sun::star::uno::Reference<::com::sun::star::io::XInputStream> & rxInStream)264 ZipStorage::ZipStorage( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& rxFactory, const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& rxInStream )
265 : StorageBase(rxInStream, false)
266 {
267 OSL_ENSURE(rxFactory.is(), "ZipStorage::ZipStorage - missing service factory");
268 //create base storage object
269 try
270 {
271 m_xStorage = ::comphelper::OStorageHelper::GetStorageOfFormatFromInputStream(
272 ZIP_STORAGE_FORMAT_STRING, rxInStream, rxFactory, sal_True);
273 }
274 catch( ::com::sun::star::uno::Exception&)
275 {
276 }
277 }
278
ZipStorage(const::com::sun::star::uno::Reference<::com::sun::star::lang::XMultiServiceFactory> & rxFactory,const::com::sun::star::uno::Reference<::com::sun::star::io::XStream> & rxStream)279 ZipStorage::ZipStorage( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& rxFactory, const ::com::sun::star::uno::Reference< ::com::sun::star::io::XStream >& rxStream )
280 : StorageBase(rxStream, false)
281 {
282 OSL_ENSURE(rxFactory.is(), "ZipStorage::ZipStorage - missing service factory");
283 try
284 {
285 using namespace ::com::sun::star::embed::ElementModes;
286 m_xStorage = ::comphelper::OStorageHelper::GetStorageOfFormatFromStream(
287 ZIP_STORAGE_FORMAT_STRING, rxStream, READWRITE | TRUNCATE, rxFactory, sal_True);
288 }
289 catch( ::com::sun::star::uno::Exception& )
290 {
291 OSL_ENSURE(false, "ZipStorage::ZipStorage - can not open output storage");
292 }
293 }
294
ZipStorage(const ZipStorage & rParentStorage,const::com::sun::star::uno::Reference<::com::sun::star::embed::XStorage> & rxStorage,const::rtl::OUString & rElementName)295 ZipStorage::ZipStorage( const ZipStorage& rParentStorage, const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& rxStorage, const ::rtl::OUString& rElementName )
296 : StorageBase(rParentStorage, rElementName, rParentStorage.isReadOnly())
297 , m_xStorage(rxStorage)
298 {
299 OSL_ENSURE(m_xStorage.is(), "ZipStorage::ZipStorage - missing storage");
300 }
301
~ZipStorage()302 ZipStorage::~ZipStorage()
303 {
304
305 }
306
implIsStorage() const307 bool ZipStorage::implIsStorage() const
308 {
309 return m_xStorage.is();
310 }
311
implGetXStorage() const312 ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage > ZipStorage::implGetXStorage() const
313 {
314 return m_xStorage;
315 }
316
implGetElementNames(::std::vector<::rtl::OUString> & orElementNames) const317 void ZipStorage::implGetElementNames( ::std::vector< ::rtl::OUString >& orElementNames ) const
318 {
319 ::com::sun::star::uno::Sequence< ::rtl::OUString > aNames;
320 if(m_xStorage.is())
321 {
322 try
323 {
324 aNames = m_xStorage->getElementNames();
325 if(aNames.getLength() > 0)
326 orElementNames.insert(orElementNames.end(), aNames.getConstArray(), aNames.getConstArray()+aNames.getLength());
327 }
328 catch( ::com::sun::star::uno::Exception& )
329 {
330 }
331 }
332 }
333
implOpenSubStorage(const::rtl::OUString & rElementName,bool bCreatedMissing)334 XSLT::StorageRef ZipStorage::implOpenSubStorage( const ::rtl::OUString& rElementName, bool bCreatedMissing )
335 {
336 ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage > xSubXStorage;
337 bool bMissing = false;
338 if(m_xStorage.is())
339 {
340 try
341 {
342 if(m_xStorage->isStorageElement(rElementName))
343 {
344 xSubXStorage = m_xStorage->openStorageElement(rElementName, ::com::sun::star::embed::ElementModes::READ);
345 }
346 }
347 catch( ::com::sun::star::container::NoSuchElementException& )
348 {
349 bMissing = true;
350 }
351 catch( ::com::sun::star::uno::Exception& )
352 {
353 }
354 }
355
356 if(bMissing && bCreatedMissing)
357 {
358 try
359 {
360 xSubXStorage = m_xStorage->openStorageElement(rElementName, ::com::sun::star::embed::ElementModes::READWRITE);
361 }
362 catch( ::com::sun::star::uno::Exception& )
363 {
364 }
365 }
366
367 StorageRef xSubStorage;
368 if(xSubXStorage.is())
369 xSubStorage.reset(new ZipStorage( *this, xSubXStorage, rElementName ));
370
371 return xSubStorage;
372 }
373
implOpenInputStream(const::rtl::OUString & rElementName)374 ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > ZipStorage::implOpenInputStream( const ::rtl::OUString& rElementName )
375 {
376 ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > xInStream;
377 if(m_xStorage.is())
378 {
379 try
380 {
381 xInStream.set(m_xStorage->openStreamElement(
382 rElementName, ::com::sun::star::embed::ElementModes::READ), ::com::sun::star::uno::UNO_QUERY);
383 }
384 catch( ::com::sun::star::uno::Exception& )
385 {
386 }
387 }
388
389 return xInStream;
390 }
391
implOpenOutputStream(const::rtl::OUString & rElementName)392 ::com::sun::star::uno::Reference< ::com::sun::star::io::XOutputStream > ZipStorage::implOpenOutputStream( const ::rtl::OUString& rElementName )
393 {
394 ::com::sun::star::uno::Reference< ::com::sun::star::io::XOutputStream > xOutStream;
395 if(m_xStorage.is())
396 {
397 try
398 {
399 xOutStream.set(m_xStorage->openStreamElement(
400 rElementName, ::com::sun::star::embed::ElementModes::READWRITE), ::com::sun::star::uno::UNO_QUERY);
401 }
402 catch( ::com::sun::star::uno::Exception& )
403 {
404 }
405 }
406
407 return xOutStream;
408 }
409
implCommit() const410 void ZipStorage::implCommit() const
411 {
412 try
413 {
414 ::com::sun::star::uno::Reference< ::com::sun::star::embed::XTransactedObject > (m_xStorage,
415 ::com::sun::star::uno::UNO_QUERY_THROW)->commit();
416 }
417 catch( ::com::sun::star::uno::Exception& )
418 {
419 }
420 }
421
422
UOF2Storage(const::com::sun::star::uno::Reference<::com::sun::star::lang::XMultiServiceFactory> & rxFactory,const::com::sun::star::uno::Reference<::com::sun::star::io::XInputStream> & rxInStream)423 UOF2Storage::UOF2Storage( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& rxFactory,
424 const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& rxInStream )
425 : m_pMainStorage(new ZipStorage(rxFactory, rxInStream))
426 {
427 }
428
UOF2Storage(const::com::sun::star::uno::Reference<::com::sun::star::lang::XMultiServiceFactory> & rxFactory,const::com::sun::star::uno::Reference<::com::sun::star::io::XStream> & rxOutStream)429 UOF2Storage::UOF2Storage( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& rxFactory,
430 const ::com::sun::star::uno::Reference< ::com::sun::star::io::XStream >& rxOutStream )
431 : m_pMainStorage(new ZipStorage(rxFactory, rxOutStream))
432 {
433 }
434
~UOF2Storage()435 UOF2Storage::~UOF2Storage()
436 {
437 }
438
getMetaInputStream() const439 ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > UOF2Storage::getMetaInputStream() const
440 {
441 return m_pMainStorage->openInputStream(METAELEMNAME);
442 }
443
getMetaOutputStream(bool)444 ::com::sun::star::uno::Reference< ::com::sun::star::io::XOutputStream > UOF2Storage::getMetaOutputStream( bool /*bMissingCreate*/ )
445 {
446 return m_pMainStorage->openOutputStream(METAELEMNAME);
447 }
448
isValidUOF2Doc() const449 bool UOF2Storage::isValidUOF2Doc() const
450 {
451 if(!m_pMainStorage->isStorage())
452 return false;
453
454 return ((getMetaInputStream().is())
455 && (m_pMainStorage->openInputStream(UOFELEMNAME).is())
456 && (m_pMainStorage->openInputStream(CONTENTELEMNAME).is()));
457 }
458
459 }
460