static int phar_wrapper_stat(php_stream_wrapper *wrapper, char *url, int flags, php_stream_statbuf *ssb, php_stream_context *context TSRMLS_DC) /* {{{ */ { php_url *resource = NULL; char *internal_file, *key, *error, *plain_map; uint keylen; ulong unused; phar_archive_data *phar; phar_entry_info *entry; uint host_len; int retval, internal_file_len; if ((resource = phar_open_url(wrapper, url, "r", flags TSRMLS_CC)) == NULL) { return FAILURE; } /* 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, flags TSRMLS_CC, "phar error: invalid url \"%s\"", url); return FAILURE; } if (strcasecmp("phar", resource->scheme)) { php_url_free(resource); php_stream_wrapper_log_error(wrapper, flags TSRMLS_CC, "phar error: not a phar url \"%s\"", url); return FAILURE; } host_len = strlen(resource->host); phar_request_initialize(TSRMLS_C); if (zend_hash_find(&(PHAR_GLOBALS->phar_plain_map), resource->host, host_len+1, (void **)&plain_map) == SUCCESS) { spprintf(&internal_file, 0, "%s%s", plain_map, resource->path); retval = php_stream_stat_path_ex(internal_file, flags, ssb, context); if (retval == -1) { php_stream_wrapper_log_error(wrapper, 0/* TODO:options */ TSRMLS_CC, "phar error: file \"%s\" extracted from \"%s\" could not be stated", internal_file, resource->host); } php_url_free(resource); efree(internal_file); return retval; } internal_file = resource->path + 1; /* strip leading "/" */ /* find the phar in our trusty global hash indexed by alias (host of phar://blah.phar/file.whatever) */ if (FAILURE == phar_get_archive(&phar, resource->host, strlen(resource->host), NULL, 0, &error TSRMLS_CC)) { php_url_free(resource); if (error) { php_stream_wrapper_log_error(wrapper, flags TSRMLS_CC, error); efree(error); } return SUCCESS; } if (error) { efree(error); } if (*internal_file == '\0') { /* root directory requested */ phar_dostat(phar, NULL, ssb, 1, phar->alias, phar->alias_len TSRMLS_CC); php_url_free(resource); return SUCCESS; } if (!phar->manifest.arBuckets) { php_url_free(resource); return SUCCESS; } internal_file_len = strlen(internal_file); /* search through the manifest of files, and if we have an exact match, it's a file */ if (SUCCESS == zend_hash_find(&phar->manifest, internal_file, internal_file_len, (void**)&entry)) { phar_dostat(phar, entry, ssb, 0, phar->alias, phar->alias_len TSRMLS_CC); php_url_free(resource); return SUCCESS; } else { /* search for directory (partial match of a file) */ zend_hash_internal_pointer_reset(&phar->manifest); while (FAILURE != zend_hash_has_more_elements(&phar->manifest)) { if (HASH_KEY_NON_EXISTANT != zend_hash_get_current_key_ex( &phar->manifest, &key, &keylen, &unused, 0, NULL)) { if (0 == memcmp(internal_file, key, internal_file_len)) {