if (!(entry = phar_find_in_include_path(entry, old, *pphar TSRMLS_CC))) {
/* this file is not in the phar, use the original path */
if (SUCCESS == phar_orig_zend_open(filename, handle TSRMLS_CC)) {
- if (filename[0] != '.' && SUCCESS == phar_mount_entry(*pphar, handle->opened_path ? handle->opened_path : filename, strlen(handle->opened_path ? handle->opened_path : filename), filename, strlen(filename), 0)) {
+ if (SUCCESS == phar_mount_entry(*pphar, handle->opened_path ? handle->opened_path : (char *) filename, strlen(handle->opened_path ? handle->opened_path : filename), (char *) filename, strlen(filename))) {
entry = (char *) filename;
goto dopharthing;
}
char * phar_decompress_filter(phar_entry_info * entry, int return_unknown);
char * phar_compress_filter(phar_entry_info * entry, int return_unknown);
+int phar_mount_entry(phar_archive_data *phar, char *filename, int filename_len, char *path, int path_len TSRMLS_DC);
char *phar_find_in_include_path(char *file, char *entry, phar_archive_data *phar TSRMLS_DC);
char *phar_fix_filepath(char *path, int *new_len, int use_cwd TSRMLS_DC);
phar_entry_info * phar_open_jit(phar_archive_data *phar, phar_entry_info *entry, php_stream *fp,
}
/* }}} */
+/* {{{ 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
+ * reference to an external location as if it were within the phar archive. This
+ * is useful for writable temp files like databases
+ */
+PHP_METHOD(Phar, mount)
+{
+ char *fname, *arch, *entry, *path, *actual;
+ int fname_len, arch_len, entry_len, path_len, actual_len;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &path, &path_len, &actual, &actual_len) == FAILURE) {
+ return;
+ }
+
+ 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)) {
+ phar_archive_data **pphar;
+ if (SUCCESS != zend_hash_find(&(PHAR_GLOBALS->phar_fname_map), arch, arch_len, (void **)&pphar)) {
+ /* TODO: throw exception */
+ return;
+ }
+ if (SUCCESS != phar_mount_entry(*pphar, actual, actual_len, path, path_len TSRMLS_CC)) {
+ /* TODO: throw exception */
+ return;
+ }
+ }
+}
+/* }}} */
+
/* {{{ proto void Phar::webPhar([string alias, [string index, [string f404, [array mimetypes, [callback rewrites]]]]])
* mapPhar for web-based phars. Reads the currently executed file (a phar)
* and registers its manifest. When executed in the CLI or CGI command-line sapi,
ZEND_ARG_INFO(0, oldfile)
ZEND_END_ARG_INFO();
+static
+ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_mount, 0, 0, 2)
+ ZEND_ARG_INFO(0, inphar)
+ ZEND_ARG_INFO(0, externalfile)
+ZEND_END_ARG_INFO();
+
static
ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_conv, 0, 0, 0)
ZEND_ARG_INFO(0, compression)
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, webPhar, arginfo_phar_webPhar, 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, interceptFileFuncs, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
PHP_ME(Phar, getExtractList, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
}
/* mount an absolute path or uri to a path internal to the phar archive */
-int phar_mount_entry(phar_archive_data *phar, char *filename, int filename_len, char *path, int path_len, int is_dir TSRMLS_DC)
+int phar_mount_entry(phar_archive_data *phar, char *filename, int filename_len, char *path, int path_len TSRMLS_DC)
{
phar_entry_info entry = {0};
php_stream_statbuf ssb;
+ const char *err;
+ int is_dir;
+
+ if (phar_path_check(&path, &path_len, &err) > pcr_is_ok) {
+ return FAILURE;
+ }
#if PHP_MAJOR_VERSION < 6
if (PG(safe_mode) && (!php_checkuid(filename, NULL, CHECKUID_ALLOW_ONLY_FILE))) {
entry.is_mounted = 1;
entry.is_crc_checked = 1;
entry.fp_type = PHAR_TMP;
- entry.is_dir = is_dir;
if (SUCCESS != php_stream_stat_path(entry.link, &ssb)) {
efree(entry.link);
efree(entry.filename);
return FAILURE;
}
+ entry.is_dir = ssb.sb.st_mode & S_IFDIR ? 1 : 0;
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)) {