This source file includes following definitions.
- ZEND_GET_MODULE
- php_bz2iop_read
- php_bz2iop_write
- php_bz2iop_close
- php_bz2iop_flush
- _php_stream_bz2open_from_BZFILE
- _php_stream_bz2open
- PHP_MINIT_FUNCTION
- PHP_MSHUTDOWN_FUNCTION
- PHP_MINFO_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- php_bz2_error
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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
31 #include "ext/standard/file.h"
32 #include "ext/standard/info.h"
33 #include "ext/standard/php_string.h"
34 #include "main/php_network.h"
35
36
37 #include <stdio.h>
38
39
40 #define PHP_BZ_ERRNO 0
41 #define PHP_BZ_ERRSTR 1
42 #define PHP_BZ_ERRBOTH 2
43
44 static PHP_MINIT_FUNCTION(bz2);
45 static PHP_MSHUTDOWN_FUNCTION(bz2);
46 static PHP_MINFO_FUNCTION(bz2);
47 static PHP_FUNCTION(bzopen);
48 static PHP_FUNCTION(bzread);
49 static PHP_FUNCTION(bzerrno);
50 static PHP_FUNCTION(bzerrstr);
51 static PHP_FUNCTION(bzerror);
52 static PHP_FUNCTION(bzcompress);
53 static PHP_FUNCTION(bzdecompress);
54
55
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 ZEND_BEGIN_ARG_INFO(arginfo_bzopen, 0)
62 ZEND_ARG_INFO(0, file)
63 ZEND_ARG_INFO(0, mode)
64 ZEND_END_ARG_INFO()
65
66 ZEND_BEGIN_ARG_INFO(arginfo_bzerrno, 0)
67 ZEND_ARG_INFO(0, bz)
68 ZEND_END_ARG_INFO()
69
70 ZEND_BEGIN_ARG_INFO(arginfo_bzerrstr, 0)
71 ZEND_ARG_INFO(0, bz)
72 ZEND_END_ARG_INFO()
73
74 ZEND_BEGIN_ARG_INFO(arginfo_bzerror, 0)
75 ZEND_ARG_INFO(0, bz)
76 ZEND_END_ARG_INFO()
77
78 ZEND_BEGIN_ARG_INFO_EX(arginfo_bzcompress, 0, 0, 2)
79 ZEND_ARG_INFO(0, source)
80 ZEND_ARG_INFO(0, blocksize)
81 ZEND_ARG_INFO(0, workfactor)
82 ZEND_END_ARG_INFO()
83
84 ZEND_BEGIN_ARG_INFO_EX(arginfo_bzdecompress, 0, 0, 1)
85 ZEND_ARG_INFO(0, source)
86 ZEND_ARG_INFO(0, small)
87 ZEND_END_ARG_INFO()
88
89 ZEND_BEGIN_ARG_INFO_EX(arginfo_bzwrite, 0, 0, 2)
90 ZEND_ARG_INFO(0, fp)
91 ZEND_ARG_INFO(0, str)
92 ZEND_ARG_INFO(0, length)
93 ZEND_END_ARG_INFO()
94
95 ZEND_BEGIN_ARG_INFO(arginfo_bzflush, 0)
96 ZEND_ARG_INFO(0, fp)
97 ZEND_END_ARG_INFO()
98
99
100 static const zend_function_entry bz2_functions[] = {
101 PHP_FE(bzopen, arginfo_bzopen)
102 PHP_FE(bzread, arginfo_bzread)
103 PHP_FALIAS(bzwrite, fwrite, arginfo_bzwrite)
104 PHP_FALIAS(bzflush, fflush, arginfo_bzflush)
105 PHP_FALIAS(bzclose, fclose, arginfo_bzflush)
106 PHP_FE(bzerrno, arginfo_bzerrno)
107 PHP_FE(bzerrstr, arginfo_bzerrstr)
108 PHP_FE(bzerror, arginfo_bzerror)
109 PHP_FE(bzcompress, arginfo_bzcompress)
110 PHP_FE(bzdecompress, arginfo_bzdecompress)
111 PHP_FE_END
112 };
113
114 zend_module_entry bz2_module_entry = {
115 STANDARD_MODULE_HEADER,
116 "bz2",
117 bz2_functions,
118 PHP_MINIT(bz2),
119 PHP_MSHUTDOWN(bz2),
120 NULL,
121 NULL,
122 PHP_MINFO(bz2),
123 NO_VERSION_YET,
124 STANDARD_MODULE_PROPERTIES
125 };
126
127 #ifdef COMPILE_DL_BZ2
128 ZEND_GET_MODULE(bz2)
129 #endif
130
131 struct php_bz2_stream_data_t {
132 BZFILE *bz_file;
133 php_stream *stream;
134 };
135
136
137
138 static size_t php_bz2iop_read(php_stream *stream, char *buf, size_t count TSRMLS_DC)
139 {
140 struct php_bz2_stream_data_t *self = (struct php_bz2_stream_data_t *) stream->abstract;
141 size_t ret;
142
143 ret = BZ2_bzread(self->bz_file, buf, count);
144
145 if (ret == 0) {
146 stream->eof = 1;
147 }
148
149 return ret;
150 }
151
152 static size_t php_bz2iop_write(php_stream *stream, const char *buf, size_t count TSRMLS_DC)
153 {
154 struct php_bz2_stream_data_t *self = (struct php_bz2_stream_data_t *) stream->abstract;
155
156 return BZ2_bzwrite(self->bz_file, (char*)buf, count);
157 }
158
159 static int php_bz2iop_close(php_stream *stream, int close_handle TSRMLS_DC)
160 {
161 struct php_bz2_stream_data_t *self = (struct php_bz2_stream_data_t *)stream->abstract;
162 int ret = EOF;
163
164 if (close_handle) {
165 BZ2_bzclose(self->bz_file);
166 }
167
168 if (self->stream) {
169 php_stream_free(self->stream, PHP_STREAM_FREE_CLOSE | (close_handle == 0 ? PHP_STREAM_FREE_PRESERVE_HANDLE : 0));
170 }
171
172 efree(self);
173
174 return ret;
175 }
176
177 static int php_bz2iop_flush(php_stream *stream TSRMLS_DC)
178 {
179 struct php_bz2_stream_data_t *self = (struct php_bz2_stream_data_t *)stream->abstract;
180 return BZ2_bzflush(self->bz_file);
181 }
182
183
184 php_stream_ops php_stream_bz2io_ops = {
185 php_bz2iop_write, php_bz2iop_read,
186 php_bz2iop_close, php_bz2iop_flush,
187 "BZip2",
188 NULL,
189 NULL,
190 NULL,
191 NULL
192 };
193
194
195 PHP_BZ2_API php_stream *_php_stream_bz2open_from_BZFILE(BZFILE *bz,
196 const char *mode, php_stream *innerstream STREAMS_DC TSRMLS_DC)
197 {
198 struct php_bz2_stream_data_t *self;
199
200 self = emalloc(sizeof(*self));
201
202 self->stream = innerstream;
203 self->bz_file = bz;
204
205 return php_stream_alloc_rel(&php_stream_bz2io_ops, self, 0, mode);
206 }
207
208 PHP_BZ2_API php_stream *_php_stream_bz2open(php_stream_wrapper *wrapper,
209 const char *path,
210 const char *mode,
211 int options,
212 char **opened_path,
213 php_stream_context *context STREAMS_DC TSRMLS_DC)
214 {
215 php_stream *retstream = NULL, *stream = NULL;
216 char *path_copy = NULL;
217 BZFILE *bz_file = NULL;
218
219 if (strncasecmp("compress.bzip2://", path, 17) == 0) {
220 path += 17;
221 }
222 if (mode[0] == '\0' || (mode[0] != 'w' && mode[0] != 'r' && mode[1] != '\0')) {
223 return NULL;
224 }
225
226 #ifdef VIRTUAL_DIR
227 virtual_filepath_ex(path, &path_copy, NULL TSRMLS_CC);
228 #else
229 path_copy = path;
230 #endif
231
232 if (php_check_open_basedir(path_copy TSRMLS_CC)) {
233 #ifdef VIRTUAL_DIR
234 efree(path_copy);
235 #endif
236 return NULL;
237 }
238
239
240 bz_file = BZ2_bzopen(path_copy, mode);
241
242 if (opened_path && bz_file) {
243 *opened_path = estrdup(path_copy);
244 }
245 #ifdef VIRTUAL_DIR
246 efree(path_copy);
247 #endif
248 path_copy = NULL;
249
250 if (bz_file == NULL) {
251
252 stream = php_stream_open_wrapper(path, mode, options | STREAM_WILL_CAST, opened_path);
253
254 if (stream) {
255 php_socket_t fd;
256 if (SUCCESS == php_stream_cast(stream, PHP_STREAM_AS_FD, (void **) &fd, REPORT_ERRORS)) {
257 bz_file = BZ2_bzdopen(fd, mode);
258 }
259 }
260
261
262
263
264 if (opened_path && !bz_file && mode[0] == 'w') {
265 VCWD_UNLINK(*opened_path);
266 }
267 }
268
269 if (bz_file) {
270 retstream = _php_stream_bz2open_from_BZFILE(bz_file, mode, stream STREAMS_REL_CC TSRMLS_CC);
271 if (retstream) {
272 return retstream;
273 }
274
275 BZ2_bzclose(bz_file);
276 }
277
278 if (stream) {
279 php_stream_close(stream);
280 }
281
282 return NULL;
283 }
284
285
286
287 static php_stream_wrapper_ops bzip2_stream_wops = {
288 _php_stream_bz2open,
289 NULL,
290 NULL,
291 NULL,
292 NULL,
293 "BZip2",
294 NULL,
295 NULL,
296 NULL,
297 NULL
298 };
299
300 static php_stream_wrapper php_stream_bzip2_wrapper = {
301 &bzip2_stream_wops,
302 NULL,
303 0
304 };
305
306 static void php_bz2_error(INTERNAL_FUNCTION_PARAMETERS, int);
307
308 static PHP_MINIT_FUNCTION(bz2)
309 {
310 php_register_url_stream_wrapper("compress.bzip2", &php_stream_bzip2_wrapper TSRMLS_CC);
311 php_stream_filter_register_factory("bzip2.*", &php_bz2_filter_factory TSRMLS_CC);
312 return SUCCESS;
313 }
314
315 static PHP_MSHUTDOWN_FUNCTION(bz2)
316 {
317 php_unregister_url_stream_wrapper("compress.bzip2" TSRMLS_CC);
318 php_stream_filter_unregister_factory("bzip2.*" TSRMLS_CC);
319
320 return SUCCESS;
321 }
322
323 static PHP_MINFO_FUNCTION(bz2)
324 {
325 php_info_print_table_start();
326 php_info_print_table_row(2, "BZip2 Support", "Enabled");
327 php_info_print_table_row(2, "Stream Wrapper support", "compress.bzip2://");
328 php_info_print_table_row(2, "Stream Filter support", "bzip2.decompress, bzip2.compress");
329 php_info_print_table_row(2, "BZip2 Version", (char *) BZ2_bzlibVersion());
330 php_info_print_table_end();
331 }
332
333
334
335 static PHP_FUNCTION(bzread)
336 {
337 zval *bz;
338 long len = 1024;
339 php_stream *stream;
340
341 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &bz, &len)) {
342 RETURN_FALSE;
343 }
344
345 php_stream_from_zval(stream, &bz);
346
347 if ((len + 1) < 1) {
348 php_error_docref(NULL TSRMLS_CC, E_WARNING, "length may not be negative");
349 RETURN_FALSE;
350 }
351
352 Z_STRVAL_P(return_value) = emalloc(len + 1);
353 Z_STRLEN_P(return_value) = php_stream_read(stream, Z_STRVAL_P(return_value), len);
354
355 if (Z_STRLEN_P(return_value) < 0) {
356 efree(Z_STRVAL_P(return_value));
357 php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not read valid bz2 data from stream");
358 RETURN_FALSE;
359 }
360
361 Z_STRVAL_P(return_value)[Z_STRLEN_P(return_value)] = 0;
362 Z_TYPE_P(return_value) = IS_STRING;
363 }
364
365
366
367
368 static PHP_FUNCTION(bzopen)
369 {
370 zval **file;
371 char *mode;
372 int mode_len;
373
374 BZFILE *bz;
375 php_stream *stream = NULL;
376
377 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Zs", &file, &mode, &mode_len) == FAILURE) {
378 return;
379 }
380
381 if (mode_len != 1 || (mode[0] != 'r' && mode[0] != 'w')) {
382 php_error_docref(NULL TSRMLS_CC, E_WARNING, "'%s' is not a valid mode for bzopen(). Only 'w' and 'r' are supported.", mode);
383 RETURN_FALSE;
384 }
385
386
387 if (Z_TYPE_PP(file) == IS_STRING) {
388 if (Z_STRLEN_PP(file) == 0) {
389 php_error_docref(NULL TSRMLS_CC, E_WARNING, "filename cannot be empty");
390 RETURN_FALSE;
391 }
392
393 if (CHECK_ZVAL_NULL_PATH(*file)) {
394 RETURN_FALSE;
395 }
396
397 stream = php_stream_bz2open(NULL,
398 Z_STRVAL_PP(file),
399 mode,
400 REPORT_ERRORS,
401 NULL);
402 } else if (Z_TYPE_PP(file) == IS_RESOURCE) {
403
404 php_socket_t fd;
405 int stream_mode_len;
406
407 php_stream_from_zval(stream, file);
408 stream_mode_len = strlen(stream->mode);
409
410 if (stream_mode_len != 1 && !(stream_mode_len == 2 && memchr(stream->mode, 'b', 2))) {
411 php_error_docref(NULL TSRMLS_CC, E_WARNING, "cannot use stream opened in mode '%s'", stream->mode);
412 RETURN_FALSE;
413 } else if (stream_mode_len == 1 && stream->mode[0] != 'r' && stream->mode[0] != 'w' && stream->mode[0] != 'a' && stream->mode[0] != 'x') {
414 php_error_docref(NULL TSRMLS_CC, E_WARNING, "cannot use stream opened in mode '%s'", stream->mode);
415 RETURN_FALSE;
416 }
417
418 switch(mode[0]) {
419 case 'r':
420
421 if (stream->mode[0] != mode[0] && !(stream_mode_len == 2 && stream->mode[1] != mode[0])) {
422 php_error_docref(NULL TSRMLS_CC, E_WARNING, "cannot read from a stream opened in write only mode");
423 RETURN_FALSE;
424 }
425 break;
426 case 'w':
427
428 if (stream->mode[0] != mode[0] && !(stream_mode_len == 2 && stream->mode[1] != mode[0])
429 && stream->mode[0] != 'a' && !(stream_mode_len == 2 && stream->mode[1] != 'a')
430 && stream->mode[0] != 'x' && !(stream_mode_len == 2 && stream->mode[1] != 'x')) {
431 php_error_docref(NULL TSRMLS_CC, E_WARNING, "cannot write to a stream opened in read only mode");
432 RETURN_FALSE;
433 }
434 break;
435 default:
436
437 break;
438 }
439
440 if (FAILURE == php_stream_cast(stream, PHP_STREAM_AS_FD, (void *) &fd, REPORT_ERRORS)) {
441 RETURN_FALSE;
442 }
443
444 bz = BZ2_bzdopen(fd, mode);
445
446 stream = php_stream_bz2open_from_BZFILE(bz, mode, stream);
447 } else {
448 php_error_docref(NULL TSRMLS_CC, E_WARNING, "first parameter has to be string or file-resource");
449 RETURN_FALSE;
450 }
451
452 if (stream) {
453 php_stream_to_zval(stream, return_value);
454 } else {
455 RETURN_FALSE;
456 }
457 }
458
459
460
461
462 static PHP_FUNCTION(bzerrno)
463 {
464 php_bz2_error(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_BZ_ERRNO);
465 }
466
467
468
469
470 static PHP_FUNCTION(bzerrstr)
471 {
472 php_bz2_error(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_BZ_ERRSTR);
473 }
474
475
476
477
478 static PHP_FUNCTION(bzerror)
479 {
480 php_bz2_error(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_BZ_ERRBOTH);
481 }
482
483
484
485
486 static PHP_FUNCTION(bzcompress)
487 {
488 char *source;
489 long zblock_size = 0;
490 long zwork_factor = 0;
491 char *dest = NULL;
492 int error,
493 block_size = 4,
494 work_factor = 0,
495 argc;
496 int source_len;
497 unsigned int dest_len;
498
499 argc = ZEND_NUM_ARGS();
500
501 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|ll", &source, &source_len, &zblock_size, &zwork_factor) == FAILURE) {
502 return;
503 }
504
505
506
507
508
509 dest_len = (unsigned int) (source_len + (0.01 * source_len) + 600);
510
511
512 dest = emalloc(dest_len + 1);
513
514
515 if (argc > 1) {
516 block_size = zblock_size;
517 }
518
519 if (argc > 2) {
520 work_factor = zwork_factor;
521 }
522
523 error = BZ2_bzBuffToBuffCompress(dest, &dest_len, source, source_len, block_size, 0, work_factor);
524 if (error != BZ_OK) {
525 efree(dest);
526 RETURN_LONG(error);
527 } else {
528
529
530 dest = erealloc(dest, dest_len + 1);
531 dest[dest_len] = 0;
532 RETURN_STRINGL(dest, dest_len, 0);
533 }
534 }
535
536
537
538
539 static PHP_FUNCTION(bzdecompress)
540 {
541 char *source, *dest;
542 int source_len, error;
543 long small = 0;
544 #if defined(PHP_WIN32)
545 unsigned __int64 size = 0;
546 #else
547 unsigned long long size = 0;
548 #endif
549 bz_stream bzs;
550
551 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &source, &source_len, &small)) {
552 RETURN_FALSE;
553 }
554
555 bzs.bzalloc = NULL;
556 bzs.bzfree = NULL;
557
558 if (BZ2_bzDecompressInit(&bzs, 0, small) != BZ_OK) {
559 RETURN_FALSE;
560 }
561
562 bzs.next_in = source;
563 bzs.avail_in = source_len;
564
565
566 bzs.avail_out = source_len * 2;
567 bzs.next_out = dest = emalloc(bzs.avail_out + 1);
568
569 while ((error = BZ2_bzDecompress(&bzs)) == BZ_OK && bzs.avail_in > 0) {
570
571 bzs.avail_out = source_len;
572 size = (bzs.total_out_hi32 * (unsigned int) -1) + bzs.total_out_lo32;
573 dest = safe_erealloc(dest, 1, bzs.avail_out+1, (size_t) size );
574 bzs.next_out = dest + size;
575 }
576
577 if (error == BZ_STREAM_END || error == BZ_OK) {
578 size = (bzs.total_out_hi32 * (unsigned int) -1) + bzs.total_out_lo32;
579 dest = safe_erealloc(dest, 1, (size_t) size, 1);
580 dest[size] = '\0';
581 RETVAL_STRINGL(dest, (int) size, 0);
582 } else {
583 efree(dest);
584 RETVAL_LONG(error);
585 }
586
587 BZ2_bzDecompressEnd(&bzs);
588 }
589
590
591
592
593 static void php_bz2_error(INTERNAL_FUNCTION_PARAMETERS, int opt)
594 {
595 zval *bzp;
596 php_stream *stream;
597 const char *errstr;
598 int errnum;
599 struct php_bz2_stream_data_t *self;
600
601 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &bzp) == FAILURE) {
602 return;
603 }
604
605 php_stream_from_zval(stream, &bzp);
606
607 if (!php_stream_is(stream, PHP_STREAM_IS_BZIP2)) {
608 RETURN_FALSE;
609 }
610
611 self = (struct php_bz2_stream_data_t *) stream->abstract;
612
613
614 errstr = BZ2_bzerror(self->bz_file, &errnum);
615
616
617 switch (opt) {
618 case PHP_BZ_ERRNO:
619 RETURN_LONG(errnum);
620 break;
621 case PHP_BZ_ERRSTR:
622 RETURN_STRING((char*)errstr, 1);
623 break;
624 case PHP_BZ_ERRBOTH:
625 array_init(return_value);
626
627 add_assoc_long (return_value, "errno", errnum);
628 add_assoc_string(return_value, "errstr", (char*)errstr, 1);
629 break;
630 }
631 }
632
633
634 #endif
635
636
637
638
639
640
641
642
643