diff options
Diffstat (limited to '')
-rw-r--r-- | oox/source/ole/axbinaryreader.cxx | 291 |
1 files changed, 291 insertions, 0 deletions
diff --git a/oox/source/ole/axbinaryreader.cxx b/oox/source/ole/axbinaryreader.cxx new file mode 100644 index 000000000..6467e51bc --- /dev/null +++ b/oox/source/ole/axbinaryreader.cxx @@ -0,0 +1,291 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <oox/ole/axbinaryreader.hxx> + +#include <oox/ole/axfontdata.hxx> +#include <oox/ole/olehelper.hxx> + +#include <osl/diagnose.h> + +namespace oox::ole { + +namespace { + +const sal_uInt32 AX_STRING_SIZEMASK = 0x7FFFFFFF; +const sal_uInt32 AX_STRING_COMPRESSED = 0x80000000; + +} // namespace + +AxAlignedInputStream::AxAlignedInputStream( BinaryInputStream& rInStrm ) : + BinaryStreamBase( false ), + mpInStrm( &rInStrm ), + mnStrmPos( 0 ), + mnStrmSize( rInStrm.getRemaining() ) +{ + mbEof = mbEof || rInStrm.isEof(); +} + +sal_Int64 AxAlignedInputStream::size() const +{ + return mpInStrm ? mnStrmSize : -1; +} + +sal_Int64 AxAlignedInputStream::tell() const +{ + return mpInStrm ? mnStrmPos : -1; +} + +void AxAlignedInputStream::seek( sal_Int64 nPos ) +{ + mbEof = mbEof || (nPos < mnStrmPos); + if( !mbEof ) + skip( static_cast< sal_Int32 >( nPos - mnStrmPos ) ); +} + +void AxAlignedInputStream::close() +{ + mpInStrm = nullptr; + mbEof = true; +} + +sal_Int32 AxAlignedInputStream::readData( StreamDataSequence& orData, sal_Int32 nBytes, size_t nAtomSize ) +{ + sal_Int32 nReadSize = 0; + if( !mbEof ) + { + nReadSize = mpInStrm->readData( orData, nBytes, nAtomSize ); + mnStrmPos += nReadSize; + mbEof = mpInStrm->isEof(); + } + return nReadSize; +} + +sal_Int32 AxAlignedInputStream::readMemory( void* opMem, sal_Int32 nBytes, size_t nAtomSize ) +{ + sal_Int32 nReadSize = 0; + if( !mbEof ) + { + nReadSize = mpInStrm->readMemory( opMem, nBytes, nAtomSize ); + mnStrmPos += nReadSize; + mbEof = mpInStrm->isEof(); + } + return nReadSize; +} + +void AxAlignedInputStream::skip( sal_Int32 nBytes, size_t nAtomSize ) +{ + if( !mbEof ) + { + mpInStrm->skip( nBytes, nAtomSize ); + mnStrmPos += nBytes; + mbEof = mpInStrm->isEof(); + } +} + +void AxAlignedInputStream::align( size_t nSize ) +{ + skip( static_cast< sal_Int32 >( (nSize - (mnStrmPos % nSize)) % nSize ) ); +} + +namespace { + +bool lclReadString( AxAlignedInputStream& rInStrm, OUString& rValue, sal_uInt32 nSize, bool bArrayString ) +{ + bool bCompressed = getFlag( nSize, AX_STRING_COMPRESSED ); + sal_uInt32 nBufSize = nSize & AX_STRING_SIZEMASK; + // Unicode: simple strings store byte count, array strings store char count + sal_Int32 nChars = static_cast< sal_Int32 >( nBufSize / ((bCompressed || bArrayString) ? 1 : 2) ); + bool bValidChars = nChars <= 65536; + OSL_ENSURE( bValidChars, "lclReadString - string too long" ); + sal_Int64 nEndPos = rInStrm.tell() + nChars * (bCompressed ? 1 : 2); + nChars = ::std::min< sal_Int32 >( nChars, 65536 ); + rValue = rInStrm.readCompressedUnicodeArray( nChars, bCompressed ); + rInStrm.seek( nEndPos ); + return bValidChars; +} + +} // namespace + +AxBinaryPropertyReader::ComplexProperty::~ComplexProperty() +{ +} + +bool AxBinaryPropertyReader::PairProperty::readProperty( AxAlignedInputStream& rInStrm ) +{ + mrPairData.first = rInStrm.readInt32(); + mrPairData.second = rInStrm.readInt32(); + return true; +} + +bool AxBinaryPropertyReader::StringProperty::readProperty( AxAlignedInputStream& rInStrm ) +{ + return lclReadString( rInStrm, mrValue, mnSize, false ); +} + +bool AxBinaryPropertyReader::ArrayStringProperty::readProperty( AxAlignedInputStream& rInStrm ) +{ + sal_Int64 nEndPos = rInStrm.tell() + mnSize; + while( rInStrm.tell() < nEndPos ) + { + OUString aString; + if( !lclReadString( rInStrm, aString, rInStrm.readuInt32(), true ) ) + return false; + mrArray.push_back( aString ); + // every array string is aligned on 4 byte boundaries + rInStrm.align( 4 ); + } + return true; +} + +bool AxBinaryPropertyReader::GuidProperty::readProperty( AxAlignedInputStream& rInStrm ) +{ + mrGuid = OleHelper::importGuid( rInStrm ); + return true; +} + +bool AxBinaryPropertyReader::FontProperty::readProperty( AxAlignedInputStream& rInStrm ) +{ + return mrFontData.importGuidAndFont( rInStrm ); +} + +bool AxBinaryPropertyReader::PictureProperty::readProperty( AxAlignedInputStream& rInStrm ) +{ + return OleHelper::importStdPic( mrPicData, rInStrm ); +} + +AxBinaryPropertyReader::AxBinaryPropertyReader( BinaryInputStream& rInStrm, bool b64BitPropFlags ) : + maInStrm( rInStrm ), + mbValid( true ) +{ + // version and size of property block + maInStrm.skip( 2 ); + sal_uInt16 nBlockSize = maInStrm.readuInt16(); + mnPropsEnd = maInStrm.tell() + nBlockSize; + // flagfield containing existing properties + if( b64BitPropFlags ) + mnPropFlags = maInStrm.readInt64(); + else + mnPropFlags = maInStrm.readuInt32(); + mnNextProp = 1; +} + +void AxBinaryPropertyReader::readBoolProperty( bool& orbValue, bool bReverse ) +{ + // there is no data, the boolean value is equivalent to the property flag itself + orbValue = startNextProperty() != bReverse; +} + +void AxBinaryPropertyReader::readPairProperty( AxPairData& orPairData ) +{ + if( startNextProperty() ) + maLargeProps.push_back( ComplexPropVector::value_type( std::make_shared<PairProperty>( orPairData ) ) ); +} + +void AxBinaryPropertyReader::readStringProperty( OUString& orValue ) +{ + if( startNextProperty() ) + { + sal_uInt32 nSize = maInStrm.readAligned< sal_uInt32 >(); + maLargeProps.push_back( ComplexPropVector::value_type( std::make_shared<StringProperty>( orValue, nSize ) ) ); + } +} + +void AxBinaryPropertyReader::readArrayStringProperty( std::vector<OUString>& orValue ) +{ + if( startNextProperty() ) + { + sal_uInt32 nSize = maInStrm.readAligned< sal_uInt32 >(); + maLargeProps.push_back( ComplexPropVector::value_type( std::make_shared<ArrayStringProperty>( orValue, nSize ) ) ); + } +} + +void AxBinaryPropertyReader::readGuidProperty( OUString& orGuid ) +{ + if( startNextProperty() ) + maLargeProps.push_back( ComplexPropVector::value_type( std::make_shared<GuidProperty>( orGuid ) ) ); +} + +void AxBinaryPropertyReader::readFontProperty( AxFontData& orFontData ) +{ + if( startNextProperty() ) + { + sal_Int16 nData = maInStrm.readAligned< sal_Int16 >(); + if( ensureValid( nData == -1 ) ) + maStreamProps.push_back( ComplexPropVector::value_type( std::make_shared<FontProperty>( orFontData ) ) ); + } +} + +void AxBinaryPropertyReader::readPictureProperty( StreamDataSequence& orPicData ) +{ + if( startNextProperty() ) + { + sal_Int16 nData = maInStrm.readAligned< sal_Int16 >(); + if( ensureValid( nData == -1 ) ) + maStreamProps.push_back( ComplexPropVector::value_type( std::make_shared<PictureProperty>( orPicData ) ) ); + } +} + +bool AxBinaryPropertyReader::finalizeImport() +{ + // read large properties + maInStrm.align( 4 ); + if( ensureValid( mnPropFlags == 0 ) ) + { + for (auto const& largeProp : maLargeProps) + { + if (!ensureValid()) + break; + ensureValid( largeProp->readProperty( maInStrm ) ); + maInStrm.align( 4 ); + } + } + maInStrm.seek( mnPropsEnd ); + + // read stream properties (no stream alignment between properties!) + if( ensureValid() ) + { + for (auto const& streamProp : maStreamProps) + { + if (!ensureValid()) + break; + ensureValid( streamProp->readProperty( maInStrm ) ); + } + } + + return mbValid; +} + +bool AxBinaryPropertyReader::ensureValid( bool bCondition ) +{ + mbValid = mbValid && bCondition && !maInStrm.isEof(); + return mbValid; +} + +bool AxBinaryPropertyReader::startNextProperty() +{ + bool bHasProp = getFlag( mnPropFlags, mnNextProp ); + setFlag( mnPropFlags, mnNextProp, false ); + mnNextProp <<= 1; + return ensureValid() && bHasProp; +} + +} // namespace oox::ole + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |