1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
3  *
4  *  The Contents of this file are made available subject to the terms of
5  *  either of the following licenses
6  *
7  *         - GNU Lesser General Public License Version 2.1
8  *         - Sun Industry Standards Source License Version 1.1
9  *
10  *  Sun Microsystems Inc., October, 2000
11  *
12  *  GNU Lesser General Public License Version 2.1
13  *  =============================================
14  *  Copyright 2000 by Sun Microsystems, Inc.
15  *  901 San Antonio Road, Palo Alto, CA 94303, USA
16  *
17  *  This library is free software; you can redistribute it and/or
18  *  modify it under the terms of the GNU Lesser General Public
19  *  License version 2.1, as published by the Free Software Foundation.
20  *
21  *  This library is distributed in the hope that it will be useful,
22  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
23  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
24  *  Lesser General Public License for more details.
25  *
26  *  You should have received a copy of the GNU Lesser General Public
27  *  License along with this library; if not, write to the Free Software
28  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
29  *  MA  02111-1307  USA
30  *
31  *
32  *  Sun Industry Standards Source License Version 1.1
33  *  =================================================
34  *  The contents of this file are subject to the Sun Industry Standards
35  *  Source License Version 1.1 (the "License"); You may not use this file
36  *  except in compliance with the License. You may obtain a copy of the
37  *  License at http://www.openoffice.org/license.html.
38  *
39  *  Software provided under this License is provided on an "AS IS" basis,
40  *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
41  *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
42  *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
43  *  See the License for the specific provisions governing your rights and
44  *  obligations concerning the Software.
45  *
46  *  The Initial Developer of the Original Code is: IBM Corporation
47  *
48  *  Copyright: 2008 by IBM Corporation
49  *
50  *  All Rights Reserved.
51  *
52  *  Contributor(s): _______________________________________
53  *
54  *
55  ************************************************************************/
56 
57 #include <lwpobjstrm.hxx>
58 #include <lwptools.hxx>
59 
60 #include <sal/types.h>
61 #include <tools/solar.h>
62 #include <memory>
63 
64 /**
65  * @descr  ctor() from LwpSvStream
66  */
LwpObjectStream(LwpSvStream * pStrm,bool isCompressed,sal_uInt16 size)67 LwpObjectStream::LwpObjectStream(LwpSvStream* pStrm, bool isCompressed, sal_uInt16 size)
68     : m_pContentBuf(nullptr)
69     , m_nBufSize(size)
70     , m_nReadPos(0)
71     , m_pStrm(pStrm)
72     , m_bCompressed(isCompressed)
73 {
74     if (m_nBufSize >= IO_BUFFERSIZE)
75         throw std::range_error("bad Object size");
76     // read object data from stream
77     if (m_nBufSize > 0)
78         Read2Buffer();
79 }
80 
81 /**
82  * @descr  read object data from stream to buffer
83  */
Read2Buffer()84 void LwpObjectStream::Read2Buffer()
85 {
86     ReleaseBuffer();
87 
88     m_nReadPos = 0;
89 
90     if (m_bCompressed)
91     {
92         std::unique_ptr<sal_uInt8[]> xCompressBuf(new sal_uInt8[m_nBufSize]);
93 
94         sal_uInt8* pCompressBuffer = xCompressBuf.get();
95         memset(pCompressBuffer, 0, m_nBufSize);
96         m_nBufSize = m_pStrm->Read(pCompressBuffer, m_nBufSize);
97 
98         sal_uInt8 pTempDst[IO_BUFFERSIZE];
99         m_nBufSize = DecompressBuffer(pTempDst, pCompressBuffer, m_nBufSize);
100         assert(m_nBufSize < IO_BUFFERSIZE);
101 
102         m_pContentBuf = AllocBuffer(m_nBufSize);
103         memcpy(m_pContentBuf, pTempDst, m_nBufSize);
104     }
105     else
106     {
107         m_pContentBuf = AllocBuffer(m_nBufSize);
108         m_nBufSize = m_pStrm->Read(m_pContentBuf, m_nBufSize);
109     }
110 }
111 /**
112  * @descr  alloc size of buffer
113  */
AllocBuffer(sal_uInt16 size)114 sal_uInt8* LwpObjectStream::AllocBuffer(sal_uInt16 size)
115 {
116     if (size <= 100)
117     {
118         return m_SmallBuffer;
119     }
120     m_BigBuffer.resize(size);
121     return m_BigBuffer.data();
122 }
123 /**
124  * @descr  signal complete to release object buffer
125  */
ReadComplete()126 void LwpObjectStream::ReadComplete() { ReleaseBuffer(); }
127 
~LwpObjectStream()128 LwpObjectStream::~LwpObjectStream() { ReleaseBuffer(); }
129 /**
130  * @descr  release object buffer
131  */
ReleaseBuffer()132 void LwpObjectStream::ReleaseBuffer()
133 {
134     m_BigBuffer.clear();
135     m_pContentBuf = nullptr;
136 }
137 
remainingSize() const138 sal_uInt16 LwpObjectStream::remainingSize() const { return m_nBufSize - m_nReadPos; }
139 
140 /**
141  * @descr  read len bytes from object stream to buffer
142  */
QuickRead(void * buf,sal_uInt16 len)143 sal_uInt16 LwpObjectStream::QuickRead(void* buf, sal_uInt16 len)
144 {
145     memset(buf, 0, len);
146     if (len > m_nBufSize - m_nReadPos)
147     {
148         len = m_nBufSize - m_nReadPos;
149     }
150     if (m_pContentBuf && len)
151     {
152         memcpy(buf, m_pContentBuf + m_nReadPos, len);
153         m_nReadPos += len;
154     }
155     return len;
156 }
157 /**
158  * @descr  SeekRel pos in object stream/buffer
159  */
SeekRel(sal_uInt16 pos)160 void LwpObjectStream::SeekRel(sal_uInt16 pos)
161 {
162     if (pos > m_nBufSize - m_nReadPos)
163         pos = m_nBufSize - m_nReadPos;
164     m_nReadPos += pos;
165 }
166 /**
167  * @descr  Seek to pos in object buffer/buffer
168  */
Seek(sal_uInt16 pos)169 void LwpObjectStream::Seek(sal_uInt16 pos)
170 {
171     if (pos < m_nBufSize)
172     {
173         m_nReadPos = pos;
174     }
175 }
176 
177 /**
178  * @descr  Quick read sal_Bool
179  */
QuickReadBool()180 bool LwpObjectStream::QuickReadBool()
181 {
182     SVBT16 aValue = { 0 };
183     QuickRead(aValue, sizeof(aValue));
184     return static_cast<bool>(SVBT16ToUInt16(aValue));
185 }
186 /**
187  * @descr  Quick read sal_uInt32
188  */
QuickReaduInt32(bool * pFailure)189 sal_uInt32 LwpObjectStream::QuickReaduInt32(bool* pFailure)
190 {
191     SVBT32 aValue = { 0 };
192     sal_uInt16 nRead = QuickRead(aValue, sizeof(aValue));
193     if (pFailure)
194         *pFailure = (nRead != sizeof(aValue));
195     return SVBT32ToUInt32(aValue);
196 }
197 /**
198  * @descr  Quick read sal_uInt32
199  */
QuickReaduInt16(bool * pFailure)200 sal_uInt16 LwpObjectStream::QuickReaduInt16(bool* pFailure)
201 {
202     SVBT16 aValue = { 0 };
203     sal_uInt16 nRead = QuickRead(aValue, sizeof(aValue));
204     if (pFailure)
205         *pFailure = (nRead != sizeof(aValue));
206     return SVBT16ToUInt16(aValue);
207 }
208 /**
209  * @descr  Quick read sal_Int32
210  */
QuickReadInt32()211 sal_Int32 LwpObjectStream::QuickReadInt32()
212 {
213     SVBT32 aValue = { 0 };
214     QuickRead(aValue, sizeof(aValue));
215     return static_cast<sal_Int32>(SVBT32ToUInt32(aValue));
216 }
217 /**
218  * @descr  Quick read sal_Int16
219  */
QuickReadInt16()220 sal_Int16 LwpObjectStream::QuickReadInt16()
221 {
222     SVBT16 aValue = { 0 };
223     QuickRead(aValue, sizeof(aValue));
224 
225     return static_cast<sal_Int16>(SVBT16ToUInt16(aValue));
226 }
227 /**
228  * @descr  Quick read sal_uInt8
229  */
QuickReaduInt8(bool * pFailure)230 sal_uInt8 LwpObjectStream::QuickReaduInt8(bool* pFailure)
231 {
232     sal_uInt8 aValue = 0;
233     sal_uInt16 nRead = QuickRead(&aValue, sizeof(aValue));
234     if (pFailure)
235         *pFailure = (nRead != sizeof(aValue));
236     return aValue;
237 }
238 /**
239  * @descr  Quick read double
240  */
QuickReadDouble()241 double LwpObjectStream::QuickReadDouble()
242 {
243     union {
244         double d;
245         sal_uInt8 c[8];
246     } s;
247     memset(s.c, 0, sizeof(s.c));
248     QuickRead(s.c, sizeof(s.c));
249 #if defined(OSL_BIGENDIAN)
250     for (size_t i = 0; i < 4; ++i)
251         std::swap(s.c[i], s.c[7 - i]);
252 #endif
253     return s.d;
254 }
255 /**
256  * @descr  skip extra bytes
257  */
SkipExtra()258 void LwpObjectStream::SkipExtra()
259 {
260     sal_uInt16 extra = QuickReaduInt16();
261     while (extra != 0)
262         extra = QuickReaduInt16();
263 }
264 /**
265  * @descr  check if extra bytes
266  */
CheckExtra()267 sal_uInt16 LwpObjectStream::CheckExtra() { return QuickReaduInt16(); }
268 /**
269  * @descr  decompress data buffer from pSrc to pDst
270  *        Refer to the CAmiPro40File::DecompressObject(~) in LWP
271  */
DecompressBuffer(sal_uInt8 * pDst,sal_uInt8 * pSrc,sal_uInt16 Size)272 sal_uInt16 LwpObjectStream::DecompressBuffer(sal_uInt8* pDst, sal_uInt8* pSrc, sal_uInt16 Size)
273 {
274     sal_uInt16 Cnt;
275     sal_uInt32 DstSize = 0;
276 
277     while (Size)
278     {
279         switch (*pSrc & 0xC0)
280         {
281             case 0x00:
282                 // 1 - 64 bytes of 0
283                 // Code 00zzzzzz
284                 // where zzzzzz is the count - 1 of compressed 0 bytes
285 
286                 Cnt = (*pSrc++ & 0x3F) + 1;
287                 if (DstSize + Cnt >= IO_BUFFERSIZE)
288                     throw BadDecompress();
289                 memset(pDst, 0, Cnt);
290                 pDst += Cnt;
291                 DstSize += Cnt;
292                 Size--;
293                 break;
294 
295             case 0x40:
296                 // 1 - 8 zeros followed by 1 - 8 non-zero
297                 // Code 01zzznnn binary
298                 // where zzz is the count - 1 of compressed zero bytes
299                 // and nnn is the count - 1 of following non-zero bytes
300 
301                 Cnt = ((*pSrc & 0x38) >> 3) + 1;
302                 if (DstSize + Cnt >= IO_BUFFERSIZE)
303                     throw BadDecompress();
304                 memset(pDst, 0, Cnt);
305                 pDst += Cnt;
306                 DstSize += Cnt;
307                 Cnt = (*pSrc++ & 0x07) + 1;
308                 if (Size < Cnt + 1)
309                     throw BadDecompress();
310                 Size -= Cnt + 1;
311                 if (DstSize + Cnt >= IO_BUFFERSIZE)
312                     throw BadDecompress();
313                 memcpy(pDst, pSrc, Cnt);
314                 pDst += Cnt;
315                 DstSize += Cnt;
316                 pSrc += Cnt;
317                 break;
318 
319             case 0x80:
320                 // 1 0 followed by 1 - 64 bytes of non-zero
321                 // Code 0x80 (or 0x40 if 8 or less non-zero)
322                 // Code 10nnnnnn binary
323                 // where nnnnnn is the count - 1 of following non-zero bytes
324 
325                 *pDst++ = 0;
326                 DstSize++;
327                 [[fallthrough]];
328 
329             case 0xC0:
330                 // 1 - 64 bytes of non-zero
331                 // Code = 11nnnnnn binary
332                 // nnnnnn is the count less 1 of following non-zero bytes
333 
334                 Cnt = (*pSrc++ & 0x3F) + 1;
335                 if (Size < Cnt + 1)
336                     throw BadDecompress();
337                 Size -= Cnt + 1;
338                 if (DstSize + Cnt >= IO_BUFFERSIZE)
339                     throw BadDecompress();
340                 memcpy(pDst, pSrc, Cnt);
341                 pDst += Cnt;
342                 DstSize += Cnt;
343                 pSrc += Cnt;
344                 break;
345         }
346         assert(DstSize < IO_BUFFERSIZE);
347         if (DstSize >= IO_BUFFERSIZE)
348             throw BadDecompress();
349     }
350     return static_cast<sal_uInt16>(DstSize);
351 }
352 /**
353  * @descr  quick read string with 1252
354  */
QuickReadStringPtr()355 OUString LwpObjectStream::QuickReadStringPtr()
356 {
357     sal_uInt16 diskSize;
358 
359     diskSize = QuickReaduInt16();
360     QuickReaduInt16(); //len
361 
362     OUString str;
363     if (diskSize < sizeof diskSize)
364         throw std::range_error("Too small size");
365     LwpTools::QuickReadUnicode(this, str, diskSize - sizeof(diskSize), RTL_TEXTENCODING_MS_1252);
366     return str;
367 }
368 
369 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
370