diff options
Diffstat (limited to 'comphelper/source/misc/storagehelper.cxx')
-rw-r--r-- | comphelper/source/misc/storagehelper.cxx | 320 |
1 files changed, 168 insertions, 152 deletions
diff --git a/comphelper/source/misc/storagehelper.cxx b/comphelper/source/misc/storagehelper.cxx index 01cec5831223..b504aef0be61 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,18 @@ #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 <comphelper/xmlsechelper.hxx> #include <cppuhelper/exc_hlp.hxx> +#include <o3tl/string_view.hxx> #if HAVE_FEATURE_GPGME # include <context.h> @@ -98,10 +101,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 +113,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; @@ -136,7 +134,7 @@ uno::Reference< embed::XStorage > OStorageHelper::GetStorageFromURL2( if (!xFact.is()) { if (anyEx.hasValue()) - throw css::lang::WrappedTargetRuntimeException( "", nullptr, anyEx ); + throw css::lang::WrappedTargetRuntimeException( u""_ustr, nullptr, anyEx ); else throw uno::RuntimeException(); } @@ -151,10 +149,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 +161,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 +174,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 +221,7 @@ void OStorageHelper::SetCommonStorageEncryptionData( { uno::Reference< embed::XEncryptionProtectedStorage > xEncrSet( xStorage, uno::UNO_QUERY ); if ( !xEncrSet.is() ) - throw io::IOException(); // TODO + throw io::IOException(u"no XEncryptionProtectedStorage"_ustr); // TODO if ( aEncryptionData.getLength() == 2 && aEncryptionData[0].Name == "GpgInfos" && @@ -240,7 +243,7 @@ sal_Int32 OStorageHelper::GetXStorageFormat( uno::Reference< beans::XPropertySet > xStorProps( xStorage, uno::UNO_QUERY_THROW ); OUString aMediaType; - xStorProps->getPropertyValue("MediaType") >>= aMediaType; + xStorProps->getPropertyValue(u"MediaType"_ustr) >>= aMediaType; sal_Int32 nResult = 0; @@ -284,8 +287,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 +306,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(u"StorageFormat"_ustr, + 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 +322,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 +346,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( + 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,52 +412,56 @@ 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(), + 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()); } return aEncryptionData; } -uno::Sequence< beans::NamedValue > OStorageHelper::CreateGpgPackageEncryptionData() +uno::Sequence<beans::NamedValue> +OStorageHelper::CreateGpgPackageEncryptionData(const css::uno::Reference<css::awt::XWindow>& +#if HAVE_FEATURE_GPGME + xParentWindow +#endif +) { #if HAVE_FEATURE_GPGME // generate session key // -------------------- - rtlRandomPool aRandomPool = rtl_random_createPool(); - // get 32 random chars out of it uno::Sequence < sal_Int8 > aVector(32); - rtl_random_getBytes( aRandomPool, aVector.getArray(), aVector.getLength() ); - - rtl_random_destroyPool(aRandomPool); + if (rtl_random_getBytes(nullptr, aVector.getArray(), aVector.getLength()) != rtl_Random_E_None) + { + throw uno::RuntimeException(u"rtl_random_getBytes failed"_ustr); + } - 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 security::DocumentDigitalSignatures::createDefault( comphelper::getProcessComponentContext())); + xSigner->setParentWindow(xParentWindow); + // fire up certificate chooser dialog - user can multi-select! const uno::Sequence< uno::Reference< security::XCertificate > > xSignCertificates= - xSigner->chooseEncryptionCertificate(); + xSigner->chooseEncryptionCertificate(css::security::CertificateKind_OPENPGP); if (!xSignCertificates.hasElements()) return uno::Sequence< beans::NamedValue >(); // user cancelled @@ -486,24 +472,29 @@ uno::Sequence< beans::NamedValue > OStorageHelper::CreateGpgPackageEncryptionDat std::unique_ptr<GpgME::Context> ctx; GpgME::Error err = GpgME::checkEngine(GpgME::OpenPGP); 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); + throw uno::RuntimeException(u"The GpgME library failed to initialize for the OpenPGP protocol."_ustr); + bool bResetContext = true; for (const auto & cert : xSignCertificates) { - uno::Sequence < sal_Int8 > aKeyID; + if (bResetContext) + { + bResetContext = false; + ctx.reset( GpgME::Context::createForProtocol(GpgME::OpenPGP) ); + if (ctx == nullptr) + throw uno::RuntimeException(u"The GpgME library failed to initialize for the OpenPGP protocol."_ustr); + ctx->setArmor(false); + } + + OString aKeyID; if (cert.is()) - aKeyID = cert->getSHA1Thumbprint(); + { + aKeyID + = OUStringToOString(comphelper::xmlsec::GetHexString(cert->getSHA1Thumbprint(), ""), + RTL_TEXTENCODING_UTF8); + } - std::vector<GpgME::Key> keys; - keys.push_back( - ctx->key( - reinterpret_cast<const char*>(aKeyID.getConstArray()), - err, false)); + std::vector<GpgME::Key> keys{ ctx->key(aKeyID.getStr(), err, false) }; // ctx is setup now, let's encrypt the lot! GpgME::Data plain( @@ -515,6 +506,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); @@ -524,34 +538,34 @@ uno::Sequence< beans::NamedValue > OStorageHelper::CreateGpgPackageEncryptionDat if(crypt_res.error() || !len) throw lang::IllegalArgumentException( - "Not a suitable key, or failed to encrypt.", + u"Not a suitable key, or failed to encrypt."_ustr, css::uno::Reference<css::uno::XInterface>(), -1); uno::Sequence < sal_Int8 > aCipherValue(len); result = cipher.seek(0,SEEK_SET); assert(result == 0); if( cipher.read(aCipherValue.getArray(), len) != len ) - throw uno::RuntimeException("The GpgME library failed to read the encrypted value."); + throw uno::RuntimeException(u"The GpgME library failed to read the encrypted value."_ustr); 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<sal_Int8> aKeyIdSequence + = comphelper::arrayToSequence<sal_Int8>(aKeyID.getStr(), aKeyID.getLength() + 1); + uno::Sequence<beans::NamedValue> aGpgEncryptionEntry{ + { u"KeyId"_ustr, uno::Any(aKeyIdSequence) }, + { u"KeyPacket"_ustr, uno::Any(aKeyIdSequence) }, + { u"CipherValue"_ustr, 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 + = { { u"GpgInfos"_ustr, uno::Any(comphelper::containerToSequence(aGpgEncryptions)) }, + { u"EncryptionKey"_ustr, uno::Any(aEncryptionData) } }; return aContainer; #else @@ -559,19 +573,19 @@ uno::Sequence< beans::NamedValue > OStorageHelper::CreateGpgPackageEncryptionDat #endif } -bool OStorageHelper::IsValidZipEntryFileName( const OUString& aName, bool bSlashAllowed ) +bool OStorageHelper::IsValidZipEntryFileName( std::u16string_view aName, bool bSlashAllowed ) { - return IsValidZipEntryFileName( aName.getStr(), aName.getLength(), bSlashAllowed ); -} - - -bool OStorageHelper::IsValidZipEntryFileName( - const sal_Unicode *pChar, sal_Int32 nLength, bool bSlashAllowed ) -{ - for ( sal_Int32 i = 0; i < nLength; i++ ) + long nDots{0}; + for ( size_t i = 0; i < aName.size(); i++ ) { - switch ( pChar[i] ) + switch ( aName[i] ) { + case '.': + if (nDots != -1) + { + ++nDots; + } + break; case '\\': case '?': case '<': @@ -581,39 +595,41 @@ bool OStorageHelper::IsValidZipEntryFileName( case ':': return false; case '/': - if ( !bSlashAllowed ) + if (!bSlashAllowed || nDots == 1 || nDots == 2 || i == 0) return false; + nDots = 0; break; default: - if ( pChar[i] < 32 || (pChar[i] >= 0xD800 && pChar[i] <= 0xDFFF) ) + nDots = -1; + if ( aName[i] < 32 || (aName[i] >= 0xD800 && aName[i] <= 0xDFFF) ) return false; } } - return true; + return nDots != 1 && nDots != 2; } -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 +654,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 +677,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 +687,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; @@ -691,7 +706,7 @@ uno::Reference< io::XStream > OStorageHelper::GetStreamAtPackageURL( const OUString& rURL, sal_uInt32 const nOpenMode, LifecycleProxy const & rNastiness) { - OUString path; + std::u16string_view path; if (rURL.startsWithIgnoreAsciiCase("vnd.sun.star.Package:", &path)) { return GetStreamAtPath(xParentStorage, path, nOpenMode, rNastiness); @@ -704,8 +719,9 @@ OUString OStorageHelper::GetODFVersionFromStorage(const uno::Reference<embed::XS OUString aODFVersion; try { - uno::Reference<beans::XPropertySet> xPropSet(xStorage, uno::UNO_QUERY_THROW); - xPropSet->getPropertyValue("Version") >>= aODFVersion; + uno::Reference<beans::XPropertySet> xPropSet(xStorage, uno::UNO_QUERY); + if (xPropSet) + xPropSet->getPropertyValue(u"Version"_ustr) >>= aODFVersion; } catch (uno::Exception&) { |