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-2007, Michael Wallner <mike@php.net> |
10 : +--------------------------------------------------------------------+
11 : */
12 :
13 : /* $Id: http_inflatestream_object.c,v 1.14 2007/02/22 11:04:37 mike Exp $ */
14 :
15 : #define HTTP_WANT_ZLIB
16 : #include "php_http.h"
17 :
18 : #if defined(ZEND_ENGINE_2) && defined(HTTP_HAVE_ZLIB)
19 :
20 : #include "php_http_api.h"
21 : #include "php_http_encoding_api.h"
22 : #include "php_http_exception_object.h"
23 : #include "php_http_inflatestream_object.h"
24 :
25 : #define HTTP_BEGIN_ARGS(method, req_args) HTTP_BEGIN_ARGS_EX(HttpInflateStream, method, 0, req_args)
26 : #define HTTP_EMPTY_ARGS(method) HTTP_EMPTY_ARGS_EX(HttpInflateStream, method, 0)
27 : #define HTTP_INFLATE_ME(method, visibility) PHP_ME(HttpInflateStream, method, HTTP_ARGS(HttpInflateStream, method), visibility)
28 :
29 : HTTP_BEGIN_ARGS(__construct, 0)
30 : HTTP_ARG_VAL(flags, 0)
31 : HTTP_END_ARGS;
32 :
33 : HTTP_BEGIN_ARGS(factory, 0)
34 : HTTP_ARG_VAL(flags, 0)
35 : HTTP_ARG_VAL(class_name, 0)
36 : HTTP_END_ARGS;
37 :
38 : HTTP_BEGIN_ARGS(update, 1)
39 : HTTP_ARG_VAL(data, 0)
40 : HTTP_END_ARGS;
41 :
42 : HTTP_BEGIN_ARGS(flush, 0)
43 : HTTP_ARG_VAL(data, 0)
44 : HTTP_END_ARGS;
45 :
46 : HTTP_BEGIN_ARGS(finish, 0)
47 : HTTP_ARG_VAL(data, 0)
48 : HTTP_END_ARGS;
49 :
50 : #define THIS_CE http_inflatestream_object_ce
51 : zend_class_entry *http_inflatestream_object_ce;
52 : zend_function_entry http_inflatestream_object_fe[] = {
53 : HTTP_INFLATE_ME(__construct, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)
54 : HTTP_INFLATE_ME(update, ZEND_ACC_PUBLIC)
55 : HTTP_INFLATE_ME(flush, ZEND_ACC_PUBLIC)
56 : HTTP_INFLATE_ME(finish, ZEND_ACC_PUBLIC)
57 :
58 : HTTP_INFLATE_ME(factory, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
59 :
60 : EMPTY_FUNCTION_ENTRY
61 : };
62 : static zend_object_handlers http_inflatestream_object_handlers;
63 :
64 : PHP_MINIT_FUNCTION(http_inflatestream_object)
65 220 : {
66 220 : HTTP_REGISTER_CLASS_EX(HttpInflateStream, http_inflatestream_object, NULL, 0);
67 220 : http_inflatestream_object_handlers.clone_obj = _http_inflatestream_object_clone_obj;
68 :
69 : #ifndef WONKY
70 220 : zend_declare_class_constant_long(THIS_CE, ZEND_STRS("FLUSH_NONE")-1, HTTP_ENCODING_STREAM_FLUSH_NONE TSRMLS_CC);
71 220 : zend_declare_class_constant_long(THIS_CE, ZEND_STRS("FLUSH_SYNC")-1, HTTP_ENCODING_STREAM_FLUSH_SYNC TSRMLS_CC);
72 220 : zend_declare_class_constant_long(THIS_CE, ZEND_STRS("FLUSH_FULL")-1, HTTP_ENCODING_STREAM_FLUSH_FULL TSRMLS_CC);
73 : #endif
74 :
75 220 : return SUCCESS;
76 : }
77 :
78 : zend_object_value _http_inflatestream_object_new(zend_class_entry *ce TSRMLS_DC)
79 1 : {
80 1 : return http_inflatestream_object_new_ex(ce, NULL, NULL);
81 : }
82 :
83 : zend_object_value _http_inflatestream_object_new_ex(zend_class_entry *ce, http_encoding_stream *s, http_inflatestream_object **ptr TSRMLS_DC)
84 1 : {
85 : zend_object_value ov;
86 : http_inflatestream_object *o;
87 :
88 1 : o = ecalloc(1, sizeof(http_inflatestream_object));
89 1 : o->zo.ce = ce;
90 :
91 1 : if (ptr) {
92 0 : *ptr = o;
93 : }
94 :
95 1 : if (s) {
96 0 : o->stream = s;
97 : }
98 :
99 1 : ALLOC_HASHTABLE(OBJ_PROP(o));
100 1 : zend_hash_init(OBJ_PROP(o), zend_hash_num_elements(&ce->default_properties), NULL, ZVAL_PTR_DTOR, 0);
101 1 : zend_hash_copy(OBJ_PROP(o), &ce->default_properties, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
102 :
103 1 : ov.handle = putObject(http_inflatestream_object, o);
104 1 : ov.handlers = &http_inflatestream_object_handlers;
105 :
106 1 : return ov;
107 : }
108 :
109 : zend_object_value _http_inflatestream_object_clone_obj(zval *this_ptr TSRMLS_DC)
110 0 : {
111 : http_encoding_stream *s;
112 : zend_object_value new_ov;
113 0 : http_inflatestream_object *new_obj = NULL;
114 0 : getObject(http_inflatestream_object, old_obj);
115 :
116 0 : s = ecalloc(1, sizeof(http_encoding_stream));
117 0 : s->flags = old_obj->stream->flags;
118 0 : inflateCopy(&s->stream, &old_obj->stream->stream);
119 0 : s->stream.opaque = phpstr_dup(s->stream.opaque);
120 :
121 0 : new_ov = http_inflatestream_object_new_ex(old_obj->zo.ce, s, &new_obj);
122 0 : zend_objects_clone_members(&new_obj->zo, new_ov, &old_obj->zo, Z_OBJ_HANDLE_P(this_ptr) TSRMLS_CC);
123 :
124 0 : return new_ov;
125 : }
126 :
127 : void _http_inflatestream_object_free(zend_object *object TSRMLS_DC)
128 1 : {
129 1 : http_inflatestream_object *o = (http_inflatestream_object *) object;
130 :
131 1 : if (o->stream) {
132 1 : http_encoding_inflate_stream_free(&o->stream);
133 : }
134 1 : freeObject(o);
135 1 : }
136 :
137 : /* {{{ proto void HttpInflateStream::__construct([int flags = 0])
138 : Creates a new HttpInflateStream object instance. */
139 : PHP_METHOD(HttpInflateStream, __construct)
140 1 : {
141 1 : long flags = 0;
142 :
143 1 : SET_EH_THROW_HTTP();
144 1 : if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &flags)) {
145 1 : getObject(http_inflatestream_object, obj);
146 :
147 1 : if (!obj->stream) {
148 1 : obj->stream = http_encoding_inflate_stream_init(NULL, flags & 0x0fffffff);
149 : } else {
150 0 : http_error_ex(HE_WARNING, HTTP_E_ENCODING, "HttpInflateStream cannot be initialized twice");
151 : }
152 : }
153 1 : SET_EH_NORMAL();
154 1 : }
155 : /* }}} */
156 :
157 : /* {{{ proto HttpInflateStream HttpInflateStream::factory([int flags[, string class = "HttpInflateStream"]])
158 : Creates a new HttpInflateStream object instance. */
159 : PHP_METHOD(HttpInflateStream, factory)
160 0 : {
161 0 : long flags = 0;
162 0 : char *cn = NULL;
163 0 : int cl = 0;
164 :
165 0 : SET_EH_THROW_HTTP();
166 0 : if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|ls", &flags, &cn, &cl)) {
167 : zend_object_value ov;
168 0 : http_encoding_stream *s = http_encoding_inflate_stream_init(NULL, flags & 0x0fffffff);
169 :
170 0 : if (SUCCESS == http_object_new(&ov, cn, cl, _http_inflatestream_object_new_ex, http_inflatestream_object_ce, s, NULL)) {
171 0 : RETVAL_OBJVAL(ov, 0);
172 : }
173 : }
174 0 : SET_EH_NORMAL();
175 0 : }
176 : /* }}} */
177 :
178 : /* {{{ proto string HttpInflateStream::update(string data)
179 : Passes more data through the inflate stream. */
180 : PHP_METHOD(HttpInflateStream, update)
181 111 : {
182 : int data_len;
183 111 : size_t decoded_len = 0;
184 111 : char *data, *decoded = NULL;
185 111 : getObject(http_inflatestream_object, obj);
186 :
187 111 : if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &data, &data_len)) {
188 0 : RETURN_FALSE;
189 : }
190 :
191 111 : if (!data_len) {
192 110 : RETURN_STRING("", 1);
193 : }
194 :
195 1 : if (!obj->stream && !(obj->stream = http_encoding_inflate_stream_init(NULL, 0))) {
196 0 : RETURN_FALSE;
197 : }
198 :
199 1 : if (SUCCESS == http_encoding_inflate_stream_update(obj->stream, data, data_len, &decoded, &decoded_len)) {
200 1 : RETURN_STRINGL(decoded, decoded_len, 0);
201 : } else {
202 0 : RETURN_FALSE;
203 : }
204 : }
205 : /* }}} */
206 :
207 : /* {{{ proto string HttpInflateStream::flush([string data])
208 : Flush the inflate stream. */
209 : PHP_METHOD(HttpInflateStream, flush)
210 1 : {
211 1 : int data_len = 0;
212 1 : size_t decoded_len = 0;
213 1 : char *decoded = NULL, *data = NULL;
214 1 : getObject(http_inflatestream_object, obj);
215 :
216 1 : if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &data, &data_len)) {
217 0 : RETURN_FALSE;
218 : }
219 :
220 1 : if (!obj->stream && !(obj->stream = http_encoding_inflate_stream_init(NULL, 0))) {
221 0 : RETURN_FALSE;
222 : }
223 :
224 : /* flushing the inflate stream is a no-op */
225 1 : if (!data_len) {
226 0 : RETURN_STRINGL("", 0, 1);
227 1 : } else if (SUCCESS == http_encoding_inflate_stream_update(obj->stream, data, data_len, &decoded, &decoded_len)) {
228 1 : RETURN_STRINGL(decoded, decoded_len, 0);
229 : } else {
230 0 : RETURN_FALSE;
231 : }
232 : }
233 : /* }}} */
234 :
235 : /* {{{ proto string HttpInflateStream::finish([string data])
236 : Finalizes the inflate stream. The inflate stream can be reused after finalizing. */
237 : PHP_METHOD(HttpInflateStream, finish)
238 3 : {
239 3 : int data_len = 0;
240 3 : size_t updated_len = 0, decoded_len = 0;
241 3 : char *updated = NULL, *decoded = NULL, *data = NULL;
242 3 : getObject(http_inflatestream_object, obj);
243 :
244 3 : if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &data, &data_len)) {
245 0 : RETURN_FALSE;
246 : }
247 :
248 3 : if (!obj->stream && !(obj->stream = http_encoding_inflate_stream_init(NULL, 0))) {
249 0 : RETURN_FALSE;
250 : }
251 :
252 3 : if (data_len) {
253 3 : if (SUCCESS != http_encoding_inflate_stream_update(obj->stream, data, data_len, &updated, &updated_len)) {
254 0 : RETURN_FALSE;
255 : }
256 : }
257 :
258 3 : if (SUCCESS == http_encoding_inflate_stream_finish(obj->stream, &decoded, &decoded_len)) {
259 3 : if (updated_len) {
260 3 : updated = erealloc(updated, updated_len + decoded_len + 1);
261 3 : updated[updated_len + decoded_len] = '\0';
262 3 : memcpy(updated + updated_len, decoded, decoded_len);
263 3 : STR_FREE(decoded);
264 3 : updated_len += decoded_len;
265 3 : RETVAL_STRINGL(updated, updated_len, 0);
266 : } else {
267 0 : STR_FREE(updated);
268 0 : RETVAL_STRINGL(decoded, decoded_len, 0);
269 : }
270 : } else {
271 0 : STR_FREE(updated);
272 0 : RETVAL_FALSE;
273 : }
274 :
275 3 : http_encoding_inflate_stream_dtor(obj->stream);
276 3 : http_encoding_inflate_stream_init(obj->stream, obj->stream->flags);
277 : }
278 : /* }}} */
279 :
280 : #endif /* ZEND_ENGINE_2 && HTTP_HAVE_ZLIB*/
281 :
282 : /*
283 : * Local variables:
284 : * tab-width: 4
285 : * c-basic-offset: 4
286 : * End:
287 : * vim600: noet sw=4 ts=4 fdm=marker
288 : * vim<600: noet sw=4 ts=4
289 : */
290 :
|