summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOndřej Surý <ondrej@sury.org>2013-03-29 01:32:44 +0100
committerOndřej Surý <ondrej@sury.org>2013-03-29 01:32:44 +0100
commitcf099ba2ee4e438bae16c3670a14ce0c4390529a (patch)
tree062683b6a7226ded35262e94c933b9bd81199314
parentf21eff8954d5956842795ea5653a9a5b8d62caa3 (diff)
downloadphp-cf099ba2ee4e438bae16c3670a14ce0c4390529a.tar.gz
Imported Upstream version 5.5.0~beta2upstream/5.5.0_beta2
-rw-r--r--.gitattributes2
-rw-r--r--.travis.yml4
-rw-r--r--NEWS13
-rw-r--r--README.RELEASE_PROCESS3
-rwxr-xr-xUPGRADING108
-rw-r--r--UPGRADING.INTERNALS50
-rw-r--r--Zend/tests/bug64239_1.phpt26
-rw-r--r--Zend/tests/bug64239_2.phpt58
-rw-r--r--Zend/tests/bug64239_3.phpt33
-rw-r--r--Zend/tests/bug64239_4.phpt31
-rw-r--r--Zend/tests/bug64515.phpt12
-rw-r--r--Zend/zend_API.c56
-rw-r--r--Zend/zend_API.h3
-rw-r--r--Zend/zend_builtin_functions.c20
-rw-r--r--Zend/zend_ini_parser.c562
-rw-r--r--Zend/zend_ini_parser.h33
-rw-r--r--Zend/zend_language_parser.c685
-rw-r--r--Zend/zend_language_parser.h41
-rw-r--r--Zend/zend_language_parser.y12
-rw-r--r--Zend/zend_vm_def.h34
-rw-r--r--Zend/zend_vm_execute.h34
-rwxr-xr-xconfigure93
-rw-r--r--configure.in2
-rw-r--r--ext/gd/config.m42
-rw-r--r--ext/gd/config.w324
-rw-r--r--ext/gd/gd.c425
-rw-r--r--ext/gd/libgd/gd.c73
-rw-r--r--ext/gd/libgd/gd.h141
-rw-r--r--ext/gd/libgd/gd_interpolation.c2553
-rw-r--r--ext/gd/libgd/gd_matrix.c334
-rw-r--r--ext/gd/php_gd.h6
-rw-r--r--ext/mysql/tests/mysql_field_flags.phpt6
-rw-r--r--ext/mysql/tests/mysql_list_fields.phpt2
-rw-r--r--ext/mysqlnd/mysqlnd_charset.c20
-rw-r--r--ext/opcache/Optimizer/block_pass.c4
-rw-r--r--ext/opcache/Optimizer/pass1_5.c4
-rw-r--r--ext/opcache/README6
-rw-r--r--ext/opcache/ZendAccelerator.c33
-rw-r--r--ext/opcache/ZendAccelerator.h6
-rw-r--r--ext/opcache/config.m433
-rw-r--r--ext/opcache/shared_alloc_win32.c2
-rw-r--r--ext/opcache/tests/bug64482.inc2
-rw-r--r--ext/opcache/tests/bug64482.phpt17
-rw-r--r--ext/opcache/zend_accelerator_module.c1
-rw-r--r--ext/opcache/zend_accelerator_util_funcs.c2
-rw-r--r--ext/opcache/zend_shared_alloc.c14
-rw-r--r--ext/opcache/zend_shared_alloc.h4
-rw-r--r--ext/pdo_pgsql/tests/is_in_transaction.phpt8
-rw-r--r--ext/pgsql/tests/bug46408.phpt3
-rw-r--r--ext/phar/tests/phpinfo_001.phpt4
-rw-r--r--ext/phar/tests/phpinfo_002.phpt2
-rw-r--r--ext/phar/tests/phpinfo_004.phpt4
-rw-r--r--ext/reflection/php_reflection.c3
-rw-r--r--ext/reflection/tests/bug64239.phpt44
-rw-r--r--ext/spl/spl_dllist.c2
-rw-r--r--ext/standard/info.c8
-rw-r--r--ext/standard/string.c4
-rw-r--r--ext/standard/tests/strings/stristr_error.phpt4
-rw-r--r--ext/standard/tests/strings/strstr.phptbin10539 -> 10530 bytes
-rw-r--r--ext/zip/lib/zip_close.c5
-rw-r--r--main/php_version.h4
-rw-r--r--main/win32_internal_function_disabled.h6
-rwxr-xr-xmakedist5
-rw-r--r--pear/install-pear-nozlib.phar12181
-rw-r--r--php.ini-development96
-rw-r--r--php.ini-production96
-rw-r--r--sapi/cli/php.1.in32
-rw-r--r--sapi/cli/php_cli_server.c61
-rw-r--r--win32/time.c19
69 files changed, 16582 insertions, 1618 deletions
diff --git a/.gitattributes b/.gitattributes
index 9ed6e5f4b..79b218fcb 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -23,6 +23,8 @@ sapi/continuity/capi.c ident
Zend/RFCs/002.txt ident
Zend/RFCs/003.txt ident
NEWS merge=NEWS
+UPGRADING merge=NEWS
+UPGRADING.INTERNALS merge=NEWS
/ext/bz2/tests/with_strings.phpt -crlf
/ext/dom/tests/bug40836.phpt -crlf
/ext/dom/tests/domelement.phpt -crlf
diff --git a/.travis.yml b/.travis.yml
index 2939e3e92..4d127fe02 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -8,7 +8,7 @@ notifications:
email: false
env:
- - REPORT_EXIT_STATUS=1 TEST_PHP_EXECUTABLE=./sapi/cli/php
+ - REPORT_EXIT_STATUS=1
before_script:
# Compile PHP
@@ -21,4 +21,4 @@ before_script:
- . ./travis/ext/pdo_pgsql/setup.sh
# Run PHPs run-tests.php
-script: ./sapi/cli/php run-tests.php -g "FAIL,XFAIL,BORK,WARN,LEAK,SKIP"
+script: ./sapi/cli/php run-tests.php -p `pwd`/sapi/cli/php -g "FAIL,XFAIL,BORK,WARN,LEAK,SKIP" --show-diff
diff --git a/NEWS b/NEWS
index 5f29170fb..6a14d15e0 100644
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,18 @@
PHP NEWS
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+28 Mar 2013, PHP 5.5.0 Beta 2
+
+- Core:
+ . Fixed bug #64515 (Memoryleak when using the same variablename 2times in
+ function declaration). (Laruence)
+ . Fixed bug #64503 (Compilation fails with error: conflicting types for
+ 'zendparse'). (Laruence)
+ . Fixed bug #64239 (Debug backtrace changed behavior since 5.4.10 or 5.4.11).
+ (Dmitry, Laruence)
+
+- Opcache:
+ . Fixed bug # 64490 (struct flock undefined on FreeBSD). (Joe Watkins)
+
21 Mar 2013, PHP 5.5.0 Beta 1
- Core:
diff --git a/README.RELEASE_PROCESS b/README.RELEASE_PROCESS
index c8eeb4e13..58d3cd4e8 100644
--- a/README.RELEASE_PROCESS
+++ b/README.RELEASE_PROCESS
@@ -64,7 +64,8 @@ Do not use abbreviations for alpha and beta.
``git push --tags origin HEAD``
8. run: ``./makedist 5.4.2RC2``, this will export the tree, create configure
-and build three tarballs (gz,bz2 and xz).
+and build three tarballs (gz,bz2 and xz). Make sure you use the same GNU Bison
+version as snaps. Recent bison version are known to break ZTS.
9. Copy those three tarballs to www.php.net, in your homedir there should be a
directory "downloads/". Copy them into there, so that the system can generate
diff --git a/UPGRADING b/UPGRADING
index ca35a99cd..c02061175 100755
--- a/UPGRADING
+++ b/UPGRADING
@@ -30,38 +30,6 @@ PHP 5.5 UPGRADE NOTES
zend_logo_guid() have been removed
- Removal of Logo GUIDs
-- extensions can't override zend_execute() any more, they should override
- zend_execute_ex() instead. The EG(current_execute_data) is already
- initialized in zend_execute_ex(), so for compatibility extensions
- may need to use EG(current_execute_data)->prev_execute_data instead.
-- removed EG(arg_types_stack), EX(fbc), EX(called_scope), EX(current_object)
-- added op_array->nested_calls. It's calculated at compile time.
-- added EX(call_slots). It is an array to store information about syntaticaly
- nested calls (e.g. foo(bar())). It's preallocated together with execute_data.
-- added EX(call) - pointer to a current calling function. Actually an
- element of EX(call_slots)
-- opcodes INIT_METHOD_CALL, ZEND_INIT_STATIC_METHOD_CALL,
- ZEND_INIT_FCALL_BY_NAME, ZEND_INIT_NS_FCALL_BY_NAME use result.num as
- an index in EX(call_slots)
-- opcode ZEND_NEW uses extended_vallue as an index in EX(call_slots)
-- opcoes ZEND_DO_FCALL and ZEND_DO_FCALL_BY_NAME use op2.num as
- an index in EX(call_slots)
-- added op_array->used_stack. It's calculated at compile time and the
- corresponding stack space is preallocated together with execute_data.
- ZEND_SEND* and ZEND_DO_FCALL* don't need to check for stack overflow
- anymore.
-- Removed execute_data->Ts field. The VM temporary variables always allocated
- immediately before execute_data structure. Now they are accessed by offset
- from the execute_data base pointer (instead of execute_data->Ts). Compiler
- stores new offsets in op_array->opcodes[*].op?.num. You can use macros
- EX_TMP_VAR() and EX_TMP_VAR_NUM() to access temp_variable by offset or
- number. You can convert number to offset using EX_TMP_VAR_NUM(0, num) or
- offset to number (EX_TMP_VAR_NUM(0,0)-EX_TMP_VAR(0,offset)).
-- Removed execute_data->CVs field. The VM compiled variables always allocated
- immediately after execute_data structure. Now they are accessed by offset
- from the execute_data base pointer (instead of execute_data->CVs). You can
- use macros EX_CV_NUM() to access compiled variables by number.
-
========================================
2. New Features
========================================
@@ -79,15 +47,17 @@ PHP 5.5 UPGRADE NOTES
(https://wiki.php.net/rfc/generators)
- ClassName::class syntax returning full class name for a class as
a string constant. (https://wiki.php.net/rfc/class_name_scalars)
-- Support for changing the process's title in CLI/CLI-Server SAPIs. (Keyur)
- (https://wiki.php.net/rfc/cli_process_title)
- Added support for non-scalar Iterator keys in foreach.
(https://wiki.php.net/rfc/foreach-non-scalar-keys).
+- Bundled Zend OPcache extension
+ (https://wiki.php.net/rfc/optimizerplus)
========================================
2. Changes in SAPI modules
========================================
+- Support for changing the process's title in CLI/CLI-Server SAPIs. (Keyur)
+ (https://wiki.php.net/rfc/cli_process_title)
========================================
3. Deprecated Functionality
@@ -169,6 +139,7 @@ PHP 5.5 UPGRADE NOTES
========================================
- Core:
+ - array_column()
- boolval()
- password_get_info()
- password_hash()
@@ -182,6 +153,11 @@ PHP 5.5 UPGRADE NOTES
- imageflip
- imagecrop
- imagecropauto
+ - imagesetinterpolation
+ - imageaffine
+ - imageaffinematrixget
+ - imageaffinematrixconcat
+ - imagescale
- Hash:
- hash_pbkdf2()
@@ -275,6 +251,12 @@ PHP 5.5 UPGRADE NOTES
- SPL:
- SplFixedArray::__wakeup()
+ - SplDoublyLinkedList::add()
+
+- Zend OPcache
+ - opcache_get_configuration()
+ - opcache_get_status()
+ - opcache_reset()
========================================
6. New Classes and Interfaces
@@ -326,13 +308,42 @@ PHP 5.5 UPGRADE NOTES
. IMG_CROP_WHITE
. IMG_CROP_SIDES
. IMG_CROP_THRESHOLD
+ - Added constants for imagesetinterpolation, used by imagescale
+ imagerotate and imageaffine:
+ . IMG_BELL
+ . IMG_BESSEL
+ . IMG_BILINEAR_FIXED
+ . IMG_BICUBIC
+ . IMG_BICUBIC_FIXED
+ . IMG_BLACKMAN
+ . IMG_BOX
+ . IMG_BSPLINE
+ . IMG_CATMULLROM
+ . IMG_GAUSSIAN
+ . IMG_GENERALIZED_CUBIC
+ . IMG_HERMITE
+ . IMG_HAMMING
+ . IMG_HANNING
+ . IMG_MITCHELL
+ . IMG_POWER
+ . IMG_QUADRATIC
+ . IMG_SINC
+ . IMG_NEAREST_NEIGHBOUR
+ . IMG_WEIGHTED4
+ . IMG_TRIANGLE
+ - Added constants for imageaffinematrixget
+ . IMG_AFFINE_TRANSLATE
+ . IMG_AFFINE_SCALE
+ . IMG_AFFINE_ROTATE
+ . IMG_AFFINE_SHEAR_HORIZONTAL
+ . IMG_AFFINE_SHEAR_VERTICAL
========================================
10. Changes to INI File Handling
========================================
- Core:
- - Added sys_temp_dir INI directive, for specifying temp firectory.
+ - Added sys_temp_dir INI directive, for specifying temp directory.
- Intl:
- Added intl.use_exceptions INI directive, which controls what happens when
@@ -343,6 +354,33 @@ PHP 5.5 UPGRADE NOTES
APIs which use(are built) for mysqlnd. This allows ext/mysqli to be used
with the new auth protocol, although at coarser level.
+- Zend OPcache (See ext/opcache/README for more details)
+ - Added the following directives:
+ - opcache.enable (default "1")
+ - opcache.memory_consumption (default "64")
+ - opcache.interned_strings_buffer (default "4")
+ - opcache.max_accelerated_files (default "2000")
+ - opcache.max_wasted_percentage (default "5")
+ - opcache.use_cwd (default "1")
+ - opcache.validate_timestamps (default "1")
+ - opcache.revalidate_freq (default "2")
+ - opcache.revalidate_path (default "0")
+ - opcache.save_comments (default "1")
+ - opcache.load_comments (default "1")
+ - opcache.fast_shutdown (default "0")
+ - opcache.enable_file_override (default "0")
+ - opcache.optimization_level (default "0xffffffff")
+ - opcache.inherited_hack (default "1")
+ - opcache.blacklist_filename (default "")
+ - opcache.max_file_size (default "0")
+ - opcache.consistency_checks (default "0")
+ - opcache.force_restart_timeout (default "180")
+ - opcache.error_log (default "" which means stderr)
+ - opcache.log_verbosity_level (default "1")
+ - opcache.preferred_memory_model (default "")
+ - opcache.protect_memory (default "0")
+ - opcache.mmap_base (Windows-only)
+
========================================
11. Windows Support
========================================
diff --git a/UPGRADING.INTERNALS b/UPGRADING.INTERNALS
index 56243d1f8..bdc2a43ab 100644
--- a/UPGRADING.INTERNALS
+++ b/UPGRADING.INTERNALS
@@ -3,9 +3,11 @@ $Id$
UPGRADE NOTES - PHP X.Y
1. Internal API changes
- a. Streams pooling API
- b. Lowercasing and locales
- c. zend_qsort_r
+ a. Executor changes
+ b. Streams pooling API
+ c. Lowercasing and locales
+ d. zend_qsort_r
+ e. get_current_key
2. Build system changes
a. Unix build system changes
@@ -16,7 +18,41 @@ UPGRADE NOTES - PHP X.Y
1. Internal API changes
========================
- a. Streams pooling API
+ a. Executor changes
+
+ * extensions can't override zend_execute() any more, they should override
+ zend_execute_ex() instead. The EG(current_execute_data) is already
+ initialized in zend_execute_ex(), so for compatibility extensions
+ may need to use EG(current_execute_data)->prev_execute_data instead.
+ * removed EG(arg_types_stack), EX(fbc), EX(called_scope), EX(current_object)
+ * added op_array->nested_calls. It's calculated at compile time.
+ * added EX(call_slots). It is an array to store information about syntaticaly
+ nested calls (e.g. foo(bar())). It's preallocated together with execute_data.
+ * added EX(call) - pointer to a current calling function. Actually an
+ element of EX(call_slots)
+ * opcodes INIT_METHOD_CALL, ZEND_INIT_STATIC_METHOD_CALL,
+ ZEND_INIT_FCALL_BY_NAME, ZEND_INIT_NS_FCALL_BY_NAME use result.num as
+ an index in EX(call_slots)
+ * opcode ZEND_NEW uses extended_vallue as an index in EX(call_slots)
+ * opcoes ZEND_DO_FCALL and ZEND_DO_FCALL_BY_NAME use op2.num as
+ an index in EX(call_slots)
+ * added op_array->used_stack. It's calculated at compile time and the
+ corresponding stack space is preallocated together with execute_data.
+ ZEND_SEND* and ZEND_DO_FCALL* don't need to check for stack overflow
+ anymore.
+ * Removed execute_data->Ts field. The VM temporary variables always allocated
+ immediately before execute_data structure. Now they are accessed by offset
+ from the execute_data base pointer (instead of execute_data->Ts). Compiler
+ stores new offsets in op_array->opcodes[*].op?.num. You can use macros
+ EX_TMP_VAR() and EX_TMP_VAR_NUM() to access temp_variable by offset or
+ number. You can convert number to offset using EX_TMP_VAR_NUM(0, num) or
+ offset to number (EX_TMP_VAR_NUM(0,0)-EX_TMP_VAR(0,offset)).
+ * Removed execute_data->CVs field. The VM compiled variables always allocated
+ immediately after execute_data structure. Now they are accessed by offset
+ from the execute_data base pointer (instead of execute_data->CVs). You can
+ use macros EX_CV_NUM() to access compiled variables by number.
+
+ b. Streams pooling API
The streams pooling API has been removed. The following functions no longer
exist:
@@ -28,7 +64,7 @@ PHPAPI int php_stream_context_set_link(php_stream_context *context,
PHPAPI int php_stream_context_del_link(php_stream_context *context,
php_stream *stream);
- b. Lowercasing and locales
+ c. Lowercasing and locales
The lowercasing functions in zend_operators.c were split into those that do
lowercasing according to locale rules and those that do ASCII lowercasing.
@@ -54,7 +90,7 @@ such as strcasecmp, will be using locale rules.
Two new functions - zend_binary_strncasecmp_l and zend_binary_strcasecmp_l - added as
locale-based counterparts to zend_binary_strcasecmp and zend_binary_strncasecmp.
- c. zend_qsort_r
+ d. zend_qsort_r
Added the function zend_qsort_r():
@@ -64,7 +100,7 @@ void zend_qsort_r(void *base, size_t nmemb, size_t siz, compare_r_func_t compare
The extra argument it has (relatively to zend_qsort()) is passed to the
comparison function.
- d. get_current_key
+ e. get_current_key
The signature of the get_current_key iteration handler has been changed to:
diff --git a/Zend/tests/bug64239_1.phpt b/Zend/tests/bug64239_1.phpt
index fe58cbd76..10d44c181 100644
--- a/Zend/tests/bug64239_1.phpt
+++ b/Zend/tests/bug64239_1.phpt
@@ -3,20 +3,26 @@ Bug #64239 (get_class_methods() changed behavior)
--FILE--
<?php
class A {
- public function test() { $this->backtrace(); }
-}
-class B {
use T2 { t2method as Bmethod; }
}
+
+class B extends A {
+}
+
trait T2 {
public function t2method() {
}
}
-var_dump(get_class_methods("B"));
+print_r(get_class_methods("A"));
+print_r(get_class_methods("B"));
--EXPECT--
-array(2) {
- [0]=>
- string(7) "bmethod"
- [1]=>
- string(8) "t2method"
-}
+Array
+(
+ [0] => Bmethod
+ [1] => t2method
+)
+Array
+(
+ [0] => Bmethod
+ [1] => t2method
+)
diff --git a/Zend/tests/bug64239_2.phpt b/Zend/tests/bug64239_2.phpt
new file mode 100644
index 000000000..26cf8ee1a
--- /dev/null
+++ b/Zend/tests/bug64239_2.phpt
@@ -0,0 +1,58 @@
+--TEST--
+Bug #64239 (debug_backtrace() changed behavior)
+--FILE--
+<?php
+class A {
+ use T1;
+ public function test() { $this->backtrace(); }
+}
+
+class B {
+ use T2 { t2method as Bmethod; }
+}
+
+class C extends A {
+}
+
+trait T1 {
+ protected function backtrace() {
+ $b = new B();
+ $b->Bmethod();
+ }
+}
+trait T2 {
+ public function t2method() {
+ print_r(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 1));
+ }
+}
+$a = new A();
+$a->test();
+
+$c = new C();
+$c->test();
+?>
+--EXPECTF--
+Array
+(
+ [0] => Array
+ (
+ [file] => %sbug64239_2.php
+ [line] => %d
+ [function] => Bmethod
+ [class] => B
+ [type] => ->
+ )
+
+)
+Array
+(
+ [0] => Array
+ (
+ [file] => %sbug64239_2.php
+ [line] => %d
+ [function] => Bmethod
+ [class] => B
+ [type] => ->
+ )
+
+)
diff --git a/Zend/tests/bug64239_3.phpt b/Zend/tests/bug64239_3.phpt
new file mode 100644
index 000000000..15faeb985
--- /dev/null
+++ b/Zend/tests/bug64239_3.phpt
@@ -0,0 +1,33 @@
+--TEST--
+Bug #64239 (debug_print_backtrace() changed behavior)
+--FILE--
+<?php
+class A {
+ use T2 { t2method as Bmethod; }
+}
+
+class C extends A {
+ public function Bmethod() {
+ debug_print_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 1);
+ }
+}
+
+trait T2 {
+ public function t2method() {
+ debug_print_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 1);
+ }
+}
+
+$a = new A();
+$a->Bmethod();
+$a->t2method();
+
+$c = new C();
+$c->Bmethod();
+$c->t2method();
+?>
+--EXPECTF--
+#0 A->Bmethod() called at [%sbug64239_3.php:%d]
+#0 A->t2method() called at [%sbug64239_3.php:%d]
+#0 C->Bmethod() called at [%sbug64239_3.php:%d]
+#0 A->t2method() called at [%sbug64239_3.php:%d]
diff --git a/Zend/tests/bug64239_4.phpt b/Zend/tests/bug64239_4.phpt
new file mode 100644
index 000000000..7ab761ef7
--- /dev/null
+++ b/Zend/tests/bug64239_4.phpt
@@ -0,0 +1,31 @@
+--TEST--
+Bug #64239 (debug_print_backtrace() changed behavior)
+--FILE--
+<?php
+class A {
+ use T2 { t2method as Bmethod; }
+}
+
+class C extends A {
+ public static function Bmethod() {
+ debug_print_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 1);
+ }
+}
+
+trait T2 {
+ public static function t2method() {
+ debug_print_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 1);
+ }
+}
+
+A::Bmethod();
+A::t2method();
+
+C::Bmethod();
+C::t2method();
+?>
+--EXPECTF--
+#0 A::Bmethod() called at [%sbug64239_4.php:%d]
+#0 A::t2method() called at [%sbug64239_4.php:%d]
+#0 C::Bmethod() called at [%sbug64239_4.php:%d]
+#0 A::t2method() called at [%sbug64239_4.php:%d]
diff --git a/Zend/tests/bug64515.phpt b/Zend/tests/bug64515.phpt
new file mode 100644
index 000000000..5390a6cdc
--- /dev/null
+++ b/Zend/tests/bug64515.phpt
@@ -0,0 +1,12 @@
+--TEST--
+Bug #64515 (Memoryleak when using the same variablename 2times in function declaration)
+--FILE--
+<?php
+function foo($unused = null, $unused = null, $arg = array()) {
+ return 1;
+}
+foo();
+echo "okey";
+?>
+--EXPECT--
+okey
diff --git a/Zend/zend_API.c b/Zend/zend_API.c
index 1f400dea1..e867ca5da 100644
--- a/Zend/zend_API.c
+++ b/Zend/zend_API.c
@@ -3976,6 +3976,62 @@ ZEND_API void zend_restore_error_handling(zend_error_handling *saved TSRMLS_DC)
}
/* }}} */
+ZEND_API const char* zend_find_alias_name(zend_class_entry *ce, const char *name, zend_uint len) /* {{{ */
+{
+ zend_trait_alias *alias, **alias_ptr;
+
+ alias_ptr = ce->trait_aliases;
+ alias = *alias_ptr;
+ while (alias) {
+ if (alias->alias_len == len &&
+ !strncasecmp(name, alias->alias, alias->alias_len)) {
+ return alias->alias;
+ }
+ alias_ptr++;
+ alias = *alias_ptr;
+ }
+
+ return name;
+}
+/* }}} */
+
+ZEND_API const char* zend_resolve_method_name(zend_class_entry *ce, zend_function *f) /* {{{ */
+{
+ zend_function *func;
+ HashPosition iterator;
+ HashTable *function_table;
+
+ if (f->common.type != ZEND_USER_FUNCTION ||
+ *(f->op_array.refcount) < 2 ||
+ !f->common.scope ||
+ !f->common.scope->trait_aliases) {
+ return f->common.function_name;
+ }
+
+ function_table = &ce->function_table;
+ zend_hash_internal_pointer_reset_ex(function_table, &iterator);
+ while (zend_hash_get_current_data_ex(function_table, (void **)&func, &iterator) == SUCCESS) {
+ if (func == f) {
+ char *name;
+ uint len;
+ ulong idx;
+
+ if (zend_hash_get_current_key_ex(function_table, &name, &len, &idx, 0, &iterator) != HASH_KEY_IS_STRING) {
+ return f->common.function_name;
+ }
+ --len;
+ if (len == strlen(f->common.function_name) &&
+ !strncasecmp(name, f->common.function_name, len)) {
+ return f->common.function_name;
+ }
+ return zend_find_alias_name(f->common.scope, name, len);
+ }
+ zend_hash_move_forward_ex(function_table, &iterator);
+ }
+ return f->common.function_name;
+}
+/* }}} */
+
/*
* Local variables:
* tab-width: 4
diff --git a/Zend/zend_API.h b/Zend/zend_API.h
index c26141b18..26aa1e6b1 100644
--- a/Zend/zend_API.h
+++ b/Zend/zend_API.h
@@ -521,6 +521,9 @@ ZEND_API void zend_reset_all_cv(HashTable *symbol_table TSRMLS_DC);
ZEND_API void zend_rebuild_symbol_table(TSRMLS_D);
+ZEND_API const char* zend_find_alias_name(zend_class_entry *ce, const char *name, zend_uint len);
+ZEND_API const char* zend_resolve_method_name(zend_class_entry *ce, zend_function *f);
+
#define add_method(arg, key, method) add_assoc_function((arg), (key), (method))
ZEND_API ZEND_FUNCTION(display_disabled_function);
diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c
index ee75f521f..d61aba14b 100644
--- a/Zend/zend_builtin_functions.c
+++ b/Zend/zend_builtin_functions.c
@@ -1092,7 +1092,7 @@ ZEND_FUNCTION(get_class_methods)
(len != key_len - 1 ||
!same_name(key, mptr->common.function_name, len))) {
MAKE_STD_ZVAL(method_name);
- ZVAL_STRINGL(method_name, key, key_len - 1, 1);
+ ZVAL_STRINGL(method_name, zend_find_alias_name(mptr->common.scope, key, key_len - 1), key_len - 1, 1);
zend_hash_next_index_insert(return_value->value.ht, &method_name, sizeof(zval *), NULL);
} else {
MAKE_STD_ZVAL(method_name);
@@ -2103,7 +2103,14 @@ ZEND_FUNCTION(debug_print_backtrace)
lineno = 0;
}
- function_name = ptr->function_state.function->common.function_name;
+ function_name = (ptr->function_state.function->common.scope &&
+ ptr->function_state.function->common.scope->trait_aliases) ?
+ zend_resolve_method_name(
+ ptr->object ?
+ Z_OBJCE_P(ptr->object) :
+ ptr->function_state.function->common.scope,
+ ptr->function_state.function) :
+ ptr->function_state.function->common.function_name;
if (function_name) {
if (ptr->object) {
@@ -2284,7 +2291,14 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int
filename = NULL;
}
- function_name = ptr->function_state.function->common.function_name;
+ function_name = (ptr->function_state.function->common.scope &&
+ ptr->function_state.function->common.scope->trait_aliases) ?
+ zend_resolve_method_name(
+ ptr->object ?
+ Z_OBJCE_P(ptr->object) :
+ ptr->function_state.function->common.scope,
+ ptr->function_state.function) :
+ ptr->function_state.function->common.function_name;
if (function_name) {
add_assoc_string_ex(stack_frame, "function", sizeof("function"), (char*)function_name, 1);
diff --git a/Zend/zend_ini_parser.c b/Zend/zend_ini_parser.c
index 6270c6c86..70be84343 100644
--- a/Zend/zend_ini_parser.c
+++ b/Zend/zend_ini_parser.c
@@ -1,8 +1,10 @@
-/* A Bison parser, made by GNU Bison 2.6.1. */
-/* Bison implementation for Yacc-like parsers in C
+/* A Bison parser, made by GNU Bison 2.4.1. */
+
+/* Skeleton implementation for Bison's Yacc-like parsers in C
- Copyright (C) 1984, 1989-1990, 2000-2012 Free Software Foundation, Inc.
+ Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+ Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -44,7 +46,7 @@
#define YYBISON 1
/* Bison version. */
-#define YYBISON_VERSION "2.6.1"
+#define YYBISON_VERSION "2.4.1"
/* Skeleton name. */
#define YYSKELETON_NAME "yacc.c"
@@ -58,6 +60,8 @@
/* Pull parsers. */
#define YYPULL 1
+/* Using locations. */
+#define YYLSP_NEEDED 0
/* Substitute the variable and function names. */
#define yyparse ini_parse
@@ -68,6 +72,7 @@
#define yydebug ini_debug
#define yynerrs ini_nerrs
+
/* Copy the first part of user declarations. */
@@ -319,13 +324,10 @@ ZEND_API int zend_parse_ini_string(char *str, zend_bool unbuffered_errors, int s
-# ifndef YY_NULL
-# if defined __cplusplus && 201103L <= __cplusplus
-# define YY_NULL nullptr
-# else
-# define YY_NULL 0
-# endif
-# endif
+/* Enabling traces. */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
/* Enabling verbose error messages. */
#ifdef YYERROR_VERBOSE
@@ -335,18 +337,12 @@ ZEND_API int zend_parse_ini_string(char *str, zend_bool unbuffered_errors, int s
# define YYERROR_VERBOSE 0
#endif
-/* In a future release of Bison, this section will be replaced
- by #include "zend_ini_parser.h". */
-#ifndef INI_ZEND_ZEND_INI_PARSER_H
-# define INI_ZEND_ZEND_INI_PARSER_H
-/* Enabling traces. */
-#ifndef YYDEBUG
-# define YYDEBUG 0
-#endif
-#if YYDEBUG
-extern int ini_debug;
+/* Enabling the token table. */
+#ifndef YYTOKEN_TABLE
+# define YYTOKEN_TABLE 0
#endif
+
/* Tokens. */
#ifndef YYTOKENTYPE
# define YYTOKENTYPE
@@ -387,6 +383,7 @@ extern int ini_debug;
+
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
typedef int YYSTYPE;
# define YYSTYPE_IS_TRIVIAL 1
@@ -395,22 +392,6 @@ typedef int YYSTYPE;
#endif
-#ifdef YYPARSE_PARAM
-#if defined __STDC__ || defined __cplusplus
-int ini_parse (void *YYPARSE_PARAM);
-#else
-int ini_parse ();
-#endif
-#else /* ! YYPARSE_PARAM */
-#if defined __STDC__ || defined __cplusplus
-int ini_parse (void);
-#else
-int ini_parse ();
-#endif
-#endif /* ! YYPARSE_PARAM */
-
-#endif /* !INI_ZEND_ZEND_INI_PARSER_H */
-
/* Copy the second part of user declarations. */
@@ -463,7 +444,7 @@ typedef short int yytype_int16;
#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
#ifndef YY_
-# if defined YYENABLE_NLS && YYENABLE_NLS
+# if YYENABLE_NLS
# if ENABLE_NLS
# include <libintl.h> /* INFRINGES ON USER NAME SPACE */
# define YY_(msgid) dgettext ("bison-runtime", msgid)
@@ -516,12 +497,11 @@ YYID (yyi)
# define alloca _alloca
# else
# define YYSTACK_ALLOC alloca
-# if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \
+# if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
|| defined __cplusplus || defined _MSC_VER)
# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
- /* Use EXIT_SUCCESS as a witness for stdlib.h. */
-# ifndef EXIT_SUCCESS
-# define EXIT_SUCCESS 0
+# ifndef _STDLIB_H
+# define _STDLIB_H 1
# endif
# endif
# endif
@@ -544,24 +524,24 @@ YYID (yyi)
# ifndef YYSTACK_ALLOC_MAXIMUM
# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
# endif
-# if (defined __cplusplus && ! defined EXIT_SUCCESS \
+# if (defined __cplusplus && ! defined _STDLIB_H \
&& ! ((defined YYMALLOC || defined malloc) \
&& (defined YYFREE || defined free)))
# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
-# ifndef EXIT_SUCCESS
-# define EXIT_SUCCESS 0
+# ifndef _STDLIB_H
+# define _STDLIB_H 1
# endif
# endif
# ifndef YYMALLOC
# define YYMALLOC malloc
-# if ! defined malloc && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \
+# if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
|| defined __cplusplus || defined _MSC_VER)
void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
# endif
# endif
# ifndef YYFREE
# define YYFREE free
-# if ! defined free && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \
+# if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
|| defined __cplusplus || defined _MSC_VER)
void free (void *); /* INFRINGES ON USER NAME SPACE */
# endif
@@ -590,7 +570,23 @@ union yyalloc
((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \
+ YYSTACK_GAP_MAXIMUM)
-# define YYCOPY_NEEDED 1
+/* Copy COUNT objects from FROM to TO. The source and destination do
+ not overlap. */
+# ifndef YYCOPY
+# if defined __GNUC__ && 1 < __GNUC__
+# define YYCOPY(To, From, Count) \
+ __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
+# else
+# define YYCOPY(To, From, Count) \
+ do \
+ { \
+ YYSIZE_T yyi; \
+ for (yyi = 0; yyi < (Count); yyi++) \
+ (To)[yyi] = (From)[yyi]; \
+ } \
+ while (YYID (0))
+# endif
+# endif
/* Relocate STACK from its old location to the new one. The
local variables YYSIZE and YYSTACKSIZE give the old and new number of
@@ -610,26 +606,6 @@ union yyalloc
#endif
-#if defined YYCOPY_NEEDED && YYCOPY_NEEDED
-/* Copy COUNT objects from SRC to DST. The source and destination do
- not overlap. */
-# ifndef YYCOPY
-# if defined __GNUC__ && 1 < __GNUC__
-# define YYCOPY(Dst, Src, Count) \
- __builtin_memcpy (Dst, Src, (Count) * sizeof (*(Src)))
-# else
-# define YYCOPY(Dst, Src, Count) \
- do \
- { \
- YYSIZE_T yyi; \
- for (yyi = 0; yyi < (Count); yyi++) \
- (Dst)[yyi] = (Src)[yyi]; \
- } \
- while (YYID (0))
-# endif
-# endif
-#endif /* !YYCOPY_NEEDED */
-
/* YYFINAL -- State number of the termination state. */
#define YYFINAL 2
/* YYLAST -- Last index in YYTABLE. */
@@ -725,7 +701,7 @@ static const yytype_uint16 yyrline[] =
};
#endif
-#if YYDEBUG || YYERROR_VERBOSE || 0
+#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
First, the terminals, then, starting at YYNTOKENS, nonterminals. */
static const char *const yytname[] =
@@ -739,7 +715,7 @@ static const char *const yytname[] =
"$accept", "statement_list", "statement", "section_string_or_value",
"string_or_value", "option_offset", "encapsed_list",
"var_string_list_section", "var_string_list", "expr", "cfg_var_ref",
- "constant_literal", "constant_string", YY_NULL
+ "constant_literal", "constant_string", 0
};
#endif
@@ -776,8 +752,8 @@ static const yytype_uint8 yyr2[] =
1, 1, 1, 1, 1, 1, 1, 1, 1
};
-/* YYDEFACT[STATE-NAME] -- Default reduction number in state STATE-NUM.
- Performed when YYTABLE doesn't specify something else to do. Zero
+/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
+ STATE-NUM when YYTABLE doesn't specify something else to do. Zero
means the default is an error. */
static const yytype_uint8 yydefact[] =
{
@@ -820,7 +796,8 @@ static const yytype_int8 yypgoto[] =
/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If
positive, shift that token. If negative, reduce the rule which
- number is the opposite. If YYTABLE_NINF, syntax error. */
+ number is the opposite. If zero, do what YYDEFACT says.
+ If YYTABLE_NINF, syntax error. */
#define YYTABLE_NINF -1
static const yytype_uint8 yytable[] =
{
@@ -837,12 +814,6 @@ static const yytype_uint8 yytable[] =
0, 0, 4, 5, 0, 47, 0, 68, 0, 6
};
-#define yypact_value_is_default(yystate) \
- ((yystate) == (-36))
-
-#define yytable_value_is_error(yytable_value) \
- YYID (0)
-
static const yytype_int8 yycheck[] =
{
3, 25, 37, 38, 4, 5, 6, 7, 8, 33,
@@ -883,33 +854,24 @@ static const yytype_uint8 yystos[] =
/* Like YYERROR except do call yyerror. This remains here temporarily
to ease the transition to the new meaning of YYERROR, for GCC.
- Once GCC version 2 has supplanted version 1, this can go. However,
- YYFAIL appears to be in use. Nevertheless, it is formally deprecated
- in Bison 2.4.2's NEWS entry, where a plan to phase it out is
- discussed. */
+ Once GCC version 2 has supplanted version 1, this can go. */
#define YYFAIL goto yyerrlab
-#if defined YYFAIL
- /* This is here to suppress warnings from the GCC cpp's
- -Wunused-macros. Normally we don't worry about that warning, but
- some users do, and we want to make it easy for users to remove
- YYFAIL uses, which will produce warnings from Bison 2.5. */
-#endif
#define YYRECOVERING() (!!yyerrstatus)
-#define YYBACKUP(Token, Value) \
-do \
- if (yychar == YYEMPTY) \
- { \
- yychar = (Token); \
- yylval = (Value); \
- YYPOPSTACK (yylen); \
- yystate = *yyssp; \
- goto yybackup; \
- } \
- else \
- { \
+#define YYBACKUP(Token, Value) \
+do \
+ if (yychar == YYEMPTY && yylen == 1) \
+ { \
+ yychar = (Token); \
+ yylval = (Value); \
+ yytoken = YYTRANSLATE (yychar); \
+ YYPOPSTACK (1); \
+ goto yybackup; \
+ } \
+ else \
+ { \
yyerror (YY_("syntax error: cannot back up")); \
YYERROR; \
} \
@@ -919,38 +881,46 @@ while (YYID (0))
#define YYTERROR 1
#define YYERRCODE 256
+
/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
If N is 0, then set CURRENT to the empty location which ends
the previous symbol: RHS[0] (always defined). */
+#define YYRHSLOC(Rhs, K) ((Rhs)[K])
#ifndef YYLLOC_DEFAULT
-# define YYLLOC_DEFAULT(Current, Rhs, N) \
- do \
- if (YYID (N)) \
- { \
- (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \
- (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \
- (Current).last_line = YYRHSLOC (Rhs, N).last_line; \
- (Current).last_column = YYRHSLOC (Rhs, N).last_column; \
- } \
- else \
- { \
- (Current).first_line = (Current).last_line = \
- YYRHSLOC (Rhs, 0).last_line; \
- (Current).first_column = (Current).last_column = \
- YYRHSLOC (Rhs, 0).last_column; \
- } \
+# define YYLLOC_DEFAULT(Current, Rhs, N) \
+ do \
+ if (YYID (N)) \
+ { \
+ (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \
+ (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \
+ (Current).last_line = YYRHSLOC (Rhs, N).last_line; \
+ (Current).last_column = YYRHSLOC (Rhs, N).last_column; \
+ } \
+ else \
+ { \
+ (Current).first_line = (Current).last_line = \
+ YYRHSLOC (Rhs, 0).last_line; \
+ (Current).first_column = (Current).last_column = \
+ YYRHSLOC (Rhs, 0).last_column; \
+ } \
while (YYID (0))
#endif
-#define YYRHSLOC(Rhs, K) ((Rhs)[K])
-
-
-/* This macro is provided for backward compatibility. */
+/* YY_LOCATION_PRINT -- Print the location on the stream.
+ This macro was not mandated originally: define only if we know
+ we won't break user code: when these are the locations we know. */
#ifndef YY_LOCATION_PRINT
-# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
+# if YYLTYPE_IS_TRIVIAL
+# define YY_LOCATION_PRINT(File, Loc) \
+ fprintf (File, "%d.%d-%d.%d", \
+ (Loc).first_line, (Loc).first_column, \
+ (Loc).last_line, (Loc).last_column)
+# else
+# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
+# endif
#endif
@@ -1005,8 +975,6 @@ yy_symbol_value_print (yyoutput, yytype, yyvaluep)
YYSTYPE const * const yyvaluep;
#endif
{
- FILE *yyo = yyoutput;
- YYUSE (yyo);
if (!yyvaluep)
return;
# ifdef YYPRINT
@@ -1144,6 +1112,7 @@ int yydebug;
# define YYMAXDEPTH 10000
#endif
+
#if YYERROR_VERBOSE
@@ -1246,142 +1215,115 @@ yytnamerr (char *yyres, const char *yystr)
}
# endif
-/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message
- about the unexpected token YYTOKEN for the state stack whose top is
- YYSSP.
-
- Return 0 if *YYMSG was successfully written. Return 1 if *YYMSG is
- not large enough to hold the message. In that case, also set
- *YYMSG_ALLOC to the required number of bytes. Return 2 if the
- required number of bytes is too large to store. */
-static int
-yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
- yytype_int16 *yyssp, int yytoken)
+/* Copy into YYRESULT an error message about the unexpected token
+ YYCHAR while in state YYSTATE. Return the number of bytes copied,
+ including the terminating null byte. If YYRESULT is null, do not
+ copy anything; just return the number of bytes that would be
+ copied. As a special case, return 0 if an ordinary "syntax error"
+ message will do. Return YYSIZE_MAXIMUM if overflow occurs during
+ size calculation. */
+static YYSIZE_T
+yysyntax_error (char *yyresult, int yystate, int yychar)
{
- YYSIZE_T yysize0 = yytnamerr (YY_NULL, yytname[yytoken]);
- YYSIZE_T yysize = yysize0;
- YYSIZE_T yysize1;
- enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
- /* Internationalized format string. */
- const char *yyformat = YY_NULL;
- /* Arguments of yyformat. */
- char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
- /* Number of reported tokens (one for the "unexpected", one per
- "expected"). */
- int yycount = 0;
-
- /* There are many possibilities here to consider:
- - Assume YYFAIL is not used. It's too flawed to consider. See
- <http://lists.gnu.org/archive/html/bison-patches/2009-12/msg00024.html>
- for details. YYERROR is fine as it does not invoke this
- function.
- - If this state is a consistent state with a default action, then
- the only way this function was invoked is if the default action
- is an error action. In that case, don't check for expected
- tokens because there are none.
- - The only way there can be no lookahead present (in yychar) is if
- this state is a consistent state with a default action. Thus,
- detecting the absence of a lookahead is sufficient to determine
- that there is no unexpected or expected token to report. In that
- case, just report a simple "syntax error".
- - Don't assume there isn't a lookahead just because this state is a
- consistent state with a default action. There might have been a
- previous inconsistent state, consistent state with a non-default
- action, or user semantic action that manipulated yychar.
- - Of course, the expected token list depends on states to have
- correct lookahead information, and it depends on the parser not
- to perform extra reductions after fetching a lookahead from the
- scanner and before detecting a syntax error. Thus, state merging
- (from LALR or IELR) and default reductions corrupt the expected
- token list. However, the list is correct for canonical LR with
- one exception: it will still contain any token that will not be
- accepted due to an error action in a later state.
- */
- if (yytoken != YYEMPTY)
- {
- int yyn = yypact[*yyssp];
- yyarg[yycount++] = yytname[yytoken];
- if (!yypact_value_is_default (yyn))
- {
- /* Start YYX at -YYN if negative to avoid negative indexes in
- YYCHECK. In other words, skip the first -YYN actions for
- this state because they are default actions. */
- int yyxbegin = yyn < 0 ? -yyn : 0;
- /* Stay within bounds of both yycheck and yytname. */
- int yychecklim = YYLAST - yyn + 1;
- int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
- int yyx;
-
- for (yyx = yyxbegin; yyx < yyxend; ++yyx)
- if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR
- && !yytable_value_is_error (yytable[yyx + yyn]))
- {
- if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
- {
- yycount = 1;
- yysize = yysize0;
- break;
- }
- yyarg[yycount++] = yytname[yyx];
- yysize1 = yysize + yytnamerr (YY_NULL, yytname[yyx]);
- if (! (yysize <= yysize1
- && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
- return 2;
- yysize = yysize1;
- }
- }
- }
+ int yyn = yypact[yystate];
- switch (yycount)
+ if (! (YYPACT_NINF < yyn && yyn <= YYLAST))
+ return 0;
+ else
{
-# define YYCASE_(N, S) \
- case N: \
- yyformat = S; \
- break
- YYCASE_(0, YY_("syntax error"));
- YYCASE_(1, YY_("syntax error, unexpected %s"));
- YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s"));
- YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s"));
- YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s"));
- YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"));
-# undef YYCASE_
- }
+ int yytype = YYTRANSLATE (yychar);
+ YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]);
+ YYSIZE_T yysize = yysize0;
+ YYSIZE_T yysize1;
+ int yysize_overflow = 0;
+ enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
+ char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
+ int yyx;
+
+# if 0
+ /* This is so xgettext sees the translatable formats that are
+ constructed on the fly. */
+ YY_("syntax error, unexpected %s");
+ YY_("syntax error, unexpected %s, expecting %s");
+ YY_("syntax error, unexpected %s, expecting %s or %s");
+ YY_("syntax error, unexpected %s, expecting %s or %s or %s");
+ YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s");
+# endif
+ char *yyfmt;
+ char const *yyf;
+ static char const yyunexpected[] = "syntax error, unexpected %s";
+ static char const yyexpecting[] = ", expecting %s";
+ static char const yyor[] = " or %s";
+ char yyformat[sizeof yyunexpected
+ + sizeof yyexpecting - 1
+ + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2)
+ * (sizeof yyor - 1))];
+ char const *yyprefix = yyexpecting;
+
+ /* Start YYX at -YYN if negative to avoid negative indexes in
+ YYCHECK. */
+ int yyxbegin = yyn < 0 ? -yyn : 0;
+
+ /* Stay within bounds of both yycheck and yytname. */
+ int yychecklim = YYLAST - yyn + 1;
+ int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
+ int yycount = 1;
+
+ yyarg[0] = yytname[yytype];
+ yyfmt = yystpcpy (yyformat, yyunexpected);
+
+ for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+ if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
+ {
+ if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
+ {
+ yycount = 1;
+ yysize = yysize0;
+ yyformat[sizeof yyunexpected - 1] = '\0';
+ break;
+ }
+ yyarg[yycount++] = yytname[yyx];
+ yysize1 = yysize + yytnamerr (0, yytname[yyx]);
+ yysize_overflow |= (yysize1 < yysize);
+ yysize = yysize1;
+ yyfmt = yystpcpy (yyfmt, yyprefix);
+ yyprefix = yyor;
+ }
- yysize1 = yysize + yystrlen (yyformat);
- if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
- return 2;
- yysize = yysize1;
+ yyf = YY_(yyformat);
+ yysize1 = yysize + yystrlen (yyf);
+ yysize_overflow |= (yysize1 < yysize);
+ yysize = yysize1;
- if (*yymsg_alloc < yysize)
- {
- *yymsg_alloc = 2 * yysize;
- if (! (yysize <= *yymsg_alloc
- && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM))
- *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM;
- return 1;
- }
+ if (yysize_overflow)
+ return YYSIZE_MAXIMUM;
- /* Avoid sprintf, as that infringes on the user's name space.
- Don't have undefined behavior even if the translation
- produced a string with the wrong number of "%s"s. */
- {
- char *yyp = *yymsg;
- int yyi = 0;
- while ((*yyp = *yyformat) != '\0')
- if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount)
- {
- yyp += yytnamerr (yyp, yyarg[yyi++]);
- yyformat += 2;
- }
- else
- {
- yyp++;
- yyformat++;
- }
- }
- return 0;
+ if (yyresult)
+ {
+ /* Avoid sprintf, as that infringes on the user's name space.
+ Don't have undefined behavior even if the translation
+ produced a string with the wrong number of "%s"s. */
+ char *yyp = yyresult;
+ int yyi = 0;
+ while ((*yyp = *yyf) != '\0')
+ {
+ if (*yyp == '%' && yyf[1] == 's' && yyi < yycount)
+ {
+ yyp += yytnamerr (yyp, yyarg[yyi++]);
+ yyf += 2;
+ }
+ else
+ {
+ yyp++;
+ yyf++;
+ }
+ }
+ }
+ return yysize;
+ }
}
#endif /* YYERROR_VERBOSE */
+
/*-----------------------------------------------.
| Release the memory associated to this symbol. |
@@ -1414,12 +1356,28 @@ yydestruct (yymsg, yytype, yyvaluep)
}
}
+/* Prevent warnings from -Wmissing-prototypes. */
+#ifdef YYPARSE_PARAM
+#if defined __STDC__ || defined __cplusplus
+int yyparse (void *YYPARSE_PARAM);
+#else
+int yyparse ();
+#endif
+#else /* ! YYPARSE_PARAM */
+#if defined __STDC__ || defined __cplusplus
+int yyparse (void);
+#else
+int yyparse ();
+#endif
+#endif /* ! YYPARSE_PARAM */
+
+
-/*----------.
-| yyparse. |
-`----------*/
+/*-------------------------.
+| yyparse or yypush_parse. |
+`-------------------------*/
#ifdef YYPARSE_PARAM
#if (defined __STDC__ || defined __C99__FUNC__ \
@@ -1460,7 +1418,7 @@ YYSTYPE yylval;
`yyss': related to states.
`yyvs': related to semantic values.
- Refer to the stacks through separate pointers, to allow yyoverflow
+ Refer to the stacks thru separate pointers, to allow yyoverflow
to reallocate them elsewhere. */
/* The state stack. */
@@ -1514,6 +1472,7 @@ YYSTYPE yylval;
The wasted elements are never initialized. */
yyssp = yyss;
yyvsp = yyvs;
+
goto yysetstate;
/*------------------------------------------------------------.
@@ -1605,7 +1564,7 @@ yybackup:
/* First try to decide what to do without reference to lookahead token. */
yyn = yypact[yystate];
- if (yypact_value_is_default (yyn))
+ if (yyn == YYPACT_NINF)
goto yydefault;
/* Not known => get a lookahead token if don't already have one. */
@@ -1636,8 +1595,8 @@ yybackup:
yyn = yytable[yyn];
if (yyn <= 0)
{
- if (yytable_value_is_error (yyn))
- goto yyerrlab;
+ if (yyn == 0 || yyn == YYTABLE_NINF)
+ goto yyerrlab;
yyn = -yyn;
goto yyreduce;
}
@@ -1935,17 +1894,6 @@ yyreduce:
default: break;
}
- /* User semantic actions sometimes alter yychar, and that requires
- that yytoken be updated with the new translation. We take the
- approach of translating immediately before every use of yytoken.
- One alternative is translating here after every semantic action,
- but that translation would be missed if the semantic action invokes
- YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or
- if it invokes YYBACKUP. In the case of YYABORT or YYACCEPT, an
- incorrect destructor might then be invoked immediately. In the
- case of YYERROR or YYBACKUP, subsequent parser actions might lead
- to an incorrect destructor call or verbose syntax error message
- before the lookahead is translated. */
YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
YYPOPSTACK (yylen);
@@ -1973,10 +1921,6 @@ yyreduce:
| yyerrlab -- here on detecting error |
`------------------------------------*/
yyerrlab:
- /* Make sure we have latest lookahead translation. See comments at
- user semantic actions for why this is necessary. */
- yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar);
-
/* If not already recovering from an error, report this error. */
if (!yyerrstatus)
{
@@ -1984,36 +1928,37 @@ yyerrlab:
#if ! YYERROR_VERBOSE
yyerror (YY_("syntax error"));
#else
-# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \
- yyssp, yytoken)
{
- char const *yymsgp = YY_("syntax error");
- int yysyntax_error_status;
- yysyntax_error_status = YYSYNTAX_ERROR;
- if (yysyntax_error_status == 0)
- yymsgp = yymsg;
- else if (yysyntax_error_status == 1)
- {
- if (yymsg != yymsgbuf)
- YYSTACK_FREE (yymsg);
- yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc);
- if (!yymsg)
- {
- yymsg = yymsgbuf;
- yymsg_alloc = sizeof yymsgbuf;
- yysyntax_error_status = 2;
- }
- else
- {
- yysyntax_error_status = YYSYNTAX_ERROR;
- yymsgp = yymsg;
- }
- }
- yyerror (yymsgp);
- if (yysyntax_error_status == 2)
- goto yyexhaustedlab;
+ YYSIZE_T yysize = yysyntax_error (0, yystate, yychar);
+ if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM)
+ {
+ YYSIZE_T yyalloc = 2 * yysize;
+ if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM))
+ yyalloc = YYSTACK_ALLOC_MAXIMUM;
+ if (yymsg != yymsgbuf)
+ YYSTACK_FREE (yymsg);
+ yymsg = (char *) YYSTACK_ALLOC (yyalloc);
+ if (yymsg)
+ yymsg_alloc = yyalloc;
+ else
+ {
+ yymsg = yymsgbuf;
+ yymsg_alloc = sizeof yymsgbuf;
+ }
+ }
+
+ if (0 < yysize && yysize <= yymsg_alloc)
+ {
+ (void) yysyntax_error (yymsg, yystate, yychar);
+ yyerror (yymsg);
+ }
+ else
+ {
+ yyerror (YY_("syntax error"));
+ if (yysize != 0)
+ goto yyexhaustedlab;
+ }
}
-# undef YYSYNTAX_ERROR
#endif
}
@@ -2072,7 +2017,7 @@ yyerrlab1:
for (;;)
{
yyn = yypact[yystate];
- if (!yypact_value_is_default (yyn))
+ if (yyn != YYPACT_NINF)
{
yyn += YYTERROR;
if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
@@ -2119,7 +2064,7 @@ yyabortlab:
yyresult = 1;
goto yyreturn;
-#if !defined yyoverflow || YYERROR_VERBOSE
+#if !defined(yyoverflow) || YYERROR_VERBOSE
/*-------------------------------------------------.
| yyexhaustedlab -- memory exhaustion comes here. |
`-------------------------------------------------*/
@@ -2131,13 +2076,8 @@ yyexhaustedlab:
yyreturn:
if (yychar != YYEMPTY)
- {
- /* Make sure we have latest lookahead translation. See comments at
- user semantic actions for why this is necessary. */
- yytoken = YYTRANSLATE (yychar);
- yydestruct ("Cleanup: discarding lookahead",
- yytoken, &yylval);
- }
+ yydestruct ("Cleanup: discarding lookahead",
+ yytoken, &yylval);
/* Do not reclaim the symbols of the rule which action triggered
this YYABORT or YYACCEPT. */
YYPOPSTACK (yylen);
diff --git a/Zend/zend_ini_parser.h b/Zend/zend_ini_parser.h
index 870799a6e..1e0c9a96d 100644
--- a/Zend/zend_ini_parser.h
+++ b/Zend/zend_ini_parser.h
@@ -1,8 +1,10 @@
-/* A Bison parser, made by GNU Bison 2.6.1. */
-/* Bison interface for Yacc-like parsers in C
+/* A Bison parser, made by GNU Bison 2.4.1. */
+
+/* Skeleton interface for Bison's Yacc-like parsers in C
- Copyright (C) 1984, 1989-1990, 2000-2012 Free Software Foundation, Inc.
+ Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+ Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -30,15 +32,6 @@
This special exception was added by the Free Software Foundation in
version 2.2 of Bison. */
-#ifndef INI_ZEND_ZEND_INI_PARSER_H
-# define INI_ZEND_ZEND_INI_PARSER_H
-/* Enabling traces. */
-#ifndef YYDEBUG
-# define YYDEBUG 0
-#endif
-#if YYDEBUG
-extern int ini_debug;
-#endif
/* Tokens. */
#ifndef YYTOKENTYPE
@@ -80,6 +73,7 @@ extern int ini_debug;
+
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
typedef int YYSTYPE;
# define YYSTYPE_IS_TRIVIAL 1
@@ -88,18 +82,5 @@ typedef int YYSTYPE;
#endif
-#ifdef YYPARSE_PARAM
-#if defined __STDC__ || defined __cplusplus
-int ini_parse (void *YYPARSE_PARAM);
-#else
-int ini_parse ();
-#endif
-#else /* ! YYPARSE_PARAM */
-#if defined __STDC__ || defined __cplusplus
-int ini_parse (void);
-#else
-int ini_parse ();
-#endif
-#endif /* ! YYPARSE_PARAM */
-#endif /* !INI_ZEND_ZEND_INI_PARSER_H */
+
diff --git a/Zend/zend_language_parser.c b/Zend/zend_language_parser.c
index e348dcb0f..ccb2be0a0 100644
--- a/Zend/zend_language_parser.c
+++ b/Zend/zend_language_parser.c
@@ -1,8 +1,10 @@
-/* A Bison parser, made by GNU Bison 2.6.1. */
-/* Bison implementation for Yacc-like parsers in C
+/* A Bison parser, made by GNU Bison 2.4.1. */
+
+/* Skeleton implementation for Bison's Yacc-like parsers in C
- Copyright (C) 1984, 1989-1990, 2000-2012 Free Software Foundation, Inc.
+ Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+ Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -44,7 +46,7 @@
#define YYBISON 1
/* Bison version. */
-#define YYBISON_VERSION "2.6.1"
+#define YYBISON_VERSION "2.4.1"
/* Skeleton name. */
#define YYSKELETON_NAME "yacc.c"
@@ -58,6 +60,8 @@
/* Pull parsers. */
#define YYPULL 1
+/* Using locations. */
+#define YYLSP_NEEDED 0
/* Substitute the variable and function names. */
#define yyparse zendparse
@@ -68,6 +72,7 @@
#define yydebug zenddebug
#define yynerrs zendnerrs
+
/* Copy the first part of user declarations. */
@@ -113,22 +118,14 @@ static YYSIZE_T zend_yytnamerr(char*, const char*);
#define YYERROR_VERBOSE
#define YYSTYPE znode
-#ifdef ZTS
-# define YYPARSE_PARAM tsrm_ls
-# define YYLEX_PARAM tsrm_ls
-#endif
-
-# ifndef YY_NULL
-# if defined __cplusplus && 201103L <= __cplusplus
-# define YY_NULL nullptr
-# else
-# define YY_NULL 0
-# endif
-# endif
+/* Enabling traces. */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
/* Enabling verbose error messages. */
#ifdef YYERROR_VERBOSE
@@ -138,18 +135,22 @@ static YYSIZE_T zend_yytnamerr(char*, const char*);
# define YYERROR_VERBOSE 0
#endif
-/* In a future release of Bison, this section will be replaced
- by #include "zend_language_parser.h". */
-#ifndef ZEND_ZEND_ZEND_LANGUAGE_PARSER_H
-# define ZEND_ZEND_ZEND_LANGUAGE_PARSER_H
-/* Enabling traces. */
-#ifndef YYDEBUG
-# define YYDEBUG 0
+/* Enabling the token table. */
+#ifndef YYTOKEN_TABLE
+# define YYTOKEN_TABLE 0
#endif
-#if YYDEBUG
-extern int zenddebug;
+
+/* "%code requires" blocks. */
+
+
+#ifdef ZTS
+# define YYPARSE_PARAM tsrm_ls
+# define YYLEX_PARAM tsrm_ls
#endif
+
+
+
/* Tokens. */
#ifndef YYTOKENTYPE
# define YYTOKENTYPE
@@ -422,6 +423,7 @@ extern int zenddebug;
+
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
typedef int YYSTYPE;
# define YYSTYPE_IS_TRIVIAL 1
@@ -430,22 +432,6 @@ typedef int YYSTYPE;
#endif
-#ifdef YYPARSE_PARAM
-#if defined __STDC__ || defined __cplusplus
-int zendparse (void *YYPARSE_PARAM);
-#else
-int zendparse ();
-#endif
-#else /* ! YYPARSE_PARAM */
-#if defined __STDC__ || defined __cplusplus
-int zendparse (void);
-#else
-int zendparse ();
-#endif
-#endif /* ! YYPARSE_PARAM */
-
-#endif /* !ZEND_ZEND_ZEND_LANGUAGE_PARSER_H */
-
/* Copy the second part of user declarations. */
@@ -498,7 +484,7 @@ typedef short int yytype_int16;
#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
#ifndef YY_
-# if defined YYENABLE_NLS && YYENABLE_NLS
+# if YYENABLE_NLS
# if ENABLE_NLS
# include <libintl.h> /* INFRINGES ON USER NAME SPACE */
# define YY_(msgid) dgettext ("bison-runtime", msgid)
@@ -551,12 +537,11 @@ YYID (yyi)
# define alloca _alloca
# else
# define YYSTACK_ALLOC alloca
-# if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \
+# if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
|| defined __cplusplus || defined _MSC_VER)
# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
- /* Use EXIT_SUCCESS as a witness for stdlib.h. */
-# ifndef EXIT_SUCCESS
-# define EXIT_SUCCESS 0
+# ifndef _STDLIB_H
+# define _STDLIB_H 1
# endif
# endif
# endif
@@ -579,24 +564,24 @@ YYID (yyi)
# ifndef YYSTACK_ALLOC_MAXIMUM
# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
# endif
-# if (defined __cplusplus && ! defined EXIT_SUCCESS \
+# if (defined __cplusplus && ! defined _STDLIB_H \
&& ! ((defined YYMALLOC || defined malloc) \
&& (defined YYFREE || defined free)))
# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
-# ifndef EXIT_SUCCESS
-# define EXIT_SUCCESS 0
+# ifndef _STDLIB_H
+# define _STDLIB_H 1
# endif
# endif
# ifndef YYMALLOC
# define YYMALLOC malloc
-# if ! defined malloc && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \
+# if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
|| defined __cplusplus || defined _MSC_VER)
void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
# endif
# endif
# ifndef YYFREE
# define YYFREE free
-# if ! defined free && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \
+# if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
|| defined __cplusplus || defined _MSC_VER)
void free (void *); /* INFRINGES ON USER NAME SPACE */
# endif
@@ -625,7 +610,23 @@ union yyalloc
((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \
+ YYSTACK_GAP_MAXIMUM)
-# define YYCOPY_NEEDED 1
+/* Copy COUNT objects from FROM to TO. The source and destination do
+ not overlap. */
+# ifndef YYCOPY
+# if defined __GNUC__ && 1 < __GNUC__
+# define YYCOPY(To, From, Count) \
+ __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
+# else
+# define YYCOPY(To, From, Count) \
+ do \
+ { \
+ YYSIZE_T yyi; \
+ for (yyi = 0; yyi < (Count); yyi++) \
+ (To)[yyi] = (From)[yyi]; \
+ } \
+ while (YYID (0))
+# endif
+# endif
/* Relocate STACK from its old location to the new one. The
local variables YYSIZE and YYSTACKSIZE give the old and new number of
@@ -645,26 +646,6 @@ union yyalloc
#endif
-#if defined YYCOPY_NEEDED && YYCOPY_NEEDED
-/* Copy COUNT objects from SRC to DST. The source and destination do
- not overlap. */
-# ifndef YYCOPY
-# if defined __GNUC__ && 1 < __GNUC__
-# define YYCOPY(Dst, Src, Count) \
- __builtin_memcpy (Dst, Src, (Count) * sizeof (*(Src)))
-# else
-# define YYCOPY(Dst, Src, Count) \
- do \
- { \
- YYSIZE_T yyi; \
- for (yyi = 0; yyi < (Count); yyi++) \
- (Dst)[yyi] = (Src)[yyi]; \
- } \
- while (YYID (0))
-# endif
-# endif
-#endif /* !YYCOPY_NEEDED */
-
/* YYFINAL -- State number of the termination state. */
#define YYFINAL 3
/* YYLAST -- Last index in YYTABLE. */
@@ -974,65 +955,65 @@ static const yytype_int16 yyrhs[] =
/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
static const yytype_uint16 yyrline[] =
{
- 0, 217, 217, 221, 221, 222, 226, 227, 231, 232,
- 233, 234, 235, 236, 236, 238, 238, 240, 241, 245,
- 246, 250, 251, 252, 253, 257, 258, 262, 262, 263,
- 268, 269, 270, 271, 276, 277, 281, 282, 282, 282,
- 283, 283, 283, 284, 284, 284, 285, 285, 285, 289,
- 291, 293, 286, 295, 295, 296, 297, 298, 299, 300,
- 301, 302, 303, 304, 305, 306, 307, 308, 309, 311,
- 312, 310, 315, 316, 314, 318, 318, 319, 320, 321,
- 320, 323, 324, 328, 329, 330, 331, 332, 329, 336,
- 337, 337, 341, 342, 346, 347, 351, 351, 351, 355,
- 356, 360, 364, 368, 372, 373, 378, 378, 385, 384,
- 391, 390, 400, 401, 402, 403, 407, 408, 412, 415,
- 417, 420, 422, 426, 427, 431, 432, 436, 437, 438,
- 438, 442, 443, 448, 449, 454, 455, 460, 461, 466,
- 467, 468, 469, 474, 475, 475, 476, 476, 481, 482,
- 487, 488, 493, 495, 495, 499, 501, 501, 505, 507,
- 511, 513, 518, 519, 524, 525, 526, 527, 528, 529,
- 530, 531, 536, 537, 538, 539, 544, 545, 546, 551,
- 552, 553, 554, 555, 556, 560, 561, 566, 567, 568,
- 573, 574, 575, 576, 582, 583, 588, 588, 589, 590,
- 591, 591, 597, 601, 602, 606, 607, 610, 612, 616,
- 617, 621, 622, 626, 630, 631, 635, 636, 640, 644,
- 645, 649, 650, 654, 655, 659, 660, 664, 665, 669,
- 670, 674, 675, 676, 677, 678, 679, 683, 684, 685,
- 686, 690, 691, 695, 696, 701, 702, 706, 706, 707,
- 711, 712, 716, 717, 721, 721, 722, 723, 727, 728,
- 728, 733, 733, 737, 737, 738, 739, 740, 740, 741,
- 742, 743, 744, 745, 746, 747, 748, 749, 750, 751,
- 752, 753, 754, 755, 756, 757, 757, 758, 758, 759,
- 759, 760, 760, 761, 762, 763, 764, 765, 766, 767,
- 768, 769, 770, 771, 772, 773, 774, 775, 776, 777,
- 778, 779, 780, 781, 782, 783, 784, 785, 786, 787,
- 788, 788, 789, 790, 789, 792, 792, 794, 795, 796,
- 797, 798, 799, 800, 801, 802, 803, 803, 804, 805,
- 806, 807, 808, 809, 810, 810, 813, 813, 819, 820,
- 821, 822, 826, 827, 828, 831, 832, 835, 838, 840,
- 844, 845, 846, 847, 851, 851, 853, 853, 855, 855,
- 857, 857, 859, 859, 861, 861, 863, 863, 865, 865,
- 870, 871, 872, 873, 877, 878, 879, 885, 886, 891,
- 892, 891, 894, 899, 900, 905, 909, 910, 911, 915,
- 916, 917, 922, 923, 928, 929, 930, 931, 932, 933,
- 934, 935, 936, 937, 938, 939, 944, 945, 946, 947,
- 948, 949, 950, 951, 952, 953, 954, 958, 962, 963,
- 964, 965, 966, 967, 968, 969, 970, 971, 976, 977,
- 980, 982, 986, 987, 988, 989, 993, 994, 998, 999,
- 1004, 1009, 1014, 1019, 1020, 1019, 1022, 1026, 1027, 1032,
- 1032, 1036, 1037, 1041, 1041, 1046, 1047, 1048, 1052, 1053,
- 1057, 1058, 1063, 1067, 1068, 1068, 1073, 1074, 1075, 1080,
- 1081, 1082, 1086, 1087, 1088, 1093, 1094, 1098, 1099, 1104,
- 1105, 1105, 1109, 1110, 1111, 1115, 1116, 1120, 1121, 1125,
- 1126, 1131, 1132, 1132, 1133, 1138, 1139, 1143, 1144, 1145,
- 1146, 1147, 1148, 1149, 1150, 1154, 1155, 1156, 1157, 1163,
- 1164, 1164, 1165, 1166, 1167, 1168, 1173, 1174, 1175, 1180,
- 1181, 1182, 1183, 1184, 1185, 1186, 1187, 1191, 1192, 1192,
- 1196, 1197, 1201, 1202, 1206, 1210
+ 0, 219, 219, 223, 223, 224, 228, 229, 233, 234,
+ 235, 236, 237, 238, 238, 240, 240, 242, 243, 247,
+ 248, 252, 253, 254, 255, 259, 260, 264, 264, 265,
+ 270, 271, 272, 273, 278, 279, 283, 284, 284, 284,
+ 285, 285, 285, 286, 286, 286, 287, 287, 287, 291,
+ 293, 295, 288, 297, 297, 298, 299, 300, 301, 302,
+ 303, 304, 305, 306, 307, 308, 309, 310, 311, 313,
+ 314, 312, 317, 318, 316, 320, 320, 321, 322, 323,
+ 322, 325, 326, 330, 331, 332, 333, 334, 331, 338,
+ 339, 339, 343, 344, 348, 349, 353, 353, 353, 357,
+ 358, 362, 366, 370, 374, 375, 380, 380, 387, 386,
+ 393, 392, 402, 403, 404, 405, 409, 410, 414, 417,
+ 419, 422, 424, 428, 429, 433, 434, 438, 439, 440,
+ 440, 444, 445, 450, 451, 456, 457, 462, 463, 468,
+ 469, 470, 471, 476, 477, 477, 478, 478, 483, 484,
+ 489, 490, 495, 497, 497, 501, 503, 503, 507, 509,
+ 513, 515, 520, 521, 526, 527, 528, 529, 530, 531,
+ 532, 533, 538, 539, 540, 541, 546, 547, 548, 553,
+ 554, 555, 556, 557, 558, 562, 563, 568, 569, 570,
+ 575, 576, 577, 578, 584, 585, 590, 590, 591, 592,
+ 593, 593, 599, 603, 604, 608, 609, 612, 614, 618,
+ 619, 623, 624, 628, 632, 633, 637, 638, 642, 646,
+ 647, 651, 652, 656, 657, 661, 662, 666, 667, 671,
+ 672, 676, 677, 678, 679, 680, 681, 685, 686, 687,
+ 688, 692, 693, 697, 698, 703, 704, 708, 708, 709,
+ 713, 714, 718, 719, 723, 723, 724, 725, 729, 730,
+ 730, 735, 735, 739, 739, 740, 741, 742, 742, 743,
+ 744, 745, 746, 747, 748, 749, 750, 751, 752, 753,
+ 754, 755, 756, 757, 758, 759, 759, 760, 760, 761,
+ 761, 762, 762, 763, 764, 765, 766, 767, 768, 769,
+ 770, 771, 772, 773, 774, 775, 776, 777, 778, 779,
+ 780, 781, 782, 783, 784, 785, 786, 787, 788, 789,
+ 790, 790, 791, 792, 791, 794, 794, 796, 797, 798,
+ 799, 800, 801, 802, 803, 804, 805, 805, 806, 807,
+ 808, 809, 810, 811, 812, 812, 815, 815, 821, 822,
+ 823, 824, 828, 829, 830, 833, 834, 837, 840, 842,
+ 846, 847, 848, 849, 853, 853, 855, 855, 857, 857,
+ 859, 859, 861, 861, 863, 863, 865, 865, 867, 867,
+ 872, 873, 874, 875, 879, 880, 881, 887, 888, 893,
+ 894, 893, 896, 901, 902, 907, 911, 912, 913, 917,
+ 918, 919, 924, 925, 930, 931, 932, 933, 934, 935,
+ 936, 937, 938, 939, 940, 941, 946, 947, 948, 949,
+ 950, 951, 952, 953, 954, 955, 956, 960, 964, 965,
+ 966, 967, 968, 969, 970, 971, 972, 973, 978, 979,
+ 982, 984, 988, 989, 990, 991, 995, 996, 1000, 1001,
+ 1006, 1011, 1016, 1021, 1022, 1021, 1024, 1028, 1029, 1034,
+ 1034, 1038, 1039, 1043, 1043, 1048, 1049, 1050, 1054, 1055,
+ 1059, 1060, 1065, 1069, 1070, 1070, 1075, 1076, 1077, 1082,
+ 1083, 1084, 1088, 1089, 1090, 1095, 1096, 1100, 1101, 1106,
+ 1107, 1107, 1111, 1112, 1113, 1117, 1118, 1122, 1123, 1127,
+ 1128, 1133, 1134, 1134, 1135, 1140, 1141, 1145, 1146, 1147,
+ 1148, 1149, 1150, 1151, 1152, 1156, 1157, 1158, 1159, 1165,
+ 1166, 1166, 1167, 1168, 1169, 1170, 1175, 1176, 1177, 1182,
+ 1183, 1184, 1185, 1186, 1187, 1188, 1189, 1193, 1194, 1194,
+ 1198, 1199, 1203, 1204, 1208, 1212
};
#endif
-#if YYDEBUG || YYERROR_VERBOSE || 0
+#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
First, the terminals, then, starting at YYNTOKENS, nonterminals. */
static const char *const yytname[] =
@@ -1157,7 +1138,7 @@ static const char *const yytname[] =
"non_empty_array_pair_list", "encaps_list", "encaps_var", "$@75",
"encaps_var_offset", "internal_functions_in_yacc", "isset_variables",
"$@76", "isset_variable", "class_constant", "static_class_name_scalar",
- "class_name_scalar", YY_NULL
+ "class_name_scalar", 0
};
#endif
@@ -1305,8 +1286,8 @@ static const yytype_uint8 yyr2[] =
1, 1, 3, 3, 3, 3
};
-/* YYDEFACT[STATE-NAME] -- Default reduction number in state STATE-NUM.
- Performed when YYTABLE doesn't specify something else to do. Zero
+/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
+ STATE-NUM when YYTABLE doesn't specify something else to do. Zero
means the default is an error. */
static const yytype_uint16 yydefact[] =
{
@@ -1577,7 +1558,8 @@ static const yytype_int16 yypgoto[] =
/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If
positive, shift that token. If negative, reduce the rule which
- number is the opposite. If YYTABLE_NINF, syntax error. */
+ number is the opposite. If zero, do what YYDEFACT says.
+ If YYTABLE_NINF, syntax error. */
#define YYTABLE_NINF -542
static const yytype_int16 yytable[] =
{
@@ -2096,12 +2078,6 @@ static const yytype_int16 yytable[] =
272, 273, 274, 275, 276, 0, 277
};
-#define yypact_value_is_default(yystate) \
- ((yystate) == (-770))
-
-#define yytable_value_is_error(yytable_value) \
- ((yytable_value) == (-542))
-
static const yytype_int16 yycheck[] =
{
24, 25, 4, 126, 28, 24, 25, 4, 11, 28,
@@ -2738,33 +2714,24 @@ static const yytype_uint16 yystos[] =
/* Like YYERROR except do call yyerror. This remains here temporarily
to ease the transition to the new meaning of YYERROR, for GCC.
- Once GCC version 2 has supplanted version 1, this can go. However,
- YYFAIL appears to be in use. Nevertheless, it is formally deprecated
- in Bison 2.4.2's NEWS entry, where a plan to phase it out is
- discussed. */
+ Once GCC version 2 has supplanted version 1, this can go. */
#define YYFAIL goto yyerrlab
-#if defined YYFAIL
- /* This is here to suppress warnings from the GCC cpp's
- -Wunused-macros. Normally we don't worry about that warning, but
- some users do, and we want to make it easy for users to remove
- YYFAIL uses, which will produce warnings from Bison 2.5. */
-#endif
#define YYRECOVERING() (!!yyerrstatus)
-#define YYBACKUP(Token, Value) \
-do \
- if (yychar == YYEMPTY) \
- { \
- yychar = (Token); \
- yylval = (Value); \
- YYPOPSTACK (yylen); \
- yystate = *yyssp; \
- goto yybackup; \
- } \
- else \
- { \
+#define YYBACKUP(Token, Value) \
+do \
+ if (yychar == YYEMPTY && yylen == 1) \
+ { \
+ yychar = (Token); \
+ yylval = (Value); \
+ yytoken = YYTRANSLATE (yychar); \
+ YYPOPSTACK (1); \
+ goto yybackup; \
+ } \
+ else \
+ { \
yyerror (YY_("syntax error: cannot back up")); \
YYERROR; \
} \
@@ -2774,38 +2741,46 @@ while (YYID (0))
#define YYTERROR 1
#define YYERRCODE 256
+
/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
If N is 0, then set CURRENT to the empty location which ends
the previous symbol: RHS[0] (always defined). */
+#define YYRHSLOC(Rhs, K) ((Rhs)[K])
#ifndef YYLLOC_DEFAULT
-# define YYLLOC_DEFAULT(Current, Rhs, N) \
- do \
- if (YYID (N)) \
- { \
- (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \
- (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \
- (Current).last_line = YYRHSLOC (Rhs, N).last_line; \
- (Current).last_column = YYRHSLOC (Rhs, N).last_column; \
- } \
- else \
- { \
- (Current).first_line = (Current).last_line = \
- YYRHSLOC (Rhs, 0).last_line; \
- (Current).first_column = (Current).last_column = \
- YYRHSLOC (Rhs, 0).last_column; \
- } \
+# define YYLLOC_DEFAULT(Current, Rhs, N) \
+ do \
+ if (YYID (N)) \
+ { \
+ (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \
+ (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \
+ (Current).last_line = YYRHSLOC (Rhs, N).last_line; \
+ (Current).last_column = YYRHSLOC (Rhs, N).last_column; \
+ } \
+ else \
+ { \
+ (Current).first_line = (Current).last_line = \
+ YYRHSLOC (Rhs, 0).last_line; \
+ (Current).first_column = (Current).last_column = \
+ YYRHSLOC (Rhs, 0).last_column; \
+ } \
while (YYID (0))
#endif
-#define YYRHSLOC(Rhs, K) ((Rhs)[K])
-
-
-/* This macro is provided for backward compatibility. */
+/* YY_LOCATION_PRINT -- Print the location on the stream.
+ This macro was not mandated originally: define only if we know
+ we won't break user code: when these are the locations we know. */
#ifndef YY_LOCATION_PRINT
-# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
+# if YYLTYPE_IS_TRIVIAL
+# define YY_LOCATION_PRINT(File, Loc) \
+ fprintf (File, "%d.%d-%d.%d", \
+ (Loc).first_line, (Loc).first_column, \
+ (Loc).last_line, (Loc).last_column)
+# else
+# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
+# endif
#endif
@@ -2860,8 +2835,6 @@ yy_symbol_value_print (yyoutput, yytype, yyvaluep)
YYSTYPE const * const yyvaluep;
#endif
{
- FILE *yyo = yyoutput;
- YYUSE (yyo);
if (!yyvaluep)
return;
# ifdef YYPRINT
@@ -2999,6 +2972,7 @@ int yydebug;
# define YYMAXDEPTH 10000
#endif
+
#if YYERROR_VERBOSE
@@ -3101,142 +3075,115 @@ yytnamerr (char *yyres, const char *yystr)
}
# endif
-/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message
- about the unexpected token YYTOKEN for the state stack whose top is
- YYSSP.
-
- Return 0 if *YYMSG was successfully written. Return 1 if *YYMSG is
- not large enough to hold the message. In that case, also set
- *YYMSG_ALLOC to the required number of bytes. Return 2 if the
- required number of bytes is too large to store. */
-static int
-yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
- yytype_int16 *yyssp, int yytoken)
+/* Copy into YYRESULT an error message about the unexpected token
+ YYCHAR while in state YYSTATE. Return the number of bytes copied,
+ including the terminating null byte. If YYRESULT is null, do not
+ copy anything; just return the number of bytes that would be
+ copied. As a special case, return 0 if an ordinary "syntax error"
+ message will do. Return YYSIZE_MAXIMUM if overflow occurs during
+ size calculation. */
+static YYSIZE_T
+yysyntax_error (char *yyresult, int yystate, int yychar)
{
- YYSIZE_T yysize0 = yytnamerr (YY_NULL, yytname[yytoken]);
- YYSIZE_T yysize = yysize0;
- YYSIZE_T yysize1;
- enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
- /* Internationalized format string. */
- const char *yyformat = YY_NULL;
- /* Arguments of yyformat. */
- char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
- /* Number of reported tokens (one for the "unexpected", one per
- "expected"). */
- int yycount = 0;
-
- /* There are many possibilities here to consider:
- - Assume YYFAIL is not used. It's too flawed to consider. See
- <http://lists.gnu.org/archive/html/bison-patches/2009-12/msg00024.html>
- for details. YYERROR is fine as it does not invoke this
- function.
- - If this state is a consistent state with a default action, then
- the only way this function was invoked is if the default action
- is an error action. In that case, don't check for expected
- tokens because there are none.
- - The only way there can be no lookahead present (in yychar) is if
- this state is a consistent state with a default action. Thus,
- detecting the absence of a lookahead is sufficient to determine
- that there is no unexpected or expected token to report. In that
- case, just report a simple "syntax error".
- - Don't assume there isn't a lookahead just because this state is a
- consistent state with a default action. There might have been a
- previous inconsistent state, consistent state with a non-default
- action, or user semantic action that manipulated yychar.
- - Of course, the expected token list depends on states to have
- correct lookahead information, and it depends on the parser not
- to perform extra reductions after fetching a lookahead from the
- scanner and before detecting a syntax error. Thus, state merging
- (from LALR or IELR) and default reductions corrupt the expected
- token list. However, the list is correct for canonical LR with
- one exception: it will still contain any token that will not be
- accepted due to an error action in a later state.
- */
- if (yytoken != YYEMPTY)
- {
- int yyn = yypact[*yyssp];
- yyarg[yycount++] = yytname[yytoken];
- if (!yypact_value_is_default (yyn))
- {
- /* Start YYX at -YYN if negative to avoid negative indexes in
- YYCHECK. In other words, skip the first -YYN actions for
- this state because they are default actions. */
- int yyxbegin = yyn < 0 ? -yyn : 0;
- /* Stay within bounds of both yycheck and yytname. */
- int yychecklim = YYLAST - yyn + 1;
- int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
- int yyx;
-
- for (yyx = yyxbegin; yyx < yyxend; ++yyx)
- if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR
- && !yytable_value_is_error (yytable[yyx + yyn]))
- {
- if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
- {
- yycount = 1;
- yysize = yysize0;
- break;
- }
- yyarg[yycount++] = yytname[yyx];
- yysize1 = yysize + yytnamerr (YY_NULL, yytname[yyx]);
- if (! (yysize <= yysize1
- && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
- return 2;
- yysize = yysize1;
- }
- }
- }
+ int yyn = yypact[yystate];
- switch (yycount)
+ if (! (YYPACT_NINF < yyn && yyn <= YYLAST))
+ return 0;
+ else
{
-# define YYCASE_(N, S) \
- case N: \
- yyformat = S; \
- break
- YYCASE_(0, YY_("syntax error"));
- YYCASE_(1, YY_("syntax error, unexpected %s"));
- YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s"));
- YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s"));
- YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s"));
- YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"));
-# undef YYCASE_
- }
+ int yytype = YYTRANSLATE (yychar);
+ YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]);
+ YYSIZE_T yysize = yysize0;
+ YYSIZE_T yysize1;
+ int yysize_overflow = 0;
+ enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
+ char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
+ int yyx;
+
+# if 0
+ /* This is so xgettext sees the translatable formats that are
+ constructed on the fly. */
+ YY_("syntax error, unexpected %s");
+ YY_("syntax error, unexpected %s, expecting %s");
+ YY_("syntax error, unexpected %s, expecting %s or %s");
+ YY_("syntax error, unexpected %s, expecting %s or %s or %s");
+ YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s");
+# endif
+ char *yyfmt;
+ char const *yyf;
+ static char const yyunexpected[] = "syntax error, unexpected %s";
+ static char const yyexpecting[] = ", expecting %s";
+ static char const yyor[] = " or %s";
+ char yyformat[sizeof yyunexpected
+ + sizeof yyexpecting - 1
+ + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2)
+ * (sizeof yyor - 1))];
+ char const *yyprefix = yyexpecting;
+
+ /* Start YYX at -YYN if negative to avoid negative indexes in
+ YYCHECK. */
+ int yyxbegin = yyn < 0 ? -yyn : 0;
+
+ /* Stay within bounds of both yycheck and yytname. */
+ int yychecklim = YYLAST - yyn + 1;
+ int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
+ int yycount = 1;
+
+ yyarg[0] = yytname[yytype];
+ yyfmt = yystpcpy (yyformat, yyunexpected);
+
+ for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+ if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
+ {
+ if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
+ {
+ yycount = 1;
+ yysize = yysize0;
+ yyformat[sizeof yyunexpected - 1] = '\0';
+ break;
+ }
+ yyarg[yycount++] = yytname[yyx];
+ yysize1 = yysize + yytnamerr (0, yytname[yyx]);
+ yysize_overflow |= (yysize1 < yysize);
+ yysize = yysize1;
+ yyfmt = yystpcpy (yyfmt, yyprefix);
+ yyprefix = yyor;
+ }
- yysize1 = yysize + yystrlen (yyformat);
- if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
- return 2;
- yysize = yysize1;
+ yyf = YY_(yyformat);
+ yysize1 = yysize + yystrlen (yyf);
+ yysize_overflow |= (yysize1 < yysize);
+ yysize = yysize1;
- if (*yymsg_alloc < yysize)
- {
- *yymsg_alloc = 2 * yysize;
- if (! (yysize <= *yymsg_alloc
- && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM))
- *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM;
- return 1;
- }
+ if (yysize_overflow)
+ return YYSIZE_MAXIMUM;
- /* Avoid sprintf, as that infringes on the user's name space.
- Don't have undefined behavior even if the translation
- produced a string with the wrong number of "%s"s. */
- {
- char *yyp = *yymsg;
- int yyi = 0;
- while ((*yyp = *yyformat) != '\0')
- if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount)
- {
- yyp += yytnamerr (yyp, yyarg[yyi++]);
- yyformat += 2;
- }
- else
- {
- yyp++;
- yyformat++;
- }
- }
- return 0;
+ if (yyresult)
+ {
+ /* Avoid sprintf, as that infringes on the user's name space.
+ Don't have undefined behavior even if the translation
+ produced a string with the wrong number of "%s"s. */
+ char *yyp = yyresult;
+ int yyi = 0;
+ while ((*yyp = *yyf) != '\0')
+ {
+ if (*yyp == '%' && yyf[1] == 's' && yyi < yycount)
+ {
+ yyp += yytnamerr (yyp, yyarg[yyi++]);
+ yyf += 2;
+ }
+ else
+ {
+ yyp++;
+ yyf++;
+ }
+ }
+ }
+ return yysize;
+ }
}
#endif /* YYERROR_VERBOSE */
+
/*-----------------------------------------------.
| Release the memory associated to this symbol. |
@@ -3269,12 +3216,28 @@ yydestruct (yymsg, yytype, yyvaluep)
}
}
+/* Prevent warnings from -Wmissing-prototypes. */
+#ifdef YYPARSE_PARAM
+#if defined __STDC__ || defined __cplusplus
+int yyparse (void *YYPARSE_PARAM);
+#else
+int yyparse ();
+#endif
+#else /* ! YYPARSE_PARAM */
+#if defined __STDC__ || defined __cplusplus
+int yyparse (void);
+#else
+int yyparse ();
+#endif
+#endif /* ! YYPARSE_PARAM */
+
-/*----------.
-| yyparse. |
-`----------*/
+
+/*-------------------------.
+| yyparse or yypush_parse. |
+`-------------------------*/
#ifdef YYPARSE_PARAM
#if (defined __STDC__ || defined __C99__FUNC__ \
@@ -3315,7 +3278,7 @@ YYSTYPE yylval;
`yyss': related to states.
`yyvs': related to semantic values.
- Refer to the stacks through separate pointers, to allow yyoverflow
+ Refer to the stacks thru separate pointers, to allow yyoverflow
to reallocate them elsewhere. */
/* The state stack. */
@@ -3369,6 +3332,7 @@ YYSTYPE yylval;
The wasted elements are never initialized. */
yyssp = yyss;
yyvsp = yyvs;
+
goto yysetstate;
/*------------------------------------------------------------.
@@ -3460,7 +3424,7 @@ yybackup:
/* First try to decide what to do without reference to lookahead token. */
yyn = yypact[yystate];
- if (yypact_value_is_default (yyn))
+ if (yyn == YYPACT_NINF)
goto yydefault;
/* Not known => get a lookahead token if don't already have one. */
@@ -3491,8 +3455,8 @@ yybackup:
yyn = yytable[yyn];
if (yyn <= 0)
{
- if (yytable_value_is_error (yyn))
- goto yyerrlab;
+ if (yyn == 0 || yyn == YYTABLE_NINF)
+ goto yyerrlab;
yyn = -yyn;
goto yyreduce;
}
@@ -5976,17 +5940,6 @@ yyreduce:
default: break;
}
- /* User semantic actions sometimes alter yychar, and that requires
- that yytoken be updated with the new translation. We take the
- approach of translating immediately before every use of yytoken.
- One alternative is translating here after every semantic action,
- but that translation would be missed if the semantic action invokes
- YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or
- if it invokes YYBACKUP. In the case of YYABORT or YYACCEPT, an
- incorrect destructor might then be invoked immediately. In the
- case of YYERROR or YYBACKUP, subsequent parser actions might lead
- to an incorrect destructor call or verbose syntax error message
- before the lookahead is translated. */
YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
YYPOPSTACK (yylen);
@@ -6014,10 +5967,6 @@ yyreduce:
| yyerrlab -- here on detecting error |
`------------------------------------*/
yyerrlab:
- /* Make sure we have latest lookahead translation. See comments at
- user semantic actions for why this is necessary. */
- yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar);
-
/* If not already recovering from an error, report this error. */
if (!yyerrstatus)
{
@@ -6025,36 +5974,37 @@ yyerrlab:
#if ! YYERROR_VERBOSE
yyerror (YY_("syntax error"));
#else
-# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \
- yyssp, yytoken)
{
- char const *yymsgp = YY_("syntax error");
- int yysyntax_error_status;
- yysyntax_error_status = YYSYNTAX_ERROR;
- if (yysyntax_error_status == 0)
- yymsgp = yymsg;
- else if (yysyntax_error_status == 1)
- {
- if (yymsg != yymsgbuf)
- YYSTACK_FREE (yymsg);
- yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc);
- if (!yymsg)
- {
- yymsg = yymsgbuf;
- yymsg_alloc = sizeof yymsgbuf;
- yysyntax_error_status = 2;
- }
- else
- {
- yysyntax_error_status = YYSYNTAX_ERROR;
- yymsgp = yymsg;
- }
- }
- yyerror (yymsgp);
- if (yysyntax_error_status == 2)
- goto yyexhaustedlab;
+ YYSIZE_T yysize = yysyntax_error (0, yystate, yychar);
+ if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM)
+ {
+ YYSIZE_T yyalloc = 2 * yysize;
+ if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM))
+ yyalloc = YYSTACK_ALLOC_MAXIMUM;
+ if (yymsg != yymsgbuf)
+ YYSTACK_FREE (yymsg);
+ yymsg = (char *) YYSTACK_ALLOC (yyalloc);
+ if (yymsg)
+ yymsg_alloc = yyalloc;
+ else
+ {
+ yymsg = yymsgbuf;
+ yymsg_alloc = sizeof yymsgbuf;
+ }
+ }
+
+ if (0 < yysize && yysize <= yymsg_alloc)
+ {
+ (void) yysyntax_error (yymsg, yystate, yychar);
+ yyerror (yymsg);
+ }
+ else
+ {
+ yyerror (YY_("syntax error"));
+ if (yysize != 0)
+ goto yyexhaustedlab;
+ }
}
-# undef YYSYNTAX_ERROR
#endif
}
@@ -6113,7 +6063,7 @@ yyerrlab1:
for (;;)
{
yyn = yypact[yystate];
- if (!yypact_value_is_default (yyn))
+ if (yyn != YYPACT_NINF)
{
yyn += YYTERROR;
if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
@@ -6160,7 +6110,7 @@ yyabortlab:
yyresult = 1;
goto yyreturn;
-#if !defined yyoverflow || YYERROR_VERBOSE
+#if !defined(yyoverflow) || YYERROR_VERBOSE
/*-------------------------------------------------.
| yyexhaustedlab -- memory exhaustion comes here. |
`-------------------------------------------------*/
@@ -6172,13 +6122,8 @@ yyexhaustedlab:
yyreturn:
if (yychar != YYEMPTY)
- {
- /* Make sure we have latest lookahead translation. See comments at
- user semantic actions for why this is necessary. */
- yytoken = YYTRANSLATE (yychar);
- yydestruct ("Cleanup: discarding lookahead",
- yytoken, &yylval);
- }
+ yydestruct ("Cleanup: discarding lookahead",
+ yytoken, &yylval);
/* Do not reclaim the symbols of the rule which action triggered
this YYABORT or YYACCEPT. */
YYPOPSTACK (yylen);
diff --git a/Zend/zend_language_parser.h b/Zend/zend_language_parser.h
index 074c954b8..a64121e5c 100644
--- a/Zend/zend_language_parser.h
+++ b/Zend/zend_language_parser.h
@@ -1,8 +1,10 @@
-/* A Bison parser, made by GNU Bison 2.6.1. */
-/* Bison interface for Yacc-like parsers in C
+/* A Bison parser, made by GNU Bison 2.4.1. */
+
+/* Skeleton interface for Bison's Yacc-like parsers in C
- Copyright (C) 1984, 1989-1990, 2000-2012 Free Software Foundation, Inc.
+ Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+ Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -30,16 +32,17 @@
This special exception was added by the Free Software Foundation in
version 2.2 of Bison. */
-#ifndef ZEND_ZEND_ZEND_LANGUAGE_PARSER_H
-# define ZEND_ZEND_ZEND_LANGUAGE_PARSER_H
-/* Enabling traces. */
-#ifndef YYDEBUG
-# define YYDEBUG 0
-#endif
-#if YYDEBUG
-extern int zenddebug;
+/* "%code requires" blocks. */
+
+
+#ifdef ZTS
+# define YYPARSE_PARAM tsrm_ls
+# define YYLEX_PARAM tsrm_ls
#endif
+
+
+
/* Tokens. */
#ifndef YYTOKENTYPE
# define YYTOKENTYPE
@@ -312,6 +315,7 @@ extern int zenddebug;
+
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
typedef int YYSTYPE;
# define YYSTYPE_IS_TRIVIAL 1
@@ -320,18 +324,5 @@ typedef int YYSTYPE;
#endif
-#ifdef YYPARSE_PARAM
-#if defined __STDC__ || defined __cplusplus
-int zendparse (void *YYPARSE_PARAM);
-#else
-int zendparse ();
-#endif
-#else /* ! YYPARSE_PARAM */
-#if defined __STDC__ || defined __cplusplus
-int zendparse (void);
-#else
-int zendparse ();
-#endif
-#endif /* ! YYPARSE_PARAM */
-#endif /* !ZEND_ZEND_ZEND_LANGUAGE_PARSER_H */
+
diff --git a/Zend/zend_language_parser.y b/Zend/zend_language_parser.y
index ccbc9b174..6a9a24a87 100644
--- a/Zend/zend_language_parser.y
+++ b/Zend/zend_language_parser.y
@@ -41,17 +41,19 @@ static YYSIZE_T zend_yytnamerr(char*, const char*);
#define YYERROR_VERBOSE
#define YYSTYPE znode
-#ifdef ZTS
-# define YYPARSE_PARAM tsrm_ls
-# define YYLEX_PARAM tsrm_ls
-#endif
-
%}
%pure_parser
%expect 3
+%code requires {
+#ifdef ZTS
+# define YYPARSE_PARAM tsrm_ls
+# define YYLEX_PARAM tsrm_ls
+#endif
+}
+
%token END 0 "end of file"
%left T_INCLUDE T_INCLUDE_ONCE T_EVAL T_REQUIRE T_REQUIRE_ONCE
%token T_INCLUDE "include (T_INCLUDE)"
diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h
index 206a2333f..7371d0e44 100644
--- a/Zend/zend_vm_def.h
+++ b/Zend/zend_vm_def.h
@@ -1967,13 +1967,6 @@ ZEND_VM_HELPER(zend_do_fcall_common_helper, ANY, ANY)
LOAD_OPLINE();
if (fbc->type == ZEND_INTERNAL_FUNCTION) {
- temp_variable *ret = &EX_T(opline->result.var);
-
- MAKE_STD_ZVAL(ret->var.ptr);
- ZVAL_NULL(ret->var.ptr);
- ret->var.ptr_ptr = &ret->var.ptr;
- ret->var.fcall_returned_reference = (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0;
-
if (fbc->common.arg_info) {
zend_uint i=0;
zval **p = (zval**)EX(function_state).arguments;
@@ -1985,15 +1978,24 @@ ZEND_VM_HELPER(zend_do_fcall_common_helper, ANY, ANY)
}
}
- if (!zend_execute_internal) {
- /* saves one function call if zend_execute_internal is not used */
- fbc->internal_function.handler(opline->extended_value, ret->var.ptr, (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) ? &ret->var.ptr : NULL, EX(object), RETURN_VALUE_USED(opline) TSRMLS_CC);
- } else {
- zend_execute_internal(execute_data, NULL, RETURN_VALUE_USED(opline) TSRMLS_CC);
- }
+ if (EXPECTED(EG(exception) == NULL)) {
+ temp_variable *ret = &EX_T(opline->result.var);
- if (!RETURN_VALUE_USED(opline)) {
- zval_ptr_dtor(&ret->var.ptr);
+ MAKE_STD_ZVAL(ret->var.ptr);
+ ZVAL_NULL(ret->var.ptr);
+ ret->var.ptr_ptr = &ret->var.ptr;
+ ret->var.fcall_returned_reference = (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0;
+
+ if (!zend_execute_internal) {
+ /* saves one function call if zend_execute_internal is not used */
+ fbc->internal_function.handler(opline->extended_value, ret->var.ptr, (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) ? &ret->var.ptr : NULL, EX(object), RETURN_VALUE_USED(opline) TSRMLS_CC);
+ } else {
+ zend_execute_internal(execute_data, NULL, RETURN_VALUE_USED(opline) TSRMLS_CC);
+ }
+
+ if (!RETURN_VALUE_USED(opline)) {
+ zval_ptr_dtor(&ret->var.ptr);
+ }
}
} else if (fbc->type == ZEND_USER_FUNCTION) {
EX(original_return_value) = EG(return_value_ptr_ptr);
@@ -3260,7 +3262,7 @@ ZEND_VM_HANDLER(64, ZEND_RECV_INIT, ANY, CONST)
zend_verify_arg_type((zend_function *) EG(active_op_array), arg_num, assignment_value, opline->extended_value TSRMLS_CC);
var_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->result.var TSRMLS_CC);
- Z_DELREF_PP(var_ptr);
+ zval_ptr_dtor(var_ptr);
*var_ptr = assignment_value;
CHECK_EXCEPTION();
diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h
index d65dfc41f..8703dec22 100644
--- a/Zend/zend_vm_execute.h
+++ b/Zend/zend_vm_execute.h
@@ -519,13 +519,6 @@ static int ZEND_FASTCALL zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_AR
LOAD_OPLINE();
if (fbc->type == ZEND_INTERNAL_FUNCTION) {
- temp_variable *ret = &EX_T(opline->result.var);
-
- MAKE_STD_ZVAL(ret->var.ptr);
- ZVAL_NULL(ret->var.ptr);
- ret->var.ptr_ptr = &ret->var.ptr;
- ret->var.fcall_returned_reference = (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0;
-
if (fbc->common.arg_info) {
zend_uint i=0;
zval **p = (zval**)EX(function_state).arguments;
@@ -537,15 +530,24 @@ static int ZEND_FASTCALL zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_AR
}
}
- if (!zend_execute_internal) {
- /* saves one function call if zend_execute_internal is not used */
- fbc->internal_function.handler(opline->extended_value, ret->var.ptr, (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) ? &ret->var.ptr : NULL, EX(object), RETURN_VALUE_USED(opline) TSRMLS_CC);
- } else {
- zend_execute_internal(execute_data, NULL, RETURN_VALUE_USED(opline) TSRMLS_CC);
- }
+ if (EXPECTED(EG(exception) == NULL)) {
+ temp_variable *ret = &EX_T(opline->result.var);
- if (!RETURN_VALUE_USED(opline)) {
- zval_ptr_dtor(&ret->var.ptr);
+ MAKE_STD_ZVAL(ret->var.ptr);
+ ZVAL_NULL(ret->var.ptr);
+ ret->var.ptr_ptr = &ret->var.ptr;
+ ret->var.fcall_returned_reference = (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0;
+
+ if (!zend_execute_internal) {
+ /* saves one function call if zend_execute_internal is not used */
+ fbc->internal_function.handler(opline->extended_value, ret->var.ptr, (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) ? &ret->var.ptr : NULL, EX(object), RETURN_VALUE_USED(opline) TSRMLS_CC);
+ } else {
+ zend_execute_internal(execute_data, NULL, RETURN_VALUE_USED(opline) TSRMLS_CC);
+ }
+
+ if (!RETURN_VALUE_USED(opline)) {
+ zval_ptr_dtor(&ret->var.ptr);
+ }
}
} else if (fbc->type == ZEND_USER_FUNCTION) {
EX(original_return_value) = EG(return_value_ptr_ptr);
@@ -1404,7 +1406,7 @@ static int ZEND_FASTCALL ZEND_RECV_INIT_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_
zend_verify_arg_type((zend_function *) EG(active_op_array), arg_num, assignment_value, opline->extended_value TSRMLS_CC);
var_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->result.var TSRMLS_CC);
- Z_DELREF_PP(var_ptr);
+ zval_ptr_dtor(var_ptr);
*var_ptr = assignment_value;
CHECK_EXCEPTION();
diff --git a/configure b/configure
index cc19b8a3f..cebcf69c7 100755
--- a/configure
+++ b/configure
@@ -3686,7 +3686,7 @@ ac_config_headers="$ac_config_headers main/php_config.h"
PHP_MAJOR_VERSION=5
PHP_MINOR_VERSION=5
PHP_RELEASE_VERSION=0
-PHP_EXTRA_VERSION="beta1"
+PHP_EXTRA_VERSION="beta2"
PHP_VERSION="$PHP_MAJOR_VERSION.$PHP_MINOR_VERSION.$PHP_RELEASE_VERSION$PHP_EXTRA_VERSION"
PHP_VERSION_ID=`expr $PHP_MAJOR_VERSION \* 10000 + $PHP_MINOR_VERSION \* 100 + $PHP_RELEASE_VERSION`
@@ -37496,7 +37496,7 @@ if test "$PHP_GD" = "yes"; then
libgd/gdcache.c libgd/gdkanji.c libgd/wbmp.c libgd/gd_wbmp.c libgd/gdhelpers.c \
libgd/gd_topal.c libgd/gd_gif_in.c libgd/xbm.c libgd/gd_gif_out.c libgd/gd_security.c \
libgd/gd_filter.c libgd/gd_pixelate.c libgd/gd_arc.c libgd/gd_rotate.c libgd/gd_color.c \
- libgd/gd_transform.c libgd/gd_crop.c"
+ libgd/gd_transform.c libgd/gd_crop.c libgd/gd_interpolation.c libgd/gd_matrix.c"
for ac_func in fabsf floorf
do :
@@ -67648,6 +67648,57 @@ fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $msg" >&5
$as_echo "$msg" >&6; }
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for known struct flock definition" >&5
+$as_echo_n "checking for known struct flock definition... " >&6; }
+ if test "$cross_compiling" = yes; then :
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot run test program while cross compiling
+See \`config.log' for more details" "$LINENO" 5; }
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+#include <fcntl.h>
+#include <stdlib.h>
+
+#ifndef ZEND_WIN32
+extern int lock_file;
+
+# if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || (defined(__APPLE__) && defined(__MACH__)/* Darwin */) || defined(__OpenBSD__) || defined(__NetBSD__)
+# define FLOCK_STRUCTURE(name, type, whence, start, len) \
+ struct flock name = {start, len, -1, type, whence}
+# elif defined(__svr4__)
+# define FLOCK_STRUCTURE(name, type, whence, start, len) \
+ struct flock name = {type, whence, start, len}
+# elif defined(__linux__) || defined(__hpux)
+# define FLOCK_STRUCTURE(name, type, whence, start, len) \
+ struct flock name = {type, whence, start, len, 0}
+# elif defined(_AIX)
+# if defined(_LARGE_FILES) || defined(__64BIT__)
+# define FLOCK_STRUCTURE(name, type, whence, start, len) \
+ struct flock name = {type, whence, 0, 0, 0, start, len }
+# else
+# define FLOCK_STRUCTURE(name, type, whence, start, len) \
+ struct flock name = {type, whence, start, len}
+# endif
+# else
+# error "Don't know how to define struct flock"
+# endif
+#endif
+int main() { return 0; }
+
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+
+else
+ as_fn_error $? "Don't know how to define struct flock on this system, set --enable-opcache=no" "$LINENO" 5
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+ conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+
ext_builddir=ext/opcache
ext_srcdir=$abs_srcdir/ext/opcache
@@ -105653,7 +105704,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<EOF
-#line 105656 "configure"
+#line 105707 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -107565,7 +107616,7 @@ ia64-*-hpux*)
;;
*-*-irix6*)
# Find out which ABI we are using.
- echo '#line 107568 "configure"' > conftest.$ac_ext
+ echo '#line 107619 "configure"' > conftest.$ac_ext
if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
(eval $ac_compile) 2>&5
ac_status=$?
@@ -108957,7 +109008,7 @@ else
LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym"
cat > conftest.$ac_ext <<EOF
-#line 108960 "configure"
+#line 109011 "configure"
#include "confdefs.h"
int main() {
; return 0; }
@@ -109115,11 +109166,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"configure:109118: $lt_compile\"" >&5)
+ (eval echo "\"configure:109169: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "configure:109122: \$? = $ac_status" >&5
+ echo "configure:109173: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output.
@@ -109413,11 +109464,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"configure:109416: $lt_compile\"" >&5)
+ (eval echo "\"configure:109467: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "configure:109420: \$? = $ac_status" >&5
+ echo "configure:109471: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output.
@@ -109517,11 +109568,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"configure:109520: $lt_compile\"" >&5)
+ (eval echo "\"configure:109571: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
- echo "configure:109524: \$? = $ac_status" >&5
+ echo "configure:109575: \$? = $ac_status" >&5
if (exit $ac_status) && test -s out/conftest2.$ac_objext
then
# The compiler can only warn and ignore the option if not recognized
@@ -109981,7 +110032,7 @@ _LT_EOF
# Determine the default libpath from the value encoded in an empty executable.
cat > conftest.$ac_ext <<EOF
-#line 109984 "configure"
+#line 110035 "configure"
#include "confdefs.h"
int main() {
; return 0; }
@@ -110023,7 +110074,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
# Determine the default libpath from the value encoded in an empty executable.
cat > conftest.$ac_ext <<EOF
-#line 110026 "configure"
+#line 110077 "configure"
#include "confdefs.h"
int main() {
; return 0; }
@@ -111548,7 +111599,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<EOF
-#line 111551 "configure"
+#line 111602 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -111648,7 +111699,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<EOF
-#line 111651 "configure"
+#line 111702 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -112713,7 +112764,7 @@ case $host_os in
# Determine the default libpath from the value encoded in an empty executable.
cat > conftest.$ac_ext <<EOF
-#line 112716 "configure"
+#line 112767 "configure"
#include "confdefs.h"
int main() {
; return 0; }
@@ -112756,7 +112807,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
# Determine the default libpath from the value encoded in an empty executable.
cat > conftest.$ac_ext <<EOF
-#line 112759 "configure"
+#line 112810 "configure"
#include "confdefs.h"
int main() {
; return 0; }
@@ -114008,11 +114059,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"configure:114011: $lt_compile\"" >&5)
+ (eval echo "\"configure:114062: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "configure:114015: \$? = $ac_status" >&5
+ echo "configure:114066: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output.
@@ -114112,11 +114163,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"configure:114115: $lt_compile\"" >&5)
+ (eval echo "\"configure:114166: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
- echo "configure:114119: \$? = $ac_status" >&5
+ echo "configure:114170: \$? = $ac_status" >&5
if (exit $ac_status) && test -s out/conftest2.$ac_objext
then
# The compiler can only warn and ignore the option if not recognized
diff --git a/configure.in b/configure.in
index cc49903f8..490f9d574 100644
--- a/configure.in
+++ b/configure.in
@@ -120,7 +120,7 @@ int zend_sprintf(char *buffer, const char *format, ...);
PHP_MAJOR_VERSION=5
PHP_MINOR_VERSION=5
PHP_RELEASE_VERSION=0
-PHP_EXTRA_VERSION="beta1"
+PHP_EXTRA_VERSION="beta2"
PHP_VERSION="$PHP_MAJOR_VERSION.$PHP_MINOR_VERSION.$PHP_RELEASE_VERSION$PHP_EXTRA_VERSION"
PHP_VERSION_ID=`expr [$]PHP_MAJOR_VERSION \* 10000 + [$]PHP_MINOR_VERSION \* 100 + [$]PHP_RELEASE_VERSION`
diff --git a/ext/gd/config.m4 b/ext/gd/config.m4
index 2f7170586..e6cc03683 100644
--- a/ext/gd/config.m4
+++ b/ext/gd/config.m4
@@ -298,7 +298,7 @@ if test "$PHP_GD" = "yes"; then
libgd/gdcache.c libgd/gdkanji.c libgd/wbmp.c libgd/gd_wbmp.c libgd/gdhelpers.c \
libgd/gd_topal.c libgd/gd_gif_in.c libgd/xbm.c libgd/gd_gif_out.c libgd/gd_security.c \
libgd/gd_filter.c libgd/gd_pixelate.c libgd/gd_arc.c libgd/gd_rotate.c libgd/gd_color.c \
- libgd/gd_transform.c libgd/gd_crop.c"
+ libgd/gd_transform.c libgd/gd_crop.c libgd/gd_interpolation.c libgd/gd_matrix.c"
dnl check for fabsf and floorf which are available since C99
AC_CHECK_FUNCS(fabsf floorf)
diff --git a/ext/gd/config.w32 b/ext/gd/config.w32
index b25a0e2d9..e6fbc49ea 100644
--- a/ext/gd/config.w32
+++ b/ext/gd/config.w32
@@ -48,7 +48,7 @@ if (PHP_GD != "no") {
gd_io_file.c gd_io_ss.c gd_jpeg.c gdkanji.c gd_png.c gd_ss.c \
gdtables.c gd_topal.c gd_wbmp.c gdxpm.c wbmp.c xbm.c gd_security.c gd_transform.c \
gd_filter.c gd_pixelate.c gd_arc.c gd_rotate.c gd_color.c webpimg.c gd_webp.c \
- gd_crop.c", "gd");
+ gd_crop.c gd_interpolation.c gd_matrix.c", "gd");
AC_DEFINE('HAVE_LIBGD', 1, 'GD support');
ADD_FLAG("CFLAGS_GD", " \
/D HAVE_GD_DYNAMIC_CTX_EX=1 \
@@ -84,7 +84,7 @@ if (PHP_GD != "no") {
");
PHP_INSTALL_HEADERS("", "ext/gd ext/gd/libgd" );
- } else {
+ } else {
WARNING("gd not enabled; libraries and headers not found");
}
}
diff --git a/ext/gd/gd.c b/ext/gd/gd.c
index be9501e55..d929e7f84 100644
--- a/ext/gd/gd.c
+++ b/ext/gd/gd.c
@@ -58,7 +58,6 @@
# include "libgd/gd_compat.h"
#endif
-
static int le_gd, le_gd_font;
#if HAVE_LIBT1
#include <t1lib.h>
@@ -195,6 +194,10 @@ ZEND_BEGIN_ARG_INFO(arginfo_imagetruecolortopalette, 0)
ZEND_ARG_INFO(0, colorsWanted)
ZEND_END_ARG_INFO()
+ZEND_BEGIN_ARG_INFO(arginfo_imagepalettetotruecolor, 0)
+ ZEND_ARG_INFO(0, im)
+ZEND_END_ARG_INFO()
+
ZEND_BEGIN_ARG_INFO(arginfo_imagecolormatch, 0)
ZEND_ARG_INFO(0, im1)
ZEND_ARG_INFO(0, im2)
@@ -902,6 +905,35 @@ ZEND_BEGIN_ARG_INFO(arginfo_imagecropauto, 0)
ZEND_ARG_INFO(0, threshold)
ZEND_ARG_INFO(0, color)
ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_imagescale, 0)
+ ZEND_ARG_INFO(0, im)
+ ZEND_ARG_INFO(0, new_width)
+ ZEND_ARG_INFO(0, new_height)
+ ZEND_ARG_INFO(0, mode)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_imageaffine, 0)
+ ZEND_ARG_INFO(0, im)
+ ZEND_ARG_INFO(0, affine)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_imageaffinematrixget, 0)
+ ZEND_ARG_INFO(0, im)
+ ZEND_ARG_INFO(0, matrox)
+ ZEND_ARG_INFO(0, options)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_imageaffinematrixconcat, 0)
+ ZEND_ARG_INFO(0, m1)
+ ZEND_ARG_INFO(0, m2)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_imagesetinterpolation, 0)
+ ZEND_ARG_INFO(0, im)
+ ZEND_ARG_INFO(0, method)
+ZEND_END_ARG_INFO()
+
#endif
/* }}} */
@@ -941,6 +973,7 @@ const zend_function_entry gd_functions[] = {
PHP_FE(imagecreatetruecolor, arginfo_imagecreatetruecolor)
PHP_FE(imageistruecolor, arginfo_imageistruecolor)
PHP_FE(imagetruecolortopalette, arginfo_imagetruecolortopalette)
+ PHP_FE(imagepalettetotruecolor, arginfo_imagepalettetotruecolor)
PHP_FE(imagesetthickness, arginfo_imagesetthickness)
PHP_FE(imagefilledarc, arginfo_imagefilledarc)
PHP_FE(imagefilledellipse, arginfo_imagefilledellipse)
@@ -964,6 +997,11 @@ const zend_function_entry gd_functions[] = {
PHP_FE(imageflip, arginfo_imageflip)
PHP_FE(imagecrop, arginfo_imagecrop)
PHP_FE(imagecropauto, arginfo_imagecropauto)
+ PHP_FE(imagescale, arginfo_imagescale)
+ PHP_FE(imageaffine, arginfo_imageaffine)
+ PHP_FE(imageaffinematrixconcat, arginfo_imageaffinematrixconcat)
+ PHP_FE(imageaffinematrixget, arginfo_imageaffinematrixget)
+ PHP_FE(imagesetinterpolation, arginfo_imagesetinterpolation)
#endif
#if HAVE_GD_IMAGESETTILE
@@ -1218,13 +1256,43 @@ PHP_MINIT_FUNCTION(gd)
REGISTER_LONG_CONSTANT("IMG_FLIP_HORIZONTAL", GD_FLIP_HORINZONTAL, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("IMG_FLIP_VERTICAL", GD_FLIP_VERTICAL, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("IMG_FLIP_BOTH", GD_FLIP_BOTH, CONST_CS | CONST_PERSISTENT);
-
+
REGISTER_LONG_CONSTANT("IMG_CROP_DEFAULT", GD_CROP_DEFAULT, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("IMG_CROP_TRANSPARENT", GD_CROP_TRANSPARENT, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("IMG_CROP_BLACK", GD_CROP_BLACK, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("IMG_CROP_WHITE", GD_CROP_WHITE, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("IMG_CROP_SIDES", GD_CROP_SIDES, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("IMG_CROP_THRESHOLD", GD_CROP_THRESHOLD, CONST_CS | CONST_PERSISTENT);
+
+
+ REGISTER_LONG_CONSTANT("IMG_BELL", GD_BILINEAR_FIXED, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("IMG_BESSEL", GD_BESSEL, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("IMG_BILINEAR_FIXED", GD_BILINEAR_FIXED, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("IMG_BICUBIC", GD_BICUBIC, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("IMG_BICUBIC_FIXED", GD_BICUBIC_FIXED, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("IMG_BLACKMAN", GD_BLACKMAN, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("IMG_BOX", GD_BOX, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("IMG_BSPLINE", GD_BSPLINE, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("IMG_CATMULLROM", GD_CATMULLROM, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("IMG_GAUSSIAN", GD_GAUSSIAN, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("IMG_GENERALIZED_CUBIC", GD_GENERALIZED_CUBIC, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("IMG_HERMITE", GD_HERMITE, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("IMG_HAMMING", GD_HAMMING, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("IMG_HANNING", GD_HANNING, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("IMG_MITCHELL", GD_MITCHELL, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("IMG_POWER", GD_POWER, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("IMG_QUADRATIC", GD_QUADRATIC, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("IMG_SINC", GD_SINC, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("IMG_NEAREST_NEIGHBOUR", GD_NEAREST_NEIGHBOUR, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("IMG_WEIGHTED4", GD_WEIGHTED4, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("IMG_TRIANGLE", GD_TRIANGLE, CONST_CS | CONST_PERSISTENT);
+
+ REGISTER_LONG_CONSTANT("IMG_AFFINE_TRANSLATE", GD_AFFINE_TRANSLATE, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("IMG_AFFINE_SCALE", GD_AFFINE_SCALE, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("IMG_AFFINE_ROTATE", GD_AFFINE_ROTATE, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("IMG_AFFINE_SHEAR_HORIZONTAL", GD_AFFINE_SHEAR_HORIZONTAL, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("IMG_AFFINE_SHEAR_VERTICAL", GD_AFFINE_SHEAR_VERTICAL, CONST_CS | CONST_PERSISTENT);
+
#else
REGISTER_LONG_CONSTANT("GD_BUNDLED", 0, CONST_CS | CONST_PERSISTENT);
#endif
@@ -1371,6 +1439,9 @@ PHP_MINFO_FUNCTION(gd)
#if defined(USE_GD_JISX0208) && defined(HAVE_GD_BUNDLED)
php_info_print_table_row(2, "JIS-mapped Japanese Font Support", "enabled");
#endif
+#ifdef HAVE_GD_WEBP
+ php_info_print_table_row(2, "WebP Support", "enabled");
+#endif
php_info_print_table_end();
DISPLAY_INI_ENTRIES();
}
@@ -1730,6 +1801,29 @@ PHP_FUNCTION(imagetruecolortopalette)
}
/* }}} */
+
+
+/* {{{ proto void imagetruecolortopalette(resource im, bool ditherFlag, int colorsWanted)
+ Convert a true colour image to a palette based image with a number of colours, optionally using dithering. */
+PHP_FUNCTION(imagepalettetotruecolor)
+{
+ zval *IM;
+ gdImagePtr im;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &IM) == FAILURE) {
+ return;
+ }
+
+ ZEND_FETCH_RESOURCE(im, gdImagePtr, &IM, -1, "Image", le_gd);
+
+ if (gdImagePaletteToTrueColor(im) == 0) {
+ RETURN_FALSE;
+ }
+
+ RETURN_TRUE;
+}
+/* }}} */
+
/* {{{ proto bool imagecolormatch(resource im1, resource im2)
Makes the colors of the palette version of an image more closely match the true color version */
PHP_FUNCTION(imagecolormatch)
@@ -2172,7 +2266,7 @@ PHP_FUNCTION(imagerotate)
ZEND_FETCH_RESOURCE(im_src, gdImagePtr, &SIM, -1, "Image", le_gd);
- im_dst = gdImageRotate(im_src, degrees, color, ignoretransparent);
+ im_dst = gdImageRotateInterpolated(im_src, (float)degrees, color);
if (im_dst != NULL) {
ZEND_REGISTER_RESOURCE(return_value, im_dst, le_gd);
@@ -5127,11 +5221,11 @@ PHP_FUNCTION(imageflip)
switch (mode) {
case GD_FLIP_VERTICAL:
- gdImageFlipHorizontal(im);
+ gdImageFlipVertical(im);
break;
case GD_FLIP_HORINZONTAL:
- gdImageFlipVertical(im);
+ gdImageFlipHorizontal(im);
break;
case GD_FLIP_BOTH:
@@ -5252,6 +5346,327 @@ PHP_FUNCTION(imagecropauto)
}
}
/* }}} */
+
+/* {{{ proto resource imagescale(resource im, new_width[, new_height[, method]])
+ Crop an image using the given coordinates and size, x, y, width and height. */
+PHP_FUNCTION(imagescale)
+{
+ zval *IM;
+ long mode = -1;
+ long color = -1;
+ double threshold = 0.5f;
+ gdImagePtr im;
+ gdImagePtr im_scaled;
+ int new_width, new_height = -1;
+ gdInterpolationMethod method = GD_BILINEAR_FIXED;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl|ll", &IM, &new_width, &new_height, &method) == FAILURE) {
+ return;
+ }
+
+ ZEND_FETCH_RESOURCE(im, gdImagePtr, &IM, -1, "Image", le_gd);
+ im_scaled = gdImageScale(im, new_width, new_height);
+ goto finish;
+ switch (method) {
+ case GD_NEAREST_NEIGHBOUR:
+ im_scaled = gdImageScaleNearestNeighbour(im, new_width, new_height);
+ break;
+
+ case GD_BILINEAR_FIXED:
+ im_scaled = gdImageScaleBilinear(im, new_width, new_height);
+ break;
+
+ case GD_BICUBIC:
+ im_scaled = gdImageScaleBicubicFixed(im, new_width, new_height);
+ break;
+
+ case GD_BICUBIC_FIXED:
+ im_scaled = gdImageScaleBicubicFixed(im, new_width, new_height);
+ break;
+
+ default:
+ im_scaled = gdImageScaleTwoPass(im, im->sx, im->sy, new_width, new_height);
+ break;
+
+ }
+finish:
+ if (im_scaled == NULL) {
+ RETURN_FALSE;
+ } else {
+ ZEND_REGISTER_RESOURCE(return_value, im_scaled, le_gd);
+ }
+}
+/* }}} */
+
+/* {{{ proto resource imageaffine(resource dst, resource src, array affine, array clip)
+ Return an image containing the affine tramsformed src image, using an optional clipping area */
+PHP_FUNCTION(imageaffine)
+{
+ zval *IM;
+ long mode = -1;
+ long color = -1;
+ double threshold = 0.5f;
+ gdImagePtr src;
+ gdImagePtr dst;
+ gdRect rect;
+ gdRectPtr pRect = NULL;
+ zval *z_rect = NULL;
+ zval *z_affine;
+ zval **tmp;
+ double affine[6];
+ int i, nelems;
+ zval **zval_affine_elem = NULL;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ra|a", &IM, &z_affine, &z_rect) == FAILURE) {
+ return;
+ }
+
+ ZEND_FETCH_RESOURCE(src, gdImagePtr, &IM, -1, "Image", le_gd);
+
+ if ((nelems = zend_hash_num_elements(Z_ARRVAL_P(z_affine))) != 6) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Affine array must have six elements");
+ RETURN_FALSE;
+ }
+
+ for (i = 0; i < nelems; i++) {
+ if (zend_hash_index_find(Z_ARRVAL_P(z_affine), i, (void **) &zval_affine_elem) == SUCCESS) {
+ switch (Z_TYPE_PP(zval_affine_elem)) {
+ case IS_LONG:
+ affine[i] = Z_LVAL_PP(zval_affine_elem);
+ break;
+ case IS_DOUBLE:
+ affine[i] = Z_DVAL_PP(zval_affine_elem);
+ break;
+ case IS_STRING:
+ convert_to_double_ex(zval_affine_elem);
+ affine[i] = Z_DVAL_PP(zval_affine_elem);
+ break;
+ default:
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid type for element %i", i);
+ RETURN_FALSE;
+ }
+ }
+ }
+
+ if (z_rect != NULL) {
+ if (zend_hash_find(HASH_OF(z_rect), "x", sizeof("x"), (void **)&tmp) != FAILURE) {
+ convert_to_long_ex(tmp);
+ rect.x = Z_LVAL_PP(tmp);
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Missing x position");
+ RETURN_FALSE;
+ }
+
+ if (zend_hash_find(HASH_OF(z_rect), "y", sizeof("x"), (void **)&tmp) != FAILURE) {
+ convert_to_long_ex(tmp);
+ rect.y = Z_LVAL_PP(tmp);
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Missing y position");
+ RETURN_FALSE;
+ }
+
+ if (zend_hash_find(HASH_OF(z_rect), "width", sizeof("width"), (void **)&tmp) != FAILURE) {
+ convert_to_long_ex(tmp);
+ rect.width = Z_LVAL_PP(tmp);
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Missing width");
+ RETURN_FALSE;
+ }
+
+ if (zend_hash_find(HASH_OF(z_rect), "height", sizeof("height"), (void **)&tmp) != FAILURE) {
+ convert_to_long_ex(tmp);
+ rect.height = Z_LVAL_PP(tmp);
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Missing height");
+ RETURN_FALSE;
+ }
+ pRect = &rect;
+ } else {
+ rect.x = -1;
+ rect.y = -1;
+ rect.width = gdImageSX(src);
+ rect.height = gdImageSY(src);
+ pRect = NULL;
+ }
+
+
+ //int gdTransformAffineGetImage(gdImagePtr *dst, const gdImagePtr src, gdRectPtr src_area, const double affine[6]);
+ if (gdTransformAffineGetImage(&dst, src, pRect, affine) != GD_TRUE) {
+ RETURN_FALSE;
+ }
+
+ if (dst == NULL) {
+ RETURN_FALSE;
+ } else {
+ ZEND_REGISTER_RESOURCE(return_value, dst, le_gd);
+ }
+}
+/* }}} */
+
+/* {{{ proto array imageaffinematrixget(type[, options])
+ Return an image containing the affine tramsformed src image, using an optional clipping area */
+PHP_FUNCTION(imageaffinematrixget)
+{
+ double affine[6];
+ gdAffineStandardMatrix type;
+ zval *options;
+ zval **tmp;
+ int res, i;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|z", &type, &options) == FAILURE) {
+ return;
+ }
+
+ switch(type) {
+ case GD_AFFINE_TRANSLATE:
+ case GD_AFFINE_SCALE: {
+ double x, y;
+ if (Z_TYPE_P(options) != IS_ARRAY) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Array expected as options");
+ }
+ if (zend_hash_find(HASH_OF(options), "x", sizeof("x"), (void **)&tmp) != FAILURE) {
+ convert_to_double_ex(tmp);
+ x = Z_DVAL_PP(tmp);
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Missing x position");
+ RETURN_FALSE;
+ }
+
+ if (zend_hash_find(HASH_OF(options), "y", sizeof("y"), (void **)&tmp) != FAILURE) {
+ convert_to_double_ex(tmp);
+ y = Z_DVAL_PP(tmp);
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Missing y position");
+ RETURN_FALSE;
+ }
+
+ if (type == GD_AFFINE_TRANSLATE) {
+ res = gdAffineTranslate(affine, x, y);
+ } else {
+ res = gdAffineScale(affine, x, y);
+ }
+ break;
+ }
+
+ case GD_AFFINE_ROTATE:
+ case GD_AFFINE_SHEAR_HORIZONTAL:
+ case GD_AFFINE_SHEAR_VERTICAL: {
+ double angle;
+
+ convert_to_double_ex(&options);
+ angle = Z_DVAL_P(options);
+
+ if (type == GD_AFFINE_SHEAR_HORIZONTAL) {
+ res = gdAffineShearHorizontal(affine, angle);
+ } else if (type == GD_AFFINE_SHEAR_VERTICAL) {
+ res = gdAffineShearVertical(affine, angle);
+ } else {
+ res = gdAffineRotate(affine, angle);
+ }
+ break;
+ }
+
+ default:
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid type for element %i", type);
+ RETURN_FALSE;
+ }
+
+ array_init(return_value);
+ for (i = 0; i < 6; i++) {
+ add_index_double(return_value, i, affine[i]);
+ }
+}
+
+
+/* {{{ proto array imageaffineconcat(array m1, array m2)
+ Concat two matrices (as in doing many ops in one go) */
+PHP_FUNCTION(imageaffinematrixconcat)
+{
+ double m1[6];
+ double m2[6];
+ double mr[6];
+
+ zval **tmp;
+ zval *z_m1;
+ zval *z_m2;
+ int i, nelems;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "aa", &z_m1, &z_m2) == FAILURE) {
+ return;
+ }
+
+ if (((nelems = zend_hash_num_elements(Z_ARRVAL_P(z_m1))) != 6) || (nelems = zend_hash_num_elements(Z_ARRVAL_P(z_m2))) != 6) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Affine arrays must have six elements");
+ RETURN_FALSE;
+ }
+
+ for (i = 0; i < 6; i++) {
+ if (zend_hash_index_find(Z_ARRVAL_P(z_m1), i, (void **) &tmp) == SUCCESS) {
+ switch (Z_TYPE_PP(tmp)) {
+ case IS_LONG:
+ m1[i] = Z_LVAL_PP(tmp);
+ break;
+ case IS_DOUBLE:
+ m1[i] = Z_DVAL_PP(tmp);
+ break;
+ case IS_STRING:
+ convert_to_double_ex(tmp);
+ m1[i] = Z_DVAL_PP(tmp);
+ break;
+ default:
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid type for element %i", i);
+ RETURN_FALSE;
+ }
+ }
+ if (zend_hash_index_find(Z_ARRVAL_P(z_m2), i, (void **) &tmp) == SUCCESS) {
+ switch (Z_TYPE_PP(tmp)) {
+ case IS_LONG:
+ m2[i] = Z_LVAL_PP(tmp);
+ break;
+ case IS_DOUBLE:
+ m2[i] = Z_DVAL_PP(tmp);
+ break;
+ case IS_STRING:
+ convert_to_double_ex(tmp);
+ m2[i] = Z_DVAL_PP(tmp);
+ break;
+ default:
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid type for element %i", i);
+ RETURN_FALSE;
+ }
+ }
+ }
+
+ if (gdAffineConcat (mr, m1, m2) != GD_TRUE) {
+ RETURN_FALSE;
+ }
+
+ array_init(return_value);
+ for (i = 0; i < 6; i++) {
+ add_index_double(return_value, i, mr[i]);
+ }
+}
+
+/* {{{ proto resource imagesetinterpolation(resource im, [, method]])
+ Set the default interpolation method, passing -1 or 0 sets it to the libgd default (bilinear). */
+PHP_FUNCTION(imagesetinterpolation)
+{
+ zval *IM;
+ gdImagePtr im;
+ gdInterpolationMethod method = GD_BILINEAR_FIXED;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &IM, &method) == FAILURE) {
+ return;
+ }
+
+ ZEND_FETCH_RESOURCE(im, gdImagePtr, &IM, -1, "Image", le_gd);
+
+ if (method == -1) {
+ method = GD_BILINEAR_FIXED;
+ }
+ RETURN_BOOL(gdImageSetInterpolationMethod(im, (gdInterpolationMethod) method));
+}
+/* }}} */
#endif
diff --git a/ext/gd/libgd/gd.c b/ext/gd/libgd/gd.c
index fa75898dd..cb45c0e9c 100644
--- a/ext/gd/libgd/gd.c
+++ b/ext/gd/libgd/gd.c
@@ -168,6 +168,8 @@ gdImagePtr gdImageCreate (int sx, int sy)
im->cy1 = 0;
im->cx2 = im->sx - 1;
im->cy2 = im->sy - 1;
+ im->interpolation = NULL;
+ im->interpolation_id = GD_BILINEAR_FIXED;
return im;
}
@@ -183,7 +185,7 @@ gdImagePtr gdImageCreateTrueColor (int sx, int sy)
if (overflow2(sizeof(unsigned char *), sy)) {
return NULL;
}
-
+
if (overflow2(sizeof(int), sx)) {
return NULL;
}
@@ -221,6 +223,8 @@ gdImagePtr gdImageCreateTrueColor (int sx, int sy)
im->cy1 = 0;
im->cx2 = im->sx - 1;
im->cy2 = im->sy - 1;
+ im->interpolation = NULL;
+ im->interpolation_id = GD_BILINEAR_FIXED;
return im;
}
@@ -3009,3 +3013,70 @@ void gdImageGetClip (gdImagePtr im, int *x1P, int *y1P, int *x2P, int *y2P)
*y2P = im->cy2;
}
+/* convert a palette image to true color */
+int gdImagePaletteToTrueColor(gdImagePtr src)
+{
+ unsigned int y;
+ unsigned char alloc_y = 0, alloc_aa = 0;
+ unsigned int yy;
+
+ if (src == NULL) {
+ return 0;
+ }
+
+ if (src->trueColor == 1) {
+ return 1;
+ } else {
+ unsigned int x;
+ const unsigned int sy = gdImageSY(src);
+ const unsigned int sx = gdImageSX(src);
+
+ src->tpixels = (int **) gdMalloc(sizeof(int *) * sy);
+ if (src->tpixels == NULL) {
+ return 0;
+ }
+
+ for (y = 0; y < sy; y++) {
+ const unsigned char *src_row = src->pixels[y];
+ int * dst_row;
+
+ /* no need to calloc it, we overwrite all pxl anyway */
+ src->tpixels[y] = (int *) gdMalloc(sx * sizeof(int));
+ if (src->tpixels[y] == NULL) {
+ goto clean_on_error;
+ }
+
+ dst_row = src->tpixels[y];
+ for (x = 0; x < sx; x++) {
+ const unsigned char c = *(src_row + x);
+ if (c == src->transparent) {
+ *(dst_row + x) = gdTrueColorAlpha(0, 0, 0, 127);;
+ } else {
+ *(dst_row + x) = gdTrueColorAlpha(src->red[c], src->green[c], src->blue[c], src->alpha[c]);
+ }
+ }
+ }
+ }
+
+ /* free old palette buffer */
+ for (yy = y - 1; yy >= yy - 1; yy--) {
+ gdFree(src->pixels[yy]);
+ }
+ gdFree(src->pixels);
+ src->trueColor = 1;
+ src->pixels = NULL;
+ src->alphaBlendingFlag = 0;
+ src->saveAlphaFlag = 1;
+ return 1;
+
+clean_on_error:
+ if (y > 0) {
+
+ for (yy = y; yy >= yy - 1; y--) {
+ gdFree(src->tpixels[y]);
+ }
+ gdFree(src->tpixels);
+ }
+ return 0;
+}
+
diff --git a/ext/gd/libgd/gd.h b/ext/gd/libgd/gd.h
index 8d9df2a49..0bd8ad336 100644
--- a/ext/gd/libgd/gd.h
+++ b/ext/gd/libgd/gd.h
@@ -93,6 +93,10 @@ void php_gd_error(const char *format, ...);
#define gdEffectNormal 2
#define gdEffectOverlay 3
+#define GD_TRUE 1
+#define GD_FALSE 0
+
+#define GD_EPSILON 1e-6
/* This function accepts truecolor pixel values only. The
source color is composited with the destination color
@@ -101,6 +105,67 @@ void php_gd_error(const char *format, ...);
int gdAlphaBlend(int dest, int src);
+/**
+ * Group: Transform
+ *
+ * Constants: gdInterpolationMethod
+
+ * GD_BELL - Bell
+ * GD_BESSEL - Bessel
+ * GD_BILINEAR_FIXED - fixed point bilinear
+ * GD_BICUBIC - Bicubic
+ * GD_BICUBIC_FIXED - fixed point bicubic integer
+ * GD_BLACKMAN - Blackman
+ * GD_BOX - Box
+ * GD_BSPLINE - BSpline
+ * GD_CATMULLROM - Catmullrom
+ * GD_GAUSSIAN - Gaussian
+ * GD_GENERALIZED_CUBIC - Generalized cubic
+ * GD_HERMITE - Hermite
+ * GD_HAMMING - Hamming
+ * GD_HANNING - Hannig
+ * GD_MITCHELL - Mitchell
+ * GD_NEAREST_NEIGHBOUR - Nearest neighbour interpolation
+ * GD_POWER - Power
+ * GD_QUADRATIC - Quadratic
+ * GD_SINC - Sinc
+ * GD_TRIANGLE - Triangle
+ * GD_WEIGHTED4 - 4 pixels weighted bilinear interpolation
+ *
+ * See also:
+ * <gdSetInterpolationMethod>
+ **/
+typedef enum {
+ GD_DEFAULT = 0,
+ GD_BELL,
+ GD_BESSEL,
+ GD_BILINEAR_FIXED,
+ GD_BICUBIC,
+ GD_BICUBIC_FIXED,
+ GD_BLACKMAN,
+ GD_BOX,
+ GD_BSPLINE,
+ GD_CATMULLROM,
+ GD_GAUSSIAN,
+ GD_GENERALIZED_CUBIC,
+ GD_HERMITE,
+ GD_HAMMING,
+ GD_HANNING,
+ GD_MITCHELL,
+ GD_NEAREST_NEIGHBOUR,
+ GD_POWER,
+ GD_QUADRATIC,
+ GD_SINC,
+ GD_TRIANGLE,
+ GD_WEIGHTED4,
+ GD_METHOD_COUNT = 21
+} gdInterpolationMethod;
+
+/* define struct with name and func ptr and add it to gdImageStruct gdInterpolationMethod interpolation; */
+
+/* Interpolation function ptr */
+typedef double (* interpolation_method )(double);
+
typedef struct gdImageStruct {
/* Palette-based image pixels */
unsigned char ** pixels;
@@ -188,10 +253,35 @@ typedef struct gdImageStruct {
int cy1;
int cx2;
int cy2;
+ gdInterpolationMethod interpolation_id;
+ interpolation_method interpolation;
} gdImage;
typedef gdImage * gdImagePtr;
+/* Point type for use in polygon drawing. */
+
+/**
+ * Group: Types
+ *
+ * typedef: gdPointF
+ * Defines a point in a 2D coordinate system using floating point
+ * values.
+ * x - Floating point position (increase from left to right)
+ * y - Floating point Row position (increase from top to bottom)
+ *
+ * typedef: gdPointFPtr
+ * Pointer to a <gdPointF>
+ *
+ * See also:
+ * <gdImageCreate>, <gdImageCreateTrueColor>,
+ **/
+typedef struct
+{
+ double x, y;
+}
+gdPointF, *gdPointFPtr;
+
typedef struct {
/* # of characters in font */
int nchars;
@@ -469,7 +559,7 @@ void gdImageColorDeallocate(gdImagePtr im, int color);
gdImagePtr gdImageCreatePaletteFromTrueColor (gdImagePtr im, int ditherFlag, int colorsWanted);
void gdImageTrueColorToPalette(gdImagePtr im, int ditherFlag, int colorsWanted);
-
+int gdImagePaletteToTrueColor(gdImagePtr src);
/* An attempt at getting the results of gdImageTrueColorToPalette
to look a bit more like the original (im1 is the original
@@ -600,6 +690,7 @@ gdImagePtr gdImageRotate180(gdImagePtr src, int ignoretransparent);
gdImagePtr gdImageRotate270(gdImagePtr src, int ignoretransparent);
gdImagePtr gdImageRotate45(gdImagePtr src, double dAngle, int clrBack, int ignoretransparent);
gdImagePtr gdImageRotate (gdImagePtr src, double dAngle, int clrBack, int ignoretransparent);
+gdImagePtr gdImageRotateInterpolated(const gdImagePtr src, const float angle, int bgcolor);
void gdImageSetBrush(gdImagePtr im, gdImagePtr brush);
void gdImageSetTile(gdImagePtr im, gdImagePtr tile);
@@ -741,6 +832,54 @@ gdImagePtr gdImageCrop(gdImagePtr src, const gdRectPtr crop);
gdImagePtr gdImageCropAuto(gdImagePtr im, const unsigned int mode);
gdImagePtr gdImageCropThreshold(gdImagePtr im, const unsigned int color, const float threshold);
+int gdImageSetInterpolationMethod(gdImagePtr im, gdInterpolationMethod id);
+
+gdImagePtr gdImageScaleBilinear(gdImagePtr im, const unsigned int new_width, const unsigned int new_height);
+gdImagePtr gdImageScaleBicubic(gdImagePtr src_img, const unsigned int new_width, const unsigned int new_height);
+gdImagePtr gdImageScaleBicubicFixed(gdImagePtr src, const unsigned int width, const unsigned int height);
+gdImagePtr gdImageScaleNearestNeighbour(gdImagePtr im, const unsigned int width, const unsigned int height);
+gdImagePtr gdImageScaleTwoPass(const gdImagePtr pOrigImage, const unsigned int uOrigWidth, const unsigned int uOrigHeight, const unsigned int uNewWidth, const unsigned int uNewHeight);
+gdImagePtr gdImageScale(const gdImagePtr src, const unsigned int new_width, const unsigned int new_height);
+
+gdImagePtr gdImageRotateNearestNeighbour(gdImagePtr src, const float degrees, const int bgColor);
+gdImagePtr gdImageRotateBilinear(gdImagePtr src, const float degrees, const int bgColor);
+gdImagePtr gdImageRotateBicubicFixed(gdImagePtr src, const float degrees, const int bgColor);
+gdImagePtr gdImageRotateGeneric(gdImagePtr src, const float degrees, const int bgColor);
+
+
+
+typedef enum {
+ GD_AFFINE_TRANSLATE = 0,
+ GD_AFFINE_SCALE,
+ GD_AFFINE_ROTATE,
+ GD_AFFINE_SHEAR_HORIZONTAL,
+ GD_AFFINE_SHEAR_VERTICAL,
+} gdAffineStandardMatrix;
+
+int gdAffineApplyToPointF (gdPointFPtr dst, const gdPointFPtr src, const double affine[6]);
+int gdAffineInvert (double dst[6], const double src[6]);
+int gdAffineFlip (double dst_affine[6], const double src_affine[6], const int flip_h, const int flip_v);
+int gdAffineConcat (double dst[6], const double m1[6], const double m2[6]);
+
+int gdAffineIdentity (double dst[6]);
+int gdAffineScale (double dst[6], const double scale_x, const double scale_y);
+int gdAffineRotate (double dst[6], const double angle);
+int gdAffineShearHorizontal (double dst[6], const double angle);
+int gdAffineShearVertical(double dst[6], const double angle);
+int gdAffineTranslate (double dst[6], const double offset_x, const double offset_y);
+double gdAffineExpansion (const double src[6]);
+int gdAffineRectilinear (const double src[6]);
+int gdAffineEqual (const double matrix1[6], const double matrix2[6]);
+int gdTransformAffineGetImage(gdImagePtr *dst, const gdImagePtr src, gdRectPtr src_area, const double affine[6]);
+int gdTransformAffineCopy(gdImagePtr dst, int dst_x, int dst_y, const gdImagePtr src, gdRectPtr src_region, const double affine[6]);
+/*
+gdTransformAffineCopy(gdImagePtr dst, int x0, int y0, int x1, int y1,
+ const gdImagePtr src, int src_width, int src_height,
+ const double affine[6]);
+*/
+int gdTransformAffineBoundingBox(gdRectPtr src, const double affine[6], gdRectPtr bbox);
+
+
#define GD_CMP_IMAGE 1 /* Actual image IS different */
#define GD_CMP_NUM_COLORS 2 /* Number of Colours in pallette differ */
#define GD_CMP_COLOR 4 /* Image colours differ */
diff --git a/ext/gd/libgd/gd_interpolation.c b/ext/gd/libgd/gd_interpolation.c
new file mode 100644
index 000000000..d805ec93e
--- /dev/null
+++ b/ext/gd/libgd/gd_interpolation.c
@@ -0,0 +1,2553 @@
+/*
+ * Filtered Image Rescaling
+ * Based on Gems III
+ * - Schumacher general filtered image rescaling
+ * (pp. 414-424)
+ * by Dale Schumacher
+ *
+ * Additional changes by Ray Gardener, Daylon Graphics Ltd.
+ * December 4, 1999
+ *
+ * Ported to libgd by Pierre Joye. Support for multiple channels
+ * added (argb for now).
+ *
+ * Initial sources code is avaibable in the Gems Source Code Packages:
+ * http://www.acm.org/pubs/tog/GraphicsGems/GGemsIII.tar.gz
+ */
+
+/*
+ Summary:
+
+ - Horizontal filter contributions are calculated on the fly,
+ as each column is mapped from src to dst image. This lets
+ us omit having to allocate a temporary full horizontal stretch
+ of the src image.
+
+ - If none of the src pixels within a sampling region differ,
+ then the output pixel is forced to equal (any of) the source pixel.
+ This ensures that filters do not corrupt areas of constant color.
+
+ - Filter weight contribution results, after summing, are
+ rounded to the nearest pixel color value instead of
+ being casted to ILubyte (usually an int or char). Otherwise,
+ artifacting occurs.
+
+*/
+
+/*
+TODO:
+ - Optimize pixel accesses and loops once we have continuous buffer
+ - Add scale support for a portion only of an image (equivalent of copyresized/resampled)
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include <gd.h>
+#include "gdhelpers.h"
+
+#ifdef _MSC_VER
+# pragma optimize("t", on)
+# include <emmintrin.h>
+#endif
+
+#ifndef MIN
+#define MIN(a,b) ((a)<(b)?(a):(b))
+#endif
+#define MIN3(a,b,c) ((a)<(b)?(MIN(a,c)):(MIN(b,c)))
+#ifndef MAX
+#define MAX(a,b) ((a)<(b)?(b):(a))
+#endif
+#define MAX3(a,b,c) ((a)<(b)?(MAX(b,c)):(MAX(a,c)))
+
+#define CLAMP(x, low, high) (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x)))
+
+/* only used here, let do a generic fixed point integers later if required by other
+ part of GD */
+typedef long gdFixed;
+/* Integer to fixed point */
+#define gd_itofx(x) ((x) << 8)
+
+/* Float to fixed point */
+#define gd_ftofx(x) (long)((x) * 256)
+
+/* Double to fixed point */
+#define gd_dtofx(x) (long)((x) * 256)
+
+/* Fixed point to integer */
+#define gd_fxtoi(x) ((x) >> 8)
+
+/* Fixed point to float */
+# define gd_fxtof(x) ((float)(x) / 256)
+
+/* Fixed point to double */
+#define gd_fxtod(x) ((double)(x) / 256)
+
+/* Multiply a fixed by a fixed */
+#define gd_mulfx(x,y) (((x) * (y)) >> 8)
+
+/* Divide a fixed by a fixed */
+#define gd_divfx(x,y) (((x) << 8) / (y))
+
+typedef struct
+{
+ double *Weights; /* Normalized weights of neighboring pixels */
+ int Left,Right; /* Bounds of source pixels window */
+} ContributionType; /* Contirbution information for a single pixel */
+
+typedef struct
+{
+ ContributionType *ContribRow; /* Row (or column) of contribution weights */
+ unsigned int WindowSize, /* Filter window size (of affecting source pixels) */
+ LineLength; /* Length of line (no. or rows / cols) */
+} LineContribType;
+
+/* Each core filter has its own radius */
+#define DEFAULT_FILTER_BICUBIC 3.0
+#define DEFAULT_FILTER_BOX 0.5
+#define DEFAULT_FILTER_GENERALIZED_CUBIC 0.5
+#define DEFAULT_FILTER_RADIUS 1.0
+#define DEFAULT_LANCZOS8_RADIUS 8.0
+#define DEFAULT_LANCZOS3_RADIUS 3.0
+#define DEFAULT_HERMITE_RADIUS 1.0
+#define DEFAULT_BOX_RADIUS 0.5
+#define DEFAULT_TRIANGLE_RADIUS 1.0
+#define DEFAULT_BELL_RADIUS 1.5
+#define DEFAULT_CUBICSPLINE_RADIUS 2.0
+#define DEFAULT_MITCHELL_RADIUS 2.0
+#define DEFAULT_COSINE_RADIUS 1.0
+#define DEFAULT_CATMULLROM_RADIUS 2.0
+#define DEFAULT_QUADRATIC_RADIUS 1.5
+#define DEFAULT_QUADRATICBSPLINE_RADIUS 1.5
+#define DEFAULT_CUBICCONVOLUTION_RADIUS 3.0
+#define DEFAULT_GAUSSIAN_RADIUS 1.0
+#define DEFAULT_HANNING_RADIUS 1.0
+#define DEFAULT_HAMMING_RADIUS 1.0
+#define DEFAULT_SINC_RADIUS 1.0
+#define DEFAULT_WELSH_RADIUS 1.0
+
+enum GD_RESIZE_FILTER_TYPE{
+ FILTER_DEFAULT = 0,
+ FILTER_BELL,
+ FILTER_BESSEL,
+ FILTER_BLACKMAN,
+ FILTER_BOX,
+ FILTER_BSPLINE,
+ FILTER_CATMULLROM,
+ FILTER_COSINE,
+ FILTER_CUBICCONVOLUTION,
+ FILTER_CUBICSPLINE,
+ FILTER_HERMITE,
+ FILTER_LANCZOS3,
+ FILTER_LANCZOS8,
+ FILTER_MITCHELL,
+ FILTER_QUADRATIC,
+ FILTER_QUADRATICBSPLINE,
+ FILTER_TRIANGLE,
+ FILTER_GAUSSIAN,
+ FILTER_HANNING,
+ FILTER_HAMMING,
+ FILTER_SINC,
+ FILTER_WELSH,
+
+ FILTER_CALLBACK = 999
+};
+
+typedef enum GD_RESIZE_FILTER_TYPE gdResizeFilterType;
+
+static double KernelBessel_J1(const double x)
+{
+ double p, q;
+
+ register long i;
+
+ static const double
+ Pone[] =
+ {
+ 0.581199354001606143928050809e+21,
+ -0.6672106568924916298020941484e+20,
+ 0.2316433580634002297931815435e+19,
+ -0.3588817569910106050743641413e+17,
+ 0.2908795263834775409737601689e+15,
+ -0.1322983480332126453125473247e+13,
+ 0.3413234182301700539091292655e+10,
+ -0.4695753530642995859767162166e+7,
+ 0.270112271089232341485679099e+4
+ },
+ Qone[] =
+ {
+ 0.11623987080032122878585294e+22,
+ 0.1185770712190320999837113348e+20,
+ 0.6092061398917521746105196863e+17,
+ 0.2081661221307607351240184229e+15,
+ 0.5243710262167649715406728642e+12,
+ 0.1013863514358673989967045588e+10,
+ 0.1501793594998585505921097578e+7,
+ 0.1606931573481487801970916749e+4,
+ 0.1e+1
+ };
+
+ p = Pone[8];
+ q = Qone[8];
+ for (i=7; i >= 0; i--)
+ {
+ p = p*x*x+Pone[i];
+ q = q*x*x+Qone[i];
+ }
+ return (double)(p/q);
+}
+
+static double KernelBessel_P1(const double x)
+{
+ double p, q;
+
+ register long i;
+
+ static const double
+ Pone[] =
+ {
+ 0.352246649133679798341724373e+5,
+ 0.62758845247161281269005675e+5,
+ 0.313539631109159574238669888e+5,
+ 0.49854832060594338434500455e+4,
+ 0.2111529182853962382105718e+3,
+ 0.12571716929145341558495e+1
+ },
+ Qone[] =
+ {
+ 0.352246649133679798068390431e+5,
+ 0.626943469593560511888833731e+5,
+ 0.312404063819041039923015703e+5,
+ 0.4930396490181088979386097e+4,
+ 0.2030775189134759322293574e+3,
+ 0.1e+1
+ };
+
+ p = Pone[5];
+ q = Qone[5];
+ for (i=4; i >= 0; i--)
+ {
+ p = p*(8.0/x)*(8.0/x)+Pone[i];
+ q = q*(8.0/x)*(8.0/x)+Qone[i];
+ }
+ return (double)(p/q);
+}
+
+static double KernelBessel_Q1(const double x)
+{
+ double p, q;
+
+ register long i;
+
+ static const double
+ Pone[] =
+ {
+ 0.3511751914303552822533318e+3,
+ 0.7210391804904475039280863e+3,
+ 0.4259873011654442389886993e+3,
+ 0.831898957673850827325226e+2,
+ 0.45681716295512267064405e+1,
+ 0.3532840052740123642735e-1
+ },
+ Qone[] =
+ {
+ 0.74917374171809127714519505e+4,
+ 0.154141773392650970499848051e+5,
+ 0.91522317015169922705904727e+4,
+ 0.18111867005523513506724158e+4,
+ 0.1038187585462133728776636e+3,
+ 0.1e+1
+ };
+
+ p = Pone[5];
+ q = Qone[5];
+ for (i=4; i >= 0; i--)
+ {
+ p = p*(8.0/x)*(8.0/x)+Pone[i];
+ q = q*(8.0/x)*(8.0/x)+Qone[i];
+ }
+ return (double)(p/q);
+}
+
+static double KernelBessel_Order1(double x)
+{
+ double p, q;
+
+ if (x == 0.0)
+ return (0.0f);
+ p = x;
+ if (x < 0.0)
+ x=(-x);
+ if (x < 8.0)
+ return (p*KernelBessel_J1(x));
+ q = (double)sqrt(2.0f/(M_PI*x))*(double)(KernelBessel_P1(x)*(1.0f/sqrt(2.0f)*(sin(x)-cos(x)))-8.0f/x*KernelBessel_Q1(x)*
+ (-1.0f/sqrt(2.0f)*(sin(x)+cos(x))));
+ if (p < 0.0f)
+ q = (-q);
+ return (q);
+}
+
+static double filter_bessel(const double x)
+{
+ if (x == 0.0f)
+ return (double)(M_PI/4.0f);
+ return (KernelBessel_Order1((double)M_PI*x)/(2.0f*x));
+}
+
+
+static double filter_blackman(const double x)
+{
+ return (0.42f+0.5f*(double)cos(M_PI*x)+0.08f*(double)cos(2.0f*M_PI*x));
+}
+
+/**
+ * Bicubic interpolation kernel (a=-1):
+ \verbatim
+ /
+ | 1-2|t|**2+|t|**3 , if |t| < 1
+ h(t) = | 4-8|t|+5|t|**2-|t|**3 , if 1<=|t|<2
+ | 0 , otherwise
+ \
+ \endverbatim
+ * ***bd*** 2.2004
+ */
+static double filter_bicubic(const double t)
+{
+ const double abs_t = (double)fabs(t);
+ const double abs_t_sq = abs_t * abs_t;
+ if (abs_t<1) return 1-2*abs_t_sq+abs_t_sq*abs_t;
+ if (abs_t<2) return 4 - 8*abs_t +5*abs_t_sq - abs_t_sq*abs_t;
+ return 0;
+}
+
+/**
+ * Generalized cubic kernel (for a=-1 it is the same as BicubicKernel):
+ \verbatim
+ /
+ | (a+2)|t|**3 - (a+3)|t|**2 + 1 , |t| <= 1
+ h(t) = | a|t|**3 - 5a|t|**2 + 8a|t| - 4a , 1 < |t| <= 2
+ | 0 , otherwise
+ \
+ \endverbatim
+ * Often used values for a are -1 and -1/2.
+ */
+static double filter_generalized_cubic(const double t)
+{
+ const double a = -DEFAULT_FILTER_GENERALIZED_CUBIC;
+ double abs_t = (double)fabs(t);
+ double abs_t_sq = abs_t * abs_t;
+ if (abs_t < 1) return (a + 2) * abs_t_sq * abs_t - (a + 3) * abs_t_sq + 1;
+ if (abs_t < 2) return a * abs_t_sq * abs_t - 5 * a * abs_t_sq + 8 * a * abs_t - 4 * a;
+ return 0;
+}
+
+/* CubicSpline filter, default radius 2 */
+static double filter_cubic_spline(const double x1)
+{
+ const double x = x1 < 0.0 ? -x1 : x1;
+
+ if (x < 1.0 ) {
+ const double x2 = x*x;
+
+ return (0.5 * x2 * x - x2 + 2.0 / 3.0);
+ }
+ if (x < 2.0) {
+ return (pow(2.0 - x, 3.0)/6.0);
+ }
+ return 0;
+}
+
+/* CubicConvolution filter, default radius 3 */
+static double filter_cubic_convolution(const double x1)
+{
+ const double x = x1 < 0.0 ? -x1 : x1;
+ const double x2 = x1 * x1;
+ const double x2_x = x2 * x;
+
+ if (x <= 1.0) return ((4.0 / 3.0)* x2_x - (7.0 / 3.0) * x2 + 1.0);
+ if (x <= 2.0) return (- (7.0 / 12.0) * x2_x + 3 * x2 - (59.0 / 12.0) * x + 2.5);
+ if (x <= 3.0) return ( (1.0/12.0) * x2_x - (2.0 / 3.0) * x2 + 1.75 * x - 1.5);
+ return 0;
+}
+
+static double filter_box(double x) {
+ if (x < - DEFAULT_FILTER_BOX)
+ return 0.0f;
+ if (x < DEFAULT_FILTER_BOX)
+ return 1.0f;
+ return 0.0f;
+}
+
+static double filter_catmullrom(const double x)
+{
+ if (x < -2.0)
+ return(0.0f);
+ if (x < -1.0)
+ return(0.5f*(4.0f+x*(8.0f+x*(5.0f+x))));
+ if (x < 0.0)
+ return(0.5f*(2.0f+x*x*(-5.0f-3.0f*x)));
+ if (x < 1.0)
+ return(0.5f*(2.0f+x*x*(-5.0f+3.0f*x)));
+ if (x < 2.0)
+ return(0.5f*(4.0f+x*(-8.0f+x*(5.0f-x))));
+ return(0.0f);
+}
+
+static double filter_filter(double t)
+{
+ /* f(t) = 2|t|^3 - 3|t|^2 + 1, -1 <= t <= 1 */
+ if(t < 0.0) t = -t;
+ if(t < 1.0) return((2.0 * t - 3.0) * t * t + 1.0);
+ return(0.0);
+}
+
+
+/* Lanczos8 filter, default radius 8 */
+static double filter_lanczos8(const double x1)
+{
+ const double x = x1 < 0.0 ? -x1 : x1;
+#define R DEFAULT_LANCZOS8_RADIUS
+
+ if ( x == 0.0) return 1;
+
+ if ( x < R) {
+ return R * sin(x*M_PI) * sin(x * M_PI/ R) / (x * M_PI * x * M_PI);
+ }
+ return 0.0;
+#undef R
+}
+
+
+/* Lanczos3 filter, default radius 3 */
+static double filter_lanczos3(const double x1)
+{
+ const double x = x1 < 0.0 ? -x1 : x1;
+#define R DEFAULT_LANCZOS3_RADIUS
+
+ if ( x == 0.0) return 1;
+
+ if ( x < R)
+ {
+ return R * sin(x*M_PI) * sin(x * M_PI / R) / (x * M_PI * x * M_PI);
+ }
+ return 0.0;
+#undef R
+}
+
+/* Hermite filter, default radius 1 */
+static double filter_hermite(const double x1)
+{
+ const double x = x1 < 0.0 ? -x1 : x1;
+
+ if (x < 1.0) return ((2.0 * x - 3) * x * x + 1.0 );
+
+ return 0.0;
+}
+
+/* Trangle filter, default radius 1 */
+static double filter_triangle(const double x1)
+{
+ const double x = x1 < 0.0 ? -x1 : x1;
+ if (x < 1.0) return (1.0 - x);
+ return 0.0;
+}
+
+/* Bell filter, default radius 1.5 */
+static double filter_bell(const double x1)
+{
+ const double x = x1 < 0.0 ? -x1 : x1;
+
+ if (x < 0.5) return (0.75 - x*x);
+ if (x < 1.5) return (0.5 * pow(x - 1.5, 2.0));
+ return 0.0;
+}
+
+/* Mitchell filter, default radius 2.0 */
+static double filter_mitchell(const double x)
+{
+#define KM_B (1.0f/3.0f)
+#define KM_C (1.0f/3.0f)
+#define KM_P0 (( 6.0f - 2.0f * KM_B ) / 6.0f)
+#define KM_P2 ((-18.0f + 12.0f * KM_B + 6.0f * KM_C) / 6.0f)
+#define KM_P3 (( 12.0f - 9.0f * KM_B - 6.0f * KM_C) / 6.0f)
+#define KM_Q0 (( 8.0f * KM_B + 24.0f * KM_C) / 6.0f)
+#define KM_Q1 ((-12.0f * KM_B - 48.0f * KM_C) / 6.0f)
+#define KM_Q2 (( 6.0f * KM_B + 30.0f * KM_C) / 6.0f)
+#define KM_Q3 (( -1.0f * KM_B - 6.0f * KM_C) / 6.0f)
+
+ if (x < -2.0)
+ return(0.0f);
+ if (x < -1.0)
+ return(KM_Q0-x*(KM_Q1-x*(KM_Q2-x*KM_Q3)));
+ if (x < 0.0f)
+ return(KM_P0+x*x*(KM_P2-x*KM_P3));
+ if (x < 1.0f)
+ return(KM_P0+x*x*(KM_P2+x*KM_P3));
+ if (x < 2.0f)
+ return(KM_Q0+x*(KM_Q1+x*(KM_Q2+x*KM_Q3)));
+ return(0.0f);
+}
+
+
+
+/* Cosine filter, default radius 1 */
+static double filter_cosine(const double x)
+{
+ if ((x >= -1.0) && (x <= 1.0)) return ((cos(x * M_PI) + 1.0)/2.0);
+
+ return 0;
+}
+
+/* Quadratic filter, default radius 1.5 */
+static double filter_quadratic(const double x1)
+{
+ const double x = x1 < 0.0 ? -x1 : x1;
+
+ if (x <= 0.5) return (- 2.0 * x * x + 1);
+ if (x <= 1.5) return (x * x - 2.5* x + 1.5);
+ return 0.0;
+}
+
+static double filter_bspline(const double x)
+{
+ if (x>2.0f) {
+ return 0.0f;
+ } else {
+ double a, b, c, d;
+ /* Was calculated anyway cause the "if((x-1.0f) < 0)" */
+ const double xm1 = x - 1.0f;
+ const double xp1 = x + 1.0f;
+ const double xp2 = x + 2.0f;
+
+ if ((xp2) <= 0.0f) a = 0.0f; else a = xp2*xp2*xp2;
+ if ((xp1) <= 0.0f) b = 0.0f; else b = xp1*xp1*xp1;
+ if (x <= 0) c = 0.0f; else c = x*x*x;
+ if ((xm1) <= 0.0f) d = 0.0f; else d = xm1*xm1*xm1;
+
+ return (0.16666666666666666667f * (a - (4.0f * b) + (6.0f * c) - (4.0f * d)));
+ }
+}
+
+/* QuadraticBSpline filter, default radius 1.5 */
+static double filter_quadratic_bspline(const double x1)
+{
+ const double x = x1 < 0.0 ? -x1 : x1;
+
+ if (x <= 0.5) return (- x * x + 0.75);
+ if (x <= 1.5) return (0.5 * x * x - 1.5 * x + 1.125);
+ return 0.0;
+}
+
+static double filter_gaussian(const double x)
+{
+ /* return(exp((double) (-2.0 * x * x)) * sqrt(2.0 / M_PI)); */
+ return (double)(exp(-2.0f * x * x) * 0.79788456080287f);
+}
+
+static double filter_hanning(const double x)
+{
+ /* A Cosine windowing function */
+ return(0.5 + 0.5 * cos(M_PI * x));
+}
+
+static double filter_hamming(const double x)
+{
+ /* should be
+ (0.54+0.46*cos(M_PI*(double) x));
+ but this approximation is sufficient */
+ if (x < -1.0f)
+ return 0.0f;
+ if (x < 0.0f)
+ return 0.92f*(-2.0f*x-3.0f)*x*x+1.0f;
+ if (x < 1.0f)
+ return 0.92f*(2.0f*x-3.0f)*x*x+1.0f;
+ return 0.0f;
+}
+
+static double filter_power(const double x)
+{
+ const double a = 2.0f;
+ if (fabs(x)>1) return 0.0f;
+ return (1.0f - (double)fabs(pow(x,a)));
+}
+
+static double filter_sinc(const double x)
+{
+ /* X-scaled Sinc(x) function. */
+ if (x == 0.0) return(1.0);
+ return (sin(M_PI * (double) x) / (M_PI * (double) x));
+}
+
+static double filter_welsh(const double x)
+{
+ /* Welsh parabolic windowing filter */
+ if (x < 1.0)
+ return(1 - x*x);
+ return(0.0);
+}
+
+
+/* Copied from upstream's libgd */
+static inline int _color_blend (const int dst, const int src)
+{
+ const int src_alpha = gdTrueColorGetAlpha(src);
+
+ if( src_alpha == gdAlphaOpaque ) {
+ return src;
+ } else {
+ const int dst_alpha = gdTrueColorGetAlpha(dst);
+
+ if( src_alpha == gdAlphaTransparent ) return dst;
+ if( dst_alpha == gdAlphaTransparent ) {
+ return src;
+ } else {
+ register int alpha, red, green, blue;
+ const int src_weight = gdAlphaTransparent - src_alpha;
+ const int dst_weight = (gdAlphaTransparent - dst_alpha) * src_alpha / gdAlphaMax;
+ const int tot_weight = src_weight + dst_weight;
+
+ alpha = src_alpha * dst_alpha / gdAlphaMax;
+
+ red = (gdTrueColorGetRed(src) * src_weight
+ + gdTrueColorGetRed(dst) * dst_weight) / tot_weight;
+ green = (gdTrueColorGetGreen(src) * src_weight
+ + gdTrueColorGetGreen(dst) * dst_weight) / tot_weight;
+ blue = (gdTrueColorGetBlue(src) * src_weight
+ + gdTrueColorGetBlue(dst) * dst_weight) / tot_weight;
+
+ return ((alpha << 24) + (red << 16) + (green << 8) + blue);
+ }
+ }
+}
+
+static inline int _setEdgePixel(const gdImagePtr src, unsigned int x, unsigned int y, gdFixed coverage, const int bgColor)
+{
+ const gdFixed f_127 = gd_itofx(127);
+ register int c = src->tpixels[y][x];
+ c = c | (( (int) (gd_fxtof(gd_mulfx(coverage, f_127)) + 50.5f)) << 24);
+ return _color_blend(bgColor, c);
+}
+
+static inline int getPixelOverflowTC(gdImagePtr im, const int x, const int y, const int bgColor)
+{
+ if (gdImageBoundsSafe(im, x, y)) {
+ const int c = im->tpixels[y][x];
+ if (c == im->transparent) {
+ return bgColor == -1 ? gdTrueColorAlpha(0, 0, 0, 127) : bgColor;
+ }
+ return c;
+ } else {
+ register int border;
+
+ if (y < im->cy1) {
+ border = im->tpixels[0][im->cx1];
+ goto processborder;
+ }
+
+ if (y < im->cy1) {
+ border = im->tpixels[0][im->cx1];
+ goto processborder;
+ }
+
+ if (y > im->cy2) {
+ if (x >= im->cx1 && x <= im->cx1) {
+ border = im->tpixels[im->cy2][x];
+ goto processborder;
+ } else {
+ return gdTrueColorAlpha(0, 0, 0, 127);
+ }
+ }
+
+ /* y is bound safe at this point */
+ if (x < im->cx1) {
+ border = im->tpixels[y][im->cx1];
+ goto processborder;
+ }
+
+ if (x > im->cx2) {
+ border = im->tpixels[y][im->cx2];
+ }
+
+processborder:
+ if (border == im->transparent) {
+ return gdTrueColorAlpha(0, 0, 0, 127);
+ } else{
+ return gdTrueColorAlpha(gdTrueColorGetRed(border), gdTrueColorGetGreen(border), gdTrueColorGetBlue(border), 127);
+ }
+ }
+}
+
+#define colorIndex2RGBA(c) gdTrueColorAlpha(im->red[(c)], im->green[(c)], im->blue[(c)], im->alpha[(c)])
+#define colorIndex2RGBcustomA(c, a) gdTrueColorAlpha(im->red[(c)], im->green[(c)], im->blue[(c)], im->alpha[(a)])
+static inline int getPixelOverflowPalette(gdImagePtr im, const int x, const int y, const int bgColor)
+{
+ if (gdImageBoundsSafe(im, x, y)) {
+ const int c = im->pixels[y][x];
+ if (c == im->transparent) {
+ return bgColor == -1 ? gdTrueColorAlpha(0, 0, 0, 127) : bgColor;
+ }
+ return colorIndex2RGBA(c);
+ } else {
+ register int border;
+ if (y < im->cy1) {
+ border = gdImageGetPixel(im, im->cx1, 0);
+ goto processborder;
+ }
+
+ if (y < im->cy1) {
+ border = gdImageGetPixel(im, im->cx1, 0);
+ goto processborder;
+ }
+
+ if (y > im->cy2) {
+ if (x >= im->cx1 && x <= im->cx1) {
+ border = gdImageGetPixel(im, x, im->cy2);
+ goto processborder;
+ } else {
+ return gdTrueColorAlpha(0, 0, 0, 127);
+ }
+ }
+
+ /* y is bound safe at this point */
+ if (x < im->cx1) {
+ border = gdImageGetPixel(im, im->cx1, y);
+ goto processborder;
+ }
+
+ if (x > im->cx2) {
+ border = gdImageGetPixel(im, im->cx2, y);
+ }
+
+processborder:
+ if (border == im->transparent) {
+ return gdTrueColorAlpha(0, 0, 0, 127);
+ } else{
+ return colorIndex2RGBcustomA(border, 127);
+ }
+ }
+}
+
+static int getPixelInterpolateWeight(gdImagePtr im, const double x, const double y, const int bgColor)
+{
+ /* Closest pixel <= (xf,yf) */
+ int sx = (int)(x);
+ int sy = (int)(y);
+ const double xf = x - (double)sx;
+ const double yf = y - (double)sy;
+ const double nxf = (double) 1.0 - xf;
+ const double nyf = (double) 1.0 - yf;
+ const double m1 = xf * yf;
+ const double m2 = nxf * yf;
+ const double m3 = xf * nyf;
+ const double m4 = nxf * nyf;
+
+ /* get color values of neighbouring pixels */
+ const int c1 = im->trueColor == 1 ? getPixelOverflowTC(im, sx, sy, bgColor) : getPixelOverflowPalette(im, sx, sy, bgColor);
+ const int c2 = im->trueColor == 1 ? getPixelOverflowTC(im, sx - 1, sy, bgColor) : getPixelOverflowPalette(im, sx - 1, sy, bgColor);
+ const int c3 = im->trueColor == 1 ? getPixelOverflowTC(im, sx, sy - 1, bgColor) : getPixelOverflowPalette(im, sx, sy - 1, bgColor);
+ const int c4 = im->trueColor == 1 ? getPixelOverflowTC(im, sx - 1, sy - 1, bgColor) : getPixelOverflowPalette(im, sx, sy - 1, bgColor);
+ int r, g, b, a;
+
+ if (x < 0) sx--;
+ if (y < 0) sy--;
+
+ /* component-wise summing-up of color values */
+ if (im->trueColor) {
+ r = (int)(m1*gdTrueColorGetRed(c1) + m2*gdTrueColorGetRed(c2) + m3*gdTrueColorGetRed(c3) + m4*gdTrueColorGetRed(c4));
+ g = (int)(m1*gdTrueColorGetGreen(c1) + m2*gdTrueColorGetGreen(c2) + m3*gdTrueColorGetGreen(c3) + m4*gdTrueColorGetGreen(c4));
+ b = (int)(m1*gdTrueColorGetBlue(c1) + m2*gdTrueColorGetBlue(c2) + m3*gdTrueColorGetBlue(c3) + m4*gdTrueColorGetBlue(c4));
+ a = (int)(m1*gdTrueColorGetAlpha(c1) + m2*gdTrueColorGetAlpha(c2) + m3*gdTrueColorGetAlpha(c3) + m4*gdTrueColorGetAlpha(c4));
+ } else {
+ r = (int)(m1*im->red[(c1)] + m2*im->red[(c2)] + m3*im->red[(c3)] + m4*im->red[(c4)]);
+ g = (int)(m1*im->green[(c1)] + m2*im->green[(c2)] + m3*im->green[(c3)] + m4*im->green[(c4)]);
+ b = (int)(m1*im->blue[(c1)] + m2*im->blue[(c2)] + m3*im->blue[(c3)] + m4*im->blue[(c4)]);
+ a = (int)(m1*im->alpha[(c1)] + m2*im->alpha[(c2)] + m3*im->alpha[(c3)] + m4*im->alpha[(c4)]);
+ }
+
+ r = CLAMP(r, 0, 255);
+ g = CLAMP(g, 0, 255);
+ b = CLAMP(b, 0, 255);
+ a = CLAMP(a, 0, gdAlphaMax);
+ return gdTrueColorAlpha(r, g, b, a);
+}
+
+/**
+ * Function: getPixelInterpolated
+ * Returns the interpolated color value using the default interpolation
+ * method. The returned color is always in the ARGB format (truecolor).
+ *
+ * Parameters:
+ * im - Image to set the default interpolation method
+ * y - X value of the ideal position
+ * y - Y value of the ideal position
+ * method - Interpolation method <gdInterpolationMethod>
+ *
+ * Returns:
+ * GD_TRUE if the affine is rectilinear or GD_FALSE
+ *
+ * See also:
+ * <gdSetInterpolationMethod>
+ */
+int getPixelInterpolated(gdImagePtr im, const double x, const double y, const int bgColor)
+{
+ const int xi=(int)((x) < 0 ? x - 1: x);
+ const int yi=(int)((y) < 0 ? y - 1: y);
+ int yii;
+ int i;
+ double kernel, kernel_cache_y;
+ double kernel_x[12], kernel_y[4];
+ double new_r = 0.0f, new_g = 0.0f, new_b = 0.0f, new_a = 0.0f;
+
+ /* These methods use special implementations */
+ if (im->interpolation_id == GD_BILINEAR_FIXED || im->interpolation_id == GD_BICUBIC_FIXED || im->interpolation_id == GD_NEAREST_NEIGHBOUR) {
+ return -1;
+ }
+
+ /* Default to full alpha */
+ if (bgColor == -1) {
+ }
+
+ if (im->interpolation_id == GD_WEIGHTED4) {
+ return getPixelInterpolateWeight(im, x, y, bgColor);
+ }
+
+ if (im->interpolation_id == GD_NEAREST_NEIGHBOUR) {
+ if (im->trueColor == 1) {
+ return getPixelOverflowTC(im, xi, yi, bgColor);
+ } else {
+ return getPixelOverflowPalette(im, xi, yi, bgColor);
+ }
+ }
+ if (im->interpolation) {
+ for (i=0; i<4; i++) {
+ kernel_x[i] = (double) im->interpolation((double)(xi+i-1-x));
+ kernel_y[i] = (double) im->interpolation((double)(yi+i-1-y));
+ }
+ } else {
+ return -1;
+ }
+
+ /*
+ * TODO: use the known fast rgba multiplication implementation once
+ * the new formats are in place
+ */
+ for (yii = yi-1; yii < yi+3; yii++) {
+ int xii;
+ kernel_cache_y = kernel_y[yii-(yi-1)];
+ if (im->trueColor) {
+ for (xii=xi-1; xii<xi+3; xii++) {
+ const int rgbs = getPixelOverflowTC(im, xii, yii, bgColor);
+
+ kernel = kernel_cache_y * kernel_x[xii-(xi-1)];
+ new_r += kernel * gdTrueColorGetRed(rgbs);
+ new_g += kernel * gdTrueColorGetGreen(rgbs);
+ new_b += kernel * gdTrueColorGetBlue(rgbs);
+ new_a += kernel * gdTrueColorGetAlpha(rgbs);
+ }
+ } else {
+ for (xii=xi-1; xii<xi+3; xii++) {
+ const int rgbs = getPixelOverflowPalette(im, xii, yii, bgColor);
+
+ kernel = kernel_cache_y * kernel_x[xii-(xi-1)];
+ new_r += kernel * gdTrueColorGetRed(rgbs);
+ new_g += kernel * gdTrueColorGetGreen(rgbs);
+ new_b += kernel * gdTrueColorGetBlue(rgbs);
+ new_a += kernel * gdTrueColorGetAlpha(rgbs);
+ }
+ }
+ }
+
+ new_r = CLAMP(new_r, 0, 255);
+ new_g = CLAMP(new_g, 0, 255);
+ new_b = CLAMP(new_b, 0, 255);
+ new_a = CLAMP(new_a, 0, gdAlphaMax);
+
+ return gdTrueColorAlpha(((int)new_r), ((int)new_g), ((int)new_b), ((int)new_a));
+}
+
+static inline LineContribType * _gdContributionsAlloc(unsigned int line_length, unsigned int windows_size)
+{
+ unsigned int u = 0;
+ LineContribType *res;
+
+ res = (LineContribType *) gdMalloc(sizeof(LineContribType));
+ if (!res) {
+ return NULL;
+ }
+ res->WindowSize = windows_size;
+ res->LineLength = line_length;
+ res->ContribRow = (ContributionType *) gdMalloc(line_length * sizeof(ContributionType));
+
+ for (u = 0 ; u < line_length ; u++) {
+ res->ContribRow[u].Weights = (double *) gdMalloc(windows_size * sizeof(double));
+ }
+ return res;
+}
+
+static inline _gdContributionsFree(LineContribType * p)
+{
+ unsigned int u;
+ for (u = 0; u < p->LineLength; u++) {
+ gdFree(p->ContribRow[u].Weights);
+ }
+ gdFree(p->ContribRow);
+ gdFree(p);
+}
+
+static inline LineContribType *_gdContributionsCalc(unsigned int line_size, unsigned int src_size, double scale_d, const interpolation_method pFilter)
+{
+ double width_d;
+ double scale_f_d = 1.0;
+ const double filter_width_d = DEFAULT_BOX_RADIUS;
+ int windows_size;
+ unsigned int u;
+ LineContribType *res;
+
+ if (scale_d < 1.0) {
+ width_d = filter_width_d / scale_d;
+ scale_f_d = scale_d;
+ } else {
+ width_d= filter_width_d;
+ }
+
+ windows_size = 2 * (int)ceil(width_d) + 1;
+ res = _gdContributionsAlloc(line_size, windows_size);
+
+ for (u = 0; u < line_size; u++) {
+ const double dCenter = (double)u / scale_d;
+ /* get the significant edge points affecting the pixel */
+ register int iLeft = MAX(0, (int)floor (dCenter - width_d));
+ int iRight = MIN((int)ceil(dCenter + width_d), (int)src_size - 1);
+ double dTotalWeight = 0.0;
+ int iSrc;
+
+ res->ContribRow[u].Left = iLeft;
+ res->ContribRow[u].Right = iRight;
+
+ /* Cut edge points to fit in filter window in case of spill-off */
+ if (iRight - iLeft + 1 > windows_size) {
+ if (iLeft < ((int)src_size - 1 / 2)) {
+ iLeft++;
+ } else {
+ iRight--;
+ }
+ }
+
+ for (iSrc = iLeft; iSrc <= iRight; iSrc++) {
+ dTotalWeight += (res->ContribRow[u].Weights[iSrc-iLeft] = scale_f_d * (*pFilter)(scale_f_d * (dCenter - (double)iSrc)));
+ }
+
+ if (dTotalWeight < 0.0) {
+ _gdContributionsFree(res);
+ return NULL;
+ }
+
+ if (dTotalWeight > 0.0) {
+ for (iSrc = iLeft; iSrc <= iRight; iSrc++) {
+ res->ContribRow[u].Weights[iSrc-iLeft] /= dTotalWeight;
+ }
+ }
+ }
+ return res;
+}
+
+static inline void _gdScaleRow(gdImagePtr pSrc, unsigned int src_width, gdImagePtr dst, unsigned int dst_width, unsigned int row, LineContribType *contrib)
+{
+ int *p_src_row = pSrc->tpixels[row];
+ int *p_dst_row = dst->tpixels[row];
+ unsigned int x;
+
+ for (x = 0; x < dst_width - 1; x++) {
+ register unsigned char r = 0, g = 0, b = 0, a = 0;
+ const int left = contrib->ContribRow[x].Left;
+ const int right = contrib->ContribRow[x].Right;
+ int i;
+
+ /* Accumulate each channel */
+ for (i = left; i <= right; i++) {
+ const left_channel = i - left;
+ r += (unsigned char)(contrib->ContribRow[x].Weights[left_channel] * (double)(gdTrueColorGetRed(p_src_row[i])));
+ g += (unsigned char)(contrib->ContribRow[x].Weights[left_channel] * (double)(gdTrueColorGetGreen(p_src_row[i])));
+ b += (unsigned char)(contrib->ContribRow[x].Weights[left_channel] * (double)(gdTrueColorGetBlue(p_src_row[i])));
+ a += (unsigned char)(contrib->ContribRow[x].Weights[left_channel] * (double)(gdTrueColorGetAlpha(p_src_row[i])));
+ }
+ p_dst_row[x] = gdTrueColorAlpha(r, g, b, a);
+ }
+}
+
+static inline void _gdScaleHoriz(gdImagePtr pSrc, unsigned int src_width, unsigned int src_height, gdImagePtr pDst, unsigned int dst_width, unsigned int dst_height)
+{
+ unsigned int u;
+ LineContribType * contrib;
+
+ /* same width, just copy it */
+ if (dst_width == src_width) {
+ unsigned int y;
+ for (y = 0; y < src_height - 1; ++y) {
+ memcpy(pDst->tpixels[y], pSrc->tpixels[y], src_width);
+ }
+ }
+
+ contrib = _gdContributionsCalc(dst_width, src_width, (double)dst_width / (double)src_width, pSrc->interpolation);
+ if (contrib == NULL) {
+ return;
+ }
+ /* Scale each row */
+ for (u = 0; u < dst_height - 1; u++) {
+ _gdScaleRow(pSrc, src_width, pDst, dst_width, u, contrib);
+ }
+ _gdContributionsFree (contrib);
+}
+
+static inline _gdScaleCol (gdImagePtr pSrc, unsigned int src_width, gdImagePtr pRes, unsigned int dst_width, unsigned int dst_height, unsigned int uCol, LineContribType *contrib)
+{
+ unsigned int y;
+ for (y = 0; y < dst_height - 1; y++) {
+ register unsigned char r = 0, g = 0, b = 0, a = 0;
+ const int iLeft = contrib->ContribRow[y].Left;
+ const int iRight = contrib->ContribRow[y].Right;
+ int i;
+ int *row = pRes->tpixels[y];
+
+ /* Accumulate each channel */
+ for (i = iLeft; i <= iRight; i++) {
+ const int pCurSrc = pSrc->tpixels[i][uCol];
+ const int i_iLeft = i - iLeft;
+ r += (unsigned char)(contrib->ContribRow[y].Weights[i_iLeft] * (double)(gdTrueColorGetRed(pCurSrc)));
+ g += (unsigned char)(contrib->ContribRow[y].Weights[i_iLeft] * (double)(gdTrueColorGetGreen(pCurSrc)));
+ b += (unsigned char)(contrib->ContribRow[y].Weights[i_iLeft] * (double)(gdTrueColorGetBlue(pCurSrc)));
+ a += (unsigned char)(contrib->ContribRow[y].Weights[i_iLeft] * (double)(gdTrueColorGetAlpha(pCurSrc)));
+ }
+ pRes->tpixels[y][uCol] = gdTrueColorAlpha(r, g, b, a);
+ }
+}
+
+static inline _gdScaleVert (const gdImagePtr pSrc, const unsigned int src_width, const unsigned int src_height, const gdImagePtr pDst, const unsigned int dst_width, const unsigned int dst_height)
+{
+ unsigned int u;
+ LineContribType * contrib;
+
+ /* same height, copy it */
+ if (src_height == dst_height) {
+ unsigned int y;
+ for (y = 0; y < src_height - 1; ++y) {
+ memcpy(pDst->tpixels[y], pSrc->tpixels[y], src_width);
+ }
+ }
+
+ contrib = _gdContributionsCalc(dst_height, src_height, (double)(dst_height) / (double)(src_height), pSrc->interpolation);
+ /* scale each column */
+ for (u = 0; u < dst_width - 1; u++) {
+ _gdScaleCol(pSrc, src_width, pDst, dst_width, dst_height, u, contrib);
+ }
+ _gdContributionsFree(contrib);
+}
+
+gdImagePtr gdImageScaleTwoPass(const gdImagePtr src, const unsigned int src_width, const unsigned int src_height, const unsigned int new_width, const unsigned int new_height)
+{
+ gdImagePtr tmp_im;
+ gdImagePtr dst;
+
+ tmp_im = gdImageCreateTrueColor(new_width, src_height);
+ if (tmp_im == NULL) {
+ return NULL;
+ }
+ _gdScaleHoriz (src, src_width, src_height, tmp_im, new_width, src_height);
+
+ dst = gdImageCreateTrueColor(new_width, new_height);
+ if (dst == NULL) {
+ return NULL;
+ }
+ _gdScaleVert(tmp_im, new_width, src_height, dst, new_width, new_height);
+ gdFree(tmp_im);
+
+
+ return dst;
+}
+
+gdImagePtr Scale(const gdImagePtr src, const unsigned int src_width, const unsigned int src_height, const gdImagePtr dst, const unsigned int new_width, const unsigned int new_height)
+{
+ gdImagePtr tmp_im;
+
+ tmp_im = gdImageCreateTrueColor(new_width, src_height);
+ if (tmp_im == NULL) {
+ return NULL;
+ }
+ _gdScaleHoriz(src, src_width, src_height, tmp_im, new_width, src_height);
+
+ _gdScaleVert(tmp_im, new_width, src_height, dst, new_width, new_height);
+
+ gdFree(tmp_im);
+ return dst;
+}
+
+/*
+ BilinearFixed, BicubicFixed and nearest implementations are rewamped versions of the implementation in CBitmapEx
+ http://www.codeproject.com/Articles/29121/CBitmapEx-Free-C-Bitmap-Manipulation-Class
+ Integer only implementation, good to have for common usages like pre scale very large
+ images before using another interpolation methods for the last step.
+*/
+gdImagePtr gdImageScaleNearestNeighbour(gdImagePtr im, const unsigned int width, const unsigned int height)
+{
+ const unsigned long new_width = MAX(1, width);
+ const unsigned long new_height = MAX(1, height);
+ const float dx = (float)im->sx / (float)new_width;
+ const float dy = (float)im->sy / (float)new_height;
+ const gdFixed f_dx = gd_ftofx(dx);
+ const gdFixed f_dy = gd_ftofx(dy);
+
+ gdImagePtr dst_img;
+ unsigned long dst_offset_x;
+ unsigned long dst_offset_y = 0;
+ unsigned int i;
+
+ dst_img = gdImageCreateTrueColor(new_width, new_height);
+
+ if (dst_img == NULL) {
+ return NULL;
+ }
+
+ for (i=0; i<new_height; i++) {
+ unsigned int j;
+ dst_offset_x = 0;
+ if (im->trueColor) {
+ for (j=0; j<new_width; j++) {
+ const gdFixed f_i = gd_itofx(i);
+ const gdFixed f_j = gd_itofx(j);
+ const gdFixed f_a = gd_mulfx(f_i, f_dy);
+ const gdFixed f_b = gd_mulfx(f_j, f_dx);
+ const long m = gd_fxtoi(f_a);
+ const long n = gd_fxtoi(f_b);
+
+ dst_img->tpixels[dst_offset_y][dst_offset_x++] = im->tpixels[m][n];
+ }
+ } else {
+ for (j=0; j<new_width; j++) {
+ const gdFixed f_i = gd_itofx(i);
+ const gdFixed f_j = gd_itofx(j);
+ const gdFixed f_a = gd_mulfx(f_i, f_dy);
+ const gdFixed f_b = gd_mulfx(f_j, f_dx);
+ const long m = gd_fxtoi(f_a);
+ const long n = gd_fxtoi(f_b);
+
+ dst_img->tpixels[dst_offset_y][dst_offset_x++] = colorIndex2RGBA(im->pixels[m][n]);
+ }
+ }
+ dst_offset_y++;
+ }
+ return dst_img;
+}
+
+static inline int getPixelOverflowColorTC(gdImagePtr im, const int x, const int y, const int color)
+{
+ if (gdImageBoundsSafe(im, x, y)) {
+ const int c = im->tpixels[y][x];
+ if (c == im->transparent) {
+ return gdTrueColorAlpha(0, 0, 0, 127);
+ }
+ return c;
+ } else {
+ register int border;
+ if (y < im->cy1) {
+ border = im->tpixels[0][im->cx1];
+ goto processborder;
+ }
+
+ if (y < im->cy1) {
+ border = im->tpixels[0][im->cx1];
+ goto processborder;
+ }
+
+ if (y > im->cy2) {
+ if (x >= im->cx1 && x <= im->cx1) {
+ border = im->tpixels[im->cy2][x];
+ goto processborder;
+ } else {
+ return gdTrueColorAlpha(0, 0, 0, 127);
+ }
+ }
+
+ /* y is bound safe at this point */
+ if (x < im->cx1) {
+ border = im->tpixels[y][im->cx1];
+ goto processborder;
+ }
+
+ if (x > im->cx2) {
+ border = im->tpixels[y][im->cx2];
+ }
+
+processborder:
+ if (border == im->transparent) {
+ return gdTrueColorAlpha(0, 0, 0, 127);
+ } else{
+ return gdTrueColorAlpha(gdTrueColorGetRed(border), gdTrueColorGetGreen(border), gdTrueColorGetBlue(border), 127);
+ }
+ }
+}
+
+static gdImagePtr gdImageScaleBilinearPalette(gdImagePtr im, const unsigned int new_width, const unsigned int new_height)
+{
+ long _width = MAX(1, new_width);
+ long _height = MAX(1, new_height);
+ float dx = (float)gdImageSX(im) / (float)_width;
+ float dy = (float)gdImageSY(im) / (float)_height;
+ gdFixed f_dx = gd_ftofx(dx);
+ gdFixed f_dy = gd_ftofx(dy);
+ gdFixed f_1 = gd_itofx(1);
+
+ int dst_offset_h;
+ int dst_offset_v = 0;
+ long i;
+ gdImagePtr new_img;
+ const int transparent = im->transparent;
+
+ new_img = gdImageCreateTrueColor(new_width, new_height);
+ if (new_img == NULL) {
+ return NULL;
+ }
+ new_img->transparent = gdTrueColorAlpha(im->red[transparent], im->green[transparent], im->blue[transparent], im->alpha[transparent]);
+
+ for (i=0; i < _height; i++) {
+ long j;
+ const gdFixed f_i = gd_itofx(i);
+ const gdFixed f_a = gd_mulfx(f_i, f_dy);
+ register long m = gd_fxtoi(f_a);
+
+ dst_offset_h = 0;
+
+ for (j=0; j < _width; j++) {
+ /* Update bitmap */
+ gdFixed f_j = gd_itofx(j);
+ gdFixed f_b = gd_mulfx(f_j, f_dx);
+
+ const long n = gd_fxtoi(f_b);
+ gdFixed f_f = f_a - gd_itofx(m);
+ gdFixed f_g = f_b - gd_itofx(n);
+
+ const gdFixed f_w1 = gd_mulfx(f_1-f_f, f_1-f_g);
+ const gdFixed f_w2 = gd_mulfx(f_1-f_f, f_g);
+ const gdFixed f_w3 = gd_mulfx(f_f, f_1-f_g);
+ const gdFixed f_w4 = gd_mulfx(f_f, f_g);
+ unsigned int pixel1;
+ unsigned int pixel2;
+ unsigned int pixel3;
+ unsigned int pixel4;
+ register gdFixed f_r1, f_r2, f_r3, f_r4,
+ f_g1, f_g2, f_g3, f_g4,
+ f_b1, f_b2, f_b3, f_b4,
+ f_a1, f_a2, f_a3, f_a4;
+
+ /* zero for the background color, nothig gets outside anyway */
+ pixel1 = getPixelOverflowPalette(im, n, m, 0);
+ pixel2 = getPixelOverflowPalette(im, n + 1, m, 0);
+ pixel3 = getPixelOverflowPalette(im, n, m + 1, 0);
+ pixel4 = getPixelOverflowPalette(im, n + 1, m + 1, 0);
+
+ f_r1 = gd_itofx(gdTrueColorGetRed(pixel1));
+ f_r2 = gd_itofx(gdTrueColorGetRed(pixel2));
+ f_r3 = gd_itofx(gdTrueColorGetRed(pixel3));
+ f_r4 = gd_itofx(gdTrueColorGetRed(pixel4));
+ f_g1 = gd_itofx(gdTrueColorGetGreen(pixel1));
+ f_g2 = gd_itofx(gdTrueColorGetGreen(pixel2));
+ f_g3 = gd_itofx(gdTrueColorGetGreen(pixel3));
+ f_g4 = gd_itofx(gdTrueColorGetGreen(pixel4));
+ f_b1 = gd_itofx(gdTrueColorGetBlue(pixel1));
+ f_b2 = gd_itofx(gdTrueColorGetBlue(pixel2));
+ f_b3 = gd_itofx(gdTrueColorGetBlue(pixel3));
+ f_b4 = gd_itofx(gdTrueColorGetBlue(pixel4));
+ f_a1 = gd_itofx(gdTrueColorGetAlpha(pixel1));
+ f_a2 = gd_itofx(gdTrueColorGetAlpha(pixel2));
+ f_a3 = gd_itofx(gdTrueColorGetAlpha(pixel3));
+ f_a4 = gd_itofx(gdTrueColorGetAlpha(pixel4));
+
+ {
+ const char red = (char) gd_fxtoi(gd_mulfx(f_w1, f_r1) + gd_mulfx(f_w2, f_r2) + gd_mulfx(f_w3, f_r3) + gd_mulfx(f_w4, f_r4));
+ const char green = (char) gd_fxtoi(gd_mulfx(f_w1, f_g1) + gd_mulfx(f_w2, f_g2) + gd_mulfx(f_w3, f_g3) + gd_mulfx(f_w4, f_g4));
+ const char blue = (char) gd_fxtoi(gd_mulfx(f_w1, f_b1) + gd_mulfx(f_w2, f_b2) + gd_mulfx(f_w3, f_b3) + gd_mulfx(f_w4, f_b4));
+ const char alpha = (char) gd_fxtoi(gd_mulfx(f_w1, f_a1) + gd_mulfx(f_w2, f_a2) + gd_mulfx(f_w3, f_a3) + gd_mulfx(f_w4, f_a4));
+
+ new_img->tpixels[dst_offset_v][dst_offset_h] = gdTrueColorAlpha(red, green, blue, alpha);
+ }
+
+ dst_offset_h++;
+ }
+
+ dst_offset_v++;
+ }
+ return new_img;
+}
+
+static gdImagePtr gdImageScaleBilinearTC(gdImagePtr im, const unsigned int new_width, const unsigned int new_height)
+{
+ long dst_w = MAX(1, new_width);
+ long dst_h = MAX(1, new_height);
+ float dx = (float)gdImageSX(im) / (float)dst_w;
+ float dy = (float)gdImageSY(im) / (float)dst_h;
+ gdFixed f_dx = gd_ftofx(dx);
+ gdFixed f_dy = gd_ftofx(dy);
+ gdFixed f_1 = gd_itofx(1);
+
+ int dst_offset_h;
+ int dst_offset_v = 0;
+ int dwSrcTotalOffset;
+ long i;
+ gdImagePtr new_img;
+
+ new_img = gdImageCreateTrueColor(new_width, new_height);
+ if (!new_img){
+ return NULL;
+ }
+
+ for (i=0; i < dst_h; i++) {
+ long j;
+ dst_offset_h = 0;
+ for (j=0; j < dst_w; j++) {
+ /* Update bitmap */
+ gdFixed f_i = gd_itofx(i);
+ gdFixed f_j = gd_itofx(j);
+ gdFixed f_a = gd_mulfx(f_i, f_dy);
+ gdFixed f_b = gd_mulfx(f_j, f_dx);
+ const long m = gd_fxtoi(f_a);
+ const long n = gd_fxtoi(f_b);
+ gdFixed f_f = f_a - gd_itofx(m);
+ gdFixed f_g = f_b - gd_itofx(n);
+
+ const gdFixed f_w1 = gd_mulfx(f_1-f_f, f_1-f_g);
+ const gdFixed f_w2 = gd_mulfx(f_1-f_f, f_g);
+ const gdFixed f_w3 = gd_mulfx(f_f, f_1-f_g);
+ const gdFixed f_w4 = gd_mulfx(f_f, f_g);
+ unsigned int pixel1;
+ unsigned int pixel2;
+ unsigned int pixel3;
+ unsigned int pixel4;
+ register gdFixed f_r1, f_r2, f_r3, f_r4,
+ f_g1, f_g2, f_g3, f_g4,
+ f_b1, f_b2, f_b3, f_b4,
+ f_a1, f_a2, f_a3, f_a4;
+ dwSrcTotalOffset = m + n;
+ /* 0 for bgColor, nothing gets outside anyway */
+ pixel1 = getPixelOverflowTC(im, n, m, 0);
+ pixel2 = getPixelOverflowTC(im, n + 1, m, 0);
+ pixel3 = getPixelOverflowTC(im, n, m + 1, 0);
+ pixel4 = getPixelOverflowTC(im, n + 1, m + 1, 0);
+
+ f_r1 = gd_itofx(gdTrueColorGetRed(pixel1));
+ f_r2 = gd_itofx(gdTrueColorGetRed(pixel2));
+ f_r3 = gd_itofx(gdTrueColorGetRed(pixel3));
+ f_r4 = gd_itofx(gdTrueColorGetRed(pixel4));
+ f_g1 = gd_itofx(gdTrueColorGetGreen(pixel1));
+ f_g2 = gd_itofx(gdTrueColorGetGreen(pixel2));
+ f_g3 = gd_itofx(gdTrueColorGetGreen(pixel3));
+ f_g4 = gd_itofx(gdTrueColorGetGreen(pixel4));
+ f_b1 = gd_itofx(gdTrueColorGetBlue(pixel1));
+ f_b2 = gd_itofx(gdTrueColorGetBlue(pixel2));
+ f_b3 = gd_itofx(gdTrueColorGetBlue(pixel3));
+ f_b4 = gd_itofx(gdTrueColorGetBlue(pixel4));
+ f_a1 = gd_itofx(gdTrueColorGetAlpha(pixel1));
+ f_a2 = gd_itofx(gdTrueColorGetAlpha(pixel2));
+ f_a3 = gd_itofx(gdTrueColorGetAlpha(pixel3));
+ f_a4 = gd_itofx(gdTrueColorGetAlpha(pixel4));
+ {
+ const char red = (char) gd_fxtoi(gd_mulfx(f_w1, f_r1) + gd_mulfx(f_w2, f_r2) + gd_mulfx(f_w3, f_r3) + gd_mulfx(f_w4, f_r4));
+ const char green = (char) gd_fxtoi(gd_mulfx(f_w1, f_g1) + gd_mulfx(f_w2, f_g2) + gd_mulfx(f_w3, f_g3) + gd_mulfx(f_w4, f_g4));
+ const char blue = (char) gd_fxtoi(gd_mulfx(f_w1, f_b1) + gd_mulfx(f_w2, f_b2) + gd_mulfx(f_w3, f_b3) + gd_mulfx(f_w4, f_b4));
+ const char alpha = (char) gd_fxtoi(gd_mulfx(f_w1, f_a1) + gd_mulfx(f_w2, f_a2) + gd_mulfx(f_w3, f_a3) + gd_mulfx(f_w4, f_a4));
+
+ new_img->tpixels[dst_offset_v][dst_offset_h] = gdTrueColorAlpha(red, green, blue, alpha);
+ }
+
+ dst_offset_h++;
+ }
+
+ dst_offset_v++;
+ }
+ return new_img;
+}
+
+gdImagePtr gdImageScaleBilinear(gdImagePtr im, const unsigned int new_width, const unsigned int new_height)
+{
+ if (im->trueColor) {
+ return gdImageScaleBilinearTC(im, new_width, new_height);
+ } else {
+ return gdImageScaleBilinearPalette(im, new_width, new_height);
+ }
+}
+
+gdImagePtr gdImageScaleBicubicFixed(gdImagePtr src, const unsigned int width, const unsigned int height)
+{
+ const long new_width = MAX(1, width);
+ const long new_height = MAX(1, height);
+ const int src_w = gdImageSX(src);
+ const int src_h = gdImageSY(src);
+ const gdFixed f_dx = gd_ftofx((float)src_w / (float)new_width);
+ const gdFixed f_dy = gd_ftofx((float)src_h / (float)new_height);
+ const gdFixed f_1 = gd_itofx(1);
+ const gdFixed f_2 = gd_itofx(2);
+ const gdFixed f_4 = gd_itofx(4);
+ const gdFixed f_6 = gd_itofx(6);
+ const gdFixed f_gamma = gd_ftofx(1.04f);
+ gdImagePtr dst;
+
+ unsigned int dst_offset_x;
+ unsigned int dst_offset_y = 0;
+ long i;
+
+ /* impact perf a bit, but not that much. Implementation for palette
+ images can be done at a later point.
+ */
+ if (src->trueColor == 0) {
+ gdImagePaletteToTrueColor(src);
+ }
+
+ dst = gdImageCreateTrueColor(new_width, new_height);
+ if (!dst) {
+ return NULL;
+ }
+
+ dst->saveAlphaFlag = 1;
+
+ for (i=0; i < new_height; i++) {
+ long j;
+ dst_offset_x = 0;
+
+ for (j=0; j < new_width; j++) {
+ const gdFixed f_a = gd_mulfx(gd_itofx(i), f_dy);
+ const gdFixed f_b = gd_mulfx(gd_itofx(j), f_dx);
+ const long m = gd_fxtoi(f_a);
+ const long n = gd_fxtoi(f_b);
+ const gdFixed f_f = f_a - gd_itofx(m);
+ const gdFixed f_g = f_b - gd_itofx(n);
+ unsigned int src_offset_x[16], src_offset_y[16];
+ long k;
+ register gdFixed f_red = 0, f_green = 0, f_blue = 0, f_alpha = 0;
+ unsigned char red, green, blue, alpha = 0;
+ int *dst_row = dst->tpixels[dst_offset_y];
+
+ if ((m < 1) || (n < 1)) {
+ src_offset_x[0] = n;
+ src_offset_y[0] = m;
+ } else {
+ src_offset_x[0] = n - 1;
+ src_offset_y[0] = m;
+ }
+
+ if (m < 1) {
+ src_offset_x[1] = n;
+ src_offset_y[1] = m;
+ } else {
+ src_offset_x[1] = n;
+ src_offset_y[1] = m;
+ }
+
+ if ((m < 1) || (n >= src_w - 1)) {
+ src_offset_x[2] = n;
+ src_offset_y[2] = m;
+ } else {
+ src_offset_x[2] = n + 1;
+ src_offset_y[2] = m;
+ }
+
+ if ((m < 1) || (n >= src_w - 2)) {
+ src_offset_x[3] = n;
+ src_offset_y[3] = m;
+ } else {
+ src_offset_x[3] = n + 1 + 1;
+ src_offset_y[3] = m;
+ }
+
+ if (n < 1) {
+ src_offset_x[4] = n;
+ src_offset_y[4] = m;
+ } else {
+ src_offset_x[4] = n - 1;
+ src_offset_y[4] = m;
+ }
+
+ src_offset_x[5] = n;
+ src_offset_y[5] = m;
+ if (n >= src_w-1) {
+ src_offset_x[6] = n;
+ src_offset_y[6] = m;
+ } else {
+ src_offset_x[6] = n + 1;
+ src_offset_y[6] = m;
+ }
+
+ if (n >= src_w - 2) {
+ src_offset_x[7] = n;
+ src_offset_y[7] = m;
+ } else {
+ src_offset_x[7] = n + 1 + 1;
+ src_offset_y[7] = m;
+ }
+
+ if ((m >= src_h - 1) || (n < 1)) {
+ src_offset_x[8] = n;
+ src_offset_y[8] = m;
+ } else {
+ src_offset_x[8] = n - 1;
+ src_offset_y[8] = m;
+ }
+
+ if (m >= src_h - 1) {
+ src_offset_x[8] = n;
+ src_offset_y[8] = m;
+ } else {
+ src_offset_x[9] = n;
+ src_offset_y[9] = m;
+ }
+
+ if ((m >= src_h-1) || (n >= src_w-1)) {
+ src_offset_x[10] = n;
+ src_offset_y[10] = m;
+ } else {
+ src_offset_x[10] = n + 1;
+ src_offset_y[10] = m;
+ }
+
+ if ((m >= src_h - 1) || (n >= src_w - 2)) {
+ src_offset_x[11] = n;
+ src_offset_y[11] = m;
+ } else {
+ src_offset_x[11] = n + 1 + 1;
+ src_offset_y[11] = m;
+ }
+
+ if ((m >= src_h - 2) || (n < 1)) {
+ src_offset_x[12] = n;
+ src_offset_y[12] = m;
+ } else {
+ src_offset_x[12] = n - 1;
+ src_offset_y[12] = m;
+ }
+
+ if (m >= src_h - 2) {
+ src_offset_x[13] = n;
+ src_offset_y[13] = m;
+ } else {
+ src_offset_x[13] = n;
+ src_offset_y[13] = m;
+ }
+
+ if ((m >= src_h - 2) || (n >= src_w - 1)) {
+ src_offset_x[14] = n;
+ src_offset_y[14] = m;
+ } else {
+ src_offset_x[14] = n + 1;
+ src_offset_y[14] = m;
+ }
+
+ if ((m >= src_h - 2) || (n >= src_w - 2)) {
+ src_offset_x[15] = n;
+ src_offset_y[15] = m;
+ } else {
+ src_offset_x[15] = n + 1 + 1;
+ src_offset_y[15] = m;
+ }
+
+ for (k = -1; k < 3; k++) {
+ const gdFixed f = gd_itofx(k)-f_f;
+ const gdFixed f_fm1 = f - f_1;
+ const gdFixed f_fp1 = f + f_1;
+ const gdFixed f_fp2 = f + f_2;
+ register gdFixed f_a = 0, f_b = 0, f_d = 0, f_c = 0;
+ register gdFixed f_RY;
+ int l;
+
+ if (f_fp2 > 0) f_a = gd_mulfx(f_fp2, gd_mulfx(f_fp2,f_fp2));
+ if (f_fp1 > 0) f_b = gd_mulfx(f_fp1, gd_mulfx(f_fp1,f_fp1));
+ if (f > 0) f_c = gd_mulfx(f, gd_mulfx(f,f));
+ if (f_fm1 > 0) f_d = gd_mulfx(f_fm1, gd_mulfx(f_fm1,f_fm1));
+
+ f_RY = gd_divfx((f_a - gd_mulfx(f_4,f_b) + gd_mulfx(f_6,f_c) - gd_mulfx(f_4,f_d)),f_6);
+
+ for (l = -1; l < 3; l++) {
+ const gdFixed f = gd_itofx(l) - f_g;
+ const gdFixed f_fm1 = f - f_1;
+ const gdFixed f_fp1 = f + f_1;
+ const gdFixed f_fp2 = f + f_2;
+ register gdFixed f_a = 0, f_b = 0, f_c = 0, f_d = 0;
+ register gdFixed f_RX, f_R, f_rs, f_gs, f_bs, f_ba;
+ register int c;
+ const int _k = ((k+1)*4) + (l+1);
+
+ if (f_fp2 > 0) f_a = gd_mulfx(f_fp2,gd_mulfx(f_fp2,f_fp2));
+
+ if (f_fp1 > 0) f_b = gd_mulfx(f_fp1,gd_mulfx(f_fp1,f_fp1));
+
+ if (f > 0) f_c = gd_mulfx(f,gd_mulfx(f,f));
+
+ if (f_fm1 > 0) f_d = gd_mulfx(f_fm1,gd_mulfx(f_fm1,f_fm1));
+
+ f_RX = gd_divfx((f_a-gd_mulfx(f_4,f_b)+gd_mulfx(f_6,f_c)-gd_mulfx(f_4,f_d)),f_6);
+ f_R = gd_mulfx(f_RY,f_RX);
+
+ c = src->tpixels[*(src_offset_y + _k)][*(src_offset_x + _k)];
+ f_rs = gd_itofx(gdTrueColorGetRed(c));
+ f_gs = gd_itofx(gdTrueColorGetGreen(c));
+ f_bs = gd_itofx(gdTrueColorGetBlue(c));
+ f_ba = gd_itofx(gdTrueColorGetAlpha(c));
+
+ f_red += gd_mulfx(f_rs,f_R);
+ f_green += gd_mulfx(f_gs,f_R);
+ f_blue += gd_mulfx(f_bs,f_R);
+ f_alpha += gd_mulfx(f_ba,f_R);
+ }
+ }
+
+ red = (unsigned char) CLAMP(gd_fxtoi(gd_mulfx(f_red, f_gamma)), 0, 255);
+ green = (unsigned char) CLAMP(gd_fxtoi(gd_mulfx(f_green, f_gamma)), 0, 255);
+ blue = (unsigned char) CLAMP(gd_fxtoi(gd_mulfx(f_blue, f_gamma)), 0, 255);
+ alpha = (unsigned char) CLAMP(gd_fxtoi(gd_mulfx(f_alpha, f_gamma)), 0, 127);
+
+ *(dst_row + dst_offset_x) = gdTrueColorAlpha(red, green, blue, alpha);
+
+ dst_offset_x++;
+ }
+ dst_offset_y++;
+ }
+ return dst;
+}
+
+gdImagePtr gdImageScale(const gdImagePtr src, const unsigned int new_width, const unsigned int new_height)
+{
+ gdImagePtr im_scaled = NULL;
+
+ if (src == NULL || src->interpolation_id < 0 || src->interpolation_id > GD_METHOD_COUNT) {
+ return 0;
+ }
+
+ switch (src->interpolation_id) {
+ /*Special cases, optimized implementations */
+ case GD_NEAREST_NEIGHBOUR:
+ im_scaled = gdImageScaleNearestNeighbour(src, new_width, new_height);
+ break;
+
+ case GD_BILINEAR_FIXED:
+ im_scaled = gdImageScaleBilinear(src, new_width, new_height);
+ break;
+
+ case GD_BICUBIC_FIXED:
+ im_scaled = gdImageScaleBicubicFixed(src, new_width, new_height);
+ break;
+
+ /* generic */
+ default:
+ if (src->interpolation == NULL) {
+ return NULL;
+ }
+ im_scaled = gdImageScaleTwoPass(src, src->sx, src->sy, new_width, new_height);
+ break;
+ }
+ return im_scaled;
+}
+
+gdImagePtr gdImageRotateNearestNeighbour(gdImagePtr src, const float degrees, const int bgColor)
+{
+ float _angle = ((float) (-degrees / 180.0f) * (float)M_PI);
+ const int src_w = gdImageSX(src);
+ const int src_h = gdImageSY(src);
+ const unsigned int new_width = (unsigned int)(abs((int)(src_w * cos(_angle))) + abs((int)(src_h * sin(_angle))) + 0.5f);
+ const unsigned int new_height = (unsigned int)(abs((int)(src_w * sin(_angle))) + abs((int)(src_h * cos(_angle))) + 0.5f);
+ const gdFixed f_0_5 = gd_ftofx(0.5f);
+ const gdFixed f_H = gd_itofx(src_h/2);
+ const gdFixed f_W = gd_itofx(src_w/2);
+ const gdFixed f_cos = gd_ftofx(cos(-_angle));
+ const gdFixed f_sin = gd_ftofx(sin(-_angle));
+
+ unsigned int dst_offset_x;
+ unsigned int dst_offset_y = 0;
+ unsigned int i;
+ gdImagePtr dst;
+
+ /* impact perf a bit, but not that much. Implementation for palette
+ images can be done at a later point.
+ */
+ if (src->trueColor == 0) {
+ gdImagePaletteToTrueColor(src);
+ }
+
+ dst = gdImageCreateTrueColor(new_width, new_height);
+ if (!dst) {
+ return NULL;
+ }
+ dst->saveAlphaFlag = 1;
+ for (i = 0; i < new_height; i++) {
+ unsigned int j;
+ dst_offset_x = 0;
+ for (j = 0; j < new_width; j++) {
+ gdFixed f_i = gd_itofx(i - new_height/2);
+ gdFixed f_j = gd_itofx(j-new_width/2);
+ gdFixed f_m = gd_mulfx(f_j,f_sin) + gd_mulfx(f_i,f_cos) + f_0_5 + f_H;
+ gdFixed f_n = gd_mulfx(f_j,f_cos) - gd_mulfx(f_i,f_sin) + f_0_5 + f_W;
+ long m = gd_fxtoi(f_m);
+ long n = gd_fxtoi(f_n);
+
+ if ((m > 0) && (m < src_h-1) && (n > 0) && (n < src_w-1)) {
+ if (dst_offset_y < new_height) {
+ dst->tpixels[dst_offset_y][dst_offset_x++] = src->tpixels[m][n];
+ }
+ } else {
+ if (dst_offset_y < new_height) {
+ dst->tpixels[dst_offset_y][dst_offset_x++] = bgColor;
+ }
+ }
+ }
+ dst_offset_y++;
+ }
+ return dst;
+}
+
+gdImagePtr gdImageRotateGeneric(gdImagePtr src, const float degrees, const int bgColor)
+{
+ float _angle = ((float) (-degrees / 180.0f) * (float)M_PI);
+ const int src_w = gdImageSX(src);
+ const int src_h = gdImageSY(src);
+ const unsigned int new_width = (unsigned int)(abs((int)(src_w * cos(_angle))) + abs((int)(src_h * sin(_angle))) + 0.5f);
+ const unsigned int new_height = (unsigned int)(abs((int)(src_w * sin(_angle))) + abs((int)(src_h * cos(_angle))) + 0.5f);
+ const gdFixed f_0_5 = gd_ftofx(0.5f);
+ const gdFixed f_H = gd_itofx(src_h/2);
+ const gdFixed f_W = gd_itofx(src_w/2);
+ const gdFixed f_cos = gd_ftofx(cos(-_angle));
+ const gdFixed f_sin = gd_ftofx(sin(-_angle));
+
+ unsigned int dst_offset_x;
+ unsigned int dst_offset_y = 0;
+ unsigned int i;
+ gdImagePtr dst;
+
+ const gdFixed f_slop_y = f_sin;
+ const gdFixed f_slop_x = f_cos;
+ const gdFixed f_slop = f_slop_x > 0 && f_slop_x > 0 ?
+ f_slop_x > f_slop_y ? gd_divfx(f_slop_y, f_slop_x) : gd_divfx(f_slop_x, f_slop_y)
+ : 0;
+
+ /* impact perf a bit, but not that much. Implementation for palette
+ images can be done at a later point.
+ */
+ if (src->trueColor == 0) {
+ gdImagePaletteToTrueColor(src);
+ }
+
+ dst = gdImageCreateTrueColor(new_width, new_height);
+ if (!dst) {
+ return NULL;
+ }
+ dst->saveAlphaFlag = 1;
+
+ for (i = 0; i < new_height; i++) {
+ unsigned int j;
+ dst_offset_x = 0;
+ for (j = 0; j < new_width; j++) {
+ gdFixed f_i = gd_itofx(i - new_height/ 2);
+ gdFixed f_j = gd_itofx(j -new_width / 2);
+ gdFixed f_m = gd_mulfx(f_j,f_sin) + gd_mulfx(f_i,f_cos) + f_0_5 + f_H;
+ gdFixed f_n = gd_mulfx(f_j,f_cos) - gd_mulfx(f_i,f_sin) + f_0_5 + f_W;
+ long m = gd_fxtoi(f_m);
+ long n = gd_fxtoi(f_n);
+
+ if ((n <= 0) || (m <= 0) || (m >= src_h) || (n >= src_w)) {
+ dst->tpixels[dst_offset_y][dst_offset_x++] = bgColor;
+ } else if ((n <= 1) || (m <= 1) || (m >= src_h - 1) || (n >= src_w - 1)) {
+ gdFixed f_127 = gd_itofx(127);
+ register int c = getPixelInterpolated(src, n, m, bgColor);
+ c = c | (( gdTrueColorGetAlpha(c) + ((int)(127* gd_fxtof(f_slop)))) << 24);
+
+ dst->tpixels[dst_offset_y][dst_offset_x++] = _color_blend(bgColor, c);
+ } else {
+ dst->tpixels[dst_offset_y][dst_offset_x++] = getPixelInterpolated(src, n, m, bgColor);
+ }
+ }
+ dst_offset_y++;
+ }
+ return dst;
+}
+
+gdImagePtr gdImageRotateBilinear(gdImagePtr src, const float degrees, const int bgColor)
+{
+ float _angle = (float)((- degrees / 180.0f) * M_PI);
+ const unsigned int src_w = gdImageSX(src);
+ const unsigned int src_h = gdImageSY(src);
+ unsigned int new_width = abs((int)(src_w*cos(_angle))) + abs((int)(src_h*sin(_angle) + 0.5f));
+ unsigned int new_height = abs((int)(src_w*sin(_angle))) + abs((int)(src_h*cos(_angle) + 0.5f));
+ const gdFixed f_0_5 = gd_ftofx(0.5f);
+ const gdFixed f_H = gd_itofx(src_h/2);
+ const gdFixed f_W = gd_itofx(src_w/2);
+ const gdFixed f_cos = gd_ftofx(cos(-_angle));
+ const gdFixed f_sin = gd_ftofx(sin(-_angle));
+ const gdFixed f_1 = gd_itofx(1);
+ unsigned int i;
+ unsigned int dst_offset_x;
+ unsigned int dst_offset_y = 0;
+ unsigned int src_offset_x, src_offset_y;
+ gdImagePtr dst;
+
+ /* impact perf a bit, but not that much. Implementation for palette
+ images can be done at a later point.
+ */
+ if (src->trueColor == 0) {
+ gdImagePaletteToTrueColor(src);
+ }
+
+ dst = gdImageCreateTrueColor(new_width, new_height);
+ if (dst == NULL) {
+ return NULL;
+ }
+ dst->saveAlphaFlag = 1;
+
+ for (i = 0; i < new_height; i++) {
+ unsigned int j;
+ dst_offset_x = 0;
+
+ for (j=0; j < new_width; j++) {
+ const gdFixed f_i = gd_itofx(i-new_height/2);
+ const gdFixed f_j = gd_itofx(j-new_width/2);
+ const gdFixed f_m = gd_mulfx(f_j,f_sin) + gd_mulfx(f_i,f_cos) + f_0_5 + f_H;
+ const gdFixed f_n = gd_mulfx(f_j,f_cos) - gd_mulfx(f_i,f_sin) + f_0_5 + f_W;
+ const unsigned int m = gd_fxtoi(f_m);
+ const unsigned int n = gd_fxtoi(f_n);
+
+ if ((m > 0) && (m < src_h - 1) && (n > 0) && (n < src_w - 1)) {
+ const gdFixed f_f = f_m - gd_itofx(m);
+ const gdFixed f_g = f_n - gd_itofx(n);
+ const gdFixed f_w1 = gd_mulfx(f_1-f_f, f_1-f_g);
+ const gdFixed f_w2 = gd_mulfx(f_1-f_f, f_g);
+ const gdFixed f_w3 = gd_mulfx(f_f, f_1-f_g);
+ const gdFixed f_w4 = gd_mulfx(f_f, f_g);
+
+ if (n < src_w - 1) {
+ src_offset_x = m + 1;
+ src_offset_y = n;
+ }
+
+ if (m < src_h-1) {
+ src_offset_x = m;
+ src_offset_y = n + 1;
+ }
+
+ if (!((n >= src_w-1) || (m >= src_h-1))) {
+ src_offset_x = m + 1;
+ src_offset_y = n + 1;
+ }
+ {
+ const int pixel1 = src->tpixels[src_offset_y][src_offset_x];
+ register int pixel2, pixel3, pixel4;
+
+ if (src_offset_y + 1 >= src_h) {
+ pixel2 = bgColor;
+ pixel3 = bgColor;
+ pixel4 = bgColor;
+ } else if (src_offset_x + 1 >= src_w) {
+ pixel2 = bgColor;
+ pixel3 = bgColor;
+ pixel4 = bgColor;
+ } else {
+ pixel2 = src->tpixels[src_offset_y][src_offset_x + 1];
+ pixel3 = src->tpixels[src_offset_y + 1][src_offset_x];
+ pixel4 = src->tpixels[src_offset_y + 1][src_offset_x + 1];
+ }
+ {
+ const gdFixed f_r1 = gd_itofx(gdTrueColorGetRed(pixel1));
+ const gdFixed f_r2 = gd_itofx(gdTrueColorGetRed(pixel2));
+ const gdFixed f_r3 = gd_itofx(gdTrueColorGetRed(pixel3));
+ const gdFixed f_r4 = gd_itofx(gdTrueColorGetRed(pixel4));
+ const gdFixed f_g1 = gd_itofx(gdTrueColorGetGreen(pixel1));
+ const gdFixed f_g2 = gd_itofx(gdTrueColorGetGreen(pixel2));
+ const gdFixed f_g3 = gd_itofx(gdTrueColorGetGreen(pixel3));
+ const gdFixed f_g4 = gd_itofx(gdTrueColorGetGreen(pixel4));
+ const gdFixed f_b1 = gd_itofx(gdTrueColorGetBlue(pixel1));
+ const gdFixed f_b2 = gd_itofx(gdTrueColorGetBlue(pixel2));
+ const gdFixed f_b3 = gd_itofx(gdTrueColorGetBlue(pixel3));
+ const gdFixed f_b4 = gd_itofx(gdTrueColorGetBlue(pixel4));
+ const gdFixed f_a1 = gd_itofx(gdTrueColorGetAlpha(pixel1));
+ const gdFixed f_a2 = gd_itofx(gdTrueColorGetAlpha(pixel2));
+ const gdFixed f_a3 = gd_itofx(gdTrueColorGetAlpha(pixel3));
+ const gdFixed f_a4 = gd_itofx(gdTrueColorGetAlpha(pixel4));
+ const gdFixed f_red = gd_mulfx(f_w1, f_r1) + gd_mulfx(f_w2, f_r2) + gd_mulfx(f_w3, f_r3) + gd_mulfx(f_w4, f_r4);
+ const gdFixed f_green = gd_mulfx(f_w1, f_g1) + gd_mulfx(f_w2, f_g2) + gd_mulfx(f_w3, f_g3) + gd_mulfx(f_w4, f_g4);
+ const gdFixed f_blue = gd_mulfx(f_w1, f_b1) + gd_mulfx(f_w2, f_b2) + gd_mulfx(f_w3, f_b3) + gd_mulfx(f_w4, f_b4);
+ const gdFixed f_alpha = gd_mulfx(f_w1, f_a1) + gd_mulfx(f_w2, f_a2) + gd_mulfx(f_w3, f_a3) + gd_mulfx(f_w4, f_a4);
+
+ const unsigned char red = (unsigned char) CLAMP(gd_fxtoi(f_red), 0, 255);
+ const unsigned char green = (unsigned char) CLAMP(gd_fxtoi(f_green), 0, 255);
+ const unsigned char blue = (unsigned char) CLAMP(gd_fxtoi(f_blue), 0, 255);
+ const unsigned char alpha = (unsigned char) CLAMP(gd_fxtoi(f_alpha), 0, 127);
+
+ dst->tpixels[dst_offset_y][dst_offset_x++] = gdTrueColorAlpha(red, green, blue, alpha);
+ }
+ }
+ } else {
+ dst->tpixels[dst_offset_y][dst_offset_x++] = bgColor;
+ }
+ }
+ dst_offset_y++;
+ }
+ return dst;
+}
+
+gdImagePtr gdImageRotateBicubicFixed(gdImagePtr src, const float degrees, const int bgColor)
+{
+ const float _angle = (float)((- degrees / 180.0f) * M_PI);
+ const int src_w = gdImageSX(src);
+ const int src_h = gdImageSY(src);
+ const unsigned int new_width = abs((int)(src_w*cos(_angle))) + abs((int)(src_h*sin(_angle) + 0.5f));
+ const unsigned int new_height = abs((int)(src_w*sin(_angle))) + abs((int)(src_h*cos(_angle) + 0.5f));
+ const gdFixed f_0_5 = gd_ftofx(0.5f);
+ const gdFixed f_H = gd_itofx(src_h/2);
+ const gdFixed f_W = gd_itofx(src_w/2);
+ const gdFixed f_cos = gd_ftofx(cos(-_angle));
+ const gdFixed f_sin = gd_ftofx(sin(-_angle));
+ const gdFixed f_1 = gd_itofx(1);
+ const gdFixed f_2 = gd_itofx(2);
+ const gdFixed f_4 = gd_itofx(4);
+ const gdFixed f_6 = gd_itofx(6);
+ const gdFixed f_gama = gd_ftofx(1.04f);
+
+ unsigned int dst_offset_x;
+ unsigned int dst_offset_y = 0;
+ unsigned int i;
+ gdImagePtr dst;
+
+ /* impact perf a bit, but not that much. Implementation for palette
+ images can be done at a later point.
+ */
+ if (src->trueColor == 0) {
+ gdImagePaletteToTrueColor(src);
+ }
+
+ dst = gdImageCreateTrueColor(new_width, new_height);
+
+ if (dst == NULL) {
+ return NULL;
+ }
+ dst->saveAlphaFlag = 1;
+
+ for (i=0; i < new_height; i++) {
+ unsigned int j;
+ dst_offset_x = 0;
+
+ for (j=0; j < new_width; j++) {
+ const gdFixed f_i = gd_itofx(i-new_height/2);
+ const gdFixed f_j = gd_itofx(j-new_width/2);
+ const gdFixed f_m = gd_mulfx(f_j,f_sin) + gd_mulfx(f_i,f_cos) + f_0_5 + f_H;
+ const gdFixed f_n = gd_mulfx(f_j,f_cos) - gd_mulfx(f_i,f_sin) + f_0_5 + f_W;
+ const int m = gd_fxtoi(f_m);
+ const int n = gd_fxtoi(f_n);
+
+ if ((m > 0) && (m < src_h - 1) && (n > 0) && (n < src_w-1)) {
+ const gdFixed f_f = f_m - gd_itofx(m);
+ const gdFixed f_g = f_n - gd_itofx(n);
+ unsigned int src_offset_x[16], src_offset_y[16];
+ unsigned char red, green, blue, alpha;
+ gdFixed f_red=0, f_green=0, f_blue=0, f_alpha=0;
+ int k;
+
+ if ((m < 1) || (n < 1)) {
+ src_offset_x[0] = n;
+ src_offset_y[0] = m;
+ } else {
+ src_offset_x[0] = n - 1;
+ src_offset_y[0] = m;
+ }
+
+ if (m < 1) {
+ src_offset_x[1] = n;
+ src_offset_y[1] = m;
+ } else {
+ src_offset_x[1] = n;
+ src_offset_y[1] = m ;
+ }
+
+ if ((m < 1) || (n >= src_w-1)) {
+ src_offset_x[2] = - 1;
+ src_offset_y[2] = - 1;
+ } else {
+ src_offset_x[2] = n + 1;
+ src_offset_y[2] = m ;
+ }
+
+ if ((m < 1) || (n >= src_w-2)) {
+ src_offset_x[3] = - 1;
+ src_offset_y[3] = - 1;
+ } else {
+ src_offset_x[3] = n + 1 + 1;
+ src_offset_y[3] = m ;
+ }
+
+ if (n < 1) {
+ src_offset_x[4] = - 1;
+ src_offset_y[4] = - 1;
+ } else {
+ src_offset_x[4] = n - 1;
+ src_offset_y[4] = m;
+ }
+
+ src_offset_x[5] = n;
+ src_offset_y[5] = m;
+ if (n >= src_w-1) {
+ src_offset_x[6] = - 1;
+ src_offset_y[6] = - 1;
+ } else {
+ src_offset_x[6] = n + 1;
+ src_offset_y[6] = m;
+ }
+
+ if (n >= src_w-2) {
+ src_offset_x[7] = - 1;
+ src_offset_y[7] = - 1;
+ } else {
+ src_offset_x[7] = n + 1 + 1;
+ src_offset_y[7] = m;
+ }
+
+ if ((m >= src_h-1) || (n < 1)) {
+ src_offset_x[8] = - 1;
+ src_offset_y[8] = - 1;
+ } else {
+ src_offset_x[8] = n - 1;
+ src_offset_y[8] = m;
+ }
+
+ if (m >= src_h-1) {
+ src_offset_x[8] = - 1;
+ src_offset_y[8] = - 1;
+ } else {
+ src_offset_x[9] = n;
+ src_offset_y[9] = m;
+ }
+
+ if ((m >= src_h-1) || (n >= src_w-1)) {
+ src_offset_x[10] = - 1;
+ src_offset_y[10] = - 1;
+ } else {
+ src_offset_x[10] = n + 1;
+ src_offset_y[10] = m;
+ }
+
+ if ((m >= src_h-1) || (n >= src_w-2)) {
+ src_offset_x[11] = - 1;
+ src_offset_y[11] = - 1;
+ } else {
+ src_offset_x[11] = n + 1 + 1;
+ src_offset_y[11] = m;
+ }
+
+ if ((m >= src_h-2) || (n < 1)) {
+ src_offset_x[12] = - 1;
+ src_offset_y[12] = - 1;
+ } else {
+ src_offset_x[12] = n - 1;
+ src_offset_y[12] = m;
+ }
+
+ if (m >= src_h-2) {
+ src_offset_x[13] = - 1;
+ src_offset_y[13] = - 1;
+ } else {
+ src_offset_x[13] = n;
+ src_offset_y[13] = m;
+ }
+
+ if ((m >= src_h-2) || (n >= src_w - 1)) {
+ src_offset_x[14] = - 1;
+ src_offset_y[14] = - 1;
+ } else {
+ src_offset_x[14] = n + 1;
+ src_offset_y[14] = m;
+ }
+
+ if ((m >= src_h-2) || (n >= src_w-2)) {
+ src_offset_x[15] = - 1;
+ src_offset_y[15] = - 1;
+ } else {
+ src_offset_x[15] = n + 1 + 1;
+ src_offset_y[15] = m;
+ }
+
+ for (k=-1; k<3; k++) {
+ const gdFixed f = gd_itofx(k)-f_f;
+ const gdFixed f_fm1 = f - f_1;
+ const gdFixed f_fp1 = f + f_1;
+ const gdFixed f_fp2 = f + f_2;
+ gdFixed f_a = 0, f_b = 0,f_c = 0, f_d = 0;
+ gdFixed f_RY;
+ int l;
+
+ if (f_fp2 > 0) {
+ f_a = gd_mulfx(f_fp2,gd_mulfx(f_fp2,f_fp2));
+ }
+
+ if (f_fp1 > 0) {
+ f_b = gd_mulfx(f_fp1,gd_mulfx(f_fp1,f_fp1));
+ }
+
+ if (f > 0) {
+ f_c = gd_mulfx(f,gd_mulfx(f,f));
+ }
+
+ if (f_fm1 > 0) {
+ f_d = gd_mulfx(f_fm1,gd_mulfx(f_fm1,f_fm1));
+ }
+ f_RY = gd_divfx((f_a-gd_mulfx(f_4,f_b)+gd_mulfx(f_6,f_c)-gd_mulfx(f_4,f_d)),f_6);
+
+ for (l=-1; l< 3; l++) {
+ const gdFixed f = gd_itofx(l) - f_g;
+ const gdFixed f_fm1 = f - f_1;
+ const gdFixed f_fp1 = f + f_1;
+ const gdFixed f_fp2 = f + f_2;
+ gdFixed f_a = 0, f_b = 0, f_c = 0, f_d = 0;
+ gdFixed f_RX, f_R;
+ const int _k = ((k + 1) * 4) + (l + 1);
+ register gdFixed f_rs, f_gs, f_bs, f_as;
+ register int c;
+
+ if (f_fp2 > 0) {
+ f_a = gd_mulfx(f_fp2,gd_mulfx(f_fp2,f_fp2));
+ }
+
+ if (f_fp1 > 0) {
+ f_b = gd_mulfx(f_fp1,gd_mulfx(f_fp1,f_fp1));
+ }
+
+ if (f > 0) {
+ f_c = gd_mulfx(f,gd_mulfx(f,f));
+ }
+
+ if (f_fm1 > 0) {
+ f_d = gd_mulfx(f_fm1,gd_mulfx(f_fm1,f_fm1));
+ }
+
+ f_RX = gd_divfx((f_a - gd_mulfx(f_4, f_b) + gd_mulfx(f_6, f_c) - gd_mulfx(f_4, f_d)), f_6);
+ f_R = gd_mulfx(f_RY, f_RX);
+
+ if ((src_offset_x[_k] <= 0) || (src_offset_y[_k] <= 0) || (src_offset_y[_k] >= src_h) || (src_offset_x[_k] >= src_w)) {
+ c = bgColor;
+ } else if ((src_offset_x[_k] <= 1) || (src_offset_y[_k] <= 1) || (src_offset_y[_k] >= (int)src_h - 1) || (src_offset_x[_k] >= (int)src_w - 1)) {
+ gdFixed f_127 = gd_itofx(127);
+ c = src->tpixels[src_offset_y[_k]][src_offset_x[_k]];
+ c = c | (( (int) (gd_fxtof(gd_mulfx(f_R, f_127)) + 50.5f)) << 24);
+ c = _color_blend(bgColor, c);
+ } else {
+ c = src->tpixels[src_offset_y[_k]][src_offset_x[_k]];
+ }
+
+ f_rs = gd_itofx(gdTrueColorGetRed(c));
+ f_gs = gd_itofx(gdTrueColorGetGreen(c));
+ f_bs = gd_itofx(gdTrueColorGetBlue(c));
+ f_as = gd_itofx(gdTrueColorGetAlpha(c));
+
+ f_red += gd_mulfx(f_rs, f_R);
+ f_green += gd_mulfx(f_gs, f_R);
+ f_blue += gd_mulfx(f_bs, f_R);
+ f_alpha += gd_mulfx(f_as, f_R);
+ }
+ }
+
+ red = (unsigned char) CLAMP(gd_fxtoi(gd_mulfx(f_red, f_gama)), 0, 255);
+ green = (unsigned char) CLAMP(gd_fxtoi(gd_mulfx(f_green, f_gama)), 0, 255);
+ blue = (unsigned char) CLAMP(gd_fxtoi(gd_mulfx(f_blue, f_gama)), 0, 255);
+ alpha = (unsigned char) CLAMP(gd_fxtoi(gd_mulfx(f_alpha, f_gama)), 0, 127);
+
+ dst->tpixels[dst_offset_y][dst_offset_x] = gdTrueColorAlpha(red, green, blue, alpha);
+ } else {
+ dst->tpixels[dst_offset_y][dst_offset_x] = bgColor;
+ }
+ dst_offset_x++;
+ }
+
+ dst_offset_y++;
+ }
+ return dst;
+}
+
+gdImagePtr gdImageRotateInterpolated(const gdImagePtr src, const float angle, int bgcolor)
+{
+ const int angle_rounded = (int)floor(angle * 100);
+
+ if (bgcolor < 0) {
+ return NULL;
+ }
+
+ /* no interpolation needed here */
+ switch (angle_rounded) {
+ case 9000:
+ return gdImageRotate90(src, 0);
+ case 18000:
+ return gdImageRotate180(src, 0);
+ case 27000:
+ return gdImageRotate270(src, 0);
+ }
+
+ if (src == NULL || src->interpolation_id < 1 || src->interpolation_id > GD_METHOD_COUNT) {
+ return NULL;
+ }
+
+ switch (src->interpolation_id) {
+ case GD_NEAREST_NEIGHBOUR:
+ return gdImageRotateNearestNeighbour(src, angle, bgcolor);
+ break;
+
+ case GD_BILINEAR_FIXED:
+ return gdImageRotateBilinear(src, angle, bgcolor);
+ break;
+
+ case GD_BICUBIC_FIXED:
+ return gdImageRotateBicubicFixed(src, angle, bgcolor);
+ break;
+
+ default:
+ return gdImageRotateGeneric(src, angle, bgcolor);
+ }
+ return NULL;
+}
+
+/**
+ * Title: Affine transformation
+ **/
+
+/**
+ * Group: Transform
+ **/
+
+ static void gdImageClipRectangle(gdImagePtr im, gdRectPtr r)
+{
+ int c1x, c1y, c2x, c2y;
+ int x1,y1;
+
+ gdImageGetClip(im, &c1x, &c1y, &c2x, &c2y);
+ x1 = r->x + r->width - 1;
+ y1 = r->y + r->height - 1;
+ r->x = CLAMP(r->x, c1x, c2x);
+ r->y = CLAMP(r->y, c1y, c2y);
+ r->width = CLAMP(x1, c1x, c2x) - r->x + 1;
+ r->height = CLAMP(y1, c1y, c2y) - r->y + 1;
+}
+
+void gdDumpRect(const char *msg, gdRectPtr r)
+{
+ printf("%s (%i, %i) (%i, %i)\n", msg, r->x, r->y, r->width, r->height);
+}
+
+/**
+ * Function: gdTransformAffineGetImage
+ * Applies an affine transformation to a region and return an image
+ * containing the complete transformation.
+ *
+ * Parameters:
+ * dst - Pointer to a gdImagePtr to store the created image, NULL when
+ * the creation or the transformation failed
+ * src - Source image
+ * src_area - rectangle defining the source region to transform
+ * dstY - Y position in the destination image
+ * affine - The desired affine transformation
+ *
+ * Returns:
+ * GD_TRUE if the affine is rectilinear or GD_FALSE
+ */
+int gdTransformAffineGetImage(gdImagePtr *dst,
+ const gdImagePtr src,
+ gdRectPtr src_area,
+ const double affine[6])
+{
+ int res;
+ double m[6];
+ gdRect bbox;
+ gdRect area_full;
+
+ if (src_area == NULL) {
+ area_full.x = 0;
+ area_full.y = 0;
+ area_full.width = gdImageSX(src);
+ area_full.height = gdImageSY(src);
+ src_area = &area_full;
+ }
+
+ gdTransformAffineBoundingBox(src_area, affine, &bbox);
+
+ *dst = gdImageCreateTrueColor(bbox.width, bbox.height);
+ if (*dst == NULL) {
+ return GD_FALSE;
+ }
+ (*dst)->saveAlphaFlag = 1;
+
+ if (!src->trueColor) {
+ gdImagePaletteToTrueColor(src);
+ }
+
+ /* Translate to dst origin (0,0) */
+ gdAffineTranslate(m, -bbox.x, -bbox.y);
+ gdAffineConcat(m, affine, m);
+
+ gdImageAlphaBlending(*dst, 0);
+
+ res = gdTransformAffineCopy(*dst,
+ 0,0,
+ src,
+ src_area,
+ m);
+
+ if (res != GD_TRUE) {
+ gdImageDestroy(*dst);
+ dst = NULL;
+ return GD_FALSE;
+ } else {
+ return GD_TRUE;
+ }
+}
+
+/**
+ * Function: gdTransformAffineCopy
+ * Applies an affine transformation to a region and copy the result
+ * in a destination to the given position.
+ *
+ * Parameters:
+ * dst - Image to draw the transformed image
+ * src - Source image
+ * dstX - X position in the destination image
+ * dstY - Y position in the destination image
+ * src_area - Rectangular region to rotate in the src image
+ *
+ * Returns:
+ * GD_TRUE if the affine is rectilinear or GD_FALSE
+ */
+int gdTransformAffineCopy(gdImagePtr dst,
+ int dst_x, int dst_y,
+ const gdImagePtr src,
+ gdRectPtr src_region,
+ const double affine[6])
+{
+ int c1x,c1y,c2x,c2y;
+ int backclip = 0;
+ int backup_clipx1, backup_clipy1, backup_clipx2, backup_clipy2;
+ register int x, y, src_offset_x, src_offset_y;
+ double inv[6];
+ int *dst_p;
+ gdPointF pt, src_pt;
+ gdRect bbox;
+ int end_x, end_y;
+ gdInterpolationMethod interpolotion_id_bak;
+ interpolation_method interpolation_bak;
+
+ /* These methods use special implementations */
+ if (src->interpolation_id == GD_BILINEAR_FIXED || src->interpolation_id == GD_BICUBIC_FIXED || src->interpolation_id == GD_NEAREST_NEIGHBOUR) {
+ interpolotion_id_bak = src->interpolation_id;
+ interpolation_bak = src->interpolation;
+
+ gdImageSetInterpolationMethod(src, GD_BICUBIC);
+ }
+
+
+ gdImageClipRectangle(src, src_region);
+
+ if (src_region->x > 0 || src_region->y > 0
+ || src_region->width < gdImageSX(src)
+ || src_region->height < gdImageSY(src)) {
+ backclip = 1;
+
+ gdImageGetClip(src, &backup_clipx1, &backup_clipy1,
+ &backup_clipx2, &backup_clipy2);
+
+ gdImageSetClip(src, src_region->x, src_region->y,
+ src_region->x + src_region->width - 1,
+ src_region->y + src_region->height - 1);
+ }
+
+ if (!gdTransformAffineBoundingBox(src_region, affine, &bbox)) {
+ if (backclip) {
+ gdImageSetClip(src, backup_clipx1, backup_clipy1,
+ backup_clipx2, backup_clipy2);
+ }
+ gdImageSetInterpolationMethod(src, interpolotion_id_bak);
+ return GD_FALSE;
+ }
+
+ gdImageGetClip(dst, &c1x, &c1y, &c2x, &c2y);
+
+ end_x = bbox.width + (int) fabs(bbox.x);
+ end_y = bbox.height + (int) fabs(bbox.y);
+
+ /* Get inverse affine to let us work with destination -> source */
+ gdAffineInvert(inv, affine);
+
+ src_offset_x = src_region->x;
+ src_offset_y = src_region->y;
+
+ if (dst->alphaBlendingFlag) {
+ for (y = bbox.y; y <= end_y; y++) {
+ pt.y = y + 0.5;
+ for (x = 0; x <= end_x; x++) {
+ pt.x = x + 0.5;
+ gdAffineApplyToPointF(&src_pt, &pt, inv);
+ gdImageSetPixel(dst, dst_x + x, dst_y + y, getPixelInterpolated(src, src_offset_x + src_pt.x, src_offset_y + src_pt.y, 0));
+ }
+ }
+ } else {
+ for (y = 0; y <= end_y; y++) {
+ pt.y = y + 0.5 + bbox.y;
+ if ((dst_y + y) < 0 || ((dst_y + y) > gdImageSY(dst) -1)) {
+ continue;
+ }
+ dst_p = dst->tpixels[dst_y + y] + dst_x;
+
+ for (x = 0; x <= end_x; x++) {
+ pt.x = x + 0.5 + bbox.x;
+ gdAffineApplyToPointF(&src_pt, &pt, inv);
+
+ if ((dst_x + x) < 0 || (dst_x + x) > (gdImageSX(dst) - 1)) {
+ break;
+ }
+ *(dst_p++) = getPixelInterpolated(src, src_offset_x + src_pt.x, src_offset_y + src_pt.y, -1);
+ }
+ }
+ }
+
+ /* Restore clip if required */
+ if (backclip) {
+ gdImageSetClip(src, backup_clipx1, backup_clipy1,
+ backup_clipx2, backup_clipy2);
+ }
+
+ gdImageSetInterpolationMethod(src, interpolotion_id_bak);
+ return GD_TRUE;
+}
+
+/**
+ * Function: gdTransformAffineBoundingBox
+ * Returns the bounding box of an affine transformation applied to a
+ * rectangular area <gdRect>
+ *
+ * Parameters:
+ * src - Rectangular source area for the affine transformation
+ * affine - the affine transformation
+ * bbox - the resulting bounding box
+ *
+ * Returns:
+ * GD_TRUE if the affine is rectilinear or GD_FALSE
+ */
+int gdTransformAffineBoundingBox(gdRectPtr src, const double affine[6], gdRectPtr bbox)
+{
+ gdPointF extent[4], min, max, point;
+ int i;
+
+ extent[0].x=0.0;
+ extent[0].y=0.0;
+ extent[1].x=(double) src->width;
+ extent[1].y=0.0;
+ extent[2].x=(double) src->width;
+ extent[2].y=(double) src->height;
+ extent[3].x=0.0;
+ extent[3].y=(double) src->height;
+
+ for (i=0; i < 4; i++) {
+ point=extent[i];
+ if (gdAffineApplyToPointF(&extent[i], &point, affine) != GD_TRUE) {
+ return GD_FALSE;
+ }
+ }
+ min=extent[0];
+ max=extent[0];
+
+ for (i=1; i < 4; i++) {
+ if (min.x > extent[i].x)
+ min.x=extent[i].x;
+ if (min.y > extent[i].y)
+ min.y=extent[i].y;
+ if (max.x < extent[i].x)
+ max.x=extent[i].x;
+ if (max.y < extent[i].y)
+ max.y=extent[i].y;
+ }
+ bbox->x = (int) min.x;
+ bbox->y = (int) min.y;
+ bbox->width = (int) floor(max.x - min.x) - 1;
+ bbox->height = (int) floor(max.y - min.y);
+ return GD_TRUE;
+}
+
+int gdImageSetInterpolationMethod(gdImagePtr im, gdInterpolationMethod id)
+{
+ if (im == NULL || id < 0 || id > GD_METHOD_COUNT) {
+ return 0;
+ }
+
+ switch (id) {
+ case GD_DEFAULT:
+ im->interpolation_id = GD_BILINEAR_FIXED;
+ im->interpolation = NULL;
+ break;
+
+ /* Optimized versions */
+ case GD_BILINEAR_FIXED:
+ case GD_BICUBIC_FIXED:
+ case GD_NEAREST_NEIGHBOUR:
+ case GD_WEIGHTED4:
+ im->interpolation = NULL;
+ break;
+
+ /* generic versions*/
+ case GD_BELL:
+ im->interpolation = filter_bell;
+ break;
+ case GD_BESSEL:
+ im->interpolation = filter_bessel;
+ break;
+ case GD_BICUBIC:
+ im->interpolation = filter_bicubic;
+ break;
+ case GD_BLACKMAN:
+ im->interpolation = filter_blackman;
+ break;
+ case GD_BOX:
+ im->interpolation = filter_box;
+ break;
+ case GD_BSPLINE:
+ im->interpolation = filter_bspline;
+ break;
+ case GD_CATMULLROM:
+ im->interpolation = filter_catmullrom;
+ break;
+ case GD_GAUSSIAN:
+ im->interpolation = filter_gaussian;
+ break;
+ case GD_GENERALIZED_CUBIC:
+ im->interpolation = filter_generalized_cubic;
+ break;
+ case GD_HERMITE:
+ im->interpolation = filter_hermite;
+ break;
+ case GD_HAMMING:
+ im->interpolation = filter_hamming;
+ break;
+ case GD_HANNING:
+ im->interpolation = filter_hanning;
+ break;
+ case GD_MITCHELL:
+ im->interpolation = filter_mitchell;
+ break;
+ case GD_POWER:
+ im->interpolation = filter_power;
+ break;
+ case GD_QUADRATIC:
+ im->interpolation = filter_quadratic;
+ break;
+ case GD_SINC:
+ im->interpolation = filter_sinc;
+ break;
+ case GD_TRIANGLE:
+ im->interpolation = filter_triangle;
+ break;
+
+ default:
+ return 0;
+ break;
+ }
+ im->interpolation_id = id;
+ return 1;
+}
+
+#ifdef _MSC_VER
+# pragma optimize("", on)
+#endif
diff --git a/ext/gd/libgd/gd_matrix.c b/ext/gd/libgd/gd_matrix.c
new file mode 100644
index 000000000..83438bdbe
--- /dev/null
+++ b/ext/gd/libgd/gd_matrix.c
@@ -0,0 +1,334 @@
+#include "gd.h"
+#include <math.h>
+
+#ifndef M_PI
+# define M_PI 3.14159265358979323846
+#endif
+
+/**
+ * Title: Matrix
+ * Group: Affine Matrix
+ */
+
+/**
+ * Function: gdAffineApplyToPointF
+ * Applies an affine transformation to a point (floating point
+ * gdPointF)
+ *
+ *
+ * Parameters:
+ * dst - Where to store the resulting point
+ * affine - Source Point
+ * flip_horz - affine matrix
+ *
+ * Returns:
+ * GD_TRUE if the affine is rectilinear or GD_FALSE
+ */
+int gdAffineApplyToPointF (gdPointFPtr dst, const gdPointFPtr src,
+ const double affine[6])
+{
+ double x = src->x;
+ double y = src->y;
+ x = src->x;
+ y = src->y;
+ dst->x = x * affine[0] + y * affine[2] + affine[4];
+ dst->y = x * affine[1] + y * affine[3] + affine[5];
+ return GD_TRUE;
+}
+
+/**
+ * Function: gdAffineInvert
+ * Find the inverse of an affine transformation.
+ *
+ * All non-degenerate affine transforms are invertible. Applying the
+ * inverted matrix will restore the original values. Multiplying <src>
+ * by <dst> (commutative) will return the identity affine (rounding
+ * error possible).
+ *
+ * Parameters:
+ * dst - Where to store the resulting affine transform
+ * src_affine - Original affine matrix
+ * flip_horz - Whether or not to flip horizontally
+ * flip_vert - Whether or not to flip vertically
+ *
+ * See also:
+ * <gdAffineIdentity>
+ *
+ * Returns:
+ * GD_TRUE if the affine is rectilinear or GD_FALSE
+ */
+int gdAffineInvert (double dst[6], const double src[6])
+{
+ double r_det = (src[0] * src[3] - src[1] * src[2]);
+
+ if (r_det <= 0.0) {
+ return GD_FALSE;
+ }
+
+ r_det = 1.0 / r_det;
+ dst[0] = src[3] * r_det;
+ dst[1] = -src[1] * r_det;
+ dst[2] = -src[2] * r_det;
+ dst[3] = src[0] * r_det;
+ dst[4] = -src[4] * dst[0] - src[5] * dst[2];
+ dst[5] = -src[4] * dst[1] - src[5] * dst[3];
+ return GD_TRUE;
+}
+
+/**
+ * Function: gdAffineFlip
+ * Flip an affine transformation horizontally or vertically.
+ *
+ * Flips the affine transform, giving GD_FALSE for <flip_horz> and
+ * <flip_vert> will clone the affine matrix. GD_TRUE for both will
+ * copy a 180° rotation.
+ *
+ * Parameters:
+ * dst - Where to store the resulting affine transform
+ * src_affine - Original affine matrix
+ * flip_h - Whether or not to flip horizontally
+ * flip_v - Whether or not to flip vertically
+ *
+ * Returns:
+ * GD_SUCCESS on success or GD_FAILURE
+ */
+int gdAffineFlip (double dst[6], const double src[6], const int flip_h, const int flip_v)
+{
+ dst[0] = flip_h ? - src[0] : src[0];
+ dst[1] = flip_h ? - src[1] : src[1];
+ dst[2] = flip_v ? - src[2] : src[2];
+ dst[3] = flip_v ? - src[3] : src[3];
+ dst[4] = flip_h ? - src[4] : src[4];
+ dst[5] = flip_v ? - src[5] : src[5];
+ return GD_TRUE;
+}
+
+/**
+ * Function: gdAffineConcat
+ * Concat (Multiply) two affine transformation matrices.
+ *
+ * Concats two affine transforms together, i.e. the result
+ * will be the equivalent of doing first the transformation m1 and then
+ * m2. All parameters can be the same matrix (safe to call using
+ * the same array for all three arguments).
+ *
+ * Parameters:
+ * dst - Where to store the resulting affine transform
+ * m1 - First affine matrix
+ * m2 - Second affine matrix
+ *
+ * Returns:
+ * GD_SUCCESS on success or GD_FAILURE
+ */
+int gdAffineConcat (double dst[6], const double m1[6], const double m2[6])
+{
+ double dst0, dst1, dst2, dst3, dst4, dst5;
+
+ dst0 = m1[0] * m2[0] + m1[1] * m2[2];
+ dst1 = m1[0] * m2[1] + m1[1] * m2[3];
+ dst2 = m1[2] * m2[0] + m1[3] * m2[2];
+ dst3 = m1[2] * m2[1] + m1[3] * m2[3];
+ dst4 = m1[4] * m2[0] + m1[5] * m2[2] + m2[4];
+ dst5 = m1[4] * m2[1] + m1[5] * m2[3] + m2[5];
+ dst[0] = dst0;
+ dst[1] = dst1;
+ dst[2] = dst2;
+ dst[3] = dst3;
+ dst[4] = dst4;
+ dst[5] = dst5;
+ return GD_TRUE;
+}
+
+/**
+ * Function: gdAffineIdentity
+ * Set up the identity matrix.
+ *
+ * Parameters:
+ * dst - Where to store the resulting affine transform
+ *
+ * Returns:
+ * GD_SUCCESS on success or GD_FAILURE
+ */
+int gdAffineIdentity (double dst[6])
+{
+ dst[0] = 1;
+ dst[1] = 0;
+ dst[2] = 0;
+ dst[3] = 1;
+ dst[4] = 0;
+ dst[5] = 0;
+ return GD_TRUE;
+}
+
+/**
+ * Function: gdAffineScale
+ * Set up a scaling matrix.
+ *
+ * Parameters:
+ * scale_x - X scale factor
+ * scale_y - Y scale factor
+ *
+ * Returns:
+ * GD_SUCCESS on success or GD_FAILURE
+ */
+int gdAffineScale (double dst[6], const double scale_x, const double scale_y)
+{
+ dst[0] = scale_x;
+ dst[1] = 0;
+ dst[2] = 0;
+ dst[3] = scale_y;
+ dst[4] = 0;
+ dst[5] = 0;
+ return GD_TRUE;
+}
+
+/**
+ * Function: gdAffineRotate
+ * Set up a rotation affine transform.
+ *
+ * Like the other angle in libGD, in which increasing y moves
+ * downward, this is a counterclockwise rotation.
+ *
+ * Parameters:
+ * dst - Where to store the resulting affine transform
+ * angle - Rotation angle in degrees
+ *
+ * Returns:
+ * GD_SUCCESS on success or GD_FAILURE
+ */
+int gdAffineRotate (double dst[6], const double angle)
+{
+ const double sin_t = sin (angle * M_PI / 180.0);
+ const double cos_t = cos (angle * M_PI / 180.0);
+
+ dst[0] = cos_t;
+ dst[1] = sin_t;
+ dst[2] = -sin_t;
+ dst[3] = cos_t;
+ dst[4] = 0;
+ dst[5] = 0;
+ return GD_TRUE;
+}
+
+/**
+ * Function: gdAffineShearHorizontal
+ * Set up a horizontal shearing matrix || becomes \\.
+ *
+ * Parameters:
+ * dst - Where to store the resulting affine transform
+ * angle - Shear angle in degrees
+ *
+ * Returns:
+ * GD_SUCCESS on success or GD_FAILURE
+ */
+int gdAffineShearHorizontal(double dst[6], const double angle)
+{
+ dst[0] = 1;
+ dst[1] = 0;
+ dst[2] = tan(angle * M_PI / 180.0);
+ dst[3] = 1;
+ dst[4] = 0;
+ dst[5] = 0;
+ return GD_TRUE;
+}
+
+/**
+ * Function: gdAffineShearVertical
+ * Set up a vertical shearing matrix, columns are untouched.
+ *
+ * Parameters:
+ * dst - Where to store the resulting affine transform
+ * angle - Shear angle in degrees
+ *
+ * Returns:
+ * GD_SUCCESS on success or GD_FAILURE
+ */
+int gdAffineShearVertical(double dst[6], const double angle)
+{
+ dst[0] = 1;
+ dst[1] = tan(angle * M_PI / 180.0);;
+ dst[2] = 0;
+ dst[3] = 1;
+ dst[4] = 0;
+ dst[5] = 0;
+ return GD_TRUE;
+}
+
+/**
+ * Function: gdAffineTranslate
+ * Set up a translation matrix.
+ *
+ * Parameters:
+ * dst - Where to store the resulting affine transform
+ * offset_x - Horizontal translation amount
+ * offset_y - Vertical translation amount
+ *
+ * Returns:
+ * GD_SUCCESS on success or GD_FAILURE
+ */
+int gdAffineTranslate (double dst[6], const double offset_x, const double offset_y)
+{
+ dst[0] = 1;
+ dst[1] = 0;
+ dst[2] = 0;
+ dst[3] = 1;
+ dst[4] = offset_x;
+ dst[5] = offset_y;
+ return GD_TRUE;
+}
+
+/**
+ * gdAffineexpansion: Find the affine's expansion factor.
+ * @src: The affine transformation.
+ *
+ * Finds the expansion factor, i.e. the square root of the factor
+ * by which the affine transform affects area. In an affine transform
+ * composed of scaling, rotation, shearing, and translation, returns
+ * the amount of scaling.
+ *
+ * GD_SUCCESS on success or GD_FAILURE
+ **/
+double gdAffineExpansion (const double src[6])
+{
+ return sqrt (fabs (src[0] * src[3] - src[1] * src[2]));
+}
+
+/**
+ * Function: gdAffineRectilinear
+ * Determines whether the affine transformation is axis aligned. A
+ * tolerance has been implemented using GD_EPSILON.
+ *
+ * Parameters:
+ * m - The affine transformation
+ *
+ * Returns:
+ * GD_TRUE if the affine is rectilinear or GD_FALSE
+ */
+int gdAffineRectilinear (const double m[6])
+{
+ return ((fabs (m[1]) < GD_EPSILON && fabs (m[2]) < GD_EPSILON) ||
+ (fabs (m[0]) < GD_EPSILON && fabs (m[3]) < GD_EPSILON));
+}
+
+/**
+ * Function: gdAffineEqual
+ * Determines whether two affine transformations are equal. A tolerance
+ * has been implemented using GD_EPSILON.
+ *
+ * Parameters:
+ * m1 - The first affine transformation
+ * m2 - The first affine transformation
+ *
+ * Returns:
+ * GD_SUCCESS on success or GD_FAILURE
+ */
+int gdAffineEqual (const double m1[6], const double m2[6])
+{
+ return (fabs (m1[0] - m2[0]) < GD_EPSILON &&
+ fabs (m1[1] - m2[1]) < GD_EPSILON &&
+ fabs (m1[2] - m2[2]) < GD_EPSILON &&
+ fabs (m1[3] - m2[3]) < GD_EPSILON &&
+ fabs (m1[4] - m2[4]) < GD_EPSILON &&
+ fabs (m1[5] - m2[5]) < GD_EPSILON);
+}
+
diff --git a/ext/gd/php_gd.h b/ext/gd/php_gd.h
index 90ebd6526..3c60007a7 100644
--- a/ext/gd/php_gd.h
+++ b/ext/gd/php_gd.h
@@ -104,6 +104,7 @@ PHP_FUNCTION(imagefttext);
PHP_FUNCTION(imagecreatetruecolor);
PHP_FUNCTION(imagetruecolortopalette);
+PHP_FUNCTION(imagepalettetotruecolor);
PHP_FUNCTION(imagesetthickness);
PHP_FUNCTION(imagefilledellipse);
PHP_FUNCTION(imagefilledarc);
@@ -127,6 +128,11 @@ PHP_FUNCTION(imageantialias);
PHP_FUNCTION(imageflip);
PHP_FUNCTION(imagecrop);
PHP_FUNCTION(imagecropauto);
+PHP_FUNCTION(imagescale);
+PHP_FUNCTION(imageaffine);
+PHP_FUNCTION(imageaffinematrixget);
+PHP_FUNCTION(imageaffinematrixconcat);
+PHP_FUNCTION(imagesetinterpolation);
#endif
PHP_FUNCTION(imagesetthickness);
diff --git a/ext/mysql/tests/mysql_field_flags.phpt b/ext/mysql/tests/mysql_field_flags.phpt
index 7f1b366d5..5f8eb0995 100644
--- a/ext/mysql/tests/mysql_field_flags.phpt
+++ b/ext/mysql/tests/mysql_field_flags.phpt
@@ -45,12 +45,12 @@ mysql_free_result($res);
$version = mysql_get_server_info($link);
if (!preg_match('@(\d+)\.(\d+)\.(\d+)@ism', $version, $matches))
printf("[009] Cannot get server version\n");
-$version = ($matches[1] * 100) + ($matches[2] * 10) + $matches[3];
+$version = ($matches[1] * 1000) + ($matches[2] * 100) + $matches[3];
$tables = array(
'label INT, UNIQUE KEY (label)' => array(
array('label', '1'),
- 'label' => array(($version < 500) ? 'multiple_key' : 'unique_key')
+ 'label' => array(($version < 5000) ? 'multiple_key' : 'unique_key')
),
'labela INT, label2 CHAR(1), KEY keyname (labela, label2)' => array(
array('labela, label2', "1, 'a'"),
@@ -86,7 +86,7 @@ $tables = array(
),
);
-if ($version < 560) {
+if ($version < 5600) {
$tables['label1 TIMESTAMP']['label1'][] = 'zerofill';
$tables['label1 TIMESTAMP']['label1'][] = 'unsigned';
}
diff --git a/ext/mysql/tests/mysql_list_fields.phpt b/ext/mysql/tests/mysql_list_fields.phpt
index 259a94a39..6b6ae9b31 100644
--- a/ext/mysql/tests/mysql_list_fields.phpt
+++ b/ext/mysql/tests/mysql_list_fields.phpt
@@ -74,7 +74,7 @@ mysql_field_name(): id
mysql_field_type(): int
Field Offset 1
mysql_field_flags()%s
-mysql_field_len(): 1
+mysql_field_len(): %s
mysql_field_name(): label
mysql_field_type(): string
done!
diff --git a/ext/mysqlnd/mysqlnd_charset.c b/ext/mysqlnd/mysqlnd_charset.c
index 8766a4b25..0ca419b5a 100644
--- a/ext/mysqlnd/mysqlnd_charset.c
+++ b/ext/mysqlnd/mysqlnd_charset.c
@@ -445,12 +445,12 @@ mysqlnd_mbcharlen_utf32(unsigned int utf32 __attribute((unused)))
const MYSQLND_CHARSET mysqlnd_charsets[] =
{
{ 1, "big5","big5_chinese_ci", 1, 2, "", mysqlnd_mbcharlen_big5, check_mb_big5},
- { 3, "dec8", "dec8_swedisch_ci", 1, 1, "", NULL, NULL},
+ { 3, "dec8", "dec8_swedish_ci", 1, 1, "", NULL, NULL},
{ 4, "cp850", "cp850_general_ci", 1, 1, "", NULL, NULL},
{ 6, "hp8", "hp8_english_ci", 1, 1, "", NULL, NULL},
{ 7, "koi8r", "koi8r_general_ci", 1, 1, "", NULL, NULL},
{ 8, "latin1", "latin1_swedish_ci", 1, 1, "", NULL, NULL},
- { 5, "latin1", "latin1_german_ci", 1, 1, "", NULL, NULL}, /* should be after 0x9 because swedish_ci is the default collation */
+ { 5, "latin1", "latin1_german1_ci", 1, 1, "", NULL, NULL}, /* should be after 0x8 because swedish_ci is the default collation */
{ 9, "latin2", "latin2_general_ci", 1, 1, "", NULL, NULL},
{ 2, "latin2", "latin2_czech_cs", 1, 1, "", NULL, NULL}, /* should be after 0x9 because general_ci is the default collation */
{ 10, "swe7", "swe7_swedish_ci", 1, 1, "", NULL, NULL},
@@ -485,7 +485,7 @@ const MYSQLND_CHARSET mysqlnd_charsets[] =
{ 59, "cp1257", "cp1257_general_ci", 1, 1, "", NULL, NULL},
{ 63, "binary", "binary", 1, 1, "", NULL, NULL},
{ 97, "eucjpms", "eucjpms_japanese_ci", 1, 3, "", mysqlnd_mbcharlen_eucjpms, check_mb_eucjpms},
- { 29, "cp1257", "cp1257_lithunian_ci", 1, 1, "", NULL, NULL},
+ { 29, "cp1257", "cp1257_lithuanian_ci", 1, 1, "", NULL, NULL},
{ 31, "latin1", "latin1_german2_ci", 1, 1, "", NULL, NULL},
{ 34, "cp1250", "cp1250_czech_cs", 1, 1, "", NULL, NULL},
{ 42, "latin7", "latin7_general_cs", 1, 1, "", NULL, NULL},
@@ -506,19 +506,17 @@ const MYSQLND_CHARSET mysqlnd_charsets[] =
{ 55, "utf16", "utf16_bin", 2, 4, "UTF-16 Unicode", mysqlnd_mbcharlen_utf16, check_mb_utf16},
{ 56, "utf16le", "utf16le_general_ci", 2, 4, "UTF-16LE Unicode", mysqlnd_mbcharlen_utf16, check_mb_utf16},
{ 58, "cp1257", "cp1257_bin", 1, 1, "", NULL, NULL},
-#ifdef USED_TO_BE_SO_BEFORE_MYSQL_5_5
- { 60, "armascii8", "armascii8_bin", 1, 1, "", NULL, NULL},
-#endif
/*55*/{ 60, "utf32", "utf32_general_ci", 4, 4, "UTF-32 Unicode", mysqlnd_mbcharlen_utf32, check_mb_utf32},
/*55*/{ 61, "utf32", "utf32_bin", 4, 4, "UTF-32 Unicode", mysqlnd_mbcharlen_utf32, check_mb_utf32},
{ 62, "utf16le", "utf16le_bin", 2, 4, "UTF-16LE Unicode", mysqlnd_mbcharlen_utf16, check_mb_utf16},
+ { 64, "armscii8", "armscii8_bin", 1, 1, "", NULL, NULL},
{ 65, "ascii", "ascii_bin", 1, 1, "", NULL, NULL},
{ 66, "cp1250", "cp1250_bin", 1, 1, "", NULL, NULL},
{ 67, "cp1256", "cp1256_bin", 1, 1, "", NULL, NULL},
{ 68, "cp866", "cp866_bin", 1, 1, "", NULL, NULL},
{ 69, "dec8", "dec8_bin", 1, 1, "", NULL, NULL},
{ 70, "greek", "greek_bin", 1, 1, "", NULL, NULL},
- { 71, "hebew", "hebrew_bin", 1, 1, "", NULL, NULL},
+ { 71, "hebrew", "hebrew_bin", 1, 1, "", NULL, NULL},
{ 72, "hp8", "hp8_bin", 1, 1, "", NULL, NULL},
{ 73, "keybcs2", "keybcs2_bin", 1, 1, "", NULL, NULL},
{ 74, "koi8r", "koi8r_bin", 1, 1, "", NULL, NULL},
@@ -558,7 +556,7 @@ const MYSQLND_CHARSET mysqlnd_charsets[] =
{ 137, "ucs2", "ucs2_turkish_ci", 2, 2, "", mysqlnd_mbcharlen_ucs2, check_mb_ucs2},
{ 138, "ucs2", "ucs2_czech_ci", 2, 2, "", mysqlnd_mbcharlen_ucs2, check_mb_ucs2},
{ 139, "ucs2", "ucs2_danish_ci", 2, 2, "", mysqlnd_mbcharlen_ucs2, check_mb_ucs2},
- { 140, "ucs2", "ucs2_lithunian_ci", 2, 2, "", mysqlnd_mbcharlen_ucs2, check_mb_ucs2},
+ { 140, "ucs2", "ucs2_lithuanian_ci", 2, 2, "", mysqlnd_mbcharlen_ucs2, check_mb_ucs2},
{ 141, "ucs2", "ucs2_slovak_ci", 2, 2, "", mysqlnd_mbcharlen_ucs2, check_mb_ucs2},
{ 142, "ucs2", "ucs2_spanish2_ci", 2, 2, "", mysqlnd_mbcharlen_ucs2, check_mb_ucs2},
{ 143, "ucs2", "ucs2_roman_ci", 2, 2, "", mysqlnd_mbcharlen_ucs2, check_mb_ucs2},
@@ -596,7 +594,7 @@ const MYSQLND_CHARSET mysqlnd_charsets[] =
/*56*/{182, "utf32", "utf32_unicode_520_ci", 4, 4, "UTF-32 Unicode", mysqlnd_mbcharlen_utf32, check_mb_utf32},
/*56*/{183, "utf32", "utf32_vietnamese_ci", 4, 4, "UTF-32 Unicode", mysqlnd_mbcharlen_utf32, check_mb_utf32},
- { 192, UTF8_MB3, UTF8_MB3"_general_ci", 1, 3, "", mysqlnd_mbcharlen_utf8mb3, check_mb_utf8mb3_valid},
+ { 192, UTF8_MB3, UTF8_MB3"_unicode_ci", 1, 3, "", mysqlnd_mbcharlen_utf8mb3, check_mb_utf8mb3_valid},
{ 193, UTF8_MB3, UTF8_MB3"_icelandic_ci", 1, 3, "", mysqlnd_mbcharlen_utf8mb3, check_mb_utf8mb3_valid},
{ 194, UTF8_MB3, UTF8_MB3"_latvian_ci", 1, 3, "", mysqlnd_mbcharlen_utf8mb3, check_mb_utf8mb3_valid},
{ 195, UTF8_MB3, UTF8_MB3"_romanian_ci", 1, 3, "", mysqlnd_mbcharlen_utf8mb3, check_mb_utf8mb3_valid},
@@ -608,7 +606,7 @@ const MYSQLND_CHARSET mysqlnd_charsets[] =
{ 201, UTF8_MB3, UTF8_MB3"_turkish_ci", 1, 3, "", mysqlnd_mbcharlen_utf8mb3, check_mb_utf8mb3_valid},
{ 202, UTF8_MB3, UTF8_MB3"_czech_ci", 1, 3, "", mysqlnd_mbcharlen_utf8mb3, check_mb_utf8mb3_valid},
{ 203, UTF8_MB3, UTF8_MB3"_danish_ci", 1, 3, "", mysqlnd_mbcharlen_utf8mb3, check_mb_utf8mb3_valid },
- { 204, UTF8_MB3, UTF8_MB3"_lithunian_ci", 1, 3, "", mysqlnd_mbcharlen_utf8mb3, check_mb_utf8mb3_valid },
+ { 204, UTF8_MB3, UTF8_MB3"_lithuanian_ci", 1, 3, "", mysqlnd_mbcharlen_utf8mb3, check_mb_utf8mb3_valid },
{ 205, UTF8_MB3, UTF8_MB3"_slovak_ci", 1, 3, "", mysqlnd_mbcharlen_utf8mb3, check_mb_utf8mb3_valid},
{ 206, UTF8_MB3, UTF8_MB3"_spanish2_ci", 1, 3, "", mysqlnd_mbcharlen_utf8mb3, check_mb_utf8mb3_valid},
{ 207, UTF8_MB3, UTF8_MB3"_roman_ci", 1, 3, "", mysqlnd_mbcharlen_utf8mb3, check_mb_utf8mb3_valid},
@@ -616,7 +614,7 @@ const MYSQLND_CHARSET mysqlnd_charsets[] =
{ 209, UTF8_MB3, UTF8_MB3"_esperanto_ci", 1, 3, "", mysqlnd_mbcharlen_utf8mb3, check_mb_utf8mb3_valid},
{ 210, UTF8_MB3, UTF8_MB3"_hungarian_ci", 1, 3, "", mysqlnd_mbcharlen_utf8mb3, check_mb_utf8mb3_valid},
{ 211, UTF8_MB3, UTF8_MB3"_sinhala_ci", 1, 3, "", mysqlnd_mbcharlen_utf8mb3, check_mb_utf8mb3_valid},
- { 211, UTF8_MB3, UTF8_MB3"_german2_ci", 1, 3, "", mysqlnd_mbcharlen_utf8mb3, check_mb_utf8mb3_valid},
+ { 212, UTF8_MB3, UTF8_MB3"_german2_ci", 1, 3, "", mysqlnd_mbcharlen_utf8mb3, check_mb_utf8mb3_valid},
{ 213, UTF8_MB3, UTF8_MB3"_croatian_ci", 1, 3, "", mysqlnd_mbcharlen_utf8mb3, check_mb_utf8mb3_valid},
{ 214, UTF8_MB3, UTF8_MB3"_unicode_520_ci", 1, 3, "", mysqlnd_mbcharlen_utf8mb3, check_mb_utf8mb3_valid},
{ 215, UTF8_MB3, UTF8_MB3"_vietnamese_ci", 1, 3, "", mysqlnd_mbcharlen_utf8mb3, check_mb_utf8mb3_valid},
diff --git a/ext/opcache/Optimizer/block_pass.c b/ext/opcache/Optimizer/block_pass.c
index d4299c8ad..7fd986ca6 100644
--- a/ext/opcache/Optimizer/block_pass.c
+++ b/ext/opcache/Optimizer/block_pass.c
@@ -972,7 +972,11 @@ static void zend_optimize_block(zend_code_block *block, zend_op_array *op_array,
zval result;
if (unary_op) {
+#if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO
+ unary_op(&result, &ZEND_OP1_LITERAL(opline));
+#else
unary_op(&result, &ZEND_OP1_LITERAL(opline) TSRMLS_CC);
+#endif
literal_dtor(&ZEND_OP1_LITERAL(opline));
} else {
/* BOOL */
diff --git a/ext/opcache/Optimizer/pass1_5.c b/ext/opcache/Optimizer/pass1_5.c
index 8938e148c..dc9e7319a 100644
--- a/ext/opcache/Optimizer/pass1_5.c
+++ b/ext/opcache/Optimizer/pass1_5.c
@@ -203,7 +203,11 @@ if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) {
er = EG(error_reporting);
EG(error_reporting) = 0;
+#if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO
+ if (unary_op(&result, &ZEND_OP1_LITERAL(opline)) != SUCCESS) {
+#else
if (unary_op(&result, &ZEND_OP1_LITERAL(opline) TSRMLS_CC) != SUCCESS) {
+#endif
EG(error_reporting) = er;
break;
}
diff --git a/ext/opcache/README b/ext/opcache/README
index f87e1ccbf..03386a0a7 100644
--- a/ext/opcache/README
+++ b/ext/opcache/README
@@ -63,7 +63,11 @@ Configuration Directives
------------------------
opcache.enable (default "1")
- OPcache On/Off switch. When set to Off, code is not optimized.
+ OPcache On/Off switch. When set to Off, code is not optimized and cached.
+
+opcache.enable_cli (default "0")
+ Enables the OPcache for the CLI version of PHP. It's mostly for testing
+ and debugging.
opcache.memory_consumption (default "64")
The OPcache shared memory storage size. The amount of memory for storing
diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c
index 64c5aa8f1..694bbed55 100644
--- a/ext/opcache/ZendAccelerator.c
+++ b/ext/opcache/ZendAccelerator.c
@@ -134,6 +134,12 @@ static inline int is_stream_path(const char *filename)
return ((*p == ':') && (p - filename > 1) && (p[1] == '/') && (p[2] == '/'));
}
+static inline int is_cachable_stream_path(const char *filename)
+{
+ return memcmp(filename, "file://", sizeof("file://") - 1) == 0 ||
+ memcmp(filename, "phar://", sizeof("phar://") - 1) == 0;
+}
+
/* O+ overrides PHP chdir() function and remembers the current working directory
* in ZCG(cwd) and ZCG(cwd_len). Later accel_getcwd() can use stored value and
* avoid getcwd() call.
@@ -1204,10 +1210,18 @@ static zend_persistent_script *compile_and_cache_file(zend_file_handle *file_han
} else {
*op_array_p = NULL;
if (type == ZEND_REQUIRE) {
+#if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO
+ zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, file_handle->filename);
+#else
zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, file_handle->filename TSRMLS_CC);
+#endif
zend_bailout();
} else {
+#if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO
+ zend_message_dispatcher(ZMSG_FAILED_INCLUDE_FOPEN, file_handle->filename);
+#else
zend_message_dispatcher(ZMSG_FAILED_INCLUDE_FOPEN, file_handle->filename TSRMLS_CC);
+#endif
}
return NULL;
}
@@ -1365,7 +1379,9 @@ static zend_op_array *persistent_compile_file(zend_file_handle *file_handle, int
!ZCG(enabled) || !accel_startup_ok ||
(!ZCG(counted) && !ZCSG(accelerator_enabled)) ||
CG(interactive) ||
- (ZCSG(restart_in_progress) && accel_restart_is_active(TSRMLS_C))) {
+ (ZCSG(restart_in_progress) && accel_restart_is_active(TSRMLS_C)) ||
+ (is_stream_path(file_handle->filename) &&
+ !is_cachable_stream_path(file_handle->filename))) {
/* The Accelerator is disabled, act as if without the Accelerator */
return accelerator_orig_compile_file(file_handle, type TSRMLS_CC);
}
@@ -1422,10 +1438,18 @@ static zend_op_array *persistent_compile_file(zend_file_handle *file_handle, int
zend_stream_open(file_handle->filename, file_handle TSRMLS_CC) == FAILURE) {
#endif
if (type == ZEND_REQUIRE) {
+#if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO
+ zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, file_handle->filename);
+#else
zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, file_handle->filename TSRMLS_CC);
+#endif
zend_bailout();
} else {
+#if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO
+ zend_message_dispatcher(ZMSG_FAILED_INCLUDE_FOPEN, file_handle->filename);
+#else
zend_message_dispatcher(ZMSG_FAILED_INCLUDE_FOPEN, file_handle->filename TSRMLS_CC);
+#endif
}
return NULL;
}
@@ -1542,7 +1566,11 @@ static zend_op_array *persistent_compile_file(zend_file_handle *file_handle, int
zend_hash_quick_add(&EG(included_files), persistent_script->full_path, persistent_script->full_path_len + 1, persistent_script->hash_value, &dummy, sizeof(void *), NULL);
}
}
+#if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO
+ zend_file_handle_dtor(file_handle);
+#else
zend_file_handle_dtor(file_handle TSRMLS_CC);
+#endif
from_shared_memory = 1;
}
@@ -2342,7 +2370,8 @@ static void zend_accel_init_shm(TSRMLS_D)
ZCSG(manual_restarts) = 0;
ZCSG(accelerator_enabled) = 1;
- ZCSG(last_restart_time) = zend_accel_get_time();
+ ZCSG(start_time) = zend_accel_get_time();
+ ZCSG(last_restart_time) = 0;
ZCSG(restart_in_progress) = 0;
zend_shared_alloc_unlock(TSRMLS_C);
diff --git a/ext/opcache/ZendAccelerator.h b/ext/opcache/ZendAccelerator.h
index 3f10630ac..f9b51b0df 100644
--- a/ext/opcache/ZendAccelerator.h
+++ b/ext/opcache/ZendAccelerator.h
@@ -27,7 +27,7 @@
#endif
#define ACCELERATOR_PRODUCT_NAME "Zend OPcache"
-#define ACCELERATOR_VERSION "7.0.1-dev"
+#define ACCELERATOR_VERSION "7.0.2-dev"
/* 2 - added Profiler support, on 20010712 */
/* 3 - added support for Optimizer's encoded-only-files mode */
/* 4 - works with the new Optimizer, that supports the file format with licenses */
@@ -88,12 +88,13 @@
#define PHP_5_2_X_API_NO 220060519
#define PHP_5_3_X_API_NO 220090626
#define PHP_5_4_X_API_NO 220100525
+#define PHP_5_5_X_API_NO 220121212
/*** file locking ***/
#ifndef ZEND_WIN32
extern int lock_file;
-# if defined(__FreeBSD__) || (defined(__APPLE__) && defined(__MACH__)/* Darwin */) || defined(__OpenBSD__) || defined(__NetBSD__)
+# if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || (defined(__APPLE__) && defined(__MACH__)/* Darwin */) || defined(__OpenBSD__) || defined(__NetBSD__)
# define FLOCK_STRUCTURE(name, type, whence, start, len) \
struct flock name = {start, len, -1, type, whence}
# elif defined(__svr4__)
@@ -274,6 +275,7 @@ typedef struct _zend_accel_shared_globals {
zend_accel_hash include_paths; /* used "include_path" values */
/* Directives & Maintenance */
+ time_t start_time;
time_t last_restart_time;
time_t force_restart_time;
zend_bool accelerator_enabled;
diff --git a/ext/opcache/config.m4 b/ext/opcache/config.m4
index cbf7d5a19..f9c38b1f7 100644
--- a/ext/opcache/config.m4
+++ b/ext/opcache/config.m4
@@ -325,6 +325,39 @@ int main() {
AC_DEFINE(HAVE_SHM_MMAP_FILE, 1, [Define if you have mmap() SHM support])
msg=yes,msg=no,msg=no)
AC_MSG_RESULT([$msg])
+
+ AC_MSG_CHECKING(for known struct flock definition)
+ dnl Copied from ZendAccelerator.h
+ AC_TRY_RUN([
+#include <fcntl.h>
+#include <stdlib.h>
+
+#ifndef ZEND_WIN32
+extern int lock_file;
+
+# if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || (defined(__APPLE__) && defined(__MACH__)/* Darwin */) || defined(__OpenBSD__) || defined(__NetBSD__)
+# define FLOCK_STRUCTURE(name, type, whence, start, len) \
+ struct flock name = {start, len, -1, type, whence}
+# elif defined(__svr4__)
+# define FLOCK_STRUCTURE(name, type, whence, start, len) \
+ struct flock name = {type, whence, start, len}
+# elif defined(__linux__) || defined(__hpux)
+# define FLOCK_STRUCTURE(name, type, whence, start, len) \
+ struct flock name = {type, whence, start, len, 0}
+# elif defined(_AIX)
+# if defined(_LARGE_FILES) || defined(__64BIT__)
+# define FLOCK_STRUCTURE(name, type, whence, start, len) \
+ struct flock name = {type, whence, 0, 0, 0, start, len }
+# else
+# define FLOCK_STRUCTURE(name, type, whence, start, len) \
+ struct flock name = {type, whence, start, len}
+# endif
+# else
+# error "Don't know how to define struct flock"
+# endif
+#endif
+int main() { return 0; }
+], [], [AC_MSG_ERROR([Don't know how to define struct flock on this system[,] set --enable-opcache=no])], [])
PHP_NEW_EXTENSION(opcache,
ZendAccelerator.c \
diff --git a/ext/opcache/shared_alloc_win32.c b/ext/opcache/shared_alloc_win32.c
index e32395284..2c3218414 100644
--- a/ext/opcache/shared_alloc_win32.c
+++ b/ext/opcache/shared_alloc_win32.c
@@ -166,7 +166,7 @@ static int zend_shared_alloc_reattach(size_t requested_size, char **error_in)
}
return ALLOC_FAIL_MAPPING;
}
- smm_shared_globals = (zend_smm_shared_globals *) (((char *) mapping_base) + sizeof(zend_shared_memory_block_header));
+ smm_shared_globals = (zend_smm_shared_globals *) mapping_base;
return SUCCESSFULLY_REATTACHED;
}
diff --git a/ext/opcache/tests/bug64482.inc b/ext/opcache/tests/bug64482.inc
new file mode 100644
index 000000000..e3d2b210c
--- /dev/null
+++ b/ext/opcache/tests/bug64482.inc
@@ -0,0 +1,2 @@
+<?php
+echo "Dynamic include";
diff --git a/ext/opcache/tests/bug64482.phpt b/ext/opcache/tests/bug64482.phpt
new file mode 100644
index 000000000..fa722f6d4
--- /dev/null
+++ b/ext/opcache/tests/bug64482.phpt
@@ -0,0 +1,17 @@
+--TEST--
+Bug #64482 (Opcodes for dynamic includes should not be cached)
+--INI--
+opcache.enable=1
+opcache.enable_cli=1
+--SKIPIF--
+<?php require_once('skipif.inc'); ?>
+--FILE--
+<?php
+include 'bug64482.inc';
+echo "\n";
+include 'php://filter/read=string.toupper/resource=bug64482.inc';
+echo "\n";
+?>
+--EXPECT--
+Dynamic include
+DYNAMIC INCLUDE
diff --git a/ext/opcache/zend_accelerator_module.c b/ext/opcache/zend_accelerator_module.c
index 778fee54b..0d452adf8 100644
--- a/ext/opcache/zend_accelerator_module.c
+++ b/ext/opcache/zend_accelerator_module.c
@@ -503,6 +503,7 @@ static ZEND_FUNCTION(opcache_get_status)
add_assoc_long(statistics, "num_cached_keys", ZCSG(hash).num_entries);
add_assoc_long(statistics, "max_cached_keys", ZCSG(hash).max_num_entries);
add_assoc_long(statistics, "hits", ZCSG(hits));
+ add_assoc_long(statistics, "start_time", ZCSG(start_time));
add_assoc_long(statistics, "last_restart_time", ZCSG(last_restart_time));
add_assoc_long(statistics, "oom_restarts", ZCSG(oom_restarts));
add_assoc_long(statistics, "wasted_restarts", ZCSG(wasted_restarts));
diff --git a/ext/opcache/zend_accelerator_util_funcs.c b/ext/opcache/zend_accelerator_util_funcs.c
index 7d5028c4c..75b156171 100644
--- a/ext/opcache/zend_accelerator_util_funcs.c
+++ b/ext/opcache/zend_accelerator_util_funcs.c
@@ -857,7 +857,7 @@ static void zend_do_delayed_early_binding(zend_op_array *op_array, zend_uint ear
}
opline_num = op_array->opcodes[opline_num].result.u.opline_num;
}
- zend_restore_compiled_filename(orig_compiled_filename);
+ zend_restore_compiled_filename(orig_compiled_filename TSRMLS_CC);
CG(in_compilation) = orig_in_compilation;
}
}
diff --git a/ext/opcache/zend_shared_alloc.c b/ext/opcache/zend_shared_alloc.c
index f4465ce78..18e8bdb1f 100644
--- a/ext/opcache/zend_shared_alloc.c
+++ b/ext/opcache/zend_shared_alloc.c
@@ -284,7 +284,7 @@ static size_t zend_shared_alloc_get_largest_free_block(void)
void *zend_shared_alloc(size_t size)
{
int i;
- unsigned int block_size = size + sizeof(zend_shared_memory_block_header);
+ unsigned int block_size = ZEND_ALIGNED_SIZE(size);
TSRMLS_FETCH();
#if 1
@@ -298,19 +298,11 @@ void *zend_shared_alloc(size_t size)
}
for (i = 0; i < ZSMMG(shared_segments_count); i++) {
if (ZSMMG(shared_segments)[i]->size - ZSMMG(shared_segments)[i]->pos >= block_size) { /* found a valid block */
- zend_shared_memory_block_header *p = (zend_shared_memory_block_header *) (((char *) ZSMMG(shared_segments)[i]->p) + ZSMMG(shared_segments)[i]->pos);
- int remainder = block_size % PLATFORM_ALIGNMENT;
- void *retval;
+ void *retval = (void *) (((char *) ZSMMG(shared_segments)[i]->p) + ZSMMG(shared_segments)[i]->pos);
- if (remainder != 0) {
- size += PLATFORM_ALIGNMENT - remainder;
- block_size += PLATFORM_ALIGNMENT - remainder;
- }
ZSMMG(shared_segments)[i]->pos += block_size;
ZSMMG(shared_free) -= block_size;
- p->size = size;
- retval = ((char *) p) + sizeof(zend_shared_memory_block_header);
- memset(retval, 0, size);
+ memset(retval, 0, block_size);
return retval;
}
}
diff --git a/ext/opcache/zend_shared_alloc.h b/ext/opcache/zend_shared_alloc.h
index 23af630f8..b7f36299b 100644
--- a/ext/opcache/zend_shared_alloc.h
+++ b/ext/opcache/zend_shared_alloc.h
@@ -89,10 +89,6 @@ typedef struct _handler_entry {
zend_shared_memory_handlers *handler;
} zend_shared_memory_handler_entry;
-typedef struct _zend_shared_memory_block_header {
- int size;
-} zend_shared_memory_block_header;
-
typedef struct _zend_shared_memory_state {
int *positions; /* current positions for each segment */
int shared_free; /* amount of free shared memory */
diff --git a/ext/pdo_pgsql/tests/is_in_transaction.phpt b/ext/pdo_pgsql/tests/is_in_transaction.phpt
index 99ff56162..72da4f4e0 100644
--- a/ext/pdo_pgsql/tests/is_in_transaction.phpt
+++ b/ext/pdo_pgsql/tests/is_in_transaction.phpt
@@ -57,10 +57,10 @@ var_dump($db->inTransaction());
?>
--EXPECT--
Test PDO::PGSQL_TRANSACTION_INTRANS
-int(2)
+bool(true)
Test PDO::PGSQL_TRANSACTION_IDLE
-int(0)
+bool(false)
Test PDO::PGSQL_TRANSACTION_INERROR
-int(3)
+bool(true)
Test PDO::PGSQL_TRANSACTION_IDLE
-int(0)
+bool(false)
diff --git a/ext/pgsql/tests/bug46408.phpt b/ext/pgsql/tests/bug46408.phpt
index 8c72ba5f3..bf8429090 100644
--- a/ext/pgsql/tests/bug46408.phpt
+++ b/ext/pgsql/tests/bug46408.phpt
@@ -3,6 +3,9 @@ Bug #46408 (Locale number format settings can cause pg_query_params to break wit
--SKIPIF--
<?php
require_once('skipif.inc');
+if (false === setlocale(LC_ALL, 'hr_HR.utf-8', 'hr_HR')) {
+ echo "skip Locale hr_HR.utf-8 not present";
+}
?>
--FILE--
<?php
diff --git a/ext/phar/tests/phpinfo_001.phpt b/ext/phar/tests/phpinfo_001.phpt
index 5de74dac0..d99ccd180 100644
--- a/ext/phar/tests/phpinfo_001.phpt
+++ b/ext/phar/tests/phpinfo_001.phpt
@@ -26,7 +26,7 @@ phpinfo(INFO_MODULES);
Phar: PHP Archive support => enabled
Phar EXT version => %s
Phar API version => 1.1.1
-SVN revision => %sRevision: %s $
+SVN revision => %sId: %s $
Phar-based phar archives => enabled
Tar-based phar archives => enabled
ZIP-based phar archives => enabled
@@ -48,7 +48,7 @@ Phar
Phar: PHP Archive support => enabled
Phar EXT version => %s
Phar API version => 1.1.1
-SVN revision => %sRevision: %s $
+SVN revision => %sId: %s $
Phar-based phar archives => enabled
Tar-based phar archives => enabled
ZIP-based phar archives => enabled
diff --git a/ext/phar/tests/phpinfo_002.phpt b/ext/phar/tests/phpinfo_002.phpt
index da6db9571..ef505feda 100644
--- a/ext/phar/tests/phpinfo_002.phpt
+++ b/ext/phar/tests/phpinfo_002.phpt
@@ -24,7 +24,7 @@ Phar
Phar: PHP Archive support => enabled
Phar EXT version => %s
Phar API version => 1.1.1
-SVN revision => %sRevision: %s $
+SVN revision => %sId: %s $
Phar-based phar archives => enabled
Tar-based phar archives => enabled
ZIP-based phar archives => enabled
diff --git a/ext/phar/tests/phpinfo_004.phpt b/ext/phar/tests/phpinfo_004.phpt
index c49205c14..24263f07b 100644
--- a/ext/phar/tests/phpinfo_004.phpt
+++ b/ext/phar/tests/phpinfo_004.phpt
@@ -29,7 +29,7 @@ phpinfo(INFO_MODULES);
<tr class="h"><th>Phar: PHP Archive support</th><th>enabled</th></tr>
<tr><td class="e">Phar EXT version </td><td class="v">%s </td></tr>
<tr><td class="e">Phar API version </td><td class="v">1.1.1 </td></tr>
-<tr><td class="e">SVN revision </td><td class="v">%sRevision: %s $ </td></tr>
+<tr><td class="e">SVN revision </td><td class="v">%sId: %s $ </td></tr>
<tr><td class="e">Phar-based phar archives </td><td class="v">enabled </td></tr>
<tr><td class="e">Tar-based phar archives </td><td class="v">enabled </td></tr>
<tr><td class="e">ZIP-based phar archives </td><td class="v">enabled </td></tr>
@@ -53,7 +53,7 @@ Phar based on pear/PHP_Archive, original concept by Davey Shafik.<br />Phar full
<tr class="h"><th>Phar: PHP Archive support</th><th>enabled</th></tr>
<tr><td class="e">Phar EXT version </td><td class="v">%s </td></tr>
<tr><td class="e">Phar API version </td><td class="v">1.1.1 </td></tr>
-<tr><td class="e">SVN revision </td><td class="v">%sRevision: %s $ </td></tr>
+<tr><td class="e">SVN revision </td><td class="v">%sId: %s $ </td></tr>
<tr><td class="e">Phar-based phar archives </td><td class="v">enabled </td></tr>
<tr><td class="e">Tar-based phar archives </td><td class="v">enabled </td></tr>
<tr><td class="e">ZIP-based phar archives </td><td class="v">enabled </td></tr>
diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c
index 15befa2fc..b65ccaa26 100644
--- a/ext/reflection/php_reflection.c
+++ b/ext/reflection/php_reflection.c
@@ -1298,7 +1298,8 @@ static void reflection_method_factory(zend_class_entry *ce, zend_function *metho
}
MAKE_STD_ZVAL(name);
MAKE_STD_ZVAL(classname);
- ZVAL_STRING(name, method->common.function_name, 1);
+ ZVAL_STRING(name, (method->common.scope && method->common.scope->trait_aliases)?
+ zend_resolve_method_name(ce, method) : method->common.function_name, 1);
ZVAL_STRINGL(classname, method->common.scope->name, method->common.scope->name_length, 1);
reflection_instantiate(reflection_method_ptr, object TSRMLS_CC);
intern = (reflection_object *) zend_object_store_get_object(object TSRMLS_CC);
diff --git a/ext/reflection/tests/bug64239.phpt b/ext/reflection/tests/bug64239.phpt
new file mode 100644
index 000000000..9acdc1987
--- /dev/null
+++ b/ext/reflection/tests/bug64239.phpt
@@ -0,0 +1,44 @@
+--TEST--
+Bug #64239 (ReflectionClass::getMethods() changed behavior)
+--FILE--
+<?php
+class A {
+ use T2 { t2method as Bmethod; }
+}
+trait T2 {
+ public function t2method() {
+ }
+}
+
+class B extends A{
+}
+
+$obj = new ReflectionClass("B");
+print_r($obj->getMethods());
+print_r(($method = $obj->getMethod("Bmethod")));
+var_dump($method->getName());
+var_dump($method->getShortName());
+?>
+--EXPECT--
+Array
+(
+ [0] => ReflectionMethod Object
+ (
+ [name] => Bmethod
+ [class] => A
+ )
+
+ [1] => ReflectionMethod Object
+ (
+ [name] => t2method
+ [class] => A
+ )
+
+)
+ReflectionMethod Object
+(
+ [name] => Bmethod
+ [class] => A
+)
+string(7) "Bmethod"
+string(7) "Bmethod"
diff --git a/ext/spl/spl_dllist.c b/ext/spl/spl_dllist.c
index 83610863e..aa462dfd7 100644
--- a/ext/spl/spl_dllist.c
+++ b/ext/spl/spl_dllist.c
@@ -1246,7 +1246,6 @@ SPL_METHOD(SplDoublyLinkedList, add)
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &zindex, &value) == FAILURE) {
return;
}
- SEPARATE_ARG_IF_REF(value);
intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
index = spl_offset_convert_to_long(zindex TSRMLS_CC);
@@ -1256,6 +1255,7 @@ SPL_METHOD(SplDoublyLinkedList, add)
return;
}
+ Z_ADDREF_P(value);
if (index == intern->llist->count) {
/* If index is the last entry+1 then we do a push because we're not inserting before any entry */
spl_ptr_llist_push(intern->llist, value TSRMLS_CC);
diff --git a/ext/standard/info.c b/ext/standard/info.c
index 20e6b0c4a..e8ba90807 100644
--- a/ext/standard/info.c
+++ b/ext/standard/info.c
@@ -316,7 +316,7 @@ char* php_get_windows_name()
}
if (VER_PLATFORM_WIN32_NT==osvi.dwPlatformId && osvi.dwMajorVersion > 4 ) {
- if (osvi.dwMajorVersion == 6) {
+ if (osvi.dwMajorVersion == 6) {
if( osvi.dwMinorVersion == 0 ) {
if( osvi.wProductType == VER_NT_WORKSTATION ) {
major = "Windows Vista";
@@ -330,6 +330,12 @@ char* php_get_windows_name()
} else {
major = "Windows Server 2008 R2";
}
+ } else if ( osvi.dwMinorVersion == 2 ) {
+ if( osvi.wProductType == VER_NT_WORKSTATION ) {
+ major = "Windows 8";
+ } else {
+ major = "Windows Server 2012";
+ }
} else {
major = "Unknown Windows version";
}
diff --git a/ext/standard/string.c b/ext/standard/string.c
index e245ce3fb..f3f78100b 100644
--- a/ext/standard/string.c
+++ b/ext/standard/string.c
@@ -1715,7 +1715,7 @@ PHP_FUNCTION(stristr)
if (Z_TYPE_P(needle) == IS_STRING) {
char *orig_needle;
if (!Z_STRLEN_P(needle)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Empty delimiter");
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Empty needle");
efree(haystack_dup);
RETURN_FALSE;
}
@@ -1765,7 +1765,7 @@ PHP_FUNCTION(strstr)
if (Z_TYPE_P(needle) == IS_STRING) {
if (!Z_STRLEN_P(needle)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Empty delimiter");
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Empty needle");
RETURN_FALSE;
}
diff --git a/ext/standard/tests/strings/stristr_error.phpt b/ext/standard/tests/strings/stristr_error.phpt
index 831d93f4e..2da35de73 100644
--- a/ext/standard/tests/strings/stristr_error.phpt
+++ b/ext/standard/tests/strings/stristr_error.phpt
@@ -50,11 +50,11 @@ NULL
-- Testing stristr() function with empty haystack --
-Warning: stristr(): Empty delimiter in %s on line %d
+Warning: stristr(): Empty needle in %s on line %d
bool(false)
-- Testing stristr() function with empty needle --
-Warning: stristr(): Empty delimiter in %s on line %d
+Warning: stristr(): Empty needle in %s on line %d
bool(false)
===DONE===
diff --git a/ext/standard/tests/strings/strstr.phpt b/ext/standard/tests/strings/strstr.phpt
index 1c8d753e6..b135258f8 100644
--- a/ext/standard/tests/strings/strstr.phpt
+++ b/ext/standard/tests/strings/strstr.phpt
Binary files differ
diff --git a/ext/zip/lib/zip_close.c b/ext/zip/lib/zip_close.c
index e66c56697..576be3b35 100644
--- a/ext/zip/lib/zip_close.c
+++ b/ext/zip/lib/zip_close.c
@@ -88,9 +88,6 @@ zip_close(struct zip *za)
if (za == NULL)
return -1;
- if (za->zp == NULL)
- return -1;
-
if (!_zip_changed(za, &survivors)) {
_zip_free(za);
return 0;
@@ -196,7 +193,7 @@ zip_close(struct zip *za)
}
else {
/* copy existing directory entries */
- if (fseeko(za->zp, za->cdir->entry[i].offset, SEEK_SET) != 0) {
+ if ((NULL == za->zp) || (fseeko(za->zp, za->cdir->entry[i].offset, SEEK_SET) != 0)) {
_zip_error_set(&za->error, ZIP_ER_SEEK, errno);
error = 1;
break;
diff --git a/main/php_version.h b/main/php_version.h
index 61c507b32..04944aa63 100644
--- a/main/php_version.h
+++ b/main/php_version.h
@@ -3,6 +3,6 @@
#define PHP_MAJOR_VERSION 5
#define PHP_MINOR_VERSION 5
#define PHP_RELEASE_VERSION 0
-#define PHP_EXTRA_VERSION "beta1"
-#define PHP_VERSION "5.5.0beta1"
+#define PHP_EXTRA_VERSION "beta2"
+#define PHP_VERSION "5.5.0beta2"
#define PHP_VERSION_ID 50500
diff --git a/main/win32_internal_function_disabled.h b/main/win32_internal_function_disabled.h
index 3a78f6c59..80fd8d1b8 100644
--- a/main/win32_internal_function_disabled.h
+++ b/main/win32_internal_function_disabled.h
@@ -23,12 +23,14 @@
/*
Windows Server 2008 6.0
Windows Vista 6.0
+
+Verssions below are not supported anymore, php won't even load:
Windows Server 2003 R2 5.2
Windows Server 2003 5.2
Windows XP 5.1
Windows 2000 5.0
*/
-static const char *function_name_5[] = {"link", NULL};
-const int function_name_cnt_5 = 1;
+static const char *function_name_5[] = {NULL};
+const int function_name_cnt_5 = 0;
static const char *function_name_6[] = {"readlink", "symlink", NULL};
const int function_name_cnt_6 = 2;
diff --git a/makedist b/makedist
index bce40a948..f5823d392 100755
--- a/makedist
+++ b/makedist
@@ -35,7 +35,10 @@ if test "${1}" = "1" -a "${2}" -lt "28"; then
fi
IFS="$old_IFS"
-PHPROOT=git@git.php.net:php-src.git
+if test "$PHPROOTx" == "x"; then
+ PHPROOT=git@git.php.net:php-src.git;
+fi
+
LT_TARGETS='ltconfig ltmain.sh config.guess config.sub'
if echo '\c' | grep -s c >/dev/null 2>&1
diff --git a/pear/install-pear-nozlib.phar b/pear/install-pear-nozlib.phar
index dd40f86cc..cd9a31f6f 100644
--- a/pear/install-pear-nozlib.phar
+++ b/pear/install-pear-nozlib.phar
@@ -1234,13 +1234,16 @@ if (extension_loaded('phar')) {if (isset($_SERVER) && isset($_SERVER['REQUEST_UR
require_once 'phar://install-pear-nozlib.phar/index.php';
-__HALT_COMPILER();-
-m
-m
-
-
-¾m
-
+__HALT_COMPILER();\
+2
+2
+
+
+v
+v
+
+
+
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
@@ -1277,7 +1280,7 @@ m
* @author Vincent Blavet <vincent@phpconcept.net>
* @copyright 1997-2010 The Authors
* @license http://www.opensource.org/licenses/bsd-license.php New BSD License
- * @version CVS: $Id: Tar.php 311709 2011-06-01 12:16:57Z mrook $
+ * @version CVS: $Id$
* @link http://pear.php.net/package/Archive_Tar
*/
@@ -1292,7 +1295,7 @@ define('ARCHIVE_TAR_END_BLOCK', pack("a512", ''));
* @package Archive_Tar
* @author Vincent Blavet <vincent@phpconcept.net>
* @license http://www.opensource.org/licenses/bsd-license.php New BSD License
-* @version $Revision: 311709 $
+* @version $Revision$
*/
class Archive_Tar extends PEAR
{
@@ -1481,9 +1484,9 @@ class Archive_Tar extends PEAR
// }}}
// {{{ extract()
- function extract($p_path='')
+ function extract($p_path='', $p_preserve=false)
{
- return $this->extractModify($p_path, '');
+ return $this->extractModify($p_path, '', $p_preserve);
}
// }}}
@@ -1649,11 +1652,13 @@ class Archive_Tar extends PEAR
* with the string.
* @param string $p_string The content of the file added in
* the archive.
+ * @param int $p_datetime A custom date/time (unix timestamp)
+ * for the file (optional).
*
* @return true on success, false on error.
* @access public
*/
- function addString($p_filename, $p_string)
+ function addString($p_filename, $p_string, $p_datetime = false)
{
$v_result = true;
@@ -1668,7 +1673,7 @@ class Archive_Tar extends PEAR
return false;
// Need to check the get back to the temporary file ? ....
- $v_result = $this->_addString($p_filename, $p_string);
+ $v_result = $this->_addString($p_filename, $p_string, $p_datetime);
$this->_writeFooter();
@@ -1703,24 +1708,25 @@ class Archive_Tar extends PEAR
* is returned. However the result can be a partial extraction that may
* need to be manually cleaned.
*
- * @param string $p_path The path of the directory where the
- * files/dir need to by extracted.
- * @param string $p_remove_path Part of the memorized path that can be
- * removed if present at the beginning of
- * the file/dir path.
+ * @param string $p_path The path of the directory where the
+ * files/dir need to by extracted.
+ * @param string $p_remove_path Part of the memorized path that can be
+ * removed if present at the beginning of
+ * the file/dir path.
+ * @param boolean $p_preserve Preserve user/group ownership of files
*
* @return boolean true on success, false on error.
* @access public
* @see extractList()
*/
- function extractModify($p_path, $p_remove_path)
+ function extractModify($p_path, $p_remove_path, $p_preserve=false)
{
$v_result = true;
$v_list_detail = array();
if ($v_result = $this->_openRead()) {
$v_result = $this->_extractList($p_path, $v_list_detail,
- "complete", 0, $p_remove_path);
+ "complete", 0, $p_remove_path, $p_preserve);
$this->_close();
}
@@ -1759,20 +1765,21 @@ class Archive_Tar extends PEAR
* If indicated the $p_remove_path can be used in the same way as it is
* used in extractModify() method.
*
- * @param array $p_filelist An array of filenames and directory names,
- * or a single string with names separated
- * by a single blank space.
- * @param string $p_path The path of the directory where the
- * files/dir need to by extracted.
- * @param string $p_remove_path Part of the memorized path that can be
- * removed if present at the beginning of
- * the file/dir path.
+ * @param array $p_filelist An array of filenames and directory names,
+ * or a single string with names separated
+ * by a single blank space.
+ * @param string $p_path The path of the directory where the
+ * files/dir need to by extracted.
+ * @param string $p_remove_path Part of the memorized path that can be
+ * removed if present at the beginning of
+ * the file/dir path.
+ * @param boolean $p_preserve Preserve user/group ownership of files
*
* @return true on success, false on error.
* @access public
* @see extractModify()
*/
- function extractList($p_filelist, $p_path='', $p_remove_path='')
+ function extractList($p_filelist, $p_path='', $p_remove_path='', $p_preserve=false)
{
$v_result = true;
$v_list_detail = array();
@@ -1788,7 +1795,7 @@ class Archive_Tar extends PEAR
if ($v_result = $this->_openRead()) {
$v_result = $this->_extractList($p_path, $v_list_detail, "partial",
- $v_list, $p_remove_path);
+ $v_list, $p_remove_path, $p_preserve);
$this->_close();
}
@@ -1914,15 +1921,17 @@ class Archive_Tar extends PEAR
// {{{ _openWrite()
function _openWrite()
{
- if ($this->_compress_type == 'gz')
+ if ($this->_compress_type == 'gz' && function_exists('gzopen'))
$this->_file = @gzopen($this->_tarname, "wb9");
- else if ($this->_compress_type == 'bz2')
+ else if ($this->_compress_type == 'bz2' && function_exists('bzopen'))
$this->_file = @bzopen($this->_tarname, "w");
else if ($this->_compress_type == 'none')
$this->_file = @fopen($this->_tarname, "wb");
- else
+ else {
$this->_error('Unknown or missing compression type ('
.$this->_compress_type.')');
+ return false;
+ }
if ($this->_file == 0) {
$this->_error('Unable to open in write mode \''
@@ -1967,15 +1976,17 @@ class Archive_Tar extends PEAR
// ----- File to open if the normal Tar file
$v_filename = $this->_tarname;
- if ($this->_compress_type == 'gz')
+ if ($this->_compress_type == 'gz' && function_exists('gzopen'))
$this->_file = @gzopen($v_filename, "rb");
- else if ($this->_compress_type == 'bz2')
+ else if ($this->_compress_type == 'bz2' && function_exists('bzopen'))
$this->_file = @bzopen($v_filename, "r");
else if ($this->_compress_type == 'none')
$this->_file = @fopen($v_filename, "rb");
- else
+ else {
$this->_error('Unknown or missing compression type ('
.$this->_compress_type.')');
+ return false;
+ }
if ($this->_file == 0) {
$this->_error('Unable to open in read mode \''.$v_filename.'\'');
@@ -1997,9 +2008,11 @@ class Archive_Tar extends PEAR
return false;
} else if ($this->_compress_type == 'none')
$this->_file = @fopen($this->_tarname, "r+b");
- else
+ else {
$this->_error('Unknown or missing compression type ('
.$this->_compress_type.')');
+ return false;
+ }
if ($this->_file == 0) {
$this->_error('Unable to open in read/write mode \''
@@ -2284,7 +2297,7 @@ class Archive_Tar extends PEAR
// }}}
// {{{ _addString()
- function _addString($p_filename, $p_string)
+ function _addString($p_filename, $p_string, $p_datetime = false)
{
if (!$this->_file) {
$this->_error('Invalid file descriptor');
@@ -2298,9 +2311,14 @@ class Archive_Tar extends PEAR
// ----- Calculate the stored filename
$p_filename = $this->_translateWinPath($p_filename, false);;
+
+ // ----- If datetime is not specified, set current time
+ if ($p_datetime === false) {
+ $p_datetime = time();
+ }
if (!$this->_writeHeaderBlock($p_filename, strlen($p_string),
- time(), 384, "", 0, 0))
+ $p_datetime, 384, "", 0, 0))
return false;
$i=0;
@@ -2583,10 +2601,20 @@ class Archive_Tar extends PEAR
for ($i=156; $i<512; $i++)
$v_checksum+=ord(substr($v_binary_data,$i,1));
- $v_data = unpack("a100filename/a8mode/a8uid/a8gid/a12size/a12mtime/"
- ."a8checksum/a1typeflag/a100link/a6magic/a2version/"
- ."a32uname/a32gname/a8devmajor/a8devminor",
- $v_binary_data);
+ if (version_compare(PHP_VERSION,"5.5.0-dev")<0) {
+ $fmt = "a100filename/a8mode/a8uid/a8gid/a12size/a12mtime/" .
+ "a8checksum/a1typeflag/a100link/a6magic/a2version/" .
+ "a32uname/a32gname/a8devmajor/a8devminor/a131prefix";
+ } else {
+ $fmt = "Z100filename/Z8mode/Z8uid/Z8gid/Z12size/Z12mtime/" .
+ "Z8checksum/Z1typeflag/Z100link/Z6magic/Z2version/" .
+ "Z32uname/Z32gname/Z8devmajor/Z8devminor/Z131prefix";
+ }
+ $v_data = unpack($fmt, $v_binary_data);
+
+ if (strlen($v_data["prefix"]) > 0) {
+ $v_data["filename"] = "$v_data[prefix]/$v_data[filename]";
+ }
// ----- Extract the checksum
$v_header['checksum'] = OctDec(trim($v_data['checksum']));
@@ -2742,7 +2770,7 @@ class Archive_Tar extends PEAR
// {{{ _extractList()
function _extractList($p_path, &$p_list_detail, $p_mode,
- $p_file_list, $p_remove_path)
+ $p_file_list, $p_remove_path, $p_preserve=false)
{
$v_result=true;
$v_nb = 0;
@@ -2829,10 +2857,14 @@ class Archive_Tar extends PEAR
if (($v_extract_file) && (!$v_listing))
{
if (($p_remove_path != '')
- && (substr($v_header['filename'], 0, $p_remove_path_size)
- == $p_remove_path))
+ && (substr($v_header['filename'].'/', 0, $p_remove_path_size)
+ == $p_remove_path)) {
$v_header['filename'] = substr($v_header['filename'],
$p_remove_path_size);
+ if( $v_header['filename'] == '' ){
+ continue;
+ }
+ }
if (($p_path != './') && ($p_path != '/')) {
while (substr($p_path, -1) == '/')
$p_path = substr($p_path, 0, strlen($p_path)-1);
@@ -2909,6 +2941,11 @@ class Archive_Tar extends PEAR
}
@fclose($v_dest_file);
+
+ if ($p_preserve) {
+ @chown($v_header['filename'], $v_header['uid']);
+ @chgrp($v_header['filename'], $v_header['gid']);
+ }
// ----- Change the file mode, mtime
@touch($v_header['filename'], $v_header['mtime']);
@@ -3004,12 +3041,20 @@ class Archive_Tar extends PEAR
}
if ($this->_compress_type == 'gz') {
+ $end_blocks = 0;
+
while (!@gzeof($v_temp_tar)) {
$v_buffer = @gzread($v_temp_tar, 512);
- if ($v_buffer == ARCHIVE_TAR_END_BLOCK) {
+ if ($v_buffer == ARCHIVE_TAR_END_BLOCK || strlen($v_buffer) == 0) {
+ $end_blocks++;
// do not copy end blocks, we will re-make them
// after appending
continue;
+ } elseif ($end_blocks > 0) {
+ for ($i = 0; $i < $end_blocks; $i++) {
+ $this->_writeBlock(ARCHIVE_TAR_END_BLOCK);
+ }
+ $end_blocks = 0;
}
$v_binary_data = pack("a512", $v_buffer);
$this->_writeBlock($v_binary_data);
@@ -3018,9 +3063,19 @@ class Archive_Tar extends PEAR
@gzclose($v_temp_tar);
}
elseif ($this->_compress_type == 'bz2') {
+ $end_blocks = 0;
+
while (strlen($v_buffer = @bzread($v_temp_tar, 512)) > 0) {
- if ($v_buffer == ARCHIVE_TAR_END_BLOCK) {
+ if ($v_buffer == ARCHIVE_TAR_END_BLOCK || strlen($v_buffer) == 0) {
+ $end_blocks++;
+ // do not copy end blocks, we will re-make them
+ // after appending
continue;
+ } elseif ($end_blocks > 0) {
+ for ($i = 0; $i < $end_blocks; $i++) {
+ $this->_writeBlock(ARCHIVE_TAR_END_BLOCK);
+ }
+ $end_blocks = 0;
}
$v_binary_data = pack("a512", $v_buffer);
$this->_writeBlock($v_binary_data);
@@ -3151,7 +3206,11 @@ class Archive_Tar extends PEAR
}
}
}
- $v_result = strtr($v_result, '\\', '/');
+
+ if (defined('OS_WINDOWS') && OS_WINDOWS) {
+ $v_result = strtr($v_result, '\\', '/');
+ }
+
return $v_result;
}
@@ -3177,8 +3236,8 @@ class Archive_Tar extends PEAR
}
?>
-package.xml
-<package packagerversion="1.9.0" 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.xml
+<package packagerversion="1.9.4" 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>Archive_Tar</name>
<channel>pear.php.net</channel>
<summary>Tar file management class</summary>
@@ -3210,10 +3269,10 @@ loaded. Bz2 compression is also supported with the bz2 extension loaded.</descri
<email>stig@php.net</email>
<active>no</active>
</helper>
- <date>2010-04-26</date>
- <time>09:22:35</time>
+ <date>2013-02-09</date>
+ <time>11:44:17</time>
<version>
- <release>1.3.7</release>
+ <release>1.3.11</release>
<api>1.3.1</api>
</version>
<stability>
@@ -3222,11 +3281,12 @@ loaded. Bz2 compression is also supported with the bz2 extension loaded.</descri
</stability>
<license uri="http://www.opensource.org/licenses/bsd-license.php">New BSD License</license>
<notes>
-PEAR compatibility update
+* Fix Bug #19746: Broken with PHP 5.5 [mrook]
+ * Implement Feature #11258: Custom date/time in files added on-the-fly [mrook]
</notes>
<contents>
<dir name="/">
- <file baseinstalldir="/" md5sum="7406d6ed69f7c24506c93e02b0cdf839" name="Archive/Tar.php" role="php" />
+ <file baseinstalldir="/" md5sum="c6a0c1df229783f55d2c3e5e93c46d6e" name="Archive/Tar.php" role="php" />
<file baseinstalldir="/" md5sum="29b03715377b18b1fafcff98a99cc9a7" name="docs/Archive_Tar.txt" role="doc" />
</dir>
</contents>
@@ -3250,6 +3310,77 @@ PEAR compatibility update
<changelog>
<release>
<version>
+ <release>1.3.10</release>
+ <api>1.3.1</api>
+ </version>
+ <stability>
+ <release>stable</release>
+ <api>stable</api>
+ </stability>
+ <date>2012-04-10</date>
+ <license uri="http://www.opensource.org/licenses/bsd-license.php">New BSD
+ License</license>
+ <notes>
+* Fix Bug #13361: Unable to add() some files (ex. mp3) [mrook]
+ * Fix Bug #19330: Class creates incorrect (non-readable) tar.gz file
+ * [mrook]
+ </notes>
+ </release>
+ <release>
+ <version>
+ <release>1.3.9</release>
+ <api>1.3.1</api>
+ </version>
+ <stability>
+ <release>stable</release>
+ <api>stable</api>
+ </stability>
+ <date>2012-02-27</date>
+ <license uri="http://www.opensource.org/licenses/bsd-license.php">New BSD License</license>
+ <notes>
+* Fix Bug #16759: No error thrown from missing PHP zlib functions [mrook]
+ * Fix Bug #18877: Incorrect handling of backslashes in filenames on Linux [mrook]
+ * Fix Bug #19085: Error while packaging [mrook]
+ * Fix Bug #19289: Invalid tar file generated [mrook]
+ </notes>
+ </release>
+ <release>
+ <version>
+ <release>1.3.8</release>
+ <api>1.3.1</api>
+ </version>
+ <stability>
+ <release>stable</release>
+ <api>stable</api>
+ </stability>
+ <date>2011-10-14</date>
+ <license uri="http://www.opensource.org/licenses/bsd-license.php">New BSD License</license>
+ <notes>
+* Fix Bug #17853: Test failure: dirtraversal.phpt [mrook]
+ * Fix Bug #18512: dead links are not saved in tar file [mrook]
+ * Fix Bug #18702: Unpacks incorrectly on long file names using header prefix [mrook]
+ * Implement Feature #10145: Patch to return a Pear Error Object on failure [mrook]
+ * Implement Feature #17491: Option to preserve permissions [mrook]
+ * Implement Feature #17813: Prevent PHP notice when extracting corrupted archive [mrook]
+ </notes>
+ </release>
+ <release>
+ <version>
+ <release>1.3.7</release>
+ <api>1.3.1</api>
+ </version>
+ <stability>
+ <release>stable</release>
+ <api>stable</api>
+ </stability>
+ <date>2010-04-26</date>
+ <license uri="http://www.opensource.org/licenses/bsd-license.php">New BSD License</license>
+ <notes>
+PEAR compatibility update
+ </notes>
+ </release>
+ <release>
+ <version>
<release>1.3.6</release>
<api>1.3.1</api>
</version>
@@ -3495,7 +3626,7 @@ Windows bugfix: used wrong directory separators
</release>
</changelog>
</package>
-
+
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
@@ -3527,29 +3658,27 @@ Windows bugfix: used wrong directory separators
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- *
- * @category File_Formats
- * @package Archive_Tar
- * @author Vincent Blavet <vincent@phpconcept.net>
- * @copyright 1997-2008 The Authors
- * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
- * @version CVS: $Id: Tar.php 295988 2010-03-09 08:39:37Z mrook $
- * @link http://pear.php.net/package/Archive_Tar
+ * @category File_Formats
+ * @package Archive_Tar
+ * @author Vincent Blavet <vincent@phpconcept.net>
+ * @copyright 1997-2010 The Authors
+ * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Archive_Tar
*/
require_once 'PEAR.php';
-
-define ('ARCHIVE_TAR_ATT_SEPARATOR', 90001);
-define ('ARCHIVE_TAR_END_BLOCK', pack("a512", ''));
+define('ARCHIVE_TAR_ATT_SEPARATOR', 90001);
+define('ARCHIVE_TAR_END_BLOCK', pack("a512", ''));
/**
* Creates a (compressed) Tar archive
*
-* @author Vincent Blavet <vincent@phpconcept.net>
-* @version $Revision: 295988 $
-* @license http://www.opensource.org/licenses/bsd-license.php New BSD License
-* @package Archive_Tar
+* @package Archive_Tar
+* @author Vincent Blavet <vincent@phpconcept.net>
+* @license http://www.opensource.org/licenses/bsd-license.php New BSD License
+* @version $Revision$
*/
class Archive_Tar extends PEAR
{
@@ -3588,6 +3717,11 @@ class Archive_Tar extends PEAR
*/
var $_ignore_regexp='';
+ /**
+ * @var object PEAR_Error object
+ */
+ var $error_object=null;
+
// {{{ constructor
/**
* Archive_Tar Class constructor. This flavour of the constructor only
@@ -3596,11 +3730,12 @@ class Archive_Tar extends PEAR
* If the compress argument is set the tar will be read or created as a
* gzip or bz2 compressed TAR file.
*
- * @param string $p_tarname The name of the tar archive to create
- * @param string $p_compress can be null, 'gz' or 'bz2'. This
- * parameter indicates if gzip or bz2 compression
- * is required. For compatibility reason the
- * boolean value 'true' means 'gz'.
+ * @param string $p_tarname The name of the tar archive to create
+ * @param string $p_compress can be null, 'gz' or 'bz2'. This
+ * parameter indicates if gzip or bz2 compression
+ * is required. For compatibility reason the
+ * boolean value 'true' means 'gz'.
+ *
* @access public
*/
function Archive_Tar($p_tarname, $p_compress = null)
@@ -3617,7 +3752,7 @@ class Archive_Tar extends PEAR
if ($data == "\37\213") {
$this->_compress = true;
$this->_compress_type = 'gz';
- // No sure it's enought for a magic code ....
+ // No sure it's enought for a magic code ....
} elseif ($data == "BZ") {
$this->_compress = true;
$this->_compress_type = 'bz2';
@@ -3694,11 +3829,12 @@ class Archive_Tar extends PEAR
* sub-directories are also added.
* See also createModify() method for more details.
*
- * @param array $p_filelist An array of filenames and directory names, or a
- * single string with names separated by a single
- * blank space.
- * @return true on success, false on error.
- * @see createModify()
+ * @param array $p_filelist An array of filenames and directory names, or a
+ * single string with names separated by a single
+ * blank space.
+ *
+ * @return true on success, false on error.
+ * @see createModify()
* @access public
*/
function create($p_filelist)
@@ -3716,11 +3852,12 @@ class Archive_Tar extends PEAR
* even if a file with the same name is already archived.
* See also createModify() method for more details.
*
- * @param array $p_filelist An array of filenames and directory names, or a
- * single string with names separated by a single
- * blank space.
- * @return true on success, false on error.
- * @see createModify()
+ * @param array $p_filelist An array of filenames and directory names, or a
+ * single string with names separated by a single
+ * blank space.
+ *
+ * @return true on success, false on error.
+ * @see createModify()
* @access public
*/
function add($p_filelist)
@@ -3730,9 +3867,9 @@ class Archive_Tar extends PEAR
// }}}
// {{{ extract()
- function extract($p_path='')
+ function extract($p_path='', $p_preserve=false)
{
- return $this->extractModify($p_path, '');
+ return $this->extractModify($p_path, '', $p_preserve);
}
// }}}
@@ -3776,16 +3913,17 @@ class Archive_Tar extends PEAR
* for extraction in a different path than the origin files are.
* See also addModify() method for file adding properties.
*
- * @param array $p_filelist An array of filenames and directory names,
- * or a single string with names separated by
- * a single blank space.
- * @param string $p_add_dir A string which contains a path to be added
- * to the memorized path of each element in
- * the list.
- * @param string $p_remove_dir A string which contains a path to be
- * removed from the memorized path of each
- * element in the list, when relevant.
- * @return boolean true on success, false on error.
+ * @param array $p_filelist An array of filenames and directory names,
+ * or a single string with names separated by
+ * a single blank space.
+ * @param string $p_add_dir A string which contains a path to be added
+ * to the memorized path of each element in
+ * the list.
+ * @param string $p_remove_dir A string which contains a path to be
+ * removed from the memorized path of each
+ * element in the list, when relevant.
+ *
+ * @return boolean true on success, false on error.
* @access public
* @see addModify()
*/
@@ -3848,17 +3986,18 @@ class Archive_Tar extends PEAR
* If a file/dir is not readable the file/dir is ignored. However an
* error text is send to PEAR error.
*
- * @param array $p_filelist An array of filenames and directory
- * names, or a single string with names
- * separated by a single blank space.
- * @param string $p_add_dir A string which contains a path to be
- * added to the memorized path of each
- * element in the list.
- * @param string $p_remove_dir A string which contains a path to be
- * removed from the memorized path of
- * each element in the list, when
- * relevant.
- * @return true on success, false on error.
+ * @param array $p_filelist An array of filenames and directory
+ * names, or a single string with names
+ * separated by a single blank space.
+ * @param string $p_add_dir A string which contains a path to be
+ * added to the memorized path of each
+ * element in the list.
+ * @param string $p_remove_dir A string which contains a path to be
+ * removed from the memorized path of
+ * each element in the list, when
+ * relevant.
+ *
+ * @return true on success, false on error.
* @access public
*/
function addModify($p_filelist, $p_add_dir, $p_remove_dir='')
@@ -3867,7 +4006,7 @@ class Archive_Tar extends PEAR
if (!$this->_isArchive())
$v_result = $this->createModify($p_filelist, $p_add_dir,
- $p_remove_dir);
+ $p_remove_dir);
else {
if (is_array($p_filelist))
$v_list = $p_filelist;
@@ -3891,15 +4030,18 @@ class Archive_Tar extends PEAR
* end of the existing archive. If the archive does not yet exists it
* is created.
*
- * @param string $p_filename A string which contains the full
- * filename path that will be associated
- * with the string.
- * @param string $p_string The content of the file added in
- * the archive.
- * @return true on success, false on error.
+ * @param string $p_filename A string which contains the full
+ * filename path that will be associated
+ * with the string.
+ * @param string $p_string The content of the file added in
+ * the archive.
+ * @param int $p_datetime A custom date/time (unix timestamp)
+ * for the file (optional).
+ *
+ * @return true on success, false on error.
* @access public
*/
- function addString($p_filename, $p_string)
+ function addString($p_filename, $p_string, $p_datetime = false)
{
$v_result = true;
@@ -3914,7 +4056,7 @@ class Archive_Tar extends PEAR
return false;
// Need to check the get back to the temporary file ? ....
- $v_result = $this->_addString($p_filename, $p_string);
+ $v_result = $this->_addString($p_filename, $p_string, $p_datetime);
$this->_writeFooter();
@@ -3949,23 +4091,25 @@ class Archive_Tar extends PEAR
* is returned. However the result can be a partial extraction that may
* need to be manually cleaned.
*
- * @param string $p_path The path of the directory where the
- * files/dir need to by extracted.
- * @param string $p_remove_path Part of the memorized path that can be
- * removed if present at the beginning of
- * the file/dir path.
- * @return boolean true on success, false on error.
+ * @param string $p_path The path of the directory where the
+ * files/dir need to by extracted.
+ * @param string $p_remove_path Part of the memorized path that can be
+ * removed if present at the beginning of
+ * the file/dir path.
+ * @param boolean $p_preserve Preserve user/group ownership of files
+ *
+ * @return boolean true on success, false on error.
* @access public
- * @see extractList()
+ * @see extractList()
*/
- function extractModify($p_path, $p_remove_path)
+ function extractModify($p_path, $p_remove_path, $p_preserve=false)
{
$v_result = true;
$v_list_detail = array();
if ($v_result = $this->_openRead()) {
$v_result = $this->_extractList($p_path, $v_list_detail,
- "complete", 0, $p_remove_path);
+ "complete", 0, $p_remove_path, $p_preserve);
$this->_close();
}
@@ -3977,8 +4121,10 @@ class Archive_Tar extends PEAR
/**
* This method extract from the archive one file identified by $p_filename.
* The return value is a string with the file content, or NULL on error.
- * @param string $p_filename The path of the file to extract in a string.
- * @return a string with the file content or NULL.
+ *
+ * @param string $p_filename The path of the file to extract in a string.
+ *
+ * @return a string with the file content or NULL.
* @access public
*/
function extractInString($p_filename)
@@ -3987,7 +4133,7 @@ class Archive_Tar extends PEAR
$v_result = $this->_extractInString($p_filename);
$this->_close();
} else {
- $v_result = NULL;
+ $v_result = null;
}
return $v_result;
@@ -4001,19 +4147,22 @@ class Archive_Tar extends PEAR
* in the directory indicated by the optional $p_path parameter.
* If indicated the $p_remove_path can be used in the same way as it is
* used in extractModify() method.
- * @param array $p_filelist An array of filenames and directory names,
- * or a single string with names separated
- * by a single blank space.
- * @param string $p_path The path of the directory where the
- * files/dir need to by extracted.
- * @param string $p_remove_path Part of the memorized path that can be
- * removed if present at the beginning of
- * the file/dir path.
- * @return true on success, false on error.
+ *
+ * @param array $p_filelist An array of filenames and directory names,
+ * or a single string with names separated
+ * by a single blank space.
+ * @param string $p_path The path of the directory where the
+ * files/dir need to by extracted.
+ * @param string $p_remove_path Part of the memorized path that can be
+ * removed if present at the beginning of
+ * the file/dir path.
+ * @param boolean $p_preserve Preserve user/group ownership of files
+ *
+ * @return true on success, false on error.
* @access public
- * @see extractModify()
+ * @see extractModify()
*/
- function extractList($p_filelist, $p_path='', $p_remove_path='')
+ function extractList($p_filelist, $p_path='', $p_remove_path='', $p_preserve=false)
{
$v_result = true;
$v_list_detail = array();
@@ -4029,7 +4178,7 @@ class Archive_Tar extends PEAR
if ($v_result = $this->_openRead()) {
$v_result = $this->_extractList($p_path, $v_list_detail, "partial",
- $v_list, $p_remove_path);
+ $v_list, $p_remove_path, $p_preserve);
$this->_close();
}
@@ -4042,8 +4191,10 @@ class Archive_Tar extends PEAR
* This method set specific attributes of the archive. It uses a variable
* list of parameters, in the format attribute code + attribute values :
* $arch->setAttribute(ARCHIVE_TAR_ATT_SEPARATOR, ',');
- * @param mixed $argv variable list of attributes and values
- * @return true on success, false on error.
+ *
+ * @param mixed $argv variable list of attributes and values
+ *
+ * @return true on success, false on error.
* @access public
*/
function setAttribute()
@@ -4096,7 +4247,9 @@ class Archive_Tar extends PEAR
* This method sets the regular expression for ignoring files and directories
* at import, for example:
* $arch->setIgnoreRegexp("#CVS|\.svn#");
- * @param string $regexp regular expression defining which files or directories to ignore
+ *
+ * @param string $regexp regular expression defining which files or directories to ignore
+ *
* @access public
*/
function setIgnoreRegexp($regexp)
@@ -4110,7 +4263,9 @@ class Archive_Tar extends PEAR
* This method sets the regular expression for ignoring all files and directories
* matching the filenames in the array list at import, for example:
* $arch->setIgnoreList(array('CVS', '.svn', 'bin/tool'));
- * @param array $list a list of file or directory names to ignore
+ *
+ * @param array $list a list of file or directory names to ignore
+ *
* @access public
*/
function setIgnoreList($list)
@@ -4124,23 +4279,21 @@ class Archive_Tar extends PEAR
// {{{ _error()
function _error($p_message)
{
- // ----- To be completed
- $this->raiseError($p_message);
+ $this->error_object = &$this->raiseError($p_message);
}
// }}}
// {{{ _warning()
function _warning($p_message)
{
- // ----- To be completed
- $this->raiseError($p_message);
+ $this->error_object = &$this->raiseError($p_message);
}
// }}}
// {{{ _isArchive()
- function _isArchive($p_filename=NULL)
+ function _isArchive($p_filename=null)
{
- if ($p_filename == NULL) {
+ if ($p_filename == null) {
$p_filename = $this->_tarname;
}
clearstatcache();
@@ -4151,15 +4304,17 @@ class Archive_Tar extends PEAR
// {{{ _openWrite()
function _openWrite()
{
- if ($this->_compress_type == 'gz')
+ if ($this->_compress_type == 'gz' && function_exists('gzopen'))
$this->_file = @gzopen($this->_tarname, "wb9");
- else if ($this->_compress_type == 'bz2')
+ else if ($this->_compress_type == 'bz2' && function_exists('bzopen'))
$this->_file = @bzopen($this->_tarname, "w");
else if ($this->_compress_type == 'none')
$this->_file = @fopen($this->_tarname, "wb");
- else
+ else {
$this->_error('Unknown or missing compression type ('
.$this->_compress_type.')');
+ return false;
+ }
if ($this->_file == 0) {
$this->_error('Unable to open in write mode \''
@@ -4204,15 +4359,17 @@ class Archive_Tar extends PEAR
// ----- File to open if the normal Tar file
$v_filename = $this->_tarname;
- if ($this->_compress_type == 'gz')
+ if ($this->_compress_type == 'gz' && function_exists('gzopen'))
$this->_file = @gzopen($v_filename, "rb");
- else if ($this->_compress_type == 'bz2')
+ else if ($this->_compress_type == 'bz2' && function_exists('bzopen'))
$this->_file = @bzopen($v_filename, "r");
else if ($this->_compress_type == 'none')
$this->_file = @fopen($v_filename, "rb");
- else
+ else {
$this->_error('Unknown or missing compression type ('
.$this->_compress_type.')');
+ return false;
+ }
if ($this->_file == 0) {
$this->_error('Unable to open in read mode \''.$v_filename.'\'');
@@ -4234,9 +4391,11 @@ class Archive_Tar extends PEAR
return false;
} else if ($this->_compress_type == 'none')
$this->_file = @fopen($this->_tarname, "r+b");
- else
+ else {
$this->_error('Unknown or missing compression type ('
.$this->_compress_type.')');
+ return false;
+ }
if ($this->_file == 0) {
$this->_error('Unable to open in read/write mode \''
@@ -4420,7 +4579,7 @@ class Archive_Tar extends PEAR
continue;
}
- if (!file_exists($v_filename)) {
+ if (!file_exists($v_filename) && !is_link($v_filename)) {
$this->_warning("File '$v_filename' does not exist");
continue;
}
@@ -4521,7 +4680,7 @@ class Archive_Tar extends PEAR
// }}}
// {{{ _addString()
- function _addString($p_filename, $p_string)
+ function _addString($p_filename, $p_string, $p_datetime = false)
{
if (!$this->_file) {
$this->_error('Invalid file descriptor');
@@ -4535,9 +4694,14 @@ class Archive_Tar extends PEAR
// ----- Calculate the stored filename
$p_filename = $this->_translateWinPath($p_filename, false);;
+
+ // ----- If datetime is not specified, set current time
+ if ($p_datetime === false) {
+ $p_datetime = time();
+ }
if (!$this->_writeHeaderBlock($p_filename, strlen($p_string),
- time(), 384, "", 0, 0))
+ $p_datetime, 384, "", 0, 0))
return false;
$i=0;
@@ -4820,10 +4984,20 @@ class Archive_Tar extends PEAR
for ($i=156; $i<512; $i++)
$v_checksum+=ord(substr($v_binary_data,$i,1));
- $v_data = unpack("a100filename/a8mode/a8uid/a8gid/a12size/a12mtime/"
- ."a8checksum/a1typeflag/a100link/a6magic/a2version/"
- ."a32uname/a32gname/a8devmajor/a8devminor",
- $v_binary_data);
+ if (version_compare(PHP_VERSION,"5.5.0-dev")<0) {
+ $fmt = "a100filename/a8mode/a8uid/a8gid/a12size/a12mtime/" .
+ "a8checksum/a1typeflag/a100link/a6magic/a2version/" .
+ "a32uname/a32gname/a8devmajor/a8devminor/a131prefix";
+ } else {
+ $fmt = "Z100filename/Z8mode/Z8uid/Z8gid/Z12size/Z12mtime/" .
+ "Z8checksum/Z1typeflag/Z100link/Z6magic/Z2version/" .
+ "Z32uname/Z32gname/Z8devmajor/Z8devminor/Z131prefix";
+ }
+ $v_data = unpack($fmt, $v_binary_data);
+
+ if (strlen($v_data["prefix"]) > 0) {
+ $v_data["filename"] = "$v_data[prefix]/$v_data[filename]";
+ }
// ----- Extract the checksum
$v_header['checksum'] = OctDec(trim($v_data['checksum']));
@@ -4875,6 +5049,7 @@ class Archive_Tar extends PEAR
* Detect and report a malicious file name
*
* @param string $file
+ *
* @return bool
* @access private
*/
@@ -4925,9 +5100,11 @@ class Archive_Tar extends PEAR
// {{{ _extractInString()
/**
* This method extract from the archive one file identified by $p_filename.
- * The return value is a string with the file content, or NULL on error.
- * @param string $p_filename The path of the file to extract in a string.
- * @return a string with the file content or NULL.
+ * The return value is a string with the file content, or null on error.
+ *
+ * @param string $p_filename The path of the file to extract in a string.
+ *
+ * @return a string with the file content or null.
* @access private
*/
function _extractInString($p_filename)
@@ -4937,7 +5114,7 @@ class Archive_Tar extends PEAR
While (strlen($v_binary_data = $this->_readBlock()) != 0)
{
if (!$this->_readHeader($v_binary_data, $v_header))
- return NULL;
+ return null;
if ($v_header['filename'] == '')
continue;
@@ -4945,14 +5122,14 @@ class Archive_Tar extends PEAR
// ----- Look for long filename
if ($v_header['typeflag'] == 'L') {
if (!$this->_readLongHeader($v_header))
- return NULL;
+ return null;
}
if ($v_header['filename'] == $p_filename) {
if ($v_header['typeflag'] == "5") {
$this->_error('Unable to extract in string a directory '
.'entry {'.$v_header['filename'].'}');
- return NULL;
+ return null;
} else {
$n = floor($v_header['size']/512);
for ($i=0; $i<$n; $i++) {
@@ -4970,13 +5147,13 @@ class Archive_Tar extends PEAR
}
}
- return NULL;
+ return null;
}
// }}}
// {{{ _extractList()
function _extractList($p_path, &$p_list_detail, $p_mode,
- $p_file_list, $p_remove_path)
+ $p_file_list, $p_remove_path, $p_preserve=false)
{
$v_result=true;
$v_nb = 0;
@@ -4997,16 +5174,16 @@ class Archive_Tar extends PEAR
switch ($p_mode) {
case "complete" :
- $v_extract_all = TRUE;
- $v_listing = FALSE;
+ $v_extract_all = true;
+ $v_listing = false;
break;
case "partial" :
- $v_extract_all = FALSE;
- $v_listing = FALSE;
+ $v_extract_all = false;
+ $v_listing = false;
break;
case "list" :
- $v_extract_all = FALSE;
- $v_listing = TRUE;
+ $v_extract_all = false;
+ $v_listing = true;
break;
default :
$this->_error('Invalid extract mode ('.$p_mode.')');
@@ -5044,29 +5221,33 @@ class Archive_Tar extends PEAR
if ((strlen($v_header['filename']) > strlen($p_file_list[$i]))
&& (substr($v_header['filename'], 0, strlen($p_file_list[$i]))
== $p_file_list[$i])) {
- $v_extract_file = TRUE;
+ $v_extract_file = true;
break;
}
}
// ----- It is a file, so compare the file names
elseif ($p_file_list[$i] == $v_header['filename']) {
- $v_extract_file = TRUE;
+ $v_extract_file = true;
break;
}
}
} else {
- $v_extract_file = TRUE;
+ $v_extract_file = true;
}
// ----- Look if this file need to be extracted
if (($v_extract_file) && (!$v_listing))
{
if (($p_remove_path != '')
- && (substr($v_header['filename'], 0, $p_remove_path_size)
- == $p_remove_path))
+ && (substr($v_header['filename'].'/', 0, $p_remove_path_size)
+ == $p_remove_path)) {
$v_header['filename'] = substr($v_header['filename'],
$p_remove_path_size);
+ if( $v_header['filename'] == '' ){
+ continue;
+ }
+ }
if (($p_path != './') && ($p_path != '/')) {
while (substr($p_path, -1) == '/')
$p_path = substr($p_path, 0, strlen($p_path)-1);
@@ -5143,6 +5324,11 @@ class Archive_Tar extends PEAR
}
@fclose($v_dest_file);
+
+ if ($p_preserve) {
+ @chown($v_header['filename'], $v_header['uid']);
+ @chgrp($v_header['filename'], $v_header['gid']);
+ }
// ----- Change the file mode, mtime
@touch($v_header['filename'], $v_header['mtime']);
@@ -5155,12 +5341,19 @@ class Archive_Tar extends PEAR
// ----- Check the file size
clearstatcache();
- if (filesize($v_header['filename']) != $v_header['size']) {
+ if (!is_file($v_header['filename'])) {
+ $this->_error('Extracted file '.$v_header['filename']
+ .'does not exist. Archive may be corrupted.');
+ return false;
+ }
+
+ $filesize = filesize($v_header['filename']);
+ if ($filesize != $v_header['size']) {
$this->_error('Extracted file '.$v_header['filename']
- .' does not have the correct file size \''
- .filesize($v_header['filename'])
- .'\' ('.$v_header['size']
- .' expected). Archive may be corrupted.');
+ .' does not have the correct file size \''
+ .$filesize
+ .'\' ('.$v_header['size']
+ .' expected). Archive may be corrupted.');
return false;
}
}
@@ -5231,12 +5424,20 @@ class Archive_Tar extends PEAR
}
if ($this->_compress_type == 'gz') {
+ $end_blocks = 0;
+
while (!@gzeof($v_temp_tar)) {
$v_buffer = @gzread($v_temp_tar, 512);
- if ($v_buffer == ARCHIVE_TAR_END_BLOCK) {
+ if ($v_buffer == ARCHIVE_TAR_END_BLOCK || strlen($v_buffer) == 0) {
+ $end_blocks++;
// do not copy end blocks, we will re-make them
// after appending
continue;
+ } elseif ($end_blocks > 0) {
+ for ($i = 0; $i < $end_blocks; $i++) {
+ $this->_writeBlock(ARCHIVE_TAR_END_BLOCK);
+ }
+ $end_blocks = 0;
}
$v_binary_data = pack("a512", $v_buffer);
$this->_writeBlock($v_binary_data);
@@ -5245,9 +5446,19 @@ class Archive_Tar extends PEAR
@gzclose($v_temp_tar);
}
elseif ($this->_compress_type == 'bz2') {
+ $end_blocks = 0;
+
while (strlen($v_buffer = @bzread($v_temp_tar, 512)) > 0) {
- if ($v_buffer == ARCHIVE_TAR_END_BLOCK) {
+ if ($v_buffer == ARCHIVE_TAR_END_BLOCK || strlen($v_buffer) == 0) {
+ $end_blocks++;
+ // do not copy end blocks, we will re-make them
+ // after appending
continue;
+ } elseif ($end_blocks > 0) {
+ for ($i = 0; $i < $end_blocks; $i++) {
+ $this->_writeBlock(ARCHIVE_TAR_END_BLOCK);
+ }
+ $end_blocks = 0;
}
$v_binary_data = pack("a512", $v_buffer);
$this->_writeBlock($v_binary_data);
@@ -5309,7 +5520,7 @@ class Archive_Tar extends PEAR
*
* @param string $p_dir directory to check
*
- * @return bool TRUE if the directory exists or was created
+ * @return bool true if the directory exists or was created
*/
function _dirCheck($p_dir)
{
@@ -5378,7 +5589,11 @@ class Archive_Tar extends PEAR
}
}
}
- $v_result = strtr($v_result, '\\', '/');
+
+ if (defined('OS_WINDOWS') && OS_WINDOWS) {
+ $v_result = strtr($v_result, '\\', '/');
+ }
+
return $v_result;
}
@@ -5404,7 +5619,7 @@ class Archive_Tar extends PEAR
}
?>
-
+
===================================
Last update : 2001-08-15
@@ -6230,7 +6445,7 @@ class Console_Getopt
return $argv;
}
-}package.xml
+}package.xml
<package packagerversion="1.9.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">
<name>Console_Getopt</name>
<channel>pear.php.net</channel>
@@ -6255,10 +6470,10 @@ short and long options.</description>
<email>cellog@php.net</email>
<active>yes</active>
</helper>
- <date>2010-12-11</date>
- <time>20:20:13</time>
+ <date>2011-03-07</date>
+ <time>22:58:21</time>
<version>
- <release>1.3.0</release>
+ <release>1.3.1</release>
<api>1.3.0</api>
</version>
<stability>
@@ -6267,7 +6482,7 @@ short and long options.</description>
</stability>
<license uri="http://www.php.net/license">PHP License</license>
<notes>
-* Implement Request #13140: [PATCH] to skip unknown parameters. [patch by rquadling, improved on by dufuz]
+* Change the minimum PEAR installer dep to be lower
</notes>
<contents>
<dir name="/">
@@ -6286,13 +6501,29 @@ short and long options.</description>
<min>4.3.0</min>
</php>
<pearinstaller>
- <min>1.9.1</min>
+ <min>1.8.0</min>
</pearinstaller>
</required>
</dependencies>
<phprelease />
<changelog>
<release>
+ <date>2010-12-11</date>
+ <time>20:20:13</time>
+ <version>
+ <release>1.3.0</release>
+ <api>1.3.0</api>
+ </version>
+ <stability>
+ <release>stable</release>
+ <api>stable</api>
+ </stability>
+ <license uri="http://www.php.net/license">PHP License</license>
+ <notes>
+* Implement Request #13140: [PATCH] to skip unknown parameters. [patch by rquadling, improved on by dufuz]
+ </notes>
+ </release>
+ <release>
<date>2007-06-12</date>
<version>
<release>1.2.3</release>
@@ -6416,7 +6647,7 @@ Initial release
</release>
</changelog>
</package>
-
+
/* vim: set expandtab tabstop=4 shiftwidth=4: */
/**
* PHP Version 5
@@ -6783,7 +7014,7 @@ class Console_Getopt
}
while (@ob_end_flush());
-/* $Id: install-pear.php 308763 2011-02-28 16:18:46Z dufuz $ */
+/* $Id$ */
error_reporting(1803);
@@ -6817,11 +7048,11 @@ if (!$a) {
}
$force = false;
-$install_files = array('Archive_Tar' => 'phar://install-pear-nozlib.phar/Archive_Tar-1.3.7.tar',
-'Console_Getopt' => 'phar://install-pear-nozlib.phar/Console_Getopt-1.3.0.tar',
+$install_files = array('Archive_Tar' => 'phar://install-pear-nozlib.phar/Archive_Tar-1.3.11.tar',
+'Console_Getopt' => 'phar://install-pear-nozlib.phar/Console_Getopt-1.3.1.tar',
+'PEAR' => 'phar://install-pear-nozlib.phar/PEAR-1.9.4.tar',
'Structures_Graph' => 'phar://install-pear-nozlib.phar/Structures_Graph-1.0.4.tar',
'XML_Util' => 'phar://install-pear-nozlib.phar/XML_Util-1.2.1.tar',
-'PEAR' => 'phar://install-pear-nozlib.phar/PEAR-1.9.4.tar',
);
array_shift($argv);
$debug = false;
@@ -6831,7 +7062,7 @@ for ($i = 0; $i < sizeof($argv); $i++) {
if (preg_match('/package-(.*)\.xml$/', $bn, $matches) ||
preg_match('/([A-Za-z0-9_:]+)-.*\.(tar|tgz)$/', $bn, $matches)) {
$install_files[$matches[1]] = $arg;
- } elseif ($arg == '-a') {
+ } elseif ($arg == '-a' || $arg == '--cache') {
$cache_dir = $argv[$i+1];
$i++;
} elseif ($arg == '--force') {
@@ -6842,27 +7073,39 @@ for ($i = 0; $i < sizeof($argv); $i++) {
} elseif ($arg == '-ds') {
$suffix = $argv[$i+1];
$i++;
- } elseif ($arg == '-d') {
+ } elseif ($arg == '-d' || $arg == '--dir') {
$with_dir = $argv[$i+1];
$i++;
- } elseif ($arg == '-b') {
+ } elseif ($arg == '-b' || $arg == '--bin') {
$bin_dir = $argv[$i+1];
$i++;
- } elseif ($arg == '-c') {
+ } elseif ($arg == '-c' || $arg == '--config') {
$cfg_dir = $argv[$i+1];
$i++;
- } elseif ($arg == '-w') {
+ } elseif ($arg == '-w' || $arg == '--www') {
$www_dir = $argv[$i+1];
$i++;
- } elseif ($arg == '-p') {
+ } elseif ($arg == '-p' || $arg == '--php') {
$php_bin = $argv[$i+1];
$i++;
- } elseif ($arg == '-o') {
+ } elseif ($arg == '-o' || $arg == '--download') {
$download_dir = $argv[$i+1];
$i++;
- } elseif ($arg == '-t') {
+ } elseif ($arg == '-m' || $arg == '--metadata') {
+ $metadata_dir = $argv[$i+1];
+ $i++;
+ } elseif ($arg == '-t' || $arg == '--temp') {
$temp_dir = $argv[$i+1];
$i++;
+ } elseif ($arg == '-A' || $arg == '--data') {
+ $data_dir = $argv[$i+1];
+ $i++;
+ } elseif ($arg == '-D' || $arg == '--doc') {
+ $doc_dir = $argv[$i+1];
+ $i++;
+ } elseif ($arg == '-T' || $arg == '--test') {
+ $test_dir = $argv[$i+1];
+ $i++;
} elseif ($arg == '--debug') {
$debug = 1;
} elseif ($arg == '--extremedebug') {
@@ -6919,13 +7162,38 @@ if (!empty($temp_dir)) {
$config->set('temp_dir', $temp_dir, 'default');
}
+// Documentation files
+if (!empty($doc_dir)) {
+ $config->set('doc_dir', $doc_dir, 'default');
+}
+
+// Data files
+if (!empty($data_dir)) {
+ $config->set('data_dir', $data_dir, 'default');
+}
+
+// Unit tests
+if (!empty($test_dir)) {
+ $config->set('test_dir', $test_dir, 'default');
+}
+
// User supplied a dir prefix
if (!empty($with_dir)) {
$ds = DIRECTORY_SEPARATOR;
$config->set('php_dir', $with_dir, 'default');
- $config->set('doc_dir', $with_dir . $ds . 'doc', 'default');
- $config->set('data_dir', $with_dir . $ds . 'data', 'default');
- $config->set('test_dir', $with_dir . $ds . 'test', 'default');
+ // Metadata
+ if (!empty($metadata_dir)) {
+ $config->set('metadata_dir', $metadata_dir, 'default');
+ }
+ if (empty($doc_dir)) {
+ $config->set('doc_dir', $with_dir . $ds . 'doc', 'default');
+ }
+ if (empty($data_dir)) {
+ $config->set('data_dir', $with_dir . $ds . 'data', 'default');
+ }
+ if (empty($test_dir)) {
+ $config->set('test_dir', $with_dir . $ds . 'test', 'default');
+ }
if (empty($www_dir)) {
$config->set('www_dir', $with_dir . $ds . 'htdocs', 'default');
}
@@ -6988,7 +7256,7 @@ $options['upgrade'] = true;
$install_root = getenv('INSTALL_ROOT');
if (!empty($install_root)) {
$options['packagingroot'] = $install_root;
- $reg = &new PEAR_Registry($options['packagingroot']);
+ $reg = &new PEAR_Registry($options['packagingroot'], false, false, $metadata_dir);
} else {
$reg = $config->getRegistry('default');
}
@@ -7094,7 +7362,7 @@ foreach ($install_files as $package => $instfile) {
* @author Gregory Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version CVS: $Id: Guess.php 278521 2009-04-09 22:24:12Z dufuz $
+ * @version CVS: $Id: Guess.php 313023 2011-07-06 19:17:11Z dufuz $
* @link http://pear.php.net/package/PEAR
* @since File available since PEAR 0.1
*/
@@ -7171,7 +7439,7 @@ foreach ($install_files as $package => $instfile) {
* @author Gregory Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version Release: 1.10.0beta1
+ * @version Release: 1.9.4
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 0.1
*/
@@ -7419,7 +7687,7 @@ class OS_Guess
* indent-tabs-mode: nil
* c-basic-offset: 4
* End:
- */package2.xml
+ */package2.xml
<package packagerversion="1.9.4" 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>PEAR</name>
<channel>pear.php.net</channel>
@@ -7503,7 +7771,7 @@ class OS_Guess
<active>no</active>
</helper>
<date>2011-07-06</date>
- <time>22:13:04</time>
+ <time>22:11:24</time>
<version>
<release>1.9.4</release>
<api>1.9.4</api>
@@ -8314,7 +8582,7 @@ http://pear.php.net/advisory-20110228.txt
</release>
</changelog>
</package>
-
+
/**
* The OS_Guess class
*
@@ -8651,7 +8919,7 @@ class OS_Guess
* indent-tabs-mode: nil
* c-basic-offset: 4
* End:
- */
+ */
/**
* PEAR_ChannelFile_Parser for parsing channel.xml
*
@@ -8718,7 +8986,7 @@ class PEAR_ChannelFile_Parser extends PEAR_XMLParser
$ret->setPackagefile($file, $archive);
return $ret;
}
-}
+}
<login>
<summary>Connects and authenticates to remote server [Deprecated in favor of channel-login]</summary>
<function>doLogin</function>
@@ -8747,7 +9015,7 @@ Logs out from the remote server. This command does not actually
connect to the remote server, it only deletes the stored username and
password from your user configuration.</doc>
</logout>
-</commands>
+</commands>
/**
* PEAR_Command_Auth (login, logout commands)
*
@@ -8827,7 +9095,7 @@ password from your user configuration.',
{
parent::PEAR_Command_Channels($ui, $config);
}
-}
+}
<build>
<summary>Build an Extension From C Source</summary>
<function>doBuild</function>
@@ -8836,7 +9104,7 @@ password from your user configuration.',
<doc>[package.xml]
Builds one or more extensions contained in a package.</doc>
</build>
-</commands>
+</commands>
/**
* PEAR_Command_Auth (build command)
*
@@ -8920,7 +9188,7 @@ Builds one or more extensions contained in a package.'
$this->ui->outputData(rtrim($data), 'build');
}
}
-}
+}
<list-channels>
<summary>List Available Channels</summary>
<function>doList</function>
@@ -9042,7 +9310,7 @@ the default channel is used. This command does not actually connect to the
remote server, it only deletes the stored username and password from your user
configuration.</doc>
</channel-logout>
-</commands>
+</commands>
// /* vim: set expandtab tabstop=4 shiftwidth=4: */
/**
* PEAR_Command_Channels (list-channels, update-channels, channel-delete, channel-add,
@@ -9924,7 +10192,7 @@ configuration.',
$this->config->store();
return true;
}
-}
+}
/**
* PEAR_Command_Common base class
*
@@ -10196,7 +10464,7 @@ class PEAR_Command_Common extends PEAR
return $this->$func($command, $options, $params);
}
-}
+}
<config-show>
<summary>Show All Settings</summary>
<function>doConfigShow</function>
@@ -10287,7 +10555,7 @@ PEAR installation (using the --remoteconfig option of install, upgrade,
and uninstall).
</doc>
</config-create>
-</commands>
+</commands>
/**
* PEAR_Command_Config (config-show, config-get, config-set, config-help, config-create commands)
*
@@ -10700,7 +10968,7 @@ and uninstall).
return false;
}
-}
+}
<install>
<summary>Install Package</summary>
<function>doInstall</function>
@@ -10975,7 +11243,7 @@ package if needed.
Run post-installation scripts in package &lt;package&gt;, if any exist.
</doc>
</run-scripts>
-</commands>
+</commands>
/**
* PEAR_Command_Install (install, upgrade, upgrade-all, uninstall, bundle, run-scripts commands)
*
@@ -12242,7 +12510,7 @@ Run post-installation scripts in package <package>, if any exist.
return $ret;
}
-}
+}
<download-all>
<summary>Downloads each available package from the default channel</summary>
<function>doDownloadAll</function>
@@ -12259,7 +12527,7 @@ Requests a list of available packages from the default channel ({config default_
and downloads them to current working directory. Note: only
packages within preferred_state ({config preferred_state}) will be downloaded</doc>
</download-all>
-</commands>
+</commands>
/**
* PEAR_Command_Mirror (download-all command)
*
@@ -12397,7 +12665,7 @@ packages within preferred_state ({config preferred_state}) will be downloaded'
return true;
}
-}
+}
<package>
<summary>Build Package</summary>
<function>doPackage</function>
@@ -12633,7 +12901,7 @@ This is not the most intelligent conversion, and should only be
used for automated conversion or learning the format.
</doc>
</convert>
-</commands>
+</commands>
/**
* PEAR_Command_Package (package, package-validate, cvsdiff, cvstag, package-dependencies,
* sign, makerpm, convert commands)
@@ -13756,7 +14024,7 @@ used for automated conversion or learning the format.
$this->ui->outputData('Wrote new version 2.0 package.xml to "' . $saved . '"');
return true;
}
-}
+}
<pickle>
<summary>Build PECL Package</summary>
<function>doPackage</function>
@@ -13791,7 +14059,7 @@ uses any of these features, you are best off using PEAR_PackageFileManager to
generate both package.xml.
</doc>
</pickle>
-</commands>
+</commands>
/**
* PEAR_Command_Pickle (pickle command)
*
@@ -14211,7 +14479,7 @@ generate both package.xml.
$gen = &$pf->getDefaultGenerator();
$gen->toPackageFile('.');
}
-}
+}
<list>
<summary>List Installed Packages In The Default Channel</summary>
<function>doList</function>
@@ -14268,7 +14536,7 @@ Displays information about a package. The package argument may be a
local package file, an URL to a package file, or the name of an
installed package.</doc>
</info>
-</commands>
+</commands>
/**
* PEAR_Command_Registry (list, list-files, shell-test, info commands)
*
@@ -15412,7 +15680,7 @@ installed package.'
$data['raw'] = $obj->getArray(); // no validation needed
$this->ui->outputData($data, 'package-info');
}
-}
+}
<remote-info>
<summary>Information About Remote Packages</summary>
<function>doRemoteInfo</function>
@@ -15520,7 +15788,7 @@ Clear the XML-RPC/REST cache. See also the cache_ttl configuration
parameter.
</doc>
</clear-cache>
-</commands>
+</commands>
/**
* PEAR_Command_Remote (remote-info, list-upgrades, remote-list, search, list-all, download,
* clear-cache commands)
@@ -16329,7 +16597,7 @@ parameter.
$this->ui->outputData(rtrim($output), $command);
return $num;
}
-}
+}
<run-tests>
<summary>Run Regression Tests</summary>
<function>doRunTests</function>
@@ -16382,7 +16650,7 @@ If none is found, all .phpt tests will be tried instead.</doc>
<doc>[testfile|dir ...]
Run regression tests with PHP&#039;s regression testing script (run-tests.php).</doc>
</run-tests>
-</commands>
+</commands>
/**
* PEAR_Command_Test (run-tests)
*
@@ -16718,7 +16986,7 @@ Run regression tests with PHP\'s regression testing script (run-tests.php).',
return true;
}
-}
+}
/**
* PEAR_Downloader_Package
*
@@ -18705,7 +18973,7 @@ class PEAR_Downloader_Package
return $info;
}
-}
+}
/**
* PEAR_Frontend_CLI
*
@@ -19455,7 +19723,7 @@ class PEAR_Frontend_CLI extends PEAR_Frontend
{
print $text;
}
-}
+}
/**
* Base class for all installation roles.
*
@@ -19628,7 +19896,7 @@ class PEAR_Installer_Role_Common
return $roleInfo['phpextension'];
}
}
-?>
+?>
<releasetypes>php</releasetypes>
<releasetypes>extsrc</releasetypes>
<releasetypes>extbin</releasetypes>
@@ -19642,7 +19910,7 @@ class PEAR_Installer_Role_Common
<executable />
<phpextension />
<config_vars />
-</role>
+</role>
/**
* PEAR_Installer_Role_Cfg
*
@@ -19747,7 +20015,7 @@ class PEAR_Installer_Role_Cfg extends PEAR_Installer_Role_Common
return $test;
}
-}
+}
<releasetypes>php</releasetypes>
<releasetypes>extsrc</releasetypes>
<releasetypes>extbin</releasetypes>
@@ -19761,7 +20029,7 @@ class PEAR_Installer_Role_Cfg extends PEAR_Installer_Role_Common
<executable />
<phpextension />
<config_vars />
-</role>
+</role>
/**
* PEAR_Installer_Role_Data
*
@@ -19788,7 +20056,7 @@ class PEAR_Installer_Role_Cfg extends PEAR_Installer_Role_Common
* @since Class available since Release 1.4.0a1
*/
class PEAR_Installer_Role_Data extends PEAR_Installer_Role_Common {}
-?>
+?>
<releasetypes>php</releasetypes>
<releasetypes>extsrc</releasetypes>
<releasetypes>extbin</releasetypes>
@@ -19802,7 +20070,7 @@ class PEAR_Installer_Role_Data extends PEAR_Installer_Role_Common {}
<executable />
<phpextension />
<config_vars />
-</role>
+</role>
/**
* PEAR_Installer_Role_Doc
*
@@ -19829,7 +20097,7 @@ class PEAR_Installer_Role_Data extends PEAR_Installer_Role_Common {}
* @since Class available since Release 1.4.0a1
*/
class PEAR_Installer_Role_Doc extends PEAR_Installer_Role_Common {}
-?>
+?>
<releasetypes>extbin</releasetypes>
<releasetypes>zendextbin</releasetypes>
<installable>1</installable>
@@ -19840,7 +20108,7 @@ class PEAR_Installer_Role_Doc extends PEAR_Installer_Role_Common {}
<executable />
<phpextension>1</phpextension>
<config_vars />
-</role>
+</role>
/**
* PEAR_Installer_Role_Ext
*
@@ -19867,7 +20135,7 @@ class PEAR_Installer_Role_Doc extends PEAR_Installer_Role_Common {}
* @since Class available since Release 1.4.0a1
*/
class PEAR_Installer_Role_Ext extends PEAR_Installer_Role_Common {}
-?>
+?>
<releasetypes>php</releasetypes>
<releasetypes>extsrc</releasetypes>
<releasetypes>extbin</releasetypes>
@@ -19881,7 +20149,7 @@ class PEAR_Installer_Role_Ext extends PEAR_Installer_Role_Common {}
<executable />
<phpextension />
<config_vars />
-</role>
+</role>
/**
* PEAR_Installer_Role_Php
*
@@ -19908,7 +20176,7 @@ class PEAR_Installer_Role_Ext extends PEAR_Installer_Role_Common {}
* @since Class available since Release 1.4.0a1
*/
class PEAR_Installer_Role_Php extends PEAR_Installer_Role_Common {}
-?>
+?>
<releasetypes>php</releasetypes>
<releasetypes>extsrc</releasetypes>
<releasetypes>extbin</releasetypes>
@@ -19922,7 +20190,7 @@ class PEAR_Installer_Role_Php extends PEAR_Installer_Role_Common {}
<executable>1</executable>
<phpextension />
<config_vars />
-</role>
+</role>
/**
* PEAR_Installer_Role_Script
*
@@ -19949,7 +20217,7 @@ class PEAR_Installer_Role_Php extends PEAR_Installer_Role_Common {}
* @since Class available since Release 1.4.0a1
*/
class PEAR_Installer_Role_Script extends PEAR_Installer_Role_Common {}
-?>
+?>
<releasetypes>extsrc</releasetypes>
<releasetypes>zendextsrc</releasetypes>
<installable>1</installable>
@@ -19960,7 +20228,7 @@ class PEAR_Installer_Role_Script extends PEAR_Installer_Role_Common {}
<executable />
<phpextension />
<config_vars />
-</role>
+</role>
/**
* PEAR_Installer_Role_Src
*
@@ -19993,7 +20261,7 @@ class PEAR_Installer_Role_Src extends PEAR_Installer_Role_Common
$installer->source_files++;
}
}
-?>
+?>
<releasetypes>php</releasetypes>
<releasetypes>extsrc</releasetypes>
<releasetypes>extbin</releasetypes>
@@ -20007,7 +20275,7 @@ class PEAR_Installer_Role_Src extends PEAR_Installer_Role_Common
<executable />
<phpextension />
<config_vars />
-</role>
+</role>
/**
* PEAR_Installer_Role_Test
*
@@ -20034,7 +20302,7 @@ class PEAR_Installer_Role_Src extends PEAR_Installer_Role_Common
* @since Class available since Release 1.4.0a1
*/
class PEAR_Installer_Role_Test extends PEAR_Installer_Role_Common {}
-?>
+?>
<releasetypes>php</releasetypes>
<releasetypes>extsrc</releasetypes>
<releasetypes>extbin</releasetypes>
@@ -20048,7 +20316,7 @@ class PEAR_Installer_Role_Test extends PEAR_Installer_Role_Common {}
<executable />
<phpextension />
<config_vars />
-</role>
+</role>
/**
* PEAR_Installer_Role_Www
*
@@ -20075,7 +20343,7 @@ class PEAR_Installer_Role_Test extends PEAR_Installer_Role_Common {}
* @since Class available since Release 1.7.0
*/
class PEAR_Installer_Role_Www extends PEAR_Installer_Role_Common {}
-?>
+?>
/**
* PEAR_Installer_Role
*
@@ -20350,7 +20618,7 @@ class PEAR_Installer_Role
PEAR_Installer_Role::getValidRoles('****', true);
return true;
}
-}
+}
/**
* package.xml generation class, package.xml version 1.0
*
@@ -21633,7 +21901,7 @@ class PEAR_PackageFile_Generator_v1
return $ret;
}
}
-?>
+?>
/**
* package.xml generation class, package.xml version 2.0
*
@@ -22525,7 +22793,7 @@ http://pear.php.net/dtd/package-2.0.xsd',
}
return $tag;
}
-}
+}
/**
* package.xml parsing class, package.xml version 1.0
*
@@ -22983,7 +23251,7 @@ class PEAR_PackageFile_Parser_v1
// }}}
}
-?>
+?>
/**
* package.xml parsing class, package.xml version 2.0
*
@@ -23095,7 +23363,7 @@ class PEAR_PackageFile_Parser_v2 extends PEAR_XMLParser
$ret->setPackagefile($file, $archive);
return $ret;
}
-}
+}
/**
* PEAR_PackageFile_v2, package.xml version 2.0, read/write version
*
@@ -24698,7 +24966,7 @@ class PEAR_PackageFile_v2_rw extends PEAR_PackageFile_v2
{
unset($this->_packageInfo['changelog']);
}
-}
+}
/**
* PEAR_PackageFile_v2, package.xml version 2.0, read/write version
*
@@ -26851,7 +27119,7 @@ class PEAR_PackageFile_v2_Validator
return $providesret;
}
-}
+}
/**
* PEAR_PackageFile_v1, package.xml version 1.0
*
@@ -28463,7 +28731,7 @@ class PEAR_PackageFile_v1
// }}}
}
?>
-
+
/**
* PEAR_PackageFile_v2, package.xml version 2.0
*
@@ -30512,7 +30780,7 @@ class PEAR_PackageFile_v2
}
}
?>
-
+
/**
* PEAR_REST_10
*
@@ -31382,7 +31650,7 @@ class PEAR_REST_10
return 1;
}
}
-}
+}
/**
* PEAR_REST_11 - implement faster list-all/remote-list command
*
@@ -31722,7 +31990,7 @@ class PEAR_REST_11
return array_slice($states, $i + 1);
}
}
-?>
+?>
/**
* PEAR_REST_13
*
@@ -32020,7 +32288,7 @@ class PEAR_REST_13 extends PEAR_REST_10
return $this->_returnDownloadURL($base, $package, $release, $info, $found, $skippedphp, $channel);
}
-}
+}
/**
* <tasks:postinstallscript> - read/write version
*
@@ -32188,7 +32456,7 @@ class PEAR_Task_Postinstallscript_rw extends PEAR_Task_Postinstallscript
);
}
}
-?>
+?>
/**
* <tasks:replace> - read/write version
*
@@ -32248,7 +32516,7 @@ class PEAR_Task_Replace_rw extends PEAR_Task_Replace
return $this->_params;
}
}
-?>
+?>
/**
* <tasks:unixeol> - read/write version
*
@@ -32303,7 +32571,7 @@ class PEAR_Task_Unixeol_rw extends PEAR_Task_Unixeol
return '';
}
}
-?>
+?>
/**
* <tasks:windowseol> - read/write version
*
@@ -32358,7 +32626,7 @@ class PEAR_Task_Windowseol_rw extends PEAR_Task_Windowseol
return '';
}
}
-?>
+?>
/**
* PEAR_Task_Common, base class for installer tasks
*
@@ -32559,7 +32827,7 @@ class PEAR_Task_Common
return PEAR::raiseError($msg, $code);
}
}
-?>
+?>
/**
* <tasks:postinstallscript>
*
@@ -32881,7 +33149,7 @@ class PEAR_Task_Postinstallscript extends PEAR_Task_Common
{
}
}
-?>
+?>
/**
* <tasks:replace>
*
@@ -33056,7 +33324,7 @@ class PEAR_Task_Replace extends PEAR_Task_Common
return $contents;
}
}
-?>
+?>
/**
* <tasks:unixeol>
*
@@ -33132,7 +33400,7 @@ class PEAR_Task_Unixeol extends PEAR_Task_Common
return preg_replace("/\r\n|\n\r|\r|\n/", "\n", $contents);
}
}
-?>
+?>
/**
* <tasks:windowseol>
*
@@ -33208,7 +33476,7 @@ class PEAR_Task_Windowseol extends PEAR_Task_Common
return preg_replace("/\r\n|\n\r|\r|\n/", "\r\n", $contents);
}
}
-?>
+?>
/**
* Channel Validator for the pecl.php.net channel
*
@@ -33270,7 +33538,7 @@ class PEAR_Validator_PECL extends PEAR_Validate
return $ret;
}
}
-?>
+?>
/**
* Class auto-loader
*
@@ -33488,7 +33756,7 @@ class PEAR_Autoloader extends PEAR
overload("PEAR_Autoloader");
?>
-
+
/**
* PEAR_Builder for building PHP extensions (PECL packages)
*
@@ -33976,7 +34244,7 @@ class PEAR_Builder extends PEAR_Common
}
return PEAR_Common::log($level, $msg);
}
-}
+}
/**
* PEAR_ChannelFile, the channel handling class
*
@@ -35534,7 +35802,7 @@ class PEAR_ChannelFile
return time();
}
-}
+}
/**
* PEAR_Command, command pattern class
*
@@ -35947,7 +36215,7 @@ class PEAR_Command
return false;
}
// }}}
-}
+}
/**
* PEAR_Common, the base class for the PEAR Installer
*
@@ -36783,7 +37051,7 @@ class PEAR_Common extends PEAR
}
require_once 'PEAR/Config.php';
-require_once 'PEAR/PackageFile.php';
+require_once 'PEAR/PackageFile.php';
/**
* PEAR_Config, customized configuration handling for the PEAR Installer
*
@@ -38880,7 +39148,7 @@ class PEAR_Config extends PEAR
}
}
}
-
+
/**
* PEAR_DependencyDB, advanced installed packages dependency database
*
@@ -39648,7 +39916,7 @@ class PEAR_DependencyDB
);
}
}
-}
+}
/**
* PEAR_Dependency2, advanced dependency validation
*
@@ -41005,7 +41273,7 @@ class PEAR_Dependency2
return array(sprintf($msg, $this->_registry->parsedPackageNameToString(
$this->_currentPackage, true)));
}
-}
+}
/**
* PEAR_Downloader, the PEAR Installer's download utility class
*
@@ -42770,7 +43038,7 @@ class PEAR_Downloader extends PEAR_Common
}
return $dest_file;
}
-}
+}
/**
* Error Stack Implementation
*
@@ -43755,7 +44023,7 @@ class PEAR_ErrorStack {
$stack = &PEAR_ErrorStack::singleton('PEAR_ErrorStack');
$stack->pushCallback(array('PEAR_ErrorStack', '_handleError'));
?>
-
+
/* vim: set expandtab tabstop=4 shiftwidth=4 foldmethod=marker: */
/**
* PEAR_Exception
@@ -44143,13 +44411,13 @@ class PEAR_Exception extends Exception
}
return $causeMsg . $this->getTraceAsString();
}
-}
+}
if ($skipmsg) {
$a = &new $ec($code, $mode, $options, $userinfo);
} else {
$a = &new $ec($message, $code, $mode, $options, $userinfo);
}
-?>
+?>
/**
* PEAR_Frontend, the singleton-based frontend for user input/output
*
@@ -44376,7 +44644,7 @@ class PEAR_Frontend extends PEAR
function userDialog($command, $prompts, $types = array(), $defaults = array())
{
}
-}
+}
/**
* PEAR_Installer
*
@@ -46198,7 +46466,7 @@ class PEAR_Installer extends PEAR_Downloader
}
// }}}
-}
+}
/**
* PEAR_PackageFile, package.xml parsing utility class
*
@@ -46689,7 +46957,7 @@ class PEAR_PackageFile
$info = PEAR::raiseError("Cannot open '$info' for parsing");
return $info;
}
-}
+}
/**
* PEAR_Packager for generating releases
*
@@ -46889,7 +47157,7 @@ class PEAR_Packager extends PEAR_Common
return $dest_package;
}
-}
+}
/**
* PEAR_Registry
*
@@ -49283,7 +49551,7 @@ class PEAR_Registry extends PEAR
}
return $ret;
}
-}
+}
/**
* PEAR_REST
*
@@ -49765,7 +50033,7 @@ class PEAR_REST
return $data;
}
-}
+}
/**
* PEAR_RunTest
*
@@ -50733,7 +51001,7 @@ $text
}
}
}
-
+
/**
* PEAR_Validate
*
@@ -51361,7 +51629,7 @@ class PEAR_Validate
{
return true;
}
-}
+}
/**
* PEAR_XMLParser
*
@@ -51613,7 +51881,7 @@ class PEAR_XMLParser
{
$this->_dataStack[$this->_depth] .= $cdata;
}
-}
+}
REM ----------------------------------------------------------------------
REM PHP version 5
@@ -51723,7 +51991,7 @@ GOTO END
:RUN
"%PHP_PEAR_PHP_BIN%" -C -d date.timezone=UTC -d output_buffering=1 -d safe_mode=0 -d open_basedir="" -d auto_prepend_file="" -d auto_append_file="" -d variables_order=EGPCS -d register_argc_argv="On" -d "include_path='%PHP_PEAR_INSTALL_DIR%'" -f "%PHP_PEAR_INSTALL_DIR%\pearcmd.php" -- %1 %2 %3 %4 %5 %6 %7 %8 %9
:END
-@ECHO ON
+@ECHO ON
REM ----------------------------------------------------------------------
REM PHP version 5
@@ -51837,7 +52105,7 @@ GOTO END
:RUN
"%PHP_PEAR_PHP_BIN%" -C -d date.timezone=UTC -d memory_limit="-1" -d safe_mode=0 -d register_argc_argv="On" -d auto_prepend_file="" -d auto_append_file="" -d variables_order=EGPCS -d open_basedir="" -d output_buffering=1 -d "include_path='%PHP_PEAR_INSTALL_DIR%'" -f "%PHP_PEAR_INSTALL_DIR%\pearcmd.php" -- %1 %2 %3 %4 %5 %6 %7 %8 %9
:END
-@ECHO ON
+@ECHO ON
REM ----------------------------------------------------------------------
REM PHP version 5
@@ -51951,7 +52219,7 @@ GOTO END
:RUN
"%PHP_PEAR_PHP_BIN%" -C -n -d date.timezone=UTC -d output_buffering=1 -d safe_mode=0 -d "include_path='%PHP_PEAR_INSTALL_DIR%'" -d register_argc_argv="On" -d variables_order=EGPCS -f "%PHP_PEAR_INSTALL_DIR%\peclcmd.php" -- %1 %2 %3 %4 %5 %6 %7 %8 %9
:END
-@ECHO ON
+@ECHO ON
# first find which PHP binary to use
if test "x$PHP_PEAR_PHP_BIN" != "x"; then
@@ -51979,7 +52247,7 @@ else
fi
exec $PHP -C -q $INCARG -d date.timezone=UTC -d output_buffering=1 -d variables_order=EGPCS -d open_basedir="" -d safe_mode=0 -d register_argc_argv="On" -d auto_prepend_file="" -d auto_append_file="" $INCDIR/pearcmd.php "$@"
-
+
# first find which PHP binary to use
if test "x$PHP_PEAR_PHP_BIN" != "x"; then
@@ -52007,7 +52275,7 @@ else
fi
exec $PHP -d date.timezone=UTC -d memory_limit="-1" -C -q $INCARG -d output_buffering=1 -d open_basedir="" -d safe_mode=0 -d register_argc_argv="On" -d auto_prepend_file="" -d variables_order=EGPCS -d auto_append_file="" $INCDIR/pearcmd.php "$@"
-
+
# first find which PHP binary to use
if test "x$PHP_PEAR_PHP_BIN" != "x"; then
@@ -52035,7 +52303,7 @@ else
fi
exec $PHP -C -n -q $INCARG -d date.timezone=UTC -d output_buffering=1 -d variables_order=EGPCS -d safe_mode=0 -d register_argc_argv="On" $INCDIR/peclcmd.php "$@"
-
+
/**
* PEAR, the PHP Extension and Application Repository
*
@@ -52482,7 +52750,7 @@ function error_handler($errno, $errmsg, $file, $line, $vars) {
* mode: php
* End:
*/
-// vim600:syn=php
+// vim600:syn=php
/**
* PEAR, the PHP Extension and Application Repository
*
@@ -52523,7 +52791,7 @@ require_once 'pearcmd.php';
// vim600:syn=php
?>
-
+
Stig Bakken <ssb@php.net>,
Gregory Beaver <cellog@php.net>,
Helgi Þormar Þorbjörnsson <helgi@php.net>,
@@ -52550,7 +52818,7 @@ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
+
=========================
Installing the PEAR Installer.
@@ -52603,7 +52871,7 @@ related issues.
Happy PHPing, we hope PEAR will be a great tool for your development work!
-$Id: INSTALL 313023 2011-07-06 19:17:11Z dufuz $
+$Id: INSTALL 313023 2011-07-06 19:17:11Z dufuz $
$Id: package.dtd,v 1.38 2005-11-12 02:23:07 cellog Exp $
This is the PEAR package description, version 1.0.
@@ -52706,7 +52974,7 @@ $Id: INSTALL 313023 2011-07-06 19:17:11Z dufuz $
to CDATA #REQUIRED>
-
+
/**
* This is only meant for PHP 5 to get rid of certain strict warning
* that doesn't get hidden since it's in the shutdown function
@@ -52738,7 +53006,7 @@ class PEAR5
return $properties[$class][$var];
}
-}
+}
/**
* PEAR, the PHP Extension and Application Repository
*
@@ -53801,7 +54069,7 @@ class PEAR_Error
* c-basic-offset: 4
* End:
*/
-
+
=========================
What is the PEAR Installer? What is PEAR?
@@ -53832,7 +54100,7 @@ prior to use.
Happy PHPing, we hope PEAR will be a great tool for your development work!
-$Id: README 313023 2011-07-06 19:17:11Z dufuz $
+$Id: README 313023 2011-07-06 19:17:11Z dufuz $
/**
* File/Directory manipulation
*
@@ -54460,7 +54728,7 @@ class System
}
return $files;
}
-}
+}
Name: @rpm_package@
Version: @version@
Release: 1
@@ -54532,7 +54800,7 @@ cp -p package@package2xml@.xml %{buildroot}@rpm_xml_dir@/@package@.xml
%defattr(-,root,root)
%doc @doc_files@
/
-
+
<!DOCTYPE package SYSTEM "http://pear.php.net/dtd/package-1.0">
<package version="1.0" packagerversion="1.9.4">
<name>PEAR</name>
@@ -55242,7 +55510,7 @@ http://pear.php.net/advisory-20110228.txt
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2010 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version CVS: $Id: PEAR.php 299159 2010-05-08 22:32:52Z dufuz $
+ * @version CVS: $Id: PEAR.php 313023 2011-07-06 19:17:11Z dufuz $
* @link http://pear.php.net/package/PEAR
* @since File available since Release 0.1
*/
@@ -55306,7 +55574,7 @@ $GLOBALS['_PEAR_error_handler_stack'] = array();
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2006 The PHP Group
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version Release: 1.10.0beta1
+ * @version Release: 1.9.4
* @link http://pear.php.net/package/PEAR
* @see PEAR_Error
* @since Class available since PHP 4.0.2
@@ -56016,7 +56284,7 @@ function _PEAR_call_destructors()
* @author Gregory Beaver <cellog@php.net>
* @copyright 1997-2006 The PHP Group
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version Release: 1.10.0beta1
+ * @version Release: 1.9.4
* @link http://pear.php.net/manual/en/core.pear.pear-error.php
* @see PEAR::raiseError(), PEAR::throwError()
* @since Class available since PHP 4.0.2
@@ -56291,6 +56559,712 @@ class PEAR_Error
*/
<?php
/**
+ * Class auto-loader
+ *
+ * PHP versions 4
+
+ *
+ * @category pear
+ * @package PEAR
+ * @author Stig Bakken <ssb@php.net>
+ * @copyright 1997-2009 The Authors
+ * @license http://opensource.org/licenses/bsd-license.php New BSD License
+ * @version CVS: $Id: Autoloader.php 313023 2011-07-06 19:17:11Z dufuz $
+ * @link http://pear.php.net/manual/en/core.ppm.php#core.ppm.pear-autoloader
+ * @since File available since Release 0.1
+ * @deprecated File deprecated in Release 1.4.0a1
+ */
+
+// /* vim: set expandtab tabstop=4 shiftwidth=4: */
+
+if (!extension_loaded("overload")) {
+ // die hard without ext/overload
+ die("Rebuild PHP with the `overload' extension to use PEAR_Autoloader");
+}
+
+/**
+ * Include for PEAR_Error and PEAR classes
+ */
+require_once 'phar://install-pear-nozlib.phar/' . "PEAR.php";
+
+/**
+ * This class is for objects where you want to separate the code for
+ * some methods into separate classes. This is useful if you have a
+ * class with not-frequently-used methods that contain lots of code
+ * that you would like to avoid always parsing.
+ *
+ * The PEAR_Autoloader class provides autoloading and aggregation.
+ * The autoloading lets you set up in which classes the separated
+ * methods are found. Aggregation is the technique used to import new
+ * methods, an instance of each class providing separated methods is
+ * stored and called every time the aggregated method is called.
+ *
+ * @category pear
+ * @package PEAR
+ * @author Stig Bakken <ssb@php.net>
+ * @copyright 1997-2009 The Authors
+ * @license http://opensource.org/licenses/bsd-license.php New BSD License
+ * @version Release: 1.9.4
+ * @link http://pear.php.net/manual/en/core.ppm.php#core.ppm.pear-autoloader
+ * @since File available since Release 0.1
+ * @deprecated File deprecated in Release 1.4.0a1
+ */
+class PEAR_Autoloader extends PEAR
+{
+ // {{{ properties
+
+ /**
+ * Map of methods and classes where they are defined
+ *
+ * @var array
+ *
+ * @access private
+ */
+ var $_autoload_map = array();
+
+ /**
+ * Map of methods and aggregate objects
+ *
+ * @var array
+ *
+ * @access private
+ */
+ var $_method_map = array();
+
+ // }}}
+ // {{{ addAutoload()
+
+ /**
+ * Add one or more autoload entries.
+ *
+ * @param string $method which method to autoload
+ *
+ * @param string $classname (optional) which class to find the method in.
+ * If the $method parameter is an array, this
+ * parameter may be omitted (and will be ignored
+ * if not), and the $method parameter will be
+ * treated as an associative array with method
+ * names as keys and class names as values.
+ *
+ * @return void
+ *
+ * @access public
+ */
+ function addAutoload($method, $classname = null)
+ {
+ if (is_array($method)) {
+ array_walk($method, create_function('$a,&$b', '$b = strtolower($b);'));
+ $this->_autoload_map = array_merge($this->_autoload_map, $method);
+ } else {
+ $this->_autoload_map[strtolower($method)] = $classname;
+ }
+ }
+
+ // }}}
+ // {{{ removeAutoload()
+
+ /**
+ * Remove an autoload entry.
+ *
+ * @param string $method which method to remove the autoload entry for
+ *
+ * @return bool TRUE if an entry was removed, FALSE if not
+ *
+ * @access public
+ */
+ function removeAutoload($method)
+ {
+ $method = strtolower($method);
+ $ok = isset($this->_autoload_map[$method]);
+ unset($this->_autoload_map[$method]);
+ return $ok;
+ }
+
+ // }}}
+ // {{{ addAggregateObject()
+
+ /**
+ * Add an aggregate object to this object. If the specified class
+ * is not defined, loading it will be attempted following PEAR's
+ * file naming scheme. All the methods in the class will be
+ * aggregated, except private ones (name starting with an
+ * underscore) and constructors.
+ *
+ * @param string $classname what class to instantiate for the object.
+ *
+ * @return void
+ *
+ * @access public
+ */
+ function addAggregateObject($classname)
+ {
+ $classname = strtolower($classname);
+ if (!class_exists($classname)) {
+ $include_file = preg_replace('/[^a-z0-9]/i', '_', $classname);
+ include_once 'phar://install-pear-nozlib.phar/' . $include_file;
+ }
+ $obj =& new $classname;
+ $methods = get_class_methods($classname);
+ foreach ($methods as $method) {
+ // don't import priviate methods and constructors
+ if ($method{0} != '_' && $method != $classname) {
+ $this->_method_map[$method] = $obj;
+ }
+ }
+ }
+
+ // }}}
+ // {{{ removeAggregateObject()
+
+ /**
+ * Remove an aggregate object.
+ *
+ * @param string $classname the class of the object to remove
+ *
+ * @return bool TRUE if an object was removed, FALSE if not
+ *
+ * @access public
+ */
+ function removeAggregateObject($classname)
+ {
+ $ok = false;
+ $classname = strtolower($classname);
+ reset($this->_method_map);
+ while (list($method, $obj) = each($this->_method_map)) {
+ if (is_a($obj, $classname)) {
+ unset($this->_method_map[$method]);
+ $ok = true;
+ }
+ }
+ return $ok;
+ }
+
+ // }}}
+ // {{{ __call()
+
+ /**
+ * Overloaded object call handler, called each time an
+ * undefined/aggregated method is invoked. This method repeats
+ * the call in the right aggregate object and passes on the return
+ * value.
+ *
+ * @param string $method which method that was called
+ *
+ * @param string $args An array of the parameters passed in the
+ * original call
+ *
+ * @return mixed The return value from the aggregated method, or a PEAR
+ * error if the called method was unknown.
+ */
+ function __call($method, $args, &$retval)
+ {
+ $method = strtolower($method);
+ if (empty($this->_method_map[$method]) && isset($this->_autoload_map[$method])) {
+ $this->addAggregateObject($this->_autoload_map[$method]);
+ }
+ if (isset($this->_method_map[$method])) {
+ $retval = call_user_func_array(array($this->_method_map[$method], $method), $args);
+ return true;
+ }
+ return false;
+ }
+
+ // }}}
+}
+
+overload("PEAR_Autoloader");
+
+?>
+<?php
+/**
+ * PEAR_Builder for building PHP extensions (PECL packages)
+ *
+ * PHP versions 4 and 5
+ *
+ * @category pear
+ * @package PEAR
+ * @author Stig Bakken <ssb@php.net>
+ * @author Greg Beaver <cellog@php.net>
+ * @copyright 1997-2009 The Authors
+ * @license http://opensource.org/licenses/bsd-license.php New BSD License
+ * @version CVS: $Id: Builder.php 313024 2011-07-06 19:51:24Z dufuz $
+ * @link http://pear.php.net/package/PEAR
+ * @since File available since Release 0.1
+ *
+ * TODO: log output parameters in PECL command line
+ * TODO: msdev path in configuration
+ */
+
+/**
+ * Needed for extending PEAR_Builder
+ */
+require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Common.php';
+require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/PackageFile.php';
+
+/**
+ * Class to handle building (compiling) extensions.
+ *
+ * @category pear
+ * @package PEAR
+ * @author Stig Bakken <ssb@php.net>
+ * @author Greg Beaver <cellog@php.net>
+ * @copyright 1997-2009 The Authors
+ * @license http://opensource.org/licenses/bsd-license.php New BSD License
+ * @version Release: 1.9.4
+ * @link http://pear.php.net/package/PEAR
+ * @since Class available since PHP 4.0.2
+ * @see http://pear.php.net/manual/en/core.ppm.pear-builder.php
+ */
+class PEAR_Builder extends PEAR_Common
+{
+ var $php_api_version = 0;
+ var $zend_module_api_no = 0;
+ var $zend_extension_api_no = 0;
+
+ var $extensions_built = array();
+
+ /**
+ * @var string Used for reporting when it is not possible to pass function
+ * via extra parameter, e.g. log, msdevCallback
+ */
+ var $current_callback = null;
+
+ // used for msdev builds
+ var $_lastline = null;
+ var $_firstline = null;
+
+ /**
+ * PEAR_Builder constructor.
+ *
+ * @param object $ui user interface object (instance of PEAR_Frontend_*)
+ *
+ * @access public
+ */
+ function PEAR_Builder(&$ui)
+ {
+ parent::PEAR_Common();
+ $this->setFrontendObject($ui);
+ }
+
+ /**
+ * Build an extension from source on windows.
+ * requires msdev
+ */
+ function _build_win32($descfile, $callback = null)
+ {
+ if (is_object($descfile)) {
+ $pkg = $descfile;
+ $descfile = $pkg->getPackageFile();
+ } else {
+ $pf = &new PEAR_PackageFile($this->config, $this->debug);
+ $pkg = &$pf->fromPackageFile($descfile, PEAR_VALIDATE_NORMAL);
+ if (PEAR::isError($pkg)) {
+ return $pkg;
+ }
+ }
+ $dir = dirname($descfile);
+ $old_cwd = getcwd();
+
+ if (!file_exists($dir) || !is_dir($dir) || !chdir($dir)) {
+ return $this->raiseError("could not chdir to $dir");
+ }
+
+ // packages that were in a .tar have the packagefile in this directory
+ $vdir = $pkg->getPackage() . '-' . $pkg->getVersion();
+ if (file_exists($dir) && is_dir($vdir)) {
+ if (!chdir($vdir)) {
+ return $this->raiseError("could not chdir to " . realpath($vdir));
+ }
+
+ $dir = getcwd();
+ }
+
+ $this->log(2, "building in $dir");
+
+ $dsp = $pkg->getPackage().'.dsp';
+ if (!file_exists("$dir/$dsp")) {
+ return $this->raiseError("The DSP $dsp does not exist.");
+ }
+ // XXX TODO: make release build type configurable
+ $command = 'msdev '.$dsp.' /MAKE "'.$pkg->getPackage(). ' - Release"';
+
+ $err = $this->_runCommand($command, array(&$this, 'msdevCallback'));
+ if (PEAR::isError($err)) {
+ return $err;
+ }
+
+ // figure out the build platform and type
+ $platform = 'Win32';
+ $buildtype = 'Release';
+ if (preg_match('/.*?'.$pkg->getPackage().'\s-\s(\w+)\s(.*?)-+/i',$this->_firstline,$matches)) {
+ $platform = $matches[1];
+ $buildtype = $matches[2];
+ }
+
+ if (preg_match('/(.*)?\s-\s(\d+).*?(\d+)/', $this->_lastline, $matches)) {
+ if ($matches[2]) {
+ // there were errors in the build
+ return $this->raiseError("There were errors during compilation.");
+ }
+ $out = $matches[1];
+ } else {
+ return $this->raiseError("Did not understand the completion status returned from msdev.exe.");
+ }
+
+ // msdev doesn't tell us the output directory :/
+ // open the dsp, find /out and use that directory
+ $dsptext = join(file($dsp),'');
+
+ // this regex depends on the build platform and type having been
+ // correctly identified above.
+ $regex ='/.*?!IF\s+"\$\(CFG\)"\s+==\s+("'.
+ $pkg->getPackage().'\s-\s'.
+ $platform.'\s'.
+ $buildtype.'").*?'.
+ '\/out:"(.*?)"/is';
+
+ if ($dsptext && preg_match($regex, $dsptext, $matches)) {
+ // what we get back is a relative path to the output file itself.
+ $outfile = realpath($matches[2]);
+ } else {
+ return $this->raiseError("Could not retrieve output information from $dsp.");
+ }
+ // realpath returns false if the file doesn't exist
+ if ($outfile && copy($outfile, "$dir/$out")) {
+ $outfile = "$dir/$out";
+ }
+
+ $built_files[] = array(
+ 'file' => "$outfile",
+ 'php_api' => $this->php_api_version,
+ 'zend_mod_api' => $this->zend_module_api_no,
+ 'zend_ext_api' => $this->zend_extension_api_no,
+ );
+
+ return $built_files;
+ }
+ // }}}
+
+ // {{{ msdevCallback()
+ function msdevCallback($what, $data)
+ {
+ if (!$this->_firstline)
+ $this->_firstline = $data;
+ $this->_lastline = $data;
+ call_user_func($this->current_callback, $what, $data);
+ }
+
+ /**
+ * @param string
+ * @param string
+ * @param array
+ * @access private
+ */
+ function _harvestInstDir($dest_prefix, $dirname, &$built_files)
+ {
+ $d = opendir($dirname);
+ if (!$d)
+ return false;
+
+ $ret = true;
+ while (($ent = readdir($d)) !== false) {
+ if ($ent{0} == '.')
+ continue;
+
+ $full = $dirname . DIRECTORY_SEPARATOR . $ent;
+ if (is_dir($full)) {
+ if (!$this->_harvestInstDir(
+ $dest_prefix . DIRECTORY_SEPARATOR . $ent,
+ $full, $built_files)) {
+ $ret = false;
+ break;
+ }
+ } else {
+ $dest = $dest_prefix . DIRECTORY_SEPARATOR . $ent;
+ $built_files[] = array(
+ 'file' => $full,
+ 'dest' => $dest,
+ 'php_api' => $this->php_api_version,
+ 'zend_mod_api' => $this->zend_module_api_no,
+ 'zend_ext_api' => $this->zend_extension_api_no,
+ );
+ }
+ }
+ closedir($d);
+ return $ret;
+ }
+
+ /**
+ * Build an extension from source. Runs "phpize" in the source
+ * directory, but compiles in a temporary directory
+ * (TMPDIR/pear-build-USER/PACKAGE-VERSION).
+ *
+ * @param string|PEAR_PackageFile_v* $descfile path to XML package description file, or
+ * a PEAR_PackageFile object
+ *
+ * @param mixed $callback callback function used to report output,
+ * see PEAR_Builder::_runCommand for details
+ *
+ * @return array an array of associative arrays with built files,
+ * format:
+ * array( array( 'file' => '/path/to/ext.so',
+ * 'php_api' => YYYYMMDD,
+ * 'zend_mod_api' => YYYYMMDD,
+ * 'zend_ext_api' => YYYYMMDD ),
+ * ... )
+ *
+ * @access public
+ *
+ * @see PEAR_Builder::_runCommand
+ */
+ function build($descfile, $callback = null)
+ {
+ if (preg_match('/(\\/|\\\\|^)([^\\/\\\\]+)?php(.+)?$/',
+ $this->config->get('php_bin'), $matches)) {
+ if (isset($matches[2]) && strlen($matches[2]) &&
+ trim($matches[2]) != trim($this->config->get('php_prefix'))) {
+ $this->log(0, 'WARNING: php_bin ' . $this->config->get('php_bin') .
+ ' appears to have a prefix ' . $matches[2] . ', but' .
+ ' config variable php_prefix does not match');
+ }
+
+ if (isset($matches[3]) && strlen($matches[3]) &&
+ trim($matches[3]) != trim($this->config->get('php_suffix'))) {
+ $this->log(0, 'WARNING: php_bin ' . $this->config->get('php_bin') .
+ ' appears to have a suffix ' . $matches[3] . ', but' .
+ ' config variable php_suffix does not match');
+ }
+ }
+
+ $this->current_callback = $callback;
+ if (PEAR_OS == "Windows") {
+ return $this->_build_win32($descfile, $callback);
+ }
+
+ if (PEAR_OS != 'Unix') {
+ return $this->raiseError("building extensions not supported on this platform");
+ }
+
+ if (is_object($descfile)) {
+ $pkg = $descfile;
+ $descfile = $pkg->getPackageFile();
+ if (is_a($pkg, 'PEAR_PackageFile_v1')) {
+ $dir = dirname($descfile);
+ } else {
+ $dir = $pkg->_config->get('temp_dir') . '/' . $pkg->getName();
+ // automatically delete at session end
+ $this->addTempFile($dir);
+ }
+ } else {
+ $pf = &new PEAR_PackageFile($this->config);
+ $pkg = &$pf->fromPackageFile($descfile, PEAR_VALIDATE_NORMAL);
+ if (PEAR::isError($pkg)) {
+ return $pkg;
+ }
+ $dir = dirname($descfile);
+ }
+
+ // Find config. outside of normal path - e.g. config.m4
+ foreach (array_keys($pkg->getInstallationFileList()) as $item) {
+ if (stristr(basename($item), 'config.m4') && dirname($item) != '.') {
+ $dir .= DIRECTORY_SEPARATOR . dirname($item);
+ break;
+ }
+ }
+
+ $old_cwd = getcwd();
+ if (!file_exists($dir) || !is_dir($dir) || !chdir($dir)) {
+ return $this->raiseError("could not chdir to $dir");
+ }
+
+ $vdir = $pkg->getPackage() . '-' . $pkg->getVersion();
+ if (is_dir($vdir)) {
+ chdir($vdir);
+ }
+
+ $dir = getcwd();
+ $this->log(2, "building in $dir");
+ putenv('PATH=' . $this->config->get('bin_dir') . ':' . getenv('PATH'));
+ $err = $this->_runCommand($this->config->get('php_prefix')
+ . "phpize" .
+ $this->config->get('php_suffix'),
+ array(&$this, 'phpizeCallback'));
+ if (PEAR::isError($err)) {
+ return $err;
+ }
+
+ if (!$err) {
+ return $this->raiseError("`phpize' failed");
+ }
+
+ // {{{ start of interactive part
+ $configure_command = "$dir/configure";
+ $configure_options = $pkg->getConfigureOptions();
+ if ($configure_options) {
+ foreach ($configure_options as $o) {
+ $default = array_key_exists('default', $o) ? $o['default'] : null;
+ list($r) = $this->ui->userDialog('build',
+ array($o['prompt']),
+ array('text'),
+ array($default));
+ if (substr($o['name'], 0, 5) == 'with-' &&
+ ($r == 'yes' || $r == 'autodetect')) {
+ $configure_command .= " --$o[name]";
+ } else {
+ $configure_command .= " --$o[name]=".trim($r);
+ }
+ }
+ }
+ // }}} end of interactive part
+
+ // FIXME make configurable
+ if (!$user=getenv('USER')) {
+ $user='defaultuser';
+ }
+
+ $tmpdir = $this->config->get('temp_dir');
+ $build_basedir = System::mktemp(' -t "' . $tmpdir . '" -d "pear-build-' . $user . '"');
+ $build_dir = "$build_basedir/$vdir";
+ $inst_dir = "$build_basedir/install-$vdir";
+ $this->log(1, "building in $build_dir");
+ if (is_dir($build_dir)) {
+ System::rm(array('-rf', $build_dir));
+ }
+
+ if (!System::mkDir(array('-p', $build_dir))) {
+ return $this->raiseError("could not create build dir: $build_dir");
+ }
+
+ $this->addTempFile($build_dir);
+ if (!System::mkDir(array('-p', $inst_dir))) {
+ return $this->raiseError("could not create temporary install dir: $inst_dir");
+ }
+ $this->addTempFile($inst_dir);
+
+ $make_command = getenv('MAKE') ? getenv('MAKE') : 'make';
+
+ $to_run = array(
+ $configure_command,
+ $make_command,
+ "$make_command INSTALL_ROOT=\"$inst_dir\" install",
+ "find \"$inst_dir\" | xargs ls -dils"
+ );
+ if (!file_exists($build_dir) || !is_dir($build_dir) || !chdir($build_dir)) {
+ return $this->raiseError("could not chdir to $build_dir");
+ }
+ putenv('PHP_PEAR_VERSION=1.9.4');
+ foreach ($to_run as $cmd) {
+ $err = $this->_runCommand($cmd, $callback);
+ if (PEAR::isError($err)) {
+ chdir($old_cwd);
+ return $err;
+ }
+ if (!$err) {
+ chdir($old_cwd);
+ return $this->raiseError("`$cmd' failed");
+ }
+ }
+ if (!($dp = opendir("modules"))) {
+ chdir($old_cwd);
+ return $this->raiseError("no `modules' directory found");
+ }
+ $built_files = array();
+ $prefix = exec($this->config->get('php_prefix')
+ . "php-config" .
+ $this->config->get('php_suffix') . " --prefix");
+ $this->_harvestInstDir($prefix, $inst_dir . DIRECTORY_SEPARATOR . $prefix, $built_files);
+ chdir($old_cwd);
+ return $built_files;
+ }
+
+ /**
+ * Message callback function used when running the "phpize"
+ * program. Extracts the API numbers used. Ignores other message
+ * types than "cmdoutput".
+ *
+ * @param string $what the type of message
+ * @param mixed $data the message
+ *
+ * @return void
+ *
+ * @access public
+ */
+ function phpizeCallback($what, $data)
+ {
+ if ($what != 'cmdoutput') {
+ return;
+ }
+ $this->log(1, rtrim($data));
+ if (preg_match('/You should update your .aclocal.m4/', $data)) {
+ return;
+ }
+ $matches = array();
+ if (preg_match('/^\s+(\S[^:]+):\s+(\d{8})/', $data, $matches)) {
+ $member = preg_replace('/[^a-z]/', '_', strtolower($matches[1]));
+ $apino = (int)$matches[2];
+ if (isset($this->$member)) {
+ $this->$member = $apino;
+ //$msg = sprintf("%-22s : %d", $matches[1], $apino);
+ //$this->log(1, $msg);
+ }
+ }
+ }
+
+ /**
+ * Run an external command, using a message callback to report
+ * output. The command will be run through popen and output is
+ * reported for every line with a "cmdoutput" message with the
+ * line string, including newlines, as payload.
+ *
+ * @param string $command the command to run
+ *
+ * @param mixed $callback (optional) function to use as message
+ * callback
+ *
+ * @return bool whether the command was successful (exit code 0
+ * means success, any other means failure)
+ *
+ * @access private
+ */
+ function _runCommand($command, $callback = null)
+ {
+ $this->log(1, "running: $command");
+ $pp = popen("$command 2>&1", "r");
+ if (!$pp) {
+ return $this->raiseError("failed to run `$command'");
+ }
+ if ($callback && $callback[0]->debug == 1) {
+ $olddbg = $callback[0]->debug;
+ $callback[0]->debug = 2;
+ }
+
+ while ($line = fgets($pp, 1024)) {
+ if ($callback) {
+ call_user_func($callback, 'cmdoutput', $line);
+ } else {
+ $this->log(2, rtrim($line));
+ }
+ }
+ if ($callback && isset($olddbg)) {
+ $callback[0]->debug = $olddbg;
+ }
+
+ $exitcode = is_resource($pp) ? pclose($pp) : -1;
+ return ($exitcode == 0);
+ }
+
+ function log($level, $msg)
+ {
+ if ($this->current_callback) {
+ if ($this->debug >= $level) {
+ call_user_func($this->current_callback, 'output', $msg);
+ }
+ return;
+ }
+ return PEAR_Common::log($level, $msg);
+ }
+}<?php
+/**
* PEAR_ChannelFile, the channel handling class
*
* PHP versions 4 and 5
@@ -56300,7 +57274,7 @@ class PEAR_Error
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version CVS: $Id: ChannelFile.php 286951 2009-08-09 14:41:22Z dufuz $
+ * @version CVS: $Id: ChannelFile.php 313023 2011-07-06 19:17:11Z dufuz $
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.4.0a1
*/
@@ -56437,7 +57411,7 @@ $GLOBALS['_PEAR_CHANNELS_MIRROR_TYPES'] = array('server');
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version Release: 1.10.0beta1
+ * @version Release: 1.9.4
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a1
*/
@@ -57858,7 +58832,7 @@ class PEAR_ChannelFile
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version CVS: $Id: Parser.php 276383 2009-02-24 23:39:37Z dufuz $
+ * @version CVS: $Id: Parser.php 313023 2011-07-06 19:17:11Z dufuz $
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.4.0a1
*/
@@ -57875,7 +58849,7 @@ require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/ChannelFile.php';
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version Release: 1.10.0beta1
+ * @version Release: 1.9.4
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a1
*/
@@ -57926,7 +58900,7 @@ class PEAR_ChannelFile_Parser extends PEAR_XMLParser
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version CVS: $Id: Command.php 286494 2009-07-29 06:57:11Z dufuz $
+ * @version CVS: $Id: Command.php 313023 2011-07-06 19:17:11Z dufuz $
* @link http://pear.php.net/package/PEAR
* @since File available since Release 0.1
*/
@@ -58010,7 +58984,7 @@ $GLOBALS['_PEAR_Command_objects'] = array();
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version Release: 1.10.0beta1
+ * @version Release: 1.9.4
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 0.1
*/
@@ -58329,6 +59303,1212 @@ class PEAR_Command
// }}}
}<?php
/**
+ * PEAR_Command_Auth (login, logout commands)
+ *
+ * PHP versions 4 and 5
+ *
+ * @category pear
+ * @package PEAR
+ * @author Stig Bakken <ssb@php.net>
+ * @author Greg Beaver <cellog@php.net>
+ * @copyright 1997-2009 The Authors
+ * @license http://opensource.org/licenses/bsd-license.php New BSD License
+ * @version CVS: $Id: Auth.php 313023 2011-07-06 19:17:11Z dufuz $
+ * @link http://pear.php.net/package/PEAR
+ * @since File available since Release 0.1
+ * @deprecated since 1.8.0alpha1
+ */
+
+/**
+ * base class
+ */
+require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Command/Channels.php';
+
+/**
+ * PEAR commands for login/logout
+ *
+ * @category pear
+ * @package PEAR
+ * @author Stig Bakken <ssb@php.net>
+ * @author Greg Beaver <cellog@php.net>
+ * @copyright 1997-2009 The Authors
+ * @license http://opensource.org/licenses/bsd-license.php New BSD License
+ * @version Release: 1.9.4
+ * @link http://pear.php.net/package/PEAR
+ * @since Class available since Release 0.1
+ * @deprecated since 1.8.0alpha1
+ */
+class PEAR_Command_Auth extends PEAR_Command_Channels
+{
+ var $commands = array(
+ 'login' => array(
+ 'summary' => 'Connects and authenticates to remote server [Deprecated in favor of channel-login]',
+ 'shortcut' => 'li',
+ 'function' => 'doLogin',
+ 'options' => array(),
+ 'doc' => '<channel name>
+WARNING: This function is deprecated in favor of using channel-login
+
+Log in to a remote channel server. If <channel name> is not supplied,
+the default channel is used. To use remote functions in the installer
+that require any kind of privileges, you need to log in first. The
+username and password you enter here will be stored in your per-user
+PEAR configuration (~/.pearrc on Unix-like systems). After logging
+in, your username and password will be sent along in subsequent
+operations on the remote server.',
+ ),
+ 'logout' => array(
+ 'summary' => 'Logs out from the remote server [Deprecated in favor of channel-logout]',
+ 'shortcut' => 'lo',
+ 'function' => 'doLogout',
+ 'options' => array(),
+ 'doc' => '
+WARNING: This function is deprecated in favor of using channel-logout
+
+Logs out from the remote server. This command does not actually
+connect to the remote server, it only deletes the stored username and
+password from your user configuration.',
+ )
+
+ );
+
+ /**
+ * PEAR_Command_Auth constructor.
+ *
+ * @access public
+ */
+ function PEAR_Command_Auth(&$ui, &$config)
+ {
+ parent::PEAR_Command_Channels($ui, $config);
+ }
+}<commands version="1.0">
+ <login>
+ <summary>Connects and authenticates to remote server [Deprecated in favor of channel-login]</summary>
+ <function>doLogin</function>
+ <shortcut>li</shortcut>
+ <options />
+ <doc>&lt;channel name&gt;
+WARNING: This function is deprecated in favor of using channel-login
+
+Log in to a remote channel server. If &lt;channel name&gt; is not supplied,
+the default channel is used. To use remote functions in the installer
+that require any kind of privileges, you need to log in first. The
+username and password you enter here will be stored in your per-user
+PEAR configuration (~/.pearrc on Unix-like systems). After logging
+in, your username and password will be sent along in subsequent
+operations on the remote server.</doc>
+ </login>
+ <logout>
+ <summary>Logs out from the remote server [Deprecated in favor of channel-logout]</summary>
+ <function>doLogout</function>
+ <shortcut>lo</shortcut>
+ <options />
+ <doc>
+WARNING: This function is deprecated in favor of using channel-logout
+
+Logs out from the remote server. This command does not actually
+connect to the remote server, it only deletes the stored username and
+password from your user configuration.</doc>
+ </logout>
+</commands><?php
+/**
+ * PEAR_Command_Auth (build command)
+ *
+ * PHP versions 4 and 5
+ *
+ * @category pear
+ * @package PEAR
+ * @author Stig Bakken <ssb@php.net>
+ * @author Tomas V.V.Cox <cox@idecnet.com>
+ * @author Greg Beaver <cellog@php.net>
+ * @copyright 1997-2009 The Authors
+ * @license http://opensource.org/licenses/bsd-license.php New BSD License
+ * @version CVS: $Id: Build.php 313023 2011-07-06 19:17:11Z dufuz $
+ * @link http://pear.php.net/package/PEAR
+ * @since File available since Release 0.1
+ */
+
+/**
+ * base class
+ */
+require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Command/Common.php';
+
+/**
+ * PEAR commands for building extensions.
+ *
+ * @category pear
+ * @package PEAR
+ * @author Stig Bakken <ssb@php.net>
+ * @author Tomas V.V.Cox <cox@idecnet.com>
+ * @author Greg Beaver <cellog@php.net>
+ * @copyright 1997-2009 The Authors
+ * @license http://opensource.org/licenses/bsd-license.php New BSD License
+ * @version Release: 1.9.4
+ * @link http://pear.php.net/package/PEAR
+ * @since Class available since Release 0.1
+ */
+class PEAR_Command_Build extends PEAR_Command_Common
+{
+ var $commands = array(
+ 'build' => array(
+ 'summary' => 'Build an Extension From C Source',
+ 'function' => 'doBuild',
+ 'shortcut' => 'b',
+ 'options' => array(),
+ 'doc' => '[package.xml]
+Builds one or more extensions contained in a package.'
+ ),
+ );
+
+ /**
+ * PEAR_Command_Build constructor.
+ *
+ * @access public
+ */
+ function PEAR_Command_Build(&$ui, &$config)
+ {
+ parent::PEAR_Command_Common($ui, $config);
+ }
+
+ function doBuild($command, $options, $params)
+ {
+ require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Builder.php';
+ if (sizeof($params) < 1) {
+ $params[0] = 'package.xml';
+ }
+
+ $builder = &new PEAR_Builder($this->ui);
+ $this->debug = $this->config->get('verbose');
+ $err = $builder->build($params[0], array(&$this, 'buildCallback'));
+ if (PEAR::isError($err)) {
+ return $err;
+ }
+
+ return true;
+ }
+
+ function buildCallback($what, $data)
+ {
+ if (($what == 'cmdoutput' && $this->debug > 1) ||
+ ($what == 'output' && $this->debug > 0)) {
+ $this->ui->outputData(rtrim($data), 'build');
+ }
+ }
+}<commands version="1.0">
+ <build>
+ <summary>Build an Extension From C Source</summary>
+ <function>doBuild</function>
+ <shortcut>b</shortcut>
+ <options />
+ <doc>[package.xml]
+Builds one or more extensions contained in a package.</doc>
+ </build>
+</commands><?php
+// /* vim: set expandtab tabstop=4 shiftwidth=4: */
+/**
+ * PEAR_Command_Channels (list-channels, update-channels, channel-delete, channel-add,
+ * channel-update, channel-info, channel-alias, channel-discover commands)
+ *
+ * PHP versions 4 and 5
+ *
+ * @category pear
+ * @package PEAR
+ * @author Stig Bakken <ssb@php.net>
+ * @author Greg Beaver <cellog@php.net>
+ * @copyright 1997-2009 The Authors
+ * @license http://opensource.org/licenses/bsd-license.php New BSD License
+ * @version CVS: $Id: Channels.php 313023 2011-07-06 19:17:11Z dufuz $
+ * @link http://pear.php.net/package/PEAR
+ * @since File available since Release 1.4.0a1
+ */
+
+/**
+ * base class
+ */
+require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Command/Common.php';
+
+define('PEAR_COMMAND_CHANNELS_CHANNEL_EXISTS', -500);
+
+/**
+ * PEAR commands for managing channels.
+ *
+ * @category pear
+ * @package PEAR
+ * @author Greg Beaver <cellog@php.net>
+ * @copyright 1997-2009 The Authors
+ * @license http://opensource.org/licenses/bsd-license.php New BSD License
+ * @version Release: 1.9.4
+ * @link http://pear.php.net/package/PEAR
+ * @since Class available since Release 1.4.0a1
+ */
+class PEAR_Command_Channels extends PEAR_Command_Common
+{
+ var $commands = array(
+ 'list-channels' => array(
+ 'summary' => 'List Available Channels',
+ 'function' => 'doList',
+ 'shortcut' => 'lc',
+ 'options' => array(),
+ 'doc' => '
+List all available channels for installation.
+',
+ ),
+ 'update-channels' => array(
+ 'summary' => 'Update the Channel List',
+ 'function' => 'doUpdateAll',
+ 'shortcut' => 'uc',
+ 'options' => array(),
+ 'doc' => '
+List all installed packages in all channels.
+'
+ ),
+ 'channel-delete' => array(
+ 'summary' => 'Remove a Channel From the List',
+ 'function' => 'doDelete',
+ 'shortcut' => 'cde',
+ 'options' => array(),
+ 'doc' => '<channel name>
+Delete a channel from the registry. You may not
+remove any channel that has installed packages.
+'
+ ),
+ 'channel-add' => array(
+ 'summary' => 'Add a Channel',
+ 'function' => 'doAdd',
+ 'shortcut' => 'ca',
+ 'options' => array(),
+ 'doc' => '<channel.xml>
+Add a private channel to the channel list. Note that all
+public channels should be synced using "update-channels".
+Parameter may be either a local file or remote URL to a
+channel.xml.
+'
+ ),
+ 'channel-update' => array(
+ 'summary' => 'Update an Existing Channel',
+ 'function' => 'doUpdate',
+ 'shortcut' => 'cu',
+ 'options' => array(
+ 'force' => array(
+ 'shortopt' => 'f',
+ 'doc' => 'will force download of new channel.xml if an existing channel name is used',
+ ),
+ 'channel' => array(
+ 'shortopt' => 'c',
+ 'arg' => 'CHANNEL',
+ 'doc' => 'will force download of new channel.xml if an existing channel name is used',
+ ),
+),
+ 'doc' => '[<channel.xml>|<channel name>]
+Update a channel in the channel list directly. Note that all
+public channels can be synced using "update-channels".
+Parameter may be a local or remote channel.xml, or the name of
+an existing channel.
+'
+ ),
+ 'channel-info' => array(
+ 'summary' => 'Retrieve Information on a Channel',
+ 'function' => 'doInfo',
+ 'shortcut' => 'ci',
+ 'options' => array(),
+ 'doc' => '<package>
+List the files in an installed package.
+'
+ ),
+ 'channel-alias' => array(
+ 'summary' => 'Specify an alias to a channel name',
+ 'function' => 'doAlias',
+ 'shortcut' => 'cha',
+ 'options' => array(),
+ 'doc' => '<channel> <alias>
+Specify a specific alias to use for a channel name.
+The alias may not be an existing channel name or
+alias.
+'
+ ),
+ 'channel-discover' => array(
+ 'summary' => 'Initialize a Channel from its server',
+ 'function' => 'doDiscover',
+ 'shortcut' => 'di',
+ 'options' => array(),
+ 'doc' => '[<channel.xml>|<channel name>]
+Initialize a channel from its server and create a local channel.xml.
+If <channel name> is in the format "<username>:<password>@<channel>" then
+<username> and <password> will be set as the login username/password for
+<channel>. Use caution when passing the username/password in this way, as
+it may allow other users on your computer to briefly view your username/
+password via the system\'s process list.
+'
+ ),
+ 'channel-login' => array(
+ 'summary' => 'Connects and authenticates to remote channel server',
+ 'shortcut' => 'cli',
+ 'function' => 'doLogin',
+ 'options' => array(),
+ 'doc' => '<channel name>
+Log in to a remote channel server. If <channel name> is not supplied,
+the default channel is used. To use remote functions in the installer
+that require any kind of privileges, you need to log in first. The
+username and password you enter here will be stored in your per-user
+PEAR configuration (~/.pearrc on Unix-like systems). After logging
+in, your username and password will be sent along in subsequent
+operations on the remote server.',
+ ),
+ 'channel-logout' => array(
+ 'summary' => 'Logs out from the remote channel server',
+ 'shortcut' => 'clo',
+ 'function' => 'doLogout',
+ 'options' => array(),
+ 'doc' => '<channel name>
+Logs out from a remote channel server. If <channel name> is not supplied,
+the default channel is used. This command does not actually connect to the
+remote server, it only deletes the stored username and password from your user
+configuration.',
+ ),
+ );
+
+ /**
+ * PEAR_Command_Registry constructor.
+ *
+ * @access public
+ */
+ function PEAR_Command_Channels(&$ui, &$config)
+ {
+ parent::PEAR_Command_Common($ui, $config);
+ }
+
+ function _sortChannels($a, $b)
+ {
+ return strnatcasecmp($a->getName(), $b->getName());
+ }
+
+ function doList($command, $options, $params)
+ {
+ $reg = &$this->config->getRegistry();
+ $registered = $reg->getChannels();
+ usort($registered, array(&$this, '_sortchannels'));
+ $i = $j = 0;
+ $data = array(
+ 'caption' => 'Registered Channels:',
+ 'border' => true,
+ 'headline' => array('Channel', 'Alias', 'Summary')
+ );
+ foreach ($registered as $channel) {
+ $data['data'][] = array($channel->getName(),
+ $channel->getAlias(),
+ $channel->getSummary());
+ }
+
+ if (count($registered) === 0) {
+ $data = '(no registered channels)';
+ }
+ $this->ui->outputData($data, $command);
+ return true;
+ }
+
+ function doUpdateAll($command, $options, $params)
+ {
+ $reg = &$this->config->getRegistry();
+ $channels = $reg->getChannels();
+
+ $success = true;
+ foreach ($channels as $channel) {
+ if ($channel->getName() != '__uri') {
+ PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
+ $err = $this->doUpdate('channel-update',
+ $options,
+ array($channel->getName()));
+ if (PEAR::isError($err)) {
+ $this->ui->outputData($err->getMessage(), $command);
+ $success = false;
+ } else {
+ $success &= $err;
+ }
+ }
+ }
+ return $success;
+ }
+
+ function doInfo($command, $options, $params)
+ {
+ if (count($params) !== 1) {
+ return $this->raiseError("No channel specified");
+ }
+
+ $reg = &$this->config->getRegistry();
+ $channel = strtolower($params[0]);
+ if ($reg->channelExists($channel)) {
+ $chan = $reg->getChannel($channel);
+ if (PEAR::isError($chan)) {
+ return $this->raiseError($chan);
+ }
+ } else {
+ if (strpos($channel, '://')) {
+ $downloader = &$this->getDownloader();
+ $tmpdir = $this->config->get('temp_dir');
+ PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
+ $loc = $downloader->downloadHttp($channel, $this->ui, $tmpdir);
+ PEAR::staticPopErrorHandling();
+ if (PEAR::isError($loc)) {
+ return $this->raiseError('Cannot open "' . $channel .
+ '" (' . $loc->getMessage() . ')');
+ } else {
+ $contents = implode('', file($loc));
+ }
+ } else {
+ if (!file_exists($params[0])) {
+ return $this->raiseError('Unknown channel "' . $channel . '"');
+ }
+
+ $fp = fopen($params[0], 'r');
+ if (!$fp) {
+ return $this->raiseError('Cannot open "' . $params[0] . '"');
+ }
+
+ $contents = '';
+ while (!feof($fp)) {
+ $contents .= fread($fp, 1024);
+ }
+ fclose($fp);
+ }
+
+ if (!class_exists('PEAR_ChannelFile')) {
+ require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/ChannelFile.php';
+ }
+
+ $chan = new PEAR_ChannelFile;
+ $chan->fromXmlString($contents);
+ $chan->validate();
+ if ($errs = $chan->getErrors(true)) {
+ foreach ($errs as $err) {
+ $this->ui->outputData($err['level'] . ': ' . $err['message']);
+ }
+ return $this->raiseError('Channel file "' . $params[0] . '" is not valid');
+ }
+ }
+
+ if (!$chan) {
+ return $this->raiseError('Serious error: Channel "' . $params[0] .
+ '" has a corrupted registry entry');
+ }
+
+ $channel = $chan->getName();
+ $caption = 'Channel ' . $channel . ' Information:';
+ $data1 = array(
+ 'caption' => $caption,
+ 'border' => true);
+ $data1['data']['server'] = array('Name and Server', $chan->getName());
+ if ($chan->getAlias() != $chan->getName()) {
+ $data1['data']['alias'] = array('Alias', $chan->getAlias());
+ }
+
+ $data1['data']['summary'] = array('Summary', $chan->getSummary());
+ $validate = $chan->getValidationPackage();
+ $data1['data']['vpackage'] = array('Validation Package Name', $validate['_content']);
+ $data1['data']['vpackageversion'] =
+ array('Validation Package Version', $validate['attribs']['version']);
+ $d = array();
+ $d['main'] = $data1;
+
+ $data['data'] = array();
+ $data['caption'] = 'Server Capabilities';
+ $data['headline'] = array('Type', 'Version/REST type', 'Function Name/REST base');
+ if ($chan->supportsREST()) {
+ if ($chan->supportsREST()) {
+ $funcs = $chan->getFunctions('rest');
+ if (!isset($funcs[0])) {
+ $funcs = array($funcs);
+ }
+ foreach ($funcs as $protocol) {
+ $data['data'][] = array('rest', $protocol['attribs']['type'],
+ $protocol['_content']);
+ }
+ }
+ } else {
+ $data['data'][] = array('No supported protocols');
+ }
+
+ $d['protocols'] = $data;
+ $data['data'] = array();
+ $mirrors = $chan->getMirrors();
+ if ($mirrors) {
+ $data['caption'] = 'Channel ' . $channel . ' Mirrors:';
+ unset($data['headline']);
+ foreach ($mirrors as $mirror) {
+ $data['data'][] = array($mirror['attribs']['host']);
+ $d['mirrors'] = $data;
+ }
+
+ foreach ($mirrors as $i => $mirror) {
+ $data['data'] = array();
+ $data['caption'] = 'Mirror ' . $mirror['attribs']['host'] . ' Capabilities';
+ $data['headline'] = array('Type', 'Version/REST type', 'Function Name/REST base');
+ if ($chan->supportsREST($mirror['attribs']['host'])) {
+ if ($chan->supportsREST($mirror['attribs']['host'])) {
+ $funcs = $chan->getFunctions('rest', $mirror['attribs']['host']);
+ if (!isset($funcs[0])) {
+ $funcs = array($funcs);
+ }
+
+ foreach ($funcs as $protocol) {
+ $data['data'][] = array('rest', $protocol['attribs']['type'],
+ $protocol['_content']);
+ }
+ }
+ } else {
+ $data['data'][] = array('No supported protocols');
+ }
+ $d['mirrorprotocols' . $i] = $data;
+ }
+ }
+ $this->ui->outputData($d, 'channel-info');
+ }
+
+ // }}}
+
+ function doDelete($command, $options, $params)
+ {
+ if (count($params) !== 1) {
+ return $this->raiseError('channel-delete: no channel specified');
+ }
+
+ $reg = &$this->config->getRegistry();
+ if (!$reg->channelExists($params[0])) {
+ return $this->raiseError('channel-delete: channel "' . $params[0] . '" does not exist');
+ }
+
+ $channel = $reg->channelName($params[0]);
+ if ($channel == 'pear.php.net') {
+ return $this->raiseError('Cannot delete the pear.php.net channel');
+ }
+
+ if ($channel == 'pecl.php.net') {
+ return $this->raiseError('Cannot delete the pecl.php.net channel');
+ }
+
+ if ($channel == 'doc.php.net') {
+ return $this->raiseError('Cannot delete the doc.php.net channel');
+ }
+
+ if ($channel == '__uri') {
+ return $this->raiseError('Cannot delete the __uri pseudo-channel');
+ }
+
+ if (PEAR::isError($err = $reg->listPackages($channel))) {
+ return $err;
+ }
+
+ if (count($err)) {
+ return $this->raiseError('Channel "' . $channel .
+ '" has installed packages, cannot delete');
+ }
+
+ if (!$reg->deleteChannel($channel)) {
+ return $this->raiseError('Channel "' . $channel . '" deletion failed');
+ } else {
+ $this->config->deleteChannel($channel);
+ $this->ui->outputData('Channel "' . $channel . '" deleted', $command);
+ }
+ }
+
+ function doAdd($command, $options, $params)
+ {
+ if (count($params) !== 1) {
+ return $this->raiseError('channel-add: no channel file specified');
+ }
+
+ if (strpos($params[0], '://')) {
+ $downloader = &$this->getDownloader();
+ $tmpdir = $this->config->get('temp_dir');
+ if (!file_exists($tmpdir)) {
+ require_once 'phar://install-pear-nozlib.phar/' . 'System.php';
+ PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
+ $err = System::mkdir(array('-p', $tmpdir));
+ PEAR::staticPopErrorHandling();
+ if (PEAR::isError($err)) {
+ return $this->raiseError('channel-add: temp_dir does not exist: "' .
+ $tmpdir .
+ '" - You can change this location with "pear config-set temp_dir"');
+ }
+ }
+
+ if (!is_writable($tmpdir)) {
+ return $this->raiseError('channel-add: temp_dir is not writable: "' .
+ $tmpdir .
+ '" - You can change this location with "pear config-set temp_dir"');
+ }
+
+ PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
+ $loc = $downloader->downloadHttp($params[0], $this->ui, $tmpdir, null, false);
+ PEAR::staticPopErrorHandling();
+ if (PEAR::isError($loc)) {
+ return $this->raiseError('channel-add: Cannot open "' . $params[0] .
+ '" (' . $loc->getMessage() . ')');
+ }
+
+ list($loc, $lastmodified) = $loc;
+ $contents = implode('', file($loc));
+ } else {
+ $lastmodified = $fp = false;
+ if (file_exists($params[0])) {
+ $fp = fopen($params[0], 'r');
+ }
+
+ if (!$fp) {
+ return $this->raiseError('channel-add: cannot open "' . $params[0] . '"');
+ }
+
+ $contents = '';
+ while (!feof($fp)) {
+ $contents .= fread($fp, 1024);
+ }
+ fclose($fp);
+ }
+
+ if (!class_exists('PEAR_ChannelFile')) {
+ require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/ChannelFile.php';
+ }
+
+ $channel = new PEAR_ChannelFile;
+ PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
+ $result = $channel->fromXmlString($contents);
+ PEAR::staticPopErrorHandling();
+ if (!$result) {
+ $exit = false;
+ if (count($errors = $channel->getErrors(true))) {
+ foreach ($errors as $error) {
+ $this->ui->outputData(ucfirst($error['level'] . ': ' . $error['message']));
+ if (!$exit) {
+ $exit = $error['level'] == 'error' ? true : false;
+ }
+ }
+ if ($exit) {
+ return $this->raiseError('channel-add: invalid channel.xml file');
+ }
+ }
+ }
+
+ $reg = &$this->config->getRegistry();
+ if ($reg->channelExists($channel->getName())) {
+ return $this->raiseError('channel-add: Channel "' . $channel->getName() .
+ '" exists, use channel-update to update entry', PEAR_COMMAND_CHANNELS_CHANNEL_EXISTS);
+ }
+
+ $ret = $reg->addChannel($channel, $lastmodified);
+ if (PEAR::isError($ret)) {
+ return $ret;
+ }
+
+ if (!$ret) {
+ return $this->raiseError('channel-add: adding Channel "' . $channel->getName() .
+ '" to registry failed');
+ }
+
+ $this->config->setChannels($reg->listChannels());
+ $this->config->writeConfigFile();
+ $this->ui->outputData('Adding Channel "' . $channel->getName() . '" succeeded', $command);
+ }
+
+ function doUpdate($command, $options, $params)
+ {
+ if (count($params) !== 1) {
+ return $this->raiseError("No channel file specified");
+ }
+
+ $tmpdir = $this->config->get('temp_dir');
+ if (!file_exists($tmpdir)) {
+ require_once 'phar://install-pear-nozlib.phar/' . 'System.php';
+ PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
+ $err = System::mkdir(array('-p', $tmpdir));
+ PEAR::staticPopErrorHandling();
+ if (PEAR::isError($err)) {
+ return $this->raiseError('channel-add: temp_dir does not exist: "' .
+ $tmpdir .
+ '" - You can change this location with "pear config-set temp_dir"');
+ }
+ }
+
+ if (!is_writable($tmpdir)) {
+ return $this->raiseError('channel-add: temp_dir is not writable: "' .
+ $tmpdir .
+ '" - You can change this location with "pear config-set temp_dir"');
+ }
+
+ $reg = &$this->config->getRegistry();
+ $lastmodified = false;
+ if ((!file_exists($params[0]) || is_dir($params[0]))
+ && $reg->channelExists(strtolower($params[0]))) {
+ $c = $reg->getChannel(strtolower($params[0]));
+ if (PEAR::isError($c)) {
+ return $this->raiseError($c);
+ }
+
+ $this->ui->outputData("Updating channel \"$params[0]\"", $command);
+ $dl = &$this->getDownloader(array());
+ // if force is specified, use a timestamp of "1" to force retrieval
+ $lastmodified = isset($options['force']) ? false : $c->lastModified();
+ PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
+ $contents = $dl->downloadHttp('http://' . $c->getName() . '/channel.xml',
+ $this->ui, $tmpdir, null, $lastmodified);
+ PEAR::staticPopErrorHandling();
+ if (PEAR::isError($contents)) {
+ // Attempt to fall back to https
+ $this->ui->outputData("Channel \"$params[0]\" is not responding over http://, failed with message: " . $contents->getMessage());
+ $this->ui->outputData("Trying channel \"$params[0]\" over https:// instead");
+ PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
+ $contents = $dl->downloadHttp('https://' . $c->getName() . '/channel.xml',
+ $this->ui, $tmpdir, null, $lastmodified);
+ PEAR::staticPopErrorHandling();
+ if (PEAR::isError($contents)) {
+ return $this->raiseError('Cannot retrieve channel.xml for channel "' .
+ $c->getName() . '" (' . $contents->getMessage() . ')');
+ }
+ }
+
+ list($contents, $lastmodified) = $contents;
+ if (!$contents) {
+ $this->ui->outputData("Channel \"$params[0]\" is up to date");
+ return;
+ }
+
+ $contents = implode('', file($contents));
+ if (!class_exists('PEAR_ChannelFile')) {
+ require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/ChannelFile.php';
+ }
+
+ $channel = new PEAR_ChannelFile;
+ $channel->fromXmlString($contents);
+ if (!$channel->getErrors()) {
+ // security check: is the downloaded file for the channel we got it from?
+ if (strtolower($channel->getName()) != strtolower($c->getName())) {
+ if (!isset($options['force'])) {
+ return $this->raiseError('ERROR: downloaded channel definition file' .
+ ' for channel "' . $channel->getName() . '" from channel "' .
+ strtolower($c->getName()) . '"');
+ }
+
+ $this->ui->log(0, 'WARNING: downloaded channel definition file' .
+ ' for channel "' . $channel->getName() . '" from channel "' .
+ strtolower($c->getName()) . '"');
+ }
+ }
+ } else {
+ if (strpos($params[0], '://')) {
+ $dl = &$this->getDownloader();
+ PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
+ $loc = $dl->downloadHttp($params[0],
+ $this->ui, $tmpdir, null, $lastmodified);
+ PEAR::staticPopErrorHandling();
+ if (PEAR::isError($loc)) {
+ return $this->raiseError("Cannot open " . $params[0] .
+ ' (' . $loc->getMessage() . ')');
+ }
+
+ list($loc, $lastmodified) = $loc;
+ $contents = implode('', file($loc));
+ } else {
+ $fp = false;
+ if (file_exists($params[0])) {
+ $fp = fopen($params[0], 'r');
+ }
+
+ if (!$fp) {
+ return $this->raiseError("Cannot open " . $params[0]);
+ }
+
+ $contents = '';
+ while (!feof($fp)) {
+ $contents .= fread($fp, 1024);
+ }
+ fclose($fp);
+ }
+
+ if (!class_exists('PEAR_ChannelFile')) {
+ require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/ChannelFile.php';
+ }
+
+ $channel = new PEAR_ChannelFile;
+ $channel->fromXmlString($contents);
+ }
+
+ $exit = false;
+ if (count($errors = $channel->getErrors(true))) {
+ foreach ($errors as $error) {
+ $this->ui->outputData(ucfirst($error['level'] . ': ' . $error['message']));
+ if (!$exit) {
+ $exit = $error['level'] == 'error' ? true : false;
+ }
+ }
+ if ($exit) {
+ return $this->raiseError('Invalid channel.xml file');
+ }
+ }
+
+ if (!$reg->channelExists($channel->getName())) {
+ return $this->raiseError('Error: Channel "' . $channel->getName() .
+ '" does not exist, use channel-add to add an entry');
+ }
+
+ $ret = $reg->updateChannel($channel, $lastmodified);
+ if (PEAR::isError($ret)) {
+ return $ret;
+ }
+
+ if (!$ret) {
+ return $this->raiseError('Updating Channel "' . $channel->getName() .
+ '" in registry failed');
+ }
+
+ $this->config->setChannels($reg->listChannels());
+ $this->config->writeConfigFile();
+ $this->ui->outputData('Update of Channel "' . $channel->getName() . '" succeeded');
+ }
+
+ function &getDownloader()
+ {
+ if (!class_exists('PEAR_Downloader')) {
+ require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Downloader.php';
+ }
+ $a = new PEAR_Downloader($this->ui, array(), $this->config);
+ return $a;
+ }
+
+ function doAlias($command, $options, $params)
+ {
+ if (count($params) === 1) {
+ return $this->raiseError('No channel alias specified');
+ }
+
+ if (count($params) !== 2 || (!empty($params[1]) && $params[1]{0} == '-')) {
+ return $this->raiseError(
+ 'Invalid format, correct is: channel-alias channel alias');
+ }
+
+ $reg = &$this->config->getRegistry();
+ if (!$reg->channelExists($params[0], true)) {
+ $extra = '';
+ if ($reg->isAlias($params[0])) {
+ $extra = ' (use "channel-alias ' . $reg->channelName($params[0]) . ' ' .
+ strtolower($params[1]) . '")';
+ }
+
+ return $this->raiseError('"' . $params[0] . '" is not a valid channel' . $extra);
+ }
+
+ if ($reg->isAlias($params[1])) {
+ return $this->raiseError('Channel "' . $reg->channelName($params[1]) . '" is ' .
+ 'already aliased to "' . strtolower($params[1]) . '", cannot re-alias');
+ }
+
+ $chan = &$reg->getChannel($params[0]);
+ if (PEAR::isError($chan)) {
+ return $this->raiseError('Corrupt registry? Error retrieving channel "' . $params[0] .
+ '" information (' . $chan->getMessage() . ')');
+ }
+
+ // make it a local alias
+ if (!$chan->setAlias(strtolower($params[1]), true)) {
+ return $this->raiseError('Alias "' . strtolower($params[1]) .
+ '" is not a valid channel alias');
+ }
+
+ $reg->updateChannel($chan);
+ $this->ui->outputData('Channel "' . $chan->getName() . '" aliased successfully to "' .
+ strtolower($params[1]) . '"');
+ }
+
+ /**
+ * The channel-discover command
+ *
+ * @param string $command command name
+ * @param array $options option_name => value
+ * @param array $params list of additional parameters.
+ * $params[0] should contain a string with either:
+ * - <channel name> or
+ * - <username>:<password>@<channel name>
+ * @return null|PEAR_Error
+ */
+ function doDiscover($command, $options, $params)
+ {
+ if (count($params) !== 1) {
+ return $this->raiseError("No channel server specified");
+ }
+
+ // Look for the possible input format "<username>:<password>@<channel>"
+ if (preg_match('/^(.+):(.+)@(.+)\\z/', $params[0], $matches)) {
+ $username = $matches[1];
+ $password = $matches[2];
+ $channel = $matches[3];
+ } else {
+ $channel = $params[0];
+ }
+
+ $reg = &$this->config->getRegistry();
+ if ($reg->channelExists($channel)) {
+ if (!$reg->isAlias($channel)) {
+ return $this->raiseError("Channel \"$channel\" is already initialized", PEAR_COMMAND_CHANNELS_CHANNEL_EXISTS);
+ }
+
+ return $this->raiseError("A channel alias named \"$channel\" " .
+ 'already exists, aliasing channel "' . $reg->channelName($channel)
+ . '"');
+ }
+
+ $this->pushErrorHandling(PEAR_ERROR_RETURN);
+ $err = $this->doAdd($command, $options, array('http://' . $channel . '/channel.xml'));
+ $this->popErrorHandling();
+ if (PEAR::isError($err)) {
+ if ($err->getCode() === PEAR_COMMAND_CHANNELS_CHANNEL_EXISTS) {
+ return $this->raiseError("Discovery of channel \"$channel\" failed (" .
+ $err->getMessage() . ')');
+ }
+ // Attempt fetch via https
+ $this->ui->outputData("Discovering channel $channel over http:// failed with message: " . $err->getMessage());
+ $this->ui->outputData("Trying to discover channel $channel over https:// instead");
+ $this->pushErrorHandling(PEAR_ERROR_RETURN);
+ $err = $this->doAdd($command, $options, array('https://' . $channel . '/channel.xml'));
+ $this->popErrorHandling();
+ if (PEAR::isError($err)) {
+ return $this->raiseError("Discovery of channel \"$channel\" failed (" .
+ $err->getMessage() . ')');
+ }
+ }
+
+ // Store username/password if they were given
+ // Arguably we should do a logintest on the channel here, but since
+ // that's awkward on a REST-based channel (even "pear login" doesn't
+ // do it for those), and XML-RPC is deprecated, it's fairly pointless.
+ if (isset($username)) {
+ $this->config->set('username', $username, 'user', $channel);
+ $this->config->set('password', $password, 'user', $channel);
+ $this->config->store();
+ $this->ui->outputData("Stored login for channel \"$channel\" using username \"$username\"", $command);
+ }
+
+ $this->ui->outputData("Discovery of channel \"$channel\" succeeded", $command);
+ }
+
+ /**
+ * Execute the 'login' command.
+ *
+ * @param string $command command name
+ * @param array $options option_name => value
+ * @param array $params list of additional parameters
+ *
+ * @return bool TRUE on success or
+ * a PEAR error on failure
+ *
+ * @access public
+ */
+ function doLogin($command, $options, $params)
+ {
+ $reg = &$this->config->getRegistry();
+
+ // If a parameter is supplied, use that as the channel to log in to
+ $channel = isset($params[0]) ? $params[0] : $this->config->get('default_channel');
+
+ $chan = $reg->getChannel($channel);
+ if (PEAR::isError($chan)) {
+ return $this->raiseError($chan);
+ }
+
+ $server = $this->config->get('preferred_mirror', null, $channel);
+ $username = $this->config->get('username', null, $channel);
+ if (empty($username)) {
+ $username = isset($_ENV['USER']) ? $_ENV['USER'] : null;
+ }
+ $this->ui->outputData("Logging in to $server.", $command);
+
+ list($username, $password) = $this->ui->userDialog(
+ $command,
+ array('Username', 'Password'),
+ array('text', 'password'),
+ array($username, '')
+ );
+ $username = trim($username);
+ $password = trim($password);
+
+ $ourfile = $this->config->getConfFile('user');
+ if (!$ourfile) {
+ $ourfile = $this->config->getConfFile('system');
+ }
+
+ $this->config->set('username', $username, 'user', $channel);
+ $this->config->set('password', $password, 'user', $channel);
+
+ if ($chan->supportsREST()) {
+ $ok = true;
+ }
+
+ if ($ok !== true) {
+ return $this->raiseError('Login failed!');
+ }
+
+ $this->ui->outputData("Logged in.", $command);
+ // avoid changing any temporary settings changed with -d
+ $ourconfig = new PEAR_Config($ourfile, $ourfile);
+ $ourconfig->set('username', $username, 'user', $channel);
+ $ourconfig->set('password', $password, 'user', $channel);
+ $ourconfig->store();
+
+ return true;
+ }
+
+ /**
+ * Execute the 'logout' command.
+ *
+ * @param string $command command name
+ * @param array $options option_name => value
+ * @param array $params list of additional parameters
+ *
+ * @return bool TRUE on success or
+ * a PEAR error on failure
+ *
+ * @access public
+ */
+ function doLogout($command, $options, $params)
+ {
+ $reg = &$this->config->getRegistry();
+
+ // If a parameter is supplied, use that as the channel to log in to
+ $channel = isset($params[0]) ? $params[0] : $this->config->get('default_channel');
+
+ $chan = $reg->getChannel($channel);
+ if (PEAR::isError($chan)) {
+ return $this->raiseError($chan);
+ }
+
+ $server = $this->config->get('preferred_mirror', null, $channel);
+ $this->ui->outputData("Logging out from $server.", $command);
+ $this->config->remove('username', 'user', $channel);
+ $this->config->remove('password', 'user', $channel);
+ $this->config->store();
+ return true;
+ }
+}<commands version="1.0">
+ <list-channels>
+ <summary>List Available Channels</summary>
+ <function>doList</function>
+ <shortcut>lc</shortcut>
+ <options />
+ <doc>
+List all available channels for installation.
+</doc>
+ </list-channels>
+ <update-channels>
+ <summary>Update the Channel List</summary>
+ <function>doUpdateAll</function>
+ <shortcut>uc</shortcut>
+ <options />
+ <doc>
+List all installed packages in all channels.
+</doc>
+ </update-channels>
+ <channel-delete>
+ <summary>Remove a Channel From the List</summary>
+ <function>doDelete</function>
+ <shortcut>cde</shortcut>
+ <options />
+ <doc>&lt;channel name&gt;
+Delete a channel from the registry. You may not
+remove any channel that has installed packages.
+</doc>
+ </channel-delete>
+ <channel-add>
+ <summary>Add a Channel</summary>
+ <function>doAdd</function>
+ <shortcut>ca</shortcut>
+ <options />
+ <doc>&lt;channel.xml&gt;
+Add a private channel to the channel list. Note that all
+public channels should be synced using &quot;update-channels&quot;.
+Parameter may be either a local file or remote URL to a
+channel.xml.
+</doc>
+ </channel-add>
+ <channel-update>
+ <summary>Update an Existing Channel</summary>
+ <function>doUpdate</function>
+ <shortcut>cu</shortcut>
+ <options>
+ <force>
+ <shortopt>f</shortopt>
+ <doc>will force download of new channel.xml if an existing channel name is used</doc>
+ </force>
+ <channel>
+ <shortopt>c</shortopt>
+ <doc>will force download of new channel.xml if an existing channel name is used</doc>
+ <arg>CHANNEL</arg>
+ </channel>
+ </options>
+ <doc>[&lt;channel.xml&gt;|&lt;channel name&gt;]
+Update a channel in the channel list directly. Note that all
+public channels can be synced using &quot;update-channels&quot;.
+Parameter may be a local or remote channel.xml, or the name of
+an existing channel.
+</doc>
+ </channel-update>
+ <channel-info>
+ <summary>Retrieve Information on a Channel</summary>
+ <function>doInfo</function>
+ <shortcut>ci</shortcut>
+ <options />
+ <doc>&lt;package&gt;
+List the files in an installed package.
+</doc>
+ </channel-info>
+ <channel-alias>
+ <summary>Specify an alias to a channel name</summary>
+ <function>doAlias</function>
+ <shortcut>cha</shortcut>
+ <options />
+ <doc>&lt;channel&gt; &lt;alias&gt;
+Specify a specific alias to use for a channel name.
+The alias may not be an existing channel name or
+alias.
+</doc>
+ </channel-alias>
+ <channel-discover>
+ <summary>Initialize a Channel from its server</summary>
+ <function>doDiscover</function>
+ <shortcut>di</shortcut>
+ <options />
+ <doc>[&lt;channel.xml&gt;|&lt;channel name&gt;]
+Initialize a channel from its server and create a local channel.xml.
+If &lt;channel name&gt; is in the format &quot;&lt;username&gt;:&lt;password&gt;@&lt;channel&gt;&quot; then
+&lt;username&gt; and &lt;password&gt; will be set as the login username/password for
+&lt;channel&gt;. Use caution when passing the username/password in this way, as
+it may allow other users on your computer to briefly view your username/
+password via the system&#039;s process list.
+</doc>
+ </channel-discover>
+ <channel-login>
+ <summary>Connects and authenticates to remote channel server</summary>
+ <function>doLogin</function>
+ <shortcut>cli</shortcut>
+ <options />
+ <doc>&lt;channel name&gt;
+Log in to a remote channel server. If &lt;channel name&gt; is not supplied,
+the default channel is used. To use remote functions in the installer
+that require any kind of privileges, you need to log in first. The
+username and password you enter here will be stored in your per-user
+PEAR configuration (~/.pearrc on Unix-like systems). After logging
+in, your username and password will be sent along in subsequent
+operations on the remote server.</doc>
+ </channel-login>
+ <channel-logout>
+ <summary>Logs out from the remote channel server</summary>
+ <function>doLogout</function>
+ <shortcut>clo</shortcut>
+ <options />
+ <doc>&lt;channel name&gt;
+Logs out from a remote channel server. If &lt;channel name&gt; is not supplied,
+the default channel is used. This command does not actually connect to the
+remote server, it only deletes the stored username and password from your user
+configuration.</doc>
+ </channel-logout>
+</commands><?php
+/**
* PEAR_Command_Common base class
*
* PHP versions 4 and 5
@@ -58339,7 +60519,7 @@ class PEAR_Command
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version CVS: $Id: Common.php 276383 2009-02-24 23:39:37Z dufuz $
+ * @version CVS: $Id: Common.php 313023 2011-07-06 19:17:11Z dufuz $
* @link http://pear.php.net/package/PEAR
* @since File available since Release 0.1
*/
@@ -58358,7 +60538,7 @@ require_once 'phar://install-pear-nozlib.phar/' . 'PEAR.php';
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version Release: 1.10.0beta1
+ * @version Release: 1.9.4
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 0.1
*/
@@ -58601,6 +60781,510 @@ class PEAR_Command_Common extends PEAR
}
}<?php
/**
+ * PEAR_Command_Config (config-show, config-get, config-set, config-help, config-create commands)
+ *
+ * PHP versions 4 and 5
+ *
+ * @category pear
+ * @package PEAR
+ * @author Stig Bakken <ssb@php.net>
+ * @author Greg Beaver <cellog@php.net>
+ * @copyright 1997-2009 The Authors
+ * @license http://opensource.org/licenses/bsd-license.php New BSD License
+ * @version CVS: $Id: Config.php 313024 2011-07-06 19:51:24Z dufuz $
+ * @link http://pear.php.net/package/PEAR
+ * @since File available since Release 0.1
+ */
+
+/**
+ * base class
+ */
+require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Command/Common.php';
+
+/**
+ * PEAR commands for managing configuration data.
+ *
+ * @category pear
+ * @package PEAR
+ * @author Stig Bakken <ssb@php.net>
+ * @author Greg Beaver <cellog@php.net>
+ * @copyright 1997-2009 The Authors
+ * @license http://opensource.org/licenses/bsd-license.php New BSD License
+ * @version Release: 1.9.4
+ * @link http://pear.php.net/package/PEAR
+ * @since Class available since Release 0.1
+ */
+class PEAR_Command_Config extends PEAR_Command_Common
+{
+ var $commands = array(
+ 'config-show' => array(
+ 'summary' => 'Show All Settings',
+ 'function' => 'doConfigShow',
+ 'shortcut' => 'csh',
+ 'options' => array(
+ 'channel' => array(
+ 'shortopt' => 'c',
+ 'doc' => 'show configuration variables for another channel',
+ 'arg' => 'CHAN',
+ ),
+),
+ 'doc' => '[layer]
+Displays all configuration values. An optional argument
+may be used to tell which configuration layer to display. Valid
+configuration layers are "user", "system" and "default". To display
+configurations for different channels, set the default_channel
+configuration variable and run config-show again.
+',
+ ),
+ 'config-get' => array(
+ 'summary' => 'Show One Setting',
+ 'function' => 'doConfigGet',
+ 'shortcut' => 'cg',
+ 'options' => array(
+ 'channel' => array(
+ 'shortopt' => 'c',
+ 'doc' => 'show configuration variables for another channel',
+ 'arg' => 'CHAN',
+ ),
+),
+ 'doc' => '<parameter> [layer]
+Displays the value of one configuration parameter. The
+first argument is the name of the parameter, an optional second argument
+may be used to tell which configuration layer to look in. Valid configuration
+layers are "user", "system" and "default". If no layer is specified, a value
+will be picked from the first layer that defines the parameter, in the order
+just specified. The configuration value will be retrieved for the channel
+specified by the default_channel configuration variable.
+',
+ ),
+ 'config-set' => array(
+ 'summary' => 'Change Setting',
+ 'function' => 'doConfigSet',
+ 'shortcut' => 'cs',
+ 'options' => array(
+ 'channel' => array(
+ 'shortopt' => 'c',
+ 'doc' => 'show configuration variables for another channel',
+ 'arg' => 'CHAN',
+ ),
+),
+ 'doc' => '<parameter> <value> [layer]
+Sets the value of one configuration parameter. The first argument is
+the name of the parameter, the second argument is the new value. Some
+parameters are subject to validation, and the command will fail with
+an error message if the new value does not make sense. An optional
+third argument may be used to specify in which layer to set the
+configuration parameter. The default layer is "user". The
+configuration value will be set for the current channel, which
+is controlled by the default_channel configuration variable.
+',
+ ),
+ 'config-help' => array(
+ 'summary' => 'Show Information About Setting',
+ 'function' => 'doConfigHelp',
+ 'shortcut' => 'ch',
+ 'options' => array(),
+ 'doc' => '[parameter]
+Displays help for a configuration parameter. Without arguments it
+displays help for all configuration parameters.
+',
+ ),
+ 'config-create' => array(
+ 'summary' => 'Create a Default configuration file',
+ 'function' => 'doConfigCreate',
+ 'shortcut' => 'coc',
+ 'options' => array(
+ 'windows' => array(
+ 'shortopt' => 'w',
+ 'doc' => 'create a config file for a windows install',
+ ),
+ ),
+ 'doc' => '<root path> <filename>
+Create a default configuration file with all directory configuration
+variables set to subdirectories of <root path>, and save it as <filename>.
+This is useful especially for creating a configuration file for a remote
+PEAR installation (using the --remoteconfig option of install, upgrade,
+and uninstall).
+',
+ ),
+ );
+
+ /**
+ * PEAR_Command_Config constructor.
+ *
+ * @access public
+ */
+ function PEAR_Command_Config(&$ui, &$config)
+ {
+ parent::PEAR_Command_Common($ui, $config);
+ }
+
+ function doConfigShow($command, $options, $params)
+ {
+ $layer = null;
+ if (is_array($params)) {
+ $layer = isset($params[0]) ? $params[0] : null;
+ }
+
+ // $params[0] -> the layer
+ if ($error = $this->_checkLayer($layer)) {
+ return $this->raiseError("config-show:$error");
+ }
+
+ $keys = $this->config->getKeys();
+ sort($keys);
+ $channel = isset($options['channel']) ? $options['channel'] :
+ $this->config->get('default_channel');
+ $reg = &$this->config->getRegistry();
+ if (!$reg->channelExists($channel)) {
+ return $this->raiseError('Channel "' . $channel . '" does not exist');
+ }
+
+ $channel = $reg->channelName($channel);
+ $data = array('caption' => 'Configuration (channel ' . $channel . '):');
+ foreach ($keys as $key) {
+ $type = $this->config->getType($key);
+ $value = $this->config->get($key, $layer, $channel);
+ if ($type == 'password' && $value) {
+ $value = '********';
+ }
+
+ if ($value === false) {
+ $value = 'false';
+ } elseif ($value === true) {
+ $value = 'true';
+ }
+
+ $data['data'][$this->config->getGroup($key)][] = array($this->config->getPrompt($key) , $key, $value);
+ }
+
+ foreach ($this->config->getLayers() as $layer) {
+ $data['data']['Config Files'][] = array(ucfirst($layer) . ' Configuration File', 'Filename' , $this->config->getConfFile($layer));
+ }
+
+ $this->ui->outputData($data, $command);
+ return true;
+ }
+
+ function doConfigGet($command, $options, $params)
+ {
+ $args_cnt = is_array($params) ? count($params) : 0;
+ switch ($args_cnt) {
+ case 1:
+ $config_key = $params[0];
+ $layer = null;
+ break;
+ case 2:
+ $config_key = $params[0];
+ $layer = $params[1];
+ if ($error = $this->_checkLayer($layer)) {
+ return $this->raiseError("config-get:$error");
+ }
+ break;
+ case 0:
+ default:
+ return $this->raiseError("config-get expects 1 or 2 parameters");
+ }
+
+ $reg = &$this->config->getRegistry();
+ $channel = isset($options['channel']) ? $options['channel'] : $this->config->get('default_channel');
+ if (!$reg->channelExists($channel)) {
+ return $this->raiseError('Channel "' . $channel . '" does not exist');
+ }
+
+ $channel = $reg->channelName($channel);
+ $this->ui->outputData($this->config->get($config_key, $layer, $channel), $command);
+ return true;
+ }
+
+ function doConfigSet($command, $options, $params)
+ {
+ // $param[0] -> a parameter to set
+ // $param[1] -> the value for the parameter
+ // $param[2] -> the layer
+ $failmsg = '';
+ if (count($params) < 2 || count($params) > 3) {
+ $failmsg .= "config-set expects 2 or 3 parameters";
+ return PEAR::raiseError($failmsg);
+ }
+
+ if (isset($params[2]) && ($error = $this->_checkLayer($params[2]))) {
+ $failmsg .= $error;
+ return PEAR::raiseError("config-set:$failmsg");
+ }
+
+ $channel = isset($options['channel']) ? $options['channel'] : $this->config->get('default_channel');
+ $reg = &$this->config->getRegistry();
+ if (!$reg->channelExists($channel)) {
+ return $this->raiseError('Channel "' . $channel . '" does not exist');
+ }
+
+ $channel = $reg->channelName($channel);
+ if ($params[0] == 'default_channel' && !$reg->channelExists($params[1])) {
+ return $this->raiseError('Channel "' . $params[1] . '" does not exist');
+ }
+
+ if ($params[0] == 'preferred_mirror'
+ && (
+ !$reg->mirrorExists($channel, $params[1]) &&
+ (!$reg->channelExists($params[1]) || $channel != $params[1])
+ )
+ ) {
+ $msg = 'Channel Mirror "' . $params[1] . '" does not exist';
+ $msg .= ' in your registry for channel "' . $channel . '".';
+ $msg .= "\n" . 'Attempt to run "pear channel-update ' . $channel .'"';
+ $msg .= ' if you believe this mirror should exist as you may';
+ $msg .= ' have outdated channel information.';
+ return $this->raiseError($msg);
+ }
+
+ if (count($params) == 2) {
+ array_push($params, 'user');
+ $layer = 'user';
+ } else {
+ $layer = $params[2];
+ }
+
+ array_push($params, $channel);
+ if (!call_user_func_array(array(&$this->config, 'set'), $params)) {
+ array_pop($params);
+ $failmsg = "config-set (" . implode(", ", $params) . ") failed, channel $channel";
+ } else {
+ $this->config->store($layer);
+ }
+
+ if ($failmsg) {
+ return $this->raiseError($failmsg);
+ }
+
+ $this->ui->outputData('config-set succeeded', $command);
+ return true;
+ }
+
+ function doConfigHelp($command, $options, $params)
+ {
+ if (empty($params)) {
+ $params = $this->config->getKeys();
+ }
+
+ $data['caption'] = "Config help" . ((count($params) == 1) ? " for $params[0]" : '');
+ $data['headline'] = array('Name', 'Type', 'Description');
+ $data['border'] = true;
+ foreach ($params as $name) {
+ $type = $this->config->getType($name);
+ $docs = $this->config->getDocs($name);
+ if ($type == 'set') {
+ $docs = rtrim($docs) . "\nValid set: " .
+ implode(' ', $this->config->getSetValues($name));
+ }
+
+ $data['data'][] = array($name, $type, $docs);
+ }
+
+ $this->ui->outputData($data, $command);
+ }
+
+ function doConfigCreate($command, $options, $params)
+ {
+ if (count($params) != 2) {
+ return PEAR::raiseError('config-create: must have 2 parameters, root path and ' .
+ 'filename to save as');
+ }
+
+ $root = $params[0];
+ // Clean up the DIRECTORY_SEPARATOR mess
+ $ds2 = DIRECTORY_SEPARATOR . DIRECTORY_SEPARATOR;
+ $root = preg_replace(array('!\\\\+!', '!/+!', "!$ds2+!"),
+ array('/', '/', '/'),
+ $root);
+ if ($root{0} != '/') {
+ if (!isset($options['windows'])) {
+ return PEAR::raiseError('Root directory must be an absolute path beginning ' .
+ 'with "/", was: "' . $root . '"');
+ }
+
+ if (!preg_match('/^[A-Za-z]:/', $root)) {
+ return PEAR::raiseError('Root directory must be an absolute path beginning ' .
+ 'with "\\" or "C:\\", was: "' . $root . '"');
+ }
+ }
+
+ $windows = isset($options['windows']);
+ if ($windows) {
+ $root = str_replace('/', '\\', $root);
+ }
+
+ if (!file_exists($params[1]) && !@touch($params[1])) {
+ return PEAR::raiseError('Could not create "' . $params[1] . '"');
+ }
+
+ $params[1] = realpath($params[1]);
+ $config = &new PEAR_Config($params[1], '#no#system#config#', false, false);
+ if ($root{strlen($root) - 1} == '/') {
+ $root = substr($root, 0, strlen($root) - 1);
+ }
+
+ $config->noRegistry();
+ $config->set('php_dir', $windows ? "$root\\pear\\php" : "$root/pear/php", 'user');
+ $config->set('data_dir', $windows ? "$root\\pear\\data" : "$root/pear/data");
+ $config->set('www_dir', $windows ? "$root\\pear\\www" : "$root/pear/www");
+ $config->set('cfg_dir', $windows ? "$root\\pear\\cfg" : "$root/pear/cfg");
+ $config->set('ext_dir', $windows ? "$root\\pear\\ext" : "$root/pear/ext");
+ $config->set('doc_dir', $windows ? "$root\\pear\\docs" : "$root/pear/docs");
+ $config->set('test_dir', $windows ? "$root\\pear\\tests" : "$root/pear/tests");
+ $config->set('cache_dir', $windows ? "$root\\pear\\cache" : "$root/pear/cache");
+ $config->set('download_dir', $windows ? "$root\\pear\\download" : "$root/pear/download");
+ $config->set('temp_dir', $windows ? "$root\\pear\\temp" : "$root/pear/temp");
+ $config->set('bin_dir', $windows ? "$root\\pear" : "$root/pear");
+ $config->writeConfigFile();
+ $this->_showConfig($config);
+ $this->ui->outputData('Successfully created default configuration file "' . $params[1] . '"',
+ $command);
+ }
+
+ function _showConfig(&$config)
+ {
+ $params = array('user');
+ $keys = $config->getKeys();
+ sort($keys);
+ $channel = 'pear.php.net';
+ $data = array('caption' => 'Configuration (channel ' . $channel . '):');
+ foreach ($keys as $key) {
+ $type = $config->getType($key);
+ $value = $config->get($key, 'user', $channel);
+ if ($type == 'password' && $value) {
+ $value = '********';
+ }
+
+ if ($value === false) {
+ $value = 'false';
+ } elseif ($value === true) {
+ $value = 'true';
+ }
+ $data['data'][$config->getGroup($key)][] =
+ array($config->getPrompt($key) , $key, $value);
+ }
+
+ foreach ($config->getLayers() as $layer) {
+ $data['data']['Config Files'][] =
+ array(ucfirst($layer) . ' Configuration File', 'Filename' ,
+ $config->getConfFile($layer));
+ }
+
+ $this->ui->outputData($data, 'config-show');
+ return true;
+ }
+
+ /**
+ * Checks if a layer is defined or not
+ *
+ * @param string $layer The layer to search for
+ * @return mixed False on no error or the error message
+ */
+ function _checkLayer($layer = null)
+ {
+ if (!empty($layer) && $layer != 'default') {
+ $layers = $this->config->getLayers();
+ if (!in_array($layer, $layers)) {
+ return " only the layers: \"" . implode('" or "', $layers) . "\" are supported";
+ }
+ }
+
+ return false;
+ }
+}<commands version="1.0">
+ <config-show>
+ <summary>Show All Settings</summary>
+ <function>doConfigShow</function>
+ <shortcut>csh</shortcut>
+ <options>
+ <channel>
+ <shortopt>c</shortopt>
+ <doc>show configuration variables for another channel</doc>
+ <arg>CHAN</arg>
+ </channel>
+ </options>
+ <doc>[layer]
+Displays all configuration values. An optional argument
+may be used to tell which configuration layer to display. Valid
+configuration layers are &quot;user&quot;, &quot;system&quot; and &quot;default&quot;. To display
+configurations for different channels, set the default_channel
+configuration variable and run config-show again.
+</doc>
+ </config-show>
+ <config-get>
+ <summary>Show One Setting</summary>
+ <function>doConfigGet</function>
+ <shortcut>cg</shortcut>
+ <options>
+ <channel>
+ <shortopt>c</shortopt>
+ <doc>show configuration variables for another channel</doc>
+ <arg>CHAN</arg>
+ </channel>
+ </options>
+ <doc>&lt;parameter&gt; [layer]
+Displays the value of one configuration parameter. The
+first argument is the name of the parameter, an optional second argument
+may be used to tell which configuration layer to look in. Valid configuration
+layers are &quot;user&quot;, &quot;system&quot; and &quot;default&quot;. If no layer is specified, a value
+will be picked from the first layer that defines the parameter, in the order
+just specified. The configuration value will be retrieved for the channel
+specified by the default_channel configuration variable.
+</doc>
+ </config-get>
+ <config-set>
+ <summary>Change Setting</summary>
+ <function>doConfigSet</function>
+ <shortcut>cs</shortcut>
+ <options>
+ <channel>
+ <shortopt>c</shortopt>
+ <doc>show configuration variables for another channel</doc>
+ <arg>CHAN</arg>
+ </channel>
+ </options>
+ <doc>&lt;parameter&gt; &lt;value&gt; [layer]
+Sets the value of one configuration parameter. The first argument is
+the name of the parameter, the second argument is the new value. Some
+parameters are subject to validation, and the command will fail with
+an error message if the new value does not make sense. An optional
+third argument may be used to specify in which layer to set the
+configuration parameter. The default layer is &quot;user&quot;. The
+configuration value will be set for the current channel, which
+is controlled by the default_channel configuration variable.
+</doc>
+ </config-set>
+ <config-help>
+ <summary>Show Information About Setting</summary>
+ <function>doConfigHelp</function>
+ <shortcut>ch</shortcut>
+ <options />
+ <doc>[parameter]
+Displays help for a configuration parameter. Without arguments it
+displays help for all configuration parameters.
+</doc>
+ </config-help>
+ <config-create>
+ <summary>Create a Default configuration file</summary>
+ <function>doConfigCreate</function>
+ <shortcut>coc</shortcut>
+ <options>
+ <windows>
+ <shortopt>w</shortopt>
+ <doc>create a config file for a windows install</doc>
+ </windows>
+ </options>
+ <doc>&lt;root path&gt; &lt;filename&gt;
+Create a default configuration file with all directory configuration
+variables set to subdirectories of &lt;root path&gt;, and save it as &lt;filename&gt;.
+This is useful especially for creating a configuration file for a remote
+PEAR installation (using the --remoteconfig option of install, upgrade,
+and uninstall).
+</doc>
+ </config-create>
+</commands><?php
+/**
* PEAR_Command_Install (install, upgrade, upgrade-all, uninstall, bundle, run-scripts commands)
*
* PHP versions 4 and 5
@@ -58611,7 +61295,7 @@ class PEAR_Command_Common extends PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version CVS: $Id: Install.php 311686 2011-06-01 02:35:01Z dufuz $
+ * @version CVS: $Id: Install.php 313023 2011-07-06 19:17:11Z dufuz $
* @link http://pear.php.net/package/PEAR
* @since File available since Release 0.1
*/
@@ -58631,7 +61315,7 @@ require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Command/Common.php';
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version Release: 1.10.0beta1
+ * @version Release: 1.9.4
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 0.1
*/
@@ -60143,6 +62827,4482 @@ Run post-installation scripts in package &lt;package&gt;, if any exist.
</run-scripts>
</commands><?php
/**
+ * PEAR_Command_Mirror (download-all command)
+ *
+ * PHP versions 4 and 5
+ *
+ * @category pear
+ * @package PEAR
+ * @author Alexander Merz <alexmerz@php.net>
+ * @copyright 1997-2009 The Authors
+ * @license http://opensource.org/licenses/bsd-license.php New BSD License
+ * @version CVS: $Id: Mirror.php 313023 2011-07-06 19:17:11Z dufuz $
+ * @link http://pear.php.net/package/PEAR
+ * @since File available since Release 1.2.0
+ */
+
+/**
+ * base class
+ */
+require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Command/Common.php';
+
+/**
+ * PEAR commands for providing file mirrors
+ *
+ * @category pear
+ * @package PEAR
+ * @author Alexander Merz <alexmerz@php.net>
+ * @copyright 1997-2009 The Authors
+ * @license http://opensource.org/licenses/bsd-license.php New BSD License
+ * @version Release: 1.9.4
+ * @link http://pear.php.net/package/PEAR
+ * @since Class available since Release 1.2.0
+ */
+class PEAR_Command_Mirror extends PEAR_Command_Common
+{
+ var $commands = array(
+ 'download-all' => array(
+ 'summary' => 'Downloads each available package from the default channel',
+ 'function' => 'doDownloadAll',
+ 'shortcut' => 'da',
+ 'options' => array(
+ 'channel' =>
+ array(
+ 'shortopt' => 'c',
+ 'doc' => 'specify a channel other than the default channel',
+ 'arg' => 'CHAN',
+ ),
+ ),
+ 'doc' => '
+Requests a list of available packages from the default channel ({config default_channel})
+and downloads them to current working directory. Note: only
+packages within preferred_state ({config preferred_state}) will be downloaded'
+ ),
+ );
+
+ /**
+ * PEAR_Command_Mirror constructor.
+ *
+ * @access public
+ * @param object PEAR_Frontend a reference to an frontend
+ * @param object PEAR_Config a reference to the configuration data
+ */
+ function PEAR_Command_Mirror(&$ui, &$config)
+ {
+ parent::PEAR_Command_Common($ui, $config);
+ }
+
+ /**
+ * For unit-testing
+ */
+ function &factory($a)
+ {
+ $a = &PEAR_Command::factory($a, $this->config);
+ return $a;
+ }
+
+ /**
+ * retrieves a list of avaible Packages from master server
+ * and downloads them
+ *
+ * @access public
+ * @param string $command the command
+ * @param array $options the command options before the command
+ * @param array $params the stuff after the command name
+ * @return bool true if succesful
+ * @throw PEAR_Error
+ */
+ function doDownloadAll($command, $options, $params)
+ {
+ $savechannel = $this->config->get('default_channel');
+ $reg = &$this->config->getRegistry();
+ $channel = isset($options['channel']) ? $options['channel'] :
+ $this->config->get('default_channel');
+ if (!$reg->channelExists($channel)) {
+ $this->config->set('default_channel', $savechannel);
+ return $this->raiseError('Channel "' . $channel . '" does not exist');
+ }
+ $this->config->set('default_channel', $channel);
+
+ $this->ui->outputData('Using Channel ' . $this->config->get('default_channel'));
+ $chan = $reg->getChannel($channel);
+ if (PEAR::isError($chan)) {
+ return $this->raiseError($chan);
+ }
+
+ if ($chan->supportsREST($this->config->get('preferred_mirror')) &&
+ $base = $chan->getBaseURL('REST1.0', $this->config->get('preferred_mirror'))) {
+ $rest = &$this->config->getREST('1.0', array());
+ $remoteInfo = array_flip($rest->listPackages($base, $channel));
+ }
+
+ if (PEAR::isError($remoteInfo)) {
+ return $remoteInfo;
+ }
+
+ $cmd = &$this->factory("download");
+ if (PEAR::isError($cmd)) {
+ return $cmd;
+ }
+
+ $this->ui->outputData('Using Preferred State of ' .
+ $this->config->get('preferred_state'));
+ $this->ui->outputData('Gathering release information, please wait...');
+
+ /**
+ * Error handling not necessary, because already done by
+ * the download command
+ */
+ PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
+ $err = $cmd->run('download', array('downloadonly' => true), array_keys($remoteInfo));
+ PEAR::staticPopErrorHandling();
+ $this->config->set('default_channel', $savechannel);
+ if (PEAR::isError($err)) {
+ $this->ui->outputData($err->getMessage());
+ }
+
+ return true;
+ }
+}<commands version="1.0">
+ <download-all>
+ <summary>Downloads each available package from the default channel</summary>
+ <function>doDownloadAll</function>
+ <shortcut>da</shortcut>
+ <options>
+ <channel>
+ <shortopt>c</shortopt>
+ <doc>specify a channel other than the default channel</doc>
+ <arg>CHAN</arg>
+ </channel>
+ </options>
+ <doc>
+Requests a list of available packages from the default channel ({config default_channel})
+and downloads them to current working directory. Note: only
+packages within preferred_state ({config preferred_state}) will be downloaded</doc>
+ </download-all>
+</commands><?php
+/**
+ * PEAR_Command_Package (package, package-validate, cvsdiff, cvstag, package-dependencies,
+ * sign, makerpm, convert commands)
+ *
+ * PHP versions 4 and 5
+ *
+ * @category pear
+ * @package PEAR
+ * @author Stig Bakken <ssb@php.net>
+ * @author Martin Jansen <mj@php.net>
+ * @author Greg Beaver <cellog@php.net>
+ * @copyright 1997-2009 The Authors
+ * @license http://opensource.org/licenses/bsd-license.php New BSD License
+ * @version CVS: $Id: Package.php 313024 2011-07-06 19:51:24Z dufuz $
+ * @link http://pear.php.net/package/PEAR
+ * @since File available since Release 0.1
+ */
+
+/**
+ * base class
+ */
+require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Command/Common.php';
+
+/**
+ * PEAR commands for login/logout
+ *
+ * @category pear
+ * @package PEAR
+ * @author Stig Bakken <ssb@php.net>
+ * @author Martin Jansen <mj@php.net>
+ * @author Greg Beaver <cellog@php.net>
+ * @copyright 1997-2009 The Authors
+ * @license http://opensource.org/licenses/bsd-license.php New BSD License
+ * @version Release: 1.10.0beta1
+ * @link http://pear.php.net/package/PEAR
+ * @since Class available since Release 0.1
+ */
+
+class PEAR_Command_Package extends PEAR_Command_Common
+{
+ var $commands = array(
+ 'package' => array(
+ 'summary' => 'Build Package',
+ 'function' => 'doPackage',
+ 'shortcut' => 'p',
+ 'options' => array(
+ 'nocompress' => array(
+ 'shortopt' => 'Z',
+ 'doc' => 'Do not gzip the package file'
+ ),
+ 'showname' => array(
+ 'shortopt' => 'n',
+ 'doc' => 'Print the name of the packaged file.',
+ ),
+ ),
+ 'doc' => '[descfile] [descfile2]
+Creates a PEAR package from its description file (usually called
+package.xml). If a second packagefile is passed in, then
+the packager will check to make sure that one is a package.xml
+version 1.0, and the other is a package.xml version 2.0. The
+package.xml version 1.0 will be saved as "package.xml" in the archive,
+and the other as "package2.xml" in the archive"
+'
+ ),
+ 'package-validate' => array(
+ 'summary' => 'Validate Package Consistency',
+ 'function' => 'doPackageValidate',
+ 'shortcut' => 'pv',
+ 'options' => array(),
+ 'doc' => '
+',
+ ),
+ 'cvsdiff' => array(
+ 'summary' => 'Run a "cvs diff" for all files in a package',
+ 'function' => 'doCvsDiff',
+ 'shortcut' => 'cd',
+ 'options' => array(
+ 'quiet' => array(
+ 'shortopt' => 'q',
+ 'doc' => 'Be quiet',
+ ),
+ 'reallyquiet' => array(
+ 'shortopt' => 'Q',
+ 'doc' => 'Be really quiet',
+ ),
+ 'date' => array(
+ 'shortopt' => 'D',
+ 'doc' => 'Diff against revision of DATE',
+ 'arg' => 'DATE',
+ ),
+ 'release' => array(
+ 'shortopt' => 'R',
+ 'doc' => 'Diff against tag for package release REL',
+ 'arg' => 'REL',
+ ),
+ 'revision' => array(
+ 'shortopt' => 'r',
+ 'doc' => 'Diff against revision REV',
+ 'arg' => 'REV',
+ ),
+ 'context' => array(
+ 'shortopt' => 'c',
+ 'doc' => 'Generate context diff',
+ ),
+ 'unified' => array(
+ 'shortopt' => 'u',
+ 'doc' => 'Generate unified diff',
+ ),
+ 'ignore-case' => array(
+ 'shortopt' => 'i',
+ 'doc' => 'Ignore case, consider upper- and lower-case letters equivalent',
+ ),
+ 'ignore-whitespace' => array(
+ 'shortopt' => 'b',
+ 'doc' => 'Ignore changes in amount of white space',
+ ),
+ 'ignore-blank-lines' => array(
+ 'shortopt' => 'B',
+ 'doc' => 'Ignore changes that insert or delete blank lines',
+ ),
+ 'brief' => array(
+ 'doc' => 'Report only whether the files differ, no details',
+ ),
+ 'dry-run' => array(
+ 'shortopt' => 'n',
+ 'doc' => 'Don\'t do anything, just pretend',
+ ),
+ ),
+ 'doc' => '<package.xml>
+Compares all the files in a package. Without any options, this
+command will compare the current code with the last checked-in code.
+Using the -r or -R option you may compare the current code with that
+of a specific release.
+',
+ ),
+ 'svntag' => array(
+ 'summary' => 'Set SVN Release Tag',
+ 'function' => 'doSvnTag',
+ 'shortcut' => 'sv',
+ 'options' => array(
+ 'quiet' => array(
+ 'shortopt' => 'q',
+ 'doc' => 'Be quiet',
+ ),
+ 'slide' => array(
+ 'shortopt' => 'F',
+ 'doc' => 'Move (slide) tag if it exists',
+ ),
+ 'delete' => array(
+ 'shortopt' => 'd',
+ 'doc' => 'Remove tag',
+ ),
+ 'dry-run' => array(
+ 'shortopt' => 'n',
+ 'doc' => 'Don\'t do anything, just pretend',
+ ),
+ ),
+ 'doc' => '<package.xml> [files...]
+ Sets a SVN tag on all files in a package. Use this command after you have
+ packaged a distribution tarball with the "package" command to tag what
+ revisions of what files were in that release. If need to fix something
+ after running svntag once, but before the tarball is released to the public,
+ use the "slide" option to move the release tag.
+
+ to include files (such as a second package.xml, or tests not included in the
+ release), pass them as additional parameters.
+ ',
+ ),
+ 'cvstag' => array(
+ 'summary' => 'Set CVS Release Tag',
+ 'function' => 'doCvsTag',
+ 'shortcut' => 'ct',
+ 'options' => array(
+ 'quiet' => array(
+ 'shortopt' => 'q',
+ 'doc' => 'Be quiet',
+ ),
+ 'reallyquiet' => array(
+ 'shortopt' => 'Q',
+ 'doc' => 'Be really quiet',
+ ),
+ 'slide' => array(
+ 'shortopt' => 'F',
+ 'doc' => 'Move (slide) tag if it exists',
+ ),
+ 'delete' => array(
+ 'shortopt' => 'd',
+ 'doc' => 'Remove tag',
+ ),
+ 'dry-run' => array(
+ 'shortopt' => 'n',
+ 'doc' => 'Don\'t do anything, just pretend',
+ ),
+ ),
+ 'doc' => '<package.xml> [files...]
+Sets a CVS tag on all files in a package. Use this command after you have
+packaged a distribution tarball with the "package" command to tag what
+revisions of what files were in that release. If need to fix something
+after running cvstag once, but before the tarball is released to the public,
+use the "slide" option to move the release tag.
+
+to include files (such as a second package.xml, or tests not included in the
+release), pass them as additional parameters.
+',
+ ),
+ 'package-dependencies' => array(
+ 'summary' => 'Show package dependencies',
+ 'function' => 'doPackageDependencies',
+ 'shortcut' => 'pd',
+ 'options' => array(),
+ 'doc' => '<package-file> or <package.xml> or <install-package-name>
+List all dependencies the package has.
+Can take a tgz / tar file, package.xml or a package name of an installed package.'
+ ),
+ 'sign' => array(
+ 'summary' => 'Sign a package distribution file',
+ 'function' => 'doSign',
+ 'shortcut' => 'si',
+ 'options' => array(
+ 'verbose' => array(
+ 'shortopt' => 'v',
+ 'doc' => 'Display GnuPG output',
+ ),
+ ),
+ 'doc' => '<package-file>
+Signs a package distribution (.tar or .tgz) file with GnuPG.',
+ ),
+ 'makerpm' => array(
+ 'summary' => 'Builds an RPM spec file from a PEAR package',
+ 'function' => 'doMakeRPM',
+ 'shortcut' => 'rpm',
+ 'options' => array(
+ 'spec-template' => array(
+ 'shortopt' => 't',
+ 'arg' => 'FILE',
+ 'doc' => 'Use FILE as RPM spec file template'
+ ),
+ 'rpm-pkgname' => array(
+ 'shortopt' => 'p',
+ 'arg' => 'FORMAT',
+ 'doc' => 'Use FORMAT as format string for RPM package name, %s is replaced
+by the PEAR package name, defaults to "PEAR::%s".',
+ ),
+ ),
+ 'doc' => '<package-file>
+
+Creates an RPM .spec file for wrapping a PEAR package inside an RPM
+package. Intended to be used from the SPECS directory, with the PEAR
+package tarball in the SOURCES directory:
+
+$ pear makerpm ../SOURCES/Net_Socket-1.0.tgz
+Wrote RPM spec file PEAR::Net_Geo-1.0.spec
+$ rpm -bb PEAR::Net_Socket-1.0.spec
+...
+Wrote: /usr/src/redhat/RPMS/i386/PEAR::Net_Socket-1.0-1.i386.rpm
+',
+ ),
+ 'convert' => array(
+ 'summary' => 'Convert a package.xml 1.0 to package.xml 2.0 format',
+ 'function' => 'doConvert',
+ 'shortcut' => 'c2',
+ 'options' => array(
+ 'flat' => array(
+ 'shortopt' => 'f',
+ 'doc' => 'do not beautify the filelist.',
+ ),
+ ),
+ 'doc' => '[descfile] [descfile2]
+Converts a package.xml in 1.0 format into a package.xml
+in 2.0 format. The new file will be named package2.xml by default,
+and package.xml will be used as the old file by default.
+This is not the most intelligent conversion, and should only be
+used for automated conversion or learning the format.
+'
+ ),
+ );
+
+ var $output;
+
+ /**
+ * PEAR_Command_Package constructor.
+ *
+ * @access public
+ */
+ function PEAR_Command_Package(&$ui, &$config)
+ {
+ parent::PEAR_Command_Common($ui, $config);
+ }
+
+ function _displayValidationResults($err, $warn, $strict = false)
+ {
+ foreach ($err as $e) {
+ $this->output .= "Error: $e\n";
+ }
+ foreach ($warn as $w) {
+ $this->output .= "Warning: $w\n";
+ }
+ $this->output .= sprintf('Validation: %d error(s), %d warning(s)'."\n",
+ sizeof($err), sizeof($warn));
+ if ($strict && count($err) > 0) {
+ $this->output .= "Fix these errors and try again.";
+ return false;
+ }
+ return true;
+ }
+
+ function &getPackager()
+ {
+ if (!class_exists('PEAR_Packager')) {
+ require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Packager.php';
+ }
+ $a = &new PEAR_Packager;
+ return $a;
+ }
+
+ function &getPackageFile($config, $debug = false)
+ {
+ if (!class_exists('PEAR_Common')) {
+ require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Common.php';
+ }
+ if (!class_exists('PEAR_PackageFile')) {
+ require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/PackageFile.php';
+ }
+ $a = &new PEAR_PackageFile($config, $debug);
+ $common = new PEAR_Common;
+ $common->ui = $this->ui;
+ $a->setLogger($common);
+ return $a;
+ }
+
+ function doPackage($command, $options, $params)
+ {
+ $this->output = '';
+ $pkginfofile = isset($params[0]) ? $params[0] : 'package.xml';
+ $pkg2 = isset($params[1]) ? $params[1] : null;
+ if (!$pkg2 && !isset($params[0]) && file_exists('package2.xml')) {
+ $pkg2 = 'package2.xml';
+ }
+
+ $packager = &$this->getPackager();
+ $compress = empty($options['nocompress']) ? true : false;
+ $result = $packager->package($pkginfofile, $compress, $pkg2);
+ if (PEAR::isError($result)) {
+ return $this->raiseError($result);
+ }
+
+ // Don't want output, only the package file name just created
+ if (isset($options['showname'])) {
+ $this->output = $result;
+ }
+
+ if ($this->output) {
+ $this->ui->outputData($this->output, $command);
+ }
+
+ return true;
+ }
+
+ function doPackageValidate($command, $options, $params)
+ {
+ $this->output = '';
+ if (count($params) < 1) {
+ $params[0] = 'package.xml';
+ }
+
+ $obj = &$this->getPackageFile($this->config, $this->_debug);
+ $obj->rawReturn();
+ PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
+ $info = $obj->fromTgzFile($params[0], PEAR_VALIDATE_NORMAL);
+ if (PEAR::isError($info)) {
+ $info = $obj->fromPackageFile($params[0], PEAR_VALIDATE_NORMAL);
+ } else {
+ $archive = $info->getArchiveFile();
+ $tar = &new Archive_Tar($archive);
+ $tar->extract(dirname($info->getPackageFile()));
+ $info->setPackageFile(dirname($info->getPackageFile()) . DIRECTORY_SEPARATOR .
+ $info->getPackage() . '-' . $info->getVersion() . DIRECTORY_SEPARATOR .
+ basename($info->getPackageFile()));
+ }
+
+ PEAR::staticPopErrorHandling();
+ if (PEAR::isError($info)) {
+ return $this->raiseError($info);
+ }
+
+ $valid = false;
+ if ($info->getPackagexmlVersion() == '2.0') {
+ if ($valid = $info->validate(PEAR_VALIDATE_NORMAL)) {
+ $info->flattenFileList();
+ $valid = $info->validate(PEAR_VALIDATE_PACKAGING);
+ }
+ } else {
+ $valid = $info->validate(PEAR_VALIDATE_PACKAGING);
+ }
+
+ $err = $warn = array();
+ if ($errors = $info->getValidationWarnings()) {
+ foreach ($errors as $error) {
+ if ($error['level'] == 'warning') {
+ $warn[] = $error['message'];
+ } else {
+ $err[] = $error['message'];
+ }
+ }
+ }
+
+ $this->_displayValidationResults($err, $warn);
+ $this->ui->outputData($this->output, $command);
+ return true;
+ }
+
+ function doSvnTag($command, $options, $params)
+ {
+ $this->output = '';
+ $_cmd = $command;
+ if (count($params) < 1) {
+ $help = $this->getHelp($command);
+ return $this->raiseError("$command: missing parameter: $help[0]");
+ }
+
+ $packageFile = realpath($params[0]);
+ $dir = dirname($packageFile);
+ $dir = substr($dir, strrpos($dir, DIRECTORY_SEPARATOR) + 1);
+ $obj = &$this->getPackageFile($this->config, $this->_debug);
+ $info = $obj->fromAnyFile($packageFile, PEAR_VALIDATE_NORMAL);
+ if (PEAR::isError($info)) {
+ return $this->raiseError($info);
+ }
+
+ $err = $warn = array();
+ if (!$info->validate()) {
+ foreach ($info->getValidationWarnings() as $error) {
+ if ($error['level'] == 'warning') {
+ $warn[] = $error['message'];
+ } else {
+ $err[] = $error['message'];
+ }
+ }
+ }
+
+ if (!$this->_displayValidationResults($err, $warn, true)) {
+ $this->ui->outputData($this->output, $command);
+ return $this->raiseError('SVN tag failed');
+ }
+
+ $version = $info->getVersion();
+ $package = $info->getName();
+ $svntag = "$package-$version";
+
+ if (isset($options['delete'])) {
+ return $this->_svnRemoveTag($version, $package, $svntag, $packageFile, $options);
+ }
+
+ $path = $this->_svnFindPath($packageFile);
+
+ // Check if there are any modified files
+ $fp = popen('svn st --xml ' . dirname($packageFile), "r");
+ $out = '';
+ while ($line = fgets($fp, 1024)) {
+ $out .= rtrim($line)."\n";
+ }
+ pclose($fp);
+
+ if (!isset($options['quiet']) && strpos($out, 'item="modified"')) {
+ $params = array(array(
+ 'name' => 'modified',
+ 'type' => 'yesno',
+ 'default' => 'no',
+ 'prompt' => 'You have files in your SVN checkout (' . $path['from'] . ') that have been modified but not commited, do you still want to tag ' . $version . '?',
+ ));
+ $answers = $this->ui->confirmDialog($params);
+
+ if (!in_array($answers['modified'], array('y', 'yes', 'on', '1'))) {
+ return true;
+ }
+ }
+
+ if (isset($options['slide'])) {
+ $this->_svnRemoveTag($version, $package, $svntag, $packageFile, $options);
+ }
+
+ // Check if tag already exists
+ $releaseTag = $path['local']['base'] . 'tags' . DIRECTORY_SEPARATOR . $svntag;
+ $existsCommand = 'svn ls ' . $path['base'] . 'tags/';
+
+ $fp = popen($existsCommand, "r");
+ $out = '';
+ while ($line = fgets($fp, 1024)) {
+ $out .= rtrim($line)."\n";
+ }
+ pclose($fp);
+
+ if (in_array($svntag . DIRECTORY_SEPARATOR, explode("\n", $out))) {
+ $this->ui->outputData($this->output, $command);
+ return $this->raiseError('SVN tag ' . $svntag . ' for ' . $package . ' already exists.');
+ } elseif (file_exists($path['local']['base'] . 'tags') === false) {
+ return $this->raiseError('Can not locate the tags directory at ' . $path['local']['base'] . 'tags');
+ } elseif (is_writeable($path['local']['base'] . 'tags') === false) {
+ return $this->raiseError('Can not write to the tag directory at ' . $path['local']['base'] . 'tags');
+ } else {
+ $makeCommand = 'svn mkdir ' . $releaseTag;
+ $this->output .= "+ $makeCommand\n";
+ if (empty($options['dry-run'])) {
+ // We need to create the tag dir.
+ $fp = popen($makeCommand, "r");
+ $out = '';
+ while ($line = fgets($fp, 1024)) {
+ $out .= rtrim($line)."\n";
+ }
+ pclose($fp);
+ $this->output .= "$out\n";
+ }
+ }
+
+ $command = 'svn';
+ if (isset($options['quiet'])) {
+ $command .= ' -q';
+ }
+
+ $command .= ' copy --parents ';
+
+ $dir = dirname($packageFile);
+ $dir = substr($dir, strrpos($dir, DIRECTORY_SEPARATOR) + 1);
+ $files = array_keys($info->getFilelist());
+ if (!in_array(basename($packageFile), $files)) {
+ $files[] = basename($packageFile);
+ }
+
+ array_shift($params);
+ if (count($params)) {
+ // add in additional files to be tagged (package files and such)
+ $files = array_merge($files, $params);
+ }
+
+ $commands = array();
+ foreach ($files as $file) {
+ if (!file_exists($file)) {
+ $file = $dir . DIRECTORY_SEPARATOR . $file;
+ }
+ $commands[] = $command . ' ' . escapeshellarg($file) . ' ' .
+ escapeshellarg($releaseTag . DIRECTORY_SEPARATOR . $file);
+ }
+
+ $this->output .= implode("\n", $commands) . "\n";
+ if (empty($options['dry-run'])) {
+ foreach ($commands as $command) {
+ $fp = popen($command, "r");
+ while ($line = fgets($fp, 1024)) {
+ $this->output .= rtrim($line)."\n";
+ }
+ pclose($fp);
+ }
+ }
+
+ $command = 'svn ci -m "Tagging the ' . $version . ' release" ' . $releaseTag . "\n";
+ $this->output .= "+ $command\n";
+ if (empty($options['dry-run'])) {
+ $fp = popen($command, "r");
+ while ($line = fgets($fp, 1024)) {
+ $this->output .= rtrim($line)."\n";
+ }
+ pclose($fp);
+ }
+
+ $this->ui->outputData($this->output, $_cmd);
+ return true;
+ }
+
+ function _svnFindPath($file)
+ {
+ $xml = '';
+ $command = "svn info --xml $file";
+ $fp = popen($command, "r");
+ while ($line = fgets($fp, 1024)) {
+ $xml .= rtrim($line)."\n";
+ }
+ pclose($fp);
+ $url_tag = strpos($xml, '<url>');
+ $url = substr($xml, $url_tag + 5, strpos($xml, '</url>', $url_tag + 5) - ($url_tag + 5));
+
+ $path = array();
+ $path['from'] = substr($url, 0, strrpos($url, '/'));
+ $path['base'] = substr($path['from'], 0, strrpos($path['from'], '/') + 1);
+
+ // Figure out the local paths - see http://pear.php.net/bugs/17463
+ $pos = strpos($file, DIRECTORY_SEPARATOR . 'trunk' . DIRECTORY_SEPARATOR);
+ if ($pos === false) {
+ $pos = strpos($file, DIRECTORY_SEPARATOR . 'branches' . DIRECTORY_SEPARATOR);
+ }
+ $path['local']['base'] = substr($file, 0, $pos + 1);
+
+ return $path;
+ }
+
+ function _svnRemoveTag($version, $package, $tag, $packageFile, $options)
+ {
+ $command = 'svn';
+
+ if (isset($options['quiet'])) {
+ $command .= ' -q';
+ }
+
+ $command .= ' remove';
+ $command .= ' -m "Removing tag for the ' . $version . ' release."';
+
+ $path = $this->_svnFindPath($packageFile);
+ $command .= ' ' . $path['base'] . 'tags/' . $tag;
+
+
+ if ($this->config->get('verbose') > 1) {
+ $this->output .= "+ $command\n";
+ }
+
+ $this->output .= "+ $command\n";
+ if (empty($options['dry-run'])) {
+ $fp = popen($command, "r");
+ while ($line = fgets($fp, 1024)) {
+ $this->output .= rtrim($line)."\n";
+ }
+ pclose($fp);
+ }
+
+ $this->ui->outputData($this->output, $command);
+ return true;
+ }
+
+ function doCvsTag($command, $options, $params)
+ {
+ $this->output = '';
+ $_cmd = $command;
+ if (count($params) < 1) {
+ $help = $this->getHelp($command);
+ return $this->raiseError("$command: missing parameter: $help[0]");
+ }
+
+ $packageFile = realpath($params[0]);
+ $obj = &$this->getPackageFile($this->config, $this->_debug);
+ $info = $obj->fromAnyFile($packageFile, PEAR_VALIDATE_NORMAL);
+ if (PEAR::isError($info)) {
+ return $this->raiseError($info);
+ }
+
+ $err = $warn = array();
+ if (!$info->validate()) {
+ foreach ($info->getValidationWarnings() as $error) {
+ if ($error['level'] == 'warning') {
+ $warn[] = $error['message'];
+ } else {
+ $err[] = $error['message'];
+ }
+ }
+ }
+
+ if (!$this->_displayValidationResults($err, $warn, true)) {
+ $this->ui->outputData($this->output, $command);
+ return $this->raiseError('CVS tag failed');
+ }
+
+ $version = $info->getVersion();
+ $cvsversion = preg_replace('/[^a-z0-9]/i', '_', $version);
+ $cvstag = "RELEASE_$cvsversion";
+ $files = array_keys($info->getFilelist());
+ $command = 'cvs';
+ if (isset($options['quiet'])) {
+ $command .= ' -q';
+ }
+
+ if (isset($options['reallyquiet'])) {
+ $command .= ' -Q';
+ }
+
+ $command .= ' tag';
+ if (isset($options['slide'])) {
+ $command .= ' -F';
+ }
+
+ if (isset($options['delete'])) {
+ $command .= ' -d';
+ }
+
+ $command .= ' ' . $cvstag . ' ' . escapeshellarg($params[0]);
+ array_shift($params);
+ if (count($params)) {
+ // add in additional files to be tagged
+ $files = array_merge($files, $params);
+ }
+
+ $dir = dirname($packageFile);
+ $dir = substr($dir, strrpos($dir, '/') + 1);
+ foreach ($files as $file) {
+ if (!file_exists($file)) {
+ $file = $dir . DIRECTORY_SEPARATOR . $file;
+ }
+ $command .= ' ' . escapeshellarg($file);
+ }
+
+ if ($this->config->get('verbose') > 1) {
+ $this->output .= "+ $command\n";
+ }
+
+ $this->output .= "+ $command\n";
+ if (empty($options['dry-run'])) {
+ $fp = popen($command, "r");
+ while ($line = fgets($fp, 1024)) {
+ $this->output .= rtrim($line)."\n";
+ }
+ pclose($fp);
+ }
+
+ $this->ui->outputData($this->output, $_cmd);
+ return true;
+ }
+
+ function doCvsDiff($command, $options, $params)
+ {
+ $this->output = '';
+ if (sizeof($params) < 1) {
+ $help = $this->getHelp($command);
+ return $this->raiseError("$command: missing parameter: $help[0]");
+ }
+
+ $file = realpath($params[0]);
+ $obj = &$this->getPackageFile($this->config, $this->_debug);
+ $info = $obj->fromAnyFile($file, PEAR_VALIDATE_NORMAL);
+ if (PEAR::isError($info)) {
+ return $this->raiseError($info);
+ }
+
+ $err = $warn = array();
+ if (!$info->validate()) {
+ foreach ($info->getValidationWarnings() as $error) {
+ if ($error['level'] == 'warning') {
+ $warn[] = $error['message'];
+ } else {
+ $err[] = $error['message'];
+ }
+ }
+ }
+
+ if (!$this->_displayValidationResults($err, $warn, true)) {
+ $this->ui->outputData($this->output, $command);
+ return $this->raiseError('CVS diff failed');
+ }
+
+ $info1 = $info->getFilelist();
+ $files = $info1;
+ $cmd = "cvs";
+ if (isset($options['quiet'])) {
+ $cmd .= ' -q';
+ unset($options['quiet']);
+ }
+
+ if (isset($options['reallyquiet'])) {
+ $cmd .= ' -Q';
+ unset($options['reallyquiet']);
+ }
+
+ if (isset($options['release'])) {
+ $cvsversion = preg_replace('/[^a-z0-9]/i', '_', $options['release']);
+ $cvstag = "RELEASE_$cvsversion";
+ $options['revision'] = $cvstag;
+ unset($options['release']);
+ }
+
+ $execute = true;
+ if (isset($options['dry-run'])) {
+ $execute = false;
+ unset($options['dry-run']);
+ }
+
+ $cmd .= ' diff';
+ // the rest of the options are passed right on to "cvs diff"
+ foreach ($options as $option => $optarg) {
+ $arg = $short = false;
+ if (isset($this->commands[$command]['options'][$option])) {
+ $arg = $this->commands[$command]['options'][$option]['arg'];
+ $short = $this->commands[$command]['options'][$option]['shortopt'];
+ }
+ $cmd .= $short ? " -$short" : " --$option";
+ if ($arg && $optarg) {
+ $cmd .= ($short ? '' : '=') . escapeshellarg($optarg);
+ }
+ }
+
+ foreach ($files as $file) {
+ $cmd .= ' ' . escapeshellarg($file['name']);
+ }
+
+ if ($this->config->get('verbose') > 1) {
+ $this->output .= "+ $cmd\n";
+ }
+
+ if ($execute) {
+ $fp = popen($cmd, "r");
+ while ($line = fgets($fp, 1024)) {
+ $this->output .= rtrim($line)."\n";
+ }
+ pclose($fp);
+ }
+
+ $this->ui->outputData($this->output, $command);
+ return true;
+ }
+
+ function doPackageDependencies($command, $options, $params)
+ {
+ // $params[0] -> the PEAR package to list its information
+ if (count($params) !== 1) {
+ return $this->raiseError("bad parameter(s), try \"help $command\"");
+ }
+
+ $obj = &$this->getPackageFile($this->config, $this->_debug);
+ if (is_file($params[0]) || strpos($params[0], '.xml') > 0) {
+ $info = $obj->fromAnyFile($params[0], PEAR_VALIDATE_NORMAL);
+ } else {
+ $reg = $this->config->getRegistry();
+ $info = $obj->fromArray($reg->packageInfo($params[0]));
+ }
+
+ if (PEAR::isError($info)) {
+ return $this->raiseError($info);
+ }
+
+ $deps = $info->getDeps();
+ if (is_array($deps)) {
+ if ($info->getPackagexmlVersion() == '1.0') {
+ $data = array(
+ 'caption' => 'Dependencies for pear/' . $info->getPackage(),
+ 'border' => true,
+ 'headline' => array("Required?", "Type", "Name", "Relation", "Version"),
+ );
+
+ foreach ($deps as $d) {
+ if (isset($d['optional'])) {
+ if ($d['optional'] == 'yes') {
+ $req = 'No';
+ } else {
+ $req = 'Yes';
+ }
+ } else {
+ $req = 'Yes';
+ }
+
+ if (isset($this->_deps_rel_trans[$d['rel']])) {
+ $rel = $this->_deps_rel_trans[$d['rel']];
+ } else {
+ $rel = $d['rel'];
+ }
+
+ if (isset($this->_deps_type_trans[$d['type']])) {
+ $type = ucfirst($this->_deps_type_trans[$d['type']]);
+ } else {
+ $type = $d['type'];
+ }
+
+ if (isset($d['name'])) {
+ $name = $d['name'];
+ } else {
+ $name = '';
+ }
+
+ if (isset($d['version'])) {
+ $version = $d['version'];
+ } else {
+ $version = '';
+ }
+
+ $data['data'][] = array($req, $type, $name, $rel, $version);
+ }
+ } else { // package.xml 2.0 dependencies display
+ require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Dependency2.php';
+ $deps = $info->getDependencies();
+ $reg = &$this->config->getRegistry();
+ if (is_array($deps)) {
+ $d = new PEAR_Dependency2($this->config, array(), '');
+ $data = array(
+ 'caption' => 'Dependencies for ' . $info->getPackage(),
+ 'border' => true,
+ 'headline' => array("Required?", "Type", "Name", 'Versioning', 'Group'),
+ );
+ foreach ($deps as $type => $subd) {
+ $req = ($type == 'required') ? 'Yes' : 'No';
+ if ($type == 'group') {
+ $group = $subd['attribs']['name'];
+ } else {
+ $group = '';
+ }
+
+ if (!isset($subd[0])) {
+ $subd = array($subd);
+ }
+
+ foreach ($subd as $groupa) {
+ foreach ($groupa as $deptype => $depinfo) {
+ if ($deptype == 'attribs') {
+ continue;
+ }
+
+ if ($deptype == 'pearinstaller') {
+ $deptype = 'pear Installer';
+ }
+
+ if (!isset($depinfo[0])) {
+ $depinfo = array($depinfo);
+ }
+
+ foreach ($depinfo as $inf) {
+ $name = '';
+ if (isset($inf['channel'])) {
+ $alias = $reg->channelAlias($inf['channel']);
+ if (!$alias) {
+ $alias = '(channel?) ' .$inf['channel'];
+ }
+ $name = $alias . '/';
+
+ }
+ if (isset($inf['name'])) {
+ $name .= $inf['name'];
+ } elseif (isset($inf['pattern'])) {
+ $name .= $inf['pattern'];
+ } else {
+ $name .= '';
+ }
+
+ if (isset($inf['uri'])) {
+ $name .= ' [' . $inf['uri'] . ']';
+ }
+
+ if (isset($inf['conflicts'])) {
+ $ver = 'conflicts';
+ } else {
+ $ver = $d->_getExtraString($inf);
+ }
+
+ $data['data'][] = array($req, ucfirst($deptype), $name,
+ $ver, $group);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ $this->ui->outputData($data, $command);
+ return true;
+ }
+
+ // Fallback
+ $this->ui->outputData("This package does not have any dependencies.", $command);
+ }
+
+ function doSign($command, $options, $params)
+ {
+ // should move most of this code into PEAR_Packager
+ // so it'll be easy to implement "pear package --sign"
+ if (count($params) !== 1) {
+ return $this->raiseError("bad parameter(s), try \"help $command\"");
+ }
+
+ require_once 'phar://install-pear-nozlib.phar/' . 'System.php';
+ require_once 'phar://install-pear-nozlib.phar/' . 'Archive/Tar.php';
+
+ if (!file_exists($params[0])) {
+ return $this->raiseError("file does not exist: $params[0]");
+ }
+
+ $obj = $this->getPackageFile($this->config, $this->_debug);
+ $info = $obj->fromTgzFile($params[0], PEAR_VALIDATE_NORMAL);
+ if (PEAR::isError($info)) {
+ return $this->raiseError($info);
+ }
+
+ $tar = new Archive_Tar($params[0]);
+
+ $tmpdir = $this->config->get('temp_dir');
+ $tmpdir = System::mktemp(' -t "' . $tmpdir . '" -d pearsign');
+ if (!$tar->extractList('package2.xml package.xml package.sig', $tmpdir)) {
+ return $this->raiseError("failed to extract tar file");
+ }
+
+ if (file_exists("$tmpdir/package.sig")) {
+ return $this->raiseError("package already signed");
+ }
+
+ $packagexml = 'package.xml';
+ if (file_exists("$tmpdir/package2.xml")) {
+ $packagexml = 'package2.xml';
+ }
+
+ if (file_exists("$tmpdir/package.sig")) {
+ unlink("$tmpdir/package.sig");
+ }
+
+ if (!file_exists("$tmpdir/$packagexml")) {
+ return $this->raiseError("Extracted file $tmpdir/$packagexml not found.");
+ }
+
+ $input = $this->ui->userDialog($command,
+ array('GnuPG Passphrase'),
+ array('password'));
+ if (!isset($input[0])) {
+ //use empty passphrase
+ $input[0] = '';
+ }
+
+ $devnull = (isset($options['verbose'])) ? '' : ' 2>/dev/null';
+ $gpg = popen("gpg --batch --passphrase-fd 0 --armor --detach-sign --output $tmpdir/package.sig $tmpdir/$packagexml" . $devnull, "w");
+ if (!$gpg) {
+ return $this->raiseError("gpg command failed");
+ }
+
+ fwrite($gpg, "$input[0]\n");
+ if (pclose($gpg) || !file_exists("$tmpdir/package.sig")) {
+ return $this->raiseError("gpg sign failed");
+ }
+
+ if (!$tar->addModify("$tmpdir/package.sig", '', $tmpdir)) {
+ return $this->raiseError('failed adding signature to file');
+ }
+
+ $this->ui->outputData("Package signed.", $command);
+ return true;
+ }
+
+ /**
+ * For unit testing purposes
+ */
+ function &getInstaller(&$ui)
+ {
+ if (!class_exists('PEAR_Installer')) {
+ require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Installer.php';
+ }
+ $a = &new PEAR_Installer($ui);
+ return $a;
+ }
+
+ /**
+ * For unit testing purposes
+ */
+ function &getCommandPackaging(&$ui, &$config)
+ {
+ if (!class_exists('PEAR_Command_Packaging')) {
+ if ($fp = @fopen('PEAR/Command/Packaging.php', 'r', true)) {
+ fclose($fp);
+ include_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Command/Packaging.php';
+ }
+ }
+
+ if (class_exists('PEAR_Command_Packaging')) {
+ $a = &new PEAR_Command_Packaging($ui, $config);
+ } else {
+ $a = null;
+ }
+
+ return $a;
+ }
+
+ function doMakeRPM($command, $options, $params)
+ {
+
+ // Check to see if PEAR_Command_Packaging is installed, and
+ // transparently switch to use the "make-rpm-spec" command from it
+ // instead, if it does. Otherwise, continue to use the old version
+ // of "makerpm" supplied with this package (PEAR).
+ $packaging_cmd = $this->getCommandPackaging($this->ui, $this->config);
+ if ($packaging_cmd !== null) {
+ $this->ui->outputData('PEAR_Command_Packaging is installed; using '.
+ 'newer "make-rpm-spec" command instead');
+ return $packaging_cmd->run('make-rpm-spec', $options, $params);
+ }
+
+ $this->ui->outputData('WARNING: "pear makerpm" is no longer available; an '.
+ 'improved version is available via "pear make-rpm-spec", which '.
+ 'is available by installing PEAR_Command_Packaging');
+ return true;
+ }
+
+ function doConvert($command, $options, $params)
+ {
+ $packagexml = isset($params[0]) ? $params[0] : 'package.xml';
+ $newpackagexml = isset($params[1]) ? $params[1] : dirname($packagexml) .
+ DIRECTORY_SEPARATOR . 'package2.xml';
+ $pkg = &$this->getPackageFile($this->config, $this->_debug);
+ PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
+ $pf = $pkg->fromPackageFile($packagexml, PEAR_VALIDATE_NORMAL);
+ PEAR::staticPopErrorHandling();
+ if (PEAR::isError($pf)) {
+ if (is_array($pf->getUserInfo())) {
+ foreach ($pf->getUserInfo() as $warning) {
+ $this->ui->outputData($warning['message']);
+ }
+ }
+ return $this->raiseError($pf);
+ }
+
+ if (is_a($pf, 'PEAR_PackageFile_v2')) {
+ $this->ui->outputData($packagexml . ' is already a package.xml version 2.0');
+ return true;
+ }
+
+ $gen = &$pf->getDefaultGenerator();
+ $newpf = &$gen->toV2();
+ $newpf->setPackagefile($newpackagexml);
+ $gen = &$newpf->getDefaultGenerator();
+ PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
+ $state = (isset($options['flat']) ? PEAR_VALIDATE_PACKAGING : PEAR_VALIDATE_NORMAL);
+ $saved = $gen->toPackageFile(dirname($newpackagexml), $state, basename($newpackagexml));
+ PEAR::staticPopErrorHandling();
+ if (PEAR::isError($saved)) {
+ if (is_array($saved->getUserInfo())) {
+ foreach ($saved->getUserInfo() as $warning) {
+ $this->ui->outputData($warning['message']);
+ }
+ }
+
+ $this->ui->outputData($saved->getMessage());
+ return true;
+ }
+
+ $this->ui->outputData('Wrote new version 2.0 package.xml to "' . $saved . '"');
+ return true;
+ }
+}<commands version="1.0">
+ <package>
+ <summary>Build Package</summary>
+ <function>doPackage</function>
+ <shortcut>p</shortcut>
+ <options>
+ <nocompress>
+ <shortopt>Z</shortopt>
+ <doc>Do not gzip the package file</doc>
+ </nocompress>
+ <showname>
+ <shortopt>n</shortopt>
+ <doc>Print the name of the packaged file.</doc>
+ </showname>
+ </options>
+ <doc>[descfile] [descfile2]
+Creates a PEAR package from its description file (usually called
+package.xml). If a second packagefile is passed in, then
+the packager will check to make sure that one is a package.xml
+version 1.0, and the other is a package.xml version 2.0. The
+package.xml version 1.0 will be saved as &quot;package.xml&quot; in the archive,
+and the other as &quot;package2.xml&quot; in the archive&quot;
+</doc>
+ </package>
+ <package-validate>
+ <summary>Validate Package Consistency</summary>
+ <function>doPackageValidate</function>
+ <shortcut>pv</shortcut>
+ <options />
+ <doc>
+</doc>
+ </package-validate>
+ <cvsdiff>
+ <summary>Run a &quot;cvs diff&quot; for all files in a package</summary>
+ <function>doCvsDiff</function>
+ <shortcut>cd</shortcut>
+ <options>
+ <quiet>
+ <shortopt>q</shortopt>
+ <doc>Be quiet</doc>
+ </quiet>
+ <reallyquiet>
+ <shortopt>Q</shortopt>
+ <doc>Be really quiet</doc>
+ </reallyquiet>
+ <date>
+ <shortopt>D</shortopt>
+ <doc>Diff against revision of DATE</doc>
+ <arg>DATE</arg>
+ </date>
+ <release>
+ <shortopt>R</shortopt>
+ <doc>Diff against tag for package release REL</doc>
+ <arg>REL</arg>
+ </release>
+ <revision>
+ <shortopt>r</shortopt>
+ <doc>Diff against revision REV</doc>
+ <arg>REV</arg>
+ </revision>
+ <context>
+ <shortopt>c</shortopt>
+ <doc>Generate context diff</doc>
+ </context>
+ <unified>
+ <shortopt>u</shortopt>
+ <doc>Generate unified diff</doc>
+ </unified>
+ <ignore-case>
+ <shortopt>i</shortopt>
+ <doc>Ignore case, consider upper- and lower-case letters equivalent</doc>
+ </ignore-case>
+ <ignore-whitespace>
+ <shortopt>b</shortopt>
+ <doc>Ignore changes in amount of white space</doc>
+ </ignore-whitespace>
+ <ignore-blank-lines>
+ <shortopt>B</shortopt>
+ <doc>Ignore changes that insert or delete blank lines</doc>
+ </ignore-blank-lines>
+ <brief>
+ <shortopt></shortopt>
+ <doc>Report only whether the files differ, no details</doc>
+ </brief>
+ <dry-run>
+ <shortopt>n</shortopt>
+ <doc>Don&#039;t do anything, just pretend</doc>
+ </dry-run>
+ </options>
+ <doc>&lt;package.xml&gt;
+Compares all the files in a package. Without any options, this
+command will compare the current code with the last checked-in code.
+Using the -r or -R option you may compare the current code with that
+of a specific release.
+</doc>
+ </cvsdiff>
+ <svntag>
+ <summary>Set SVN Release Tag</summary>
+ <function>doSvnTag</function>
+ <shortcut>sv</shortcut>
+ <options>
+ <quiet>
+ <shortopt>q</shortopt>
+ <doc>Be quiet</doc>
+ </quiet>
+ <slide>
+ <shortopt>F</shortopt>
+ <doc>Move (slide) tag if it exists</doc>
+ </slide>
+ <delete>
+ <shortopt>d</shortopt>
+ <doc>Remove tag</doc>
+ </delete>
+ <dry-run>
+ <shortopt>n</shortopt>
+ <doc>Don&#039;t do anything, just pretend</doc>
+ </dry-run>
+ </options>
+ <doc>&lt;package.xml&gt; [files...]
+ Sets a SVN tag on all files in a package. Use this command after you have
+ packaged a distribution tarball with the &quot;package&quot; command to tag what
+ revisions of what files were in that release. If need to fix something
+ after running svntag once, but before the tarball is released to the public,
+ use the &quot;slide&quot; option to move the release tag.
+
+ to include files (such as a second package.xml, or tests not included in the
+ release), pass them as additional parameters.
+ </doc>
+ </svntag>
+ <cvstag>
+ <summary>Set CVS Release Tag</summary>
+ <function>doCvsTag</function>
+ <shortcut>ct</shortcut>
+ <options>
+ <quiet>
+ <shortopt>q</shortopt>
+ <doc>Be quiet</doc>
+ </quiet>
+ <reallyquiet>
+ <shortopt>Q</shortopt>
+ <doc>Be really quiet</doc>
+ </reallyquiet>
+ <slide>
+ <shortopt>F</shortopt>
+ <doc>Move (slide) tag if it exists</doc>
+ </slide>
+ <delete>
+ <shortopt>d</shortopt>
+ <doc>Remove tag</doc>
+ </delete>
+ <dry-run>
+ <shortopt>n</shortopt>
+ <doc>Don&#039;t do anything, just pretend</doc>
+ </dry-run>
+ </options>
+ <doc>&lt;package.xml&gt; [files...]
+Sets a CVS tag on all files in a package. Use this command after you have
+packaged a distribution tarball with the &quot;package&quot; command to tag what
+revisions of what files were in that release. If need to fix something
+after running cvstag once, but before the tarball is released to the public,
+use the &quot;slide&quot; option to move the release tag.
+
+to include files (such as a second package.xml, or tests not included in the
+release), pass them as additional parameters.
+</doc>
+ </cvstag>
+ <package-dependencies>
+ <summary>Show package dependencies</summary>
+ <function>doPackageDependencies</function>
+ <shortcut>pd</shortcut>
+ <options />
+ <doc>&lt;package-file&gt; or &lt;package.xml&gt; or &lt;install-package-name&gt;
+List all dependencies the package has.
+Can take a tgz / tar file, package.xml or a package name of an installed package.</doc>
+ </package-dependencies>
+ <sign>
+ <summary>Sign a package distribution file</summary>
+ <function>doSign</function>
+ <shortcut>si</shortcut>
+ <options>
+ <verbose>
+ <shortopt>v</shortopt>
+ <doc>Display GnuPG output</doc>
+ </verbose>
+ </options>
+ <doc>&lt;package-file&gt;
+Signs a package distribution (.tar or .tgz) file with GnuPG.</doc>
+ </sign>
+ <makerpm>
+ <summary>Builds an RPM spec file from a PEAR package</summary>
+ <function>doMakeRPM</function>
+ <shortcut>rpm</shortcut>
+ <options>
+ <spec-template>
+ <shortopt>t</shortopt>
+ <doc>Use FILE as RPM spec file template</doc>
+ <arg>FILE</arg>
+ </spec-template>
+ <rpm-pkgname>
+ <shortopt>p</shortopt>
+ <doc>Use FORMAT as format string for RPM package name, %s is replaced
+by the PEAR package name, defaults to &quot;PEAR::%s&quot;.</doc>
+ <arg>FORMAT</arg>
+ </rpm-pkgname>
+ </options>
+ <doc>&lt;package-file&gt;
+
+Creates an RPM .spec file for wrapping a PEAR package inside an RPM
+package. Intended to be used from the SPECS directory, with the PEAR
+package tarball in the SOURCES directory:
+
+$ pear makerpm ../SOURCES/Net_Socket-1.0.tgz
+Wrote RPM spec file PEAR::Net_Geo-1.0.spec
+$ rpm -bb PEAR::Net_Socket-1.0.spec
+...
+Wrote: /usr/src/redhat/RPMS/i386/PEAR::Net_Socket-1.0-1.i386.rpm
+</doc>
+ </makerpm>
+ <convert>
+ <summary>Convert a package.xml 1.0 to package.xml 2.0 format</summary>
+ <function>doConvert</function>
+ <shortcut>c2</shortcut>
+ <options>
+ <flat>
+ <shortopt>f</shortopt>
+ <doc>do not beautify the filelist.</doc>
+ </flat>
+ </options>
+ <doc>[descfile] [descfile2]
+Converts a package.xml in 1.0 format into a package.xml
+in 2.0 format. The new file will be named package2.xml by default,
+and package.xml will be used as the old file by default.
+This is not the most intelligent conversion, and should only be
+used for automated conversion or learning the format.
+</doc>
+ </convert>
+</commands><?php
+/**
+ * PEAR_Command_Pickle (pickle command)
+ *
+ * PHP versions 4 and 5
+ *
+ * @category pear
+ * @package PEAR
+ * @author Greg Beaver <cellog@php.net>
+ * @copyright 2005-2009 The Authors
+ * @license http://opensource.org/licenses/bsd-license.php New BSD License
+ * @version CVS: $Id: Pickle.php 313023 2011-07-06 19:17:11Z dufuz $
+ * @link http://pear.php.net/package/PEAR
+ * @since File available since Release 1.4.1
+ */
+
+/**
+ * base class
+ */
+require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Command/Common.php';
+
+/**
+ * PEAR commands for login/logout
+ *
+ * @category pear
+ * @package PEAR
+ * @author Greg Beaver <cellog@php.net>
+ * @copyright 2005-2009 The Authors
+ * @license http://opensource.org/licenses/bsd-license.php New BSD License
+ * @version Release: 1.9.4
+ * @link http://pear.php.net/package/PEAR
+ * @since Class available since Release 1.4.1
+ */
+
+class PEAR_Command_Pickle extends PEAR_Command_Common
+{
+ var $commands = array(
+ 'pickle' => array(
+ 'summary' => 'Build PECL Package',
+ 'function' => 'doPackage',
+ 'shortcut' => 'pi',
+ 'options' => array(
+ 'nocompress' => array(
+ 'shortopt' => 'Z',
+ 'doc' => 'Do not gzip the package file'
+ ),
+ 'showname' => array(
+ 'shortopt' => 'n',
+ 'doc' => 'Print the name of the packaged file.',
+ ),
+ ),
+ 'doc' => '[descfile]
+Creates a PECL package from its package2.xml file.
+
+An automatic conversion will be made to a package.xml 1.0 and written out to
+disk in the current directory as "package.xml". Note that
+only simple package.xml 2.0 will be converted. package.xml 2.0 with:
+
+ - dependency types other than required/optional PECL package/ext/php/pearinstaller
+ - more than one extsrcrelease or zendextsrcrelease
+ - zendextbinrelease, extbinrelease, phprelease, or bundle release type
+ - dependency groups
+ - ignore tags in release filelist
+ - tasks other than replace
+ - custom roles
+
+will cause pickle to fail, and output an error message. If your package2.xml
+uses any of these features, you are best off using PEAR_PackageFileManager to
+generate both package.xml.
+'
+ ),
+ );
+
+ /**
+ * PEAR_Command_Package constructor.
+ *
+ * @access public
+ */
+ function PEAR_Command_Pickle(&$ui, &$config)
+ {
+ parent::PEAR_Command_Common($ui, $config);
+ }
+
+ /**
+ * For unit-testing ease
+ *
+ * @return PEAR_Packager
+ */
+ function &getPackager()
+ {
+ if (!class_exists('PEAR_Packager')) {
+ require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Packager.php';
+ }
+
+ $a = &new PEAR_Packager;
+ return $a;
+ }
+
+ /**
+ * For unit-testing ease
+ *
+ * @param PEAR_Config $config
+ * @param bool $debug
+ * @param string|null $tmpdir
+ * @return PEAR_PackageFile
+ */
+ function &getPackageFile($config, $debug = false)
+ {
+ if (!class_exists('PEAR_Common')) {
+ require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Common.php';
+ }
+
+ if (!class_exists('PEAR_PackageFile')) {
+ require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/PackageFile.php';
+ }
+
+ $a = &new PEAR_PackageFile($config, $debug);
+ $common = new PEAR_Common;
+ $common->ui = $this->ui;
+ $a->setLogger($common);
+ return $a;
+ }
+
+ function doPackage($command, $options, $params)
+ {
+ $this->output = '';
+ $pkginfofile = isset($params[0]) ? $params[0] : 'package2.xml';
+ $packager = &$this->getPackager();
+ if (PEAR::isError($err = $this->_convertPackage($pkginfofile))) {
+ return $err;
+ }
+
+ $compress = empty($options['nocompress']) ? true : false;
+ $result = $packager->package($pkginfofile, $compress, 'package.xml');
+ if (PEAR::isError($result)) {
+ return $this->raiseError($result);
+ }
+
+ // Don't want output, only the package file name just created
+ if (isset($options['showname'])) {
+ $this->ui->outputData($result, $command);
+ }
+
+ return true;
+ }
+
+ function _convertPackage($packagexml)
+ {
+ $pkg = &$this->getPackageFile($this->config);
+ $pf2 = &$pkg->fromPackageFile($packagexml, PEAR_VALIDATE_NORMAL);
+ if (!is_a($pf2, 'PEAR_PackageFile_v2')) {
+ return $this->raiseError('Cannot process "' .
+ $packagexml . '", is not a package.xml 2.0');
+ }
+
+ require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/PackageFile/v1.php';
+ $pf = new PEAR_PackageFile_v1;
+ $pf->setConfig($this->config);
+ if ($pf2->getPackageType() != 'extsrc' && $pf2->getPackageType() != 'zendextsrc') {
+ return $this->raiseError('Cannot safely convert "' . $packagexml .
+ '", is not an extension source package. Using a PEAR_PackageFileManager-based ' .
+ 'script is an option');
+ }
+
+ if (is_array($pf2->getUsesRole())) {
+ return $this->raiseError('Cannot safely convert "' . $packagexml .
+ '", contains custom roles. Using a PEAR_PackageFileManager-based script or ' .
+ 'the convert command is an option');
+ }
+
+ if (is_array($pf2->getUsesTask())) {
+ return $this->raiseError('Cannot safely convert "' . $packagexml .
+ '", contains custom tasks. Using a PEAR_PackageFileManager-based script or ' .
+ 'the convert command is an option');
+ }
+
+ $deps = $pf2->getDependencies();
+ if (isset($deps['group'])) {
+ return $this->raiseError('Cannot safely convert "' . $packagexml .
+ '", contains dependency groups. Using a PEAR_PackageFileManager-based script ' .
+ 'or the convert command is an option');
+ }
+
+ if (isset($deps['required']['subpackage']) ||
+ isset($deps['optional']['subpackage'])) {
+ return $this->raiseError('Cannot safely convert "' . $packagexml .
+ '", contains subpackage dependencies. Using a PEAR_PackageFileManager-based '.
+ 'script is an option');
+ }
+
+ if (isset($deps['required']['os'])) {
+ return $this->raiseError('Cannot safely convert "' . $packagexml .
+ '", contains os dependencies. Using a PEAR_PackageFileManager-based '.
+ 'script is an option');
+ }
+
+ if (isset($deps['required']['arch'])) {
+ return $this->raiseError('Cannot safely convert "' . $packagexml .
+ '", contains arch dependencies. Using a PEAR_PackageFileManager-based '.
+ 'script is an option');
+ }
+
+ $pf->setPackage($pf2->getPackage());
+ $pf->setSummary($pf2->getSummary());
+ $pf->setDescription($pf2->getDescription());
+ foreach ($pf2->getMaintainers() as $maintainer) {
+ $pf->addMaintainer($maintainer['role'], $maintainer['handle'],
+ $maintainer['name'], $maintainer['email']);
+ }
+
+ $pf->setVersion($pf2->getVersion());
+ $pf->setDate($pf2->getDate());
+ $pf->setLicense($pf2->getLicense());
+ $pf->setState($pf2->getState());
+ $pf->setNotes($pf2->getNotes());
+ $pf->addPhpDep($deps['required']['php']['min'], 'ge');
+ if (isset($deps['required']['php']['max'])) {
+ $pf->addPhpDep($deps['required']['php']['max'], 'le');
+ }
+
+ if (isset($deps['required']['package'])) {
+ if (!isset($deps['required']['package'][0])) {
+ $deps['required']['package'] = array($deps['required']['package']);
+ }
+
+ foreach ($deps['required']['package'] as $dep) {
+ if (!isset($dep['channel'])) {
+ return $this->raiseError('Cannot safely convert "' . $packagexml . '"' .
+ ' contains uri-based dependency on a package. Using a ' .
+ 'PEAR_PackageFileManager-based script is an option');
+ }
+
+ if ($dep['channel'] != 'pear.php.net'
+ && $dep['channel'] != 'pecl.php.net'
+ && $dep['channel'] != 'doc.php.net') {
+ return $this->raiseError('Cannot safely convert "' . $packagexml . '"' .
+ ' contains dependency on a non-standard channel package. Using a ' .
+ 'PEAR_PackageFileManager-based script is an option');
+ }
+
+ if (isset($dep['conflicts'])) {
+ return $this->raiseError('Cannot safely convert "' . $packagexml . '"' .
+ ' contains conflicts dependency. Using a ' .
+ 'PEAR_PackageFileManager-based script is an option');
+ }
+
+ if (isset($dep['exclude'])) {
+ $this->ui->outputData('WARNING: exclude tags are ignored in conversion');
+ }
+
+ if (isset($dep['min'])) {
+ $pf->addPackageDep($dep['name'], $dep['min'], 'ge');
+ }
+
+ if (isset($dep['max'])) {
+ $pf->addPackageDep($dep['name'], $dep['max'], 'le');
+ }
+ }
+ }
+
+ if (isset($deps['required']['extension'])) {
+ if (!isset($deps['required']['extension'][0])) {
+ $deps['required']['extension'] = array($deps['required']['extension']);
+ }
+
+ foreach ($deps['required']['extension'] as $dep) {
+ if (isset($dep['conflicts'])) {
+ return $this->raiseError('Cannot safely convert "' . $packagexml . '"' .
+ ' contains conflicts dependency. Using a ' .
+ 'PEAR_PackageFileManager-based script is an option');
+ }
+
+ if (isset($dep['exclude'])) {
+ $this->ui->outputData('WARNING: exclude tags are ignored in conversion');
+ }
+
+ if (isset($dep['min'])) {
+ $pf->addExtensionDep($dep['name'], $dep['min'], 'ge');
+ }
+
+ if (isset($dep['max'])) {
+ $pf->addExtensionDep($dep['name'], $dep['max'], 'le');
+ }
+ }
+ }
+
+ if (isset($deps['optional']['package'])) {
+ if (!isset($deps['optional']['package'][0])) {
+ $deps['optional']['package'] = array($deps['optional']['package']);
+ }
+
+ foreach ($deps['optional']['package'] as $dep) {
+ if (!isset($dep['channel'])) {
+ return $this->raiseError('Cannot safely convert "' . $packagexml . '"' .
+ ' contains uri-based dependency on a package. Using a ' .
+ 'PEAR_PackageFileManager-based script is an option');
+ }
+
+ if ($dep['channel'] != 'pear.php.net'
+ && $dep['channel'] != 'pecl.php.net'
+ && $dep['channel'] != 'doc.php.net') {
+ return $this->raiseError('Cannot safely convert "' . $packagexml . '"' .
+ ' contains dependency on a non-standard channel package. Using a ' .
+ 'PEAR_PackageFileManager-based script is an option');
+ }
+
+ if (isset($dep['exclude'])) {
+ $this->ui->outputData('WARNING: exclude tags are ignored in conversion');
+ }
+
+ if (isset($dep['min'])) {
+ $pf->addPackageDep($dep['name'], $dep['min'], 'ge', 'yes');
+ }
+
+ if (isset($dep['max'])) {
+ $pf->addPackageDep($dep['name'], $dep['max'], 'le', 'yes');
+ }
+ }
+ }
+
+ if (isset($deps['optional']['extension'])) {
+ if (!isset($deps['optional']['extension'][0])) {
+ $deps['optional']['extension'] = array($deps['optional']['extension']);
+ }
+
+ foreach ($deps['optional']['extension'] as $dep) {
+ if (isset($dep['exclude'])) {
+ $this->ui->outputData('WARNING: exclude tags are ignored in conversion');
+ }
+
+ if (isset($dep['min'])) {
+ $pf->addExtensionDep($dep['name'], $dep['min'], 'ge', 'yes');
+ }
+
+ if (isset($dep['max'])) {
+ $pf->addExtensionDep($dep['name'], $dep['max'], 'le', 'yes');
+ }
+ }
+ }
+
+ $contents = $pf2->getContents();
+ $release = $pf2->getReleases();
+ if (isset($releases[0])) {
+ return $this->raiseError('Cannot safely process "' . $packagexml . '" contains '
+ . 'multiple extsrcrelease/zendextsrcrelease tags. Using a PEAR_PackageFileManager-based script ' .
+ 'or the convert command is an option');
+ }
+
+ if ($configoptions = $pf2->getConfigureOptions()) {
+ foreach ($configoptions as $option) {
+ $default = isset($option['default']) ? $option['default'] : false;
+ $pf->addConfigureOption($option['name'], $option['prompt'], $default);
+ }
+ }
+
+ if (isset($release['filelist']['ignore'])) {
+ return $this->raiseError('Cannot safely process "' . $packagexml . '" contains '
+ . 'ignore tags. Using a PEAR_PackageFileManager-based script or the convert' .
+ ' command is an option');
+ }
+
+ if (isset($release['filelist']['install']) &&
+ !isset($release['filelist']['install'][0])) {
+ $release['filelist']['install'] = array($release['filelist']['install']);
+ }
+
+ if (isset($contents['dir']['attribs']['baseinstalldir'])) {
+ $baseinstalldir = $contents['dir']['attribs']['baseinstalldir'];
+ } else {
+ $baseinstalldir = false;
+ }
+
+ if (!isset($contents['dir']['file'][0])) {
+ $contents['dir']['file'] = array($contents['dir']['file']);
+ }
+
+ foreach ($contents['dir']['file'] as $file) {
+ if ($baseinstalldir && !isset($file['attribs']['baseinstalldir'])) {
+ $file['attribs']['baseinstalldir'] = $baseinstalldir;
+ }
+
+ $processFile = $file;
+ unset($processFile['attribs']);
+ if (count($processFile)) {
+ foreach ($processFile as $name => $task) {
+ if ($name != $pf2->getTasksNs() . ':replace') {
+ return $this->raiseError('Cannot safely process "' . $packagexml .
+ '" contains tasks other than replace. Using a ' .
+ 'PEAR_PackageFileManager-based script is an option.');
+ }
+ $file['attribs']['replace'][] = $task;
+ }
+ }
+
+ if (!in_array($file['attribs']['role'], PEAR_Common::getFileRoles())) {
+ return $this->raiseError('Cannot safely convert "' . $packagexml .
+ '", contains custom roles. Using a PEAR_PackageFileManager-based script ' .
+ 'or the convert command is an option');
+ }
+
+ if (isset($release['filelist']['install'])) {
+ foreach ($release['filelist']['install'] as $installas) {
+ if ($installas['attribs']['name'] == $file['attribs']['name']) {
+ $file['attribs']['install-as'] = $installas['attribs']['as'];
+ }
+ }
+ }
+
+ $pf->addFile('/', $file['attribs']['name'], $file['attribs']);
+ }
+
+ if ($pf2->getChangeLog()) {
+ $this->ui->outputData('WARNING: changelog is not translated to package.xml ' .
+ '1.0, use PEAR_PackageFileManager-based script if you need changelog-' .
+ 'translation for package.xml 1.0');
+ }
+
+ $gen = &$pf->getDefaultGenerator();
+ $gen->toPackageFile('.');
+ }
+}<commands version="1.0">
+ <pickle>
+ <summary>Build PECL Package</summary>
+ <function>doPackage</function>
+ <shortcut>pi</shortcut>
+ <options>
+ <nocompress>
+ <shortopt>Z</shortopt>
+ <doc>Do not gzip the package file</doc>
+ </nocompress>
+ <showname>
+ <shortopt>n</shortopt>
+ <doc>Print the name of the packaged file.</doc>
+ </showname>
+ </options>
+ <doc>[descfile]
+Creates a PECL package from its package2.xml file.
+
+An automatic conversion will be made to a package.xml 1.0 and written out to
+disk in the current directory as &quot;package.xml&quot;. Note that
+only simple package.xml 2.0 will be converted. package.xml 2.0 with:
+
+ - dependency types other than required/optional PECL package/ext/php/pearinstaller
+ - more than one extsrcrelease or zendextsrcrelease
+ - zendextbinrelease, extbinrelease, phprelease, or bundle release type
+ - dependency groups
+ - ignore tags in release filelist
+ - tasks other than replace
+ - custom roles
+
+will cause pickle to fail, and output an error message. If your package2.xml
+uses any of these features, you are best off using PEAR_PackageFileManager to
+generate both package.xml.
+</doc>
+ </pickle>
+</commands><?php
+/**
+ * PEAR_Command_Registry (list, list-files, shell-test, info commands)
+ *
+ * PHP versions 4 and 5
+ *
+ * @category pear
+ * @package PEAR
+ * @author Stig Bakken <ssb@php.net>
+ * @author Greg Beaver <cellog@php.net>
+ * @copyright 1997-2009 The Authors
+ * @license http://opensource.org/licenses/bsd-license.php New BSD License
+ * @version CVS: $Id: Registry.php 313023 2011-07-06 19:17:11Z dufuz $
+ * @link http://pear.php.net/package/PEAR
+ * @since File available since Release 0.1
+ */
+
+/**
+ * base class
+ */
+require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Command/Common.php';
+
+/**
+ * PEAR commands for registry manipulation
+ *
+ * @category pear
+ * @package PEAR
+ * @author Stig Bakken <ssb@php.net>
+ * @author Greg Beaver <cellog@php.net>
+ * @copyright 1997-2009 The Authors
+ * @license http://opensource.org/licenses/bsd-license.php New BSD License
+ * @version Release: 1.9.4
+ * @link http://pear.php.net/package/PEAR
+ * @since Class available since Release 0.1
+ */
+class PEAR_Command_Registry extends PEAR_Command_Common
+{
+ var $commands = array(
+ 'list' => array(
+ 'summary' => 'List Installed Packages In The Default Channel',
+ 'function' => 'doList',
+ 'shortcut' => 'l',
+ 'options' => array(
+ 'channel' => array(
+ 'shortopt' => 'c',
+ 'doc' => 'list installed packages from this channel',
+ 'arg' => 'CHAN',
+ ),
+ 'allchannels' => array(
+ 'shortopt' => 'a',
+ 'doc' => 'list installed packages from all channels',
+ ),
+ 'channelinfo' => array(
+ 'shortopt' => 'i',
+ 'doc' => 'output fully channel-aware data, even on failure',
+ ),
+ ),
+ 'doc' => '<package>
+If invoked without parameters, this command lists the PEAR packages
+installed in your php_dir ({config php_dir}). With a parameter, it
+lists the files in a package.
+',
+ ),
+ 'list-files' => array(
+ 'summary' => 'List Files In Installed Package',
+ 'function' => 'doFileList',
+ 'shortcut' => 'fl',
+ 'options' => array(),
+ 'doc' => '<package>
+List the files in an installed package.
+'
+ ),
+ 'shell-test' => array(
+ 'summary' => 'Shell Script Test',
+ 'function' => 'doShellTest',
+ 'shortcut' => 'st',
+ 'options' => array(),
+ 'doc' => '<package> [[relation] version]
+Tests if a package is installed in the system. Will exit(1) if it is not.
+ <relation> The version comparison operator. One of:
+ <, lt, <=, le, >, gt, >=, ge, ==, =, eq, !=, <>, ne
+ <version> The version to compare with
+'),
+ 'info' => array(
+ 'summary' => 'Display information about a package',
+ 'function' => 'doInfo',
+ 'shortcut' => 'in',
+ 'options' => array(),
+ 'doc' => '<package>
+Displays information about a package. The package argument may be a
+local package file, an URL to a package file, or the name of an
+installed package.'
+ )
+ );
+
+ /**
+ * PEAR_Command_Registry constructor.
+ *
+ * @access public
+ */
+ function PEAR_Command_Registry(&$ui, &$config)
+ {
+ parent::PEAR_Command_Common($ui, $config);
+ }
+
+ function _sortinfo($a, $b)
+ {
+ $apackage = isset($a['package']) ? $a['package'] : $a['name'];
+ $bpackage = isset($b['package']) ? $b['package'] : $b['name'];
+ return strcmp($apackage, $bpackage);
+ }
+
+ function doList($command, $options, $params)
+ {
+ $reg = &$this->config->getRegistry();
+ $channelinfo = isset($options['channelinfo']);
+ if (isset($options['allchannels']) && !$channelinfo) {
+ return $this->doListAll($command, array(), $params);
+ }
+
+ if (isset($options['allchannels']) && $channelinfo) {
+ // allchannels with $channelinfo
+ unset($options['allchannels']);
+ $channels = $reg->getChannels();
+ $errors = array();
+ PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
+ foreach ($channels as $channel) {
+ $options['channel'] = $channel->getName();
+ $ret = $this->doList($command, $options, $params);
+
+ if (PEAR::isError($ret)) {
+ $errors[] = $ret;
+ }
+ }
+
+ PEAR::staticPopErrorHandling();
+ if (count($errors)) {
+ // for now, only give first error
+ return PEAR::raiseError($errors[0]);
+ }
+
+ return true;
+ }
+
+ if (count($params) === 1) {
+ return $this->doFileList($command, $options, $params);
+ }
+
+ if (isset($options['channel'])) {
+ if (!$reg->channelExists($options['channel'])) {
+ return $this->raiseError('Channel "' . $options['channel'] .'" does not exist');
+ }
+
+ $channel = $reg->channelName($options['channel']);
+ } else {
+ $channel = $this->config->get('default_channel');
+ }
+
+ $installed = $reg->packageInfo(null, null, $channel);
+ usort($installed, array(&$this, '_sortinfo'));
+
+ $data = array(
+ 'caption' => 'Installed packages, channel ' .
+ $channel . ':',
+ 'border' => true,
+ 'headline' => array('Package', 'Version', 'State'),
+ 'channel' => $channel,
+ );
+ if ($channelinfo) {
+ $data['headline'] = array('Channel', 'Package', 'Version', 'State');
+ }
+
+ if (count($installed) && !isset($data['data'])) {
+ $data['data'] = array();
+ }
+
+ foreach ($installed as $package) {
+ $pobj = $reg->getPackage(isset($package['package']) ?
+ $package['package'] : $package['name'], $channel);
+ if ($channelinfo) {
+ $packageinfo = array($pobj->getChannel(), $pobj->getPackage(), $pobj->getVersion(),
+ $pobj->getState() ? $pobj->getState() : null);
+ } else {
+ $packageinfo = array($pobj->getPackage(), $pobj->getVersion(),
+ $pobj->getState() ? $pobj->getState() : null);
+ }
+ $data['data'][] = $packageinfo;
+ }
+
+ if (count($installed) === 0) {
+ if (!$channelinfo) {
+ $data = '(no packages installed from channel ' . $channel . ')';
+ } else {
+ $data = array(
+ 'caption' => 'Installed packages, channel ' .
+ $channel . ':',
+ 'border' => true,
+ 'channel' => $channel,
+ 'data' => array(array('(no packages installed)')),
+ );
+ }
+ }
+
+ $this->ui->outputData($data, $command);
+ return true;
+ }
+
+ function doListAll($command, $options, $params)
+ {
+ // This duplicate code is deprecated over
+ // list --channelinfo, which gives identical
+ // output for list and list --allchannels.
+ $reg = &$this->config->getRegistry();
+ $installed = $reg->packageInfo(null, null, null);
+ foreach ($installed as $channel => $packages) {
+ usort($packages, array($this, '_sortinfo'));
+ $data = array(
+ 'caption' => 'Installed packages, channel ' . $channel . ':',
+ 'border' => true,
+ 'headline' => array('Package', 'Version', 'State'),
+ 'channel' => $channel
+ );
+
+ foreach ($packages as $package) {
+ $p = isset($package['package']) ? $package['package'] : $package['name'];
+ $pobj = $reg->getPackage($p, $channel);
+ $data['data'][] = array($pobj->getPackage(), $pobj->getVersion(),
+ $pobj->getState() ? $pobj->getState() : null);
+ }
+
+ // Adds a blank line after each section
+ $data['data'][] = array();
+
+ if (count($packages) === 0) {
+ $data = array(
+ 'caption' => 'Installed packages, channel ' . $channel . ':',
+ 'border' => true,
+ 'data' => array(array('(no packages installed)'), array()),
+ 'channel' => $channel
+ );
+ }
+ $this->ui->outputData($data, $command);
+ }
+ return true;
+ }
+
+ function doFileList($command, $options, $params)
+ {
+ if (count($params) !== 1) {
+ return $this->raiseError('list-files expects 1 parameter');
+ }
+
+ $reg = &$this->config->getRegistry();
+ $fp = false;
+ if (!is_dir($params[0]) && (file_exists($params[0]) || $fp = @fopen($params[0], 'r'))) {
+ if ($fp) {
+ fclose($fp);
+ }
+
+ if (!class_exists('PEAR_PackageFile')) {
+ require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/PackageFile.php';
+ }
+
+ $pkg = &new PEAR_PackageFile($this->config, $this->_debug);
+ PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
+ $info = &$pkg->fromAnyFile($params[0], PEAR_VALIDATE_NORMAL);
+ PEAR::staticPopErrorHandling();
+ $headings = array('Package File', 'Install Path');
+ $installed = false;
+ } else {
+ PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
+ $parsed = $reg->parsePackageName($params[0], $this->config->get('default_channel'));
+ PEAR::staticPopErrorHandling();
+ if (PEAR::isError($parsed)) {
+ return $this->raiseError($parsed);
+ }
+
+ $info = &$reg->getPackage($parsed['package'], $parsed['channel']);
+ $headings = array('Type', 'Install Path');
+ $installed = true;
+ }
+
+ if (PEAR::isError($info)) {
+ return $this->raiseError($info);
+ }
+
+ if ($info === null) {
+ return $this->raiseError("`$params[0]' not installed");
+ }
+
+ $list = ($info->getPackagexmlVersion() == '1.0' || $installed) ?
+ $info->getFilelist() : $info->getContents();
+ if ($installed) {
+ $caption = 'Installed Files For ' . $params[0];
+ } else {
+ $caption = 'Contents of ' . basename($params[0]);
+ }
+
+ $data = array(
+ 'caption' => $caption,
+ 'border' => true,
+ 'headline' => $headings);
+ if ($info->getPackagexmlVersion() == '1.0' || $installed) {
+ foreach ($list as $file => $att) {
+ if ($installed) {
+ if (empty($att['installed_as'])) {
+ continue;
+ }
+ $data['data'][] = array($att['role'], $att['installed_as']);
+ } else {
+ if (isset($att['baseinstalldir']) && !in_array($att['role'],
+ array('test', 'data', 'doc'))) {
+ $dest = $att['baseinstalldir'] . DIRECTORY_SEPARATOR .
+ $file;
+ } else {
+ $dest = $file;
+ }
+ switch ($att['role']) {
+ case 'test':
+ case 'data':
+ case 'doc':
+ $role = $att['role'];
+ if ($role == 'test') {
+ $role .= 's';
+ }
+ $dest = $this->config->get($role . '_dir') . DIRECTORY_SEPARATOR .
+ $info->getPackage() . DIRECTORY_SEPARATOR . $dest;
+ break;
+ case 'php':
+ default:
+ $dest = $this->config->get('php_dir') . DIRECTORY_SEPARATOR .
+ $dest;
+ }
+ $ds2 = DIRECTORY_SEPARATOR . DIRECTORY_SEPARATOR;
+ $dest = preg_replace(array('!\\\\+!', '!/!', "!$ds2+!"),
+ array(DIRECTORY_SEPARATOR,
+ DIRECTORY_SEPARATOR,
+ DIRECTORY_SEPARATOR),
+ $dest);
+ $file = preg_replace('!/+!', '/', $file);
+ $data['data'][] = array($file, $dest);
+ }
+ }
+ } else { // package.xml 2.0, not installed
+ if (!isset($list['dir']['file'][0])) {
+ $list['dir']['file'] = array($list['dir']['file']);
+ }
+
+ foreach ($list['dir']['file'] as $att) {
+ $att = $att['attribs'];
+ $file = $att['name'];
+ $role = &PEAR_Installer_Role::factory($info, $att['role'], $this->config);
+ $role->setup($this, $info, $att, $file);
+ if (!$role->isInstallable()) {
+ $dest = '(not installable)';
+ } else {
+ $dest = $role->processInstallation($info, $att, $file, '');
+ if (PEAR::isError($dest)) {
+ $dest = '(Unknown role "' . $att['role'] . ')';
+ } else {
+ list(,, $dest) = $dest;
+ }
+ }
+ $data['data'][] = array($file, $dest);
+ }
+ }
+
+ $this->ui->outputData($data, $command);
+ return true;
+ }
+
+ function doShellTest($command, $options, $params)
+ {
+ if (count($params) < 1) {
+ return PEAR::raiseError('ERROR, usage: pear shell-test packagename [[relation] version]');
+ }
+
+ PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
+ $reg = &$this->config->getRegistry();
+ $info = $reg->parsePackageName($params[0], $this->config->get('default_channel'));
+ if (PEAR::isError($info)) {
+ exit(1); // invalid package name
+ }
+
+ $package = $info['package'];
+ $channel = $info['channel'];
+ // "pear shell-test Foo"
+ if (!$reg->packageExists($package, $channel)) {
+ if ($channel == 'pecl.php.net') {
+ if ($reg->packageExists($package, 'pear.php.net')) {
+ $channel = 'pear.php.net'; // magically change channels for extensions
+ }
+ }
+ }
+
+ if (count($params) === 1) {
+ if (!$reg->packageExists($package, $channel)) {
+ exit(1);
+ }
+ // "pear shell-test Foo 1.0"
+ } elseif (count($params) === 2) {
+ $v = $reg->packageInfo($package, 'version', $channel);
+ if (!$v || !version_compare("$v", "{$params[1]}", "ge")) {
+ exit(1);
+ }
+ // "pear shell-test Foo ge 1.0"
+ } elseif (count($params) === 3) {
+ $v = $reg->packageInfo($package, 'version', $channel);
+ if (!$v || !version_compare("$v", "{$params[2]}", $params[1])) {
+ exit(1);
+ }
+ } else {
+ PEAR::staticPopErrorHandling();
+ $this->raiseError("$command: expects 1 to 3 parameters");
+ exit(1);
+ }
+ }
+
+ function doInfo($command, $options, $params)
+ {
+ if (count($params) !== 1) {
+ return $this->raiseError('pear info expects 1 parameter');
+ }
+
+ $info = $fp = false;
+ $reg = &$this->config->getRegistry();
+ if (is_file($params[0]) && !is_dir($params[0]) &&
+ (file_exists($params[0]) || $fp = @fopen($params[0], 'r'))
+ ) {
+ if ($fp) {
+ fclose($fp);
+ }
+
+ if (!class_exists('PEAR_PackageFile')) {
+ require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/PackageFile.php';
+ }
+
+ $pkg = &new PEAR_PackageFile($this->config, $this->_debug);
+ PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
+ $obj = &$pkg->fromAnyFile($params[0], PEAR_VALIDATE_NORMAL);
+ PEAR::staticPopErrorHandling();
+ if (PEAR::isError($obj)) {
+ $uinfo = $obj->getUserInfo();
+ if (is_array($uinfo)) {
+ foreach ($uinfo as $message) {
+ if (is_array($message)) {
+ $message = $message['message'];
+ }
+ $this->ui->outputData($message);
+ }
+ }
+
+ return $this->raiseError($obj);
+ }
+
+ if ($obj->getPackagexmlVersion() != '1.0') {
+ return $this->_doInfo2($command, $options, $params, $obj, false);
+ }
+
+ $info = $obj->toArray();
+ } else {
+ $parsed = $reg->parsePackageName($params[0], $this->config->get('default_channel'));
+ if (PEAR::isError($parsed)) {
+ return $this->raiseError($parsed);
+ }
+
+ $package = $parsed['package'];
+ $channel = $parsed['channel'];
+ $info = $reg->packageInfo($package, null, $channel);
+ if (isset($info['old'])) {
+ $obj = $reg->getPackage($package, $channel);
+ return $this->_doInfo2($command, $options, $params, $obj, true);
+ }
+ }
+
+ if (PEAR::isError($info)) {
+ return $info;
+ }
+
+ if (empty($info)) {
+ $this->raiseError("No information found for `$params[0]'");
+ return;
+ }
+
+ unset($info['filelist']);
+ unset($info['dirtree']);
+ unset($info['changelog']);
+ if (isset($info['xsdversion'])) {
+ $info['package.xml version'] = $info['xsdversion'];
+ unset($info['xsdversion']);
+ }
+
+ if (isset($info['packagerversion'])) {
+ $info['packaged with PEAR version'] = $info['packagerversion'];
+ unset($info['packagerversion']);
+ }
+
+ $keys = array_keys($info);
+ $longtext = array('description', 'summary');
+ foreach ($keys as $key) {
+ if (is_array($info[$key])) {
+ switch ($key) {
+ case 'maintainers': {
+ $i = 0;
+ $mstr = '';
+ foreach ($info[$key] as $m) {
+ if ($i++ > 0) {
+ $mstr .= "\n";
+ }
+ $mstr .= $m['name'] . " <";
+ if (isset($m['email'])) {
+ $mstr .= $m['email'];
+ } else {
+ $mstr .= $m['handle'] . '@php.net';
+ }
+ $mstr .= "> ($m[role])";
+ }
+ $info[$key] = $mstr;
+ break;
+ }
+ case 'release_deps': {
+ $i = 0;
+ $dstr = '';
+ foreach ($info[$key] as $d) {
+ if (isset($this->_deps_rel_trans[$d['rel']])) {
+ $rel = $this->_deps_rel_trans[$d['rel']];
+ } else {
+ $rel = $d['rel'];
+ }
+ if (isset($this->_deps_type_trans[$d['type']])) {
+ $type = ucfirst($this->_deps_type_trans[$d['type']]);
+ } else {
+ $type = $d['type'];
+ }
+ if (isset($d['name'])) {
+ $name = $d['name'] . ' ';
+ } else {
+ $name = '';
+ }
+ if (isset($d['version'])) {
+ $version = $d['version'] . ' ';
+ } else {
+ $version = '';
+ }
+ if (isset($d['optional']) && $d['optional'] == 'yes') {
+ $optional = ' (optional)';
+ } else {
+ $optional = '';
+ }
+ $dstr .= "$type $name$rel $version$optional\n";
+ }
+ $info[$key] = $dstr;
+ break;
+ }
+ case 'provides' : {
+ $debug = $this->config->get('verbose');
+ if ($debug < 2) {
+ $pstr = 'Classes: ';
+ } else {
+ $pstr = '';
+ }
+ $i = 0;
+ foreach ($info[$key] as $p) {
+ if ($debug < 2 && $p['type'] != "class") {
+ continue;
+ }
+ // Only print classes when verbosity mode is < 2
+ if ($debug < 2) {
+ if ($i++ > 0) {
+ $pstr .= ", ";
+ }
+ $pstr .= $p['name'];
+ } else {
+ if ($i++ > 0) {
+ $pstr .= "\n";
+ }
+ $pstr .= ucfirst($p['type']) . " " . $p['name'];
+ if (isset($p['explicit']) && $p['explicit'] == 1) {
+ $pstr .= " (explicit)";
+ }
+ }
+ }
+ $info[$key] = $pstr;
+ break;
+ }
+ case 'configure_options' : {
+ foreach ($info[$key] as $i => $p) {
+ $info[$key][$i] = array_map(null, array_keys($p), array_values($p));
+ $info[$key][$i] = array_map(create_function('$a',
+ 'return join(" = ",$a);'), $info[$key][$i]);
+ $info[$key][$i] = implode(', ', $info[$key][$i]);
+ }
+ $info[$key] = implode("\n", $info[$key]);
+ break;
+ }
+ default: {
+ $info[$key] = implode(", ", $info[$key]);
+ break;
+ }
+ }
+ }
+
+ if ($key == '_lastmodified') {
+ $hdate = date('Y-m-d', $info[$key]);
+ unset($info[$key]);
+ $info['Last Modified'] = $hdate;
+ } elseif ($key == '_lastversion') {
+ $info['Previous Installed Version'] = $info[$key] ? $info[$key] : '- None -';
+ unset($info[$key]);
+ } else {
+ $info[$key] = trim($info[$key]);
+ if (in_array($key, $longtext)) {
+ $info[$key] = preg_replace('/ +/', ' ', $info[$key]);
+ }
+ }
+ }
+
+ $caption = 'About ' . $info['package'] . '-' . $info['version'];
+ $data = array(
+ 'caption' => $caption,
+ 'border' => true);
+ foreach ($info as $key => $value) {
+ $key = ucwords(trim(str_replace('_', ' ', $key)));
+ $data['data'][] = array($key, $value);
+ }
+ $data['raw'] = $info;
+
+ $this->ui->outputData($data, 'package-info');
+ }
+
+ /**
+ * @access private
+ */
+ function _doInfo2($command, $options, $params, &$obj, $installed)
+ {
+ $reg = &$this->config->getRegistry();
+ $caption = 'About ' . $obj->getChannel() . '/' .$obj->getPackage() . '-' .
+ $obj->getVersion();
+ $data = array(
+ 'caption' => $caption,
+ 'border' => true);
+ switch ($obj->getPackageType()) {
+ case 'php' :
+ $release = 'PEAR-style PHP-based Package';
+ break;
+ case 'extsrc' :
+ $release = 'PECL-style PHP extension (source code)';
+ break;
+ case 'zendextsrc' :
+ $release = 'PECL-style Zend extension (source code)';
+ break;
+ case 'extbin' :
+ $release = 'PECL-style PHP extension (binary)';
+ break;
+ case 'zendextbin' :
+ $release = 'PECL-style Zend extension (binary)';
+ break;
+ case 'bundle' :
+ $release = 'Package bundle (collection of packages)';
+ break;
+ }
+ $extends = $obj->getExtends();
+ $extends = $extends ?
+ $obj->getPackage() . ' (extends ' . $extends . ')' : $obj->getPackage();
+ if ($src = $obj->getSourcePackage()) {
+ $extends .= ' (source package ' . $src['channel'] . '/' . $src['package'] . ')';
+ }
+
+ $info = array(
+ 'Release Type' => $release,
+ 'Name' => $extends,
+ 'Channel' => $obj->getChannel(),
+ 'Summary' => preg_replace('/ +/', ' ', $obj->getSummary()),
+ 'Description' => preg_replace('/ +/', ' ', $obj->getDescription()),
+ );
+ $info['Maintainers'] = '';
+ foreach (array('lead', 'developer', 'contributor', 'helper') as $role) {
+ $leads = $obj->{"get{$role}s"}();
+ if (!$leads) {
+ continue;
+ }
+
+ if (isset($leads['active'])) {
+ $leads = array($leads);
+ }
+
+ foreach ($leads as $lead) {
+ if (!empty($info['Maintainers'])) {
+ $info['Maintainers'] .= "\n";
+ }
+
+ $active = $lead['active'] == 'no' ? ', inactive' : '';
+ $info['Maintainers'] .= $lead['name'] . ' <';
+ $info['Maintainers'] .= $lead['email'] . "> ($role$active)";
+ }
+ }
+
+ $info['Release Date'] = $obj->getDate();
+ if ($time = $obj->getTime()) {
+ $info['Release Date'] .= ' ' . $time;
+ }
+
+ $info['Release Version'] = $obj->getVersion() . ' (' . $obj->getState() . ')';
+ $info['API Version'] = $obj->getVersion('api') . ' (' . $obj->getState('api') . ')';
+ $info['License'] = $obj->getLicense();
+ $uri = $obj->getLicenseLocation();
+ if ($uri) {
+ if (isset($uri['uri'])) {
+ $info['License'] .= ' (' . $uri['uri'] . ')';
+ } else {
+ $extra = $obj->getInstalledLocation($info['filesource']);
+ if ($extra) {
+ $info['License'] .= ' (' . $uri['filesource'] . ')';
+ }
+ }
+ }
+
+ $info['Release Notes'] = $obj->getNotes();
+ if ($compat = $obj->getCompatible()) {
+ if (!isset($compat[0])) {
+ $compat = array($compat);
+ }
+
+ $info['Compatible with'] = '';
+ foreach ($compat as $package) {
+ $info['Compatible with'] .= $package['channel'] . '/' . $package['name'] .
+ "\nVersions >= " . $package['min'] . ', <= ' . $package['max'];
+ if (isset($package['exclude'])) {
+ if (is_array($package['exclude'])) {
+ $package['exclude'] = implode(', ', $package['exclude']);
+ }
+
+ if (!isset($info['Not Compatible with'])) {
+ $info['Not Compatible with'] = '';
+ } else {
+ $info['Not Compatible with'] .= "\n";
+ }
+ $info['Not Compatible with'] .= $package['channel'] . '/' .
+ $package['name'] . "\nVersions " . $package['exclude'];
+ }
+ }
+ }
+
+ $usesrole = $obj->getUsesrole();
+ if ($usesrole) {
+ if (!isset($usesrole[0])) {
+ $usesrole = array($usesrole);
+ }
+
+ foreach ($usesrole as $roledata) {
+ if (isset($info['Uses Custom Roles'])) {
+ $info['Uses Custom Roles'] .= "\n";
+ } else {
+ $info['Uses Custom Roles'] = '';
+ }
+
+ if (isset($roledata['package'])) {
+ $rolepackage = $reg->parsedPackageNameToString($roledata, true);
+ } else {
+ $rolepackage = $roledata['uri'];
+ }
+ $info['Uses Custom Roles'] .= $roledata['role'] . ' (' . $rolepackage . ')';
+ }
+ }
+
+ $usestask = $obj->getUsestask();
+ if ($usestask) {
+ if (!isset($usestask[0])) {
+ $usestask = array($usestask);
+ }
+
+ foreach ($usestask as $taskdata) {
+ if (isset($info['Uses Custom Tasks'])) {
+ $info['Uses Custom Tasks'] .= "\n";
+ } else {
+ $info['Uses Custom Tasks'] = '';
+ }
+
+ if (isset($taskdata['package'])) {
+ $taskpackage = $reg->parsedPackageNameToString($taskdata, true);
+ } else {
+ $taskpackage = $taskdata['uri'];
+ }
+ $info['Uses Custom Tasks'] .= $taskdata['task'] . ' (' . $taskpackage . ')';
+ }
+ }
+
+ $deps = $obj->getDependencies();
+ $info['Required Dependencies'] = 'PHP version ' . $deps['required']['php']['min'];
+ if (isset($deps['required']['php']['max'])) {
+ $info['Required Dependencies'] .= '-' . $deps['required']['php']['max'] . "\n";
+ } else {
+ $info['Required Dependencies'] .= "\n";
+ }
+
+ if (isset($deps['required']['php']['exclude'])) {
+ if (!isset($info['Not Compatible with'])) {
+ $info['Not Compatible with'] = '';
+ } else {
+ $info['Not Compatible with'] .= "\n";
+ }
+
+ if (is_array($deps['required']['php']['exclude'])) {
+ $deps['required']['php']['exclude'] =
+ implode(', ', $deps['required']['php']['exclude']);
+ }
+ $info['Not Compatible with'] .= "PHP versions\n " .
+ $deps['required']['php']['exclude'];
+ }
+
+ $info['Required Dependencies'] .= 'PEAR installer version';
+ if (isset($deps['required']['pearinstaller']['max'])) {
+ $info['Required Dependencies'] .= 's ' .
+ $deps['required']['pearinstaller']['min'] . '-' .
+ $deps['required']['pearinstaller']['max'];
+ } else {
+ $info['Required Dependencies'] .= ' ' .
+ $deps['required']['pearinstaller']['min'] . ' or newer';
+ }
+
+ if (isset($deps['required']['pearinstaller']['exclude'])) {
+ if (!isset($info['Not Compatible with'])) {
+ $info['Not Compatible with'] = '';
+ } else {
+ $info['Not Compatible with'] .= "\n";
+ }
+
+ if (is_array($deps['required']['pearinstaller']['exclude'])) {
+ $deps['required']['pearinstaller']['exclude'] =
+ implode(', ', $deps['required']['pearinstaller']['exclude']);
+ }
+ $info['Not Compatible with'] .= "PEAR installer\n Versions " .
+ $deps['required']['pearinstaller']['exclude'];
+ }
+
+ foreach (array('Package', 'Extension') as $type) {
+ $index = strtolower($type);
+ if (isset($deps['required'][$index])) {
+ if (isset($deps['required'][$index]['name'])) {
+ $deps['required'][$index] = array($deps['required'][$index]);
+ }
+
+ foreach ($deps['required'][$index] as $package) {
+ if (isset($package['conflicts'])) {
+ $infoindex = 'Not Compatible with';
+ if (!isset($info['Not Compatible with'])) {
+ $info['Not Compatible with'] = '';
+ } else {
+ $info['Not Compatible with'] .= "\n";
+ }
+ } else {
+ $infoindex = 'Required Dependencies';
+ $info[$infoindex] .= "\n";
+ }
+
+ if ($index == 'extension') {
+ $name = $package['name'];
+ } else {
+ if (isset($package['channel'])) {
+ $name = $package['channel'] . '/' . $package['name'];
+ } else {
+ $name = '__uri/' . $package['name'] . ' (static URI)';
+ }
+ }
+
+ $info[$infoindex] .= "$type $name";
+ if (isset($package['uri'])) {
+ $info[$infoindex] .= "\n Download URI: $package[uri]";
+ continue;
+ }
+
+ if (isset($package['max']) && isset($package['min'])) {
+ $info[$infoindex] .= " \n Versions " .
+ $package['min'] . '-' . $package['max'];
+ } elseif (isset($package['min'])) {
+ $info[$infoindex] .= " \n Version " .
+ $package['min'] . ' or newer';
+ } elseif (isset($package['max'])) {
+ $info[$infoindex] .= " \n Version " .
+ $package['max'] . ' or older';
+ }
+
+ if (isset($package['recommended'])) {
+ $info[$infoindex] .= "\n Recommended version: $package[recommended]";
+ }
+
+ if (isset($package['exclude'])) {
+ if (!isset($info['Not Compatible with'])) {
+ $info['Not Compatible with'] = '';
+ } else {
+ $info['Not Compatible with'] .= "\n";
+ }
+
+ if (is_array($package['exclude'])) {
+ $package['exclude'] = implode(', ', $package['exclude']);
+ }
+
+ $package['package'] = $package['name']; // for parsedPackageNameToString
+ if (isset($package['conflicts'])) {
+ $info['Not Compatible with'] .= '=> except ';
+ }
+ $info['Not Compatible with'] .= 'Package ' .
+ $reg->parsedPackageNameToString($package, true);
+ $info['Not Compatible with'] .= "\n Versions " . $package['exclude'];
+ }
+ }
+ }
+ }
+
+ if (isset($deps['required']['os'])) {
+ if (isset($deps['required']['os']['name'])) {
+ $dep['required']['os']['name'] = array($dep['required']['os']['name']);
+ }
+
+ foreach ($dep['required']['os'] as $os) {
+ if (isset($os['conflicts']) && $os['conflicts'] == 'yes') {
+ if (!isset($info['Not Compatible with'])) {
+ $info['Not Compatible with'] = '';
+ } else {
+ $info['Not Compatible with'] .= "\n";
+ }
+ $info['Not Compatible with'] .= "$os[name] Operating System";
+ } else {
+ $info['Required Dependencies'] .= "\n";
+ $info['Required Dependencies'] .= "$os[name] Operating System";
+ }
+ }
+ }
+
+ if (isset($deps['required']['arch'])) {
+ if (isset($deps['required']['arch']['pattern'])) {
+ $dep['required']['arch']['pattern'] = array($dep['required']['os']['pattern']);
+ }
+
+ foreach ($dep['required']['arch'] as $os) {
+ if (isset($os['conflicts']) && $os['conflicts'] == 'yes') {
+ if (!isset($info['Not Compatible with'])) {
+ $info['Not Compatible with'] = '';
+ } else {
+ $info['Not Compatible with'] .= "\n";
+ }
+ $info['Not Compatible with'] .= "OS/Arch matching pattern '/$os[pattern]/'";
+ } else {
+ $info['Required Dependencies'] .= "\n";
+ $info['Required Dependencies'] .= "OS/Arch matching pattern '/$os[pattern]/'";
+ }
+ }
+ }
+
+ if (isset($deps['optional'])) {
+ foreach (array('Package', 'Extension') as $type) {
+ $index = strtolower($type);
+ if (isset($deps['optional'][$index])) {
+ if (isset($deps['optional'][$index]['name'])) {
+ $deps['optional'][$index] = array($deps['optional'][$index]);
+ }
+
+ foreach ($deps['optional'][$index] as $package) {
+ if (isset($package['conflicts']) && $package['conflicts'] == 'yes') {
+ $infoindex = 'Not Compatible with';
+ if (!isset($info['Not Compatible with'])) {
+ $info['Not Compatible with'] = '';
+ } else {
+ $info['Not Compatible with'] .= "\n";
+ }
+ } else {
+ $infoindex = 'Optional Dependencies';
+ if (!isset($info['Optional Dependencies'])) {
+ $info['Optional Dependencies'] = '';
+ } else {
+ $info['Optional Dependencies'] .= "\n";
+ }
+ }
+
+ if ($index == 'extension') {
+ $name = $package['name'];
+ } else {
+ if (isset($package['channel'])) {
+ $name = $package['channel'] . '/' . $package['name'];
+ } else {
+ $name = '__uri/' . $package['name'] . ' (static URI)';
+ }
+ }
+
+ $info[$infoindex] .= "$type $name";
+ if (isset($package['uri'])) {
+ $info[$infoindex] .= "\n Download URI: $package[uri]";
+ continue;
+ }
+
+ if ($infoindex == 'Not Compatible with') {
+ // conflicts is only used to say that all versions conflict
+ continue;
+ }
+
+ if (isset($package['max']) && isset($package['min'])) {
+ $info[$infoindex] .= " \n Versions " .
+ $package['min'] . '-' . $package['max'];
+ } elseif (isset($package['min'])) {
+ $info[$infoindex] .= " \n Version " .
+ $package['min'] . ' or newer';
+ } elseif (isset($package['max'])) {
+ $info[$infoindex] .= " \n Version " .
+ $package['min'] . ' or older';
+ }
+
+ if (isset($package['recommended'])) {
+ $info[$infoindex] .= "\n Recommended version: $package[recommended]";
+ }
+
+ if (isset($package['exclude'])) {
+ if (!isset($info['Not Compatible with'])) {
+ $info['Not Compatible with'] = '';
+ } else {
+ $info['Not Compatible with'] .= "\n";
+ }
+
+ if (is_array($package['exclude'])) {
+ $package['exclude'] = implode(', ', $package['exclude']);
+ }
+
+ $info['Not Compatible with'] .= "Package $package\n Versions " .
+ $package['exclude'];
+ }
+ }
+ }
+ }
+ }
+
+ if (isset($deps['group'])) {
+ if (!isset($deps['group'][0])) {
+ $deps['group'] = array($deps['group']);
+ }
+
+ foreach ($deps['group'] as $group) {
+ $info['Dependency Group ' . $group['attribs']['name']] = $group['attribs']['hint'];
+ $groupindex = $group['attribs']['name'] . ' Contents';
+ $info[$groupindex] = '';
+ foreach (array('Package', 'Extension') as $type) {
+ $index = strtolower($type);
+ if (isset($group[$index])) {
+ if (isset($group[$index]['name'])) {
+ $group[$index] = array($group[$index]);
+ }
+
+ foreach ($group[$index] as $package) {
+ if (!empty($info[$groupindex])) {
+ $info[$groupindex] .= "\n";
+ }
+
+ if ($index == 'extension') {
+ $name = $package['name'];
+ } else {
+ if (isset($package['channel'])) {
+ $name = $package['channel'] . '/' . $package['name'];
+ } else {
+ $name = '__uri/' . $package['name'] . ' (static URI)';
+ }
+ }
+
+ if (isset($package['uri'])) {
+ if (isset($package['conflicts']) && $package['conflicts'] == 'yes') {
+ $info[$groupindex] .= "Not Compatible with $type $name";
+ } else {
+ $info[$groupindex] .= "$type $name";
+ }
+
+ $info[$groupindex] .= "\n Download URI: $package[uri]";
+ continue;
+ }
+
+ if (isset($package['conflicts']) && $package['conflicts'] == 'yes') {
+ $info[$groupindex] .= "Not Compatible with $type $name";
+ continue;
+ }
+
+ $info[$groupindex] .= "$type $name";
+ if (isset($package['max']) && isset($package['min'])) {
+ $info[$groupindex] .= " \n Versions " .
+ $package['min'] . '-' . $package['max'];
+ } elseif (isset($package['min'])) {
+ $info[$groupindex] .= " \n Version " .
+ $package['min'] . ' or newer';
+ } elseif (isset($package['max'])) {
+ $info[$groupindex] .= " \n Version " .
+ $package['min'] . ' or older';
+ }
+
+ if (isset($package['recommended'])) {
+ $info[$groupindex] .= "\n Recommended version: $package[recommended]";
+ }
+
+ if (isset($package['exclude'])) {
+ if (!isset($info['Not Compatible with'])) {
+ $info['Not Compatible with'] = '';
+ } else {
+ $info[$groupindex] .= "Not Compatible with\n";
+ }
+
+ if (is_array($package['exclude'])) {
+ $package['exclude'] = implode(', ', $package['exclude']);
+ }
+ $info[$groupindex] .= " Package $package\n Versions " .
+ $package['exclude'];
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if ($obj->getPackageType() == 'bundle') {
+ $info['Bundled Packages'] = '';
+ foreach ($obj->getBundledPackages() as $package) {
+ if (!empty($info['Bundled Packages'])) {
+ $info['Bundled Packages'] .= "\n";
+ }
+
+ if (isset($package['uri'])) {
+ $info['Bundled Packages'] .= '__uri/' . $package['name'];
+ $info['Bundled Packages'] .= "\n (URI: $package[uri]";
+ } else {
+ $info['Bundled Packages'] .= $package['channel'] . '/' . $package['name'];
+ }
+ }
+ }
+
+ $info['package.xml version'] = '2.0';
+ if ($installed) {
+ if ($obj->getLastModified()) {
+ $info['Last Modified'] = date('Y-m-d H:i', $obj->getLastModified());
+ }
+
+ $v = $obj->getLastInstalledVersion();
+ $info['Previous Installed Version'] = $v ? $v : '- None -';
+ }
+
+ foreach ($info as $key => $value) {
+ $data['data'][] = array($key, $value);
+ }
+
+ $data['raw'] = $obj->getArray(); // no validation needed
+ $this->ui->outputData($data, 'package-info');
+ }
+}<commands version="1.0">
+ <list>
+ <summary>List Installed Packages In The Default Channel</summary>
+ <function>doList</function>
+ <shortcut>l</shortcut>
+ <options>
+ <channel>
+ <shortopt>c</shortopt>
+ <doc>list installed packages from this channel</doc>
+ <arg>CHAN</arg>
+ </channel>
+ <allchannels>
+ <shortopt>a</shortopt>
+ <doc>list installed packages from all channels</doc>
+ </allchannels>
+ <channelinfo>
+ <shortopt>i</shortopt>
+ <doc>output fully channel-aware data, even on failure</doc>
+ </channelinfo>
+ </options>
+ <doc>&lt;package&gt;
+If invoked without parameters, this command lists the PEAR packages
+installed in your php_dir ({config php_dir}). With a parameter, it
+lists the files in a package.
+</doc>
+ </list>
+ <list-files>
+ <summary>List Files In Installed Package</summary>
+ <function>doFileList</function>
+ <shortcut>fl</shortcut>
+ <options />
+ <doc>&lt;package&gt;
+List the files in an installed package.
+</doc>
+ </list-files>
+ <shell-test>
+ <summary>Shell Script Test</summary>
+ <function>doShellTest</function>
+ <shortcut>st</shortcut>
+ <options />
+ <doc>&lt;package&gt; [[relation] version]
+Tests if a package is installed in the system. Will exit(1) if it is not.
+ &lt;relation&gt; The version comparison operator. One of:
+ &lt;, lt, &lt;=, le, &gt;, gt, &gt;=, ge, ==, =, eq, !=, &lt;&gt;, ne
+ &lt;version&gt; The version to compare with
+</doc>
+ </shell-test>
+ <info>
+ <summary>Display information about a package</summary>
+ <function>doInfo</function>
+ <shortcut>in</shortcut>
+ <options />
+ <doc>&lt;package&gt;
+Displays information about a package. The package argument may be a
+local package file, an URL to a package file, or the name of an
+installed package.</doc>
+ </info>
+</commands><?php
+/**
+ * PEAR_Command_Remote (remote-info, list-upgrades, remote-list, search, list-all, download,
+ * clear-cache commands)
+ *
+ * PHP versions 4 and 5
+ *
+ * @category pear
+ * @package PEAR
+ * @author Stig Bakken <ssb@php.net>
+ * @author Greg Beaver <cellog@php.net>
+ * @copyright 1997-2009 The Authors
+ * @license http://opensource.org/licenses/bsd-license.php New BSD License
+ * @version CVS: $Id: Remote.php 313023 2011-07-06 19:17:11Z dufuz $
+ * @link http://pear.php.net/package/PEAR
+ * @since File available since Release 0.1
+ */
+
+/**
+ * base class
+ */
+require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Command/Common.php';
+require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/REST.php';
+
+/**
+ * PEAR commands for remote server querying
+ *
+ * @category pear
+ * @package PEAR
+ * @author Stig Bakken <ssb@php.net>
+ * @author Greg Beaver <cellog@php.net>
+ * @copyright 1997-2009 The Authors
+ * @license http://opensource.org/licenses/bsd-license.php New BSD License
+ * @version Release: 1.9.4
+ * @link http://pear.php.net/package/PEAR
+ * @since Class available since Release 0.1
+ */
+class PEAR_Command_Remote extends PEAR_Command_Common
+{
+ var $commands = array(
+ 'remote-info' => array(
+ 'summary' => 'Information About Remote Packages',
+ 'function' => 'doRemoteInfo',
+ 'shortcut' => 'ri',
+ 'options' => array(),
+ 'doc' => '<package>
+Get details on a package from the server.',
+ ),
+ 'list-upgrades' => array(
+ 'summary' => 'List Available Upgrades',
+ 'function' => 'doListUpgrades',
+ 'shortcut' => 'lu',
+ 'options' => array(
+ 'channelinfo' => array(
+ 'shortopt' => 'i',
+ 'doc' => 'output fully channel-aware data, even on failure',
+ ),
+ ),
+ 'doc' => '[preferred_state]
+List releases on the server of packages you have installed where
+a newer version is available with the same release state (stable etc.)
+or the state passed as the second parameter.'
+ ),
+ 'remote-list' => array(
+ 'summary' => 'List Remote Packages',
+ 'function' => 'doRemoteList',
+ 'shortcut' => 'rl',
+ 'options' => array(
+ 'channel' =>
+ array(
+ 'shortopt' => 'c',
+ 'doc' => 'specify a channel other than the default channel',
+ 'arg' => 'CHAN',
+ )
+ ),
+ 'doc' => '
+Lists the packages available on the configured server along with the
+latest stable release of each package.',
+ ),
+ 'search' => array(
+ 'summary' => 'Search remote package database',
+ 'function' => 'doSearch',
+ 'shortcut' => 'sp',
+ 'options' => array(
+ 'channel' =>
+ array(
+ 'shortopt' => 'c',
+ 'doc' => 'specify a channel other than the default channel',
+ 'arg' => 'CHAN',
+ ),
+ 'allchannels' => array(
+ 'shortopt' => 'a',
+ 'doc' => 'search packages from all known channels',
+ ),
+ 'channelinfo' => array(
+ 'shortopt' => 'i',
+ 'doc' => 'output fully channel-aware data, even on failure',
+ ),
+ ),
+ 'doc' => '[packagename] [packageinfo]
+Lists all packages which match the search parameters. The first
+parameter is a fragment of a packagename. The default channel
+will be used unless explicitly overridden. The second parameter
+will be used to match any portion of the summary/description',
+ ),
+ 'list-all' => array(
+ 'summary' => 'List All Packages',
+ 'function' => 'doListAll',
+ 'shortcut' => 'la',
+ 'options' => array(
+ 'channel' =>
+ array(
+ 'shortopt' => 'c',
+ 'doc' => 'specify a channel other than the default channel',
+ 'arg' => 'CHAN',
+ ),
+ 'channelinfo' => array(
+ 'shortopt' => 'i',
+ 'doc' => 'output fully channel-aware data, even on failure',
+ ),
+ ),
+ 'doc' => '
+Lists the packages available on the configured server along with the
+latest stable release of each package.',
+ ),
+ 'download' => array(
+ 'summary' => 'Download Package',
+ 'function' => 'doDownload',
+ 'shortcut' => 'd',
+ 'options' => array(
+ 'nocompress' => array(
+ 'shortopt' => 'Z',
+ 'doc' => 'download an uncompressed (.tar) file',
+ ),
+ ),
+ 'doc' => '<package>...
+Download package tarballs. The files will be named as suggested by the
+server, for example if you download the DB package and the latest stable
+version of DB is 1.6.5, the downloaded file will be DB-1.6.5.tgz.',
+ ),
+ 'clear-cache' => array(
+ 'summary' => 'Clear Web Services Cache',
+ 'function' => 'doClearCache',
+ 'shortcut' => 'cc',
+ 'options' => array(),
+ 'doc' => '
+Clear the REST cache. See also the cache_ttl configuration
+parameter.
+',
+ ),
+ );
+
+ /**
+ * PEAR_Command_Remote constructor.
+ *
+ * @access public
+ */
+ function PEAR_Command_Remote(&$ui, &$config)
+ {
+ parent::PEAR_Command_Common($ui, $config);
+ }
+
+ function _checkChannelForStatus($channel, $chan)
+ {
+ if (PEAR::isError($chan)) {
+ $this->raiseError($chan);
+ }
+ if (!is_a($chan, 'PEAR_ChannelFile')) {
+ return $this->raiseError('Internal corruption error: invalid channel "' .
+ $channel . '"');
+ }
+ $rest = new PEAR_REST($this->config);
+ PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
+ $mirror = $this->config->get('preferred_mirror', null,
+ $channel);
+ $a = $rest->downloadHttp('http://' . $channel .
+ '/channel.xml', $chan->lastModified());
+ PEAR::staticPopErrorHandling();
+ if (!PEAR::isError($a) && $a) {
+ $this->ui->outputData('WARNING: channel "' . $channel . '" has ' .
+ 'updated its protocols, use "' . PEAR_RUNTYPE . ' channel-update ' . $channel .
+ '" to update');
+ }
+ }
+
+ function doRemoteInfo($command, $options, $params)
+ {
+ if (sizeof($params) != 1) {
+ return $this->raiseError("$command expects one param: the remote package name");
+ }
+ $savechannel = $channel = $this->config->get('default_channel');
+ $reg = &$this->config->getRegistry();
+ $package = $params[0];
+ $parsed = $reg->parsePackageName($package, $channel);
+ if (PEAR::isError($parsed)) {
+ return $this->raiseError('Invalid package name "' . $package . '"');
+ }
+
+ $channel = $parsed['channel'];
+ $this->config->set('default_channel', $channel);
+ $chan = $reg->getChannel($channel);
+ if (PEAR::isError($e = $this->_checkChannelForStatus($channel, $chan))) {
+ return $e;
+ }
+
+ $mirror = $this->config->get('preferred_mirror');
+ if ($chan->supportsREST($mirror) && $base = $chan->getBaseURL('REST1.0', $mirror)) {
+ $rest = &$this->config->getREST('1.0', array());
+ $info = $rest->packageInfo($base, $parsed['package'], $channel);
+ }
+
+ if (!isset($info)) {
+ return $this->raiseError('No supported protocol was found');
+ }
+
+ if (PEAR::isError($info)) {
+ $this->config->set('default_channel', $savechannel);
+ return $this->raiseError($info);
+ }
+
+ if (!isset($info['name'])) {
+ return $this->raiseError('No remote package "' . $package . '" was found');
+ }
+
+ $installed = $reg->packageInfo($info['name'], null, $channel);
+ $info['installed'] = $installed['version'] ? $installed['version'] : '- no -';
+ if (is_array($info['installed'])) {
+ $info['installed'] = $info['installed']['release'];
+ }
+
+ $this->ui->outputData($info, $command);
+ $this->config->set('default_channel', $savechannel);
+
+ return true;
+ }
+
+ function doRemoteList($command, $options, $params)
+ {
+ $savechannel = $channel = $this->config->get('default_channel');
+ $reg = &$this->config->getRegistry();
+ if (isset($options['channel'])) {
+ $channel = $options['channel'];
+ if (!$reg->channelExists($channel)) {
+ return $this->raiseError('Channel "' . $channel . '" does not exist');
+ }
+
+ $this->config->set('default_channel', $channel);
+ }
+
+ $chan = $reg->getChannel($channel);
+ if (PEAR::isError($e = $this->_checkChannelForStatus($channel, $chan))) {
+ return $e;
+ }
+
+ $list_options = false;
+ if ($this->config->get('preferred_state') == 'stable') {
+ $list_options = true;
+ }
+
+ $available = array();
+ if ($chan->supportsREST($this->config->get('preferred_mirror')) &&
+ $base = $chan->getBaseURL('REST1.1', $this->config->get('preferred_mirror'))
+ ) {
+ // use faster list-all if available
+ $rest = &$this->config->getREST('1.1', array());
+ $available = $rest->listAll($base, $list_options, true, false, false, $chan->getName());
+ } elseif ($chan->supportsREST($this->config->get('preferred_mirror')) &&
+ $base = $chan->getBaseURL('REST1.0', $this->config->get('preferred_mirror'))) {
+ $rest = &$this->config->getREST('1.0', array());
+ $available = $rest->listAll($base, $list_options, true, false, false, $chan->getName());
+ }
+
+ if (PEAR::isError($available)) {
+ $this->config->set('default_channel', $savechannel);
+ return $this->raiseError($available);
+ }
+
+ $i = $j = 0;
+ $data = array(
+ 'caption' => 'Channel ' . $channel . ' Available packages:',
+ 'border' => true,
+ 'headline' => array('Package', 'Version'),
+ 'channel' => $channel
+ );
+
+ if (count($available) == 0) {
+ $data = '(no packages available yet)';
+ } else {
+ foreach ($available as $name => $info) {
+ $version = (isset($info['stable']) && $info['stable']) ? $info['stable'] : '-n/a-';
+ $data['data'][] = array($name, $version);
+ }
+ }
+ $this->ui->outputData($data, $command);
+ $this->config->set('default_channel', $savechannel);
+ return true;
+ }
+
+ function doListAll($command, $options, $params)
+ {
+ $savechannel = $channel = $this->config->get('default_channel');
+ $reg = &$this->config->getRegistry();
+ if (isset($options['channel'])) {
+ $channel = $options['channel'];
+ if (!$reg->channelExists($channel)) {
+ return $this->raiseError("Channel \"$channel\" does not exist");
+ }
+
+ $this->config->set('default_channel', $channel);
+ }
+
+ $list_options = false;
+ if ($this->config->get('preferred_state') == 'stable') {
+ $list_options = true;
+ }
+
+ $chan = $reg->getChannel($channel);
+ if (PEAR::isError($e = $this->_checkChannelForStatus($channel, $chan))) {
+ return $e;
+ }
+
+ if ($chan->supportsREST($this->config->get('preferred_mirror')) &&
+ $base = $chan->getBaseURL('REST1.1', $this->config->get('preferred_mirror'))) {
+ // use faster list-all if available
+ $rest = &$this->config->getREST('1.1', array());
+ $available = $rest->listAll($base, $list_options, false, false, false, $chan->getName());
+ } elseif ($chan->supportsREST($this->config->get('preferred_mirror')) &&
+ $base = $chan->getBaseURL('REST1.0', $this->config->get('preferred_mirror'))) {
+ $rest = &$this->config->getREST('1.0', array());
+ $available = $rest->listAll($base, $list_options, false, false, false, $chan->getName());
+ }
+
+ if (PEAR::isError($available)) {
+ $this->config->set('default_channel', $savechannel);
+ return $this->raiseError('The package list could not be fetched from the remote server. Please try again. (Debug info: "' . $available->getMessage() . '")');
+ }
+
+ $data = array(
+ 'caption' => 'All packages [Channel ' . $channel . ']:',
+ 'border' => true,
+ 'headline' => array('Package', 'Latest', 'Local'),
+ 'channel' => $channel,
+ );
+
+ if (isset($options['channelinfo'])) {
+ // add full channelinfo
+ $data['caption'] = 'Channel ' . $channel . ' All packages:';
+ $data['headline'] = array('Channel', 'Package', 'Latest', 'Local',
+ 'Description', 'Dependencies');
+ }
+ $local_pkgs = $reg->listPackages($channel);
+
+ foreach ($available as $name => $info) {
+ $installed = $reg->packageInfo($name, null, $channel);
+ if (is_array($installed['version'])) {
+ $installed['version'] = $installed['version']['release'];
+ }
+ $desc = $info['summary'];
+ if (isset($params[$name])) {
+ $desc .= "\n\n".$info['description'];
+ }
+ if (isset($options['mode']))
+ {
+ if ($options['mode'] == 'installed' && !isset($installed['version'])) {
+ continue;
+ }
+ if ($options['mode'] == 'notinstalled' && isset($installed['version'])) {
+ continue;
+ }
+ if ($options['mode'] == 'upgrades'
+ && (!isset($installed['version']) || version_compare($installed['version'],
+ $info['stable'], '>='))) {
+ continue;
+ }
+ }
+ $pos = array_search(strtolower($name), $local_pkgs);
+ if ($pos !== false) {
+ unset($local_pkgs[$pos]);
+ }
+
+ if (isset($info['stable']) && !$info['stable']) {
+ $info['stable'] = null;
+ }
+
+ if (isset($options['channelinfo'])) {
+ // add full channelinfo
+ if ($info['stable'] === $info['unstable']) {
+ $state = $info['state'];
+ } else {
+ $state = 'stable';
+ }
+ $latest = $info['stable'].' ('.$state.')';
+ $local = '';
+ if (isset($installed['version'])) {
+ $inst_state = $reg->packageInfo($name, 'release_state', $channel);
+ $local = $installed['version'].' ('.$inst_state.')';
+ }
+
+ $packageinfo = array(
+ $channel,
+ $name,
+ $latest,
+ $local,
+ isset($desc) ? $desc : null,
+ isset($info['deps']) ? $info['deps'] : null,
+ );
+ } else {
+ $packageinfo = array(
+ $reg->channelAlias($channel) . '/' . $name,
+ isset($info['stable']) ? $info['stable'] : null,
+ isset($installed['version']) ? $installed['version'] : null,
+ isset($desc) ? $desc : null,
+ isset($info['deps']) ? $info['deps'] : null,
+ );
+ }
+ $data['data'][$info['category']][] = $packageinfo;
+ }
+
+ if (isset($options['mode']) && in_array($options['mode'], array('notinstalled', 'upgrades'))) {
+ $this->config->set('default_channel', $savechannel);
+ $this->ui->outputData($data, $command);
+ return true;
+ }
+
+ foreach ($local_pkgs as $name) {
+ $info = &$reg->getPackage($name, $channel);
+ $data['data']['Local'][] = array(
+ $reg->channelAlias($channel) . '/' . $info->getPackage(),
+ '',
+ $info->getVersion(),
+ $info->getSummary(),
+ $info->getDeps()
+ );
+ }
+
+ $this->config->set('default_channel', $savechannel);
+ $this->ui->outputData($data, $command);
+ return true;
+ }
+
+ function doSearch($command, $options, $params)
+ {
+ if ((!isset($params[0]) || empty($params[0]))
+ && (!isset($params[1]) || empty($params[1])))
+ {
+ return $this->raiseError('no valid search string supplied');
+ }
+
+ $channelinfo = isset($options['channelinfo']);
+ $reg = &$this->config->getRegistry();
+ if (isset($options['allchannels'])) {
+ // search all channels
+ unset($options['allchannels']);
+ $channels = $reg->getChannels();
+ $errors = array();
+ PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
+ foreach ($channels as $channel) {
+ if ($channel->getName() != '__uri') {
+ $options['channel'] = $channel->getName();
+ $ret = $this->doSearch($command, $options, $params);
+ if (PEAR::isError($ret)) {
+ $errors[] = $ret;
+ }
+ }
+ }
+
+ PEAR::staticPopErrorHandling();
+ if (count($errors) !== 0) {
+ // for now, only give first error
+ return PEAR::raiseError($errors[0]);
+ }
+
+ return true;
+ }
+
+ $savechannel = $channel = $this->config->get('default_channel');
+ $package = strtolower($params[0]);
+ $summary = isset($params[1]) ? $params[1] : false;
+ if (isset($options['channel'])) {
+ $reg = &$this->config->getRegistry();
+ $channel = $options['channel'];
+ if (!$reg->channelExists($channel)) {
+ return $this->raiseError('Channel "' . $channel . '" does not exist');
+ }
+
+ $this->config->set('default_channel', $channel);
+ }
+
+ $chan = $reg->getChannel($channel);
+ if (PEAR::isError($e = $this->_checkChannelForStatus($channel, $chan))) {
+ return $e;
+ }
+
+ if ($chan->supportsREST($this->config->get('preferred_mirror')) &&
+ $base = $chan->getBaseURL('REST1.0', $this->config->get('preferred_mirror'))) {
+ $rest = &$this->config->getREST('1.0', array());
+ $available = $rest->listAll($base, false, false, $package, $summary, $chan->getName());
+ }
+
+ if (PEAR::isError($available)) {
+ $this->config->set('default_channel', $savechannel);
+ return $this->raiseError($available);
+ }
+
+ if (!$available && !$channelinfo) {
+ // clean exit when not found, no error !
+ $data = 'no packages found that match pattern "' . $package . '", for channel '.$channel.'.';
+ $this->ui->outputData($data);
+ $this->config->set('default_channel', $channel);
+ return true;
+ }
+
+ if ($channelinfo) {
+ $data = array(
+ 'caption' => 'Matched packages, channel ' . $channel . ':',
+ 'border' => true,
+ 'headline' => array('Channel', 'Package', 'Stable/(Latest)', 'Local'),
+ 'channel' => $channel
+ );
+ } else {
+ $data = array(
+ 'caption' => 'Matched packages, channel ' . $channel . ':',
+ 'border' => true,
+ 'headline' => array('Package', 'Stable/(Latest)', 'Local'),
+ 'channel' => $channel
+ );
+ }
+
+ if (!$available && $channelinfo) {
+ unset($data['headline']);
+ $data['data'] = 'No packages found that match pattern "' . $package . '".';
+ $available = array();
+ }
+
+ foreach ($available as $name => $info) {
+ $installed = $reg->packageInfo($name, null, $channel);
+ $desc = $info['summary'];
+ if (isset($params[$name]))
+ $desc .= "\n\n".$info['description'];
+
+ if (!isset($info['stable']) || !$info['stable']) {
+ $version_remote = 'none';
+ } else {
+ if ($info['unstable']) {
+ $version_remote = $info['unstable'];
+ } else {
+ $version_remote = $info['stable'];
+ }
+ $version_remote .= ' ('.$info['state'].')';
+ }
+ $version = is_array($installed['version']) ? $installed['version']['release'] :
+ $installed['version'];
+ if ($channelinfo) {
+ $packageinfo = array(
+ $channel,
+ $name,
+ $version_remote,
+ $version,
+ $desc,
+ );
+ } else {
+ $packageinfo = array(
+ $name,
+ $version_remote,
+ $version,
+ $desc,
+ );
+ }
+ $data['data'][$info['category']][] = $packageinfo;
+ }
+
+ $this->ui->outputData($data, $command);
+ $this->config->set('default_channel', $channel);
+ return true;
+ }
+
+ function &getDownloader($options)
+ {
+ if (!class_exists('PEAR_Downloader')) {
+ require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Downloader.php';
+ }
+ $a = &new PEAR_Downloader($this->ui, $options, $this->config);
+ return $a;
+ }
+
+ function doDownload($command, $options, $params)
+ {
+ // make certain that dependencies are ignored
+ $options['downloadonly'] = 1;
+
+ // eliminate error messages for preferred_state-related errors
+ /* TODO: Should be an option, but until now download does respect
+ prefered state */
+ /* $options['ignorepreferred_state'] = 1; */
+ // eliminate error messages for preferred_state-related errors
+
+ $downloader = &$this->getDownloader($options);
+ PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
+ $e = $downloader->setDownloadDir(getcwd());
+ PEAR::staticPopErrorHandling();
+ if (PEAR::isError($e)) {
+ return $this->raiseError('Current directory is not writeable, cannot download');
+ }
+
+ $errors = array();
+ $downloaded = array();
+ $err = $downloader->download($params);
+ if (PEAR::isError($err)) {
+ return $err;
+ }
+
+ $errors = $downloader->getErrorMsgs();
+ if (count($errors)) {
+ foreach ($errors as $error) {
+ if ($error !== null) {
+ $this->ui->outputData($error);
+ }
+ }
+
+ return $this->raiseError("$command failed");
+ }
+
+ $downloaded = $downloader->getDownloadedPackages();
+ foreach ($downloaded as $pkg) {
+ $this->ui->outputData("File $pkg[file] downloaded", $command);
+ }
+
+ return true;
+ }
+
+ function downloadCallback($msg, $params = null)
+ {
+ if ($msg == 'done') {
+ $this->bytes_downloaded = $params;
+ }
+ }
+
+ function doListUpgrades($command, $options, $params)
+ {
+ require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Common.php';
+ if (isset($params[0]) && !is_array(PEAR_Common::betterStates($params[0]))) {
+ return $this->raiseError($params[0] . ' is not a valid state (stable/beta/alpha/devel/etc.) try "pear help list-upgrades"');
+ }
+
+ $savechannel = $channel = $this->config->get('default_channel');
+ $reg = &$this->config->getRegistry();
+ foreach ($reg->listChannels() as $channel) {
+ $inst = array_flip($reg->listPackages($channel));
+ if (!count($inst)) {
+ continue;
+ }
+
+ if ($channel == '__uri') {
+ continue;
+ }
+
+ $this->config->set('default_channel', $channel);
+ $state = empty($params[0]) ? $this->config->get('preferred_state') : $params[0];
+
+ $caption = $channel . ' Available Upgrades';
+ $chan = $reg->getChannel($channel);
+ if (PEAR::isError($e = $this->_checkChannelForStatus($channel, $chan))) {
+ return $e;
+ }
+
+ $latest = array();
+ $base2 = false;
+ $preferred_mirror = $this->config->get('preferred_mirror');
+ if ($chan->supportsREST($preferred_mirror) &&
+ (
+ //($base2 = $chan->getBaseURL('REST1.4', $preferred_mirror)) ||
+ ($base = $chan->getBaseURL('REST1.0', $preferred_mirror))
+ )
+
+ ) {
+ if ($base2) {
+ $rest = &$this->config->getREST('1.4', array());
+ $base = $base2;
+ } else {
+ $rest = &$this->config->getREST('1.0', array());
+ }
+
+ if (empty($state) || $state == 'any') {
+ $state = false;
+ } else {
+ $caption .= ' (' . implode(', ', PEAR_Common::betterStates($state, true)) . ')';
+ }
+
+ PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
+ $latest = $rest->listLatestUpgrades($base, $state, $inst, $channel, $reg);
+ PEAR::staticPopErrorHandling();
+ }
+
+ if (PEAR::isError($latest)) {
+ $this->ui->outputData($latest->getMessage());
+ continue;
+ }
+
+ $caption .= ':';
+ if (PEAR::isError($latest)) {
+ $this->config->set('default_channel', $savechannel);
+ return $latest;
+ }
+
+ $data = array(
+ 'caption' => $caption,
+ 'border' => 1,
+ 'headline' => array('Channel', 'Package', 'Local', 'Remote', 'Size'),
+ 'channel' => $channel
+ );
+
+ foreach ((array)$latest as $pkg => $info) {
+ $package = strtolower($pkg);
+ if (!isset($inst[$package])) {
+ // skip packages we don't have installed
+ continue;
+ }
+
+ extract($info);
+ $inst_version = $reg->packageInfo($package, 'version', $channel);
+ $inst_state = $reg->packageInfo($package, 'release_state', $channel);
+ if (version_compare("$version", "$inst_version", "le")) {
+ // installed version is up-to-date
+ continue;
+ }
+
+ if ($filesize >= 20480) {
+ $filesize += 1024 - ($filesize % 1024);
+ $fs = sprintf("%dkB", $filesize / 1024);
+ } elseif ($filesize > 0) {
+ $filesize += 103 - ($filesize % 103);
+ $fs = sprintf("%.1fkB", $filesize / 1024.0);
+ } else {
+ $fs = " -"; // XXX center instead
+ }
+
+ $data['data'][] = array($channel, $pkg, "$inst_version ($inst_state)", "$version ($state)", $fs);
+ }
+
+ if (isset($options['channelinfo'])) {
+ if (empty($data['data'])) {
+ unset($data['headline']);
+ if (count($inst) == 0) {
+ $data['data'] = '(no packages installed)';
+ } else {
+ $data['data'] = '(no upgrades available)';
+ }
+ }
+ $this->ui->outputData($data, $command);
+ } else {
+ if (empty($data['data'])) {
+ $this->ui->outputData('Channel ' . $channel . ': No upgrades available');
+ } else {
+ $this->ui->outputData($data, $command);
+ }
+ }
+ }
+
+ $this->config->set('default_channel', $savechannel);
+ return true;
+ }
+
+ function doClearCache($command, $options, $params)
+ {
+ $cache_dir = $this->config->get('cache_dir');
+ $verbose = $this->config->get('verbose');
+ $output = '';
+ if (!file_exists($cache_dir) || !is_dir($cache_dir)) {
+ return $this->raiseError("$cache_dir does not exist or is not a directory");
+ }
+
+ if (!($dp = @opendir($cache_dir))) {
+ return $this->raiseError("opendir($cache_dir) failed: $php_errormsg");
+ }
+
+ if ($verbose >= 1) {
+ $output .= "reading directory $cache_dir\n";
+ }
+
+ $num = 0;
+ while ($ent = readdir($dp)) {
+ if (preg_match('/rest.cache(file|id)\\z/', $ent)) {
+ $path = $cache_dir . DIRECTORY_SEPARATOR . $ent;
+ if (file_exists($path)) {
+ $ok = @unlink($path);
+ } else {
+ $ok = false;
+ $php_errormsg = '';
+ }
+
+ if ($ok) {
+ if ($verbose >= 2) {
+ $output .= "deleted $path\n";
+ }
+ $num++;
+ } elseif ($verbose >= 1) {
+ $output .= "failed to delete $path $php_errormsg\n";
+ }
+ }
+ }
+
+ closedir($dp);
+ if ($verbose >= 1) {
+ $output .= "$num cache entries cleared\n";
+ }
+
+ $this->ui->outputData(rtrim($output), $command);
+ return $num;
+ }
+}<commands version="1.0">
+ <remote-info>
+ <summary>Information About Remote Packages</summary>
+ <function>doRemoteInfo</function>
+ <shortcut>ri</shortcut>
+ <options />
+ <doc>&lt;package&gt;
+Get details on a package from the server.</doc>
+ </remote-info>
+ <list-upgrades>
+ <summary>List Available Upgrades</summary>
+ <function>doListUpgrades</function>
+ <shortcut>lu</shortcut>
+ <options>
+ <channelinfo>
+ <shortopt>i</shortopt>
+ <doc>output fully channel-aware data, even on failure</doc>
+ </channelinfo>
+ </options>
+ <doc>[preferred_state]
+List releases on the server of packages you have installed where
+a newer version is available with the same release state (stable etc.)
+or the state passed as the second parameter.</doc>
+ </list-upgrades>
+ <remote-list>
+ <summary>List Remote Packages</summary>
+ <function>doRemoteList</function>
+ <shortcut>rl</shortcut>
+ <options>
+ <channel>
+ <shortopt>c</shortopt>
+ <doc>specify a channel other than the default channel</doc>
+ <arg>CHAN</arg>
+ </channel>
+ </options>
+ <doc>
+Lists the packages available on the configured server along with the
+latest stable release of each package.</doc>
+ </remote-list>
+ <search>
+ <summary>Search remote package database</summary>
+ <function>doSearch</function>
+ <shortcut>sp</shortcut>
+ <options>
+ <channel>
+ <shortopt>c</shortopt>
+ <doc>specify a channel other than the default channel</doc>
+ <arg>CHAN</arg>
+ </channel>
+ <allchannels>
+ <shortopt>a</shortopt>
+ <doc>search packages from all known channels</doc>
+ </allchannels>
+ <channelinfo>
+ <shortopt>i</shortopt>
+ <doc>output fully channel-aware data, even on failure</doc>
+ </channelinfo>
+ </options>
+ <doc>[packagename] [packageinfo]
+Lists all packages which match the search parameters. The first
+parameter is a fragment of a packagename. The default channel
+will be used unless explicitly overridden. The second parameter
+will be used to match any portion of the summary/description</doc>
+ </search>
+ <list-all>
+ <summary>List All Packages</summary>
+ <function>doListAll</function>
+ <shortcut>la</shortcut>
+ <options>
+ <channel>
+ <shortopt>c</shortopt>
+ <doc>specify a channel other than the default channel</doc>
+ <arg>CHAN</arg>
+ </channel>
+ <channelinfo>
+ <shortopt>i</shortopt>
+ <doc>output fully channel-aware data, even on failure</doc>
+ </channelinfo>
+ </options>
+ <doc>
+Lists the packages available on the configured server along with the
+latest stable release of each package.</doc>
+ </list-all>
+ <download>
+ <summary>Download Package</summary>
+ <function>doDownload</function>
+ <shortcut>d</shortcut>
+ <options>
+ <nocompress>
+ <shortopt>Z</shortopt>
+ <doc>download an uncompressed (.tar) file</doc>
+ </nocompress>
+ </options>
+ <doc>&lt;package&gt;...
+Download package tarballs. The files will be named as suggested by the
+server, for example if you download the DB package and the latest stable
+version of DB is 1.6.5, the downloaded file will be DB-1.6.5.tgz.</doc>
+ </download>
+ <clear-cache>
+ <summary>Clear Web Services Cache</summary>
+ <function>doClearCache</function>
+ <shortcut>cc</shortcut>
+ <options />
+ <doc>
+Clear the XML-RPC/REST cache. See also the cache_ttl configuration
+parameter.
+</doc>
+ </clear-cache>
+</commands><?php
+/**
+ * PEAR_Command_Test (run-tests)
+ *
+ * PHP versions 4 and 5
+ *
+ * @category pear
+ * @package PEAR
+ * @author Stig Bakken <ssb@php.net>
+ * @author Martin Jansen <mj@php.net>
+ * @author Greg Beaver <cellog@php.net>
+ * @copyright 1997-2009 The Authors
+ * @license http://opensource.org/licenses/bsd-license.php New BSD License
+ * @version CVS: $Id: Test.php 313023 2011-07-06 19:17:11Z dufuz $
+ * @link http://pear.php.net/package/PEAR
+ * @since File available since Release 0.1
+ */
+
+/**
+ * base class
+ */
+require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Command/Common.php';
+
+/**
+ * PEAR commands for login/logout
+ *
+ * @category pear
+ * @package PEAR
+ * @author Stig Bakken <ssb@php.net>
+ * @author Martin Jansen <mj@php.net>
+ * @author Greg Beaver <cellog@php.net>
+ * @copyright 1997-2009 The Authors
+ * @license http://opensource.org/licenses/bsd-license.php New BSD License
+ * @version Release: 1.9.4
+ * @link http://pear.php.net/package/PEAR
+ * @since Class available since Release 0.1
+ */
+
+class PEAR_Command_Test extends PEAR_Command_Common
+{
+ var $commands = array(
+ 'run-tests' => array(
+ 'summary' => 'Run Regression Tests',
+ 'function' => 'doRunTests',
+ 'shortcut' => 'rt',
+ 'options' => array(
+ 'recur' => array(
+ 'shortopt' => 'r',
+ 'doc' => 'Run tests in child directories, recursively. 4 dirs deep maximum',
+ ),
+ 'ini' => array(
+ 'shortopt' => 'i',
+ 'doc' => 'actual string of settings to pass to php in format " -d setting=blah"',
+ 'arg' => 'SETTINGS'
+ ),
+ 'realtimelog' => array(
+ 'shortopt' => 'l',
+ 'doc' => 'Log test runs/results as they are run',
+ ),
+ 'quiet' => array(
+ 'shortopt' => 'q',
+ 'doc' => 'Only display detail for failed tests',
+ ),
+ 'simple' => array(
+ 'shortopt' => 's',
+ 'doc' => 'Display simple output for all tests',
+ ),
+ 'package' => array(
+ 'shortopt' => 'p',
+ 'doc' => 'Treat parameters as installed packages from which to run tests',
+ ),
+ 'phpunit' => array(
+ 'shortopt' => 'u',
+ 'doc' => 'Search parameters for AllTests.php, and use that to run phpunit-based tests
+If none is found, all .phpt tests will be tried instead.',
+ ),
+ 'tapoutput' => array(
+ 'shortopt' => 't',
+ 'doc' => 'Output run-tests.log in TAP-compliant format',
+ ),
+ 'cgi' => array(
+ 'shortopt' => 'c',
+ 'doc' => 'CGI php executable (needed for tests with POST/GET section)',
+ 'arg' => 'PHPCGI',
+ ),
+ 'coverage' => array(
+ 'shortopt' => 'x',
+ 'doc' => 'Generate a code coverage report (requires Xdebug 2.0.0+)',
+ ),
+ ),
+ 'doc' => '[testfile|dir ...]
+Run regression tests with PHP\'s regression testing script (run-tests.php).',
+ ),
+ );
+
+ var $output;
+
+ /**
+ * PEAR_Command_Test constructor.
+ *
+ * @access public
+ */
+ function PEAR_Command_Test(&$ui, &$config)
+ {
+ parent::PEAR_Command_Common($ui, $config);
+ }
+
+ function doRunTests($command, $options, $params)
+ {
+ if (isset($options['phpunit']) && isset($options['tapoutput'])) {
+ return $this->raiseError('ERROR: cannot use both --phpunit and --tapoutput at the same time');
+ }
+
+ require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Common.php';
+ require_once 'phar://install-pear-nozlib.phar/' . 'System.php';
+ $log = new PEAR_Common;
+ $log->ui = &$this->ui; // slightly hacky, but it will work
+ $tests = array();
+ $depth = isset($options['recur']) ? 14 : 1;
+
+ if (!count($params)) {
+ $params[] = '.';
+ }
+
+ if (isset($options['package'])) {
+ $oldparams = $params;
+ $params = array();
+ $reg = &$this->config->getRegistry();
+ foreach ($oldparams as $param) {
+ $pname = $reg->parsePackageName($param, $this->config->get('default_channel'));
+ if (PEAR::isError($pname)) {
+ return $this->raiseError($pname);
+ }
+
+ $package = &$reg->getPackage($pname['package'], $pname['channel']);
+ if (!$package) {
+ return PEAR::raiseError('Unknown package "' .
+ $reg->parsedPackageNameToString($pname) . '"');
+ }
+
+ $filelist = $package->getFilelist();
+ foreach ($filelist as $name => $atts) {
+ if (isset($atts['role']) && $atts['role'] != 'test') {
+ continue;
+ }
+
+ if (isset($options['phpunit']) && preg_match('/AllTests\.php\\z/i', $name)) {
+ $params[] = $atts['installed_as'];
+ continue;
+ } elseif (!preg_match('/\.phpt\\z/', $name)) {
+ continue;
+ }
+ $params[] = $atts['installed_as'];
+ }
+ }
+ }
+
+ foreach ($params as $p) {
+ if (is_dir($p)) {
+ if (isset($options['phpunit'])) {
+ $dir = System::find(array($p, '-type', 'f',
+ '-maxdepth', $depth,
+ '-name', 'AllTests.php'));
+ if (count($dir)) {
+ foreach ($dir as $p) {
+ $p = realpath($p);
+ if (!count($tests) ||
+ (count($tests) && strlen($p) < strlen($tests[0]))) {
+ // this is in a higher-level directory, use this one instead.
+ $tests = array($p);
+ }
+ }
+ }
+ continue;
+ }
+
+ $args = array($p, '-type', 'f', '-name', '*.phpt');
+ } else {
+ if (isset($options['phpunit'])) {
+ if (preg_match('/AllTests\.php\\z/i', $p)) {
+ $p = realpath($p);
+ if (!count($tests) ||
+ (count($tests) && strlen($p) < strlen($tests[0]))) {
+ // this is in a higher-level directory, use this one instead.
+ $tests = array($p);
+ }
+ }
+ continue;
+ }
+
+ if (file_exists($p) && preg_match('/\.phpt$/', $p)) {
+ $tests[] = $p;
+ continue;
+ }
+
+ if (!preg_match('/\.phpt\\z/', $p)) {
+ $p .= '.phpt';
+ }
+
+ $args = array(dirname($p), '-type', 'f', '-name', $p);
+ }
+
+ if (!isset($options['recur'])) {
+ $args[] = '-maxdepth';
+ $args[] = 1;
+ }
+
+ $dir = System::find($args);
+ $tests = array_merge($tests, $dir);
+ }
+
+ $ini_settings = '';
+ if (isset($options['ini'])) {
+ $ini_settings .= $options['ini'];
+ }
+
+ if (isset($_ENV['TEST_PHP_INCLUDE_PATH'])) {
+ $ini_settings .= " -d include_path={$_ENV['TEST_PHP_INCLUDE_PATH']}";
+ }
+
+ if ($ini_settings) {
+ $this->ui->outputData('Using INI settings: "' . $ini_settings . '"');
+ }
+
+ $skipped = $passed = $failed = array();
+ $tests_count = count($tests);
+ $this->ui->outputData('Running ' . $tests_count . ' tests', $command);
+ $start = time();
+ if (isset($options['realtimelog']) && file_exists('run-tests.log')) {
+ unlink('run-tests.log');
+ }
+
+ if (isset($options['tapoutput'])) {
+ $tap = '1..' . $tests_count . "\n";
+ }
+
+ require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/RunTest.php';
+ $run = new PEAR_RunTest($log, $options);
+ $run->tests_count = $tests_count;
+
+ if (isset($options['coverage']) && extension_loaded('xdebug')){
+ $run->xdebug_loaded = true;
+ } else {
+ $run->xdebug_loaded = false;
+ }
+
+ $j = $i = 1;
+ foreach ($tests as $t) {
+ if (isset($options['realtimelog'])) {
+ $fp = @fopen('run-tests.log', 'a');
+ if ($fp) {
+ fwrite($fp, "Running test [$i / $tests_count] $t...");
+ fclose($fp);
+ }
+ }
+ PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
+ if (isset($options['phpunit'])) {
+ $result = $run->runPHPUnit($t, $ini_settings);
+ } else {
+ $result = $run->run($t, $ini_settings, $j);
+ }
+ PEAR::staticPopErrorHandling();
+ if (PEAR::isError($result)) {
+ $this->ui->log($result->getMessage());
+ continue;
+ }
+
+ if (isset($options['tapoutput'])) {
+ $tap .= $result[0] . ' ' . $i . $result[1] . "\n";
+ continue;
+ }
+
+ if (isset($options['realtimelog'])) {
+ $fp = @fopen('run-tests.log', 'a');
+ if ($fp) {
+ fwrite($fp, "$result\n");
+ fclose($fp);
+ }
+ }
+
+ if ($result == 'FAILED') {
+ $failed[] = $t;
+ }
+ if ($result == 'PASSED') {
+ $passed[] = $t;
+ }
+ if ($result == 'SKIPPED') {
+ $skipped[] = $t;
+ }
+
+ $j++;
+ }
+
+ $total = date('i:s', time() - $start);
+ if (isset($options['tapoutput'])) {
+ $fp = @fopen('run-tests.log', 'w');
+ if ($fp) {
+ fwrite($fp, $tap, strlen($tap));
+ fclose($fp);
+ $this->ui->outputData('wrote TAP-format log to "' .realpath('run-tests.log') .
+ '"', $command);
+ }
+ } else {
+ if (count($failed)) {
+ $output = "TOTAL TIME: $total\n";
+ $output .= count($passed) . " PASSED TESTS\n";
+ $output .= count($skipped) . " SKIPPED TESTS\n";
+ $output .= count($failed) . " FAILED TESTS:\n";
+ foreach ($failed as $failure) {
+ $output .= $failure . "\n";
+ }
+
+ $mode = isset($options['realtimelog']) ? 'a' : 'w';
+ $fp = @fopen('run-tests.log', $mode);
+
+ if ($fp) {
+ fwrite($fp, $output, strlen($output));
+ fclose($fp);
+ $this->ui->outputData('wrote log to "' . realpath('run-tests.log') . '"', $command);
+ }
+ } elseif (file_exists('run-tests.log') && !is_dir('run-tests.log')) {
+ @unlink('run-tests.log');
+ }
+ }
+ $this->ui->outputData('TOTAL TIME: ' . $total);
+ $this->ui->outputData(count($passed) . ' PASSED TESTS', $command);
+ $this->ui->outputData(count($skipped) . ' SKIPPED TESTS', $command);
+ if (count($failed)) {
+ $this->ui->outputData(count($failed) . ' FAILED TESTS:', $command);
+ foreach ($failed as $failure) {
+ $this->ui->outputData($failure, $command);
+ }
+ }
+
+ return true;
+ }
+}<commands version="1.0">
+ <run-tests>
+ <summary>Run Regression Tests</summary>
+ <function>doRunTests</function>
+ <shortcut>rt</shortcut>
+ <options>
+ <recur>
+ <shortopt>r</shortopt>
+ <doc>Run tests in child directories, recursively. 4 dirs deep maximum</doc>
+ </recur>
+ <ini>
+ <shortopt>i</shortopt>
+ <doc>actual string of settings to pass to php in format &quot; -d setting=blah&quot;</doc>
+ <arg>SETTINGS</arg>
+ </ini>
+ <realtimelog>
+ <shortopt>l</shortopt>
+ <doc>Log test runs/results as they are run</doc>
+ </realtimelog>
+ <quiet>
+ <shortopt>q</shortopt>
+ <doc>Only display detail for failed tests</doc>
+ </quiet>
+ <simple>
+ <shortopt>s</shortopt>
+ <doc>Display simple output for all tests</doc>
+ </simple>
+ <package>
+ <shortopt>p</shortopt>
+ <doc>Treat parameters as installed packages from which to run tests</doc>
+ </package>
+ <phpunit>
+ <shortopt>u</shortopt>
+ <doc>Search parameters for AllTests.php, and use that to run phpunit-based tests
+If none is found, all .phpt tests will be tried instead.</doc>
+ </phpunit>
+ <tapoutput>
+ <shortopt>t</shortopt>
+ <doc>Output run-tests.log in TAP-compliant format</doc>
+ </tapoutput>
+ <cgi>
+ <shortopt>c</shortopt>
+ <doc>CGI php executable (needed for tests with POST/GET section)</doc>
+ <arg>PHPCGI</arg>
+ </cgi>
+ <coverage>
+ <shortopt>x</shortopt>
+ <doc>Generate a code coverage report (requires Xdebug 2.0.0+)</doc>
+ </coverage>
+ </options>
+ <doc>[testfile|dir ...]
+Run regression tests with PHP&#039;s regression testing script (run-tests.php).</doc>
+ </run-tests>
+</commands><?php
+/**
* PEAR_Common, the base class for the PEAR Installer
*
* PHP versions 4 and 5
@@ -60154,7 +67314,7 @@ Run post-installation scripts in package &lt;package&gt;, if any exist.
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version CVS: $Id: Common.php 282969 2009-06-28 23:09:27Z dufuz $
+ * @version CVS: $Id: Common.php 313023 2011-07-06 19:17:11Z dufuz $
* @link http://pear.php.net/package/PEAR
* @since File available since Release 0.1.0
* @deprecated File deprecated since Release 1.4.0a1
@@ -60261,7 +67421,7 @@ $GLOBALS['_PEAR_Common_script_phases'] = array('pre-install', 'post-install', 'p
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version Release: 1.10.0beta1
+ * @version Release: 1.9.4
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a1
* @deprecated This class will disappear, and its components will be spread
@@ -60989,7 +68149,7 @@ require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/PackageFile.php';<?php
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version CVS: $Id: Config.php 286480 2009-07-29 02:50:02Z dufuz $
+ * @version CVS: $Id: Config.php 313023 2011-07-06 19:17:11Z dufuz $
* @link http://pear.php.net/package/PEAR
* @since File available since Release 0.1
*/
@@ -61225,7 +68385,7 @@ if (getenv('PHP_PEAR_SIG_KEYDIR')) {
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version Release: 1.10.0beta1
+ * @version Release: 1.9.4
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 0.1
*/
@@ -63085,7 +70245,7 @@ class PEAR_Config extends PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version CVS: $Id: Dependency2.php 286494 2009-07-29 06:57:11Z dufuz $
+ * @version CVS: $Id: Dependency2.php 313023 2011-07-06 19:17:11Z dufuz $
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.4.0a1
*/
@@ -63107,7 +70267,7 @@ require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Validate.php';
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version Release: 1.10.0beta1
+ * @version Release: 1.9.4
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a1
*/
@@ -63617,7 +70777,7 @@ class PEAR_Dependency2
*/
function getPEARVersion()
{
- return '1.10.0beta1';
+ return '1.9.4';
}
function validatePearinstallerDependency($dep)
@@ -64443,7 +71603,7 @@ class PEAR_Dependency2
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version CVS: $Id: DependencyDB.php 286686 2009-08-02 17:38:57Z dufuz $
+ * @version CVS: $Id: DependencyDB.php 313023 2011-07-06 19:17:11Z dufuz $
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.4.0a1
*/
@@ -64463,7 +71623,7 @@ $GLOBALS['_PEAR_DEPENDENCYDB_INSTANCE'] = array();
* @author Tomas V.V.Cox <cox@idec.net.com>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version Release: 1.10.0beta1
+ * @version Release: 1.9.4
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a1
*/
@@ -65213,7 +72373,7 @@ class PEAR_DependencyDB
* @author Martin Jansen <mj@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version CVS: $Id: Downloader.php 312909 2011-07-04 19:49:14Z dufuz $
+ * @version CVS: $Id: Downloader.php 313024 2011-07-06 19:51:24Z dufuz $
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.3.0
*/
@@ -65240,7 +72400,7 @@ define('PEAR_INSTALLER_ERROR_NO_PREF_STATE', 2);
* @author Martin Jansen <mj@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version Release: 1.10.0beta1
+ * @version Release: 1.9.4
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.3.0
*/
@@ -66840,7 +74000,7 @@ class PEAR_Downloader extends PEAR_Common
}
$request .= $ifmodifiedsince .
- "User-Agent: PEAR/1.10.0beta1/PHP/" . PHP_VERSION . "\r\n";
+ "User-Agent: PEAR/1.9.4/PHP/" . PHP_VERSION . "\r\n";
if (isset($this)) { // only pass in authentication for non-static calls
$username = $config->get('username', null, $channel);
@@ -66929,8 +74089,7 @@ class PEAR_Downloader extends PEAR_Common
}
while ($data = fread($fp, 1024)) {
- $len = strlen($data);
- $bytes += $len;
+ $bytes += strlen($data);
if ($callback) {
call_user_func($callback, 'bytesread', $bytes);
}
@@ -66976,7 +74135,7 @@ class PEAR_Downloader extends PEAR_Common
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version CVS: $Id: Package.php 308688 2011-02-25 23:18:06Z dufuz $
+ * @version CVS: $Id: Package.php 313023 2011-07-06 19:17:11Z dufuz $
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.4.0a1
*/
@@ -67017,7 +74176,7 @@ define('PEAR_DOWNLOADER_PACKAGE_PHPVERSION', -1004);
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version Release: 1.10.0beta1
+ * @version Release: 1.9.4
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a1
*/
@@ -68977,7 +76136,7 @@ class PEAR_Downloader_Package
* @author Greg Beaver <cellog@php.net>
* @copyright 2004-2008 Greg Beaver
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version CVS: $Id: ErrorStack.php 276383 2009-02-24 23:39:37Z dufuz $
+ * @version CVS: $Id: ErrorStack.php 313023 2011-07-06 19:17:11Z dufuz $
* @link http://pear.php.net/package/PEAR_ErrorStack
*/
@@ -69086,12 +76245,12 @@ define('PEAR_ERRORSTACK_ERR_OBJTOSTRING', 2);
* $local_stack = new PEAR_ErrorStack('MyPackage');
* </code>
* @author Greg Beaver <cellog@php.net>
- * @version 1.10.0beta1
+ * @version 1.9.4
* @package PEAR_ErrorStack
* @category Debugging
* @copyright 2004-2008 Greg Beaver
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version CVS: $Id: ErrorStack.php 276383 2009-02-24 23:39:37Z dufuz $
+ * @version CVS: $Id: ErrorStack.php 313023 2011-07-06 19:17:11Z dufuz $
* @link http://pear.php.net/package/PEAR_ErrorStack
*/
class PEAR_ErrorStack {
@@ -69945,16 +77104,16 @@ $stack->pushCallback(array('PEAR_ErrorStack', '_handleError'));
* PHP versions 4 and 5
*
* @category pear
- * @package PEAR_Exception
+ * @package PEAR
* @author Tomas V. V. Cox <cox@idecnet.com>
* @author Hans Lellelid <hans@velum.net>
* @author Bertrand Mansion <bmansion@mamasam.com>
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version CVS: $Id: Exception.php 309057 2011-03-09 23:34:29Z dufuz $
- * @link http://pear.php.net/package/PEAR_Exception
- * @since File available since Release 1.0.0
+ * @version CVS: $Id: Exception.php 313023 2011-07-06 19:17:11Z dufuz $
+ * @link http://pear.php.net/package/PEAR
+ * @since File available since Release 1.3.3
*/
@@ -70021,16 +77180,16 @@ $stack->pushCallback(array('PEAR_ErrorStack', '_handleError'));
* </code>
*
* @category pear
- * @package PEAR_Exception
+ * @package PEAR
* @author Tomas V.V.Cox <cox@idecnet.com>
* @author Hans Lellelid <hans@velum.net>
* @author Bertrand Mansion <bmansion@mamasam.com>
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version Release: 1.10.0beta1
- * @link http://pear.php.net/package/PEAR_Exception
- * @since Class available since Release 1.0.0
+ * @version Release: 1.9.4
+ * @link http://pear.php.net/package/PEAR
+ * @since Class available since Release 1.3.3
*
*/
class PEAR_Exception extends Exception
@@ -70326,6 +77485,12 @@ class PEAR_Exception extends Exception
return $causeMsg . $this->getTraceAsString();
}
}<?php
+if ($skipmsg) {
+ $a = &new $ec($code, $mode, $options, $userinfo);
+} else {
+ $a = &new $ec($message, $code, $mode, $options, $userinfo);
+}
+?><?php
/**
* PEAR_Frontend, the singleton-based frontend for user input/output
*
@@ -70336,7 +77501,7 @@ class PEAR_Exception extends Exception
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version CVS: $Id: Frontend.php 276383 2009-02-24 23:39:37Z dufuz $
+ * @version CVS: $Id: Frontend.php 313023 2011-07-06 19:17:11Z dufuz $
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.4.0a1
*/
@@ -70366,7 +77531,7 @@ $GLOBALS['_PEAR_FRONTEND_SINGLETON'] = null;
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version Release: 1.10.0beta1
+ * @version Release: 1.9.4
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a1
*/
@@ -70564,7 +77729,7 @@ class PEAR_Frontend extends PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version CVS: $Id: CLI.php 305390 2010-11-15 23:46:43Z dufuz $
+ * @version CVS: $Id: CLI.php 313023 2011-07-06 19:17:11Z dufuz $
* @link http://pear.php.net/package/PEAR
* @since File available since Release 0.1
*/
@@ -70581,7 +77746,7 @@ require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Frontend.php';
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version Release: 1.10.0beta1
+ * @version Release: 1.9.4
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 0.1
*/
@@ -71316,7 +78481,7 @@ class PEAR_Frontend_CLI extends PEAR_Frontend
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version CVS: $Id: Installer.php 312945 2011-07-05 18:38:56Z dufuz $
+ * @version CVS: $Id: Installer.php 313024 2011-07-06 19:51:24Z dufuz $
* @link http://pear.php.net/package/PEAR
* @since File available since Release 0.1
*/
@@ -71340,12 +78505,14 @@ define('PEAR_INSTALLER_NOBINARY', -240);
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version Release: 1.10.0beta1
+ * @version Release: 1.9.4
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 0.1
*/
class PEAR_Installer extends PEAR_Downloader
{
+ // {{{ properties
+
/** name of the package directory, for example Foo-1.0
* @var string
*/
@@ -71407,6 +78574,10 @@ class PEAR_Installer extends PEAR_Downloader
*/
var $file_operations = array();
+ // }}}
+
+ // {{{ constructor
+
/**
* PEAR_Installer constructor.
*
@@ -71432,6 +78603,8 @@ class PEAR_Installer extends PEAR_Downloader
$this->_registry = &$config->getRegistry();
}
+ // }}}
+
function _removeBackups($files)
{
foreach ($files as $path) {
@@ -71439,6 +78612,8 @@ class PEAR_Installer extends PEAR_Downloader
}
}
+ // {{{ _deletePackageFiles()
+
/**
* Delete a package's installed files, does not remove empty directories.
*
@@ -71497,6 +78672,9 @@ class PEAR_Installer extends PEAR_Downloader
return true;
}
+ // }}}
+ // {{{ _installFile()
+
/**
* @param string filename
* @param array attributes from <file> tag in package.xml
@@ -71506,7 +78684,7 @@ class PEAR_Installer extends PEAR_Downloader
*/
function _installFile($file, $atts, $tmp_path, $options)
{
- // return if this file is meant for another platform
+ // {{{ return if this file is meant for another platform
static $os;
if (!isset($this->_registry)) {
$this->_registry = &$this->config->getRegistry();
@@ -71514,7 +78692,7 @@ class PEAR_Installer extends PEAR_Downloader
if (isset($atts['platform'])) {
if (empty($os)) {
- $os = new OS_Guess;
+ $os = new OS_Guess();
}
if (strlen($atts['platform']) && $atts['platform']{0} == '!') {
@@ -71530,9 +78708,10 @@ class PEAR_Installer extends PEAR_Downloader
return PEAR_INSTALLER_SKIPPED;
}
}
+ // }}}
$channel = $this->pkginfo->getChannel();
- // assemble the destination paths
+ // {{{ assemble the destination paths
switch ($atts['role']) {
case 'src':
case 'extsrc':
@@ -71594,11 +78773,10 @@ class PEAR_Installer extends PEAR_Downloader
if (preg_match('~/\.\.(/|\\z)|^\.\./~', str_replace('\\', '/', $dest_file))) {
return $this->raiseError("SECURITY ERROR: file $file (installed to $dest_file) contains parent directory reference ..", PEAR_INSTALLER_FAILED);
}
+ // }}}
- if (
- empty($this->_options['register-only']) &&
- (!file_exists($dest_dir) || !is_dir($dest_dir))
- ) {
+ if (empty($this->_options['register-only']) &&
+ (!file_exists($dest_dir) || !is_dir($dest_dir))) {
if (!$this->mkDirHier($dest_dir)) {
return $this->raiseError("failed to mkdir $dest_dir",
PEAR_INSTALLER_FAILED);
@@ -71624,7 +78802,7 @@ class PEAR_Installer extends PEAR_Downloader
$md5sum = md5_file($dest_file);
}
} else {
- // file with replacements
+ // {{{ file with replacements
if (!file_exists($orig_file)) {
return $this->raiseError("file does not exist",
PEAR_INSTALLER_FAILED);
@@ -71662,12 +78840,10 @@ class PEAR_Installer extends PEAR_Downloader
} else {
$to = $this->config->get($a['to'], null, $channel);
}
-
if (is_null($to)) {
if (!isset($options['soft'])) {
$this->log(0, "invalid pear-config replacement: $a[to]");
}
-
continue;
}
} elseif ($a['type'] == 'package-info') {
@@ -71677,11 +78853,9 @@ class PEAR_Installer extends PEAR_Downloader
if (!isset($options['soft'])) {
$this->log(0, "invalid package-info replacement: $a[to]");
}
-
continue;
}
}
-
if (!is_null($to)) {
$subst_from[] = $a['from'];
$subst_to[] = $to;
@@ -71705,9 +78879,10 @@ class PEAR_Installer extends PEAR_Downloader
}
fclose($wp);
+ // }}}
}
- // check the md5
+ // {{{ check the md5
if (isset($md5sum)) {
if (strtolower($md5sum) === strtolower($atts['md5sum'])) {
$this->log(2, "md5sum ok: $final_dest_file");
@@ -71733,15 +78908,14 @@ class PEAR_Installer extends PEAR_Downloader
}
}
}
-
- // set file permissions
+ // }}}
+ // {{{ set file permissions
if (!OS_WINDOWS) {
- $umask = $this->config->get('umask');
if ($atts['role'] == 'script') {
- $mode = 0777 & ~(int)octdec($umask);
+ $mode = 0777 & ~(int)octdec($this->config->get('umask'));
$this->log(3, "+ chmod +x $dest_file");
} else {
- $mode = 0666 & ~(int)octdec($umask);
+ $mode = 0666 & ~(int)octdec($this->config->get('umask'));
}
if ($atts['role'] != 'src') {
@@ -71753,6 +78927,7 @@ class PEAR_Installer extends PEAR_Downloader
}
}
}
+ // }}}
if ($atts['role'] == 'src') {
rename($dest_file, $final_dest_file);
@@ -71780,6 +78955,9 @@ class PEAR_Installer extends PEAR_Downloader
return PEAR_INSTALLER_OK;
}
+ // }}}
+ // {{{ _installFile2()
+
/**
* @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
* @param string filename
@@ -71796,9 +78974,9 @@ class PEAR_Installer extends PEAR_Downloader
}
$channel = $pkg->getChannel();
- // assemble the destination paths
- $roles = PEAR_Installer_Role::getValidRoles($pkg->getPackageType());
- if (!in_array($atts['attribs']['role'], $roles)) {
+ // {{{ assemble the destination paths
+ if (!in_array($atts['attribs']['role'],
+ PEAR_Installer_Role::getValidRoles($pkg->getPackageType()))) {
return $this->raiseError('Invalid role `' . $atts['attribs']['role'] .
"' for file $file");
}
@@ -71825,11 +79003,13 @@ class PEAR_Installer extends PEAR_Downloader
$final_dest_file = $installed_as = $dest_file;
if (isset($this->_options['packagingroot'])) {
- $final_dest_file = $this->_prependPath($final_dest_file, $this->_options['packagingroot']);
+ $final_dest_file = $this->_prependPath($final_dest_file,
+ $this->_options['packagingroot']);
}
$dest_dir = dirname($final_dest_file);
$dest_file = $dest_dir . DIRECTORY_SEPARATOR . '.tmp' . basename($final_dest_file);
+ // }}}
if (empty($this->_options['register-only'])) {
if (!file_exists($dest_dir) || !is_dir($dest_dir)) {
@@ -71908,7 +79088,7 @@ class PEAR_Installer extends PEAR_Downloader
}
}
- // check the md5
+ // {{{ check the md5
if (isset($md5sum)) {
// Make sure the original md5 sum matches with expected
if (strtolower($md5sum) === strtolower($attribs['md5sum'])) {
@@ -71943,7 +79123,8 @@ class PEAR_Installer extends PEAR_Downloader
$real_atts['attribs']['md5sum'] = md5_file($dest_file);
}
- //set file permissions
+ // }}}
+ // {{{ set file permissions
if (!OS_WINDOWS) {
if ($role->isExecutable()) {
$mode = 0777 & ~(int)octdec($this->config->get('umask'));
@@ -71961,6 +79142,7 @@ class PEAR_Installer extends PEAR_Downloader
}
}
}
+ // }}}
if ($attribs['role'] == 'src') {
rename($dest_file, $final_dest_file);
@@ -71982,6 +79164,9 @@ class PEAR_Installer extends PEAR_Downloader
return PEAR_INSTALLER_OK;
}
+ // }}}
+ // {{{ addFileOperation()
+
/**
* Add a file operation to the current file transaction.
*
@@ -72022,6 +79207,9 @@ class PEAR_Installer extends PEAR_Downloader
$this->file_operations[] = array($type, $data);
}
+ // }}}
+ // {{{ startFileTransaction()
+
function startFileTransaction($rollback_in_case = false)
{
if (count($this->file_operations) && $rollback_in_case) {
@@ -72030,9 +79218,12 @@ class PEAR_Installer extends PEAR_Downloader
$this->file_operations = array();
}
+ // }}}
+ // {{{ commitFileTransaction()
+
function commitFileTransaction()
{
- //first, check permissions and such manually
+ // {{{ first, check permissions and such manually
$errors = array();
foreach ($this->file_operations as $key => $tr) {
list($type, $data) = $tr;
@@ -72057,7 +79248,6 @@ class PEAR_Installer extends PEAR_Downloader
if (!file_exists($data[0])) {
$this->log(2, "warning: file $data[0] doesn't exist, can't be deleted");
}
-
// check that directory is writable
if (file_exists($data[0])) {
if (!is_writable(dirname($data[0]))) {
@@ -72093,7 +79283,9 @@ class PEAR_Installer extends PEAR_Downloader
}
break;
}
+
}
+ // }}}
$n = count($this->file_operations);
$this->log(2, "about to commit $n file operations for " . $this->pkginfo->getName());
@@ -72112,7 +79304,7 @@ class PEAR_Installer extends PEAR_Downloader
}
$this->_dirtree = array();
- // really commit the transaction
+ // {{{ really commit the transaction
foreach ($this->file_operations as $i => $tr) {
if (!$tr) {
// support removal of non-existing backups
@@ -72233,12 +79425,15 @@ class PEAR_Installer extends PEAR_Downloader
break;
}
}
-
+ // }}}
$this->log(2, "successfully committed $n file operations");
$this->file_operations = array();
return true;
}
+ // }}}
+ // {{{ rollbackFileTransaction()
+
function rollbackFileTransaction()
{
$n = count($this->file_operations);
@@ -72282,12 +79477,18 @@ class PEAR_Installer extends PEAR_Downloader
$this->file_operations = array();
}
+ // }}}
+ // {{{ mkDirHier($dir)
+
function mkDirHier($dir)
{
$this->addFileOperation('mkdir', array($dir));
return parent::mkDirHier($dir);
}
+ // }}}
+ // {{{ download()
+
/**
* Download any files and their dependencies, if necessary
*
@@ -72321,9 +79522,12 @@ class PEAR_Installer extends PEAR_Downloader
return $ret;
}
+ // }}}
+ // {{{ _parsePackageXml()
+
function _parsePackageXml(&$descfile)
{
- // Parse xml file
+ // Parse xml file -----------------------------------------------
$pkg = new PEAR_PackageFile($this->config, $this->debug);
PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
$p = &$pkg->fromAnyFile($descfile, PEAR_VALIDATE_INSTALLING);
@@ -72344,6 +79548,7 @@ class PEAR_Installer extends PEAR_Downloader
return $p;
}
+ // }}}
/**
* Set the list of PEAR_Downloader_Package objects to allow more sane
* dependency validation
@@ -72375,6 +79580,8 @@ class PEAR_Installer extends PEAR_Downloader
return $this->_downloadedPackages;
}
+ // {{{ install()
+
/**
* Installs the files within the package file specified.
*
@@ -72422,7 +79629,7 @@ class PEAR_Installer extends PEAR_Downloader
}
}
- $name = $pkg->getName();
+ $pkgname = $pkg->getName();
$channel = $pkg->getChannel();
if (isset($this->_options['packagingroot'])) {
$regdir = $this->_prependPath(
@@ -72458,11 +79665,11 @@ class PEAR_Installer extends PEAR_Downloader
$this->installroot = '';
}
- // checks to do when not in "force" mode
+ // {{{ checks to do when not in "force" mode
if (empty($options['force']) &&
(file_exists($this->config->get('php_dir')) &&
is_dir($this->config->get('php_dir')))) {
- $testp = $channel == 'pear.php.net' ? $name : array($channel, $name);
+ $testp = $channel == 'pear.php.net' ? $pkgname : array($channel, $pkgname);
$instfilelist = $pkg->getInstallationFileList(true);
if (PEAR::isError($instfilelist)) {
return $instfilelist;
@@ -72552,7 +79759,7 @@ class PEAR_Installer extends PEAR_Downloader
}
if (count($test)) {
- $msg = "$channel/$name: conflicting files found:\n";
+ $msg = "$channel/$pkgname: conflicting files found:\n";
$longest = max(array_map("strlen", array_keys($test)));
$fmt = "%${longest}s (%s)\n";
foreach ($test as $file => $info) {
@@ -72573,30 +79780,30 @@ class PEAR_Installer extends PEAR_Downloader
}
}
}
+ // }}}
$this->startFileTransaction();
- // Figure out what channel to use and if the package exists or not
$usechannel = $channel;
if ($channel == 'pecl.php.net') {
- $test = $installregistry->packageExists($name, $channel);
+ $test = $installregistry->packageExists($pkgname, $channel);
if (!$test) {
- $test = $installregistry->packageExists($name, 'pear.php.net');
+ $test = $installregistry->packageExists($pkgname, 'pear.php.net');
$usechannel = 'pear.php.net';
}
} else {
- $test = $installregistry->packageExists($name, $channel);
+ $test = $installregistry->packageExists($pkgname, $channel);
}
- // checks to do only when installing new packages
if (empty($options['upgrade']) && empty($options['soft'])) {
+ // checks to do only when installing new packages
if (empty($options['force']) && $test) {
- return $this->raiseError("$channel/$name is already installed");
+ return $this->raiseError("$channel/$pkgname is already installed");
}
} else {
// Upgrade
if ($test) {
- $v1 = $installregistry->packageInfo($name, 'version', $usechannel);
+ $v1 = $installregistry->packageInfo($pkgname, 'version', $usechannel);
$v2 = $pkg->getVersion();
$cmp = version_compare("$v1", "$v2", 'gt');
if (empty($options['force']) && !version_compare("$v2", "$v1", 'gt')) {
@@ -72607,8 +79814,9 @@ class PEAR_Installer extends PEAR_Downloader
// Do cleanups for upgrade and install, remove old release's files first
if ($test && empty($options['register-only'])) {
- $err = $this->_deletePackageFiles($name, $usechannel, true);
- if (PEAR::isError($err)) {
+ // when upgrading, remove old release's files first:
+ if (PEAR::isError($err = $this->_deletePackageFiles($pkgname, $usechannel,
+ true))) {
if (!isset($options['ignore-errors'])) {
return $this->raiseError($err);
}
@@ -72621,7 +79829,7 @@ class PEAR_Installer extends PEAR_Downloader
}
}
- // Copy files to dest dir
+ // {{{ Copy files to dest dir ---------------------------------------
// info from the package it self we want to access from _installFile
$this->pkginfo = &$pkg;
@@ -72636,23 +79844,29 @@ class PEAR_Installer extends PEAR_Downloader
}
if (substr($pkgfile, -4) != '.xml') {
- $tmpdir .= DIRECTORY_SEPARATOR . $name . '-' . $pkg->getVersion();
+ $tmpdir .= DIRECTORY_SEPARATOR . $pkgname . '-' . $pkg->getVersion();
}
$this->configSet('default_channel', $channel);
- // install files
+ // {{{ install files
+
+ $ver = $pkg->getPackagexmlVersion();
+ if (version_compare($ver, '2.0', '>=')) {
+ $filelist = $pkg->getInstallationFilelist();
+ } else {
+ $filelist = $pkg->getFileList();
+ }
- $filelist = $pkg->getInstallationFilelist();
if (PEAR::isError($filelist)) {
return $filelist;
}
- $p = &$installregistry->getPackage($name, $channel);
+ $p = &$installregistry->getPackage($pkgname, $channel);
$dirtree = (empty($options['register-only']) && $p) ? $p->getDirTree() : false;
$pkg->resetFilelist();
- $version = $installregistry->packageInfo($pkg->getPackage(), 'version', $pkg->getChannel());
- $pkg->setLastInstalledVersion($version);
+ $pkg->setLastInstalledVersion($installregistry->packageInfo($pkg->getPackage(),
+ 'version', $pkg->getChannel()));
foreach ($filelist as $file => $atts) {
$this->expectError(PEAR_INSTALLER_FAILED);
if ($pkg->getPackagexmlVersion() == '1.0') {
@@ -72683,18 +79897,16 @@ class PEAR_Installer extends PEAR_Downloader
$pkg->installedFile($file, $atts);
}
}
+ // }}}
- // compile and install source files
+ // {{{ compile and install source files
if ($this->source_files > 0 && empty($options['nobuild'])) {
- if (!isset($options['__compile_configureoptions'])) {
- $options['__compile_configureoptions'] = array();
- }
-
if (PEAR::isError($err =
- $this->_compileSourceFiles($savechannel, $pkg, $options['__compile_configureoptions']))) {
+ $this->_compileSourceFiles($savechannel, $pkg))) {
return $err;
}
}
+ // }}}
if (isset($backedup)) {
$this->_removeBackups($backedup);
@@ -72705,28 +79917,28 @@ class PEAR_Installer extends PEAR_Downloader
$this->configSet('default_channel', $savechannel);
return $this->raiseError("commit failed", PEAR_INSTALLER_FAILED);
}
-
- // See if package already exists
- $usechannel = $channel;
- if ($channel == 'pecl.php.net') {
- $test = $installregistry->packageExists($name, $channel);
- if (!$test) {
- $test = $installregistry->packageExists($name, 'pear.php.net');
- $usechannel = 'pear.php.net';
- }
- } else {
- $test = $installregistry->packageExists($name, $channel);
- }
+ // }}}
$ret = false;
$installphase = 'install';
$oldversion = false;
- // Register that the package is installed
+ // {{{ Register that the package is installed -----------------------
if (empty($options['upgrade'])) {
// if 'force' is used, replace the info in registry
+ $usechannel = $channel;
+ if ($channel == 'pecl.php.net') {
+ $test = $installregistry->packageExists($pkgname, $channel);
+ if (!$test) {
+ $test = $installregistry->packageExists($pkgname, 'pear.php.net');
+ $usechannel = 'pear.php.net';
+ }
+ } else {
+ $test = $installregistry->packageExists($pkgname, $channel);
+ }
+
if (!empty($options['force']) && $test) {
- $oldversion = $installregistry->packageInfo($name, 'version', $usechannel);
- $installregistry->deletePackage($name, $usechannel);
+ $oldversion = $installregistry->packageInfo($pkgname, 'version', $usechannel);
+ $installregistry->deletePackage($pkgname, $usechannel);
}
$ret = $installregistry->addPackage2($pkg);
} else {
@@ -72740,12 +79952,23 @@ class PEAR_Installer extends PEAR_Downloader
$this->commitFileTransaction();
}
+ $usechannel = $channel;
+ if ($channel == 'pecl.php.net') {
+ $test = $installregistry->packageExists($pkgname, $channel);
+ if (!$test) {
+ $test = $installregistry->packageExists($pkgname, 'pear.php.net');
+ $usechannel = 'pear.php.net';
+ }
+ } else {
+ $test = $installregistry->packageExists($pkgname, $channel);
+ }
+
// new: upgrade installs a package if it isn't installed
if (!$test) {
$ret = $installregistry->addPackage2($pkg);
} else {
if ($usechannel != $channel) {
- $installregistry->deletePackage($name, $usechannel);
+ $installregistry->deletePackage($pkgname, $usechannel);
$ret = $installregistry->addPackage2($pkg);
} else {
$ret = $installregistry->updatePackage2($pkg);
@@ -72756,7 +79979,7 @@ class PEAR_Installer extends PEAR_Downloader
if (!$ret) {
$this->configSet('default_channel', $savechannel);
- return $this->raiseError("Adding package $channel/$name to registry failed");
+ return $this->raiseError("Adding package $channel/$pkgname to registry failed");
}
// }}}
@@ -72770,17 +79993,20 @@ class PEAR_Installer extends PEAR_Downloader
return $pkg->toArray(true);
}
+ // }}}
+
+ // {{{ _compileSourceFiles()
/**
* @param string
* @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
*/
- function _compileSourceFiles($savechannel, &$filelist, $configure_options = array())
+ function _compileSourceFiles($savechannel, &$filelist)
{
require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Builder.php';
$this->log(1, "$this->source_files source files, building");
$bob = &new PEAR_Builder($this->ui);
$bob->debug = $this->debug;
- $built = $bob->build($filelist, array(&$this, '_buildCallback'), $configure_options);
+ $built = $bob->build($filelist, array(&$this, '_buildCallback'));
if (PEAR::isError($built)) {
$this->rollbackFileTransaction();
$this->configSet('default_channel', $savechannel);
@@ -72839,6 +80065,7 @@ class PEAR_Installer extends PEAR_Downloader
}
}
+
$data = array(
'role' => $role,
'name' => $bn,
@@ -72856,10 +80083,12 @@ class PEAR_Installer extends PEAR_Downloader
}
}
+ // }}}
function &getUninstallPackages()
{
return $this->_downloadedPackages;
}
+ // {{{ uninstall()
/**
* Uninstall a package
@@ -72941,7 +80170,7 @@ class PEAR_Installer extends PEAR_Downloader
$this->pkginfo = &$pkg;
// pretty much nothing happens if we are only registering the uninstall
if (empty($options['register-only'])) {
- // Delete the files
+ // {{{ Delete the files
$this->startFileTransaction();
PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
if (PEAR::isError($err = $this->_deletePackageFiles($package, $channel))) {
@@ -72993,6 +80222,7 @@ class PEAR_Installer extends PEAR_Downloader
}
}
}
+ // }}}
}
$this->configSet('default_channel', $savechannel);
@@ -73037,6 +80267,8 @@ class PEAR_Installer extends PEAR_Downloader
return 0;
}
+ // }}}
+ // {{{ _sortDirs()
function _sortDirs($a, $b)
{
if (strnatcmp($a, $b) == -1) return 1;
@@ -73044,6 +80276,10 @@ class PEAR_Installer extends PEAR_Downloader
return 0;
}
+ // }}}
+
+ // {{{ _buildCallback()
+
function _buildCallback($what, $data)
{
if (($what == 'cmdoutput' && $this->debug > 1) ||
@@ -73051,6 +80287,8 @@ class PEAR_Installer extends PEAR_Downloader
$this->ui->outputData(rtrim($data), 'build');
}
}
+
+ // }}}
}<?php
/**
* PEAR_Installer_Role
@@ -73062,7 +80300,7 @@ class PEAR_Installer extends PEAR_Downloader
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version CVS: $Id: Role.php 278552 2009-04-10 19:42:49Z dufuz $
+ * @version CVS: $Id: Role.php 313023 2011-07-06 19:17:11Z dufuz $
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.4.0a1
*/
@@ -73078,7 +80316,7 @@ require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/XMLParser.php';
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version Release: 1.10.0beta1
+ * @version Release: 1.9.4
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a1
*/
@@ -73328,6 +80566,125 @@ class PEAR_Installer_Role
}
}<?php
/**
+ * PEAR_Installer_Role_Cfg
+ *
+ * PHP versions 4 and 5
+ *
+ * @category pear
+ * @package PEAR
+ * @author Greg Beaver <cellog@php.net>
+ * @copyright 2007-2009 The Authors
+ * @license http://opensource.org/licenses/bsd-license.php New BSD License
+ * @version CVS: $Id: Cfg.php 313023 2011-07-06 19:17:11Z dufuz $
+ * @link http://pear.php.net/package/PEAR
+ * @since File available since Release 1.7.0
+ */
+
+/**
+ * @category pear
+ * @package PEAR
+ * @author Greg Beaver <cellog@php.net>
+ * @copyright 2007-2009 The Authors
+ * @license http://opensource.org/licenses/bsd-license.php New BSD License
+ * @version Release: 1.9.4
+ * @link http://pear.php.net/package/PEAR
+ * @since Class available since Release 1.7.0
+ */
+class PEAR_Installer_Role_Cfg extends PEAR_Installer_Role_Common
+{
+ /**
+ * @var PEAR_Installer
+ */
+ var $installer;
+
+ /**
+ * the md5 of the original file
+ *
+ * @var unknown_type
+ */
+ var $md5 = null;
+
+ /**
+ * Do any unusual setup here
+ * @param PEAR_Installer
+ * @param PEAR_PackageFile_v2
+ * @param array file attributes
+ * @param string file name
+ */
+ function setup(&$installer, $pkg, $atts, $file)
+ {
+ $this->installer = &$installer;
+ $reg = &$this->installer->config->getRegistry();
+ $package = $reg->getPackage($pkg->getPackage(), $pkg->getChannel());
+ if ($package) {
+ $filelist = $package->getFilelist();
+ if (isset($filelist[$file]) && isset($filelist[$file]['md5sum'])) {
+ $this->md5 = $filelist[$file]['md5sum'];
+ }
+ }
+ }
+
+ function processInstallation($pkg, $atts, $file, $tmp_path, $layer = null)
+ {
+ $test = parent::processInstallation($pkg, $atts, $file, $tmp_path, $layer);
+ if (@file_exists($test[2]) && @file_exists($test[3])) {
+ $md5 = md5_file($test[2]);
+ // configuration has already been installed, check for mods
+ if ($md5 !== $this->md5 && $md5 !== md5_file($test[3])) {
+ // configuration has been modified, so save our version as
+ // configfile-version
+ $old = $test[2];
+ $test[2] .= '.new-' . $pkg->getVersion();
+ // backup original and re-install it
+ PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
+ $tmpcfg = $this->config->get('temp_dir');
+ $newloc = System::mkdir(array('-p', $tmpcfg));
+ if (!$newloc) {
+ // try temp_dir
+ $newloc = System::mktemp(array('-d'));
+ if (!$newloc || PEAR::isError($newloc)) {
+ PEAR::popErrorHandling();
+ return PEAR::raiseError('Could not save existing configuration file '.
+ $old . ', unable to install. Please set temp_dir ' .
+ 'configuration variable to a writeable location and try again');
+ }
+ } else {
+ $newloc = $tmpcfg;
+ }
+
+ $temp_file = $newloc . DIRECTORY_SEPARATOR . uniqid('savefile');
+ if (!@copy($old, $temp_file)) {
+ PEAR::popErrorHandling();
+ return PEAR::raiseError('Could not save existing configuration file '.
+ $old . ', unable to install. Please set temp_dir ' .
+ 'configuration variable to a writeable location and try again');
+ }
+
+ PEAR::popErrorHandling();
+ $this->installer->log(0, "WARNING: configuration file $old is being installed as $test[2], you should manually merge in changes to the existing configuration file");
+ $this->installer->addFileOperation('rename', array($temp_file, $old, false));
+ $this->installer->addFileOperation('delete', array($temp_file));
+ }
+ }
+
+ return $test;
+ }
+}<role version="1.0">
+ <releasetypes>php</releasetypes>
+ <releasetypes>extsrc</releasetypes>
+ <releasetypes>extbin</releasetypes>
+ <releasetypes>zendextsrc</releasetypes>
+ <releasetypes>zendextbin</releasetypes>
+ <installable>1</installable>
+ <locationconfig>cfg_dir</locationconfig>
+ <honorsbaseinstall />
+ <unusualbaseinstall>1</unusualbaseinstall>
+ <phpfile />
+ <executable />
+ <phpextension />
+ <config_vars />
+</role><?php
+/**
* Base class for all installation roles.
*
* PHP versions 4 and 5
@@ -73337,7 +80694,7 @@ class PEAR_Installer_Role
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2006 The PHP Group
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version CVS: $Id: Common.php 312908 2011-07-04 19:43:30Z dufuz $
+ * @version CVS: $Id: Common.php 313023 2011-07-06 19:17:11Z dufuz $
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.4.0a1
*/
@@ -73352,7 +80709,7 @@ class PEAR_Installer_Role
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2006 The PHP Group
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version Release: 1.10.0beta1
+ * @version Release: 1.9.4
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a1
*/
@@ -73400,53 +80757,47 @@ class PEAR_Installer_Role_Common
*/
function processInstallation($pkg, $atts, $file, $tmp_path, $layer = null)
{
- $role = $this->getRoleFromClass();
- $info = PEAR_Installer_Role_Common::getInfo('PEAR_Installer_Role_' . $role);
- if (PEAR::isError($info)) {
- return $info;
+ $roleInfo = PEAR_Installer_Role_Common::getInfo('PEAR_Installer_Role_' .
+ ucfirst(str_replace('pear_installer_role_', '', strtolower(get_class($this)))));
+ if (PEAR::isError($roleInfo)) {
+ return $roleInfo;
}
-
- if (!$info['locationconfig']) {
+ if (!$roleInfo['locationconfig']) {
return false;
}
-
- if ($info['honorsbaseinstall']) {
- $dest_dir = $save_destdir = $this->config->get($info['locationconfig'], $layer,
+ if ($roleInfo['honorsbaseinstall']) {
+ $dest_dir = $save_destdir = $this->config->get($roleInfo['locationconfig'], $layer,
$pkg->getChannel());
if (!empty($atts['baseinstalldir'])) {
$dest_dir .= DIRECTORY_SEPARATOR . $atts['baseinstalldir'];
}
- } elseif ($info['unusualbaseinstall']) {
- $dest_dir = $save_destdir = $this->config->get($info['locationconfig'],
+ } elseif ($roleInfo['unusualbaseinstall']) {
+ $dest_dir = $save_destdir = $this->config->get($roleInfo['locationconfig'],
$layer, $pkg->getChannel()) . DIRECTORY_SEPARATOR . $pkg->getPackage();
if (!empty($atts['baseinstalldir'])) {
$dest_dir .= DIRECTORY_SEPARATOR . $atts['baseinstalldir'];
}
} else {
- $save_destdir = $dest_dir = $this->config->get($info['locationconfig'],
+ $dest_dir = $save_destdir = $this->config->get($roleInfo['locationconfig'],
$layer, $pkg->getChannel()) . DIRECTORY_SEPARATOR . $pkg->getPackage();
}
-
if (dirname($file) != '.' && empty($atts['install-as'])) {
$dest_dir .= DIRECTORY_SEPARATOR . dirname($file);
}
-
if (empty($atts['install-as'])) {
$dest_file = $dest_dir . DIRECTORY_SEPARATOR . basename($file);
} else {
$dest_file = $dest_dir . DIRECTORY_SEPARATOR . $atts['install-as'];
}
-
$orig_file = $tmp_path . DIRECTORY_SEPARATOR . $file;
// Clean up the DIRECTORY_SEPARATOR mess
$ds2 = DIRECTORY_SEPARATOR . DIRECTORY_SEPARATOR;
-
+
list($dest_dir, $dest_file, $orig_file) = preg_replace(array('!\\\\+!', '!/!', "!$ds2+!"),
array(DIRECTORY_SEPARATOR, DIRECTORY_SEPARATOR,
DIRECTORY_SEPARATOR),
array($dest_dir, $dest_file, $orig_file));
-
return array($save_destdir, $dest_dir, $dest_file, $orig_file);
}
@@ -73456,13 +80807,12 @@ class PEAR_Installer_Role_Common
*/
function getLocationConfig()
{
- $role = ucfirst(str_replace('pear_installer_role_', '', strtolower(get_class($this))));
- $info = PEAR_Installer_Role_Common::getInfo('PEAR_Installer_Role_' . $role);
- if (PEAR::isError($info)) {
- return $info;
+ $roleInfo = PEAR_Installer_Role_Common::getInfo('PEAR_Installer_Role_' .
+ ucfirst(str_replace('pear_installer_role_', '', strtolower(get_class($this)))));
+ if (PEAR::isError($roleInfo)) {
+ return $roleInfo;
}
-
- return $info['locationconfig'];
+ return $roleInfo['locationconfig'];
}
/**
@@ -73478,43 +80828,35 @@ class PEAR_Installer_Role_Common
function isExecutable()
{
- $role = $this->getRoleFromClass();
- $info = PEAR_Installer_Role_Common::getInfo('PEAR_Installer_Role_' . $role);
- if (PEAR::isError($info)) {
- return $info;
+ $roleInfo = PEAR_Installer_Role_Common::getInfo('PEAR_Installer_Role_' .
+ ucfirst(str_replace('pear_installer_role_', '', strtolower(get_class($this)))));
+ if (PEAR::isError($roleInfo)) {
+ return $roleInfo;
}
-
- return $info['executable'];
+ return $roleInfo['executable'];
}
function isInstallable()
{
- $role = $this->getRoleFromClass();
- $info = PEAR_Installer_Role_Common::getInfo('PEAR_Installer_Role_' . $role);
- if (PEAR::isError($info)) {
- return $info;
+ $roleInfo = PEAR_Installer_Role_Common::getInfo('PEAR_Installer_Role_' .
+ ucfirst(str_replace('pear_installer_role_', '', strtolower(get_class($this)))));
+ if (PEAR::isError($roleInfo)) {
+ return $roleInfo;
}
-
- return $info['installable'];
+ return $roleInfo['installable'];
}
function isExtension()
{
- $role = $this->getRoleFromClass();
- $info = PEAR_Installer_Role_Common::getInfo('PEAR_Installer_Role_' . $role);
- if (PEAR::isError($info)) {
- return $info;
+ $roleInfo = PEAR_Installer_Role_Common::getInfo('PEAR_Installer_Role_' .
+ ucfirst(str_replace('pear_installer_role_', '', strtolower(get_class($this)))));
+ if (PEAR::isError($roleInfo)) {
+ return $roleInfo;
}
-
- return $info['phpextension'];
- }
-
- function getRoleFromClass()
- {
- $lower = strtolower(get_class($this));
- return ucfirst(str_replace('pear_installer_role_', '', $lower));
+ return $roleInfo['phpextension'];
}
-}<?php
+}
+?><?php
/**
* PEAR_Installer_Role_Data
*
@@ -73525,7 +80867,7 @@ class PEAR_Installer_Role_Common
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version CVS: $Id: Data.php 276383 2009-02-24 23:39:37Z dufuz $
+ * @version CVS: $Id: Data.php 313023 2011-07-06 19:17:11Z dufuz $
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.4.0a1
*/
@@ -73536,7 +80878,7 @@ class PEAR_Installer_Role_Common
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version Release: 1.10.0beta1
+ * @version Release: 1.9.4
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a1
*/
@@ -73566,7 +80908,7 @@ class PEAR_Installer_Role_Data extends PEAR_Installer_Role_Common {}
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version CVS: $Id: Doc.php 276383 2009-02-24 23:39:37Z dufuz $
+ * @version CVS: $Id: Doc.php 313023 2011-07-06 19:17:11Z dufuz $
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.4.0a1
*/
@@ -73577,7 +80919,7 @@ class PEAR_Installer_Role_Data extends PEAR_Installer_Role_Common {}
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version Release: 1.10.0beta1
+ * @version Release: 1.9.4
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a1
*/
@@ -73598,6 +80940,44 @@ class PEAR_Installer_Role_Doc extends PEAR_Installer_Role_Common {}
<config_vars />
</role><?php
/**
+ * PEAR_Installer_Role_Ext
+ *
+ * PHP versions 4 and 5
+ *
+ * @category pear
+ * @package PEAR
+ * @author Greg Beaver <cellog@php.net>
+ * @copyright 1997-2009 The Authors
+ * @license http://opensource.org/licenses/bsd-license.php New BSD License
+ * @version CVS: $Id: Ext.php 313023 2011-07-06 19:17:11Z dufuz $
+ * @link http://pear.php.net/package/PEAR
+ * @since File available since Release 1.4.0a1
+ */
+
+/**
+ * @category pear
+ * @package PEAR
+ * @author Greg Beaver <cellog@php.net>
+ * @copyright 1997-2009 The Authors
+ * @license http://opensource.org/licenses/bsd-license.php New BSD License
+ * @version Release: 1.9.4
+ * @link http://pear.php.net/package/PEAR
+ * @since Class available since Release 1.4.0a1
+ */
+class PEAR_Installer_Role_Ext extends PEAR_Installer_Role_Common {}
+?><role version="1.0">
+ <releasetypes>extbin</releasetypes>
+ <releasetypes>zendextbin</releasetypes>
+ <installable>1</installable>
+ <locationconfig>ext_dir</locationconfig>
+ <honorsbaseinstall>1</honorsbaseinstall>
+ <unusualbaseinstall />
+ <phpfile />
+ <executable />
+ <phpextension>1</phpextension>
+ <config_vars />
+</role><?php
+/**
* PEAR_Installer_Role_Php
*
* PHP versions 4 and 5
@@ -73607,7 +80987,7 @@ class PEAR_Installer_Role_Doc extends PEAR_Installer_Role_Common {}
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version CVS: $Id: Php.php 276383 2009-02-24 23:39:37Z dufuz $
+ * @version CVS: $Id: Php.php 313023 2011-07-06 19:17:11Z dufuz $
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.4.0a1
*/
@@ -73618,7 +80998,7 @@ class PEAR_Installer_Role_Doc extends PEAR_Installer_Role_Common {}
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version Release: 1.10.0beta1
+ * @version Release: 1.9.4
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a1
*/
@@ -73648,7 +81028,7 @@ class PEAR_Installer_Role_Php extends PEAR_Installer_Role_Common {}
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version CVS: $Id: Script.php 276383 2009-02-24 23:39:37Z dufuz $
+ * @version CVS: $Id: Script.php 313023 2011-07-06 19:17:11Z dufuz $
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.4.0a1
*/
@@ -73659,7 +81039,7 @@ class PEAR_Installer_Role_Php extends PEAR_Installer_Role_Common {}
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version Release: 1.10.0beta1
+ * @version Release: 1.9.4
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a1
*/
@@ -73680,6 +81060,50 @@ class PEAR_Installer_Role_Script extends PEAR_Installer_Role_Common {}
<config_vars />
</role><?php
/**
+ * PEAR_Installer_Role_Src
+ *
+ * PHP versions 4 and 5
+ *
+ * @category pear
+ * @package PEAR
+ * @author Greg Beaver <cellog@php.net>
+ * @copyright 1997-2009 The Authors
+ * @license http://opensource.org/licenses/bsd-license.php New BSD License
+ * @version CVS: $Id: Src.php 313023 2011-07-06 19:17:11Z dufuz $
+ * @link http://pear.php.net/package/PEAR
+ * @since File available since Release 1.4.0a1
+ */
+
+/**
+ * @category pear
+ * @package PEAR
+ * @author Greg Beaver <cellog@php.net>
+ * @copyright 1997-2009 The Authors
+ * @license http://opensource.org/licenses/bsd-license.php New BSD License
+ * @version Release: 1.9.4
+ * @link http://pear.php.net/package/PEAR
+ * @since Class available since Release 1.4.0a1
+ */
+class PEAR_Installer_Role_Src extends PEAR_Installer_Role_Common
+{
+ function setup(&$installer, $pkg, $atts, $file)
+ {
+ $installer->source_files++;
+ }
+}
+?><role version="1.0">
+ <releasetypes>extsrc</releasetypes>
+ <releasetypes>zendextsrc</releasetypes>
+ <installable>1</installable>
+ <locationconfig>temp_dir</locationconfig>
+ <honorsbaseinstall />
+ <unusualbaseinstall />
+ <phpfile />
+ <executable />
+ <phpextension />
+ <config_vars />
+</role><?php
+/**
* PEAR_Installer_Role_Test
*
* PHP versions 4 and 5
@@ -73689,7 +81113,7 @@ class PEAR_Installer_Role_Script extends PEAR_Installer_Role_Common {}
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version CVS: $Id: Test.php 276383 2009-02-24 23:39:37Z dufuz $
+ * @version CVS: $Id: Test.php 313023 2011-07-06 19:17:11Z dufuz $
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.4.0a1
*/
@@ -73700,7 +81124,7 @@ class PEAR_Installer_Role_Script extends PEAR_Installer_Role_Common {}
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version Release: 1.10.0beta1
+ * @version Release: 1.9.4
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a1
*/
@@ -73721,6 +81145,47 @@ class PEAR_Installer_Role_Test extends PEAR_Installer_Role_Common {}
<config_vars />
</role><?php
/**
+ * PEAR_Installer_Role_Www
+ *
+ * PHP versions 4 and 5
+ *
+ * @category pear
+ * @package PEAR
+ * @author Greg Beaver <cellog@php.net>
+ * @copyright 2007-2009 The Authors
+ * @license http://opensource.org/licenses/bsd-license.php New BSD License
+ * @version CVS: $Id: Www.php 313023 2011-07-06 19:17:11Z dufuz $
+ * @link http://pear.php.net/package/PEAR
+ * @since File available since Release 1.7.0
+ */
+
+/**
+ * @category pear
+ * @package PEAR
+ * @author Greg Beaver <cellog@php.net>
+ * @copyright 2007-2009 The Authors
+ * @license http://opensource.org/licenses/bsd-license.php New BSD License
+ * @version Release: 1.9.4
+ * @link http://pear.php.net/package/PEAR
+ * @since Class available since Release 1.7.0
+ */
+class PEAR_Installer_Role_Www extends PEAR_Installer_Role_Common {}
+?><role version="1.0">
+ <releasetypes>php</releasetypes>
+ <releasetypes>extsrc</releasetypes>
+ <releasetypes>extbin</releasetypes>
+ <releasetypes>zendextsrc</releasetypes>
+ <releasetypes>zendextbin</releasetypes>
+ <installable>1</installable>
+ <locationconfig>www_dir</locationconfig>
+ <honorsbaseinstall>1</honorsbaseinstall>
+ <unusualbaseinstall />
+ <phpfile />
+ <executable />
+ <phpextension />
+ <config_vars />
+</role><?php
+/**
* PEAR_PackageFile, package.xml parsing utility class
*
* PHP versions 4 and 5
@@ -73730,7 +81195,7 @@ class PEAR_Installer_Role_Test extends PEAR_Installer_Role_Common {}
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version CVS: $Id: PackageFile.php 312909 2011-07-04 19:49:14Z dufuz $
+ * @version CVS: $Id: PackageFile.php 313024 2011-07-06 19:51:24Z dufuz $
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.4.0a1
*/
@@ -73756,7 +81221,7 @@ define('PEAR_PACKAGEFILE_ERROR_INVALID_PACKAGEVERSION', 2);
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version Release: 1.10.0beta1
+ * @version Release: 1.9.4
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a1
*/
@@ -74221,7 +81686,7 @@ class PEAR_PackageFile
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version CVS: $Id: v1.php 286494 2009-07-29 06:57:11Z dufuz $
+ * @version CVS: $Id: v1.php 313023 2011-07-06 19:17:11Z dufuz $
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.4.0a1
*/
@@ -74241,7 +81706,7 @@ require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/PackageFile/v2.php';
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version Release: 1.10.0beta1
+ * @version Release: 1.9.4
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a1
*/
@@ -74258,7 +81723,7 @@ class PEAR_PackageFile_Generator_v1
function getPackagerVersion()
{
- return '1.10.0beta1';
+ return '1.9.4';
}
/**
@@ -74412,7 +81877,7 @@ class PEAR_PackageFile_Generator_v1
);
$ret = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n";
$ret .= "<!DOCTYPE package SYSTEM \"http://pear.php.net/dtd/package-1.0\">\n";
- $ret .= "<package version=\"1.0\" packagerversion=\"1.10.0beta1\">\n" .
+ $ret .= "<package version=\"1.0\" packagerversion=\"1.9.4\">\n" .
" <name>$pkginfo[package]</name>";
if (isset($pkginfo['extends'])) {
$ret .= "\n<extends>$pkginfo[extends]</extends>";
@@ -75505,7 +82970,7 @@ class PEAR_PackageFile_Generator_v1
* @author Stephan Schmidt (original XML_Serializer code)
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version CVS: $Id: v2.php 278907 2009-04-17 21:10:04Z dufuz $
+ * @version CVS: $Id: v2.php 313023 2011-07-06 19:17:11Z dufuz $
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.4.0a1
*/
@@ -75526,7 +82991,7 @@ require_once 'phar://install-pear-nozlib.phar/' . 'XML/Util.php';
* @author Stephan Schmidt (original XML_Serializer code)
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version Release: 1.10.0beta1
+ * @version Release: 1.9.4
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a1
*/
@@ -75608,7 +83073,7 @@ http://pear.php.net/dtd/package-2.0.xsd',
*/
function getPackagerVersion()
{
- return '1.10.0beta1';
+ return '1.9.4';
}
/**
@@ -75893,7 +83358,7 @@ http://pear.php.net/dtd/package-2.0.xsd',
$this->options['beautifyFilelist'] = true;
}
- $arr['attribs']['packagerversion'] = '1.10.0beta1';
+ $arr['attribs']['packagerversion'] = '1.9.4';
if ($this->serialize($arr, $options)) {
return $this->_serializedData . "\n";
}
@@ -76396,7 +83861,7 @@ http://pear.php.net/dtd/package-2.0.xsd',
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version CVS: $Id: v1.php 276385 2009-02-24 23:46:03Z dufuz $
+ * @version CVS: $Id: v1.php 313023 2011-07-06 19:17:11Z dufuz $
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.4.0a1
*/
@@ -76854,7 +84319,7 @@ class PEAR_PackageFile_Parser_v1
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version CVS: $Id: v2.php 276385 2009-02-24 23:46:03Z dufuz $
+ * @version CVS: $Id: v2.php 313023 2011-07-06 19:17:11Z dufuz $
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.4.0a1
*/
@@ -76966,7 +84431,7 @@ class PEAR_PackageFile_Parser_v2 extends PEAR_XMLParser
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version CVS: $Id: v1.php 276383 2009-02-24 23:39:37Z dufuz $
+ * @version CVS: $Id: v1.php 313023 2011-07-06 19:17:11Z dufuz $
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.4.0a1
*/
@@ -77232,7 +84697,7 @@ define('PEAR_PACKAGEFILE_ERROR_INVALID_FILENAME', 52);
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version Release: 1.10.0beta1
+ * @version Release: 1.9.4
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a1
*/
@@ -77293,7 +84758,7 @@ class PEAR_PackageFile_v1
*
* - package name
* - channel name
- * - dependencies
+ * - dependencies
* @var boolean
* @access private
*/
@@ -78157,14 +85622,14 @@ class PEAR_PackageFile_v1
array('file' => $file));
}
if (isset($fa['install-as']) &&
- preg_match('~/\.\.?(/|\\z)|^\.\.?/~',
+ preg_match('~/\.\.?(/|\\z)|^\.\.?/~',
str_replace('\\', '/', $fa['install-as']))) {
// install-as contains .. parent directory or . cur directory references
$this->_validateError(PEAR_PACKAGEFILE_ERROR_INVALID_FILENAME,
array('file' => $file . ' [installed as ' . $fa['install-as'] . ']'));
}
if (isset($fa['baseinstalldir']) &&
- preg_match('~/\.\.?(/|\\z)|^\.\.?/~',
+ preg_match('~/\.\.?(/|\\z)|^\.\.?/~',
str_replace('\\', '/', $fa['baseinstalldir']))) {
// install-as contains .. parent directory or . cur directory references
$this->_validateError(PEAR_PACKAGEFILE_ERROR_INVALID_FILENAME,
@@ -78426,7 +85891,7 @@ class PEAR_PackageFile_v1
if (version_compare(zend_version(), '2.0', '<')) {
if (in_array(strtolower($data),
array('public', 'private', 'protected', 'abstract',
- 'interface', 'implements', 'throw')
+ 'interface', 'implements', 'throw')
)) {
$this->_validateWarning(PEAR_PACKAGEFILE_ERROR_PHP5,
array($file));
@@ -78578,7 +86043,7 @@ class PEAR_PackageFile_v1
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version CVS: $Id: v2.php 309461 2011-03-20 03:57:29Z dufuz $
+ * @version CVS: $Id: v2.php 313023 2011-07-06 19:17:11Z dufuz $
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.4.0a1
*/
@@ -78592,7 +86057,7 @@ require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/ErrorStack.php';
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version Release: 1.10.0beta1
+ * @version Release: 1.9.4
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a1
*/
@@ -79736,18 +87201,15 @@ class PEAR_PackageFile_v2
if (isset($this->_packageInfo['filelist']) && !$preserve) {
return $this->_packageInfo['filelist'];
}
-
$this->flattenFilelist();
if ($contents = $this->getContents()) {
$ret = array();
if (!isset($contents['dir'])) {
return false;
}
-
if (!isset($contents['dir']['file'][0])) {
$contents['dir']['file'] = array($contents['dir']['file']);
}
-
foreach ($contents['dir']['file'] as $file) {
$name = $file['attribs']['name'];
if (!$preserve) {
@@ -79755,14 +87217,11 @@ class PEAR_PackageFile_v2
}
$ret[$name] = $file;
}
-
if (!$preserve) {
$this->_packageInfo['filelist'] = $ret;
}
-
return $ret;
}
-
return false;
}
@@ -79816,12 +87275,10 @@ class PEAR_PackageFile_v2
if (isset($contents['dir']['attribs']['baseinstalldir'])) {
$base = $contents['dir']['attribs']['baseinstalldir'];
}
-
if (isset($this->_packageInfo['bundle'])) {
return PEAR::raiseError(
'Exception: bundles should be handled in download code only');
}
-
$release = $this->getReleases();
if ($release) {
if (!isset($release[0])) {
@@ -79829,12 +87286,10 @@ class PEAR_PackageFile_v2
if ($forfilecheck) {
return $this->getFilelist();
}
-
return $contents;
}
$release = array($release);
}
-
$depchecker = &$this->getPEARDependency2($this->_config, array(),
array('channel' => $this->getChannel(), 'package' => $this->getPackage()),
PEAR_VALIDATE_INSTALLING);
@@ -79847,7 +87302,6 @@ class PEAR_PackageFile_v2
if (!isset($conditions[0])) {
$conditions = array($conditions);
}
-
foreach ($conditions as $condition) {
$ret = $depchecker->{"validate{$type}Dependency"}($condition);
if (PEAR::isError($ret)) {
@@ -79856,11 +87310,9 @@ class PEAR_PackageFile_v2
}
}
}
-
PEAR::popErrorHandling();
}
}
-
// this is the release to use
if (isset($instance['filelist'])) {
// ignore files
@@ -79872,7 +87324,6 @@ class PEAR_PackageFile_v2
unset ($contents[$ig['attribs']['name']]);
}
}
-
// install files as this name
if (isset($instance['filelist']['install'])) {
$installas = isset($instance['filelist']['install'][0]) ?
@@ -79884,23 +87335,19 @@ class PEAR_PackageFile_v2
}
}
}
-
if ($forfilecheck) {
foreach ($contents as $file => $attrs) {
$contents[$file] = $attrs['attribs'];
}
}
-
return $contents;
}
} else { // simple release - no installconditions or install-as
if ($forfilecheck) {
return $this->getFilelist();
}
-
return $contents;
}
-
// no releases matched
return PEAR::raiseError('No releases in package.xml matched the existing operating ' .
'system, extensions installed, or architecture, cannot install');
@@ -80645,7 +88092,1610 @@ class PEAR_PackageFile_v2
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version CVS: $Id: Validator.php 308728 2011-02-27 18:58:02Z dufuz $
+ * @version CVS: $Id: rw.php 313023 2011-07-06 19:17:11Z dufuz $
+ * @link http://pear.php.net/package/PEAR
+ * @since File available since Release 1.4.0a8
+ */
+/**
+ * For base class
+ */
+require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/PackageFile/v2.php';
+/**
+ * @category pear
+ * @package PEAR
+ * @author Greg Beaver <cellog@php.net>
+ * @copyright 1997-2009 The Authors
+ * @license http://opensource.org/licenses/bsd-license.php New BSD License
+ * @version Release: 1.9.4
+ * @link http://pear.php.net/package/PEAR
+ * @since Class available since Release 1.4.0a8
+ */
+class PEAR_PackageFile_v2_rw extends PEAR_PackageFile_v2
+{
+ /**
+ * @param string Extension name
+ * @return bool success of operation
+ */
+ function setProvidesExtension($extension)
+ {
+ if (in_array($this->getPackageType(),
+ array('extsrc', 'extbin', 'zendextsrc', 'zendextbin'))) {
+ if (!isset($this->_packageInfo['providesextension'])) {
+ // ensure that the channel tag is set up in the right location
+ $this->_packageInfo = $this->_insertBefore($this->_packageInfo,
+ array('usesrole', 'usestask', 'srcpackage', 'srcuri', 'phprelease',
+ 'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease',
+ 'bundle', 'changelog'),
+ $extension, 'providesextension');
+ }
+ $this->_packageInfo['providesextension'] = $extension;
+ return true;
+ }
+ return false;
+ }
+
+ function setPackage($package)
+ {
+ $this->_isValid = 0;
+ if (!isset($this->_packageInfo['attribs'])) {
+ $this->_packageInfo = array_merge(array('attribs' => array(
+ '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',
+ )), $this->_packageInfo);
+ }
+ if (!isset($this->_packageInfo['name'])) {
+ return $this->_packageInfo = array_merge(array('name' => $package),
+ $this->_packageInfo);
+ }
+ $this->_packageInfo['name'] = $package;
+ }
+
+ /**
+ * set this as a package.xml version 2.1
+ * @access private
+ */
+ function _setPackageVersion2_1()
+ {
+ $info = array(
+ 'version' => '2.1',
+ 'xmlns' => 'http://pear.php.net/dtd/package-2.1',
+ '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.1
+ http://pear.php.net/dtd/package-2.1.xsd',
+ );
+ if (!isset($this->_packageInfo['attribs'])) {
+ $this->_packageInfo = array_merge(array('attribs' => $info), $this->_packageInfo);
+ } else {
+ $this->_packageInfo['attribs'] = $info;
+ }
+ }
+
+ function setUri($uri)
+ {
+ unset($this->_packageInfo['channel']);
+ $this->_isValid = 0;
+ if (!isset($this->_packageInfo['uri'])) {
+ // ensure that the uri tag is set up in the right location
+ $this->_packageInfo = $this->_insertBefore($this->_packageInfo,
+ array('extends', 'summary', 'description', 'lead',
+ 'developer', 'contributor', 'helper', 'date', 'time', 'version',
+ 'stability', 'license', 'notes', 'contents', 'compatible',
+ 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
+ 'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
+ 'extbinrelease', 'bundle', 'changelog'), $uri, 'uri');
+ }
+ $this->_packageInfo['uri'] = $uri;
+ }
+
+ function setChannel($channel)
+ {
+ unset($this->_packageInfo['uri']);
+ $this->_isValid = 0;
+ if (!isset($this->_packageInfo['channel'])) {
+ // ensure that the channel tag is set up in the right location
+ $this->_packageInfo = $this->_insertBefore($this->_packageInfo,
+ array('extends', 'summary', 'description', 'lead',
+ 'developer', 'contributor', 'helper', 'date', 'time', 'version',
+ 'stability', 'license', 'notes', 'contents', 'compatible',
+ 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
+ 'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
+ 'extbinrelease', 'bundle', 'changelog'), $channel, 'channel');
+ }
+ $this->_packageInfo['channel'] = $channel;
+ }
+
+ function setExtends($extends)
+ {
+ $this->_isValid = 0;
+ if (!isset($this->_packageInfo['extends'])) {
+ // ensure that the extends tag is set up in the right location
+ $this->_packageInfo = $this->_insertBefore($this->_packageInfo,
+ array('summary', 'description', 'lead',
+ 'developer', 'contributor', 'helper', 'date', 'time', 'version',
+ 'stability', 'license', 'notes', 'contents', 'compatible',
+ 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
+ 'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
+ 'extbinrelease', 'bundle', 'changelog'), $extends, 'extends');
+ }
+ $this->_packageInfo['extends'] = $extends;
+ }
+
+ function setSummary($summary)
+ {
+ $this->_isValid = 0;
+ if (!isset($this->_packageInfo['summary'])) {
+ // ensure that the summary tag is set up in the right location
+ $this->_packageInfo = $this->_insertBefore($this->_packageInfo,
+ array('description', 'lead',
+ 'developer', 'contributor', 'helper', 'date', 'time', 'version',
+ 'stability', 'license', 'notes', 'contents', 'compatible',
+ 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
+ 'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
+ 'extbinrelease', 'bundle', 'changelog'), $summary, 'summary');
+ }
+ $this->_packageInfo['summary'] = $summary;
+ }
+
+ function setDescription($desc)
+ {
+ $this->_isValid = 0;
+ if (!isset($this->_packageInfo['description'])) {
+ // ensure that the description tag is set up in the right location
+ $this->_packageInfo = $this->_insertBefore($this->_packageInfo,
+ array('lead',
+ 'developer', 'contributor', 'helper', 'date', 'time', 'version',
+ 'stability', 'license', 'notes', 'contents', 'compatible',
+ 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
+ 'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
+ 'extbinrelease', 'bundle', 'changelog'), $desc, 'description');
+ }
+ $this->_packageInfo['description'] = $desc;
+ }
+
+ /**
+ * Adds a new maintainer - no checking of duplicates is performed, use
+ * updatemaintainer for that purpose.
+ */
+ function addMaintainer($role, $handle, $name, $email, $active = 'yes')
+ {
+ if (!in_array($role, array('lead', 'developer', 'contributor', 'helper'))) {
+ return false;
+ }
+ if (isset($this->_packageInfo[$role])) {
+ if (!isset($this->_packageInfo[$role][0])) {
+ $this->_packageInfo[$role] = array($this->_packageInfo[$role]);
+ }
+ $this->_packageInfo[$role][] =
+ array(
+ 'name' => $name,
+ 'user' => $handle,
+ 'email' => $email,
+ 'active' => $active,
+ );
+ } else {
+ $testarr = array('lead',
+ 'developer', 'contributor', 'helper', 'date', 'time', 'version',
+ 'stability', 'license', 'notes', 'contents', 'compatible',
+ 'dependencies', 'providesextension', 'usesrole', 'usestask',
+ 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease',
+ 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog');
+ foreach (array('lead', 'developer', 'contributor', 'helper') as $testrole) {
+ array_shift($testarr);
+ if ($role == $testrole) {
+ break;
+ }
+ }
+ if (!isset($this->_packageInfo[$role])) {
+ // ensure that the extends tag is set up in the right location
+ $this->_packageInfo = $this->_insertBefore($this->_packageInfo, $testarr,
+ array(), $role);
+ }
+ $this->_packageInfo[$role] =
+ array(
+ 'name' => $name,
+ 'user' => $handle,
+ 'email' => $email,
+ 'active' => $active,
+ );
+ }
+ $this->_isValid = 0;
+ }
+
+ function updateMaintainer($newrole, $handle, $name, $email, $active = 'yes')
+ {
+ $found = false;
+ foreach (array('lead', 'developer', 'contributor', 'helper') as $role) {
+ if (!isset($this->_packageInfo[$role])) {
+ continue;
+ }
+ $info = $this->_packageInfo[$role];
+ if (!isset($info[0])) {
+ if ($info['user'] == $handle) {
+ $found = true;
+ break;
+ }
+ }
+ foreach ($info as $i => $maintainer) {
+ if ($maintainer['user'] == $handle) {
+ $found = $i;
+ break 2;
+ }
+ }
+ }
+ if ($found === false) {
+ return $this->addMaintainer($newrole, $handle, $name, $email, $active);
+ }
+ if ($found !== false) {
+ if ($found === true) {
+ unset($this->_packageInfo[$role]);
+ } else {
+ unset($this->_packageInfo[$role][$found]);
+ $this->_packageInfo[$role] = array_values($this->_packageInfo[$role]);
+ }
+ }
+ $this->addMaintainer($newrole, $handle, $name, $email, $active);
+ $this->_isValid = 0;
+ }
+
+ function deleteMaintainer($handle)
+ {
+ $found = false;
+ foreach (array('lead', 'developer', 'contributor', 'helper') as $role) {
+ if (!isset($this->_packageInfo[$role])) {
+ continue;
+ }
+ if (!isset($this->_packageInfo[$role][0])) {
+ $this->_packageInfo[$role] = array($this->_packageInfo[$role]);
+ }
+ foreach ($this->_packageInfo[$role] as $i => $maintainer) {
+ if ($maintainer['user'] == $handle) {
+ $found = $i;
+ break;
+ }
+ }
+ if ($found !== false) {
+ unset($this->_packageInfo[$role][$found]);
+ if (!count($this->_packageInfo[$role]) && $role == 'lead') {
+ $this->_isValid = 0;
+ }
+ if (!count($this->_packageInfo[$role])) {
+ unset($this->_packageInfo[$role]);
+ return true;
+ }
+ $this->_packageInfo[$role] =
+ array_values($this->_packageInfo[$role]);
+ if (count($this->_packageInfo[$role]) == 1) {
+ $this->_packageInfo[$role] = $this->_packageInfo[$role][0];
+ }
+ return true;
+ }
+ if (count($this->_packageInfo[$role]) == 1) {
+ $this->_packageInfo[$role] = $this->_packageInfo[$role][0];
+ }
+ }
+ return false;
+ }
+
+ function setReleaseVersion($version)
+ {
+ if (isset($this->_packageInfo['version']) &&
+ isset($this->_packageInfo['version']['release'])) {
+ unset($this->_packageInfo['version']['release']);
+ }
+ $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $version, array(
+ 'version' => array('stability', 'license', 'notes', 'contents', 'compatible',
+ 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
+ 'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
+ 'extbinrelease', 'bundle', 'changelog'),
+ 'release' => array('api')));
+ $this->_isValid = 0;
+ }
+
+ function setAPIVersion($version)
+ {
+ if (isset($this->_packageInfo['version']) &&
+ isset($this->_packageInfo['version']['api'])) {
+ unset($this->_packageInfo['version']['api']);
+ }
+ $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $version, array(
+ 'version' => array('stability', 'license', 'notes', 'contents', 'compatible',
+ 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
+ 'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
+ 'extbinrelease', 'bundle', 'changelog'),
+ 'api' => array()));
+ $this->_isValid = 0;
+ }
+
+ /**
+ * snapshot|devel|alpha|beta|stable
+ */
+ function setReleaseStability($state)
+ {
+ if (isset($this->_packageInfo['stability']) &&
+ isset($this->_packageInfo['stability']['release'])) {
+ unset($this->_packageInfo['stability']['release']);
+ }
+ $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $state, array(
+ 'stability' => array('license', 'notes', 'contents', 'compatible',
+ 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
+ 'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
+ 'extbinrelease', 'bundle', 'changelog'),
+ 'release' => array('api')));
+ $this->_isValid = 0;
+ }
+
+ /**
+ * @param devel|alpha|beta|stable
+ */
+ function setAPIStability($state)
+ {
+ if (isset($this->_packageInfo['stability']) &&
+ isset($this->_packageInfo['stability']['api'])) {
+ unset($this->_packageInfo['stability']['api']);
+ }
+ $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $state, array(
+ 'stability' => array('license', 'notes', 'contents', 'compatible',
+ 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
+ 'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
+ 'extbinrelease', 'bundle', 'changelog'),
+ 'api' => array()));
+ $this->_isValid = 0;
+ }
+
+ function setLicense($license, $uri = false, $filesource = false)
+ {
+ if (!isset($this->_packageInfo['license'])) {
+ // ensure that the license tag is set up in the right location
+ $this->_packageInfo = $this->_insertBefore($this->_packageInfo,
+ array('notes', 'contents', 'compatible',
+ 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
+ 'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
+ 'extbinrelease', 'bundle', 'changelog'), 0, 'license');
+ }
+ if ($uri || $filesource) {
+ $attribs = array();
+ if ($uri) {
+ $attribs['uri'] = $uri;
+ }
+ $uri = true; // for test below
+ if ($filesource) {
+ $attribs['filesource'] = $filesource;
+ }
+ }
+ $license = $uri ? array('attribs' => $attribs, '_content' => $license) : $license;
+ $this->_packageInfo['license'] = $license;
+ $this->_isValid = 0;
+ }
+
+ function setNotes($notes)
+ {
+ $this->_isValid = 0;
+ if (!isset($this->_packageInfo['notes'])) {
+ // ensure that the notes tag is set up in the right location
+ $this->_packageInfo = $this->_insertBefore($this->_packageInfo,
+ array('contents', 'compatible',
+ 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
+ 'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
+ 'extbinrelease', 'bundle', 'changelog'), $notes, 'notes');
+ }
+ $this->_packageInfo['notes'] = $notes;
+ }
+
+ /**
+ * This is only used at install-time, after all serialization
+ * is over.
+ * @param string file name
+ * @param string installed path
+ */
+ function setInstalledAs($file, $path)
+ {
+ if ($path) {
+ return $this->_packageInfo['filelist'][$file]['installed_as'] = $path;
+ }
+ unset($this->_packageInfo['filelist'][$file]['installed_as']);
+ }
+
+ /**
+ * This is only used at install-time, after all serialization
+ * is over.
+ */
+ function installedFile($file, $atts)
+ {
+ if (isset($this->_packageInfo['filelist'][$file])) {
+ $this->_packageInfo['filelist'][$file] =
+ array_merge($this->_packageInfo['filelist'][$file], $atts['attribs']);
+ } else {
+ $this->_packageInfo['filelist'][$file] = $atts['attribs'];
+ }
+ }
+
+ /**
+ * Reset the listing of package contents
+ * @param string base installation dir for the whole package, if any
+ */
+ function clearContents($baseinstall = false)
+ {
+ $this->_filesValid = false;
+ $this->_isValid = 0;
+ if (!isset($this->_packageInfo['contents'])) {
+ $this->_packageInfo = $this->_insertBefore($this->_packageInfo,
+ array('compatible',
+ 'dependencies', 'providesextension', 'usesrole', 'usestask',
+ 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease',
+ 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease',
+ 'bundle', 'changelog'), array(), 'contents');
+ }
+ if ($this->getPackageType() != 'bundle') {
+ $this->_packageInfo['contents'] =
+ array('dir' => array('attribs' => array('name' => '/')));
+ if ($baseinstall) {
+ $this->_packageInfo['contents']['dir']['attribs']['baseinstalldir'] = $baseinstall;
+ }
+ } else {
+ $this->_packageInfo['contents'] = array('bundledpackage' => array());
+ }
+ }
+
+ /**
+ * @param string relative path of the bundled package.
+ */
+ function addBundledPackage($path)
+ {
+ if ($this->getPackageType() != 'bundle') {
+ return false;
+ }
+ $this->_filesValid = false;
+ $this->_isValid = 0;
+ $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $path, array(
+ 'contents' => array('compatible', 'dependencies', 'providesextension',
+ 'usesrole', 'usestask', 'srcpackage', 'srcuri', 'phprelease',
+ 'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease',
+ 'bundle', 'changelog'),
+ 'bundledpackage' => array()));
+ }
+
+ /**
+ * @param string file name
+ * @param PEAR_Task_Common a read/write task
+ */
+ function addTaskToFile($filename, $task)
+ {
+ if (!method_exists($task, 'getXml')) {
+ return false;
+ }
+ if (!method_exists($task, 'getName')) {
+ return false;
+ }
+ if (!method_exists($task, 'validate')) {
+ return false;
+ }
+ if (!$task->validate()) {
+ return false;
+ }
+ if (!isset($this->_packageInfo['contents']['dir']['file'])) {
+ return false;
+ }
+ $this->getTasksNs(); // discover the tasks namespace if not done already
+ $files = $this->_packageInfo['contents']['dir']['file'];
+ if (!isset($files[0])) {
+ $files = array($files);
+ $ind = false;
+ } else {
+ $ind = true;
+ }
+ foreach ($files as $i => $file) {
+ if (isset($file['attribs'])) {
+ if ($file['attribs']['name'] == $filename) {
+ if ($ind) {
+ $t = isset($this->_packageInfo['contents']['dir']['file'][$i]
+ ['attribs'][$this->_tasksNs .
+ ':' . $task->getName()]) ?
+ $this->_packageInfo['contents']['dir']['file'][$i]
+ ['attribs'][$this->_tasksNs .
+ ':' . $task->getName()] : false;
+ if ($t && !isset($t[0])) {
+ $this->_packageInfo['contents']['dir']['file'][$i]
+ [$this->_tasksNs . ':' . $task->getName()] = array($t);
+ }
+ $this->_packageInfo['contents']['dir']['file'][$i][$this->_tasksNs .
+ ':' . $task->getName()][] = $task->getXml();
+ } else {
+ $t = isset($this->_packageInfo['contents']['dir']['file']
+ ['attribs'][$this->_tasksNs .
+ ':' . $task->getName()]) ? $this->_packageInfo['contents']['dir']['file']
+ ['attribs'][$this->_tasksNs .
+ ':' . $task->getName()] : false;
+ if ($t && !isset($t[0])) {
+ $this->_packageInfo['contents']['dir']['file']
+ [$this->_tasksNs . ':' . $task->getName()] = array($t);
+ }
+ $this->_packageInfo['contents']['dir']['file'][$this->_tasksNs .
+ ':' . $task->getName()][] = $task->getXml();
+ }
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * @param string path to the file
+ * @param string filename
+ * @param array extra attributes
+ */
+ function addFile($dir, $file, $attrs)
+ {
+ if ($this->getPackageType() == 'bundle') {
+ return false;
+ }
+ $this->_filesValid = false;
+ $this->_isValid = 0;
+ $dir = preg_replace(array('!\\\\+!', '!/+!'), array('/', '/'), $dir);
+ if ($dir == '/' || $dir == '') {
+ $dir = '';
+ } else {
+ $dir .= '/';
+ }
+ $attrs['name'] = $dir . $file;
+ if (!isset($this->_packageInfo['contents'])) {
+ // ensure that the contents tag is set up
+ $this->_packageInfo = $this->_insertBefore($this->_packageInfo,
+ array('compatible', 'dependencies', 'providesextension', 'usesrole', 'usestask',
+ 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease',
+ 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease',
+ 'bundle', 'changelog'), array(), 'contents');
+ }
+ if (isset($this->_packageInfo['contents']['dir']['file'])) {
+ if (!isset($this->_packageInfo['contents']['dir']['file'][0])) {
+ $this->_packageInfo['contents']['dir']['file'] =
+ array($this->_packageInfo['contents']['dir']['file']);
+ }
+ $this->_packageInfo['contents']['dir']['file'][]['attribs'] = $attrs;
+ } else {
+ $this->_packageInfo['contents']['dir']['file']['attribs'] = $attrs;
+ }
+ }
+
+ /**
+ * @param string Dependent package name
+ * @param string Dependent package's channel name
+ * @param string minimum version of specified package that this release is guaranteed to be
+ * compatible with
+ * @param string maximum version of specified package that this release is guaranteed to be
+ * compatible with
+ * @param string versions of specified package that this release is not compatible with
+ */
+ function addCompatiblePackage($name, $channel, $min, $max, $exclude = false)
+ {
+ $this->_isValid = 0;
+ $set = array(
+ 'name' => $name,
+ 'channel' => $channel,
+ 'min' => $min,
+ 'max' => $max,
+ );
+ if ($exclude) {
+ $set['exclude'] = $exclude;
+ }
+ $this->_isValid = 0;
+ $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $set, array(
+ 'compatible' => array('dependencies', 'providesextension', 'usesrole', 'usestask',
+ 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
+ 'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog')
+ ));
+ }
+
+ /**
+ * Removes the <usesrole> tag entirely
+ */
+ function resetUsesrole()
+ {
+ if (isset($this->_packageInfo['usesrole'])) {
+ unset($this->_packageInfo['usesrole']);
+ }
+ }
+
+ /**
+ * @param string
+ * @param string package name or uri
+ * @param string channel name if non-uri
+ */
+ function addUsesrole($role, $packageOrUri, $channel = false) {
+ $set = array('role' => $role);
+ if ($channel) {
+ $set['package'] = $packageOrUri;
+ $set['channel'] = $channel;
+ } else {
+ $set['uri'] = $packageOrUri;
+ }
+ $this->_isValid = 0;
+ $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $set, array(
+ 'usesrole' => array('usestask', 'srcpackage', 'srcuri',
+ 'phprelease', 'extsrcrelease', 'extbinrelease',
+ 'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog')
+ ));
+ }
+
+ /**
+ * Removes the <usestask> tag entirely
+ */
+ function resetUsestask()
+ {
+ if (isset($this->_packageInfo['usestask'])) {
+ unset($this->_packageInfo['usestask']);
+ }
+ }
+
+
+ /**
+ * @param string
+ * @param string package name or uri
+ * @param string channel name if non-uri
+ */
+ function addUsestask($task, $packageOrUri, $channel = false) {
+ $set = array('task' => $task);
+ if ($channel) {
+ $set['package'] = $packageOrUri;
+ $set['channel'] = $channel;
+ } else {
+ $set['uri'] = $packageOrUri;
+ }
+ $this->_isValid = 0;
+ $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $set, array(
+ 'usestask' => array('srcpackage', 'srcuri',
+ 'phprelease', 'extsrcrelease', 'extbinrelease',
+ 'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog')
+ ));
+ }
+
+ /**
+ * Remove all compatible tags
+ */
+ function clearCompatible()
+ {
+ unset($this->_packageInfo['compatible']);
+ }
+
+ /**
+ * Reset dependencies prior to adding new ones
+ */
+ function clearDeps()
+ {
+ if (!isset($this->_packageInfo['dependencies'])) {
+ $this->_packageInfo = $this->_mergeTag($this->_packageInfo, array(),
+ array(
+ 'dependencies' => array('providesextension', 'usesrole', 'usestask',
+ 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
+ 'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog')));
+ }
+ $this->_packageInfo['dependencies'] = array();
+ }
+
+ /**
+ * @param string minimum PHP version allowed
+ * @param string maximum PHP version allowed
+ * @param array $exclude incompatible PHP versions
+ */
+ function setPhpDep($min, $max = false, $exclude = false)
+ {
+ $this->_isValid = 0;
+ $dep =
+ array(
+ 'min' => $min,
+ );
+ if ($max) {
+ $dep['max'] = $max;
+ }
+ if ($exclude) {
+ if (count($exclude) == 1) {
+ $exclude = $exclude[0];
+ }
+ $dep['exclude'] = $exclude;
+ }
+ if (isset($this->_packageInfo['dependencies']['required']['php'])) {
+ $this->_stack->push(__FUNCTION__, 'warning', array('dep' =>
+ $this->_packageInfo['dependencies']['required']['php']),
+ 'warning: PHP dependency already exists, overwriting');
+ unset($this->_packageInfo['dependencies']['required']['php']);
+ }
+ $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep,
+ array(
+ 'dependencies' => array('providesextension', 'usesrole', 'usestask',
+ 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
+ 'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
+ 'required' => array('optional', 'group'),
+ 'php' => array('pearinstaller', 'package', 'subpackage', 'extension', 'os', 'arch')
+ ));
+ return true;
+ }
+
+ /**
+ * @param string minimum allowed PEAR installer version
+ * @param string maximum allowed PEAR installer version
+ * @param string recommended PEAR installer version
+ * @param array incompatible version of the PEAR installer
+ */
+ function setPearinstallerDep($min, $max = false, $recommended = false, $exclude = false)
+ {
+ $this->_isValid = 0;
+ $dep =
+ array(
+ 'min' => $min,
+ );
+ if ($max) {
+ $dep['max'] = $max;
+ }
+ if ($recommended) {
+ $dep['recommended'] = $recommended;
+ }
+ if ($exclude) {
+ if (count($exclude) == 1) {
+ $exclude = $exclude[0];
+ }
+ $dep['exclude'] = $exclude;
+ }
+ if (isset($this->_packageInfo['dependencies']['required']['pearinstaller'])) {
+ $this->_stack->push(__FUNCTION__, 'warning', array('dep' =>
+ $this->_packageInfo['dependencies']['required']['pearinstaller']),
+ 'warning: PEAR Installer dependency already exists, overwriting');
+ unset($this->_packageInfo['dependencies']['required']['pearinstaller']);
+ }
+ $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep,
+ array(
+ 'dependencies' => array('providesextension', 'usesrole', 'usestask',
+ 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
+ 'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
+ 'required' => array('optional', 'group'),
+ 'pearinstaller' => array('package', 'subpackage', 'extension', 'os', 'arch')
+ ));
+ }
+
+ /**
+ * Mark a package as conflicting with this package
+ * @param string package name
+ * @param string package channel
+ * @param string extension this package provides, if any
+ * @param string|false minimum version required
+ * @param string|false maximum version allowed
+ * @param array|false versions to exclude from installation
+ */
+ function addConflictingPackageDepWithChannel($name, $channel,
+ $providesextension = false, $min = false, $max = false, $exclude = false)
+ {
+ $this->_isValid = 0;
+ $dep = $this->_constructDep($name, $channel, false, $min, $max, false,
+ $exclude, $providesextension, false, true);
+ $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep,
+ array(
+ 'dependencies' => array('providesextension', 'usesrole', 'usestask',
+ 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
+ 'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
+ 'required' => array('optional', 'group'),
+ 'package' => array('subpackage', 'extension', 'os', 'arch')
+ ));
+ }
+
+ /**
+ * Mark a package as conflicting with this package
+ * @param string package name
+ * @param string package channel
+ * @param string extension this package provides, if any
+ */
+ function addConflictingPackageDepWithUri($name, $uri, $providesextension = false)
+ {
+ $this->_isValid = 0;
+ $dep =
+ array(
+ 'name' => $name,
+ 'uri' => $uri,
+ 'conflicts' => '',
+ );
+ if ($providesextension) {
+ $dep['providesextension'] = $providesextension;
+ }
+ $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep,
+ array(
+ 'dependencies' => array('providesextension', 'usesrole', 'usestask',
+ 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
+ 'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
+ 'required' => array('optional', 'group'),
+ 'package' => array('subpackage', 'extension', 'os', 'arch')
+ ));
+ }
+
+ function addDependencyGroup($name, $hint)
+ {
+ $this->_isValid = 0;
+ $this->_packageInfo = $this->_mergeTag($this->_packageInfo,
+ array('attribs' => array('name' => $name, 'hint' => $hint)),
+ array(
+ 'dependencies' => array('providesextension', 'usesrole', 'usestask',
+ 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
+ 'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
+ 'group' => array(),
+ ));
+ }
+
+ /**
+ * @param string package name
+ * @param string|false channel name, false if this is a uri
+ * @param string|false uri name, false if this is a channel
+ * @param string|false minimum version required
+ * @param string|false maximum version allowed
+ * @param string|false recommended installation version
+ * @param array|false versions to exclude from installation
+ * @param string extension this package provides, if any
+ * @param bool if true, tells the installer to ignore the default optional dependency group
+ * when installing this package
+ * @param bool if true, tells the installer to negate this dependency (conflicts)
+ * @return array
+ * @access private
+ */
+ function _constructDep($name, $channel, $uri, $min, $max, $recommended, $exclude,
+ $providesextension = false, $nodefault = false,
+ $conflicts = false)
+ {
+ $dep =
+ array(
+ 'name' => $name,
+ );
+ if ($channel) {
+ $dep['channel'] = $channel;
+ } elseif ($uri) {
+ $dep['uri'] = $uri;
+ }
+ if ($min) {
+ $dep['min'] = $min;
+ }
+ if ($max) {
+ $dep['max'] = $max;
+ }
+ if ($recommended) {
+ $dep['recommended'] = $recommended;
+ }
+ if ($exclude) {
+ if (is_array($exclude) && count($exclude) == 1) {
+ $exclude = $exclude[0];
+ }
+ $dep['exclude'] = $exclude;
+ }
+ if ($conflicts) {
+ $dep['conflicts'] = '';
+ }
+ if ($nodefault) {
+ $dep['nodefault'] = '';
+ }
+ if ($providesextension) {
+ $dep['providesextension'] = $providesextension;
+ }
+ return $dep;
+ }
+
+ /**
+ * @param package|subpackage
+ * @param string group name
+ * @param string package name
+ * @param string package channel
+ * @param string minimum version
+ * @param string maximum version
+ * @param string recommended version
+ * @param array|false optional excluded versions
+ * @param string extension this package provides, if any
+ * @param bool if true, tells the installer to ignore the default optional dependency group
+ * when installing this package
+ * @return bool false if the dependency group has not been initialized with
+ * {@link addDependencyGroup()}, or a subpackage is added with
+ * a providesextension
+ */
+ function addGroupPackageDepWithChannel($type, $groupname, $name, $channel, $min = false,
+ $max = false, $recommended = false, $exclude = false,
+ $providesextension = false, $nodefault = false)
+ {
+ if ($type == 'subpackage' && $providesextension) {
+ return false; // subpackages must be php packages
+ }
+ $dep = $this->_constructDep($name, $channel, false, $min, $max, $recommended, $exclude,
+ $providesextension, $nodefault);
+ return $this->_addGroupDependency($type, $dep, $groupname);
+ }
+
+ /**
+ * @param package|subpackage
+ * @param string group name
+ * @param string package name
+ * @param string package uri
+ * @param string extension this package provides, if any
+ * @param bool if true, tells the installer to ignore the default optional dependency group
+ * when installing this package
+ * @return bool false if the dependency group has not been initialized with
+ * {@link addDependencyGroup()}
+ */
+ function addGroupPackageDepWithURI($type, $groupname, $name, $uri, $providesextension = false,
+ $nodefault = false)
+ {
+ if ($type == 'subpackage' && $providesextension) {
+ return false; // subpackages must be php packages
+ }
+ $dep = $this->_constructDep($name, false, $uri, false, false, false, false,
+ $providesextension, $nodefault);
+ return $this->_addGroupDependency($type, $dep, $groupname);
+ }
+
+ /**
+ * @param string group name (must be pre-existing)
+ * @param string extension name
+ * @param string minimum version allowed
+ * @param string maximum version allowed
+ * @param string recommended version
+ * @param array incompatible versions
+ */
+ function addGroupExtensionDep($groupname, $name, $min = false, $max = false,
+ $recommended = false, $exclude = false)
+ {
+ $this->_isValid = 0;
+ $dep = $this->_constructDep($name, false, false, $min, $max, $recommended, $exclude);
+ return $this->_addGroupDependency('extension', $dep, $groupname);
+ }
+
+ /**
+ * @param package|subpackage|extension
+ * @param array dependency contents
+ * @param string name of the dependency group to add this to
+ * @return boolean
+ * @access private
+ */
+ function _addGroupDependency($type, $dep, $groupname)
+ {
+ $arr = array('subpackage', 'extension');
+ if ($type != 'package') {
+ array_shift($arr);
+ }
+ if ($type == 'extension') {
+ array_shift($arr);
+ }
+ if (!isset($this->_packageInfo['dependencies']['group'])) {
+ return false;
+ } else {
+ if (!isset($this->_packageInfo['dependencies']['group'][0])) {
+ if ($this->_packageInfo['dependencies']['group']['attribs']['name'] == $groupname) {
+ $this->_packageInfo['dependencies']['group'] = $this->_mergeTag(
+ $this->_packageInfo['dependencies']['group'], $dep,
+ array(
+ $type => $arr
+ ));
+ $this->_isValid = 0;
+ return true;
+ } else {
+ return false;
+ }
+ } else {
+ foreach ($this->_packageInfo['dependencies']['group'] as $i => $group) {
+ if ($group['attribs']['name'] == $groupname) {
+ $this->_packageInfo['dependencies']['group'][$i] = $this->_mergeTag(
+ $this->_packageInfo['dependencies']['group'][$i], $dep,
+ array(
+ $type => $arr
+ ));
+ $this->_isValid = 0;
+ return true;
+ }
+ }
+ return false;
+ }
+ }
+ }
+
+ /**
+ * @param optional|required
+ * @param string package name
+ * @param string package channel
+ * @param string minimum version
+ * @param string maximum version
+ * @param string recommended version
+ * @param string extension this package provides, if any
+ * @param bool if true, tells the installer to ignore the default optional dependency group
+ * when installing this package
+ * @param array|false optional excluded versions
+ */
+ function addPackageDepWithChannel($type, $name, $channel, $min = false, $max = false,
+ $recommended = false, $exclude = false,
+ $providesextension = false, $nodefault = false)
+ {
+ if (!in_array($type, array('optional', 'required'), true)) {
+ $type = 'required';
+ }
+ $this->_isValid = 0;
+ $arr = array('optional', 'group');
+ if ($type != 'required') {
+ array_shift($arr);
+ }
+ $dep = $this->_constructDep($name, $channel, false, $min, $max, $recommended, $exclude,
+ $providesextension, $nodefault);
+ $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep,
+ array(
+ 'dependencies' => array('providesextension', 'usesrole', 'usestask',
+ 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
+ 'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
+ $type => $arr,
+ 'package' => array('subpackage', 'extension', 'os', 'arch')
+ ));
+ }
+
+ /**
+ * @param optional|required
+ * @param string name of the package
+ * @param string uri of the package
+ * @param string extension this package provides, if any
+ * @param bool if true, tells the installer to ignore the default optional dependency group
+ * when installing this package
+ */
+ function addPackageDepWithUri($type, $name, $uri, $providesextension = false,
+ $nodefault = false)
+ {
+ $this->_isValid = 0;
+ $arr = array('optional', 'group');
+ if ($type != 'required') {
+ array_shift($arr);
+ }
+ $dep = $this->_constructDep($name, false, $uri, false, false, false, false,
+ $providesextension, $nodefault);
+ $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep,
+ array(
+ 'dependencies' => array('providesextension', 'usesrole', 'usestask',
+ 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
+ 'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
+ $type => $arr,
+ 'package' => array('subpackage', 'extension', 'os', 'arch')
+ ));
+ }
+
+ /**
+ * @param optional|required optional, required
+ * @param string package name
+ * @param string package channel
+ * @param string minimum version
+ * @param string maximum version
+ * @param string recommended version
+ * @param array incompatible versions
+ * @param bool if true, tells the installer to ignore the default optional dependency group
+ * when installing this package
+ */
+ function addSubpackageDepWithChannel($type, $name, $channel, $min = false, $max = false,
+ $recommended = false, $exclude = false,
+ $nodefault = false)
+ {
+ $this->_isValid = 0;
+ $arr = array('optional', 'group');
+ if ($type != 'required') {
+ array_shift($arr);
+ }
+ $dep = $this->_constructDep($name, $channel, false, $min, $max, $recommended, $exclude,
+ $nodefault);
+ $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep,
+ array(
+ 'dependencies' => array('providesextension', 'usesrole', 'usestask',
+ 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
+ 'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
+ $type => $arr,
+ 'subpackage' => array('extension', 'os', 'arch')
+ ));
+ }
+
+ /**
+ * @param optional|required optional, required
+ * @param string package name
+ * @param string package uri for download
+ * @param bool if true, tells the installer to ignore the default optional dependency group
+ * when installing this package
+ */
+ function addSubpackageDepWithUri($type, $name, $uri, $nodefault = false)
+ {
+ $this->_isValid = 0;
+ $arr = array('optional', 'group');
+ if ($type != 'required') {
+ array_shift($arr);
+ }
+ $dep = $this->_constructDep($name, false, $uri, false, false, false, false, $nodefault);
+ $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep,
+ array(
+ 'dependencies' => array('providesextension', 'usesrole', 'usestask',
+ 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
+ 'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
+ $type => $arr,
+ 'subpackage' => array('extension', 'os', 'arch')
+ ));
+ }
+
+ /**
+ * @param optional|required optional, required
+ * @param string extension name
+ * @param string minimum version
+ * @param string maximum version
+ * @param string recommended version
+ * @param array incompatible versions
+ */
+ function addExtensionDep($type, $name, $min = false, $max = false, $recommended = false,
+ $exclude = false)
+ {
+ $this->_isValid = 0;
+ $arr = array('optional', 'group');
+ if ($type != 'required') {
+ array_shift($arr);
+ }
+ $dep = $this->_constructDep($name, false, false, $min, $max, $recommended, $exclude);
+ $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep,
+ array(
+ 'dependencies' => array('providesextension', 'usesrole', 'usestask',
+ 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
+ 'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
+ $type => $arr,
+ 'extension' => array('os', 'arch')
+ ));
+ }
+
+ /**
+ * @param string Operating system name
+ * @param boolean true if this package cannot be installed on this OS
+ */
+ function addOsDep($name, $conflicts = false)
+ {
+ $this->_isValid = 0;
+ $dep = array('name' => $name);
+ if ($conflicts) {
+ $dep['conflicts'] = '';
+ }
+ $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep,
+ array(
+ 'dependencies' => array('providesextension', 'usesrole', 'usestask',
+ 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
+ 'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
+ 'required' => array('optional', 'group'),
+ 'os' => array('arch')
+ ));
+ }
+
+ /**
+ * @param string Architecture matching pattern
+ * @param boolean true if this package cannot be installed on this architecture
+ */
+ function addArchDep($pattern, $conflicts = false)
+ {
+ $this->_isValid = 0;
+ $dep = array('pattern' => $pattern);
+ if ($conflicts) {
+ $dep['conflicts'] = '';
+ }
+ $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep,
+ array(
+ 'dependencies' => array('providesextension', 'usesrole', 'usestask',
+ 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
+ 'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
+ 'required' => array('optional', 'group'),
+ 'arch' => array()
+ ));
+ }
+
+ /**
+ * Set the kind of package, and erase all release tags
+ *
+ * - a php package is a PEAR-style package
+ * - an extbin package is a PECL-style extension binary
+ * - an extsrc package is a PECL-style source for a binary
+ * - an zendextbin package is a PECL-style zend extension binary
+ * - an zendextsrc package is a PECL-style source for a zend extension binary
+ * - a bundle package is a collection of other pre-packaged packages
+ * @param php|extbin|extsrc|zendextsrc|zendextbin|bundle
+ * @return bool success
+ */
+ function setPackageType($type)
+ {
+ $this->_isValid = 0;
+ if (!in_array($type, array('php', 'extbin', 'extsrc', 'zendextsrc',
+ 'zendextbin', 'bundle'))) {
+ return false;
+ }
+
+ if (in_array($type, array('zendextsrc', 'zendextbin'))) {
+ $this->_setPackageVersion2_1();
+ }
+
+ if ($type != 'bundle') {
+ $type .= 'release';
+ }
+
+ foreach (array('phprelease', 'extbinrelease', 'extsrcrelease',
+ 'zendextsrcrelease', 'zendextbinrelease', 'bundle') as $test) {
+ unset($this->_packageInfo[$test]);
+ }
+
+ if (!isset($this->_packageInfo[$type])) {
+ // ensure that the release tag is set up
+ $this->_packageInfo = $this->_insertBefore($this->_packageInfo, array('changelog'),
+ array(), $type);
+ }
+
+ $this->_packageInfo[$type] = array();
+ return true;
+ }
+
+ /**
+ * @return bool true if package type is set up
+ */
+ function addRelease()
+ {
+ if ($type = $this->getPackageType()) {
+ if ($type != 'bundle') {
+ $type .= 'release';
+ }
+ $this->_packageInfo = $this->_mergeTag($this->_packageInfo, array(),
+ array($type => array('changelog')));
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Get the current release tag in order to add to it
+ * @param bool returns only releases that have installcondition if true
+ * @return array|null
+ */
+ function &_getCurrentRelease($strict = true)
+ {
+ if ($p = $this->getPackageType()) {
+ if ($strict) {
+ if ($p == 'extsrc' || $p == 'zendextsrc') {
+ $a = null;
+ return $a;
+ }
+ }
+ if ($p != 'bundle') {
+ $p .= 'release';
+ }
+ if (isset($this->_packageInfo[$p][0])) {
+ return $this->_packageInfo[$p][count($this->_packageInfo[$p]) - 1];
+ } else {
+ return $this->_packageInfo[$p];
+ }
+ } else {
+ $a = null;
+ return $a;
+ }
+ }
+
+ /**
+ * Add a file to the current release that should be installed under a different name
+ * @param string <contents> path to file
+ * @param string name the file should be installed as
+ */
+ function addInstallAs($path, $as)
+ {
+ $r = &$this->_getCurrentRelease();
+ if ($r === null) {
+ return false;
+ }
+ $this->_isValid = 0;
+ $r = $this->_mergeTag($r, array('attribs' => array('name' => $path, 'as' => $as)),
+ array(
+ 'filelist' => array(),
+ 'install' => array('ignore')
+ ));
+ }
+
+ /**
+ * Add a file to the current release that should be ignored
+ * @param string <contents> path to file
+ * @return bool success of operation
+ */
+ function addIgnore($path)
+ {
+ $r = &$this->_getCurrentRelease();
+ if ($r === null) {
+ return false;
+ }
+ $this->_isValid = 0;
+ $r = $this->_mergeTag($r, array('attribs' => array('name' => $path)),
+ array(
+ 'filelist' => array(),
+ 'ignore' => array()
+ ));
+ }
+
+ /**
+ * Add an extension binary package for this extension source code release
+ *
+ * Note that the package must be from the same channel as the extension source package
+ * @param string
+ */
+ function addBinarypackage($package)
+ {
+ if ($this->getPackageType() != 'extsrc' && $this->getPackageType() != 'zendextsrc') {
+ return false;
+ }
+ $r = &$this->_getCurrentRelease(false);
+ if ($r === null) {
+ return false;
+ }
+ $this->_isValid = 0;
+ $r = $this->_mergeTag($r, $package,
+ array(
+ 'binarypackage' => array('filelist'),
+ ));
+ }
+
+ /**
+ * Add a configureoption to an extension source package
+ * @param string
+ * @param string
+ * @param string
+ */
+ function addConfigureOption($name, $prompt, $default = null)
+ {
+ if ($this->getPackageType() != 'extsrc' && $this->getPackageType() != 'zendextsrc') {
+ return false;
+ }
+
+ $r = &$this->_getCurrentRelease(false);
+ if ($r === null) {
+ return false;
+ }
+
+ $opt = array('attribs' => array('name' => $name, 'prompt' => $prompt));
+ if ($default !== null) {
+ $opt['attribs']['default'] = $default;
+ }
+
+ $this->_isValid = 0;
+ $r = $this->_mergeTag($r, $opt,
+ array(
+ 'configureoption' => array('binarypackage', 'filelist'),
+ ));
+ }
+
+ /**
+ * Set an installation condition based on php version for the current release set
+ * @param string minimum version
+ * @param string maximum version
+ * @param false|array incompatible versions of PHP
+ */
+ function setPhpInstallCondition($min, $max, $exclude = false)
+ {
+ $r = &$this->_getCurrentRelease();
+ if ($r === null) {
+ return false;
+ }
+ $this->_isValid = 0;
+ if (isset($r['installconditions']['php'])) {
+ unset($r['installconditions']['php']);
+ }
+ $dep = array('min' => $min, 'max' => $max);
+ if ($exclude) {
+ if (is_array($exclude) && count($exclude) == 1) {
+ $exclude = $exclude[0];
+ }
+ $dep['exclude'] = $exclude;
+ }
+ if ($this->getPackageType() == 'extsrc' || $this->getPackageType() == 'zendextsrc') {
+ $r = $this->_mergeTag($r, $dep,
+ array(
+ 'installconditions' => array('configureoption', 'binarypackage',
+ 'filelist'),
+ 'php' => array('extension', 'os', 'arch')
+ ));
+ } else {
+ $r = $this->_mergeTag($r, $dep,
+ array(
+ 'installconditions' => array('filelist'),
+ 'php' => array('extension', 'os', 'arch')
+ ));
+ }
+ }
+
+ /**
+ * @param optional|required optional, required
+ * @param string extension name
+ * @param string minimum version
+ * @param string maximum version
+ * @param string recommended version
+ * @param array incompatible versions
+ */
+ function addExtensionInstallCondition($name, $min = false, $max = false, $recommended = false,
+ $exclude = false)
+ {
+ $r = &$this->_getCurrentRelease();
+ if ($r === null) {
+ return false;
+ }
+ $this->_isValid = 0;
+ $dep = $this->_constructDep($name, false, false, $min, $max, $recommended, $exclude);
+ if ($this->getPackageType() == 'extsrc' || $this->getPackageType() == 'zendextsrc') {
+ $r = $this->_mergeTag($r, $dep,
+ array(
+ 'installconditions' => array('configureoption', 'binarypackage',
+ 'filelist'),
+ 'extension' => array('os', 'arch')
+ ));
+ } else {
+ $r = $this->_mergeTag($r, $dep,
+ array(
+ 'installconditions' => array('filelist'),
+ 'extension' => array('os', 'arch')
+ ));
+ }
+ }
+
+ /**
+ * Set an installation condition based on operating system for the current release set
+ * @param string OS name
+ * @param bool whether this OS is incompatible with the current release
+ */
+ function setOsInstallCondition($name, $conflicts = false)
+ {
+ $r = &$this->_getCurrentRelease();
+ if ($r === null) {
+ return false;
+ }
+ $this->_isValid = 0;
+ if (isset($r['installconditions']['os'])) {
+ unset($r['installconditions']['os']);
+ }
+ $dep = array('name' => $name);
+ if ($conflicts) {
+ $dep['conflicts'] = '';
+ }
+ if ($this->getPackageType() == 'extsrc' || $this->getPackageType() == 'zendextsrc') {
+ $r = $this->_mergeTag($r, $dep,
+ array(
+ 'installconditions' => array('configureoption', 'binarypackage',
+ 'filelist'),
+ 'os' => array('arch')
+ ));
+ } else {
+ $r = $this->_mergeTag($r, $dep,
+ array(
+ 'installconditions' => array('filelist'),
+ 'os' => array('arch')
+ ));
+ }
+ }
+
+ /**
+ * Set an installation condition based on architecture for the current release set
+ * @param string architecture pattern
+ * @param bool whether this arch is incompatible with the current release
+ */
+ function setArchInstallCondition($pattern, $conflicts = false)
+ {
+ $r = &$this->_getCurrentRelease();
+ if ($r === null) {
+ return false;
+ }
+ $this->_isValid = 0;
+ if (isset($r['installconditions']['arch'])) {
+ unset($r['installconditions']['arch']);
+ }
+ $dep = array('pattern' => $pattern);
+ if ($conflicts) {
+ $dep['conflicts'] = '';
+ }
+ if ($this->getPackageType() == 'extsrc' || $this->getPackageType() == 'zendextsrc') {
+ $r = $this->_mergeTag($r, $dep,
+ array(
+ 'installconditions' => array('configureoption', 'binarypackage',
+ 'filelist'),
+ 'arch' => array()
+ ));
+ } else {
+ $r = $this->_mergeTag($r, $dep,
+ array(
+ 'installconditions' => array('filelist'),
+ 'arch' => array()
+ ));
+ }
+ }
+
+ /**
+ * For extension binary releases, this is used to specify either the
+ * static URI to a source package, or the package name and channel of the extsrc/zendextsrc
+ * package it is based on.
+ * @param string Package name, or full URI to source package (extsrc/zendextsrc type)
+ */
+ function setSourcePackage($packageOrUri)
+ {
+ $this->_isValid = 0;
+ if (isset($this->_packageInfo['channel'])) {
+ $this->_packageInfo = $this->_insertBefore($this->_packageInfo, array('phprelease',
+ 'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease',
+ 'bundle', 'changelog'),
+ $packageOrUri, 'srcpackage');
+ } else {
+ $this->_packageInfo = $this->_insertBefore($this->_packageInfo, array('phprelease',
+ 'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease',
+ 'bundle', 'changelog'), $packageOrUri, 'srcuri');
+ }
+ }
+
+ /**
+ * Generate a valid change log entry from the current package.xml
+ * @param string|false
+ */
+ function generateChangeLogEntry($notes = false)
+ {
+ return array(
+ 'version' =>
+ array(
+ 'release' => $this->getVersion('release'),
+ 'api' => $this->getVersion('api'),
+ ),
+ 'stability' =>
+ $this->getStability(),
+ 'date' => $this->getDate(),
+ 'license' => $this->getLicense(true),
+ 'notes' => $notes ? $notes : $this->getNotes()
+ );
+ }
+
+ /**
+ * @param string release version to set change log notes for
+ * @param array output of {@link generateChangeLogEntry()}
+ */
+ function setChangelogEntry($releaseversion, $contents)
+ {
+ if (!isset($this->_packageInfo['changelog'])) {
+ $this->_packageInfo['changelog']['release'] = $contents;
+ return;
+ }
+ if (!isset($this->_packageInfo['changelog']['release'][0])) {
+ if ($this->_packageInfo['changelog']['release']['version']['release'] == $releaseversion) {
+ $this->_packageInfo['changelog']['release'] = array(
+ $this->_packageInfo['changelog']['release']);
+ } else {
+ $this->_packageInfo['changelog']['release'] = array(
+ $this->_packageInfo['changelog']['release']);
+ return $this->_packageInfo['changelog']['release'][] = $contents;
+ }
+ }
+ foreach($this->_packageInfo['changelog']['release'] as $index => $changelog) {
+ if (isset($changelog['version']) &&
+ strnatcasecmp($changelog['version']['release'], $releaseversion) == 0) {
+ $curlog = $index;
+ }
+ }
+ if (isset($curlog)) {
+ $this->_packageInfo['changelog']['release'][$curlog] = $contents;
+ } else {
+ $this->_packageInfo['changelog']['release'][] = $contents;
+ }
+ }
+
+ /**
+ * Remove the changelog entirely
+ */
+ function clearChangeLog()
+ {
+ unset($this->_packageInfo['changelog']);
+ }
+}<?php
+/**
+ * PEAR_PackageFile_v2, package.xml version 2.0, read/write version
+ *
+ * PHP versions 4 and 5
+ *
+ * @category pear
+ * @package PEAR
+ * @author Greg Beaver <cellog@php.net>
+ * @copyright 1997-2009 The Authors
+ * @license http://opensource.org/licenses/bsd-license.php New BSD License
+ * @version CVS: $Id: Validator.php 313023 2011-07-06 19:17:11Z dufuz $
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.4.0a8
*/
@@ -80657,7 +89707,7 @@ class PEAR_PackageFile_v2
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version Release: 1.10.0beta1
+ * @version Release: 1.9.4
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a8
* @access private
@@ -80748,7 +89798,7 @@ class PEAR_PackageFile_v2_Validator
isset($test['dependencies']['required']) &&
isset($test['dependencies']['required']['pearinstaller']) &&
isset($test['dependencies']['required']['pearinstaller']['min']) &&
- version_compare('1.10.0beta1',
+ version_compare('1.9.4',
$test['dependencies']['required']['pearinstaller']['min'], '<')
) {
$this->_pearVersionTooLow($test['dependencies']['required']['pearinstaller']['min']);
@@ -80892,7 +89942,7 @@ class PEAR_PackageFile_v2_Validator
$validator = $chan->getValidationObject($this->_pf->getPackage());
if (!$validator) {
$this->_stack->push(__FUNCTION__, 'error',
- array('channel' => $chan->getName(),
+ array('channel' => $chan->getName(),
'package' => $this->_pf->getPackage(),
'name' => $valpack['_content'],
'version' => $valpack['attribs']['version']),
@@ -81986,7 +91036,7 @@ class PEAR_PackageFile_v2_Validator
$this->_stack->push(__FUNCTION__, 'error',
array('version' => $version),
'This package.xml requires PEAR version %version% to parse properly, we are ' .
- 'version 1.10.0beta1');
+ 'version 1.9.4');
}
function _invalidTagOrder($oktags, $actual, $root)
@@ -82789,6 +91839,206 @@ class PEAR_PackageFile_v2_Validator
}
}<?php
/**
+ * PEAR_Packager for generating releases
+ *
+ * PHP versions 4 and 5
+ *
+ * @category pear
+ * @package PEAR
+ * @author Stig Bakken <ssb@php.net>
+ * @author Tomas V. V. Cox <cox@idecnet.com>
+ * @author Greg Beaver <cellog@php.net>
+ * @copyright 1997-2009 The Authors
+ * @license http://opensource.org/licenses/bsd-license.php New BSD License
+ * @version CVS: $Id: Packager.php 313023 2011-07-06 19:17:11Z dufuz $
+ * @link http://pear.php.net/package/PEAR
+ * @since File available since Release 0.1
+ */
+
+/**
+ * base class
+ */
+require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Common.php';
+require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/PackageFile.php';
+require_once 'phar://install-pear-nozlib.phar/' . 'System.php';
+
+/**
+ * Administration class used to make a PEAR release tarball.
+ *
+ * @category pear
+ * @package PEAR
+ * @author Greg Beaver <cellog@php.net>
+ * @copyright 1997-2009 The Authors
+ * @license http://opensource.org/licenses/bsd-license.php New BSD License
+ * @version Release: 1.9.4
+ * @link http://pear.php.net/package/PEAR
+ * @since Class available since Release 0.1
+ */
+class PEAR_Packager extends PEAR_Common
+{
+ /**
+ * @var PEAR_Registry
+ */
+ var $_registry;
+
+ function package($pkgfile = null, $compress = true, $pkg2 = null)
+ {
+ // {{{ validate supplied package.xml file
+ if (empty($pkgfile)) {
+ $pkgfile = 'package.xml';
+ }
+
+ PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
+ $pkg = &new PEAR_PackageFile($this->config, $this->debug);
+ $pf = &$pkg->fromPackageFile($pkgfile, PEAR_VALIDATE_NORMAL);
+ $main = &$pf;
+ PEAR::staticPopErrorHandling();
+ if (PEAR::isError($pf)) {
+ if (is_array($pf->getUserInfo())) {
+ foreach ($pf->getUserInfo() as $error) {
+ $this->log(0, 'Error: ' . $error['message']);
+ }
+ }
+
+ $this->log(0, $pf->getMessage());
+ return $this->raiseError("Cannot package, errors in package file");
+ }
+
+ foreach ($pf->getValidationWarnings() as $warning) {
+ $this->log(1, 'Warning: ' . $warning['message']);
+ }
+
+ // }}}
+ if ($pkg2) {
+ $this->log(0, 'Attempting to process the second package file');
+ PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
+ $pf2 = &$pkg->fromPackageFile($pkg2, PEAR_VALIDATE_NORMAL);
+ PEAR::staticPopErrorHandling();
+ if (PEAR::isError($pf2)) {
+ if (is_array($pf2->getUserInfo())) {
+ foreach ($pf2->getUserInfo() as $error) {
+ $this->log(0, 'Error: ' . $error['message']);
+ }
+ }
+ $this->log(0, $pf2->getMessage());
+ return $this->raiseError("Cannot package, errors in second package file");
+ }
+
+ foreach ($pf2->getValidationWarnings() as $warning) {
+ $this->log(1, 'Warning: ' . $warning['message']);
+ }
+
+ if ($pf2->getPackagexmlVersion() == '2.0' ||
+ $pf2->getPackagexmlVersion() == '2.1'
+ ) {
+ $main = &$pf2;
+ $other = &$pf;
+ } else {
+ $main = &$pf;
+ $other = &$pf2;
+ }
+
+ if ($main->getPackagexmlVersion() != '2.0' &&
+ $main->getPackagexmlVersion() != '2.1') {
+ return PEAR::raiseError('Error: cannot package two package.xml version 1.0, can ' .
+ 'only package together a package.xml 1.0 and package.xml 2.0');
+ }
+
+ if ($other->getPackagexmlVersion() != '1.0') {
+ return PEAR::raiseError('Error: cannot package two package.xml version 2.0, can ' .
+ 'only package together a package.xml 1.0 and package.xml 2.0');
+ }
+ }
+
+ $main->setLogger($this);
+ if (!$main->validate(PEAR_VALIDATE_PACKAGING)) {
+ foreach ($main->getValidationWarnings() as $warning) {
+ $this->log(0, 'Error: ' . $warning['message']);
+ }
+ return $this->raiseError("Cannot package, errors in package");
+ }
+
+ foreach ($main->getValidationWarnings() as $warning) {
+ $this->log(1, 'Warning: ' . $warning['message']);
+ }
+
+ if ($pkg2) {
+ $other->setLogger($this);
+ $a = false;
+ if (!$other->validate(PEAR_VALIDATE_NORMAL) || $a = !$main->isEquivalent($other)) {
+ foreach ($other->getValidationWarnings() as $warning) {
+ $this->log(0, 'Error: ' . $warning['message']);
+ }
+
+ foreach ($main->getValidationWarnings() as $warning) {
+ $this->log(0, 'Error: ' . $warning['message']);
+ }
+
+ if ($a) {
+ return $this->raiseError('The two package.xml files are not equivalent!');
+ }
+
+ return $this->raiseError("Cannot package, errors in package");
+ }
+
+ foreach ($other->getValidationWarnings() as $warning) {
+ $this->log(1, 'Warning: ' . $warning['message']);
+ }
+
+ $gen = &$main->getDefaultGenerator();
+ $tgzfile = $gen->toTgz2($this, $other, $compress);
+ if (PEAR::isError($tgzfile)) {
+ return $tgzfile;
+ }
+
+ $dest_package = basename($tgzfile);
+ $pkgdir = dirname($pkgfile);
+
+ // TAR the Package -------------------------------------------
+ $this->log(1, "Package $dest_package done");
+ if (file_exists("$pkgdir/CVS/Root")) {
+ $cvsversion = preg_replace('/[^a-z0-9]/i', '_', $pf->getVersion());
+ $cvstag = "RELEASE_$cvsversion";
+ $this->log(1, 'Tag the released code with "pear cvstag ' .
+ $main->getPackageFile() . '"');
+ $this->log(1, "(or set the CVS tag $cvstag by hand)");
+ } elseif (file_exists("$pkgdir/.svn")) {
+ $svnversion = preg_replace('/[^a-z0-9]/i', '.', $pf->getVersion());
+ $svntag = $pf->getName() . "-$svnversion";
+ $this->log(1, 'Tag the released code with "pear svntag ' .
+ $main->getPackageFile() . '"');
+ $this->log(1, "(or set the SVN tag $svntag by hand)");
+ }
+ } else { // this branch is executed for single packagefile packaging
+ $gen = &$pf->getDefaultGenerator();
+ $tgzfile = $gen->toTgz($this, $compress);
+ if (PEAR::isError($tgzfile)) {
+ $this->log(0, $tgzfile->getMessage());
+ return $this->raiseError("Cannot package, errors in package");
+ }
+
+ $dest_package = basename($tgzfile);
+ $pkgdir = dirname($pkgfile);
+
+ // TAR the Package -------------------------------------------
+ $this->log(1, "Package $dest_package done");
+ if (file_exists("$pkgdir/CVS/Root")) {
+ $cvsversion = preg_replace('/[^a-z0-9]/i', '_', $pf->getVersion());
+ $cvstag = "RELEASE_$cvsversion";
+ $this->log(1, "Tag the released code with `pear cvstag $pkgfile'");
+ $this->log(1, "(or set the CVS tag $cvstag by hand)");
+ } elseif (file_exists("$pkgdir/.svn")) {
+ $svnversion = preg_replace('/[^a-z0-9]/i', '.', $pf->getVersion());
+ $svntag = $pf->getName() . "-$svnversion";
+ $this->log(1, "Tag the released code with `pear svntag $pkgfile'");
+ $this->log(1, "(or set the SVN tag $svntag by hand)");
+ }
+ }
+
+ return $dest_package;
+ }
+}<?php
+/**
* PEAR_Registry
*
* PHP versions 4 and 5
@@ -82800,7 +92050,7 @@ class PEAR_PackageFile_v2_Validator
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version CVS: $Id: Registry.php 287555 2009-08-21 21:27:27Z dufuz $
+ * @version CVS: $Id: Registry.php 313023 2011-07-06 19:17:11Z dufuz $
* @link http://pear.php.net/package/PEAR
* @since File available since Release 0.1
*/
@@ -82826,7 +92076,7 @@ define('PEAR_REGISTRY_ERROR_CHANNEL_FILE', -6);
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version Release: 1.10.0beta1
+ * @version Release: 1.9.4
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a1
*/
@@ -85192,7 +94442,7 @@ class PEAR_Registry extends PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version CVS: $Id: REST.php 309593 2011-03-23 12:34:39Z dufuz $
+ * @version CVS: $Id: REST.php 313023 2011-07-06 19:17:11Z dufuz $
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.4.0a1
*/
@@ -85211,7 +94461,7 @@ require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/XMLParser.php';
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version Release: 1.10.0beta1
+ * @version Release: 1.9.4
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a1
*/
@@ -85566,7 +94816,7 @@ class PEAR_REST
}
$request .= $ifmodifiedsince .
- "User-Agent: PEAR/1.10.0beta1/PHP/" . PHP_VERSION . "\r\n";
+ "User-Agent: PEAR/1.9.4/PHP/" . PHP_VERSION . "\r\n";
$username = $this->config->get('username', null, $channel);
$password = $this->config->get('password', null, $channel);
@@ -85663,8 +94913,7 @@ class PEAR_REST
return $data;
}
-}
-<?php
+}<?php
/**
* PEAR_REST_10
*
@@ -85675,7 +94924,7 @@ class PEAR_REST
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version CVS: $Id: 10.php 311690 2011-06-01 04:57:58Z dufuz $
+ * @version CVS: $Id: 10.php 313023 2011-07-06 19:17:11Z dufuz $
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.4.0a12
*/
@@ -85693,7 +94942,7 @@ require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/REST.php';
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version Release: 1.10.0beta1
+ * @version Release: 1.9.4
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a12
*/
@@ -86535,6 +95784,1612 @@ class PEAR_REST_10
}
}
}<?php
+/**
+ * PEAR_REST_11 - implement faster list-all/remote-list command
+ *
+ * PHP versions 4 and 5
+ *
+ * @category pear
+ * @package PEAR
+ * @author Greg Beaver <cellog@php.net>
+ * @copyright 1997-2009 The Authors
+ * @license http://opensource.org/licenses/bsd-license.php New BSD License
+ * @version CVS: $Id: 11.php 313023 2011-07-06 19:17:11Z dufuz $
+ * @link http://pear.php.net/package/PEAR
+ * @since File available since Release 1.4.3
+ */
+
+/**
+ * For downloading REST xml/txt files
+ */
+require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/REST.php';
+
+/**
+ * Implement REST 1.1
+ *
+ * @category pear
+ * @package PEAR
+ * @author Greg Beaver <cellog@php.net>
+ * @copyright 1997-2009 The Authors
+ * @license http://opensource.org/licenses/bsd-license.php New BSD License
+ * @version Release: 1.9.4
+ * @link http://pear.php.net/package/PEAR
+ * @since Class available since Release 1.4.3
+ */
+class PEAR_REST_11
+{
+ /**
+ * @var PEAR_REST
+ */
+ var $_rest;
+
+ function PEAR_REST_11($config, $options = array())
+ {
+ $this->_rest = &new PEAR_REST($config, $options);
+ }
+
+ function listAll($base, $dostable, $basic = true, $searchpackage = false, $searchsummary = false, $channel = false)
+ {
+ $categorylist = $this->_rest->retrieveData($base . 'c/categories.xml', false, false, $channel);
+ if (PEAR::isError($categorylist)) {
+ return $categorylist;
+ }
+
+ $ret = array();
+ if (!is_array($categorylist['c']) || !isset($categorylist['c'][0])) {
+ $categorylist['c'] = array($categorylist['c']);
+ }
+
+ PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
+
+ foreach ($categorylist['c'] as $progress => $category) {
+ $category = $category['_content'];
+ $packagesinfo = $this->_rest->retrieveData($base .
+ 'c/' . urlencode($category) . '/packagesinfo.xml', false, false, $channel);
+
+ if (PEAR::isError($packagesinfo)) {
+ continue;
+ }
+
+ if (!is_array($packagesinfo) || !isset($packagesinfo['pi'])) {
+ continue;
+ }
+
+ if (!is_array($packagesinfo['pi']) || !isset($packagesinfo['pi'][0])) {
+ $packagesinfo['pi'] = array($packagesinfo['pi']);
+ }
+
+ foreach ($packagesinfo['pi'] as $packageinfo) {
+ if (empty($packageinfo)) {
+ continue;
+ }
+
+ $info = $packageinfo['p'];
+ $package = $info['n'];
+ $releases = isset($packageinfo['a']) ? $packageinfo['a'] : false;
+ unset($latest);
+ unset($unstable);
+ unset($stable);
+ unset($state);
+
+ if ($releases) {
+ if (!isset($releases['r'][0])) {
+ $releases['r'] = array($releases['r']);
+ }
+
+ foreach ($releases['r'] as $release) {
+ if (!isset($latest)) {
+ if ($dostable && $release['s'] == 'stable') {
+ $latest = $release['v'];
+ $state = 'stable';
+ }
+ if (!$dostable) {
+ $latest = $release['v'];
+ $state = $release['s'];
+ }
+ }
+
+ if (!isset($stable) && $release['s'] == 'stable') {
+ $stable = $release['v'];
+ if (!isset($unstable)) {
+ $unstable = $stable;
+ }
+ }
+
+ if (!isset($unstable) && $release['s'] != 'stable') {
+ $unstable = $release['v'];
+ $state = $release['s'];
+ }
+
+ if (isset($latest) && !isset($state)) {
+ $state = $release['s'];
+ }
+
+ if (isset($latest) && isset($stable) && isset($unstable)) {
+ break;
+ }
+ }
+ }
+
+ if ($basic) { // remote-list command
+ if (!isset($latest)) {
+ $latest = false;
+ }
+
+ if ($dostable) {
+ // $state is not set if there are no releases
+ if (isset($state) && $state == 'stable') {
+ $ret[$package] = array('stable' => $latest);
+ } else {
+ $ret[$package] = array('stable' => '-n/a-');
+ }
+ } else {
+ $ret[$package] = array('stable' => $latest);
+ }
+
+ continue;
+ }
+
+ // list-all command
+ if (!isset($unstable)) {
+ $unstable = false;
+ $state = 'stable';
+ if (isset($stable)) {
+ $latest = $unstable = $stable;
+ }
+ } else {
+ $latest = $unstable;
+ }
+
+ if (!isset($latest)) {
+ $latest = false;
+ }
+
+ $deps = array();
+ if ($latest && isset($packageinfo['deps'])) {
+ if (!is_array($packageinfo['deps']) ||
+ !isset($packageinfo['deps'][0])
+ ) {
+ $packageinfo['deps'] = array($packageinfo['deps']);
+ }
+
+ $d = false;
+ foreach ($packageinfo['deps'] as $dep) {
+ if ($dep['v'] == $latest) {
+ $d = unserialize($dep['d']);
+ }
+ }
+
+ if ($d) {
+ if (isset($d['required'])) {
+ if (!class_exists('PEAR_PackageFile_v2')) {
+ require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/PackageFile/v2.php';
+ }
+
+ if (!isset($pf)) {
+ $pf = new PEAR_PackageFile_v2;
+ }
+
+ $pf->setDeps($d);
+ $tdeps = $pf->getDeps();
+ } else {
+ $tdeps = $d;
+ }
+
+ foreach ($tdeps as $dep) {
+ if ($dep['type'] !== 'pkg') {
+ continue;
+ }
+
+ $deps[] = $dep;
+ }
+ }
+ }
+
+ $info = array(
+ 'stable' => $latest,
+ 'summary' => $info['s'],
+ 'description' => $info['d'],
+ 'deps' => $deps,
+ 'category' => $info['ca']['_content'],
+ 'unstable' => $unstable,
+ 'state' => $state
+ );
+ $ret[$package] = $info;
+ }
+ }
+
+ PEAR::popErrorHandling();
+ return $ret;
+ }
+
+ /**
+ * List all categories of a REST server
+ *
+ * @param string $base base URL of the server
+ * @return array of categorynames
+ */
+ function listCategories($base, $channel = false)
+ {
+ $categorylist = $this->_rest->retrieveData($base . 'c/categories.xml', false, false, $channel);
+ if (PEAR::isError($categorylist)) {
+ return $categorylist;
+ }
+
+ if (!is_array($categorylist) || !isset($categorylist['c'])) {
+ return array();
+ }
+
+ if (isset($categorylist['c']['_content'])) {
+ // only 1 category
+ $categorylist['c'] = array($categorylist['c']);
+ }
+
+ return $categorylist['c'];
+ }
+
+ /**
+ * List packages in a category of a REST server
+ *
+ * @param string $base base URL of the server
+ * @param string $category name of the category
+ * @param boolean $info also download full package info
+ * @return array of packagenames
+ */
+ function listCategory($base, $category, $info = false, $channel = false)
+ {
+ if ($info == false) {
+ $url = '%s'.'c/%s/packages.xml';
+ } else {
+ $url = '%s'.'c/%s/packagesinfo.xml';
+ }
+ $url = sprintf($url,
+ $base,
+ urlencode($category));
+
+ // gives '404 Not Found' error when category doesn't exist
+ $packagelist = $this->_rest->retrieveData($url, false, false, $channel);
+ if (PEAR::isError($packagelist)) {
+ return $packagelist;
+ }
+ if (!is_array($packagelist)) {
+ return array();
+ }
+
+ if ($info == false) {
+ if (!isset($packagelist['p'])) {
+ return array();
+ }
+ if (!is_array($packagelist['p']) ||
+ !isset($packagelist['p'][0])) { // only 1 pkg
+ $packagelist = array($packagelist['p']);
+ } else {
+ $packagelist = $packagelist['p'];
+ }
+ return $packagelist;
+ }
+
+ // info == true
+ if (!isset($packagelist['pi'])) {
+ return array();
+ }
+
+ if (!is_array($packagelist['pi']) ||
+ !isset($packagelist['pi'][0])) { // only 1 pkg
+ $packagelist_pre = array($packagelist['pi']);
+ } else {
+ $packagelist_pre = $packagelist['pi'];
+ }
+
+ $packagelist = array();
+ foreach ($packagelist_pre as $i => $item) {
+ // compatibility with r/<latest.txt>.xml
+ if (isset($item['a']['r'][0])) {
+ // multiple releases
+ $item['p']['v'] = $item['a']['r'][0]['v'];
+ $item['p']['st'] = $item['a']['r'][0]['s'];
+ } elseif (isset($item['a'])) {
+ // first and only release
+ $item['p']['v'] = $item['a']['r']['v'];
+ $item['p']['st'] = $item['a']['r']['s'];
+ }
+
+ $packagelist[$i] = array('attribs' => $item['p']['r'],
+ '_content' => $item['p']['n'],
+ 'info' => $item['p']);
+ }
+
+ return $packagelist;
+ }
+
+ /**
+ * Return an array containing all of the states that are more stable than
+ * or equal to the passed in state
+ *
+ * @param string Release state
+ * @param boolean Determines whether to include $state in the list
+ * @return false|array False if $state is not a valid release state
+ */
+ function betterStates($state, $include = false)
+ {
+ static $states = array('snapshot', 'devel', 'alpha', 'beta', 'stable');
+ $i = array_search($state, $states);
+ if ($i === false) {
+ return false;
+ }
+ if ($include) {
+ $i--;
+ }
+ return array_slice($states, $i + 1);
+ }
+}
+?><?php
+/**
+ * PEAR_REST_13
+ *
+ * PHP versions 4 and 5
+ *
+ * @category pear
+ * @package PEAR
+ * @author Greg Beaver <cellog@php.net>
+ * @copyright 1997-2009 The Authors
+ * @license http://opensource.org/licenses/bsd-license.php New BSD License
+ * @version CVS: $Id: 13.php 313023 2011-07-06 19:17:11Z dufuz $
+ * @link http://pear.php.net/package/PEAR
+ * @since File available since Release 1.4.0a12
+ */
+
+/**
+ * For downloading REST xml/txt files
+ */
+require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/REST.php';
+require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/REST/10.php';
+
+/**
+ * Implement REST 1.3
+ *
+ * @category pear
+ * @package PEAR
+ * @author Greg Beaver <cellog@php.net>
+ * @copyright 1997-2009 The Authors
+ * @license http://opensource.org/licenses/bsd-license.php New BSD License
+ * @version Release: 1.9.4
+ * @link http://pear.php.net/package/PEAR
+ * @since Class available since Release 1.4.0a12
+ */
+class PEAR_REST_13 extends PEAR_REST_10
+{
+ /**
+ * Retrieve information about a remote package to be downloaded from a REST server
+ *
+ * This is smart enough to resolve the minimum PHP version dependency prior to download
+ * @param string $base The uri to prepend to all REST calls
+ * @param array $packageinfo an array of format:
+ * <pre>
+ * array(
+ * 'package' => 'packagename',
+ * 'channel' => 'channelname',
+ * ['state' => 'alpha' (or valid state),]
+ * -or-
+ * ['version' => '1.whatever']
+ * </pre>
+ * @param string $prefstate Current preferred_state config variable value
+ * @param bool $installed the installed version of this package to compare against
+ * @return array|false|PEAR_Error see {@link _returnDownloadURL()}
+ */
+ function getDownloadURL($base, $packageinfo, $prefstate, $installed, $channel = false)
+ {
+ $states = $this->betterStates($prefstate, true);
+ if (!$states) {
+ return PEAR::raiseError('"' . $prefstate . '" is not a valid state');
+ }
+
+ $channel = $packageinfo['channel'];
+ $package = $packageinfo['package'];
+ $state = isset($packageinfo['state']) ? $packageinfo['state'] : null;
+ $version = isset($packageinfo['version']) ? $packageinfo['version'] : null;
+ $restFile = $base . 'r/' . strtolower($package) . '/allreleases2.xml';
+
+ $info = $this->_rest->retrieveData($restFile, false, false, $channel);
+ if (PEAR::isError($info)) {
+ return PEAR::raiseError('No releases available for package "' .
+ $channel . '/' . $package . '"');
+ }
+
+ if (!isset($info['r'])) {
+ return false;
+ }
+
+ $release = $found = false;
+ if (!is_array($info['r']) || !isset($info['r'][0])) {
+ $info['r'] = array($info['r']);
+ }
+
+ $skippedphp = false;
+ foreach ($info['r'] as $release) {
+ if (!isset($this->_rest->_options['force']) && ($installed &&
+ version_compare($release['v'], $installed, '<'))) {
+ continue;
+ }
+
+ if (isset($state)) {
+ // try our preferred state first
+ if ($release['s'] == $state) {
+ if (!isset($version) && version_compare($release['m'], phpversion(), '>')) {
+ // skip releases that require a PHP version newer than our PHP version
+ $skippedphp = $release;
+ continue;
+ }
+ $found = true;
+ break;
+ }
+
+ // see if there is something newer and more stable
+ // bug #7221
+ if (in_array($release['s'], $this->betterStates($state), true)) {
+ if (!isset($version) && version_compare($release['m'], phpversion(), '>')) {
+ // skip releases that require a PHP version newer than our PHP version
+ $skippedphp = $release;
+ continue;
+ }
+ $found = true;
+ break;
+ }
+ } elseif (isset($version)) {
+ if ($release['v'] == $version) {
+ if (!isset($this->_rest->_options['force']) &&
+ !isset($version) &&
+ version_compare($release['m'], phpversion(), '>')) {
+ // skip releases that require a PHP version newer than our PHP version
+ $skippedphp = $release;
+ continue;
+ }
+ $found = true;
+ break;
+ }
+ } else {
+ if (in_array($release['s'], $states)) {
+ if (version_compare($release['m'], phpversion(), '>')) {
+ // skip releases that require a PHP version newer than our PHP version
+ $skippedphp = $release;
+ continue;
+ }
+ $found = true;
+ break;
+ }
+ }
+ }
+
+ if (!$found && $skippedphp) {
+ $found = null;
+ }
+
+ return $this->_returnDownloadURL($base, $package, $release, $info, $found, $skippedphp, $channel);
+ }
+
+ function getDepDownloadURL($base, $xsdversion, $dependency, $deppackage,
+ $prefstate = 'stable', $installed = false, $channel = false)
+ {
+ $states = $this->betterStates($prefstate, true);
+ if (!$states) {
+ return PEAR::raiseError('"' . $prefstate . '" is not a valid state');
+ }
+
+ $channel = $dependency['channel'];
+ $package = $dependency['name'];
+ $state = isset($dependency['state']) ? $dependency['state'] : null;
+ $version = isset($dependency['version']) ? $dependency['version'] : null;
+ $restFile = $base . 'r/' . strtolower($package) .'/allreleases2.xml';
+
+ $info = $this->_rest->retrieveData($restFile, false, false, $channel);
+ if (PEAR::isError($info)) {
+ return PEAR::raiseError('Package "' . $deppackage['channel'] . '/' . $deppackage['package']
+ . '" dependency "' . $channel . '/' . $package . '" has no releases');
+ }
+
+ if (!is_array($info) || !isset($info['r'])) {
+ return false;
+ }
+
+ $exclude = array();
+ $min = $max = $recommended = false;
+ if ($xsdversion == '1.0') {
+ $pinfo['package'] = $dependency['name'];
+ $pinfo['channel'] = 'pear.php.net'; // this is always true - don't change this
+ switch ($dependency['rel']) {
+ case 'ge' :
+ $min = $dependency['version'];
+ break;
+ case 'gt' :
+ $min = $dependency['version'];
+ $exclude = array($dependency['version']);
+ break;
+ case 'eq' :
+ $recommended = $dependency['version'];
+ break;
+ case 'lt' :
+ $max = $dependency['version'];
+ $exclude = array($dependency['version']);
+ break;
+ case 'le' :
+ $max = $dependency['version'];
+ break;
+ case 'ne' :
+ $exclude = array($dependency['version']);
+ break;
+ }
+ } else {
+ $pinfo['package'] = $dependency['name'];
+ $min = isset($dependency['min']) ? $dependency['min'] : false;
+ $max = isset($dependency['max']) ? $dependency['max'] : false;
+ $recommended = isset($dependency['recommended']) ?
+ $dependency['recommended'] : false;
+ if (isset($dependency['exclude'])) {
+ if (!isset($dependency['exclude'][0])) {
+ $exclude = array($dependency['exclude']);
+ }
+ }
+ }
+
+ $skippedphp = $found = $release = false;
+ if (!is_array($info['r']) || !isset($info['r'][0])) {
+ $info['r'] = array($info['r']);
+ }
+
+ foreach ($info['r'] as $release) {
+ if (!isset($this->_rest->_options['force']) && ($installed &&
+ version_compare($release['v'], $installed, '<'))) {
+ continue;
+ }
+
+ if (in_array($release['v'], $exclude)) { // skip excluded versions
+ continue;
+ }
+
+ // allow newer releases to say "I'm OK with the dependent package"
+ if ($xsdversion == '2.0' && isset($release['co'])) {
+ if (!is_array($release['co']) || !isset($release['co'][0])) {
+ $release['co'] = array($release['co']);
+ }
+
+ foreach ($release['co'] as $entry) {
+ if (isset($entry['x']) && !is_array($entry['x'])) {
+ $entry['x'] = array($entry['x']);
+ } elseif (!isset($entry['x'])) {
+ $entry['x'] = array();
+ }
+
+ if ($entry['c'] == $deppackage['channel'] &&
+ strtolower($entry['p']) == strtolower($deppackage['package']) &&
+ version_compare($deppackage['version'], $entry['min'], '>=') &&
+ version_compare($deppackage['version'], $entry['max'], '<=') &&
+ !in_array($release['v'], $entry['x'])) {
+ if (version_compare($release['m'], phpversion(), '>')) {
+ // skip dependency releases that require a PHP version
+ // newer than our PHP version
+ $skippedphp = $release;
+ continue;
+ }
+
+ $recommended = $release['v'];
+ break;
+ }
+ }
+ }
+
+ if ($recommended) {
+ if ($release['v'] != $recommended) { // if we want a specific
+ // version, then skip all others
+ continue;
+ }
+
+ if (!in_array($release['s'], $states)) {
+ // the stability is too low, but we must return the
+ // recommended version if possible
+ return $this->_returnDownloadURL($base, $package, $release, $info, true, false, $channel);
+ }
+ }
+
+ if ($min && version_compare($release['v'], $min, 'lt')) { // skip too old versions
+ continue;
+ }
+
+ if ($max && version_compare($release['v'], $max, 'gt')) { // skip too new versions
+ continue;
+ }
+
+ if ($installed && version_compare($release['v'], $installed, '<')) {
+ continue;
+ }
+
+ if (in_array($release['s'], $states)) { // if in the preferred state...
+ if (version_compare($release['m'], phpversion(), '>')) {
+ // skip dependency releases that require a PHP version
+ // newer than our PHP version
+ $skippedphp = $release;
+ continue;
+ }
+
+ $found = true; // ... then use it
+ break;
+ }
+ }
+
+ if (!$found && $skippedphp) {
+ $found = null;
+ }
+
+ return $this->_returnDownloadURL($base, $package, $release, $info, $found, $skippedphp, $channel);
+ }
+}<?php
+/**
+ * PEAR_RunTest
+ *
+ * PHP versions 4 and 5
+ *
+ * @category pear
+ * @package PEAR
+ * @author Tomas V.V.Cox <cox@idecnet.com>
+ * @author Greg Beaver <cellog@php.net>
+ * @copyright 1997-2009 The Authors
+ * @license http://opensource.org/licenses/bsd-license.php New BSD License
+ * @version CVS: $Id: RunTest.php 313024 2011-07-06 19:51:24Z dufuz $
+ * @link http://pear.php.net/package/PEAR
+ * @since File available since Release 1.3.3
+ */
+
+/**
+ * for error handling
+ */
+require_once 'phar://install-pear-nozlib.phar/' . 'PEAR.php';
+require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Config.php';
+
+define('DETAILED', 1);
+putenv("PHP_PEAR_RUNTESTS=1");
+
+/**
+ * Simplified version of PHP's test suite
+ *
+ * Try it with:
+ *
+ * $ php -r 'include "../PEAR/RunTest.php"; $t=new PEAR_RunTest; $o=$t->run("./pear_system.phpt");print_r($o);'
+ *
+ *
+ * @category pear
+ * @package PEAR
+ * @author Tomas V.V.Cox <cox@idecnet.com>
+ * @author Greg Beaver <cellog@php.net>
+ * @copyright 1997-2009 The Authors
+ * @license http://opensource.org/licenses/bsd-license.php New BSD License
+ * @version Release: 1.9.4
+ * @link http://pear.php.net/package/PEAR
+ * @since Class available since Release 1.3.3
+ */
+class PEAR_RunTest
+{
+ var $_headers = array();
+ var $_logger;
+ var $_options;
+ var $_php;
+ var $tests_count;
+ var $xdebug_loaded;
+ /**
+ * Saved value of php executable, used to reset $_php when we
+ * have a test that uses cgi
+ *
+ * @var unknown_type
+ */
+ var $_savephp;
+ var $ini_overwrites = array(
+ 'output_handler=',
+ 'open_basedir=',
+ 'safe_mode=0',
+ 'disable_functions=',
+ 'output_buffering=Off',
+ 'display_errors=1',
+ 'log_errors=0',
+ 'html_errors=0',
+ 'track_errors=1',
+ 'report_memleaks=0',
+ 'report_zend_debug=0',
+ 'docref_root=',
+ 'docref_ext=.html',
+ 'error_prepend_string=',
+ 'error_append_string=',
+ 'auto_prepend_file=',
+ 'auto_append_file=',
+ 'magic_quotes_runtime=0',
+ 'xdebug.default_enable=0',
+ 'allow_url_fopen=1',
+ );
+
+ /**
+ * An object that supports the PEAR_Common->log() signature, or null
+ * @param PEAR_Common|null
+ */
+ function PEAR_RunTest($logger = null, $options = array())
+ {
+ if (!defined('E_DEPRECATED')) {
+ define('E_DEPRECATED', 0);
+ }
+ if (!defined('E_STRICT')) {
+ define('E_STRICT', 0);
+ }
+ $this->ini_overwrites[] = 'error_reporting=' . (E_ALL & ~(E_DEPRECATED | E_STRICT));
+ if (is_null($logger)) {
+ require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Common.php';
+ $logger = new PEAR_Common;
+ }
+ $this->_logger = $logger;
+ $this->_options = $options;
+
+ $conf = &PEAR_Config::singleton();
+ $this->_php = $conf->get('php_bin');
+ }
+
+ /**
+ * Taken from php-src/run-tests.php
+ *
+ * @param string $commandline command name
+ * @param array $env
+ * @param string $stdin standard input to pass to the command
+ * @return unknown
+ */
+ function system_with_timeout($commandline, $env = null, $stdin = null)
+ {
+ $data = '';
+ if (version_compare(phpversion(), '5.0.0', '<')) {
+ $proc = proc_open($commandline, array(
+ 0 => array('pipe', 'r'),
+ 1 => array('pipe', 'w'),
+ 2 => array('pipe', 'w')
+ ), $pipes);
+ } else {
+ $proc = proc_open($commandline, array(
+ 0 => array('pipe', 'r'),
+ 1 => array('pipe', 'w'),
+ 2 => array('pipe', 'w')
+ ), $pipes, null, $env, array('suppress_errors' => true));
+ }
+
+ if (!$proc) {
+ return false;
+ }
+
+ if (is_string($stdin)) {
+ fwrite($pipes[0], $stdin);
+ }
+ fclose($pipes[0]);
+
+ while (true) {
+ /* hide errors from interrupted syscalls */
+ $r = $pipes;
+ $e = $w = null;
+ $n = @stream_select($r, $w, $e, 60);
+
+ if ($n === 0) {
+ /* timed out */
+ $data .= "\n ** ERROR: process timed out **\n";
+ proc_terminate($proc);
+ return array(1234567890, $data);
+ } else if ($n > 0) {
+ $line = fread($pipes[1], 8192);
+ if (strlen($line) == 0) {
+ /* EOF */
+ break;
+ }
+ $data .= $line;
+ }
+ }
+ if (function_exists('proc_get_status')) {
+ $stat = proc_get_status($proc);
+ if ($stat['signaled']) {
+ $data .= "\nTermsig=".$stat['stopsig'];
+ }
+ }
+ $code = proc_close($proc);
+ if (function_exists('proc_get_status')) {
+ $code = $stat['exitcode'];
+ }
+ return array($code, $data);
+ }
+
+ /**
+ * Turns a PHP INI string into an array
+ *
+ * Turns -d "include_path=/foo/bar" into this:
+ * array(
+ * 'include_path' => array(
+ * 'operator' => '-d',
+ * 'value' => '/foo/bar',
+ * )
+ * )
+ * Works both with quotes and without
+ *
+ * @param string an PHP INI string, -d "include_path=/foo/bar"
+ * @return array
+ */
+ function iniString2array($ini_string)
+ {
+ if (!$ini_string) {
+ return array();
+ }
+ $split = preg_split('/[\s]|=/', $ini_string, -1, PREG_SPLIT_NO_EMPTY);
+ $key = $split[1][0] == '"' ? substr($split[1], 1) : $split[1];
+ $value = $split[2][strlen($split[2]) - 1] == '"' ? substr($split[2], 0, -1) : $split[2];
+ // FIXME review if this is really the struct to go with
+ $array = array($key => array('operator' => $split[0], 'value' => $value));
+ return $array;
+ }
+
+ function settings2array($settings, $ini_settings)
+ {
+ foreach ($settings as $setting) {
+ if (strpos($setting, '=') !== false) {
+ $setting = explode('=', $setting, 2);
+ $name = trim(strtolower($setting[0]));
+ $value = trim($setting[1]);
+ $ini_settings[$name] = $value;
+ }
+ }
+ return $ini_settings;
+ }
+
+ function settings2params($ini_settings)
+ {
+ $settings = '';
+ foreach ($ini_settings as $name => $value) {
+ if (is_array($value)) {
+ $operator = $value['operator'];
+ $value = $value['value'];
+ } else {
+ $operator = '-d';
+ }
+ $value = addslashes($value);
+ $settings .= " $operator \"$name=$value\"";
+ }
+ return $settings;
+ }
+
+ function _preparePhpBin($php, $file, $ini_settings)
+ {
+ $file = escapeshellarg($file);
+ // This was fixed in php 5.3 and is not needed after that
+ if (OS_WINDOWS && version_compare(PHP_VERSION, '5.3', '<')) {
+ $cmd = '"'.escapeshellarg($php).' '.$ini_settings.' -f ' . $file .'"';
+ } else {
+ $cmd = $php . $ini_settings . ' -f ' . $file;
+ }
+
+ return $cmd;
+ }
+
+ function runPHPUnit($file, $ini_settings = '')
+ {
+ if (!file_exists($file) && file_exists(getcwd() . DIRECTORY_SEPARATOR . $file)) {
+ $file = realpath(getcwd() . DIRECTORY_SEPARATOR . $file);
+ } elseif (file_exists($file)) {
+ $file = realpath($file);
+ }
+
+ $cmd = $this->_preparePhpBin($this->_php, $file, $ini_settings);
+ if (isset($this->_logger)) {
+ $this->_logger->log(2, 'Running command "' . $cmd . '"');
+ }
+
+ $savedir = getcwd(); // in case the test moves us around
+ chdir(dirname($file));
+ echo `$cmd`;
+ chdir($savedir);
+ return 'PASSED'; // we have no way of knowing this information so assume passing
+ }
+
+ /**
+ * Runs an individual test case.
+ *
+ * @param string The filename of the test
+ * @param array|string INI settings to be applied to the test run
+ * @param integer Number what the current running test is of the
+ * whole test suite being runned.
+ *
+ * @return string|object Returns PASSED, WARNED, FAILED depending on how the
+ * test came out.
+ * PEAR Error when the tester it self fails
+ */
+ function run($file, $ini_settings = array(), $test_number = 1)
+ {
+ if (isset($this->_savephp)) {
+ $this->_php = $this->_savephp;
+ unset($this->_savephp);
+ }
+ if (empty($this->_options['cgi'])) {
+ // try to see if php-cgi is in the path
+ $res = $this->system_with_timeout('php-cgi -v');
+ if (false !== $res && !(is_array($res) && in_array($res[0], array(-1, 127)))) {
+ $this->_options['cgi'] = 'php-cgi';
+ }
+ }
+ if (1 < $len = strlen($this->tests_count)) {
+ $test_number = str_pad($test_number, $len, ' ', STR_PAD_LEFT);
+ $test_nr = "[$test_number/$this->tests_count] ";
+ } else {
+ $test_nr = '';
+ }
+
+ $file = realpath($file);
+ $section_text = $this->_readFile($file);
+ if (PEAR::isError($section_text)) {
+ return $section_text;
+ }
+
+ if (isset($section_text['POST_RAW']) && isset($section_text['UPLOAD'])) {
+ return PEAR::raiseError("Cannot contain both POST_RAW and UPLOAD in test file: $file");
+ }
+
+ $cwd = getcwd();
+
+ $pass_options = '';
+ if (!empty($this->_options['ini'])) {
+ $pass_options = $this->_options['ini'];
+ }
+
+ if (is_string($ini_settings)) {
+ $ini_settings = $this->iniString2array($ini_settings);
+ }
+
+ $ini_settings = $this->settings2array($this->ini_overwrites, $ini_settings);
+ if ($section_text['INI']) {
+ if (strpos($section_text['INI'], '{PWD}') !== false) {
+ $section_text['INI'] = str_replace('{PWD}', dirname($file), $section_text['INI']);
+ }
+ $ini = preg_split( "/[\n\r]+/", $section_text['INI']);
+ $ini_settings = $this->settings2array($ini, $ini_settings);
+ }
+ $ini_settings = $this->settings2params($ini_settings);
+ $shortname = str_replace($cwd . DIRECTORY_SEPARATOR, '', $file);
+
+ $tested = trim($section_text['TEST']);
+ $tested.= !isset($this->_options['simple']) ? "[$shortname]" : ' ';
+
+ if (!empty($section_text['POST']) || !empty($section_text['POST_RAW']) ||
+ !empty($section_text['UPLOAD']) || !empty($section_text['GET']) ||
+ !empty($section_text['COOKIE']) || !empty($section_text['EXPECTHEADERS'])) {
+ if (empty($this->_options['cgi'])) {
+ if (!isset($this->_options['quiet'])) {
+ $this->_logger->log(0, "SKIP $test_nr$tested (reason: --cgi option needed for this test, type 'pear help run-tests')");
+ }
+ if (isset($this->_options['tapoutput'])) {
+ return array('ok', ' # skip --cgi option needed for this test, "pear help run-tests" for info');
+ }
+ return 'SKIPPED';
+ }
+ $this->_savephp = $this->_php;
+ $this->_php = $this->_options['cgi'];
+ }
+
+ $temp_dir = realpath(dirname($file));
+ $main_file_name = basename($file, 'phpt');
+ $diff_filename = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'diff';
+ $log_filename = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'log';
+ $exp_filename = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'exp';
+ $output_filename = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'out';
+ $memcheck_filename = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'mem';
+ $temp_file = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'php';
+ $temp_skipif = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'skip.php';
+ $temp_clean = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'clean.php';
+ $tmp_post = $temp_dir . DIRECTORY_SEPARATOR . uniqid('phpt.');
+
+ // unlink old test results
+ $this->_cleanupOldFiles($file);
+
+ // Check if test should be skipped.
+ $res = $this->_runSkipIf($section_text, $temp_skipif, $tested, $ini_settings);
+ if (count($res) != 2) {
+ return $res;
+ }
+ $info = $res['info'];
+ $warn = $res['warn'];
+
+ // We've satisfied the preconditions - run the test!
+ if (isset($this->_options['coverage']) && $this->xdebug_loaded) {
+ $xdebug_file = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name . 'xdebug';
+ $text = "\n" . 'function coverage_shutdown() {' .
+ "\n" . ' $xdebug = var_export(xdebug_get_code_coverage(), true);';
+ if (!function_exists('file_put_contents')) {
+ $text .= "\n" . ' $fh = fopen(\'' . $xdebug_file . '\', "wb");' .
+ "\n" . ' if ($fh !== false) {' .
+ "\n" . ' fwrite($fh, $xdebug);' .
+ "\n" . ' fclose($fh);' .
+ "\n" . ' }';
+ } else {
+ $text .= "\n" . ' file_put_contents(\'' . $xdebug_file . '\', $xdebug);';
+ }
+
+ // Workaround for http://pear.php.net/bugs/bug.php?id=17292
+ $lines = explode("\n", $section_text['FILE']);
+ $numLines = count($lines);
+ $namespace = '';
+ $coverage_shutdown = 'coverage_shutdown';
+
+ if (
+ substr($lines[0], 0, 2) == '<?' ||
+ substr($lines[0], 0, 5) == '<?php'
+ ) {
+ unset($lines[0]);
+ }
+
+
+ for ($i = 0; $i < $numLines; $i++) {
+ if (isset($lines[$i]) && substr($lines[$i], 0, 9) == 'namespace') {
+ $namespace = substr($lines[$i], 10, -1);
+ $coverage_shutdown = $namespace . '\\coverage_shutdown';
+ $namespace = "namespace " . $namespace . ";\n";
+
+ unset($lines[$i]);
+ break;
+ }
+ }
+
+ $text .= "\n xdebug_stop_code_coverage();" .
+ "\n" . '} // end coverage_shutdown()' .
+ "\n\n" . 'register_shutdown_function("' . $coverage_shutdown . '");';
+ $text .= "\n" . 'xdebug_start_code_coverage(XDEBUG_CC_UNUSED | XDEBUG_CC_DEAD_CODE);' . "\n";
+
+ $this->save_text($temp_file, "<?php\n" . $namespace . $text . "\n" . implode("\n", $lines));
+ } else {
+ $this->save_text($temp_file, $section_text['FILE']);
+ }
+
+ $args = $section_text['ARGS'] ? ' -- '.$section_text['ARGS'] : '';
+ $cmd = $this->_preparePhpBin($this->_php, $temp_file, $ini_settings);
+ $cmd.= "$args 2>&1";
+ if (isset($this->_logger)) {
+ $this->_logger->log(2, 'Running command "' . $cmd . '"');
+ }
+
+ // Reset environment from any previous test.
+ $env = $this->_resetEnv($section_text, $temp_file);
+
+ $section_text = $this->_processUpload($section_text, $file);
+ if (PEAR::isError($section_text)) {
+ return $section_text;
+ }
+
+ if (array_key_exists('POST_RAW', $section_text) && !empty($section_text['POST_RAW'])) {
+ $post = trim($section_text['POST_RAW']);
+ $raw_lines = explode("\n", $post);
+
+ $request = '';
+ $started = false;
+ foreach ($raw_lines as $i => $line) {
+ if (empty($env['CONTENT_TYPE']) &&
+ preg_match('/^Content-Type:(.*)/i', $line, $res)) {
+ $env['CONTENT_TYPE'] = trim(str_replace("\r", '', $res[1]));
+ continue;
+ }
+ if ($started) {
+ $request .= "\n";
+ }
+ $started = true;
+ $request .= $line;
+ }
+
+ $env['CONTENT_LENGTH'] = strlen($request);
+ $env['REQUEST_METHOD'] = 'POST';
+
+ $this->save_text($tmp_post, $request);
+ $cmd = "$this->_php$pass_options$ini_settings \"$temp_file\" 2>&1 < $tmp_post";
+ } elseif (array_key_exists('POST', $section_text) && !empty($section_text['POST'])) {
+ $post = trim($section_text['POST']);
+ $this->save_text($tmp_post, $post);
+ $content_length = strlen($post);
+
+ $env['REQUEST_METHOD'] = 'POST';
+ $env['CONTENT_TYPE'] = 'application/x-www-form-urlencoded';
+ $env['CONTENT_LENGTH'] = $content_length;
+
+ $cmd = "$this->_php$pass_options$ini_settings \"$temp_file\" 2>&1 < $tmp_post";
+ } else {
+ $env['REQUEST_METHOD'] = 'GET';
+ $env['CONTENT_TYPE'] = '';
+ $env['CONTENT_LENGTH'] = '';
+ }
+
+ if (OS_WINDOWS && isset($section_text['RETURNS'])) {
+ ob_start();
+ system($cmd, $return_value);
+ $out = ob_get_contents();
+ ob_end_clean();
+ $section_text['RETURNS'] = (int) trim($section_text['RETURNS']);
+ $returnfail = ($return_value != $section_text['RETURNS']);
+ } else {
+ $returnfail = false;
+ $stdin = isset($section_text['STDIN']) ? $section_text['STDIN'] : null;
+ $out = $this->system_with_timeout($cmd, $env, $stdin);
+ $return_value = $out[0];
+ $out = $out[1];
+ }
+
+ $output = preg_replace('/\r\n/', "\n", trim($out));
+
+ if (isset($tmp_post) && realpath($tmp_post) && file_exists($tmp_post)) {
+ @unlink(realpath($tmp_post));
+ }
+ chdir($cwd); // in case the test moves us around
+
+ $this->_testCleanup($section_text, $temp_clean);
+
+ /* when using CGI, strip the headers from the output */
+ $output = $this->_stripHeadersCGI($output);
+
+ if (isset($section_text['EXPECTHEADERS'])) {
+ $testheaders = $this->_processHeaders($section_text['EXPECTHEADERS']);
+ $missing = array_diff_assoc($testheaders, $this->_headers);
+ $changed = '';
+ foreach ($missing as $header => $value) {
+ if (isset($this->_headers[$header])) {
+ $changed .= "-$header: $value\n+$header: ";
+ $changed .= $this->_headers[$header];
+ } else {
+ $changed .= "-$header: $value\n";
+ }
+ }
+ if ($missing) {
+ // tack on failed headers to output:
+ $output .= "\n====EXPECTHEADERS FAILURE====:\n$changed";
+ }
+ }
+ // Does the output match what is expected?
+ do {
+ if (isset($section_text['EXPECTF']) || isset($section_text['EXPECTREGEX'])) {
+ if (isset($section_text['EXPECTF'])) {
+ $wanted = trim($section_text['EXPECTF']);
+ } else {
+ $wanted = trim($section_text['EXPECTREGEX']);
+ }
+ $wanted_re = preg_replace('/\r\n/', "\n", $wanted);
+ if (isset($section_text['EXPECTF'])) {
+ $wanted_re = preg_quote($wanted_re, '/');
+ // Stick to basics
+ $wanted_re = str_replace("%s", ".+?", $wanted_re); //not greedy
+ $wanted_re = str_replace("%i", "[+\-]?[0-9]+", $wanted_re);
+ $wanted_re = str_replace("%d", "[0-9]+", $wanted_re);
+ $wanted_re = str_replace("%x", "[0-9a-fA-F]+", $wanted_re);
+ $wanted_re = str_replace("%f", "[+\-]?\.?[0-9]+\.?[0-9]*(E-?[0-9]+)?", $wanted_re);
+ $wanted_re = str_replace("%c", ".", $wanted_re);
+ // %f allows two points "-.0.0" but that is the best *simple* expression
+ }
+
+ /* DEBUG YOUR REGEX HERE
+ var_dump($wanted_re);
+ print(str_repeat('=', 80) . "\n");
+ var_dump($output);
+ */
+ if (!$returnfail && preg_match("/^$wanted_re\$/s", $output)) {
+ if (file_exists($temp_file)) {
+ unlink($temp_file);
+ }
+ if (array_key_exists('FAIL', $section_text)) {
+ break;
+ }
+ if (!isset($this->_options['quiet'])) {
+ $this->_logger->log(0, "PASS $test_nr$tested$info");
+ }
+ if (isset($this->_options['tapoutput'])) {
+ return array('ok', ' - ' . $tested);
+ }
+ return 'PASSED';
+ }
+ } else {
+ if (isset($section_text['EXPECTFILE'])) {
+ $f = $temp_dir . '/' . trim($section_text['EXPECTFILE']);
+ if (!($fp = @fopen($f, 'rb'))) {
+ return PEAR::raiseError('--EXPECTFILE-- section file ' .
+ $f . ' not found');
+ }
+ fclose($fp);
+ $section_text['EXPECT'] = file_get_contents($f);
+ }
+
+ if (isset($section_text['EXPECT'])) {
+ $wanted = preg_replace('/\r\n/', "\n", trim($section_text['EXPECT']));
+ } else {
+ $wanted = '';
+ }
+
+ // compare and leave on success
+ if (!$returnfail && 0 == strcmp($output, $wanted)) {
+ if (file_exists($temp_file)) {
+ unlink($temp_file);
+ }
+ if (array_key_exists('FAIL', $section_text)) {
+ break;
+ }
+ if (!isset($this->_options['quiet'])) {
+ $this->_logger->log(0, "PASS $test_nr$tested$info");
+ }
+ if (isset($this->_options['tapoutput'])) {
+ return array('ok', ' - ' . $tested);
+ }
+ return 'PASSED';
+ }
+ }
+ } while (false);
+
+ if (array_key_exists('FAIL', $section_text)) {
+ // we expect a particular failure
+ // this is only used for testing PEAR_RunTest
+ $expectf = isset($section_text['EXPECTF']) ? $wanted_re : null;
+ $faildiff = $this->generate_diff($wanted, $output, null, $expectf);
+ $faildiff = preg_replace('/\r/', '', $faildiff);
+ $wanted = preg_replace('/\r/', '', trim($section_text['FAIL']));
+ if ($faildiff == $wanted) {
+ if (!isset($this->_options['quiet'])) {
+ $this->_logger->log(0, "PASS $test_nr$tested$info");
+ }
+ if (isset($this->_options['tapoutput'])) {
+ return array('ok', ' - ' . $tested);
+ }
+ return 'PASSED';
+ }
+ unset($section_text['EXPECTF']);
+ $output = $faildiff;
+ if (isset($section_text['RETURNS'])) {
+ return PEAR::raiseError('Cannot have both RETURNS and FAIL in the same test: ' .
+ $file);
+ }
+ }
+
+ // Test failed so we need to report details.
+ $txt = $warn ? 'WARN ' : 'FAIL ';
+ $this->_logger->log(0, $txt . $test_nr . $tested . $info);
+
+ // write .exp
+ $res = $this->_writeLog($exp_filename, $wanted);
+ if (PEAR::isError($res)) {
+ return $res;
+ }
+
+ // write .out
+ $res = $this->_writeLog($output_filename, $output);
+ if (PEAR::isError($res)) {
+ return $res;
+ }
+
+ // write .diff
+ $returns = isset($section_text['RETURNS']) ?
+ array(trim($section_text['RETURNS']), $return_value) : null;
+ $expectf = isset($section_text['EXPECTF']) ? $wanted_re : null;
+ $data = $this->generate_diff($wanted, $output, $returns, $expectf);
+ $res = $this->_writeLog($diff_filename, $data);
+ if (PEAR::isError($res)) {
+ return $res;
+ }
+
+ // write .log
+ $data = "
+---- EXPECTED OUTPUT
+$wanted
+---- ACTUAL OUTPUT
+$output
+---- FAILED
+";
+
+ if ($returnfail) {
+ $data .= "
+---- EXPECTED RETURN
+$section_text[RETURNS]
+---- ACTUAL RETURN
+$return_value
+";
+ }
+
+ $res = $this->_writeLog($log_filename, $data);
+ if (PEAR::isError($res)) {
+ return $res;
+ }
+
+ if (isset($this->_options['tapoutput'])) {
+ $wanted = explode("\n", $wanted);
+ $wanted = "# Expected output:\n#\n#" . implode("\n#", $wanted);
+ $output = explode("\n", $output);
+ $output = "#\n#\n# Actual output:\n#\n#" . implode("\n#", $output);
+ return array($wanted . $output . 'not ok', ' - ' . $tested);
+ }
+ return $warn ? 'WARNED' : 'FAILED';
+ }
+
+ function generate_diff($wanted, $output, $rvalue, $wanted_re)
+ {
+ $w = explode("\n", $wanted);
+ $o = explode("\n", $output);
+ $wr = explode("\n", $wanted_re);
+ $w1 = array_diff_assoc($w, $o);
+ $o1 = array_diff_assoc($o, $w);
+ $o2 = $w2 = array();
+ foreach ($w1 as $idx => $val) {
+ if (!$wanted_re || !isset($wr[$idx]) || !isset($o1[$idx]) ||
+ !preg_match('/^' . $wr[$idx] . '\\z/', $o1[$idx])) {
+ $w2[sprintf("%03d<", $idx)] = sprintf("%03d- ", $idx + 1) . $val;
+ }
+ }
+ foreach ($o1 as $idx => $val) {
+ if (!$wanted_re || !isset($wr[$idx]) ||
+ !preg_match('/^' . $wr[$idx] . '\\z/', $val)) {
+ $o2[sprintf("%03d>", $idx)] = sprintf("%03d+ ", $idx + 1) . $val;
+ }
+ }
+ $diff = array_merge($w2, $o2);
+ ksort($diff);
+ $extra = $rvalue ? "##EXPECTED: $rvalue[0]\r\n##RETURNED: $rvalue[1]" : '';
+ return implode("\r\n", $diff) . $extra;
+ }
+
+ // Write the given text to a temporary file, and return the filename.
+ function save_text($filename, $text)
+ {
+ if (!$fp = fopen($filename, 'w')) {
+ return PEAR::raiseError("Cannot open file '" . $filename . "' (save_text)");
+ }
+ fwrite($fp, $text);
+ fclose($fp);
+ if (1 < DETAILED) echo "
+FILE $filename {{{
+$text
+}}}
+";
+ }
+
+ function _cleanupOldFiles($file)
+ {
+ $temp_dir = realpath(dirname($file));
+ $mainFileName = basename($file, 'phpt');
+ $diff_filename = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'diff';
+ $log_filename = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'log';
+ $exp_filename = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'exp';
+ $output_filename = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'out';
+ $memcheck_filename = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'mem';
+ $temp_file = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'php';
+ $temp_skipif = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'skip.php';
+ $temp_clean = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'clean.php';
+ $tmp_post = $temp_dir . DIRECTORY_SEPARATOR . uniqid('phpt.');
+
+ // unlink old test results
+ @unlink($diff_filename);
+ @unlink($log_filename);
+ @unlink($exp_filename);
+ @unlink($output_filename);
+ @unlink($memcheck_filename);
+ @unlink($temp_file);
+ @unlink($temp_skipif);
+ @unlink($tmp_post);
+ @unlink($temp_clean);
+ }
+
+ function _runSkipIf($section_text, $temp_skipif, $tested, $ini_settings)
+ {
+ $info = '';
+ $warn = false;
+ if (array_key_exists('SKIPIF', $section_text) && trim($section_text['SKIPIF'])) {
+ $this->save_text($temp_skipif, $section_text['SKIPIF']);
+ $output = $this->system_with_timeout("$this->_php$ini_settings -f \"$temp_skipif\"");
+ $output = $output[1];
+ $loutput = ltrim($output);
+ unlink($temp_skipif);
+ if (!strncasecmp('skip', $loutput, 4)) {
+ $skipreason = "SKIP $tested";
+ if (preg_match('/^\s*skip\s*(.+)\s*/i', $output, $m)) {
+ $skipreason .= '(reason: ' . $m[1] . ')';
+ }
+ if (!isset($this->_options['quiet'])) {
+ $this->_logger->log(0, $skipreason);
+ }
+ if (isset($this->_options['tapoutput'])) {
+ return array('ok', ' # skip ' . $reason);
+ }
+ return 'SKIPPED';
+ }
+
+ if (!strncasecmp('info', $loutput, 4)
+ && preg_match('/^\s*info\s*(.+)\s*/i', $output, $m)) {
+ $info = " (info: $m[1])";
+ }
+
+ if (!strncasecmp('warn', $loutput, 4)
+ && preg_match('/^\s*warn\s*(.+)\s*/i', $output, $m)) {
+ $warn = true; /* only if there is a reason */
+ $info = " (warn: $m[1])";
+ }
+ }
+
+ return array('warn' => $warn, 'info' => $info);
+ }
+
+ function _stripHeadersCGI($output)
+ {
+ $this->headers = array();
+ if (!empty($this->_options['cgi']) &&
+ $this->_php == $this->_options['cgi'] &&
+ preg_match("/^(.*?)(?:\n\n(.*)|\\z)/s", $output, $match)) {
+ $output = isset($match[2]) ? trim($match[2]) : '';
+ $this->_headers = $this->_processHeaders($match[1]);
+ }
+
+ return $output;
+ }
+
+ /**
+ * Return an array that can be used with array_diff() to compare headers
+ *
+ * @param string $text
+ */
+ function _processHeaders($text)
+ {
+ $headers = array();
+ $rh = preg_split("/[\n\r]+/", $text);
+ foreach ($rh as $line) {
+ if (strpos($line, ':')!== false) {
+ $line = explode(':', $line, 2);
+ $headers[trim($line[0])] = trim($line[1]);
+ }
+ }
+ return $headers;
+ }
+
+ function _readFile($file)
+ {
+ // Load the sections of the test file.
+ $section_text = array(
+ 'TEST' => '(unnamed test)',
+ 'SKIPIF' => '',
+ 'GET' => '',
+ 'COOKIE' => '',
+ 'POST' => '',
+ 'ARGS' => '',
+ 'INI' => '',
+ 'CLEAN' => '',
+ );
+
+ if (!is_file($file) || !$fp = fopen($file, "r")) {
+ return PEAR::raiseError("Cannot open test file: $file");
+ }
+
+ $section = '';
+ while (!feof($fp)) {
+ $line = fgets($fp);
+
+ // Match the beginning of a section.
+ if (preg_match('/^--([_A-Z]+)--/', $line, $r)) {
+ $section = $r[1];
+ $section_text[$section] = '';
+ continue;
+ } elseif (empty($section)) {
+ fclose($fp);
+ return PEAR::raiseError("Invalid sections formats in test file: $file");
+ }
+
+ // Add to the section text.
+ $section_text[$section] .= $line;
+ }
+ fclose($fp);
+
+ return $section_text;
+ }
+
+ function _writeLog($logname, $data)
+ {
+ if (!$log = fopen($logname, 'w')) {
+ return PEAR::raiseError("Cannot create test log - $logname");
+ }
+ fwrite($log, $data);
+ fclose($log);
+ }
+
+ function _resetEnv($section_text, $temp_file)
+ {
+ $env = $_ENV;
+ $env['REDIRECT_STATUS'] = '';
+ $env['QUERY_STRING'] = '';
+ $env['PATH_TRANSLATED'] = '';
+ $env['SCRIPT_FILENAME'] = '';
+ $env['REQUEST_METHOD'] = '';
+ $env['CONTENT_TYPE'] = '';
+ $env['CONTENT_LENGTH'] = '';
+ if (!empty($section_text['ENV'])) {
+ if (strpos($section_text['ENV'], '{PWD}') !== false) {
+ $section_text['ENV'] = str_replace('{PWD}', dirname($temp_file), $section_text['ENV']);
+ }
+ foreach (explode("\n", trim($section_text['ENV'])) as $e) {
+ $e = explode('=', trim($e), 2);
+ if (!empty($e[0]) && isset($e[1])) {
+ $env[$e[0]] = $e[1];
+ }
+ }
+ }
+ if (array_key_exists('GET', $section_text)) {
+ $env['QUERY_STRING'] = trim($section_text['GET']);
+ } else {
+ $env['QUERY_STRING'] = '';
+ }
+ if (array_key_exists('COOKIE', $section_text)) {
+ $env['HTTP_COOKIE'] = trim($section_text['COOKIE']);
+ } else {
+ $env['HTTP_COOKIE'] = '';
+ }
+ $env['REDIRECT_STATUS'] = '1';
+ $env['PATH_TRANSLATED'] = $temp_file;
+ $env['SCRIPT_FILENAME'] = $temp_file;
+
+ return $env;
+ }
+
+ function _processUpload($section_text, $file)
+ {
+ if (array_key_exists('UPLOAD', $section_text) && !empty($section_text['UPLOAD'])) {
+ $upload_files = trim($section_text['UPLOAD']);
+ $upload_files = explode("\n", $upload_files);
+
+ $request = "Content-Type: multipart/form-data; boundary=---------------------------20896060251896012921717172737\n" .
+ "-----------------------------20896060251896012921717172737\n";
+ foreach ($upload_files as $fileinfo) {
+ $fileinfo = explode('=', $fileinfo);
+ if (count($fileinfo) != 2) {
+ return PEAR::raiseError("Invalid UPLOAD section in test file: $file");
+ }
+ if (!realpath(dirname($file) . '/' . $fileinfo[1])) {
+ return PEAR::raiseError("File for upload does not exist: $fileinfo[1] " .
+ "in test file: $file");
+ }
+ $file_contents = file_get_contents(dirname($file) . '/' . $fileinfo[1]);
+ $fileinfo[1] = basename($fileinfo[1]);
+ $request .= "Content-Disposition: form-data; name=\"$fileinfo[0]\"; filename=\"$fileinfo[1]\"\n";
+ $request .= "Content-Type: text/plain\n\n";
+ $request .= $file_contents . "\n" .
+ "-----------------------------20896060251896012921717172737\n";
+ }
+
+ if (array_key_exists('POST', $section_text) && !empty($section_text['POST'])) {
+ // encode POST raw
+ $post = trim($section_text['POST']);
+ $post = explode('&', $post);
+ foreach ($post as $i => $post_info) {
+ $post_info = explode('=', $post_info);
+ if (count($post_info) != 2) {
+ return PEAR::raiseError("Invalid POST data in test file: $file");
+ }
+ $post_info[0] = rawurldecode($post_info[0]);
+ $post_info[1] = rawurldecode($post_info[1]);
+ $post[$i] = $post_info;
+ }
+ foreach ($post as $post_info) {
+ $request .= "Content-Disposition: form-data; name=\"$post_info[0]\"\n\n";
+ $request .= $post_info[1] . "\n" .
+ "-----------------------------20896060251896012921717172737\n";
+ }
+ unset($section_text['POST']);
+ }
+ $section_text['POST_RAW'] = $request;
+ }
+
+ return $section_text;
+ }
+
+ function _testCleanup($section_text, $temp_clean)
+ {
+ if ($section_text['CLEAN']) {
+ // perform test cleanup
+ $this->save_text($temp_clean, $section_text['CLEAN']);
+ $output = $this->system_with_timeout("$this->_php $temp_clean 2>&1");
+ if (strlen($output[1])) {
+ echo "BORKED --CLEAN-- section! output:\n", $output[1];
+ }
+ if (file_exists($temp_clean)) {
+ unlink($temp_clean);
+ }
+ }
+ }
+}
+<?php
require_once 'phar://install-pear-nozlib.phar/' . 'PEAR.php';
require_once 'phar://install-pear-nozlib.phar/' . 'System.php';
require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Config.php';
@@ -87229,7 +98084,7 @@ End If
*/
if ($this->php_bin == '') {
print "
-We did not find any php.exe, please select the php.exe folder (CLI is
+We do not find any php.exe, please select the php.exe folder (CLI is
recommended, usually in c:\php\cli\php.exe)
";
$this->validPHPBin = false;
@@ -87587,7 +98442,7 @@ Double-click this file to add it to the current user registry.
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version CVS: $Id: Common.php 276394 2009-02-25 00:15:49Z dufuz $
+ * @version CVS: $Id: Common.php 313023 2011-07-06 19:17:11Z dufuz $
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.4.0a1
*/
@@ -87625,7 +98480,7 @@ define('PEAR_TASK_PACKAGEANDINSTALL', 3);
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version Release: 1.10.0beta1
+ * @version Release: 1.9.4
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a1
* @abstract
@@ -87788,7 +98643,7 @@ class PEAR_Task_Common
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version CVS: $Id: Postinstallscript.php 276385 2009-02-24 23:46:03Z dufuz $
+ * @version CVS: $Id: Postinstallscript.php 313023 2011-07-06 19:17:11Z dufuz $
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.4.0a1
*/
@@ -87806,7 +98661,7 @@ require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Task/Common.php';
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version Release: 1.10.0beta1
+ * @version Release: 1.9.4
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a1
*/
@@ -88110,7 +98965,7 @@ class PEAR_Task_Postinstallscript extends PEAR_Task_Common
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version CVS: $Id: rw.php 276385 2009-02-24 23:46:03Z dufuz $
+ * @version CVS: $Id: rw.php 313023 2011-07-06 19:17:11Z dufuz $
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.4.0a10
*/
@@ -88125,7 +98980,7 @@ require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Task/Postinstallscript.p
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version Release: 1.10.0beta1
+ * @version Release: 1.9.4
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a10
*/
@@ -88278,7 +99133,7 @@ class PEAR_Task_Postinstallscript_rw extends PEAR_Task_Postinstallscript
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version CVS: $Id: Replace.php 276394 2009-02-25 00:15:49Z dufuz $
+ * @version CVS: $Id: Replace.php 313023 2011-07-06 19:17:11Z dufuz $
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.4.0a1
*/
@@ -88293,7 +99148,7 @@ require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Task/Common.php';
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version Release: 1.10.0beta1
+ * @version Release: 1.9.4
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a1
*/
@@ -88453,7 +99308,7 @@ class PEAR_Task_Replace extends PEAR_Task_Common
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version CVS: $Id: rw.php 276385 2009-02-24 23:46:03Z dufuz $
+ * @version CVS: $Id: rw.php 313023 2011-07-06 19:17:11Z dufuz $
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.4.0a10
*/
@@ -88468,7 +99323,7 @@ require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Task/Replace.php';
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version Release: 1.10.0beta1
+ * @version Release: 1.9.4
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a10
*/
@@ -88513,7 +99368,7 @@ class PEAR_Task_Replace_rw extends PEAR_Task_Replace
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version CVS: $Id: Unixeol.php 276394 2009-02-25 00:15:49Z dufuz $
+ * @version CVS: $Id: Unixeol.php 313023 2011-07-06 19:17:11Z dufuz $
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.4.0a1
*/
@@ -88528,7 +99383,7 @@ require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Task/Common.php';
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version Release: 1.10.0beta1
+ * @version Release: 1.9.4
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a1
*/
@@ -88589,7 +99444,7 @@ class PEAR_Task_Unixeol extends PEAR_Task_Common
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version CVS: $Id: rw.php 276385 2009-02-24 23:46:03Z dufuz $
+ * @version CVS: $Id: rw.php 313023 2011-07-06 19:17:11Z dufuz $
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.4.0a10
*/
@@ -88604,7 +99459,7 @@ require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Task/Unixeol.php';
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version Release: 1.10.0beta1
+ * @version Release: 1.9.4
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a10
*/
@@ -88644,7 +99499,7 @@ class PEAR_Task_Unixeol_rw extends PEAR_Task_Unixeol
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version CVS: $Id: Windowseol.php 276394 2009-02-25 00:15:49Z dufuz $
+ * @version CVS: $Id: Windowseol.php 313023 2011-07-06 19:17:11Z dufuz $
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.4.0a1
*/
@@ -88659,7 +99514,7 @@ require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Task/Common.php';
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version Release: 1.10.0beta1
+ * @version Release: 1.9.4
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a1
*/
@@ -88720,7 +99575,7 @@ class PEAR_Task_Windowseol extends PEAR_Task_Common
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version CVS: $Id: rw.php 276385 2009-02-24 23:46:03Z dufuz $
+ * @version CVS: $Id: rw.php 313023 2011-07-06 19:17:11Z dufuz $
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.4.0a10
*/
@@ -88735,7 +99590,7 @@ require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Task/Windowseol.php';
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version Release: 1.10.0beta1
+ * @version Release: 1.9.4
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a10
*/
@@ -88775,7 +99630,7 @@ class PEAR_Task_Windowseol_rw extends PEAR_Task_Windowseol
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version CVS: $Id: Validate.php 276383 2009-02-24 23:39:37Z dufuz $
+ * @version CVS: $Id: Validate.php 313023 2011-07-06 19:17:11Z dufuz $
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.4.0a1
*/
@@ -88798,7 +99653,7 @@ require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Validator/PECL.php';
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version Release: 1.10.0beta1
+ * @version Release: 1.9.4
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a1
*/
@@ -89403,7 +100258,7 @@ class PEAR_Validate
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2006 The PHP Group
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version CVS: $Id: PECL.php 276383 2009-02-24 23:39:37Z dufuz $
+ * @version CVS: $Id: PECL.php 313023 2011-07-06 19:17:11Z dufuz $
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.4.0a5
*/
@@ -89418,7 +100273,7 @@ require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Validate.php';
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version Release: 1.10.0beta1
+ * @version Release: 1.9.4
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a5
*/
@@ -89466,7 +100321,7 @@ class PEAR_Validator_PECL extends PEAR_Validate
* @author Stephan Schmidt (original XML_Unserializer code)
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license New BSD License
- * @version CVS: $Id: XMLParser.php 282970 2009-06-28 23:10:07Z dufuz $
+ * @version CVS: $Id: XMLParser.php 313023 2011-07-06 19:17:11Z dufuz $
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.4.0a1
*/
@@ -89479,7 +100334,7 @@ class PEAR_Validator_PECL extends PEAR_Validate
* @author Stephan Schmidt (original XML_Unserializer code)
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license New BSD License
- * @version Release: 1.10.0beta1
+ * @version Release: 1.9.4
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a1
*/
@@ -94932,7 +105787,7 @@ That's all there is to it!
* @author Tomas V.V.Cox <cox@idecnet.com>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version CVS: $Id: System.php 312944 2011-07-05 18:31:18Z dufuz $
+ * @version CVS: $Id: System.php 313024 2011-07-06 19:51:24Z dufuz $
* @link http://pear.php.net/package/PEAR
* @since File available since Release 0.1
*/
@@ -94974,7 +105829,7 @@ $GLOBALS['_System_temp_files'] = array();
* @author Tomas V.V. Cox <cox@idecnet.com>
* @copyright 1997-2006 The PHP Group
* @license http://opensource.org/licenses/bsd-license.php New BSD License
-* @version Release: 1.10.0beta1
+* @version Release: 1.9.4
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 0.1
* @static
@@ -94994,23 +105849,6 @@ class System
function _parseArgs($argv, $short_options, $long_options = null)
{
if (!is_array($argv) && $argv !== null) {
- /*
- // Quote all items that are a short option
- $av = preg_split('/(\A| )--?[a-z0-9]+[ =]?((?<!\\\\)((,\s*)|((?<!,)\s+))?)/i', $argv, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_OFFSET_CAPTURE);
- $offset = 0;
- foreach ($av as $a) {
- $b = trim($a[0]);
- if ($b{0} == '"' || $b{0} == "'") {
- continue;
- }
-
- $escape = escapeshellarg($b);
- $pos = $a[1] + $offset;
- $argv = substr_replace($argv, $escape, $pos, strlen($b));
- $offset += 2;
- }
- */
-
// Find all items, quoted or otherwise
preg_match_all("/(?:[\"'])(.*?)(?:['\"])|([^\s]+)/", $argv, $av);
$argv = $av[1];
@@ -95021,7 +105859,6 @@ class System
$argv[$k] = trim($a) ;
}
}
-
return Console_Getopt::getopt2($argv, $short_options, $long_options);
}
@@ -95575,7 +106412,7 @@ class System
* XML_Util
*
* XML Utilities package
- *
+ *
* PHP versions 4 and 5
*
* LICENSE:
@@ -95612,7 +106449,7 @@ class System
* @author Stephan Schmidt <schst@php.net>
* @copyright 2003-2008 Stephan Schmidt <schst@php.net>
* @license http://opensource.org/licenses/bsd-license New BSD License
- * @version CVS: $Id: Util.php 275418 2009-02-09 14:23:42Z ashnazg $
+ * @version CVS: $Id: Util.php,v 1.38 2008/11/13 00:03:38 ashnazg Exp $
* @link http://pear.php.net/package/XML_Util
*/
@@ -95688,7 +106525,7 @@ define('XML_UTIL_COLLAPSE_XHTML_ONLY', 2);
* @author Stephan Schmidt <schst@php.net>
* @copyright 2003-2008 Stephan Schmidt <schst@php.net>
* @license http://opensource.org/licenses/bsd-license New BSD License
- * @version Release: @version@
+ * @version Release: 1.2.1
* @link http://pear.php.net/package/XML_Util
*/
class XML_Util
@@ -95730,11 +106567,11 @@ class XML_Util
* );
* </code>
*
- * @param string $string string where XML special chars
+ * @param string $string string where XML special chars
* should be replaced
- * @param int $replaceEntities setting for entities in attribute values
- * (one of XML_UTIL_ENTITIES_XML,
- * XML_UTIL_ENTITIES_XML_REQUIRED,
+ * @param int $replaceEntities setting for entities in attribute values
+ * (one of XML_UTIL_ENTITIES_XML,
+ * XML_UTIL_ENTITIES_XML_REQUIRED,
* XML_UTIL_ENTITIES_HTML)
* @param string $encoding encoding value (if any)...
* must be a valid encoding as determined
@@ -95796,11 +106633,11 @@ class XML_Util
* );
* </code>
*
- * @param string $string string where XML special chars
+ * @param string $string string where XML special chars
* should be replaced
- * @param int $replaceEntities setting for entities in attribute values
- * (one of XML_UTIL_ENTITIES_XML,
- * XML_UTIL_ENTITIES_XML_REQUIRED,
+ * @param int $replaceEntities setting for entities in attribute values
+ * (one of XML_UTIL_ENTITIES_XML,
+ * XML_UTIL_ENTITIES_XML_REQUIRED,
* XML_UTIL_ENTITIES_HTML)
* @param string $encoding encoding value (if any)...
* must be a valid encoding as determined
@@ -95855,7 +106692,7 @@ class XML_Util
* @static
* @uses attributesToString() to serialize the attributes of the XML declaration
*/
- function getXMLDeclaration($version = '1.0', $encoding = null,
+ function getXMLDeclaration($version = '1.0', $encoding = null,
$standalone = null)
{
$attributes = array(
@@ -95870,7 +106707,7 @@ class XML_Util
$attributes['standalone'] = $standalone ? 'yes' : 'no';
}
- return sprintf('<?xml%s?>',
+ return sprintf('<?xml%s?>',
XML_Util::attributesToString($attributes, false));
}
@@ -95885,7 +106722,7 @@ class XML_Util
* </code>
*
* @param string $root name of the root tag
- * @param string $uri uri of the doctype definition
+ * @param string $uri uri of the doctype definition
* (or array with uri and public id)
* @param string $internalDtd internal dtd entries
*
@@ -95927,20 +106764,20 @@ class XML_Util
* </code>
*
* @param array $attributes attribute array
- * @param bool|array $sort sort attribute list alphabetically,
- * may also be an assoc array containing
- * the keys 'sort', 'multiline', 'indent',
+ * @param bool|array $sort sort attribute list alphabetically,
+ * may also be an assoc array containing
+ * the keys 'sort', 'multiline', 'indent',
* 'linebreak' and 'entities'
- * @param bool $multiline use linebreaks, if more than
+ * @param bool $multiline use linebreaks, if more than
* one attribute is given
- * @param string $indent string used for indentation of
+ * @param string $indent string used for indentation of
* multiline attributes
- * @param string $linebreak string used for linebreaks of
+ * @param string $linebreak string used for linebreaks of
* multiline attributes
- * @param int $entities setting for entities in attribute values
- * (one of XML_UTIL_ENTITIES_NONE,
- * XML_UTIL_ENTITIES_XML,
- * XML_UTIL_ENTITIES_XML_REQUIRED,
+ * @param int $entities setting for entities in attribute values
+ * (one of XML_UTIL_ENTITIES_NONE,
+ * XML_UTIL_ENTITIES_XML,
+ * XML_UTIL_ENTITIES_XML_REQUIRED,
* XML_UTIL_ENTITIES_HTML)
*
* @return string string representation of the attributes
@@ -95949,7 +106786,7 @@ class XML_Util
* @uses replaceEntities() to replace XML entities in attribute values
* @todo allow sort also to be an options array
*/
- function attributesToString($attributes, $sort = true, $multiline = false,
+ function attributesToString($attributes, $sort = true, $multiline = false,
$indent = ' ', $linebreak = "\n", $entities = XML_UTIL_ENTITIES_XML)
{
/*
@@ -96020,7 +106857,7 @@ class XML_Util
* @todo PEAR CS - unable to avoid "space after open parens" error
* in the IF branch
*/
- function collapseEmptyTags($xml, $mode = XML_UTIL_COLLAPSE_ALL)
+ function collapseEmptyTags($xml, $mode = XML_UTIL_COLLAPSE_ALL)
{
if ($mode == XML_UTIL_COLLAPSE_XHTML_ONLY) {
return preg_replace(
@@ -96043,9 +106880,9 @@ class XML_Util
* require_once 'XML/Util.php';
*
* // create an XML tag:
- * $tag = XML_Util::createTag('myNs:myTag',
- * array('foo' => 'bar'),
- * 'This is inside the tag',
+ * $tag = XML_Util::createTag('myNs:myTag',
+ * array('foo' => 'bar'),
+ * 'This is inside the tag',
* 'http://www.w3c.org/myNs#');
* </code>
*
@@ -96053,13 +106890,13 @@ class XML_Util
* @param array $attributes array containg attributes
* @param mixed $content the content
* @param string $namespaceUri URI of the namespace
- * @param int $replaceEntities whether to replace XML special chars in
- * content, embedd it in a CData section
+ * @param int $replaceEntities whether to replace XML special chars in
+ * content, embedd it in a CData section
* or none of both
- * @param bool $multiline whether to create a multiline tag where
+ * @param bool $multiline whether to create a multiline tag where
* each attribute gets written to a single line
- * @param string $indent string used to indent attributes
- * (_auto indents attributes so they start
+ * @param string $indent string used to indent attributes
+ * (_auto indents attributes so they start
* at the same column)
* @param string $linebreak string used for linebreaks
* @param bool $sortAttributes Whether to sort the attributes or not
@@ -96070,9 +106907,9 @@ class XML_Util
* @see createTagFromArray()
* @uses createTagFromArray() to create the tag
*/
- function createTag($qname, $attributes = array(), $content = null,
- $namespaceUri = null, $replaceEntities = XML_UTIL_REPLACE_ENTITIES,
- $multiline = false, $indent = '_auto', $linebreak = "\n",
+ function createTag($qname, $attributes = array(), $content = null,
+ $namespaceUri = null, $replaceEntities = XML_UTIL_REPLACE_ENTITIES,
+ $multiline = false, $indent = '_auto', $linebreak = "\n",
$sortAttributes = true)
{
$tag = array(
@@ -96090,7 +106927,7 @@ class XML_Util
$tag['namespaceUri'] = $namespaceUri;
}
- return XML_Util::createTagFromArray($tag, $replaceEntities, $multiline,
+ return XML_Util::createTagFromArray($tag, $replaceEntities, $multiline,
$indent, $linebreak, $sortAttributes);
}
@@ -96100,22 +106937,22 @@ class XML_Util
* <pre>
* array(
* // qualified name of the tag
- * 'qname' => $qname
+ * 'qname' => $qname
*
* // namespace prefix (optional, if qname is specified or no namespace)
- * 'namespace' => $namespace
+ * 'namespace' => $namespace
*
* // local part of the tagname (optional, if qname is specified)
- * 'localpart' => $localpart,
+ * 'localpart' => $localpart,
*
* // array containing all attributes (optional)
- * 'attributes' => array(),
+ * 'attributes' => array(),
*
* // tag content (optional)
- * 'content' => $content,
+ * 'content' => $content,
*
* // namespaceUri for the given namespace (optional)
- * 'namespaceUri' => $namespaceUri
+ * 'namespaceUri' => $namespaceUri
* )
* </pre>
*
@@ -96133,13 +106970,13 @@ class XML_Util
* </code>
*
* @param array $tag tag definition
- * @param int $replaceEntities whether to replace XML special chars in
- * content, embedd it in a CData section
+ * @param int $replaceEntities whether to replace XML special chars in
+ * content, embedd it in a CData section
* or none of both
- * @param bool $multiline whether to create a multiline tag where each
+ * @param bool $multiline whether to create a multiline tag where each
* attribute gets written to a single line
- * @param string $indent string used to indent attributes
- * (_auto indents attributes so they start
+ * @param string $indent string used to indent attributes
+ * (_auto indents attributes so they start
* at the same column)
* @param string $linebreak string used for linebreaks
* @param bool $sortAttributes Whether to sort the attributes or not
@@ -96154,7 +106991,7 @@ class XML_Util
* @uses raiseError()
*/
function createTagFromArray($tag, $replaceEntities = XML_UTIL_REPLACE_ENTITIES,
- $multiline = false, $indent = '_auto', $linebreak = "\n",
+ $multiline = false, $indent = '_auto', $linebreak = "\n",
$sortAttributes = true)
{
if (isset($tag['content']) && !is_scalar($tag['content'])) {
@@ -96164,7 +107001,7 @@ class XML_Util
if (!isset($tag['qname']) && !isset($tag['localPart'])) {
return XML_Util::raiseError('You must either supply a qualified name '
- . '(qname) or local tag name (localPart).',
+ . '(qname) or local tag name (localPart).',
XML_UTIL_ERROR_NO_TAG_NAME);
}
@@ -96218,7 +107055,7 @@ class XML_Util
}
// create attribute list
- $attList = XML_Util::attributesToString($tag['attributes'],
+ $attList = XML_Util::attributesToString($tag['attributes'],
$sortAttributes, $multiline, $indent, $linebreak, $replaceEntities);
if (!isset($tag['content']) || (string)$tag['content'] == '') {
$tag = sprintf('<%s%s />', $tag['qname'], $attList);
@@ -96230,7 +107067,7 @@ class XML_Util
$tag['content'] = XML_Util::createCDataSection($tag['content']);
break;
default:
- $tag['content'] = XML_Util::replaceEntities($tag['content'],
+ $tag['content'] = XML_Util::replaceEntities($tag['content'],
$replaceEntities);
break;
}
@@ -96247,14 +107084,14 @@ class XML_Util
* require_once 'XML/Util.php';
*
* // create an XML start element:
- * $tag = XML_Util::createStartElement('myNs:myTag',
+ * $tag = XML_Util::createStartElement('myNs:myTag',
* array('foo' => 'bar') ,'http://www.w3c.org/myNs#');
* </code>
*
* @param string $qname qualified tagname (including namespace)
* @param array $attributes array containg attributes
* @param string $namespaceUri URI of the namespace
- * @param bool $multiline whether to create a multiline tag where each
+ * @param bool $multiline whether to create a multiline tag where each
* attribute gets written to a single line
* @param string $indent string used to indent attributes (_auto indents
* attributes so they start at the same column)
@@ -96267,7 +107104,7 @@ class XML_Util
* @see createEndElement(), createTag()
*/
function createStartElement($qname, $attributes = array(), $namespaceUri = null,
- $multiline = false, $indent = '_auto', $linebreak = "\n",
+ $multiline = false, $indent = '_auto', $linebreak = "\n",
$sortAttributes = true)
{
// if no attributes hav been set, use empty attributes
@@ -96297,7 +107134,7 @@ class XML_Util
}
// create attribute list
- $attList = XML_Util::attributesToString($attributes, $sortAttributes,
+ $attList = XML_Util::attributesToString($attributes, $sortAttributes,
$multiline, $indent, $linebreak);
$element = sprintf('<%s%s>', $qname, $attList);
return $element;
@@ -96366,7 +107203,7 @@ class XML_Util
*/
function createCDataSection($data)
{
- return sprintf('<![CDATA[%s]]>',
+ return sprintf('<![CDATA[%s]]>',
preg_replace('/\]\]>/', ']]]]><![CDATA[>', strval($data)));
}
@@ -96440,17 +107277,17 @@ class XML_Util
function isValidName($string)
{
// check for invalid chars
- if (!preg_match('/^[[:alpha:]_]\\z/', $string{0})) {
+ if (!preg_match('/^[[:alpha:]_]$/', $string{0})) {
return XML_Util::raiseError('XML names may only start with letter '
. 'or underscore', XML_UTIL_ERROR_INVALID_START);
}
// check for invalid chars
- if (!preg_match('/^([[:alpha:]_]([[:alnum:]\-\.]*)?:)?[[:alpha:]_]([[:alnum:]\_\-\.]+)?\\z/',
+ if (!preg_match('/^([[:alpha:]_]([[:alnum:]\-\.]*)?:)?[[:alpha:]_]([[:alnum:]\_\-\.]+)?$/',
$string)
) {
return XML_Util::raiseError('XML names may only contain alphanumeric '
- . 'chars, period, hyphen, colon and underscores',
+ . 'chars, period, hyphen, colon and underscores',
XML_UTIL_ERROR_INVALID_CHARS);
}
// XML name is valid
@@ -99493,4 +110330,4 @@ iEYEABECAAYFAkk8e2QACgkQcqMhusJF8XULZgCg0iwVLWueraJzK5s1AesDkVzv
GucAn22sSv3QiTSUWG9BmakiW9hFsb4V
=g2mr
-----END PGP SIGNATURE-----
-
+
diff --git a/php.ini-development b/php.ini-development
index 93a4b7d8a..e9c7cd662 100644
--- a/php.ini-development
+++ b/php.ini-development
@@ -1860,6 +1860,102 @@ ldap.max_links = -1
[dba]
;dba.default_handler=
+[opcache]
+; Determines if Zend OPCache is enabled
+;opcache.enable=0
+
+; Determines if Zend OPCache is enabled for the CLI version of PHP
+;opcache.enable_cli=0
+
+; The OPcache shared memory storage size.
+;opcache.memory_consumption=64
+
+; The amount of memory for interned strings in Mbytes.
+;opcache.interned_strings_buffer=4
+
+; The maximum number of keys (scripts) in the OPcache hash table.
+; Only numbers between 200 and 100000 are allowed.
+;opcache.max_accelerated_files=2000
+
+; The maximum percentage of "wasted" memory until a restart is scheduled.
+;opcache.max_wasted_percentage=5
+
+; When this directive is enabled, the OPcache appends the current working
+; directory to the script key, thus eliminating possible collisions between
+; files with the same name (basename). Disabling the directive improves
+; performance, but may break existing applications.
+;opcache.use_cwd=1
+
+; When disabled, you must reset the OPcache manually or restart the
+; webserver for changes to the filesystem to take effect.
+;opcache.validate_timestamps=1
+
+; How often (in seconds) to check file timestamps for changes to the shared
+; memory storage allocation. ("1" means validate once per second, but only
+; once per request. "0" means always validate)
+;opcache.revalidate_freq=2
+
+; Enables or disables file search in include_path optimization
+;opcache.revalidate_path=0
+
+; If disabled, all PHPDoc comments are dropped from the code to reduce the
+ ;size of the optimized code.
+;opcache.save_comments=1
+
+; If disabled, PHPDoc comments are not loaded from SHM, so "Doc Comments"
+; may be always stored (save_comments=1), but not loaded by applications
+; that don't need them anyway.
+;opcache.load_comments=1
+
+; If enabled, a fast shutdown sequence is used for the accelerated code
+;opcache.fast_shutdown=0
+
+; Allow file existence override (file_exists, etc.) performance feature.
+;opcache.enable_file_override=0
+
+; A bitmask, where each bit enables or disables the appropriate OPcache
+; passes
+;opcache.optimization_level=0xffffffff
+
+;opcache.inherited_hack=1
+;opcache.dups_fix=0
+
+; The location of the OPcache blacklist file.
+; The OPcache blacklist file is a text file that holds the names of files
+; that should not be accelerated. The file format is to add each filename
+; to a new line. The filename may be a full path or just a file prefix
+; (i.e., /var/www/x blacklists all the files and directories in /var/www
+; that start with 'x').
+;opcache.blacklist_filename=
+
+; Allows exclusion of large files from being cached. By default all files
+; are cached.
+;opcache.max_file_size=0
+
+; Check the cache checksum each N requests.
+; The default value of "0" means that the checks are disabled.
+;opcache.consistency_checks=0
+
+; How long to wait (in seconds) for a scheduled restart to begin if the cache
+; is not being accessed.
+;opcache.force_restart_timeout=180
+
+; OPcache error_log file name. Empty string assumes "stderr".
+;opcache.error_log=
+
+; All OPcache errors go to the Web server log.
+; By default, only fatal errors (level 0) or errors (level 1) are logged.
+; You can also enable warnings (level 2), info messages (level 3) or
+; debug messages (level 4).
+;opcache.log_verbosity_level=1
+
+; Preferred Shared Memory back-end. Leave empty and let the system decide.
+;opcache.preferred_memory_model=
+
+; Protect the shared memory from unexpected writing during script execution.
+; Useful for internal debugging only.
+;opcache.protect_memory=0
+
; Local Variables:
; tab-width: 4
; End:
diff --git a/php.ini-production b/php.ini-production
index 7d84c9b87..600debc9e 100644
--- a/php.ini-production
+++ b/php.ini-production
@@ -1860,6 +1860,102 @@ ldap.max_links = -1
[dba]
;dba.default_handler=
+[opcache]
+; Determines if Zend OPCache is enabled
+;opcache.enable=0
+
+; Determines if Zend OPCache is enabled for the CLI version of PHP
+;opcache.enable_cli=0
+
+; The OPcache shared memory storage size.
+;opcache.memory_consumption=64
+
+; The amount of memory for interned strings in Mbytes.
+;opcache.interned_strings_buffer=4
+
+; The maximum number of keys (scripts) in the OPcache hash table.
+; Only numbers between 200 and 100000 are allowed.
+;opcache.max_accelerated_files=2000
+
+; The maximum percentage of "wasted" memory until a restart is scheduled.
+;opcache.max_wasted_percentage=5
+
+; When this directive is enabled, the OPcache appends the current working
+; directory to the script key, thus eliminating possible collisions between
+; files with the same name (basename). Disabling the directive improves
+; performance, but may break existing applications.
+;opcache.use_cwd=1
+
+; When disabled, you must reset the OPcache manually or restart the
+; webserver for changes to the filesystem to take effect.
+;opcache.validate_timestamps=1
+
+; How often (in seconds) to check file timestamps for changes to the shared
+; memory storage allocation. ("1" means validate once per second, but only
+; once per request. "0" means always validate)
+;opcache.revalidate_freq=2
+
+; Enables or disables file search in include_path optimization
+;opcache.revalidate_path=0
+
+; If disabled, all PHPDoc comments are dropped from the code to reduce the
+ ;size of the optimized code.
+;opcache.save_comments=1
+
+; If disabled, PHPDoc comments are not loaded from SHM, so "Doc Comments"
+; may be always stored (save_comments=1), but not loaded by applications
+; that don't need them anyway.
+;opcache.load_comments=1
+
+; If enabled, a fast shutdown sequence is used for the accelerated code
+;opcache.fast_shutdown=0
+
+; Allow file existence override (file_exists, etc.) performance feature.
+;opcache.enable_file_override=0
+
+; A bitmask, where each bit enables or disables the appropriate OPcache
+; passes
+;opcache.optimization_level=0xffffffff
+
+;opcache.inherited_hack=1
+;opcache.dups_fix=0
+
+; The location of the OPcache blacklist file.
+; The OPcache blacklist file is a text file that holds the names of files
+; that should not be accelerated. The file format is to add each filename
+; to a new line. The filename may be a full path or just a file prefix
+; (i.e., /var/www/x blacklists all the files and directories in /var/www
+; that start with 'x').
+;opcache.blacklist_filename=
+
+; Allows exclusion of large files from being cached. By default all files
+; are cached.
+;opcache.max_file_size=0
+
+; Check the cache checksum each N requests.
+; The default value of "0" means that the checks are disabled.
+;opcache.consistency_checks=0
+
+; How long to wait (in seconds) for a scheduled restart to begin if the cache
+; is not being accessed.
+;opcache.force_restart_timeout=180
+
+; OPcache error_log file name. Empty string assumes "stderr".
+;opcache.error_log=
+
+; All OPcache errors go to the Web server log.
+; By default, only fatal errors (level 0) or errors (level 1) are logged.
+; You can also enable warnings (level 2), info messages (level 3) or
+; debug messages (level 4).
+;opcache.log_verbosity_level=1
+
+; Preferred Shared Memory back-end. Leave empty and let the system decide.
+;opcache.preferred_memory_model=
+
+; Protect the shared memory from unexpected writing during script execution.
+; Useful for internal debugging only.
+;opcache.protect_memory=0
+
; Local Variables:
; tab-width: 4
; End:
diff --git a/sapi/cli/php.1.in b/sapi/cli/php.1.in
index 186b128f8..0e9d07ac7 100644
--- a/sapi/cli/php.1.in
+++ b/sapi/cli/php.1.in
@@ -1,4 +1,4 @@
-.TH PHP 1 "2010" "The PHP Group" "Scripting Language"
+.TH PHP 1 "2013" "The PHP Group" "Scripting Language"
.SH NAME
php \- PHP Command Line Interface 'CLI'
.SH SYNOPSIS
@@ -42,6 +42,12 @@ php \- PHP Command Line Interface 'CLI'
.LP
\fBphp \fP[options] \fB\-a\fP
.LP
+.B php
+[options] \-S
+.IR addr:port
+[\-t
+.IR docroot ]
+.LP
.SH DESCRIPTION
\fBPHP\fP is a widely\-used general\-purpose scripting language that is especially suited for
Web development and can be embedded into HTML. This is the command line interface
@@ -78,7 +84,13 @@ and therefore reading from
.B STDIN
explicitly changes the next input line or skips input lines.
.LP
-If none of \-r \-f \-B \-R \-F or \-E is present but a single parameter is given
+PHP also contains an embedded web server for application development purpose. By using the \-S option where
+.B addr:port
+point to a local address and port PHP will listen to HTTP requests on that address and port and serve files from the current working directory or the
+.B docroot
+passed by the \-t option.
+.LP
+If none of \-r \-f \-B \-R \-F \-E or \-S is present but a single parameter is given
then this parameter is taken as the filename to parse and execute (same as
with \-f). If no parameter is present then the standard input is read and
executed.
@@ -263,6 +275,20 @@ after processing all input lines
Output HTML syntax highlighted source
.TP
.PD 0
+.B \-\-server \fIaddr:port\fP
+.TP
+.PD 1
+.B \-S \fIaddr:port\fP
+Start embedded Webserver on the given local address and port
+.TP
+.PD 0
+.B \-\-docroot \fIdocroot\fP
+.TP
+.PD 1
+.B \-t \fIdocroot\fP
+Specify the document root to be used by the embedded web server
+.TP
+.PD 0
.B \-\-version
.TP
.PD 1
@@ -435,7 +461,7 @@ contributors all around the world.
.SH VERSION INFORMATION
This manpage describes \fBphp\fP, version @PHP_VERSION@.
.SH COPYRIGHT
-Copyright \(co 1997\-2010 The PHP Group
+Copyright \(co 1997\-2013 The PHP Group
.LP
This source file is subject to version 3.01 of the PHP license,
that is bundled with this package in the file LICENSE, and is
diff --git a/sapi/cli/php_cli_server.c b/sapi/cli/php_cli_server.c
index a2b85d47b..5c9b2e86d 100644
--- a/sapi/cli/php_cli_server.c
+++ b/sapi/cli/php_cli_server.c
@@ -24,11 +24,12 @@
#include <assert.h>
#ifdef PHP_WIN32
-#include <process.h>
-#include <io.h>
-#include "win32/time.h"
-#include "win32/signal.h"
-#include "win32/php_registry.h"
+# include <process.h>
+# include <io.h>
+# include "win32/time.h"
+# include "win32/signal.h"
+# include "win32/php_registry.h"
+# include <sys/timeb.h>
#else
# include "php_config.h"
#endif
@@ -296,6 +297,36 @@ static const char php_cli_server_css[] = "<style>\n" \
"</style>\n";
/* }}} */
+#ifdef PHP_WIN32
+int php_cli_server_get_system_time(char *buf) {
+ struct _timeb system_time;
+ errno_t err;
+
+ if (buf == NULL) {
+ return -1;
+ }
+
+ _ftime(&system_time);
+ err = ctime_s(buf, 52, &(system_time.time) );
+ if (err) {
+ return -1;
+ }
+ return 0;
+}
+#else
+int php_cli_server_get_system_time(char *buf) {
+ struct timeval tv;
+ struct tm tm;
+
+ gettimeofday(&tv, NULL);
+
+ /* TODO: should be checked for NULL tm/return vaue */
+ php_localtime_r(&tv.tv_sec, &tm);
+ php_asctime_r(&tm, buf);
+ return 0;
+}
+#endif
+
static void char_ptr_dtor_p(char **p) /* {{{ */
{
pefree(*p, 1);
@@ -640,13 +671,11 @@ static void sapi_cli_server_register_variables(zval *track_vars_array TSRMLS_DC)
static void sapi_cli_server_log_message(char *msg TSRMLS_DC) /* {{{ */
{
- struct timeval tv;
- struct tm tm;
char buf[52];
- gettimeofday(&tv, NULL);
- php_localtime_r(&tv.tv_sec, &tm);
- php_asctime_r(&tm, buf);
- {
+
+ if (php_cli_server_get_system_time(buf) != 0) {
+ memmove(buf, "unknown time, can't be fetched", sizeof("unknown time, can't be fetched"));
+ } else {
size_t l = strlen(buf);
if (l > 0) {
buf[l - 1] = '\0';
@@ -2402,12 +2431,12 @@ int do_cli_server(int argc, char **argv TSRMLS_DC) /* {{{ */
sapi_module.phpinfo_as_text = 0;
{
- struct timeval tv;
- struct tm tm;
char buf[52];
- gettimeofday(&tv, NULL);
- php_localtime_r(&tv.tv_sec, &tm);
- php_asctime_r(&tm, buf);
+
+ if (php_cli_server_get_system_time(buf) != 0) {
+ memmove(buf, "unknown time, can't be fetched", sizeof("unknown time, can't be fetched"));
+ }
+
printf("PHP %s Development Server started at %s"
"Listening on http://%s\n"
"Document root is %s\n"
diff --git a/win32/time.c b/win32/time.c
index 77e4504cd..75539748e 100644
--- a/win32/time.c
+++ b/win32/time.c
@@ -50,6 +50,7 @@ int getfilesystemtime(struct timeval *tv)
FILETIME ft;
unsigned __int64 ff = 0;
MyGetSystemTimeAsFileTime timefunc;
+ ULARGE_INTEGER fft;
timefunc = get_time_func();
if (timefunc) {
@@ -58,14 +59,20 @@ int getfilesystemtime(struct timeval *tv)
GetSystemTimeAsFileTime(&ft);
}
- ff |= ft.dwHighDateTime;
- ff <<= 32;
- ff |= ft.dwLowDateTime;
- ff /= 10; /* convert to microseconds */
+ /*
+ * Do not cast a pointer to a FILETIME structure to either a
+ * ULARGE_INTEGER* or __int64* value because it can cause alignment faults on 64-bit Windows.
+ * via http://technet.microsoft.com/en-us/library/ms724284(v=vs.85).aspx
+ */
+ fft.HighPart = ft.dwHighDateTime;
+ fft.LowPart = ft.dwLowDateTime;
+ ff = fft.QuadPart;
+
+ ff /= 10Ui64; /* convert to microseconds */
ff -= 11644473600000000Ui64; /* convert to unix epoch */
- tv->tv_sec = (long)(ff / 1000000UL);
- tv->tv_usec = (long)(ff % 1000000UL);
+ tv->tv_sec = (long)(ff / 1000000Ui64);
+ tv->tv_usec = (long)(ff % 1000000Ui64);
return 0;
}