示例#1
0
static void phar_file_stat(const char *filename, php_stat_len filename_length, int type, void (*orig_stat_func)(INTERNAL_FUNCTION_PARAMETERS), INTERNAL_FUNCTION_PARAMETERS) /* {{{ */
{
	if (!filename_length) {
		RETURN_FALSE;
	}

	if (!IS_ABSOLUTE_PATH(filename, filename_length) && !strstr(filename, "://")) {
		char *arch, *entry, *fname;
		int arch_len, entry_len, fname_len;
		zend_stat_t sb = {0};
		phar_entry_info *data = NULL;
		phar_archive_data *phar;

		fname = (char*)zend_get_executed_filename();

		/* we are checking for existence of a file within the relative path.  Chances are good that this is
		   retrieving something from within the phar archive */

		if (strncasecmp(fname, "phar://", 7)) {
			goto skip_phar;
		}
		fname_len = strlen(fname);
		if (PHAR_G(last_phar) && fname_len - 7 >= PHAR_G(last_phar_name_len) && !memcmp(fname + 7, PHAR_G(last_phar_name), PHAR_G(last_phar_name_len))) {
			arch = estrndup(PHAR_G(last_phar_name), PHAR_G(last_phar_name_len));
			arch_len = PHAR_G(last_phar_name_len);
			entry = estrndup(filename, filename_length);
			/* fopen within phar, if :// is not in the url, then prepend phar://<archive>/ */
			entry_len = (int) filename_length;
			phar = PHAR_G(last_phar);
			goto splitted;
		}
		if (SUCCESS == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len, 2, 0)) {

			efree(entry);
			entry = estrndup(filename, filename_length);
			/* fopen within phar, if :// is not in the url, then prepend phar://<archive>/ */
			entry_len = (int) filename_length;
			if (FAILURE == phar_get_archive(&phar, arch, arch_len, NULL, 0, NULL)) {
				efree(arch);
				efree(entry);
				goto skip_phar;
			}
splitted:
			entry = phar_fix_filepath(entry, &entry_len, 1);
			if (entry[0] == '/') {
				if (NULL != (data = zend_hash_str_find_ptr(&(phar->manifest), entry + 1, entry_len - 1))) {
					efree(entry);
					goto stat_entry;
				}
				goto notfound;
			}
			if (NULL != (data = zend_hash_str_find_ptr(&(phar->manifest), entry, entry_len))) {
				efree(entry);
				goto stat_entry;
			}
			if (zend_hash_str_exists(&(phar->virtual_dirs), entry, entry_len)) {
				efree(entry);
				efree(arch);
				if (IS_EXISTS_CHECK(type)) {
					RETURN_TRUE;
				}
				sb.st_size = 0;
				sb.st_mode = 0777;
				sb.st_mode |= S_IFDIR; /* regular directory */
#ifdef NETWARE
				sb.st_mtime.tv_sec = phar->max_timestamp;
				sb.st_atime.tv_sec = phar->max_timestamp;
				sb.st_ctime.tv_sec = phar->max_timestamp;
#else
				sb.st_mtime = phar->max_timestamp;
				sb.st_atime = phar->max_timestamp;
				sb.st_ctime = phar->max_timestamp;
#endif
				goto statme_baby;
			} else {
				char *save;
				int save_len;

notfound:
				efree(entry);
				save = PHAR_G(cwd);
				save_len = PHAR_G(cwd_len);
				/* this file is not in the current directory, use the original path */
				entry = estrndup(filename, filename_length);
				entry_len = filename_length;
				PHAR_G(cwd) = "/";
				PHAR_G(cwd_len) = 0;
				/* clean path without cwd */
				entry = phar_fix_filepath(entry, &entry_len, 1);
				if (NULL != (data = zend_hash_str_find_ptr(&(phar->manifest), entry + 1, entry_len - 1))) {
					PHAR_G(cwd) = save;
					PHAR_G(cwd_len) = save_len;
					efree(entry);
					if (IS_EXISTS_CHECK(type)) {
						efree(arch);
						RETURN_TRUE;
					}
					goto stat_entry;
				}
				if (zend_hash_str_exists(&(phar->virtual_dirs), entry + 1, entry_len - 1)) {
					PHAR_G(cwd) = save;
					PHAR_G(cwd_len) = save_len;
					efree(entry);
					efree(arch);
					if (IS_EXISTS_CHECK(type)) {
						RETURN_TRUE;
					}
					sb.st_size = 0;
					sb.st_mode = 0777;
					sb.st_mode |= S_IFDIR; /* regular directory */
#ifdef NETWARE
					sb.st_mtime.tv_sec = phar->max_timestamp;
					sb.st_atime.tv_sec = phar->max_timestamp;
					sb.st_ctime.tv_sec = phar->max_timestamp;
#else
					sb.st_mtime = phar->max_timestamp;
					sb.st_atime = phar->max_timestamp;
					sb.st_ctime = phar->max_timestamp;
#endif
					goto statme_baby;
				}
				PHAR_G(cwd) = save;
				PHAR_G(cwd_len) = save_len;
				efree(entry);
				efree(arch);
				/* Error Occurred */
				if (!IS_EXISTS_CHECK(type)) {
					php_error_docref(NULL, E_WARNING, "%sstat failed for %s", IS_LINK_OPERATION(type) ? "L" : "", filename);
				}
				RETURN_FALSE;
			}
stat_entry:
			efree(arch);
			if (!data->is_dir) {
				sb.st_size = data->uncompressed_filesize;
				sb.st_mode = data->flags & PHAR_ENT_PERM_MASK;
				if (data->link) {
					sb.st_mode |= S_IFREG|S_IFLNK; /* regular file */
				} else {
					sb.st_mode |= S_IFREG; /* regular file */
				}
				/* timestamp is just the timestamp when this was added to the phar */
#ifdef NETWARE
				sb.st_mtime.tv_sec = data->timestamp;
				sb.st_atime.tv_sec = data->timestamp;
				sb.st_ctime.tv_sec = data->timestamp;
#else
				sb.st_mtime = data->timestamp;
				sb.st_atime = data->timestamp;
				sb.st_ctime = data->timestamp;
#endif
			} else {
				sb.st_size = 0;
				sb.st_mode = data->flags & PHAR_ENT_PERM_MASK;
				sb.st_mode |= S_IFDIR; /* regular directory */
				if (data->link) {
					sb.st_mode |= S_IFLNK;
				}
				/* timestamp is just the timestamp when this was added to the phar */
#ifdef NETWARE
				sb.st_mtime.tv_sec = data->timestamp;
				sb.st_atime.tv_sec = data->timestamp;
				sb.st_ctime.tv_sec = data->timestamp;
#else
				sb.st_mtime = data->timestamp;
				sb.st_atime = data->timestamp;
				sb.st_ctime = data->timestamp;
#endif
			}

statme_baby:
			if (!phar->is_writeable) {
				sb.st_mode = (sb.st_mode & 0555) | (sb.st_mode & ~0777);
			}

			sb.st_nlink = 1;
			sb.st_rdev = -1;
			/* this is only for APC, so use /dev/null device - no chance of conflict there! */
			sb.st_dev = 0xc;
			/* generate unique inode number for alias/filename, so no phars will conflict */
			if (data) {
				sb.st_ino = data->inode;
			}
#ifndef PHP_WIN32
			sb.st_blksize = -1;
			sb.st_blocks = -1;
#endif
			phar_fancy_stat(&sb, type, return_value);
			return;
		}
	}
skip_phar:
	orig_stat_func(INTERNAL_FUNCTION_PARAM_PASSTHRU);
	return;
}
示例#2
0
/**
 * Open a phar file for streams API
 */
php_url* phar_parse_url(php_stream_wrapper *wrapper, const char *filename, const char *mode, int options) /* {{{ */
{
	php_url *resource;
	char *arch = NULL, *entry = NULL, *error;
	int arch_len, entry_len;

	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, "phar error: open mode append not supported");
		}
		return NULL;
	}
	if (phar_split_fname(filename, strlen(filename), &arch, &arch_len, &entry, &entry_len, 2, (mode[0] == 'w' ? 2 : 0)) == FAILURE) {
		if (!(options & PHP_STREAM_URL_STAT_QUIET)) {
			if (arch && !entry) {
				php_stream_wrapper_log_error(wrapper, options, "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, "phar error: invalid url or non-existent phar \"%s\"", filename);
			}
		}
		return NULL;
	}
	resource = ecalloc(1, sizeof(php_url));
	resource->scheme = estrndup("phar", 4);
	resource->host = arch;

	resource->path = entry;
#if MBO_0
		if (resource) {
			fprintf(stderr, "Alias:     %s\n", alias);
			fprintf(stderr, "Scheme:    %s\n", resource->scheme);
/*			fprintf(stderr, "User:      %s\n", resource->user);*/
/*			fprintf(stderr, "Pass:      %s\n", resource->pass ? "***" : NULL);*/
			fprintf(stderr, "Host:      %s\n", resource->host);
/*			fprintf(stderr, "Port:      %d\n", resource->port);*/
			fprintf(stderr, "Path:      %s\n", resource->path);
/*			fprintf(stderr, "Query:     %s\n", resource->query);*/
/*			fprintf(stderr, "Fragment:  %s\n", resource->fragment);*/
		}
#endif
	if (mode[0] == 'w' || (mode[0] == 'r' && mode[1] == '+')) {
		phar_archive_data *pphar = NULL, *phar;

		if (PHAR_G(request_init) && PHAR_G(phar_fname_map.u.flags) && NULL == (pphar = zend_hash_str_find_ptr(&(PHAR_G(phar_fname_map)), arch, arch_len))) {
			pphar = NULL;
		}
		if (PHAR_G(readonly) && (!pphar || !pphar->is_data)) {
			if (!(options & PHP_STREAM_URL_STAT_QUIET)) {
				php_stream_wrapper_log_error(wrapper, options, "phar error: write operations disabled by the php.ini setting phar.readonly");
			}
			php_url_free(resource);
			return NULL;
		}
		if (phar_open_or_create_filename(resource->host, arch_len, NULL, 0, 0, options, &phar, &error) == FAILURE)
		{
			if (error) {
				if (!(options & PHP_STREAM_URL_STAT_QUIET)) {
					php_stream_wrapper_log_error(wrapper, options, "%s", error);
				}
				efree(error);
			}
			php_url_free(resource);
			return NULL;
		}
		if (phar->is_persistent && FAILURE == phar_copy_on_write(&phar)) {
			if (error) {
				spprintf(&error, 0, "Cannot open cached phar '%s' as writeable, copy on write failed", resource->host);
				if (!(options & PHP_STREAM_URL_STAT_QUIET)) {
					php_stream_wrapper_log_error(wrapper, options, "%s", error);
				}
				efree(error);
			}
			php_url_free(resource);
			return NULL;
		}
	} else {
		if (phar_open_from_filename(resource->host, arch_len, NULL, 0, options, NULL, &error) == FAILURE)
		{
			if (error) {
				if (!(options & PHP_STREAM_URL_STAT_QUIET)) {
					php_stream_wrapper_log_error(wrapper, options, "%s", error);
				}
				efree(error);
			}
			php_url_free(resource);
			return NULL;
		}
	}
	return resource;
}