20#include <config_gpgme.h>
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>
45#include <rtl/digest.h>
46#include <rtl/random.h>
47#include <osl/diagnose.h>
66# include <encryptionresult.h>
77 const uno::Reference< uno::XComponentContext >& rxContext )
81 return embed::StorageFactory::create( xContext );
86 const uno::Reference< uno::XComponentContext >& rxContext )
88 return embed::FileSystemStorageFactory::create(rxContext);
93 const uno::Reference< uno::XComponentContext >& rxContext )
96 uno::UNO_QUERY_THROW );
102 const OUString& aURL,
103 sal_Int32 nStorageMode,
104 const uno::Reference< uno::XComponentContext >& rxContext )
107 uno::Reference< embed::XStorage > xTempStorage(
GetStorageFactory( rxContext )->createInstanceWithArguments( aArgs ),
108 uno::UNO_QUERY_THROW );
114 const OUString& aURL,
115 sal_Int32 nStorageMode,
116 const uno::Reference< uno::XComponentContext >& rxContext )
120 uno::Reference< lang::XSingleServiceFactory > xFact;
124 uno::Reference< css::ucb::XCommandEnvironment > (),
131 }
catch (uno::Exception &)
138 if (anyEx.hasValue())
139 throw css::lang::WrappedTargetRuntimeException(
"",
nullptr, anyEx );
141 throw uno::RuntimeException();
144 uno::Reference< embed::XStorage > xTempStorage(
145 xFact->createInstanceWithArguments( aArgs ), uno::UNO_QUERY_THROW );
151 const uno::Reference < io::XInputStream >& xStream,
152 const uno::Reference< uno::XComponentContext >& rxContext )
155 uno::Reference< embed::XStorage > xTempStorage(
GetStorageFactory( rxContext )->createInstanceWithArguments( aArgs ),
156 uno::UNO_QUERY_THROW );
162 const uno::Reference < io::XStream >& xStream,
163 sal_Int32 nStorageMode,
164 const uno::Reference< uno::XComponentContext >& rxContext )
167 uno::Reference< embed::XStorage > xTempStorage(
GetStorageFactory( rxContext )->createInstanceWithArguments( aArgs ),
168 uno::UNO_QUERY_THROW );
174 const uno::Reference< io::XInputStream >& xInput,
175 const uno::Reference< io::XOutputStream >& xOutput )
179 if (
auto pByteReader =
dynamic_cast< comphelper::ByteReader*
>( xInput.get() ))
181 if (
auto pByteWriter =
dynamic_cast< comphelper::ByteWriter*
>( xOutput.get() ))
188 pByteWriter->writeBytes ( aTempBuf, nRead );
201 aSequence.realloc( nRead );
202 xOutput->writeBytes ( aSequence );
209 const OUString& aURL,
210 const uno::Reference< uno::XComponentContext >& context )
212 uno::Reference< io::XInputStream > xInputStream = ucb::SimpleFileAccess::create(context)->openFileRead(
aURL );
213 if ( !xInputStream.is() )
214 throw uno::RuntimeException();
221 const uno::Reference< embed::XStorage >& xStorage,
222 const uno::Sequence< beans::NamedValue >& aEncryptionData )
224 uno::Reference< embed::XEncryptionProtectedStorage > xEncrSet( xStorage, uno::UNO_QUERY );
225 if ( !xEncrSet.is() )
226 throw io::IOException(
"no XEncryptionProtectedStorage");
228 if ( aEncryptionData.getLength() == 2 &&
229 aEncryptionData[0].Name ==
"GpgInfos" &&
230 aEncryptionData[1].Name ==
"EncryptionKey" )
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 > >() );
238 xEncrSet->setEncryptionData( aEncryptionData );
243 const uno::Reference< embed::XStorage >& xStorage )
245 uno::Reference< beans::XPropertySet > xStorProps( xStorage, uno::UNO_QUERY_THROW );
248 xStorProps->getPropertyValue(
"MediaType") >>= aMediaType;
250 sal_Int32 nResult = 0;
292 OUString aMsg = __func__
293 + OUString::Concat(
u":")
294 + OUString::number(__LINE__)
295 +
": unknown media type '"
298 throw beans::IllegalTypeException(aMsg);
306 const OUString& aFormat,
307 const OUString& aURL,
308 sal_Int32 nStorageMode,
309 const uno::Reference< uno::XComponentContext >& rxContext )
315 uno::Reference< embed::XStorage > xTempStorage(
GetStorageFactory( rxContext )->createInstanceWithArguments( aArgs ),
316 uno::UNO_QUERY_THROW );
322 const OUString& aFormat,
323 const uno::Reference < io::XInputStream >& xStream,
324 const uno::Reference< uno::XComponentContext >& rxContext,
325 bool bRepairStorage )
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 )
333 pProps[1].Name =
"RepairPackage";
334 pProps[1].Value <<= bRepairStorage;
338 uno::Reference< embed::XStorage > xTempStorage(
GetStorageFactory( rxContext )->createInstanceWithArguments( aArgs ),
339 uno::UNO_QUERY_THROW );
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 )
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 )
357 pProps[1].Name =
"RepairPackage";
358 pProps[1].Value <<= bRepairStorage;
362 uno::Reference< embed::XStorage > xTempStorage(
GetStorageFactory( rxContext )->createInstanceWithArguments( aArgs ),
363 uno::UNO_QUERY_THROW );
371 uno::Sequence< beans::NamedValue > aEncryptionData;
372 if ( !aPassword.empty() )
374 sal_Int32 nSha1Ind = 0;
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 );
384 xDigestContext->updateDigest( uno::Sequence< sal_Int8 >(
reinterpret_cast< const sal_Int8*
>( aUTF8Password.getStr() ), aUTF8Password.getLength() ) );
385 uno::Sequence< sal_Int8 > aDigest = xDigestContext->finalizeDigestAndDispose();
390 catch ( uno::Exception& )
398 aEncryptionData.realloc( nSha1Ind + 3 );
399 auto pEncryptionData = aEncryptionData.getArray();
404 rtl_TextEncoding
const pEncoding[2] = { RTL_TEXTENCODING_UTF8, RTL_TEXTENCODING_MS_1252 };
406 for ( sal_Int32 nInd = 0; nInd < 2; nInd++ )
410 sal_uInt8 pBuffer[RTL_DIGEST_LENGTH_SHA1];
411 rtlDigestError nError = rtl_digest_SHA1( aByteStrPass.getStr(),
412 aByteStrPass.getLength(),
414 RTL_DIGEST_LENGTH_SHA1 );
416 if ( nError != rtl_Digest_E_None )
418 aEncryptionData.realloc( nSha1Ind );
419 return aEncryptionData;
423 pEncryptionData[nSha1Ind+nInd].Value <<= uno::Sequence< sal_Int8 >(
reinterpret_cast<sal_Int8*
>(pBuffer), RTL_DIGEST_LENGTH_SHA1 );
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());
436 return aEncryptionData;
441#if HAVE_FEATURE_GPGME
448 uno::Sequence < sal_Int8 > aVector(32);
449 rtl_random_getBytes( aRandomPool, aVector.getArray(), aVector.getLength() );
451 rtl_random_destroyPool(aRandomPool);
453 std::vector< uno::Sequence< beans::NamedValue > > aGpgEncryptions;
455 uno::Reference< security::XDocumentDigitalSignatures > xSigner(
457 security::DocumentDigitalSignatures::createDefault(
461 const uno::Sequence< uno::Reference< security::XCertificate > > xSignCertificates=
462 xSigner->chooseEncryptionCertificate();
464 if (!xSignCertificates.hasElements())
465 return uno::Sequence< beans::NamedValue >();
470 std::unique_ptr<GpgME::Context>
ctx;
471 GpgME::Error
err = GpgME::checkEngine(GpgME::OpenPGP);
473 throw uno::RuntimeException(
"The GpgME library failed to initialize for the OpenPGP protocol.");
475 ctx.reset( GpgME::Context::createForProtocol(GpgME::OpenPGP) );
477 throw uno::RuntimeException(
"The GpgME library failed to initialize for the OpenPGP protocol.");
478 ctx->setArmor(
false);
480 for (
const auto & cert : xSignCertificates)
482 uno::Sequence < sal_Int8 > aKeyID;
484 aKeyID = cert->getSHA1Thumbprint();
486 std::vector<GpgME::Key> keys
489 reinterpret_cast<const char*
>(aKeyID.getConstArray()),
495 reinterpret_cast<const char*
>(aVector.getConstArray()),
496 size_t(aVector.getLength()),
false);
499 GpgME::EncryptionResult crypt_res =
ctx->encrypt(
501 cipher, GpgME::Context::NoCompress);
503 off_t
result = cipher.seek(0,SEEK_SET);
506 int len=0, curr=0;
char buf;
507 while( (curr=cipher.read(&buf, 1)) )
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);
515 uno::Sequence < sal_Int8 > aCipherValue(len);
516 result = cipher.seek(0,SEEK_SET);
518 if( cipher.read(aCipherValue.getArray(), len) != len )
519 throw uno::RuntimeException(
"The GpgME library failed to read the encrypted value.");
521 SAL_INFO(
"comphelper.crypto",
"Generated gpg crypto of length: " << len);
523 uno::Sequence< beans::NamedValue > aGpgEncryptionEntry{
526 {
"CipherValue",
uno::Any(aCipherValue) }
529 aGpgEncryptions.push_back(aGpgEncryptionEntry);
532 uno::Sequence<beans::NamedValue> aEncryptionData
535 uno::Sequence<beans::NamedValue> aContainer
537 {
"EncryptionKey",
uno::Any(aEncryptionData) } };
541 return uno::Sequence< beans::NamedValue >();
547 for (
size_t i = 0;
i <
aName.size();
i++ )
560 if ( !bSlashAllowed )
574 bool bResult =
false;
575 const size_t nPathLen = aPath.size();
576 const size_t nSegLen = aSegment.size();
578 if ( !aSegment.empty() && nPathLen >= nSegLen )
580 OUString aEndSegment = OUString::Concat(
"/") + aSegment;
581 OUString aInternalSegment = aEndSegment +
"/";
583 if ( aPath.find( aInternalSegment ) != std::u16string_view::npos )
588 if ( nPathLen == nSegLen || aPath[nSegLen] ==
'/' )
592 if ( !bResult && nPathLen > nSegLen && aPath.substr( nPathLen - nSegLen - 1, nSegLen + 1 ) == aEndSegment )
600 :
public std::vector< uno::Reference< embed::XStorage > > {};
602 : m_xBadness( new
Impl ) { }
608 [](Impl::reference rxItem) {
609 uno::Reference<embed::XTransactedObject> const xTransaction(rxItem, uno::UNO_QUERY);
610 if (xTransaction.is())
612 xTransaction->commit();
617static void splitPath( std::vector<OUString> &rElems, std::u16string_view rPath )
619 for (sal_Int32
i = 0;
i >= 0;)
624 const uno::Reference< embed::XStorage > &xParentStorage,
625 std::vector<OUString> &rElems, sal_uInt32 nOpenMode,
628 uno::Reference< embed::XStorage > xStorage( xParentStorage );
630 for(
size_t i = 0;
i < rElems.size() && xStorage.is();
i++ )
632 xStorage = xStorage->openStorageElement( rElems[
i], nOpenMode );
638uno::Reference< embed::XStorage > OStorageHelper::GetStorageAtPath(
639 const uno::Reference< embed::XStorage > &xStorage,
640 std::u16string_view rPath, sal_uInt32 nOpenMode,
643 std::vector<OUString> aElems;
648uno::Reference< io::XStream > OStorageHelper::GetStreamAtPath(
649 const uno::Reference< embed::XStorage > &xParentStorage,
650 std::u16string_view rPath, sal_uInt32 nOpenMode,
653 std::vector<OUString> aElems;
655 OUString
aName( aElems.back() );
657 sal_uInt32 nStorageMode = nOpenMode & ~embed::ElementModes::TRUNCATE;
658 uno::Reference< embed::XStorage > xStorage(
660 uno::UNO_SET_THROW );
661 return xStorage->openStreamElement(
aName, nOpenMode );
664uno::Reference< io::XStream > OStorageHelper::GetStreamAtPackageURL(
665 uno::Reference< embed::XStorage >
const& xParentStorage,
666 const OUString& rURL, sal_uInt32
const nOpenMode,
670 if (rURL.startsWithIgnoreAsciiCase(
"vnd.sun.star.Package:", &path))
672 return GetStreamAtPath(xParentStorage, path, nOpenMode, rNastiness);
677OUString OStorageHelper::GetODFVersionFromStorage(
const uno::Reference<embed::XStorage>& xStorage)
679 OUString aODFVersion;
682 uno::Reference<beans::XPropertySet> xPropSet(xStorage, uno::UNO_QUERY_THROW);
683 xPropSet->getPropertyValue(
"Version") >>= aODFVersion;
685 catch (uno::Exception&)
HRESULT createInstance(REFIID iid, Ifc **ppIfc)
static std::vector< unsigned char > calculateHash(const unsigned char *pInput, size_t length, HashType eType)
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.
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
#define SAL_INFO(area, stream)
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.
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()
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