Update ooo320-m1
[ooovba.git] / oox / source / xls / biffdetector.cxx
blobc7c466f067e6810795a20fdf3b81f852d9ccbf8e
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: biffdetector.cxx,v $
10 * $Revision: 1.3.22.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 #include "oox/xls/biffdetector.hxx"
32 #include <algorithm>
33 #include <rtl/strbuf.hxx>
34 #include <com/sun/star/io/XInputStream.hpp>
35 #include <comphelper/mediadescriptor.hxx>
36 #include "oox/helper/binaryinputstream.hxx"
37 #include "oox/helper/olestorage.hxx"
39 using ::rtl::OUString;
40 using ::rtl::OStringBuffer;
41 using ::com::sun::star::uno::Reference;
42 using ::com::sun::star::uno::Sequence;
43 using ::com::sun::star::uno::Exception;
44 using ::com::sun::star::uno::RuntimeException;
45 using ::com::sun::star::uno::XInterface;
46 using ::com::sun::star::uno::UNO_QUERY;
47 using ::com::sun::star::lang::XMultiServiceFactory;
48 using ::com::sun::star::beans::PropertyValue;
49 using ::com::sun::star::io::XInputStream;
50 using ::comphelper::MediaDescriptor;
52 namespace oox {
53 namespace xls {
55 // ============================================================================
57 Sequence< OUString > BiffDetector_getSupportedServiceNames()
59 Sequence< OUString > aServiceNames( 1 );
60 aServiceNames[ 0 ] = CREATE_OUSTRING( "com.sun.star.frame.ExtendedTypeDetection" );
61 return aServiceNames;
64 OUString BiffDetector_getImplementationName()
66 return CREATE_OUSTRING( "com.sun.star.comp.oox.BiffDetector" );
69 Reference< XInterface > SAL_CALL BiffDetector_createInstance( const Reference< XMultiServiceFactory >& rxFactory ) throw( Exception )
71 return static_cast< ::cppu::OWeakObject* >( new BiffDetector( rxFactory ) );
74 // ============================================================================
76 BiffDetector::BiffDetector( const Reference< XMultiServiceFactory >& rxFactory ) :
77 mxFactory( rxFactory )
81 BiffDetector::~BiffDetector()
85 BiffType BiffDetector::detectStreamBiffVersion( BinaryInputStream& rInStream )
87 BiffType eBiff = BIFF_UNKNOWN;
88 if( !rInStream.isEof() && rInStream.isSeekable() && (rInStream.getLength() > 4) )
90 sal_Int64 nOldPos = rInStream.tell();
91 rInStream.seek( 0 );
92 sal_uInt16 nBofId, nBofSize;
93 rInStream >> nBofId >> nBofSize;
95 if( (4 <= nBofSize) && (nBofSize <= 16) && (rInStream.tell() + nBofSize <= rInStream.getLength()) )
97 switch( nBofId )
99 case BIFF2_ID_BOF:
100 eBiff = BIFF2;
101 break;
102 case BIFF3_ID_BOF:
103 eBiff = BIFF3;
104 break;
105 case BIFF4_ID_BOF:
106 eBiff = BIFF4;
107 break;
108 case BIFF5_ID_BOF:
110 if( 6 <= nBofSize )
112 sal_uInt16 nVersion;
113 rInStream >> nVersion;
114 // #i23425# #i44031# #i62752# there are some *really* broken documents out there...
115 switch( nVersion & 0xFF00 )
117 case 0: eBiff = BIFF5; break; // #i44031# #i62752#
118 case BIFF_BOF_BIFF2: eBiff = BIFF2; break;
119 case BIFF_BOF_BIFF3: eBiff = BIFF3; break;
120 case BIFF_BOF_BIFF4: eBiff = BIFF4; break;
121 case BIFF_BOF_BIFF5: eBiff = BIFF5; break;
122 case BIFF_BOF_BIFF8: eBiff = BIFF8; break;
123 default: OSL_ENSURE( false,
124 OStringBuffer( "lclDetectStreamBiffVersion - unknown BIFF version: 0x" ).
125 append( static_cast< sal_Int32 >( nVersion ), 16 ).getStr() );
129 break;
130 // else do nothing, no BIFF stream
133 rInStream.seek( nOldPos );
135 return eBiff;
138 BiffType BiffDetector::detectStorageBiffVersion( OUString& orWorkbookStreamName, StorageRef xStorage )
140 static const OUString saBookName = CREATE_OUSTRING( "Book" );
141 static const OUString saWorkbookName = CREATE_OUSTRING( "Workbook" );
143 BiffType eBiff = BIFF_UNKNOWN;
144 if( xStorage.get() )
146 if( xStorage->isStorage() )
148 // try to open the "Book" stream
149 BinaryXInputStream aBookStrm5( xStorage->openInputStream( saBookName ), true );
150 BiffType eBookStrm5Biff = detectStreamBiffVersion( aBookStrm5 );
152 // try to open the "Workbook" stream
153 BinaryXInputStream aBookStrm8( xStorage->openInputStream( saWorkbookName ), true );
154 BiffType eBookStrm8Biff = detectStreamBiffVersion( aBookStrm8 );
156 // decide which stream to use
157 if( (eBookStrm8Biff != BIFF_UNKNOWN) && ((eBookStrm5Biff == BIFF_UNKNOWN) || (eBookStrm8Biff > eBookStrm5Biff)) )
159 /* Only "Workbook" stream exists; or both streams exist,
160 and "Workbook" has higher BIFF version than "Book" stream. */
161 eBiff = eBookStrm8Biff;
162 orWorkbookStreamName = saWorkbookName;
164 else if( eBookStrm5Biff != BIFF_UNKNOWN )
166 /* Only "Book" stream exists; or both streams exist,
167 and "Book" has higher BIFF version than "Workbook" stream. */
168 eBiff = eBookStrm5Biff;
169 orWorkbookStreamName = saBookName;
172 else
174 // no storage, try plain input stream from medium (even for BIFF5+)
175 BinaryXInputStream aStrm( xStorage->openInputStream( OUString() ), false );
176 eBiff = detectStreamBiffVersion( aStrm );
177 orWorkbookStreamName = OUString();
181 return eBiff;
184 // com.sun.star.lang.XServiceInfo interface -----------------------------------
186 OUString SAL_CALL BiffDetector::getImplementationName() throw( RuntimeException )
188 return BiffDetector_getImplementationName();
191 sal_Bool SAL_CALL BiffDetector::supportsService( const OUString& rService ) throw( RuntimeException )
193 const Sequence< OUString > aServices( BiffDetector_getSupportedServiceNames() );
194 const OUString* pArray = aServices.getConstArray();
195 const OUString* pArrayEnd = pArray + aServices.getLength();
196 return ::std::find( pArray, pArrayEnd, rService ) != pArrayEnd;
199 Sequence< OUString > SAL_CALL BiffDetector::getSupportedServiceNames() throw( RuntimeException )
201 return BiffDetector_getSupportedServiceNames();
204 // com.sun.star.document.XExtendedFilterDetect interface ----------------------
206 OUString SAL_CALL BiffDetector::detect( Sequence< PropertyValue >& rDescriptor ) throw( RuntimeException )
208 OUString aTypeName;
210 MediaDescriptor aDescriptor( rDescriptor );
211 aDescriptor.addInputStream();
213 Reference< XInputStream > xInStrm( aDescriptor[ MediaDescriptor::PROP_INPUTSTREAM() ], UNO_QUERY );
214 if( xInStrm.is() )
216 OUString aWorkbookName;
217 StorageRef xStorage( new OleStorage( mxFactory, xInStrm, true ) );
218 switch( detectStorageBiffVersion( aWorkbookName, xStorage ) )
220 case BIFF2:
221 case BIFF3:
222 case BIFF4: aTypeName = CREATE_OUSTRING( "calc_MS_Excel_40" ); break;
223 case BIFF5: aTypeName = CREATE_OUSTRING( "calc_MS_Excel_95" ); break;
224 case BIFF8: aTypeName = CREATE_OUSTRING( "calc_MS_Excel_97" ); break;
225 default:;
229 return aTypeName;
232 // ============================================================================
234 } // namespace xls
235 } // namespace oox