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