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