__HALT_COMPILER();function __HALT_COMPILER(){}$a=<<<PHARDATABEGIN\n
* ability to have Phar object return file class as offsetGet() result
* ability to store empty directories
- * [optional] Phar->rollback() to abort a write transaction
* implement PPG signing
* ability to match files containing a metadata key opendir('phar://a.phar/?mime-type=image/jpeg')
or foreach ($p->match('mime-type', 'image/jpeg') as $file)
X Phar::buildFromIterator(Iterator $it[, string $base_directory]) [Greg]
* Layout: Option to compress all content rather than single files.
That excludes stub and manifest haeder.
- * stream context option for cleaning crap paths like phar://blah.phar/file//to\\here.php
+ X clean crap paths like phar://blah.phar/file//../to\\here.php [Greg]
<?php
$notes = '
+Major feature functionality release
+ * include/getcwd/fopen with include_path all work unmodified within a phar
+ * paths with . and .. work (phar://blah.phar/a/../b.php => phar://blah.phar/b.php)
* implement Phar::copy(string $from, string $to) [Greg]
* implement Phar::buildFromIterator(Iterator $it[, string $base_directory]) [Greg]
* add mapping of include/require from within a phar to location within phar [Greg]
<?xml version="1.0" encoding="UTF-8"?>
-<package packagerversion="1.7.0RC1" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd">
+<package packagerversion="1.6.1" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd">
<name>phar</name>
<channel>pecl.php.net</channel>
<summary>allows running of complete applications out of .phar files (like Java .jar files)</summary>
<email>helly@php.net</email>
<active>yes</active>
</lead>
- <date>2007-12-12</date>
- <time>11:56:58</time>
+ <date>2007-12-20</date>
+ <time>17:12:06</time>
<version>
<release>1.3.0</release>
<api>1.1.0</api>
<license uri="http://www.php.net/license">PHP License</license>
<notes>
+Major feature functionality release
+ * include/getcwd/fopen with include_path all work unmodified within a phar
+ * paths with . and .. work (phar://blah.phar/a/../b.php => phar://blah.phar/b.php)
+ * implement Phar::copy(string $from, string $to) [Greg]
* implement Phar::buildFromIterator(Iterator $it[, string $base_directory]) [Greg]
* add mapping of include/require from within a phar to location within phar [Greg]
solves the include_path issue without code munging
<file name="open_for_write_newfile_b.phpt" role="test" />
<file name="open_for_write_newfile_c.phpt" role="test" />
<file name="phar_begin_setstub_commit.phpt" role="test" />
+ <file name="phar_buildfromiterator1.phpt" role="test" />
+ <file name="phar_buildfromiterator2.phpt" role="test" />
+ <file name="phar_buildfromiterator3.phpt" role="test" />
+ <file name="phar_buildfromiterator4.phpt" role="test" />
+ <file name="phar_buildfromiterator5.phpt" role="test" />
+ <file name="phar_buildfromiterator6.phpt" role="test" />
+ <file name="phar_buildfromiterator7.phpt" role="test" />
+ <file name="phar_buildfromiterator8.phpt" role="test" />
+ <file name="phar_buildfromiterator9.phpt" role="test" />
<file name="phar_commitwrite.phpt" role="test" />
+ <file name="phar_copy.phpt" role="test" />
<file name="phar_create_in_cwd.phpt" role="test" />
<file name="phar_ctx_001.phpt" role="test" />
<file name="phar_dir_iterate.phpt" role="test" />
<file name="phar_get_supportedcomp4.phpt" role="test" />
<file name="phar_get_suppoted_signatures_001.phpt" role="test" />
<file name="phar_get_suppoted_signatures_002.phpt" role="test" />
+ <file name="phar_magic.phpt" role="test" />
<file name="phar_metadata_read.phpt" role="test" />
<file name="phar_metadata_write.phpt" role="test" />
<file name="phar_offset_get_error.phpt" role="test" />
<release>stable</release>
<api>stable</api>
</stability>
- <date>2007-12-12</date>
+ <date>2007-12-20</date>
<license uri="http://www.php.net/license">PHP License</license>
<notes>
+Major feature functionality release
+ * include/getcwd/fopen with include_path all work unmodified within a phar
+ * paths with . and .. work (phar://blah.phar/a/../b.php => phar://blah.phar/b.php)
+ * implement Phar::copy(string $from, string $to) [Greg]
* implement Phar::buildFromIterator(Iterator $it[, string $base_directory]) [Greg]
* add mapping of include/require from within a phar to location within phar [Greg]
solves the include_path issue without code munging
}
/* }}} */
+static int php_check_dots(const char *element, int n)
+{
+ while (n-- > 0) if (element[n] != '.') break;
+
+ return (n != -1);
+}
+
+#define IS_DIRECTORY_UP(element, len) \
+ (len >= 2 && !php_check_dots(element, len))
+
+#define IS_DIRECTORY_CURRENT(element, len) \
+ (len == 1 && element[0] == '.')
+
+#define IS_BACKSLASH(c) ((c) == '/')
+
+/**
+ * Remove .. and . references within a phar filename
+ */
+static char *phar_fix_filepath(char *path, int *new_len) /* {{{ */
+{
+ char *ptr, *free_path, *new_phar;
+ char *tok;
+ int ptr_length, new_phar_len = 1, path_length = *new_len;
+
+ free_path = path;
+ new_phar = estrndup("/\0", 2);
+ tok = NULL;
+ ptr = tsrm_strtok_r(path, "/", &tok);
+ while (ptr) {
+ ptr_length = strlen(ptr);
+
+ if (IS_DIRECTORY_UP(ptr, ptr_length)) {
+ char save;
+
+ save = '/';
+
+#define PREVIOUS new_phar[new_phar_len - 1]
+
+ while (new_phar_len > 1 &&
+ !IS_BACKSLASH(PREVIOUS)) {
+ save = PREVIOUS;
+ PREVIOUS = '\0';
+ new_phar_len--;
+ }
+
+ if (new_phar[0] != '/') {
+ new_phar[new_phar_len++] = save;
+ new_phar[new_phar_len] = '\0';
+ } else if (new_phar_len > 1) {
+ PREVIOUS = '\0';
+ new_phar_len--;
+ }
+ } else if (!IS_DIRECTORY_CURRENT(ptr, ptr_length)) {
+ if (new_phar_len > 1) {
+ new_phar = (char *) erealloc(new_phar, new_phar_len+ptr_length+1+1);
+ new_phar[new_phar_len++] = '/';
+ memcpy(&new_phar[new_phar_len], ptr, ptr_length+1);
+ } else {
+ new_phar = (char *) erealloc(new_phar, new_phar_len+ptr_length+1);
+ memcpy(&new_phar[new_phar_len], ptr, ptr_length+1);
+ }
+
+ new_phar_len += ptr_length;
+ }
+ ptr = tsrm_strtok_r(NULL, "/", &tok);
+ }
+
+ efree(free_path);
+
+ if (path[path_length-1] == '/') {
+ new_phar = (char*)erealloc(new_phar, new_phar_len + 2);
+ new_phar[new_phar_len++] = '/';
+ new_phar[new_phar_len] = 0;
+ }
+
+ if (new_phar_len == 0) {
+ new_phar = (char *) erealloc(new_phar, new_phar_len+1+1);
+ new_phar[new_phar_len] = '/';
+ new_phar[new_phar_len+1] = '\0';
+ new_phar_len++;
+ }
+ *new_len = new_phar_len;
+ return new_phar;
+}
+/* }}} */
+
/**
* Process a phar stream name, ensuring we can handle any of:
*
#ifdef PHP_WIN32
phar_unixify_path_separators(*entry, *entry_len);
#endif
+ *entry = phar_fix_filepath(*entry, entry_len);
} else {
*entry_len = 1;
*entry = estrndup("/", 1);
phar_globals->readonly = 1;
}
/* }}} */
-
static zend_op_array *phar_compile_file(zend_file_handle *file_handle, int type TSRMLS_DC) /* {{{ */
{
zend_op_array *res;
#include "ext/standard/sha1.h"
#include "ext/standard/php_var.h"
#include "ext/standard/php_smart_str.h"
+#include "TSRM/tsrm_strtok_r.h"
#if HAVE_SPL
#include "ext/spl/spl_array.h"
#include "ext/spl/spl_directory.h"
int phar_open_compiled_file(char *alias, int alias_len, char **error TSRMLS_DC);
static void phar_fopen(INTERNAL_FUNCTION_PARAMETERS);
-static void phar_cwd(INTERNAL_FUNCTION_PARAMETERS);
+static void phar_getcwd(INTERNAL_FUNCTION_PARAMETERS);
#ifdef PHAR_MAIN
static void phar_fopen(INTERNAL_FUNCTION_PARAMETERS);
$fname = dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.phar.php';
$p = new Phar($fname);
$p['a'] = '<?php include "b/c.php";' . "\n";
-$p['b/c.php'] = '<?php echo "in b\n";$a = fopen("a", "r", true);echo stream_get_contents($a);fclose($a);echo getcwd() . "\n";';
+$p['b/c.php'] = '<?php echo "in b\n";$a = fopen("a", "r", true);echo stream_get_contents($a);fclose($a);echo getcwd() . "\n";include dirname(__FILE__) . "/../d";';
+$p['d'] = "in d\n";
$p->setStub('<?php
include "phar://" . __FILE__ . "/a";
__HALT_COMPILER();');
in b
<?php include "b/c.php";
phar://%s/b
+in d
===DONE===