Changes to c_zlib.c to make ZLIB.DLL dynamically loadable under
[openssl.git] / crypto / comp / c_zlib.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <openssl/objects.h>
5 #include <openssl/comp.h>
6
7 COMP_METHOD *COMP_zlib(void );
8
9 static COMP_METHOD zlib_method_nozlib={
10         NID_undef,
11         "(undef)",
12         NULL,
13         NULL,
14         NULL,
15         NULL,
16         NULL,
17         };
18
19 #ifdef ZLIB
20
21 #include <zlib.h>
22
23 static int zlib_compress_block(COMP_CTX *ctx, unsigned char *out,
24         unsigned int olen, unsigned char *in, unsigned int ilen);
25 static int zlib_expand_block(COMP_CTX *ctx, unsigned char *out,
26         unsigned int olen, unsigned char *in, unsigned int ilen);
27
28 static int zz_uncompress(Bytef *dest, uLongf *destLen, const Bytef *source,
29         uLong sourceLen);
30
31 static COMP_METHOD zlib_method={
32         NID_zlib_compression,
33         LN_zlib_compression,
34         NULL,
35         NULL,
36         zlib_compress_block,
37         zlib_expand_block,
38         NULL,
39         };
40
41 /* 
42  * When OpenSSL is built on Windows, we do not want to require that
43  * the ZLIB.DLL be available in order for the OpenSSL DLLs to
44  * work.  Therefore, all ZLIB routines are loaded at run time
45  * and we do not link to a .LIB file.
46  */
47 #if defined(WINDOWS) || defined(WIN32)
48 #include <windows.h>
49
50 /* Prototypes for built in stubs */
51 int stub_compress(Bytef *dest,uLongf *destLen,
52         const Bytef *source, uLong sourceLen);
53 int stub_inflateEnd(z_streamp strm);
54 int stub_inflate(z_streamp strm, int flush);
55 int stub_inflateInit_(z_streamp strm, const char * version, int stream_size);
56
57 /* Function pointers */
58 typedef int (_stdcall *compress_ft)(Bytef *dest,uLongf *destLen,
59         const Bytef *source, uLong sourceLen);
60 typedef int (_stdcall *inflateEnd_ft)(z_streamp strm);
61 typedef int (_stdcall *inflate_ft)(z_streamp strm, int flush);
62 typedef int (_stdcall *inflateInit__ft)(z_streamp strm, const char * version,
63         int stream_size);
64 static compress_ft p_compress=NULL;
65 static inflateEnd_ft p_inflateEnd=NULL;
66 static inflate_ft p_inflate=NULL;
67 static inflate_Init__ft p_inflateInit_=NULL;
68
69 static int zlib_loaded = 0;     /* only attempt to init func pts once */
70
71 #define compress                stub_compress
72 #define inflateEnd              stub_inflateEnd
73 #define inflate                 stub_inflate
74 #define inflateInit_            stub_inflateInit_
75 #endif /* WINDOWS || WIN32 */
76
77 static int zlib_compress_block(COMP_CTX *ctx, unsigned char *out,
78              unsigned int olen, unsigned char *in, unsigned int ilen)
79         {
80         unsigned long l;
81         int i;
82         int clear=1;
83
84         if (ilen > 128)
85                 {
86                 out[0]=1;
87                 l=olen-1;
88                 i=compress(&(out[1]),&l,in,(unsigned long)ilen);
89                 if (i != Z_OK)
90                         return(-1);
91                 if (ilen > l)
92                         {
93                         clear=0;
94                         l++;
95                         }
96                 }
97         if (clear)
98                 {
99                 out[0]=0;
100                 memcpy(&(out[1]),in,ilen);
101                 l=ilen+1;
102                 }
103 #ifdef DEBUG_ZLIB
104         fprintf(stderr,"compress(%4d)->%4d %s\n",
105                 ilen,(int)l,(clear)?"clear":"zlib");
106 #endif
107         return((int)l);
108         }
109
110 static int zlib_expand_block(COMP_CTX *ctx, unsigned char *out,
111              unsigned int olen, unsigned char *in, unsigned int ilen)
112         {
113         unsigned long l;
114         int i;
115
116         if (in[0])
117                 {
118                 l=olen;
119                 i=zz_uncompress(out,&l,&(in[1]),(unsigned long)ilen-1);
120                 if (i != Z_OK)
121                         return(-1);
122                 }
123         else
124                 {
125                 memcpy(out,&(in[1]),ilen-1);
126                 l=ilen-1;
127                 }
128 #ifdef DEBUG_ZLIB
129         fprintf(stderr,"expand  (%4d)->%4d %s\n",
130                 ilen,(int)l,in[0]?"zlib":"clear");
131 #endif
132         return((int)l);
133         }
134
135 static int zz_uncompress (Bytef *dest, uLongf *destLen, const Bytef *source,
136              uLong sourceLen)
137 {
138     z_stream stream;
139     int err;
140
141     stream.next_in = (Bytef*)source;
142     stream.avail_in = (uInt)sourceLen;
143     /* Check for source > 64K on 16-bit machine: */
144     if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR;
145
146     stream.next_out = dest;
147     stream.avail_out = (uInt)*destLen;
148     if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR;
149
150     stream.zalloc = (alloc_func)0;
151     stream.zfree = (free_func)0;
152
153     err = inflateInit(&stream);
154     if (err != Z_OK) return err;
155
156     err = inflate(&stream, Z_FINISH);
157     if (err != Z_STREAM_END) {
158         inflateEnd(&stream);
159         return err;
160     }
161     *destLen = stream.total_out;
162
163     err = inflateEnd(&stream);
164     return err;
165 }
166
167 #endif
168
169 COMP_METHOD *COMP_zlib(void)
170         {
171         COMP_METHOD *meth = &zlib_method_nozlib;
172
173 #ifdef ZLIB
174 #if defined(WINDOWS) || defined(WIN32)
175         if (!zlib_method)
176                 {
177                 zlib_dso = DSO_load(NULL, "ZLIB", NULL, 0);
178                 if (dso != NULL)
179                         {
180                         (FARPROC) p_compress
181                                 = (compress_ft) DSO_bind_func(dso, "compress");
182                         (FARPROC) p_inflateEnd
183                                 = (inflateEnd_ft) DSO_bind_func(dso, "inflateEnd");
184                         (FARPROC) p_inflate
185                                 = (inflate_ft) DSO_bind_func(dso, "inflate");
186                         (FARPROC) p_inflateInit_
187                                 = (inflateInit__ft) DSO_bind_func(dso, "inflateInit_");
188                         zlib_loaded++;
189                         meth = &zlib_method;
190                         }
191                 }
192
193 #else
194         meth = &zlib_method;
195 #endif
196 #endif
197
198         return(meth);
199         }
200
201 #ifdef ZLIB
202 #if defined(WINDOWS) || defined(WIN32)
203 /* Stubs for each function to be dynamicly loaded */
204 static int 
205 stub_compress(Bytef *dest,uLongf *destLen,const Bytef *source, uLong sourceLen)
206         {
207         if (p_compress)
208                 return(p_compress(dest,destLen,source,sourceLen));
209         else
210                 return(Z_MEM_ERROR);
211         }
212
213 static int
214 stub_inflateEnd(z_streamp strm)
215         {
216         if ( p_inflateEnd )
217                 return(p_inflateEnd(strm));
218         else
219                 return(Z_MEM_ERROR);
220         }
221
222 static int
223 stub_inflate(z_streamp strm, int flush)
224         {
225         if ( p_inflate )
226                 return(p_inflate(strm,flush));
227         else
228                 return(Z_MEM_ERROR);
229         }
230
231 static int
232 stub_inflateInit_(z_streamp strm, const char * version, int stream_size)
233         {
234         if ( p_inflateInit_ )
235                 return(p_inflateInit_(strm,version,stream_size));
236         else
237                 return(Z_MEM_ERROR);
238         }
239
240 #endif /* WINDOWS || WIN32 */
241 #endif /* ZLIB */