diff options
Diffstat (limited to 'comphelper/source/misc/storagehelper.cxx')
-rw-r--r-- | comphelper/source/misc/storagehelper.cxx | 263 |
1 files changed, 132 insertions, 131 deletions
diff --git a/comphelper/source/misc/storagehelper.cxx b/comphelper/source/misc/storagehelper.cxx index 01cec5831223..c2d295c54f26 100644 --- a/comphelper/source/misc/storagehelper.cxx +++ b/comphelper/source/misc/storagehelper.cxx @@ -27,15 +27,13 @@ #include <com/sun/star/embed/FileSystemStorageFactory.hpp> #include <com/sun/star/io/IOException.hpp> #include <com/sun/star/lang/XSingleServiceFactory.hpp> +#include <com/sun/star/lang/XUnoTunnel.hpp> #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp> #include <com/sun/star/ucb/SimpleFileAccess.hpp> #include <com/sun/star/beans/XPropertySet.hpp> #include <com/sun/star/beans/PropertyValue.hpp> #include <com/sun/star/beans/NamedValue.hpp> #include <com/sun/star/beans/IllegalTypeException.hpp> -#include <com/sun/star/xml/crypto/NSSInitializer.hpp> -#include <com/sun/star/xml/crypto/XDigestContext.hpp> -#include <com/sun/star/xml/crypto/DigestID.hpp> #include <com/sun/star/security/DocumentDigitalSignatures.hpp> #include <com/sun/star/security/XCertificate.hpp> @@ -48,13 +46,17 @@ #include <ucbhelper/content.hxx> +#include <comphelper/bytereader.hxx> +#include <comphelper/diagnose_ex.hxx> #include <comphelper/fileformat.h> #include <comphelper/hash.hxx> #include <comphelper/processfactory.hxx> #include <comphelper/documentconstants.hxx> +#include <comphelper/propertyvalue.hxx> #include <comphelper/storagehelper.hxx> #include <comphelper/sequence.hxx> #include <cppuhelper/exc_hlp.hxx> +#include <o3tl/string_view.hxx> #if HAVE_FEATURE_GPGME # include <context.h> @@ -98,10 +100,7 @@ uno::Reference< embed::XStorage > OStorageHelper::GetStorageFromURL( sal_Int32 nStorageMode, const uno::Reference< uno::XComponentContext >& rxContext ) { - uno::Sequence< uno::Any > aArgs( 2 ); - aArgs[0] <<= aURL; - aArgs[1] <<= nStorageMode; - + uno::Sequence< uno::Any > aArgs{ uno::Any(aURL), uno::Any(nStorageMode) }; uno::Reference< embed::XStorage > xTempStorage( GetStorageFactory( rxContext )->createInstanceWithArguments( aArgs ), uno::UNO_QUERY_THROW ); return xTempStorage; @@ -113,9 +112,7 @@ uno::Reference< embed::XStorage > OStorageHelper::GetStorageFromURL2( sal_Int32 nStorageMode, const uno::Reference< uno::XComponentContext >& rxContext ) { - uno::Sequence< uno::Any > aArgs( 2 ); - aArgs[0] <<= aURL; - aArgs[1] <<= nStorageMode; + uno::Sequence< uno::Any > aArgs{ uno::Any(aURL), uno::Any(nStorageMode) }; uno::Reference< lang::XSingleServiceFactory > xFact; css::uno::Any anyEx; @@ -151,10 +148,7 @@ uno::Reference< embed::XStorage > OStorageHelper::GetStorageFromInputStream( const uno::Reference < io::XInputStream >& xStream, const uno::Reference< uno::XComponentContext >& rxContext ) { - uno::Sequence< uno::Any > aArgs( 2 ); - aArgs[0] <<= xStream; - aArgs[1] <<= embed::ElementModes::READ; - + uno::Sequence< uno::Any > aArgs{ uno::Any(xStream), uno::Any(embed::ElementModes::READ) }; uno::Reference< embed::XStorage > xTempStorage( GetStorageFactory( rxContext )->createInstanceWithArguments( aArgs ), uno::UNO_QUERY_THROW ); return xTempStorage; @@ -166,10 +160,7 @@ uno::Reference< embed::XStorage > OStorageHelper::GetStorageFromStream( sal_Int32 nStorageMode, const uno::Reference< uno::XComponentContext >& rxContext ) { - uno::Sequence< uno::Any > aArgs( 2 ); - aArgs[0] <<= xStream; - aArgs[1] <<= nStorageMode; - + uno::Sequence< uno::Any > aArgs{ uno::Any(xStream), uno::Any(nStorageMode) }; uno::Reference< embed::XStorage > xTempStorage( GetStorageFactory( rxContext )->createInstanceWithArguments( aArgs ), uno::UNO_QUERY_THROW ); return xTempStorage; @@ -182,19 +173,30 @@ void OStorageHelper::CopyInputToOutput( { static const sal_Int32 nConstBufferSize = 32000; + if (auto pByteReader = dynamic_cast< comphelper::ByteReader* >( xInput.get() )) + { + if (auto pByteWriter = dynamic_cast< comphelper::ByteWriter* >( xOutput.get() )) + { + sal_Int32 nRead; + sal_Int8 aTempBuf[ nConstBufferSize ]; + do + { + nRead = pByteReader->readSomeBytes ( aTempBuf, nConstBufferSize ); + pByteWriter->writeBytes ( aTempBuf, nRead ); + } + while ( nRead == nConstBufferSize ); + return; + } + } + sal_Int32 nRead; uno::Sequence < sal_Int8 > aSequence ( nConstBufferSize ); - do { nRead = xInput->readBytes ( aSequence, nConstBufferSize ); if ( nRead < nConstBufferSize ) - { - uno::Sequence < sal_Int8 > aTempBuf ( aSequence.getConstArray(), nRead ); - xOutput->writeBytes ( aTempBuf ); - } - else - xOutput->writeBytes ( aSequence ); + aSequence.realloc( nRead ); + xOutput->writeBytes ( aSequence ); } while ( nRead == nConstBufferSize ); } @@ -218,7 +220,7 @@ void OStorageHelper::SetCommonStorageEncryptionData( { uno::Reference< embed::XEncryptionProtectedStorage > xEncrSet( xStorage, uno::UNO_QUERY ); if ( !xEncrSet.is() ) - throw io::IOException(); // TODO + throw io::IOException("no XEncryptionProtectedStorage"); // TODO if ( aEncryptionData.getLength() == 2 && aEncryptionData[0].Name == "GpgInfos" && @@ -284,8 +286,8 @@ sal_Int32 OStorageHelper::GetXStorageFormat( else { // the mediatype is not known - OUString aMsg = OUStringLiteral(OSL_THIS_FUNC) - + ":" + OUString aMsg = __func__ + + OUString::Concat(u":") + OUString::number(__LINE__) + ": unknown media type '" + aMediaType @@ -303,15 +305,10 @@ uno::Reference< embed::XStorage > OStorageHelper::GetStorageOfFormatFromURL( sal_Int32 nStorageMode, const uno::Reference< uno::XComponentContext >& rxContext ) { - uno::Sequence< beans::PropertyValue > aProps( 1 ); - aProps[0].Name = "StorageFormat"; - aProps[0].Value <<= aFormat; - - uno::Sequence< uno::Any > aArgs( 3 ); - aArgs[0] <<= aURL; - aArgs[1] <<= nStorageMode; - aArgs[2] <<= aProps; + uno::Sequence< beans::PropertyValue > aProps{ comphelper::makePropertyValue("StorageFormat", + aFormat) }; + uno::Sequence< uno::Any > aArgs{ uno::Any(aURL), uno::Any(nStorageMode), uno::Any(aProps) }; uno::Reference< embed::XStorage > xTempStorage( GetStorageFactory( rxContext )->createInstanceWithArguments( aArgs ), uno::UNO_QUERY_THROW ); return xTempStorage; @@ -324,24 +321,17 @@ uno::Reference< embed::XStorage > OStorageHelper::GetStorageOfFormatFromInputStr const uno::Reference< uno::XComponentContext >& rxContext, bool bRepairStorage ) { - uno::Sequence< beans::PropertyValue > aProps( 1 ); - sal_Int32 nPos = 0; - aProps[nPos].Name = "StorageFormat"; - aProps[nPos].Value <<= aFormat; - ++nPos; + uno::Sequence< beans::PropertyValue > aProps( bRepairStorage ? 2 : 1 ); + auto pProps = aProps.getArray(); + pProps[0].Name = "StorageFormat"; + pProps[0].Value <<= aFormat; if ( bRepairStorage ) { - aProps.realloc(nPos+1); - aProps[nPos].Name = "RepairPackage"; - aProps[nPos].Value <<= bRepairStorage; - ++nPos; + pProps[1].Name = "RepairPackage"; + pProps[1].Value <<= bRepairStorage; } - uno::Sequence< uno::Any > aArgs( 3 ); - aArgs[0] <<= xStream; - aArgs[1] <<= embed::ElementModes::READ; - aArgs[2] <<= aProps; - + uno::Sequence< uno::Any > aArgs{ uno::Any(xStream), uno::Any(embed::ElementModes::READ), uno::Any(aProps) }; uno::Reference< embed::XStorage > xTempStorage( GetStorageFactory( rxContext )->createInstanceWithArguments( aArgs ), uno::UNO_QUERY_THROW ); return xTempStorage; @@ -355,65 +345,56 @@ uno::Reference< embed::XStorage > OStorageHelper::GetStorageOfFormatFromStream( const uno::Reference< uno::XComponentContext >& rxContext, bool bRepairStorage ) { - uno::Sequence< beans::PropertyValue > aProps( 1 ); - sal_Int32 nPos = 0; - aProps[nPos].Name = "StorageFormat"; - aProps[nPos].Value <<= aFormat; - ++nPos; + uno::Sequence< beans::PropertyValue > aProps( bRepairStorage ? 2 : 1 ); + auto pProps = aProps.getArray(); + pProps[0].Name = "StorageFormat"; + pProps[0].Value <<= aFormat; if ( bRepairStorage ) { - aProps.realloc(nPos+1); - aProps[nPos].Name = "RepairPackage"; - aProps[nPos].Value <<= bRepairStorage; - ++nPos; + pProps[1].Name = "RepairPackage"; + pProps[1].Value <<= bRepairStorage; } - uno::Sequence< uno::Any > aArgs( 3 ); - aArgs[0] <<= xStream; - aArgs[1] <<= nStorageMode; - aArgs[2] <<= aProps; - + uno::Sequence< uno::Any > aArgs{ uno::Any(xStream), uno::Any(nStorageMode), uno::Any(aProps) }; uno::Reference< embed::XStorage > xTempStorage( GetStorageFactory( rxContext )->createInstanceWithArguments( aArgs ), uno::UNO_QUERY_THROW ); return xTempStorage; } -uno::Sequence< beans::NamedValue > OStorageHelper::CreatePackageEncryptionData( const OUString& aPassword ) +uno::Sequence< beans::NamedValue > OStorageHelper::CreatePackageEncryptionData( std::u16string_view aPassword ) { // TODO/LATER: Should not the method be part of DocPasswordHelper? uno::Sequence< beans::NamedValue > aEncryptionData; - if ( !aPassword.isEmpty() ) + if ( !aPassword.empty() ) { sal_Int32 nSha1Ind = 0; // generate SHA256 start key try { - uno::Reference< uno::XComponentContext > xContext = ::comphelper::getProcessComponentContext(); - - uno::Reference< css::xml::crypto::XNSSInitializer > xDigestContextSupplier = css::xml::crypto::NSSInitializer::create(xContext); - uno::Reference< css::xml::crypto::XDigestContext > xDigestContext( xDigestContextSupplier->getDigestContext( css::xml::crypto::DigestID::SHA256, uno::Sequence< beans::NamedValue >() ), uno::UNO_SET_THROW ); - OString aUTF8Password( OUStringToOString( aPassword, RTL_TEXTENCODING_UTF8 ) ); - xDigestContext->updateDigest( uno::Sequence< sal_Int8 >( reinterpret_cast< const sal_Int8* >( aUTF8Password.getStr() ), aUTF8Password.getLength() ) ); - uno::Sequence< sal_Int8 > aDigest = xDigestContext->finalizeDigestAndDispose(); + std::vector<unsigned char> const hash(comphelper::Hash::calculateHash( + reinterpret_cast<unsigned char const*>(aUTF8Password.getStr()), aUTF8Password.getLength(), + comphelper::HashType::SHA256)); + uno::Sequence<sal_Int8> aDigest(reinterpret_cast<const sal_Int8*>(hash.data()), hash.size()); - aEncryptionData.realloc( ++nSha1Ind ); - aEncryptionData[0].Name = PACKAGE_ENCRYPTIONDATA_SHA256UTF8; - aEncryptionData[0].Value <<= aDigest; + ++nSha1Ind; + aEncryptionData = { { PACKAGE_ENCRYPTIONDATA_SHA256UTF8, uno::Any(aDigest) } }; } catch ( uno::Exception& ) { - OSL_ENSURE( false, "Can not create SHA256 digest!" ); + TOOLS_WARN_EXCEPTION("comphelper", "Can not create SHA256 digest!" ); + throw; // tdf#159519 DO NOT RETURN SUCCESS } // MS_1252 encoding was used for SO60 document format password encoding, // this encoding supports only a minor subset of nonascii characters, // but for compatibility reasons it has to be used for old document formats aEncryptionData.realloc( nSha1Ind + 3 ); + auto pEncryptionData = aEncryptionData.getArray(); // these are StarOffice not-quite-SHA1 - aEncryptionData[nSha1Ind].Name = PACKAGE_ENCRYPTIONDATA_SHA1UTF8; - aEncryptionData[nSha1Ind + 1].Name = PACKAGE_ENCRYPTIONDATA_SHA1MS1252; + pEncryptionData[nSha1Ind].Name = PACKAGE_ENCRYPTIONDATA_SHA1UTF8; + pEncryptionData[nSha1Ind + 1].Name = PACKAGE_ENCRYPTIONDATA_SHA1MS1252; rtl_TextEncoding const pEncoding[2] = { RTL_TEXTENCODING_UTF8, RTL_TEXTENCODING_MS_1252 }; @@ -430,19 +411,20 @@ uno::Sequence< beans::NamedValue > OStorageHelper::CreatePackageEncryptionData( if ( nError != rtl_Digest_E_None ) { aEncryptionData.realloc( nSha1Ind ); - break; + return aEncryptionData; } - aEncryptionData[nSha1Ind+nInd].Value <<= uno::Sequence< sal_Int8 >( reinterpret_cast<sal_Int8*>(pBuffer), RTL_DIGEST_LENGTH_SHA1 ); + // coverity[overrun-buffer-arg : FALSE] - coverity has difficulty with css::uno::Sequence + pEncryptionData[nSha1Ind+nInd].Value <<= uno::Sequence< sal_Int8 >( reinterpret_cast<sal_Int8*>(pBuffer), RTL_DIGEST_LENGTH_SHA1 ); } // actual SHA1 - aEncryptionData[nSha1Ind + 2].Name = PACKAGE_ENCRYPTIONDATA_SHA1CORRECT; + pEncryptionData[nSha1Ind + 2].Name = PACKAGE_ENCRYPTIONDATA_SHA1CORRECT; OString aByteStrPass = OUStringToOString(aPassword, RTL_TEXTENCODING_UTF8); std::vector<unsigned char> const sha1(::comphelper::Hash::calculateHash( reinterpret_cast<unsigned char const*>(aByteStrPass.getStr()), aByteStrPass.getLength(), ::comphelper::HashType::SHA1)); - aEncryptionData[nSha1Ind + 2].Value <<= uno::Sequence<sal_Int8>( + pEncryptionData[nSha1Ind + 2].Value <<= uno::Sequence<sal_Int8>( reinterpret_cast<sal_Int8 const*>(sha1.data()), sha1.size()); } @@ -459,14 +441,14 @@ uno::Sequence< beans::NamedValue > OStorageHelper::CreateGpgPackageEncryptionDat // get 32 random chars out of it uno::Sequence < sal_Int8 > aVector(32); - rtl_random_getBytes( aRandomPool, aVector.getArray(), aVector.getLength() ); + if (rtl_random_getBytes(aRandomPool, aVector.getArray(), aVector.getLength()) != rtl_Random_E_None) + { + throw uno::RuntimeException("rtl_random_getBytes failed"); + } rtl_random_destroyPool(aRandomPool); - uno::Sequence< beans::NamedValue > aContainer(2); std::vector< uno::Sequence< beans::NamedValue > > aGpgEncryptions; - uno::Sequence< beans::NamedValue > aGpgEncryptionEntry(3); - uno::Sequence< beans::NamedValue > aEncryptionData(1); uno::Reference< security::XDocumentDigitalSignatures > xSigner( // here none of the version-dependent methods are called @@ -488,22 +470,28 @@ uno::Sequence< beans::NamedValue > OStorageHelper::CreateGpgPackageEncryptionDat if (err) throw uno::RuntimeException("The GpgME library failed to initialize for the OpenPGP protocol."); - ctx.reset( GpgME::Context::createForProtocol(GpgME::OpenPGP) ); - if (ctx == nullptr) - throw uno::RuntimeException("The GpgME library failed to initialize for the OpenPGP protocol."); - ctx->setArmor(false); - + bool bResetContext = true; for (const auto & cert : xSignCertificates) { + if (bResetContext) + { + bResetContext = false; + ctx.reset( GpgME::Context::createForProtocol(GpgME::OpenPGP) ); + if (ctx == nullptr) + throw uno::RuntimeException("The GpgME library failed to initialize for the OpenPGP protocol."); + ctx->setArmor(false); + } + uno::Sequence < sal_Int8 > aKeyID; if (cert.is()) aKeyID = cert->getSHA1Thumbprint(); - std::vector<GpgME::Key> keys; - keys.push_back( + std::vector<GpgME::Key> keys + { ctx->key( reinterpret_cast<const char*>(aKeyID.getConstArray()), - err, false)); + err, false) + }; // ctx is setup now, let's encrypt the lot! GpgME::Data plain( @@ -515,6 +503,29 @@ uno::Sequence< beans::NamedValue > OStorageHelper::CreateGpgPackageEncryptionDat keys, plain, cipher, GpgME::Context::NoCompress); + // tdf#160184 ask user if they want to trust an untrusted certificate + // gpgme contexts uses the "auto" trust model by default which only + // allows encrypting with keys that have their trust level set to + // "Ultimate". The gpg command, however, gives the user the option + // to encrypt with a certificate that has a lower trust level so + // emulate that behavior by asking the user if they want to trust + // the certificate for just this operation only. + if (crypt_res.error().code() == GPG_ERR_UNUSABLE_PUBKEY) + { + if (xSigner->trustUntrustedCertificate(cert)) + { + // Reset the trust model back to "auto" before processing + // the next certificate + bResetContext = true; + + ctx->setFlag("trust-model", "tofu+pgp"); + ctx->setFlag("tofu-default-policy", "unknown"); + crypt_res = ctx->encrypt( + keys, plain, + cipher, GpgME::Context::NoCompress); + } + } + off_t result = cipher.seek(0,SEEK_SET); (void) result; assert(result == 0); @@ -535,23 +546,21 @@ uno::Sequence< beans::NamedValue > OStorageHelper::CreateGpgPackageEncryptionDat SAL_INFO("comphelper.crypto", "Generated gpg crypto of length: " << len); - aGpgEncryptionEntry[0].Name = "KeyId"; - aGpgEncryptionEntry[0].Value <<= aKeyID; - aGpgEncryptionEntry[1].Name = "KeyPacket"; - aGpgEncryptionEntry[1].Value <<= aKeyID; - aGpgEncryptionEntry[2].Name = "CipherValue"; - aGpgEncryptionEntry[2].Value <<= aCipherValue; + uno::Sequence< beans::NamedValue > aGpgEncryptionEntry{ + { "KeyId", uno::Any(aKeyID) }, + { "KeyPacket", uno::Any(aKeyID) }, + { "CipherValue", uno::Any(aCipherValue) } + }; aGpgEncryptions.push_back(aGpgEncryptionEntry); } - aEncryptionData[0].Name = PACKAGE_ENCRYPTIONDATA_SHA256UTF8; - aEncryptionData[0].Value <<= aVector; + uno::Sequence<beans::NamedValue> aEncryptionData + = { { PACKAGE_ENCRYPTIONDATA_SHA256UTF8, uno::Any(aVector) } }; - aContainer[0].Name = "GpgInfos"; - aContainer[0].Value <<= comphelper::containerToSequence(aGpgEncryptions); - aContainer[1].Name = "EncryptionKey"; - aContainer[1].Value <<= aEncryptionData; + uno::Sequence<beans::NamedValue> aContainer + = { { "GpgInfos", uno::Any(comphelper::containerToSequence(aGpgEncryptions)) }, + { "EncryptionKey", uno::Any(aEncryptionData) } }; return aContainer; #else @@ -559,18 +568,11 @@ uno::Sequence< beans::NamedValue > OStorageHelper::CreateGpgPackageEncryptionDat #endif } -bool OStorageHelper::IsValidZipEntryFileName( const OUString& aName, bool bSlashAllowed ) -{ - return IsValidZipEntryFileName( aName.getStr(), aName.getLength(), bSlashAllowed ); -} - - -bool OStorageHelper::IsValidZipEntryFileName( - const sal_Unicode *pChar, sal_Int32 nLength, bool bSlashAllowed ) +bool OStorageHelper::IsValidZipEntryFileName( std::u16string_view aName, bool bSlashAllowed ) { - for ( sal_Int32 i = 0; i < nLength; i++ ) + for ( size_t i = 0; i < aName.size(); i++ ) { - switch ( pChar[i] ) + switch ( aName[i] ) { case '\\': case '?': @@ -585,7 +587,7 @@ bool OStorageHelper::IsValidZipEntryFileName( return false; break; default: - if ( pChar[i] < 32 || (pChar[i] >= 0xD800 && pChar[i] <= 0xDFFF) ) + if ( aName[i] < 32 || (aName[i] >= 0xD800 && aName[i] <= 0xDFFF) ) return false; } } @@ -593,27 +595,27 @@ bool OStorageHelper::IsValidZipEntryFileName( } -bool OStorageHelper::PathHasSegment( const OUString& aPath, const OUString& aSegment ) +bool OStorageHelper::PathHasSegment( std::u16string_view aPath, std::u16string_view aSegment ) { bool bResult = false; - const sal_Int32 nPathLen = aPath.getLength(); - const sal_Int32 nSegLen = aSegment.getLength(); + const size_t nPathLen = aPath.size(); + const size_t nSegLen = aSegment.size(); - if ( !aSegment.isEmpty() && nPathLen >= nSegLen ) + if ( !aSegment.empty() && nPathLen >= nSegLen ) { - OUString aEndSegment = "/" + aSegment; + OUString aEndSegment = OUString::Concat("/") + aSegment; OUString aInternalSegment = aEndSegment + "/"; - if ( aPath.indexOf( aInternalSegment ) >= 0 ) + if ( aPath.find( aInternalSegment ) != std::u16string_view::npos ) bResult = true; - if ( !bResult && aPath.startsWith( aSegment ) ) + if ( !bResult && o3tl::starts_with(aPath, aSegment ) ) { if ( nPathLen == nSegLen || aPath[nSegLen] == '/' ) bResult = true; } - if ( !bResult && nPathLen > nSegLen && aPath.copy( nPathLen - nSegLen - 1, nSegLen + 1 ) == aEndSegment ) + if ( !bResult && nPathLen > nSegLen && aPath.substr( nPathLen - nSegLen - 1, nSegLen + 1 ) == aEndSegment ) bResult = true; } @@ -638,11 +640,10 @@ void LifecycleProxy::commitStorages() }); } -static void splitPath( std::vector<OUString> &rElems, - const OUString& rPath ) +static void splitPath( std::vector<OUString> &rElems, std::u16string_view rPath ) { for (sal_Int32 i = 0; i >= 0;) - rElems.push_back( rPath.getToken( 0, '/', i ) ); + rElems.push_back( OUString(o3tl::getToken(rPath, 0, '/', i )) ); } static uno::Reference< embed::XStorage > LookupStorageAtPath( @@ -662,7 +663,7 @@ static uno::Reference< embed::XStorage > LookupStorageAtPath( uno::Reference< embed::XStorage > OStorageHelper::GetStorageAtPath( const uno::Reference< embed::XStorage > &xStorage, - const OUString& rPath, sal_uInt32 nOpenMode, + std::u16string_view rPath, sal_uInt32 nOpenMode, LifecycleProxy const &rNastiness ) { std::vector<OUString> aElems; @@ -672,7 +673,7 @@ uno::Reference< embed::XStorage > OStorageHelper::GetStorageAtPath( uno::Reference< io::XStream > OStorageHelper::GetStreamAtPath( const uno::Reference< embed::XStorage > &xParentStorage, - const OUString& rPath, sal_uInt32 nOpenMode, + std::u16string_view rPath, sal_uInt32 nOpenMode, LifecycleProxy const &rNastiness ) { std::vector<OUString> aElems; |