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