xref: /PHP-5.4/ext/zlib/zlib.c (revision 4435b914)
1 /*
2    +----------------------------------------------------------------------+
3    | PHP Version 5                                                        |
4    +----------------------------------------------------------------------+
5    | Copyright (c) 1997-2014 The PHP Group                                |
6    +----------------------------------------------------------------------+
7    | This source file is subject to version 3.01 of the PHP license,      |
8    | that is bundled with this package in the file LICENSE, and is        |
9    | available through the world-wide-web at the following url:           |
10    | http://www.php.net/license/3_01.txt                                  |
11    | If you did not receive a copy of the PHP license and are unable to   |
12    | obtain it through the world-wide-web, please send a note to          |
13    | license@php.net so we can mail you a copy immediately.               |
14    +----------------------------------------------------------------------+
15    | Authors: Rasmus Lerdorf <rasmus@lerdorf.on.ca>                       |
16    |          Stefan Röhrich <sr@linux.de>                                |
17    |          Zeev Suraski <zeev@zend.com>                                |
18    |          Jade Nicoletti <nicoletti@nns.ch>                           |
19    |          Michael Wallner <mike@php.net>                              |
20    +----------------------------------------------------------------------+
21  */
22 
23 /* $Id$ */
24 
25 #ifdef HAVE_CONFIG_H
26 #include "config.h"
27 #endif
28 
29 #include "php.h"
30 #include "SAPI.h"
31 #include "php_ini.h"
32 #include "ext/standard/info.h"
33 #include "ext/standard/file.h"
34 #include "ext/standard/php_string.h"
35 #include "php_zlib.h"
36 
37 ZEND_DECLARE_MODULE_GLOBALS(zlib);
38 
39 /* {{{ Memory management wrappers */
40 
php_zlib_alloc(voidpf opaque,uInt items,uInt size)41 static voidpf php_zlib_alloc(voidpf opaque, uInt items, uInt size)
42 {
43 	return (voidpf)safe_emalloc(items, size, 0);
44 }
45 
php_zlib_free(voidpf opaque,voidpf address)46 static void php_zlib_free(voidpf opaque, voidpf address)
47 {
48 	efree((void*)address);
49 }
50 /* }}} */
51 
52 /* {{{ php_zlib_output_conflict_check() */
php_zlib_output_conflict_check(const char * handler_name,size_t handler_name_len TSRMLS_DC)53 static int php_zlib_output_conflict_check(const char *handler_name, size_t handler_name_len TSRMLS_DC)
54 {
55 	if (php_output_get_level(TSRMLS_C) > 0) {
56 		if (php_output_handler_conflict(handler_name, handler_name_len, ZEND_STRL(PHP_ZLIB_OUTPUT_HANDLER_NAME) TSRMLS_CC)
57 		||	php_output_handler_conflict(handler_name, handler_name_len, ZEND_STRL("ob_gzhandler") TSRMLS_CC)
58 		||  php_output_handler_conflict(handler_name, handler_name_len, ZEND_STRL("mb_output_handler") TSRMLS_CC)
59 		||	php_output_handler_conflict(handler_name, handler_name_len, ZEND_STRL("URL-Rewriter") TSRMLS_CC)) {
60 			return FAILURE;
61 		}
62 	}
63 	return SUCCESS;
64 }
65 /* }}} */
66 
67 /* {{{ php_zlib_output_encoding() */
php_zlib_output_encoding(TSRMLS_D)68 static int php_zlib_output_encoding(TSRMLS_D)
69 {
70 	zval **enc;
71 
72 	if (!ZLIBG(compression_coding)) {
73 		zend_is_auto_global(ZEND_STRL("_SERVER") TSRMLS_CC);
74 		if (PG(http_globals)[TRACK_VARS_SERVER] && SUCCESS == zend_hash_find(Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_SERVER]), "HTTP_ACCEPT_ENCODING", sizeof("HTTP_ACCEPT_ENCODING"), (void *) &enc)) {
75 			convert_to_string(*enc);
76 			if (strstr(Z_STRVAL_PP(enc), "gzip")) {
77 				ZLIBG(compression_coding) = PHP_ZLIB_ENCODING_GZIP;
78 			} else if (strstr(Z_STRVAL_PP(enc), "deflate")) {
79 				ZLIBG(compression_coding) = PHP_ZLIB_ENCODING_DEFLATE;
80 			}
81 		}
82 	}
83 	return ZLIBG(compression_coding);
84 }
85 /* }}} */
86 
87 /* {{{ php_zlib_output_handler_ex() */
php_zlib_output_handler_ex(php_zlib_context * ctx,php_output_context * output_context)88 static int php_zlib_output_handler_ex(php_zlib_context *ctx, php_output_context *output_context)
89 {
90 	int flags = Z_SYNC_FLUSH;
91 	PHP_OUTPUT_TSRMLS(output_context);
92 
93 	if (output_context->op & PHP_OUTPUT_HANDLER_START) {
94 		/* start up */
95 		if (Z_OK != deflateInit2(&ctx->Z, ZLIBG(output_compression_level), Z_DEFLATED, ZLIBG(compression_coding), MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY)) {
96 			return FAILURE;
97 		}
98 	}
99 
100 	if (output_context->op & PHP_OUTPUT_HANDLER_CLEAN) {
101 		/* free buffers */
102 		deflateEnd(&ctx->Z);
103 
104 		if (output_context->op & PHP_OUTPUT_HANDLER_FINAL) {
105 			/* discard */
106 			return SUCCESS;
107 		} else {
108 			/* restart */
109 			if (Z_OK != deflateInit2(&ctx->Z, ZLIBG(output_compression_level), Z_DEFLATED, ZLIBG(compression_coding), MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY)) {
110 				return FAILURE;
111 			}
112 			ctx->buffer.used = 0;
113 		}
114 	} else {
115 		if (output_context->in.used) {
116 			/* append input */
117 			if (ctx->buffer.free < output_context->in.used) {
118 				if (!(ctx->buffer.aptr = erealloc_recoverable(ctx->buffer.data, ctx->buffer.used + ctx->buffer.free + output_context->in.used))) {
119 					deflateEnd(&ctx->Z);
120 					return FAILURE;
121 				}
122 				ctx->buffer.data = ctx->buffer.aptr;
123 				ctx->buffer.free += output_context->in.used;
124 			}
125 			memcpy(ctx->buffer.data + ctx->buffer.used, output_context->in.data, output_context->in.used);
126 			ctx->buffer.free -= output_context->in.used;
127 			ctx->buffer.used += output_context->in.used;
128 		}
129 		output_context->out.size = PHP_ZLIB_BUFFER_SIZE_GUESS(output_context->in.used);
130 		output_context->out.data = emalloc(output_context->out.size);
131 		output_context->out.free = 1;
132 		output_context->out.used = 0;
133 
134 		ctx->Z.avail_in = ctx->buffer.used;
135 		ctx->Z.next_in = (Bytef *) ctx->buffer.data;
136 		ctx->Z.avail_out = output_context->out.size;
137 		ctx->Z.next_out = (Bytef *) output_context->out.data;
138 
139 		if (output_context->op & PHP_OUTPUT_HANDLER_FINAL) {
140 			flags = Z_FINISH;
141 		} else if (output_context->op & PHP_OUTPUT_HANDLER_FLUSH) {
142 			flags = Z_FULL_FLUSH;
143 		}
144 
145 		switch (deflate(&ctx->Z, flags)) {
146 			case Z_OK:
147 				if (flags == Z_FINISH) {
148 					deflateEnd(&ctx->Z);
149 					return FAILURE;
150 				}
151 			case Z_STREAM_END:
152 				if (ctx->Z.avail_in) {
153 					memmove(ctx->buffer.data, ctx->buffer.data + ctx->buffer.used - ctx->Z.avail_in, ctx->Z.avail_in);
154 				}
155 				ctx->buffer.free += ctx->buffer.used - ctx->Z.avail_in;
156 				ctx->buffer.used = ctx->Z.avail_in;
157 				output_context->out.used = output_context->out.size - ctx->Z.avail_out;
158 				break;
159 			default:
160 				deflateEnd(&ctx->Z);
161 				return FAILURE;
162 		}
163 
164 		if (output_context->op & PHP_OUTPUT_HANDLER_FINAL) {
165 			deflateEnd(&ctx->Z);
166 		}
167 	}
168 
169 	return SUCCESS;
170 }
171 /* }}} */
172 
173 /* {{{ php_zlib_output_handler() */
php_zlib_output_handler(void ** handler_context,php_output_context * output_context)174 static int php_zlib_output_handler(void **handler_context, php_output_context *output_context)
175 {
176 	php_zlib_context *ctx = *(php_zlib_context **) handler_context;
177 	PHP_OUTPUT_TSRMLS(output_context);
178 
179 	if (!php_zlib_output_encoding(TSRMLS_C)) {
180 		/* "Vary: Accept-Encoding" header sent along uncompressed content breaks caching in MSIE,
181 			so let's just send it with successfully compressed content or unless the complete
182 			buffer gets discarded, see http://bugs.php.net/40325;
183 
184 			Test as follows:
185 			+Vary: $ HTTP_ACCEPT_ENCODING=gzip ./sapi/cgi/php <<<'<?php ob_start("ob_gzhandler"); echo "foo\n";'
186 			+Vary: $ HTTP_ACCEPT_ENCODING= ./sapi/cgi/php <<<'<?php ob_start("ob_gzhandler"); echo "foo\n";'
187 			-Vary: $ HTTP_ACCEPT_ENCODING=gzip ./sapi/cgi/php <<<'<?php ob_start("ob_gzhandler"); echo "foo\n"; ob_end_clean();'
188 			-Vary: $ HTTP_ACCEPT_ENCODING= ./sapi/cgi/php <<<'<?php ob_start("ob_gzhandler"); echo "foo\n"; ob_end_clean();'
189 		*/
190 		if ((output_context->op & PHP_OUTPUT_HANDLER_START)
191 		&&	(output_context->op != (PHP_OUTPUT_HANDLER_START|PHP_OUTPUT_HANDLER_CLEAN|PHP_OUTPUT_HANDLER_FINAL))
192 		) {
193 			sapi_add_header_ex(ZEND_STRL("Vary: Accept-Encoding"), 1, 0 TSRMLS_CC);
194 		}
195 		return FAILURE;
196 	}
197 
198 	if (SUCCESS != php_zlib_output_handler_ex(ctx, output_context)) {
199 		return FAILURE;
200 	}
201 
202 	if (!(output_context->op & PHP_OUTPUT_HANDLER_CLEAN)) {
203 		int flags;
204 
205 		if (SUCCESS == php_output_handler_hook(PHP_OUTPUT_HANDLER_HOOK_GET_FLAGS, &flags TSRMLS_CC)) {
206 			/* only run this once */
207 			if (!(flags & PHP_OUTPUT_HANDLER_STARTED)) {
208 				if (SG(headers_sent) || !ZLIBG(output_compression)) {
209 					deflateEnd(&ctx->Z);
210 					return FAILURE;
211 				}
212 				switch (ZLIBG(compression_coding)) {
213 					case PHP_ZLIB_ENCODING_GZIP:
214 						sapi_add_header_ex(ZEND_STRL("Content-Encoding: gzip"), 1, 1 TSRMLS_CC);
215 						break;
216 					case PHP_ZLIB_ENCODING_DEFLATE:
217 						sapi_add_header_ex(ZEND_STRL("Content-Encoding: deflate"), 1, 1 TSRMLS_CC);
218 						break;
219 					default:
220 						deflateEnd(&ctx->Z);
221 						return FAILURE;
222 				}
223 				sapi_add_header_ex(ZEND_STRL("Vary: Accept-Encoding"), 1, 0 TSRMLS_CC);
224 				php_output_handler_hook(PHP_OUTPUT_HANDLER_HOOK_IMMUTABLE, NULL TSRMLS_CC);
225 			}
226 		}
227 	}
228 
229 	return SUCCESS;
230 }
231 /* }}} */
232 
233 /* {{{ php_zlib_output_handler_context_init() */
php_zlib_output_handler_context_init(TSRMLS_D)234 static php_zlib_context *php_zlib_output_handler_context_init(TSRMLS_D)
235 {
236 	php_zlib_context *ctx = (php_zlib_context *) ecalloc(1, sizeof(php_zlib_context));
237 	ctx->Z.zalloc = php_zlib_alloc;
238 	ctx->Z.zfree = php_zlib_free;
239 	return ctx;
240 }
241 /* }}} */
242 
243 /* {{{ php_zlib_output_handler_context_dtor() */
php_zlib_output_handler_context_dtor(void * opaq TSRMLS_DC)244 static void php_zlib_output_handler_context_dtor(void *opaq TSRMLS_DC)
245 {
246 	php_zlib_context *ctx = (php_zlib_context *) opaq;
247 
248 	if (ctx) {
249 		if (ctx->buffer.data) {
250 			efree(ctx->buffer.data);
251 		}
252 		efree(ctx);
253 	}
254 }
255 /* }}} */
256 
257 /* {{{ php_zlib_output_handler_init() */
php_zlib_output_handler_init(const char * handler_name,size_t handler_name_len,size_t chunk_size,int flags TSRMLS_DC)258 static php_output_handler *php_zlib_output_handler_init(const char *handler_name, size_t handler_name_len, size_t chunk_size, int flags TSRMLS_DC)
259 {
260 	php_output_handler *h = NULL;
261 
262 	if (!ZLIBG(output_compression)) {
263 		ZLIBG(output_compression) = chunk_size ? chunk_size : PHP_OUTPUT_HANDLER_DEFAULT_SIZE;
264 	}
265 
266     ZLIBG(handler_registered) = 1;
267 
268 	if ((h = php_output_handler_create_internal(handler_name, handler_name_len, php_zlib_output_handler, chunk_size, flags TSRMLS_CC))) {
269 		php_output_handler_set_context(h, php_zlib_output_handler_context_init(TSRMLS_C), php_zlib_output_handler_context_dtor TSRMLS_CC);
270 	}
271 
272 	return h;
273 }
274 /* }}} */
275 
276 /* {{{ php_zlib_output_compression_start() */
php_zlib_output_compression_start(TSRMLS_D)277 static void php_zlib_output_compression_start(TSRMLS_D)
278 {
279 	zval *zoh;
280 	php_output_handler *h;
281 
282 	switch (ZLIBG(output_compression)) {
283 		case 0:
284 			break;
285 		case 1:
286 			ZLIBG(output_compression) = PHP_OUTPUT_HANDLER_DEFAULT_SIZE;
287 			/* break omitted intentionally */
288 		default:
289 			if (	php_zlib_output_encoding(TSRMLS_C) &&
290 					(h = php_zlib_output_handler_init(ZEND_STRL(PHP_ZLIB_OUTPUT_HANDLER_NAME), ZLIBG(output_compression), PHP_OUTPUT_HANDLER_STDFLAGS TSRMLS_CC)) &&
291 					(SUCCESS == php_output_handler_start(h TSRMLS_CC))) {
292 				if (ZLIBG(output_handler) && *ZLIBG(output_handler)) {
293 					MAKE_STD_ZVAL(zoh);
294 					ZVAL_STRING(zoh, ZLIBG(output_handler), 1);
295 					php_output_start_user(zoh, ZLIBG(output_compression), PHP_OUTPUT_HANDLER_STDFLAGS TSRMLS_CC);
296 					zval_ptr_dtor(&zoh);
297 				}
298 			}
299 			break;
300 	}
301 }
302 /* }}} */
303 
304 /* {{{ php_zlib_encode() */
php_zlib_encode(const char * in_buf,size_t in_len,char ** out_buf,size_t * out_len,int encoding,int level TSRMLS_DC)305 static int php_zlib_encode(const char *in_buf, size_t in_len, char **out_buf, size_t *out_len, int encoding, int level TSRMLS_DC)
306 {
307 	int status;
308 	z_stream Z;
309 
310 	memset(&Z, 0, sizeof(z_stream));
311 	Z.zalloc = php_zlib_alloc;
312 	Z.zfree = php_zlib_free;
313 
314 	if (Z_OK == (status = deflateInit2(&Z, level, Z_DEFLATED, encoding, MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY))) {
315 		*out_len = PHP_ZLIB_BUFFER_SIZE_GUESS(in_len);
316 		*out_buf = emalloc(*out_len);
317 
318 		Z.next_in = (Bytef *) in_buf;
319 		Z.next_out = (Bytef *) *out_buf;
320 		Z.avail_in = in_len;
321 		Z.avail_out = *out_len;
322 
323 		status = deflate(&Z, Z_FINISH);
324 		deflateEnd(&Z);
325 
326 		if (Z_STREAM_END == status) {
327 			/* size buffer down to actual length */
328 			*out_buf = erealloc(*out_buf, Z.total_out + 1);
329 			(*out_buf)[*out_len = Z.total_out] = '\0';
330 			return SUCCESS;
331 		} else {
332 			efree(*out_buf);
333 		}
334 	}
335 
336 	*out_buf = NULL;
337 	*out_len = 0;
338 
339 	php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", zError(status));
340 	return FAILURE;
341 }
342 /* }}} */
343 
344 /* {{{ php_zlib_inflate_rounds() */
php_zlib_inflate_rounds(z_stream * Z,size_t max,char ** buf,size_t * len)345 static inline int php_zlib_inflate_rounds(z_stream *Z, size_t max, char **buf, size_t *len)
346 {
347 	int status, round = 0;
348 	php_zlib_buffer buffer = {NULL, NULL, 0, 0, 0};
349 
350 	*buf = NULL;
351 	*len = 0;
352 
353 	buffer.size = (max && (max < Z->avail_in)) ? max : Z->avail_in;
354 
355 	do {
356 		if ((max && (max <= buffer.used)) || !(buffer.aptr = erealloc_recoverable(buffer.data, buffer.size))) {
357 			status = Z_MEM_ERROR;
358 		} else {
359 			buffer.data = buffer.aptr;
360 			Z->avail_out = buffer.free = buffer.size - buffer.used;
361 			Z->next_out = (Bytef *) buffer.data + buffer.used;
362 #if 0
363 			fprintf(stderr, "\n%3d: %3d PRIOR: size=%7lu,\tfree=%7lu,\tused=%7lu,\tavail_in=%7lu,\tavail_out=%7lu\n", round, status, buffer.size, buffer.free, buffer.used, Z->avail_in, Z->avail_out);
364 #endif
365 			status = inflate(Z, Z_NO_FLUSH);
366 
367 			buffer.used += buffer.free - Z->avail_out;
368 			buffer.free = Z->avail_out;
369 #if 0
370 			fprintf(stderr, "%3d: %3d AFTER: size=%7lu,\tfree=%7lu,\tused=%7lu,\tavail_in=%7lu,\tavail_out=%7lu\n", round, status, buffer.size, buffer.free, buffer.used, Z->avail_in, Z->avail_out);
371 #endif
372 			buffer.size += (buffer.size >> 3) + 1;
373 		}
374 	} while ((Z_BUF_ERROR == status || (Z_OK == status && Z->avail_in)) && ++round < 100);
375 
376 	if (status == Z_STREAM_END) {
377 		buffer.data = erealloc(buffer.data, buffer.used + 1);
378 		buffer.data[buffer.used] = '\0';
379 		*buf = buffer.data;
380 		*len = buffer.used;
381 	} else {
382 		if (buffer.data) {
383 			efree(buffer.data);
384 		}
385 		/* HACK: See zlib/examples/zpipe.c inf() function for explanation. */
386 		/* This works as long as this function is not used for streaming. Required to catch very short invalid data. */
387 		status = (status == Z_OK) ? Z_DATA_ERROR : status;
388 	}
389 	return status;
390 }
391 /* }}} */
392 
393 /* {{{ php_zlib_decode() */
php_zlib_decode(const char * in_buf,size_t in_len,char ** out_buf,size_t * out_len,int encoding,size_t max_len TSRMLS_DC)394 static int php_zlib_decode(const char *in_buf, size_t in_len, char **out_buf, size_t *out_len, int encoding, size_t max_len TSRMLS_DC)
395 {
396 	int status = Z_DATA_ERROR;
397 	z_stream Z;
398 
399 	memset(&Z, 0, sizeof(z_stream));
400 	Z.zalloc = php_zlib_alloc;
401 	Z.zfree = php_zlib_free;
402 
403 	if (in_len) {
404 retry_raw_inflate:
405 		status = inflateInit2(&Z, encoding);
406 		if (Z_OK == status) {
407 			Z.next_in = (Bytef *) in_buf;
408 			Z.avail_in = in_len + 1; /* NOTE: data must be zero terminated */
409 
410 			switch (status = php_zlib_inflate_rounds(&Z, max_len, out_buf, out_len)) {
411 				case Z_STREAM_END:
412 					inflateEnd(&Z);
413 					return SUCCESS;
414 
415 				case Z_DATA_ERROR:
416 					/* raw deflated data? */
417 					if (PHP_ZLIB_ENCODING_ANY == encoding) {
418 						inflateEnd(&Z);
419 						encoding = PHP_ZLIB_ENCODING_RAW;
420 						goto retry_raw_inflate;
421 					}
422 			}
423 			inflateEnd(&Z);
424 		}
425 	}
426 
427 	*out_buf = NULL;
428 	*out_len = 0;
429 
430 	php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", zError(status));
431 	return FAILURE;
432 }
433 /* }}} */
434 
435 /* {{{ php_zlib_cleanup_ob_gzhandler_mess() */
php_zlib_cleanup_ob_gzhandler_mess(TSRMLS_D)436 static void php_zlib_cleanup_ob_gzhandler_mess(TSRMLS_D)
437 {
438 	if (ZLIBG(ob_gzhandler)) {
439 		deflateEnd(&(ZLIBG(ob_gzhandler)->Z));
440 		php_zlib_output_handler_context_dtor(ZLIBG(ob_gzhandler) TSRMLS_CC);
441 		ZLIBG(ob_gzhandler) = NULL;
442 	}
443 }
444 /* }}} */
445 
446 /* {{{ proto string ob_gzhandler(string data, int flags)
447    Legacy hack */
PHP_FUNCTION(ob_gzhandler)448 static PHP_FUNCTION(ob_gzhandler)
449 {
450 	char *in_str;
451 	int in_len;
452 	long flags = 0;
453 	php_output_context ctx = {0};
454 	int encoding, rv;
455 
456 	/*
457 	 * NOTE that the real ob_gzhandler is an alias to "zlib output compression".
458 	 * This is a really bad hack, because
459 	 * - we have to initialize a php_zlib_context on demand
460 	 * - we have to clean it up in RSHUTDOWN
461 	 * - OG(running) is not set or set to any other output handler
462 	 * - we have to mess around with php_output_context */
463 
464 	if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl", &in_str, &in_len, &flags)) {
465 		RETURN_FALSE;
466 	}
467 
468 	if (!(encoding = php_zlib_output_encoding(TSRMLS_C))) {
469 		RETURN_FALSE;
470 	}
471 
472 	if (flags & PHP_OUTPUT_HANDLER_START) {
473 		switch (encoding) {
474 			case PHP_ZLIB_ENCODING_GZIP:
475 				sapi_add_header_ex(ZEND_STRL("Content-Encoding: gzip"), 1, 1 TSRMLS_CC);
476 				break;
477 			case PHP_ZLIB_ENCODING_DEFLATE:
478 				sapi_add_header_ex(ZEND_STRL("Content-Encoding: deflate"), 1, 1 TSRMLS_CC);
479 				break;
480 		}
481 		sapi_add_header_ex(ZEND_STRL("Vary: Accept-Encoding"), 1, 0 TSRMLS_CC);
482 	}
483 
484 	if (!ZLIBG(ob_gzhandler)) {
485 		ZLIBG(ob_gzhandler) = php_zlib_output_handler_context_init(TSRMLS_C);
486 	}
487 
488 	TSRMLS_SET_CTX(ctx.tsrm_ls);
489 	ctx.op = flags;
490 	ctx.in.data = in_str;
491 	ctx.in.used = in_len;
492 
493 	rv = php_zlib_output_handler_ex(ZLIBG(ob_gzhandler), &ctx);
494 
495 	if (SUCCESS != rv) {
496 		if (ctx.out.data && ctx.out.free) {
497 			efree(ctx.out.data);
498 		}
499 		php_zlib_cleanup_ob_gzhandler_mess(TSRMLS_C);
500 		RETURN_FALSE;
501 	}
502 
503 	if (ctx.out.data) {
504 		RETVAL_STRINGL(ctx.out.data, ctx.out.used, 1);
505 		if (ctx.out.free) {
506 			efree(ctx.out.data);
507 		}
508 	} else {
509 		RETVAL_EMPTY_STRING();
510 	}
511 }
512 /* }}} */
513 
514 /* {{{ proto string zlib_get_coding_type(void)
515    Returns the coding type used for output compression */
PHP_FUNCTION(zlib_get_coding_type)516 static PHP_FUNCTION(zlib_get_coding_type)
517 {
518 	if (zend_parse_parameters_none() == FAILURE) {
519 		return;
520 	}
521 	switch (ZLIBG(compression_coding)) {
522 		case PHP_ZLIB_ENCODING_GZIP:
523 			RETURN_STRINGL("gzip", sizeof("gzip") - 1, 1);
524 		case PHP_ZLIB_ENCODING_DEFLATE:
525 			RETURN_STRINGL("deflate", sizeof("deflate") - 1, 1);
526 		default:
527 			RETURN_FALSE;
528 	}
529 }
530 /* }}} */
531 
532 /* {{{ proto array gzfile(string filename [, int use_include_path])
533    Read and uncompress entire .gz-file into an array */
PHP_FUNCTION(gzfile)534 static PHP_FUNCTION(gzfile)
535 {
536 	char *filename;
537 	int filename_len;
538 	int flags = REPORT_ERRORS;
539 	char buf[8192] = {0};
540 	register int i = 0;
541 	long use_include_path = 0;
542 	php_stream *stream;
543 
544 	if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|l", &filename, &filename_len, &use_include_path)) {
545 		return;
546 	}
547 
548 	if (use_include_path) {
549 		flags |= USE_PATH;
550 	}
551 
552 	/* using a stream here is a bit more efficient (resource wise) than php_gzopen_wrapper */
553 	stream = php_stream_gzopen(NULL, filename, "rb", flags, NULL, NULL STREAMS_CC TSRMLS_CC);
554 
555 	if (!stream) {
556 		/* Error reporting is already done by stream code */
557 		RETURN_FALSE;
558 	}
559 
560 	/* Initialize return array */
561 	array_init(return_value);
562 
563 	/* Now loop through the file and do the magic quotes thing if needed */
564 	memset(buf, 0, sizeof(buf));
565 
566 	while (php_stream_gets(stream, buf, sizeof(buf) - 1) != NULL) {
567 		add_index_string(return_value, i++, buf, 1);
568 	}
569 	php_stream_close(stream);
570 }
571 /* }}} */
572 
573 /* {{{ proto resource gzopen(string filename, string mode [, int use_include_path])
574    Open a .gz-file and return a .gz-file pointer */
PHP_FUNCTION(gzopen)575 static PHP_FUNCTION(gzopen)
576 {
577 	char *filename;
578 	char *mode;
579 	int filename_len, mode_len;
580 	int flags = REPORT_ERRORS;
581 	php_stream *stream;
582 	long use_include_path = 0;
583 
584 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ps|l", &filename, &filename_len, &mode, &mode_len, &use_include_path) == FAILURE) {
585 		return;
586 	}
587 
588 	if (use_include_path) {
589 		flags |= USE_PATH;
590 	}
591 
592 	stream = php_stream_gzopen(NULL, filename, mode, flags, NULL, NULL STREAMS_CC TSRMLS_CC);
593 
594 	if (!stream) {
595 		RETURN_FALSE;
596 	}
597 	php_stream_to_zval(stream, return_value);
598 }
599 /* }}} */
600 
601 /* {{{ proto int readgzfile(string filename [, int use_include_path])
602    Output a .gz-file */
PHP_FUNCTION(readgzfile)603 static PHP_FUNCTION(readgzfile)
604 {
605 	char *filename;
606 	int filename_len;
607 	int flags = REPORT_ERRORS;
608 	php_stream *stream;
609 	int size;
610 	long use_include_path = 0;
611 
612 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|l", &filename, &filename_len, &use_include_path) == FAILURE) {
613 		return;
614 	}
615 
616 	if (use_include_path) {
617 		flags |= USE_PATH;
618 	}
619 
620 	stream = php_stream_gzopen(NULL, filename, "rb", flags, NULL, NULL STREAMS_CC TSRMLS_CC);
621 
622 	if (!stream) {
623 		RETURN_FALSE;
624 	}
625 	size = php_stream_passthru(stream);
626 	php_stream_close(stream);
627 	RETURN_LONG(size);
628 }
629 /* }}} */
630 
631 #define PHP_ZLIB_ENCODE_FUNC(name, default_encoding) \
632 static PHP_FUNCTION(name) \
633 { \
634 	char *in_buf, *out_buf; \
635 	int in_len; \
636 	size_t out_len; \
637 	long level = -1; \
638 	long encoding = default_encoding; \
639 	if (default_encoding) { \
640 		if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|ll", &in_buf, &in_len, &level, &encoding)) { \
641 			return; \
642 		} \
643 	} else { \
644 		if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl|l", &in_buf, &in_len, &encoding, &level)) { \
645 			return; \
646 		} \
647 	} \
648 	if (level < -1 || level > 9) { \
649 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "compression level (%ld) must be within -1..9", level); \
650 		RETURN_FALSE; \
651 	} \
652 	switch (encoding) { \
653 		case PHP_ZLIB_ENCODING_RAW: \
654 		case PHP_ZLIB_ENCODING_GZIP: \
655 		case PHP_ZLIB_ENCODING_DEFLATE: \
656 			break; \
657 		default: \
658 			php_error_docref(NULL TSRMLS_CC, E_WARNING, "encoding mode must be either ZLIB_ENCODING_RAW, ZLIB_ENCODING_GZIP or ZLIB_ENCODING_DEFLATE"); \
659 			RETURN_FALSE; \
660 	} \
661 	if (SUCCESS != php_zlib_encode(in_buf, in_len, &out_buf, &out_len, encoding, level TSRMLS_CC)) { \
662 		RETURN_FALSE; \
663 	} \
664 	RETURN_STRINGL(out_buf, out_len, 0); \
665 }
666 
667 #define PHP_ZLIB_DECODE_FUNC(name, encoding) \
668 static PHP_FUNCTION(name) \
669 { \
670 	char *in_buf, *out_buf; \
671 	int in_len; \
672 	size_t out_len; \
673 	long max_len = 0; \
674 	if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &in_buf, &in_len, &max_len)) { \
675 		return; \
676 	} \
677 	if (max_len < 0) { \
678 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "length (%ld) must be greater or equal zero", max_len); \
679 		RETURN_FALSE; \
680 	} \
681 	if (SUCCESS != php_zlib_decode(in_buf, in_len, &out_buf, &out_len, encoding, max_len TSRMLS_CC)) { \
682 		RETURN_FALSE; \
683 	} \
684 	RETURN_STRINGL(out_buf, out_len, 0); \
685 }
686 
687 /* {{{ proto binary zlib_encode(binary data, int encoding[, int level = -1])
688    Compress data with the specified encoding */
689 PHP_ZLIB_ENCODE_FUNC(zlib_encode, 0);
690 /* }}} */
691 
692 /* {{{ proto binary zlib_decode(binary data[, int max_decoded_len])
693    Uncompress any raw/gzip/zlib encoded data */
694 PHP_ZLIB_DECODE_FUNC(zlib_decode, PHP_ZLIB_ENCODING_ANY);
695 /* }}} */
696 
697 /* NOTE: The naming of these userland functions was quite unlucky */
698 /* {{{ proto binary gzdeflate(binary data[, int level = -1[, int encoding = ZLIB_ENCODING_RAW])
699    Encode data with the raw deflate encoding */
700 PHP_ZLIB_ENCODE_FUNC(gzdeflate, PHP_ZLIB_ENCODING_RAW);
701 /* }}} */
702 
703 /* {{{ proto binary gzencode(binary data[, int level = -1[, int encoding = ZLIB_ENCODING_GZIP])
704    Encode data with the gzip encoding */
705 PHP_ZLIB_ENCODE_FUNC(gzencode, PHP_ZLIB_ENCODING_GZIP);
706 /* }}} */
707 
708 /* {{{ proto binary gzcompress(binary data[, int level = -1[, int encoding = ZLIB_ENCODING_DEFLATE])
709    Encode data with the zlib encoding */
710 PHP_ZLIB_ENCODE_FUNC(gzcompress, PHP_ZLIB_ENCODING_DEFLATE);
711 /* }}} */
712 
713 /* {{{ proto binary gzinflate(binary data[, int max_decoded_len])
714    Decode raw deflate encoded data */
715 PHP_ZLIB_DECODE_FUNC(gzinflate, PHP_ZLIB_ENCODING_RAW);
716 /* }}} */
717 
718 /* {{{ proto binary gzdecode(binary data[, int max_decoded_len])
719    Decode gzip encoded data */
720 PHP_ZLIB_DECODE_FUNC(gzdecode, PHP_ZLIB_ENCODING_GZIP);
721 /* }}} */
722 
723 /* {{{ proto binary gzuncompress(binary data[, int max_decoded_len])
724    Decode zlib encoded data */
725 PHP_ZLIB_DECODE_FUNC(gzuncompress, PHP_ZLIB_ENCODING_DEFLATE);
726 /* }}} */
727 
728 #ifdef COMPILE_DL_ZLIB
729 ZEND_GET_MODULE(php_zlib)
730 #endif
731 
732 /* {{{ arginfo */
733 ZEND_BEGIN_ARG_INFO_EX(arginfo_ob_gzhandler, 0, 0, 2)
734 	ZEND_ARG_INFO(0, data)
735 	ZEND_ARG_INFO(0, flags)
736 ZEND_END_ARG_INFO()
737 
738 ZEND_BEGIN_ARG_INFO(arginfo_zlib_get_coding_type, 0)
739 ZEND_END_ARG_INFO()
740 
741 ZEND_BEGIN_ARG_INFO_EX(arginfo_gzfile, 0, 0, 1)
742 	ZEND_ARG_INFO(0, filename)
743 	ZEND_ARG_INFO(0, use_include_path)
744 ZEND_END_ARG_INFO()
745 
746 ZEND_BEGIN_ARG_INFO_EX(arginfo_gzopen, 0, 0, 2)
747 	ZEND_ARG_INFO(0, filename)
748 	ZEND_ARG_INFO(0, mode)
749 	ZEND_ARG_INFO(0, use_include_path)
750 ZEND_END_ARG_INFO()
751 
752 ZEND_BEGIN_ARG_INFO_EX(arginfo_readgzfile, 0, 0, 1)
753 	ZEND_ARG_INFO(0, filename)
754 	ZEND_ARG_INFO(0, use_include_path)
755 ZEND_END_ARG_INFO()
756 
757 ZEND_BEGIN_ARG_INFO_EX(arginfo_zlib_encode, 0, 0, 2)
758 	ZEND_ARG_INFO(0, data)
759 	ZEND_ARG_INFO(0, encoding)
760 	ZEND_ARG_INFO(0, level)
761 ZEND_END_ARG_INFO()
762 
763 ZEND_BEGIN_ARG_INFO_EX(arginfo_zlib_decode, 0, 0, 1)
764 	ZEND_ARG_INFO(0, data)
765 	ZEND_ARG_INFO(0, max_decoded_len)
766 ZEND_END_ARG_INFO()
767 
768 ZEND_BEGIN_ARG_INFO_EX(arginfo_gzdeflate, 0, 0, 1)
769 	ZEND_ARG_INFO(0, data)
770 	ZEND_ARG_INFO(0, level)
771 	ZEND_ARG_INFO(0, encoding)
772 ZEND_END_ARG_INFO()
773 
774 ZEND_BEGIN_ARG_INFO_EX(arginfo_gzencode, 0, 0, 1)
775 	ZEND_ARG_INFO(0, data)
776 	ZEND_ARG_INFO(0, level)
777 	ZEND_ARG_INFO(0, encoding)
778 ZEND_END_ARG_INFO()
779 
780 ZEND_BEGIN_ARG_INFO_EX(arginfo_gzcompress, 0, 0, 1)
781 	ZEND_ARG_INFO(0, data)
782 	ZEND_ARG_INFO(0, level)
783 	ZEND_ARG_INFO(0, encoding)
784 ZEND_END_ARG_INFO()
785 
786 ZEND_BEGIN_ARG_INFO_EX(arginfo_gzinflate, 0, 0, 1)
787 	ZEND_ARG_INFO(0, data)
788 	ZEND_ARG_INFO(0, max_decoded_len)
789 ZEND_END_ARG_INFO()
790 
791 ZEND_BEGIN_ARG_INFO_EX(arginfo_gzdecode, 0, 0, 1)
792 	ZEND_ARG_INFO(0, data)
793 	ZEND_ARG_INFO(0, max_decoded_len)
794 ZEND_END_ARG_INFO()
795 
796 ZEND_BEGIN_ARG_INFO_EX(arginfo_gzuncompress, 0, 0, 1)
797 	ZEND_ARG_INFO(0, data)
798 	ZEND_ARG_INFO(0, max_decoded_len)
799 ZEND_END_ARG_INFO()
800 
801 ZEND_BEGIN_ARG_INFO_EX(arginfo_gzputs, 0, 0, 2)
802 	ZEND_ARG_INFO(0, fp)
803 	ZEND_ARG_INFO(0, str)
804 	ZEND_ARG_INFO(0, length)
805 ZEND_END_ARG_INFO()
806 
807 ZEND_BEGIN_ARG_INFO(arginfo_gzpassthru, 0)
808 	ZEND_ARG_INFO(0, fp)
809 ZEND_END_ARG_INFO()
810 
811 ZEND_BEGIN_ARG_INFO_EX(arginfo_gzseek, 0, 0, 2)
812 	ZEND_ARG_INFO(0, fp)
813 	ZEND_ARG_INFO(0, offset)
814 	ZEND_ARG_INFO(0, whence)
815 ZEND_END_ARG_INFO()
816 
817 ZEND_BEGIN_ARG_INFO(arginfo_gzread, 0)
818 	ZEND_ARG_INFO(0, fp)
819 	ZEND_ARG_INFO(0, length)
820 ZEND_END_ARG_INFO()
821 
822 ZEND_BEGIN_ARG_INFO_EX(arginfo_gzgetss, 0, 0, 1)
823 	ZEND_ARG_INFO(0, fp)
824 	ZEND_ARG_INFO(0, length)
825 	ZEND_ARG_INFO(0, allowable_tags)
826 ZEND_END_ARG_INFO()
827 
828 ZEND_BEGIN_ARG_INFO_EX(arginfo_gzgets, 0, 0, 1)
829 	ZEND_ARG_INFO(0, fp)
830 	ZEND_ARG_INFO(0, length)
831 ZEND_END_ARG_INFO()
832 /* }}} */
833 
834 /* {{{ php_zlib_functions[] */
835 static const zend_function_entry php_zlib_functions[] = {
836 	PHP_FE(readgzfile,						arginfo_readgzfile)
837 	PHP_FALIAS(gzrewind,	rewind,			arginfo_gzpassthru)
838 	PHP_FALIAS(gzclose,		fclose,			arginfo_gzpassthru)
839 	PHP_FALIAS(gzeof,		feof,			arginfo_gzpassthru)
840 	PHP_FALIAS(gzgetc,		fgetc,			arginfo_gzpassthru)
841 	PHP_FALIAS(gzgets,		fgets,			arginfo_gzgets)
842 	PHP_FALIAS(gzgetss,		fgetss,			arginfo_gzgetss)
843 	PHP_FALIAS(gzread,		fread,			arginfo_gzread)
844 	PHP_FE(gzopen,							arginfo_gzopen)
845 	PHP_FALIAS(gzpassthru,	fpassthru,		arginfo_gzpassthru)
846 	PHP_FALIAS(gzseek,		fseek,			arginfo_gzseek)
847 	PHP_FALIAS(gztell,		ftell,			arginfo_gzpassthru)
848 	PHP_FALIAS(gzwrite,		fwrite,			arginfo_gzputs)
849 	PHP_FALIAS(gzputs,		fwrite,			arginfo_gzputs)
850 	PHP_FE(gzfile,							arginfo_gzfile)
851 	PHP_FE(gzcompress,						arginfo_gzcompress)
852 	PHP_FE(gzuncompress,					arginfo_gzuncompress)
853 	PHP_FE(gzdeflate,						arginfo_gzdeflate)
854 	PHP_FE(gzinflate,						arginfo_gzinflate)
855 	PHP_FE(gzencode,						arginfo_gzencode)
856 	PHP_FE(gzdecode,						arginfo_gzdecode)
857 	PHP_FE(zlib_encode,						arginfo_zlib_encode)
858 	PHP_FE(zlib_decode,						arginfo_zlib_decode)
859 	PHP_FE(zlib_get_coding_type,			arginfo_zlib_get_coding_type)
860 	PHP_FE(ob_gzhandler,					arginfo_ob_gzhandler)
861 	PHP_FE_END
862 };
863 /* }}} */
864 
865 /* {{{ OnUpdate_zlib_output_compression */
PHP_INI_MH(OnUpdate_zlib_output_compression)866 static PHP_INI_MH(OnUpdate_zlib_output_compression)
867 {
868 	int status, int_value;
869 	char *ini_value;
870 
871 	if (new_value == NULL) {
872 		return FAILURE;
873 	}
874 
875 	if (!strncasecmp(new_value, "off", sizeof("off"))) {
876 		new_value = "0";
877 		new_value_length = sizeof("0");
878 	} else if (!strncasecmp(new_value, "on", sizeof("on"))) {
879 		new_value = "1";
880 		new_value_length = sizeof("1");
881 	}
882 
883 	int_value = zend_atoi(new_value, new_value_length);
884 	ini_value = zend_ini_string("output_handler", sizeof("output_handler"), 0);
885 
886 	if (ini_value && *ini_value && int_value) {
887 		php_error_docref("ref.outcontrol" TSRMLS_CC, E_CORE_ERROR, "Cannot use both zlib.output_compression and output_handler together!!");
888 		return FAILURE;
889 	}
890 	if (stage == PHP_INI_STAGE_RUNTIME) {
891 		status = php_output_get_status(TSRMLS_C);
892 		if (status & PHP_OUTPUT_SENT) {
893 			php_error_docref("ref.outcontrol" TSRMLS_CC, E_WARNING, "Cannot change zlib.output_compression - headers already sent");
894 			return FAILURE;
895 		}
896 	}
897 
898 	status = OnUpdateLong(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC);
899 
900 	ZLIBG(output_compression) = ZLIBG(output_compression_default);
901 	if (stage == PHP_INI_STAGE_RUNTIME && int_value) {
902 		if (!php_output_handler_started(ZEND_STRL(PHP_ZLIB_OUTPUT_HANDLER_NAME) TSRMLS_CC)) {
903 			php_zlib_output_compression_start(TSRMLS_C);
904 		}
905 	}
906 
907 	return status;
908 }
909 /* }}} */
910 
911 /* {{{ OnUpdate_zlib_output_handler */
PHP_INI_MH(OnUpdate_zlib_output_handler)912 static PHP_INI_MH(OnUpdate_zlib_output_handler)
913 {
914 	if (stage == PHP_INI_STAGE_RUNTIME && (php_output_get_status(TSRMLS_C) & PHP_OUTPUT_SENT)) {
915 		php_error_docref("ref.outcontrol" TSRMLS_CC, E_WARNING, "Cannot change zlib.output_handler - headers already sent");
916 		return FAILURE;
917 	}
918 
919 	return OnUpdateString(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC);
920 }
921 /* }}} */
922 
923 /* {{{ INI */
924 PHP_INI_BEGIN()
925 	STD_PHP_INI_BOOLEAN("zlib.output_compression",      "0", PHP_INI_ALL, OnUpdate_zlib_output_compression,       output_compression_default,       zend_zlib_globals, zlib_globals)
926 	STD_PHP_INI_ENTRY("zlib.output_compression_level", "-1", PHP_INI_ALL, OnUpdateLong,                           output_compression_level, zend_zlib_globals, zlib_globals)
927 	STD_PHP_INI_ENTRY("zlib.output_handler",             "", PHP_INI_ALL, OnUpdate_zlib_output_handler,           output_handler,           zend_zlib_globals, zlib_globals)
PHP_INI_END()928 PHP_INI_END()
929 
930 /* }}} */
931 
932 /* {{{ PHP_MINIT_FUNCTION */
933 static PHP_MINIT_FUNCTION(zlib)
934 {
935 	php_register_url_stream_wrapper("compress.zlib", &php_stream_gzip_wrapper TSRMLS_CC);
936 	php_stream_filter_register_factory("zlib.*", &php_zlib_filter_factory TSRMLS_CC);
937 
938 	php_output_handler_alias_register(ZEND_STRL("ob_gzhandler"), php_zlib_output_handler_init TSRMLS_CC);
939 	php_output_handler_conflict_register(ZEND_STRL("ob_gzhandler"), php_zlib_output_conflict_check TSRMLS_CC);
940 	php_output_handler_conflict_register(ZEND_STRL(PHP_ZLIB_OUTPUT_HANDLER_NAME), php_zlib_output_conflict_check TSRMLS_CC);
941 
942 	REGISTER_LONG_CONSTANT("FORCE_GZIP", PHP_ZLIB_ENCODING_GZIP, CONST_CS|CONST_PERSISTENT);
943 	REGISTER_LONG_CONSTANT("FORCE_DEFLATE", PHP_ZLIB_ENCODING_DEFLATE, CONST_CS|CONST_PERSISTENT);
944 
945 	REGISTER_LONG_CONSTANT("ZLIB_ENCODING_RAW", PHP_ZLIB_ENCODING_RAW, CONST_CS|CONST_PERSISTENT);
946 	REGISTER_LONG_CONSTANT("ZLIB_ENCODING_GZIP", PHP_ZLIB_ENCODING_GZIP, CONST_CS|CONST_PERSISTENT);
947 	REGISTER_LONG_CONSTANT("ZLIB_ENCODING_DEFLATE", PHP_ZLIB_ENCODING_DEFLATE, CONST_CS|CONST_PERSISTENT);
948 	REGISTER_INI_ENTRIES();
949 	return SUCCESS;
950 }
951 /* }}} */
952 
953 /* {{{ PHP_MSHUTDOWN_FUNCTION */
PHP_MSHUTDOWN_FUNCTION(zlib)954 static PHP_MSHUTDOWN_FUNCTION(zlib)
955 {
956 	php_unregister_url_stream_wrapper("zlib" TSRMLS_CC);
957 	php_stream_filter_unregister_factory("zlib.*" TSRMLS_CC);
958 
959 	UNREGISTER_INI_ENTRIES();
960 
961 	return SUCCESS;
962 }
963 /* }}} */
964 
965 /* {{{ PHP_RINIT_FUNCTION */
PHP_RINIT_FUNCTION(zlib)966 static PHP_RINIT_FUNCTION(zlib)
967 {
968 	ZLIBG(compression_coding) = 0;
969     if (!ZLIBG(handler_registered)) {
970         ZLIBG(output_compression) = ZLIBG(output_compression_default);
971         php_zlib_output_compression_start(TSRMLS_C);
972     }
973 
974 	return SUCCESS;
975 }
976 /* }}} */
977 
978 /* {{{ PHP_RSHUTDOWN_FUNCTION */
PHP_RSHUTDOWN_FUNCTION(zlib)979 static PHP_RSHUTDOWN_FUNCTION(zlib)
980 {
981 	php_zlib_cleanup_ob_gzhandler_mess(TSRMLS_C);
982     ZLIBG(handler_registered) = 0;
983 
984     return SUCCESS;
985 }
986 /* }}} */
987 
988 /* {{{ PHP_MINFO_FUNCTION */
PHP_MINFO_FUNCTION(zlib)989 static PHP_MINFO_FUNCTION(zlib)
990 {
991 	php_info_print_table_start();
992 	php_info_print_table_header(2, "ZLib Support", "enabled");
993 	php_info_print_table_row(2, "Stream Wrapper", "compress.zlib://");
994 	php_info_print_table_row(2, "Stream Filter", "zlib.inflate, zlib.deflate");
995 	php_info_print_table_row(2, "Compiled Version", ZLIB_VERSION);
996 	php_info_print_table_row(2, "Linked Version", (char *) zlibVersion());
997 	php_info_print_table_end();
998 
999 	DISPLAY_INI_ENTRIES();
1000 }
1001 /* }}} */
1002 
1003 /* {{{ ZEND_MODULE_GLOBALS_CTOR */
ZEND_MODULE_GLOBALS_CTOR_D(zlib)1004 static ZEND_MODULE_GLOBALS_CTOR_D(zlib)
1005 {
1006 	zlib_globals->ob_gzhandler = NULL;
1007     zlib_globals->handler_registered = 0;
1008 }
1009 /* }}} */
1010 
1011 /* {{{ php_zlib_module_entry */
1012 zend_module_entry php_zlib_module_entry = {
1013 	STANDARD_MODULE_HEADER,
1014 	"zlib",
1015 	php_zlib_functions,
1016 	PHP_MINIT(zlib),
1017 	PHP_MSHUTDOWN(zlib),
1018 	PHP_RINIT(zlib),
1019 	PHP_RSHUTDOWN(zlib),
1020 	PHP_MINFO(zlib),
1021 	"2.0",
1022 	PHP_MODULE_GLOBALS(zlib),
1023 	ZEND_MODULE_GLOBALS_CTOR_N(zlib),
1024 	NULL,
1025 	NULL,
1026 	STANDARD_MODULE_PROPERTIES_EX
1027 };
1028 /* }}} */
1029 
1030 /*
1031  * Local variables:
1032  * tab-width: 4
1033  * c-basic-offset: 4
1034  * End:
1035  * vim600: sw=4 ts=4 fdm=marker
1036  * vim<600: sw=4 ts=4
1037  */
1038