Line data Source code
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 <com/sun/star/embed/ElementModes.hpp>
21 : #include <com/sun/star/embed/XEncryptionProtectedSource2.hpp>
22 : #include <com/sun/star/embed/XStorage.hpp>
23 : #include <com/sun/star/embed/XTransactedObject.hpp>
24 : #include <com/sun/star/embed/StorageFactory.hpp>
25 : #include <com/sun/star/embed/FileSystemStorageFactory.hpp>
26 : #include <com/sun/star/lang/XSingleServiceFactory.hpp>
27 : #include <com/sun/star/ucb/SimpleFileAccess.hpp>
28 : #include <com/sun/star/beans/XPropertySet.hpp>
29 : #include <com/sun/star/beans/PropertyValue.hpp>
30 : #include <com/sun/star/beans/NamedValue.hpp>
31 : #include <com/sun/star/beans/IllegalTypeException.hpp>
32 : #include <com/sun/star/xml/crypto/NSSInitializer.hpp>
33 : #include <com/sun/star/xml/crypto/XDigestContext.hpp>
34 : #include <com/sun/star/xml/crypto/XDigestContextSupplier.hpp>
35 : #include <com/sun/star/xml/crypto/DigestID.hpp>
36 :
37 : #include <vector>
38 : #include <rtl/digest.h>
39 :
40 : #include <ucbhelper/content.hxx>
41 :
42 : #include <comphelper/fileformat.h>
43 : #include <comphelper/processfactory.hxx>
44 : #include <comphelper/documentconstants.hxx>
45 :
46 : #include <comphelper/storagehelper.hxx>
47 :
48 :
49 : using namespace ::com::sun::star;
50 :
51 : namespace comphelper {
52 :
53 :
54 0 : uno::Reference< lang::XSingleServiceFactory > OStorageHelper::GetStorageFactory(
55 : const uno::Reference< uno::XComponentContext >& rxContext )
56 : throw ( uno::Exception )
57 : {
58 0 : uno::Reference< uno::XComponentContext> xContext = rxContext.is() ? rxContext : ::comphelper::getProcessComponentContext();
59 :
60 0 : return embed::StorageFactory::create( xContext );
61 : }
62 :
63 :
64 0 : uno::Reference< lang::XSingleServiceFactory > OStorageHelper::GetFileSystemStorageFactory(
65 : const uno::Reference< uno::XComponentContext >& rxContext )
66 : throw ( uno::Exception )
67 : {
68 0 : uno::Reference< uno::XComponentContext> xContext = rxContext.is() ? rxContext : ::comphelper::getProcessComponentContext();
69 :
70 0 : return embed::FileSystemStorageFactory::create(rxContext);
71 : }
72 :
73 :
74 0 : uno::Reference< embed::XStorage > OStorageHelper::GetTemporaryStorage(
75 : const uno::Reference< uno::XComponentContext >& rxContext )
76 : throw ( uno::Exception )
77 : {
78 0 : uno::Reference< embed::XStorage > xTempStorage( GetStorageFactory( rxContext )->createInstance(),
79 0 : uno::UNO_QUERY );
80 0 : if ( !xTempStorage.is() )
81 0 : throw uno::RuntimeException();
82 :
83 0 : return xTempStorage;
84 : }
85 :
86 :
87 0 : uno::Reference< embed::XStorage > OStorageHelper::GetStorageFromURL(
88 : const OUString& aURL,
89 : sal_Int32 nStorageMode,
90 : const uno::Reference< uno::XComponentContext >& rxContext )
91 : throw ( uno::Exception )
92 : {
93 0 : uno::Sequence< uno::Any > aArgs( 2 );
94 0 : aArgs[0] <<= aURL;
95 0 : aArgs[1] <<= nStorageMode;
96 :
97 0 : uno::Reference< embed::XStorage > xTempStorage( GetStorageFactory( rxContext )->createInstanceWithArguments( aArgs ),
98 0 : uno::UNO_QUERY );
99 0 : if ( !xTempStorage.is() )
100 0 : throw uno::RuntimeException();
101 :
102 0 : return xTempStorage;
103 : }
104 :
105 :
106 0 : uno::Reference< embed::XStorage > OStorageHelper::GetStorageFromURL2(
107 : const OUString& aURL,
108 : sal_Int32 nStorageMode,
109 : const uno::Reference< uno::XComponentContext >& rxContext )
110 : throw ( uno::Exception )
111 : {
112 0 : uno::Sequence< uno::Any > aArgs( 2 );
113 0 : aArgs[0] <<= aURL;
114 0 : aArgs[1] <<= nStorageMode;
115 :
116 0 : uno::Reference< lang::XSingleServiceFactory > xFact;
117 : try {
118 : ::ucbhelper::Content aCntnt( aURL,
119 : uno::Reference< ::com::sun::star::ucb::XCommandEnvironment > (),
120 0 : getProcessComponentContext() );
121 0 : if (aCntnt.isDocument()) {
122 0 : xFact = GetStorageFactory( rxContext );
123 : } else {
124 0 : xFact = GetFileSystemStorageFactory( rxContext );
125 0 : }
126 0 : } catch (uno::Exception &) { }
127 :
128 0 : if (!xFact.is()) throw uno::RuntimeException();
129 :
130 : uno::Reference< embed::XStorage > xTempStorage(
131 0 : xFact->createInstanceWithArguments( aArgs ), uno::UNO_QUERY );
132 0 : if ( !xTempStorage.is() )
133 0 : throw uno::RuntimeException();
134 :
135 0 : return xTempStorage;
136 : }
137 :
138 :
139 0 : uno::Reference< embed::XStorage > OStorageHelper::GetStorageFromInputStream(
140 : const uno::Reference < io::XInputStream >& xStream,
141 : const uno::Reference< uno::XComponentContext >& rxContext )
142 : throw ( uno::Exception )
143 : {
144 0 : uno::Sequence< uno::Any > aArgs( 2 );
145 0 : aArgs[0] <<= xStream;
146 0 : aArgs[1] <<= embed::ElementModes::READ;
147 :
148 0 : uno::Reference< embed::XStorage > xTempStorage( GetStorageFactory( rxContext )->createInstanceWithArguments( aArgs ),
149 0 : uno::UNO_QUERY );
150 0 : if ( !xTempStorage.is() )
151 0 : throw uno::RuntimeException();
152 :
153 0 : return xTempStorage;
154 : }
155 :
156 :
157 0 : uno::Reference< embed::XStorage > OStorageHelper::GetStorageFromStream(
158 : const uno::Reference < io::XStream >& xStream,
159 : sal_Int32 nStorageMode,
160 : const uno::Reference< uno::XComponentContext >& rxContext )
161 : throw ( uno::Exception )
162 : {
163 0 : uno::Sequence< uno::Any > aArgs( 2 );
164 0 : aArgs[0] <<= xStream;
165 0 : aArgs[1] <<= nStorageMode;
166 :
167 0 : uno::Reference< embed::XStorage > xTempStorage( GetStorageFactory( rxContext )->createInstanceWithArguments( aArgs ),
168 0 : uno::UNO_QUERY );
169 0 : if ( !xTempStorage.is() )
170 0 : throw uno::RuntimeException();
171 :
172 0 : return xTempStorage;
173 : }
174 :
175 :
176 0 : void OStorageHelper::CopyInputToOutput(
177 : const uno::Reference< io::XInputStream >& xInput,
178 : const uno::Reference< io::XOutputStream >& xOutput )
179 : throw ( uno::Exception )
180 : {
181 : static const sal_Int32 nConstBufferSize = 32000;
182 :
183 : sal_Int32 nRead;
184 0 : uno::Sequence < sal_Int8 > aSequence ( nConstBufferSize );
185 :
186 0 : do
187 : {
188 0 : nRead = xInput->readBytes ( aSequence, nConstBufferSize );
189 0 : if ( nRead < nConstBufferSize )
190 : {
191 0 : uno::Sequence < sal_Int8 > aTempBuf ( aSequence.getConstArray(), nRead );
192 0 : xOutput->writeBytes ( aTempBuf );
193 : }
194 : else
195 0 : xOutput->writeBytes ( aSequence );
196 : }
197 0 : while ( nRead == nConstBufferSize );
198 0 : }
199 :
200 :
201 0 : uno::Reference< io::XInputStream > OStorageHelper::GetInputStreamFromURL(
202 : const OUString& aURL,
203 : const uno::Reference< uno::XComponentContext >& context )
204 : throw ( uno::Exception )
205 : {
206 0 : uno::Reference< io::XInputStream > xInputStream = ucb::SimpleFileAccess::create(context)->openFileRead( aURL );
207 0 : if ( !xInputStream.is() )
208 0 : throw uno::RuntimeException();
209 :
210 0 : return xInputStream;
211 : }
212 :
213 :
214 0 : void OStorageHelper::SetCommonStorageEncryptionData(
215 : const uno::Reference< embed::XStorage >& xStorage,
216 : const uno::Sequence< beans::NamedValue >& aEncryptionData )
217 : throw ( uno::Exception )
218 : {
219 0 : uno::Reference< embed::XEncryptionProtectedSource2 > xEncrSet( xStorage, uno::UNO_QUERY );
220 0 : if ( !xEncrSet.is() )
221 0 : throw io::IOException(); // TODO
222 :
223 0 : xEncrSet->setEncryptionData( aEncryptionData );
224 0 : }
225 :
226 :
227 0 : sal_Int32 OStorageHelper::GetXStorageFormat(
228 : const uno::Reference< embed::XStorage >& xStorage )
229 : throw ( uno::Exception )
230 : {
231 0 : uno::Reference< beans::XPropertySet > xStorProps( xStorage, uno::UNO_QUERY_THROW );
232 :
233 0 : OUString aMediaType;
234 0 : xStorProps->getPropertyValue("MediaType") >>= aMediaType;
235 :
236 0 : sal_Int32 nResult = 0;
237 :
238 : // TODO/LATER: the filter configuration could be used to detect it later, or batter a special service
239 0 : if (
240 0 : aMediaType.equalsIgnoreAsciiCase(MIMETYPE_VND_SUN_XML_WRITER_ASCII ) ||
241 0 : aMediaType.equalsIgnoreAsciiCase(MIMETYPE_VND_SUN_XML_WRITER_WEB_ASCII ) ||
242 0 : aMediaType.equalsIgnoreAsciiCase(MIMETYPE_VND_SUN_XML_WRITER_GLOBAL_ASCII) ||
243 0 : aMediaType.equalsIgnoreAsciiCase(MIMETYPE_VND_SUN_XML_DRAW_ASCII ) ||
244 0 : aMediaType.equalsIgnoreAsciiCase(MIMETYPE_VND_SUN_XML_IMPRESS_ASCII ) ||
245 0 : aMediaType.equalsIgnoreAsciiCase(MIMETYPE_VND_SUN_XML_CALC_ASCII ) ||
246 0 : aMediaType.equalsIgnoreAsciiCase(MIMETYPE_VND_SUN_XML_CHART_ASCII ) ||
247 0 : aMediaType.equalsIgnoreAsciiCase(MIMETYPE_VND_SUN_XML_MATH_ASCII )
248 : )
249 : {
250 0 : nResult = SOFFICE_FILEFORMAT_60;
251 : }
252 0 : else if (
253 0 : aMediaType.equalsIgnoreAsciiCase(MIMETYPE_OASIS_OPENDOCUMENT_TEXT_ASCII ) ||
254 0 : aMediaType.equalsIgnoreAsciiCase(MIMETYPE_OASIS_OPENDOCUMENT_TEXT_WEB_ASCII ) ||
255 0 : aMediaType.equalsIgnoreAsciiCase(MIMETYPE_OASIS_OPENDOCUMENT_TEXT_GLOBAL_ASCII ) ||
256 0 : aMediaType.equalsIgnoreAsciiCase(MIMETYPE_OASIS_OPENDOCUMENT_DRAWING_ASCII ) ||
257 0 : aMediaType.equalsIgnoreAsciiCase(MIMETYPE_OASIS_OPENDOCUMENT_PRESENTATION_ASCII) ||
258 0 : aMediaType.equalsIgnoreAsciiCase(MIMETYPE_OASIS_OPENDOCUMENT_SPREADSHEET_ASCII ) ||
259 0 : aMediaType.equalsIgnoreAsciiCase(MIMETYPE_OASIS_OPENDOCUMENT_CHART_ASCII ) ||
260 0 : aMediaType.equalsIgnoreAsciiCase(MIMETYPE_OASIS_OPENDOCUMENT_FORMULA_ASCII ) ||
261 0 : aMediaType.equalsIgnoreAsciiCase(MIMETYPE_OASIS_OPENDOCUMENT_DATABASE_ASCII ) ||
262 0 : aMediaType.equalsIgnoreAsciiCase(MIMETYPE_OASIS_OPENDOCUMENT_REPORT_ASCII ) ||
263 0 : aMediaType.equalsIgnoreAsciiCase(MIMETYPE_OASIS_OPENDOCUMENT_REPORT_CHART_ASCII ) ||
264 0 : aMediaType.equalsIgnoreAsciiCase(MIMETYPE_OASIS_OPENDOCUMENT_TEXT_TEMPLATE_ASCII ) ||
265 0 : aMediaType.equalsIgnoreAsciiCase(MIMETYPE_OASIS_OPENDOCUMENT_DRAWING_TEMPLATE_ASCII ) ||
266 0 : aMediaType.equalsIgnoreAsciiCase(MIMETYPE_OASIS_OPENDOCUMENT_PRESENTATION_TEMPLATE_ASCII) ||
267 0 : aMediaType.equalsIgnoreAsciiCase(MIMETYPE_OASIS_OPENDOCUMENT_SPREADSHEET_TEMPLATE_ASCII ) ||
268 0 : aMediaType.equalsIgnoreAsciiCase(MIMETYPE_OASIS_OPENDOCUMENT_CHART_TEMPLATE_ASCII ) ||
269 0 : aMediaType.equalsIgnoreAsciiCase(MIMETYPE_OASIS_OPENDOCUMENT_FORMULA_TEMPLATE_ASCII )
270 : )
271 : {
272 0 : nResult = SOFFICE_FILEFORMAT_8;
273 : }
274 : else
275 : {
276 : // the mediatype is not known
277 0 : throw beans::IllegalTypeException();
278 : }
279 :
280 0 : return nResult;
281 : }
282 :
283 :
284 0 : uno::Reference< embed::XStorage > OStorageHelper::GetStorageOfFormatFromURL(
285 : const OUString& aFormat,
286 : const OUString& aURL,
287 : sal_Int32 nStorageMode,
288 : const uno::Reference< uno::XComponentContext >& rxContext,
289 : bool bRepairStorage )
290 : throw ( uno::Exception )
291 : {
292 0 : uno::Sequence< beans::PropertyValue > aProps( 1 );
293 0 : aProps[0].Name = "StorageFormat";
294 0 : aProps[0].Value <<= aFormat;
295 0 : if ( bRepairStorage )
296 : {
297 0 : aProps.realloc( 2 );
298 0 : aProps[1].Name = "RepairPackage";
299 0 : aProps[1].Value <<= bRepairStorage;
300 : }
301 :
302 0 : uno::Sequence< uno::Any > aArgs( 3 );
303 0 : aArgs[0] <<= aURL;
304 0 : aArgs[1] <<= nStorageMode;
305 0 : aArgs[2] <<= aProps;
306 :
307 0 : uno::Reference< embed::XStorage > xTempStorage( GetStorageFactory( rxContext )->createInstanceWithArguments( aArgs ),
308 0 : uno::UNO_QUERY );
309 0 : if ( !xTempStorage.is() )
310 0 : throw uno::RuntimeException();
311 :
312 0 : return xTempStorage;
313 : }
314 :
315 :
316 0 : uno::Reference< embed::XStorage > OStorageHelper::GetStorageOfFormatFromInputStream(
317 : const OUString& aFormat,
318 : const uno::Reference < io::XInputStream >& xStream,
319 : const uno::Reference< uno::XComponentContext >& rxContext,
320 : bool bRepairStorage )
321 : throw ( uno::Exception )
322 : {
323 0 : uno::Sequence< beans::PropertyValue > aProps( 1 );
324 0 : aProps[0].Name = "StorageFormat";
325 0 : aProps[0].Value <<= aFormat;
326 0 : if ( bRepairStorage )
327 : {
328 0 : aProps.realloc( 2 );
329 0 : aProps[1].Name = "RepairPackage";
330 0 : aProps[1].Value <<= bRepairStorage;
331 : }
332 :
333 0 : uno::Sequence< uno::Any > aArgs( 3 );
334 0 : aArgs[0] <<= xStream;
335 0 : aArgs[1] <<= embed::ElementModes::READ;
336 0 : aArgs[2] <<= aProps;
337 :
338 0 : uno::Reference< embed::XStorage > xTempStorage( GetStorageFactory( rxContext )->createInstanceWithArguments( aArgs ),
339 0 : uno::UNO_QUERY );
340 0 : if ( !xTempStorage.is() )
341 0 : throw uno::RuntimeException();
342 :
343 0 : return xTempStorage;
344 : }
345 :
346 :
347 0 : uno::Reference< embed::XStorage > OStorageHelper::GetStorageOfFormatFromStream(
348 : const OUString& aFormat,
349 : const uno::Reference < io::XStream >& xStream,
350 : sal_Int32 nStorageMode,
351 : const uno::Reference< uno::XComponentContext >& rxContext,
352 : bool bRepairStorage )
353 : throw ( uno::Exception )
354 : {
355 0 : uno::Sequence< beans::PropertyValue > aProps( 1 );
356 0 : aProps[0].Name = "StorageFormat";
357 0 : aProps[0].Value <<= aFormat;
358 0 : if ( bRepairStorage )
359 : {
360 0 : aProps.realloc( 2 );
361 0 : aProps[1].Name = "RepairPackage";
362 0 : aProps[1].Value <<= bRepairStorage;
363 : }
364 :
365 0 : uno::Sequence< uno::Any > aArgs( 3 );
366 0 : aArgs[0] <<= xStream;
367 0 : aArgs[1] <<= nStorageMode;
368 0 : aArgs[2] <<= aProps;
369 :
370 0 : uno::Reference< embed::XStorage > xTempStorage( GetStorageFactory( rxContext )->createInstanceWithArguments( aArgs ),
371 0 : uno::UNO_QUERY );
372 0 : if ( !xTempStorage.is() )
373 0 : throw uno::RuntimeException();
374 :
375 0 : return xTempStorage;
376 : }
377 :
378 :
379 0 : uno::Sequence< beans::NamedValue > OStorageHelper::CreatePackageEncryptionData( const OUString& aPassword )
380 : {
381 : // TODO/LATER: Should not the method be part of DocPasswordHelper?
382 0 : uno::Sequence< beans::NamedValue > aEncryptionData;
383 0 : if ( !aPassword.isEmpty() )
384 : {
385 0 : sal_Int32 nSha1Ind = 0;
386 : // generate SHA256 start key
387 : try
388 : {
389 0 : uno::Reference< uno::XComponentContext > xContext = ::comphelper::getProcessComponentContext();
390 :
391 0 : uno::Reference< xml::crypto::XNSSInitializer > xDigestContextSupplier = xml::crypto::NSSInitializer::create(xContext);
392 0 : uno::Reference< xml::crypto::XDigestContext > xDigestContext( xDigestContextSupplier->getDigestContext( xml::crypto::DigestID::SHA256, uno::Sequence< beans::NamedValue >() ), uno::UNO_SET_THROW );
393 :
394 0 : OString aUTF8Password( OUStringToOString( aPassword, RTL_TEXTENCODING_UTF8 ) );
395 0 : xDigestContext->updateDigest( uno::Sequence< sal_Int8 >( reinterpret_cast< const sal_Int8* >( aUTF8Password.getStr() ), aUTF8Password.getLength() ) );
396 0 : uno::Sequence< sal_Int8 > aDigest = xDigestContext->finalizeDigestAndDispose();
397 :
398 0 : aEncryptionData.realloc( ++nSha1Ind );
399 0 : aEncryptionData[0].Name = PACKAGE_ENCRYPTIONDATA_SHA256UTF8;
400 0 : aEncryptionData[0].Value <<= aDigest;
401 : }
402 0 : catch ( uno::Exception& )
403 : {
404 : OSL_ENSURE( false, "Can not create SHA256 digest!" );
405 : }
406 :
407 : // MS_1252 encoding was used for SO60 document format password encoding,
408 : // this encoding supports only a minor subset of nonascii characters,
409 : // but for compatibility reasons it has to be used for old document formats
410 0 : aEncryptionData.realloc( nSha1Ind + 2 );
411 0 : aEncryptionData[nSha1Ind].Name = PACKAGE_ENCRYPTIONDATA_SHA1UTF8;
412 0 : aEncryptionData[nSha1Ind + 1].Name = PACKAGE_ENCRYPTIONDATA_SHA1MS1252;
413 :
414 0 : rtl_TextEncoding pEncoding[2] = { RTL_TEXTENCODING_UTF8, RTL_TEXTENCODING_MS_1252 };
415 :
416 0 : for ( sal_Int32 nInd = 0; nInd < 2; nInd++ )
417 : {
418 0 : OString aByteStrPass = OUStringToOString( aPassword, pEncoding[nInd] );
419 :
420 : sal_uInt8 pBuffer[RTL_DIGEST_LENGTH_SHA1];
421 0 : rtlDigestError nError = rtl_digest_SHA1( aByteStrPass.getStr(),
422 0 : aByteStrPass.getLength(),
423 : pBuffer,
424 0 : RTL_DIGEST_LENGTH_SHA1 );
425 :
426 0 : if ( nError != rtl_Digest_E_None )
427 : {
428 0 : aEncryptionData.realloc( nSha1Ind );
429 0 : break;
430 : }
431 :
432 0 : aEncryptionData[nSha1Ind+nInd].Value <<= uno::Sequence< sal_Int8 >( (sal_Int8*)pBuffer, RTL_DIGEST_LENGTH_SHA1 );
433 0 : }
434 : }
435 :
436 0 : return aEncryptionData;
437 : }
438 :
439 :
440 0 : bool OStorageHelper::IsValidZipEntryFileName( const OUString& aName, bool bSlashAllowed )
441 : {
442 0 : return IsValidZipEntryFileName( aName.getStr(), aName.getLength(), bSlashAllowed );
443 : }
444 :
445 :
446 0 : bool OStorageHelper::IsValidZipEntryFileName(
447 : const sal_Unicode *pChar, sal_Int32 nLength, bool bSlashAllowed )
448 : {
449 0 : for ( sal_Int32 i = 0; i < nLength; i++ )
450 : {
451 0 : switch ( pChar[i] )
452 : {
453 : case '\\':
454 : case '?':
455 : case '<':
456 : case '>':
457 : case '\"':
458 : case '|':
459 : case ':':
460 0 : return false;
461 : case '/':
462 0 : if ( !bSlashAllowed )
463 0 : return false;
464 0 : break;
465 : default:
466 0 : if ( pChar[i] < 32 || (pChar[i] >= 0xD800 && pChar[i] <= 0xDFFF) )
467 0 : return false;
468 : }
469 : }
470 0 : return true;
471 : }
472 :
473 :
474 0 : bool OStorageHelper::PathHasSegment( const OUString& aPath, const OUString& aSegment )
475 : {
476 0 : bool bResult = false;
477 0 : const sal_Int32 nPathLen = aPath.getLength();
478 0 : const sal_Int32 nSegLen = aSegment.getLength();
479 :
480 0 : if ( !aSegment.isEmpty() && nPathLen >= nSegLen )
481 : {
482 0 : OUString aEndSegment( "/" );
483 0 : aEndSegment += aSegment;
484 :
485 0 : OUString aInternalSegment( aEndSegment );
486 0 : aInternalSegment += "/";
487 :
488 0 : if ( aPath.indexOf( aInternalSegment ) >= 0 )
489 0 : bResult = true;
490 :
491 0 : if ( !bResult && !aPath.compareTo( aSegment, nSegLen ) )
492 : {
493 0 : if ( nPathLen == nSegLen || aPath[nSegLen] == '/' )
494 0 : bResult = true;
495 : }
496 :
497 0 : if ( !bResult && nPathLen > nSegLen && aPath.copy( nPathLen - nSegLen - 1, nSegLen + 1 ) == aEndSegment )
498 0 : bResult = true;
499 : }
500 :
501 0 : return bResult;
502 : }
503 :
504 0 : class LifecycleProxy::Impl
505 : : public std::vector< uno::Reference< embed::XStorage > > {};
506 0 : LifecycleProxy::LifecycleProxy()
507 0 : : m_pBadness( new Impl() ) { }
508 0 : LifecycleProxy::~LifecycleProxy() { }
509 :
510 0 : void LifecycleProxy::commitStorages()
511 : {
512 0 : for (Impl::reverse_iterator iter = m_pBadness->rbegin();
513 0 : iter != m_pBadness->rend(); ++iter) // reverse order (outwards)
514 : {
515 0 : uno::Reference<embed::XTransactedObject> const xTransaction(*iter,
516 0 : uno::UNO_QUERY);
517 0 : if (xTransaction.is())
518 : {
519 0 : xTransaction->commit();
520 : }
521 0 : }
522 0 : }
523 :
524 0 : static void splitPath( std::vector<OUString> &rElems,
525 : const OUString& rPath )
526 : {
527 0 : for (sal_Int32 i = 0; i >= 0;)
528 0 : rElems.push_back( rPath.getToken( 0, '/', i ) );
529 0 : }
530 :
531 0 : static uno::Reference< embed::XStorage > LookupStorageAtPath(
532 : const uno::Reference< embed::XStorage > &xParentStorage,
533 : std::vector<OUString> &rElems, sal_uInt32 nOpenMode,
534 : LifecycleProxy &rNastiness )
535 : {
536 0 : uno::Reference< embed::XStorage > xStorage( xParentStorage );
537 0 : rNastiness.m_pBadness->push_back( xStorage );
538 0 : for( size_t i = 0; i < rElems.size() && xStorage.is(); i++ )
539 : {
540 0 : xStorage = xStorage->openStorageElement( rElems[i], nOpenMode );
541 0 : rNastiness.m_pBadness->push_back( xStorage );
542 : }
543 0 : return xStorage;
544 : }
545 :
546 0 : uno::Reference< embed::XStorage > OStorageHelper::GetStorageAtPath(
547 : const uno::Reference< embed::XStorage > &xStorage,
548 : const OUString& rPath, sal_uInt32 nOpenMode,
549 : LifecycleProxy &rNastiness )
550 : {
551 0 : std::vector<OUString> aElems;
552 0 : splitPath( aElems, rPath );
553 0 : return LookupStorageAtPath( xStorage, aElems, nOpenMode, rNastiness );
554 : }
555 :
556 0 : uno::Reference< io::XStream > OStorageHelper::GetStreamAtPath(
557 : const uno::Reference< embed::XStorage > &xParentStorage,
558 : const OUString& rPath, sal_uInt32 nOpenMode,
559 : LifecycleProxy &rNastiness )
560 : {
561 0 : std::vector<OUString> aElems;
562 0 : splitPath( aElems, rPath );
563 0 : OUString aName( aElems.back() );
564 0 : aElems.pop_back();
565 0 : sal_uInt32 nStorageMode = nOpenMode & ~embed::ElementModes::TRUNCATE;
566 : uno::Reference< embed::XStorage > xStorage(
567 : LookupStorageAtPath( xParentStorage, aElems, nStorageMode, rNastiness ),
568 0 : uno::UNO_QUERY_THROW );
569 0 : return xStorage->openStreamElement( aName, nOpenMode );
570 : }
571 :
572 0 : uno::Reference< io::XStream > OStorageHelper::GetStreamAtPackageURL(
573 : uno::Reference< embed::XStorage > const& xParentStorage,
574 : const OUString& rURL, sal_uInt32 const nOpenMode,
575 : LifecycleProxy & rNastiness)
576 : {
577 0 : OUString path;
578 0 : if (rURL.startsWithIgnoreAsciiCase("vnd.sun.star.Package:", &path))
579 : {
580 0 : return GetStreamAtPath(xParentStorage, path, nOpenMode, rNastiness);
581 : }
582 0 : return 0;
583 : }
584 :
585 : }
586 :
587 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|