cellog Tue Apr 15 03:36:56 2008 UTC Added files: /pecl/phar/tests readfile.phpt
Modified files: /pecl/phar func_interceptors.c phar_internal.h Log: add interception for readfile [DOC] http://cvs.php.net/viewvc.cgi/pecl/phar/func_interceptors.c?r1=1.14&r2=1.15&diff_format=u Index: pecl/phar/func_interceptors.c diff -u pecl/phar/func_interceptors.c:1.14 pecl/phar/func_interceptors.c:1.15 --- pecl/phar/func_interceptors.c:1.14 Mon Apr 14 17:31:00 2008 +++ pecl/phar/func_interceptors.c Tue Apr 15 03:36:56 2008 @@ -16,7 +16,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: func_interceptors.c,v 1.14 2008/04/14 17:31:00 cellog Exp $ */ +/* $Id: func_interceptors.c,v 1.15 2008/04/15 03:36:56 cellog Exp $ */ #include "phar_internal.h" @@ -199,6 +199,83 @@ } /* }}} */ +PHAR_FUNC(phar_readfile) /* {{{ */ +{ + char *filename; + int filename_len; + int size = 0; + zend_bool use_include_path = 0; + zval *zcontext = NULL; + php_stream *stream; + + if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "s|br!", &filename, &filename_len, &use_include_path, &zcontext) == FAILURE) { + goto skip_phar; + } + if (use_include_path || (!IS_ABSOLUTE_PATH(filename, filename_len) && !strstr(filename, "://"))) { + char *arch, *entry, *fname; + int arch_len, entry_len, fname_len; + php_stream_context *context = NULL; + char *name; + phar_archive_data **pphar; + fname = zend_get_executed_filename(TSRMLS_C); + + if (strncasecmp(fname, "phar://", 7)) { + goto skip_phar; + } + fname_len = strlen(fname); + if (FAILURE == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len TSRMLS_CC)) { + goto skip_phar; + } + + efree(entry); + entry = filename; + /* fopen within phar, if :// is not in the url, then prepend phar://<archive>/ */ + entry_len = filename_len; + /* retrieving a file defaults to within the current directory, so use this if possible */ + if (FAILURE == (zend_hash_find(&(PHAR_GLOBALS->phar_fname_map), arch, arch_len, (void **) &pphar))) { + efree(arch); + goto skip_phar; + } + if (use_include_path) { + if (!(entry = phar_find_in_include_path(entry, entry_len, NULL TSRMLS_CC))) { + /* this file is not in the phar, use the original path */ + efree(arch); + goto skip_phar; + } else { + name = entry; + } + } else { + entry = phar_fix_filepath(estrndup(entry, entry_len), &entry_len, 1 TSRMLS_CC); + if (!zend_hash_exists(&((*pphar)->manifest), entry + 1, entry_len - 1)) { + /* this file is not in the phar, use the original path */ + efree(entry); + efree(arch); + goto skip_phar; + } + /* auto-convert to phar:// */ + spprintf(&name, 4096, "phar://%s%s", arch, entry); + efree(entry); + } + + efree(arch); + context = php_stream_context_from_zval(zcontext, 0); + stream = php_stream_open_wrapper_ex(name, "rb", 0 | REPORT_ERRORS, NULL, context); + efree(name); + if (stream == NULL) { + RETURN_FALSE; + } + size = php_stream_passthru(stream); + php_stream_close(stream); + RETURN_LONG(size); + } + +skip_phar: + PHAR_G(orig_readfile)(INTERNAL_FUNCTION_PARAM_PASSTHRU); + return; + +} +/* }}} */ + PHAR_FUNC(phar_fopen) /* {{{ */ { char *filename, *mode; @@ -878,6 +955,7 @@ PHAR_INTERCEPT(is_executable); PHAR_INTERCEPT(lstat); PHAR_INTERCEPT(stat); + PHAR_INTERCEPT(readfile); } /* }}} */ @@ -912,6 +990,7 @@ PHAR_RELEASE(is_executable); PHAR_RELEASE(lstat); PHAR_RELEASE(stat); + PHAR_RELEASE(readfile); } /* }}} */ http://cvs.php.net/viewvc.cgi/pecl/phar/phar_internal.h?r1=1.100&r2=1.101&diff_format=u Index: pecl/phar/phar_internal.h diff -u pecl/phar/phar_internal.h:1.100 pecl/phar/phar_internal.h:1.101 --- pecl/phar/phar_internal.h:1.100 Mon Apr 14 04:47:33 2008 +++ pecl/phar/phar_internal.h Tue Apr 15 03:36:56 2008 @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: phar_internal.h,v 1.100 2008/04/14 04:47:33 cellog Exp $ */ +/* $Id: phar_internal.h,v 1.101 2008/04/15 03:36:56 cellog Exp $ */ #ifdef HAVE_CONFIG_H #include "config.h" @@ -164,6 +164,7 @@ void (*orig_is_readable)(INTERNAL_FUNCTION_PARAMETERS); void (*orig_is_executable)(INTERNAL_FUNCTION_PARAMETERS); void (*orig_lstat)(INTERNAL_FUNCTION_PARAMETERS); + void (*orig_readfile)(INTERNAL_FUNCTION_PARAMETERS); void (*orig_stat)(INTERNAL_FUNCTION_PARAMETERS); /* used for includes with . in them inside front controller */ char* cwd; http://cvs.php.net/viewvc.cgi/pecl/phar/tests/readfile.phpt?view=markup&rev=1.1 Index: pecl/phar/tests/readfile.phpt +++ pecl/phar/tests/readfile.phpt --TEST-- Phar: test readfile() interception --SKIPIF-- <?php if (!extension_loaded("phar")) die("skip");?> --INI-- phar.require_hash=1 phar.readonly=0 --FILE-- <?php $fname = dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.phar.php'; $a = new Phar($fname); $a['index.php'] = '<?php readfile("dir/file1.txt"); readfile("file1.txt", true); ?>'; $a['dir/file1.txt'] = 'hi'; $a['dir/file2.txt'] = 'hi2'; $a['dir/file3.txt'] = 'hi3'; $a->setStub('<?php Phar::interceptFileFuncs(); set_include_path("phar://" . __FILE__ . "/dir" . PATH_SEPARATOR . "phar://" . __FILE__); include "index.php"; __HALT_COMPILER();'); include $fname; ?> ===DONE=== --CLEAN-- <?php unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.phar.php'); ?> --EXPECT-- hihi===DONE===