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