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