move to PHP-7.4 as current GA
[m6w6/ext-http] / src / php_http_encoding_zlib.c
1 /*
2 +--------------------------------------------------------------------+
3 | PECL :: http |
4 +--------------------------------------------------------------------+
5 | Redistribution and use in source and binary forms, with or without |
6 | modification, are permitted provided that the conditions mentioned |
7 | in the accompanying LICENSE file are met. |
8 +--------------------------------------------------------------------+
9 | Copyright (c) 2004-2014, Michael Wallner <mike@php.net> |
10 +--------------------------------------------------------------------+
11 */
12
13 #include "php_http_api.h"
14
15 #define PHP_HTTP_INFLATE_ROUNDS 100
16 #define PHP_HTTP_INFLATE_BUFFER_SIZE 0x1000
17
18 #define PHP_HTTP_DEFLATE_BUFFER_SIZE 0x8000
19
20 #define PHP_HTTP_DEFLATE_BUFFER_SIZE_GUESS(S) \
21 (((size_t) ((double) S * (double) 1.015)) + 10 + 8 + 4 + 1)
22
23 #define PHP_HTTP_INFLATE_BUFFER_SIZE_GUESS(S) \
24 (((S) + 1) << 3)
25 #define PHP_HTTP_INFLATE_BUFFER_SIZE_ALIGN(S) \
26 ((S) += (S) >> (3))
27
28 #define PHP_HTTP_INFLATE_FLUSH_FLAG(flags) \
29 PHP_HTTP_ENCODING_STREAM_FLUSH_FLAG((flags), Z_FULL_FLUSH, Z_SYNC_FLUSH, Z_NO_FLUSH)
30 #define PHP_HTTP_DEFLATE_FLUSH_FLAG(flags) \
31 PHP_HTTP_ENCODING_STREAM_FLUSH_FLAG((flags), Z_FULL_FLUSH, Z_SYNC_FLUSH, Z_NO_FLUSH)
32
33 #define PHP_HTTP_WINDOW_BITS_ZLIB 0x0000000f
34 #define PHP_HTTP_WINDOW_BITS_GZIP 0x0000001f
35 #define PHP_HTTP_WINDOW_BITS_ANY 0x0000002f
36 #define PHP_HTTP_WINDOW_BITS_RAW -0x000000f
37
38 #define PHP_HTTP_DEFLATE_LEVEL_SET(flags, level) \
39 switch (flags & 0xf) \
40 { \
41 default: \
42 if ((flags & 0xf) < 10) { \
43 level = flags & 0xf; \
44 break; \
45 } \
46 case PHP_HTTP_DEFLATE_LEVEL_DEF: \
47 level = Z_DEFAULT_COMPRESSION; \
48 break; \
49 }
50
51 #define PHP_HTTP_DEFLATE_WBITS_SET(flags, wbits) \
52 switch (flags & 0xf0) \
53 { \
54 case PHP_HTTP_DEFLATE_TYPE_GZIP: \
55 wbits = PHP_HTTP_WINDOW_BITS_GZIP; \
56 break; \
57 case PHP_HTTP_DEFLATE_TYPE_RAW: \
58 wbits = PHP_HTTP_WINDOW_BITS_RAW; \
59 break; \
60 default: \
61 wbits = PHP_HTTP_WINDOW_BITS_ZLIB; \
62 break; \
63 }
64
65 #define PHP_HTTP_INFLATE_WBITS_SET(flags, wbits) \
66 if (flags & PHP_HTTP_INFLATE_TYPE_RAW) { \
67 wbits = PHP_HTTP_WINDOW_BITS_RAW; \
68 } else { \
69 wbits = PHP_HTTP_WINDOW_BITS_ANY; \
70 }
71
72 #define PHP_HTTP_DEFLATE_STRATEGY_SET(flags, strategy) \
73 switch (flags & 0xf00) \
74 { \
75 case PHP_HTTP_DEFLATE_STRATEGY_FILT: \
76 strategy = Z_FILTERED; \
77 break; \
78 case PHP_HTTP_DEFLATE_STRATEGY_HUFF: \
79 strategy = Z_HUFFMAN_ONLY; \
80 break; \
81 case PHP_HTTP_DEFLATE_STRATEGY_RLE: \
82 strategy = Z_RLE; \
83 break; \
84 case PHP_HTTP_DEFLATE_STRATEGY_FIXED: \
85 strategy = Z_FIXED; \
86 break; \
87 default: \
88 strategy = Z_DEFAULT_STRATEGY; \
89 break; \
90 }
91
92 ZEND_RESULT_CODE php_http_encoding_deflate(int flags, const char *data, size_t data_len, char **encoded, size_t *encoded_len)
93 {
94 int status, level, wbits, strategy;
95 z_stream Z;
96
97 PHP_HTTP_DEFLATE_LEVEL_SET(flags, level);
98 PHP_HTTP_DEFLATE_WBITS_SET(flags, wbits);
99 PHP_HTTP_DEFLATE_STRATEGY_SET(flags, strategy);
100
101 memset(&Z, 0, sizeof(z_stream));
102 *encoded = NULL;
103 *encoded_len = 0;
104
105 status = deflateInit2(&Z, level, Z_DEFLATED, wbits, MAX_MEM_LEVEL, strategy);
106 if (EXPECTED(Z_OK == status)) {
107 *encoded_len = PHP_HTTP_DEFLATE_BUFFER_SIZE_GUESS(data_len);
108 *encoded = emalloc(*encoded_len);
109
110 Z.next_in = (Bytef *) data;
111 Z.next_out = (Bytef *) *encoded;
112 Z.avail_in = data_len;
113 Z.avail_out = *encoded_len;
114
115 status = deflate(&Z, Z_FINISH);
116 deflateEnd(&Z);
117
118 if (EXPECTED(Z_STREAM_END == status)) {
119 /* size buffer down to actual length */
120 *encoded = erealloc(*encoded, Z.total_out + 1);
121 (*encoded)[*encoded_len = Z.total_out] = '\0';
122 return SUCCESS;
123 } else {
124 PTR_SET(*encoded, NULL);
125 *encoded_len = 0;
126 }
127 }
128
129 php_error_docref(NULL, E_WARNING, "Could not deflate data: %s", zError(status));
130 return FAILURE;
131 }
132
133 static php_http_encoding_stream_t *deflate_init(php_http_encoding_stream_t *s)
134 {
135 int status, level, wbits, strategy, p = (s->flags & PHP_HTTP_ENCODING_STREAM_PERSISTENT);
136 z_streamp ctx = pecalloc(1, sizeof(z_stream), p);
137
138 PHP_HTTP_DEFLATE_LEVEL_SET(s->flags, level);
139 PHP_HTTP_DEFLATE_WBITS_SET(s->flags, wbits);
140 PHP_HTTP_DEFLATE_STRATEGY_SET(s->flags, strategy);
141
142 if (EXPECTED(Z_OK == (status = deflateInit2(ctx, level, Z_DEFLATED, wbits, MAX_MEM_LEVEL, strategy)))) {
143 if (EXPECTED(ctx->opaque = php_http_buffer_init_ex(NULL, PHP_HTTP_DEFLATE_BUFFER_SIZE, p ? PHP_HTTP_BUFFER_INIT_PERSISTENT : 0))) {
144 s->ctx = ctx;
145 return s;
146 }
147 deflateEnd(ctx);
148 status = Z_MEM_ERROR;
149 }
150 pefree(ctx, p);
151 php_error_docref(NULL, E_WARNING, "Failed to initialize deflate encoding stream: %s", zError(status));
152 return NULL;
153 }
154
155 static php_http_encoding_stream_t *deflate_copy(php_http_encoding_stream_t *from, php_http_encoding_stream_t *to)
156 {
157 int status, p = to->flags & PHP_HTTP_ENCODING_STREAM_PERSISTENT;
158 z_streamp from_ctx = from->ctx, to_ctx = pecalloc(1, sizeof(*to_ctx), p);
159
160 if (Z_OK == (status = deflateCopy(to_ctx, from_ctx))) {
161 if ((to_ctx->opaque = php_http_buffer_init_ex(NULL, PHP_HTTP_DEFLATE_BUFFER_SIZE, p ? PHP_HTTP_BUFFER_INIT_PERSISTENT : 0))) {
162 php_http_buffer_append(to_ctx->opaque, PHP_HTTP_BUFFER(from_ctx->opaque)->data, PHP_HTTP_BUFFER(from_ctx->opaque)->used);
163 to->ctx = to_ctx;
164 return to;
165 }
166 deflateEnd(to_ctx);
167 status = Z_MEM_ERROR;
168 }
169 php_error_docref(NULL, E_WARNING, "Failed to copy deflate encoding stream: %s", zError(status));
170 return NULL;
171 }
172
173 static ZEND_RESULT_CODE deflate_update(php_http_encoding_stream_t *s, const char *data, size_t data_len, char **encoded, size_t *encoded_len)
174 {
175 int status;
176 z_streamp ctx = s->ctx;
177
178 /* append input to our buffer */
179 php_http_buffer_append(PHP_HTTP_BUFFER(ctx->opaque), data, data_len);
180
181 ctx->next_in = (Bytef *) PHP_HTTP_BUFFER(ctx->opaque)->data;
182 ctx->avail_in = PHP_HTTP_BUFFER(ctx->opaque)->used;
183
184 /* deflate */
185 *encoded_len = PHP_HTTP_DEFLATE_BUFFER_SIZE_GUESS(data_len);
186 *encoded = emalloc(*encoded_len);
187 ctx->avail_out = *encoded_len;
188 ctx->next_out = (Bytef *) *encoded;
189
190 switch (status = deflate(ctx, PHP_HTTP_DEFLATE_FLUSH_FLAG(s->flags))) {
191 case Z_OK:
192 case Z_STREAM_END:
193 /* cut processed chunk off the buffer */
194 if (ctx->avail_in) {
195 php_http_buffer_cut(PHP_HTTP_BUFFER(ctx->opaque), 0, PHP_HTTP_BUFFER(ctx->opaque)->used - ctx->avail_in);
196 } else {
197 php_http_buffer_reset(PHP_HTTP_BUFFER(ctx->opaque));
198 }
199
200 /* size buffer down to actual size */
201 *encoded_len -= ctx->avail_out;
202 *encoded = erealloc(*encoded, *encoded_len + 1);
203 (*encoded)[*encoded_len] = '\0';
204 return SUCCESS;
205 }
206
207 PTR_SET(*encoded, NULL);
208 *encoded_len = 0;
209 php_error_docref(NULL, E_WARNING, "Failed to update deflate stream: %s", zError(status));
210 return FAILURE;
211 }
212
213 static ZEND_RESULT_CODE deflate_flush(php_http_encoding_stream_t *s, char **encoded, size_t *encoded_len)
214 {
215 int status;
216 z_streamp ctx = s->ctx;
217
218 *encoded_len = PHP_HTTP_DEFLATE_BUFFER_SIZE;
219 *encoded = emalloc(*encoded_len);
220
221 ctx->avail_in = 0;
222 ctx->next_in = NULL;
223 ctx->avail_out = *encoded_len;
224 ctx->next_out = (Bytef *) *encoded;
225
226 status = deflate(ctx, Z_FULL_FLUSH);
227 if (EXPECTED(Z_OK == status || Z_STREAM_END == status)) {
228 *encoded_len = PHP_HTTP_DEFLATE_BUFFER_SIZE - ctx->avail_out;
229 *encoded = erealloc(*encoded, *encoded_len + 1);
230 (*encoded)[*encoded_len] = '\0';
231 return SUCCESS;
232 }
233
234 PTR_SET(*encoded, NULL);
235 *encoded_len = 0;
236 php_error_docref(NULL, E_WARNING, "Failed to flush deflate stream: %s", zError(status));
237 return FAILURE;
238 }
239
240 static ZEND_RESULT_CODE deflate_finish(php_http_encoding_stream_t *s, char **encoded, size_t *encoded_len)
241 {
242 int status;
243 z_streamp ctx = s->ctx;
244
245 *encoded_len = PHP_HTTP_DEFLATE_BUFFER_SIZE;
246 *encoded = emalloc(*encoded_len);
247
248 /* deflate remaining input */
249 ctx->next_in = (Bytef *) PHP_HTTP_BUFFER(ctx->opaque)->data;
250 ctx->avail_in = PHP_HTTP_BUFFER(ctx->opaque)->used;
251
252 ctx->avail_out = *encoded_len;
253 ctx->next_out = (Bytef *) *encoded;
254
255 do {
256 status = deflate(ctx, Z_FINISH);
257 } while (Z_OK == status);
258
259 if (EXPECTED(Z_STREAM_END == status)) {
260 /* cut processed input off */
261 php_http_buffer_cut(PHP_HTTP_BUFFER(ctx->opaque), 0, PHP_HTTP_BUFFER(ctx->opaque)->used - ctx->avail_in);
262
263 /* size down */
264 *encoded_len -= ctx->avail_out;
265 *encoded = erealloc(*encoded, *encoded_len + 1);
266 (*encoded)[*encoded_len] = '\0';
267 return SUCCESS;
268 }
269
270 PTR_SET(*encoded, NULL);
271 *encoded_len = 0;
272 php_error_docref(NULL, E_WARNING, "Failed to finish deflate stream: %s", zError(status));
273 return FAILURE;
274 }
275
276 static zend_bool deflate_done(php_http_encoding_stream_t *s)
277 {
278 z_streamp ctx = s->ctx;
279 return !ctx->avail_in && !PHP_HTTP_BUFFER(ctx->opaque)->used;
280 }
281
282 static void deflate_dtor(php_http_encoding_stream_t *s)
283 {
284 if (EXPECTED(s->ctx)) {
285 z_streamp ctx = s->ctx;
286
287 if (EXPECTED(ctx->opaque)) {
288 php_http_buffer_free((php_http_buffer_t **) &ctx->opaque);
289 }
290 deflateEnd(ctx);
291 pefree(ctx, (s->flags & PHP_HTTP_ENCODING_STREAM_PERSISTENT));
292 s->ctx = NULL;
293 }
294 }
295
296 static inline int php_http_inflate_rounds(z_stream *Z, int flush, char **buf, size_t *len)
297 {
298 int status = 0, round = 0;
299 php_http_buffer_t buffer;
300
301 *buf = NULL;
302 *len = 0;
303
304 php_http_buffer_init_ex(&buffer, Z->avail_in, PHP_HTTP_BUFFER_INIT_PREALLOC);
305
306 do {
307 if (UNEXPECTED(PHP_HTTP_BUFFER_NOMEM == php_http_buffer_resize_ex(&buffer, buffer.size, 0, 1))) {
308 status = Z_MEM_ERROR;
309 } else {
310 Z->avail_out = buffer.free;
311 Z->next_out = (Bytef *) buffer.data + buffer.used;
312 #if 0
313 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);
314 #endif
315 status = inflate(Z, flush);
316 php_http_buffer_account(&buffer, buffer.free - Z->avail_out);
317 #if 0
318 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);
319 #endif
320 PHP_HTTP_INFLATE_BUFFER_SIZE_ALIGN(buffer.size);
321 }
322 } while ((Z_BUF_ERROR == status || (Z_OK == status && Z->avail_in)) && ++round < PHP_HTTP_INFLATE_ROUNDS);
323
324 if (EXPECTED(status == Z_OK || status == Z_STREAM_END)) {
325 php_http_buffer_shrink(&buffer);
326 php_http_buffer_fix(&buffer);
327 *buf = buffer.data;
328 *len = buffer.used;
329 } else {
330 php_http_buffer_dtor(&buffer);
331 }
332
333 return status;
334 }
335
336 ZEND_RESULT_CODE php_http_encoding_inflate(const char *data, size_t data_len, char **decoded, size_t *decoded_len)
337 {
338 z_stream Z;
339 int status, wbits = PHP_HTTP_WINDOW_BITS_ANY;
340
341 memset(&Z, 0, sizeof(z_stream));
342
343 retry_raw_inflate:
344 status = inflateInit2(&Z, wbits);
345 if (EXPECTED(Z_OK == status)) {
346 Z.next_in = (Bytef *) data;
347 Z.avail_in = data_len + 1; /* include the terminating NULL, see #61287 */
348
349 switch (status = php_http_inflate_rounds(&Z, Z_NO_FLUSH, decoded, decoded_len)) {
350 case Z_STREAM_END:
351 inflateEnd(&Z);
352 return SUCCESS;
353
354 case Z_OK:
355 status = Z_DATA_ERROR;
356 break;
357
358 case Z_DATA_ERROR:
359 /* raw deflated data? */
360 if (PHP_HTTP_WINDOW_BITS_ANY == wbits) {
361 inflateEnd(&Z);
362 wbits = PHP_HTTP_WINDOW_BITS_RAW;
363 goto retry_raw_inflate;
364 }
365 break;
366 }
367 inflateEnd(&Z);
368
369 if (*decoded_len && *decoded) {
370 efree(*decoded);
371 }
372 }
373
374 php_error_docref(NULL, E_WARNING, "Could not inflate data: %s", zError(status));
375 return FAILURE;
376 }
377
378 static php_http_encoding_stream_t *inflate_init(php_http_encoding_stream_t *s)
379 {
380 int status, wbits, p = (s->flags & PHP_HTTP_ENCODING_STREAM_PERSISTENT);
381 z_streamp ctx = pecalloc(1, sizeof(z_stream), p);
382
383 PHP_HTTP_INFLATE_WBITS_SET(s->flags, wbits);
384
385 if (EXPECTED(Z_OK == (status = inflateInit2(ctx, wbits)))) {
386 if ((ctx->opaque = php_http_buffer_init_ex(NULL, PHP_HTTP_DEFLATE_BUFFER_SIZE, p ? PHP_HTTP_BUFFER_INIT_PERSISTENT : 0))) {
387 s->ctx = ctx;
388 return s;
389 }
390 inflateEnd(ctx);
391 status = Z_MEM_ERROR;
392 }
393 pefree(ctx, p);
394 php_error_docref(NULL, E_WARNING, "Failed to initialize inflate stream: %s", zError(status));
395 return NULL;
396 }
397
398 static php_http_encoding_stream_t *inflate_copy(php_http_encoding_stream_t *from, php_http_encoding_stream_t *to)
399 {
400 int status, p = from->flags & PHP_HTTP_ENCODING_STREAM_PERSISTENT;
401 z_streamp from_ctx = from->ctx, to_ctx = pecalloc(1, sizeof(*to_ctx), p);
402
403 if (Z_OK == (status = inflateCopy(to_ctx, from_ctx))) {
404 if ((to_ctx->opaque = php_http_buffer_init_ex(NULL, PHP_HTTP_DEFLATE_BUFFER_SIZE, p ? PHP_HTTP_BUFFER_INIT_PERSISTENT : 0))) {
405 php_http_buffer_append(to_ctx->opaque, PHP_HTTP_BUFFER(from_ctx->opaque)->data, PHP_HTTP_BUFFER(from_ctx->opaque)->used);
406 to->ctx = to_ctx;
407 return to;
408 }
409 inflateEnd(to_ctx);
410 status = Z_MEM_ERROR;
411 }
412 php_error_docref(NULL, E_WARNING, "Failed to copy inflate encoding stream: %s", zError(status));
413 return NULL;
414 }
415
416 static ZEND_RESULT_CODE inflate_update(php_http_encoding_stream_t *s, const char *data, size_t data_len, char **decoded, size_t *decoded_len)
417 {
418 int status;
419 z_streamp ctx = s->ctx;
420
421 /* append input to buffer */
422 php_http_buffer_append(PHP_HTTP_BUFFER(ctx->opaque), data, data_len);
423
424 retry_raw_inflate:
425 ctx->next_in = (Bytef *) PHP_HTTP_BUFFER(ctx->opaque)->data;
426 ctx->avail_in = PHP_HTTP_BUFFER(ctx->opaque)->used;
427
428 switch (status = php_http_inflate_rounds(ctx, PHP_HTTP_INFLATE_FLUSH_FLAG(s->flags), decoded, decoded_len)) {
429 case Z_OK:
430 case Z_STREAM_END:
431 /* cut off */
432 if (ctx->avail_in) {
433 php_http_buffer_cut(PHP_HTTP_BUFFER(ctx->opaque), 0, PHP_HTTP_BUFFER(ctx->opaque)->used - ctx->avail_in);
434 } else {
435 php_http_buffer_reset(PHP_HTTP_BUFFER(ctx->opaque));
436 }
437 return SUCCESS;
438
439 case Z_DATA_ERROR:
440 /* raw deflated data ? */
441 if (!(s->flags & PHP_HTTP_INFLATE_TYPE_RAW) && !ctx->total_out) {
442 inflateEnd(ctx);
443 s->flags |= PHP_HTTP_INFLATE_TYPE_RAW;
444 inflateInit2(ctx, PHP_HTTP_WINDOW_BITS_RAW);
445 goto retry_raw_inflate;
446 }
447 break;
448 }
449
450 php_error_docref(NULL, E_WARNING, "Failed to update inflate stream: %s", zError(status));
451 return FAILURE;
452 }
453
454 static ZEND_RESULT_CODE inflate_finish(php_http_encoding_stream_t *s, char **decoded, size_t *decoded_len)
455 {
456 int status;
457 z_streamp ctx = s->ctx;
458
459 if (!PHP_HTTP_BUFFER(ctx->opaque)->used) {
460 *decoded = NULL;
461 *decoded_len = 0;
462 return SUCCESS;
463 }
464
465 *decoded_len = (PHP_HTTP_BUFFER(ctx->opaque)->used + 1) * PHP_HTTP_INFLATE_ROUNDS;
466 *decoded = emalloc(*decoded_len);
467
468 /* inflate remaining input */
469 ctx->next_in = (Bytef *) PHP_HTTP_BUFFER(ctx->opaque)->data;
470 ctx->avail_in = PHP_HTTP_BUFFER(ctx->opaque)->used;
471
472 ctx->avail_out = *decoded_len;
473 ctx->next_out = (Bytef *) *decoded;
474
475 if (Z_STREAM_END == (status = inflate(ctx, Z_FINISH))) {
476 /* cut processed input off */
477 php_http_buffer_cut(PHP_HTTP_BUFFER(ctx->opaque), 0, PHP_HTTP_BUFFER(ctx->opaque)->used - ctx->avail_in);
478
479 /* size down */
480 *decoded_len -= ctx->avail_out;
481 *decoded = erealloc(*decoded, *decoded_len + 1);
482 (*decoded)[*decoded_len] = '\0';
483 return SUCCESS;
484 }
485
486 PTR_SET(*decoded, NULL);
487 *decoded_len = 0;
488 php_error_docref(NULL, E_WARNING, "Failed to finish inflate stream: %s", zError(status));
489 return FAILURE;
490 }
491
492 static zend_bool inflate_done(php_http_encoding_stream_t *s)
493 {
494 z_streamp ctx = s->ctx;
495 return !ctx->avail_in && !PHP_HTTP_BUFFER(ctx->opaque)->used;
496 }
497
498 static void inflate_dtor(php_http_encoding_stream_t *s)
499 {
500 if (EXPECTED(s->ctx)) {
501 z_streamp ctx = s->ctx;
502
503 if (EXPECTED(ctx->opaque)) {
504 php_http_buffer_free((php_http_buffer_t **) &ctx->opaque);
505 }
506 inflateEnd(ctx);
507 pefree(ctx, (s->flags & PHP_HTTP_ENCODING_STREAM_PERSISTENT));
508 s->ctx = NULL;
509 }
510 }
511
512 static php_http_encoding_stream_ops_t php_http_encoding_deflate_ops = {
513 deflate_init,
514 deflate_copy,
515 deflate_update,
516 deflate_flush,
517 deflate_done,
518 deflate_finish,
519 deflate_dtor
520 };
521
522 php_http_encoding_stream_ops_t *php_http_encoding_stream_get_deflate_ops(void)
523 {
524 return &php_http_encoding_deflate_ops;
525 }
526
527 static php_http_encoding_stream_ops_t php_http_encoding_inflate_ops = {
528 inflate_init,
529 inflate_copy,
530 inflate_update,
531 NULL,
532 inflate_done,
533 inflate_finish,
534 inflate_dtor
535 };
536
537 php_http_encoding_stream_ops_t *php_http_encoding_stream_get_inflate_ops(void)
538 {
539 return &php_http_encoding_inflate_ops;
540 }
541
542 static zend_class_entry *php_http_deflate_stream_class_entry;
543 zend_class_entry *php_http_get_deflate_stream_class_entry(void)
544 {
545 return php_http_deflate_stream_class_entry;
546 }
547
548 static zend_class_entry *php_http_inflate_stream_class_entry;
549 zend_class_entry *php_http_get_inflate_stream_class_entry(void)
550 {
551 return php_http_inflate_stream_class_entry;
552 }
553
554
555 ZEND_BEGIN_ARG_INFO_EX(ai_HttpDeflateStream_encode, 0, 0, 1)
556 ZEND_ARG_INFO(0, data)
557 ZEND_ARG_INFO(0, flags)
558 ZEND_END_ARG_INFO();
559 static PHP_METHOD(HttpDeflateStream, encode)
560 {
561 char *str;
562 size_t len;
563 zend_long flags = 0;
564
565 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS(), "s|l", &str, &len, &flags)) {
566 char *enc_str = NULL;
567 size_t enc_len;
568
569 if (SUCCESS == php_http_encoding_deflate(flags, str, len, &enc_str, &enc_len)) {
570 if (enc_str) {
571 RETURN_STR(php_http_cs2zs(enc_str, enc_len));
572 } else {
573 RETURN_EMPTY_STRING();
574 }
575 }
576 }
577 RETURN_FALSE;
578 }
579
580 static zend_function_entry php_http_deflate_stream_methods[] = {
581 PHP_ME(HttpDeflateStream, encode, ai_HttpDeflateStream_encode, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
582 EMPTY_FUNCTION_ENTRY
583 };
584
585 ZEND_BEGIN_ARG_INFO_EX(ai_HttpInflateStream_decode, 0, 0, 1)
586 ZEND_ARG_INFO(0, data)
587 ZEND_END_ARG_INFO();
588 static PHP_METHOD(HttpInflateStream, decode)
589 {
590 char *str;
591 size_t len;
592
593 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS(), "s", &str, &len)) {
594 char *enc_str = NULL;
595 size_t enc_len;
596
597 if (SUCCESS == php_http_encoding_inflate(str, len, &enc_str, &enc_len)) {
598 if (enc_str) {
599 RETURN_STR(php_http_cs2zs(enc_str, enc_len));
600 } else {
601 RETURN_EMPTY_STRING();
602 }
603 }
604 }
605 RETURN_FALSE;
606 }
607
608 static zend_function_entry php_http_inflate_stream_methods[] = {
609 PHP_ME(HttpInflateStream, decode, ai_HttpInflateStream_decode, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
610 EMPTY_FUNCTION_ENTRY
611 };
612
613 PHP_MINIT_FUNCTION(http_encoding_zlib)
614 {
615 zend_class_entry ce;
616
617 memset(&ce, 0, sizeof(ce));
618 INIT_NS_CLASS_ENTRY(ce, "http\\Encoding\\Stream", "Deflate", php_http_deflate_stream_methods);
619 php_http_deflate_stream_class_entry = zend_register_internal_class_ex(&ce, php_http_get_encoding_stream_class_entry());
620 php_http_deflate_stream_class_entry->create_object = php_http_encoding_stream_object_new;
621
622 zend_declare_class_constant_long(php_http_deflate_stream_class_entry, ZEND_STRL("TYPE_GZIP"), PHP_HTTP_DEFLATE_TYPE_GZIP);
623 zend_declare_class_constant_long(php_http_deflate_stream_class_entry, ZEND_STRL("TYPE_ZLIB"), PHP_HTTP_DEFLATE_TYPE_ZLIB);
624 zend_declare_class_constant_long(php_http_deflate_stream_class_entry, ZEND_STRL("TYPE_RAW"), PHP_HTTP_DEFLATE_TYPE_RAW);
625 zend_declare_class_constant_long(php_http_deflate_stream_class_entry, ZEND_STRL("LEVEL_DEF"), PHP_HTTP_DEFLATE_LEVEL_DEF);
626 zend_declare_class_constant_long(php_http_deflate_stream_class_entry, ZEND_STRL("LEVEL_MIN"), PHP_HTTP_DEFLATE_LEVEL_MIN);
627 zend_declare_class_constant_long(php_http_deflate_stream_class_entry, ZEND_STRL("LEVEL_MAX"), PHP_HTTP_DEFLATE_LEVEL_MAX);
628 zend_declare_class_constant_long(php_http_deflate_stream_class_entry, ZEND_STRL("STRATEGY_DEF"), PHP_HTTP_DEFLATE_STRATEGY_DEF);
629 zend_declare_class_constant_long(php_http_deflate_stream_class_entry, ZEND_STRL("STRATEGY_FILT"), PHP_HTTP_DEFLATE_STRATEGY_FILT);
630 zend_declare_class_constant_long(php_http_deflate_stream_class_entry, ZEND_STRL("STRATEGY_HUFF"), PHP_HTTP_DEFLATE_STRATEGY_HUFF);
631 zend_declare_class_constant_long(php_http_deflate_stream_class_entry, ZEND_STRL("STRATEGY_RLE"), PHP_HTTP_DEFLATE_STRATEGY_RLE);
632 zend_declare_class_constant_long(php_http_deflate_stream_class_entry, ZEND_STRL("STRATEGY_FIXED"), PHP_HTTP_DEFLATE_STRATEGY_FIXED);
633
634 memset(&ce, 0, sizeof(ce));
635 INIT_NS_CLASS_ENTRY(ce, "http\\Encoding\\Stream", "Inflate", php_http_inflate_stream_methods);
636 php_http_inflate_stream_class_entry = zend_register_internal_class_ex(&ce, php_http_get_encoding_stream_class_entry());
637 php_http_inflate_stream_class_entry->create_object = php_http_encoding_stream_object_new;
638
639 return SUCCESS;
640 }
641
642 /*
643 * Local variables:
644 * tab-width: 4
645 * c-basic-offset: 4
646 * End:
647 * vim600: noet sw=4 ts=4 fdm=marker
648 * vim<600: noet sw=4 ts=4
649 */
650