zlib.c 48 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635
  1. /*
  2. +----------------------------------------------------------------------+
  3. | PHP Version 7 |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 1997-2018 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@php.net> |
  18. | Jade Nicoletti <nicoletti@nns.ch> |
  19. | Michael Wallner <mike@php.net> |
  20. +----------------------------------------------------------------------+
  21. */
  22. #ifdef HAVE_CONFIG_H
  23. #include "config.h"
  24. #endif
  25. #include "php.h"
  26. #include "SAPI.h"
  27. #include "php_ini.h"
  28. #include "ext/standard/info.h"
  29. #include "ext/standard/file.h"
  30. #include "ext/standard/php_string.h"
  31. #include "php_zlib.h"
  32. /*
  33. * zlib include files can define the following preprocessor defines which rename
  34. * the corresponding PHP functions to gzopen64, gzseek64 and gztell64 and thereby
  35. * breaking some software, most notably PEAR's Archive_Tar, which halts execution
  36. * without error message on gzip compressed archivesa.
  37. *
  38. * This only seems to happen on 32bit systems with large file support.
  39. */
  40. #undef gzopen
  41. #undef gzseek
  42. #undef gztell
  43. int le_deflate;
  44. int le_inflate;
  45. ZEND_DECLARE_MODULE_GLOBALS(zlib);
  46. /* {{{ Memory management wrappers */
  47. static voidpf php_zlib_alloc(voidpf opaque, uInt items, uInt size)
  48. {
  49. return (voidpf)safe_emalloc(items, size, 0);
  50. }
  51. static void php_zlib_free(voidpf opaque, voidpf address)
  52. {
  53. efree((void*)address);
  54. }
  55. /* }}} */
  56. /* {{{ Incremental deflate/inflate resource destructors */
  57. void deflate_rsrc_dtor(zend_resource *res)
  58. {
  59. z_stream *ctx = zend_fetch_resource(res, NULL, le_deflate);
  60. deflateEnd(ctx);
  61. efree(ctx);
  62. }
  63. void inflate_rsrc_dtor(zend_resource *res)
  64. {
  65. z_stream *ctx = zend_fetch_resource(res, NULL, le_inflate);
  66. if (((php_zlib_context *) ctx)->inflateDict) {
  67. efree(((php_zlib_context *) ctx)->inflateDict);
  68. }
  69. inflateEnd(ctx);
  70. efree(ctx);
  71. }
  72. /* }}} */
  73. /* {{{ php_zlib_output_conflict_check() */
  74. static int php_zlib_output_conflict_check(const char *handler_name, size_t handler_name_len)
  75. {
  76. if (php_output_get_level() > 0) {
  77. if (php_output_handler_conflict(handler_name, handler_name_len, ZEND_STRL(PHP_ZLIB_OUTPUT_HANDLER_NAME))
  78. || php_output_handler_conflict(handler_name, handler_name_len, ZEND_STRL("ob_gzhandler"))
  79. || php_output_handler_conflict(handler_name, handler_name_len, ZEND_STRL("mb_output_handler"))
  80. || php_output_handler_conflict(handler_name, handler_name_len, ZEND_STRL("URL-Rewriter"))) {
  81. return FAILURE;
  82. }
  83. }
  84. return SUCCESS;
  85. }
  86. /* }}} */
  87. /* {{{ php_zlib_output_encoding() */
  88. static int php_zlib_output_encoding(void)
  89. {
  90. zval *enc;
  91. if (!ZLIBG(compression_coding)) {
  92. if ((Z_TYPE(PG(http_globals)[TRACK_VARS_SERVER]) == IS_ARRAY || zend_is_auto_global_str(ZEND_STRL("_SERVER"))) &&
  93. (enc = zend_hash_str_find(Z_ARRVAL(PG(http_globals)[TRACK_VARS_SERVER]), "HTTP_ACCEPT_ENCODING", sizeof("HTTP_ACCEPT_ENCODING") - 1))) {
  94. convert_to_string(enc);
  95. if (strstr(Z_STRVAL_P(enc), "gzip")) {
  96. ZLIBG(compression_coding) = PHP_ZLIB_ENCODING_GZIP;
  97. } else if (strstr(Z_STRVAL_P(enc), "deflate")) {
  98. ZLIBG(compression_coding) = PHP_ZLIB_ENCODING_DEFLATE;
  99. }
  100. }
  101. }
  102. return ZLIBG(compression_coding);
  103. }
  104. /* }}} */
  105. /* {{{ php_zlib_output_handler_ex() */
  106. static int php_zlib_output_handler_ex(php_zlib_context *ctx, php_output_context *output_context)
  107. {
  108. int flags = Z_SYNC_FLUSH;
  109. if (output_context->op & PHP_OUTPUT_HANDLER_START) {
  110. /* start up */
  111. if (Z_OK != deflateInit2(&ctx->Z, ZLIBG(output_compression_level), Z_DEFLATED, ZLIBG(compression_coding), MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY)) {
  112. return FAILURE;
  113. }
  114. }
  115. if (output_context->op & PHP_OUTPUT_HANDLER_CLEAN) {
  116. /* free buffers */
  117. deflateEnd(&ctx->Z);
  118. if (output_context->op & PHP_OUTPUT_HANDLER_FINAL) {
  119. /* discard */
  120. return SUCCESS;
  121. } else {
  122. /* restart */
  123. if (Z_OK != deflateInit2(&ctx->Z, ZLIBG(output_compression_level), Z_DEFLATED, ZLIBG(compression_coding), MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY)) {
  124. return FAILURE;
  125. }
  126. ctx->buffer.used = 0;
  127. }
  128. } else {
  129. if (output_context->in.used) {
  130. /* append input */
  131. if (ctx->buffer.free < output_context->in.used) {
  132. if (!(ctx->buffer.aptr = erealloc_recoverable(ctx->buffer.data, ctx->buffer.used + ctx->buffer.free + output_context->in.used))) {
  133. deflateEnd(&ctx->Z);
  134. return FAILURE;
  135. }
  136. ctx->buffer.data = ctx->buffer.aptr;
  137. ctx->buffer.free += output_context->in.used;
  138. }
  139. memcpy(ctx->buffer.data + ctx->buffer.used, output_context->in.data, output_context->in.used);
  140. ctx->buffer.free -= output_context->in.used;
  141. ctx->buffer.used += output_context->in.used;
  142. }
  143. output_context->out.size = PHP_ZLIB_BUFFER_SIZE_GUESS(output_context->in.used);
  144. output_context->out.data = emalloc(output_context->out.size);
  145. output_context->out.free = 1;
  146. output_context->out.used = 0;
  147. ctx->Z.avail_in = ctx->buffer.used;
  148. ctx->Z.next_in = (Bytef *) ctx->buffer.data;
  149. ctx->Z.avail_out = output_context->out.size;
  150. ctx->Z.next_out = (Bytef *) output_context->out.data;
  151. if (output_context->op & PHP_OUTPUT_HANDLER_FINAL) {
  152. flags = Z_FINISH;
  153. } else if (output_context->op & PHP_OUTPUT_HANDLER_FLUSH) {
  154. flags = Z_FULL_FLUSH;
  155. }
  156. switch (deflate(&ctx->Z, flags)) {
  157. case Z_OK:
  158. if (flags == Z_FINISH) {
  159. deflateEnd(&ctx->Z);
  160. return FAILURE;
  161. }
  162. case Z_STREAM_END:
  163. if (ctx->Z.avail_in) {
  164. memmove(ctx->buffer.data, ctx->buffer.data + ctx->buffer.used - ctx->Z.avail_in, ctx->Z.avail_in);
  165. }
  166. ctx->buffer.free += ctx->buffer.used - ctx->Z.avail_in;
  167. ctx->buffer.used = ctx->Z.avail_in;
  168. output_context->out.used = output_context->out.size - ctx->Z.avail_out;
  169. break;
  170. default:
  171. deflateEnd(&ctx->Z);
  172. return FAILURE;
  173. }
  174. if (output_context->op & PHP_OUTPUT_HANDLER_FINAL) {
  175. deflateEnd(&ctx->Z);
  176. }
  177. }
  178. return SUCCESS;
  179. }
  180. /* }}} */
  181. /* {{{ php_zlib_output_handler() */
  182. static int php_zlib_output_handler(void **handler_context, php_output_context *output_context)
  183. {
  184. php_zlib_context *ctx = *(php_zlib_context **) handler_context;
  185. if (!php_zlib_output_encoding()) {
  186. /* "Vary: Accept-Encoding" header sent along uncompressed content breaks caching in MSIE,
  187. so let's just send it with successfully compressed content or unless the complete
  188. buffer gets discarded, see http://bugs.php.net/40325;
  189. Test as follows:
  190. +Vary: $ HTTP_ACCEPT_ENCODING=gzip ./sapi/cgi/php <<<'<?php ob_start("ob_gzhandler"); echo "foo\n";'
  191. +Vary: $ HTTP_ACCEPT_ENCODING= ./sapi/cgi/php <<<'<?php ob_start("ob_gzhandler"); echo "foo\n";'
  192. -Vary: $ HTTP_ACCEPT_ENCODING=gzip ./sapi/cgi/php <<<'<?php ob_start("ob_gzhandler"); echo "foo\n"; ob_end_clean();'
  193. -Vary: $ HTTP_ACCEPT_ENCODING= ./sapi/cgi/php <<<'<?php ob_start("ob_gzhandler"); echo "foo\n"; ob_end_clean();'
  194. */
  195. if ((output_context->op & PHP_OUTPUT_HANDLER_START)
  196. && (output_context->op != (PHP_OUTPUT_HANDLER_START|PHP_OUTPUT_HANDLER_CLEAN|PHP_OUTPUT_HANDLER_FINAL))
  197. ) {
  198. sapi_add_header_ex(ZEND_STRL("Vary: Accept-Encoding"), 1, 0);
  199. }
  200. return FAILURE;
  201. }
  202. if (SUCCESS != php_zlib_output_handler_ex(ctx, output_context)) {
  203. return FAILURE;
  204. }
  205. if (!(output_context->op & PHP_OUTPUT_HANDLER_CLEAN)) {
  206. int flags;
  207. if (SUCCESS == php_output_handler_hook(PHP_OUTPUT_HANDLER_HOOK_GET_FLAGS, &flags)) {
  208. /* only run this once */
  209. if (!(flags & PHP_OUTPUT_HANDLER_STARTED)) {
  210. if (SG(headers_sent) || !ZLIBG(output_compression)) {
  211. deflateEnd(&ctx->Z);
  212. return FAILURE;
  213. }
  214. switch (ZLIBG(compression_coding)) {
  215. case PHP_ZLIB_ENCODING_GZIP:
  216. sapi_add_header_ex(ZEND_STRL("Content-Encoding: gzip"), 1, 1);
  217. break;
  218. case PHP_ZLIB_ENCODING_DEFLATE:
  219. sapi_add_header_ex(ZEND_STRL("Content-Encoding: deflate"), 1, 1);
  220. break;
  221. default:
  222. deflateEnd(&ctx->Z);
  223. return FAILURE;
  224. }
  225. sapi_add_header_ex(ZEND_STRL("Vary: Accept-Encoding"), 1, 0);
  226. php_output_handler_hook(PHP_OUTPUT_HANDLER_HOOK_IMMUTABLE, NULL);
  227. }
  228. }
  229. }
  230. return SUCCESS;
  231. }
  232. /* }}} */
  233. /* {{{ php_zlib_output_handler_context_init() */
  234. static php_zlib_context *php_zlib_output_handler_context_init(void)
  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. /* {{{ php_zlib_output_handler_context_dtor() */
  243. static void php_zlib_output_handler_context_dtor(void *opaq)
  244. {
  245. php_zlib_context *ctx = (php_zlib_context *) opaq;
  246. if (ctx) {
  247. if (ctx->buffer.data) {
  248. efree(ctx->buffer.data);
  249. }
  250. efree(ctx);
  251. }
  252. }
  253. /* }}} */
  254. /* {{{ php_zlib_output_handler_init() */
  255. static php_output_handler *php_zlib_output_handler_init(const char *handler_name, size_t handler_name_len, size_t chunk_size, int flags)
  256. {
  257. php_output_handler *h = NULL;
  258. if (!ZLIBG(output_compression)) {
  259. ZLIBG(output_compression) = chunk_size ? chunk_size : PHP_OUTPUT_HANDLER_DEFAULT_SIZE;
  260. }
  261. ZLIBG(handler_registered) = 1;
  262. if ((h = php_output_handler_create_internal(handler_name, handler_name_len, php_zlib_output_handler, chunk_size, flags))) {
  263. php_output_handler_set_context(h, php_zlib_output_handler_context_init(), php_zlib_output_handler_context_dtor);
  264. }
  265. return h;
  266. }
  267. /* }}} */
  268. /* {{{ php_zlib_output_compression_start() */
  269. static void php_zlib_output_compression_start(void)
  270. {
  271. zval zoh;
  272. php_output_handler *h;
  273. switch (ZLIBG(output_compression)) {
  274. case 0:
  275. break;
  276. case 1:
  277. ZLIBG(output_compression) = PHP_OUTPUT_HANDLER_DEFAULT_SIZE;
  278. /* break omitted intentionally */
  279. default:
  280. if ( php_zlib_output_encoding() &&
  281. (h = php_zlib_output_handler_init(ZEND_STRL(PHP_ZLIB_OUTPUT_HANDLER_NAME), ZLIBG(output_compression), PHP_OUTPUT_HANDLER_STDFLAGS)) &&
  282. (SUCCESS == php_output_handler_start(h))) {
  283. if (ZLIBG(output_handler) && *ZLIBG(output_handler)) {
  284. ZVAL_STRING(&zoh, ZLIBG(output_handler));
  285. php_output_start_user(&zoh, ZLIBG(output_compression), PHP_OUTPUT_HANDLER_STDFLAGS);
  286. zval_ptr_dtor(&zoh);
  287. }
  288. }
  289. break;
  290. }
  291. }
  292. /* }}} */
  293. /* {{{ php_zlib_encode() */
  294. static zend_string *php_zlib_encode(const char *in_buf, size_t in_len, int encoding, int level)
  295. {
  296. int status;
  297. z_stream Z;
  298. zend_string *out;
  299. memset(&Z, 0, sizeof(z_stream));
  300. Z.zalloc = php_zlib_alloc;
  301. Z.zfree = php_zlib_free;
  302. if (Z_OK == (status = deflateInit2(&Z, level, Z_DEFLATED, encoding, MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY))) {
  303. out = zend_string_alloc(PHP_ZLIB_BUFFER_SIZE_GUESS(in_len), 0);
  304. Z.next_in = (Bytef *) in_buf;
  305. Z.next_out = (Bytef *) ZSTR_VAL(out);
  306. Z.avail_in = in_len;
  307. Z.avail_out = ZSTR_LEN(out);
  308. status = deflate(&Z, Z_FINISH);
  309. deflateEnd(&Z);
  310. if (Z_STREAM_END == status) {
  311. /* size buffer down to actual length */
  312. out = zend_string_truncate(out, Z.total_out, 0);
  313. ZSTR_VAL(out)[ZSTR_LEN(out)] = '\0';
  314. return out;
  315. } else {
  316. zend_string_efree(out);
  317. }
  318. }
  319. php_error_docref(NULL, E_WARNING, "%s", zError(status));
  320. return NULL;
  321. }
  322. /* }}} */
  323. /* {{{ php_zlib_inflate_rounds() */
  324. static inline int php_zlib_inflate_rounds(z_stream *Z, size_t max, char **buf, size_t *len)
  325. {
  326. int status, round = 0;
  327. php_zlib_buffer buffer = {NULL, NULL, 0, 0, 0};
  328. *buf = NULL;
  329. *len = 0;
  330. buffer.size = (max && (max < Z->avail_in)) ? max : Z->avail_in;
  331. do {
  332. if ((max && (max <= buffer.used)) || !(buffer.aptr = erealloc_recoverable(buffer.data, buffer.size))) {
  333. status = Z_MEM_ERROR;
  334. } else {
  335. buffer.data = buffer.aptr;
  336. Z->avail_out = buffer.free = buffer.size - buffer.used;
  337. Z->next_out = (Bytef *) buffer.data + buffer.used;
  338. #if 0
  339. 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);
  340. #endif
  341. status = inflate(Z, Z_NO_FLUSH);
  342. buffer.used += buffer.free - Z->avail_out;
  343. buffer.free = Z->avail_out;
  344. #if 0
  345. 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);
  346. #endif
  347. buffer.size += (buffer.size >> 3) + 1;
  348. }
  349. } while ((Z_BUF_ERROR == status || (Z_OK == status && Z->avail_in)) && ++round < 100);
  350. if (status == Z_STREAM_END) {
  351. buffer.data = erealloc(buffer.data, buffer.used + 1);
  352. buffer.data[buffer.used] = '\0';
  353. *buf = buffer.data;
  354. *len = buffer.used;
  355. } else {
  356. if (buffer.data) {
  357. efree(buffer.data);
  358. }
  359. /* HACK: See zlib/examples/zpipe.c inf() function for explanation. */
  360. /* This works as long as this function is not used for streaming. Required to catch very short invalid data. */
  361. status = (status == Z_OK) ? Z_DATA_ERROR : status;
  362. }
  363. return status;
  364. }
  365. /* }}} */
  366. /* {{{ php_zlib_decode() */
  367. 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)
  368. {
  369. int status = Z_DATA_ERROR;
  370. z_stream Z;
  371. memset(&Z, 0, sizeof(z_stream));
  372. Z.zalloc = php_zlib_alloc;
  373. Z.zfree = php_zlib_free;
  374. if (in_len) {
  375. retry_raw_inflate:
  376. status = inflateInit2(&Z, encoding);
  377. if (Z_OK == status) {
  378. Z.next_in = (Bytef *) in_buf;
  379. Z.avail_in = in_len + 1; /* NOTE: data must be zero terminated */
  380. switch (status = php_zlib_inflate_rounds(&Z, max_len, out_buf, out_len)) {
  381. case Z_STREAM_END:
  382. inflateEnd(&Z);
  383. return SUCCESS;
  384. case Z_DATA_ERROR:
  385. /* raw deflated data? */
  386. if (PHP_ZLIB_ENCODING_ANY == encoding) {
  387. inflateEnd(&Z);
  388. encoding = PHP_ZLIB_ENCODING_RAW;
  389. goto retry_raw_inflate;
  390. }
  391. }
  392. inflateEnd(&Z);
  393. }
  394. }
  395. *out_buf = NULL;
  396. *out_len = 0;
  397. php_error_docref(NULL, E_WARNING, "%s", zError(status));
  398. return FAILURE;
  399. }
  400. /* }}} */
  401. /* {{{ php_zlib_cleanup_ob_gzhandler_mess() */
  402. static void php_zlib_cleanup_ob_gzhandler_mess(void)
  403. {
  404. if (ZLIBG(ob_gzhandler)) {
  405. deflateEnd(&(ZLIBG(ob_gzhandler)->Z));
  406. php_zlib_output_handler_context_dtor(ZLIBG(ob_gzhandler));
  407. ZLIBG(ob_gzhandler) = NULL;
  408. }
  409. }
  410. /* }}} */
  411. /* {{{ proto string ob_gzhandler(string data, int flags)
  412. Legacy hack */
  413. static PHP_FUNCTION(ob_gzhandler)
  414. {
  415. char *in_str;
  416. size_t in_len;
  417. zend_long flags = 0;
  418. php_output_context ctx = {0};
  419. int encoding, rv;
  420. /*
  421. * NOTE that the real ob_gzhandler is an alias to "zlib output compression".
  422. * This is a really bad hack, because
  423. * - we have to initialize a php_zlib_context on demand
  424. * - we have to clean it up in RSHUTDOWN
  425. * - OG(running) is not set or set to any other output handler
  426. * - we have to mess around with php_output_context */
  427. if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS(), "sl", &in_str, &in_len, &flags)) {
  428. RETURN_FALSE;
  429. }
  430. if (!(encoding = php_zlib_output_encoding())) {
  431. RETURN_FALSE;
  432. }
  433. if (flags & PHP_OUTPUT_HANDLER_START) {
  434. switch (encoding) {
  435. case PHP_ZLIB_ENCODING_GZIP:
  436. sapi_add_header_ex(ZEND_STRL("Content-Encoding: gzip"), 1, 1);
  437. break;
  438. case PHP_ZLIB_ENCODING_DEFLATE:
  439. sapi_add_header_ex(ZEND_STRL("Content-Encoding: deflate"), 1, 1);
  440. break;
  441. }
  442. sapi_add_header_ex(ZEND_STRL("Vary: Accept-Encoding"), 1, 0);
  443. }
  444. if (!ZLIBG(ob_gzhandler)) {
  445. ZLIBG(ob_gzhandler) = php_zlib_output_handler_context_init();
  446. }
  447. ctx.op = flags;
  448. ctx.in.data = in_str;
  449. ctx.in.used = in_len;
  450. rv = php_zlib_output_handler_ex(ZLIBG(ob_gzhandler), &ctx);
  451. if (SUCCESS != rv) {
  452. if (ctx.out.data && ctx.out.free) {
  453. efree(ctx.out.data);
  454. }
  455. php_zlib_cleanup_ob_gzhandler_mess();
  456. RETURN_FALSE;
  457. }
  458. if (ctx.out.data) {
  459. RETVAL_STRINGL(ctx.out.data, ctx.out.used);
  460. if (ctx.out.free) {
  461. efree(ctx.out.data);
  462. }
  463. } else {
  464. RETVAL_EMPTY_STRING();
  465. }
  466. }
  467. /* }}} */
  468. /* {{{ proto string zlib_get_coding_type(void)
  469. Returns the coding type used for output compression */
  470. static PHP_FUNCTION(zlib_get_coding_type)
  471. {
  472. if (zend_parse_parameters_none() == FAILURE) {
  473. return;
  474. }
  475. switch (ZLIBG(compression_coding)) {
  476. case PHP_ZLIB_ENCODING_GZIP:
  477. RETURN_STRINGL("gzip", sizeof("gzip") - 1);
  478. case PHP_ZLIB_ENCODING_DEFLATE:
  479. RETURN_STRINGL("deflate", sizeof("deflate") - 1);
  480. default:
  481. RETURN_FALSE;
  482. }
  483. }
  484. /* }}} */
  485. /* {{{ proto array gzfile(string filename [, int use_include_path])
  486. Read and uncompress entire .gz-file into an array */
  487. static PHP_FUNCTION(gzfile)
  488. {
  489. char *filename;
  490. size_t filename_len;
  491. int flags = REPORT_ERRORS;
  492. char buf[8192] = {0};
  493. register int i = 0;
  494. zend_long use_include_path = 0;
  495. php_stream *stream;
  496. if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS(), "p|l", &filename, &filename_len, &use_include_path)) {
  497. return;
  498. }
  499. if (use_include_path) {
  500. flags |= USE_PATH;
  501. }
  502. /* using a stream here is a bit more efficient (resource wise) than php_gzopen_wrapper */
  503. stream = php_stream_gzopen(NULL, filename, "rb", flags, NULL, NULL STREAMS_CC);
  504. if (!stream) {
  505. /* Error reporting is already done by stream code */
  506. RETURN_FALSE;
  507. }
  508. /* Initialize return array */
  509. array_init(return_value);
  510. /* Now loop through the file and do the magic quotes thing if needed */
  511. memset(buf, 0, sizeof(buf));
  512. while (php_stream_gets(stream, buf, sizeof(buf) - 1) != NULL) {
  513. add_index_string(return_value, i++, buf);
  514. }
  515. php_stream_close(stream);
  516. }
  517. /* }}} */
  518. /* {{{ proto resource gzopen(string filename, string mode [, int use_include_path])
  519. Open a .gz-file and return a .gz-file pointer */
  520. static PHP_FUNCTION(gzopen)
  521. {
  522. char *filename;
  523. char *mode;
  524. size_t filename_len, mode_len;
  525. int flags = REPORT_ERRORS;
  526. php_stream *stream;
  527. zend_long use_include_path = 0;
  528. if (zend_parse_parameters(ZEND_NUM_ARGS(), "ps|l", &filename, &filename_len, &mode, &mode_len, &use_include_path) == FAILURE) {
  529. return;
  530. }
  531. if (use_include_path) {
  532. flags |= USE_PATH;
  533. }
  534. stream = php_stream_gzopen(NULL, filename, mode, flags, NULL, NULL STREAMS_CC);
  535. if (!stream) {
  536. RETURN_FALSE;
  537. }
  538. php_stream_to_zval(stream, return_value);
  539. }
  540. /* }}} */
  541. /* {{{ proto int readgzfile(string filename [, int use_include_path])
  542. Output a .gz-file */
  543. static PHP_FUNCTION(readgzfile)
  544. {
  545. char *filename;
  546. size_t filename_len;
  547. int flags = REPORT_ERRORS;
  548. php_stream *stream;
  549. size_t size;
  550. zend_long use_include_path = 0;
  551. if (zend_parse_parameters(ZEND_NUM_ARGS(), "p|l", &filename, &filename_len, &use_include_path) == FAILURE) {
  552. return;
  553. }
  554. if (use_include_path) {
  555. flags |= USE_PATH;
  556. }
  557. stream = php_stream_gzopen(NULL, filename, "rb", flags, NULL, NULL STREAMS_CC);
  558. if (!stream) {
  559. RETURN_FALSE;
  560. }
  561. size = php_stream_passthru(stream);
  562. php_stream_close(stream);
  563. RETURN_LONG(size);
  564. }
  565. /* }}} */
  566. #define PHP_ZLIB_ENCODE_FUNC(name, default_encoding) \
  567. static PHP_FUNCTION(name) \
  568. { \
  569. zend_string *in, *out; \
  570. zend_long level = -1; \
  571. zend_long encoding = default_encoding; \
  572. if (default_encoding) { \
  573. if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS(), "S|ll", &in, &level, &encoding)) { \
  574. return; \
  575. } \
  576. } else { \
  577. if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS(), "Sl|l", &in, &encoding, &level)) { \
  578. return; \
  579. } \
  580. } \
  581. if (level < -1 || level > 9) { \
  582. php_error_docref(NULL, E_WARNING, "compression level (" ZEND_LONG_FMT ") must be within -1..9", level); \
  583. RETURN_FALSE; \
  584. } \
  585. switch (encoding) { \
  586. case PHP_ZLIB_ENCODING_RAW: \
  587. case PHP_ZLIB_ENCODING_GZIP: \
  588. case PHP_ZLIB_ENCODING_DEFLATE: \
  589. break; \
  590. default: \
  591. php_error_docref(NULL, E_WARNING, "encoding mode must be either ZLIB_ENCODING_RAW, ZLIB_ENCODING_GZIP or ZLIB_ENCODING_DEFLATE"); \
  592. RETURN_FALSE; \
  593. } \
  594. if ((out = php_zlib_encode(ZSTR_VAL(in), ZSTR_LEN(in), encoding, level)) == NULL) { \
  595. RETURN_FALSE; \
  596. } \
  597. RETURN_STR(out); \
  598. }
  599. #define PHP_ZLIB_DECODE_FUNC(name, encoding) \
  600. static PHP_FUNCTION(name) \
  601. { \
  602. char *in_buf, *out_buf; \
  603. size_t in_len; \
  604. size_t out_len; \
  605. zend_long max_len = 0; \
  606. if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS(), "s|l", &in_buf, &in_len, &max_len)) { \
  607. return; \
  608. } \
  609. if (max_len < 0) { \
  610. php_error_docref(NULL, E_WARNING, "length (" ZEND_LONG_FMT ") must be greater or equal zero", max_len); \
  611. RETURN_FALSE; \
  612. } \
  613. if (SUCCESS != php_zlib_decode(in_buf, in_len, &out_buf, &out_len, encoding, max_len)) { \
  614. RETURN_FALSE; \
  615. } \
  616. RETVAL_STRINGL(out_buf, out_len); \
  617. efree(out_buf); \
  618. }
  619. /* {{{ proto binary zlib_encode(binary data, int encoding[, int level = -1])
  620. Compress data with the specified encoding */
  621. PHP_ZLIB_ENCODE_FUNC(zlib_encode, 0);
  622. /* }}} */
  623. /* {{{ proto binary zlib_decode(binary data[, int max_decoded_len])
  624. Uncompress any raw/gzip/zlib encoded data */
  625. PHP_ZLIB_DECODE_FUNC(zlib_decode, PHP_ZLIB_ENCODING_ANY);
  626. /* }}} */
  627. /* NOTE: The naming of these userland functions was quite unlucky */
  628. /* {{{ proto binary gzdeflate(binary data[, int level = -1[, int encoding = ZLIB_ENCODING_RAW])
  629. Encode data with the raw deflate encoding */
  630. PHP_ZLIB_ENCODE_FUNC(gzdeflate, PHP_ZLIB_ENCODING_RAW);
  631. /* }}} */
  632. /* {{{ proto binary gzencode(binary data[, int level = -1[, int encoding = ZLIB_ENCODING_GZIP])
  633. Encode data with the gzip encoding */
  634. PHP_ZLIB_ENCODE_FUNC(gzencode, PHP_ZLIB_ENCODING_GZIP);
  635. /* }}} */
  636. /* {{{ proto binary gzcompress(binary data[, int level = -1[, int encoding = ZLIB_ENCODING_DEFLATE])
  637. Encode data with the zlib encoding */
  638. PHP_ZLIB_ENCODE_FUNC(gzcompress, PHP_ZLIB_ENCODING_DEFLATE);
  639. /* }}} */
  640. /* {{{ proto binary gzinflate(binary data[, int max_decoded_len])
  641. Decode raw deflate encoded data */
  642. PHP_ZLIB_DECODE_FUNC(gzinflate, PHP_ZLIB_ENCODING_RAW);
  643. /* }}} */
  644. /* {{{ proto binary gzdecode(binary data[, int max_decoded_len])
  645. Decode gzip encoded data */
  646. PHP_ZLIB_DECODE_FUNC(gzdecode, PHP_ZLIB_ENCODING_GZIP);
  647. /* }}} */
  648. /* {{{ proto binary gzuncompress(binary data[, int max_decoded_len])
  649. Decode zlib encoded data */
  650. PHP_ZLIB_DECODE_FUNC(gzuncompress, PHP_ZLIB_ENCODING_DEFLATE);
  651. /* }}} */
  652. static zend_bool zlib_create_dictionary_string(HashTable *options, char **dict, size_t *dictlen) {
  653. zval *option_buffer;
  654. if (options && (option_buffer = zend_hash_str_find(options, ZEND_STRL("dictionary"))) != NULL) {
  655. ZVAL_DEREF(option_buffer);
  656. switch (Z_TYPE_P(option_buffer)) {
  657. case IS_STRING: {
  658. zend_string *str = Z_STR_P(option_buffer);
  659. *dict = emalloc(ZSTR_LEN(str));
  660. memcpy(*dict, ZSTR_VAL(str), ZSTR_LEN(str));
  661. *dictlen = ZSTR_LEN(str);
  662. } break;
  663. case IS_ARRAY: {
  664. HashTable *dictionary = Z_ARR_P(option_buffer);
  665. if (zend_hash_num_elements(dictionary) > 0) {
  666. char *dictptr;
  667. zval *cur;
  668. zend_string **strings = emalloc(sizeof(zend_string *) * zend_hash_num_elements(dictionary));
  669. zend_string **end, **ptr = strings - 1;
  670. ZEND_HASH_FOREACH_VAL(dictionary, cur) {
  671. size_t i;
  672. *++ptr = zval_get_string(cur);
  673. if (!*ptr || ZSTR_LEN(*ptr) == 0) {
  674. if (*ptr) {
  675. efree(*ptr);
  676. }
  677. while (--ptr >= strings) {
  678. efree(ptr);
  679. }
  680. efree(strings);
  681. php_error_docref(NULL, E_WARNING, "dictionary entries must be non-empty strings");
  682. return 0;
  683. }
  684. for (i = 0; i < ZSTR_LEN(*ptr); i++) {
  685. if (ZSTR_VAL(*ptr)[i] == 0) {
  686. do {
  687. efree(ptr);
  688. } while (--ptr >= strings);
  689. efree(strings);
  690. php_error_docref(NULL, E_WARNING, "dictionary entries must not contain a NULL-byte");
  691. return 0;
  692. }
  693. }
  694. *dictlen += ZSTR_LEN(*ptr) + 1;
  695. } ZEND_HASH_FOREACH_END();
  696. dictptr = *dict = emalloc(*dictlen);
  697. ptr = strings;
  698. end = strings + zend_hash_num_elements(dictionary);
  699. do {
  700. memcpy(dictptr, ZSTR_VAL(*ptr), ZSTR_LEN(*ptr));
  701. dictptr += ZSTR_LEN(*ptr);
  702. *dictptr++ = 0;
  703. zend_string_release_ex(*ptr, 0);
  704. } while (++ptr != end);
  705. efree(strings);
  706. }
  707. } break;
  708. default:
  709. php_error_docref(NULL, E_WARNING, "dictionary must be of type zero-terminated string or array, got %s", zend_get_type_by_const(Z_TYPE_P(option_buffer)));
  710. return 0;
  711. }
  712. }
  713. return 1;
  714. }
  715. /* {{{ proto resource inflate_init(int encoding)
  716. Initialize an incremental inflate context with the specified encoding */
  717. PHP_FUNCTION(inflate_init)
  718. {
  719. z_stream *ctx;
  720. zend_long encoding, window = 15;
  721. char *dict = NULL;
  722. size_t dictlen = 0;
  723. HashTable *options = NULL;
  724. zval *option_buffer;
  725. if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS(), "l|H", &encoding, &options)) {
  726. return;
  727. }
  728. if (options && (option_buffer = zend_hash_str_find(options, ZEND_STRL("window"))) != NULL) {
  729. window = zval_get_long(option_buffer);
  730. }
  731. if (window < 8 || window > 15) {
  732. php_error_docref(NULL, E_WARNING, "zlib window size (lograithm) (" ZEND_LONG_FMT ") must be within 8..15", window);
  733. RETURN_FALSE;
  734. }
  735. if (!zlib_create_dictionary_string(options, &dict, &dictlen)) {
  736. RETURN_FALSE;
  737. }
  738. switch (encoding) {
  739. case PHP_ZLIB_ENCODING_RAW:
  740. case PHP_ZLIB_ENCODING_GZIP:
  741. case PHP_ZLIB_ENCODING_DEFLATE:
  742. break;
  743. default:
  744. php_error_docref(NULL, E_WARNING, "encoding mode must be ZLIB_ENCODING_RAW, ZLIB_ENCODING_GZIP or ZLIB_ENCODING_DEFLATE");
  745. RETURN_FALSE;
  746. }
  747. ctx = ecalloc(1, sizeof(php_zlib_context));
  748. ctx->zalloc = php_zlib_alloc;
  749. ctx->zfree = php_zlib_free;
  750. ((php_zlib_context *) ctx)->inflateDict = dict;
  751. ((php_zlib_context *) ctx)->inflateDictlen = dictlen;
  752. ((php_zlib_context *) ctx)->status = Z_OK;
  753. if (encoding < 0) {
  754. encoding += 15 - window;
  755. } else {
  756. encoding -= 15 - window;
  757. }
  758. if (Z_OK == inflateInit2(ctx, encoding)) {
  759. if (encoding == PHP_ZLIB_ENCODING_RAW && dictlen > 0) {
  760. php_zlib_context *php_ctx = (php_zlib_context *) ctx;
  761. switch (inflateSetDictionary(ctx, (Bytef *) php_ctx->inflateDict, php_ctx->inflateDictlen)) {
  762. case Z_OK:
  763. efree(php_ctx->inflateDict);
  764. php_ctx->inflateDict = NULL;
  765. break;
  766. case Z_DATA_ERROR:
  767. php_error_docref(NULL, E_WARNING, "dictionary does not match expected dictionary (incorrect adler32 hash)");
  768. efree(php_ctx->inflateDict);
  769. php_ctx->inflateDict = NULL;
  770. RETURN_FALSE;
  771. EMPTY_SWITCH_DEFAULT_CASE()
  772. }
  773. }
  774. RETURN_RES(zend_register_resource(ctx, le_inflate));
  775. } else {
  776. efree(ctx);
  777. php_error_docref(NULL, E_WARNING, "failed allocating zlib.inflate context");
  778. RETURN_FALSE;
  779. }
  780. }
  781. /* }}} */
  782. /* {{{ proto string inflate_add(resource context, string encoded_data[, int flush_mode = ZLIB_SYNC_FLUSH])
  783. Incrementally inflate encoded data in the specified context */
  784. PHP_FUNCTION(inflate_add)
  785. {
  786. zend_string *out;
  787. char *in_buf;
  788. size_t in_len, buffer_used = 0, CHUNK_SIZE = 8192;
  789. zval *res;
  790. z_stream *ctx;
  791. zend_long flush_type = Z_SYNC_FLUSH;
  792. int status;
  793. if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS(), "rs|l", &res, &in_buf, &in_len, &flush_type)) {
  794. return;
  795. }
  796. if (!(ctx = zend_fetch_resource_ex(res, NULL, le_inflate))) {
  797. php_error_docref(NULL, E_WARNING, "Invalid zlib.inflate resource");
  798. RETURN_FALSE;
  799. }
  800. switch (flush_type) {
  801. case Z_NO_FLUSH:
  802. case Z_PARTIAL_FLUSH:
  803. case Z_SYNC_FLUSH:
  804. case Z_FULL_FLUSH:
  805. case Z_BLOCK:
  806. case Z_FINISH:
  807. break;
  808. default:
  809. php_error_docref(NULL, E_WARNING,
  810. "flush mode must be ZLIB_NO_FLUSH, ZLIB_PARTIAL_FLUSH, ZLIB_SYNC_FLUSH, ZLIB_FULL_FLUSH, ZLIB_BLOCK or ZLIB_FINISH");
  811. RETURN_FALSE;
  812. }
  813. /* Lazy-resetting the zlib stream so ctx->total_in remains available until the next inflate_add() call. */
  814. if (((php_zlib_context *) ctx)->status == Z_STREAM_END)
  815. {
  816. ((php_zlib_context *) ctx)->status = Z_OK;
  817. inflateReset(ctx);
  818. }
  819. if (in_len <= 0 && flush_type != Z_FINISH) {
  820. RETURN_EMPTY_STRING();
  821. }
  822. out = zend_string_alloc((in_len > CHUNK_SIZE) ? in_len : CHUNK_SIZE, 0);
  823. ctx->next_in = (Bytef *) in_buf;
  824. ctx->next_out = (Bytef *) ZSTR_VAL(out);
  825. ctx->avail_in = in_len;
  826. ctx->avail_out = ZSTR_LEN(out);
  827. do {
  828. status = inflate(ctx, flush_type);
  829. buffer_used = ZSTR_LEN(out) - ctx->avail_out;
  830. ((php_zlib_context *) ctx)->status = status; /* Save status for exposing to userspace */
  831. switch (status) {
  832. case Z_OK:
  833. if (ctx->avail_out == 0) {
  834. /* more output buffer space needed; realloc and try again */
  835. out = zend_string_realloc(out, ZSTR_LEN(out) + CHUNK_SIZE, 0);
  836. ctx->avail_out = CHUNK_SIZE;
  837. ctx->next_out = (Bytef *) ZSTR_VAL(out) + buffer_used;
  838. break;
  839. } else {
  840. goto complete;
  841. }
  842. case Z_STREAM_END:
  843. goto complete;
  844. case Z_BUF_ERROR:
  845. if (flush_type == Z_FINISH && ctx->avail_out == 0) {
  846. /* more output buffer space needed; realloc and try again */
  847. out = zend_string_realloc(out, ZSTR_LEN(out) + CHUNK_SIZE, 0);
  848. ctx->avail_out = CHUNK_SIZE;
  849. ctx->next_out = (Bytef *) ZSTR_VAL(out) + buffer_used;
  850. break;
  851. } else {
  852. /* No more input data; we're finished */
  853. goto complete;
  854. }
  855. case Z_NEED_DICT:
  856. if (((php_zlib_context *) ctx)->inflateDict) {
  857. php_zlib_context *php_ctx = (php_zlib_context *) ctx;
  858. switch (inflateSetDictionary(ctx, (Bytef *) php_ctx->inflateDict, php_ctx->inflateDictlen)) {
  859. case Z_OK:
  860. efree(php_ctx->inflateDict);
  861. php_ctx->inflateDict = NULL;
  862. break;
  863. case Z_DATA_ERROR:
  864. php_error_docref(NULL, E_WARNING, "dictionary does not match expected dictionary (incorrect adler32 hash)");
  865. efree(php_ctx->inflateDict);
  866. zend_string_release_ex(out, 0);
  867. php_ctx->inflateDict = NULL;
  868. RETURN_FALSE;
  869. EMPTY_SWITCH_DEFAULT_CASE()
  870. }
  871. break;
  872. } else {
  873. php_error_docref(NULL, E_WARNING, "inflating this data requires a preset dictionary, please specify it in the options array of inflate_init()");
  874. RETURN_FALSE;
  875. }
  876. default:
  877. zend_string_release_ex(out, 0);
  878. php_error_docref(NULL, E_WARNING, "%s", zError(status));
  879. RETURN_FALSE;
  880. }
  881. } while (1);
  882. complete: {
  883. out = zend_string_realloc(out, buffer_used, 0);
  884. ZSTR_VAL(out)[buffer_used] = 0;
  885. RETURN_STR(out);
  886. }
  887. }
  888. /* }}} */
  889. /* {{{ proto bool inflate_get_status(resource context)
  890. Get decompression status, usually returns either ZLIB_OK or ZLIB_STREAM_END. */
  891. PHP_FUNCTION(inflate_get_status)
  892. {
  893. zval *res;
  894. z_stream *ctx;
  895. if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS(), "r", &res))
  896. {
  897. RETURN_NULL();
  898. }
  899. if (!(ctx = zend_fetch_resource_ex(res, NULL, le_inflate))) {
  900. php_error_docref(NULL, E_WARNING, "Invalid zlib.inflate resource");
  901. RETURN_FALSE;
  902. }
  903. RETURN_LONG(((php_zlib_context *) ctx)->status);
  904. }
  905. /* }}} */
  906. /* {{{ proto bool inflate_get_read_len(resource context)
  907. Get number of bytes read so far. */
  908. PHP_FUNCTION(inflate_get_read_len)
  909. {
  910. zval *res;
  911. z_stream *ctx;
  912. if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS(), "r", &res))
  913. {
  914. RETURN_NULL();
  915. }
  916. if (!(ctx = zend_fetch_resource_ex(res, NULL, le_inflate))) {
  917. php_error_docref(NULL, E_WARNING, "Invalid zlib.inflate resource");
  918. RETURN_FALSE;
  919. }
  920. RETURN_LONG(ctx->total_in);
  921. }
  922. /* }}} */
  923. /* {{{ proto resource deflate_init(int encoding[, array options])
  924. Initialize an incremental deflate context using the specified encoding */
  925. PHP_FUNCTION(deflate_init)
  926. {
  927. z_stream *ctx;
  928. zend_long encoding, level = -1, memory = 8, window = 15, strategy = Z_DEFAULT_STRATEGY;
  929. char *dict = NULL;
  930. size_t dictlen = 0;
  931. HashTable *options = NULL;
  932. zval *option_buffer;
  933. if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS(), "l|H", &encoding, &options)) {
  934. return;
  935. }
  936. if (options && (option_buffer = zend_hash_str_find(options, ZEND_STRL("level"))) != NULL) {
  937. level = zval_get_long(option_buffer);
  938. }
  939. if (level < -1 || level > 9) {
  940. php_error_docref(NULL, E_WARNING, "compression level (" ZEND_LONG_FMT ") must be within -1..9", level);
  941. RETURN_FALSE;
  942. }
  943. if (options && (option_buffer = zend_hash_str_find(options, ZEND_STRL("memory"))) != NULL) {
  944. memory = zval_get_long(option_buffer);
  945. }
  946. if (memory < 1 || memory > 9) {
  947. php_error_docref(NULL, E_WARNING, "compression memory level (" ZEND_LONG_FMT ") must be within 1..9", memory);
  948. RETURN_FALSE;
  949. }
  950. if (options && (option_buffer = zend_hash_str_find(options, ZEND_STRL("window"))) != NULL) {
  951. window = zval_get_long(option_buffer);
  952. }
  953. if (window < 8 || window > 15) {
  954. php_error_docref(NULL, E_WARNING, "zlib window size (logarithm) (" ZEND_LONG_FMT ") must be within 8..15", window);
  955. RETURN_FALSE;
  956. }
  957. if (options && (option_buffer = zend_hash_str_find(options, ZEND_STRL("strategy"))) != NULL) {
  958. strategy = zval_get_long(option_buffer);
  959. }
  960. switch (strategy) {
  961. case Z_FILTERED:
  962. case Z_HUFFMAN_ONLY:
  963. case Z_RLE:
  964. case Z_FIXED:
  965. case Z_DEFAULT_STRATEGY:
  966. break;
  967. default:
  968. php_error_docref(NULL, E_WARNING, "strategy must be one of ZLIB_FILTERED, ZLIB_HUFFMAN_ONLY, ZLIB_RLE, ZLIB_FIXED or ZLIB_DEFAULT_STRATEGY");
  969. RETURN_FALSE;
  970. }
  971. if (!zlib_create_dictionary_string(options, &dict, &dictlen)) {
  972. RETURN_FALSE;
  973. }
  974. switch (encoding) {
  975. case PHP_ZLIB_ENCODING_RAW:
  976. case PHP_ZLIB_ENCODING_GZIP:
  977. case PHP_ZLIB_ENCODING_DEFLATE:
  978. break;
  979. default:
  980. php_error_docref(NULL, E_WARNING,
  981. "encoding mode must be ZLIB_ENCODING_RAW, ZLIB_ENCODING_GZIP or ZLIB_ENCODING_DEFLATE");
  982. RETURN_FALSE;
  983. }
  984. ctx = ecalloc(1, sizeof(php_zlib_context));
  985. ctx->zalloc = php_zlib_alloc;
  986. ctx->zfree = php_zlib_free;
  987. if (encoding < 0) {
  988. encoding += 15 - window;
  989. } else {
  990. encoding -= 15 - window;
  991. }
  992. if (Z_OK == deflateInit2(ctx, level, Z_DEFLATED, encoding, memory, strategy)) {
  993. if (dict) {
  994. int success = deflateSetDictionary(ctx, (Bytef *) dict, dictlen);
  995. ZEND_ASSERT(success == Z_OK);
  996. efree(dict);
  997. }
  998. RETURN_RES(zend_register_resource(ctx, le_deflate));
  999. } else {
  1000. efree(ctx);
  1001. php_error_docref(NULL, E_WARNING, "failed allocating zlib.deflate context");
  1002. RETURN_FALSE;
  1003. }
  1004. }
  1005. /* }}} */
  1006. /* {{{ proto string deflate_add(resource context, string data[, int flush_mode = ZLIB_SYNC_FLUSH])
  1007. Incrementally deflate data in the specified context */
  1008. PHP_FUNCTION(deflate_add)
  1009. {
  1010. zend_string *out;
  1011. char *in_buf;
  1012. size_t in_len, out_size, buffer_used;
  1013. zval *res;
  1014. z_stream *ctx;
  1015. zend_long flush_type = Z_SYNC_FLUSH;
  1016. int status;
  1017. if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS(), "rs|l", &res, &in_buf, &in_len, &flush_type)) {
  1018. return;
  1019. }
  1020. if (!(ctx = zend_fetch_resource_ex(res, NULL, le_deflate))) {
  1021. php_error_docref(NULL, E_WARNING, "Invalid deflate resource");
  1022. RETURN_FALSE;
  1023. }
  1024. switch (flush_type) {
  1025. case Z_BLOCK:
  1026. #if ZLIB_VERNUM < 0x1240L
  1027. php_error_docref(NULL, E_WARNING,
  1028. "zlib >= 1.2.4 required for BLOCK deflate; current version: %s", ZLIB_VERSION);
  1029. RETURN_FALSE;
  1030. #endif
  1031. case Z_NO_FLUSH:
  1032. case Z_PARTIAL_FLUSH:
  1033. case Z_SYNC_FLUSH:
  1034. case Z_FULL_FLUSH:
  1035. case Z_FINISH:
  1036. break;
  1037. default:
  1038. php_error_docref(NULL, E_WARNING,
  1039. "flush mode must be ZLIB_NO_FLUSH, ZLIB_PARTIAL_FLUSH, ZLIB_SYNC_FLUSH, ZLIB_FULL_FLUSH, ZLIB_BLOCK or ZLIB_FINISH");
  1040. RETURN_FALSE;
  1041. }
  1042. if (in_len <= 0 && flush_type != Z_FINISH) {
  1043. RETURN_EMPTY_STRING();
  1044. }
  1045. out_size = PHP_ZLIB_BUFFER_SIZE_GUESS(in_len);
  1046. out_size = (out_size < 64) ? 64 : out_size;
  1047. out = zend_string_alloc(out_size, 0);
  1048. ctx->next_in = (Bytef *) in_buf;
  1049. ctx->next_out = (Bytef *) ZSTR_VAL(out);
  1050. ctx->avail_in = in_len;
  1051. ctx->avail_out = ZSTR_LEN(out);
  1052. buffer_used = 0;
  1053. do {
  1054. if (ctx->avail_out == 0) {
  1055. /* more output buffer space needed; realloc and try again */
  1056. /* adding 64 more bytes solved every issue I have seen */
  1057. out = zend_string_realloc(out, ZSTR_LEN(out) + 64, 0);
  1058. ctx->avail_out = 64;
  1059. ctx->next_out = (Bytef *) ZSTR_VAL(out) + buffer_used;
  1060. }
  1061. status = deflate(ctx, flush_type);
  1062. buffer_used = ZSTR_LEN(out) - ctx->avail_out;
  1063. } while (status == Z_OK && ctx->avail_out == 0);
  1064. switch (status) {
  1065. case Z_OK:
  1066. ZSTR_LEN(out) = (char *) ctx->next_out - ZSTR_VAL(out);
  1067. ZSTR_VAL(out)[ZSTR_LEN(out)] = 0;
  1068. RETURN_STR(out);
  1069. break;
  1070. case Z_STREAM_END:
  1071. ZSTR_LEN(out) = (char *) ctx->next_out - ZSTR_VAL(out);
  1072. ZSTR_VAL(out)[ZSTR_LEN(out)] = 0;
  1073. deflateReset(ctx);
  1074. RETURN_STR(out);
  1075. break;
  1076. default:
  1077. zend_string_release_ex(out, 0);
  1078. php_error_docref(NULL, E_WARNING, "zlib error (%s)", zError(status));
  1079. RETURN_FALSE;
  1080. }
  1081. }
  1082. /* }}} */
  1083. #ifdef COMPILE_DL_ZLIB
  1084. #ifdef ZTS
  1085. ZEND_TSRMLS_CACHE_DEFINE()
  1086. #endif
  1087. ZEND_GET_MODULE(php_zlib)
  1088. #endif
  1089. /* {{{ arginfo */
  1090. ZEND_BEGIN_ARG_INFO_EX(arginfo_ob_gzhandler, 0, 0, 2)
  1091. ZEND_ARG_INFO(0, data)
  1092. ZEND_ARG_INFO(0, flags)
  1093. ZEND_END_ARG_INFO()
  1094. ZEND_BEGIN_ARG_INFO(arginfo_zlib_get_coding_type, 0)
  1095. ZEND_END_ARG_INFO()
  1096. ZEND_BEGIN_ARG_INFO_EX(arginfo_gzfile, 0, 0, 1)
  1097. ZEND_ARG_INFO(0, filename)
  1098. ZEND_ARG_INFO(0, use_include_path)
  1099. ZEND_END_ARG_INFO()
  1100. ZEND_BEGIN_ARG_INFO_EX(arginfo_gzopen, 0, 0, 2)
  1101. ZEND_ARG_INFO(0, filename)
  1102. ZEND_ARG_INFO(0, mode)
  1103. ZEND_ARG_INFO(0, use_include_path)
  1104. ZEND_END_ARG_INFO()
  1105. ZEND_BEGIN_ARG_INFO_EX(arginfo_readgzfile, 0, 0, 1)
  1106. ZEND_ARG_INFO(0, filename)
  1107. ZEND_ARG_INFO(0, use_include_path)
  1108. ZEND_END_ARG_INFO()
  1109. ZEND_BEGIN_ARG_INFO_EX(arginfo_zlib_encode, 0, 0, 2)
  1110. ZEND_ARG_INFO(0, data)
  1111. ZEND_ARG_INFO(0, encoding)
  1112. ZEND_ARG_INFO(0, level)
  1113. ZEND_END_ARG_INFO()
  1114. ZEND_BEGIN_ARG_INFO_EX(arginfo_zlib_decode, 0, 0, 1)
  1115. ZEND_ARG_INFO(0, data)
  1116. ZEND_ARG_INFO(0, max_decoded_len)
  1117. ZEND_END_ARG_INFO()
  1118. ZEND_BEGIN_ARG_INFO_EX(arginfo_gzdeflate, 0, 0, 1)
  1119. ZEND_ARG_INFO(0, data)
  1120. ZEND_ARG_INFO(0, level)
  1121. ZEND_ARG_INFO(0, encoding)
  1122. ZEND_END_ARG_INFO()
  1123. ZEND_BEGIN_ARG_INFO_EX(arginfo_gzencode, 0, 0, 1)
  1124. ZEND_ARG_INFO(0, data)
  1125. ZEND_ARG_INFO(0, level)
  1126. ZEND_ARG_INFO(0, encoding)
  1127. ZEND_END_ARG_INFO()
  1128. ZEND_BEGIN_ARG_INFO_EX(arginfo_gzcompress, 0, 0, 1)
  1129. ZEND_ARG_INFO(0, data)
  1130. ZEND_ARG_INFO(0, level)
  1131. ZEND_ARG_INFO(0, encoding)
  1132. ZEND_END_ARG_INFO()
  1133. ZEND_BEGIN_ARG_INFO_EX(arginfo_gzinflate, 0, 0, 1)
  1134. ZEND_ARG_INFO(0, data)
  1135. ZEND_ARG_INFO(0, max_decoded_len)
  1136. ZEND_END_ARG_INFO()
  1137. ZEND_BEGIN_ARG_INFO_EX(arginfo_gzdecode, 0, 0, 1)
  1138. ZEND_ARG_INFO(0, data)
  1139. ZEND_ARG_INFO(0, max_decoded_len)
  1140. ZEND_END_ARG_INFO()
  1141. ZEND_BEGIN_ARG_INFO_EX(arginfo_gzuncompress, 0, 0, 1)
  1142. ZEND_ARG_INFO(0, data)
  1143. ZEND_ARG_INFO(0, max_decoded_len)
  1144. ZEND_END_ARG_INFO()
  1145. ZEND_BEGIN_ARG_INFO_EX(arginfo_gzputs, 0, 0, 2)
  1146. ZEND_ARG_INFO(0, fp)
  1147. ZEND_ARG_INFO(0, str)
  1148. ZEND_ARG_INFO(0, length)
  1149. ZEND_END_ARG_INFO()
  1150. ZEND_BEGIN_ARG_INFO(arginfo_gzpassthru, 0)
  1151. ZEND_ARG_INFO(0, fp)
  1152. ZEND_END_ARG_INFO()
  1153. ZEND_BEGIN_ARG_INFO_EX(arginfo_gzseek, 0, 0, 2)
  1154. ZEND_ARG_INFO(0, fp)
  1155. ZEND_ARG_INFO(0, offset)
  1156. ZEND_ARG_INFO(0, whence)
  1157. ZEND_END_ARG_INFO()
  1158. ZEND_BEGIN_ARG_INFO(arginfo_gzread, 0)
  1159. ZEND_ARG_INFO(0, fp)
  1160. ZEND_ARG_INFO(0, length)
  1161. ZEND_END_ARG_INFO()
  1162. ZEND_BEGIN_ARG_INFO_EX(arginfo_gzgetss, 0, 0, 1)
  1163. ZEND_ARG_INFO(0, fp)
  1164. ZEND_ARG_INFO(0, length)
  1165. ZEND_ARG_INFO(0, allowable_tags)
  1166. ZEND_END_ARG_INFO()
  1167. ZEND_BEGIN_ARG_INFO_EX(arginfo_gzgets, 0, 0, 1)
  1168. ZEND_ARG_INFO(0, fp)
  1169. ZEND_ARG_INFO(0, length)
  1170. ZEND_END_ARG_INFO()
  1171. ZEND_BEGIN_ARG_INFO_EX(arginfo_deflate_init, 0, 0, 1)
  1172. ZEND_ARG_INFO(0, encoding)
  1173. ZEND_ARG_INFO(0, level)
  1174. ZEND_END_ARG_INFO()
  1175. ZEND_BEGIN_ARG_INFO_EX(arginfo_deflate_add, 0, 0, 2)
  1176. ZEND_ARG_INFO(0, resource)
  1177. ZEND_ARG_INFO(0, add)
  1178. ZEND_ARG_INFO(0, flush_behavior)
  1179. ZEND_END_ARG_INFO()
  1180. ZEND_BEGIN_ARG_INFO_EX(arginfo_inflate_init, 0, 0, 1)
  1181. ZEND_ARG_INFO(0, encoding)
  1182. ZEND_ARG_INFO(0, options)
  1183. ZEND_END_ARG_INFO()
  1184. ZEND_BEGIN_ARG_INFO_EX(arginfo_inflate_add, 0, 0, 2)
  1185. ZEND_ARG_INFO(0, context)
  1186. ZEND_ARG_INFO(0, encoded_data)
  1187. ZEND_ARG_INFO(0, flush_mode)
  1188. ZEND_END_ARG_INFO()
  1189. ZEND_BEGIN_ARG_INFO_EX(arginfo_inflate_get_status, 0, 0, 1)
  1190. ZEND_ARG_INFO(0, resource)
  1191. ZEND_END_ARG_INFO()
  1192. ZEND_BEGIN_ARG_INFO_EX(arginfo_inflate_get_read_len, 0, 0, 1)
  1193. ZEND_ARG_INFO(0, resource)
  1194. ZEND_END_ARG_INFO()
  1195. /* }}} */
  1196. /* {{{ php_zlib_functions[] */
  1197. static const zend_function_entry php_zlib_functions[] = {
  1198. PHP_FE(readgzfile, arginfo_readgzfile)
  1199. PHP_FALIAS(gzrewind, rewind, arginfo_gzpassthru)
  1200. PHP_FALIAS(gzclose, fclose, arginfo_gzpassthru)
  1201. PHP_FALIAS(gzeof, feof, arginfo_gzpassthru)
  1202. PHP_FALIAS(gzgetc, fgetc, arginfo_gzpassthru)
  1203. PHP_FALIAS(gzgets, fgets, arginfo_gzgets)
  1204. PHP_DEP_FALIAS(gzgetss, fgetss, arginfo_gzgetss)
  1205. PHP_FALIAS(gzread, fread, arginfo_gzread)
  1206. PHP_FE(gzopen, arginfo_gzopen)
  1207. PHP_FALIAS(gzpassthru, fpassthru, arginfo_gzpassthru)
  1208. PHP_FALIAS(gzseek, fseek, arginfo_gzseek)
  1209. PHP_FALIAS(gztell, ftell, arginfo_gzpassthru)
  1210. PHP_FALIAS(gzwrite, fwrite, arginfo_gzputs)
  1211. PHP_FALIAS(gzputs, fwrite, arginfo_gzputs)
  1212. PHP_FE(gzfile, arginfo_gzfile)
  1213. PHP_FE(gzcompress, arginfo_gzcompress)
  1214. PHP_FE(gzuncompress, arginfo_gzuncompress)
  1215. PHP_FE(gzdeflate, arginfo_gzdeflate)
  1216. PHP_FE(gzinflate, arginfo_gzinflate)
  1217. PHP_FE(gzencode, arginfo_gzencode)
  1218. PHP_FE(gzdecode, arginfo_gzdecode)
  1219. PHP_FE(zlib_encode, arginfo_zlib_encode)
  1220. PHP_FE(zlib_decode, arginfo_zlib_decode)
  1221. PHP_FE(zlib_get_coding_type, arginfo_zlib_get_coding_type)
  1222. PHP_FE(deflate_init, arginfo_deflate_init)
  1223. PHP_FE(deflate_add, arginfo_deflate_add)
  1224. PHP_FE(inflate_init, arginfo_inflate_init)
  1225. PHP_FE(inflate_add, arginfo_inflate_add)
  1226. PHP_FE(inflate_get_status, arginfo_inflate_get_status)
  1227. PHP_FE(inflate_get_read_len, arginfo_inflate_get_read_len)
  1228. PHP_FE(ob_gzhandler, arginfo_ob_gzhandler)
  1229. PHP_FE_END
  1230. };
  1231. /* }}} */
  1232. /* {{{ OnUpdate_zlib_output_compression */
  1233. static PHP_INI_MH(OnUpdate_zlib_output_compression)
  1234. {
  1235. int int_value;
  1236. char *ini_value;
  1237. zend_long *p;
  1238. #ifndef ZTS
  1239. char *base = (char *) mh_arg2;
  1240. #else
  1241. char *base;
  1242. base = (char *) ts_resource(*((int *) mh_arg2));
  1243. #endif
  1244. if (new_value == NULL) {
  1245. return FAILURE;
  1246. }
  1247. if (!strncasecmp(ZSTR_VAL(new_value), "off", sizeof("off"))) {
  1248. int_value = 0;
  1249. } else if (!strncasecmp(ZSTR_VAL(new_value), "on", sizeof("on"))) {
  1250. int_value = 1;
  1251. } else {
  1252. int_value = zend_atoi(ZSTR_VAL(new_value), ZSTR_LEN(new_value));
  1253. }
  1254. ini_value = zend_ini_string("output_handler", sizeof("output_handler"), 0);
  1255. if (ini_value && *ini_value && int_value) {
  1256. php_error_docref("ref.outcontrol", E_CORE_ERROR, "Cannot use both zlib.output_compression and output_handler together!!");
  1257. return FAILURE;
  1258. }
  1259. if (stage == PHP_INI_STAGE_RUNTIME) {
  1260. int status = php_output_get_status();
  1261. if (status & PHP_OUTPUT_SENT) {
  1262. php_error_docref("ref.outcontrol", E_WARNING, "Cannot change zlib.output_compression - headers already sent");
  1263. return FAILURE;
  1264. }
  1265. }
  1266. p = (zend_long *) (base+(size_t) mh_arg1);
  1267. *p = int_value;
  1268. ZLIBG(output_compression) = ZLIBG(output_compression_default);
  1269. if (stage == PHP_INI_STAGE_RUNTIME && int_value) {
  1270. if (!php_output_handler_started(ZEND_STRL(PHP_ZLIB_OUTPUT_HANDLER_NAME))) {
  1271. php_zlib_output_compression_start();
  1272. }
  1273. }
  1274. return SUCCESS;
  1275. }
  1276. /* }}} */
  1277. /* {{{ OnUpdate_zlib_output_handler */
  1278. static PHP_INI_MH(OnUpdate_zlib_output_handler)
  1279. {
  1280. if (stage == PHP_INI_STAGE_RUNTIME && (php_output_get_status() & PHP_OUTPUT_SENT)) {
  1281. php_error_docref("ref.outcontrol", E_WARNING, "Cannot change zlib.output_handler - headers already sent");
  1282. return FAILURE;
  1283. }
  1284. return OnUpdateString(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage);
  1285. }
  1286. /* }}} */
  1287. /* {{{ INI */
  1288. PHP_INI_BEGIN()
  1289. STD_PHP_INI_BOOLEAN("zlib.output_compression", "0", PHP_INI_ALL, OnUpdate_zlib_output_compression, output_compression_default, zend_zlib_globals, zlib_globals)
  1290. STD_PHP_INI_ENTRY("zlib.output_compression_level", "-1", PHP_INI_ALL, OnUpdateLong, output_compression_level, zend_zlib_globals, zlib_globals)
  1291. STD_PHP_INI_ENTRY("zlib.output_handler", "", PHP_INI_ALL, OnUpdate_zlib_output_handler, output_handler, zend_zlib_globals, zlib_globals)
  1292. PHP_INI_END()
  1293. /* }}} */
  1294. /* {{{ PHP_MINIT_FUNCTION */
  1295. static PHP_MINIT_FUNCTION(zlib)
  1296. {
  1297. php_register_url_stream_wrapper("compress.zlib", &php_stream_gzip_wrapper);
  1298. php_stream_filter_register_factory("zlib.*", &php_zlib_filter_factory);
  1299. php_output_handler_alias_register(ZEND_STRL("ob_gzhandler"), php_zlib_output_handler_init);
  1300. php_output_handler_conflict_register(ZEND_STRL("ob_gzhandler"), php_zlib_output_conflict_check);
  1301. php_output_handler_conflict_register(ZEND_STRL(PHP_ZLIB_OUTPUT_HANDLER_NAME), php_zlib_output_conflict_check);
  1302. le_deflate = zend_register_list_destructors_ex(deflate_rsrc_dtor, NULL, "zlib.deflate", module_number);
  1303. le_inflate = zend_register_list_destructors_ex(inflate_rsrc_dtor, NULL, "zlib.inflate", module_number);
  1304. REGISTER_LONG_CONSTANT("FORCE_GZIP", PHP_ZLIB_ENCODING_GZIP, CONST_CS|CONST_PERSISTENT);
  1305. REGISTER_LONG_CONSTANT("FORCE_DEFLATE", PHP_ZLIB_ENCODING_DEFLATE, CONST_CS|CONST_PERSISTENT);
  1306. REGISTER_LONG_CONSTANT("ZLIB_ENCODING_RAW", PHP_ZLIB_ENCODING_RAW, CONST_CS|CONST_PERSISTENT);
  1307. REGISTER_LONG_CONSTANT("ZLIB_ENCODING_GZIP", PHP_ZLIB_ENCODING_GZIP, CONST_CS|CONST_PERSISTENT);
  1308. REGISTER_LONG_CONSTANT("ZLIB_ENCODING_DEFLATE", PHP_ZLIB_ENCODING_DEFLATE, CONST_CS|CONST_PERSISTENT);
  1309. REGISTER_LONG_CONSTANT("ZLIB_NO_FLUSH", Z_NO_FLUSH, CONST_CS|CONST_PERSISTENT);
  1310. REGISTER_LONG_CONSTANT("ZLIB_PARTIAL_FLUSH", Z_PARTIAL_FLUSH, CONST_CS|CONST_PERSISTENT);
  1311. REGISTER_LONG_CONSTANT("ZLIB_SYNC_FLUSH", Z_SYNC_FLUSH, CONST_CS|CONST_PERSISTENT);
  1312. REGISTER_LONG_CONSTANT("ZLIB_FULL_FLUSH", Z_FULL_FLUSH, CONST_CS|CONST_PERSISTENT);
  1313. REGISTER_LONG_CONSTANT("ZLIB_BLOCK", Z_BLOCK, CONST_CS|CONST_PERSISTENT);
  1314. REGISTER_LONG_CONSTANT("ZLIB_FINISH", Z_FINISH, CONST_CS|CONST_PERSISTENT);
  1315. REGISTER_LONG_CONSTANT("ZLIB_FILTERED", Z_FILTERED, CONST_CS|CONST_PERSISTENT);
  1316. REGISTER_LONG_CONSTANT("ZLIB_HUFFMAN_ONLY", Z_HUFFMAN_ONLY, CONST_CS|CONST_PERSISTENT);
  1317. REGISTER_LONG_CONSTANT("ZLIB_RLE", Z_RLE, CONST_CS|CONST_PERSISTENT);
  1318. REGISTER_LONG_CONSTANT("ZLIB_FIXED", Z_FIXED, CONST_CS|CONST_PERSISTENT);
  1319. REGISTER_LONG_CONSTANT("ZLIB_DEFAULT_STRATEGY", Z_DEFAULT_STRATEGY, CONST_CS|CONST_PERSISTENT);
  1320. REGISTER_STRING_CONSTANT("ZLIB_VERSION", ZLIB_VERSION, CONST_CS|CONST_PERSISTENT);
  1321. REGISTER_LONG_CONSTANT("ZLIB_VERNUM", ZLIB_VERNUM, CONST_CS|CONST_PERSISTENT);
  1322. REGISTER_LONG_CONSTANT("ZLIB_OK", Z_OK, CONST_CS|CONST_PERSISTENT);
  1323. REGISTER_LONG_CONSTANT("ZLIB_STREAM_END", Z_STREAM_END, CONST_CS|CONST_PERSISTENT);
  1324. REGISTER_LONG_CONSTANT("ZLIB_NEED_DICT", Z_NEED_DICT, CONST_CS|CONST_PERSISTENT);
  1325. REGISTER_LONG_CONSTANT("ZLIB_ERRNO", Z_ERRNO, CONST_CS|CONST_PERSISTENT);
  1326. REGISTER_LONG_CONSTANT("ZLIB_STREAM_ERROR", Z_STREAM_ERROR, CONST_CS|CONST_PERSISTENT);
  1327. REGISTER_LONG_CONSTANT("ZLIB_DATA_ERROR", Z_DATA_ERROR, CONST_CS|CONST_PERSISTENT);
  1328. REGISTER_LONG_CONSTANT("ZLIB_MEM_ERROR", Z_MEM_ERROR, CONST_CS|CONST_PERSISTENT);
  1329. REGISTER_LONG_CONSTANT("ZLIB_BUF_ERROR", Z_BUF_ERROR, CONST_CS|CONST_PERSISTENT);
  1330. REGISTER_LONG_CONSTANT("ZLIB_VERSION_ERROR", Z_VERSION_ERROR, CONST_CS|CONST_PERSISTENT);
  1331. REGISTER_INI_ENTRIES();
  1332. return SUCCESS;
  1333. }
  1334. /* }}} */
  1335. /* {{{ PHP_MSHUTDOWN_FUNCTION */
  1336. static PHP_MSHUTDOWN_FUNCTION(zlib)
  1337. {
  1338. php_unregister_url_stream_wrapper("zlib");
  1339. php_stream_filter_unregister_factory("zlib.*");
  1340. UNREGISTER_INI_ENTRIES();
  1341. return SUCCESS;
  1342. }
  1343. /* }}} */
  1344. /* {{{ PHP_RINIT_FUNCTION */
  1345. static PHP_RINIT_FUNCTION(zlib)
  1346. {
  1347. ZLIBG(compression_coding) = 0;
  1348. if (!ZLIBG(handler_registered)) {
  1349. ZLIBG(output_compression) = ZLIBG(output_compression_default);
  1350. php_zlib_output_compression_start();
  1351. }
  1352. return SUCCESS;
  1353. }
  1354. /* }}} */
  1355. /* {{{ PHP_RSHUTDOWN_FUNCTION */
  1356. static PHP_RSHUTDOWN_FUNCTION(zlib)
  1357. {
  1358. php_zlib_cleanup_ob_gzhandler_mess();
  1359. ZLIBG(handler_registered) = 0;
  1360. return SUCCESS;
  1361. }
  1362. /* }}} */
  1363. /* {{{ PHP_MINFO_FUNCTION */
  1364. static PHP_MINFO_FUNCTION(zlib)
  1365. {
  1366. php_info_print_table_start();
  1367. php_info_print_table_header(2, "ZLib Support", "enabled");
  1368. php_info_print_table_row(2, "Stream Wrapper", "compress.zlib://");
  1369. php_info_print_table_row(2, "Stream Filter", "zlib.inflate, zlib.deflate");
  1370. php_info_print_table_row(2, "Compiled Version", ZLIB_VERSION);
  1371. php_info_print_table_row(2, "Linked Version", (char *) zlibVersion());
  1372. php_info_print_table_end();
  1373. DISPLAY_INI_ENTRIES();
  1374. }
  1375. /* }}} */
  1376. /* {{{ ZEND_MODULE_GLOBALS_CTOR */
  1377. static PHP_GINIT_FUNCTION(zlib)
  1378. {
  1379. #if defined(COMPILE_DL_ZLIB) && defined(ZTS)
  1380. ZEND_TSRMLS_CACHE_UPDATE();
  1381. #endif
  1382. zlib_globals->ob_gzhandler = NULL;
  1383. zlib_globals->handler_registered = 0;
  1384. }
  1385. /* }}} */
  1386. /* {{{ php_zlib_module_entry */
  1387. zend_module_entry php_zlib_module_entry = {
  1388. STANDARD_MODULE_HEADER,
  1389. "zlib",
  1390. php_zlib_functions,
  1391. PHP_MINIT(zlib),
  1392. PHP_MSHUTDOWN(zlib),
  1393. PHP_RINIT(zlib),
  1394. PHP_RSHUTDOWN(zlib),
  1395. PHP_MINFO(zlib),
  1396. PHP_ZLIB_VERSION,
  1397. PHP_MODULE_GLOBALS(zlib),
  1398. PHP_GINIT(zlib),
  1399. NULL,
  1400. NULL,
  1401. STANDARD_MODULE_PROPERTIES_EX
  1402. };
  1403. /* }}} */
  1404. /*
  1405. * Local variables:
  1406. * tab-width: 4
  1407. * c-basic-offset: 4
  1408. * End:
  1409. * vim600: sw=4 ts=4 fdm=marker
  1410. * vim<600: sw=4 ts=4
  1411. */