File: | home/maarten/src/libreoffice/core/sc/source/filter/excel/excel.cxx |
Warning: | line 226, column 9 Use of memory after it is freed |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 <sfx2/docfile.hxx> | ||||
21 | #include <sfx2/frame.hxx> | ||||
22 | #include <sfx2/sfxsids.hrc> | ||||
23 | #include <sot/storage.hxx> | ||||
24 | #include <sot/exchange.hxx> | ||||
25 | #include <filter/msfilter/classids.hxx> | ||||
26 | #include <tools/globname.hxx> | ||||
27 | #include <com/sun/star/packages/XPackageEncryption.hpp> | ||||
28 | #include <com/sun/star/ucb/ContentCreationException.hpp> | ||||
29 | #include <com/sun/star/uno/XComponentContext.hpp> | ||||
30 | #include <unotools/streamwrap.hxx> | ||||
31 | #include <unotools/defaultencoding.hxx> | ||||
32 | #include <unotools/wincodepage.hxx> | ||||
33 | #include <osl/diagnose.h> | ||||
34 | #include <filter.hxx> | ||||
35 | #include <document.hxx> | ||||
36 | #include <xistream.hxx> | ||||
37 | #include <xltools.hxx> | ||||
38 | #include <docoptio.hxx> | ||||
39 | #include <comphelper/sequenceashashmap.hxx> | ||||
40 | #include <comphelper/processfactory.hxx> | ||||
41 | |||||
42 | #include <docsh.hxx> | ||||
43 | #include <scerrors.hxx> | ||||
44 | #include <imp_op.hxx> | ||||
45 | #include <excimp8.hxx> | ||||
46 | #include <exp_op.hxx> | ||||
47 | #include <scdll.hxx> | ||||
48 | |||||
49 | #include <memory> | ||||
50 | |||||
51 | using namespace css; | ||||
52 | |||||
53 | static void lcl_getListOfStreams(SotStorage * pStorage, comphelper::SequenceAsHashMap& aStreamsData, const OUString& sPrefix) | ||||
54 | { | ||||
55 | SvStorageInfoList aElements; | ||||
56 | pStorage->FillInfoList(&aElements); | ||||
57 | for (const auto & aElement : aElements) | ||||
58 | { | ||||
59 | OUString sStreamFullName = sPrefix.getLength() ? sPrefix + "/" + aElement.GetName() : aElement.GetName(); | ||||
60 | if (aElement.IsStorage()) | ||||
61 | { | ||||
62 | tools::SvRef<SotStorage> xSubStorage = pStorage->OpenSotStorage(aElement.GetName(), StreamMode::STD_READ | StreamMode::SHARE_DENYALL); | ||||
63 | lcl_getListOfStreams(xSubStorage.get(), aStreamsData, sStreamFullName); | ||||
64 | } | ||||
65 | else | ||||
66 | { | ||||
67 | // Read stream | ||||
68 | tools::SvRef<SotStorageStream> rStream = pStorage->OpenSotStream(aElement.GetName(), StreamMode::READ | StreamMode::SHARE_DENYALL); | ||||
69 | if (rStream.is()) | ||||
70 | { | ||||
71 | sal_Int32 nStreamSize = rStream->GetSize(); | ||||
72 | uno::Sequence< sal_Int8 > oData; | ||||
73 | oData.realloc(nStreamSize); | ||||
74 | sal_Int32 nReadBytes = rStream->ReadBytes(oData.getArray(), nStreamSize); | ||||
75 | if (nStreamSize == nReadBytes) | ||||
76 | aStreamsData[sStreamFullName] <<= oData; | ||||
77 | } | ||||
78 | } | ||||
79 | } | ||||
80 | } | ||||
81 | |||||
82 | static tools::SvRef<SotStorage> lcl_DRMDecrypt(const SfxMedium& rMedium, const tools::SvRef<SotStorage>& rStorage, std::shared_ptr<SvStream>& rNewStorageStrm) | ||||
83 | { | ||||
84 | tools::SvRef<SotStorage> aNewStorage; | ||||
85 | |||||
86 | // We have DRM encrypted storage. We should try to decrypt it first, if we can | ||||
87 | uno::Sequence< uno::Any > aArguments; | ||||
88 | uno::Reference<uno::XComponentContext> xComponentContext(comphelper::getProcessComponentContext()); | ||||
89 | uno::Reference< packages::XPackageEncryption > xPackageEncryption( | ||||
90 | xComponentContext->getServiceManager()->createInstanceWithArgumentsAndContext( | ||||
91 | "com.sun.star.comp.oox.crypto.DRMDataSpace", aArguments, xComponentContext), uno::UNO_QUERY); | ||||
92 | |||||
93 | if (!xPackageEncryption.is()) | ||||
94 | { | ||||
95 | // We do not know how to decrypt this | ||||
96 | return aNewStorage; | ||||
97 | } | ||||
98 | |||||
99 | comphelper::SequenceAsHashMap aStreamsData; | ||||
100 | lcl_getListOfStreams(rStorage.get(), aStreamsData, ""); | ||||
101 | |||||
102 | try { | ||||
103 | uno::Sequence<beans::NamedValue> aStreams = aStreamsData.getAsConstNamedValueList(); | ||||
104 | if (!xPackageEncryption->readEncryptionInfo(aStreams)) | ||||
105 | { | ||||
106 | // We failed with decryption | ||||
107 | return aNewStorage; | ||||
108 | } | ||||
109 | |||||
110 | tools::SvRef<SotStorageStream> rContentStream = rStorage->OpenSotStream("\011DRMContent", StreamMode::READ | StreamMode::SHARE_DENYALL); | ||||
111 | if (!rContentStream.is()) | ||||
112 | { | ||||
113 | return aNewStorage; | ||||
114 | } | ||||
115 | |||||
116 | rNewStorageStrm = std::make_shared<SvMemoryStream>(); | ||||
117 | |||||
118 | uno::Reference<io::XInputStream > xInputStream(new utl::OSeekableInputStreamWrapper(rContentStream.get(), false)); | ||||
119 | uno::Reference<io::XOutputStream > xDecryptedStream(new utl::OSeekableOutputStreamWrapper(*rNewStorageStrm)); | ||||
120 | |||||
121 | if (!xPackageEncryption->decrypt(xInputStream, xDecryptedStream)) | ||||
122 | { | ||||
123 | // We failed with decryption | ||||
124 | return aNewStorage; | ||||
125 | } | ||||
126 | |||||
127 | rNewStorageStrm->Seek(0); | ||||
128 | |||||
129 | // Further reading is done from new document | ||||
130 | aNewStorage = new SotStorage(*rNewStorageStrm); | ||||
131 | |||||
132 | // Set the media descriptor data | ||||
133 | uno::Sequence<beans::NamedValue> aEncryptionData = xPackageEncryption->createEncryptionData(""); | ||||
134 | rMedium.GetItemSet()->Put(SfxUnoAnyItem(SID_ENCRYPTIONDATA(5000 + 1722), uno::makeAny(aEncryptionData))); | ||||
135 | } | ||||
136 | catch (const std::exception&) | ||||
137 | { | ||||
138 | return aNewStorage; | ||||
139 | } | ||||
140 | |||||
141 | return aNewStorage; | ||||
142 | } | ||||
143 | |||||
144 | ErrCode ScFormatFilterPluginImpl::ScImportExcel( SfxMedium& rMedium, ScDocument* pDocument, const EXCIMPFORMAT eFormat ) | ||||
145 | { | ||||
146 | // check the passed Calc document | ||||
147 | OSL_ENSURE( pDocument, "::ScImportExcel - no document" )do { if (true && (!(pDocument))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/filter/excel/excel.cxx" ":" "147" ": "), "%s", "::ScImportExcel - no document"); } } while (false); | ||||
| |||||
148 | if( !pDocument
| ||||
149 | |||||
150 | /* Import all BIFF versions regardless on eFormat, needed for import of | ||||
151 | external cells (file type detection returns Excel4.0). */ | ||||
152 | if( (eFormat != EIF_AUTO) && (eFormat != EIF_BIFF_LE4) && (eFormat != EIF_BIFF5) && (eFormat != EIF_BIFF8) ) | ||||
153 | { | ||||
154 | OSL_FAIL( "::ScImportExcel - wrong file format specification" )do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/filter/excel/excel.cxx" ":" "154" ": "), "%s", "::ScImportExcel - wrong file format specification" ); } } while (false); | ||||
155 | return SCERR_IMPORT_FORMATErrCode( ErrCodeArea::Sc, ErrCodeClass::Read, 6 ); | ||||
156 | } | ||||
157 | |||||
158 | // check the input stream from medium | ||||
159 | SvStream* pMedStrm = rMedium.GetInStream(); | ||||
160 | OSL_ENSURE( pMedStrm, "::ScImportExcel - medium without input stream" )do { if (true && (!(pMedStrm))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/filter/excel/excel.cxx" ":" "160" ": "), "%s", "::ScImportExcel - medium without input stream" ); } } while (false); | ||||
161 | if( !pMedStrm
| ||||
162 | |||||
163 | SvStream* pBookStrm = nullptr; // The "Book"/"Workbook" stream containing main data. | ||||
164 | XclBiff eBiff = EXC_BIFF_UNKNOWN; // The BIFF version of the main stream. | ||||
165 | |||||
166 | // try to open an OLE storage | ||||
167 | tools::SvRef<SotStorage> xRootStrg; | ||||
168 | tools::SvRef<SotStorageStream> xStrgStrm; | ||||
169 | std::shared_ptr<SvStream> aNewStorageStrm; | ||||
170 | if( SotStorage::IsStorageFile( pMedStrm ) ) | ||||
171 | { | ||||
172 | xRootStrg = new SotStorage( pMedStrm, false ); | ||||
173 | if( xRootStrg->GetError() ) | ||||
174 | xRootStrg = nullptr; | ||||
175 | } | ||||
176 | |||||
177 | // try to open "Book" or "Workbook" stream in OLE storage | ||||
178 | if( xRootStrg.is() ) | ||||
179 | { | ||||
180 | // Check if there is DRM encryption in storage | ||||
181 | tools::SvRef<SotStorageStream> xDRMStrm = ScfTools::OpenStorageStreamRead(xRootStrg, "\011DRMContent"); | ||||
182 | if (xDRMStrm.is()) | ||||
183 | { | ||||
184 | xRootStrg = lcl_DRMDecrypt(rMedium, xRootStrg, aNewStorageStrm); | ||||
185 | } | ||||
186 | |||||
187 | // try to open the "Book" stream | ||||
188 | tools::SvRef<SotStorageStream> xBookStrm = ScfTools::OpenStorageStreamRead( xRootStrg, EXC_STREAM_BOOK"Book" ); | ||||
189 | XclBiff eBookBiff = xBookStrm.is() ? XclImpStream::DetectBiffVersion( *xBookStrm ) : EXC_BIFF_UNKNOWN; | ||||
190 | |||||
191 | // try to open the "Workbook" stream | ||||
192 | tools::SvRef<SotStorageStream> xWorkbookStrm = ScfTools::OpenStorageStreamRead( xRootStrg, EXC_STREAM_WORKBOOK"Workbook" ); | ||||
193 | XclBiff eWorkbookBiff = xWorkbookStrm.is() ? XclImpStream::DetectBiffVersion( *xWorkbookStrm ) : EXC_BIFF_UNKNOWN; | ||||
194 | |||||
195 | // decide which stream to use | ||||
196 | if( (eWorkbookBiff != EXC_BIFF_UNKNOWN) && ((eBookBiff
| ||||
197 | { | ||||
198 | /* Only "Workbook" stream exists; or both streams exist, | ||||
199 | and "Workbook" has higher BIFF version than "Book" stream. */ | ||||
200 | xStrgStrm = xWorkbookStrm; | ||||
201 | eBiff = eWorkbookBiff; | ||||
202 | } | ||||
203 | else if( eBookBiff != EXC_BIFF_UNKNOWN ) | ||||
204 | { | ||||
205 | /* Only "Book" stream exists; or both streams exist, | ||||
206 | and "Book" has higher BIFF version than "Workbook" stream. */ | ||||
207 | xStrgStrm = xBookStrm; | ||||
208 | eBiff = eBookBiff; | ||||
209 | } | ||||
210 | |||||
211 | pBookStrm = xStrgStrm.get(); | ||||
212 | } | ||||
213 | |||||
214 | // no "Book" or "Workbook" stream found, try plain input stream from medium (even for BIFF5+) | ||||
215 | if( !pBookStrm
| ||||
216 | { | ||||
217 | eBiff = XclImpStream::DetectBiffVersion( *pMedStrm ); | ||||
218 | if( eBiff != EXC_BIFF_UNKNOWN ) | ||||
219 | pBookStrm = pMedStrm; | ||||
220 | } | ||||
221 | |||||
222 | // try to import the file | ||||
223 | ErrCode eRet = SCERR_IMPORT_UNKNOWN_BIFFErrCode( ErrCodeArea::Sc, ErrCodeClass::Read, 8 ); | ||||
224 | if( pBookStrm
| ||||
225 | { | ||||
226 | pBookStrm->SetBufferSize( 0x8000 ); // still needed? | ||||
| |||||
227 | |||||
228 | XclImpRootData aImpData( | ||||
229 | eBiff, rMedium, xRootStrg, *pDocument, | ||||
230 | utl_getWinTextEncodingFromLangStr(utl_getLocaleForGlobalDefaultEncoding())); | ||||
231 | std::unique_ptr< ImportExcel > xFilter; | ||||
232 | switch( eBiff ) | ||||
233 | { | ||||
234 | case EXC_BIFF2: | ||||
235 | case EXC_BIFF3: | ||||
236 | case EXC_BIFF4: | ||||
237 | case EXC_BIFF5: | ||||
238 | xFilter.reset( new ImportExcel( aImpData, *pBookStrm ) ); | ||||
239 | break; | ||||
240 | case EXC_BIFF8: | ||||
241 | xFilter.reset( new ImportExcel8( aImpData, *pBookStrm ) ); | ||||
242 | break; | ||||
243 | default: DBG_ERROR_BIFF()do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/filter/excel/excel.cxx" ":" "243" ": "), "%s", "Unknown BIFF type!"); } } while (false ); | ||||
244 | } | ||||
245 | |||||
246 | eRet = xFilter ? xFilter->Read() : SCERR_IMPORT_INTERNALErrCode( ErrCodeArea::Sc, ErrCodeClass::Read, 11 ); | ||||
247 | } | ||||
248 | |||||
249 | return eRet; | ||||
250 | } | ||||
251 | |||||
252 | static ErrCode lcl_ExportExcelBiff( SfxMedium& rMedium, ScDocument *pDocument, | ||||
253 | SvStream* pMedStrm, bool bBiff8, rtl_TextEncoding eNach ) | ||||
254 | { | ||||
255 | uno::Reference< packages::XPackageEncryption > xPackageEncryption; | ||||
256 | uno::Sequence< beans::NamedValue > aEncryptionData; | ||||
257 | const SfxUnoAnyItem* pEncryptionDataItem = SfxItemSet::GetItem<SfxUnoAnyItem>(rMedium.GetItemSet(), SID_ENCRYPTIONDATA(5000 + 1722), false); | ||||
258 | SvStream* pOriginalMediaStrm = pMedStrm; | ||||
259 | std::shared_ptr<SvStream> pMediaStrm; | ||||
260 | if (pEncryptionDataItem && (pEncryptionDataItem->GetValue() >>= aEncryptionData)) | ||||
261 | { | ||||
262 | ::comphelper::SequenceAsHashMap aHashData(aEncryptionData); | ||||
263 | OUString sCryptoType = aHashData.getUnpackedValueOrDefault("CryptoType", OUString()); | ||||
264 | |||||
265 | if (sCryptoType.getLength()) | ||||
266 | { | ||||
267 | uno::Reference<uno::XComponentContext> xComponentContext(comphelper::getProcessComponentContext()); | ||||
268 | uno::Sequence<uno::Any> aArguments{ | ||||
269 | uno::makeAny(beans::NamedValue("Binary", uno::makeAny(true))) }; | ||||
270 | xPackageEncryption.set( | ||||
271 | xComponentContext->getServiceManager()->createInstanceWithArgumentsAndContext( | ||||
272 | "com.sun.star.comp.oox.crypto." + sCryptoType, aArguments, xComponentContext), uno::UNO_QUERY); | ||||
273 | |||||
274 | if (xPackageEncryption.is()) | ||||
275 | { | ||||
276 | // We have an encryptor. Export document into memory stream and encrypt it later | ||||
277 | pMediaStrm = std::make_shared<SvMemoryStream>(); | ||||
278 | pMedStrm = pMediaStrm.get(); | ||||
279 | |||||
280 | // Temp removal of EncryptionData to avoid password protection triggering | ||||
281 | rMedium.GetItemSet()->ClearItem(SID_ENCRYPTIONDATA(5000 + 1722)); | ||||
282 | } | ||||
283 | } | ||||
284 | } | ||||
285 | |||||
286 | // try to open an OLE storage | ||||
287 | tools::SvRef<SotStorage> xRootStrg = new SotStorage( pMedStrm, false ); | ||||
288 | if( xRootStrg->GetError() ) return SCERR_IMPORT_OPENErrCode( ErrCodeArea::Sc, ErrCodeClass::Read, 2 ); | ||||
289 | |||||
290 | // create BIFF dependent strings | ||||
291 | OUString aStrmName, aClipName, aClassName; | ||||
292 | if( bBiff8 ) | ||||
293 | { | ||||
294 | aStrmName = EXC_STREAM_WORKBOOK"Workbook"; | ||||
295 | aClipName = "Biff8"; | ||||
296 | aClassName = "Microsoft Excel 97-Tabelle"; | ||||
297 | } | ||||
298 | else | ||||
299 | { | ||||
300 | aStrmName = EXC_STREAM_BOOK"Book"; | ||||
301 | aClipName = "Biff5"; | ||||
302 | aClassName = "Microsoft Excel 5.0-Tabelle"; | ||||
303 | } | ||||
304 | |||||
305 | // open the "Book"/"Workbook" stream | ||||
306 | tools::SvRef<SotStorageStream> xStrgStrm = ScfTools::OpenStorageStreamWrite( xRootStrg, aStrmName ); | ||||
307 | if( !xStrgStrm.is() || xStrgStrm->GetError() ) return SCERR_IMPORT_OPENErrCode( ErrCodeArea::Sc, ErrCodeClass::Read, 2 ); | ||||
308 | |||||
309 | xStrgStrm->SetBufferSize( 0x8000 ); // still needed? | ||||
310 | |||||
311 | ErrCode eRet = SCERR_IMPORT_UNKNOWN_BIFFErrCode( ErrCodeArea::Sc, ErrCodeClass::Read, 8 ); | ||||
312 | XclExpRootData aExpData( bBiff8 ? EXC_BIFF8 : EXC_BIFF5, rMedium, xRootStrg, *pDocument, eNach ); | ||||
313 | if ( bBiff8 ) | ||||
314 | { | ||||
315 | ExportBiff8 aFilter( aExpData, *xStrgStrm ); | ||||
316 | eRet = aFilter.Write(); | ||||
317 | } | ||||
318 | else | ||||
319 | { | ||||
320 | ExportBiff5 aFilter( aExpData, *xStrgStrm ); | ||||
321 | eRet = aFilter.Write(); | ||||
322 | } | ||||
323 | |||||
324 | if( eRet == SCWARN_IMPORT_RANGE_OVERFLOWErrCode( WarningFlag::Yes, ErrCodeArea::Sc, ErrCodeClass::Import , 1 ) ) | ||||
325 | eRet = SCWARN_EXPORT_MAXROWErrCode( WarningFlag::Yes, ErrCodeArea::Sc, ErrCodeClass::Export , 3 ); | ||||
326 | |||||
327 | SvGlobalName aGlobName(MSO_EXCEL5_CLASSID0x00020810L, 0x0000, 0x0000, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00 , 0x00, 0x46); | ||||
328 | SotClipboardFormatId nClip = SotExchange::RegisterFormatName( aClipName ); | ||||
329 | xRootStrg->SetClass( aGlobName, nClip, aClassName ); | ||||
330 | |||||
331 | xStrgStrm->Commit(); | ||||
332 | xRootStrg->Commit(); | ||||
333 | |||||
334 | if (xPackageEncryption.is()) | ||||
335 | { | ||||
336 | // Perform DRM encryption | ||||
337 | pMedStrm->Seek(0); | ||||
338 | |||||
339 | xPackageEncryption->setupEncryption(aEncryptionData); | ||||
340 | |||||
341 | uno::Reference<io::XInputStream > xInputStream(new utl::OSeekableInputStreamWrapper(pMedStrm, false)); | ||||
342 | uno::Sequence<beans::NamedValue> aStreams = xPackageEncryption->encrypt(xInputStream); | ||||
343 | |||||
344 | tools::SvRef<SotStorage> xEncryptedRootStrg = new SotStorage(pOriginalMediaStrm, false); | ||||
345 | for (const beans::NamedValue & aStreamData : std::as_const(aStreams)) | ||||
346 | { | ||||
347 | // To avoid long paths split and open substorages recursively | ||||
348 | // Splitting paths manually, since comphelper::string::split is trimming special characters like \0x01, \0x09 | ||||
349 | tools::SvRef<SotStorage> pStorage = xEncryptedRootStrg.get(); | ||||
350 | OUString sFileName; | ||||
351 | sal_Int32 idx = 0; | ||||
352 | do | ||||
353 | { | ||||
354 | OUString sPathElem = aStreamData.Name.getToken(0, L'/', idx); | ||||
355 | if (!sPathElem.isEmpty()) | ||||
356 | { | ||||
357 | if (idx < 0) | ||||
358 | { | ||||
359 | sFileName = sPathElem; | ||||
360 | } | ||||
361 | else | ||||
362 | { | ||||
363 | pStorage = pStorage->OpenSotStorage(sPathElem); | ||||
364 | } | ||||
365 | } | ||||
366 | } while (pStorage && idx >= 0); | ||||
367 | |||||
368 | if (!pStorage) | ||||
369 | { | ||||
370 | eRet = ERRCODE_IO_GENERALErrCode( ErrCodeArea::Io, ErrCodeClass::General, 13 ); | ||||
371 | break; | ||||
372 | } | ||||
373 | |||||
374 | tools::SvRef<SotStorageStream> pStream = pStorage->OpenSotStream(sFileName); | ||||
375 | if (!pStream) | ||||
376 | { | ||||
377 | eRet = ERRCODE_IO_GENERALErrCode( ErrCodeArea::Io, ErrCodeClass::General, 13 ); | ||||
378 | break; | ||||
379 | } | ||||
380 | uno::Sequence<sal_Int8> aStreamContent; | ||||
381 | aStreamData.Value >>= aStreamContent; | ||||
382 | size_t nBytesWritten = pStream->WriteBytes(aStreamContent.getArray(), aStreamContent.getLength()); | ||||
383 | if (nBytesWritten != static_cast<size_t>(aStreamContent.getLength())) | ||||
384 | { | ||||
385 | eRet = ERRCODE_IO_CANTWRITEErrCode( ErrCodeArea::Io, ErrCodeClass::Write, 16 ); | ||||
386 | break; | ||||
387 | } | ||||
388 | } | ||||
389 | xEncryptedRootStrg->Commit(); | ||||
390 | |||||
391 | // Restore encryption data | ||||
392 | rMedium.GetItemSet()->Put(SfxUnoAnyItem(SID_ENCRYPTIONDATA(5000 + 1722), uno::makeAny(aEncryptionData))); | ||||
393 | } | ||||
394 | |||||
395 | return eRet; | ||||
396 | } | ||||
397 | |||||
398 | ErrCode ScFormatFilterPluginImpl::ScExportExcel5( SfxMedium& rMedium, ScDocument *pDocument, | ||||
399 | ExportFormatExcel eFormat, rtl_TextEncoding eNach ) | ||||
400 | { | ||||
401 | if( eFormat != ExpBiff5 && eFormat != ExpBiff8 ) | ||||
402 | return SCERR_IMPORT_NIErrCode( ErrCodeArea::Sc, ErrCodeClass::Read, 7 ); | ||||
403 | |||||
404 | // check the passed Calc document | ||||
405 | OSL_ENSURE( pDocument, "::ScExportExcel5 - no document" )do { if (true && (!(pDocument))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/filter/excel/excel.cxx" ":" "405" ": "), "%s", "::ScExportExcel5 - no document"); } } while (false); | ||||
406 | if( !pDocument ) return SCERR_IMPORT_INTERNALErrCode( ErrCodeArea::Sc, ErrCodeClass::Read, 11 ); // should not happen | ||||
407 | |||||
408 | // check the output stream from medium | ||||
409 | SvStream* pMedStrm = rMedium.GetOutStream(); | ||||
410 | OSL_ENSURE( pMedStrm, "::ScExportExcel5 - medium without output stream" )do { if (true && (!(pMedStrm))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/filter/excel/excel.cxx" ":" "410" ": "), "%s", "::ScExportExcel5 - medium without output stream" ); } } while (false); | ||||
411 | if( !pMedStrm ) return SCERR_IMPORT_OPENErrCode( ErrCodeArea::Sc, ErrCodeClass::Read, 2 ); // should not happen | ||||
412 | |||||
413 | ErrCode eRet = lcl_ExportExcelBiff(rMedium, pDocument, pMedStrm, eFormat == ExpBiff8, eNach); | ||||
414 | return eRet; | ||||
415 | } | ||||
416 | |||||
417 | extern "C" SAL_DLLPUBLIC_EXPORT__attribute__ ((visibility("default"))) bool TestImportCalcRTF(SvStream &rStream) | ||||
418 | { | ||||
419 | ScDLL::Init(); | ||||
420 | ScDocument aDocument; | ||||
421 | ScDocOptions aDocOpt = aDocument.GetDocOptions(); | ||||
422 | aDocOpt.SetLookUpColRowNames(false); | ||||
423 | aDocument.SetDocOptions(aDocOpt); | ||||
424 | aDocument.MakeTable(0); | ||||
425 | aDocument.EnableExecuteLink(false); | ||||
426 | aDocument.SetInsertingFromOtherDoc(true); | ||||
427 | ScRange aRange; | ||||
428 | return ScFormatFilter::Get().ScImportRTF(rStream, OUString(), &aDocument, aRange) == ERRCODE_NONEErrCode(0); | ||||
429 | } | ||||
430 | |||||
431 | extern "C" SAL_DLLPUBLIC_EXPORT__attribute__ ((visibility("default"))) bool TestImportXLS(SvStream& rStream) | ||||
432 | { | ||||
433 | ScDLL::Init(); | ||||
434 | SfxMedium aMedium; | ||||
435 | css::uno::Reference<css::io::XInputStream> xStm(new utl::OInputStreamWrapper(rStream)); | ||||
436 | aMedium.GetItemSet()->Put(SfxUnoAnyItem(SID_INPUTSTREAM(5000 + 1648), css::uno::makeAny(xStm))); | ||||
437 | |||||
438 | ScDocShellRef xDocShell = new ScDocShell(SfxModelFlags::EMBEDDED_OBJECT | | ||||
439 | SfxModelFlags::DISABLE_EMBEDDED_SCRIPTS | | ||||
440 | SfxModelFlags::DISABLE_DOCUMENT_RECOVERY); | ||||
441 | |||||
442 | xDocShell->DoInitNew(); | ||||
443 | |||||
444 | ScDocument& rDoc = xDocShell->GetDocument(); | ||||
445 | |||||
446 | ScDocOptions aDocOpt = rDoc.GetDocOptions(); | ||||
447 | aDocOpt.SetLookUpColRowNames(false); | ||||
448 | rDoc.SetDocOptions(aDocOpt); | ||||
449 | rDoc.MakeTable(0); | ||||
450 | rDoc.EnableExecuteLink(false); | ||||
451 | rDoc.SetInsertingFromOtherDoc(true); | ||||
452 | rDoc.InitDrawLayer(xDocShell.get()); | ||||
453 | bool bRet(false); | ||||
454 | try | ||||
455 | { | ||||
456 | bRet = ScFormatFilter::Get().ScImportExcel(aMedium, &rDoc, EIF_AUTO) == ERRCODE_NONEErrCode(0); | ||||
457 | } | ||||
458 | catch (const css::ucb::ContentCreationException&) | ||||
459 | { | ||||
460 | } | ||||
461 | catch (const std::out_of_range&) | ||||
462 | { | ||||
463 | } | ||||
464 | xDocShell->DoClose(); | ||||
465 | xDocShell.clear(); | ||||
466 | return bRet; | ||||
467 | } | ||||
468 | |||||
469 | extern "C" SAL_DLLPUBLIC_EXPORT__attribute__ ((visibility("default"))) bool TestImportDIF(SvStream &rStream) | ||||
470 | { | ||||
471 | ScDLL::Init(); | ||||
472 | ScDocument aDocument; | ||||
473 | ScDocOptions aDocOpt = aDocument.GetDocOptions(); | ||||
474 | aDocOpt.SetLookUpColRowNames(false); | ||||
475 | aDocument.SetDocOptions(aDocOpt); | ||||
476 | aDocument.MakeTable(0); | ||||
477 | aDocument.EnableExecuteLink(false); | ||||
478 | aDocument.SetInsertingFromOtherDoc(true); | ||||
479 | return ScFormatFilter::Get().ScImportDif(rStream, &aDocument, ScAddress(0, 0, 0), RTL_TEXTENCODING_IBM_850(((rtl_TextEncoding) 4))) == ERRCODE_NONEErrCode(0); | ||||
480 | } | ||||
481 | |||||
482 | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |
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 | #ifndef INCLUDED_TOOLS_REF_HXX |
20 | #define INCLUDED_TOOLS_REF_HXX |
21 | |
22 | #include <sal/config.h> |
23 | #include <cassert> |
24 | #include <tools/toolsdllapi.h> |
25 | #include <utility> |
26 | |
27 | /** |
28 | This implements similar functionality to boost::intrusive_ptr |
29 | */ |
30 | |
31 | namespace tools { |
32 | |
33 | /** T must be a class that extends SvRefBase */ |
34 | template<typename T> class SAL_DLLPUBLIC_RTTI__attribute__ ((type_visibility("default"))) SvRef final { |
35 | public: |
36 | SvRef(): pObj(nullptr) {} |
37 | |
38 | SvRef(SvRef&& rObj) noexcept |
39 | { |
40 | pObj = rObj.pObj; |
41 | rObj.pObj = nullptr; |
42 | } |
43 | |
44 | SvRef(SvRef const & rObj): pObj(rObj.pObj) |
45 | { |
46 | if (pObj != nullptr) pObj->AddNextRef(); |
47 | } |
48 | |
49 | SvRef(T * pObjP): pObj(pObjP) |
50 | { |
51 | if (pObj != nullptr) pObj->AddFirstRef(); |
52 | } |
53 | |
54 | ~SvRef() |
55 | { |
56 | if (pObj != nullptr) pObj->ReleaseRef(); |
57 | } |
58 | |
59 | void clear() |
60 | { |
61 | if (pObj != nullptr) { |
62 | T * pRefObj = pObj; |
63 | pObj = nullptr; |
64 | pRefObj->ReleaseRef(); |
65 | } |
66 | } |
67 | |
68 | SvRef & operator =(SvRef const & rObj) |
69 | { |
70 | if (rObj.pObj != nullptr) { |
71 | rObj.pObj->AddNextRef(); |
72 | } |
73 | T * pRefObj = pObj; |
74 | pObj = rObj.pObj; |
75 | if (pRefObj != nullptr) { |
76 | pRefObj->ReleaseRef(); |
77 | } |
78 | return *this; |
79 | } |
80 | |
81 | SvRef & operator =(SvRef && rObj) |
82 | { |
83 | if (pObj != nullptr) { |
84 | pObj->ReleaseRef(); |
85 | } |
86 | pObj = rObj.pObj; |
87 | rObj.pObj = nullptr; |
88 | return *this; |
89 | } |
90 | |
91 | bool is() const { return pObj != nullptr; } |
92 | |
93 | explicit operator bool() const { return is(); } |
94 | |
95 | T * get() const { return pObj; } |
96 | |
97 | T * operator ->() const { assert(pObj != nullptr)(static_cast <bool> (pObj != nullptr) ? void (0) : __assert_fail ("pObj != nullptr", "/home/maarten/src/libreoffice/core/include/tools/ref.hxx" , 97, __extension__ __PRETTY_FUNCTION__)); return pObj; } |
98 | |
99 | T & operator *() const { assert(pObj != nullptr)(static_cast <bool> (pObj != nullptr) ? void (0) : __assert_fail ("pObj != nullptr", "/home/maarten/src/libreoffice/core/include/tools/ref.hxx" , 99, __extension__ __PRETTY_FUNCTION__)); return *pObj; } |
100 | |
101 | bool operator ==(const SvRef<T> &rhs) const { return pObj == rhs.pObj; } |
102 | bool operator !=(const SvRef<T> &rhs) const { return !(*this == rhs); } |
103 | |
104 | private: |
105 | T * pObj; |
106 | }; |
107 | |
108 | /** |
109 | * This implements similar functionality to std::make_shared. |
110 | */ |
111 | template<typename T, typename... Args> |
112 | SvRef<T> make_ref(Args&& ... args) |
113 | { |
114 | return SvRef<T>(new T(std::forward<Args>(args)...)); |
115 | } |
116 | |
117 | } |
118 | |
119 | /** Classes that want to be referenced-counted via SvRef<T>, should extend this base class */ |
120 | class TOOLS_DLLPUBLIC__attribute__ ((visibility("default"))) SvRefBase |
121 | { |
122 | // work around a clang 3.5 optimization bug: if the bNoDelete is *first* |
123 | // it mis-compiles "if (--nRefCount == 0)" and never deletes any object |
124 | unsigned int nRefCount : 31; |
125 | // the only reason this is not bool is because MSVC cannot handle mixed type bitfields |
126 | unsigned int bNoDelete : 1; |
127 | |
128 | protected: |
129 | virtual ~SvRefBase() COVERITY_NOEXCEPT_FALSE; |
130 | |
131 | public: |
132 | SvRefBase() : nRefCount(0), bNoDelete(1) {} |
133 | SvRefBase(const SvRefBase &) : nRefCount(0), bNoDelete(1) {} |
134 | |
135 | SvRefBase & operator=(const SvRefBase &) { return *this; } |
136 | |
137 | void RestoreNoDelete() |
138 | { bNoDelete = 1; } |
139 | |
140 | void AddNextRef() |
141 | { |
142 | assert( nRefCount < (1 << 30) && "Do not add refs to dead objects" )(static_cast <bool> (nRefCount < (1 << 30) && "Do not add refs to dead objects") ? void (0) : __assert_fail ("nRefCount < (1 << 30) && \"Do not add refs to dead objects\"" , "/home/maarten/src/libreoffice/core/include/tools/ref.hxx", 142, __extension__ __PRETTY_FUNCTION__)); |
143 | ++nRefCount; |
144 | } |
145 | |
146 | void AddFirstRef() |
147 | { |
148 | assert( nRefCount < (1 << 30) && "Do not add refs to dead objects" )(static_cast <bool> (nRefCount < (1 << 30) && "Do not add refs to dead objects") ? void (0) : __assert_fail ("nRefCount < (1 << 30) && \"Do not add refs to dead objects\"" , "/home/maarten/src/libreoffice/core/include/tools/ref.hxx", 148, __extension__ __PRETTY_FUNCTION__)); |
149 | if( bNoDelete ) |
150 | bNoDelete = 0; |
151 | ++nRefCount; |
152 | } |
153 | |
154 | void ReleaseRef() |
155 | { |
156 | assert( nRefCount >= 1)(static_cast <bool> (nRefCount >= 1) ? void (0) : __assert_fail ("nRefCount >= 1", "/home/maarten/src/libreoffice/core/include/tools/ref.hxx" , 156, __extension__ __PRETTY_FUNCTION__)); |
157 | if( --nRefCount == 0 && !bNoDelete) |
158 | { |
159 | // I'm not sure about the original purpose of this line, but right now |
160 | // it serves the purpose that anything that attempts to do an AddRef() |
161 | // after an object is deleted will trip an assert. |
162 | nRefCount = 1 << 30; |
163 | delete this; |
164 | } |
165 | } |
166 | |
167 | unsigned int GetRefCount() const |
168 | { return nRefCount; } |
169 | }; |
170 | |
171 | template<typename T> |
172 | class SvCompatWeakBase; |
173 | |
174 | /** SvCompatWeakHdl acts as an intermediary between SvCompatWeakRef<T> and T. |
175 | */ |
176 | template<typename T> |
177 | class SvCompatWeakHdl final : public SvRefBase |
178 | { |
179 | friend class SvCompatWeakBase<T>; |
180 | T* _pObj; |
181 | |
182 | SvCompatWeakHdl( T* pObj ) : _pObj( pObj ) {} |
183 | |
184 | public: |
185 | void ResetWeakBase( ) { _pObj = nullptr; } |
186 | T* GetObj() { return _pObj; } |
187 | }; |
188 | |
189 | /** We only have one place that extends this, in include/sfx2/frame.hxx, class SfxFrame. |
190 | Its function is to notify the SvCompatWeakHdl when an SfxFrame object is deleted. |
191 | */ |
192 | template<typename T> |
193 | class SvCompatWeakBase |
194 | { |
195 | tools::SvRef< SvCompatWeakHdl<T> > _xHdl; |
196 | |
197 | public: |
198 | /** Does not use initializer due to compiler warnings, |
199 | because the lifetime of the _xHdl object can exceed the lifetime of this class. |
200 | */ |
201 | SvCompatWeakBase( T* pObj ) { _xHdl = new SvCompatWeakHdl<T>( pObj ); } |
202 | |
203 | ~SvCompatWeakBase() { _xHdl->ResetWeakBase(); } |
204 | |
205 | SvCompatWeakHdl<T>* GetHdl() { return _xHdl.get(); } |
206 | }; |
207 | |
208 | /** We only have one weak reference in LO, in include/sfx2/frame.hxx, class SfxFrameWeak. |
209 | */ |
210 | template<typename T> |
211 | class SAL_WARN_UNUSED__attribute__((warn_unused)) SvCompatWeakRef |
212 | { |
213 | tools::SvRef< SvCompatWeakHdl<T> > _xHdl; |
214 | public: |
215 | SvCompatWeakRef( ) {} |
216 | SvCompatWeakRef( T* pObj ) |
217 | { if( pObj ) _xHdl = pObj->GetHdl(); } |
218 | #if defined(__COVERITY__) |
219 | ~SvCompatWeakRef() COVERITY_NOEXCEPT_FALSE {} |
220 | #endif |
221 | SvCompatWeakRef& operator = ( T * pObj ) |
222 | { _xHdl = pObj ? pObj->GetHdl() : nullptr; return *this; } |
223 | bool is() const |
224 | { return _xHdl.is() && _xHdl->GetObj(); } |
225 | explicit operator bool() const { return is(); } |
226 | T* operator -> () const |
227 | { return _xHdl.is() ? _xHdl->GetObj() : nullptr; } |
228 | operator T* () const |
229 | { return _xHdl.is() ? _xHdl->GetObj() : nullptr; } |
230 | }; |
231 | |
232 | #endif |
233 | |
234 | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |