uint host_len;
/* pre-readonly check, we need to know if this is a data phar */
- if (FAILURE == phar_split_fname(url_from, strlen(url_from), &arch, &arch_len, &entry2, &entry_len TSRMLS_CC)) {
+ if (FAILURE == phar_split_fname(url_from, strlen(url_from), &arch, &arch_len, &entry2, &entry_len, 2, 2 TSRMLS_CC)) {
php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: cannot create directory \"%s\", no phar archive specified", url_from);
return FAILURE;
}
uint host_len;
/* pre-readonly check, we need to know if this is a data phar */
- if (FAILURE == phar_split_fname(url, strlen(url), &arch, &arch_len, &entry2, &entry_len TSRMLS_CC)) {
- php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: cannot remove directory \"%s\", no phar archive specified", url);
+ if (FAILURE == phar_split_fname(url, strlen(url), &arch, &arch_len, &entry2, &entry_len, 2, 2 TSRMLS_CC)) {
+ php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: cannot remove directory \"%s\", no phar archive specified, or phar archive does not exist", url);
return FAILURE;
}
if (FAILURE == phar_get_archive(&phar, arch, arch_len, NULL, 0, NULL TSRMLS_CC)) {
goto skip_phar;
}
fname_len = strlen(fname);
- if (SUCCESS == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len TSRMLS_CC)) {
+ if (SUCCESS == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len, 2, 0 TSRMLS_CC)) {
php_stream_context *context = NULL;
php_stream *stream;
char *name;
goto skip_phar;
}
fname_len = strlen(fname);
- if (SUCCESS == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len TSRMLS_CC)) {
+ if (SUCCESS == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len, 2, 0 TSRMLS_CC)) {
char *name, *old;
phar_archive_data **pphar;
goto skip_phar;
}
fname_len = strlen(fname);
- if (FAILURE == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len TSRMLS_CC)) {
+ if (FAILURE == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len, 2, 0 TSRMLS_CC)) {
goto skip_phar;
}
goto skip_phar;
}
fname_len = strlen(fname);
- if (FAILURE == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len TSRMLS_CC)) {
+ if (FAILURE == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len, 2, 0 TSRMLS_CC)) {
goto skip_phar;
}
goto skip_phar;
}
fname_len = strlen(fname);
- if (SUCCESS == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len TSRMLS_CC)) {
+ if (SUCCESS == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len, 2, 0 TSRMLS_CC)) {
phar_archive_data **pphar;
efree(entry);
goto skip_phar;
}
fname_len = strlen(fname);
- if (SUCCESS == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len TSRMLS_CC)) {
+ if (SUCCESS == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len, 2, 0 TSRMLS_CC)) {
phar_archive_data **pphar;
efree(entry);
goto skip_phar;
}
fname_len = strlen(fname);
- if (SUCCESS == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len TSRMLS_CC)) {
+ if (SUCCESS == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len, 2, 0 TSRMLS_CC)) {
phar_archive_data **pphar;
efree(entry);
/**
* Create or open a phar for writing
*/
-int phar_open_or_create_filename(char *fname, int fname_len, char *alias, int alias_len, char *objname, int options, phar_archive_data** pphar, char **error TSRMLS_DC) /* {{{ */
+int phar_open_or_create_filename(char *fname, int fname_len, char *alias, int alias_len, int is_data, int options, phar_archive_data** pphar, char **error TSRMLS_DC) /* {{{ */
{
- const char *ext_str;
- int ext_len, is_data = 0, zip = 0, tar = 0;
+ const char *ext_str, *z;
+ int ext_len;
if (error) {
*error = NULL;
}
- if (phar_detect_phar_fname_ext(fname, 1, &ext_str, &ext_len) == SUCCESS) {
-
- if (ext_len >= sizeof(".zip")-1 && !memcmp((void *) ext_str, (void *) ".zip", sizeof(".zip")-1)) {
- zip = 1;
- }
-
- if ((ext_len >= sizeof(".tar")-1 && !memcmp((void *) ext_str, (void *) ".tar", sizeof(".tar")-1)) || (ext_len >= sizeof(".tgz")-1 && !memcmp((void *) ext_str, (void *) ".tgz", sizeof(".tgz")-1))) {
- tar = 1;
+ /* first try to open an existing file */
+ if (phar_detect_phar_fname_ext(fname, 1, &ext_str, &ext_len, !is_data, 0, 1 TSRMLS_CC) == SUCCESS) {
+ goto check_file;
+ }
+ /* next try to create a new file */
+ if (FAILURE == phar_detect_phar_fname_ext(fname, 1, &ext_str, &ext_len, !is_data, 1, 1 TSRMLS_CC)) {
+ if (error) {
+ spprintf(error, 0, "Cannot create phar '%s', file extension (or combination) not recognised", fname);
}
+ return FAILURE;
+ }
- if (tar || zip) {
- if (objname && strncmp(objname, "PharData", 8) != 0) {
- /* Nested exception causes memleak here */
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot open '%s' as a Phar object. Use PharData::__construct() for a standard %s archive", fname, tar ? "tar" : "zip");
- return FAILURE;
+check_file:
+ if (phar_open_loaded(fname, fname_len, alias, alias_len, is_data, options, pphar, 0 TSRMLS_CC) == SUCCESS) {
+ if (is_data && !((*pphar)->is_tar || (*pphar)->is_zip)) {
+ if (error) {
+ spprintf(error, 0, "Cannot open '%s' as a PharData object. Use Phar::__construct() for executable archives", fname);
}
- is_data = 1;
- } else {
- if (objname && strncmp(objname, "PharData", 8) == 0) {
- /* Nested exception causes memleak here */
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot open '%s' as a PharData object. Use Phar::__construct() for archives named other than .zip or .tar", fname);
+ }
+ if (PHAR_G(readonly) && !is_data && ((*pphar)->is_tar || (*pphar)->is_zip)) {
+ phar_entry_info *stub;
+ if (FAILURE == zend_hash_find(&((*pphar)->manifest), ".phar/stub.php", sizeof(".phar/stub.php")-1, (void **)&stub)) {
+ spprintf(error, 0, "'%s' is not a phar archive. Use PharData::__construct() for a standard zip or tar archive", fname);
return FAILURE;
}
}
-
- } else {
-
- /* Nested exception causes memleak here */
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot open '%s' as a %s object, file extension (or combination) not recognised", fname, objname);
- return FAILURE;
- }
-
- if (phar_open_loaded(fname, fname_len, alias, alias_len, is_data, options, pphar, 0 TSRMLS_CC) == SUCCESS) {
if (pphar && (!PHAR_G(readonly) || is_data)) {
(*pphar)->is_writeable = 1;
}
return SUCCESS;
}
- if ((ext_len >= sizeof(".phar.zip")-1 && !memcmp((void *) ext_str, (void *) ".phar.zip", sizeof(".phar.zip")-1)) || zip) {
+ if (ext_len > 3 && (z = memchr(ext_str, 'z', ext_len)) && ((ext_str + ext_len) - z >= 2) && !memcmp(z + 1, "ip", 2)) {
// assume zip-based phar
return phar_open_or_create_zip(fname, fname_len, alias, alias_len, is_data, options, pphar, error TSRMLS_CC);
}
- if ((ext_len >= sizeof(".phar.tar")-1 && !memcmp((void *) ext_str, (void *) ".phar.tar", sizeof(".phar.tar")-1)) || tar) {
+ if (ext_len > 3 && (z = memchr(ext_str, 't', ext_len)) && ((ext_str + ext_len) - z >= 2) && !memcmp(z + 1, "ar", 2)) {
// assume tar-based phar
return phar_open_or_create_tar(fname, fname_len, alias, alias_len, is_data, options, pphar, error TSRMLS_CC);
}
}
/* }}} */
-int phar_detect_phar_fname_ext(const char *filename, int check_length, const char **ext_str, int *ext_len) /* {{{ */
+/*
+ * given the location of the file extension and the start of the file path,
+ * determine the end of the portion of the path (i.e. /path/to/file.ext/blah
+ * grabs "/path/to/file.ext" as does the straight /path/to/file.ext),
+ * stat it to determine if it exists.
+ * if so, check to see if it is a directory and fail if so
+ * if not, check to see if its dirname() exists (i.e. "/path/to") and is a directory
+ * succeed if we are creating the file, otherwise fail.
+ */
+static int phar_analyze_path(const char *fname, const char *ext, int ext_len, int for_create TSRMLS_DC)
+{
+ php_stream_statbuf ssb;
+ char *realpath, old, *a = (char *)(ext + ext_len);
+
+ old = *a;
+ *a = '\0';
+ if ((realpath = expand_filepath(fname, NULL TSRMLS_CC))) {
+ if (zend_hash_exists(&(PHAR_GLOBALS->phar_fname_map), realpath, strlen(realpath))) {
+ *a = old;
+ efree(realpath);
+ return SUCCESS;
+ }
+ efree(realpath);
+ }
+ if (SUCCESS == php_stream_stat_path((char *) fname, &ssb)) {
+ *a = old;
+ if (ssb.sb.st_mode & S_IFDIR) {
+ return FAILURE;
+ }
+ if (for_create == 1) {
+ return FAILURE;
+ }
+ return SUCCESS;
+ } else {
+ char *slash;
+
+ if (!for_create) {
+ *a = old;
+ return FAILURE;
+ }
+ slash = (char *) strrchr(fname, '/');
+ *a = old;
+ if (slash) {
+ old = *slash;
+ *slash = '\0';
+ }
+ if (SUCCESS != php_stream_stat_path((char *) fname, &ssb)) {
+ if (slash) {
+ *slash = old;
+ } else {
+ if (!(realpath = expand_filepath(fname, NULL TSRMLS_CC))) {
+ return FAILURE;
+ }
+ a = strstr(realpath, fname) + ((ext - fname) + ext_len);
+ *a = '\0';
+ slash = strrchr(realpath, '/');
+ if (slash) {
+ *slash = '\0';
+ } else {
+ efree(realpath);
+ return FAILURE;
+ }
+ if (SUCCESS != php_stream_stat_path(realpath, &ssb)) {
+ efree(realpath);
+ return FAILURE;
+ }
+ efree(realpath);
+ if (ssb.sb.st_mode & S_IFDIR) {
+ return SUCCESS;
+ }
+ }
+ return FAILURE;
+ }
+ if (slash) {
+ *slash = old;
+ }
+ if (ssb.sb.st_mode & S_IFDIR) {
+ return SUCCESS;
+ }
+ return FAILURE;
+ }
+}
+
+/* check for ".phar" in extension */
+static int phar_check_str(const char *fname, const char *ext_str, int ext_len, int executable, int for_create TSRMLS_DC)
{
- int i;
- char end;
+ char test[51];
const char *pos;
-#define EXTINF(check, ext) { check, ext, sizeof(ext)-1 }
- const struct {
- int check;
- const char * const ext;
- int len;
- } ext_info[] = {
- /* longer exts must be specified later */
- EXTINF(1, ".php"),
- EXTINF(0, ".phar"),
- EXTINF(0, ".tgz"),
- EXTINF(0, ".zip"),
- EXTINF(0, ".tar"),
- EXTINF(0, ".tar.gz"),
- EXTINF(0, ".tar.bz2"),
- EXTINF(0, ".phar.gz"),
- EXTINF(0, ".phar.bz2"),
- EXTINF(0, ".phar.php"),
- EXTINF(0, ".phar.tar"),
- EXTINF(0, ".phar.zip"),
- EXTINF(0, ".phar.tar.gz"),
- EXTINF(0, ".phar.tar.bz2"),
- EXTINF(0, ".phar.tar.php"),
- EXTINF(0, ".phar.zip.php")};
+
+ if (ext_len >= 50) {
+ return FAILURE;
+ }
+ if (executable == 1) {
+ /* copy "." as well */
+ memcpy(test, ext_str - 1, ext_len + 1);
+ test[ext_len + 1] = '\0';
+ /* executable phars must contain ".phar" as a valid extension (phar://.pharmy/oops is invalid) */
+ /* (phar://hi/there/.phar/oops is also invalid) */
+ if ((pos = strstr(test, ".phar")) && (*(pos - 1) != '/')
+ && (pos += 5) && (*pos == '\0' || *pos == '/' || *pos == '.')) {
+ return phar_analyze_path(fname, ext_str, ext_len, for_create TSRMLS_CC);
+ } else {
+ return FAILURE;
+ }
+ }
+ /* data phars need only contain a single non-"." to be valid */
+ if (*(ext_str + 1) != '.' && *(ext_str + 1) != '/' && *(ext_str + 1) != '\0') {
+ return phar_analyze_path(fname, ext_str, ext_len, for_create TSRMLS_CC);
+ }
+ return FAILURE;
+}
+
+/*
+ * if executable is 1, only returns SUCCESS if the extension is one of the tar/zip .phar extensions
+ * if executable is 0, it returns SUCCESS only if the filename does *not* contain ".phar" anywhere, and treats
+ * the first extension as the filename extension
+ *
+ * if an extension is found, it sets ext_str to the location of the file extension in filename,
+ * and ext_len to the length of the extension.
+ * for urls like "phar://alias/oops" it instead sets ext_len to -1 and returns FAILURE, which tells
+ * the calling function to use "alias" as the phar alias
+ *
+ * the last parameter should be set to tell the thing to assume that filename is the full path, and only to check the
+ * extension rules, not to iterate.
+ */
+int phar_detect_phar_fname_ext(const char *filename, int check_length, const char **ext_str, int *ext_len, int executable, int for_create, int is_complete TSRMLS_DC) /* {{{ */
+{
+ const char *pos, *slash;
+ int filename_len = strlen(filename);
*ext_str = NULL;
- for (i = 0; i < sizeof(ext_info) / sizeof(ext_info[0]); ++i) {
- pos = strstr(filename, ext_info[i].ext);
- /* If pos is not NULL then we found the extension. But we have to check
- * to more things. First some extensions cannot be the end of the string
- * (e.g. .php). Second when we already found an extension at an earlier
- * position, we ignore the new one. In case we found one at the same
- * place, we probably found a longer one. As the list is ordered that
- * way we do not need to check for a greater length.
- */
- if (pos && (/*1*/ !ext_info[i].check || pos[ext_info[i].len] != '\0')
- && (/*2*/ !*ext_str || pos <= *ext_str)) {
- *ext_str = pos;
- *ext_len = ext_info[i].len;
+
+ if (!filename_len || filename_len == 1) {
+ return FAILURE;
+ }
+ phar_request_initialize(TSRMLS_C);
+ /* first check for extract_list */
+ if (zend_hash_num_elements(&(PHAR_GLOBALS->phar_plain_map))) {
+ for (zend_hash_internal_pointer_reset(&(PHAR_GLOBALS->phar_plain_map));
+ zend_hash_has_more_elements(&(PHAR_GLOBALS->phar_plain_map)) == SUCCESS;
+ zend_hash_move_forward(&(PHAR_GLOBALS->phar_plain_map))) {
+ char *key;
+ uint keylen;
+ ulong intkey;
+
+ if (HASH_KEY_IS_STRING != zend_hash_get_current_key_ex(&(PHAR_GLOBALS->phar_plain_map), &key, &keylen, &intkey, 0, NULL)) {
+ continue;
+ }
+
+ if (keylen <= filename_len && !memcmp(key, filename, keylen - 1)) {
+ /* found plain map, so we grab the extension, if any */
+ if (is_complete && keylen != filename_len + 1) {
+ continue;
+ }
+ if (for_create == 1) {
+ return FAILURE;
+ }
+ if (!executable == 1) {
+ return FAILURE;
+ }
+ pos = strrchr(key, '/');
+ if (pos) {
+ pos = filename + (pos - key);
+ slash = strchr(pos, '.');
+ if (slash) {
+ *ext_str = slash;
+ *ext_len = keylen - (slash - filename);
+ return SUCCESS;
+ }
+ *ext_str = pos;
+ *ext_len = -1;
+ return FAILURE;
+ }
+ *ext_str = filename + keylen - 1;
+ *ext_len = -1;
+ return FAILURE;
+ }
}
}
- if (!*ext_str) {
- /* We have an alias with no extension, so locate the first / and fail */
- *ext_str = strstr(filename, "/");
- if (*ext_str) {
+ /* next check for alias in first segment */
+ pos = strchr(filename, '/');
+ if (pos) {
+ if (zend_hash_exists(&(PHAR_GLOBALS->phar_alias_map), filename, pos - filename)) {
+ *ext_str = pos;
*ext_len = -1;
+ return FAILURE;
}
- return FAILURE;
}
- if (check_length && (*ext_str)[*ext_len] != '\0') {
+
+ pos = strchr(filename + 1, '.');
+next_extension:
+ if (!pos) {
return FAILURE;
}
- end = (*ext_str)[*ext_len];
- if (end != '\0' && end != '/' && end != '\\') {
- return FAILURE;
+
+ slash = strchr(pos, '/');
+ if (!slash) {
+ /* this is a url like "phar://blah.phar" with no directory */
+ *ext_str = pos;
+ *ext_len = strlen(pos);
+ /* file extension must contain "phar" */
+ switch (phar_check_str(filename, *ext_str, *ext_len, executable, for_create TSRMLS_CC)) {
+ case SUCCESS :
+ return SUCCESS;
+ case FAILURE :
+ /* we are at the end of the string, so we fail */
+ return FAILURE;
+ }
}
- return SUCCESS;
+ /* we've found an extension that ends at a directory separator */
+ *ext_str = pos;
+ *ext_len = slash - pos;
+ switch (phar_check_str(filename, *ext_str, *ext_len, executable, for_create TSRMLS_CC)) {
+ case SUCCESS :
+ return SUCCESS;
+ case FAILURE :
+ /* look for more extensions */
+ if (is_complete) {
+ return FAILURE;
+ }
+ pos = strchr(pos + 1, '.');
+ if (pos) {
+ *ext_str = NULL;
+ *ext_len = 0;
+ }
+ goto next_extension;
+ }
+ return FAILURE;
}
/* }}} */
*
* This is used by phar_open_url()
*/
-int phar_split_fname(char *filename, int filename_len, char **arch, int *arch_len, char **entry, int *entry_len TSRMLS_DC) /* {{{ */
+int phar_split_fname(char *filename, int filename_len, char **arch, int *arch_len, char **entry, int *entry_len, int executable, int for_create TSRMLS_DC) /* {{{ */
{
const char *ext_str;
int ext_len;
}
ext_len = 0;
- if (phar_detect_phar_fname_ext(filename, 0, &ext_str, &ext_len) == FAILURE) {
+ if (phar_detect_phar_fname_ext(filename, 0, &ext_str, &ext_len, executable, for_create, 0) == FAILURE) {
if (ext_len != -1) {
if (!ext_str) {
/* no / detected, restore arch for error message */
fname = zend_get_executed_filename(TSRMLS_C);
fname_len = strlen(fname);
if (fname_len > 7 && !strncasecmp(fname, "phar://", 7)) {
- if (SUCCESS == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len TSRMLS_CC)) {
+ if (SUCCESS == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len, 1, 0 TSRMLS_CC)) {
zend_hash_find(&(PHAR_GLOBALS->phar_fname_map), arch, arch_len, (void **) &pphar);
efree(arch);
efree(entry);
int phar_open_entry_file(phar_archive_data *phar, phar_entry_info *entry, char **error TSRMLS_DC);
int phar_open_filename(char *fname, int fname_len, char *alias, int alias_len, int options, phar_archive_data** pphar, char **error TSRMLS_DC);
-int phar_open_or_create_filename(char *fname, int fname_len, char *alias, int alias_len, char *objname, int options, phar_archive_data** pphar, char **error TSRMLS_DC);
+int phar_open_or_create_filename(char *fname, int fname_len, char *alias, int alias_len, int is_data, int options, phar_archive_data** pphar, char **error TSRMLS_DC);
int phar_create_or_parse_filename(char *fname, int fname_len, char *alias, int alias_len, int is_data, int options, phar_archive_data** pphar, char **error TSRMLS_DC);
int phar_open_compiled_file(char *alias, int alias_len, char **error TSRMLS_DC);
int phar_get_archive(phar_archive_data **archive, char *fname, int fname_len, char *alias, int alias_len, char **error TSRMLS_DC);
phar_entry_data *phar_get_or_create_entry_data(char *fname, int fname_len, char *path, int path_len, char *mode, char allow_dir, char **error TSRMLS_DC);
int phar_get_entry_data(phar_entry_data **ret, char *fname, int fname_len, char *path, int path_len, char *mode, char allow_dir, char **error TSRMLS_DC);
int phar_flush(phar_archive_data *archive, char *user_stub, long len, int convert, char **error TSRMLS_DC);
-int phar_detect_phar_fname_ext(const char *filename, int check_length, const char **ext_str, int *ext_len);
-int phar_split_fname(char *filename, int filename_len, char **arch, int *arch_len, char **entry, int *entry_len TSRMLS_DC);
+int phar_detect_phar_fname_ext(const char *filename, int check_length, const char **ext_str, int *ext_len, int executable, int for_create, int is_complete TSRMLS_DC);
+int phar_split_fname(char *filename, int filename_len, char **arch, int *arch_len, char **entry, int *entry_len, int executable, int for_create TSRMLS_DC);
typedef enum {
pcr_use_query,
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)) {
+ if (SUCCESS == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len, 2, 0 TSRMLS_CC)) {
efree(entry);
if (retphar) {
RETVAL_STRINGL(fname, arch_len + 7, 1);
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)) {
+ if (SUCCESS == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len, 2, 0 TSRMLS_CC)) {
efree(entry);
if (SUCCESS != zend_hash_find(&(PHAR_GLOBALS->phar_fname_map), arch, arch_len, (void **)&pphar)) {
zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "%s is not a phar archive, cannot mount", arch);
}
/* }}} */
-/* {{{ proto bool Phar::isValidPharFilename(string filename)
+/* {{{ proto bool Phar::isValidPharFilename(string filename[, bool executable = true])
* Returns whether the given filename is a valid phar filename */
PHP_METHOD(Phar, isValidPharFilename)
{
char *fname;
const char *ext_str;
int fname_len, ext_len;
+ zend_bool executable = 1;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &fname, &fname_len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &fname, &fname_len, &executable) == FAILURE) {
return;
}
- RETURN_BOOL(phar_detect_phar_fname_ext(fname, 1, &ext_str, &ext_len) == SUCCESS);
+ fname_len = executable;
+ RETURN_BOOL(phar_detect_phar_fname_ext(fname, 1, &ext_str, &ext_len, fname_len, 1, 1) == SUCCESS);
}
/* }}} */
return;
}
- if (SUCCESS == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len TSRMLS_CC)) {
+#if PHP_VERSION_ID >= 60000
+ objname = phar_obj->std.ce->name.s;
+#else
+ objname = phar_obj->std.ce->name;
+#endif
+ if (!strncmp(objname, "PharData", 8)) {
+ is_data = 1;
+ } else {
+ is_data = 0;
+ }
+
+ if (SUCCESS == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len, !is_data, 2 TSRMLS_CC)) {
/* use arch (the basename for the archive) for fname instead of fname */
/* this allows support for RecursiveDirectoryIterator of subdirectories */
save_fname = fname;
#endif
}
-#if PHP_VERSION_ID >= 60000
- objname = phar_obj->std.ce->name.s;
-#else
- objname = phar_obj->std.ce->name;
-#endif
-
- if (phar_open_or_create_filename(fname, fname_len, alias, alias_len, objname, REPORT_ERRORS, &phar_data, &error TSRMLS_CC) == FAILURE) {
+ if (phar_open_or_create_filename(fname, fname_len, alias, alias_len, is_data, REPORT_ERRORS, &phar_data, &error TSRMLS_CC) == FAILURE) {
if (fname == arch) {
efree(arch);
return;
}
- if (phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len TSRMLS_CC) == FAILURE) {
+ if (phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len, 2, 0 TSRMLS_CC) == FAILURE) {
efree(arch);
efree(entry);
zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC,
}
return NULL;
}
- if (phar_split_fname(filename, strlen(filename), &arch, &arch_len, &entry, &entry_len TSRMLS_CC) == FAILURE) {
+ if (phar_split_fname(filename, strlen(filename), &arch, &arch_len, &entry, &entry_len, 2, (mode[0] == 'w' ? 2 : 0) 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);
+ php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: invalid url or non-existent phar \"%s\"", filename);
}
}
return NULL;
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 (phar_open_or_create_filename(resource->host, arch_len, NULL, 0, 0, options, NULL, &error TSRMLS_CC) == FAILURE)
{
if (error) {
if (!(options & PHP_STREAM_URL_STAT_QUIET)) {
error = NULL;
- if ((resource_from = phar_open_url(wrapper, url_from, "rb", options|PHP_STREAM_URL_STAT_QUIET TSRMLS_CC)) == NULL) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "phar error: cannot rename \"%s\" to \"%s\": invalid url \"%s\"", url_from, url_to, url_from);
+ if ((resource_from = phar_open_url(wrapper, url_from, "wb", options|PHP_STREAM_URL_STAT_QUIET TSRMLS_CC)) == NULL) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "phar error: cannot rename \"%s\" to \"%s\": invalid or non-writable url \"%s\"", url_from, url_to, url_from);
return 0;
}
-
-
if (SUCCESS != phar_get_archive(&pfrom, resource_from->host, strlen(resource_from->host), NULL, 0, &error TSRMLS_CC)) {
pfrom = NULL;
if (error) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "phar error: write operations disabled by phar.readonly INI setting");
return 0;
}
+
if ((resource_to = phar_open_url(wrapper, url_to, "wb", options|PHP_STREAM_URL_STAT_QUIET TSRMLS_CC)) == NULL) {
php_url_free(resource_from);
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "phar error: cannot rename \"%s\" to \"%s\": invalid url \"%s\"", url_from, url_to, url_to);
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "phar error: cannot rename \"%s\" to \"%s\": invalid or non-writable url \"%s\"", url_from, url_to, url_to);
+ return 0;
+ }
+ if (SUCCESS != phar_get_archive(&pto, resource_to->host, strlen(resource_to->host), NULL, 0, &error TSRMLS_CC)) {
+ if (error) {
+ efree(error);
+ }
+ pto = NULL;
+ }
+ if (PHAR_G(readonly) && (!pto || !pto->is_data)) {
+ php_url_free(resource_from);
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "phar error: write operations disabled by phar.readonly INI setting");
return 0;
}
return 0;
}
- if (SUCCESS != phar_get_archive(&pto, resource_to->host, strlen(resource_to->host), NULL, 0, &error TSRMLS_CC)) {
- if (error) {
- efree(error);
- }
- pto = NULL;
- }
-
/* we must have at the very least phar://alias.phar/internalfile.php */
if (!resource_from->scheme || !resource_from->host || !resource_from->path) {
php_url_free(resource_from);
phar url "phar://" is unknown in %s027.php on line %d
bool(false)
-Warning: opendir(phar://foo.phar/hi): failed to open dir: phar url "phar://foo.phar/hi" is unknown in %s027.php on line %d
+Warning: opendir(phar://foo.phar/hi): failed to open dir: phar error: invalid url or non-existent phar "phar://foo.phar/hi"
+phar url "phar://foo.phar/hi" is unknown in %s027.php on line %d
bool(false)
extract_list test
.
Warning: mkdir(): phar error: cannot create directory "phar://", no phar archive specified in %sdir.php on line %d
-Warning: rmdir(): phar error: cannot remove directory "phar://", no phar archive specified in %sdir.php on line %d
+Warning: rmdir(): phar error: cannot remove directory "phar://", no phar archive specified, or phar archive does not exist in %sdir.php on line %d
Warning: rmdir(): phar error: cannot remove directory "hi" in phar "%sunknown.phar", directory does not exist in %sdir.php on line %d
--EXPECTF--
Warning: fopen() expects at least 2 parameters, 0 given in %sfopen.php on line %d
hihi
-Warning: fopen(phar://%sfopen.phar.php/notfound.txt): failed to open stream: phar error: "notfound.txt" is not a file in phar "%sfopen.phar.php" in phar://%sfopen.phar.php/index.php on line %d
+Warning: fopen(notfound.txt): failed to open stream: No such file or directory in phar://%sfopen.phar.php/index.php on line %d
===DONE===
\ No newline at end of file
$pname2 = 'phar://' . $fname2;
$pname3 = 'phar://' . $fname3;
+// create in cwd
+chdir(dirname(__FILE__));
+file_put_contents('phar://fopen_edgetest.phar/hi', 'hi');
// append
$a = fopen($pname . '/b/c.php', 'a');
// invalid pharname
--CLEAN--
<?php unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.phar.php'); ?>
<?php unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.2.phar.php'); ?>
+<?php unlink(dirname(__FILE__) . '/fopen_edgetest.phar');
--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
+Warning: fopen(phar://%sfopen_edgecases.phar.php.phar.gz): failed to open stream: phar error: invalid url or non-existent phar "phar://%sfopen_edgecases.phar.php.phar.gz" 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
Warning: unlink(): phar error: unlink failed in %sfopen_edgecases.php on line %d
-Warning: unlink(): unable to open phar for reading "foo.phar" in %sfopen_edgecases.php on line %d
+Warning: unlink(): phar error: invalid url or non-existent phar "phar://foo.phar" in %sfopen_edgecases.php on line %d
Warning: unlink(): phar error: unlink failed in %sfopen_edgecases.php on line %d
Warning: unlink(): unlink of "phar://%sfopen_edgecases.phar.php/oops" failed, file does not exist in %sfopen_edgecases.php on line %d
-Warning: rename(): phar error: cannot rename "phar://" to "phar://": invalid url "phar://" in %sfopen_edgecases.php on line %d
+Warning: rename(): phar error: cannot rename "phar://" to "phar://": invalid or non-writable url "phar://" in %sfopen_edgecases.php on line %d
-Warning: rename(): phar error: cannot rename "phar://%sfopen_edgecases.phar.php/hi" to "phar://": invalid url "phar://" in %sfopen_edgecases.php on line %d
+Warning: rename(): phar error: cannot rename "phar://%sfopen_edgecases.phar.php/hi" to "phar://": invalid or non-writable url "phar://" in %sfopen_edgecases.php on line %d
-Warning: rename(): phar error: cannot rename "phar://foo.phar/hi" to "phar://": invalid url "phar://foo.phar/hi" in %sfopen_edgecases.php on line %d
+Warning: rename(): phar error: cannot rename "phar://foo.phar/hi" to "phar://": invalid or non-writable url "phar://" in %sfopen_edgecases.php on line %d
Warning: rename(): phar error: cannot rename "phar://%sfopen_edgecases.phar.php/hi" to "phar://foo.phar/hi", not within the same phar archive in %sfopen_edgecases.php on line %d
-Warning: rename(): phar error: write operations disabled by phar.readonly INI setting in %sfopen_edgecases.php on line %d
+Warning: rename(): phar error: cannot rename "phar://%sfopen_edgecases.phar.php/hi" to "phar://%sfopen_edgecases.phar.php/there": invalid or non-writable url "phar://%sfopen_edgecases.phar.php/hi" in %sfopen_edgecases.php on line %d
Warning: rename(): phar error: cannot rename "phar://test.phar/fopen_edgecases.php" to "phar://test.phar/hi" from extracted phar archive in %sfopen_edgecases.php on line %d
Warning: mkdir(): phar error: cannot create directory "a" in phar "%smkdir.phar.php", phar error: path "a" exists and is a not a directory in %smkdir.php on line %d
-Warning: rmdir(): phar error: cannot remove directory "phar://", no phar archive specified in %smkdir.php on line %d
+Warning: rmdir(): phar error: cannot remove directory "phar://", no phar archive specified, or phar archive does not exist in %smkdir.php on line %d
Warning: rmdir(): phar error: cannot remove directory "" in phar "foo.phar", directory does not exist in %smkdir.php on line %d
Warning: opendir(phar://): failed to open dir: phar error: no directory in "phar://", must have at least phar:/// for root directory (always use full path to a new phar)
phar url "phar://" is unknown in %sopendir.php on line %d
-Warning: opendir(phar://hi.phar): failed to open dir: phar url "phar://hi.phar" is unknown in %sopendir.php on line %d
+Warning: opendir(phar://hi.phar): failed to open dir: phar error: invalid url or non-existent phar "phar://hi.phar"
+phar url "phar://hi.phar" is unknown in %sopendir.php on line %d
Warning: opendir(phar://hi.phar/oopsie/daisy/): failed to open dir: phar error: file "%soopsie/daisy" extracted from "hi.phar" could not be opened in %sopendir.php on line %d
===DONE===
\ No newline at end of file
return phar_save_resolve_path(filename, filename_len TSRMLS_CC);
}
fname = zend_get_executed_filename(TSRMLS_C);
- if (SUCCESS != phar_split_fname(fname, strlen(fname), &arch, &arch_len, &entry, &entry_len TSRMLS_CC)) {
+ if (SUCCESS != phar_split_fname(fname, strlen(fname), &arch, &arch_len, &entry, &entry_len, 0, 0 TSRMLS_CC)) {
return phar_save_resolve_path(filename, filename_len TSRMLS_CC);
}
if (*filename == '.') {
ret_len = strlen(ret);
/* found phar:// */
- if (SUCCESS != phar_split_fname(ret, ret_len, &arch, &arch_len, &entry, &entry_len TSRMLS_CC)) {
+ if (SUCCESS != phar_split_fname(ret, ret_len, &arch, &arch_len, &entry, &entry_len, 0, 0 TSRMLS_CC)) {
return ret;
}
zend_hash_find(&(PHAR_GLOBALS->phar_fname_map), arch, arch_len, (void **) &pphar);
goto doit;
}
fname = zend_get_executed_filename(TSRMLS_C);
- if (SUCCESS != phar_split_fname(fname, strlen(fname), &arch, &arch_len, &entry, &entry_len TSRMLS_CC)) {
+ if (SUCCESS != phar_split_fname(fname, strlen(fname), &arch, &arch_len, &entry, &entry_len, 0, 0 TSRMLS_CC)) {
goto doit;
}
ret_len = strlen(trypath);
/* found phar:// */
- if (SUCCESS != phar_split_fname(trypath, ret_len, &arch, &arch_len, &entry, &entry_len TSRMLS_CC)) {
+ if (SUCCESS != phar_split_fname(trypath, ret_len, &arch, &arch_len, &entry, &entry_len, 0, 0 TSRMLS_CC)) {
return estrndup(trypath, ret_len);
}
zend_hash_find(&(PHAR_GLOBALS->phar_fname_map), arch, arch_len, (void **) &pphar);