1 : /*
2 : +----------------------------------------------------------------------+
3 : | PHP Version 5 |
4 : +----------------------------------------------------------------------+
5 : | Copyright (c) 1997-2009 The PHP Group |
6 : +----------------------------------------------------------------------+
7 : | This source file is subject to version 3.01 of the PHP license, |
8 : | that is bundled with this package in the file LICENSE, and is |
9 : | available through the world-wide-web at the following url: |
10 : | http://www.php.net/license/3_01.txt |
11 : | If you did not receive a copy of the PHP license and are unable to |
12 : | obtain it through the world-wide-web, please send a note to |
13 : | license@php.net so we can mail you a copy immediately. |
14 : +----------------------------------------------------------------------+
15 : | Author: Sterling Hughes <sterling@php.net> |
16 : +----------------------------------------------------------------------+
17 : */
18 :
19 : /* $Id: bz2.c 272374 2008-12-31 11:17:49Z sebastian $ */
20 :
21 : #ifdef HAVE_CONFIG_H
22 : #include "config.h"
23 : #endif
24 :
25 : #include "php.h"
26 : #include "php_bz2.h"
27 :
28 : #if HAVE_BZ2
29 :
30 : /* PHP Includes */
31 : #include "ext/standard/file.h"
32 : #include "ext/standard/info.h"
33 : #include "ext/standard/php_string.h"
34 :
35 : /* for fileno() */
36 : #include <stdio.h>
37 :
38 : /* Internal error constants */
39 : #define PHP_BZ_ERRNO 0
40 : #define PHP_BZ_ERRSTR 1
41 : #define PHP_BZ_ERRBOTH 2
42 :
43 : static PHP_MINIT_FUNCTION(bz2);
44 : static PHP_MSHUTDOWN_FUNCTION(bz2);
45 : static PHP_MINFO_FUNCTION(bz2);
46 : static PHP_FUNCTION(bzopen);
47 : static PHP_FUNCTION(bzread);
48 : static PHP_FUNCTION(bzerrno);
49 : static PHP_FUNCTION(bzerrstr);
50 : static PHP_FUNCTION(bzerror);
51 : static PHP_FUNCTION(bzcompress);
52 : static PHP_FUNCTION(bzdecompress);
53 :
54 : /* {{{ arginfo */
55 : static
56 : ZEND_BEGIN_ARG_INFO_EX(arginfo_bzread, 0, 0, 1)
57 : ZEND_ARG_INFO(0, bz)
58 : ZEND_ARG_INFO(0, length)
59 : ZEND_END_ARG_INFO()
60 :
61 : static
62 : ZEND_BEGIN_ARG_INFO(arginfo_bzopen, 0)
63 : ZEND_ARG_INFO(0, file)
64 : ZEND_ARG_INFO(0, mode)
65 : ZEND_END_ARG_INFO()
66 :
67 : static
68 : ZEND_BEGIN_ARG_INFO(arginfo_bzerrno, 0)
69 : ZEND_ARG_INFO(0, bz)
70 : ZEND_END_ARG_INFO()
71 :
72 : static
73 : ZEND_BEGIN_ARG_INFO(arginfo_bzerrstr, 0)
74 : ZEND_ARG_INFO(0, bz)
75 : ZEND_END_ARG_INFO()
76 :
77 : static
78 : ZEND_BEGIN_ARG_INFO(arginfo_bzerror, 0)
79 : ZEND_ARG_INFO(0, bz)
80 : ZEND_END_ARG_INFO()
81 :
82 : static
83 : ZEND_BEGIN_ARG_INFO_EX(arginfo_bzcompress, 0, 0, 2)
84 : ZEND_ARG_INFO(0, source)
85 : ZEND_ARG_INFO(0, blocksize)
86 : ZEND_ARG_INFO(0, workfactor)
87 : ZEND_END_ARG_INFO()
88 :
89 : static
90 : ZEND_BEGIN_ARG_INFO_EX(arginfo_bzdecompress, 0, 0, 1)
91 : ZEND_ARG_INFO(0, source)
92 : ZEND_ARG_INFO(0, small)
93 : ZEND_END_ARG_INFO()
94 :
95 : /* }}} */
96 :
97 : static zend_function_entry bz2_functions[] = {
98 : PHP_FE(bzopen, arginfo_bzopen)
99 : PHP_FE(bzread, arginfo_bzread)
100 : PHP_FALIAS(bzwrite, fwrite, NULL)
101 : PHP_FALIAS(bzflush, fflush, NULL)
102 : PHP_FALIAS(bzclose, fclose, NULL)
103 : PHP_FE(bzerrno, arginfo_bzerrno)
104 : PHP_FE(bzerrstr, arginfo_bzerrstr)
105 : PHP_FE(bzerror, arginfo_bzerror)
106 : PHP_FE(bzcompress, arginfo_bzcompress)
107 : PHP_FE(bzdecompress, arginfo_bzdecompress)
108 : {NULL, NULL, NULL}
109 : };
110 :
111 : zend_module_entry bz2_module_entry = {
112 : STANDARD_MODULE_HEADER,
113 : "bz2",
114 : bz2_functions,
115 : PHP_MINIT(bz2),
116 : PHP_MSHUTDOWN(bz2),
117 : NULL,
118 : NULL,
119 : PHP_MINFO(bz2),
120 : NO_VERSION_YET,
121 : STANDARD_MODULE_PROPERTIES
122 : };
123 :
124 : #ifdef COMPILE_DL_BZ2
125 : ZEND_GET_MODULE(bz2)
126 : #endif
127 :
128 : struct php_bz2_stream_data_t {
129 : BZFILE *bz_file;
130 : php_stream *stream;
131 : };
132 :
133 : /* {{{ BZip2 stream implementation */
134 :
135 : static size_t php_bz2iop_read(php_stream *stream, char *buf, size_t count TSRMLS_DC)
136 8 : {
137 8 : struct php_bz2_stream_data_t *self = (struct php_bz2_stream_data_t *) stream->abstract;
138 : size_t ret;
139 :
140 8 : ret = BZ2_bzread(self->bz_file, buf, count);
141 :
142 8 : if (ret == 0) {
143 2 : stream->eof = 1;
144 : }
145 :
146 8 : return ret;
147 : }
148 :
149 : static size_t php_bz2iop_write(php_stream *stream, const char *buf, size_t count TSRMLS_DC)
150 1 : {
151 1 : struct php_bz2_stream_data_t *self = (struct php_bz2_stream_data_t *) stream->abstract;
152 :
153 1 : return BZ2_bzwrite(self->bz_file, (char*)buf, count);
154 : }
155 :
156 : static int php_bz2iop_close(php_stream *stream, int close_handle TSRMLS_DC)
157 12 : {
158 12 : struct php_bz2_stream_data_t *self = (struct php_bz2_stream_data_t *)stream->abstract;
159 12 : int ret = EOF;
160 :
161 12 : if (close_handle) {
162 12 : BZ2_bzclose(self->bz_file);
163 : }
164 :
165 12 : if (self->stream) {
166 7 : php_stream_free(self->stream, PHP_STREAM_FREE_CLOSE | (close_handle == 0 ? PHP_STREAM_FREE_PRESERVE_HANDLE : 0));
167 : }
168 :
169 12 : efree(self);
170 :
171 12 : return ret;
172 : }
173 :
174 : static int php_bz2iop_flush(php_stream *stream TSRMLS_DC)
175 12 : {
176 12 : struct php_bz2_stream_data_t *self = (struct php_bz2_stream_data_t *)stream->abstract;
177 12 : return BZ2_bzflush(self->bz_file);
178 : }
179 : /* }}} */
180 :
181 : php_stream_ops php_stream_bz2io_ops = {
182 : php_bz2iop_write, php_bz2iop_read,
183 : php_bz2iop_close, php_bz2iop_flush,
184 : "BZip2",
185 : NULL, /* seek */
186 : NULL, /* cast */
187 : NULL, /* stat */
188 : NULL /* set_option */
189 : };
190 :
191 : /* {{{ Bzip2 stream openers */
192 : PHP_BZ2_API php_stream *_php_stream_bz2open_from_BZFILE(BZFILE *bz,
193 : char *mode, php_stream *innerstream STREAMS_DC TSRMLS_DC)
194 12 : {
195 : struct php_bz2_stream_data_t *self;
196 :
197 12 : self = emalloc(sizeof(*self));
198 :
199 12 : self->stream = innerstream;
200 12 : self->bz_file = bz;
201 :
202 12 : return php_stream_alloc_rel(&php_stream_bz2io_ops, self, 0, mode);
203 : }
204 :
205 : PHP_BZ2_API php_stream *_php_stream_bz2open(php_stream_wrapper *wrapper,
206 : char *path,
207 : char *mode,
208 : int options,
209 : char **opened_path,
210 : php_stream_context *context STREAMS_DC TSRMLS_DC)
211 6 : {
212 6 : php_stream *retstream = NULL, *stream = NULL;
213 6 : char *path_copy = NULL;
214 6 : BZFILE *bz_file = NULL;
215 :
216 6 : if (strncasecmp("compress.bzip2://", path, 17) == 0) {
217 0 : path += 17;
218 : }
219 6 : if (mode[0] == '\0' || (mode[0] != 'w' && mode[0] != 'r' && mode[1] != '\0')) {
220 0 : return NULL;
221 : }
222 :
223 : #ifdef VIRTUAL_DIR
224 : virtual_filepath_ex(path, &path_copy, NULL TSRMLS_CC);
225 : #else
226 6 : path_copy = path;
227 : #endif
228 :
229 6 : if ((PG(safe_mode) && (!php_checkuid(path_copy, NULL, CHECKUID_CHECK_FILE_AND_DIR))) || php_check_open_basedir(path_copy TSRMLS_CC)) {
230 0 : return NULL;
231 : }
232 :
233 : /* try and open it directly first */
234 6 : bz_file = BZ2_bzopen(path_copy, mode);
235 :
236 6 : if (opened_path && bz_file) {
237 0 : *opened_path = estrdup(path_copy);
238 : }
239 6 : path_copy = NULL;
240 :
241 6 : if (bz_file == NULL) {
242 : /* that didn't work, so try and get something from the network/wrapper */
243 1 : stream = php_stream_open_wrapper(path, mode, options | STREAM_WILL_CAST | ENFORCE_SAFE_MODE, opened_path);
244 :
245 1 : if (stream) {
246 : int fd;
247 0 : if (SUCCESS == php_stream_cast(stream, PHP_STREAM_AS_FD, (void **) &fd, REPORT_ERRORS)) {
248 0 : bz_file = BZ2_bzdopen(fd, mode);
249 : }
250 : }
251 :
252 : /* remove the file created by php_stream_open_wrapper(), it is not needed since BZ2 functions
253 : * failed.
254 : */
255 1 : if (opened_path && !bz_file && mode[0] == 'w') {
256 0 : VCWD_UNLINK(*opened_path);
257 : }
258 : }
259 :
260 6 : if (bz_file) {
261 5 : retstream = _php_stream_bz2open_from_BZFILE(bz_file, mode, stream STREAMS_REL_CC TSRMLS_CC);
262 5 : if (retstream) {
263 5 : return retstream;
264 : }
265 :
266 0 : BZ2_bzclose(bz_file);
267 : }
268 :
269 1 : if (stream) {
270 0 : php_stream_close(stream);
271 : }
272 :
273 1 : return NULL;
274 : }
275 :
276 : /* }}} */
277 :
278 : static php_stream_wrapper_ops bzip2_stream_wops = {
279 : _php_stream_bz2open,
280 : NULL, /* close */
281 : NULL, /* fstat */
282 : NULL, /* stat */
283 : NULL, /* opendir */
284 : "BZip2",
285 : NULL, /* unlink */
286 : NULL, /* rename */
287 : NULL, /* mkdir */
288 : NULL /* rmdir */
289 : };
290 :
291 : static php_stream_wrapper php_stream_bzip2_wrapper = {
292 : &bzip2_stream_wops,
293 : NULL,
294 : 0 /* is_url */
295 : };
296 :
297 : static void php_bz2_error(INTERNAL_FUNCTION_PARAMETERS, int);
298 :
299 : static PHP_MINIT_FUNCTION(bz2)
300 13565 : {
301 13565 : php_register_url_stream_wrapper("compress.bzip2", &php_stream_bzip2_wrapper TSRMLS_CC);
302 13565 : php_stream_filter_register_factory("bzip2.*", &php_bz2_filter_factory TSRMLS_CC);
303 13565 : return SUCCESS;
304 : }
305 :
306 : static PHP_MSHUTDOWN_FUNCTION(bz2)
307 13597 : {
308 13597 : php_unregister_url_stream_wrapper("compress.bzip2" TSRMLS_CC);
309 13597 : php_stream_filter_unregister_factory("bzip2.*" TSRMLS_CC);
310 :
311 13597 : return SUCCESS;
312 : }
313 :
314 : static PHP_MINFO_FUNCTION(bz2)
315 6 : {
316 6 : php_info_print_table_start();
317 6 : php_info_print_table_row(2, "BZip2 Support", "Enabled");
318 6 : php_info_print_table_row(2, "Stream Wrapper support", "compress.bz2://");
319 6 : php_info_print_table_row(2, "Stream Filter support", "bzip2.decompress, bzip2.compress");
320 6 : php_info_print_table_row(2, "BZip2 Version", (char *) BZ2_bzlibVersion());
321 6 : php_info_print_table_end();
322 6 : }
323 :
324 : /* {{{ proto string bzread(resource bz[, int length])
325 : Reads up to length bytes from a BZip2 stream, or 1024 bytes if length is not specified */
326 : static PHP_FUNCTION(bzread)
327 14 : {
328 : zval *bz;
329 14 : long len = 1024;
330 : php_stream *stream;
331 :
332 14 : if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &bz, &len)) {
333 2 : RETURN_FALSE;
334 : }
335 :
336 12 : php_stream_from_zval(stream, &bz);
337 :
338 11 : if ((len + 1) < 1) {
339 1 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "length may not be negative");
340 1 : RETURN_FALSE;
341 : }
342 :
343 10 : Z_STRVAL_P(return_value) = emalloc(len + 1);
344 10 : Z_STRLEN_P(return_value) = php_stream_read(stream, Z_STRVAL_P(return_value), len);
345 :
346 10 : if (Z_STRLEN_P(return_value) < 0) {
347 0 : efree(Z_STRVAL_P(return_value));
348 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not read valid bz2 data from stream");
349 0 : RETURN_FALSE;
350 : }
351 :
352 10 : Z_STRVAL_P(return_value)[Z_STRLEN_P(return_value)] = 0;
353 :
354 10 : if (PG(magic_quotes_runtime)) {
355 0 : Z_STRVAL_P(return_value) = php_addslashes( Z_STRVAL_P(return_value),
356 : Z_STRLEN_P(return_value),
357 : &Z_STRLEN_P(return_value), 1 TSRMLS_CC);
358 : }
359 :
360 10 : Z_TYPE_P(return_value) = IS_STRING;
361 : }
362 : /* }}} */
363 :
364 : /* {{{ proto resource bzopen(string|int file|fp, string mode)
365 : Opens a new BZip2 stream */
366 : static PHP_FUNCTION(bzopen)
367 33 : {
368 : zval **file, /* The file to open */
369 : **mode; /* The mode to open the stream with */
370 : BZFILE *bz; /* The compressed file stream */
371 33 : php_stream *stream = NULL;
372 :
373 33 : if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &file, &mode) == FAILURE) {
374 1 : WRONG_PARAM_COUNT;
375 : }
376 32 : convert_to_string_ex(mode);
377 :
378 32 : if (Z_STRLEN_PP(mode) != 1 || (Z_STRVAL_PP(mode)[0] != 'r' && Z_STRVAL_PP(mode)[0] != 'w')) {
379 3 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "'%s' is not a valid mode for bzopen(). Only 'w' and 'r' are supported.", Z_STRVAL_PP(mode));
380 3 : RETURN_FALSE;
381 : }
382 :
383 : /* If it's not a resource its a string containing the filename to open */
384 29 : if (Z_TYPE_PP(file) != IS_RESOURCE) {
385 10 : convert_to_string_ex(file);
386 :
387 10 : if (Z_STRLEN_PP(file) == 0) {
388 4 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "filename cannot be empty");
389 4 : RETURN_FALSE;
390 : }
391 :
392 6 : stream = php_stream_bz2open(NULL,
393 : Z_STRVAL_PP(file),
394 : Z_STRVAL_PP(mode),
395 : ENFORCE_SAFE_MODE | REPORT_ERRORS,
396 : NULL);
397 : } else {
398 : /* If it is a resource, than its a stream resource */
399 : int fd;
400 : int stream_mode_len;
401 :
402 19 : php_stream_from_zval(stream, file);
403 19 : stream_mode_len = strlen(stream->mode);
404 :
405 19 : if (stream_mode_len != 1 && !(stream_mode_len == 2 && memchr(stream->mode, 'b', 2))) {
406 8 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "cannot use stream opened in mode '%s'", stream->mode);
407 8 : RETURN_FALSE;
408 11 : } else if (stream_mode_len == 1 && stream->mode[0] != 'r' && stream->mode[0] != 'w' && stream->mode[0] != 'a' && stream->mode[0] != 'x') {
409 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "cannot use stream opened in mode '%s'", stream->mode);
410 0 : RETURN_FALSE;
411 : }
412 :
413 11 : switch(Z_STRVAL_PP(mode)[0]) {
414 : case 'r':
415 : /* only "r" and "rb" are supported */
416 6 : if (stream->mode[0] != Z_STRVAL_PP(mode)[0] && !(stream_mode_len == 2 && stream->mode[1] != Z_STRVAL_PP(mode)[0])) {
417 3 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "cannot read from a stream opened in write only mode");
418 3 : RETURN_FALSE;
419 : }
420 3 : break;
421 : case 'w':
422 : /* support only "w"(b), "a"(b), "x"(b) */
423 5 : if (stream->mode[0] != Z_STRVAL_PP(mode)[0] && !(stream_mode_len == 2 && stream->mode[1] != Z_STRVAL_PP(mode)[0])
424 : && stream->mode[0] != 'a' && !(stream_mode_len == 2 && stream->mode[1] != 'a')
425 : && stream->mode[0] != 'x' && !(stream_mode_len == 2 && stream->mode[1] != 'x')) {
426 1 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "cannot write to a stream opened in read only mode");
427 1 : RETURN_FALSE;
428 : }
429 : break;
430 : default:
431 : /* not reachable */
432 : break;
433 : }
434 :
435 7 : if (FAILURE == php_stream_cast(stream, PHP_STREAM_AS_FD, (void *) &fd, REPORT_ERRORS)) {
436 0 : RETURN_FALSE;
437 : }
438 :
439 7 : bz = BZ2_bzdopen(fd, Z_STRVAL_PP(mode));
440 :
441 7 : stream = php_stream_bz2open_from_BZFILE(bz, Z_STRVAL_PP(mode), stream);
442 : }
443 :
444 13 : if (stream) {
445 12 : php_stream_to_zval(stream, return_value);
446 : } else {
447 1 : RETURN_FALSE;
448 : }
449 : }
450 : /* }}} */
451 :
452 : /* {{{ proto int bzerrno(resource bz)
453 : Returns the error number */
454 : static PHP_FUNCTION(bzerrno)
455 7 : {
456 7 : php_bz2_error(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_BZ_ERRNO);
457 7 : }
458 : /* }}} */
459 :
460 : /* {{{ proto string bzerrstr(resource bz)
461 : Returns the error string */
462 : static PHP_FUNCTION(bzerrstr)
463 7 : {
464 7 : php_bz2_error(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_BZ_ERRSTR);
465 7 : }
466 : /* }}} */
467 :
468 : /* {{{ proto array bzerror(resource bz)
469 : Returns the error number and error string in an associative array */
470 : static PHP_FUNCTION(bzerror)
471 7 : {
472 7 : php_bz2_error(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_BZ_ERRBOTH);
473 7 : }
474 : /* }}} */
475 :
476 : /* {{{ proto string bzcompress(string source [, int blocksize100k [, int workfactor]])
477 : Compresses a string into BZip2 encoded data */
478 : static PHP_FUNCTION(bzcompress)
479 9 : {
480 : zval **source, /* Source data to compress */
481 : **zblock_size, /* Optional block size to use */
482 : **zwork_factor; /* Optional work factor to use */
483 9 : char *dest = NULL; /* Destination to place the compressed data into */
484 : int error, /* Error Container */
485 9 : block_size = 4, /* Block size for compression algorithm */
486 9 : work_factor = 0, /* Work factor for compression algorithm */
487 : argc; /* Argument count */
488 : unsigned int source_len, /* Length of the source data */
489 : dest_len; /* Length of the destination buffer */
490 :
491 9 : argc = ZEND_NUM_ARGS();
492 :
493 9 : if (argc < 1 || argc > 3 || zend_get_parameters_ex(argc, &source, &zblock_size, &zwork_factor) == FAILURE) {
494 1 : WRONG_PARAM_COUNT;
495 : }
496 :
497 8 : convert_to_string_ex(source);
498 :
499 : /* Assign them to easy to use variables, dest_len is initially the length of the data
500 : + .01 x length of data + 600 which is the largest size the results of the compression
501 : could possibly be, at least that's what the libbz2 docs say (thanks to jeremy@nirvani.net
502 : for pointing this out). */
503 8 : source_len = Z_STRLEN_PP(source);
504 8 : dest_len = Z_STRLEN_PP(source) + (0.01 * Z_STRLEN_PP(source)) + 600;
505 :
506 : /* Allocate the destination buffer */
507 8 : dest = emalloc(dest_len + 1);
508 :
509 : /* Handle the optional arguments */
510 8 : if (argc > 1) {
511 6 : convert_to_long_ex(zblock_size);
512 6 : block_size = Z_LVAL_PP(zblock_size);
513 : }
514 :
515 8 : if (argc > 2) {
516 5 : convert_to_long_ex(zwork_factor);
517 5 : work_factor = Z_LVAL_PP(zwork_factor);
518 : }
519 :
520 8 : error = BZ2_bzBuffToBuffCompress(dest, &dest_len, Z_STRVAL_PP(source), source_len, block_size, 0, work_factor);
521 8 : if (error != BZ_OK) {
522 4 : efree(dest);
523 4 : RETURN_LONG(error);
524 : } else {
525 : /* Copy the buffer, we have perhaps allocate alot more than we need,
526 : so we erealloc() the buffer to the proper size */
527 4 : dest = erealloc(dest, dest_len + 1);
528 4 : dest[dest_len] = 0;
529 4 : RETURN_STRINGL(dest, dest_len, 0);
530 : }
531 : }
532 : /* }}} */
533 :
534 : /* {{{ proto string bzdecompress(string source [, int small])
535 : Decompresses BZip2 compressed data */
536 : static PHP_FUNCTION(bzdecompress)
537 11 : {
538 : char *source, *dest;
539 : int source_len, error;
540 11 : long small = 0;
541 : #if defined(PHP_WIN32)
542 : unsigned __int64 size = 0;
543 : #else
544 11 : unsigned long long size = 0;
545 : #endif
546 : bz_stream bzs;
547 :
548 11 : if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &source, &source_len, &small)) {
549 2 : RETURN_FALSE;
550 : }
551 :
552 9 : bzs.bzalloc = NULL;
553 9 : bzs.bzfree = NULL;
554 :
555 9 : if (BZ2_bzDecompressInit(&bzs, 0, small) != BZ_OK) {
556 2 : RETURN_FALSE;
557 : }
558 :
559 7 : bzs.next_in = source;
560 7 : bzs.avail_in = source_len;
561 :
562 : /* in most cases bz2 offers at least 2:1 compression, so we use that as our base */
563 7 : bzs.avail_out = source_len * 2;
564 7 : bzs.next_out = dest = emalloc(bzs.avail_out + 1);
565 :
566 14 : while ((error = BZ2_bzDecompress(&bzs)) == BZ_OK && bzs.avail_in > 0) {
567 : /* compression is better then 2:1, need to allocate more memory */
568 0 : bzs.avail_out = source_len;
569 0 : size = (bzs.total_out_hi32 * (unsigned int) -1) + bzs.total_out_lo32;
570 0 : dest = safe_erealloc(dest, 1, bzs.avail_out+1, size );
571 0 : bzs.next_out = dest + size;
572 : }
573 :
574 11 : if (error == BZ_STREAM_END || error == BZ_OK) {
575 4 : size = (bzs.total_out_hi32 * (unsigned int) -1) + bzs.total_out_lo32;
576 4 : dest = safe_erealloc(dest, 1, size, 1);
577 4 : dest[size] = '\0';
578 4 : RETVAL_STRINGL(dest, size, 0);
579 : } else { /* real error */
580 3 : efree(dest);
581 3 : RETVAL_LONG(error);
582 : }
583 :
584 7 : BZ2_bzDecompressEnd(&bzs);
585 : }
586 : /* }}} */
587 :
588 : /* {{{ php_bz2_error()
589 : The central error handling interface, does the work for bzerrno, bzerrstr and bzerror */
590 : static void php_bz2_error(INTERNAL_FUNCTION_PARAMETERS, int opt)
591 21 : {
592 : zval **bzp; /* BZip2 Resource Pointer */
593 : php_stream *stream;
594 : const char *errstr; /* Error string */
595 : int errnum; /* Error number */
596 : struct php_bz2_stream_data_t *self;
597 :
598 21 : if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &bzp) == FAILURE) {
599 0 : WRONG_PARAM_COUNT;
600 : }
601 :
602 21 : php_stream_from_zval(stream, bzp);
603 :
604 18 : if (!php_stream_is(stream, PHP_STREAM_IS_BZIP2)) {
605 0 : RETURN_FALSE;
606 : }
607 :
608 18 : self = (struct php_bz2_stream_data_t *) stream->abstract;
609 :
610 : /* Fetch the error information */
611 18 : errstr = BZ2_bzerror(self->bz_file, &errnum);
612 :
613 : /* Determine what to return */
614 18 : switch (opt) {
615 : case PHP_BZ_ERRNO:
616 6 : RETURN_LONG(errnum);
617 : break;
618 : case PHP_BZ_ERRSTR:
619 6 : RETURN_STRING((char*)errstr, 1);
620 : break;
621 : case PHP_BZ_ERRBOTH:
622 6 : array_init(return_value);
623 :
624 6 : add_assoc_long (return_value, "errno", errnum);
625 6 : add_assoc_string(return_value, "errstr", (char*)errstr, 1);
626 : break;
627 : }
628 : }
629 : /* }}} */
630 :
631 : #endif
632 :
633 : /*
634 : * Local variables:
635 : * tab-width: 4
636 : * c-basic-offset: 4
637 : * End:
638 : * vim600: fdm=marker
639 : * vim: noet sw=4 ts=4
640 : */
|