}
zend_hash_init(&mydata->manifest, sizeof(phar_entry_info),
zend_get_hash_value, destroy_phar_manifest_entry, 0);
+ zend_hash_init(&mydata->mounted_dirs, sizeof(char *),
+ zend_get_hash_value, NULL, 0);
mydata->fname_len = fname_len;
mydata->alias = alias ? estrndup(alias, alias_len) : estrndup(mydata->fname, fname_len);
mydata->alias_len = alias ? alias_len : fname_len;
}
/* }}} */
+/* {{{ proto void Phar::getRunningPhar()
+ * return the name of the currently running phar archive
+ */
+PHP_METHOD(Phar, getRunningPhar)
+{
+ char *fname, *arch, *entry;
+ int fname_len, arch_len, entry_len;
+
+ fname = zend_get_executed_filename(TSRMLS_C);
+ fname_len = strlen(fname);
+
+ if (SUCCESS == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len TSRMLS_CC)) {
+ efree(entry);
+ RETURN_STRINGL(arch, arch_len, 0);
+ }
+ efree(entry);
+ RETURN_STRING("", 0);
+}
+/* }}} */
+
/* {{{ proto void Phar::mount(string pharpath, string externalfile)
* mount an external file or path to a location within the phar. This maps
* an external file or directory to a location within the phar archive, allowing
{
char *fname, *arch, *entry, *path, *actual;
int fname_len, arch_len, entry_len, path_len, actual_len;
+ phar_archive_data **pphar;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &path, &path_len, &actual, &actual_len) == FAILURE) {
return;
fname_len = strlen(fname);
if (SUCCESS == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len TSRMLS_CC)) {
- phar_archive_data **pphar;
+ efree(entry);
if (SUCCESS != zend_hash_find(&(PHAR_GLOBALS->phar_fname_map), arch, arch_len, (void **)&pphar)) {
- /* TODO: throw exception */
+ zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "%s is not a phar archive, cannot mount", arch);
+ efree(arch);
return;
}
+carry_on:
if (SUCCESS != phar_mount_entry(*pphar, actual, actual_len, path, path_len TSRMLS_CC)) {
- /* TODO: throw exception */
- return;
+ zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "Mounting of %s to %s within phar %s failed", path, actual, arch);
+ efree(arch);
}
+ efree(arch);
+ return;
+ } else if (SUCCESS == zend_hash_find(&(PHAR_GLOBALS->phar_fname_map), fname, fname_len, (void **)&pphar)) {
+ goto carry_on;
}
+ zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "Phar::mount() can only be run from within a phar archive");
}
/* }}} */
PHP_ME(Phar, isValidPharFilename, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
PHP_ME(Phar, loadPhar, arginfo_phar_loadPhar, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
PHP_ME(Phar, mapPhar, arginfo_phar_mapPhar, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
+ PHP_ME(Phar, getRunningPhar, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
PHP_ME(Phar, mount, arginfo_phar_mount, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
PHP_ME(Phar, mungServer, arginfo_phar_mungServer, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
PHP_ME(Phar, webPhar, arginfo_phar_webPhar, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
--- /dev/null
+--TEST--
+Phar: mounted manifest directory test
+--SKIPIF--
+<?php if (!extension_loaded("phar")) die("skip"); ?>
+--INI--
+phar.readonly=0
+--FILE--
+<?php
+$fname = dirname(__FILE__) . '/tempmanifest1.phar.php';
+$a = new Phar($fname);
+$a['index.php'] = '<?php
+set_include_path(".");
+Phar::mount("testit", dirname(Phar::getRunningPhar()) . "/testit");
+include "testit/extfile.php";
+include "testit/extfile2.php";
+?>';
+$a->setStub('<?php
+include "phar://" . __FILE__ . "/index.php";
+__HALT_COMPILER();');
+unset($a);
+mkdir(dirname(__FILE__) . '/testit');
+file_put_contents(dirname(__FILE__) . '/testit/extfile.php', '<?php
+var_dump(__FILE__);
+?>');
+file_put_contents(dirname(__FILE__) . '/testit/extfile2.php', '<?php
+var_dump(__FILE__);
+?>');
+include dirname(__FILE__) . '/testit/extfile.php';
+include $fname;
+?>
+===DONE===
+--CLEAN--
+<?php
+@unlink(dirname(__FILE__) . '/tempmanifest1.phar.php');
+@unlink(dirname(__FILE__) . '/testit/extfile.php');
+@unlink(dirname(__FILE__) . '/testit/extfile2.php');
+@rmdir(dirname(__FILE__) . '/testit');
+
+?>
+--EXPECTF--
+string(%d) "%sextfile.php"
+string(%d) "phar://%sextfile.php"
+string(%d) "phar://%sextfile2.php"
+===DONE===
\ No newline at end of file
return php_stream_seek(fp, temp, SEEK_SET);
}
-void phar_rename_archive(phar_archive_data *phar, char *ext TSRMLS_DC) {
-
+void phar_rename_archive(phar_archive_data *phar, char *ext TSRMLS_DC)
+{
char *oldname = NULL, *oldpath = NULL;
char *basename = NULL, *basepath = NULL;
char *newname = NULL, *newpath = NULL;
return FAILURE;
}
+
+ entry.phar = phar;
+ entry.filename = estrndup(path, path_len);
+ entry.filename_len = path_len;
+ if (strstr(filename, "phar://")) {
+ entry.link = estrndup(filename, filename_len);
+ } else {
+ entry.link = expand_filepath(filename, NULL TSRMLS_CC);
+ if (!entry.link) {
+ entry.link = estrndup(filename, filename_len);
+ }
+ }
#if PHP_MAJOR_VERSION < 6
- if (PG(safe_mode) && (!php_checkuid(filename, NULL, CHECKUID_ALLOW_ONLY_FILE))) {
+ if (PG(safe_mode) && !strstr(filename, "phar://") && (!php_checkuid(entry.link, NULL, CHECKUID_ALLOW_ONLY_FILE))) {
+ efree(entry.link);
+ efree(entry.filename);
return FAILURE;
}
#endif
+ filename_len = strlen(entry.link);
+ filename = entry.link;
/* only check openbasedir for files, not for phar streams */
if (!strstr(filename, "phar://") && php_check_open_basedir(filename TSRMLS_CC)) {
+ efree(entry.link);
+ efree(entry.filename);
return FAILURE;
}
-
- entry.phar = phar;
- entry.filename = estrndup(path, path_len);
- entry.filename_len = path_len;
- entry.link = estrndup(filename, filename_len);
entry.is_mounted = 1;
entry.is_crc_checked = 1;
entry.fp_type = PHAR_TMP;
- if (SUCCESS != php_stream_stat_path(entry.link, &ssb)) {
+ if (SUCCESS != php_stream_stat_path(filename, &ssb)) {
efree(entry.link);
efree(entry.filename);
return FAILURE;
}
} else {
entry.is_dir = 0;
+ entry.uncompressed_filesize = entry.compressed_filesize = ssb.sb.st_size;
}
- entry.uncompressed_filesize = entry.compressed_filesize = ssb.sb.st_size;
entry.flags = ssb.sb.st_mode;
if (SUCCESS == zend_hash_add(&phar->manifest, path, path_len, (void*)&entry, sizeof(phar_entry_info), NULL)) {
return SUCCESS;
efree(save);
return test;
}
+ if (zend_hash_num_elements(&(phar->mounted_dirs))) {
+ if (phar_get_entry_info_dir(phar, test + 1, try_len - 1, 0, NULL TSRMLS_CC)) {
+ char *save = test;
+ efree(pathbuf);
+ test = estrndup(test + 1, try_len - 1);
+ efree(save);
+ return test;
+ }
+ }
efree(test);
stream_skip:
ptr = end;
return NULL;
}
return entry;
+ } else if (phar->mounted_dirs.arBuckets && zend_hash_num_elements(&phar->mounted_dirs)) {
+ char *key;
+ ulong unused;
+ uint keylen;
+
+ zend_hash_internal_pointer_reset(&phar->mounted_dirs);
+ while (FAILURE != zend_hash_has_more_elements(&phar->mounted_dirs)) {
+ if (HASH_KEY_NON_EXISTANT == zend_hash_get_current_key_ex(&phar->mounted_dirs, &key, &keylen, &unused, 0, NULL)) {
+ break;
+ }
+ if (keylen >= path_len || strncmp(key, path, keylen)) {
+ continue;
+ } else {
+ char *test;
+ int test_len;
+ phar_entry_info *entry;
+ php_stream_statbuf ssb;
+
+ if (SUCCESS != zend_hash_find(&phar->manifest, key, keylen, (void **) &entry)) {
+ if (error) {
+ spprintf(error, 4096, "phar internal error: mounted path \"%s\" could not be retrieved from manifest", key);
+ }
+ return NULL;
+ }
+ if (!entry->link || !entry->is_mounted) {
+ if (error) {
+ spprintf(error, 4096, "phar internal error: mounted path \"%s\" is not properly initialized as a mounted path", key);
+ }
+ return NULL;
+ }
+ test_len = spprintf(&test, MAXPATHLEN, "%s%s", entry->link, path + keylen);
+ if (SUCCESS != php_stream_stat_path(test, &ssb)) {
+ efree(test);
+ return NULL;
+ }
+ if (ssb.sb.st_mode & S_IFDIR && !dir) {
+ efree(test);
+ if (error) {
+ spprintf(error, 4096, "phar error: path \"%s\" is a directory", path);
+ }
+ return NULL;
+ }
+ if (ssb.sb.st_mode & S_IFDIR && dir) {
+ efree(test);
+ /* user requested a directory, we must return one */
+ if (error) {
+ spprintf(error, 4096, "phar error: path \"%s\" exists and is a not a directory", path);
+ }
+ return NULL;
+ }
+ /* mount the file just in time */
+ if (SUCCESS != phar_mount_entry(phar, test, test_len, path, path_len TSRMLS_CC)) {
+ efree(test);
+ if (error) {
+ spprintf(error, 4096, "phar error: path \"%s\" exists as file \"%s\" and could not be mounted", path, test);
+ }
+ return NULL;
+ }
+ efree(test);
+ if (SUCCESS != zend_hash_find(&phar->manifest, path, path_len, (void**)&entry)) {
+ if (error) {
+ spprintf(error, 4096, "phar error: path \"%s\" exists as file \"%s\" and could not be retrieved after being mounted", path, test);
+ }
+ return NULL;
+ }
+ return entry;
+ }
+ }
}
- if (dir == 1) {
+ if (dir) {
/* try to find a directory */
HashTable *manifest;
char *key;