Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Zend/Optimizer/zend_func_infos.h
Original file line number Diff line number Diff line change
Expand Up @@ -596,6 +596,7 @@ static const func_info_t func_infos[] = {
F1("stream_get_line", MAY_BE_STRING|MAY_BE_FALSE),
F1("stream_resolve_include_path", MAY_BE_STRING|MAY_BE_FALSE),
F1("stream_get_wrappers", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_OF_STRING),
F1("stream_last_errors", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_OF_OBJECT),
F1("stream_get_transports", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_OF_STRING),
#if defined(HAVE_GETTIMEOFDAY)
F1("uniqid", MAY_BE_STRING),
Expand Down
22 changes: 22 additions & 0 deletions build/gen_stub.php
Original file line number Diff line number Diff line change
Expand Up @@ -3385,6 +3385,7 @@ public function __construct(
private /* readonly */ array $propertyInfos,
public array $funcInfos,
private readonly array $enumCaseInfos,
private readonly bool $generateCNameTable,
public readonly ?string $cond,
public ?int $phpVersionIdMinimumCompatibility,
public readonly bool $isUndocumentable,
Expand Down Expand Up @@ -3599,6 +3600,25 @@ public function getCDeclarations(): string

$code .= "} {$cEnumName};\n";

$caseCount = count($this->enumCaseInfos);

if ($this->generateCNameTable && $caseCount > 0) {
$cPrefix = 'ZEND_ENUM_' . str_replace('\\', '_', $this->name->toString());
$useGuard = $cPrefix . '_USE_NAME_TABLE';

$code .= "\n#define {$cPrefix}_CASE_COUNT {$caseCount}\n";
$code .= "\n#ifdef {$useGuard}\n";
$code .= "static const char *{$cEnumName}_case_names[{$cPrefix}_CASE_COUNT + 1] = {\n";

foreach ($this->enumCaseInfos as $case) {
$cName = $cPrefix . '_' . $case->name->case;
$code .= "\t[{$cName}] = \"{$case->name->case}\",\n";
}

$code .= "};\n";
$code .= "#endif\n";
}

if ($this->cond) {
$code .= "#endif\n";
}
Expand Down Expand Up @@ -5149,6 +5169,7 @@ function parseClass(
$isStrictProperties = array_key_exists('strict-properties', $tagMap);
$isNotSerializable = array_key_exists('not-serializable', $tagMap);
$isUndocumentable = $isUndocumentable || array_key_exists('undocumentable', $tagMap);
$generateCNameTable = array_key_exists('c-name-table', $tagMap);
foreach ($tags as $tag) {
if ($tag->name === 'alias') {
$alias = $tag->getValue();
Expand Down Expand Up @@ -5210,6 +5231,7 @@ function parseClass(
$properties,
$methods,
$enumCases,
$generateCNameTable,
$cond,
$minimumPhpVersionIdCompatibility,
$isUndocumentable
Expand Down
1 change: 1 addition & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -1689,6 +1689,7 @@ PHP_ADD_SOURCES([main/streams], m4_normalize([
memory.c
mmap.c
plain_wrapper.c
stream_errors.c
streams.c
transports.c
userspace.c
Expand Down
103 changes: 70 additions & 33 deletions ext/phar/dirstream.c
Original file line number Diff line number Diff line change
Expand Up @@ -247,27 +247,32 @@ php_stream *phar_wrapper_open_dir(php_stream_wrapper *wrapper, const char *path,
{
char *error;

php_url *resource = phar_parse_url(wrapper, path, mode, options);
if (!resource) {
php_stream_wrapper_log_error(wrapper, options, "phar url \"%s\" is unknown", path);
php_url *resource = phar_parse_url(wrapper, context, path, mode, options);
if (resource == NULL) {
php_stream_wrapper_log_warn(wrapper, context, options, InvalidUrl,
"phar url \"%s\" is unknown", path);
return NULL;
}

/* we must have at the very least phar://alias.phar/ */
if (!resource->scheme || !resource->host || !resource->path) {
if (resource->host && !resource->path) {
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)", path, ZSTR_VAL(resource->host));
php_stream_wrapper_log_warn(wrapper, context, options, InvalidPath,
"phar error: no directory in \"%s\", must have at least phar://%s/ for root directory (always use full path to a new phar)",
path, ZSTR_VAL(resource->host));
php_url_free(resource);
return NULL;
}
php_url_free(resource);
php_stream_wrapper_log_error(wrapper, options, "phar error: invalid url \"%s\", must have at least phar://%s/", path, path);
php_stream_wrapper_log_warn(wrapper, context, options, InvalidUrl,
"phar error: invalid url \"%s\", must have at least phar://%s/", path, path);
return NULL;
}

if (!zend_string_equals_literal_ci(resource->scheme, "phar")) {
php_url_free(resource);
php_stream_wrapper_log_error(wrapper, options, "phar error: not a phar url \"%s\"", path);
php_stream_wrapper_log_warn(wrapper, context, options, ProtocolUnsupported,
"phar error: not a phar url \"%s\"", path);
return NULL;
}

Expand All @@ -276,10 +281,11 @@ php_stream *phar_wrapper_open_dir(php_stream_wrapper *wrapper, const char *path,
const phar_archive_data *phar = phar_get_archive(ZSTR_VAL(resource->host), ZSTR_LEN(resource->host), NULL, 0, &error);
if (!phar) {
if (error) {
php_stream_wrapper_log_error(wrapper, options, "%s", error);
php_stream_wrapper_log_warn(wrapper, context, options, NotFound, "%s", error);
efree(error);
} else {
php_stream_wrapper_log_error(wrapper, options, "phar file \"%s\" is unknown", ZSTR_VAL(resource->host));
php_stream_wrapper_log_warn(wrapper, context, options, NotFound,
"phar file \"%s\" is unknown", ZSTR_VAL(resource->host));
}
php_url_free(resource);
return NULL;
Expand Down Expand Up @@ -344,7 +350,8 @@ int phar_wrapper_mkdir(php_stream_wrapper *wrapper, const char *url_from, int mo
/* pre-readonly check, we need to know if this is a data phar */
zend_string *arch = phar_split_fname(url_from, strlen(url_from), NULL, 2, 2);
if (!arch) {
php_stream_wrapper_log_error(wrapper, options, "phar error: cannot create directory \"%s\", no phar archive specified", url_from);
php_stream_wrapper_log_warn(wrapper, context, options, NotFound,
"phar error: cannot create directory \"%s\", no phar archive specified", url_from);
return 0;
}

Expand All @@ -353,30 +360,35 @@ int phar_wrapper_mkdir(php_stream_wrapper *wrapper, const char *url_from, int mo
zend_string_release_ex(arch, false);

if (PHAR_G(readonly) && (!phar || !phar->is_data)) {
php_stream_wrapper_log_error(wrapper, options, "phar error: cannot create directory \"%s\", write operations disabled", url_from);
php_stream_wrapper_log_warn(wrapper, context, options, Readonly,
"phar error: cannot create directory \"%s\", write operations disabled", url_from);
return 0;
}

if ((resource = phar_parse_url(wrapper, url_from, "w", options)) == NULL) {
if ((resource = phar_parse_url(wrapper, context, url_from, "w", options)) == NULL) {
return 0;
}

/* we must have at the very least phar://alias.phar/internalfile.php */
if (!resource->scheme || !resource->host || !resource->path) {
php_url_free(resource);
php_stream_wrapper_log_error(wrapper, options, "phar error: invalid url \"%s\"", url_from);
php_stream_wrapper_log_warn(wrapper, context, options, InvalidUrl,
"phar error: invalid url \"%s\"", url_from);
return 0;
}

if (!zend_string_equals_literal_ci(resource->scheme, "phar")) {
php_url_free(resource);
php_stream_wrapper_log_error(wrapper, options, "phar error: not a phar stream url \"%s\"", url_from);
php_stream_wrapper_log_warn(wrapper, context, options, ProtocolUnsupported,
"phar error: not a phar stream url \"%s\"", url_from);
return 0;
}

phar = phar_get_archive(ZSTR_VAL(resource->host), ZSTR_LEN(resource->host), NULL, 0, &error);
if (!phar) {
php_stream_wrapper_log_error(wrapper, options, "phar error: cannot create directory \"%s\" in phar \"%s\", error retrieving phar information: %s", ZSTR_VAL(resource->path) + 1, ZSTR_VAL(resource->host), error);
php_stream_wrapper_log_warn(wrapper, context, options, MkdirFailed,
"phar error: cannot create directory \"%s\" in phar \"%s\", error retrieving phar information: %s",
ZSTR_VAL(resource->path) + 1, ZSTR_VAL(resource->host), error);
efree(error);
php_url_free(resource);
return 0;
Expand All @@ -389,27 +401,35 @@ int phar_wrapper_mkdir(php_stream_wrapper *wrapper, const char *url_from, int mo
zend_string_efree(e->filename);
efree(e);
}
php_stream_wrapper_log_error(wrapper, options, "phar error: cannot create directory \"%s\" in phar \"%s\", directory already exists", ZSTR_VAL(resource->path)+1, ZSTR_VAL(resource->host));
php_stream_wrapper_log_warn(wrapper, context, options, AlreadyExists,
"phar error: cannot create directory \"%s\" in phar \"%s\", directory already exists",
ZSTR_VAL(resource->path)+1, ZSTR_VAL(resource->host));
php_url_free(resource);
return 0;
}

if (error) {
php_stream_wrapper_log_error(wrapper, options, "phar error: cannot create directory \"%s\" in phar \"%s\", %s", ZSTR_VAL(resource->path)+1, ZSTR_VAL(resource->host), error);
php_stream_wrapper_log_warn(wrapper, context, options, MkdirFailed,
"phar error: cannot create directory \"%s\" in phar \"%s\", %s",
ZSTR_VAL(resource->path)+1, ZSTR_VAL(resource->host), error);
efree(error);
php_url_free(resource);
return 0;
}

if (phar_get_entry_info_dir(phar, ZSTR_VAL(resource->path) + 1, ZSTR_LEN(resource->path) - 1, 0, &error, true)) {
/* entry exists as a file */
php_stream_wrapper_log_error(wrapper, options, "phar error: cannot create directory \"%s\" in phar \"%s\", file already exists", ZSTR_VAL(resource->path)+1, ZSTR_VAL(resource->host));
php_stream_wrapper_log_warn(wrapper, context, options, AlreadyExists,
"phar error: cannot create directory \"%s\" in phar \"%s\", file already exists",
ZSTR_VAL(resource->path)+1, ZSTR_VAL(resource->host));
php_url_free(resource);
return 0;
}

if (error) {
php_stream_wrapper_log_error(wrapper, options, "phar error: cannot create directory \"%s\" in phar \"%s\", %s", ZSTR_VAL(resource->path)+1, ZSTR_VAL(resource->host), error);
php_stream_wrapper_log_warn(wrapper, context, options, MkdirFailed,
"phar error: cannot create directory \"%s\" in phar \"%s\", %s",
ZSTR_VAL(resource->path)+1, ZSTR_VAL(resource->host), error);
efree(error);
php_url_free(resource);
return 0;
Expand Down Expand Up @@ -437,17 +457,20 @@ int phar_wrapper_mkdir(php_stream_wrapper *wrapper, const char *url_from, int mo
entry.flags = PHAR_ENT_PERM_DEF_DIR;
entry.old_flags = PHAR_ENT_PERM_DEF_DIR;

void *had_been_added = zend_hash_add_mem(&phar->manifest, entry.filename, &entry, sizeof(phar_entry_info));
if (!had_been_added) {
php_stream_wrapper_log_error(wrapper, options, "phar error: cannot create directory \"%s\" in phar \"%s\", adding to manifest failed", ZSTR_VAL(entry.filename), ZSTR_VAL(phar->fname));
if (NULL == zend_hash_add_mem(&phar->manifest, entry.filename, &entry, sizeof(phar_entry_info))) {
php_stream_wrapper_log_warn(wrapper, context, options, MkdirFailed,
"phar error: cannot create directory \"%s\" in phar \"%s\", adding to manifest failed",
ZSTR_VAL(entry.filename), ZSTR_VAL(phar->fname));
zend_string_efree(entry.filename);
return 0;
}

phar_flush(phar, &error);

if (error) {
php_stream_wrapper_log_error(wrapper, options, "phar error: cannot create directory \"%s\" in phar \"%s\", %s", ZSTR_VAL(entry.filename), ZSTR_VAL(phar->fname), error);
php_stream_wrapper_log_warn(wrapper, context, options, MkdirFailed,
"phar error: cannot create directory \"%s\" in phar \"%s\", %s",
ZSTR_VAL(entry.filename), ZSTR_VAL(phar->fname), error);
zend_hash_del(&phar->manifest, entry.filename);
efree(error);
return 0;
Expand All @@ -468,7 +491,8 @@ int phar_wrapper_rmdir(php_stream_wrapper *wrapper, const char *url, int options
/* pre-readonly check, we need to know if this is a data phar */
zend_string *arch = phar_split_fname(url, strlen(url), NULL, 2, 2);
if (!arch) {
php_stream_wrapper_log_error(wrapper, options, "phar error: cannot remove directory \"%s\", no phar archive specified, or phar archive does not exist", url);
php_stream_wrapper_log_warn(wrapper, context, options, NotFound,
"phar error: cannot remove directory \"%s\", no phar archive specified, or phar archive does not exist", url);
return 0;
}

Expand All @@ -477,31 +501,36 @@ int phar_wrapper_rmdir(php_stream_wrapper *wrapper, const char *url, int options
zend_string_release_ex(arch, false);

if (PHAR_G(readonly) && (!phar || !phar->is_data)) {
php_stream_wrapper_log_error(wrapper, options, "phar error: cannot rmdir directory \"%s\", write operations disabled", url);
php_stream_wrapper_log_warn(wrapper, context, options, Readonly,
"phar error: cannot rmdir directory \"%s\", write operations disabled", url);
return 0;
}

php_url *resource = phar_parse_url(wrapper, url, "w", options);
php_url *resource = phar_parse_url(wrapper, context, url, "w", options);
if (!resource) {
return 0;
}

/* we must have at the very least phar://alias.phar/internalfile.php */
if (!resource->scheme || !resource->host || !resource->path) {
php_url_free(resource);
php_stream_wrapper_log_error(wrapper, options, "phar error: invalid url \"%s\"", url);
php_stream_wrapper_log_warn(wrapper, context, options, InvalidUrl,
"phar error: invalid url \"%s\"", url);
return 0;
}

if (!zend_string_equals_literal_ci(resource->scheme, "phar")) {
php_url_free(resource);
php_stream_wrapper_log_error(wrapper, options, "phar error: not a phar stream url \"%s\"", url);
php_stream_wrapper_log_warn(wrapper, context, options, ProtocolUnsupported,
"phar error: not a phar stream url \"%s\"", url);
return 0;
}

phar = phar_get_archive(ZSTR_VAL(resource->host), ZSTR_LEN(resource->host), NULL, 0, &error);
if (!phar) {
php_stream_wrapper_log_error(wrapper, options, "phar error: cannot remove directory \"%s\" in phar \"%s\", error retrieving phar information: %s", ZSTR_VAL(resource->path)+1, ZSTR_VAL(resource->host), error);
php_stream_wrapper_log_warn(wrapper, context, options, RmdirFailed,
"phar error: cannot remove directory \"%s\" in phar \"%s\", error retrieving phar information: %s",
ZSTR_VAL(resource->path)+1, ZSTR_VAL(resource->host), error);
efree(error);
php_url_free(resource);
return 0;
Expand All @@ -512,10 +541,14 @@ int phar_wrapper_rmdir(php_stream_wrapper *wrapper, const char *url, int options
phar_entry_info *entry = phar_get_entry_info_dir(phar, ZSTR_VAL(resource->path) + 1, path_len, 2, &error, true);
if (!entry) {
if (error) {
php_stream_wrapper_log_error(wrapper, options, "phar error: cannot remove directory \"%s\" in phar \"%s\", %s", ZSTR_VAL(resource->path)+1, ZSTR_VAL(resource->host), error);
php_stream_wrapper_log_warn(wrapper, context, options, RmdirFailed,
"phar error: cannot remove directory \"%s\" in phar \"%s\", %s",
ZSTR_VAL(resource->path)+1, ZSTR_VAL(resource->host), error);
efree(error);
} else {
php_stream_wrapper_log_error(wrapper, options, "phar error: cannot remove directory \"%s\" in phar \"%s\", directory does not exist", ZSTR_VAL(resource->path)+1, ZSTR_VAL(resource->host));
php_stream_wrapper_log_warn(wrapper, context, options, NotFound,
"phar error: cannot remove directory \"%s\" in phar \"%s\", directory does not exist",
ZSTR_VAL(resource->path)+1, ZSTR_VAL(resource->host));
}
php_url_free(resource);
return 0;
Expand All @@ -529,7 +562,8 @@ int phar_wrapper_rmdir(php_stream_wrapper *wrapper, const char *url, int options
zend_string_starts_with_cstr(str_key, ZSTR_VAL(resource->path)+1, path_len)
&& IS_SLASH(ZSTR_VAL(str_key)[path_len])
) {
php_stream_wrapper_log_error(wrapper, options, "phar error: Directory not empty");
php_stream_wrapper_log_warn(wrapper, context, options, RmdirFailed,
"phar error: Directory not empty");
if (entry->is_temp_dir) {
zend_string_efree(entry->filename);
efree(entry);
Expand All @@ -545,7 +579,8 @@ int phar_wrapper_rmdir(php_stream_wrapper *wrapper, const char *url, int options
zend_string_starts_with_cstr(str_key, ZSTR_VAL(resource->path)+1, path_len)
&& IS_SLASH(ZSTR_VAL(str_key)[path_len])
) {
php_stream_wrapper_log_error(wrapper, options, "phar error: Directory not empty");
php_stream_wrapper_log_warn(wrapper, context, options, RmdirFailed,
"phar error: Directory not empty");
if (entry->is_temp_dir) {
zend_string_efree(entry->filename);
efree(entry);
Expand All @@ -566,7 +601,9 @@ int phar_wrapper_rmdir(php_stream_wrapper *wrapper, const char *url, int options
phar_flush(phar, &error);

if (error) {
php_stream_wrapper_log_error(wrapper, options, "phar error: cannot remove directory \"%s\" in phar \"%s\", %s", ZSTR_VAL(entry->filename), ZSTR_VAL(phar->fname), error);
php_stream_wrapper_log_warn(wrapper, context, options, RmdirFailed,
"phar error: cannot remove directory \"%s\" in phar \"%s\", %s",
ZSTR_VAL(entry->filename), ZSTR_VAL(phar->fname), error);
php_url_free(resource);
efree(error);
return 0;
Expand Down
2 changes: 1 addition & 1 deletion ext/phar/dirstream.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ int phar_wrapper_rmdir(php_stream_wrapper *wrapper, const char *url, int options
#ifdef PHAR_DIRSTREAM
#include "ext/standard/url.h"

php_url* phar_parse_url(php_stream_wrapper *wrapper, const char *filename, const char *mode, int options);
php_url* phar_parse_url(php_stream_wrapper *wrapper, php_stream_context *context, const char *filename, const char *mode, int options);

/* directory handlers */
static ssize_t phar_dir_write(php_stream *stream, const char *buf, size_t count);
Expand Down
Loading
Loading