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