1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <oox/ole/axbinaryreader.hxx>
22 #include <oox/ole/axfontdata.hxx>
23 #include <oox/ole/olehelper.hxx>
25 #include <osl/diagnose.h>
32 const sal_uInt32 AX_STRING_SIZEMASK
= 0x7FFFFFFF;
33 const sal_uInt32 AX_STRING_COMPRESSED
= 0x80000000;
37 AxAlignedInputStream::AxAlignedInputStream( BinaryInputStream
& rInStrm
) :
38 BinaryStreamBase( false ),
41 mnStrmSize( rInStrm
.getRemaining() )
43 mbEof
= mbEof
|| rInStrm
.isEof();
46 sal_Int64
AxAlignedInputStream::size() const
48 return mpInStrm
? mnStrmSize
: -1;
51 sal_Int64
AxAlignedInputStream::tell() const
53 return mpInStrm
? mnStrmPos
: -1;
56 void AxAlignedInputStream::seek( sal_Int64 nPos
)
58 mbEof
= mbEof
|| (nPos
< mnStrmPos
);
60 skip( static_cast< sal_Int32
>( nPos
- mnStrmPos
) );
63 void AxAlignedInputStream::close()
69 sal_Int32
AxAlignedInputStream::readData( StreamDataSequence
& orData
, sal_Int32 nBytes
, size_t nAtomSize
)
71 sal_Int32 nReadSize
= 0;
74 nReadSize
= mpInStrm
->readData( orData
, nBytes
, nAtomSize
);
75 mnStrmPos
+= nReadSize
;
76 mbEof
= mpInStrm
->isEof();
81 sal_Int32
AxAlignedInputStream::readMemory( void* opMem
, sal_Int32 nBytes
, size_t nAtomSize
)
83 sal_Int32 nReadSize
= 0;
86 nReadSize
= mpInStrm
->readMemory( opMem
, nBytes
, nAtomSize
);
87 mnStrmPos
+= nReadSize
;
88 mbEof
= mpInStrm
->isEof();
93 void AxAlignedInputStream::skip( sal_Int32 nBytes
, size_t nAtomSize
)
97 mpInStrm
->skip( nBytes
, nAtomSize
);
99 mbEof
= mpInStrm
->isEof();
103 void AxAlignedInputStream::align( size_t nSize
)
105 skip( static_cast< sal_Int32
>( (nSize
- (mnStrmPos
% nSize
)) % nSize
) );
110 bool lclReadString( AxAlignedInputStream
& rInStrm
, OUString
& rValue
, sal_uInt32 nSize
, bool bArrayString
)
112 bool bCompressed
= getFlag( nSize
, AX_STRING_COMPRESSED
);
113 sal_uInt32 nBufSize
= nSize
& AX_STRING_SIZEMASK
;
114 // Unicode: simple strings store byte count, array strings store char count
115 sal_Int32 nChars
= static_cast< sal_Int32
>( nBufSize
/ ((bCompressed
|| bArrayString
) ? 1 : 2) );
116 bool bValidChars
= nChars
<= 65536;
117 OSL_ENSURE( bValidChars
, "lclReadString - string too long" );
118 sal_Int64 nEndPos
= rInStrm
.tell() + nChars
* (bCompressed
? 1 : 2);
119 nChars
= ::std::min
< sal_Int32
>( nChars
, 65536 );
120 rValue
= rInStrm
.readCompressedUnicodeArray( nChars
, bCompressed
);
121 rInStrm
.seek( nEndPos
);
127 AxBinaryPropertyReader::ComplexProperty::~ComplexProperty()
131 bool AxBinaryPropertyReader::PairProperty::readProperty( AxAlignedInputStream
& rInStrm
)
133 mrPairData
.first
= rInStrm
.readInt32();
134 mrPairData
.second
= rInStrm
.readInt32();
138 bool AxBinaryPropertyReader::StringProperty::readProperty( AxAlignedInputStream
& rInStrm
)
140 return lclReadString( rInStrm
, mrValue
, mnSize
, false );
143 bool AxBinaryPropertyReader::ArrayStringProperty::readProperty( AxAlignedInputStream
& rInStrm
)
145 sal_Int64 nEndPos
= rInStrm
.tell() + mnSize
;
146 while( rInStrm
.tell() < nEndPos
)
149 if( !lclReadString( rInStrm
, aString
, rInStrm
.readuInt32(), true ) )
151 mrArray
.push_back( aString
);
152 // every array string is aligned on 4 byte boundaries
158 bool AxBinaryPropertyReader::GuidProperty::readProperty( AxAlignedInputStream
& rInStrm
)
160 mrGuid
= OleHelper::importGuid( rInStrm
);
164 bool AxBinaryPropertyReader::FontProperty::readProperty( AxAlignedInputStream
& rInStrm
)
166 return mrFontData
.importGuidAndFont( rInStrm
);
169 bool AxBinaryPropertyReader::PictureProperty::readProperty( AxAlignedInputStream
& rInStrm
)
171 return OleHelper::importStdPic( mrPicData
, rInStrm
);
174 AxBinaryPropertyReader::AxBinaryPropertyReader( BinaryInputStream
& rInStrm
, bool b64BitPropFlags
) :
178 // version and size of property block
180 sal_uInt16 nBlockSize
= maInStrm
.readuInt16();
181 mnPropsEnd
= maInStrm
.tell() + nBlockSize
;
182 // flagfield containing existing properties
183 if( b64BitPropFlags
)
184 mnPropFlags
= maInStrm
.readInt64();
186 mnPropFlags
= maInStrm
.readuInt32();
190 void AxBinaryPropertyReader::readBoolProperty( bool& orbValue
, bool bReverse
)
192 // there is no data, the boolean value is equivalent to the property flag itself
193 orbValue
= startNextProperty() != bReverse
;
196 void AxBinaryPropertyReader::readPairProperty( AxPairData
& orPairData
)
198 if( startNextProperty() )
199 maLargeProps
.push_back( ComplexPropVector::value_type( new PairProperty( orPairData
) ) );
202 void AxBinaryPropertyReader::readStringProperty( OUString
& orValue
)
204 if( startNextProperty() )
206 sal_uInt32 nSize
= maInStrm
.readAligned
< sal_uInt32
>();
207 maLargeProps
.push_back( ComplexPropVector::value_type( new StringProperty( orValue
, nSize
) ) );
211 void AxBinaryPropertyReader::readArrayStringProperty( std::vector
<OUString
>& orValue
)
213 if( startNextProperty() )
215 sal_uInt32 nSize
= maInStrm
.readAligned
< sal_uInt32
>();
216 maLargeProps
.push_back( ComplexPropVector::value_type( new ArrayStringProperty( orValue
, nSize
) ) );
220 void AxBinaryPropertyReader::readGuidProperty( OUString
& orGuid
)
222 if( startNextProperty() )
223 maLargeProps
.push_back( ComplexPropVector::value_type( new GuidProperty( orGuid
) ) );
226 void AxBinaryPropertyReader::readFontProperty( AxFontData
& orFontData
)
228 if( startNextProperty() )
230 sal_Int16 nData
= maInStrm
.readAligned
< sal_Int16
>();
231 if( ensureValid( nData
== -1 ) )
232 maStreamProps
.push_back( ComplexPropVector::value_type( new FontProperty( orFontData
) ) );
236 void AxBinaryPropertyReader::readPictureProperty( StreamDataSequence
& orPicData
)
238 if( startNextProperty() )
240 sal_Int16 nData
= maInStrm
.readAligned
< sal_Int16
>();
241 if( ensureValid( nData
== -1 ) )
242 maStreamProps
.push_back( ComplexPropVector::value_type( new PictureProperty( orPicData
) ) );
246 bool AxBinaryPropertyReader::finalizeImport()
248 // read large properties
250 if( ensureValid( mnPropFlags
== 0 ) )
252 for (auto const& largeProp
: maLargeProps
)
256 ensureValid( largeProp
->readProperty( maInStrm
) );
260 maInStrm
.seek( mnPropsEnd
);
262 // read stream properties (no stream alignment between properties!)
265 for (auto const& streamProp
: maStreamProps
)
269 ensureValid( streamProp
->readProperty( maInStrm
) );
276 bool AxBinaryPropertyReader::ensureValid( bool bCondition
)
278 mbValid
= mbValid
&& bCondition
&& !maInStrm
.isEof();
282 bool AxBinaryPropertyReader::startNextProperty()
284 bool bHasProp
= getFlag( mnPropFlags
, mnNextProp
);
285 setFlag( mnPropFlags
, mnNextProp
, false );
287 return ensureValid() && bHasProp
;
293 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */