char *arch = NULL, *entry = NULL, *error;
int arch_len, entry_len;
- if (!strncasecmp(filename, "phar://", 7)) {
- if (mode[0] == 'a') {
- if (!(options & PHP_STREAM_URL_STAT_QUIET)) {
- php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: open mode append not supported");
- }
- return NULL;
- }
- if (phar_split_fname(filename, strlen(filename), &arch, &arch_len, &entry, &entry_len TSRMLS_CC) == FAILURE) {
- if (!(options & PHP_STREAM_URL_STAT_QUIET)) {
- if (arch && !entry) {
- php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: no directory in \"%s\", must have at least phar://%s/ for root directory (always use full path to a new phar)", filename, arch);
- arch = NULL;
- } else {
- php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: invalid url \"%s\" (cannot contain .phar.php and .phar.gz/.phar.bz2)", filename);
- }
- }
- if (arch) {
- efree(arch);
- }
- if (entry) {
- efree(entry);
+ if (strlen(filename) < 7 || strncasecmp(filename, "phar://", 7)) {
+ return NULL;
+ }
+ if (mode[0] == 'a') {
+ if (!(options & PHP_STREAM_URL_STAT_QUIET)) {
+ php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: open mode append not supported");
+ }
+ return NULL;
+ }
+ if (phar_split_fname(filename, strlen(filename), &arch, &arch_len, &entry, &entry_len TSRMLS_CC) == FAILURE) {
+ if (!(options & PHP_STREAM_URL_STAT_QUIET)) {
+ if (arch && !entry) {
+ php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: no directory in \"%s\", must have at least phar://%s/ for root directory (always use full path to a new phar)", filename, arch);
+ arch = NULL;
+ } else {
+ php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: invalid url \"%s\" (cannot contain .phar.php and .phar.gz/.phar.bz2)", filename);
}
- return NULL;
}
- resource = ecalloc(1, sizeof(php_url));
- resource->scheme = estrndup("phar", 4);
- resource->host = arch;
+ if (arch) {
+ efree(arch);
+ }
+ if (entry) {
+ efree(entry);
+ }
+ return NULL;
+ }
+ resource = ecalloc(1, sizeof(php_url));
+ resource->scheme = estrndup("phar", 4);
+ resource->host = arch;
- resource->path = entry;
+ resource->path = entry;
#if MBO_0
if (resource) {
fprintf(stderr, "Alias: %s\n", alias);
/* fprintf(stderr, "Fragment: %s\n", resource->fragment);*/
}
#endif
- if (PHAR_GLOBALS->request_init && PHAR_GLOBALS->phar_plain_map.arBuckets && zend_hash_exists(&(PHAR_GLOBALS->phar_plain_map), arch, arch_len+1)) {
- return resource;
- }
- if (mode[0] == 'w' || (mode[0] == 'r' && mode[1] == '+')) {
- phar_archive_data **pphar = NULL;
+ if (PHAR_GLOBALS->request_init && PHAR_GLOBALS->phar_plain_map.arBuckets && zend_hash_exists(&(PHAR_GLOBALS->phar_plain_map), arch, arch_len+1)) {
+ return resource;
+ }
+ if (mode[0] == 'w' || (mode[0] == 'r' && mode[1] == '+')) {
+ phar_archive_data **pphar = NULL;
- if (PHAR_GLOBALS->request_init && PHAR_GLOBALS->phar_fname_map.arBuckets && FAILURE == zend_hash_find(&(PHAR_GLOBALS->phar_fname_map), arch, arch_len, (void **)&pphar)) {
- pphar = NULL;
+ if (PHAR_GLOBALS->request_init && PHAR_GLOBALS->phar_fname_map.arBuckets && FAILURE == zend_hash_find(&(PHAR_GLOBALS->phar_fname_map), arch, arch_len, (void **)&pphar)) {
+ pphar = NULL;
+ }
+ if (PHAR_G(readonly) && (!pphar || !(*pphar)->is_data)) {
+ if (!(options & PHP_STREAM_URL_STAT_QUIET)) {
+ php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: write operations disabled by INI setting");
}
- if (PHAR_G(readonly) && (!pphar || !(*pphar)->is_data)) {
+ php_url_free(resource);
+ return NULL;
+ }
+ if (phar_open_or_create_filename(resource->host, arch_len, NULL, 0, NULL, options, NULL, &error TSRMLS_CC) == FAILURE)
+ {
+ if (error) {
if (!(options & PHP_STREAM_URL_STAT_QUIET)) {
- php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: write operations disabled by INI setting");
- }
- php_url_free(resource);
- return NULL;
- }
- if (phar_open_or_create_filename(resource->host, arch_len, NULL, 0, NULL, options, NULL, &error TSRMLS_CC) == FAILURE)
- {
- if (error) {
- if (!(options & PHP_STREAM_URL_STAT_QUIET)) {
- php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, error);
- }
- efree(error);
+ php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, error);
}
- php_url_free(resource);
- return NULL;
+ efree(error);
}
- } else {
- if (phar_open_filename(resource->host, arch_len, NULL, 0, options, NULL, &error TSRMLS_CC) == FAILURE)
- {
- if (error) {
- if (!(options & PHP_STREAM_URL_STAT_QUIET)) {
- php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, error);
- }
- efree(error);
+ php_url_free(resource);
+ return NULL;
+ }
+ } else {
+ if (phar_open_filename(resource->host, arch_len, NULL, 0, options, NULL, &error TSRMLS_CC) == FAILURE)
+ {
+ if (error) {
+ if (!(options & PHP_STREAM_URL_STAT_QUIET)) {
+ php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, error);
}
- php_url_free(resource);
- return NULL;
+ efree(error);
}
- }
- return resource;
- }
-
- return NULL;
+ php_url_free(resource);
+ return NULL;
+ }
+ }
+ return resource;
}
/* }}} */
--- /dev/null
+--TEST--
+Phar: fopen/stat edge cases
+--SKIPIF--
+<?php if (!extension_loaded("phar")) die("skip"); ?>
+--INI--
+phar.readonly=0
+phar.require_hash=0
+--FILE--
+<?php
+$fname = dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.phar.php';
+$fname2 = dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.2.phar.php';
+$pname = 'phar://' . $fname;
+$pname2 = 'phar://' . $fname2;
+
+// append
+$a = fopen($pname . '/b/c.php', 'a');
+// invalid pharname
+$a = fopen($pname . '.phar.gz', 'r');
+// test phar_open_url() with quiet stat for code coverage
+var_dump(file_exists($pname . '.phar.gz/hi'));
+// test open for write with new phar
+$a = fopen($pname . '/hi', 'w');
+fclose($a);
+// test open for write with corrupted phar
+file_put_contents($fname2, '<?php oh crap __HALT_COMPILER();');
+$a = fopen($pname2 . '/hi', 'w');
+$a = fopen('phar://', 'r');
+$a = fopen('phar://foo.phar', 'r');
+?>
+
+===DONE===
+--CLEAN--
+<?php unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.phar.php'); ?>
+<?php unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.2.phar.php'); ?>
+--EXPECTF--
+Warning: fopen(phar://%sfopen_edgecases.phar.php/b/c.php): failed to open stream: phar error: open mode append not supported in %sfopen_edgecases.php on line %d
+
+Warning: fopen(phar://%sfopen_edgecases.phar.php.phar.gz): failed to open stream: phar error: invalid url "phar://%sfopen_edgecases.phar.php.phar.gz" (cannot contain .phar.php and .phar.gz/.phar.bz2) in %sfopen_edgecases.php on line %d
+bool(false)
+
+Warning: fopen(phar://%sfopen_edgecases.2.phar.php/hi): failed to open stream: internal corruption of phar "%sfopen_edgecases.2.phar.php" (truncated manifest at stub end) in %sfopen_edgecases.php on line %d
+
+===DONE===
\ No newline at end of file