LibreOffice Module oox (master)  1
axbinaryreader.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
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 .
18  */
19 
21 
22 #include <oox/ole/axfontdata.hxx>
23 #include <oox/ole/olehelper.hxx>
24 
25 #include <osl/diagnose.h>
26 
27 namespace oox::ole {
28 
29 namespace {
30 
31 const sal_uInt32 AX_STRING_SIZEMASK = 0x7FFFFFFF;
32 const sal_uInt32 AX_STRING_COMPRESSED = 0x80000000;
33 
34 } // namespace
35 
37  BinaryStreamBase( false ),
38  mpInStrm( &rInStrm ),
39  mnStrmPos( 0 ),
40  mnStrmSize( rInStrm.getRemaining() )
41 {
42  mbEof = mbEof || rInStrm.isEof();
43 }
44 
45 sal_Int64 AxAlignedInputStream::size() const
46 {
47  return mpInStrm ? mnStrmSize : -1;
48 }
49 
50 sal_Int64 AxAlignedInputStream::tell() const
51 {
52  return mpInStrm ? mnStrmPos : -1;
53 }
54 
55 void AxAlignedInputStream::seek( sal_Int64 nPos )
56 {
57  mbEof = mbEof || (nPos < mnStrmPos);
58  if( !mbEof )
59  skip( static_cast< sal_Int32 >( nPos - mnStrmPos ) );
60 }
61 
63 {
64  mpInStrm = nullptr;
65  mbEof = true;
66 }
67 
68 sal_Int32 AxAlignedInputStream::readData( StreamDataSequence& orData, sal_Int32 nBytes, size_t nAtomSize )
69 {
70  sal_Int32 nReadSize = 0;
71  if( !mbEof )
72  {
73  nReadSize = mpInStrm->readData( orData, nBytes, nAtomSize );
74  mnStrmPos += nReadSize;
75  mbEof = mpInStrm->isEof();
76  }
77  return nReadSize;
78 }
79 
80 sal_Int32 AxAlignedInputStream::readMemory( void* opMem, sal_Int32 nBytes, size_t nAtomSize )
81 {
82  sal_Int32 nReadSize = 0;
83  if( !mbEof )
84  {
85  nReadSize = mpInStrm->readMemory( opMem, nBytes, nAtomSize );
86  mnStrmPos += nReadSize;
87  mbEof = mpInStrm->isEof();
88  }
89  return nReadSize;
90 }
91 
92 void AxAlignedInputStream::skip( sal_Int32 nBytes, size_t nAtomSize )
93 {
94  if( !mbEof )
95  {
96  mpInStrm->skip( nBytes, nAtomSize );
97  mnStrmPos += nBytes;
98  mbEof = mpInStrm->isEof();
99  }
100 }
101 
102 void AxAlignedInputStream::align( size_t nSize )
103 {
104  skip( static_cast< sal_Int32 >( (nSize - (mnStrmPos % nSize)) % nSize ) );
105 }
106 
107 namespace {
108 
109 bool lclReadString( AxAlignedInputStream& rInStrm, OUString& rValue, sal_uInt32 nSize, bool bArrayString )
110 {
111  bool bCompressed = getFlag( nSize, AX_STRING_COMPRESSED );
112  sal_uInt32 nBufSize = nSize & AX_STRING_SIZEMASK;
113  // Unicode: simple strings store byte count, array strings store char count
114  sal_Int32 nChars = static_cast< sal_Int32 >( nBufSize / ((bCompressed || bArrayString) ? 1 : 2) );
115  bool bValidChars = nChars <= 65536;
116  OSL_ENSURE( bValidChars, "lclReadString - string too long" );
117  sal_Int64 nEndPos = rInStrm.tell() + nChars * (bCompressed ? 1 : 2);
118  nChars = ::std::min< sal_Int32 >( nChars, 65536 );
119  rValue = rInStrm.readCompressedUnicodeArray( nChars, bCompressed );
120  rInStrm.seek( nEndPos );
121  return bValidChars;
122 }
123 
124 } // namespace
125 
127 {
128 }
129 
131 {
132  mrPairData.first = rInStrm.readInt32();
133  mrPairData.second = rInStrm.readInt32();
134  return true;
135 }
136 
138 {
139  return lclReadString( rInStrm, mrValue, mnSize, false );
140 }
141 
143 {
144  sal_Int64 nEndPos = rInStrm.tell() + mnSize;
145  while( rInStrm.tell() < nEndPos )
146  {
147  OUString aString;
148  if( !lclReadString( rInStrm, aString, rInStrm.readuInt32(), true ) )
149  return false;
150  mrArray.push_back( aString );
151  // every array string is aligned on 4 byte boundaries
152  rInStrm.align( 4 );
153  }
154  return true;
155 }
156 
158 {
159  mrGuid = OleHelper::importGuid( rInStrm );
160  return true;
161 }
162 
164 {
165  return mrFontData.importGuidAndFont( rInStrm );
166 }
167 
169 {
170  return OleHelper::importStdPic( mrPicData, rInStrm );
171 }
172 
174  maInStrm( rInStrm ),
175  mbValid( true )
176 {
177  // version and size of property block
178  maInStrm.skip( 2 );
179  sal_uInt16 nBlockSize = maInStrm.readuInt16();
180  mnPropsEnd = maInStrm.tell() + nBlockSize;
181  // flagfield containing existing properties
182  if( b64BitPropFlags )
184  else
186  mnNextProp = 1;
187 }
188 
189 void AxBinaryPropertyReader::readBoolProperty( bool& orbValue, bool bReverse )
190 {
191  // there is no data, the boolean value is equivalent to the property flag itself
192  orbValue = startNextProperty() != bReverse;
193 }
194 
196 {
197  if( startNextProperty() )
198  maLargeProps.push_back( ComplexPropVector::value_type( std::make_shared<PairProperty>( orPairData ) ) );
199 }
200 
202 {
203  if( startNextProperty() )
204  {
205  sal_uInt32 nSize = maInStrm.readAligned< sal_uInt32 >();
206  maLargeProps.push_back( ComplexPropVector::value_type( std::make_shared<StringProperty>( orValue, nSize ) ) );
207  }
208 }
209 
210 void AxBinaryPropertyReader::readArrayStringProperty( std::vector<OUString>& orValue )
211 {
212  if( startNextProperty() )
213  {
214  sal_uInt32 nSize = maInStrm.readAligned< sal_uInt32 >();
215  maLargeProps.push_back( ComplexPropVector::value_type( std::make_shared<ArrayStringProperty>( orValue, nSize ) ) );
216  }
217 }
218 
220 {
221  if( startNextProperty() )
222  maLargeProps.push_back( ComplexPropVector::value_type( std::make_shared<GuidProperty>( orGuid ) ) );
223 }
224 
226 {
227  if( startNextProperty() )
228  {
229  sal_Int16 nData = maInStrm.readAligned< sal_Int16 >();
230  if( ensureValid( nData == -1 ) )
231  maStreamProps.push_back( ComplexPropVector::value_type( std::make_shared<FontProperty>( orFontData ) ) );
232  }
233 }
234 
236 {
237  if( startNextProperty() )
238  {
239  sal_Int16 nData = maInStrm.readAligned< sal_Int16 >();
240  if( ensureValid( nData == -1 ) )
241  maStreamProps.push_back( ComplexPropVector::value_type( std::make_shared<PictureProperty>( orPicData ) ) );
242  }
243 }
244 
246 {
247  // read large properties
248  maInStrm.align( 4 );
249  if( ensureValid( mnPropFlags == 0 ) )
250  {
251  for (auto const& largeProp : maLargeProps)
252  {
253  if (!ensureValid())
254  break;
255  ensureValid( largeProp->readProperty( maInStrm ) );
256  maInStrm.align( 4 );
257  }
258  }
260 
261  // read stream properties (no stream alignment between properties!)
262  if( ensureValid() )
263  {
264  for (auto const& streamProp : maStreamProps)
265  {
266  if (!ensureValid())
267  break;
268  ensureValid( streamProp->readProperty( maInStrm ) );
269  }
270  }
271 
272  return mbValid;
273 }
274 
275 bool AxBinaryPropertyReader::ensureValid( bool bCondition )
276 {
277  mbValid = mbValid && bCondition && !maInStrm.isEof();
278  return mbValid;
279 }
280 
282 {
283  bool bHasProp = getFlag( mnPropFlags, mnNextProp );
284  setFlag( mnPropFlags, mnNextProp, false );
285  mnNextProp <<= 1;
286  return ensureValid() && bHasProp;
287 }
288 
289 } // namespace oox::ole
290 
291 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
void readPairProperty(AxPairData &orPairData)
Reads the next pair property from the stream, if the respective flag in the property mask is set...
void readFontProperty(AxFontData &orFontData)
Reads the next font property from the stream, if the respective flag in the property mask is set...
Base class for binary stream classes.
bool mbValid
True = stream still valid.
sal_Int64 mnPropFlags
Flags specifying existing properties.
OOX_DLLPUBLIC bool importStdPic(StreamDataSequence &orGraphicData, BinaryInputStream &rInStrm)
Imports an OLE StdPic picture from the current position of the passed binary stream.
Definition: olehelper.cxx:302
virtual sal_Int64 size() const override
Returns the size of the data this stream represents, if the wrapped stream supports the size() operat...
void readArrayStringProperty(std::vector< OUString > &rStrings)
Reads ArrayString, an array of fmString ( compressed or uncompressed ) is read from the stream and in...
sal_Int64 mnNextProp
Next property to read.
::std::pair< sal_Int32, sal_Int32 > AxPairData
A pair of integer values as a property.
OOX_DLLPUBLIC OUString importGuid(BinaryInputStream &rInStrm)
Imports a GUID from the passed binary stream and returns its string representation (in uppercase char...
Definition: olehelper.cxx:260
A wrapper for a binary input stream that supports aligned read operations.
virtual sal_Int32 readMemory(void *opMem, sal_Int32 nBytes, size_t nAtomSize=1)=0
Derived classes implement reading nBytes bytes to the (preallocated!) memory buffer opMem...
virtual sal_Int64 tell() const override
Return the current relative stream position (relative to position of the wrapped stream at constructi...
All entries of a font property.
Definition: axfontdata.hxx:53
sal_Int64 mnStrmSize
Size of the wrapped stream data.
ComplexPropVector maLargeProps
Stores info for all used large properties.
sal_Int64 mnStrmPos
Tracks relative position in the stream.
virtual bool readProperty(AxAlignedInputStream &rInStrm) override
virtual bool readProperty(AxAlignedInputStream &rInStrm) override
bool getFlag(Type nBitField, Type nMask)
Returns true, if at least one of the bits set in nMask is set in nBitField.
Definition: helper.hxx:135
Type readAligned()
Aligns the stream according to the passed type and reads a value.
Interface for binary input stream classes.
void setFlag(Type &ornBitField, Type nMask, bool bSet=true)
Sets or clears (according to bSet) all set bits of nMask in ornBitField.
Definition: helper.hxx:165
virtual bool readProperty(AxAlignedInputStream &rInStrm) override
css::uno::Sequence< sal_Int8 > StreamDataSequence
container_type::value_type value_type
Definition: refvector.hxx:45
virtual void seek(sal_Int64 nPos) override
Seeks the stream to the passed relative position, if it is behind the current position.
BinaryInputStream * mpInStrm
The wrapped input stream.
bool mbEof
End of stream flag.
void readStringProperty(OUString &orValue)
Reads the next string property from the stream, if the respective flag in the property mask is set...
void readPictureProperty(StreamDataSequence &orPicData)
Reads the next picture property from the stream, if the respective flag in the property mask is set...
virtual bool readProperty(AxAlignedInputStream &rInStrm) override
virtual sal_Int32 readMemory(void *opMem, sal_Int32 nBytes, size_t nAtomSize=1) override
Reads nBytes bytes to the (existing) buffer opMem.
AxAlignedInputStream maInStrm
The input stream to read from.
void align(size_t nSize)
Aligns the stream to a multiple of the passed size (relative to the position of the wrapped stream at...
virtual sal_Int32 readData(StreamDataSequence &orData, sal_Int32 nBytes, size_t nAtomSize=1) override
Reads nBytes bytes to the passed sequence.
virtual bool readProperty(AxAlignedInputStream &rInStrm) override
virtual bool readProperty(AxAlignedInputStream &rInStrm) override
virtual void close() override
Closes the input stream but not the wrapped stream.
void readGuidProperty(OUString &orGuid)
Reads the next GUID property from the stream, if the respective flag in the property mask is set...
virtual void skip(sal_Int32 nBytes, size_t nAtomSize=1)=0
Derived classes implement seeking the stream forward by the passed number of bytes.
virtual sal_Int32 readData(StreamDataSequence &orData, sal_Int32 nBytes, size_t nAtomSize=1)=0
Derived classes implement reading nBytes bytes to the passed sequence.
virtual void skip(sal_Int32 nBytes, size_t nAtomSize=1) override
Seeks the stream forward by the passed number of bytes.
OUString readCompressedUnicodeArray(sal_Int32 nChars, bool bCompressed)
Reads a Unicode character array (may be compressed) and returns the string.
ComplexPropVector maStreamProps
Stores info for all used stream data properties.
AxAlignedInputStream(BinaryInputStream &rInStrm)
bool isEof() const
Returns true, if the stream position is invalid (EOF).
bool ensureValid(bool bCondition=true)
bool finalizeImport()
Final processing, reads contents of all complex properties.
sal_Int64 mnPropsEnd
End position of simple/large properties.
void readBoolProperty(bool &orbValue, bool bReverse=false)
Reads the next boolean property value from the stream, if the respective flag in the property mask is...
AxBinaryPropertyReader(BinaryInputStream &rInStrm, bool b64BitPropFlags=false)
sal_uInt32 mnSize
Definition: dffdumper.cxx:163