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