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