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