1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_package.hxx"
26 #include <Inflater.hxx>
27 #ifndef _ZLIB_H
28 #ifdef SYSTEM_ZLIB
29 #include <zlib.h>
30 #else
31 #include <external/zlib/zlib.h>
32 #endif
33 #endif
34 #include <string.h> // for memset
35
36 using namespace com::sun::star::uno;
37
38 /** Provides general purpose decompression using the ZLIB library */
39
Inflater(sal_Bool bNoWrap)40 Inflater::Inflater(sal_Bool bNoWrap)
41 : bFinished(sal_False),
42 bSetParams(sal_False),
43 bNeedDict(sal_False),
44 nOffset(0),
45 nLength(0),
46 nLastInflateError(0),
47 pStream(NULL)
48 {
49 pStream = new z_stream;
50 /* memset to 0 to set zalloc/opaque etc */
51 memset (pStream, 0, sizeof(*pStream));
52 sal_Int32 nRes;
53 nRes = inflateInit2(pStream, bNoWrap ? -MAX_WBITS : MAX_WBITS);
54 switch (nRes)
55 {
56 case Z_OK:
57 break;
58 case Z_MEM_ERROR:
59 delete pStream;
60 break;
61 case Z_STREAM_ERROR:
62 delete pStream;
63 break;
64 default:
65 break;
66 }
67 }
68
~Inflater()69 Inflater::~Inflater()
70 {
71 end();
72 }
73
setInput(const Sequence<sal_Int8> & rBuffer)74 void SAL_CALL Inflater::setInput( const Sequence< sal_Int8 >& rBuffer )
75 {
76 sInBuffer = rBuffer;
77 nOffset = 0;
78 nLength = rBuffer.getLength();
79 }
80
needsDictionary()81 sal_Bool SAL_CALL Inflater::needsDictionary( )
82 {
83 return bNeedDict;
84 }
85
finished()86 sal_Bool SAL_CALL Inflater::finished( )
87 {
88 return bFinished;
89 }
90
doInflateSegment(Sequence<sal_Int8> & rBuffer,sal_Int32 nNewOffset,sal_Int32 nNewLength)91 sal_Int32 SAL_CALL Inflater::doInflateSegment( Sequence< sal_Int8 >& rBuffer, sal_Int32 nNewOffset, sal_Int32 nNewLength )
92 {
93 if (nNewOffset < 0 || nNewLength < 0 || nNewOffset + nNewLength > rBuffer.getLength())
94 {
95 // do error handling
96 }
97 return doInflateBytes(rBuffer, nNewOffset, nNewLength);
98 }
99
end()100 void SAL_CALL Inflater::end( )
101 {
102 if (pStream != NULL)
103 {
104 #if defined SYSTEM_ZLIB || !defined ZLIB_PREFIX
105 inflateEnd(pStream);
106 #else
107 z_inflateEnd(pStream);
108 #endif
109 delete pStream;
110 }
111 pStream = NULL;
112 }
113
doInflateBytes(Sequence<sal_Int8> & rBuffer,sal_Int32 nNewOffset,sal_Int32 nNewLength)114 sal_Int32 Inflater::doInflateBytes (Sequence < sal_Int8 > &rBuffer, sal_Int32 nNewOffset, sal_Int32 nNewLength)
115 {
116 if ( !pStream )
117 {
118 nLastInflateError = Z_STREAM_ERROR;
119 return 0;
120 }
121
122 nLastInflateError = 0;
123
124 pStream->next_in = ( unsigned char* ) ( sInBuffer.getConstArray() + nOffset );
125 pStream->avail_in = nLength;
126 pStream->next_out = reinterpret_cast < unsigned char* > ( rBuffer.getArray() + nNewOffset );
127 pStream->avail_out = nNewLength;
128
129 #if defined SYSTEM_ZLIB || !defined ZLIB_PREFIX
130 sal_Int32 nResult = ::inflate(pStream, Z_PARTIAL_FLUSH);
131 #else
132 sal_Int32 nResult = ::z_inflate(pStream, Z_PARTIAL_FLUSH);
133 #endif
134
135 switch (nResult)
136 {
137 case Z_STREAM_END:
138 bFinished = sal_True;
139 case Z_OK:
140 nOffset += nLength - pStream->avail_in;
141 nLength = pStream->avail_in;
142 return nNewLength - pStream->avail_out;
143
144 case Z_NEED_DICT:
145 bNeedDict = sal_True;
146 nOffset += nLength - pStream->avail_in;
147 nLength = pStream->avail_in;
148 return 0;
149
150 default:
151 // it is no error, if there is no input or no output
152 if ( nLength && nNewLength )
153 nLastInflateError = nResult;
154 }
155
156 return 0;
157 }
158
159