Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : :
30 : : #include "scdetect.hxx"
31 : :
32 : : #include <sal/macros.h>
33 : :
34 : : #include <framework/interaction.hxx>
35 : : #include <com/sun/star/lang/XMultiServiceFactory.hpp>
36 : : #include <com/sun/star/beans/PropertyValue.hpp>
37 : : #include <com/sun/star/frame/XFrame.hpp>
38 : : #include <com/sun/star/frame/XModel.hpp>
39 : : #include <com/sun/star/awt/XWindow.hpp>
40 : : #include <com/sun/star/lang/XUnoTunnel.hpp>
41 : : #include <comphelper/processfactory.hxx>
42 : : #include <comphelper/string.hxx>
43 : : #include <com/sun/star/container/XNameAccess.hpp>
44 : : #include <com/sun/star/io/XInputStream.hpp>
45 : : #include <com/sun/star/task/XInteractionHandler.hpp>
46 : : #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
47 : : #include <com/sun/star/ucb/CommandAbortedException.hpp>
48 : : #include <com/sun/star/ucb/InteractiveAppException.hpp>
49 : : #include <com/sun/star/ucb/XContent.hpp>
50 : : #include <com/sun/star/packages/zip/ZipIOException.hpp>
51 : :
52 : : #include <toolkit/helper/vclunohelper.hxx>
53 : : #include <ucbhelper/simpleinteractionrequest.hxx>
54 : :
55 : : #include <svtools/parhtml.hxx>
56 : : #include <rtl/ustring.h>
57 : : #include <rtl/logfile.hxx>
58 : : #include <svl/itemset.hxx>
59 : : #include <vcl/window.hxx>
60 : : #include <svl/eitem.hxx>
61 : : #include <svl/stritem.hxx>
62 : : #include <tools/urlobj.hxx>
63 : : #include <osl/mutex.hxx>
64 : : #include <svtools/sfxecode.hxx>
65 : : #include <svtools/ehdl.hxx>
66 : : #include <sot/storinfo.hxx>
67 : : #include <vcl/svapp.hxx>
68 : : #include <sfx2/sfxsids.hrc>
69 : : #include <sfx2/request.hxx>
70 : : #include <sfx2/docfile.hxx>
71 : : #include <sfx2/docfilt.hxx>
72 : : #include <sfx2/fcontnr.hxx>
73 : : #include <sfx2/app.hxx>
74 : : #include <sfx2/brokenpackageint.hxx>
75 : : #include <sot/storage.hxx>
76 : :
77 : : using namespace ::com::sun::star;
78 : : using namespace ::com::sun::star::uno;
79 : : using namespace ::com::sun::star::io;
80 : : using namespace ::com::sun::star::frame;
81 : : using namespace ::com::sun::star::task;
82 : : using namespace ::com::sun::star::beans;
83 : : using namespace ::com::sun::star::lang;
84 : : using namespace ::com::sun::star::ucb;
85 : : using ::rtl::OUString;
86 : :
87 : 47 : ScFilterDetect::ScFilterDetect( const REFERENCE < ::com::sun::star::lang::XMultiServiceFactory >& /* xFactory */ )
88 : : {
89 : 47 : }
90 : :
91 : 47 : ScFilterDetect::~ScFilterDetect()
92 : : {
93 [ - + ]: 94 : }
94 : :
95 : : static const sal_Char pFilterSc50[] = "StarCalc 5.0";
96 : : static const sal_Char pFilterSc50Temp[] = "StarCalc 5.0 Vorlage/Template";
97 : : static const sal_Char pFilterSc40[] = "StarCalc 4.0";
98 : : static const sal_Char pFilterSc40Temp[] = "StarCalc 4.0 Vorlage/Template";
99 : : static const sal_Char pFilterSc30[] = "StarCalc 3.0";
100 : : static const sal_Char pFilterSc30Temp[] = "StarCalc 3.0 Vorlage/Template";
101 : : static const sal_Char pFilterSc10[] = "StarCalc 1.0";
102 : : static const sal_Char pFilterXML[] = "StarOffice XML (Calc)";
103 : : static const sal_Char pFilterAscii[] = "Text - txt - csv (StarCalc)";
104 : : static const sal_Char pFilterLotus[] = "Lotus";
105 : : static const sal_Char pFilterQPro6[] = "Quattro Pro 6.0";
106 : : static const sal_Char pFilterExcel4[] = "MS Excel 4.0";
107 : : static const sal_Char pFilterEx4Temp[] = "MS Excel 4.0 Vorlage/Template";
108 : : static const sal_Char pFilterExcel5[] = "MS Excel 5.0/95";
109 : : static const sal_Char pFilterEx5Temp[] = "MS Excel 5.0/95 Vorlage/Template";
110 : : static const sal_Char pFilterExcel95[] = "MS Excel 95";
111 : : static const sal_Char pFilterEx95Temp[] = "MS Excel 95 Vorlage/Template";
112 : : static const sal_Char pFilterExcel97[] = "MS Excel 97";
113 : : static const sal_Char pFilterEx97Temp[] = "MS Excel 97 Vorlage/Template";
114 : : static const sal_Char pFilterExcelXML[] = "MS Excel 2003 XML";
115 : : static const sal_Char pFilterDBase[] = "dBase";
116 : : static const sal_Char pFilterDif[] = "DIF";
117 : : static const sal_Char pFilterSylk[] = "SYLK";
118 : : static const sal_Char pFilterHtml[] = "HTML (StarCalc)";
119 : : static const sal_Char pFilterHtmlWeb[] = "calc_HTML_WebQuery";
120 : : static const sal_Char pFilterRtf[] = "Rich Text Format (StarCalc)";
121 : :
122 : :
123 : 0 : static sal_Bool lcl_MayBeAscii( SvStream& rStream )
124 : : {
125 : : // ASCII/CSV is considered possible if there are no null bytes, or a Byte
126 : : // Order Mark is present, or if, for Unicode UCS2/UTF-16, all null bytes
127 : : // are on either even or uneven byte positions.
128 : :
129 [ # # ]: 0 : rStream.Seek(STREAM_SEEK_TO_BEGIN);
130 : :
131 : 0 : const size_t nBufSize = 2048;
132 : : sal_uInt16 aBuffer[ nBufSize ];
133 : 0 : sal_uInt8* pByte = reinterpret_cast<sal_uInt8*>(aBuffer);
134 [ # # ]: 0 : sal_uLong nBytesRead = rStream.Read( pByte, nBufSize*2);
135 : :
136 [ # # ][ # # ]: 0 : if ( nBytesRead >= 2 && (aBuffer[0] == 0xfffe || aBuffer[0] == 0xfeff) )
[ # # ]
137 : : {
138 : : // Unicode BOM file may contain null bytes.
139 : 0 : return sal_True;
140 : : }
141 : :
142 : 0 : const sal_uInt16* p = aBuffer;
143 : 0 : sal_uInt16 nMask = 0xffff;
144 : 0 : nBytesRead /= 2;
145 [ # # ][ # # ]: 0 : while( nBytesRead-- && nMask )
[ # # ]
146 : : {
147 : 0 : sal_uInt16 nVal = *p++ & nMask;
148 [ # # ]: 0 : if (!(nVal & 0x00ff))
149 : 0 : nMask &= 0xff00;
150 [ # # ]: 0 : if (!(nVal & 0xff00))
151 : 0 : nMask &= 0x00ff;
152 : : }
153 : :
154 : 0 : return nMask != 0;
155 : : }
156 : :
157 : 0 : static const SfxFilter* lcl_DetectExcelXML( SvStream& rStream, SfxFilterMatcher& rMatcher )
158 : : {
159 : 0 : const SfxFilter* pFound = NULL;
160 [ # # ]: 0 : rStream.Seek(STREAM_SEEK_TO_BEGIN);
161 : :
162 : 0 : const size_t nBufSize = 4000;
163 : : sal_uInt8 aBuffer[ nBufSize ];
164 [ # # ]: 0 : sal_uLong nBytesRead = rStream.Read( aBuffer, nBufSize );
165 : 0 : sal_uLong nXMLStart = 0;
166 : :
167 : : // Skip UTF-8 BOM if present.
168 : : // No need to handle UTF-16 etc (also rejected in XMLFilterDetect).
169 [ # # ][ # # ]: 0 : if ( nBytesRead >= 3 && aBuffer[0] == 0xEF && aBuffer[1] == 0xBB && aBuffer[2] == 0xBF )
[ # # ][ # # ]
170 : 0 : nXMLStart = 3;
171 : :
172 [ # # ][ # # ]: 0 : if ( nBytesRead >= nXMLStart + 5 && memcmp( aBuffer+nXMLStart, "<?xml", 5 ) == 0 )
173 : : {
174 : : // Be consistent with XMLFilterDetect service: Check for presence of "Workbook" in XML file.
175 : :
176 : 0 : rtl::OString aTryStr( "Workbook" );
177 : 0 : rtl::OString aFileString(reinterpret_cast<const sal_Char*>(aBuffer), nBytesRead);
178 : :
179 [ # # ]: 0 : if (aFileString.indexOf(aTryStr) >= 0)
180 [ # # ][ # # ]: 0 : pFound = rMatcher.GetFilter4FilterName( rtl::OUString(pFilterExcelXML) );
[ # # ]
181 : : }
182 : :
183 : 0 : return pFound;
184 : : }
185 : :
186 : 0 : static sal_Bool lcl_MayBeDBase( SvStream& rStream )
187 : : {
188 : : // Look for dbf marker, see connectivity/source/inc/dbase/DTable.hxx
189 : : // DBFType for values.
190 : : const sal_uInt8 nValidMarks[] = {
191 : 0 : 0x03, 0x04, 0x05, 0x30, 0x43, 0xB3, 0x83, 0x8b, 0x8e, 0xf5 };
192 : : sal_uInt8 nMark;
193 [ # # ]: 0 : rStream.Seek(STREAM_SEEK_TO_BEGIN);
194 [ # # ]: 0 : rStream >> nMark;
195 : 0 : bool bValidMark = false;
196 [ # # ][ # # ]: 0 : for (size_t i=0; i < sizeof(nValidMarks)/sizeof(nValidMarks[0]) && !bValidMark; ++i)
[ # # ]
197 : : {
198 [ # # ]: 0 : if (nValidMarks[i] == nMark)
199 : 0 : bValidMark = true;
200 : : }
201 [ # # ]: 0 : if ( !bValidMark )
202 : 0 : return false;
203 : :
204 : 0 : const size_t nHeaderBlockSize = 32;
205 : : // Empty dbf is >= 32*2+1 bytes in size.
206 : 0 : const size_t nEmptyDbf = nHeaderBlockSize * 2 + 1;
207 : :
208 [ # # ]: 0 : rStream.Seek(STREAM_SEEK_TO_END);
209 : 0 : sal_uLong nSize = rStream.Tell();
210 [ # # ]: 0 : if ( nSize < nEmptyDbf )
211 : 0 : return false;
212 : :
213 : : // length of header starts at 8
214 [ # # ]: 0 : rStream.Seek(8);
215 : : sal_uInt16 nHeaderLen;
216 [ # # ]: 0 : rStream >> nHeaderLen;
217 : :
218 [ # # ][ # # ]: 0 : if ( nHeaderLen < nEmptyDbf || nSize < nHeaderLen )
219 : 0 : return false;
220 : :
221 : : // Last byte of header must be 0x0d, this is how it's specified.
222 : : // #i9581#,#i26407# but some applications don't follow the specification
223 : : // and pad the header with one byte 0x00 to reach an
224 : : // even boundary. Some (#i88577# ) even pad more or pad using a 0x1a ^Z
225 : : // control character (#i8857#). This results in:
226 : : // Last byte of header must be 0x0d on 32 bytes boundary.
227 : 0 : sal_uInt16 nBlocks = (nHeaderLen - 1) / nHeaderBlockSize;
228 : 0 : sal_uInt8 nEndFlag = 0;
229 [ # # ][ # # ]: 0 : while ( nBlocks > 1 && nEndFlag != 0x0d ) {
[ # # ]
230 [ # # ]: 0 : rStream.Seek( nBlocks-- * nHeaderBlockSize );
231 [ # # ]: 0 : rStream >> nEndFlag;
232 : : }
233 : :
234 : 0 : return ( 0x0d == nEndFlag );
235 : : }
236 : :
237 : 47 : ::rtl::OUString SAL_CALL ScFilterDetect::detect( ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& lDescriptor ) throw( ::com::sun::star::uno::RuntimeException )
238 : : {
239 : 47 : REFERENCE< XInputStream > xStream;
240 : 47 : REFERENCE< XContent > xContent;
241 : 47 : REFERENCE< XInteractionHandler > xInteraction;
242 [ + - ]: 47 : String aURL;
243 : 47 : ::rtl::OUString sTemp;
244 [ + - ]: 47 : String aTypeName; // a name describing the type (from MediaDescriptor, usually from flat detection)
245 [ + - ]: 47 : String aPreselectedFilterName; // a name describing the filter to use (from MediaDescriptor, usually from UI action)
246 : :
247 : 47 : ::rtl::OUString aDocumentTitle; // interesting only if set in this method
248 : :
249 : : // opening as template is done when a parameter tells to do so and a template filter can be detected
250 : : // (otherwise no valid filter would be found) or if the detected filter is a template filter and
251 : : // there is no parameter that forbids to open as template
252 : 47 : sal_Bool bOpenAsTemplate = false;
253 : 47 : sal_Bool bWasReadOnly = false, bReadOnly = false;
254 : :
255 : 47 : sal_Bool bRepairPackage = false;
256 : 47 : sal_Bool bRepairAllowed = false;
257 : :
258 : : // now some parameters that can already be in the array, but may be overwritten or new inserted here
259 : : // remember their indices in the case new values must be added to the array
260 : 47 : sal_Int32 nPropertyCount = lDescriptor.getLength();
261 : 47 : sal_Int32 nIndexOfFilterName = -1;
262 : 47 : sal_Int32 nIndexOfInputStream = -1;
263 : 47 : sal_Int32 nIndexOfContent = -1;
264 : 47 : sal_Int32 nIndexOfReadOnlyFlag = -1;
265 : 47 : sal_Int32 nIndexOfTemplateFlag = -1;
266 : 47 : sal_Int32 nIndexOfDocumentTitle = -1;
267 : 47 : bool bFakeXLS = false;
268 : :
269 [ + + ]: 378 : for( sal_Int32 nProperty=0; nProperty<nPropertyCount; ++nProperty )
270 : : {
271 : : // extract properties
272 [ + - ][ + + ]: 331 : if ( lDescriptor[nProperty].Name == "URL" )
273 : : {
274 [ + - ]: 47 : lDescriptor[nProperty].Value >>= sTemp;
275 [ + - ]: 47 : aURL = sTemp;
276 : : }
277 [ + + ][ + - ]: 284 : else if( !aURL.Len() && lDescriptor[nProperty].Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("FileName")) )
[ - + ][ - + ]
278 : : {
279 [ # # ]: 0 : lDescriptor[nProperty].Value >>= sTemp;
280 [ # # ]: 0 : aURL = sTemp;
281 : : }
282 [ + - ][ + + ]: 284 : else if ( lDescriptor[nProperty].Name == "TypeName" )
283 : : {
284 [ + - ]: 37 : lDescriptor[nProperty].Value >>= sTemp;
285 [ + - ]: 37 : aTypeName = sTemp;
286 : : }
287 [ + - ][ - + ]: 247 : else if ( lDescriptor[nProperty].Name == "FilterName" )
288 : : {
289 [ # # ]: 0 : lDescriptor[nProperty].Value >>= sTemp;
290 [ # # ]: 0 : aPreselectedFilterName = sTemp;
291 : :
292 : : // if the preselected filter name is not correct, it must be erased after detection
293 : : // remember index of property to get access to it later
294 : 0 : nIndexOfFilterName = nProperty;
295 : : }
296 [ + - ][ + + ]: 247 : else if ( lDescriptor[nProperty].Name == "InputStream" )
297 : 47 : nIndexOfInputStream = nProperty;
298 [ + - ][ - + ]: 200 : else if ( lDescriptor[nProperty].Name == "ReadOnly" )
299 : 0 : nIndexOfReadOnlyFlag = nProperty;
300 [ + - ][ + + ]: 200 : else if ( lDescriptor[nProperty].Name == "UCBContent" )
301 : 42 : nIndexOfContent = nProperty;
302 [ + - ][ - + ]: 158 : else if ( lDescriptor[nProperty].Name == "AsTemplate" )
303 : : {
304 [ # # ]: 0 : lDescriptor[nProperty].Value >>= bOpenAsTemplate;
305 : 0 : nIndexOfTemplateFlag = nProperty;
306 : : }
307 [ + - ][ + + ]: 158 : else if ( lDescriptor[nProperty].Name == "InteractionHandler" )
308 [ + - ][ + - ]: 47 : lDescriptor[nProperty].Value >>= xInteraction;
309 [ + - ][ - + ]: 111 : else if ( lDescriptor[nProperty].Name == "RepairPackage" )
310 [ # # ]: 0 : lDescriptor[nProperty].Value >>= bRepairPackage;
311 [ + - ][ - + ]: 111 : else if ( lDescriptor[nProperty].Name == "DocumentTitle" )
312 : 0 : nIndexOfDocumentTitle = nProperty;
313 : : }
314 : :
315 : : // can't check the type for external filters, so set the "dont" flag accordingly
316 [ + - ]: 47 : SolarMutexGuard aGuard;
317 : : //SfxFilterFlags nMust = SFX_FILTER_IMPORT, nDont = SFX_FILTER_NOTINSTALLED;
318 : :
319 [ + - ][ + - ]: 47 : SfxAllItemSet *pSet = new SfxAllItemSet( SFX_APP()->GetPool() );
[ + - ]
320 [ + - ]: 47 : TransformParameters( SID_OPENDOC, lDescriptor, *pSet );
321 [ + - ][ + - ]: 47 : SFX_ITEMSET_ARG( pSet, pItem, SfxBoolItem, SID_DOC_READONLY, false );
322 : :
323 [ - + ][ # # ]: 47 : bWasReadOnly = pItem && pItem->GetValue();
324 : :
325 : 47 : const SfxFilter* pFilter = 0;
326 [ + - ]: 47 : String aPrefix = rtl::OUString( "private:factory/" );
327 [ - + ][ + - ]: 47 : if( aURL.Match( aPrefix ) == aPrefix.Len() )
328 : : {
329 [ # # ]: 0 : String aPattern( aPrefix );
330 [ # # ]: 0 : aPattern += rtl::OUString("scalc");
331 [ # # ][ # # ]: 0 : if ( aURL.Match( aPattern ) >= aPattern.Len() )
332 [ # # ][ # # ]: 0 : pFilter = SfxFilter::GetDefaultFilterFromFactory( aURL );
333 : : }
334 : : else
335 : : {
336 : : // container for Calc filters
337 [ + - ][ + - ]: 47 : SfxFilterMatcher aMatcher( rtl::OUString("scalc") );
[ + - ]
338 [ - + ]: 47 : if ( aPreselectedFilterName.Len() )
339 [ # # ]: 0 : pFilter = SfxFilter::GetFilterByName( aPreselectedFilterName );
340 [ + + ]: 47 : else if( aTypeName.Len() )
341 [ + - ]: 37 : pFilter = aMatcher.GetFilter4EA( aTypeName );
342 : :
343 : : // ctor of SfxMedium uses owner transition of ItemSet
344 [ - + ][ + - ]: 47 : SfxMedium aMedium( aURL, bWasReadOnly ? STREAM_STD_READ : STREAM_STD_READWRITE, NULL, pSet );
345 [ + - ]: 47 : aMedium.UseInteractionHandler( sal_True );
346 : :
347 [ + - ]: 47 : sal_Bool bIsStorage = aMedium.IsStorage();
348 [ + - ][ + - ]: 47 : if ( aMedium.GetErrorCode() == ERRCODE_NONE )
349 : : {
350 : : // remember input stream and content and put them into the descriptor later
351 : : // should be done here since later the medium can switch to a version
352 [ + - ][ + - ]: 47 : xStream.set(aMedium.GetInputStream());
353 [ + - ][ + - ]: 47 : xContent.set(aMedium.GetContent());
354 [ + - ]: 47 : bReadOnly = aMedium.IsReadOnly();
355 : :
356 : : // maybe that IsStorage() already created an error!
357 [ + + ]: 47 : if ( bIsStorage )
358 : : {
359 [ + - ]: 43 : uno::Reference < embed::XStorage > xStorage(aMedium.GetStorage( false ));
360 [ + - ][ - + ]: 43 : if ( aMedium.GetLastStorageCreationState() != ERRCODE_NONE )
361 : : {
362 : : // error during storage creation means _here_ that the medium
363 : : // is broken, but we can not handle it in medium since unpossibility
364 : : // to create a storage does not _always_ means that the medium is broken
365 [ # # ][ # # ]: 0 : aMedium.SetError( aMedium.GetLastStorageCreationState(), ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
[ # # ]
366 [ # # ]: 0 : if ( xInteraction.is() )
367 : : {
368 : 0 : OUString empty;
369 : : try
370 : : {
371 : : InteractiveAppException xException( empty,
372 : : REFERENCE< XInterface >(),
373 : : InteractionClassification_ERROR,
374 [ # # ][ # # ]: 0 : aMedium.GetError() );
375 : :
376 : : REFERENCE< XInteractionRequest > xRequest(
377 : : new ucbhelper::SimpleInteractionRequest( makeAny( xException ),
378 [ # # ][ # # ]: 0 : ucbhelper::CONTINUATION_APPROVE ) );
[ # # ][ # # ]
379 [ # # ][ # # ]: 0 : xInteraction->handle( xRequest );
[ # # ][ # # ]
380 : : }
381 [ # # ]: 0 : catch ( Exception & ) {};
382 : : }
383 : : }
384 [ + - ]: 43 : else if ( xStorage.is() )
385 : : {
386 : : try
387 : : {
388 [ + - ]: 43 : String aFilterName;
389 [ + + ]: 43 : if ( pFilter )
390 [ + - ]: 33 : aFilterName = pFilter->GetName();
391 [ + + ][ + - ]: 43 : aTypeName = SfxFilter::GetTypeFromStorage( xStorage, pFilter ? pFilter->IsOwnTemplateFormat() : false, &aFilterName );
[ + - ][ + - ]
[ + - ]
392 : : }
393 [ # # ]: 0 : catch( const lang::WrappedTargetException& aWrap )
394 : : {
395 [ # # ]: 0 : packages::zip::ZipIOException aZipException;
396 : :
397 : : // repairing is done only if this type is requested from outside
398 [ # # # # : 0 : if ( ( aWrap.TargetException >>= aZipException ) && aTypeName.Len() )
# # # # ]
399 : : {
400 [ # # ]: 0 : if ( xInteraction.is() )
401 : : {
402 : : // the package is broken one
403 [ # # ]: 0 : aDocumentTitle = aMedium.GetURLObject().getName(
404 : : INetURLObject::LAST_SEGMENT,
405 : : true,
406 [ # # ]: 0 : INetURLObject::DECODE_WITH_CHARSET );
407 : :
408 [ # # ]: 0 : if ( !bRepairPackage )
409 : : {
410 : : // ask the user whether he wants to try to repair
411 [ # # ]: 0 : RequestPackageReparation aRequest( aDocumentTitle );
412 [ # # # # : 0 : xInteraction->handle( aRequest.GetRequest() );
# # ]
413 [ # # # # ]: 0 : bRepairAllowed = aRequest.isApproved();
414 : : }
415 : :
416 [ # # ]: 0 : if ( !bRepairAllowed )
417 : : {
418 : : // repair either not allowed or not successful
419 [ # # ]: 0 : NotifyBrokenPackage aNotifyRequest( aDocumentTitle );
420 [ # # # # : 0 : xInteraction->handle( aNotifyRequest.GetRequest() );
# # # # ]
421 : : }
422 : : }
423 : :
424 [ # # ]: 0 : if ( !bRepairAllowed )
425 [ # # ]: 0 : aTypeName.Erase();
426 [ # # ]: 0 : }
427 : : }
428 : 0 : catch( uno::RuntimeException& )
429 : : {
430 : 0 : throw;
431 : : }
432 [ # # # # : 0 : catch( uno::Exception& )
# # ]
433 : : {
434 [ # # ]: 0 : aTypeName.Erase();
435 : : }
436 : :
437 [ + - ]: 43 : if ( aTypeName.Len() )
438 [ + - ][ + - ]: 43 : pFilter = SfxFilterMatcher( rtl::OUString("scalc") ).GetFilter4EA( aTypeName );
[ + - ][ + - ]
[ + - ]
439 : :
440 : 43 : }
441 : : }
442 : : else
443 : : {
444 [ + - ]: 4 : SvStream* pStream = aMedium.GetInStream();
445 : 4 : const SfxFilter* pPreselectedFilter = pFilter;
446 : : bool bCsvSelected = (pPreselectedFilter &&
447 [ + - ][ + - ]: 4 : pPreselectedFilter->GetFilterName().EqualsAscii( pFilterAscii ));
[ - + ]
448 : : bool bExcelSelected = (pPreselectedFilter &&
449 [ + - ][ + - ]: 4 : (pPreselectedFilter->GetName().SearchAscii("Excel") != STRING_NOTFOUND));
[ + - ]
450 [ - + ][ # # ]: 4 : bool bIsXLS = (bExcelSelected || (bCsvSelected && !aPreselectedFilterName.Len()));
[ # # ]
451 : 4 : pFilter = 0;
452 [ + - ]: 4 : if ( pStream )
453 : : {
454 [ + - ]: 4 : pStream->Seek( STREAM_SEEK_TO_END);
455 : 4 : sal_Size nSize = pStream->Tell();
456 [ + - ]: 4 : pStream->Seek( 0);
457 : : // Do not attempt to create an SotStorage on a
458 : : // 0-length stream as that would create the compound
459 : : // document header on the stream and effectively write to
460 : : // disk!
461 : 4 : SotStorageRef aStorage;
462 [ + - ]: 4 : if (nSize > 0)
463 [ + - ][ + - ]: 4 : aStorage = new SotStorage ( pStream, false );
[ + - ]
464 [ + - ][ + - ]: 4 : if ( aStorage.Is() && !aStorage->GetError() )
[ + - ]
465 : : {
466 : : // Excel-5: detect through contained streams
467 : : // there are some "excel" formats from 3rd party vendors that need to be distinguished
468 [ + - ]: 4 : String aStreamName(RTL_CONSTASCII_USTRINGPARAM("Workbook"));
469 [ + - ]: 4 : sal_Bool bExcel97Stream = ( aStorage->IsStream( aStreamName ) );
470 : :
471 [ + - ][ + - ]: 4 : aStreamName = String(RTL_CONSTASCII_USTRINGPARAM("Book"));
[ + - ]
472 [ + - ]: 4 : sal_Bool bExcel5Stream = ( aStorage->IsStream( aStreamName ) );
473 [ - + ][ # # ]: 4 : if ( bExcel97Stream || bExcel5Stream )
474 : : {
475 [ + - ]: 4 : if ( bExcel97Stream )
476 : : {
477 [ + - ]: 4 : String aOldName;
478 : 4 : sal_Bool bIsCalcFilter = sal_True;
479 [ + - ]: 4 : if ( pPreselectedFilter )
480 : : {
481 : : // cross filter; now this should be a type detection only, not a filter detection
482 : : // we can simulate it by preserving the preselected filter if the type matches
483 : : // example: Excel filters for Writer
484 [ + - ]: 4 : aOldName = pPreselectedFilter->GetFilterName();
485 : 4 : bIsCalcFilter = pPreselectedFilter->GetServiceName() == "com.sun.star.sheet.SpreadsheetDocument";
486 : : }
487 : :
488 [ + - ][ + - ]: 4 : if ( aOldName.EqualsAscii(pFilterEx97Temp) || !bIsCalcFilter )
[ - + ][ + - ]
489 : : {
490 : : // Excel 97 template selected -> keep selection
491 : : }
492 [ - + ][ # # ]: 4 : else if ( bExcel5Stream &&
[ # # ][ # # ]
[ # # ][ + - ]
493 [ # # ][ # # ]: 0 : ( aOldName.EqualsAscii(pFilterExcel5) || aOldName.EqualsAscii(pFilterEx5Temp) ||
494 [ # # ][ # # ]: 0 : aOldName.EqualsAscii(pFilterExcel95) || aOldName.EqualsAscii(pFilterEx95Temp) ) )
495 : : {
496 : : // dual format file and Excel 5 selected -> keep selection
497 : : }
498 : : else
499 : : {
500 : : // else use Excel 97 filter
501 [ + - ][ + - ]: 4 : pFilter = aMatcher.GetFilter4FilterName( rtl::OUString(pFilterExcel97) );
[ + - ]
502 [ + - ]: 4 : }
503 : : }
504 [ # # ]: 0 : else if ( bExcel5Stream )
505 : : {
506 [ # # ]: 0 : String aOldName;
507 : 0 : sal_Bool bIsCalcFilter = sal_True;
508 [ # # ]: 0 : if ( pPreselectedFilter )
509 : : {
510 : : // cross filter; now this should be a type detection only, not a filter detection
511 : : // we can simulate it by preserving the preselected filter if the type matches
512 : : // example: Excel filters for Writer
513 [ # # ]: 0 : aOldName = pPreselectedFilter->GetFilterName();
514 : 0 : bIsCalcFilter = pPreselectedFilter->GetServiceName() == "com.sun.star.sheet.SpreadsheetDocument";
515 : : }
516 : :
517 [ # # ][ # # ]: 0 : if ( aOldName.EqualsAscii(pFilterExcel95) || aOldName.EqualsAscii(pFilterEx95Temp) ||
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
518 [ # # ]: 0 : aOldName.EqualsAscii(pFilterEx5Temp) || !bIsCalcFilter )
519 : : {
520 : : // Excel 95 oder Vorlage (5 oder 95) eingestellt -> auch gut
521 : : }
522 [ # # ][ # # ]: 0 : else if ( aOldName.EqualsAscii(pFilterEx97Temp) )
523 : : {
524 : : // auto detection has found template -> return Excel5 template
525 [ # # ][ # # ]: 0 : pFilter = aMatcher.GetFilter4FilterName( rtl::OUString(pFilterEx5Temp) );
[ # # ]
526 : : }
527 : : else
528 : : {
529 : : // sonst wird als Excel 5-Datei erkannt
530 [ # # ][ # # ]: 0 : pFilter = aMatcher.GetFilter4FilterName( rtl::OUString(pFilterExcel5) );
[ # # ]
531 [ # # ]: 0 : }
532 : : }
533 [ + - ]: 4 : }
534 : : }
535 [ # # ]: 0 : else if (nSize > 0)
536 : : {
537 : 0 : SvStream &rStr = *pStream;
538 : :
539 : : // Tabelle mit Suchmustern
540 : : // Bedeutung der Sequenzen
541 : : // 0x00??: genau Byte 0x?? muss an dieser Stelle stehen
542 : : // 0x0100: ein Byte ueberlesen (don't care)
543 : : // 0x02nn: ein Byte aus 0xnn Alternativen folgt
544 : : // 0x8000: Erkennung abgeschlossen
545 : : //
546 : :
547 : : #define M_DC 0x0100
548 : : #define M_ALT(ANZ) (0x0200+(ANZ))
549 : : #define M_ENDE 0x8000
550 : :
551 : : static const sal_uInt16 pLotus[] = // Lotus 1/1A/2
552 : : { 0x0000, 0x0000, 0x0002, 0x0000,
553 : : M_ALT(2), 0x0004, 0x0006,
554 : : 0x0004, M_ENDE };
555 : :
556 : : static const sal_uInt16 pLotusNew[] = // Lotus >= 9.7
557 : : { 0x0000, 0x0000, M_DC, 0x0000, // Rec# + Len (0x1a)
558 : : M_ALT(3), 0x0003, 0x0004, 0x0005, // File Revision Code 97->ME
559 : : 0x0010, 0x0004, 0x0000, 0x0000,
560 : : M_ENDE };
561 : :
562 : : static const sal_uInt16 pExcel1[] = // Excel BIFF2, BIFF3, BIFF4
563 : : { 0x09, // lobyte of BOF rec ID (0x0009, 0x0209, 0x0409)
564 : : M_ALT(3), 0x00, 0x02, 0x04, // hibyte of BOF rec ID (0x0009, 0x0209, 0x0409)
565 : : M_ALT(3), 4, 6, 8, // lobyte of BOF rec size (4, 6, 8, 16)
566 : : 0x00, // hibyte of BOF rec size (4, 6, 8, 16)
567 : : M_DC, M_DC, // any version
568 : : M_ALT(3), 0x10, 0x20, 0x40, // lobyte of data type (0x0010, 0x0020, 0x0040)
569 : : 0x00, // hibyte of data type (0x0010, 0x0020, 0x0040)
570 : : M_ENDE };
571 : :
572 : : static const sal_uInt16 pExcel2[] = // Excel BIFF4 Workspace
573 : : { 0x09, // lobyte of BOF rec ID (0x0409)
574 : : 0x04, // hibyte of BOF rec ID (0x0409)
575 : : M_ALT(3), 4, 6, 8, // lobyte of BOF rec size (4, 6, 8, 16)
576 : : 0x00, // hibyte of BOF rec size (4, 6, 8, 16)
577 : : M_DC, M_DC, // any version
578 : : 0x00, // lobyte of data type (0x0100)
579 : : 0x01, // hibyte of data type (0x0100)
580 : : M_ENDE };
581 : :
582 : : static const sal_uInt16 pExcel3[] = // #i23425# Excel BIFF5, BIFF7, BIFF8 (simple book stream)
583 : : { 0x09, // lobyte of BOF rec ID (0x0809)
584 : : 0x08, // hibyte of BOF rec ID (0x0809)
585 : : M_ALT(4), 4, 6, 8, 16, // lobyte of BOF rec size
586 : : 0x00, // hibyte of BOF rec size
587 : : M_DC, M_DC, // any version
588 : : M_ALT(5), 0x05, 0x06, 0x10, 0x20, 0x40, // lobyte of data type
589 : : 0x00, // hibyte of data type
590 : : M_ENDE };
591 : :
592 : : static const sal_uInt16 pSc10[] = // StarCalc 1.0 Dokumente
593 : : { 'B', 'l', 'a', 'i', 's', 'e', '-', 'T', 'a', 'b', 'e', 'l', 'l',
594 : : 'e', 0x000A, 0x000D, 0x0000, // Sc10CopyRight[16]
595 : : M_DC, M_DC, M_DC, M_DC, M_DC, M_DC, M_DC, M_DC, M_DC, M_DC, M_DC,
596 : : M_DC, M_DC, // Sc10CopyRight[29]
597 : : M_ALT(2), 0x0065, 0x0066, // Versionsnummer 101 oder 102
598 : : 0x0000,
599 : : M_ENDE };
600 : :
601 : : static const sal_uInt16 pLotus2[] = // Lotus >3
602 : : { 0x0000, 0x0000, 0x001A, 0x0000, // Rec# + Len (26)
603 : : M_ALT(2), 0x0000, 0x0002, // File Revision Code
604 : : 0x0010,
605 : : 0x0004, 0x0000, // File Revision Subcode
606 : : M_ENDE };
607 : :
608 : : static const sal_uInt16 pQPro[] =
609 : : { 0x0000, 0x0000, 0x0002, 0x0000,
610 : : M_ALT(4), 0x0001, 0x0002, // WB1, WB2
611 : : 0x0006, 0x0007, // QPro 6/7 (?)
612 : : 0x0010,
613 : : M_ENDE };
614 : :
615 : : static const sal_uInt16 pDIF1[] = // DIF mit CR-LF
616 : : {
617 : : 'T', 'A', 'B', 'L', 'E',
618 : : M_DC, M_DC,
619 : : '0', ',', '1',
620 : : M_DC, M_DC,
621 : : '\"',
622 : : M_ENDE };
623 : :
624 : : static const sal_uInt16 pDIF2[] = // DIF mit CR oder LF
625 : : {
626 : : 'T', 'A', 'B', 'L', 'E',
627 : : M_DC,
628 : : '0', ',', '1',
629 : : M_DC,
630 : : '\"',
631 : : M_ENDE };
632 : :
633 : : static const sal_uInt16 pSylk[] = // Sylk
634 : : {
635 : : 'I', 'D', ';',
636 : : M_ALT(3), 'P', 'N', 'E', // 'P' plus undocumented Excel extensions 'N' and 'E'
637 : : M_ENDE };
638 : :
639 : : static const sal_uInt16 *ppFilterPatterns[] = // Arrays mit Suchmustern
640 : : {
641 : : pLotus,
642 : : pExcel1,
643 : : pExcel2,
644 : : pExcel3,
645 : : pSc10,
646 : : pDIF1,
647 : : pDIF2,
648 : : pSylk,
649 : : pLotusNew,
650 : : pLotus2,
651 : : pQPro
652 : : };
653 : 0 : const sal_uInt16 nFilterCount = sizeof (ppFilterPatterns) / sizeof (ppFilterPatterns[0]);
654 : :
655 : : static const sal_Char* const pFilterName[] = // zugehoerige Filter
656 : : {
657 : : pFilterLotus,
658 : : pFilterExcel4,
659 : : pFilterExcel4,
660 : : pFilterExcel4,
661 : : pFilterSc10,
662 : : pFilterDif,
663 : : pFilterDif,
664 : : pFilterSylk,
665 : : pFilterLotus,
666 : : pFilterLotus,
667 : : pFilterQPro6
668 : : };
669 : :
670 : : // suchen Sie jetzt!
671 : : // ... realisiert ueber 'Mustererkennung'
672 : :
673 : : sal_uInt8 nAkt;
674 : : sal_Bool bSync; // Datei und Muster stimmen ueberein
675 : : sal_uInt16 nFilter; // Zaehler ueber alle Filter
676 : : const sal_uInt16 *pSearch; // aktuelles Musterwort
677 : :
678 [ # # ]: 0 : for ( nFilter = 0 ; nFilter < nFilterCount ; nFilter++ )
679 : : {
680 : 0 : pSearch = ppFilterPatterns[ nFilter ];
681 [ # # ][ # # ]: 0 : if (bCsvSelected && pSearch == pSylk)
682 : : // SYLK 4 characters is really too weak to
683 : : // override preselected CSV, already ID;Name
684 : : // would trigger that. fdo#48347
685 : 0 : continue;
686 : :
687 [ # # ]: 0 : rStr.Seek( 0 ); // am Anfang war alles Uebel...
688 [ # # ]: 0 : rStr >> nAkt;
689 : 0 : bSync = sal_True;
690 [ # # ][ # # ]: 0 : while( !rStr.IsEof() && bSync )
[ # # ]
691 : : {
692 : 0 : register sal_uInt16 nMuster = *pSearch;
693 : :
694 [ # # ]: 0 : if( nMuster < 0x0100 )
695 : : { // direkter Byte-Vergleich
696 [ # # ]: 0 : if( ( sal_uInt8 ) nMuster != nAkt )
697 : 0 : bSync = false;
698 : : }
699 [ # # ]: 0 : else if( nMuster & M_DC )
700 : : { // don't care
701 : : }
702 [ # # ]: 0 : else if( nMuster & M_ALT(0) )
703 : : { // alternative Bytes
704 : 0 : sal_uInt8 nAnzAlt = ( sal_uInt8 ) nMuster;
705 : 0 : bSync = false; // zunaechst unsynchron
706 [ # # ]: 0 : while( nAnzAlt > 0 )
707 : : {
708 : 0 : pSearch++;
709 [ # # ]: 0 : if( ( sal_uInt8 ) *pSearch == nAkt )
710 : 0 : bSync = sal_True; // jetzt erst Synchronisierung
711 : 0 : nAnzAlt--;
712 : : }
713 : : }
714 [ # # ]: 0 : else if( nMuster & M_ENDE )
715 : : { // Format detected
716 [ # # ][ # # ]: 0 : if ( pFilterName[nFilter] == pFilterExcel4 && pPreselectedFilter &&
[ # # ][ # # ]
[ # # ]
717 [ # # ][ # # ]: 0 : ( (pPreselectedFilter)->GetFilterName().EqualsAscii(pFilterEx4Temp) || pPreselectedFilter->GetTypeName().EqualsAscii("calc_MS_Excel_40") ) )
718 : : {
719 : : // Excel 4 erkannt, Excel 4 Vorlage eingestellt -> auch gut
720 : : // oder Excel 4 Filter anderer Applikation (simulated type detection!)
721 : : }
722 : : else
723 : : { // gefundenen Filter einstellen
724 [ # # ][ # # ]: 0 : pFilter = aMatcher.GetFilter4FilterName( rtl::OUString::createFromAscii(pFilterName[ nFilter ]) );
[ # # ]
725 : : }
726 : 0 : bSync = false; // leave inner loop
727 : 0 : nFilter = nFilterCount; // leave outer loop
728 : : }
729 : : else
730 : : { // Tabellenfehler
731 : : OSL_FAIL( "-ScApplication::DetectFilter(): Fehler in Mustertabelle");
732 : : }
733 : :
734 : 0 : pSearch++;
735 [ # # ]: 0 : rStr >> nAkt;
736 : : }
737 : : }
738 : :
739 [ # # ][ # # ]: 0 : if ( pPreselectedFilter && !pFilter )
740 : : {
741 : : // further checks for filters only if they are preselected: ASCII, HTML, RTF, DBase
742 : : // without the preselection other filters (Writer) take precedence
743 : : // DBase can't be detected reliably, so it also needs preselection
744 : :
745 [ # # ]: 0 : bool bMaybeText = lcl_MayBeAscii( rStr );
746 : :
747 : : // get file header
748 [ # # ]: 0 : rStr.Seek( 0 );
749 : 0 : const sal_Size nTrySize = 80;
750 [ # # ]: 0 : rtl::OString aHeader = read_uInt8s_ToOString(rStr, nTrySize);
751 : :
752 [ # # ]: 0 : bool bMaybeHtml = HTMLParser::IsHTMLFormat( aHeader.getStr());
753 : :
754 [ # # ]: 0 : if ( aHeader.copy(0, 5).equalsL("{\\rtf", 5) )
755 : : {
756 : : // test for RTF
757 [ # # ][ # # ]: 0 : pFilter = aMatcher.GetFilter4FilterName( rtl::OUString(pFilterRtf) );
[ # # ]
758 : : }
759 [ # # ][ # # ]: 0 : else if ( bIsXLS && (bMaybeText && !bMaybeHtml) )
[ # # ]
760 : : {
761 [ # # ]: 0 : aHeader = comphelper::string::stripStart(aHeader, ' ');
762 : : // Detect Excel 2003 XML here only if XLS was preselected.
763 : : // The configured detection for Excel 2003 XML is still in XMLFilterDetect.
764 [ # # ]: 0 : pFilter = lcl_DetectExcelXML( rStr, aMatcher );
765 [ # # ]: 0 : if (!pFilter)
766 [ # # ][ # # ]: 0 : pFilter = aMatcher.GetFilter4FilterName( rtl::OUString(pFilterAscii) );
[ # # ]
767 : 0 : bFakeXLS = true;
768 : : }
769 [ # # ][ # # ]: 0 : else if ( pPreselectedFilter->GetName().EqualsAscii(pFilterDBase) && lcl_MayBeDBase( rStr ) )
[ # # ][ # # ]
[ # # ]
770 : 0 : pFilter = pPreselectedFilter;
771 [ # # ][ # # ]: 0 : else if ( bCsvSelected && bMaybeText )
772 : 0 : pFilter = pPreselectedFilter;
773 [ # # ]: 0 : else if ( bMaybeHtml )
774 : : {
775 : : // test for HTML
776 : :
777 : : // HTMLParser::IsHTMLFormat() is convinced that
778 : : // anything containing a valid HTML tag would
779 : : // indeed be HTML, which is a rather idiotic
780 : : // assumption for us in the case of
781 : : // "foo <br> bar" with a preselected CSV
782 : : // filter. So keep this detection to the end.
783 : :
784 [ # # ][ # # ]: 0 : if ( pPreselectedFilter->GetName().EqualsAscii(pFilterHtml) )
785 : : {
786 : 0 : pFilter = pPreselectedFilter;
787 : : }
788 : : else
789 : : {
790 [ # # ][ # # ]: 0 : pFilter = aMatcher.GetFilter4FilterName( rtl::OUString(pFilterHtmlWeb) );
[ # # ]
791 [ # # ]: 0 : if ( bIsXLS )
792 : 0 : bFakeXLS = true;
793 : : }
794 : 0 : }
795 : : }
796 : : }
797 : : else
798 : : {
799 : : // 0-length stream, preselected Text/CSV is ok, user
800 : : // may want to write to that file later.
801 [ # # ]: 0 : if ( bCsvSelected )
802 : 0 : pFilter = pPreselectedFilter;
803 [ + - ]: 4 : }
804 : : }
805 : : }
806 [ + - ][ + - ]: 47 : }
807 : : }
808 : :
809 [ - + ][ # # ]: 47 : if ( nIndexOfInputStream == -1 && xStream.is() )
[ - + ]
810 : : {
811 : : // if input stream wasn't part of the descriptor, now it should be, otherwise the content would be opend twice
812 [ # # ]: 0 : lDescriptor.realloc( nPropertyCount + 1 );
813 [ # # ][ # # ]: 0 : lDescriptor[nPropertyCount].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("InputStream"));
814 [ # # ][ # # ]: 0 : lDescriptor[nPropertyCount].Value <<= xStream;
815 : 0 : nPropertyCount++;
816 : : }
817 : :
818 [ + + ][ + - ]: 47 : if ( nIndexOfContent == -1 && xContent.is() )
[ + + ]
819 : : {
820 : : // if input stream wasn't part of the descriptor, now it should be, otherwise the content would be opend twice
821 [ + - ]: 5 : lDescriptor.realloc( nPropertyCount + 1 );
822 [ + - ][ + - ]: 5 : lDescriptor[nPropertyCount].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("UCBContent"));
823 [ + - ][ + - ]: 5 : lDescriptor[nPropertyCount].Value <<= xContent;
824 : 5 : nPropertyCount++;
825 : : }
826 : :
827 [ - + ]: 47 : if ( bReadOnly != bWasReadOnly )
828 : : {
829 [ # # ]: 0 : if ( nIndexOfReadOnlyFlag == -1 )
830 : : {
831 [ # # ]: 0 : lDescriptor.realloc( nPropertyCount + 1 );
832 [ # # ][ # # ]: 0 : lDescriptor[nPropertyCount].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ReadOnly"));
833 [ # # ][ # # ]: 0 : lDescriptor[nPropertyCount].Value <<= bReadOnly;
834 : 0 : nPropertyCount++;
835 : : }
836 : : else
837 [ # # ][ # # ]: 0 : lDescriptor[nIndexOfReadOnlyFlag].Value <<= bReadOnly;
838 : : }
839 : :
840 [ + - ][ - + ]: 47 : if ( !bRepairPackage && bRepairAllowed )
841 : : {
842 [ # # ]: 0 : lDescriptor.realloc( nPropertyCount + 1 );
843 [ # # ][ # # ]: 0 : lDescriptor[nPropertyCount].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("RepairPackage"));
844 [ # # ][ # # ]: 0 : lDescriptor[nPropertyCount].Value <<= bRepairAllowed;
845 : 0 : nPropertyCount++;
846 : :
847 : 0 : bOpenAsTemplate = sal_True;
848 : :
849 : : // TODO/LATER: set progress bar that should be used
850 : : }
851 : :
852 [ - + ]: 47 : if ( bOpenAsTemplate )
853 : : {
854 [ # # ]: 0 : if ( nIndexOfTemplateFlag == -1 )
855 : : {
856 [ # # ]: 0 : lDescriptor.realloc( nPropertyCount + 1 );
857 [ # # ][ # # ]: 0 : lDescriptor[nPropertyCount].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("AsTemplate"));
858 [ # # ][ # # ]: 0 : lDescriptor[nPropertyCount].Value <<= bOpenAsTemplate;
859 : 0 : nPropertyCount++;
860 : : }
861 : : else
862 [ # # ][ # # ]: 0 : lDescriptor[nIndexOfTemplateFlag].Value <<= bOpenAsTemplate;
863 : : }
864 : :
865 [ - + ]: 47 : if ( !aDocumentTitle.isEmpty() )
866 : : {
867 : : // the title was set here
868 [ # # ]: 0 : if ( nIndexOfDocumentTitle == -1 )
869 : : {
870 [ # # ]: 0 : lDescriptor.realloc( nPropertyCount + 1 );
871 [ # # ][ # # ]: 0 : lDescriptor[nPropertyCount].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("DocumentTitle"));
872 [ # # ][ # # ]: 0 : lDescriptor[nPropertyCount].Value <<= aDocumentTitle;
873 : 0 : nPropertyCount++;
874 : : }
875 : : else
876 [ # # ][ # # ]: 0 : lDescriptor[nIndexOfDocumentTitle].Value <<= aDocumentTitle;
877 : : }
878 : :
879 [ - + ]: 47 : if ( bFakeXLS )
880 : : {
881 [ # # ]: 0 : if ( nIndexOfFilterName == -1 )
882 : : {
883 [ # # ]: 0 : lDescriptor.realloc( nPropertyCount + 1 );
884 [ # # ][ # # ]: 0 : lDescriptor[nPropertyCount].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("FilterName"));
885 [ # # ][ # # ]: 0 : lDescriptor[nPropertyCount].Value <<= rtl::OUString(pFilter->GetName());
[ # # ]
886 : 0 : nPropertyCount++;
887 : : }
888 : : else
889 [ # # ][ # # ]: 0 : lDescriptor[nIndexOfFilterName].Value <<= rtl::OUString(pFilter->GetName());
[ # # ]
890 : : }
891 : :
892 [ + + ]: 47 : if ( pFilter )
893 [ + - ]: 37 : aTypeName = pFilter->GetTypeName();
894 : : else
895 [ + - ]: 10 : aTypeName.Erase();
896 [ + - ][ + - ]: 47 : return aTypeName;
[ + - ][ + - ]
[ + - ][ + - ]
897 : : }
898 : :
899 : : /* XServiceInfo */
900 : 0 : rtl::OUString SAL_CALL ScFilterDetect::getImplementationName() throw( UNORUNTIMEEXCEPTION )
901 : : {
902 : 0 : return impl_getStaticImplementationName();
903 : : }
904 : : \
905 : : /* XServiceInfo */
906 : 0 : sal_Bool SAL_CALL ScFilterDetect::supportsService( const rtl::OUString& sServiceName ) throw( UNORUNTIMEEXCEPTION )
907 : : {
908 [ # # ]: 0 : UNOSEQUENCE< rtl::OUString > seqServiceNames(getSupportedServiceNames());
909 : 0 : const rtl::OUString* pArray = seqServiceNames.getConstArray();
910 [ # # ]: 0 : for ( sal_Int32 nCounter=0; nCounter<seqServiceNames.getLength(); nCounter++ )
911 : : {
912 [ # # ]: 0 : if ( pArray[nCounter] == sServiceName )
913 : : {
914 : 0 : return sal_True ;
915 : : }
916 : : }
917 [ # # ]: 0 : return false ;
918 : : }
919 : :
920 : : /* XServiceInfo */
921 : 0 : UNOSEQUENCE< rtl::OUString > SAL_CALL ScFilterDetect::getSupportedServiceNames() throw( UNORUNTIMEEXCEPTION )
922 : : {
923 : 0 : return impl_getStaticSupportedServiceNames();
924 : : }
925 : :
926 : : /* Helper for XServiceInfo */
927 : 27 : UNOSEQUENCE< rtl::OUString > ScFilterDetect::impl_getStaticSupportedServiceNames()
928 : : {
929 : 27 : UNOSEQUENCE< rtl::OUString > seqServiceNames( 1 );
930 [ + - ][ + - ]: 27 : seqServiceNames.getArray() [0] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.ExtendedTypeDetection" ));
931 : 27 : return seqServiceNames ;
932 : : }
933 : :
934 : : /* Helper for XServiceInfo */
935 : 54 : OUString ScFilterDetect::impl_getStaticImplementationName()
936 : : {
937 : 54 : return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.calc.FormatDetector" ));
938 : : }
939 : :
940 : : /* Helper for registry */
941 : 47 : UNOREFERENCE< UNOXINTERFACE > SAL_CALL ScFilterDetect::impl_createInstance( const UNOREFERENCE< UNOXMULTISERVICEFACTORY >& xServiceManager ) throw( UNOEXCEPTION )
942 : : {
943 [ + - ]: 47 : return UNOREFERENCE< UNOXINTERFACE >( *new ScFilterDetect( xServiceManager ) );
944 : : }
945 : :
946 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|