Line data Source code
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 :
20 : #include "oox/ole/axbinaryreader.hxx"
21 :
22 : #include "oox/ole/olehelper.hxx"
23 :
24 : namespace oox {
25 : namespace ole {
26 :
27 : namespace {
28 :
29 : const sal_uInt32 AX_STRING_SIZEMASK = 0x7FFFFFFF;
30 : const sal_uInt32 AX_STRING_COMPRESSED = 0x80000000;
31 :
32 : } // namespace
33 :
34 176 : AxAlignedInputStream::AxAlignedInputStream( BinaryInputStream& rInStrm ) :
35 : BinaryStreamBase( false ),
36 : mpInStrm( &rInStrm ),
37 : mnStrmPos( 0 ),
38 176 : mnStrmSize( rInStrm.getRemaining() )
39 : {
40 176 : mbEof = mbEof || rInStrm.isEof();
41 176 : }
42 :
43 0 : sal_Int64 AxAlignedInputStream::size() const
44 : {
45 0 : return mpInStrm ? mnStrmSize : -1;
46 : }
47 :
48 354 : sal_Int64 AxAlignedInputStream::tell() const
49 : {
50 354 : return mpInStrm ? mnStrmPos : -1;
51 : }
52 :
53 354 : void AxAlignedInputStream::seek( sal_Int64 nPos )
54 : {
55 354 : mbEof = mbEof || (nPos < mnStrmPos);
56 354 : if( !mbEof )
57 354 : skip( static_cast< sal_Int32 >( nPos - mnStrmPos ) );
58 354 : }
59 :
60 0 : void AxAlignedInputStream::close()
61 : {
62 0 : mpInStrm = 0;
63 0 : mbEof = true;
64 0 : }
65 :
66 0 : sal_Int32 AxAlignedInputStream::readData( StreamDataSequence& orData, sal_Int32 nBytes, size_t nAtomSize )
67 : {
68 0 : sal_Int32 nReadSize = 0;
69 0 : if( !mbEof )
70 : {
71 0 : nReadSize = mpInStrm->readData( orData, nBytes, nAtomSize );
72 0 : mnStrmPos += nReadSize;
73 0 : mbEof = mpInStrm->isEof();
74 : }
75 0 : return nReadSize;
76 : }
77 :
78 1268 : sal_Int32 AxAlignedInputStream::readMemory( void* opMem, sal_Int32 nBytes, size_t nAtomSize )
79 : {
80 1268 : sal_Int32 nReadSize = 0;
81 1268 : if( !mbEof )
82 : {
83 1268 : nReadSize = mpInStrm->readMemory( opMem, nBytes, nAtomSize );
84 1268 : mnStrmPos += nReadSize;
85 1268 : mbEof = mpInStrm->isEof();
86 : }
87 1268 : return nReadSize;
88 : }
89 :
90 1714 : void AxAlignedInputStream::skip( sal_Int32 nBytes, size_t nAtomSize )
91 : {
92 1714 : if( !mbEof )
93 : {
94 1714 : mpInStrm->skip( nBytes, nAtomSize );
95 1714 : mnStrmPos += nBytes;
96 1714 : mbEof = mpInStrm->isEof();
97 : }
98 1714 : }
99 :
100 1088 : void AxAlignedInputStream::align( size_t nSize )
101 : {
102 1088 : skip( static_cast< sal_Int32 >( (nSize - (mnStrmPos % nSize)) % nSize ) );
103 1088 : }
104 :
105 : namespace {
106 :
107 178 : bool lclReadString( AxAlignedInputStream& rInStrm, OUString& rValue, sal_uInt32 nSize, bool bArrayString )
108 : {
109 178 : bool bCompressed = getFlag( nSize, AX_STRING_COMPRESSED );
110 178 : sal_uInt32 nBufSize = nSize & AX_STRING_SIZEMASK;
111 : // Unicode: simple strings store byte count, array strings store char count
112 178 : sal_Int32 nChars = static_cast< sal_Int32 >( nBufSize / ((bCompressed || bArrayString) ? 1 : 2) );
113 178 : bool bValidChars = nChars <= 65536;
114 : OSL_ENSURE( bValidChars, "lclReadString - string too long" );
115 178 : sal_Int64 nEndPos = rInStrm.tell() + nChars * (bCompressed ? 1 : 2);
116 178 : nChars = ::std::min< sal_Int32 >( nChars, 65536 );
117 178 : rValue = rInStrm.readCompressedUnicodeArray( nChars, bCompressed );
118 178 : rInStrm.seek( nEndPos );
119 178 : return bValidChars;
120 : }
121 :
122 : } // namespace
123 :
124 278 : AxBinaryPropertyReader::ComplexProperty::~ComplexProperty()
125 : {
126 278 : }
127 :
128 100 : bool AxBinaryPropertyReader::PairProperty::readProperty( AxAlignedInputStream& rInStrm )
129 : {
130 100 : rInStrm >> mrPairData.first >> mrPairData.second;
131 100 : return true;
132 : }
133 :
134 178 : bool AxBinaryPropertyReader::StringProperty::readProperty( AxAlignedInputStream& rInStrm )
135 : {
136 178 : return lclReadString( rInStrm, mrValue, mnSize, false );
137 : }
138 :
139 0 : bool AxBinaryPropertyReader::ArrayStringProperty::readProperty( AxAlignedInputStream& rInStrm )
140 : {
141 0 : sal_Int64 nEndPos = rInStrm.tell() + mnSize;
142 0 : while( rInStrm.tell() < nEndPos )
143 : {
144 0 : OUString aString;
145 0 : if( !lclReadString( rInStrm, aString, rInStrm.readuInt32(), true ) )
146 0 : return false;
147 0 : mrArray.push_back( aString );
148 : // every array string is aligned on 4 byte boundries
149 0 : rInStrm.align( 4 );
150 0 : }
151 0 : return true;
152 : }
153 :
154 0 : bool AxBinaryPropertyReader::GuidProperty::readProperty( AxAlignedInputStream& rInStrm )
155 : {
156 0 : mrGuid = OleHelper::importGuid( rInStrm );
157 0 : return true;
158 : }
159 :
160 0 : bool AxBinaryPropertyReader::FontProperty::readProperty( AxAlignedInputStream& rInStrm )
161 : {
162 0 : return mrFontData.importGuidAndFont( rInStrm );
163 : }
164 :
165 0 : bool AxBinaryPropertyReader::PictureProperty::readProperty( AxAlignedInputStream& rInStrm )
166 : {
167 0 : return OleHelper::importStdPic( mrPicData, rInStrm, true );
168 : }
169 :
170 176 : AxBinaryPropertyReader::AxBinaryPropertyReader( BinaryInputStream& rInStrm, bool b64BitPropFlags ) :
171 : maInStrm( rInStrm ),
172 176 : mbValid( true )
173 : {
174 : // version and size of property block
175 176 : maInStrm.skip( 2 );
176 176 : sal_uInt16 nBlockSize = maInStrm.readValue< sal_uInt16 >();
177 176 : mnPropsEnd = maInStrm.tell() + nBlockSize;
178 : // flagfield containing existing properties
179 176 : if( b64BitPropFlags )
180 36 : maInStrm >> mnPropFlags;
181 : else
182 140 : mnPropFlags = maInStrm.readuInt32();
183 176 : mnNextProp = 1;
184 176 : }
185 :
186 46 : void AxBinaryPropertyReader::readBoolProperty( bool& orbValue, bool bReverse )
187 : {
188 : // there is no data, the boolean value is equivalent to the property flag itself
189 46 : orbValue = startNextProperty() != bReverse;
190 46 : }
191 :
192 104 : void AxBinaryPropertyReader::readPairProperty( AxPairData& orPairData )
193 : {
194 104 : if( startNextProperty() )
195 100 : maLargeProps.push_back( ComplexPropVector::value_type( new PairProperty( orPairData ) ) );
196 104 : }
197 :
198 308 : void AxBinaryPropertyReader::readStringProperty( OUString& orValue )
199 : {
200 308 : if( startNextProperty() )
201 : {
202 178 : sal_uInt32 nSize = maInStrm.readAligned< sal_uInt32 >();
203 178 : maLargeProps.push_back( ComplexPropVector::value_type( new StringProperty( orValue, nSize ) ) );
204 : }
205 308 : }
206 :
207 0 : void AxBinaryPropertyReader::readArrayStringProperty( std::vector<OUString>& orValue )
208 : {
209 0 : if( startNextProperty() )
210 : {
211 0 : sal_uInt32 nSize = maInStrm.readAligned< sal_uInt32 >();
212 0 : maLargeProps.push_back( ComplexPropVector::value_type( new ArrayStringProperty( orValue, nSize ) ) );
213 : }
214 0 : }
215 :
216 0 : void AxBinaryPropertyReader::readGuidProperty( OUString& orGuid )
217 : {
218 0 : if( startNextProperty() )
219 0 : maLargeProps.push_back( ComplexPropVector::value_type( new GuidProperty( orGuid ) ) );
220 0 : }
221 :
222 4 : void AxBinaryPropertyReader::readFontProperty( AxFontData& orFontData )
223 : {
224 4 : if( startNextProperty() )
225 : {
226 0 : sal_Int16 nData = maInStrm.readAligned< sal_Int16 >();
227 0 : if( ensureValid( nData == -1 ) )
228 0 : maStreamProps.push_back( ComplexPropVector::value_type( new FontProperty( orFontData ) ) );
229 : }
230 4 : }
231 :
232 168 : void AxBinaryPropertyReader::readPictureProperty( StreamDataSequence& orPicData )
233 : {
234 168 : if( startNextProperty() )
235 : {
236 0 : sal_Int16 nData = maInStrm.readAligned< sal_Int16 >();
237 0 : if( ensureValid( nData == -1 ) )
238 0 : maStreamProps.push_back( ComplexPropVector::value_type( new PictureProperty( orPicData ) ) );
239 : }
240 168 : }
241 :
242 176 : bool AxBinaryPropertyReader::finalizeImport()
243 : {
244 : // read large properties
245 176 : maInStrm.align( 4 );
246 176 : if( ensureValid( mnPropFlags == 0 ) && !maLargeProps.empty() )
247 : {
248 448 : for( ComplexPropVector::iterator aIt = maLargeProps.begin(), aEnd = maLargeProps.end(); ensureValid() && (aIt != aEnd); ++aIt )
249 : {
250 278 : ensureValid( (*aIt)->readProperty( maInStrm ) );
251 278 : maInStrm.align( 4 );
252 : }
253 : }
254 176 : maInStrm.seek( mnPropsEnd );
255 :
256 : // read stream properties (no stream alignment between properties!)
257 176 : if( ensureValid() && !maStreamProps.empty() )
258 0 : for( ComplexPropVector::iterator aIt = maStreamProps.begin(), aEnd = maStreamProps.end(); ensureValid() && (aIt != aEnd); ++aIt )
259 0 : ensureValid( (*aIt)->readProperty( maInStrm ) );
260 :
261 176 : return mbValid;
262 : }
263 :
264 3786 : bool AxBinaryPropertyReader::ensureValid( bool bCondition )
265 : {
266 3786 : mbValid = mbValid && bCondition && !maInStrm.isEof();
267 3786 : return mbValid;
268 : }
269 :
270 2608 : bool AxBinaryPropertyReader::startNextProperty()
271 : {
272 2608 : bool bHasProp = getFlag( mnPropFlags, mnNextProp );
273 2608 : setFlag( mnPropFlags, mnNextProp, false );
274 2608 : mnNextProp <<= 1;
275 2608 : return ensureValid() && bHasProp;
276 : }
277 :
278 : } // namespace ole
279 408 : } // namespace oox
280 :
281 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|