cellog Wed Dec 12 18:01:39 2007 UTC
Modified files: /pecl/phar TODO package.php package.xml phar.phar phar_object.c Log: implement Phar::buildFromIterator() first argument is an iterator that returns as values paths to files to add to the phar archive the key should be the path that the file should be saved as within the phar archive if the optional second parameter is passed, then the key is ignored and substr(value, strlen(base_directory)) is used as the save path within the phar archive [DOC]
http://cvs.php.net/viewvc.cgi/pecl/phar/TODO?r1=1.44&r2=1.45&diff_format=u Index: pecl/phar/TODO diff -u pecl/phar/TODO:1.44 pecl/phar/TODO:1.45 --- pecl/phar/TODO:1.44 Sat Aug 25 01:32:34 2007 +++ pecl/phar/TODO Wed Dec 12 18:01:39 2007 @@ -70,8 +70,7 @@ or foreach ($p->match('mime-type', 'image/jpeg') as $file) * Phar::copy($from, $to); X Phar::delete($what) [Greg] - * Phar::buildFromIterator($filename, Iterator $it, array $addinfo = null); - $addinfo = array('alias','flags','metadata','stub'...) + 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 http://cvs.php.net/viewvc.cgi/pecl/phar/package.php?r1=1.23&r2=1.24&diff_format=u Index: pecl/phar/package.php diff -u pecl/phar/package.php:1.23 pecl/phar/package.php:1.24 --- pecl/phar/package.php:1.23 Tue Dec 11 03:12:41 2007 +++ pecl/phar/package.php Wed Dec 12 18:01:39 2007 @@ -1,6 +1,7 @@ <?php $notes = ' + * 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 * add Phar::delete() [Greg] http://cvs.php.net/viewvc.cgi/pecl/phar/package.xml?r1=1.39&r2=1.40&diff_format=u Index: pecl/phar/package.xml diff -u pecl/phar/package.xml:1.39 pecl/phar/package.xml:1.40 --- pecl/phar/package.xml:1.39 Tue Nov 20 15:55:36 2007 +++ pecl/phar/package.xml Wed Dec 12 18:01:39 2007 @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> -<package packagerversion="1.6.2" 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.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"> <name>phar</name> <channel>pecl.php.net</channel> <summary>allows running of complete applications out of .phar files (like Java .jar files)</summary> @@ -29,10 +29,10 @@ <email>[EMAIL PROTECTED]</email> <active>yes</active> </lead> - <date>2007-08-24</date> - <time>20:06:43</time> + <date>2007-12-12</date> + <time>11:56:58</time> <version> - <release>1.2.1</release> + <release>1.3.0</release> <api>1.1.0</api> </version> <stability> @@ -42,18 +42,10 @@ <license uri="http://www.php.net/license">PHP License</license> <notes> - * add Phar::setAlias() [Greg] - * fix too many open file handles issue [Greg] - * fix rename [Greg] - * add Phar::getAlias() [Marcus] - * Made -a optional in pack subcommand of phar.phar [Marcus] - * Fix issue with apache module and extracted archives [Marcus] - * Send all error messages to stderr in phar.phar [Marcus] - * Added new subcommands add and delete to phar.phar [Marcus] - * Made Phar::loadPhar() and Phar::mapPhar() ignore extracted archives [Marcus] - * Fix issue with compressed entries and uncompressing entries [Marcus] - * Verify stubs before writing [Marcus] - * Always use longest stub end to avoid issues with length field [Marcus] + * 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 + * add Phar::delete() [Greg] </notes> <contents> @@ -66,7 +58,6 @@ <file name="phar.inc" role="src" /> <file name="phar.php" role="src" /> <file name="pharcommand.inc" role="src" /> - <file name="phar.phar" role="php" /> </dir> <!-- /phar --> <dir name="tests"> <file name="001.phpt" role="test" /> @@ -113,6 +104,7 @@ <file name="create_new_phar_b.phpt" role="test" /> <file name="create_new_phar_c.phpt" role="test" /> <file name="create_path_error.phpt" role="test" /> + <file name="delete.phpt" role="test" /> <file name="delete_in_phar.phpt" role="test" /> <file name="delete_in_phar_b.phpt" role="test" /> <file name="delete_in_phar_confirm.phpt" role="test" /> @@ -120,6 +112,7 @@ <file name="extracted_001.phpt" role="test" /> <file name="ini_set.phpt" role="test" /> <file name="ini_set_off.phpt" role="test" /> + <file name="md5.phar" role="test" /> <file name="metadata_read.phpt" role="test" /> <file name="metadata_write.phpt" role="test" /> <file name="metadata_write_commit.phpt" role="test" /> @@ -133,6 +126,11 @@ <file name="phar_commitwrite.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_supportedcomp1.phpt" role="test" /> + <file name="phar_get_supportedcomp2.phpt" role="test" /> + <file name="phar_get_supportedcomp3.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_metadata_read.phpt" role="test" /> @@ -159,6 +157,8 @@ <file name="phar_oo_compressed_001b.phpt" role="test" /> <file name="phar_oo_compressed_002.phpt" role="test" /> <file name="phar_oo_compressed_002b.phpt" role="test" /> + <file name="phar_oo_getmodified.phpt" role="test" /> + <file name="phar_oo_nosig.phpt" role="test" /> <file name="phar_oo_test.inc" role="test" /> <file name="phar_oo_uncompressall.phpt" role="test" /> <file name="phar_setalias.phpt" role="test" /> @@ -171,7 +171,12 @@ <file name="phar_stub_write_file.phpt" role="test" /> <file name="phar_test.inc" role="test" /> <file name="refcount1.phpt" role="test" /> + <file name="refcount1_5_2.phpt" role="test" /> <file name="rename.phpt" role="test" /> + <file name="sha1.phar" role="test" /> + <file name="sha256.phar" role="test" /> + <file name="sha512.phar" role="test" /> + <file name="test_signaturealgos.phpt" role="test" /> </dir> <!-- /tests --> <file name="build_precommand.php" role="php" /> <file name="config.m4" role="src" /> @@ -181,7 +186,7 @@ <file name="LICENSE" role="doc" /> <file name="Makefile.frag" role="src" /> <file name="phar.c" role="src" /> - <file name="phar.phar" role="data" /> + <file name="phar.phar" role="script" /> <file name="phar_internal.h" role="src" /> <file name="phar_object.c" role="src" /> <file name="phar_path_check.c" role="src" /> @@ -223,34 +228,50 @@ <changelog> <release> <version> - <release>1.2.1</release> + <release>1.3.0</release> <api>1.1.0</api> </version> <stability> <release>stable</release> <api>stable</api> </stability> - <date>2007-08-24</date> + <date>2007-12-12</date> <license uri="http://www.php.net/license">PHP License</license> <notes> - * add Phar::setAlias() [Greg] - * fix too many open file handles issue [Greg] - * fix rename [Greg] - * add Phar::getAlias() [Marcus] - * Made -a optional in pack subcommand of phar.phar [Marcus] - * Fix issue with apache module and extracted archives [Marcus] - * Send all error messages to stderr in phar.phar [Marcus] - * Added new subcommands add and delete to phar.phar [Marcus] - * Made Phar::loadPhar() and Phar::mapPhar() ignore extracted archives [Marcus] - * Fix issue with compressed entries and uncompressing entries [Marcus] - * Verify stubs before writing [Marcus] - * Always use longest stub end to avoid issues with length field [Marcus] + * 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 + * add Phar::delete() [Greg] </notes> </release> <release> <version> + <release>1.2.1</release> + <api>1.1.0</api> + </version> + <stability> + <release>stable</release> + <api>stable</api> + </stability> + <date>2007-08-24</date> + <license uri="http://www.php.net/license">PHP License</license> + <notes>* add Phar::setAlias() [Greg] +* fix too many open file handles issue [Greg] +* fix rename [Greg] +* add Phar::getAlias() [Marcus] +* Made -a optional in pack subcommand of phar.phar [Marcus] +* Fix issue with apache module and extracted archives [Marcus] +* Send all error messages to stderr in phar.phar [Marcus] +* Added new subcommands add and delete to phar.phar [Marcus] +* Made Phar::loadPhar() and Phar::mapPhar() ignore extracted archives [Marcus] +* Fix issue with compressed entries and uncompressing entries [Marcus] +* Verify stubs before writing [Marcus] +* Always use longest stub end to avoid issues with length field [Marcus]</notes> + </release> + <release> + <version> <release>1.2.0</release> <api>1.1.0</api> </version> http://cvs.php.net/viewvc.cgi/pecl/phar/phar.phar?r1=1.4&r2=1.5&diff_format=u Index: pecl/phar/phar.phar http://cvs.php.net/viewvc.cgi/pecl/phar/phar_object.c?r1=1.69&r2=1.70&diff_format=u Index: pecl/phar/phar_object.c diff -u pecl/phar/phar_object.c:1.69 pecl/phar/phar_object.c:1.70 --- pecl/phar/phar_object.c:1.69 Sun Nov 25 05:04:39 2007 +++ pecl/phar/phar_object.c Wed Dec 12 18:01:39 2007 @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: phar_object.c,v 1.69 2007/11/25 05:04:39 cellog Exp $ */ +/* $Id: phar_object.c,v 1.70 2007/12/12 18:01:39 cellog Exp $ */ #include "phar_internal.h" @@ -306,6 +306,156 @@ return; \ } +/* {{{ proto Phar::buildFromIterator(Iterator iter[, string base_directory]) + * Construct a phar archive from an iterator. The iterator must return a series of strings + * that are full paths to files that should be added to the phar. The iterator key should + * be the path that the file will have within the phar archive. + * + * If base directory is specified, then the key will be ignored, and instead the portion of + * the current value minus the base directory will be used + */ +PHP_METHOD(Phar, buildFromIterator) +{ + zend_object_iterator *iter = NULL; + zval *obj, **value; + char *str_key, *base, *error; + uint str_key_len, base_len = 0; + zend_uchar key_type; + ulong int_key; + zend_class_entry *ce; + PHAR_ARCHIVE_OBJECT(); + + + if (PHAR_G(readonly)) { + zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, + "Cannot write out phar archive, phar is read-only"); + return; + } + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|s", &obj, zend_ce_traversable, &base, &base_len) == FAILURE) { + RETURN_FALSE; + } + + ce = Z_OBJCE_P(obj); + + iter = ce->get_iterator(ce, obj, 0 TSRMLS_CC); + if (iter && !EG(exception)) { + obj = zend_iterator_wrap(iter TSRMLS_CC); + } else { + if (!EG(exception)) { + zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Object of type %s did not create an Iterator", ce->name); + } + return; + } + + if (iter) { + iter->index = 0; + if (iter->funcs->rewind) { + iter->funcs->rewind(iter TSRMLS_CC); + } + if (FAILURE == iter->funcs->valid(iter TSRMLS_CC)) { + zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Iterator %s returned no values", ce->name); + return; + } + do { + phar_entry_data *data; + php_stream *fp; + long contents_len; + char *fname; + iter->funcs->get_current_data(iter, &value TSRMLS_CC); + if (EG(exception)) { + break; + } + if (!value) { + /* failure in get_current_data */ + zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Iterator %s returned no value", ce->name); + } + if (Z_TYPE_PP(value) != IS_STRING) { + zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Iterator %s returned an invalid value (must return a string)", ce->name); + break; + } + if (!base_len && iter->funcs->get_current_key) { + key_type = iter->funcs->get_current_key(iter, &str_key, &str_key_len, &int_key TSRMLS_CC); + if (EG(exception)) { + break; + } + if (key_type == HASH_KEY_IS_LONG) { + zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Iterator %s returned an invalid key (must return a string)", ce->name); + break; + } + if (str_key[str_key_len - 1] == '\0') str_key_len--; + } else { + zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Iterator %s returned an invalid key (must return a string)", ce->name); + break; + } + + fname = Z_STRVAL_PP(value); + if (base_len) { + if (strstr(fname, base)) { + str_key_len = Z_STRLEN_PP(value) - base_len; + if (str_key_len <= 0) { + continue; + } + str_key = fname + base_len; + } else { + zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Iterator %s returned a path \"%s\" that is not in the base directory \"%s\"", ce->name, fname, base); + break; + } + } +#if PHP_MAJOR_VERSION < 6 + if (PG(safe_mode) && (!php_checkuid(fname, NULL, CHECKUID_ALLOW_ONLY_FILE))) { + zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Iterator %s returned a path \"%s\" that safe mode prevents opening", ce->name, fname); + break; + } +#endif + + if (php_check_open_basedir(fname TSRMLS_CC)) { + zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Iterator %s returned a path \"%s\" that open_basedir prevents opening", ce->name, fname); + break; + } + + /* try to open source file, then create internal phar file and copy contents */ + fp = php_stream_open_wrapper(fname, "rb", STREAM_MUST_SEEK|0, NULL); + if (!fp) { + zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Iterator %s returned a file that could not be opened \"%s\"", ce->name, fname); + break; + } + + if (!(data = phar_get_or_create_entry_data(phar_obj->arc.archive->fname, phar_obj->arc.archive->fname_len, str_key, str_key_len, "w+b", &error TSRMLS_CC))) { + zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Entry %s cannot be created: %s", str_key, error); + efree(error); + break; + } else { + if (error) { + efree(error); + } + contents_len = php_stream_copy_to_stream(fp, data->fp, PHP_STREAM_COPY_ALL); + } + data->internal_file->compressed_filesize = data->internal_file->uncompressed_filesize = contents_len; + phar_entry_delref(data TSRMLS_CC); + /* This could cause an endless loop if index becomes zero again. + * In case that ever happens we need an additional flag. */ + iter->funcs->move_forward(iter TSRMLS_CC); + if (EG(exception)) { + break; + } + if (iter->funcs->valid(iter TSRMLS_CC) == FAILURE) { + /* reached end of iteration */ + break; + } + } while (1); + if (!EG(exception)) { + phar_flush(phar_obj->arc.archive, 0, 0, &error TSRMLS_CC); + if (error) { + zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, error); + efree(error); + } + } + } + +} +/* }}} */ + /* {{{ proto int Phar::count() * Returns the number of entries in the Phar archive */ @@ -1603,6 +1753,12 @@ ZEND_ARG_INFO(0, entry) ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO(); + +static +ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_build, 0, 0, 1) + ZEND_ARG_INFO(0, iterator) + ZEND_ARG_INFO(0, base_directory) +ZEND_END_ARG_INFO(); #endif static @@ -1639,6 +1795,7 @@ PHP_ME(Phar, offsetSet, arginfo_phar_offsetSet, ZEND_ACC_PUBLIC) PHP_ME(Phar, offsetUnset, arginfo_phar_offsetExists, ZEND_ACC_PUBLIC) PHP_ME(Phar, uncompressAllFiles, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Phar, buildFromIterator, arginfo_phar_build, ZEND_ACC_PUBLIC) #endif /* static member functions */ PHP_ME(Phar, apiVersion, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)