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_deflatestream_object.c,v 1.13 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_deflatestream_object.h"
24 :
25 : #define HTTP_BEGIN_ARGS(method, req_args) HTTP_BEGIN_ARGS_EX(HttpDeflateStream, method, 0, req_args)
26 : #define HTTP_EMPTY_ARGS(method) HTTP_EMPTY_ARGS_EX(HttpDeflateStream, method, 0)
27 : #define HTTP_DEFLATE_ME(method, visibility) PHP_ME(HttpDeflateStream, method, HTTP_ARGS(HttpDeflateStream, 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_deflatestream_object_ce
51 : zend_class_entry *http_deflatestream_object_ce;
52 : zend_function_entry http_deflatestream_object_fe[] = {
53 : HTTP_DEFLATE_ME(__construct, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)
54 : HTTP_DEFLATE_ME(update, ZEND_ACC_PUBLIC)
55 : HTTP_DEFLATE_ME(flush, ZEND_ACC_PUBLIC)
56 : HTTP_DEFLATE_ME(finish, ZEND_ACC_PUBLIC)
57 :
58 : HTTP_DEFLATE_ME(factory, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
59 :
60 : EMPTY_FUNCTION_ENTRY
61 : };
62 : static zend_object_handlers http_deflatestream_object_handlers;
63 :
64 : PHP_MINIT_FUNCTION(http_deflatestream_object)
65 220 : {
66 220 : HTTP_REGISTER_CLASS_EX(HttpDeflateStream, http_deflatestream_object, NULL, 0);
67 220 : http_deflatestream_object_handlers.clone_obj = _http_deflatestream_object_clone_obj;
68 :
69 : #ifndef WONKY
70 220 : zend_declare_class_constant_long(THIS_CE, ZEND_STRS("TYPE_GZIP")-1, HTTP_DEFLATE_TYPE_GZIP TSRMLS_CC);
71 220 : zend_declare_class_constant_long(THIS_CE, ZEND_STRS("TYPE_ZLIB")-1, HTTP_DEFLATE_TYPE_ZLIB TSRMLS_CC);
72 220 : zend_declare_class_constant_long(THIS_CE, ZEND_STRS("TYPE_RAW")-1, HTTP_DEFLATE_TYPE_RAW TSRMLS_CC);
73 220 : zend_declare_class_constant_long(THIS_CE, ZEND_STRS("LEVEL_DEF")-1, HTTP_DEFLATE_LEVEL_DEF TSRMLS_CC);
74 220 : zend_declare_class_constant_long(THIS_CE, ZEND_STRS("LEVEL_MIN")-1, HTTP_DEFLATE_LEVEL_MIN TSRMLS_CC);
75 220 : zend_declare_class_constant_long(THIS_CE, ZEND_STRS("LEVEL_MAX")-1, HTTP_DEFLATE_LEVEL_MAX TSRMLS_CC);
76 220 : zend_declare_class_constant_long(THIS_CE, ZEND_STRS("STRATEGY_DEF")-1, HTTP_DEFLATE_STRATEGY_DEF TSRMLS_CC);
77 220 : zend_declare_class_constant_long(THIS_CE, ZEND_STRS("STRATEGY_FILT")-1, HTTP_DEFLATE_STRATEGY_FILT TSRMLS_CC);
78 220 : zend_declare_class_constant_long(THIS_CE, ZEND_STRS("STRATEGY_HUFF")-1, HTTP_DEFLATE_STRATEGY_HUFF TSRMLS_CC);
79 220 : zend_declare_class_constant_long(THIS_CE, ZEND_STRS("STRATEGY_RLE")-1, HTTP_DEFLATE_STRATEGY_RLE TSRMLS_CC);
80 220 : zend_declare_class_constant_long(THIS_CE, ZEND_STRS("STRATEGY_FIXED")-1, HTTP_DEFLATE_STRATEGY_FIXED TSRMLS_CC);
81 220 : zend_declare_class_constant_long(THIS_CE, ZEND_STRS("FLUSH_NONE")-1, HTTP_ENCODING_STREAM_FLUSH_NONE TSRMLS_CC);
82 220 : zend_declare_class_constant_long(THIS_CE, ZEND_STRS("FLUSH_SYNC")-1, HTTP_ENCODING_STREAM_FLUSH_SYNC TSRMLS_CC);
83 220 : zend_declare_class_constant_long(THIS_CE, ZEND_STRS("FLUSH_FULL")-1, HTTP_ENCODING_STREAM_FLUSH_FULL TSRMLS_CC);
84 : #endif
85 :
86 220 : return SUCCESS;
87 : }
88 :
89 : zend_object_value _http_deflatestream_object_new(zend_class_entry *ce TSRMLS_DC)
90 1 : {
91 1 : return http_deflatestream_object_new_ex(ce, NULL, NULL);
92 : }
93 :
94 : zend_object_value _http_deflatestream_object_new_ex(zend_class_entry *ce, http_encoding_stream *s, http_deflatestream_object **ptr TSRMLS_DC)
95 1 : {
96 : zend_object_value ov;
97 : http_deflatestream_object *o;
98 :
99 1 : o = ecalloc(1, sizeof(http_deflatestream_object));
100 1 : o->zo.ce = ce;
101 :
102 1 : if (ptr) {
103 0 : *ptr = o;
104 : }
105 :
106 1 : if (s) {
107 0 : o->stream = s;
108 : }
109 :
110 1 : ALLOC_HASHTABLE(OBJ_PROP(o));
111 1 : zend_hash_init(OBJ_PROP(o), zend_hash_num_elements(&ce->default_properties), NULL, ZVAL_PTR_DTOR, 0);
112 1 : zend_hash_copy(OBJ_PROP(o), &ce->default_properties, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
113 :
114 1 : ov.handle = putObject(http_deflatestream_object, o);
115 1 : ov.handlers = &http_deflatestream_object_handlers;
116 :
117 1 : return ov;
118 : }
119 :
120 : zend_object_value _http_deflatestream_object_clone_obj(zval *this_ptr TSRMLS_DC)
121 0 : {
122 : http_encoding_stream *s;
123 : zend_object_value new_ov;
124 0 : http_deflatestream_object *new_obj = NULL;
125 0 : getObject(http_deflatestream_object, old_obj);
126 :
127 0 : s = ecalloc(1, sizeof(http_encoding_stream));
128 0 : s->flags = old_obj->stream->flags;
129 0 : deflateCopy(&s->stream, &old_obj->stream->stream);
130 0 : s->stream.opaque = phpstr_dup(s->stream.opaque);
131 :
132 0 : new_ov = http_deflatestream_object_new_ex(old_obj->zo.ce, s, &new_obj);
133 0 : zend_objects_clone_members(&new_obj->zo, new_ov, &old_obj->zo, Z_OBJ_HANDLE_P(this_ptr) TSRMLS_CC);
134 :
135 0 : return new_ov;
136 : }
137 :
138 : void _http_deflatestream_object_free(zend_object *object TSRMLS_DC)
139 1 : {
140 1 : http_deflatestream_object *o = (http_deflatestream_object *) object;
141 :
142 1 : if (o->stream) {
143 1 : http_encoding_deflate_stream_free(&o->stream);
144 : }
145 1 : freeObject(o);
146 1 : }
147 :
148 : /* {{{ proto void HttpDeflateStream::__construct([int flags = 0])
149 : Creates a new HttpDeflateStream object instance. */
150 : PHP_METHOD(HttpDeflateStream, __construct)
151 1 : {
152 1 : long flags = 0;
153 :
154 1 : SET_EH_THROW_HTTP();
155 1 : if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &flags)) {
156 1 : getObject(http_deflatestream_object, obj);
157 :
158 1 : if (!obj->stream) {
159 1 : obj->stream = http_encoding_deflate_stream_init(NULL, flags & 0x0fffffff);
160 : } else {
161 0 : http_error_ex(HE_WARNING, HTTP_E_ENCODING, "HttpDeflateStream cannot be initialized twice");
162 : }
163 : }
164 1 : SET_EH_NORMAL();
165 1 : }
166 : /* }}} */
167 :
168 : /* {{{ proto HttpDeflateStream HttpDeflateStream::factory([int flags[, string class = "HttpDeflateStream"]])
169 : Creates a new HttpDeflateStream object instance. */
170 : PHP_METHOD(HttpDeflateStream, factory)
171 0 : {
172 0 : long flags = 0;
173 0 : char *cn = NULL;
174 0 : int cl = 0;
175 :
176 0 : SET_EH_THROW_HTTP();
177 0 : if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|ls", &flags, &cn, &cl)) {
178 : zend_object_value ov;
179 0 : http_encoding_stream *s = http_encoding_deflate_stream_init(NULL, flags & 0x0fffffff);
180 :
181 0 : if (SUCCESS == http_object_new(&ov, cn, cl, _http_deflatestream_object_new_ex, http_deflatestream_object_ce, s, NULL)) {
182 0 : RETVAL_OBJVAL(ov, 0);
183 : }
184 : }
185 0 : SET_EH_NORMAL();
186 0 : }
187 : /* }}} */
188 :
189 : /* {{{ proto string HttpDeflateStream::update(string data)
190 : Passes more data through the deflate stream. */
191 : PHP_METHOD(HttpDeflateStream, update)
192 111 : {
193 : int data_len;
194 111 : size_t encoded_len = 0;
195 111 : char *data, *encoded = NULL;
196 111 : getObject(http_deflatestream_object, obj);
197 :
198 111 : if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &data, &data_len)) {
199 0 : RETURN_FALSE;
200 : }
201 :
202 111 : if (!obj->stream && !(obj->stream = http_encoding_deflate_stream_init(NULL, 0))) {
203 0 : RETURN_FALSE;
204 : }
205 :
206 111 : if (SUCCESS == http_encoding_deflate_stream_update(obj->stream, data, data_len, &encoded, &encoded_len)) {
207 111 : RETURN_STRINGL(encoded, encoded_len, 0);
208 : } else {
209 0 : RETURN_FALSE;
210 : }
211 : }
212 : /* }}} */
213 :
214 : /* {{{ proto string HttpDeflateStream::flush([string data])
215 : Flushes the deflate stream. */
216 : PHP_METHOD(HttpDeflateStream, flush)
217 1 : {
218 1 : int data_len = 0;
219 1 : size_t updated_len = 0, encoded_len = 0;
220 1 : char *updated = NULL, *encoded = NULL, *data = NULL;
221 1 : getObject(http_deflatestream_object, obj);
222 :
223 1 : if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &data, &data_len)) {
224 0 : RETURN_FALSE;
225 : }
226 :
227 1 : if (!obj->stream && !(obj->stream = http_encoding_deflate_stream_init(NULL, 0))) {
228 0 : RETURN_FALSE;
229 : }
230 :
231 1 : if (data_len) {
232 1 : if (SUCCESS != http_encoding_deflate_stream_update(obj->stream, data, data_len, &updated, &updated_len)) {
233 0 : RETURN_FALSE;
234 : }
235 : }
236 :
237 1 : if (SUCCESS == http_encoding_deflate_stream_flush(obj->stream, &encoded, &encoded_len)) {
238 1 : if (updated_len) {
239 1 : updated = erealloc(updated, updated_len + encoded_len + 1);
240 1 : updated[updated_len + encoded_len] = '\0';
241 1 : memcpy(updated + updated_len, encoded, encoded_len);
242 1 : STR_FREE(encoded);
243 1 : updated_len += encoded_len;
244 1 : RETURN_STRINGL(updated, updated_len, 0);
245 : } else {
246 0 : RETVAL_STRINGL(encoded, encoded_len, 0);
247 : }
248 : } else {
249 0 : RETVAL_FALSE;
250 : }
251 0 : STR_FREE(updated);
252 : }
253 : /* }}} */
254 :
255 : /* {{{ proto string HttpDeflateStream::finish([string data])
256 : Finalizes the deflate stream. The deflate stream can be reused after finalizing. */
257 : PHP_METHOD(HttpDeflateStream, finish)
258 3 : {
259 3 : int data_len = 0;
260 3 : size_t updated_len = 0, encoded_len = 0;
261 3 : char *updated = NULL, *encoded = NULL, *data = NULL;
262 3 : getObject(http_deflatestream_object, obj);
263 :
264 3 : if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &data, &data_len)) {
265 0 : RETURN_FALSE;
266 : }
267 :
268 3 : if (!obj->stream && !(obj->stream = http_encoding_deflate_stream_init(NULL, 0))) {
269 0 : RETURN_FALSE;
270 : }
271 :
272 3 : if (data_len) {
273 2 : if (SUCCESS != http_encoding_deflate_stream_update(obj->stream, data, data_len, &updated, &updated_len)) {
274 0 : RETURN_FALSE;
275 : }
276 : }
277 :
278 3 : if (SUCCESS == http_encoding_deflate_stream_finish(obj->stream, &encoded, &encoded_len)) {
279 3 : if (updated_len) {
280 1 : updated = erealloc(updated, updated_len + encoded_len + 1);
281 1 : updated[updated_len + encoded_len] = '\0';
282 1 : memcpy(updated + updated_len, encoded, encoded_len);
283 1 : STR_FREE(encoded);
284 1 : updated_len += encoded_len;
285 1 : RETVAL_STRINGL(updated, updated_len, 0);
286 : } else {
287 2 : STR_FREE(updated);
288 2 : RETVAL_STRINGL(encoded, encoded_len, 0);
289 : }
290 : } else {
291 0 : STR_FREE(updated);
292 0 : RETVAL_FALSE;
293 : }
294 :
295 3 : http_encoding_deflate_stream_dtor(obj->stream);
296 3 : http_encoding_deflate_stream_init(obj->stream, obj->stream->flags);
297 : }
298 : /* }}} */
299 :
300 : #endif /* ZEND_ENGINE_2 && HTTP_HAVE_ZLIB*/
301 :
302 : /*
303 : * Local variables:
304 : * tab-width: 4
305 : * c-basic-offset: 4
306 : * End:
307 : * vim600: noet sw=4 ts=4 fdm=marker
308 : * vim<600: noet sw=4 ts=4
309 : */
310 :
|