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