fix missing files in package.xml; [ci skip]
[m6w6/ext-http] / php_http_encoding.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 #include <zlib.h>
16
17 static inline int eol_match(char **line, int *eol_len)
18 {
19 char *ptr = *line;
20
21 while (' ' == *ptr) ++ptr;
22
23 if (ptr == php_http_locate_eol(*line, eol_len)) {
24 *line = ptr;
25 return 1;
26 } else {
27 return 0;
28 }
29 }
30
31 const char *php_http_encoding_dechunk(const char *encoded, size_t encoded_len, char **decoded, size_t *decoded_len)
32 {
33 int eol_len = 0;
34 char *n_ptr = NULL;
35 const char *e_ptr = encoded;
36
37 *decoded_len = 0;
38 *decoded = ecalloc(1, encoded_len + 1);
39
40 while ((encoded + encoded_len - e_ptr) > 0) {
41 ulong chunk_len = 0, rest;
42
43 chunk_len = strtoul(e_ptr, &n_ptr, 16);
44
45 /* we could not read in chunk size */
46 if (n_ptr == e_ptr) {
47 /*
48 * if this is the first turn and there doesn't seem to be a chunk
49 * size at the begining of the body, do not fail on apparently
50 * not encoded data and return a copy
51 */
52 if (e_ptr == encoded) {
53 php_error_docref(NULL, E_NOTICE, "Data does not seem to be chunked encoded");
54 memcpy(*decoded, encoded, encoded_len);
55 *decoded_len = encoded_len;
56 return encoded + encoded_len;
57 } else {
58 efree(*decoded);
59 php_error_docref(NULL, E_WARNING, "Expected chunk size at pos %tu of %zu but got trash", n_ptr - encoded, encoded_len);
60 return NULL;
61 }
62 }
63
64 /* reached the end */
65 if (!chunk_len) {
66 /* move over '0' chunked encoding terminator and any new lines */
67 do {
68 switch (*e_ptr) {
69 case '0':
70 case '\r':
71 case '\n':
72 ++e_ptr;
73 continue;
74 }
75 } while (0);
76 break;
77 }
78
79 /* there should be CRLF after the chunk size, but we'll ignore SP+ too */
80 if (*n_ptr && !eol_match(&n_ptr, &eol_len)) {
81 if (eol_len == 2) {
82 php_error_docref(NULL, E_WARNING, "Expected CRLF at pos %tu of %zu but got 0x%02X 0x%02X", n_ptr - encoded, encoded_len, *n_ptr, *(n_ptr + 1));
83 } else {
84 php_error_docref(NULL, E_WARNING, "Expected LF at pos %tu of %zu but got 0x%02X", n_ptr - encoded, encoded_len, *n_ptr);
85 }
86 }
87 n_ptr += eol_len;
88
89 /* chunk size pretends more data than we actually got, so it's probably a truncated message */
90 if (chunk_len > (rest = encoded + encoded_len - n_ptr)) {
91 php_error_docref(NULL, E_WARNING, "Truncated message: chunk size %lu exceeds remaining data size %lu at pos %tu of %zu", chunk_len, rest, n_ptr - encoded, encoded_len);
92 chunk_len = rest;
93 }
94
95 /* copy the chunk */
96 memcpy(*decoded + *decoded_len, n_ptr, chunk_len);
97 *decoded_len += chunk_len;
98
99 if (chunk_len == rest) {
100 e_ptr = n_ptr + chunk_len;
101 break;
102 } else {
103 /* advance to next chunk */
104 e_ptr = n_ptr + chunk_len + eol_len;
105 }
106 }
107
108 return e_ptr;
109 }
110
111 static inline int php_http_inflate_rounds(z_stream *Z, int flush, char **buf, size_t *len)
112 {
113 int status = 0, round = 0;
114 php_http_buffer_t buffer;
115
116 *buf = NULL;
117 *len = 0;
118
119 php_http_buffer_init_ex(&buffer, Z->avail_in, PHP_HTTP_BUFFER_INIT_PREALLOC);
120
121 do {
122 if (PHP_HTTP_BUFFER_NOMEM == php_http_buffer_resize_ex(&buffer, buffer.size, 0, 1)) {
123 status = Z_MEM_ERROR;
124 } else {
125 Z->avail_out = buffer.free;
126 Z->next_out = (Bytef *) buffer.data + buffer.used;
127 #if 0
128 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);
129 #endif
130 status = inflate(Z, flush);
131 php_http_buffer_account(&buffer, buffer.free - Z->avail_out);
132 #if 0
133 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);
134 #endif
135 PHP_HTTP_INFLATE_BUFFER_SIZE_ALIGN(buffer.size);
136 }
137 } while ((Z_BUF_ERROR == status || (Z_OK == status && Z->avail_in)) && ++round < PHP_HTTP_INFLATE_ROUNDS);
138
139 if (status == Z_OK || status == Z_STREAM_END) {
140 php_http_buffer_shrink(&buffer);
141 php_http_buffer_fix(&buffer);
142 *buf = buffer.data;
143 *len = buffer.used;
144 } else {
145 php_http_buffer_dtor(&buffer);
146 }
147
148 return status;
149 }
150
151 ZEND_RESULT_CODE php_http_encoding_deflate(int flags, const char *data, size_t data_len, char **encoded, size_t *encoded_len)
152 {
153 int status, level, wbits, strategy;
154 z_stream Z;
155
156 PHP_HTTP_DEFLATE_LEVEL_SET(flags, level);
157 PHP_HTTP_DEFLATE_WBITS_SET(flags, wbits);
158 PHP_HTTP_DEFLATE_STRATEGY_SET(flags, strategy);
159
160 memset(&Z, 0, sizeof(z_stream));
161 *encoded = NULL;
162 *encoded_len = 0;
163
164 status = deflateInit2(&Z, level, Z_DEFLATED, wbits, MAX_MEM_LEVEL, strategy);
165 if (Z_OK == status) {
166 *encoded_len = PHP_HTTP_DEFLATE_BUFFER_SIZE_GUESS(data_len);
167 *encoded = emalloc(*encoded_len);
168
169 Z.next_in = (Bytef *) data;
170 Z.next_out = (Bytef *) *encoded;
171 Z.avail_in = data_len;
172 Z.avail_out = *encoded_len;
173
174 status = deflate(&Z, Z_FINISH);
175 deflateEnd(&Z);
176
177 if (Z_STREAM_END == status) {
178 /* size buffer down to actual length */
179 *encoded = erealloc(*encoded, Z.total_out + 1);
180 (*encoded)[*encoded_len = Z.total_out] = '\0';
181 return SUCCESS;
182 } else {
183 PTR_SET(*encoded, NULL);
184 *encoded_len = 0;
185 }
186 }
187
188 php_error_docref(NULL, E_WARNING, "Could not deflate data: %s", zError(status));
189 return FAILURE;
190 }
191
192 ZEND_RESULT_CODE php_http_encoding_inflate(const char *data, size_t data_len, char **decoded, size_t *decoded_len)
193 {
194 z_stream Z;
195 int status, wbits = PHP_HTTP_WINDOW_BITS_ANY;
196
197 memset(&Z, 0, sizeof(z_stream));
198
199 retry_raw_inflate:
200 status = inflateInit2(&Z, wbits);
201 if (Z_OK == status) {
202 Z.next_in = (Bytef *) data;
203 Z.avail_in = data_len + 1; /* include the terminating NULL, see #61287 */
204
205 switch (status = php_http_inflate_rounds(&Z, Z_NO_FLUSH, decoded, decoded_len)) {
206 case Z_STREAM_END:
207 inflateEnd(&Z);
208 return SUCCESS;
209
210 case Z_OK:
211 status = Z_DATA_ERROR;
212 break;
213
214 case Z_DATA_ERROR:
215 /* raw deflated data? */
216 if (PHP_HTTP_WINDOW_BITS_ANY == wbits) {
217 inflateEnd(&Z);
218 wbits = PHP_HTTP_WINDOW_BITS_RAW;
219 goto retry_raw_inflate;
220 }
221 break;
222 }
223 inflateEnd(&Z);
224
225 if (decoded_len && *decoded) {
226 efree(*decoded);
227 }
228 }
229
230 php_error_docref(NULL, E_WARNING, "Could not inflate data: %s", zError(status));
231 return FAILURE;
232 }
233
234 php_http_encoding_stream_t *php_http_encoding_stream_init(php_http_encoding_stream_t *s, php_http_encoding_stream_ops_t *ops, unsigned flags)
235 {
236 int freeme;
237
238 if ((freeme = !s)) {
239 s = pemalloc(sizeof(*s), (flags & PHP_HTTP_ENCODING_STREAM_PERSISTENT));
240 }
241 memset(s, 0, sizeof(*s));
242
243 s->flags = flags;
244
245 if ((s->ops = ops)) {
246 php_http_encoding_stream_t *ss = s->ops->init(s);
247
248 if (ss) {
249 return ss;
250 }
251 } else {
252 return s;
253 }
254
255 if (freeme) {
256 pefree(s, (flags & PHP_HTTP_ENCODING_STREAM_PERSISTENT));
257 }
258 return NULL;
259 }
260
261 php_http_encoding_stream_t *php_http_encoding_stream_copy(php_http_encoding_stream_t *from, php_http_encoding_stream_t *to)
262 {
263 if (from->ops->copy) {
264 int freeme;
265 php_http_encoding_stream_t *ns;
266
267 if ((freeme = !to)) {
268 to = pemalloc(sizeof(*to), (from->flags & PHP_HTTP_ENCODING_STREAM_PERSISTENT));
269 }
270 memset(to, 0, sizeof(*to));
271
272 to->flags = from->flags;
273 to->ops = from->ops;
274
275 if ((ns = to->ops->copy(from, to))) {
276 return ns;
277 } else {
278 return to;
279 }
280
281 if (freeme) {
282 pefree(to, (to->flags & PHP_HTTP_ENCODING_STREAM_PERSISTENT));
283 }
284 }
285
286 return NULL;
287 }
288
289 ZEND_RESULT_CODE php_http_encoding_stream_reset(php_http_encoding_stream_t **s)
290 {
291 php_http_encoding_stream_t *ss;
292
293 if ((*s)->ops->dtor) {
294 (*s)->ops->dtor(*s);
295 }
296 if ((ss = (*s)->ops->init(*s))) {
297 *s = ss;
298 return SUCCESS;
299 }
300 return FAILURE;
301 }
302
303 ZEND_RESULT_CODE php_http_encoding_stream_update(php_http_encoding_stream_t *s, const char *in_str, size_t in_len, char **out_str, size_t *out_len)
304 {
305 if (!s->ops->update) {
306 return FAILURE;
307 }
308 return s->ops->update(s, in_str, in_len, out_str, out_len);
309 }
310
311 ZEND_RESULT_CODE php_http_encoding_stream_flush(php_http_encoding_stream_t *s, char **out_str, size_t *out_len)
312 {
313 if (!s->ops->flush) {
314 *out_str = NULL;
315 *out_len = 0;
316 return SUCCESS;
317 }
318 return s->ops->flush(s, out_str, out_len);
319 }
320
321 zend_bool php_http_encoding_stream_done(php_http_encoding_stream_t *s)
322 {
323 if (!s->ops->done) {
324 return 0;
325 }
326 return s->ops->done(s);
327 }
328
329 ZEND_RESULT_CODE php_http_encoding_stream_finish(php_http_encoding_stream_t *s, char **out_str, size_t *out_len)
330 {
331 if (!s->ops->finish) {
332 *out_str = NULL;
333 *out_len = 0;
334 return SUCCESS;
335 }
336 return s->ops->finish(s, out_str, out_len);
337 }
338
339 void php_http_encoding_stream_dtor(php_http_encoding_stream_t *s)
340 {
341 if (s->ops->dtor) {
342 s->ops->dtor(s);
343 }
344 }
345
346 void php_http_encoding_stream_free(php_http_encoding_stream_t **s)
347 {
348 if (*s) {
349 if ((*s)->ops->dtor) {
350 (*s)->ops->dtor(*s);
351 }
352 pefree(*s, ((*s)->flags & PHP_HTTP_ENCODING_STREAM_PERSISTENT));
353 *s = NULL;
354 }
355 }
356
357 struct dechunk_ctx {
358 php_http_buffer_t buffer;
359 ulong hexlen;
360 unsigned zeroed:1;
361 };
362
363 static php_http_encoding_stream_t *deflate_init(php_http_encoding_stream_t *s)
364 {
365 int status, level, wbits, strategy, p = (s->flags & PHP_HTTP_ENCODING_STREAM_PERSISTENT);
366 z_streamp ctx = pecalloc(1, sizeof(z_stream), p);
367
368 PHP_HTTP_DEFLATE_LEVEL_SET(s->flags, level);
369 PHP_HTTP_DEFLATE_WBITS_SET(s->flags, wbits);
370 PHP_HTTP_DEFLATE_STRATEGY_SET(s->flags, strategy);
371
372 if (Z_OK == (status = deflateInit2(ctx, level, Z_DEFLATED, wbits, MAX_MEM_LEVEL, strategy))) {
373 if ((ctx->opaque = php_http_buffer_init_ex(NULL, PHP_HTTP_DEFLATE_BUFFER_SIZE, p ? PHP_HTTP_BUFFER_INIT_PERSISTENT : 0))) {
374 s->ctx = ctx;
375 return s;
376 }
377 deflateEnd(ctx);
378 status = Z_MEM_ERROR;
379 }
380 pefree(ctx, p);
381 php_error_docref(NULL, E_WARNING, "Failed to initialize deflate encoding stream: %s", zError(status));
382 return NULL;
383 }
384
385 static php_http_encoding_stream_t *inflate_init(php_http_encoding_stream_t *s)
386 {
387 int status, wbits, p = (s->flags & PHP_HTTP_ENCODING_STREAM_PERSISTENT);
388 z_streamp ctx = pecalloc(1, sizeof(z_stream), p);
389
390 PHP_HTTP_INFLATE_WBITS_SET(s->flags, wbits);
391
392 if (Z_OK == (status = inflateInit2(ctx, wbits))) {
393 if ((ctx->opaque = php_http_buffer_init_ex(NULL, PHP_HTTP_DEFLATE_BUFFER_SIZE, p ? PHP_HTTP_BUFFER_INIT_PERSISTENT : 0))) {
394 s->ctx = ctx;
395 return s;
396 }
397 inflateEnd(ctx);
398 status = Z_MEM_ERROR;
399 }
400 pefree(ctx, p);
401 php_error_docref(NULL, E_WARNING, "Failed to initialize inflate stream: %s", zError(status));
402 return NULL;
403 }
404
405 static php_http_encoding_stream_t *dechunk_init(php_http_encoding_stream_t *s)
406 {
407 struct dechunk_ctx *ctx = pecalloc(1, sizeof(*ctx), (s->flags & PHP_HTTP_ENCODING_STREAM_PERSISTENT));
408
409 if (!php_http_buffer_init_ex(&ctx->buffer, PHP_HTTP_BUFFER_DEFAULT_SIZE, (s->flags & PHP_HTTP_ENCODING_STREAM_PERSISTENT) ? PHP_HTTP_BUFFER_INIT_PERSISTENT : 0)) {
410 return NULL;
411 }
412
413 ctx->hexlen = 0;
414 ctx->zeroed = 0;
415 s->ctx = ctx;
416
417 return s;
418 }
419
420 static php_http_encoding_stream_t *deflate_copy(php_http_encoding_stream_t *from, php_http_encoding_stream_t *to)
421 {
422 int status, p = to->flags & PHP_HTTP_ENCODING_STREAM_PERSISTENT;
423 z_streamp from_ctx = from->ctx, to_ctx = pecalloc(1, sizeof(*to_ctx), p);
424
425 if (Z_OK == (status = deflateCopy(to_ctx, from_ctx))) {
426 if ((to_ctx->opaque = php_http_buffer_init_ex(NULL, PHP_HTTP_DEFLATE_BUFFER_SIZE, p ? PHP_HTTP_BUFFER_INIT_PERSISTENT : 0))) {
427 php_http_buffer_append(to_ctx->opaque, PHP_HTTP_BUFFER(from_ctx->opaque)->data, PHP_HTTP_BUFFER(from_ctx->opaque)->used);
428 to->ctx = to_ctx;
429 return to;
430 }
431 deflateEnd(to_ctx);
432 status = Z_MEM_ERROR;
433 }
434 php_error_docref(NULL, E_WARNING, "Failed to copy deflate encoding stream: %s", zError(status));
435 return NULL;
436 }
437
438 static php_http_encoding_stream_t *inflate_copy(php_http_encoding_stream_t *from, php_http_encoding_stream_t *to)
439 {
440 int status, p = from->flags & PHP_HTTP_ENCODING_STREAM_PERSISTENT;
441 z_streamp from_ctx = from->ctx, to_ctx = pecalloc(1, sizeof(*to_ctx), p);
442
443 if (Z_OK == (status = inflateCopy(to_ctx, from_ctx))) {
444 if ((to_ctx->opaque = php_http_buffer_init_ex(NULL, PHP_HTTP_DEFLATE_BUFFER_SIZE, p ? PHP_HTTP_BUFFER_INIT_PERSISTENT : 0))) {
445 php_http_buffer_append(to_ctx->opaque, PHP_HTTP_BUFFER(from_ctx->opaque)->data, PHP_HTTP_BUFFER(from_ctx->opaque)->used);
446 to->ctx = to_ctx;
447 return to;
448 }
449 inflateEnd(to_ctx);
450 status = Z_MEM_ERROR;
451 }
452 php_error_docref(NULL, E_WARNING, "Failed to copy inflate encoding stream: %s", zError(status));
453 return NULL;
454 }
455
456 static php_http_encoding_stream_t *dechunk_copy(php_http_encoding_stream_t *from, php_http_encoding_stream_t *to)
457 {
458 int p = from->flags & PHP_HTTP_ENCODING_STREAM_PERSISTENT;
459 struct dechunk_ctx *from_ctx = from->ctx, *to_ctx = pemalloc(sizeof(*to_ctx), p);
460
461 if (php_http_buffer_init_ex(&to_ctx->buffer, PHP_HTTP_BUFFER_DEFAULT_SIZE, p ? PHP_HTTP_BUFFER_INIT_PERSISTENT : 0)) {
462 to_ctx->hexlen = from_ctx->hexlen;
463 to_ctx->zeroed = from_ctx->zeroed;
464 php_http_buffer_append(&to_ctx->buffer, from_ctx->buffer.data, from_ctx->buffer.used);
465 to->ctx = to_ctx;
466 return to;
467 }
468 pefree(to_ctx, p);
469 php_error_docref(NULL, E_WARNING, "Failed to copy inflate encoding stream: out of memory");
470 return NULL;
471 }
472
473 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)
474 {
475 int status;
476 z_streamp ctx = s->ctx;
477
478 /* append input to our buffer */
479 php_http_buffer_append(PHP_HTTP_BUFFER(ctx->opaque), data, data_len);
480
481 ctx->next_in = (Bytef *) PHP_HTTP_BUFFER(ctx->opaque)->data;
482 ctx->avail_in = PHP_HTTP_BUFFER(ctx->opaque)->used;
483
484 /* deflate */
485 *encoded_len = PHP_HTTP_DEFLATE_BUFFER_SIZE_GUESS(data_len);
486 *encoded = emalloc(*encoded_len);
487 ctx->avail_out = *encoded_len;
488 ctx->next_out = (Bytef *) *encoded;
489
490 switch (status = deflate(ctx, PHP_HTTP_ENCODING_STREAM_FLUSH_FLAG(s->flags))) {
491 case Z_OK:
492 case Z_STREAM_END:
493 /* cut processed chunk off the buffer */
494 if (ctx->avail_in) {
495 php_http_buffer_cut(PHP_HTTP_BUFFER(ctx->opaque), 0, PHP_HTTP_BUFFER(ctx->opaque)->used - ctx->avail_in);
496 } else {
497 php_http_buffer_reset(PHP_HTTP_BUFFER(ctx->opaque));
498 }
499
500 /* size buffer down to actual size */
501 *encoded_len -= ctx->avail_out;
502 *encoded = erealloc(*encoded, *encoded_len + 1);
503 (*encoded)[*encoded_len] = '\0';
504 return SUCCESS;
505 }
506
507 PTR_SET(*encoded, NULL);
508 *encoded_len = 0;
509 php_error_docref(NULL, E_WARNING, "Failed to update deflate stream: %s", zError(status));
510 return FAILURE;
511 }
512
513 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)
514 {
515 int status;
516 z_streamp ctx = s->ctx;
517
518 /* append input to buffer */
519 php_http_buffer_append(PHP_HTTP_BUFFER(ctx->opaque), data, data_len);
520
521 retry_raw_inflate:
522 ctx->next_in = (Bytef *) PHP_HTTP_BUFFER(ctx->opaque)->data;
523 ctx->avail_in = PHP_HTTP_BUFFER(ctx->opaque)->used;
524
525 switch (status = php_http_inflate_rounds(ctx, PHP_HTTP_ENCODING_STREAM_FLUSH_FLAG(s->flags), decoded, decoded_len)) {
526 case Z_OK:
527 case Z_STREAM_END:
528 /* cut off */
529 if (ctx->avail_in) {
530 php_http_buffer_cut(PHP_HTTP_BUFFER(ctx->opaque), 0, PHP_HTTP_BUFFER(ctx->opaque)->used - ctx->avail_in);
531 } else {
532 php_http_buffer_reset(PHP_HTTP_BUFFER(ctx->opaque));
533 }
534 return SUCCESS;
535
536 case Z_DATA_ERROR:
537 /* raw deflated data ? */
538 if (!(s->flags & PHP_HTTP_INFLATE_TYPE_RAW) && !ctx->total_out) {
539 inflateEnd(ctx);
540 s->flags |= PHP_HTTP_INFLATE_TYPE_RAW;
541 inflateInit2(ctx, PHP_HTTP_WINDOW_BITS_RAW);
542 goto retry_raw_inflate;
543 }
544 break;
545 }
546
547 php_error_docref(NULL, E_WARNING, "Failed to update inflate stream: %s", zError(status));
548 return FAILURE;
549 }
550
551 static ZEND_RESULT_CODE dechunk_update(php_http_encoding_stream_t *s, const char *data, size_t data_len, char **decoded, size_t *decoded_len)
552 {
553 php_http_buffer_t tmp;
554 struct dechunk_ctx *ctx = s->ctx;
555
556 if (ctx->zeroed) {
557 php_error_docref(NULL, E_WARNING, "Dechunk encoding stream has already reached the end of chunked input");
558 return FAILURE;
559 }
560 if ((PHP_HTTP_BUFFER_NOMEM == php_http_buffer_append(&ctx->buffer, data, data_len)) || !php_http_buffer_fix(&ctx->buffer)) {
561 /* OOM */
562 return FAILURE;
563 }
564
565 *decoded = NULL;
566 *decoded_len = 0;
567
568 php_http_buffer_init(&tmp);
569
570 /* we have data in our buffer */
571 while (ctx->buffer.used) {
572
573 /* we already know the size of the chunk and are waiting for data */
574 if (ctx->hexlen) {
575
576 /* not enough data buffered */
577 if (ctx->buffer.used < ctx->hexlen) {
578
579 /* flush anyway? */
580 if (s->flags & PHP_HTTP_ENCODING_STREAM_FLUSH_FULL) {
581 /* flush all data (should only be chunk data) */
582 php_http_buffer_append(&tmp, ctx->buffer.data, ctx->buffer.used);
583 /* waiting for less data now */
584 ctx->hexlen -= ctx->buffer.used;
585 /* no more buffered data */
586 php_http_buffer_reset(&ctx->buffer);
587 /* break */
588 }
589
590 /* we have too less data and don't need to flush */
591 else {
592 break;
593 }
594 }
595
596 /* we seem to have all data of the chunk */
597 else {
598 php_http_buffer_append(&tmp, ctx->buffer.data, ctx->hexlen);
599 /* remove outgoing data from the buffer */
600 php_http_buffer_cut(&ctx->buffer, 0, ctx->hexlen);
601 /* reset hexlen */
602 ctx->hexlen = 0;
603 /* continue */
604 }
605 }
606
607 /* we don't know the length of the chunk yet */
608 else {
609 size_t off = 0;
610
611 /* ignore preceeding CRLFs (too loose?) */
612 while (off < ctx->buffer.used && (
613 ctx->buffer.data[off] == '\n' ||
614 ctx->buffer.data[off] == '\r')) {
615 ++off;
616 }
617 if (off) {
618 php_http_buffer_cut(&ctx->buffer, 0, off);
619 }
620
621 /* still data there? */
622 if (ctx->buffer.used) {
623 int eollen;
624 const char *eolstr;
625
626 /* we need eol, so we can be sure we have all hex digits */
627 php_http_buffer_fix(&ctx->buffer);
628 if ((eolstr = php_http_locate_bin_eol(ctx->buffer.data, ctx->buffer.used, &eollen))) {
629 char *stop = NULL;
630
631 /* read in chunk size */
632 ctx->hexlen = strtoul(ctx->buffer.data, &stop, 16);
633
634 /* if strtoul() stops at the beginning of the buffered data
635 there's something oddly wrong, i.e. bad input */
636 if (stop == ctx->buffer.data) {
637 php_error_docref(NULL, E_WARNING, "Failed to parse chunk len from '%.*s'", (int) MIN(16, ctx->buffer.used), ctx->buffer.data);
638 php_http_buffer_dtor(&tmp);
639 return FAILURE;
640 }
641
642 /* cut out <chunk size hex><chunk extension><eol> */
643 php_http_buffer_cut(&ctx->buffer, 0, eolstr + eollen - ctx->buffer.data);
644 /* buffer->hexlen is 0 now or contains the size of the next chunk */
645 if (!ctx->hexlen) {
646 size_t off = 0;
647
648 /* ignore following CRLFs (too loose?) */
649 while (off < ctx->buffer.used && (
650 ctx->buffer.data[off] == '\n' ||
651 ctx->buffer.data[off] == '\r')) {
652 ++off;
653 }
654 if (off) {
655 php_http_buffer_cut(&ctx->buffer, 0, off);
656 }
657
658 ctx->zeroed = 1;
659 break;
660 }
661 /* continue */
662 } else {
663 /* we have not enough data buffered to read in chunk size */
664 break;
665 }
666 }
667 /* break */
668 }
669 }
670
671 php_http_buffer_fix(&tmp);
672 *decoded = tmp.data;
673 *decoded_len = tmp.used;
674
675 return SUCCESS;
676 }
677
678 static ZEND_RESULT_CODE deflate_flush(php_http_encoding_stream_t *s, char **encoded, size_t *encoded_len)
679 {
680 int status;
681 z_streamp ctx = s->ctx;
682
683 *encoded_len = PHP_HTTP_DEFLATE_BUFFER_SIZE;
684 *encoded = emalloc(*encoded_len);
685
686 ctx->avail_in = 0;
687 ctx->next_in = NULL;
688 ctx->avail_out = *encoded_len;
689 ctx->next_out = (Bytef *) *encoded;
690
691 switch (status = deflate(ctx, Z_FULL_FLUSH)) {
692 case Z_OK:
693 case Z_STREAM_END:
694 *encoded_len = PHP_HTTP_DEFLATE_BUFFER_SIZE - ctx->avail_out;
695 *encoded = erealloc(*encoded, *encoded_len + 1);
696 (*encoded)[*encoded_len] = '\0';
697 return SUCCESS;
698 }
699
700 PTR_SET(*encoded, NULL);
701 *encoded_len = 0;
702 php_error_docref(NULL, E_WARNING, "Failed to flush deflate stream: %s", zError(status));
703 return FAILURE;
704 }
705
706 static ZEND_RESULT_CODE dechunk_flush(php_http_encoding_stream_t *s, char **decoded, size_t *decoded_len)
707 {
708 struct dechunk_ctx *ctx = s->ctx;
709
710 if (ctx->hexlen) {
711 /* flush all data (should only be chunk data) */
712 php_http_buffer_fix(&ctx->buffer);
713 php_http_buffer_data(&ctx->buffer, decoded, decoded_len);
714 /* waiting for less data now */
715 ctx->hexlen -= ctx->buffer.used;
716 /* no more buffered data */
717 php_http_buffer_reset(&ctx->buffer);
718 } else {
719 *decoded = NULL;
720 *decoded_len = 0;
721 }
722
723 return SUCCESS;
724 }
725
726 static ZEND_RESULT_CODE deflate_finish(php_http_encoding_stream_t *s, char **encoded, size_t *encoded_len)
727 {
728 int status;
729 z_streamp ctx = s->ctx;
730
731 *encoded_len = PHP_HTTP_DEFLATE_BUFFER_SIZE;
732 *encoded = emalloc(*encoded_len);
733
734 /* deflate remaining input */
735 ctx->next_in = (Bytef *) PHP_HTTP_BUFFER(ctx->opaque)->data;
736 ctx->avail_in = PHP_HTTP_BUFFER(ctx->opaque)->used;
737
738 ctx->avail_out = *encoded_len;
739 ctx->next_out = (Bytef *) *encoded;
740
741 do {
742 status = deflate(ctx, Z_FINISH);
743 } while (Z_OK == status);
744
745 if (Z_STREAM_END == status) {
746 /* cut processed input off */
747 php_http_buffer_cut(PHP_HTTP_BUFFER(ctx->opaque), 0, PHP_HTTP_BUFFER(ctx->opaque)->used - ctx->avail_in);
748
749 /* size down */
750 *encoded_len -= ctx->avail_out;
751 *encoded = erealloc(*encoded, *encoded_len + 1);
752 (*encoded)[*encoded_len] = '\0';
753 return SUCCESS;
754 }
755
756 PTR_SET(*encoded, NULL);
757 *encoded_len = 0;
758 php_error_docref(NULL, E_WARNING, "Failed to finish deflate stream: %s", zError(status));
759 return FAILURE;
760 }
761
762 static ZEND_RESULT_CODE inflate_finish(php_http_encoding_stream_t *s, char **decoded, size_t *decoded_len)
763 {
764 int status;
765 z_streamp ctx = s->ctx;
766
767 if (!PHP_HTTP_BUFFER(ctx->opaque)->used) {
768 *decoded = NULL;
769 *decoded_len = 0;
770 return SUCCESS;
771 }
772
773 *decoded_len = (PHP_HTTP_BUFFER(ctx->opaque)->used + 1) * PHP_HTTP_INFLATE_ROUNDS;
774 *decoded = emalloc(*decoded_len);
775
776 /* inflate remaining input */
777 ctx->next_in = (Bytef *) PHP_HTTP_BUFFER(ctx->opaque)->data;
778 ctx->avail_in = PHP_HTTP_BUFFER(ctx->opaque)->used;
779
780 ctx->avail_out = *decoded_len;
781 ctx->next_out = (Bytef *) *decoded;
782
783 if (Z_STREAM_END == (status = inflate(ctx, Z_FINISH))) {
784 /* cut processed input off */
785 php_http_buffer_cut(PHP_HTTP_BUFFER(ctx->opaque), 0, PHP_HTTP_BUFFER(ctx->opaque)->used - ctx->avail_in);
786
787 /* size down */
788 *decoded_len -= ctx->avail_out;
789 *decoded = erealloc(*decoded, *decoded_len + 1);
790 (*decoded)[*decoded_len] = '\0';
791 return SUCCESS;
792 }
793
794 PTR_SET(*decoded, NULL);
795 *decoded_len = 0;
796 php_error_docref(NULL, E_WARNING, "Failed to finish inflate stream: %s", zError(status));
797 return FAILURE;
798 }
799
800 static zend_bool deflate_done(php_http_encoding_stream_t *s)
801 {
802 z_streamp ctx = s->ctx;
803 return !ctx->avail_in && !PHP_HTTP_BUFFER(ctx->opaque)->used;
804 }
805
806 static zend_bool inflate_done(php_http_encoding_stream_t *s)
807 {
808 z_streamp ctx = s->ctx;
809 return !ctx->avail_in && !PHP_HTTP_BUFFER(ctx->opaque)->used;
810 }
811
812 static zend_bool dechunk_done(php_http_encoding_stream_t *s)
813 {
814 return ((struct dechunk_ctx *) s->ctx)->zeroed;
815 }
816
817 static void deflate_dtor(php_http_encoding_stream_t *s)
818 {
819 if (s->ctx) {
820 z_streamp ctx = s->ctx;
821
822 if (ctx->opaque) {
823 php_http_buffer_free((php_http_buffer_t **) &ctx->opaque);
824 }
825 deflateEnd(ctx);
826 pefree(ctx, (s->flags & PHP_HTTP_ENCODING_STREAM_PERSISTENT));
827 s->ctx = NULL;
828 }
829 }
830
831 static void inflate_dtor(php_http_encoding_stream_t *s)
832 {
833 if (s->ctx) {
834 z_streamp ctx = s->ctx;
835
836 if (ctx->opaque) {
837 php_http_buffer_free((php_http_buffer_t **) &ctx->opaque);
838 }
839 inflateEnd(ctx);
840 pefree(ctx, (s->flags & PHP_HTTP_ENCODING_STREAM_PERSISTENT));
841 s->ctx = NULL;
842 }
843 }
844
845 static void dechunk_dtor(php_http_encoding_stream_t *s)
846 {
847 if (s->ctx) {
848 struct dechunk_ctx *ctx = s->ctx;
849
850 php_http_buffer_dtor(&ctx->buffer);
851 pefree(ctx, (s->flags & PHP_HTTP_ENCODING_STREAM_PERSISTENT));
852 s->ctx = NULL;
853 }
854 }
855
856 static php_http_encoding_stream_ops_t php_http_encoding_deflate_ops = {
857 deflate_init,
858 deflate_copy,
859 deflate_update,
860 deflate_flush,
861 deflate_done,
862 deflate_finish,
863 deflate_dtor
864 };
865
866 php_http_encoding_stream_ops_t *php_http_encoding_stream_get_deflate_ops(void)
867 {
868 return &php_http_encoding_deflate_ops;
869 }
870
871 static php_http_encoding_stream_ops_t php_http_encoding_inflate_ops = {
872 inflate_init,
873 inflate_copy,
874 inflate_update,
875 NULL,
876 inflate_done,
877 inflate_finish,
878 inflate_dtor
879 };
880
881 php_http_encoding_stream_ops_t *php_http_encoding_stream_get_inflate_ops(void)
882 {
883 return &php_http_encoding_inflate_ops;
884 }
885
886 static php_http_encoding_stream_ops_t php_http_encoding_dechunk_ops = {
887 dechunk_init,
888 dechunk_copy,
889 dechunk_update,
890 dechunk_flush,
891 dechunk_done,
892 NULL,
893 dechunk_dtor
894 };
895
896 php_http_encoding_stream_ops_t *php_http_encoding_stream_get_dechunk_ops(void)
897 {
898 return &php_http_encoding_dechunk_ops;
899 }
900
901 static zend_object_handlers php_http_encoding_stream_object_handlers;
902
903 zend_object *php_http_encoding_stream_object_new(zend_class_entry *ce)
904 {
905 return &php_http_encoding_stream_object_new_ex(ce, NULL)->zo;
906 }
907
908 php_http_encoding_stream_object_t *php_http_encoding_stream_object_new_ex(zend_class_entry *ce, php_http_encoding_stream_t *s)
909 {
910 php_http_encoding_stream_object_t *o;
911
912 o = ecalloc(1, sizeof(*o) + zend_object_properties_size(ce));
913 zend_object_std_init(&o->zo, ce);
914 object_properties_init(&o->zo, ce);
915
916 if (s) {
917 o->stream = s;
918 }
919
920 o->zo.handlers = &php_http_encoding_stream_object_handlers;
921
922 return o;
923 }
924
925 zend_object *php_http_encoding_stream_object_clone(zval *object)
926 {
927 php_http_encoding_stream_object_t *new_obj = NULL, *old_obj = PHP_HTTP_OBJ(NULL, object);
928 php_http_encoding_stream_t *cpy = php_http_encoding_stream_copy(old_obj->stream, NULL);
929
930 new_obj = php_http_encoding_stream_object_new_ex(old_obj->zo.ce, cpy);
931 zend_objects_clone_members(&new_obj->zo, &old_obj->zo);
932
933 return &new_obj->zo;
934 }
935
936 void php_http_encoding_stream_object_free(zend_object *object)
937 {
938 php_http_encoding_stream_object_t *o = PHP_HTTP_OBJ(object, NULL);
939
940 if (o->stream) {
941 php_http_encoding_stream_free(&o->stream);
942 }
943 zend_object_std_dtor(object);
944 }
945
946 ZEND_BEGIN_ARG_INFO_EX(ai_HttpEncodingStream___construct, 0, 0, 0)
947 ZEND_ARG_INFO(0, flags)
948 ZEND_END_ARG_INFO();
949 static PHP_METHOD(HttpEncodingStream, __construct)
950 {
951 zend_long flags = 0;
952 php_http_encoding_stream_object_t *obj;
953 php_http_encoding_stream_ops_t *ops;
954
955 php_http_expect(SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS(), "|l", &flags), invalid_arg, return);
956
957 obj = PHP_HTTP_OBJ(NULL, getThis());
958
959 if (obj->stream) {
960 php_http_throw(bad_method_call, "http\\Encoding\\Stream cannot be initialized twice", NULL);
961 return;
962 }
963
964 if (instanceof_function(obj->zo.ce, php_http_deflate_stream_class_entry)) {
965 ops = &php_http_encoding_deflate_ops;
966 } else if (instanceof_function(obj->zo.ce, php_http_inflate_stream_class_entry)) {
967 ops = &php_http_encoding_inflate_ops;
968 } else if (instanceof_function(obj->zo.ce, php_http_dechunk_stream_class_entry)) {
969 ops = &php_http_encoding_dechunk_ops;
970 } else {
971 php_http_throw(runtime, "Unknown http\\Encoding\\Stream class '%s'", obj->zo.ce->name->val);
972 return;
973 }
974
975 php_http_expect(obj->stream = php_http_encoding_stream_init(obj->stream, ops, flags), runtime, return);
976 }
977
978 ZEND_BEGIN_ARG_INFO_EX(ai_HttpEncodingStream_update, 0, 0, 1)
979 ZEND_ARG_INFO(0, data)
980 ZEND_END_ARG_INFO();
981 static PHP_METHOD(HttpEncodingStream, update)
982 {
983 size_t data_len;
984 char *data_str;
985
986 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS(), "s", &data_str, &data_len)) {
987 php_http_encoding_stream_object_t *obj = PHP_HTTP_OBJ(NULL, getThis());
988
989 if (obj->stream) {
990 char *encoded_str = NULL;
991 size_t encoded_len;
992
993 if (SUCCESS == php_http_encoding_stream_update(obj->stream, data_str, data_len, &encoded_str, &encoded_len)) {
994 if (encoded_str) {
995 RETURN_STR(php_http_cs2zs(encoded_str, encoded_len));
996 } else {
997 RETURN_EMPTY_STRING();
998 }
999 }
1000 }
1001 }
1002 }
1003
1004 ZEND_BEGIN_ARG_INFO_EX(ai_HttpEncodingStream_flush, 0, 0, 0)
1005 ZEND_END_ARG_INFO();
1006 static PHP_METHOD(HttpEncodingStream, flush)
1007 {
1008 if (SUCCESS == zend_parse_parameters_none()) {
1009 php_http_encoding_stream_object_t *obj = PHP_HTTP_OBJ(NULL, getThis());
1010
1011 if (obj->stream) {
1012 char *encoded_str = NULL;
1013 size_t encoded_len;
1014
1015 if (SUCCESS == php_http_encoding_stream_flush(obj->stream, &encoded_str, &encoded_len)) {
1016 if (encoded_str) {
1017 RETURN_STR(php_http_cs2zs(encoded_str, encoded_len));
1018 } else {
1019 RETURN_EMPTY_STRING();
1020 }
1021 }
1022 }
1023 }
1024 }
1025
1026 ZEND_BEGIN_ARG_INFO_EX(ai_HttpEncodingStream_done, 0, 0, 0)
1027 ZEND_END_ARG_INFO();
1028 static PHP_METHOD(HttpEncodingStream, done)
1029 {
1030 if (SUCCESS == zend_parse_parameters_none()) {
1031 php_http_encoding_stream_object_t *obj = PHP_HTTP_OBJ(NULL, getThis());
1032
1033 if (obj->stream) {
1034 RETURN_BOOL(php_http_encoding_stream_done(obj->stream));
1035 }
1036 }
1037 }
1038
1039 ZEND_BEGIN_ARG_INFO_EX(ai_HttpEncodingStream_finish, 0, 0, 0)
1040 ZEND_END_ARG_INFO();
1041 static PHP_METHOD(HttpEncodingStream, finish)
1042 {
1043 if (SUCCESS == zend_parse_parameters_none()) {
1044 php_http_encoding_stream_object_t *obj = PHP_HTTP_OBJ(NULL, getThis());
1045
1046 if (obj->stream) {
1047 char *encoded_str = NULL;
1048 size_t encoded_len;
1049
1050 if (SUCCESS == php_http_encoding_stream_finish(obj->stream, &encoded_str, &encoded_len)) {
1051 if (SUCCESS == php_http_encoding_stream_reset(&obj->stream)) {
1052 if (encoded_str) {
1053 RETURN_STR(php_http_cs2zs(encoded_str, encoded_len));
1054 } else {
1055 RETURN_EMPTY_STRING();
1056 }
1057 } else {
1058 PTR_FREE(encoded_str);
1059 }
1060 }
1061 }
1062 }
1063 }
1064
1065 static zend_function_entry php_http_encoding_stream_methods[] = {
1066 PHP_ME(HttpEncodingStream, __construct, ai_HttpEncodingStream___construct, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)
1067 PHP_ME(HttpEncodingStream, update, ai_HttpEncodingStream_update, ZEND_ACC_PUBLIC)
1068 PHP_ME(HttpEncodingStream, flush, ai_HttpEncodingStream_flush, ZEND_ACC_PUBLIC)
1069 PHP_ME(HttpEncodingStream, done, ai_HttpEncodingStream_done, ZEND_ACC_PUBLIC)
1070 PHP_ME(HttpEncodingStream, finish, ai_HttpEncodingStream_finish, ZEND_ACC_PUBLIC)
1071 EMPTY_FUNCTION_ENTRY
1072 };
1073
1074 ZEND_BEGIN_ARG_INFO_EX(ai_HttpDeflateStream_encode, 0, 0, 1)
1075 ZEND_ARG_INFO(0, data)
1076 ZEND_ARG_INFO(0, flags)
1077 ZEND_END_ARG_INFO();
1078 static PHP_METHOD(HttpDeflateStream, encode)
1079 {
1080 char *str;
1081 size_t len;
1082 zend_long flags = 0;
1083
1084 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS(), "s|l", &str, &len, &flags)) {
1085 char *enc_str = NULL;
1086 size_t enc_len;
1087
1088 if (SUCCESS == php_http_encoding_deflate(flags, str, len, &enc_str, &enc_len)) {
1089 if (enc_str) {
1090 RETURN_STR(php_http_cs2zs(enc_str, enc_len));
1091 } else {
1092 RETURN_EMPTY_STRING();
1093 }
1094 }
1095 }
1096 RETURN_FALSE;
1097 }
1098
1099 static zend_function_entry php_http_deflate_stream_methods[] = {
1100 PHP_ME(HttpDeflateStream, encode, ai_HttpDeflateStream_encode, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
1101 EMPTY_FUNCTION_ENTRY
1102 };
1103
1104 ZEND_BEGIN_ARG_INFO_EX(ai_HttpInflateStream_decode, 0, 0, 1)
1105 ZEND_ARG_INFO(0, data)
1106 ZEND_END_ARG_INFO();
1107 static PHP_METHOD(HttpInflateStream, decode)
1108 {
1109 char *str;
1110 size_t len;
1111
1112 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS(), "s", &str, &len)) {
1113 char *enc_str = NULL;
1114 size_t enc_len;
1115
1116 if (SUCCESS == php_http_encoding_inflate(str, len, &enc_str, &enc_len)) {
1117 if (enc_str) {
1118 RETURN_STR(php_http_cs2zs(enc_str, enc_len));
1119 } else {
1120 RETURN_EMPTY_STRING();
1121 }
1122 }
1123 }
1124 RETURN_FALSE;
1125 }
1126
1127 static zend_function_entry php_http_inflate_stream_methods[] = {
1128 PHP_ME(HttpInflateStream, decode, ai_HttpInflateStream_decode, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
1129 EMPTY_FUNCTION_ENTRY
1130 };
1131
1132 ZEND_BEGIN_ARG_INFO_EX(ai_HttpDechunkStream_decode, 0, 0, 1)
1133 ZEND_ARG_INFO(0, data)
1134 ZEND_ARG_INFO(1, decoded_len)
1135 ZEND_END_ARG_INFO();
1136 static PHP_METHOD(HttpDechunkStream, decode)
1137 {
1138 char *str;
1139 size_t len;
1140 zval *zlen = NULL;
1141
1142 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS(), "s|z!", &str, &len, &zlen)) {
1143 const char *end_ptr;
1144 char *enc_str = NULL;
1145 size_t enc_len;
1146
1147 if ((end_ptr = php_http_encoding_dechunk(str, len, &enc_str, &enc_len))) {
1148 if (zlen) {
1149 ZVAL_DEREF(zlen);
1150 zval_dtor(zlen);
1151 ZVAL_LONG(zlen, str + len - end_ptr);
1152 }
1153 if (enc_str) {
1154 RETURN_STR(php_http_cs2zs(enc_str, enc_len));
1155 } else {
1156 RETURN_EMPTY_STRING();
1157 }
1158 }
1159 }
1160 RETURN_FALSE;
1161 }
1162
1163 static zend_function_entry php_http_dechunk_stream_methods[] = {
1164 PHP_ME(HttpDechunkStream, decode, ai_HttpDechunkStream_decode, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
1165 EMPTY_FUNCTION_ENTRY
1166 };
1167
1168 zend_class_entry *php_http_encoding_stream_class_entry;
1169 zend_class_entry *php_http_deflate_stream_class_entry;
1170 zend_class_entry *php_http_inflate_stream_class_entry;
1171 zend_class_entry *php_http_dechunk_stream_class_entry;
1172
1173 PHP_MINIT_FUNCTION(http_encoding)
1174 {
1175 zend_class_entry ce = {0};
1176
1177 INIT_NS_CLASS_ENTRY(ce, "http\\Encoding", "Stream", php_http_encoding_stream_methods);
1178 php_http_encoding_stream_class_entry = zend_register_internal_class(&ce);
1179 php_http_encoding_stream_class_entry->ce_flags |= ZEND_ACC_EXPLICIT_ABSTRACT_CLASS;
1180 php_http_encoding_stream_class_entry->create_object = php_http_encoding_stream_object_new;
1181 memcpy(&php_http_encoding_stream_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
1182 php_http_encoding_stream_object_handlers.offset = XtOffsetOf(php_http_encoding_stream_object_t, zo);
1183 php_http_encoding_stream_object_handlers.clone_obj = php_http_encoding_stream_object_clone;
1184 php_http_encoding_stream_object_handlers.free_obj = php_http_encoding_stream_object_free;
1185
1186 zend_declare_class_constant_long(php_http_encoding_stream_class_entry, ZEND_STRL("FLUSH_NONE"), PHP_HTTP_ENCODING_STREAM_FLUSH_NONE);
1187 zend_declare_class_constant_long(php_http_encoding_stream_class_entry, ZEND_STRL("FLUSH_SYNC"), PHP_HTTP_ENCODING_STREAM_FLUSH_SYNC);
1188 zend_declare_class_constant_long(php_http_encoding_stream_class_entry, ZEND_STRL("FLUSH_FULL"), PHP_HTTP_ENCODING_STREAM_FLUSH_FULL);
1189
1190 memset(&ce, 0, sizeof(ce));
1191 INIT_NS_CLASS_ENTRY(ce, "http\\Encoding\\Stream", "Deflate", php_http_deflate_stream_methods);
1192 php_http_deflate_stream_class_entry = zend_register_internal_class_ex(&ce, php_http_encoding_stream_class_entry);
1193 php_http_deflate_stream_class_entry->create_object = php_http_encoding_stream_object_new;
1194
1195 zend_declare_class_constant_long(php_http_deflate_stream_class_entry, ZEND_STRL("TYPE_GZIP"), PHP_HTTP_DEFLATE_TYPE_GZIP);
1196 zend_declare_class_constant_long(php_http_deflate_stream_class_entry, ZEND_STRL("TYPE_ZLIB"), PHP_HTTP_DEFLATE_TYPE_ZLIB);
1197 zend_declare_class_constant_long(php_http_deflate_stream_class_entry, ZEND_STRL("TYPE_RAW"), PHP_HTTP_DEFLATE_TYPE_RAW);
1198 zend_declare_class_constant_long(php_http_deflate_stream_class_entry, ZEND_STRL("LEVEL_DEF"), PHP_HTTP_DEFLATE_LEVEL_DEF);
1199 zend_declare_class_constant_long(php_http_deflate_stream_class_entry, ZEND_STRL("LEVEL_MIN"), PHP_HTTP_DEFLATE_LEVEL_MIN);
1200 zend_declare_class_constant_long(php_http_deflate_stream_class_entry, ZEND_STRL("LEVEL_MAX"), PHP_HTTP_DEFLATE_LEVEL_MAX);
1201 zend_declare_class_constant_long(php_http_deflate_stream_class_entry, ZEND_STRL("STRATEGY_DEF"), PHP_HTTP_DEFLATE_STRATEGY_DEF);
1202 zend_declare_class_constant_long(php_http_deflate_stream_class_entry, ZEND_STRL("STRATEGY_FILT"), PHP_HTTP_DEFLATE_STRATEGY_FILT);
1203 zend_declare_class_constant_long(php_http_deflate_stream_class_entry, ZEND_STRL("STRATEGY_HUFF"), PHP_HTTP_DEFLATE_STRATEGY_HUFF);
1204 zend_declare_class_constant_long(php_http_deflate_stream_class_entry, ZEND_STRL("STRATEGY_RLE"), PHP_HTTP_DEFLATE_STRATEGY_RLE);
1205 zend_declare_class_constant_long(php_http_deflate_stream_class_entry, ZEND_STRL("STRATEGY_FIXED"), PHP_HTTP_DEFLATE_STRATEGY_FIXED);
1206
1207 memset(&ce, 0, sizeof(ce));
1208 INIT_NS_CLASS_ENTRY(ce, "http\\Encoding\\Stream", "Inflate", php_http_inflate_stream_methods);
1209 php_http_inflate_stream_class_entry = zend_register_internal_class_ex(&ce, php_http_encoding_stream_class_entry);
1210 php_http_inflate_stream_class_entry->create_object = php_http_encoding_stream_object_new;
1211
1212 memset(&ce, 0, sizeof(ce));
1213 INIT_NS_CLASS_ENTRY(ce, "http\\Encoding\\Stream", "Dechunk", php_http_dechunk_stream_methods);
1214 php_http_dechunk_stream_class_entry = zend_register_internal_class_ex(&ce, php_http_encoding_stream_class_entry);
1215 php_http_dechunk_stream_class_entry->create_object = php_http_encoding_stream_object_new;
1216
1217 return SUCCESS;
1218 }
1219
1220
1221 /*
1222 * Local variables:
1223 * tab-width: 4
1224 * c-basic-offset: 4
1225 * End:
1226 * vim600: noet sw=4 ts=4 fdm=marker
1227 * vim<600: noet sw=4 ts=4
1228 */
1229