📄 zlib.c
字号:
/* +----------------------------------------------------------------------+ | PHP Version 4 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2007 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | http://www.php.net/license/3_01.txt | | If you did not receive a copy of the PHP license and are unable to | | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Authors: Rasmus Lerdorf <rasmus@lerdorf.on.ca> | | Stefan R鰄rich <sr@linux.de> | | Zeev Suraski <zeev@zend.com> | | Jade Nicoletti <nicoletti@nns.ch> | +----------------------------------------------------------------------+ *//* $Id: zlib.c,v 1.153.2.16.4.4 2007/01/01 09:46:50 sebastian Exp $ */#define IS_EXT_MODULE#ifdef HAVE_CONFIG_H#include "config.h"#endif#include "php.h"#include "SAPI.h"#include "php_ini.h"#include <stdlib.h>#include <errno.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#ifdef PHP_WIN32#include <windows.h>#include <winsock.h>#define O_RDONLY _O_RDONLY#include "win32/param.h"#else#include <sys/param.h>/* #include <sys/uio.h> */#endif#include "ext/standard/head.h"#include "safe_mode.h"#include "ext/standard/php_standard.h"#include "ext/standard/info.h"#include "php_zlib.h"#include "fopen_wrappers.h"#if HAVE_PWD_H#ifdef PHP_WIN32#include "win32/pwd.h"#else#include <pwd.h>#endif#endif#if defined(HAVE_UNISTD_H) && defined(PHP_WIN32)#undef HAVE_UNISTD_H#endif#ifdef COMPILE_DL_ZLIB#ifndef PUTS#define PUTS(a) php_printf("%s",a)#endif#ifndef PUTC#define PUTC(a) PUTS(a)#endif#ifndef PHPWRITE#define PHPWRITE(a,n) php_write((a),(n) TSRMLS_CC)#endif#endif#define OS_CODE 0x03 /* FIXME */#define GZIP_HEADER_LENGTH 10#define GZIP_FOOTER_LENGTH 8/* True globals, no need for thread safety */static int gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header *//* {{{ php_zlib_functions[] */function_entry php_zlib_functions[] = { PHP_FE(readgzfile, NULL) PHP_FALIAS(gzrewind, rewind, NULL) PHP_FALIAS(gzclose, fclose, NULL) PHP_FALIAS(gzeof, feof, NULL) PHP_FALIAS(gzgetc, fgetc, NULL) PHP_FALIAS(gzgets, fgets, NULL) PHP_FALIAS(gzgetss, fgetss, NULL) PHP_FALIAS(gzread, fread, NULL) PHP_FE(gzopen, NULL) PHP_FALIAS(gzpassthru, fpassthru, NULL) PHP_FALIAS(gzseek, fseek, NULL) PHP_FALIAS(gztell, ftell, NULL) PHP_FALIAS(gzwrite, fwrite, NULL) PHP_FALIAS(gzputs, fwrite, NULL) PHP_FE(gzfile, NULL) PHP_FE(gzcompress, NULL) PHP_FE(gzuncompress, NULL) PHP_FE(gzdeflate, NULL) PHP_FE(gzinflate, NULL) PHP_FE(gzencode, NULL) PHP_FE(ob_gzhandler, NULL) PHP_FE(zlib_get_coding_type, NULL) {NULL, NULL, NULL}};/* }}} *//* {{{ php_zlib_module_entry */zend_module_entry php_zlib_module_entry = { STANDARD_MODULE_HEADER, "zlib", php_zlib_functions, PHP_MINIT(zlib), PHP_MSHUTDOWN(zlib), PHP_RINIT(zlib), NULL, PHP_MINFO(zlib), "1.1", STANDARD_MODULE_PROPERTIES};/* }}} */ZEND_DECLARE_MODULE_GLOBALS(zlib)#ifdef COMPILE_DL_ZLIBZEND_GET_MODULE(php_zlib)#endif/* {{{ OnUpdate_zlib_output_compression */static PHP_INI_MH(OnUpdate_zlib_output_compression){ char *ini_value; if(new_value == NULL) return FAILURE; if(!strncasecmp(new_value, "off", sizeof("off"))) { new_value = "0"; new_value_length = sizeof("0"); } else if(!strncasecmp(new_value, "on", sizeof("on"))) { new_value = "1"; new_value_length = sizeof("1"); } ini_value = zend_ini_string("output_handler", sizeof("output_handler"), 0); if (ini_value != NULL && strlen(ini_value) != 0 && zend_atoi(new_value, new_value_length) != 0) { php_error_docref("ref.outcontrol" TSRMLS_CC, E_CORE_ERROR, "Cannot use both zlib.output_compression and output_handler together!!"); return FAILURE; } if (stage == PHP_INI_STAGE_RUNTIME && SG(headers_sent) && !SG(request_info).no_headers) { php_error_docref("ref.outcontrol" TSRMLS_CC, E_WARNING, "Cannot change zlib.output_compression - headers already sent"); return FAILURE; } OnUpdateInt(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC); return SUCCESS;}/* }}} *//* {{{ OnUpdate_zlib_output_compression_level */static PHP_INI_MH(OnUpdate_zlib_output_compression_level){ OnUpdateInt(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC); return SUCCESS;}/* }}} *//* {{{ OnUpdate_zlib_output_handler */static PHP_INI_MH(OnUpdate_zlib_output_handler){ if (stage == PHP_INI_STAGE_RUNTIME && SG(headers_sent) && !SG(request_info).no_headers) { php_error_docref("ref.outcontrol" TSRMLS_CC, E_WARNING, "Cannot change zlib.output_handler - headers already sent"); return FAILURE; } OnUpdateString(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC); return SUCCESS;}/* }}} */PHP_INI_BEGIN() STD_PHP_INI_BOOLEAN("zlib.output_compression", "0", PHP_INI_ALL, OnUpdate_zlib_output_compression, output_compression, zend_zlib_globals, zlib_globals) STD_PHP_INI_ENTRY("zlib.output_compression_level", "-1", PHP_INI_ALL, OnUpdate_zlib_output_compression_level, output_compression_level, zend_zlib_globals, zlib_globals) STD_PHP_INI_ENTRY("zlib.output_handler", "", PHP_INI_ALL, OnUpdate_zlib_output_handler, output_handler, zend_zlib_globals, zlib_globals)PHP_INI_END()#ifdef ZTS/* {{{ php_zlib_init_globals */static void php_zlib_init_globals(zend_zlib_globals *zlib_globals_p TSRMLS_DC){}/* }}} */#endif/* {{{ PHP_MINIT_FUNCTION */PHP_MINIT_FUNCTION(zlib){#ifdef ZTS ts_allocate_id(&zlib_globals_id, sizeof(zend_zlib_globals), (ts_allocate_ctor) php_zlib_init_globals, NULL);#endif php_register_url_stream_wrapper("compress.zlib", &php_stream_gzip_wrapper TSRMLS_CC); REGISTER_LONG_CONSTANT("FORCE_GZIP", CODING_GZIP, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("FORCE_DEFLATE", CODING_DEFLATE, CONST_CS | CONST_PERSISTENT); REGISTER_INI_ENTRIES(); return SUCCESS;}/* }}} *//* {{{ PHP_RINIT_FUNCTION */PHP_RINIT_FUNCTION(zlib){ uint chunk_size = ZLIBG(output_compression); ZLIBG(ob_gzhandler_status) = 0; ZLIBG(ob_gzip_coding) = 0; if (chunk_size) { if (chunk_size == 1) { chunk_size = 4096; /* use the default size */ ZLIBG(output_compression) = chunk_size; } php_enable_output_compression(chunk_size TSRMLS_CC); } return SUCCESS;}/* }}} *//* {{{ PHP_MSHUTDOWN_FUNCTION */PHP_MSHUTDOWN_FUNCTION(zlib){ php_unregister_url_stream_wrapper("zlib" TSRMLS_CC); UNREGISTER_INI_ENTRIES(); return SUCCESS;}/* }}} *//* {{{ PHP_MINFO_FUNCTION */PHP_MINFO_FUNCTION(zlib){ php_info_print_table_start(); php_info_print_table_row(2, "ZLib Support", "enabled"); php_info_print_table_row(2, "Compiled Version", ZLIB_VERSION ); php_info_print_table_row(2, "Linked Version", (char *)zlibVersion() ); php_info_print_table_end(); DISPLAY_INI_ENTRIES();}/* }}} *//* {{{ proto array gzfile(string filename [, int use_include_path]) Read und uncompress entire .gz-file into an array */PHP_FUNCTION(gzfile){ pval **filename, **arg2; char *slashed, buf[8192]; register int i=0; int use_include_path = 0; php_stream *stream; /* check args */ switch (ZEND_NUM_ARGS()) { case 1: if (zend_get_parameters_ex(1,&filename) == FAILURE) { WRONG_PARAM_COUNT; } break; case 2: if (zend_get_parameters_ex(2,&filename,&arg2) == FAILURE) { WRONG_PARAM_COUNT; } convert_to_long_ex(arg2); use_include_path = Z_LVAL_PP(arg2)?USE_PATH:0; break; default: WRONG_PARAM_COUNT; } convert_to_string_ex(filename); /* using a stream here is a bit more efficient (resource wise) than php_gzopen_wrapper */ stream = php_stream_gzopen(NULL, Z_STRVAL_PP(filename), "rb", use_include_path|ENFORCE_SAFE_MODE|REPORT_ERRORS, NULL, NULL STREAMS_CC TSRMLS_CC); if (stream == NULL) { /* Error reporting is already done by stream code */ RETURN_FALSE; } /* Initialize return array */ if (array_init(return_value) == FAILURE) { RETURN_FALSE; } /* Now loop through the file and do the magic quotes thing if needed */ memset(buf,0,sizeof(buf)); while(php_stream_gets(stream, buf, sizeof(buf)-1) != NULL) { if (PG(magic_quotes_runtime)) { int len; slashed = php_addslashes(buf,0,&len,0 TSRMLS_CC); /* 0 = don't free source string */ add_index_stringl(return_value, i++, slashed, len, 0); } else { add_index_string(return_value, i++, buf, 1); } } php_stream_close(stream);}/* }}} *//* {{{ proto int gzopen(string filename, string mode [, int use_include_path]) Open a .gz-file and return a .gz-file pointer */PHP_FUNCTION(gzopen){ pval **arg1, **arg2, **arg3; php_stream *stream; int use_include_path = 0; switch(ZEND_NUM_ARGS()) { case 2: if (zend_get_parameters_ex(2,&arg1,&arg2) == FAILURE) { WRONG_PARAM_COUNT; } break; case 3: if (zend_get_parameters_ex(3,&arg1,&arg2,&arg3) == FAILURE) { WRONG_PARAM_COUNT; } convert_to_long_ex(arg3); use_include_path = Z_LVAL_PP(arg3)?USE_PATH:0; break; default: WRONG_PARAM_COUNT; } convert_to_string_ex(arg1); convert_to_string_ex(arg2); stream = php_stream_gzopen(NULL, Z_STRVAL_PP(arg1), Z_STRVAL_PP(arg2), use_include_path|ENFORCE_SAFE_MODE|REPORT_ERRORS, NULL, NULL STREAMS_CC TSRMLS_CC); if (!stream) { RETURN_FALSE; } php_stream_to_zval(stream, return_value);} /* }}} *//* * Read a file and write the ouput to stdout *//* {{{ proto int readgzfile(string filename [, int use_include_path]) Output a .gz-file */PHP_FUNCTION(readgzfile){ pval **arg1, **arg2; php_stream * stream; int size; int use_include_path = 0; /* check args */ switch (ZEND_NUM_ARGS()) { case 1: if (zend_get_parameters_ex(1,&arg1) == FAILURE) { WRONG_PARAM_COUNT; } break; case 2: if (zend_get_parameters_ex(2,&arg1,&arg2) == FAILURE) { WRONG_PARAM_COUNT; } convert_to_long_ex(arg2); use_include_path = Z_LVAL_PP(arg2)?USE_PATH:0; break; default: WRONG_PARAM_COUNT; } convert_to_string_ex(arg1); stream = php_stream_gzopen(NULL, Z_STRVAL_PP(arg1), "rb", use_include_path|ENFORCE_SAFE_MODE, NULL, NULL STREAMS_CC TSRMLS_CC); if (!stream) { RETURN_FALSE; } size = php_stream_passthru(stream); php_stream_close(stream); RETURN_LONG(size);}/* }}} *//* {{{ proto string gzcompress(string data [, int level]) Gzip-compress a string */PHP_FUNCTION(gzcompress){ zval **data, **zlimit = NULL; int limit,status; unsigned long l2; char *s2; switch (ZEND_NUM_ARGS()) { case 1: if (zend_get_parameters_ex(1, &data) == FAILURE) WRONG_PARAM_COUNT; limit=-1; break; case 2: if (zend_get_parameters_ex(2, &data, &zlimit) == FAILURE) WRONG_PARAM_COUNT; convert_to_long_ex(zlimit); limit = Z_LVAL_PP(zlimit); if((limit<0)||(limit>9)) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "compression level(%d) must be within 0..9", limit); RETURN_FALSE; } break; default: WRONG_PARAM_COUNT; } convert_to_string_ex(data); l2 = Z_STRLEN_PP(data) + (Z_STRLEN_PP(data)/1000) + 15 + 1; /* room for \0 */ s2 = (char *) emalloc(l2); if(! s2) RETURN_FALSE; if(limit>=0) { status = compress2(s2,&l2,Z_STRVAL_PP(data), Z_STRLEN_PP(data),limit); } else { status = compress(s2,&l2,Z_STRVAL_PP(data), Z_STRLEN_PP(data)); } if (status==Z_OK) { s2 = erealloc(s2,l2 + 1); s2[l2] = '\0'; RETURN_STRINGL(s2, l2, 0); } else { efree(s2); php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", zError(status)); RETURN_FALSE; }}/* }}} *//* {{{ proto string gzuncompress(string data [, int length]) Unzip a gzip-compressed string */PHP_FUNCTION(gzuncompress){ zval **data, **zlimit = NULL; int status,factor=1,maxfactor=16; unsigned long plength=0,length; char *s1=NULL,*s2=NULL; switch (ZEND_NUM_ARGS()) { case 1: if (zend_get_parameters_ex(1, &data) == FAILURE) WRONG_PARAM_COUNT; length=0; break; case 2: if (zend_get_parameters_ex(2, &data, &zlimit) == FAILURE) WRONG_PARAM_COUNT; convert_to_long_ex(zlimit); if(Z_LVAL_PP(zlimit)<=0) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "length must be greater zero"); RETURN_FALSE; } plength = Z_LVAL_PP(zlimit); break; default: WRONG_PARAM_COUNT; } convert_to_string_ex(data); /* zlib::uncompress() wants to know the output data length if none was given as a parameter we try from input length * 2 up to input length * 2^8 doubling it whenever it wasn't big enough that should be eneugh for all real life cases */ do { length=plength?plength:Z_STRLEN_PP(data)*(1<<factor++); s2 = (char *) erealloc(s1,length); if(! s2) { if(s1) efree(s1); RETURN_FALSE; } status = uncompress(s2, &length ,Z_STRVAL_PP(data), Z_STRLEN_PP(data)); s1=s2; } while((status==Z_BUF_ERROR)&&(!plength)&&(factor<maxfactor)); if (status==Z_OK) { s2 = erealloc(s2, length + 1); /* space for \0 */ s2[ length ] = '\0'; RETURN_STRINGL(s2, length, 0); } else { efree(s2); php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", zError(status)); RETURN_FALSE; }}/* }}} *//* {{{ proto string gzdeflate(string data [, int level]) Gzip-compress a string */PHP_FUNCTION(gzdeflate){ zval **data, **zlimit = NULL; int level,status; z_stream stream; char *s2; switch (ZEND_NUM_ARGS()) { case 1: if (zend_get_parameters_ex(1, &data) == FAILURE) WRONG_PARAM_COUNT; level=Z_DEFAULT_COMPRESSION; break; case 2: if (zend_get_parameters_ex(2, &data, &zlimit) == FAILURE) WRONG_PARAM_COUNT; convert_to_long_ex(zlimit); level = Z_LVAL_PP(zlimit); if((level<0)||(level>9)) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "compression level(%d) must be within 0..9", level);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -