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