1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_comphelper.hxx"
26 #include <com/sun/star/embed/ElementModes.hpp>
27 #include <com/sun/star/embed/XEncryptionProtectedSource2.hpp>
28 #include <com/sun/star/ucb/XSimpleFileAccess.hpp>
29 #include <com/sun/star/beans/XPropertySet.hpp>
30 #include <com/sun/star/beans/PropertyValue.hpp>
31 #include <com/sun/star/beans/NamedValue.hpp>
32 #include <com/sun/star/beans/IllegalTypeException.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 <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 uno::Reference< lang::XSingleServiceFactory > OStorageHelper::GetStorageFactory(
54 							const uno::Reference< lang::XMultiServiceFactory >& xSF )
55 		throw ( uno::Exception )
56 {
57 	uno::Reference< lang::XMultiServiceFactory > xFactory = xSF.is() ? xSF : ::comphelper::getProcessServiceFactory();
58 	if ( !xFactory.is() )
59 		throw uno::RuntimeException();
60 
61 	uno::Reference < lang::XSingleServiceFactory > xStorageFactory(
62 					xFactory->createInstance ( ::rtl::OUString::createFromAscii( "com.sun.star.embed.StorageFactory" ) ),
63 					uno::UNO_QUERY );
64 
65 	if ( !xStorageFactory.is() )
66 		throw uno::RuntimeException();
67 
68 	return xStorageFactory;
69 }
70 
71 // ----------------------------------------------------------------------
72 uno::Reference< lang::XSingleServiceFactory > OStorageHelper::GetFileSystemStorageFactory(
73 							const uno::Reference< lang::XMultiServiceFactory >& xSF )
74 		throw ( uno::Exception )
75 {
76 	uno::Reference< lang::XMultiServiceFactory > xFactory = xSF.is() ? xSF : ::comphelper::getProcessServiceFactory();
77 	if ( !xFactory.is() )
78 		throw uno::RuntimeException();
79 
80 	uno::Reference < lang::XSingleServiceFactory > xStorageFactory(
81 					xFactory->createInstance ( ::rtl::OUString::createFromAscii( "com.sun.star.embed.FileSystemStorageFactory" ) ),
82 					uno::UNO_QUERY );
83 
84 	if ( !xStorageFactory.is() )
85 		throw uno::RuntimeException();
86 
87 	return xStorageFactory;
88 }
89 
90 // ----------------------------------------------------------------------
91 uno::Reference< embed::XStorage > OStorageHelper::GetTemporaryStorage(
92 			const uno::Reference< lang::XMultiServiceFactory >& xFactory )
93 	throw ( uno::Exception )
94 {
95 	uno::Reference< embed::XStorage > xTempStorage( GetStorageFactory( xFactory )->createInstance(),
96 													uno::UNO_QUERY );
97 	if ( !xTempStorage.is() )
98 		throw uno::RuntimeException();
99 
100 	return xTempStorage;
101 }
102 
103 // ----------------------------------------------------------------------
104 uno::Reference< embed::XStorage > OStorageHelper::GetStorageFromURL(
105 			const ::rtl::OUString& aURL,
106 			sal_Int32 nStorageMode,
107 			const uno::Reference< lang::XMultiServiceFactory >& xFactory )
108 	throw ( uno::Exception )
109 {
110 	uno::Sequence< uno::Any > aArgs( 2 );
111 	aArgs[0] <<= aURL;
112 	aArgs[1] <<= nStorageMode;
113 
114 	uno::Reference< embed::XStorage > xTempStorage( GetStorageFactory( xFactory )->createInstanceWithArguments( aArgs ),
115 													uno::UNO_QUERY );
116 	if ( !xTempStorage.is() )
117 		throw uno::RuntimeException();
118 
119 	return xTempStorage;
120 }
121 
122 // ----------------------------------------------------------------------
123 uno::Reference< embed::XStorage > OStorageHelper::GetStorageFromURL2(
124 			const ::rtl::OUString& aURL,
125 			sal_Int32 nStorageMode,
126 			const uno::Reference< lang::XMultiServiceFactory >& xFactory )
127 	throw ( uno::Exception )
128 {
129 	uno::Sequence< uno::Any > aArgs( 2 );
130 	aArgs[0] <<= aURL;
131 	aArgs[1] <<= nStorageMode;
132 
133     uno::Reference< lang::XSingleServiceFactory > xFact;
134     try {
135         ::ucbhelper::Content aCntnt( aURL,
136             uno::Reference< ::com::sun::star::ucb::XCommandEnvironment > () );
137         if (aCntnt.isDocument()) {
138             xFact = GetStorageFactory( xFactory );
139         } else {
140             xFact = GetFileSystemStorageFactory( xFactory );
141         }
142     } catch (uno::Exception &) { }
143 
144     if (!xFact.is()) throw uno::RuntimeException();
145 
146 	uno::Reference< embed::XStorage > xTempStorage(
147         xFact->createInstanceWithArguments( aArgs ), uno::UNO_QUERY );
148 	if ( !xTempStorage.is() )
149 		throw uno::RuntimeException();
150 
151 	return xTempStorage;
152 }
153 
154 // ----------------------------------------------------------------------
155 uno::Reference< embed::XStorage > OStorageHelper::GetStorageFromInputStream(
156             const uno::Reference < io::XInputStream >& xStream,
157 			const uno::Reference< lang::XMultiServiceFactory >& xFactory )
158 		throw ( uno::Exception )
159 {
160 	uno::Sequence< uno::Any > aArgs( 2 );
161 	aArgs[0] <<= xStream;
162 	aArgs[1] <<= embed::ElementModes::READ;
163 
164 	uno::Reference< embed::XStorage > xTempStorage( GetStorageFactory( xFactory )->createInstanceWithArguments( aArgs ),
165 													uno::UNO_QUERY );
166 	if ( !xTempStorage.is() )
167 		throw uno::RuntimeException();
168 
169 	return xTempStorage;
170 }
171 
172 // ----------------------------------------------------------------------
173 uno::Reference< embed::XStorage > OStorageHelper::GetStorageFromStream(
174             const uno::Reference < io::XStream >& xStream,
175 			sal_Int32 nStorageMode,
176 			const uno::Reference< lang::XMultiServiceFactory >& xFactory )
177 		throw ( uno::Exception )
178 {
179 	uno::Sequence< uno::Any > aArgs( 2 );
180 	aArgs[0] <<= xStream;
181 	aArgs[1] <<= nStorageMode;
182 
183 	uno::Reference< embed::XStorage > xTempStorage( GetStorageFactory( xFactory )->createInstanceWithArguments( aArgs ),
184 													uno::UNO_QUERY );
185 	if ( !xTempStorage.is() )
186 		throw uno::RuntimeException();
187 
188 	return xTempStorage;
189 }
190 
191 // ----------------------------------------------------------------------
192 void OStorageHelper::CopyInputToOutput(
193 			const uno::Reference< io::XInputStream >& xInput,
194 			const uno::Reference< io::XOutputStream >& xOutput )
195 	throw ( uno::Exception )
196 {
197 	static const sal_Int32 nConstBufferSize = 32000;
198 
199 	sal_Int32 nRead;
200 	uno::Sequence < sal_Int8 > aSequence ( nConstBufferSize );
201 
202 	do
203 	{
204 		nRead = xInput->readBytes ( aSequence, nConstBufferSize );
205 		if ( nRead < nConstBufferSize )
206 		{
207 			uno::Sequence < sal_Int8 > aTempBuf ( aSequence.getConstArray(), nRead );
208 			xOutput->writeBytes ( aTempBuf );
209 		}
210 		else
211 			xOutput->writeBytes ( aSequence );
212 	}
213 	while ( nRead == nConstBufferSize );
214 }
215 
216 // ----------------------------------------------------------------------
217 uno::Reference< io::XInputStream > OStorageHelper::GetInputStreamFromURL(
218 			const ::rtl::OUString& aURL,
219 			const uno::Reference< lang::XMultiServiceFactory >& xSF )
220 	throw ( uno::Exception )
221 {
222 	uno::Reference< lang::XMultiServiceFactory > xFactory = xSF.is() ? xSF : ::comphelper::getProcessServiceFactory();
223 	if ( !xFactory.is() )
224 		throw uno::RuntimeException();
225 
226 	uno::Reference < ::com::sun::star::ucb::XSimpleFileAccess > xTempAccess(
227 			xFactory->createInstance ( ::rtl::OUString::createFromAscii( "com.sun.star.ucb.SimpleFileAccess" ) ),
228 			uno::UNO_QUERY );
229 
230 	if ( !xTempAccess.is() )
231 		throw uno::RuntimeException();
232 
233 	uno::Reference< io::XInputStream > xInputStream = xTempAccess->openFileRead( aURL );
234 	if ( !xInputStream.is() )
235 		throw uno::RuntimeException();
236 
237 	return xInputStream;
238 }
239 
240 // ----------------------------------------------------------------------
241 void OStorageHelper::SetCommonStorageEncryptionData(
242 			const uno::Reference< embed::XStorage >& xStorage,
243 			const uno::Sequence< beans::NamedValue >& aEncryptionData )
244 	throw ( uno::Exception )
245 {
246 	uno::Reference< embed::XEncryptionProtectedSource2 > xEncrSet( xStorage, uno::UNO_QUERY );
247 	if ( !xEncrSet.is() )
248 		throw io::IOException(); // TODO
249 
250 	xEncrSet->setEncryptionData( aEncryptionData );
251 }
252 
253 // ----------------------------------------------------------------------
254 sal_Int32 OStorageHelper::GetXStorageFormat(
255 			const uno::Reference< embed::XStorage >& xStorage )
256 		throw ( uno::Exception )
257 {
258 	uno::Reference< beans::XPropertySet > xStorProps( xStorage, uno::UNO_QUERY_THROW );
259 
260 	::rtl::OUString aMediaType;
261 	xStorProps->getPropertyValue( ::rtl::OUString::createFromAscii( "MediaType" ) ) >>= aMediaType;
262 
263 	sal_Int32 nResult = 0;
264 
265 	// TODO/LATER: the filter configuration could be used to detect it later, or batter a special service
266     if (
267         aMediaType.equalsIgnoreAsciiCaseAscii(MIMETYPE_VND_SUN_XML_WRITER_ASCII       ) ||
268         aMediaType.equalsIgnoreAsciiCaseAscii(MIMETYPE_VND_SUN_XML_WRITER_WEB_ASCII   ) ||
269         aMediaType.equalsIgnoreAsciiCaseAscii(MIMETYPE_VND_SUN_XML_WRITER_GLOBAL_ASCII) ||
270         aMediaType.equalsIgnoreAsciiCaseAscii(MIMETYPE_VND_SUN_XML_DRAW_ASCII         ) ||
271         aMediaType.equalsIgnoreAsciiCaseAscii(MIMETYPE_VND_SUN_XML_IMPRESS_ASCII      ) ||
272         aMediaType.equalsIgnoreAsciiCaseAscii(MIMETYPE_VND_SUN_XML_CALC_ASCII         ) ||
273         aMediaType.equalsIgnoreAsciiCaseAscii(MIMETYPE_VND_SUN_XML_CHART_ASCII        ) ||
274         aMediaType.equalsIgnoreAsciiCaseAscii(MIMETYPE_VND_SUN_XML_MATH_ASCII         )
275        )
276 	{
277 		nResult = SOFFICE_FILEFORMAT_60;
278 	}
279     else
280     if (
281         aMediaType.equalsIgnoreAsciiCaseAscii(MIMETYPE_OASIS_OPENDOCUMENT_TEXT_ASCII        ) ||
282         aMediaType.equalsIgnoreAsciiCaseAscii(MIMETYPE_OASIS_OPENDOCUMENT_TEXT_WEB_ASCII    ) ||
283         aMediaType.equalsIgnoreAsciiCaseAscii(MIMETYPE_OASIS_OPENDOCUMENT_TEXT_GLOBAL_ASCII ) ||
284         aMediaType.equalsIgnoreAsciiCaseAscii(MIMETYPE_OASIS_OPENDOCUMENT_DRAWING_ASCII     ) ||
285         aMediaType.equalsIgnoreAsciiCaseAscii(MIMETYPE_OASIS_OPENDOCUMENT_PRESENTATION_ASCII) ||
286         aMediaType.equalsIgnoreAsciiCaseAscii(MIMETYPE_OASIS_OPENDOCUMENT_SPREADSHEET_ASCII ) ||
287         aMediaType.equalsIgnoreAsciiCaseAscii(MIMETYPE_OASIS_OPENDOCUMENT_CHART_ASCII       ) ||
288         aMediaType.equalsIgnoreAsciiCaseAscii(MIMETYPE_OASIS_OPENDOCUMENT_FORMULA_ASCII     ) ||
289         aMediaType.equalsIgnoreAsciiCaseAscii(MIMETYPE_OASIS_OPENDOCUMENT_DATABASE_ASCII    ) ||
290 		aMediaType.equalsIgnoreAsciiCaseAscii(MIMETYPE_OASIS_OPENDOCUMENT_REPORT_ASCII    ) ||
291         aMediaType.equalsIgnoreAsciiCaseAscii(MIMETYPE_OASIS_OPENDOCUMENT_REPORT_CHART_ASCII    ) ||
292         aMediaType.equalsIgnoreAsciiCaseAscii(MIMETYPE_OASIS_OPENDOCUMENT_TEXT_TEMPLATE_ASCII        ) ||
293         aMediaType.equalsIgnoreAsciiCaseAscii(MIMETYPE_OASIS_OPENDOCUMENT_DRAWING_TEMPLATE_ASCII     ) ||
294         aMediaType.equalsIgnoreAsciiCaseAscii(MIMETYPE_OASIS_OPENDOCUMENT_PRESENTATION_TEMPLATE_ASCII) ||
295         aMediaType.equalsIgnoreAsciiCaseAscii(MIMETYPE_OASIS_OPENDOCUMENT_SPREADSHEET_TEMPLATE_ASCII ) ||
296         aMediaType.equalsIgnoreAsciiCaseAscii(MIMETYPE_OASIS_OPENDOCUMENT_CHART_TEMPLATE_ASCII       ) ||
297         aMediaType.equalsIgnoreAsciiCaseAscii(MIMETYPE_OASIS_OPENDOCUMENT_FORMULA_TEMPLATE_ASCII     )
298        )
299 	{
300 		nResult = SOFFICE_FILEFORMAT_8;
301 	}
302 	else
303 	{
304 		// the mediatype is not known
305 		throw beans::IllegalTypeException();
306 	}
307 
308 	return nResult;
309 }
310 
311 // ----------------------------------------------------------------------
312 uno::Reference< embed::XStorage > OStorageHelper::GetTemporaryStorageOfFormat(
313 			const ::rtl::OUString& aFormat,
314 			const uno::Reference< lang::XMultiServiceFactory >& xFactory )
315 	throw ( uno::Exception )
316 {
317 	uno::Reference< lang::XMultiServiceFactory > xFactoryToUse = xFactory.is() ? xFactory : ::comphelper::getProcessServiceFactory();
318 	if ( !xFactoryToUse.is() )
319 		throw uno::RuntimeException();
320 
321 	uno::Reference< io::XStream > xTmpStream(
322 		xFactoryToUse->createInstance( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.io.TempFile" ) ) ),
323 		uno::UNO_QUERY_THROW );
324 
325 	return GetStorageOfFormatFromStream( aFormat, xTmpStream, embed::ElementModes::READWRITE, xFactoryToUse );
326 }
327 
328 // ----------------------------------------------------------------------
329 uno::Reference< embed::XStorage > OStorageHelper::GetStorageOfFormatFromURL(
330 			const ::rtl::OUString& aFormat,
331 			const ::rtl::OUString& aURL,
332 			sal_Int32 nStorageMode,
333 			const uno::Reference< lang::XMultiServiceFactory >& xFactory,
334             sal_Bool bRepairStorage )
335 	throw ( uno::Exception )
336 {
337 	uno::Sequence< beans::PropertyValue > aProps( 1 );
338 	aProps[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "StorageFormat" ) );
339 	aProps[0].Value <<= aFormat;
340     if ( bRepairStorage )
341     {
342         aProps.realloc( 2 );
343         aProps[1].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "RepairPackage" ) );
344         aProps[1].Value <<= bRepairStorage;
345     }
346 
347 	uno::Sequence< uno::Any > aArgs( 3 );
348 	aArgs[0] <<= aURL;
349 	aArgs[1] <<= nStorageMode;
350 	aArgs[2] <<= aProps;
351 
352 	uno::Reference< embed::XStorage > xTempStorage( GetStorageFactory( xFactory )->createInstanceWithArguments( aArgs ),
353 													uno::UNO_QUERY );
354 	if ( !xTempStorage.is() )
355 		throw uno::RuntimeException();
356 
357 	return xTempStorage;
358 }
359 
360 // ----------------------------------------------------------------------
361 uno::Reference< embed::XStorage > OStorageHelper::GetStorageOfFormatFromInputStream(
362 			const ::rtl::OUString& aFormat,
363             const uno::Reference < io::XInputStream >& xStream,
364 			const uno::Reference< lang::XMultiServiceFactory >& xFactory,
365             sal_Bool bRepairStorage )
366 		throw ( uno::Exception )
367 {
368 	uno::Sequence< beans::PropertyValue > aProps( 1 );
369 	aProps[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "StorageFormat" ) );
370 	aProps[0].Value <<= aFormat;
371     if ( bRepairStorage )
372     {
373         aProps.realloc( 2 );
374         aProps[1].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "RepairPackage" ) );
375         aProps[1].Value <<= bRepairStorage;
376     }
377 
378 	uno::Sequence< uno::Any > aArgs( 3 );
379 	aArgs[0] <<= xStream;
380 	aArgs[1] <<= embed::ElementModes::READ;
381 	aArgs[2] <<= aProps;
382 
383 	uno::Reference< embed::XStorage > xTempStorage( GetStorageFactory( xFactory )->createInstanceWithArguments( aArgs ),
384 													uno::UNO_QUERY );
385 	if ( !xTempStorage.is() )
386 		throw uno::RuntimeException();
387 
388 	return xTempStorage;
389 }
390 
391 // ----------------------------------------------------------------------
392 uno::Reference< embed::XStorage > OStorageHelper::GetStorageOfFormatFromStream(
393 			const ::rtl::OUString& aFormat,
394             const uno::Reference < io::XStream >& xStream,
395 			sal_Int32 nStorageMode,
396 			const uno::Reference< lang::XMultiServiceFactory >& xFactory,
397             sal_Bool bRepairStorage )
398 		throw ( uno::Exception )
399 {
400 	uno::Sequence< beans::PropertyValue > aProps( 1 );
401 	aProps[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "StorageFormat" ) );
402 	aProps[0].Value <<= aFormat;
403     if ( bRepairStorage )
404     {
405         aProps.realloc( 2 );
406         aProps[1].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "RepairPackage" ) );
407         aProps[1].Value <<= bRepairStorage;
408     }
409 
410 	uno::Sequence< uno::Any > aArgs( 3 );
411 	aArgs[0] <<= xStream;
412 	aArgs[1] <<= nStorageMode;
413 	aArgs[2] <<= aProps;
414 
415 	uno::Reference< embed::XStorage > xTempStorage( GetStorageFactory( xFactory )->createInstanceWithArguments( aArgs ),
416 													uno::UNO_QUERY );
417 	if ( !xTempStorage.is() )
418 		throw uno::RuntimeException();
419 
420 	return xTempStorage;
421 }
422 
423 // ----------------------------------------------------------------------
424 uno::Sequence< beans::NamedValue > OStorageHelper::CreatePackageEncryptionData( const ::rtl::OUString& aPassword, const uno::Reference< lang::XMultiServiceFactory >& xSF )
425 {
426     // TODO/LATER: Should not the method be part of DocPasswordHelper?
427     uno::Sequence< beans::NamedValue > aEncryptionData;
428     sal_Int32 nSha1Ind = 0;
429     if ( aPassword.getLength() )
430     {
431         // generate SHA256 start key
432         try
433         {
434             uno::Reference< lang::XMultiServiceFactory > xFactory = xSF.is() ? xSF : ::comphelper::getProcessServiceFactory();
435             if ( !xFactory.is() )
436                 throw uno::RuntimeException();
437 
438             uno::Reference< xml::crypto::XDigestContextSupplier > xDigestContextSupplier( xFactory->createInstance( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.xml.crypto.NSSInitializer" ) ) ), uno::UNO_QUERY_THROW );
439             uno::Reference< xml::crypto::XDigestContext > xDigestContext( xDigestContextSupplier->getDigestContext( xml::crypto::DigestID::SHA256, uno::Sequence< beans::NamedValue >() ), uno::UNO_SET_THROW );
440 
441             ::rtl::OString aUTF8Password( ::rtl::OUStringToOString( aPassword, RTL_TEXTENCODING_UTF8 ) );
442             xDigestContext->updateDigest( uno::Sequence< sal_Int8 >( reinterpret_cast< const sal_Int8* >( aUTF8Password.getStr() ), aUTF8Password.getLength() ) );
443             uno::Sequence< sal_Int8 > aDigest = xDigestContext->finalizeDigestAndDispose();
444 
445             aEncryptionData.realloc( ++nSha1Ind );
446             aEncryptionData[0].Name = PACKAGE_ENCRYPTIONDATA_SHA256UTF8;
447             aEncryptionData[0].Value <<= aDigest;
448         }
449         catch ( uno::Exception& )
450         {
451             OSL_ENSURE( false, "Can not create SHA256 digest!" );
452         }
453 
454         // MS_1252 encoding was used for SO60 document format password encoding,
455         // this encoding supports only a minor subset of nonascii characters,
456         // but for compatibility reasons it has to be used for old document formats
457         aEncryptionData.realloc( nSha1Ind + 2 );
458         aEncryptionData[nSha1Ind].Name = PACKAGE_ENCRYPTIONDATA_SHA1UTF8;
459         aEncryptionData[nSha1Ind + 1].Name = PACKAGE_ENCRYPTIONDATA_SHA1MS1252;
460 
461         rtl_TextEncoding pEncoding[2] = { RTL_TEXTENCODING_UTF8, RTL_TEXTENCODING_MS_1252 };
462 
463         for ( sal_Int32 nInd = 0; nInd < 2; nInd++ )
464         {
465             ::rtl::OString aByteStrPass = ::rtl::OUStringToOString( aPassword, pEncoding[nInd] );
466 
467             sal_uInt8 pBuffer[RTL_DIGEST_LENGTH_SHA1];
468             rtlDigestError nError = rtl_digest_SHA1( aByteStrPass.getStr(),
469                                                     aByteStrPass.getLength(),
470                                                     pBuffer,
471                                                     RTL_DIGEST_LENGTH_SHA1 );
472 
473             if ( nError != rtl_Digest_E_None )
474             {
475                 aEncryptionData.realloc( nSha1Ind );
476                 break;
477             }
478 
479             aEncryptionData[nSha1Ind+nInd].Value <<= uno::Sequence< sal_Int8 >( (sal_Int8*)pBuffer, RTL_DIGEST_LENGTH_SHA1 );
480         }
481     }
482 
483     return aEncryptionData;
484 }
485 
486 // ----------------------------------------------------------------------
487 sal_Bool OStorageHelper::IsValidZipEntryFileName( const ::rtl::OUString& aName, sal_Bool bSlashAllowed )
488 {
489     return IsValidZipEntryFileName( aName.getStr(), aName.getLength(), bSlashAllowed );
490 }
491 
492 // ----------------------------------------------------------------------
493 sal_Bool OStorageHelper::IsValidZipEntryFileName(
494     const sal_Unicode *pChar, sal_Int32 nLength, sal_Bool bSlashAllowed )
495 {
496     for ( sal_Int32 i = 0; i < nLength; i++ )
497     {
498         switch ( pChar[i] )
499         {
500             case '\\':
501             case '?':
502             case '<':
503             case '>':
504             case '\"':
505             case '|':
506             case ':':
507                 return sal_False;
508             case '/':
509                 if ( !bSlashAllowed )
510                     return sal_False;
511                 break;
512             default:
513                 if ( pChar[i] < 32  || (pChar[i] >= 0xD800 && pChar[i] <= 0xDFFF) )
514                     return sal_False;
515         }
516     }
517     return sal_True;
518 }
519 
520 // ----------------------------------------------------------------------
521 sal_Bool OStorageHelper::PathHasSegment( const ::rtl::OUString& aPath, const ::rtl::OUString& aSegment )
522 {
523     sal_Bool bResult = sal_False;
524     const sal_Int32 nPathLen = aPath.getLength();
525     const sal_Int32 nSegLen = aSegment.getLength();
526 
527     if ( nSegLen && nPathLen >= nSegLen )
528     {
529         ::rtl::OUString aEndSegment( RTL_CONSTASCII_USTRINGPARAM( "/" ) );
530         aEndSegment += aSegment;
531 
532         ::rtl::OUString aInternalSegment( aEndSegment );
533         aInternalSegment += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/" ) );
534 
535         if ( aPath.indexOf( aInternalSegment ) >= 0 )
536             bResult = sal_True;
537 
538         if ( !bResult && !aPath.compareTo( aSegment, nSegLen ) )
539         {
540             if ( nPathLen == nSegLen || aPath.getStr()[nSegLen] == (sal_Unicode)'/' )
541                 bResult = sal_True;
542         }
543 
544         if ( !bResult && nPathLen > nSegLen && aPath.copy( nPathLen - nSegLen - 1, nSegLen + 1 ).equals( aEndSegment ) )
545             bResult = sal_True;
546     }
547 
548     return bResult;
549 }
550 
551 }
552 
553