/**
* retrieve information on a file contained within a phar, or null if it ain't there
*/
-phar_entry_info *phar_get_entry_info(phar_archive_data *phar, char *path, int path_len TSRMLS_DC) /* {{{ */
+phar_entry_info *phar_get_entry_info(phar_archive_data *phar, char *path, int path_len, char **error TSRMLS_DC) /* {{{ */
{
+ const char *pcr_error;
phar_entry_info *entry;
- if (path && *path == '/') {
- path++;
- path_len--;
+ if (error) {
+ *error = NULL;
+ }
+
+ if (phar_path_check(&path, &path_len, &pcr_error) > pcr_is_ok) {
+ if (error) {
+ spprintf(error, 0, "phar error: invalid path \"%s\" contains %s", path, pcr_error);
+ }
+ return NULL;
}
+
if (!&phar->manifest.arBuckets) {
return NULL;
}
}
/* }}} */
-#if PHP_VERSION_ID < 50202
+#if defined(PHP_VERSION_ID) && PHP_VERSION_ID < 50202
typedef struct {
char *data;
size_t fpos;
if (FAILURE == phar_get_archive(&phar, fname, fname_len, NULL, 0, error TSRMLS_CC)) {
return FAILURE;
}
- if ((entry = phar_get_entry_info(phar, path, path_len TSRMLS_CC)) == NULL) {
+ if ((entry = phar_get_entry_info(phar, path, path_len, for_create && !PHAR_G(readonly) ? NULL : error TSRMLS_CC)) == NULL) {
if (for_create && !PHAR_G(readonly)) {
return SUCCESS;
}
if (entry->fp) {
/* make a copy */
if (for_trunc) {
-#if PHP_VERSION_ID < 50202
+#if PHP_VERSION_ID >= 50202
+ php_stream_truncate_set_size(entry->fp, 0);
+#else
if (php_stream_is(entry->fp, PHP_STREAM_IS_TEMP)) {
if (php_stream_is(*(php_stream**)entry->fp->abstract, PHP_STREAM_IS_MEMORY)) {
php_stream *inner = *(php_stream**)entry->fp->abstract;
}
return FAILURE;
}
-#else
- php_stream_truncate_set_size(entry->fp, 0);
#endif
entry->is_modified = 1;
phar->is_modified = 1;
phar_archive_data *phar;
phar_entry_info *entry, etemp;
phar_entry_data *ret;
- phar_path_check_result res;
const char *pcr_error;
- if ((res = phar_path_check(path, &path_len, &pcr_error)) > pcr_is_ok) {
- if (error) {
- spprintf(error, 0, "phar error: invalid path \"%s\" contains %s", path, pcr_error);
- }
- return NULL;
- }
-
if (FAILURE == phar_get_archive(&phar, fname, fname_len, NULL, 0, error TSRMLS_CC)) {
return NULL;
}
return ret;
}
+ if (phar_path_check(&path, &path_len, &pcr_error) > pcr_is_ok) {
+ if (error) {
+ spprintf(error, 0, "phar error: invalid path \"%s\" contains %s", path, pcr_error);
+ }
+ return NULL;
+ }
+
/* create a new phar data holder */
ret = (phar_entry_data *) emalloc(sizeof(phar_entry_data));
etemp.phar = phar;
zend_hash_add(&phar->manifest, etemp.filename, path_len, (void*)&etemp, sizeof(phar_entry_info), NULL);
/* retrieve the phar manifest copy */
- entry = phar_get_entry_info(phar, path, path_len TSRMLS_CC);
+ entry = phar_get_entry_info(phar, path, path_len, error TSRMLS_CC);
+
+ if (!entry) {
+ //return NULL;
+ }
phar->refcount++;
ret->phar = phar;
int phar_archive_delref(phar_archive_data *phar TSRMLS_DC);
int phar_entry_delref(phar_entry_data *idata TSRMLS_DC);
-phar_entry_info *phar_get_entry_info(phar_archive_data *phar, char *path, int path_len TSRMLS_DC);
+phar_entry_info *phar_get_entry_info(phar_archive_data *phar, char *path, int path_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 **error TSRMLS_DC);
int phar_flush(phar_archive_data *archive, char *user_stub, long len, char **error TSRMLS_DC);
int phar_split_fname(char *filename, int filename_len, char **arch, int *arch_len, char **entry, int *entry_len TSRMLS_DC);
pcr_err_empty_entry
} phar_path_check_result;
-phar_path_check_result phar_path_check(const char *p, int *len, const char **error);
+phar_path_check_result phar_path_check(char **p, int *len, const char **error);
END_EXTERN_C()
*/
PHP_METHOD(Phar, offsetGet)
{
- char *fname;
+ char *fname, *error;
int fname_len;
zval *zfname;
PHAR_ARCHIVE_OBJECT();
return;
}
- if (!phar_get_entry_info(phar_obj->arc.archive, fname, fname_len TSRMLS_CC)) {
- zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Entry %s does not exist", fname);
+ if (!phar_get_entry_info(phar_obj->arc.archive, fname, fname_len, &error TSRMLS_CC)) {
+ zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Entry %s does not exist%s%s", fname, error?", ":"", error?error:"");
} else {
fname_len = spprintf(&fname, 0, "phar://%s/%s", phar_obj->arc.archive->fname, fname);
MAKE_STD_ZVAL(zfname);
return;
}
- if ((entry_info = phar_get_entry_info(phar_data, entry, entry_len TSRMLS_CC)) == NULL) {
+ if ((entry_info = phar_get_entry_info(phar_data, entry, entry_len, &error TSRMLS_CC)) == NULL) {
efree(arch);
zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC,
- "Cannot access phar file entry '%s' in archive '%s'", entry, arch);
+ "Cannot access phar file entry '%s' in archive '%s'%s%s", entry, arch, error?", ":"", error?error:"");
efree(entry);
return;
}
-/* Generated by re2c 0.11.0 on Sun Feb 4 11:21:09 2007 */
+/* Generated by re2c 0.11.0 on Sun Feb 4 14:40:54 2007 */
#line 1 "ext/phar/phar_path_check.re"
/*
+----------------------------------------------------------------------+
#include "phar_internal.h"
-phar_path_check_result phar_path_check(const char *s, int *len, const char **error)
+phar_path_check_result phar_path_check(char **s, int *len, const char **error)
{
- const unsigned char *p = (const unsigned char*)s;
+ const unsigned char *p = (const unsigned char*)*s;
const unsigned char *m;
#define YYCTYPE unsigned char
#define YYCURSOR p
if(yych <= '.') goto yy16;
if(yych <= '/') goto yy17;
yy4:
-#line 77 "ext/phar/phar_path_check.re"
+#line 78 "ext/phar/phar_path_check.re"
{
goto loop;
}
++YYCURSOR;
#line 62 "ext/phar/phar_path_check.re"
{
- if (*s == '/') {
- s++;
+ if (**s == '/') {
+ (*s)++;
}
- *len = (p - (const unsigned char*)s) -1;
+ *len = (p - (const unsigned char*)*s) -1;
*error = NULL;
return pcr_use_query;
}
++YYCURSOR;
#line 70 "ext/phar/phar_path_check.re"
{
- if (*s == '/') {
- s++;
+ if (**s == '/') {
+ (*s)++;
+ (*len)--;
}
*error = NULL;
return pcr_is_ok;
}
-#line 116 "ext/phar/phar_path_check.c"
+#line 117 "ext/phar/phar_path_check.c"
yy13:
yych = *++YYCURSOR;
goto yy4;
*error = "empty entry";
return pcr_err_empty_entry;
}
-#line 127 "ext/phar/phar_path_check.c"
+#line 128 "ext/phar/phar_path_check.c"
yy16:
yych = *++YYCURSOR;
if(yych <= 0x00) goto yy20;
*error = "double slash";
return pcr_err_double_slash;
}
-#line 142 "ext/phar/phar_path_check.c"
+#line 143 "ext/phar/phar_path_check.c"
yy19:
yych = *++YYCURSOR;
if(yych <= 0x00) goto yy22;
*error = "current directory reference";
return pcr_err_curr_dir;
}
-#line 155 "ext/phar/phar_path_check.c"
+#line 156 "ext/phar/phar_path_check.c"
yy22:
++YYCURSOR;
#line 42 "ext/phar/phar_path_check.re"
*error = "upper directory reference";
return pcr_err_up_dir;
}
-#line 163 "ext/phar/phar_path_check.c"
+#line 164 "ext/phar/phar_path_check.c"
}
}
-#line 80 "ext/phar/phar_path_check.re"
+#line 81 "ext/phar/phar_path_check.re"
}
#include "phar_internal.h"
-phar_path_check_result phar_path_check(const char *s, int *len, const char **error)
+phar_path_check_result phar_path_check(char **s, int *len, const char **error)
{
- const unsigned char *p = (const unsigned char*)s;
+ const unsigned char *p = (const unsigned char*)*s;
const unsigned char *m;
#define YYCTYPE unsigned char
#define YYCURSOR p
return pcr_err_star;
}
"?" {
- if (*s == '/') {
- s++;
+ if (**s == '/') {
+ (*s)++;
}
- *len = (p - (const unsigned char*)s) -1;
+ *len = (p - (const unsigned char*)*s) -1;
*error = NULL;
return pcr_use_query;
}
END {
- if (*s == '/') {
- s++;
+ if (**s == '/') {
+ (*s)++;
+ (*len)--;
}
*error = NULL;
return pcr_is_ok;
--- /dev/null
+--TEST--
+Phar: ignore filenames starting with / on offsetSet
+--SKIPIF--
+<?php if (!extension_loaded("phar")) print "skip"; ?>
+<?php if (!extension_loaded("spl")) print "skip SPL not available"; ?>
+--INI--
+phar.readonly=0
+phar.require_hash=1
+--FILE--
+<?php
+
+$fname = dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.phar.php';
+$pname = 'phar://'.$fname;
+$iname = '/file.txt';
+$ename = '/error/';
+
+$p = new Phar($fname);
+$p[$iname] = "foobar\n";
+
+try
+{
+ $p[$ename] = "foobar\n";
+}
+catch(Exception $e)
+{
+ echo $e->getMessage() . "\n";
+}
+
+include($pname . $iname);
+?>
+===DONE===
+--CLEAN--
+<?php unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.phar.php'); ?>
+--EXPECT--
+Entry /error/ does not exist and cannot be created: phar error: invalid path "/error/" contains empty entry
+foobar
+===DONE===