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