LibreOffice Module comphelper (master) 1
storagehelper.cxx
Go to the documentation of this file.
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 <config_gpgme.h>
21
22#include <com/sun/star/embed/ElementModes.hpp>
23#include <com/sun/star/embed/XEncryptionProtectedStorage.hpp>
24#include <com/sun/star/embed/XStorage.hpp>
25#include <com/sun/star/embed/XTransactedObject.hpp>
26#include <com/sun/star/embed/StorageFactory.hpp>
27#include <com/sun/star/embed/FileSystemStorageFactory.hpp>
28#include <com/sun/star/io/IOException.hpp>
29#include <com/sun/star/lang/XSingleServiceFactory.hpp>
30#include <com/sun/star/lang/XUnoTunnel.hpp>
31#include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
32#include <com/sun/star/ucb/SimpleFileAccess.hpp>
33#include <com/sun/star/beans/XPropertySet.hpp>
34#include <com/sun/star/beans/PropertyValue.hpp>
35#include <com/sun/star/beans/NamedValue.hpp>
36#include <com/sun/star/beans/IllegalTypeException.hpp>
37#include <com/sun/star/xml/crypto/NSSInitializer.hpp>
38#include <com/sun/star/xml/crypto/XDigestContext.hpp>
39#include <com/sun/star/xml/crypto/DigestID.hpp>
40#include <com/sun/star/security/DocumentDigitalSignatures.hpp>
41#include <com/sun/star/security/XCertificate.hpp>
42
43#include <vector>
44
45#include <rtl/digest.h>
46#include <rtl/random.h>
47#include <osl/diagnose.h>
48#include <sal/log.hxx>
49
50#include <ucbhelper/content.hxx>
51
55#include <comphelper/hash.hxx>
62#include <o3tl/string_view.hxx>
63
64#if HAVE_FEATURE_GPGME
65# include <context.h>
66# include <encryptionresult.h>
67# include <key.h>
68# include <data.h>
69#endif
70
71using namespace ::com::sun::star;
72
73namespace comphelper {
74
75
76uno::Reference< lang::XSingleServiceFactory > OStorageHelper::GetStorageFactory(
77 const uno::Reference< uno::XComponentContext >& rxContext )
78{
79 uno::Reference< uno::XComponentContext> xContext = rxContext.is() ? rxContext : ::comphelper::getProcessComponentContext();
80
81 return embed::StorageFactory::create( xContext );
82}
83
84
85uno::Reference< lang::XSingleServiceFactory > OStorageHelper::GetFileSystemStorageFactory(
86 const uno::Reference< uno::XComponentContext >& rxContext )
87{
88 return embed::FileSystemStorageFactory::create(rxContext);
89}
90
91
92uno::Reference< embed::XStorage > OStorageHelper::GetTemporaryStorage(
93 const uno::Reference< uno::XComponentContext >& rxContext )
94{
95 uno::Reference< embed::XStorage > xTempStorage( GetStorageFactory( rxContext )->createInstance(),
96 uno::UNO_QUERY_THROW );
97 return xTempStorage;
98}
99
100
101uno::Reference< embed::XStorage > OStorageHelper::GetStorageFromURL(
102 const OUString& aURL,
103 sal_Int32 nStorageMode,
104 const uno::Reference< uno::XComponentContext >& rxContext )
105{
106 uno::Sequence< uno::Any > aArgs{ uno::Any(aURL), uno::Any(nStorageMode) };
107 uno::Reference< embed::XStorage > xTempStorage( GetStorageFactory( rxContext )->createInstanceWithArguments( aArgs ),
108 uno::UNO_QUERY_THROW );
109 return xTempStorage;
110}
111
112
113uno::Reference< embed::XStorage > OStorageHelper::GetStorageFromURL2(
114 const OUString& aURL,
115 sal_Int32 nStorageMode,
116 const uno::Reference< uno::XComponentContext >& rxContext )
117{
118 uno::Sequence< uno::Any > aArgs{ uno::Any(aURL), uno::Any(nStorageMode) };
119
120 uno::Reference< lang::XSingleServiceFactory > xFact;
121 css::uno::Any anyEx;
122 try {
124 uno::Reference< css::ucb::XCommandEnvironment > (),
126 if (aCntnt.isDocument()) {
127 xFact = GetStorageFactory( rxContext );
128 } else {
129 xFact = GetFileSystemStorageFactory( rxContext );
130 }
131 } catch (uno::Exception &)
132 {
133 anyEx = cppu::getCaughtException();
134 }
135
136 if (!xFact.is())
137 {
138 if (anyEx.hasValue())
139 throw css::lang::WrappedTargetRuntimeException( "", nullptr, anyEx );
140 else
141 throw uno::RuntimeException();
142 }
143
144 uno::Reference< embed::XStorage > xTempStorage(
145 xFact->createInstanceWithArguments( aArgs ), uno::UNO_QUERY_THROW );
146 return xTempStorage;
147}
148
149
150uno::Reference< embed::XStorage > OStorageHelper::GetStorageFromInputStream(
151 const uno::Reference < io::XInputStream >& xStream,
152 const uno::Reference< uno::XComponentContext >& rxContext )
153{
154 uno::Sequence< uno::Any > aArgs{ uno::Any(xStream), uno::Any(embed::ElementModes::READ) };
155 uno::Reference< embed::XStorage > xTempStorage( GetStorageFactory( rxContext )->createInstanceWithArguments( aArgs ),
156 uno::UNO_QUERY_THROW );
157 return xTempStorage;
158}
159
160
161uno::Reference< embed::XStorage > OStorageHelper::GetStorageFromStream(
162 const uno::Reference < io::XStream >& xStream,
163 sal_Int32 nStorageMode,
164 const uno::Reference< uno::XComponentContext >& rxContext )
165{
166 uno::Sequence< uno::Any > aArgs{ uno::Any(xStream), uno::Any(nStorageMode) };
167 uno::Reference< embed::XStorage > xTempStorage( GetStorageFactory( rxContext )->createInstanceWithArguments( aArgs ),
168 uno::UNO_QUERY_THROW );
169 return xTempStorage;
170}
171
172
174 const uno::Reference< io::XInputStream >& xInput,
175 const uno::Reference< io::XOutputStream >& xOutput )
176{
177 static const sal_Int32 nConstBufferSize = 32000;
178
179 if (auto pByteReader = dynamic_cast< comphelper::ByteReader* >( xInput.get() ))
180 {
181 if (auto pByteWriter = dynamic_cast< comphelper::ByteWriter* >( xOutput.get() ))
182 {
183 sal_Int32 nRead;
184 sal_Int8 aTempBuf[ nConstBufferSize ];
185 do
186 {
187 nRead = pByteReader->readSomeBytes ( aTempBuf, nConstBufferSize );
188 pByteWriter->writeBytes ( aTempBuf, nRead );
189 }
190 while ( nRead == nConstBufferSize );
191 return;
192 }
193 }
194
195 sal_Int32 nRead;
196 uno::Sequence < sal_Int8 > aSequence ( nConstBufferSize );
197 do
198 {
199 nRead = xInput->readBytes ( aSequence, nConstBufferSize );
200 if ( nRead < nConstBufferSize )
201 aSequence.realloc( nRead );
202 xOutput->writeBytes ( aSequence );
203 }
204 while ( nRead == nConstBufferSize );
205}
206
207
208uno::Reference< io::XInputStream > OStorageHelper::GetInputStreamFromURL(
209 const OUString& aURL,
210 const uno::Reference< uno::XComponentContext >& context )
211{
212 uno::Reference< io::XInputStream > xInputStream = ucb::SimpleFileAccess::create(context)->openFileRead( aURL );
213 if ( !xInputStream.is() )
214 throw uno::RuntimeException();
215
216 return xInputStream;
217}
218
219
221 const uno::Reference< embed::XStorage >& xStorage,
222 const uno::Sequence< beans::NamedValue >& aEncryptionData )
223{
224 uno::Reference< embed::XEncryptionProtectedStorage > xEncrSet( xStorage, uno::UNO_QUERY );
225 if ( !xEncrSet.is() )
226 throw io::IOException("no XEncryptionProtectedStorage"); // TODO
227
228 if ( aEncryptionData.getLength() == 2 &&
229 aEncryptionData[0].Name == "GpgInfos" &&
230 aEncryptionData[1].Name == "EncryptionKey" )
231 {
232 xEncrSet->setGpgProperties(
233 aEncryptionData[0].Value.get< uno::Sequence< uno::Sequence< beans::NamedValue > > >() );
234 xEncrSet->setEncryptionData(
235 aEncryptionData[1].Value.get< uno::Sequence< beans::NamedValue > >() );
236 }
237 else
238 xEncrSet->setEncryptionData( aEncryptionData );
239}
240
241
243 const uno::Reference< embed::XStorage >& xStorage )
244{
245 uno::Reference< beans::XPropertySet > xStorProps( xStorage, uno::UNO_QUERY_THROW );
246
247 OUString aMediaType;
248 xStorProps->getPropertyValue("MediaType") >>= aMediaType;
249
250 sal_Int32 nResult = 0;
251
252 // TODO/LATER: the filter configuration could be used to detect it later, or better a special service
253 if (
254 aMediaType.equalsIgnoreAsciiCase(MIMETYPE_VND_SUN_XML_WRITER_ASCII ) ||
255 aMediaType.equalsIgnoreAsciiCase(MIMETYPE_VND_SUN_XML_WRITER_WEB_ASCII ) ||
256 aMediaType.equalsIgnoreAsciiCase(MIMETYPE_VND_SUN_XML_WRITER_GLOBAL_ASCII) ||
257 aMediaType.equalsIgnoreAsciiCase(MIMETYPE_VND_SUN_XML_DRAW_ASCII ) ||
258 aMediaType.equalsIgnoreAsciiCase(MIMETYPE_VND_SUN_XML_IMPRESS_ASCII ) ||
259 aMediaType.equalsIgnoreAsciiCase(MIMETYPE_VND_SUN_XML_CALC_ASCII ) ||
260 aMediaType.equalsIgnoreAsciiCase(MIMETYPE_VND_SUN_XML_CHART_ASCII ) ||
261 aMediaType.equalsIgnoreAsciiCase(MIMETYPE_VND_SUN_XML_MATH_ASCII )
262 )
263 {
264 nResult = SOFFICE_FILEFORMAT_60;
265 }
266 else if (
267 aMediaType.equalsIgnoreAsciiCase(MIMETYPE_OASIS_OPENDOCUMENT_TEXT_ASCII ) ||
268 aMediaType.equalsIgnoreAsciiCase(MIMETYPE_OASIS_OPENDOCUMENT_TEXT_WEB_ASCII ) ||
269 aMediaType.equalsIgnoreAsciiCase(MIMETYPE_OASIS_OPENDOCUMENT_TEXT_GLOBAL_ASCII ) ||
270 aMediaType.equalsIgnoreAsciiCase(MIMETYPE_OASIS_OPENDOCUMENT_DRAWING_ASCII ) ||
271 aMediaType.equalsIgnoreAsciiCase(MIMETYPE_OASIS_OPENDOCUMENT_PRESENTATION_ASCII) ||
272 aMediaType.equalsIgnoreAsciiCase(MIMETYPE_OASIS_OPENDOCUMENT_SPREADSHEET_ASCII ) ||
273 aMediaType.equalsIgnoreAsciiCase(MIMETYPE_OASIS_OPENDOCUMENT_CHART_ASCII ) ||
274 aMediaType.equalsIgnoreAsciiCase(MIMETYPE_OASIS_OPENDOCUMENT_FORMULA_ASCII ) ||
275 aMediaType.equalsIgnoreAsciiCase(MIMETYPE_OASIS_OPENDOCUMENT_DATABASE_ASCII ) ||
276 aMediaType.equalsIgnoreAsciiCase(MIMETYPE_OASIS_OPENDOCUMENT_REPORT_ASCII ) ||
277 aMediaType.equalsIgnoreAsciiCase(MIMETYPE_OASIS_OPENDOCUMENT_REPORT_CHART_ASCII ) ||
278 aMediaType.equalsIgnoreAsciiCase(MIMETYPE_OASIS_OPENDOCUMENT_TEXT_TEMPLATE_ASCII ) ||
279 aMediaType.equalsIgnoreAsciiCase(MIMETYPE_OASIS_OPENDOCUMENT_TEXT_GLOBAL_TEMPLATE_ASCII ) ||
280 aMediaType.equalsIgnoreAsciiCase(MIMETYPE_OASIS_OPENDOCUMENT_DRAWING_TEMPLATE_ASCII ) ||
281 aMediaType.equalsIgnoreAsciiCase(MIMETYPE_OASIS_OPENDOCUMENT_PRESENTATION_TEMPLATE_ASCII) ||
282 aMediaType.equalsIgnoreAsciiCase(MIMETYPE_OASIS_OPENDOCUMENT_SPREADSHEET_TEMPLATE_ASCII ) ||
283 aMediaType.equalsIgnoreAsciiCase(MIMETYPE_OASIS_OPENDOCUMENT_CHART_TEMPLATE_ASCII ) ||
284 aMediaType.equalsIgnoreAsciiCase(MIMETYPE_OASIS_OPENDOCUMENT_FORMULA_TEMPLATE_ASCII )
285 )
286 {
287 nResult = SOFFICE_FILEFORMAT_8;
288 }
289 else
290 {
291 // the mediatype is not known
292 OUString aMsg = __func__
293 + OUString::Concat(u":")
294 + OUString::number(__LINE__)
295 + ": unknown media type '"
296 + aMediaType
297 + "'";
298 throw beans::IllegalTypeException(aMsg);
299 }
300
301 return nResult;
302}
303
304
305uno::Reference< embed::XStorage > OStorageHelper::GetStorageOfFormatFromURL(
306 const OUString& aFormat,
307 const OUString& aURL,
308 sal_Int32 nStorageMode,
309 const uno::Reference< uno::XComponentContext >& rxContext )
310{
311 uno::Sequence< beans::PropertyValue > aProps{ comphelper::makePropertyValue("StorageFormat",
312 aFormat) };
313
314 uno::Sequence< uno::Any > aArgs{ uno::Any(aURL), uno::Any(nStorageMode), uno::Any(aProps) };
315 uno::Reference< embed::XStorage > xTempStorage( GetStorageFactory( rxContext )->createInstanceWithArguments( aArgs ),
316 uno::UNO_QUERY_THROW );
317 return xTempStorage;
318}
319
320
322 const OUString& aFormat,
323 const uno::Reference < io::XInputStream >& xStream,
324 const uno::Reference< uno::XComponentContext >& rxContext,
325 bool bRepairStorage )
326{
327 uno::Sequence< beans::PropertyValue > aProps( bRepairStorage ? 2 : 1 );
328 auto pProps = aProps.getArray();
329 pProps[0].Name = "StorageFormat";
330 pProps[0].Value <<= aFormat;
331 if ( bRepairStorage )
332 {
333 pProps[1].Name = "RepairPackage";
334 pProps[1].Value <<= bRepairStorage;
335 }
336
337 uno::Sequence< uno::Any > aArgs{ uno::Any(xStream), uno::Any(embed::ElementModes::READ), uno::Any(aProps) };
338 uno::Reference< embed::XStorage > xTempStorage( GetStorageFactory( rxContext )->createInstanceWithArguments( aArgs ),
339 uno::UNO_QUERY_THROW );
340 return xTempStorage;
341}
342
343
344uno::Reference< embed::XStorage > OStorageHelper::GetStorageOfFormatFromStream(
345 const OUString& aFormat,
346 const uno::Reference < io::XStream >& xStream,
347 sal_Int32 nStorageMode,
348 const uno::Reference< uno::XComponentContext >& rxContext,
349 bool bRepairStorage )
350{
351 uno::Sequence< beans::PropertyValue > aProps( bRepairStorage ? 2 : 1 );
352 auto pProps = aProps.getArray();
353 pProps[0].Name = "StorageFormat";
354 pProps[0].Value <<= aFormat;
355 if ( bRepairStorage )
356 {
357 pProps[1].Name = "RepairPackage";
358 pProps[1].Value <<= bRepairStorage;
359 }
360
361 uno::Sequence< uno::Any > aArgs{ uno::Any(xStream), uno::Any(nStorageMode), uno::Any(aProps) };
362 uno::Reference< embed::XStorage > xTempStorage( GetStorageFactory( rxContext )->createInstanceWithArguments( aArgs ),
363 uno::UNO_QUERY_THROW );
364 return xTempStorage;
365}
366
367
368uno::Sequence< beans::NamedValue > OStorageHelper::CreatePackageEncryptionData( std::u16string_view aPassword )
369{
370 // TODO/LATER: Should not the method be part of DocPasswordHelper?
371 uno::Sequence< beans::NamedValue > aEncryptionData;
372 if ( !aPassword.empty() )
373 {
374 sal_Int32 nSha1Ind = 0;
375 // generate SHA256 start key
376 try
377 {
378 uno::Reference< uno::XComponentContext > xContext = ::comphelper::getProcessComponentContext();
379
380 uno::Reference< css::xml::crypto::XNSSInitializer > xDigestContextSupplier = css::xml::crypto::NSSInitializer::create(xContext);
381 uno::Reference< css::xml::crypto::XDigestContext > xDigestContext( xDigestContextSupplier->getDigestContext( css::xml::crypto::DigestID::SHA256, uno::Sequence< beans::NamedValue >() ), uno::UNO_SET_THROW );
382
383 OString aUTF8Password( OUStringToOString( aPassword, RTL_TEXTENCODING_UTF8 ) );
384 xDigestContext->updateDigest( uno::Sequence< sal_Int8 >( reinterpret_cast< const sal_Int8* >( aUTF8Password.getStr() ), aUTF8Password.getLength() ) );
385 uno::Sequence< sal_Int8 > aDigest = xDigestContext->finalizeDigestAndDispose();
386
387 ++nSha1Ind;
388 aEncryptionData = { { PACKAGE_ENCRYPTIONDATA_SHA256UTF8, uno::Any(aDigest) } };
389 }
390 catch ( uno::Exception& )
391 {
392 TOOLS_WARN_EXCEPTION("comphelper", "Can not create SHA256 digest!" );
393 }
394
395 // MS_1252 encoding was used for SO60 document format password encoding,
396 // this encoding supports only a minor subset of nonascii characters,
397 // but for compatibility reasons it has to be used for old document formats
398 aEncryptionData.realloc( nSha1Ind + 3 );
399 auto pEncryptionData = aEncryptionData.getArray();
400 // these are StarOffice not-quite-SHA1
401 pEncryptionData[nSha1Ind].Name = PACKAGE_ENCRYPTIONDATA_SHA1UTF8;
402 pEncryptionData[nSha1Ind + 1].Name = PACKAGE_ENCRYPTIONDATA_SHA1MS1252;
403
404 rtl_TextEncoding const pEncoding[2] = { RTL_TEXTENCODING_UTF8, RTL_TEXTENCODING_MS_1252 };
405
406 for ( sal_Int32 nInd = 0; nInd < 2; nInd++ )
407 {
408 OString aByteStrPass = OUStringToOString( aPassword, pEncoding[nInd] );
409
410 sal_uInt8 pBuffer[RTL_DIGEST_LENGTH_SHA1];
411 rtlDigestError nError = rtl_digest_SHA1( aByteStrPass.getStr(),
412 aByteStrPass.getLength(),
413 pBuffer,
414 RTL_DIGEST_LENGTH_SHA1 );
415
416 if ( nError != rtl_Digest_E_None )
417 {
418 aEncryptionData.realloc( nSha1Ind );
419 return aEncryptionData;
420 }
421
422 // coverity[overrun-buffer-arg : FALSE] - coverity has difficulty with css::uno::Sequence
423 pEncryptionData[nSha1Ind+nInd].Value <<= uno::Sequence< sal_Int8 >( reinterpret_cast<sal_Int8*>(pBuffer), RTL_DIGEST_LENGTH_SHA1 );
424 }
425
426 // actual SHA1
427 pEncryptionData[nSha1Ind + 2].Name = PACKAGE_ENCRYPTIONDATA_SHA1CORRECT;
428 OString aByteStrPass = OUStringToOString(aPassword, RTL_TEXTENCODING_UTF8);
429 std::vector<unsigned char> const sha1(::comphelper::Hash::calculateHash(
430 reinterpret_cast<unsigned char const*>(aByteStrPass.getStr()), aByteStrPass.getLength(),
431 ::comphelper::HashType::SHA1));
432 pEncryptionData[nSha1Ind + 2].Value <<= uno::Sequence<sal_Int8>(
433 reinterpret_cast<sal_Int8 const*>(sha1.data()), sha1.size());
434 }
435
436 return aEncryptionData;
437}
438
439uno::Sequence< beans::NamedValue > OStorageHelper::CreateGpgPackageEncryptionData()
440{
441#if HAVE_FEATURE_GPGME
442 // generate session key
443 // --------------------
444
445 rtlRandomPool aRandomPool = rtl_random_createPool();
446
447 // get 32 random chars out of it
448 uno::Sequence < sal_Int8 > aVector(32);
449 rtl_random_getBytes( aRandomPool, aVector.getArray(), aVector.getLength() );
450
451 rtl_random_destroyPool(aRandomPool);
452
453 std::vector< uno::Sequence< beans::NamedValue > > aGpgEncryptions;
454
455 uno::Reference< security::XDocumentDigitalSignatures > xSigner(
456 // here none of the version-dependent methods are called
457 security::DocumentDigitalSignatures::createDefault(
459
460 // fire up certificate chooser dialog - user can multi-select!
461 const uno::Sequence< uno::Reference< security::XCertificate > > xSignCertificates=
462 xSigner->chooseEncryptionCertificate();
463
464 if (!xSignCertificates.hasElements())
465 return uno::Sequence< beans::NamedValue >(); // user cancelled
466
467 // generate one encrypted key entry for each recipient
468 // ---------------------------------------------------
469
470 std::unique_ptr<GpgME::Context> ctx;
471 GpgME::Error err = GpgME::checkEngine(GpgME::OpenPGP);
472 if (err)
473 throw uno::RuntimeException("The GpgME library failed to initialize for the OpenPGP protocol.");
474
475 ctx.reset( GpgME::Context::createForProtocol(GpgME::OpenPGP) );
476 if (ctx == nullptr)
477 throw uno::RuntimeException("The GpgME library failed to initialize for the OpenPGP protocol.");
478 ctx->setArmor(false);
479
480 for (const auto & cert : xSignCertificates)
481 {
482 uno::Sequence < sal_Int8 > aKeyID;
483 if (cert.is())
484 aKeyID = cert->getSHA1Thumbprint();
485
486 std::vector<GpgME::Key> keys
487 {
488 ctx->key(
489 reinterpret_cast<const char*>(aKeyID.getConstArray()),
490 err, false)
491 };
492
493 // ctx is setup now, let's encrypt the lot!
494 GpgME::Data plain(
495 reinterpret_cast<const char*>(aVector.getConstArray()),
496 size_t(aVector.getLength()), false);
497 GpgME::Data cipher;
498
499 GpgME::EncryptionResult crypt_res = ctx->encrypt(
500 keys, plain,
501 cipher, GpgME::Context::NoCompress);
502
503 off_t result = cipher.seek(0,SEEK_SET);
504 (void) result;
505 assert(result == 0);
506 int len=0, curr=0; char buf;
507 while( (curr=cipher.read(&buf, 1)) )
508 len += curr;
509
510 if(crypt_res.error() || !len)
511 throw lang::IllegalArgumentException(
512 "Not a suitable key, or failed to encrypt.",
513 css::uno::Reference<css::uno::XInterface>(), -1);
514
515 uno::Sequence < sal_Int8 > aCipherValue(len);
516 result = cipher.seek(0,SEEK_SET);
517 assert(result == 0);
518 if( cipher.read(aCipherValue.getArray(), len) != len )
519 throw uno::RuntimeException("The GpgME library failed to read the encrypted value.");
520
521 SAL_INFO("comphelper.crypto", "Generated gpg crypto of length: " << len);
522
523 uno::Sequence< beans::NamedValue > aGpgEncryptionEntry{
524 { "KeyId", uno::Any(aKeyID) },
525 { "KeyPacket", uno::Any(aKeyID) },
526 { "CipherValue", uno::Any(aCipherValue) }
527 };
528
529 aGpgEncryptions.push_back(aGpgEncryptionEntry);
530 }
531
532 uno::Sequence<beans::NamedValue> aEncryptionData
534
535 uno::Sequence<beans::NamedValue> aContainer
536 = { { "GpgInfos", uno::Any(comphelper::containerToSequence(aGpgEncryptions)) },
537 { "EncryptionKey", uno::Any(aEncryptionData) } };
538
539 return aContainer;
540#else
541 return uno::Sequence< beans::NamedValue >();
542#endif
543}
544
545bool OStorageHelper::IsValidZipEntryFileName( std::u16string_view aName, bool bSlashAllowed )
546{
547 for ( size_t i = 0; i < aName.size(); i++ )
548 {
549 switch ( aName[i] )
550 {
551 case '\\':
552 case '?':
553 case '<':
554 case '>':
555 case '\"':
556 case '|':
557 case ':':
558 return false;
559 case '/':
560 if ( !bSlashAllowed )
561 return false;
562 break;
563 default:
564 if ( aName[i] < 32 || (aName[i] >= 0xD800 && aName[i] <= 0xDFFF) )
565 return false;
566 }
567 }
568 return true;
569}
570
571
572bool OStorageHelper::PathHasSegment( std::u16string_view aPath, std::u16string_view aSegment )
573{
574 bool bResult = false;
575 const size_t nPathLen = aPath.size();
576 const size_t nSegLen = aSegment.size();
577
578 if ( !aSegment.empty() && nPathLen >= nSegLen )
579 {
580 OUString aEndSegment = OUString::Concat("/") + aSegment;
581 OUString aInternalSegment = aEndSegment + "/";
582
583 if ( aPath.find( aInternalSegment ) != std::u16string_view::npos )
584 bResult = true;
585
586 if ( !bResult && o3tl::starts_with(aPath, aSegment ) )
587 {
588 if ( nPathLen == nSegLen || aPath[nSegLen] == '/' )
589 bResult = true;
590 }
591
592 if ( !bResult && nPathLen > nSegLen && aPath.substr( nPathLen - nSegLen - 1, nSegLen + 1 ) == aEndSegment )
593 bResult = true;
594 }
595
596 return bResult;
597}
598
600 : public std::vector< uno::Reference< embed::XStorage > > {};
602 : m_xBadness( new Impl ) { }
604
606{
607 std::for_each(m_xBadness->rbegin(), m_xBadness->rend(), // reverse order (outwards)
608 [](Impl::reference rxItem) {
609 uno::Reference<embed::XTransactedObject> const xTransaction(rxItem, uno::UNO_QUERY);
610 if (xTransaction.is())
611 {
612 xTransaction->commit();
613 }
614 });
615}
616
617static void splitPath( std::vector<OUString> &rElems, std::u16string_view rPath )
618{
619 for (sal_Int32 i = 0; i >= 0;)
620 rElems.push_back( OUString(o3tl::getToken(rPath, 0, '/', i )) );
621}
622
623static uno::Reference< embed::XStorage > LookupStorageAtPath(
624 const uno::Reference< embed::XStorage > &xParentStorage,
625 std::vector<OUString> &rElems, sal_uInt32 nOpenMode,
626 LifecycleProxy const &rNastiness )
627{
628 uno::Reference< embed::XStorage > xStorage( xParentStorage );
629 rNastiness.m_xBadness->push_back( xStorage );
630 for( size_t i = 0; i < rElems.size() && xStorage.is(); i++ )
631 {
632 xStorage = xStorage->openStorageElement( rElems[i], nOpenMode );
633 rNastiness.m_xBadness->push_back( xStorage );
634 }
635 return xStorage;
636}
637
638uno::Reference< embed::XStorage > OStorageHelper::GetStorageAtPath(
639 const uno::Reference< embed::XStorage > &xStorage,
640 std::u16string_view rPath, sal_uInt32 nOpenMode,
641 LifecycleProxy const &rNastiness )
642{
643 std::vector<OUString> aElems;
644 splitPath( aElems, rPath );
645 return LookupStorageAtPath( xStorage, aElems, nOpenMode, rNastiness );
646}
647
648uno::Reference< io::XStream > OStorageHelper::GetStreamAtPath(
649 const uno::Reference< embed::XStorage > &xParentStorage,
650 std::u16string_view rPath, sal_uInt32 nOpenMode,
651 LifecycleProxy const &rNastiness )
652{
653 std::vector<OUString> aElems;
654 splitPath( aElems, rPath );
655 OUString aName( aElems.back() );
656 aElems.pop_back();
657 sal_uInt32 nStorageMode = nOpenMode & ~embed::ElementModes::TRUNCATE;
658 uno::Reference< embed::XStorage > xStorage(
659 LookupStorageAtPath( xParentStorage, aElems, nStorageMode, rNastiness ),
660 uno::UNO_SET_THROW );
661 return xStorage->openStreamElement( aName, nOpenMode );
662}
663
664uno::Reference< io::XStream > OStorageHelper::GetStreamAtPackageURL(
665 uno::Reference< embed::XStorage > const& xParentStorage,
666 const OUString& rURL, sal_uInt32 const nOpenMode,
667 LifecycleProxy const & rNastiness)
668{
669 OUString path;
670 if (rURL.startsWithIgnoreAsciiCase("vnd.sun.star.Package:", &path))
671 {
672 return GetStreamAtPath(xParentStorage, path, nOpenMode, rNastiness);
673 }
674 return nullptr;
675}
676
677OUString OStorageHelper::GetODFVersionFromStorage(const uno::Reference<embed::XStorage>& xStorage)
678{
679 OUString aODFVersion;
680 try
681 {
682 uno::Reference<beans::XPropertySet> xPropSet(xStorage, uno::UNO_QUERY_THROW);
683 xPropSet->getPropertyValue("Version") >>= aODFVersion;
684 }
685 catch (uno::Exception&)
686 {
687 }
688 return aODFVersion;
689}
690}
691
692/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Reference< XInputStream > xStream
void * rtlRandomPool
HRESULT createInstance(REFIID iid, Ifc **ppIfc)
static std::vector< unsigned char > calculateHash(const unsigned char *pInput, size_t length, HashType eType)
Definition: hash.cxx:161
std::unique_ptr< Impl > m_xBadness
static css::uno::Sequence< css::beans::NamedValue > CreateGpgPackageEncryptionData()
static css::uno::Reference< css::embed::XStorage > GetStorageFromInputStream(const css::uno::Reference< css::io::XInputStream > &xStream, const css::uno::Reference< css::uno::XComponentContext > &rxContext=css::uno::Reference< css::uno::XComponentContext >())
static css::uno::Reference< css::embed::XStorage > GetStorageFromStream(const css::uno::Reference< css::io::XStream > &xStream, sal_Int32 nStorageMode=css::embed::ElementModes::READWRITE, const css::uno::Reference< css::uno::XComponentContext > &rxContext=css::uno::Reference< css::uno::XComponentContext >())
static css::uno::Reference< css::embed::XStorage > GetStorageFromURL2(const OUString &aURL, sal_Int32 nStorageMode, const css::uno::Reference< css::uno::XComponentContext > &rxContext=css::uno::Reference< css::uno::XComponentContext >())
this one will return either Storage or FileSystemStorage
static css::uno::Sequence< css::beans::NamedValue > CreatePackageEncryptionData(std::u16string_view aPassword)
static css::uno::Reference< css::lang::XSingleServiceFactory > GetFileSystemStorageFactory(const css::uno::Reference< css::uno::XComponentContext > &rxContext=css::uno::Reference< css::uno::XComponentContext >())
static bool IsValidZipEntryFileName(std::u16string_view aName, bool bSlashAllowed)
static void SetCommonStorageEncryptionData(const css::uno::Reference< css::embed::XStorage > &xStorage, const css::uno::Sequence< css::beans::NamedValue > &aEncryptionData)
static sal_Int32 GetXStorageFormat(const css::uno::Reference< css::embed::XStorage > &xStorage)
static css::uno::Reference< css::embed::XStorage > GetStorageFromURL(const OUString &aURL, sal_Int32 nStorageMode, const css::uno::Reference< css::uno::XComponentContext > &rxContext=css::uno::Reference< css::uno::XComponentContext >())
this one will only return Storage
static css::uno::Reference< css::embed::XStorage > GetStorageOfFormatFromInputStream(const OUString &aFormat, const css::uno::Reference< css::io::XInputStream > &xStream, const css::uno::Reference< css::uno::XComponentContext > &rxContext=css::uno::Reference< css::uno::XComponentContext >(), bool bRepairStorage=false)
static void CopyInputToOutput(const css::uno::Reference< css::io::XInputStream > &xInput, const css::uno::Reference< css::io::XOutputStream > &xOutput)
static css::uno::Reference< css::embed::XStorage > GetTemporaryStorage(const css::uno::Reference< css::uno::XComponentContext > &rxContext=css::uno::Reference< css::uno::XComponentContext >())
static css::uno::Reference< css::lang::XSingleServiceFactory > GetStorageFactory(const css::uno::Reference< css::uno::XComponentContext > &rxContext=css::uno::Reference< css::uno::XComponentContext >())
static bool PathHasSegment(std::u16string_view aPath, std::u16string_view aSegment)
static css::uno::Reference< css::embed::XStorage > GetStorageOfFormatFromStream(const OUString &aFormat, const css::uno::Reference< css::io::XStream > &xStream, sal_Int32 nStorageMode=css::embed::ElementModes::READWRITE, const css::uno::Reference< css::uno::XComponentContext > &rxContext=css::uno::Reference< css::uno::XComponentContext >(), bool bRepairStorage=false)
static css::uno::Reference< css::io::XInputStream > GetInputStreamFromURL(const OUString &aURL, const css::uno::Reference< css::uno::XComponentContext > &context)
static css::uno::Reference< css::embed::XStorage > GetStorageOfFormatFromURL(const OUString &aFormat, const OUString &aURL, sal_Int32 nStorageMode, const css::uno::Reference< css::uno::XComponentContext > &rxContext=css::uno::Reference< css::uno::XComponentContext >())
#define TOOLS_WARN_EXCEPTION(area, stream)
Logs an message along with a nicely formatted version of the current exception.
URL aURL
constexpr OUStringLiteral MIMETYPE_VND_SUN_XML_CHART_ASCII
constexpr OUStringLiteral MIMETYPE_OASIS_OPENDOCUMENT_DATABASE_ASCII
constexpr OUStringLiteral MIMETYPE_OASIS_OPENDOCUMENT_REPORT_CHART_ASCII
constexpr OUStringLiteral MIMETYPE_OASIS_OPENDOCUMENT_TEXT_GLOBAL_TEMPLATE_ASCII
constexpr OUStringLiteral MIMETYPE_VND_SUN_XML_IMPRESS_ASCII
constexpr OUStringLiteral MIMETYPE_OASIS_OPENDOCUMENT_DRAWING_TEMPLATE_ASCII
constexpr OUStringLiteral MIMETYPE_OASIS_OPENDOCUMENT_PRESENTATION_ASCII
constexpr OUStringLiteral MIMETYPE_VND_SUN_XML_CALC_ASCII
constexpr OUStringLiteral MIMETYPE_OASIS_OPENDOCUMENT_TEXT_ASCII
constexpr OUStringLiteral MIMETYPE_OASIS_OPENDOCUMENT_TEXT_TEMPLATE_ASCII
constexpr OUStringLiteral MIMETYPE_OASIS_OPENDOCUMENT_SPREADSHEET_ASCII
constexpr OUStringLiteral MIMETYPE_OASIS_OPENDOCUMENT_TEXT_GLOBAL_ASCII
constexpr OUStringLiteral MIMETYPE_VND_SUN_XML_WRITER_ASCII
constexpr OUStringLiteral MIMETYPE_OASIS_OPENDOCUMENT_CHART_ASCII
constexpr OUStringLiteral MIMETYPE_VND_SUN_XML_WRITER_GLOBAL_ASCII
constexpr OUStringLiteral MIMETYPE_VND_SUN_XML_DRAW_ASCII
constexpr OUStringLiteral MIMETYPE_OASIS_OPENDOCUMENT_FORMULA_ASCII
constexpr OUStringLiteral MIMETYPE_OASIS_OPENDOCUMENT_TEXT_WEB_ASCII
constexpr OUStringLiteral MIMETYPE_OASIS_OPENDOCUMENT_CHART_TEMPLATE_ASCII
constexpr OUStringLiteral MIMETYPE_OASIS_OPENDOCUMENT_DRAWING_ASCII
constexpr OUStringLiteral MIMETYPE_VND_SUN_XML_WRITER_WEB_ASCII
constexpr OUStringLiteral MIMETYPE_VND_SUN_XML_MATH_ASCII
constexpr OUStringLiteral MIMETYPE_OASIS_OPENDOCUMENT_FORMULA_TEMPLATE_ASCII
constexpr OUStringLiteral MIMETYPE_OASIS_OPENDOCUMENT_PRESENTATION_TEMPLATE_ASCII
constexpr OUStringLiteral MIMETYPE_OASIS_OPENDOCUMENT_SPREADSHEET_TEMPLATE_ASCII
constexpr OUStringLiteral MIMETYPE_OASIS_OPENDOCUMENT_REPORT_ASCII
float u
#define SOFFICE_FILEFORMAT_8
Definition: fileformat.h:29
#define SOFFICE_FILEFORMAT_60
Definition: fileformat.h:28
OUString aName
#define SAL_INFO(area, stream)
err
static uno::Reference< embed::XStorage > LookupStorageAtPath(const uno::Reference< embed::XStorage > &xParentStorage, std::vector< OUString > &rElems, sal_uInt32 nOpenMode, LifecycleProxy const &rNastiness)
const sal_Int32 nConstBufferSize
css::uno::Sequence< DstElementType > containerToSequence(const SrcType &i_Container)
Copy from a container into a Sequence.
Definition: sequence.hxx:190
Reference< XComponentContext > getProcessComponentContext()
This function gets the process service factory's default component context.
css::beans::PropertyValue makePropertyValue(const OUString &rName, T &&rValue)
Creates a beans::PropertyValue easily, i.e.
Any SAL_CALL getCaughtException()
Value
int i
ctx
constexpr bool starts_with(std::basic_string_view< charT, traits > sv, std::basic_string_view< charT, traits > x) noexcept
std::basic_string_view< charT, traits > getToken(std::basic_string_view< charT, traits > sv, charT delimiter, std::size_t &position)
OString OUStringToOString(std::u16string_view str, ConnectionSettings const *settings)
void splitPath(OString &rOrgPath, OString &rDir, OString &rBase)
constexpr OUStringLiteral PACKAGE_ENCRYPTIONDATA_SHA1UTF8
constexpr OUStringLiteral PACKAGE_ENCRYPTIONDATA_SHA1CORRECT
constexpr OUStringLiteral PACKAGE_ENCRYPTIONDATA_SHA1MS1252
constexpr OUStringLiteral PACKAGE_ENCRYPTIONDATA_SHA256UTF8
unsigned char sal_uInt8
signed char sal_Int8
Any result