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