1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 #include "oox/ole/axbinaryreader.hxx" 29 30 #include "oox/ole/olehelper.hxx" 31 32 namespace oox { 33 namespace ole { 34 35 // ============================================================================ 36 37 using ::rtl::OUString; 38 39 // ============================================================================ 40 41 namespace { 42 43 const sal_uInt32 AX_STRING_SIZEMASK = 0x7FFFFFFF; 44 const sal_uInt32 AX_STRING_COMPRESSED = 0x80000000; 45 46 } // namespace 47 48 // ============================================================================ 49 50 AxAlignedInputStream::AxAlignedInputStream( BinaryInputStream& rInStrm ) : 51 BinaryStreamBase( false ), 52 mpInStrm( &rInStrm ), 53 mnStrmPos( 0 ), 54 mnStrmSize( rInStrm.getRemaining() ) 55 { 56 mbEof = mbEof || rInStrm.isEof(); 57 } 58 59 sal_Int64 AxAlignedInputStream::size() const 60 { 61 return mpInStrm ? mnStrmSize : -1; 62 } 63 64 sal_Int64 AxAlignedInputStream::tell() const 65 { 66 return mpInStrm ? mnStrmPos : -1; 67 } 68 69 void AxAlignedInputStream::seek( sal_Int64 nPos ) 70 { 71 mbEof = mbEof || (nPos < mnStrmPos); 72 if( !mbEof ) 73 skip( static_cast< sal_Int32 >( nPos - mnStrmPos ) ); 74 } 75 76 void AxAlignedInputStream::close() 77 { 78 mpInStrm = 0; 79 mbEof = true; 80 } 81 82 sal_Int32 AxAlignedInputStream::readData( StreamDataSequence& orData, sal_Int32 nBytes, size_t nAtomSize ) 83 { 84 sal_Int32 nReadSize = 0; 85 if( !mbEof ) 86 { 87 nReadSize = mpInStrm->readData( orData, nBytes, nAtomSize ); 88 mnStrmPos += nReadSize; 89 mbEof = mpInStrm->isEof(); 90 } 91 return nReadSize; 92 } 93 94 sal_Int32 AxAlignedInputStream::readMemory( void* opMem, sal_Int32 nBytes, size_t nAtomSize ) 95 { 96 sal_Int32 nReadSize = 0; 97 if( !mbEof ) 98 { 99 nReadSize = mpInStrm->readMemory( opMem, nBytes, nAtomSize ); 100 mnStrmPos += nReadSize; 101 mbEof = mpInStrm->isEof(); 102 } 103 return nReadSize; 104 } 105 106 void AxAlignedInputStream::skip( sal_Int32 nBytes, size_t nAtomSize ) 107 { 108 if( !mbEof ) 109 { 110 mpInStrm->skip( nBytes, nAtomSize ); 111 mnStrmPos += nBytes; 112 mbEof = mpInStrm->isEof(); 113 } 114 } 115 116 void AxAlignedInputStream::align( size_t nSize ) 117 { 118 skip( static_cast< sal_Int32 >( (nSize - (mnStrmPos % nSize)) % nSize ) ); 119 } 120 121 // ============================================================================ 122 123 AxFontData::AxFontData() : 124 mnFontEffects( 0 ), 125 mnFontHeight( 160 ), 126 mnFontCharSet( WINDOWS_CHARSET_DEFAULT ), 127 mnHorAlign( AX_FONTDATA_LEFT ), 128 mbDblUnderline( false ) 129 { 130 } 131 132 sal_Int16 AxFontData::getHeightPoints() const 133 { 134 /* MSO uses weird font sizes: 135 1pt->30, 2pt->45, 3pt->60, 4pt->75, 5pt->105, 6pt->120, 7pt->135, 136 8pt->165, 9pt->180, 10pt->195, 11pt->225, ... */ 137 return getLimitedValue< sal_Int16, sal_Int32 >( (mnFontHeight + 10) / 20, 1, SAL_MAX_INT16 ); 138 } 139 140 void AxFontData::setHeightPoints( sal_Int16 nPoints ) 141 { 142 mnFontHeight = getLimitedValue< sal_Int32, sal_Int32 >( ((nPoints * 4 + 1) / 3) * 15, 30, 4294967 ); 143 } 144 145 bool AxFontData::importBinaryModel( BinaryInputStream& rInStrm ) 146 { 147 AxBinaryPropertyReader aReader( rInStrm ); 148 aReader.readStringProperty( maFontName ); 149 aReader.readIntProperty< sal_uInt32 >( mnFontEffects ); 150 aReader.readIntProperty< sal_Int32 >( mnFontHeight ); 151 aReader.skipIntProperty< sal_Int32 >(); // font offset 152 aReader.readIntProperty< sal_uInt8 >( mnFontCharSet ); 153 aReader.skipIntProperty< sal_uInt8 >(); // font pitch/family 154 aReader.readIntProperty< sal_uInt8 >( mnHorAlign ); 155 aReader.skipIntProperty< sal_uInt16 >(); // font weight 156 mbDblUnderline = false; 157 return aReader.finalizeImport(); 158 } 159 160 bool AxFontData::importStdFont( BinaryInputStream& rInStrm ) 161 { 162 StdFontInfo aFontInfo; 163 if( OleHelper::importStdFont( aFontInfo, rInStrm, false ) ) 164 { 165 maFontName = aFontInfo.maName; 166 mnFontEffects = 0; 167 setFlag( mnFontEffects, AX_FONTDATA_BOLD, aFontInfo.mnWeight >= OLE_STDFONT_BOLD ); 168 setFlag( mnFontEffects, AX_FONTDATA_ITALIC, getFlag( aFontInfo.mnFlags, OLE_STDFONT_ITALIC ) ); 169 setFlag( mnFontEffects, AX_FONTDATA_UNDERLINE, getFlag( aFontInfo.mnFlags, OLE_STDFONT_UNDERLINE ) ); 170 setFlag( mnFontEffects, AX_FONTDATA_STRIKEOUT, getFlag( aFontInfo.mnFlags,OLE_STDFONT_STRIKE ) ); 171 mbDblUnderline = false; 172 // StdFont stores font height in 1/10,000 of points 173 setHeightPoints( getLimitedValue< sal_Int16, sal_Int32 >( aFontInfo.mnHeight / 10000, 0, SAL_MAX_INT16 ) ); 174 mnFontCharSet = aFontInfo.mnCharSet; 175 mnHorAlign = AX_FONTDATA_LEFT; 176 return true; 177 } 178 return false; 179 } 180 181 bool AxFontData::importGuidAndFont( BinaryInputStream& rInStrm ) 182 { 183 OUString aGuid = OleHelper::importGuid( rInStrm ); 184 if( aGuid.equalsAscii( AX_GUID_CFONT ) ) 185 return importBinaryModel( rInStrm ); 186 if( aGuid.equalsAscii( OLE_GUID_STDFONT ) ) 187 return importStdFont( rInStrm ); 188 return false; 189 } 190 191 // ============================================================================ 192 193 namespace { 194 195 bool lclReadString( AxAlignedInputStream& rInStrm, OUString& rValue, sal_uInt32 nSize, bool bArrayString ) 196 { 197 bool bCompressed = getFlag( nSize, AX_STRING_COMPRESSED ); 198 sal_uInt32 nBufSize = nSize & AX_STRING_SIZEMASK; 199 // Unicode: simple strings store byte count, array strings store char count 200 sal_Int32 nChars = static_cast< sal_Int32 >( nBufSize / ((bCompressed || bArrayString) ? 1 : 2) ); 201 bool bValidChars = nChars <= 65536; 202 OSL_ENSURE( bValidChars, "lclReadString - string too long" ); 203 sal_Int64 nEndPos = rInStrm.tell() + nChars * (bCompressed ? 1 : 2); 204 nChars = ::std::min< sal_Int32 >( nChars, 65536 ); 205 rValue = rInStrm.readCompressedUnicodeArray( nChars, bCompressed ); 206 rInStrm.seek( nEndPos ); 207 return bValidChars; 208 } 209 210 } // namespace 211 212 // ---------------------------------------------------------------------------- 213 214 AxBinaryPropertyReader::ComplexProperty::~ComplexProperty() 215 { 216 } 217 218 bool AxBinaryPropertyReader::PairProperty::readProperty( AxAlignedInputStream& rInStrm ) 219 { 220 rInStrm >> mrPairData.first >> mrPairData.second; 221 return true; 222 } 223 224 bool AxBinaryPropertyReader::StringProperty::readProperty( AxAlignedInputStream& rInStrm ) 225 { 226 return lclReadString( rInStrm, mrValue, mnSize, false ); 227 } 228 229 bool AxBinaryPropertyReader::StringArrayProperty::readProperty( AxAlignedInputStream& rInStrm ) 230 { 231 sal_Int64 nEndPos = rInStrm.tell() + mnSize; 232 while( rInStrm.tell() < nEndPos ) 233 { 234 OUString aString; 235 if( !lclReadString( rInStrm, aString, rInStrm.readuInt32(), true ) ) 236 return false; 237 mrArray.push_back( aString ); 238 // every array string is aligned on 4 byte boundries 239 rInStrm.align( 4 ); 240 } 241 return true; 242 } 243 244 bool AxBinaryPropertyReader::GuidProperty::readProperty( AxAlignedInputStream& rInStrm ) 245 { 246 mrGuid = OleHelper::importGuid( rInStrm ); 247 return true; 248 } 249 250 bool AxBinaryPropertyReader::FontProperty::readProperty( AxAlignedInputStream& rInStrm ) 251 { 252 return mrFontData.importGuidAndFont( rInStrm ); 253 } 254 255 bool AxBinaryPropertyReader::PictureProperty::readProperty( AxAlignedInputStream& rInStrm ) 256 { 257 return OleHelper::importStdPic( mrPicData, rInStrm, true ); 258 } 259 260 // ---------------------------------------------------------------------------- 261 262 AxBinaryPropertyReader::AxBinaryPropertyReader( BinaryInputStream& rInStrm, bool b64BitPropFlags ) : 263 maInStrm( rInStrm ), 264 mbValid( true ) 265 { 266 // version and size of property block 267 maInStrm.skip( 2 ); 268 sal_uInt16 nBlockSize = maInStrm.readValue< sal_uInt16 >(); 269 mnPropsEnd = maInStrm.tell() + nBlockSize; 270 // flagfield containing existing properties 271 if( b64BitPropFlags ) 272 maInStrm >> mnPropFlags; 273 else 274 mnPropFlags = maInStrm.readuInt32(); 275 mnNextProp = 1; 276 } 277 278 void AxBinaryPropertyReader::readBoolProperty( bool& orbValue, bool bReverse ) 279 { 280 // there is no data, the boolean value is equivalent to the property flag itself 281 orbValue = startNextProperty() != bReverse; 282 } 283 284 void AxBinaryPropertyReader::readPairProperty( AxPairData& orPairData ) 285 { 286 if( startNextProperty() ) 287 maLargeProps.push_back( ComplexPropVector::value_type( new PairProperty( orPairData ) ) ); 288 } 289 290 void AxBinaryPropertyReader::readStringProperty( OUString& orValue ) 291 { 292 if( startNextProperty() ) 293 { 294 sal_uInt32 nSize = maInStrm.readAligned< sal_uInt32 >(); 295 maLargeProps.push_back( ComplexPropVector::value_type( new StringProperty( orValue, nSize ) ) ); 296 } 297 } 298 299 void AxBinaryPropertyReader::readStringArrayProperty( AxStringArray& orArray ) 300 { 301 if( startNextProperty() ) 302 { 303 sal_uInt32 nSize = maInStrm.readAligned< sal_uInt32 >(); 304 maLargeProps.push_back( ComplexPropVector::value_type( new StringArrayProperty( orArray, nSize ) ) ); 305 } 306 } 307 308 void AxBinaryPropertyReader::readGuidProperty( ::rtl::OUString& orGuid ) 309 { 310 if( startNextProperty() ) 311 maLargeProps.push_back( ComplexPropVector::value_type( new GuidProperty( orGuid ) ) ); 312 } 313 314 void AxBinaryPropertyReader::readFontProperty( AxFontData& orFontData ) 315 { 316 if( startNextProperty() ) 317 { 318 sal_Int16 nData = maInStrm.readAligned< sal_Int16 >(); 319 if( ensureValid( nData == -1 ) ) 320 maStreamProps.push_back( ComplexPropVector::value_type( new FontProperty( orFontData ) ) ); 321 } 322 } 323 324 void AxBinaryPropertyReader::readPictureProperty( StreamDataSequence& orPicData ) 325 { 326 if( startNextProperty() ) 327 { 328 sal_Int16 nData = maInStrm.readAligned< sal_Int16 >(); 329 if( ensureValid( nData == -1 ) ) 330 maStreamProps.push_back( ComplexPropVector::value_type( new PictureProperty( orPicData ) ) ); 331 } 332 } 333 334 bool AxBinaryPropertyReader::finalizeImport() 335 { 336 // read large properties 337 maInStrm.align( 4 ); 338 if( ensureValid( mnPropFlags == 0 ) && !maLargeProps.empty() ) 339 { 340 for( ComplexPropVector::iterator aIt = maLargeProps.begin(), aEnd = maLargeProps.end(); ensureValid() && (aIt != aEnd); ++aIt ) 341 { 342 ensureValid( (*aIt)->readProperty( maInStrm ) ); 343 maInStrm.align( 4 ); 344 } 345 } 346 maInStrm.seek( mnPropsEnd ); 347 348 // read stream properties (no stream alignment between properties!) 349 if( ensureValid() && !maStreamProps.empty() ) 350 for( ComplexPropVector::iterator aIt = maStreamProps.begin(), aEnd = maStreamProps.end(); ensureValid() && (aIt != aEnd); ++aIt ) 351 ensureValid( (*aIt)->readProperty( maInStrm ) ); 352 353 return mbValid; 354 } 355 356 bool AxBinaryPropertyReader::ensureValid( bool bCondition ) 357 { 358 mbValid = mbValid && bCondition && !maInStrm.isEof(); 359 return mbValid; 360 } 361 362 bool AxBinaryPropertyReader::startNextProperty() 363 { 364 bool bHasProp = getFlag( mnPropFlags, mnNextProp ); 365 setFlag( mnPropFlags, mnNextProp, false ); 366 mnNextProp <<= 1; 367 return ensureValid() && bHasProp; 368 } 369 370 // ============================================================================ 371 372 } // namespace ole 373 } // namespace oox 374