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"
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
;
55 // ============================================================================
57 Sequence
< OUString
> BiffDetector_getSupportedServiceNames()
59 Sequence
< OUString
> aServiceNames( 1 );
60 aServiceNames
[ 0 ] = CREATE_OUSTRING( "com.sun.star.frame.ExtendedTypeDetection" );
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();
92 sal_uInt16 nBofId
, nBofSize
;
93 rInStream
>> nBofId
>> nBofSize
;
95 if( (4 <= nBofSize
) && (nBofSize
<= 16) && (rInStream
.tell() + nBofSize
<= rInStream
.getLength()) )
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() );
130 // else do nothing, no BIFF stream
133 rInStream
.seek( nOldPos
);
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
;
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
;
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();
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
)
210 MediaDescriptor
aDescriptor( rDescriptor
);
211 aDescriptor
.addInputStream();
213 Reference
< XInputStream
> xInStrm( aDescriptor
[ MediaDescriptor::PROP_INPUTSTREAM() ], UNO_QUERY
);
216 OUString aWorkbookName
;
217 StorageRef
xStorage( new OleStorage( mxFactory
, xInStrm
, true ) );
218 switch( detectStorageBiffVersion( aWorkbookName
, xStorage
) )
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;
232 // ============================================================================