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