diff options
Diffstat (limited to 'ext')
515 files changed, 20835 insertions, 6163 deletions
diff --git a/ext/bz2/bz2.c b/ext/bz2/bz2.c index abe84fc316..4adaa47fa9 100644 --- a/ext/bz2/bz2.c +++ b/ext/bz2/bz2.c @@ -192,7 +192,7 @@ php_stream_ops php_stream_bz2io_ops = { /* {{{ Bzip2 stream openers */ PHP_BZ2_API php_stream *_php_stream_bz2open_from_BZFILE(BZFILE *bz, - char *mode, php_stream *innerstream STREAMS_DC TSRMLS_DC) + const char *mode, php_stream *innerstream STREAMS_DC TSRMLS_DC) { struct php_bz2_stream_data_t *self; @@ -205,8 +205,8 @@ PHP_BZ2_API php_stream *_php_stream_bz2open_from_BZFILE(BZFILE *bz, } PHP_BZ2_API php_stream *_php_stream_bz2open(php_stream_wrapper *wrapper, - char *path, - char *mode, + const char *path, + const char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC) diff --git a/ext/bz2/php_bz2.h b/ext/bz2/php_bz2.h index 8b12eca357..7bcffc1831 100644 --- a/ext/bz2/php_bz2.h +++ b/ext/bz2/php_bz2.h @@ -47,8 +47,8 @@ extern zend_module_entry bz2_module_entry; # define PHP_BZ2_API #endif -PHP_BZ2_API php_stream *_php_stream_bz2open(php_stream_wrapper *wrapper, char *path, char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC); -PHP_BZ2_API php_stream *_php_stream_bz2open_from_BZFILE(BZFILE *bz, char *mode, php_stream *innerstream STREAMS_DC TSRMLS_DC); +PHP_BZ2_API php_stream *_php_stream_bz2open(php_stream_wrapper *wrapper, const char *path, const char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC); +PHP_BZ2_API php_stream *_php_stream_bz2open_from_BZFILE(BZFILE *bz, const char *mode, php_stream *innerstream STREAMS_DC TSRMLS_DC); #define php_stream_bz2open_from_BZFILE(bz, mode, innerstream) _php_stream_bz2open_from_BZFILE((bz), (mode), (innerstream) STREAMS_CC TSRMLS_CC) #define php_stream_bz2open(wrapper, path, mode, options, opened_path) _php_stream_bz2open((wrapper), (path), (mode), (options), (opened_path), NULL STREAMS_CC TSRMLS_CC) diff --git a/ext/curl/interface.c b/ext/curl/interface.c index 9fdb57cc4e..591315973c 100644 --- a/ext/curl/interface.c +++ b/ext/curl/interface.c @@ -1791,7 +1791,7 @@ static void alloc_curl_handle(php_curl **ch) zend_llist_init(&(*ch)->to_free->str, sizeof(char *), (llist_dtor_func_t) curl_free_string, 0); zend_llist_init(&(*ch)->to_free->post, sizeof(struct HttpPost), (llist_dtor_func_t) curl_free_post, 0); - (*ch)->safe_upload = 0; /* for now, for BC reason we allow unsafe API */ + (*ch)->safe_upload = 1; /* for now, for BC reason we allow unsafe API */ (*ch)->to_free->slist = emalloc(sizeof(HashTable)); zend_hash_init((*ch)->to_free->slist, 4, NULL, curl_free_slist, 0); @@ -2504,6 +2504,7 @@ string_copy: case CURLOPT_FOLLOWLOCATION: convert_to_long_ex(zvalue); +#if LIBCURL_VERSION_NUM < 0x071304 if (PG(open_basedir) && *PG(open_basedir)) { if (Z_LVAL_PP(zvalue) != 0) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "CURLOPT_FOLLOWLOCATION cannot be activated when an open_basedir is set"); @@ -2511,6 +2512,7 @@ string_copy: return 1; } } +#endif error = curl_easy_setopt(ch->cp, option, Z_LVAL_PP(zvalue)); break; diff --git a/ext/curl/tests/bug65646.phpt b/ext/curl/tests/bug65646.phpt new file mode 100644 index 0000000000..f244f7238f --- /dev/null +++ b/ext/curl/tests/bug65646.phpt @@ -0,0 +1,15 @@ +--TEST-- +Bug #65646 (re-enable CURLOPT_FOLLOWLOCATION with open_basedir or safe_mode): open_basedir disabled +--SKIPIF-- +<?php +if (!extension_loaded('curl')) exit("skip curl extension not loaded"); +if (ini_get('open_basedir')) exit("skip open_basedir is set"); +?> +--FILE-- +<?php +$ch = curl_init(); +var_dump(curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true)); +curl_close($ch); +?> +--EXPECT-- +bool(true) diff --git a/ext/curl/tests/bug65646_open_basedir_new.phpt b/ext/curl/tests/bug65646_open_basedir_new.phpt new file mode 100644 index 0000000000..991c4a2b8a --- /dev/null +++ b/ext/curl/tests/bug65646_open_basedir_new.phpt @@ -0,0 +1,25 @@ +--TEST-- +Bug #65646 (re-enable CURLOPT_FOLLOWLOCATION with open_basedir or safe_mode): open_basedir enabled; curl >= 7.19.4 +--INI-- +open_basedir=. +--SKIPIF-- +<?php +if (!extension_loaded('curl')) exit("skip curl extension not loaded"); +if (version_compare(curl_version()['version'], '7.19.4', '<')) exit("skip curl version is too old"); +?> +--FILE-- +<?php +$ch = curl_init(); +var_dump(curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true)); +var_dump(curl_setopt($ch, CURLOPT_PROTOCOLS, CURLPROTO_FILE)); +var_dump(curl_setopt($ch, CURLOPT_REDIR_PROTOCOLS, CURLPROTO_FILE)); +curl_close($ch); +?> +--EXPECTF-- +bool(true) + +Warning: curl_setopt(): CURLPROTO_FILE cannot be activated when an open_basedir is set in %s on line %d +bool(false) + +Warning: curl_setopt(): CURLPROTO_FILE cannot be activated when an open_basedir is set in %s on line %d +bool(false) diff --git a/ext/curl/tests/bug65646_open_basedir_old.phpt b/ext/curl/tests/bug65646_open_basedir_old.phpt new file mode 100644 index 0000000000..cf11d21a20 --- /dev/null +++ b/ext/curl/tests/bug65646_open_basedir_old.phpt @@ -0,0 +1,18 @@ +--TEST-- +Bug #65646 (re-enable CURLOPT_FOLLOWLOCATION with open_basedir or safe_mode): open_basedir enabled; curl < 7.19.4 +--INI-- +open_basedir=. +--SKIPIF-- +<?php +if (!extension_loaded('curl')) exit("skip curl extension not loaded"); +if (version_compare(curl_version()['version'], '7.19.4', '>=')) exit("skip curl version is too new"); +?> +--FILE-- +<?php +$ch = curl_init(); +var_dump(curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true)); +curl_close($ch); +?> +--EXPECTF-- +Warning: curl_setopt(): CURLOPT_FOLLOWLOCATION cannot be activated when an open_basedir is set in %s on line %d +bool(false) diff --git a/ext/curl/tests/curl_setopt_CURLOPT_FOLLOWLOCATION_open_basedir.phpt b/ext/curl/tests/curl_setopt_CURLOPT_FOLLOWLOCATION_open_basedir.phpt deleted file mode 100644 index 7a778f3692..0000000000 --- a/ext/curl/tests/curl_setopt_CURLOPT_FOLLOWLOCATION_open_basedir.phpt +++ /dev/null @@ -1,22 +0,0 @@ ---TEST-- -CURLOPT_FOLLOWLOCATION case check open_basedir ---CREDITS-- -WHITE new media architects - Dennis ---INI-- -open_basedir = DIRECTORY_SEPARATOR."tmp"; ---SKIPIF-- -<?php -if (!extension_loaded("curl")) print "skip cURL not loaded"; -?> ---FILE-- -<?php -print (ini_get("OPEN_BASEDIR")); -$ch = curl_init(); -$succes = curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); -curl_close($ch); -var_dump($succes); -?> ---EXPECTF-- -Warning: curl_setopt(): CURLOPT_FOLLOWLOCATION cannot be activated when an open_basedir is set in %s.php on line %d -bool(false) - diff --git a/ext/date/config0.m4 b/ext/date/config0.m4 index f403104a8a..0b46c6803a 100644 --- a/ext/date/config0.m4 +++ b/ext/date/config0.m4 @@ -22,4 +22,5 @@ cat > $ext_builddir/lib/timelib_config.h <<EOF #else # include <php_config.h> #endif +#include <php_stdint.h> EOF diff --git a/ext/date/lib/timelib_structs.h b/ext/date/lib/timelib_structs.h index a3d7793447..cc12eb38a6 100644 --- a/ext/date/lib/timelib_structs.h +++ b/ext/date/lib/timelib_structs.h @@ -23,37 +23,7 @@ #include "timelib_config.h" -#ifdef HAVE_SYS_TYPES_H -#include <sys/types.h> -#endif - -#if defined(HAVE_INTTYPES_H) -#include <inttypes.h> -#elif defined(HAVE_STDINT_H) -#include <stdint.h> -#endif - -#ifdef PHP_WIN32 -/* TODO: Remove these hacks/defs once we have the int definitions in main/ - rathen than in each 2nd extension and win32/ */ -# include "win32/php_stdint.h" -#else -# ifndef HAVE_INT32_T -# if SIZEOF_INT == 4 -typedef int int32_t; -# elif SIZEOF_LONG == 4 -typedef long int int32_t; -# endif -# endif - -# ifndef HAVE_UINT32_T -# if SIZEOF_INT == 4 -typedef unsigned int uint32_t; -# elif SIZEOF_LONG == 4 -typedef unsigned long int uint32_t; -# endif -# endif -#endif +#include "php_stdint.h" #include <stdio.h> diff --git a/ext/exif/exif.c b/ext/exif/exif.c index 2fe54f7b31..f886bb4fea 100644 --- a/ext/exif/exif.c +++ b/ext/exif/exif.c @@ -40,16 +40,6 @@ #include "php.h" #include "ext/standard/file.h" -#ifdef HAVE_STDINT_H -# include <stdint.h> -#endif -#ifdef HAVE_INTTYPES_H -# include <inttypes.h> -#endif -#ifdef PHP_WIN32 -# include "win32/php_stdint.h" -#endif - #if HAVE_EXIF /* When EXIF_DEBUG is defined the module generates a lot of debug messages diff --git a/ext/ext_skel b/ext/ext_skel index 2492bf73da..061e78d649 100755 --- a/ext/ext_skel +++ b/ext/ext_skel @@ -12,7 +12,7 @@ echo "" echo " --extname=module module is the name of your extension" echo " --proto=file file contains prototypes of functions to create" echo " --stubs=file generate only function stubs in file" -echo " --xml generate xml documentation to be added to phpdoc-cvs" +echo " --xml generate xml documentation to be added to phpdoc-svn" echo " --skel=dir path to the skeleton directory" echo " --full-xml generate xml documentation for a self-contained extension" echo " (not yet implemented)" @@ -187,11 +187,43 @@ if (PHP_$EXTNAME != "no") { eof -$ECHO_N " .svnignore$ECHO_C" -cat >.svnignore <<eof +$ECHO_N " .gitignore$ECHO_C" +cat >.gitignore <<eof .deps *.lo *.la +.libs +acinclude.m4 +aclocal.m4 +autom4te.cache +build +config.guess +config.h +config.h.in +config.log +config.nice +config.status +config.sub +configure +configure.in +include +install-sh +libtool +ltmain.sh +Makefile +Makefile.fragments +Makefile.global +Makefile.objects +missing +mkinstalldirs +modules +run-tests.php +tests/*/*.diff +tests/*/*.out +tests/*/*.php +tests/*/*.exp +tests/*/*.log +tests/*/*.sh eof $ECHO_N " $extname.c$ECHO_C" diff --git a/ext/fileinfo/fileinfo.c b/ext/fileinfo/fileinfo.c index 353adb98b9..799891ed13 100644 --- a/ext/fileinfo/fileinfo.c +++ b/ext/fileinfo/fileinfo.c @@ -497,7 +497,7 @@ static void _php_finfo_get_type(INTERNAL_FUNCTION_PARAMETERS, int mode, int mime case FILEINFO_MODE_FILE: { /* determine if the file is a local file or remote URL */ - char *tmp2; + const char *tmp2; php_stream_wrapper *wrap; php_stream_statbuf ssb; diff --git a/ext/gd/gd.c b/ext/gd/gd.c index fb258214a1..d8a90f5fb6 100644 --- a/ext/gd/gd.c +++ b/ext/gd/gd.c @@ -82,6 +82,10 @@ static void php_free_ps_enc(zend_rsrc_list_entry *rsrc TSRMLS_DC); # endif #endif +#if defined(HAVE_GD_XPM) && defined(HAVE_GD_BUNDLED) +# include "X11/xpm.h" +#endif + #ifndef M_PI #define M_PI 3.14159265358979323846 #endif @@ -92,6 +96,10 @@ static void php_imagettftext_common(INTERNAL_FUNCTION_PARAMETERS, int, int); #include "gd_ctx.c" +/* as it is not really public, duplicate declaration here to avoid + pointless warnings */ +int overflow2(int a, int b); + /* Section Filters Declarations */ /* IMPORTANT NOTE FOR NEW FILTER * Do not forget to update: @@ -2082,7 +2090,7 @@ PHP_FUNCTION(imagerotate) ZEND_FETCH_RESOURCE(im_src, gdImagePtr, &SIM, -1, "Image", le_gd); - im_dst = gdImageRotateInterpolated(im_src, (float)degrees, color); + im_dst = gdImageRotateInterpolated(im_src, (const float)degrees, color); if (im_dst != NULL) { ZEND_REGISTER_RESOURCE(return_value, im_dst, le_gd); @@ -5175,8 +5183,6 @@ PHP_FUNCTION(imageaffine) 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; } diff --git a/ext/gd/libgd/gd.h b/ext/gd/libgd/gd.h index 72515108d6..20156b97b5 100644 --- a/ext/gd/libgd/gd.h +++ b/ext/gd/libgd/gd.h @@ -849,8 +849,7 @@ gdImagePtr gdImageRotateNearestNeighbour(gdImagePtr src, const float degrees, co 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); - - +gdImagePtr gdImageRotateInterpolated(const gdImagePtr src, const float angle, int bgcolor); typedef enum { GD_AFFINE_TRANSLATE = 0, diff --git a/ext/gd/libgd/gd_interpolation.c b/ext/gd/libgd/gd_interpolation.c index 3643535f2e..e34242bb73 100644 --- a/ext/gd/libgd/gd_interpolation.c +++ b/ext/gd/libgd/gd_interpolation.c @@ -1,4 +1,5 @@ /* + * The two pass scaling function is based on: * Filtered Image Rescaling * Based on Gems III * - Schumacher general filtered image rescaling @@ -13,6 +14,7 @@ * * Initial sources code is avaibable in the Gems Source Code Packages: * http://www.acm.org/pubs/tog/GraphicsGems/GGemsIII.tar.gz + * */ /* @@ -816,10 +818,6 @@ int getPixelInterpolated(gdImagePtr im, const double x, const double y, const in return -1; } - /* Default to full alpha */ - if (bgColor == -1) { - } - if (im->interpolation_id == GD_WEIGHTED4) { return getPixelInterpolateWeight(im, x, y, bgColor); } @@ -1711,6 +1709,7 @@ gdImagePtr gdImageRotateNearestNeighbour(gdImagePtr src, const float degrees, co gdImagePtr gdImageRotateGeneric(gdImagePtr src, const float degrees, const int bgColor) { float _angle = ((float) (-degrees / 180.0f) * (float)M_PI); + const int angle_rounded = (int)floor(degrees * 100); 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); @@ -1733,6 +1732,10 @@ gdImagePtr gdImageRotateGeneric(gdImagePtr src, const float degrees, const int b : 0; + if (bgColor < 0) { + return NULL; + } + dst = gdImageCreateTrueColor(new_width, new_height); if (!dst) { return NULL; diff --git a/ext/gmp/gmp.c b/ext/gmp/gmp.c index e3a3563aac..8835f05246 100644 --- a/ext/gmp/gmp.c +++ b/ext/gmp/gmp.c @@ -24,6 +24,9 @@ #include "php_ini.h" #include "php_gmp.h" #include "ext/standard/info.h" +#include "ext/standard/php_var.h" +#include "ext/standard/php_smart_str_public.h" +#include "zend_exceptions.h" #if HAVE_GMP @@ -34,16 +37,13 @@ #include "ext/standard/php_lcg.h" #define GMP_ABS(x) ((x) >= 0 ? (x) : -(x)) -/* True global resources - no need for thread safety here */ -static int le_gmp; - /* {{{ arginfo */ ZEND_BEGIN_ARG_INFO_EX(arginfo_gmp_init, 0, 0, 1) ZEND_ARG_INFO(0, number) ZEND_ARG_INFO(0, base) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_INFO(arginfo_gmp_intval, 0) +ZEND_BEGIN_ARG_INFO_EX(arginfo_gmp_intval, 0, 0, 1) ZEND_ARG_INFO(0, gmpnumber) ZEND_END_ARG_INFO() @@ -52,82 +52,35 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_gmp_strval, 0, 0, 1) ZEND_ARG_INFO(0, base) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_INFO(arginfo_gmp_add, 0) - ZEND_ARG_INFO(0, a) - ZEND_ARG_INFO(0, b) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO(arginfo_gmp_sub, 0) +ZEND_BEGIN_ARG_INFO_EX(arginfo_gmp_unary, 0, 0, 1) ZEND_ARG_INFO(0, a) - ZEND_ARG_INFO(0, b) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO(arginfo_gmp_mul, 0) - ZEND_ARG_INFO(0, a) - ZEND_ARG_INFO(0, b) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_gmp_div_qr, 0, 0, 2) - ZEND_ARG_INFO(0, a) - ZEND_ARG_INFO(0, b) - ZEND_ARG_INFO(0, round) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_INFO_EX(arginfo_gmp_div_r, 0, 0, 2) +ZEND_BEGIN_ARG_INFO_EX(arginfo_gmp_binary, 0, 0, 2) ZEND_ARG_INFO(0, a) ZEND_ARG_INFO(0, b) - ZEND_ARG_INFO(0, round) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_INFO_EX(arginfo_gmp_div_q, 0, 0, 2) +ZEND_BEGIN_ARG_INFO_EX(arginfo_gmp_div, 0, 0, 2) ZEND_ARG_INFO(0, a) ZEND_ARG_INFO(0, b) ZEND_ARG_INFO(0, round) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_INFO(arginfo_gmp_mod, 0) - ZEND_ARG_INFO(0, a) - ZEND_ARG_INFO(0, b) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO(arginfo_gmp_divexact, 0) - ZEND_ARG_INFO(0, a) - ZEND_ARG_INFO(0, b) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO(arginfo_gmp_neg, 0) - ZEND_ARG_INFO(0, a) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO(arginfo_gmp_abs, 0) - ZEND_ARG_INFO(0, a) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO(arginfo_gmp_fact, 0) - ZEND_ARG_INFO(0, a) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO(arginfo_gmp_pow, 0) +ZEND_BEGIN_ARG_INFO_EX(arginfo_gmp_pow, 0, 0, 2) ZEND_ARG_INFO(0, base) ZEND_ARG_INFO(0, exp) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_INFO(arginfo_gmp_powm, 0) +ZEND_BEGIN_ARG_INFO_EX(arginfo_gmp_powm, 0, 0, 3) ZEND_ARG_INFO(0, base) ZEND_ARG_INFO(0, exp) ZEND_ARG_INFO(0, mod) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_INFO(arginfo_gmp_sqrt, 0) - ZEND_ARG_INFO(0, a) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO(arginfo_gmp_sqrtrem, 0) - ZEND_ARG_INFO(0, a) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO(arginfo_gmp_perfect_square, 0) +ZEND_BEGIN_ARG_INFO_EX(arginfo_gmp_root, 0, 0, 2) ZEND_ARG_INFO(0, a) + ZEND_ARG_INFO(0, nth) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_gmp_prob_prime, 0, 0, 1) @@ -135,102 +88,26 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_gmp_prob_prime, 0, 0, 1) ZEND_ARG_INFO(0, reps) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_INFO(arginfo_gmp_gcd, 0) - ZEND_ARG_INFO(0, a) - ZEND_ARG_INFO(0, b) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO(arginfo_gmp_gcdext, 0) - ZEND_ARG_INFO(0, a) - ZEND_ARG_INFO(0, b) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO(arginfo_gmp_invert, 0) - ZEND_ARG_INFO(0, a) - ZEND_ARG_INFO(0, b) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO(arginfo_gmp_jacobi, 0) - ZEND_ARG_INFO(0, a) - ZEND_ARG_INFO(0, b) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO(arginfo_gmp_legendre, 0) - ZEND_ARG_INFO(0, a) - ZEND_ARG_INFO(0, b) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO(arginfo_gmp_cmp, 0) - ZEND_ARG_INFO(0, a) - ZEND_ARG_INFO(0, b) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO(arginfo_gmp_sign, 0) - ZEND_ARG_INFO(0, a) -ZEND_END_ARG_INFO() - ZEND_BEGIN_ARG_INFO_EX(arginfo_gmp_random, 0, 0, 0) ZEND_ARG_INFO(0, limiter) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_INFO(arginfo_gmp_and, 0) - ZEND_ARG_INFO(0, a) - ZEND_ARG_INFO(0, b) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO(arginfo_gmp_or, 0) - ZEND_ARG_INFO(0, a) - ZEND_ARG_INFO(0, b) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO(arginfo_gmp_com, 0) - ZEND_ARG_INFO(0, a) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO(arginfo_gmp_xor, 0) - ZEND_ARG_INFO(0, a) - ZEND_ARG_INFO(0, b) -ZEND_END_ARG_INFO() - ZEND_BEGIN_ARG_INFO_EX(arginfo_gmp_setbit, 0, 0, 2) - ZEND_ARG_INFO(1, a) + ZEND_ARG_INFO(0, a) ZEND_ARG_INFO(0, index) ZEND_ARG_INFO(0, set_clear) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_INFO(arginfo_gmp_clrbit, 0) - ZEND_ARG_INFO(1, a) - ZEND_ARG_INFO(0, index) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO(arginfo_gmp_testbit, 0) +ZEND_BEGIN_ARG_INFO_EX(arginfo_gmp_bit, 0, 0, 2) ZEND_ARG_INFO(0, a) ZEND_ARG_INFO(0, index) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_INFO(arginfo_gmp_popcount, 0) - ZEND_ARG_INFO(0, a) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO(arginfo_gmp_hamdist, 0) - ZEND_ARG_INFO(0, a) - ZEND_ARG_INFO(0, b) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO(arginfo_gmp_scan0, 0) - ZEND_ARG_INFO(0, a) - ZEND_ARG_INFO(0, start) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO(arginfo_gmp_scan1, 0) +ZEND_BEGIN_ARG_INFO_EX(arginfo_gmp_scan, 0, 0, 2) ZEND_ARG_INFO(0, a) ZEND_ARG_INFO(0, start) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_INFO(arginfo_gmp_nextprime, 0) - ZEND_ARG_INFO(0, a) -ZEND_END_ARG_INFO() - /* }}} */ ZEND_DECLARE_MODULE_GLOBALS(gmp) @@ -239,47 +116,49 @@ static ZEND_GINIT_FUNCTION(gmp); /* {{{ gmp_functions[] */ const zend_function_entry gmp_functions[] = { - ZEND_FE(gmp_init, arginfo_gmp_init) - ZEND_FE(gmp_intval, arginfo_gmp_intval) - ZEND_FE(gmp_strval, arginfo_gmp_strval) - ZEND_FE(gmp_add, arginfo_gmp_add) - ZEND_FE(gmp_sub, arginfo_gmp_sub) - ZEND_FE(gmp_mul, arginfo_gmp_mul) - ZEND_FE(gmp_div_qr, arginfo_gmp_div_qr) - ZEND_FE(gmp_div_q, arginfo_gmp_div_q) - ZEND_FE(gmp_div_r, arginfo_gmp_div_r) - ZEND_FALIAS(gmp_div, gmp_div_q, arginfo_gmp_div_q) - ZEND_FE(gmp_mod, arginfo_gmp_mod) - ZEND_FE(gmp_divexact, arginfo_gmp_divexact) - ZEND_FE(gmp_neg, arginfo_gmp_neg) - ZEND_FE(gmp_abs, arginfo_gmp_abs) - ZEND_FE(gmp_fact, arginfo_gmp_fact) - ZEND_FE(gmp_sqrt, arginfo_gmp_sqrt) - ZEND_FE(gmp_sqrtrem, arginfo_gmp_sqrtrem) - ZEND_FE(gmp_pow, arginfo_gmp_pow) - ZEND_FE(gmp_powm, arginfo_gmp_powm) - ZEND_FE(gmp_perfect_square, arginfo_gmp_perfect_square) - ZEND_FE(gmp_prob_prime, arginfo_gmp_prob_prime) - ZEND_FE(gmp_gcd, arginfo_gmp_gcd) - ZEND_FE(gmp_gcdext, arginfo_gmp_gcdext) - ZEND_FE(gmp_invert, arginfo_gmp_invert) - ZEND_FE(gmp_jacobi, arginfo_gmp_jacobi) - ZEND_FE(gmp_legendre, arginfo_gmp_legendre) - ZEND_FE(gmp_cmp, arginfo_gmp_cmp) - ZEND_FE(gmp_sign, arginfo_gmp_sign) - ZEND_FE(gmp_random, arginfo_gmp_random) - ZEND_FE(gmp_and, arginfo_gmp_and) - ZEND_FE(gmp_or, arginfo_gmp_or) - ZEND_FE(gmp_com, arginfo_gmp_com) - ZEND_FE(gmp_xor, arginfo_gmp_xor) - ZEND_FE(gmp_setbit, arginfo_gmp_setbit) - ZEND_FE(gmp_clrbit, arginfo_gmp_clrbit) - ZEND_FE(gmp_scan0, arginfo_gmp_scan0) - ZEND_FE(gmp_scan1, arginfo_gmp_scan1) - ZEND_FE(gmp_testbit,arginfo_gmp_testbit) - ZEND_FE(gmp_popcount, arginfo_gmp_popcount) - ZEND_FE(gmp_hamdist, arginfo_gmp_hamdist) - ZEND_FE(gmp_nextprime, arginfo_gmp_nextprime) + ZEND_FE(gmp_init, arginfo_gmp_init) + ZEND_FE(gmp_intval, arginfo_gmp_intval) + ZEND_FE(gmp_strval, arginfo_gmp_strval) + ZEND_FE(gmp_add, arginfo_gmp_binary) + ZEND_FE(gmp_sub, arginfo_gmp_binary) + ZEND_FE(gmp_mul, arginfo_gmp_binary) + ZEND_FE(gmp_div_qr, arginfo_gmp_div) + ZEND_FE(gmp_div_q, arginfo_gmp_div) + ZEND_FE(gmp_div_r, arginfo_gmp_div) + ZEND_FALIAS(gmp_div, gmp_div_q, arginfo_gmp_div) + ZEND_FE(gmp_mod, arginfo_gmp_binary) + ZEND_FE(gmp_divexact, arginfo_gmp_binary) + ZEND_FE(gmp_neg, arginfo_gmp_unary) + ZEND_FE(gmp_abs, arginfo_gmp_unary) + ZEND_FE(gmp_fact, arginfo_gmp_unary) + ZEND_FE(gmp_sqrt, arginfo_gmp_unary) + ZEND_FE(gmp_sqrtrem, arginfo_gmp_unary) + ZEND_FE(gmp_root, arginfo_gmp_root) + ZEND_FE(gmp_rootrem, arginfo_gmp_root) + ZEND_FE(gmp_pow, arginfo_gmp_pow) + ZEND_FE(gmp_powm, arginfo_gmp_powm) + ZEND_FE(gmp_perfect_square, arginfo_gmp_unary) + ZEND_FE(gmp_prob_prime, arginfo_gmp_prob_prime) + ZEND_FE(gmp_gcd, arginfo_gmp_binary) + ZEND_FE(gmp_gcdext, arginfo_gmp_binary) + ZEND_FE(gmp_invert, arginfo_gmp_binary) + ZEND_FE(gmp_jacobi, arginfo_gmp_binary) + ZEND_FE(gmp_legendre, arginfo_gmp_binary) + ZEND_FE(gmp_cmp, arginfo_gmp_binary) + ZEND_FE(gmp_sign, arginfo_gmp_unary) + ZEND_FE(gmp_random, arginfo_gmp_random) + ZEND_FE(gmp_and, arginfo_gmp_binary) + ZEND_FE(gmp_or, arginfo_gmp_binary) + ZEND_FE(gmp_com, arginfo_gmp_unary) + ZEND_FE(gmp_xor, arginfo_gmp_binary) + ZEND_FE(gmp_setbit, arginfo_gmp_setbit) + ZEND_FE(gmp_clrbit, arginfo_gmp_bit) + ZEND_FE(gmp_testbit, arginfo_gmp_bit) + ZEND_FE(gmp_scan0, arginfo_gmp_scan) + ZEND_FE(gmp_scan1, arginfo_gmp_scan) + ZEND_FE(gmp_popcount, arginfo_gmp_unary) + ZEND_FE(gmp_hamdist, arginfo_gmp_binary) + ZEND_FE(gmp_nextprime, arginfo_gmp_unary) PHP_FE_END }; /* }}} */ @@ -308,22 +187,151 @@ zend_module_entry gmp_module_entry = { ZEND_GET_MODULE(gmp) #endif -static void _php_gmpnum_free(zend_rsrc_list_entry *rsrc TSRMLS_DC); +zend_class_entry *gmp_ce; +static zend_object_handlers gmp_object_handlers; + +typedef struct _gmp_object { + zend_object std; + mpz_t num; +} gmp_object; -#define GMP_RESOURCE_NAME "GMP integer" +typedef struct _gmp_temp { + mpz_t num; + zend_bool is_used; +} gmp_temp_t; #define GMP_ROUND_ZERO 0 #define GMP_ROUND_PLUSINF 1 #define GMP_ROUND_MINUSINF 2 +#define GMP_42_OR_NEWER \ + ((__GNU_MP_VERSION >= 5) || (__GNU_MP_VERSION >= 4 && __GNU_MP_VERSION_MINOR >= 2)) + /* The maximum base for input and output conversions is 62 from GMP 4.2 * onwards. */ -#if (__GNU_MP_VERSION >= 5) || (__GNU_MP_VERSION >= 4 && __GNU_MP_VERSION_MINOR >= 2) +#if GMP_42_OR_NEWER # define MAX_BASE 62 #else # define MAX_BASE 36 #endif +#define IS_GMP(zval) \ + (Z_TYPE_P(zval) == IS_OBJECT && instanceof_function(Z_OBJCE_P(zval), gmp_ce TSRMLS_CC)) + +#define GET_GMP_FROM_ZVAL(zval) \ + (((gmp_object *) zend_object_store_get_object((zval) TSRMLS_CC))->num) + +/* The FETCH_GMP_ZVAL_* family of macros is used to fetch a gmp number + * (mpz_ptr) from a zval. If the zval is not a GMP instance, then we + * try to convert the value to a temporary gmp number using convert_to_gmp. + * This temporary number is stored in the temp argument, which is of type + * gmp_temp_t. This temporary value needs to be freed lateron using the + * FREE_GMP_TEMP macro. + * + * If the conversion to a gmp number fails, the macros return false. + * The _DEP / _DEP_DEP variants additionally free the temporary values + * passed in the last / last two arguments. + * + * If one zval can sometimes be fetched as a long you have to set the + * is_used member of the corresponding gmp_temp_t value to 0, otherwise + * the FREE_GMP_TEMP and *_DEP macros will not work properly. + * + * The three FETCH_GMP_ZVAL_* macros below are mostly copy & paste code + * as I couldn't find a way to combine them. + */ + +#define FREE_GMP_TEMP(temp) \ + if (temp.is_used) { \ + mpz_clear(temp.num); \ + } + +#define FETCH_GMP_ZVAL_DEP_DEP(gmpnumber, zval, temp, dep1, dep2) \ +if (IS_GMP(zval)) { \ + gmpnumber = GET_GMP_FROM_ZVAL(zval); \ + temp.is_used = 0; \ +} else { \ + mpz_init(temp.num); \ + if (convert_to_gmp(temp.num, zval, 0 TSRMLS_CC) == FAILURE) { \ + mpz_clear(temp.num); \ + FREE_GMP_TEMP(dep1); \ + FREE_GMP_TEMP(dep2); \ + RETURN_FALSE; \ + } \ + temp.is_used = 1; \ + gmpnumber = temp.num; \ +} + +#define FETCH_GMP_ZVAL_DEP(gmpnumber, zval, temp, dep) \ +if (IS_GMP(zval)) { \ + gmpnumber = GET_GMP_FROM_ZVAL(zval); \ + temp.is_used = 0; \ +} else { \ + mpz_init(temp.num); \ + if (convert_to_gmp(temp.num, zval, 0 TSRMLS_CC) == FAILURE) { \ + mpz_clear(temp.num); \ + FREE_GMP_TEMP(dep); \ + RETURN_FALSE; \ + } \ + temp.is_used = 1; \ + gmpnumber = temp.num; \ +} + +#define FETCH_GMP_ZVAL(gmpnumber, zval, temp) \ +if (IS_GMP(zval)) { \ + gmpnumber = GET_GMP_FROM_ZVAL(zval); \ + temp.is_used = 0; \ +} else { \ + mpz_init(temp.num); \ + if (convert_to_gmp(temp.num, zval, 0 TSRMLS_CC) == FAILURE) { \ + mpz_clear(temp.num); \ + RETURN_FALSE; \ + } \ + temp.is_used = 1; \ + gmpnumber = temp.num; \ +} + +#define INIT_GMP_RETVAL(gmpnumber) \ + gmp_create_ex(return_value, &gmpnumber TSRMLS_CC) + +static void gmp_strval(zval *result, mpz_t gmpnum, long base); +static int convert_to_gmp(mpz_t gmpnumber, zval *val, int base TSRMLS_DC); +static void gmp_cmp(zval *return_value, zval *a_arg, zval *b_arg TSRMLS_DC); + +/* + * The gmp_*_op functions provide an implementation for several common types + * of GMP functions. The gmp_zval_(unary|binary)_*_op functions have to be manually + * passed zvals to work on, whereas the gmp_(unary|binary)_*_op macros already + * include parameter parsing. + */ +typedef void (*gmp_unary_op_t)(mpz_ptr, mpz_srcptr); +typedef int (*gmp_unary_opl_t)(mpz_srcptr); + +typedef void (*gmp_unary_ui_op_t)(mpz_ptr, unsigned long); + +typedef void (*gmp_binary_op_t)(mpz_ptr, mpz_srcptr, mpz_srcptr); +typedef int (*gmp_binary_opl_t)(mpz_srcptr, mpz_srcptr); + +typedef void (*gmp_binary_ui_op_t)(mpz_ptr, mpz_srcptr, unsigned long); +typedef void (*gmp_binary_op2_t)(mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr); +typedef void (*gmp_binary_ui_op2_t)(mpz_ptr, mpz_ptr, mpz_srcptr, unsigned long); + +static inline void gmp_zval_binary_ui_op(zval *return_value, zval *a_arg, zval *b_arg, gmp_binary_op_t gmp_op, gmp_binary_ui_op_t gmp_ui_op, int check_b_zero TSRMLS_DC); +static inline void gmp_zval_binary_ui_op2(zval *return_value, zval *a_arg, zval *b_arg, gmp_binary_op2_t gmp_op, gmp_binary_ui_op2_t gmp_ui_op, int check_b_zero TSRMLS_DC); +static inline void gmp_zval_unary_op(zval *return_value, zval *a_arg, gmp_unary_op_t gmp_op TSRMLS_DC); +static inline void gmp_zval_unary_ui_op(zval *return_value, zval *a_arg, gmp_unary_ui_op_t gmp_op TSRMLS_DC); + +/* Binary operations */ +#define gmp_binary_ui_op(op, uop) _gmp_binary_ui_op(INTERNAL_FUNCTION_PARAM_PASSTHRU, op, uop, 0) +#define gmp_binary_op(op) _gmp_binary_ui_op(INTERNAL_FUNCTION_PARAM_PASSTHRU, op, NULL, 0) +#define gmp_binary_opl(op) _gmp_binary_opl(INTERNAL_FUNCTION_PARAM_PASSTHRU, op) +#define gmp_binary_ui_op_no_zero(op, uop) \ + _gmp_binary_ui_op(INTERNAL_FUNCTION_PARAM_PASSTHRU, op, uop, 1) + +/* Unary operations */ +#define gmp_unary_op(op) _gmp_unary_op(INTERNAL_FUNCTION_PARAM_PASSTHRU, op) +#define gmp_unary_opl(op) _gmp_unary_opl(INTERNAL_FUNCTION_PARAM_PASSTHRU, op) +#define gmp_unary_ui_op(op) _gmp_unary_ui_op(INTERNAL_FUNCTION_PARAM_PASSTHRU, op) + /* {{{ gmp_emalloc */ static void *gmp_emalloc(size_t size) @@ -348,6 +356,293 @@ static void gmp_efree(void *ptr, size_t size) } /* }}} */ +static inline long gmp_get_long(zval *zv) /* {{{ */ +{ + if (Z_TYPE_P(zv) == IS_LONG) { + return Z_LVAL_P(zv); + } else { + zval tmp_zv; + MAKE_COPY_ZVAL(&zv, &tmp_zv); + convert_to_long(&tmp_zv); + return Z_LVAL(tmp_zv); + } +} +/* }}} */ + +static void gmp_free_object_storage(gmp_object *intern TSRMLS_DC) /* {{{ */ +{ + mpz_clear(intern->num); + + zend_object_std_dtor(&intern->std TSRMLS_CC); + efree(intern); +} +/* }}} */ + +static inline zend_object_value gmp_create_object_ex(zend_class_entry *ce, mpz_ptr *gmpnum_target TSRMLS_DC) /* {{{ */ +{ + zend_object_value retval; + gmp_object *intern = emalloc(sizeof(gmp_object)); + + zend_object_std_init(&intern->std, ce TSRMLS_CC); + object_properties_init(&intern->std, ce); + + mpz_init(intern->num); + *gmpnum_target = intern->num; + + retval.handle = zend_objects_store_put( + intern, (zend_objects_store_dtor_t) zend_objects_destroy_object, + (zend_objects_free_object_storage_t) gmp_free_object_storage, + NULL TSRMLS_CC + ); + retval.handlers = &gmp_object_handlers; + + return retval; +} +/* }}} */ + +static zend_object_value gmp_create_object(zend_class_entry *ce TSRMLS_DC) /* {{{ */ +{ + mpz_ptr gmpnum_dummy; + return gmp_create_object_ex(ce, &gmpnum_dummy TSRMLS_CC); +} +/* }}} */ + +static inline void gmp_create_ex(zval *target, mpz_ptr *gmpnum_target TSRMLS_DC) /* {{{ */ +{ + Z_TYPE_P(target) = IS_OBJECT; + Z_OBJVAL_P(target) = gmp_create_object_ex(gmp_ce, gmpnum_target TSRMLS_CC); +} +/* }}} */ + +static zval *gmp_create(mpz_ptr *gmpnum_target TSRMLS_DC) /* {{{ */ +{ + zval *obj; + MAKE_STD_ZVAL(obj); + gmp_create_ex(obj, gmpnum_target TSRMLS_CC); + return obj; +} +/* }}} */ + +static int gmp_cast_object(zval *readobj, zval *writeobj, int type TSRMLS_DC) /* {{{ */ +{ + mpz_ptr gmpnum; + switch (type) { + case IS_STRING: + gmpnum = GET_GMP_FROM_ZVAL(readobj); + INIT_PZVAL(writeobj); + gmp_strval(writeobj, gmpnum, 10); + return SUCCESS; + case IS_LONG: + gmpnum = GET_GMP_FROM_ZVAL(readobj); + INIT_PZVAL(writeobj); + ZVAL_LONG(writeobj, mpz_get_si(gmpnum)); + return SUCCESS; + case IS_DOUBLE: + gmpnum = GET_GMP_FROM_ZVAL(readobj); + INIT_PZVAL(writeobj); + ZVAL_DOUBLE(writeobj, mpz_get_d(gmpnum)); + return SUCCESS; + default: + return FAILURE; + } +} +/* }}} */ + +static HashTable *gmp_get_debug_info(zval *obj, int *is_temp TSRMLS_DC) /* {{{ */ +{ + HashTable *ht, *props = zend_std_get_properties(obj TSRMLS_CC); + mpz_ptr gmpnum = GET_GMP_FROM_ZVAL(obj); + zval *zv; + + *is_temp = 1; + ALLOC_HASHTABLE(ht); + ZEND_INIT_SYMTABLE_EX(ht, zend_hash_num_elements(props) + 1, 0); + zend_hash_copy(ht, props, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *)); + + MAKE_STD_ZVAL(zv); + gmp_strval(zv, gmpnum, 10); + zend_hash_update(ht, "num", sizeof("num"), &zv, sizeof(zval *), NULL); + + return ht; +} +/* }}} */ + +static zend_object_value gmp_clone_obj(zval *obj TSRMLS_DC) /* {{{ */ +{ + gmp_object *old_object = zend_object_store_get_object(obj TSRMLS_CC); + zend_object_value new_object_val = gmp_create_object(Z_OBJCE_P(obj) TSRMLS_CC); + gmp_object *new_object = zend_object_store_get_object_by_handle( + new_object_val.handle TSRMLS_CC + ); + + zend_objects_clone_members( + &new_object->std, new_object_val, + &old_object->std, Z_OBJ_HANDLE_P(obj) TSRMLS_CC + ); + + mpz_set(new_object->num, old_object->num); + + return new_object_val; +} +/* }}} */ + +static void shift_operator_helper(gmp_binary_ui_op_t op, zval *return_value, zval *op1, zval *op2 TSRMLS_DC) { + zval op2_copy; + if (Z_TYPE_P(op2) != IS_LONG) { + op2_copy = *op2; + zval_copy_ctor(&op2_copy); + convert_to_long(&op2_copy); + op2 = &op2_copy; + } + + if (Z_LVAL_P(op2) < 0) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Shift cannot be negative"); + RETVAL_FALSE; + } else { + mpz_ptr gmpnum_op, gmpnum_result; + gmp_temp_t temp; + + FETCH_GMP_ZVAL(gmpnum_op, op1, temp); + INIT_GMP_RETVAL(gmpnum_result); + op(gmpnum_result, gmpnum_op, (unsigned long) Z_LVAL_P(op2)); + FREE_GMP_TEMP(temp); + } +} + +#define DO_BINARY_UI_OP_EX(op, uop, check_b_zero) \ + gmp_zval_binary_ui_op( \ + result, op1, op2, op, (gmp_binary_ui_op_t) uop, \ + check_b_zero TSRMLS_CC \ + ); \ + return SUCCESS; + +#define DO_BINARY_UI_OP(op) DO_BINARY_UI_OP_EX(op, op ## _ui, 0) +#define DO_BINARY_OP(op) DO_BINARY_UI_OP_EX(op, NULL, 0) + +#define DO_UNARY_OP(op) \ + gmp_zval_unary_op(result, op1, op TSRMLS_CC); \ + return SUCCESS; + +static int gmp_do_operation(zend_uchar opcode, zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */ +{ + switch (opcode) { + case ZEND_ADD: + DO_BINARY_UI_OP(mpz_add); + case ZEND_SUB: + DO_BINARY_UI_OP(mpz_sub); + case ZEND_MUL: + DO_BINARY_UI_OP(mpz_mul); + case ZEND_DIV: + DO_BINARY_UI_OP_EX(mpz_tdiv_q, mpz_tdiv_q_ui, 1); + case ZEND_MOD: + DO_BINARY_UI_OP_EX(mpz_mod, mpz_mod_ui, 1); + case ZEND_SL: + shift_operator_helper(mpz_mul_2exp, result, op1, op2 TSRMLS_CC); + return SUCCESS; + case ZEND_SR: + shift_operator_helper(mpz_fdiv_q_2exp, result, op1, op2 TSRMLS_CC); + return SUCCESS; + case ZEND_BW_OR: + DO_BINARY_OP(mpz_ior); + case ZEND_BW_AND: + DO_BINARY_OP(mpz_and); + case ZEND_BW_XOR: + DO_BINARY_OP(mpz_xor); + case ZEND_BW_NOT: + DO_UNARY_OP(mpz_com); + + default: + return FAILURE; + } +} +/* }}} */ + +static int gmp_compare(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */ +{ + gmp_cmp(result, op1, op2 TSRMLS_CC); + if (Z_TYPE_P(result) == IS_BOOL) { + ZVAL_LONG(result, 1); + } + return SUCCESS; +} +/* }}} */ + +static int gmp_serialize(zval *object, unsigned char **buffer, zend_uint *buf_len, zend_serialize_data *data TSRMLS_DC) /* {{{ */ +{ + mpz_ptr gmpnum = GET_GMP_FROM_ZVAL(object); + smart_str buf = {0}; + zval zv, *zv_ptr = &zv; + php_serialize_data_t *serialize_data = (php_serialize_data_t *) data; + + PHP_VAR_SERIALIZE_INIT(*serialize_data); + + INIT_PZVAL(zv_ptr); + + gmp_strval(zv_ptr, gmpnum, 10); + php_var_serialize(&buf, &zv_ptr, serialize_data TSRMLS_CC); + zval_dtor(zv_ptr); + + Z_ARRVAL_P(zv_ptr) = zend_std_get_properties(object TSRMLS_CC); + Z_TYPE_P(zv_ptr) = IS_ARRAY; + php_var_serialize(&buf, &zv_ptr, serialize_data TSRMLS_CC); + + PHP_VAR_SERIALIZE_DESTROY(*serialize_data); + + *buffer = (unsigned char *) buf.c; + *buf_len = buf.len; + + return SUCCESS; +} +/* }}} */ + +static int gmp_unserialize(zval **object, zend_class_entry *ce, const unsigned char *buf, zend_uint buf_len, zend_unserialize_data *data TSRMLS_DC) /* {{{ */ +{ + mpz_ptr gmpnum; + const unsigned char *p, *max; + zval zv, *zv_ptr = &zv; + int retval = FAILURE; + php_unserialize_data_t *unserialize_data = (php_unserialize_data_t *) data; + + PHP_VAR_UNSERIALIZE_INIT(*unserialize_data); + + gmp_create_ex(*object, &gmpnum TSRMLS_CC); + + p = buf; + max = buf + buf_len; + + INIT_ZVAL(zv); + if (!php_var_unserialize(&zv_ptr, &p, max, unserialize_data TSRMLS_CC) + || Z_TYPE_P(zv_ptr) != IS_STRING + || convert_to_gmp(gmpnum, zv_ptr, 10 TSRMLS_CC) == FAILURE + ) { + zend_throw_exception(NULL, "Could not unserialize number", 0 TSRMLS_CC); + goto exit; + } + zval_dtor(&zv); + + INIT_ZVAL(zv); + if (!php_var_unserialize(&zv_ptr, &p, max, unserialize_data TSRMLS_CC) + || Z_TYPE_P(zv_ptr) != IS_ARRAY + ) { + zend_throw_exception(NULL, "Could not unserialize properties", 0 TSRMLS_CC); + goto exit; + } + + if (zend_hash_num_elements(Z_ARRVAL_P(zv_ptr)) != 0) { + zend_hash_copy( + zend_std_get_properties(*object TSRMLS_CC), Z_ARRVAL_P(zv_ptr), + (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *) + ); + } + + retval = SUCCESS; +exit: + zval_dtor(&zv); + PHP_VAR_UNSERIALIZE_DESTROY(*unserialize_data); + return retval; +} +/* }}} */ + /* {{{ ZEND_GINIT_FUNCTION */ static ZEND_GINIT_FUNCTION(gmp) @@ -358,9 +653,22 @@ static ZEND_GINIT_FUNCTION(gmp) /* {{{ ZEND_MINIT_FUNCTION */ -ZEND_MODULE_STARTUP_D(gmp) +ZEND_MINIT_FUNCTION(gmp) { - le_gmp = zend_register_list_destructors_ex(_php_gmpnum_free, NULL, GMP_RESOURCE_NAME, module_number); + zend_class_entry tmp_ce; + INIT_CLASS_ENTRY(tmp_ce, "GMP", NULL); + gmp_ce = zend_register_internal_class(&tmp_ce TSRMLS_CC); + gmp_ce->create_object = gmp_create_object; + gmp_ce->serialize = gmp_serialize; + gmp_ce->unserialize = gmp_unserialize; + + memcpy(&gmp_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); + gmp_object_handlers.cast_object = gmp_cast_object; + gmp_object_handlers.get_debug_info = gmp_get_debug_info; + gmp_object_handlers.clone_obj = gmp_clone_obj; + gmp_object_handlers.do_operation = gmp_do_operation; + gmp_object_handlers.compare = gmp_compare; + REGISTER_LONG_CONSTANT("GMP_ROUND_ZERO", GMP_ROUND_ZERO, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("GMP_ROUND_PLUSINF", GMP_ROUND_PLUSINF, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("GMP_ROUND_MINUSINF", GMP_ROUND_MINUSINF, CONST_CS | CONST_PERSISTENT); @@ -403,246 +711,211 @@ ZEND_MODULE_INFO_D(gmp) } /* }}} */ -/* Fetch zval to be GMP number. - Initially, zval can be also number or string */ -#define FETCH_GMP_ZVAL(gmpnumber, zval, tmp_resource) \ -if (Z_TYPE_PP(zval) == IS_RESOURCE) { \ - ZEND_FETCH_RESOURCE(gmpnumber, mpz_t *, zval, -1, GMP_RESOURCE_NAME, le_gmp); \ - tmp_resource = 0; \ -} else { \ - if (convert_to_gmp(&gmpnumber, zval, 0 TSRMLS_CC) == FAILURE) { \ - RETURN_FALSE; \ - } \ - tmp_resource = ZEND_REGISTER_RESOURCE(NULL, gmpnumber, le_gmp); \ -} - -#define FREE_GMP_TEMP(tmp_resource) \ - if(tmp_resource) { \ - zend_list_delete(tmp_resource); \ - } - - -/* create a new initialized GMP number */ -#define INIT_GMP_NUM(gmpnumber) { gmpnumber=emalloc(sizeof(mpz_t)); mpz_init(*gmpnumber); } -#define FREE_GMP_NUM(gmpnumber) { mpz_clear(*gmpnumber); efree(gmpnumber); } /* {{{ convert_to_gmp * Convert zval to be gmp number */ -static int convert_to_gmp(mpz_t * *gmpnumber, zval **val, int base TSRMLS_DC) +static int convert_to_gmp(mpz_t gmpnumber, zval *val, int base TSRMLS_DC) { - int ret = 0; - int skip_lead = 0; - - *gmpnumber = emalloc(sizeof(mpz_t)); - - switch (Z_TYPE_PP(val)) { + switch (Z_TYPE_P(val)) { case IS_LONG: case IS_BOOL: - case IS_CONSTANT: - { - convert_to_long_ex(val); - mpz_init_set_si(**gmpnumber, Z_LVAL_PP(val)); - } - break; - case IS_STRING: - { - char *numstr = Z_STRVAL_PP(val); - - if (Z_STRLEN_PP(val) > 2) { - if (numstr[0] == '0') { - if (numstr[1] == 'x' || numstr[1] == 'X') { - base = 16; - skip_lead = 1; - } else if (base != 16 && (numstr[1] == 'b' || numstr[1] == 'B')) { - base = 2; - skip_lead = 1; - } + case IS_CONSTANT: { + mpz_set_si(gmpnumber, gmp_get_long(val)); + return SUCCESS; + } + case IS_STRING: { + char *numstr = Z_STRVAL_P(val); + int skip_lead = 0; + + if (Z_STRLEN_P(val) > 2) { + if (numstr[0] == '0') { + if (numstr[1] == 'x' || numstr[1] == 'X') { + base = 16; + skip_lead = 1; + } else if (base != 16 && (numstr[1] == 'b' || numstr[1] == 'B')) { + base = 2; + skip_lead = 1; } } - ret = mpz_init_set_str(**gmpnumber, (skip_lead ? &numstr[2] : numstr), base); } - break; - default: - php_error_docref(NULL TSRMLS_CC, E_WARNING,"Unable to convert variable to GMP - wrong type"); - efree(*gmpnumber); - return FAILURE; - } - if (ret) { - FREE_GMP_NUM(*gmpnumber); + return mpz_set_str(gmpnumber, (skip_lead ? &numstr[2] : numstr), base); + } + default: + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to convert variable to GMP - wrong type"); return FAILURE; } - - return SUCCESS; } /* }}} */ -/* {{{ typedefs - */ -typedef void (*gmp_unary_op_t)(mpz_ptr, mpz_srcptr); -typedef int (*gmp_unary_opl_t)(mpz_srcptr); +static void gmp_strval(zval *result, mpz_t gmpnum, long base) /* {{{ */ +{ + int num_len; + char *out_string; -typedef void (*gmp_unary_ui_op_t)(mpz_ptr, unsigned long); + num_len = mpz_sizeinbase(gmpnum, abs(base)); + if (mpz_sgn(gmpnum) < 0) { + num_len++; + } -typedef void (*gmp_binary_op_t)(mpz_ptr, mpz_srcptr, mpz_srcptr); -typedef int (*gmp_binary_opl_t)(mpz_srcptr, mpz_srcptr); + out_string = emalloc(num_len + 1); + mpz_get_str(out_string, base, gmpnum); + + /* + * From GMP documentation for mpz_sizeinbase(): + * The returned value will be exact or 1 too big. If base is a power of + * 2, the returned value will always be exact. + * + * So let's check to see if we already have a \0 byte... + */ + + if (out_string[num_len - 1] == '\0') { + num_len--; + } else { + out_string[num_len] = '\0'; + } -typedef unsigned long (*gmp_binary_ui_op_t)(mpz_ptr, mpz_srcptr, unsigned long); -typedef void (*gmp_binary_op2_t)(mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr); -typedef unsigned long (*gmp_binary_ui_op2_t)(mpz_ptr, mpz_ptr, mpz_srcptr, unsigned long); + ZVAL_STRINGL(result, out_string, num_len, 0); +} /* }}} */ -#define gmp_zval_binary_ui_op(r, a, b, o, u) gmp_zval_binary_ui_op_ex(r, a, b, o, u, 0, 0, 0 TSRMLS_CC) -#define gmp_zval_binary_ui_op2(r, a, b, o, u) gmp_zval_binary_ui_op2_ex(r, a, b, o, u, 0, 0, 0 TSRMLS_CC) +static void gmp_cmp(zval *return_value, zval *a_arg, zval *b_arg TSRMLS_DC) /* {{{ */ +{ + mpz_ptr gmpnum_a, gmpnum_b; + gmp_temp_t temp_a, temp_b; + zend_bool use_si = 0; + long res; -#define gmp_binary_ui_op(op, uop) _gmp_binary_ui_op(INTERNAL_FUNCTION_PARAM_PASSTHRU, op, uop) -#define gmp_binary_op(op) _gmp_binary_ui_op(INTERNAL_FUNCTION_PARAM_PASSTHRU, op, NULL) -#define gmp_binary_opl(op) _gmp_binary_opl(INTERNAL_FUNCTION_PARAM_PASSTHRU, op) + FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a); -/* Unary operations */ -#define gmp_unary_op(op) _gmp_unary_op(INTERNAL_FUNCTION_PARAM_PASSTHRU, op) -#define gmp_unary_opl(op) _gmp_unary_opl(INTERNAL_FUNCTION_PARAM_PASSTHRU, op) -#define gmp_unary_ui_op(op) _gmp_unary_ui_op(INTERNAL_FUNCTION_PARAM_PASSTHRU, op) + if (Z_TYPE_P(b_arg) == IS_LONG) { + use_si = 1; + temp_b.is_used = 0; + } else { + FETCH_GMP_ZVAL_DEP(gmpnum_b, b_arg, temp_b, temp_a); + } -/* {{{ gmp_zval_binary_ui_op_ex + if (use_si) { + res = mpz_cmp_si(gmpnum_a, Z_LVAL_P(b_arg)); + } else { + res = mpz_cmp(gmpnum_a, gmpnum_b); + } + + FREE_GMP_TEMP(temp_a); + FREE_GMP_TEMP(temp_b); + + RETURN_LONG(res); +} +/* }}} */ + +/* {{{ gmp_zval_binary_ui_op Execute GMP binary operation. - May return GMP resource or long if operation allows this */ -static inline void gmp_zval_binary_ui_op_ex(zval *return_value, zval **a_arg, zval **b_arg, gmp_binary_op_t gmp_op, gmp_binary_ui_op_t gmp_ui_op, int allow_ui_return, int check_b_zero, int use_sign TSRMLS_DC) +static inline void gmp_zval_binary_ui_op(zval *return_value, zval *a_arg, zval *b_arg, gmp_binary_op_t gmp_op, gmp_binary_ui_op_t gmp_ui_op, int check_b_zero TSRMLS_DC) { - mpz_t *gmpnum_a, *gmpnum_b, *gmpnum_result; - unsigned long long_result = 0; + mpz_ptr gmpnum_a, gmpnum_b, gmpnum_result; int use_ui = 0; - int arga_tmp = 0, argb_tmp = 0; + gmp_temp_t temp_a, temp_b; - FETCH_GMP_ZVAL(gmpnum_a, a_arg, arga_tmp); + FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a); - if (gmp_ui_op && Z_TYPE_PP(b_arg) == IS_LONG && Z_LVAL_PP(b_arg) >= 0) { + if (gmp_ui_op && Z_TYPE_P(b_arg) == IS_LONG && Z_LVAL_P(b_arg) >= 0) { use_ui = 1; + temp_b.is_used = 0; } else { - FETCH_GMP_ZVAL(gmpnum_b, b_arg, argb_tmp); + FETCH_GMP_ZVAL_DEP(gmpnum_b, b_arg, temp_b, temp_a); } - if(check_b_zero) { + if (check_b_zero) { int b_is_zero = 0; - if(use_ui) { - b_is_zero = (Z_LVAL_PP(b_arg) == 0); + if (use_ui) { + b_is_zero = (Z_LVAL_P(b_arg) == 0); } else { - b_is_zero = !mpz_cmp_ui(*gmpnum_b, 0); + b_is_zero = !mpz_cmp_ui(gmpnum_b, 0); } - if(b_is_zero) { + if (b_is_zero) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Zero operand not allowed"); - FREE_GMP_TEMP(arga_tmp); - FREE_GMP_TEMP(argb_tmp); + FREE_GMP_TEMP(temp_a); + FREE_GMP_TEMP(temp_b); RETURN_FALSE; } } - INIT_GMP_NUM(gmpnum_result); + INIT_GMP_RETVAL(gmpnum_result); - if (use_ui && gmp_ui_op) { - if (allow_ui_return) { - long_result = gmp_ui_op(*gmpnum_result, *gmpnum_a, (unsigned long)Z_LVAL_PP(b_arg)); - if (use_sign && mpz_sgn(*gmpnum_a) == -1) { - long_result = -long_result; - } - } else { - gmp_ui_op(*gmpnum_result, *gmpnum_a, (unsigned long)Z_LVAL_PP(b_arg)); - } + if (use_ui) { + gmp_ui_op(gmpnum_result, gmpnum_a, (unsigned long) Z_LVAL_P(b_arg)); } else { - gmp_op(*gmpnum_result, *gmpnum_a, *gmpnum_b); + gmp_op(gmpnum_result, gmpnum_a, gmpnum_b); } - FREE_GMP_TEMP(arga_tmp); - FREE_GMP_TEMP(argb_tmp); - - if (use_ui && allow_ui_return) { - FREE_GMP_NUM(gmpnum_result); - RETURN_LONG((long)long_result); - } else { - ZEND_REGISTER_RESOURCE(return_value, gmpnum_result, le_gmp); - } + FREE_GMP_TEMP(temp_a); + FREE_GMP_TEMP(temp_b); } /* }}} */ -/* {{{ gmp_zval_binary_ui_op2_ex +/* {{{ gmp_zval_binary_ui_op2 Execute GMP binary operation which returns 2 values. - May return GMP resources or longs if operation allows this. */ -static inline void gmp_zval_binary_ui_op2_ex(zval *return_value, zval **a_arg, zval **b_arg, gmp_binary_op2_t gmp_op, gmp_binary_ui_op2_t gmp_ui_op, int allow_ui_return, int check_b_zero TSRMLS_DC) +static inline void gmp_zval_binary_ui_op2(zval *return_value, zval *a_arg, zval *b_arg, gmp_binary_op2_t gmp_op, gmp_binary_ui_op2_t gmp_ui_op, int check_b_zero TSRMLS_DC) { - mpz_t *gmpnum_a, *gmpnum_b, *gmpnum_result1, *gmpnum_result2; - zval r; + mpz_ptr gmpnum_a, gmpnum_b, gmpnum_result1, gmpnum_result2; int use_ui = 0; - unsigned long long_result = 0; - int arga_tmp = 0, argb_tmp = 0; + gmp_temp_t temp_a, temp_b; - FETCH_GMP_ZVAL(gmpnum_a, a_arg, arga_tmp); + FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a); - if (gmp_ui_op && Z_TYPE_PP(b_arg) == IS_LONG && Z_LVAL_PP(b_arg) >= 0) { + if (gmp_ui_op && Z_TYPE_P(b_arg) == IS_LONG && Z_LVAL_P(b_arg) >= 0) { /* use _ui function */ use_ui = 1; + temp_b.is_used = 0; } else { - FETCH_GMP_ZVAL(gmpnum_b, b_arg, argb_tmp); + FETCH_GMP_ZVAL_DEP(gmpnum_b, b_arg, temp_b, temp_a); } - if(check_b_zero) { + if (check_b_zero) { int b_is_zero = 0; - if(use_ui) { - b_is_zero = (Z_LVAL_PP(b_arg) == 0); + if (use_ui) { + b_is_zero = (Z_LVAL_P(b_arg) == 0); } else { - b_is_zero = !mpz_cmp_ui(*gmpnum_b, 0); + b_is_zero = !mpz_cmp_ui(gmpnum_b, 0); } - if(b_is_zero) { + if (b_is_zero) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Zero operand not allowed"); - FREE_GMP_TEMP(arga_tmp); - FREE_GMP_TEMP(argb_tmp); + FREE_GMP_TEMP(temp_a); + FREE_GMP_TEMP(temp_b); RETURN_FALSE; } } - INIT_GMP_NUM(gmpnum_result1); - INIT_GMP_NUM(gmpnum_result2); + array_init(return_value); + add_index_zval(return_value, 0, gmp_create(&gmpnum_result1 TSRMLS_CC)); + add_index_zval(return_value, 1, gmp_create(&gmpnum_result2 TSRMLS_CC)); - if (use_ui && gmp_ui_op) { - if (allow_ui_return) { - long_result = gmp_ui_op(*gmpnum_result1, *gmpnum_result2, *gmpnum_a, (unsigned long)Z_LVAL_PP(b_arg)); - } else { - gmp_ui_op(*gmpnum_result1, *gmpnum_result2, *gmpnum_a, (unsigned long)Z_LVAL_PP(b_arg)); - } + if (use_ui) { + gmp_ui_op(gmpnum_result1, gmpnum_result2, gmpnum_a, (unsigned long) Z_LVAL_P(b_arg)); } else { - gmp_op(*gmpnum_result1, *gmpnum_result2, *gmpnum_a, *gmpnum_b); + gmp_op(gmpnum_result1, gmpnum_result2, gmpnum_a, gmpnum_b); } - FREE_GMP_TEMP(arga_tmp); - FREE_GMP_TEMP(argb_tmp); - - array_init(return_value); - ZEND_REGISTER_RESOURCE(&r, gmpnum_result1, le_gmp); - add_index_resource(return_value, 0, Z_LVAL(r)); - if (use_ui && allow_ui_return) { - mpz_clear(*gmpnum_result2); - add_index_long(return_value, 1, long_result); - } else { - ZEND_REGISTER_RESOURCE(&r, gmpnum_result2, le_gmp); - add_index_resource(return_value, 1, Z_LVAL(r)); - } + FREE_GMP_TEMP(temp_a); + FREE_GMP_TEMP(temp_b); } /* }}} */ /* {{{ _gmp_binary_ui_op */ -static inline void _gmp_binary_ui_op(INTERNAL_FUNCTION_PARAMETERS, gmp_binary_op_t gmp_op, gmp_binary_ui_op_t gmp_ui_op) +static inline void _gmp_binary_ui_op(INTERNAL_FUNCTION_PARAMETERS, gmp_binary_op_t gmp_op, gmp_binary_ui_op_t gmp_ui_op, int check_b_zero) { - zval **a_arg, **b_arg; + zval *a_arg, *b_arg; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ZZ", &a_arg, &b_arg) == FAILURE){ + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &a_arg, &b_arg) == FAILURE){ return; } - gmp_zval_binary_ui_op(return_value, a_arg, b_arg, gmp_op, gmp_ui_op); + gmp_zval_binary_ui_op(return_value, a_arg, b_arg, gmp_op, gmp_ui_op, check_b_zero TSRMLS_CC); } /* }}} */ @@ -650,33 +923,28 @@ static inline void _gmp_binary_ui_op(INTERNAL_FUNCTION_PARAMETERS, gmp_binary_op /* {{{ gmp_zval_unary_op */ -static inline void gmp_zval_unary_op(zval *return_value, zval **a_arg, gmp_unary_op_t gmp_op TSRMLS_DC) +static inline void gmp_zval_unary_op(zval *return_value, zval *a_arg, gmp_unary_op_t gmp_op TSRMLS_DC) { - mpz_t *gmpnum_a, *gmpnum_result; - int temp_a; + mpz_ptr gmpnum_a, gmpnum_result; + gmp_temp_t temp_a; FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a); - INIT_GMP_NUM(gmpnum_result); - gmp_op(*gmpnum_result, *gmpnum_a); + INIT_GMP_RETVAL(gmpnum_result); + gmp_op(gmpnum_result, gmpnum_a); FREE_GMP_TEMP(temp_a); - ZEND_REGISTER_RESOURCE(return_value, gmpnum_result, le_gmp); } /* }}} */ /* {{{ gmp_zval_unary_ui_op */ -static inline void gmp_zval_unary_ui_op(zval *return_value, zval **a_arg, gmp_unary_ui_op_t gmp_op TSRMLS_DC) +static inline void gmp_zval_unary_ui_op(zval *return_value, zval *a_arg, gmp_unary_ui_op_t gmp_op TSRMLS_DC) { - mpz_t *gmpnum_result; + mpz_ptr gmpnum_result; - convert_to_long_ex(a_arg); - - INIT_GMP_NUM(gmpnum_result); - gmp_op(*gmpnum_result, Z_LVAL_PP(a_arg)); - - ZEND_REGISTER_RESOURCE(return_value, gmpnum_result, le_gmp); + INIT_GMP_RETVAL(gmpnum_result); + gmp_op(gmpnum_result, gmp_get_long(a_arg)); } /* }}} */ @@ -685,9 +953,9 @@ static inline void gmp_zval_unary_ui_op(zval *return_value, zval **a_arg, gmp_un */ static inline void _gmp_unary_ui_op(INTERNAL_FUNCTION_PARAMETERS, gmp_unary_ui_op_t gmp_op) { - zval **a_arg; + zval *a_arg; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &a_arg) == FAILURE){ + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &a_arg) == FAILURE){ return; } @@ -699,9 +967,9 @@ static inline void _gmp_unary_ui_op(INTERNAL_FUNCTION_PARAMETERS, gmp_unary_ui_o */ static inline void _gmp_unary_op(INTERNAL_FUNCTION_PARAMETERS, gmp_unary_op_t gmp_op) { - zval **a_arg; + zval *a_arg; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &a_arg) == FAILURE){ + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &a_arg) == FAILURE){ return; } @@ -713,16 +981,16 @@ static inline void _gmp_unary_op(INTERNAL_FUNCTION_PARAMETERS, gmp_unary_op_t gm */ static inline void _gmp_unary_opl(INTERNAL_FUNCTION_PARAMETERS, gmp_unary_opl_t gmp_op) { - zval **a_arg; - mpz_t *gmpnum_a; - int temp_a; + zval *a_arg; + mpz_ptr gmpnum_a; + gmp_temp_t temp_a; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &a_arg) == FAILURE){ + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &a_arg) == FAILURE){ return; } FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a); - RETVAL_LONG(gmp_op(*gmpnum_a)); + RETVAL_LONG(gmp_op(gmpnum_a)); FREE_GMP_TEMP(temp_a); } /* }}} */ @@ -731,33 +999,33 @@ static inline void _gmp_unary_opl(INTERNAL_FUNCTION_PARAMETERS, gmp_unary_opl_t */ static inline void _gmp_binary_opl(INTERNAL_FUNCTION_PARAMETERS, gmp_binary_opl_t gmp_op) { - zval **a_arg, **b_arg; - mpz_t *gmpnum_a, *gmpnum_b; - int temp_a, temp_b; + zval *a_arg, *b_arg; + mpz_ptr gmpnum_a, gmpnum_b; + gmp_temp_t temp_a, temp_b; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ZZ", &a_arg, &b_arg) == FAILURE){ + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &a_arg, &b_arg) == FAILURE){ return; } FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a); - FETCH_GMP_ZVAL(gmpnum_b, b_arg, temp_b); + FETCH_GMP_ZVAL_DEP(gmpnum_b, b_arg, temp_b, temp_a); - RETVAL_LONG(gmp_op(*gmpnum_a, *gmpnum_b)); + RETVAL_LONG(gmp_op(gmpnum_a, gmpnum_b)); FREE_GMP_TEMP(temp_a); FREE_GMP_TEMP(temp_b); } /* }}} */ -/* {{{ proto resource gmp_init(mixed number [, int base]) +/* {{{ proto GMP gmp_init(mixed number [, int base]) Initializes GMP number */ ZEND_FUNCTION(gmp_init) { - zval **number_arg; - mpz_t * gmpnumber; - long base=0; + zval *number_arg; + mpz_ptr gmpnumber; + long base = 0; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z|l", &number_arg, &base) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|l", &number_arg, &base) == FAILURE) { return; } @@ -766,48 +1034,42 @@ ZEND_FUNCTION(gmp_init) RETURN_FALSE; } - if (convert_to_gmp(&gmpnumber, number_arg, base TSRMLS_CC) == FAILURE) { + INIT_GMP_RETVAL(gmpnumber); + if (convert_to_gmp(gmpnumber, number_arg, base TSRMLS_CC) == FAILURE) { + zval_dtor(return_value); RETURN_FALSE; } - - /* Write your own code here to handle argument number. */ - ZEND_REGISTER_RESOURCE(return_value, gmpnumber, le_gmp); } /* }}} */ -/* {{{ proto int gmp_intval(resource gmpnumber) +/* {{{ proto int gmp_intval(mixed gmpnumber) Gets signed long value of GMP number */ ZEND_FUNCTION(gmp_intval) { - zval **gmpnumber_arg; - mpz_t * gmpnum; + zval *gmpnumber_arg; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &gmpnumber_arg) == FAILURE){ + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &gmpnumber_arg) == FAILURE){ return; } - if (Z_TYPE_PP(gmpnumber_arg) == IS_RESOURCE) { - ZEND_FETCH_RESOURCE(gmpnum, mpz_t *, gmpnumber_arg, -1, GMP_RESOURCE_NAME, le_gmp); - RETVAL_LONG(mpz_get_si(*gmpnum)); + if (IS_GMP(gmpnumber_arg)) { + RETVAL_LONG(mpz_get_si(GET_GMP_FROM_ZVAL(gmpnumber_arg))); } else { - convert_to_long_ex(gmpnumber_arg); - RETVAL_LONG(Z_LVAL_PP(gmpnumber_arg)); + RETVAL_LONG(gmp_get_long(gmpnumber_arg)); } } /* }}} */ -/* {{{ proto string gmp_strval(resource gmpnumber [, int base]) +/* {{{ proto string gmp_strval(mixed gmpnumber [, int base]) Gets string representation of GMP number */ ZEND_FUNCTION(gmp_strval) { - zval **gmpnumber_arg; - int num_len; + zval *gmpnumber_arg; long base = 10; - mpz_t * gmpnum; - char *out_string; - int temp_a; + mpz_ptr gmpnum; + gmp_temp_t temp_a; - if( zend_parse_parameters( ZEND_NUM_ARGS() TSRMLS_CC, "Z|l", &gmpnumber_arg, &base ) == FAILURE ) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|l", &gmpnumber_arg, &base) == FAILURE) { return; } @@ -825,162 +1087,138 @@ ZEND_FUNCTION(gmp_strval) FETCH_GMP_ZVAL(gmpnum, gmpnumber_arg, temp_a); - num_len = mpz_sizeinbase(*gmpnum, abs(base)); - out_string = emalloc(num_len+2); - if (mpz_sgn(*gmpnum) < 0) { - num_len++; - } - mpz_get_str(out_string, base, *gmpnum); - - FREE_GMP_TEMP(temp_a); - - /* - From GMP documentation for mpz_sizeinbase(): - The returned value will be exact or 1 too big. If base is a power of - 2, the returned value will always be exact. + gmp_strval(return_value, gmpnum, base); - So let's check to see if we already have a \0 byte... - */ - - if (out_string[num_len-1] == '\0') { - num_len--; - } else { - out_string[num_len] = '\0'; - } - RETVAL_STRINGL(out_string, num_len, 0); + FREE_GMP_TEMP(temp_a); } /* }}} */ -/* {{{ proto resource gmp_add(resource a, resource b) +/* {{{ proto GMP gmp_add(mixed a, mixed b) Add a and b */ ZEND_FUNCTION(gmp_add) { - gmp_binary_ui_op(mpz_add, (gmp_binary_ui_op_t)mpz_add_ui); + gmp_binary_ui_op(mpz_add, mpz_add_ui); } /* }}} */ -/* {{{ proto resource gmp_sub(resource a, resource b) +/* {{{ proto GMP gmp_sub(mixed a, mixed b) Subtract b from a */ ZEND_FUNCTION(gmp_sub) { - gmp_binary_ui_op(mpz_sub, (gmp_binary_ui_op_t)mpz_sub_ui); + gmp_binary_ui_op(mpz_sub, mpz_sub_ui); } /* }}} */ -/* {{{ proto resource gmp_mul(resource a, resource b) +/* {{{ proto GMP gmp_mul(mixed a, mixed b) Multiply a and b */ ZEND_FUNCTION(gmp_mul) { - gmp_binary_ui_op(mpz_mul, (gmp_binary_ui_op_t)mpz_mul_ui); + gmp_binary_ui_op(mpz_mul, mpz_mul_ui); } /* }}} */ -/* {{{ proto array gmp_div_qr(resource a, resource b [, int round]) +/* {{{ proto array gmp_div_qr(mixed a, mixed b [, int round]) Divide a by b, returns quotient and reminder */ ZEND_FUNCTION(gmp_div_qr) { - zval **a_arg, **b_arg; + zval *a_arg, *b_arg; long round = GMP_ROUND_ZERO; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ZZ|l", &a_arg, &b_arg, &round) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz|l", &a_arg, &b_arg, &round) == FAILURE) { return; } switch (round) { case GMP_ROUND_ZERO: - gmp_zval_binary_ui_op2_ex(return_value, a_arg, b_arg, mpz_tdiv_qr, (gmp_binary_ui_op2_t)mpz_tdiv_qr_ui, 0, 1 TSRMLS_CC); + gmp_zval_binary_ui_op2(return_value, a_arg, b_arg, mpz_tdiv_qr, (gmp_binary_ui_op2_t) mpz_tdiv_qr_ui, 1 TSRMLS_CC); break; case GMP_ROUND_PLUSINF: - gmp_zval_binary_ui_op2_ex(return_value, a_arg, b_arg, mpz_cdiv_qr, (gmp_binary_ui_op2_t)mpz_cdiv_qr_ui, 0, 1 TSRMLS_CC); + gmp_zval_binary_ui_op2(return_value, a_arg, b_arg, mpz_cdiv_qr, (gmp_binary_ui_op2_t) mpz_cdiv_qr_ui, 1 TSRMLS_CC); break; case GMP_ROUND_MINUSINF: - gmp_zval_binary_ui_op2_ex(return_value, a_arg, b_arg, mpz_fdiv_qr, (gmp_binary_ui_op2_t)mpz_fdiv_qr_ui, 0, 1 TSRMLS_CC); + gmp_zval_binary_ui_op2(return_value, a_arg, b_arg, mpz_fdiv_qr, (gmp_binary_ui_op2_t) mpz_fdiv_qr_ui, 1 TSRMLS_CC); break; + default: + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid rounding mode"); + RETURN_FALSE; } - } /* }}} */ -/* {{{ proto resource gmp_div_r(resource a, resource b [, int round]) +/* {{{ proto GMP gmp_div_r(mixed a, mixed b [, int round]) Divide a by b, returns reminder only */ ZEND_FUNCTION(gmp_div_r) { - zval **a_arg, **b_arg; + zval *a_arg, *b_arg; long round = GMP_ROUND_ZERO; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ZZ|l", &a_arg, &b_arg, &round) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz|l", &a_arg, &b_arg, &round) == FAILURE) { return; } switch (round) { case GMP_ROUND_ZERO: - gmp_zval_binary_ui_op_ex(return_value, a_arg, b_arg, mpz_tdiv_r, (gmp_binary_ui_op_t)mpz_tdiv_r_ui, 1, 1, 1 TSRMLS_CC); + gmp_zval_binary_ui_op(return_value, a_arg, b_arg, mpz_tdiv_r, (gmp_binary_ui_op_t) mpz_tdiv_r_ui, 1 TSRMLS_CC); break; case GMP_ROUND_PLUSINF: - gmp_zval_binary_ui_op_ex(return_value, a_arg, b_arg, mpz_cdiv_r, (gmp_binary_ui_op_t)mpz_cdiv_r_ui, 1, 1, 1 TSRMLS_CC); + gmp_zval_binary_ui_op(return_value, a_arg, b_arg, mpz_cdiv_r, (gmp_binary_ui_op_t) mpz_cdiv_r_ui, 1 TSRMLS_CC); break; case GMP_ROUND_MINUSINF: - gmp_zval_binary_ui_op_ex(return_value, a_arg, b_arg, mpz_fdiv_r, (gmp_binary_ui_op_t)mpz_fdiv_r_ui, 1, 1, 1 TSRMLS_CC); + gmp_zval_binary_ui_op(return_value, a_arg, b_arg, mpz_fdiv_r, (gmp_binary_ui_op_t) mpz_fdiv_r_ui, 1 TSRMLS_CC); break; + default: + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid rounding mode"); + RETURN_FALSE; } } /* }}} */ -/* {{{ proto resource gmp_div_q(resource a, resource b [, int round]) +/* {{{ proto GMP gmp_div_q(mixed a, mixed b [, int round]) Divide a by b, returns quotient only */ ZEND_FUNCTION(gmp_div_q) { - zval **a_arg, **b_arg; + zval *a_arg, *b_arg; long round = GMP_ROUND_ZERO; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ZZ|l", &a_arg, &b_arg, &round) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz|l", &a_arg, &b_arg, &round) == FAILURE) { return; } switch (round) { case GMP_ROUND_ZERO: - gmp_zval_binary_ui_op_ex(return_value, a_arg, b_arg, mpz_tdiv_q, (gmp_binary_ui_op_t)mpz_tdiv_q_ui, 0, 1, 1 TSRMLS_CC); + gmp_zval_binary_ui_op(return_value, a_arg, b_arg, mpz_tdiv_q, (gmp_binary_ui_op_t) mpz_tdiv_q_ui, 1 TSRMLS_CC); break; case GMP_ROUND_PLUSINF: - gmp_zval_binary_ui_op_ex(return_value, a_arg, b_arg, mpz_cdiv_q, (gmp_binary_ui_op_t)mpz_cdiv_q_ui, 0, 1, 1 TSRMLS_CC); + gmp_zval_binary_ui_op(return_value, a_arg, b_arg, mpz_cdiv_q, (gmp_binary_ui_op_t) mpz_cdiv_q_ui, 1 TSRMLS_CC); break; case GMP_ROUND_MINUSINF: - gmp_zval_binary_ui_op_ex(return_value, a_arg, b_arg, mpz_fdiv_q, (gmp_binary_ui_op_t)mpz_fdiv_q_ui, 0, 1, 1 TSRMLS_CC); + gmp_zval_binary_ui_op(return_value, a_arg, b_arg, mpz_fdiv_q, (gmp_binary_ui_op_t) mpz_fdiv_q_ui, 1 TSRMLS_CC); break; + default: + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid rounding mode"); + RETURN_FALSE; } } /* }}} */ -/* {{{ proto resource gmp_mod(resource a, resource b) +/* {{{ proto GMP gmp_mod(mixed a, mixed b) Computes a modulo b */ ZEND_FUNCTION(gmp_mod) { - zval **a_arg, **b_arg; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ZZ", &a_arg, &b_arg) == FAILURE){ - return; - } - - gmp_zval_binary_ui_op_ex(return_value, a_arg, b_arg, mpz_mod, (gmp_binary_ui_op_t)mpz_mod_ui, 1, 1, 0 TSRMLS_CC); + gmp_binary_ui_op_no_zero(mpz_mod, (gmp_binary_ui_op_t) mpz_mod_ui); } /* }}} */ -/* {{{ proto resource gmp_divexact(resource a, resource b) +/* {{{ proto GMP gmp_divexact(mixed a, mixed b) Divide a by b using exact division algorithm */ ZEND_FUNCTION(gmp_divexact) { - zval **a_arg, **b_arg; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ZZ", &a_arg, &b_arg) == FAILURE){ - return; - } - - gmp_zval_binary_ui_op_ex(return_value, a_arg, b_arg, mpz_divexact, NULL, 0, 1, 1 TSRMLS_CC); + gmp_binary_ui_op_no_zero(mpz_divexact, NULL); } /* }}} */ -/* {{{ proto resource gmp_neg(resource a) +/* {{{ proto GMP gmp_neg(mixed a) Negates a number */ ZEND_FUNCTION(gmp_neg) { @@ -988,7 +1226,7 @@ ZEND_FUNCTION(gmp_neg) } /* }}} */ -/* {{{ proto resource gmp_abs(resource a) +/* {{{ proto GMP gmp_abs(mixed a) Calculates absolute value */ ZEND_FUNCTION(gmp_abs) { @@ -996,99 +1234,92 @@ ZEND_FUNCTION(gmp_abs) } /* }}} */ -/* {{{ proto resource gmp_fact(int a) +/* {{{ proto GMP gmp_fact(int a) Calculates factorial function */ ZEND_FUNCTION(gmp_fact) { - zval **a_arg; - mpz_t *gmpnum_tmp; - int temp_a; + zval *a_arg; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &a_arg) == FAILURE){ + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &a_arg) == FAILURE){ return; } - if (Z_TYPE_PP(a_arg) == IS_RESOURCE) { - FETCH_GMP_ZVAL(gmpnum_tmp, a_arg, temp_a); /* no need to free this since it's IS_RESOURCE */ - if (mpz_sgn(*gmpnum_tmp) < 0) { + if (IS_GMP(a_arg)) { + mpz_ptr gmpnum_tmp = GET_GMP_FROM_ZVAL(a_arg); + if (mpz_sgn(gmpnum_tmp) < 0) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Number has to be greater than or equal to 0"); RETURN_FALSE; } } else { - convert_to_long_ex(a_arg); - if (Z_LVAL_PP(a_arg) < 0) { + if (gmp_get_long(a_arg) < 0) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Number has to be greater than or equal to 0"); RETURN_FALSE; } } - + gmp_zval_unary_ui_op(return_value, a_arg, mpz_fac_ui TSRMLS_CC); } /* }}} */ -/* {{{ proto resource gmp_pow(resource base, int exp) +/* {{{ proto GMP gmp_pow(mixed base, int exp) Raise base to power exp */ ZEND_FUNCTION(gmp_pow) { - zval **base_arg; - mpz_t *gmpnum_result, *gmpnum_base; - int use_ui = 0; - int temp_base; + zval *base_arg; + mpz_ptr gmpnum_result, gmpnum_base; + gmp_temp_t temp_base; long exp; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Zl", &base_arg, &exp) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zl", &base_arg, &exp) == FAILURE) { return; } - if (Z_TYPE_PP(base_arg) == IS_LONG && Z_LVAL_PP(base_arg) >= 0) { - use_ui = 1; - } else { - FETCH_GMP_ZVAL(gmpnum_base, base_arg, temp_base); - } - if (exp < 0) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Negative exponent not supported"); RETURN_FALSE; } - INIT_GMP_NUM(gmpnum_result); - if (use_ui) { - mpz_ui_pow_ui(*gmpnum_result, Z_LVAL_PP(base_arg), exp); + INIT_GMP_RETVAL(gmpnum_result); + if (Z_TYPE_P(base_arg) == IS_LONG && Z_LVAL_P(base_arg) >= 0) { + mpz_ui_pow_ui(gmpnum_result, Z_LVAL_P(base_arg), exp); } else { - mpz_pow_ui(*gmpnum_result, *gmpnum_base, exp); + FETCH_GMP_ZVAL(gmpnum_base, base_arg, temp_base); + mpz_pow_ui(gmpnum_result, gmpnum_base, exp); FREE_GMP_TEMP(temp_base); } - ZEND_REGISTER_RESOURCE(return_value, gmpnum_result, le_gmp); } /* }}} */ -/* {{{ proto resource gmp_powm(resource base, resource exp, resource mod) +/* {{{ proto GMP gmp_powm(mixed base, mixed exp, mixed mod) Raise base to power exp and take result modulo mod */ ZEND_FUNCTION(gmp_powm) { - zval **base_arg, **exp_arg, **mod_arg; - mpz_t *gmpnum_base, *gmpnum_exp, *gmpnum_mod, *gmpnum_result; + zval *base_arg, *exp_arg, *mod_arg; + mpz_ptr gmpnum_base, gmpnum_exp, gmpnum_mod, gmpnum_result; int use_ui = 0; - int temp_base = 0, temp_exp = 0, temp_mod; + gmp_temp_t temp_base, temp_exp, temp_mod; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ZZZ", &base_arg, &exp_arg, &mod_arg) == FAILURE){ + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zzz", &base_arg, &exp_arg, &mod_arg) == FAILURE){ return; } FETCH_GMP_ZVAL(gmpnum_base, base_arg, temp_base); - if (Z_TYPE_PP(exp_arg) == IS_LONG && Z_LVAL_PP(exp_arg) >= 0) { + if (Z_TYPE_P(exp_arg) == IS_LONG && Z_LVAL_P(exp_arg) >= 0) { use_ui = 1; + temp_exp.is_used = 0; } else { - FETCH_GMP_ZVAL(gmpnum_exp, exp_arg, temp_exp); - if (mpz_sgn(*gmpnum_exp) < 0) { - php_error_docref(NULL TSRMLS_CC, E_WARNING,"Second parameter cannot be less than 0"); + FETCH_GMP_ZVAL_DEP(gmpnum_exp, exp_arg, temp_exp, temp_base); + if (mpz_sgn(gmpnum_exp) < 0) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Second parameter cannot be less than 0"); + FREE_GMP_TEMP(temp_base); + FREE_GMP_TEMP(temp_exp); RETURN_FALSE; } } - FETCH_GMP_ZVAL(gmpnum_mod, mod_arg, temp_mod); + FETCH_GMP_ZVAL_DEP_DEP(gmpnum_mod, mod_arg, temp_mod, temp_exp, temp_base); - if (!mpz_cmp_ui(*gmpnum_mod, 0)) { + if (!mpz_cmp_ui(gmpnum_mod, 0)) { FREE_GMP_TEMP(temp_base); if (use_ui) { FREE_GMP_TEMP(temp_exp); @@ -1097,202 +1328,250 @@ ZEND_FUNCTION(gmp_powm) RETURN_FALSE; } - INIT_GMP_NUM(gmpnum_result); + INIT_GMP_RETVAL(gmpnum_result); if (use_ui) { - mpz_powm_ui(*gmpnum_result, *gmpnum_base, (unsigned long)Z_LVAL_PP(exp_arg), *gmpnum_mod); + mpz_powm_ui(gmpnum_result, gmpnum_base, (unsigned long) Z_LVAL_P(exp_arg), gmpnum_mod); } else { - mpz_powm(*gmpnum_result, *gmpnum_base, *gmpnum_exp, *gmpnum_mod); + mpz_powm(gmpnum_result, gmpnum_base, gmpnum_exp, gmpnum_mod); FREE_GMP_TEMP(temp_exp); } FREE_GMP_TEMP(temp_base); FREE_GMP_TEMP(temp_mod); - - ZEND_REGISTER_RESOURCE(return_value, gmpnum_result, le_gmp); - } /* }}} */ -/* {{{ proto resource gmp_sqrt(resource a) +/* {{{ proto GMP gmp_sqrt(mixed a) Takes integer part of square root of a */ ZEND_FUNCTION(gmp_sqrt) { - zval **a_arg; - mpz_t *gmpnum_a, *gmpnum_result; - int temp_a; + zval *a_arg; + mpz_ptr gmpnum_a, gmpnum_result; + gmp_temp_t temp_a; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &a_arg) == FAILURE){ + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &a_arg) == FAILURE){ return; } FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a); - if (mpz_sgn(*gmpnum_a) < 0) { + if (mpz_sgn(gmpnum_a) < 0) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Number has to be greater than or equal to 0"); FREE_GMP_TEMP(temp_a); RETURN_FALSE; } - - INIT_GMP_NUM(gmpnum_result); - mpz_sqrt(*gmpnum_result, *gmpnum_a); - FREE_GMP_TEMP(temp_a); - ZEND_REGISTER_RESOURCE(return_value, gmpnum_result, le_gmp); + INIT_GMP_RETVAL(gmpnum_result); + mpz_sqrt(gmpnum_result, gmpnum_a); + FREE_GMP_TEMP(temp_a); } /* }}} */ -/* {{{ proto array gmp_sqrtrem(resource a) +/* {{{ proto array gmp_sqrtrem(mixed a) Square root with remainder */ ZEND_FUNCTION(gmp_sqrtrem) { - zval **a_arg; - mpz_t *gmpnum_a, *gmpnum_result1, *gmpnum_result2; - zval r; - int temp_a; + zval *a_arg; + mpz_ptr gmpnum_a, gmpnum_result1, gmpnum_result2; + gmp_temp_t temp_a; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &a_arg) == FAILURE){ + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &a_arg) == FAILURE){ return; } FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a); - - if (mpz_sgn(*gmpnum_a) < 0) { - php_error_docref(NULL TSRMLS_CC, E_WARNING,"Number has to be greater than or equal to 0"); + + if (mpz_sgn(gmpnum_a) < 0) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Number has to be greater than or equal to 0"); + FREE_GMP_TEMP(temp_a); RETURN_FALSE; } - INIT_GMP_NUM(gmpnum_result1); - INIT_GMP_NUM(gmpnum_result2); + array_init(return_value); + add_index_zval(return_value, 0, gmp_create(&gmpnum_result1 TSRMLS_CC)); + add_index_zval(return_value, 1, gmp_create(&gmpnum_result2 TSRMLS_CC)); + + mpz_sqrtrem(gmpnum_result1, gmpnum_result2, gmpnum_a); + FREE_GMP_TEMP(temp_a); +} +/* }}} */ + +/* {{{ proto GMP gmp_root(mixed a, int nth) + Takes integer part of nth root */ +ZEND_FUNCTION(gmp_root) +{ + zval *a_arg; + long nth; + mpz_ptr gmpnum_a, gmpnum_result; + gmp_temp_t temp_a; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zl", &a_arg, &nth) == FAILURE) { + return; + } + + if (nth <= 0) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "The root must be positive"); + RETURN_FALSE; + } + + FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a); + + if (nth % 2 == 0 && mpz_sgn(gmpnum_a) < 0) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Can't take even root of negative number"); + FREE_GMP_TEMP(temp_a); + RETURN_FALSE; + } - mpz_sqrtrem(*gmpnum_result1, *gmpnum_result2, *gmpnum_a); + INIT_GMP_RETVAL(gmpnum_result); + mpz_root(gmpnum_result, gmpnum_a, (unsigned long) nth); FREE_GMP_TEMP(temp_a); +} +/* }}} */ + +/* {{{ proto GMP gmp_rootrem(mixed a, int nth) + Calculates integer part of nth root and remainder */ +ZEND_FUNCTION(gmp_rootrem) +{ + zval *a_arg; + long nth; + mpz_ptr gmpnum_a, gmpnum_result1, gmpnum_result2; + gmp_temp_t temp_a; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zl", &a_arg, &nth) == FAILURE) { + return; + } + + if (nth <= 0) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "The root must be positive"); + RETURN_FALSE; + } + + FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a); + + if (nth % 2 == 0 && mpz_sgn(gmpnum_a) < 0) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Can't take even root of negative number"); + FREE_GMP_TEMP(temp_a); + RETURN_FALSE; + } array_init(return_value); - ZEND_REGISTER_RESOURCE(&r, gmpnum_result1, le_gmp); - add_index_resource(return_value, 0, Z_LVAL(r)); - ZEND_REGISTER_RESOURCE(&r, gmpnum_result2, le_gmp); - add_index_resource(return_value, 1, Z_LVAL(r)); + add_index_zval(return_value, 0, gmp_create(&gmpnum_result1 TSRMLS_CC)); + add_index_zval(return_value, 1, gmp_create(&gmpnum_result2 TSRMLS_CC)); + +#if GMP_42_OR_NEWER + mpz_rootrem(gmpnum_result1, gmpnum_result2, gmpnum_a, (unsigned long) nth); +#else + mpz_root(gmpnum_result1, gmpnum_a, (unsigned long) nth); + mpz_pow_ui(gmpnum_result2, gmpnum_result1, (unsigned long) nth); + mpz_sub(gmpnum_result2, gmpnum_a, gmpnum_result2); + mpz_abs(gmpnum_result2, gmpnum_result2); +#endif + + FREE_GMP_TEMP(temp_a); } /* }}} */ -/* {{{ proto bool gmp_perfect_square(resource a) +/* {{{ proto bool gmp_perfect_square(mixed a) Checks if a is an exact square */ ZEND_FUNCTION(gmp_perfect_square) { - zval **a_arg; - mpz_t *gmpnum_a; - int temp_a; + zval *a_arg; + mpz_ptr gmpnum_a; + gmp_temp_t temp_a; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &a_arg) == FAILURE){ + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &a_arg) == FAILURE){ return; } FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a); - RETVAL_BOOL((mpz_perfect_square_p(*gmpnum_a)!=0)); + RETVAL_BOOL((mpz_perfect_square_p(gmpnum_a) != 0)); FREE_GMP_TEMP(temp_a); } /* }}} */ -/* {{{ proto int gmp_prob_prime(resource a[, int reps]) +/* {{{ proto int gmp_prob_prime(mixed a[, int reps]) Checks if a is "probably prime" */ ZEND_FUNCTION(gmp_prob_prime) { - zval **gmpnumber_arg; - mpz_t *gmpnum_a; + zval *gmpnumber_arg; + mpz_ptr gmpnum_a; long reps = 10; - int temp_a; + gmp_temp_t temp_a; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z|l", &gmpnumber_arg, &reps) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|l", &gmpnumber_arg, &reps) == FAILURE) { return; } FETCH_GMP_ZVAL(gmpnum_a, gmpnumber_arg, temp_a); - RETVAL_LONG(mpz_probab_prime_p(*gmpnum_a, reps)); + RETVAL_LONG(mpz_probab_prime_p(gmpnum_a, reps)); FREE_GMP_TEMP(temp_a); } /* }}} */ -/* {{{ proto resource gmp_gcd(resource a, resource b) +/* {{{ proto GMP gmp_gcd(mixed a, mixed b) Computes greatest common denominator (gcd) of a and b */ ZEND_FUNCTION(gmp_gcd) { - zval **a_arg, **b_arg; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ZZ", &a_arg, &b_arg) == FAILURE){ - return; - } - - gmp_zval_binary_ui_op_ex(return_value, a_arg, b_arg, mpz_gcd, (gmp_binary_ui_op_t)mpz_gcd_ui, 0, 0, 1 TSRMLS_CC); + gmp_binary_ui_op(mpz_gcd, (gmp_binary_ui_op_t) mpz_gcd_ui); } /* }}} */ -/* {{{ proto array gmp_gcdext(resource a, resource b) +/* {{{ proto array gmp_gcdext(mixed a, mixed b) Computes G, S, and T, such that AS + BT = G = `gcd' (A, B) */ ZEND_FUNCTION(gmp_gcdext) { - zval **a_arg, **b_arg; - mpz_t *gmpnum_a, *gmpnum_b, *gmpnum_t, *gmpnum_s, *gmpnum_g; - zval r; - int temp_a, temp_b; + zval *a_arg, *b_arg; + mpz_ptr gmpnum_a, gmpnum_b, gmpnum_t, gmpnum_s, gmpnum_g; + gmp_temp_t temp_a, temp_b; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ZZ", &a_arg, &b_arg) == FAILURE){ + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &a_arg, &b_arg) == FAILURE){ return; } FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a); - FETCH_GMP_ZVAL(gmpnum_b, b_arg, temp_b); + FETCH_GMP_ZVAL_DEP(gmpnum_b, b_arg, temp_b, temp_a); - INIT_GMP_NUM(gmpnum_g); - INIT_GMP_NUM(gmpnum_s); - INIT_GMP_NUM(gmpnum_t); + array_init(return_value); + add_assoc_zval(return_value, "g", gmp_create(&gmpnum_g TSRMLS_CC)); + add_assoc_zval(return_value, "s", gmp_create(&gmpnum_s TSRMLS_CC)); + add_assoc_zval(return_value, "t", gmp_create(&gmpnum_t TSRMLS_CC)); - mpz_gcdext(*gmpnum_g, *gmpnum_s, *gmpnum_t, *gmpnum_a, *gmpnum_b); + mpz_gcdext(gmpnum_g, gmpnum_s, gmpnum_t, gmpnum_a, gmpnum_b); FREE_GMP_TEMP(temp_a); FREE_GMP_TEMP(temp_b); - - array_init(return_value); - - ZEND_REGISTER_RESOURCE(&r, gmpnum_g, le_gmp); - add_assoc_resource(return_value, "g", Z_LVAL(r)); - ZEND_REGISTER_RESOURCE(&r, gmpnum_s, le_gmp); - add_assoc_resource(return_value, "s", Z_LVAL(r)); - ZEND_REGISTER_RESOURCE(&r, gmpnum_t, le_gmp); - add_assoc_resource(return_value, "t", Z_LVAL(r)); } /* }}} */ -/* {{{ proto resource gmp_invert(resource a, resource b) +/* {{{ proto GMP gmp_invert(mixed a, mixed b) Computes the inverse of a modulo b */ ZEND_FUNCTION(gmp_invert) { - zval **a_arg, **b_arg; - mpz_t *gmpnum_a, *gmpnum_b, *gmpnum_result; - int temp_a, temp_b; + zval *a_arg, *b_arg; + mpz_ptr gmpnum_a, gmpnum_b, gmpnum_result; + gmp_temp_t temp_a, temp_b; int res; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ZZ", &a_arg, &b_arg) == FAILURE){ + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &a_arg, &b_arg) == FAILURE){ return; } FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a); - FETCH_GMP_ZVAL(gmpnum_b, b_arg, temp_b); + FETCH_GMP_ZVAL_DEP(gmpnum_b, b_arg, temp_b, temp_a); - INIT_GMP_NUM(gmpnum_result); - res=mpz_invert(*gmpnum_result, *gmpnum_a, *gmpnum_b); + INIT_GMP_RETVAL(gmpnum_result); + res = mpz_invert(gmpnum_result, gmpnum_a, gmpnum_b); FREE_GMP_TEMP(temp_a); FREE_GMP_TEMP(temp_b); - if (res) { - ZEND_REGISTER_RESOURCE(return_value, gmpnum_result, le_gmp); - } else { - FREE_GMP_NUM(gmpnum_result); + if (!res) { + zval_dtor(return_value); RETURN_FALSE; } } /* }}} */ -/* {{{ proto int gmp_jacobi(resource a, resource b) +/* {{{ proto int gmp_jacobi(mixed a, mixed b) Computes Jacobi symbol */ ZEND_FUNCTION(gmp_jacobi) { @@ -1300,7 +1579,7 @@ ZEND_FUNCTION(gmp_jacobi) } /* }}} */ -/* {{{ proto int gmp_legendre(resource a, resource b) +/* {{{ proto int gmp_legendre(mixed a, mixed b) Computes Legendre symbol */ ZEND_FUNCTION(gmp_legendre) { @@ -1308,70 +1587,52 @@ ZEND_FUNCTION(gmp_legendre) } /* }}} */ -/* {{{ proto int gmp_cmp(resource a, resource b) +/* {{{ proto int gmp_cmp(mixed a, mixed b) Compares two numbers */ ZEND_FUNCTION(gmp_cmp) { - zval **a_arg, **b_arg; - mpz_t *gmpnum_a, *gmpnum_b; - int use_si = 0, res; - int temp_a, temp_b; + zval *a_arg, *b_arg; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ZZ", &a_arg, &b_arg) == FAILURE){ + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &a_arg, &b_arg) == FAILURE){ return; } - FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a); - - if (Z_TYPE_PP(b_arg) == IS_LONG) { - use_si = 1; - } else { - FETCH_GMP_ZVAL(gmpnum_b, b_arg, temp_b); - } - - if (use_si) { - res = mpz_cmp_si(*gmpnum_a, Z_LVAL_PP(b_arg)); - } else { - res = mpz_cmp(*gmpnum_a, *gmpnum_b); - FREE_GMP_TEMP(temp_b); - } - FREE_GMP_TEMP(temp_a); - - RETURN_LONG(res); + gmp_cmp(return_value, a_arg, b_arg TSRMLS_CC); } /* }}} */ -/* {{{ proto int gmp_sign(resource a) +/* {{{ proto int gmp_sign(mixed a) Gets the sign of the number */ ZEND_FUNCTION(gmp_sign) { - zval **a_arg; - mpz_t *gmpnum_a; - int temp_a; + /* Can't use gmp_unary_opl here, because mpz_sgn is a macro */ + zval *a_arg; + mpz_ptr gmpnum_a; + gmp_temp_t temp_a; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &a_arg) == FAILURE){ + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &a_arg) == FAILURE){ return; } - + FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a); - RETVAL_LONG(mpz_sgn(*gmpnum_a)); + RETVAL_LONG(mpz_sgn(gmpnum_a)); FREE_GMP_TEMP(temp_a); } /* }}} */ -/* {{{ proto resource gmp_random([int limiter]) +/* {{{ proto GMP gmp_random([int limiter]) Gets random number */ ZEND_FUNCTION(gmp_random) { long limiter = 20; - mpz_t *gmpnum_result; + mpz_ptr gmpnum_result; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &limiter) == FAILURE) { return; } - INIT_GMP_NUM(gmpnum_result); + INIT_GMP_RETVAL(gmpnum_result); if (!GMPG(rand_initialized)) { /* Initialize */ @@ -1383,15 +1644,14 @@ ZEND_FUNCTION(gmp_random) GMPG(rand_initialized) = 1; } #ifdef GMP_LIMB_BITS - mpz_urandomb(*gmpnum_result, GMPG(rand_state), GMP_ABS (limiter) * GMP_LIMB_BITS); + mpz_urandomb(gmpnum_result, GMPG(rand_state), GMP_ABS (limiter) * GMP_LIMB_BITS); #else - mpz_urandomb(*gmpnum_result, GMPG(rand_state), GMP_ABS (limiter) * __GMP_BITS_PER_MP_LIMB); + mpz_urandomb(gmpnum_result, GMPG(rand_state), GMP_ABS (limiter) * __GMP_BITS_PER_MP_LIMB); #endif - ZEND_REGISTER_RESOURCE(return_value, gmpnum_result, le_gmp); } /* }}} */ -/* {{{ proto resource gmp_and(resource a, resource b) +/* {{{ proto GMP gmp_and(mixed a, mixed b) Calculates logical AND of a and b */ ZEND_FUNCTION(gmp_and) { @@ -1399,7 +1659,7 @@ ZEND_FUNCTION(gmp_and) } /* }}} */ -/* {{{ proto resource gmp_or(resource a, resource b) +/* {{{ proto GMP gmp_or(mixed a, mixed b) Calculates logical OR of a and b */ ZEND_FUNCTION(gmp_or) { @@ -1407,7 +1667,7 @@ ZEND_FUNCTION(gmp_or) } /* }}} */ -/* {{{ proto resource gmp_com(resource a) +/* {{{ proto GMP gmp_com(mixed a) Calculates one's complement of a */ ZEND_FUNCTION(gmp_com) { @@ -1415,7 +1675,7 @@ ZEND_FUNCTION(gmp_com) } /* }}} */ -/* {{{ proto resource gmp_nextprime(resource a) +/* {{{ proto GMP gmp_nextprime(mixed a) Finds next prime of a */ ZEND_FUNCTION(gmp_nextprime) { @@ -1423,212 +1683,149 @@ ZEND_FUNCTION(gmp_nextprime) } /* }}} */ -/* {{{ proto resource gmp_xor(resource a, resource b) +/* {{{ proto GMP gmp_xor(mixed a, mixed b) Calculates logical exclusive OR of a and b */ ZEND_FUNCTION(gmp_xor) { - /* use formula: a^b = (a|b)&^(a&b) */ - zval **a_arg, **b_arg; - mpz_t *gmpnum_a, *gmpnum_b, *gmpnum_result, *gmpnum_t; - int temp_a, temp_b; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ZZ", &a_arg, &b_arg) == FAILURE){ - return; - } - - FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a); - FETCH_GMP_ZVAL(gmpnum_b, b_arg, temp_b); - - INIT_GMP_NUM(gmpnum_result); - INIT_GMP_NUM(gmpnum_t); - - mpz_and(*gmpnum_t, *gmpnum_a, *gmpnum_b); - mpz_com(*gmpnum_t, *gmpnum_t); - - mpz_ior(*gmpnum_result, *gmpnum_a, *gmpnum_b); - mpz_and(*gmpnum_result, *gmpnum_result, *gmpnum_t); - - FREE_GMP_NUM(gmpnum_t); - - FREE_GMP_TEMP(temp_a); - FREE_GMP_TEMP(temp_b); - ZEND_REGISTER_RESOURCE(return_value, gmpnum_result, le_gmp); + gmp_binary_op(mpz_xor); } /* }}} */ -/* {{{ proto void gmp_setbit(resource &a, int index[, bool set_clear]) +/* {{{ proto void gmp_setbit(GMP a, int index[, bool set_clear]) Sets or clear bit in a */ ZEND_FUNCTION(gmp_setbit) { - zval **a_arg; + zval *a_arg; long index; zend_bool set = 1; - mpz_t *gmpnum_a; + mpz_ptr gmpnum_a; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Zl|b", &a_arg, &index, &set) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Ol|b", &a_arg, gmp_ce, &index, &set) == FAILURE) { return; } - ZEND_FETCH_RESOURCE(gmpnum_a, mpz_t *, a_arg, -1, GMP_RESOURCE_NAME, le_gmp); - if (index < 0) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Index must be greater than or equal to zero"); return; } + gmpnum_a = GET_GMP_FROM_ZVAL(a_arg); + if (set) { - mpz_setbit(*gmpnum_a, index); + mpz_setbit(gmpnum_a, index); } else { - mpz_clrbit(*gmpnum_a, index); + mpz_clrbit(gmpnum_a, index); } } /* }}} */ -/* {{{ proto void gmp_clrbit(resource &a, int index) +/* {{{ proto void gmp_clrbit(GMP a, int index) Clears bit in a */ ZEND_FUNCTION(gmp_clrbit) { - zval **a_arg; + zval *a_arg; long index; - mpz_t *gmpnum_a; + mpz_ptr gmpnum_a; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Zl", &a_arg, &index) == FAILURE){ + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Ol", &a_arg, gmp_ce, &index) == FAILURE){ return; } - ZEND_FETCH_RESOURCE(gmpnum_a, mpz_t *, a_arg, -1, GMP_RESOURCE_NAME, le_gmp); - if (index < 0) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Index must be greater than or equal to zero"); return; } - mpz_clrbit(*gmpnum_a, index); + gmpnum_a = GET_GMP_FROM_ZVAL(a_arg); + mpz_clrbit(gmpnum_a, index); } /* }}} */ -/* {{{ proto bool gmp_testbit(resource a, int index) +/* {{{ proto bool gmp_testbit(mixed a, int index) Tests if bit is set in a */ ZEND_FUNCTION(gmp_testbit) { - zval **a_arg; + zval *a_arg; long index; - mpz_t *gmpnum_a; + mpz_ptr gmpnum_a; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Zl", &a_arg, &index) == FAILURE){ + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zl", &a_arg, &index) == FAILURE){ return; } - ZEND_FETCH_RESOURCE(gmpnum_a, mpz_t *, a_arg, -1, GMP_RESOURCE_NAME, le_gmp); - if (index < 0) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Index must be greater than or equal to zero"); RETURN_FALSE; } - if (mpz_tstbit(*gmpnum_a, index)) { - RETURN_TRUE; - } - RETURN_FALSE; + gmpnum_a = GET_GMP_FROM_ZVAL(a_arg); + RETURN_BOOL(mpz_tstbit(gmpnum_a, index)); } /* }}} */ -/* {{{ proto int gmp_popcount(resource a) +/* {{{ proto int gmp_popcount(mixed a) Calculates the population count of a */ ZEND_FUNCTION(gmp_popcount) { - zval **a_arg; - mpz_t *gmpnum_a; - int temp_a; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &a_arg) == FAILURE){ - return; - } - - FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a); - - RETVAL_LONG(mpz_popcount(*gmpnum_a)); - FREE_GMP_TEMP(temp_a); + gmp_unary_opl((gmp_unary_opl_t) mpz_popcount); } /* }}} */ -/* {{{ proto int gmp_hamdist(resource a, resource b) +/* {{{ proto int gmp_hamdist(mixed a, mixed b) Calculates hamming distance between a and b */ ZEND_FUNCTION(gmp_hamdist) { - zval **a_arg, **b_arg; - mpz_t *gmpnum_a, *gmpnum_b; - int temp_a, temp_b; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ZZ", &a_arg, &b_arg) == FAILURE){ - return; - } - - FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a); - FETCH_GMP_ZVAL(gmpnum_b, b_arg, temp_b); - - RETVAL_LONG(mpz_hamdist(*gmpnum_a, *gmpnum_b)); - FREE_GMP_TEMP(temp_a); - FREE_GMP_TEMP(temp_b); + gmp_binary_opl((gmp_binary_opl_t) mpz_hamdist); } /* }}} */ -/* {{{ proto int gmp_scan0(resource a, int start) +/* {{{ proto int gmp_scan0(mixed a, int start) Finds first zero bit */ ZEND_FUNCTION(gmp_scan0) { - zval **a_arg; - mpz_t *gmpnum_a; - int temp_a; + zval *a_arg; + mpz_ptr gmpnum_a; + gmp_temp_t temp_a; long start; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Zl", &a_arg, &start) == FAILURE){ + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zl", &a_arg, &start) == FAILURE){ return; } - FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a); - if (start < 0) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Starting index must be greater than or equal to zero"); RETURN_FALSE; } - RETVAL_LONG(mpz_scan0(*gmpnum_a, start)); + FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a); + + RETVAL_LONG(mpz_scan0(gmpnum_a, start)); FREE_GMP_TEMP(temp_a); } /* }}} */ -/* {{{ proto int gmp_scan1(resource a, int start) +/* {{{ proto int gmp_scan1(mixed a, int start) Finds first non-zero bit */ ZEND_FUNCTION(gmp_scan1) { - zval **a_arg; - mpz_t *gmpnum_a; - int temp_a; + zval *a_arg; + mpz_ptr gmpnum_a; + gmp_temp_t temp_a; long start; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Zl", &a_arg, &start) == FAILURE){ + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zl", &a_arg, &start) == FAILURE){ return; } - FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a); if (start < 0) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Starting index must be greater than or equal to zero"); RETURN_FALSE; } - RETVAL_LONG(mpz_scan1(*gmpnum_a, start)); - FREE_GMP_TEMP(temp_a); -} -/* }}} */ - -/* {{{ _php_gmpnum_free - */ -static void _php_gmpnum_free(zend_rsrc_list_entry *rsrc TSRMLS_DC) -{ - mpz_t *gmpnum = (mpz_t *)rsrc->ptr; + FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a); - FREE_GMP_NUM(gmpnum); + RETVAL_LONG(mpz_scan1(gmpnum_a, start)); + FREE_GMP_TEMP(temp_a); } /* }}} */ diff --git a/ext/gmp/php_gmp.h b/ext/gmp/php_gmp.h index e1aaef886d..902c3ac0bb 100644 --- a/ext/gmp/php_gmp.h +++ b/ext/gmp/php_gmp.h @@ -45,9 +45,11 @@ ZEND_FUNCTION(gmp_neg); ZEND_FUNCTION(gmp_abs); ZEND_FUNCTION(gmp_fact); ZEND_FUNCTION(gmp_sqrt); +ZEND_FUNCTION(gmp_sqrtrem); +ZEND_FUNCTION(gmp_root); +ZEND_FUNCTION(gmp_rootrem); ZEND_FUNCTION(gmp_pow); ZEND_FUNCTION(gmp_powm); -ZEND_FUNCTION(gmp_sqrtrem); ZEND_FUNCTION(gmp_perfect_square); ZEND_FUNCTION(gmp_prob_prime); ZEND_FUNCTION(gmp_gcd); diff --git a/ext/gmp/tests/004.phpt b/ext/gmp/tests/004.phpt index a0fa1cd133..088dd08fd8 100644 --- a/ext/gmp/tests/004.phpt +++ b/ext/gmp/tests/004.phpt @@ -38,8 +38,6 @@ int(2342344) Notice: Object of class stdClass could not be converted to int in %s on line %d int(1) int(0) - -Warning: gmp_intval(): supplied resource is not a valid GMP integer resource in %s on line %d -bool(false) +int(%d) int(12345678) Done diff --git a/ext/gmp/tests/005.phpt b/ext/gmp/tests/005.phpt index 7907ffbf53..4ae0cb750a 100644 --- a/ext/gmp/tests/005.phpt +++ b/ext/gmp/tests/005.phpt @@ -47,7 +47,7 @@ bool(false) Warning: gmp_strval() expects parameter 2 to be long, string given in %s on line %d NULL -Warning: gmp_strval(): supplied resource is not a valid GMP integer resource in %s on line %d +Warning: gmp_strval(): Unable to convert variable to GMP - wrong type in %s on line %d bool(false) string(7) "9765456" diff --git a/ext/gmp/tests/006.phpt b/ext/gmp/tests/006.phpt index dedbcd0472..740760631d 100644 --- a/ext/gmp/tests/006.phpt +++ b/ext/gmp/tests/006.phpt @@ -35,9 +35,15 @@ NULL Warning: gmp_sub(): Unable to convert variable to GMP - wrong type in %s on line %d bool(false) -resource(%d) of type (GMP integer) +object(GMP)#%d (1) { + ["num"]=> + string(2) "-1" +} string(2) "-1" -resource(%d) of type (GMP integer) +object(GMP)#%d (1) { + ["num"]=> + string(5) "10001" +} string(5) "10001" Warning: gmp_sub(): Unable to convert variable to GMP - wrong type in %s on line %d diff --git a/ext/gmp/tests/007.phpt b/ext/gmp/tests/007.phpt index 4d4a993a17..e391c121f8 100644 --- a/ext/gmp/tests/007.phpt +++ b/ext/gmp/tests/007.phpt @@ -8,34 +8,16 @@ gmp_div_qr() tests var_dump(gmp_div_qr()); var_dump(gmp_div_qr("")); -var_dump($r = gmp_div_qr(0,1)); -var_dump(gmp_strval($r[0])); -var_dump(gmp_strval($r[1])); -var_dump($r = gmp_div_qr(1,0)); -var_dump($r = gmp_div_qr(12653,23482734)); -var_dump(gmp_strval($r[0])); -var_dump(gmp_strval($r[1])); -var_dump($r = gmp_div_qr(12653,23482734, 10)); -var_dump(gmp_strval($r[0])); -var_dump(gmp_strval($r[1])); -var_dump($r = gmp_div_qr(1123123,123)); -var_dump(gmp_strval($r[0])); -var_dump(gmp_strval($r[1])); -var_dump($r = gmp_div_qr(1123123,123, 1)); -var_dump(gmp_strval($r[0])); -var_dump(gmp_strval($r[1])); -var_dump($r = gmp_div_qr(1123123,123, 2)); -var_dump(gmp_strval($r[0])); -var_dump(gmp_strval($r[1])); -var_dump($r = gmp_div_qr(1123123,123, GMP_ROUND_ZERO)); -var_dump(gmp_strval($r[0])); -var_dump(gmp_strval($r[1])); -var_dump($r = gmp_div_qr(1123123,123, GMP_ROUND_PLUSINF)); -var_dump(gmp_strval($r[0])); -var_dump(gmp_strval($r[1])); -var_dump($r = gmp_div_qr(1123123,123, GMP_ROUND_MINUSINF)); -var_dump(gmp_strval($r[0])); -var_dump(gmp_strval($r[1])); +var_dump(gmp_div_qr(0,1)); +var_dump(gmp_div_qr(1,0)); +var_dump(gmp_div_qr(12653,23482734)); +var_dump(gmp_div_qr(12653,23482734, 10)); +var_dump(gmp_div_qr(1123123,123)); +var_dump(gmp_div_qr(1123123,123, 1)); +var_dump(gmp_div_qr(1123123,123, 2)); +var_dump(gmp_div_qr(1123123,123, GMP_ROUND_ZERO)); +var_dump(gmp_div_qr(1123123,123, GMP_ROUND_PLUSINF)); +var_dump(gmp_div_qr(1123123,123, GMP_ROUND_MINUSINF)); $fp = fopen(__FILE__, 'r'); @@ -52,80 +34,108 @@ Warning: gmp_div_qr() expects at least 2 parameters, 1 given in %s on line %d NULL array(2) { [0]=> - resource(%d) of type (GMP integer) + object(GMP)#%d (1) { + ["num"]=> + string(1) "0" + } [1]=> - resource(%d) of type (GMP integer) + object(GMP)#%d (1) { + ["num"]=> + string(1) "0" + } } -string(1) "0" -string(1) "0" Warning: gmp_div_qr(): Zero operand not allowed in %s on line %d bool(false) array(2) { [0]=> - resource(%d) of type (GMP integer) + object(GMP)#%d (1) { + ["num"]=> + string(1) "0" + } [1]=> - resource(%d) of type (GMP integer) + object(GMP)#%d (1) { + ["num"]=> + string(5) "12653" + } } -string(1) "0" -string(5) "12653" -NULL - -Warning: gmp_strval(): Unable to convert variable to GMP - wrong type in %s on line %d -bool(false) -Warning: gmp_strval(): Unable to convert variable to GMP - wrong type in %s on line %d +Warning: gmp_div_qr(): Invalid rounding mode in %s on line %d bool(false) array(2) { [0]=> - resource(%d) of type (GMP integer) + object(GMP)#%d (1) { + ["num"]=> + string(4) "9131" + } [1]=> - resource(%d) of type (GMP integer) + object(GMP)#%d (1) { + ["num"]=> + string(2) "10" + } } -string(4) "9131" -string(2) "10" array(2) { [0]=> - resource(%d) of type (GMP integer) + object(GMP)#%d (1) { + ["num"]=> + string(4) "9132" + } [1]=> - resource(%d) of type (GMP integer) + object(GMP)#%d (1) { + ["num"]=> + string(4) "-113" + } } -string(4) "9132" -string(4) "-113" array(2) { [0]=> - resource(%d) of type (GMP integer) + object(GMP)#%d (1) { + ["num"]=> + string(4) "9131" + } [1]=> - resource(%d) of type (GMP integer) + object(GMP)#%d (1) { + ["num"]=> + string(2) "10" + } } -string(4) "9131" -string(2) "10" array(2) { [0]=> - resource(%d) of type (GMP integer) + object(GMP)#%d (1) { + ["num"]=> + string(4) "9131" + } [1]=> - resource(%d) of type (GMP integer) + object(GMP)#%d (1) { + ["num"]=> + string(2) "10" + } } -string(4) "9131" -string(2) "10" array(2) { [0]=> - resource(%d) of type (GMP integer) + object(GMP)#%d (1) { + ["num"]=> + string(4) "9132" + } [1]=> - resource(%d) of type (GMP integer) + object(GMP)#%d (1) { + ["num"]=> + string(4) "-113" + } } -string(4) "9132" -string(4) "-113" array(2) { [0]=> - resource(%d) of type (GMP integer) + object(GMP)#%d (1) { + ["num"]=> + string(4) "9131" + } [1]=> - resource(%d) of type (GMP integer) + object(GMP)#%d (1) { + ["num"]=> + string(2) "10" + } } -string(4) "9131" -string(2) "10" -Warning: gmp_div_qr(): supplied resource is not a valid GMP integer resource in %s on line %d +Warning: gmp_div_qr(): Unable to convert variable to GMP - wrong type in %s on line %d bool(false) Warning: gmp_div_qr(): Unable to convert variable to GMP - wrong type in %s on line %d diff --git a/ext/gmp/tests/008.phpt b/ext/gmp/tests/008.phpt index 4e44ec10bf..c1874c86f9 100644 --- a/ext/gmp/tests/008.phpt +++ b/ext/gmp/tests/008.phpt @@ -9,24 +9,15 @@ var_dump(gmp_div_r()); var_dump(gmp_div_r("")); var_dump($r = gmp_div_r(0,1)); -var_dump(gmp_strval($r)); var_dump($r = gmp_div_r(1,0)); var_dump($r = gmp_div_r(12653,23482734)); -var_dump(gmp_strval($r)); var_dump($r = gmp_div_r(12653,23482734, 10)); -var_dump(gmp_strval($r)); var_dump($r = gmp_div_r(1123123,123)); -var_dump(gmp_strval($r)); var_dump($r = gmp_div_r(1123123,123, 1)); -var_dump(gmp_strval($r)); var_dump($r = gmp_div_r(1123123,123, 2)); -var_dump(gmp_strval($r)); var_dump($r = gmp_div_r(1123123,123, GMP_ROUND_ZERO)); -var_dump(gmp_strval($r)); var_dump($r = gmp_div_r(1123123,123, GMP_ROUND_PLUSINF)); -var_dump(gmp_strval($r)); var_dump($r = gmp_div_r(1123123,123, GMP_ROUND_MINUSINF)); -var_dump(gmp_strval($r)); $fp = fopen(__FILE__, 'r'); @@ -41,31 +32,46 @@ NULL Warning: gmp_div_r() expects at least 2 parameters, 1 given in %s on line %d NULL -int(0) -string(1) "0" +object(GMP)#%d (1) { + ["num"]=> + string(1) "0" +} Warning: gmp_div_r(): Zero operand not allowed in %s on line %d bool(false) -int(12653) -string(5) "12653" -NULL +object(GMP)#%d (1) { + ["num"]=> + string(5) "12653" +} -Warning: gmp_strval(): Unable to convert variable to GMP - wrong type in %s on line %d +Warning: gmp_div_r(): Invalid rounding mode in %s on line %d bool(false) -int(10) -string(2) "10" -int(113) -string(3) "113" -int(10) -string(2) "10" -int(10) -string(2) "10" -int(113) -string(3) "113" -int(10) -string(2) "10" +object(GMP)#%d (1) { + ["num"]=> + string(2) "10" +} +object(GMP)#%d (1) { + ["num"]=> + string(4) "-113" +} +object(GMP)#%d (1) { + ["num"]=> + string(2) "10" +} +object(GMP)#%d (1) { + ["num"]=> + string(2) "10" +} +object(GMP)#%d (1) { + ["num"]=> + string(4) "-113" +} +object(GMP)#%d (1) { + ["num"]=> + string(2) "10" +} -Warning: gmp_div_r(): supplied resource is not a valid GMP integer resource in %s on line %d +Warning: gmp_div_r(): Unable to convert variable to GMP - wrong type in %s on line %d bool(false) Warning: gmp_div_r(): Unable to convert variable to GMP - wrong type in %s on line %d diff --git a/ext/gmp/tests/009.phpt b/ext/gmp/tests/009.phpt index 745a4ef638..3b75a48e18 100644 --- a/ext/gmp/tests/009.phpt +++ b/ext/gmp/tests/009.phpt @@ -8,25 +8,16 @@ gmp_div_q() tests var_dump(gmp_div_q()); var_dump(gmp_div_q("")); -var_dump($r = gmp_div_q(0,1)); -var_dump(gmp_strval($r)); -var_dump($r = gmp_div_q(1,0)); -var_dump($r = gmp_div_q(12653,23482734)); -var_dump(gmp_strval($r)); -var_dump($r = gmp_div_q(12653,23482734, 10)); -var_dump(gmp_strval($r)); -var_dump($r = gmp_div_q(1123123,123)); -var_dump(gmp_strval($r)); -var_dump($r = gmp_div_q(1123123,123, 1)); -var_dump(gmp_strval($r)); -var_dump($r = gmp_div_q(1123123,123, 2)); -var_dump(gmp_strval($r)); -var_dump($r = gmp_div_q(1123123,123, GMP_ROUND_ZERO)); -var_dump(gmp_strval($r)); -var_dump($r = gmp_div_q(1123123,123, GMP_ROUND_PLUSINF)); -var_dump(gmp_strval($r)); -var_dump($r = gmp_div_q(1123123,123, GMP_ROUND_MINUSINF)); -var_dump(gmp_strval($r)); +var_dump(gmp_div_q(0,1)); +var_dump(gmp_div_q(1,0)); +var_dump(gmp_div_q(12653,23482734)); +var_dump(gmp_div_q(12653,23482734, 10)); +var_dump(gmp_div_q(1123123,123)); +var_dump(gmp_div_q(1123123,123, 1)); +var_dump(gmp_div_q(1123123,123, 2)); +var_dump(gmp_div_q(1123123,123, GMP_ROUND_ZERO)); +var_dump(gmp_div_q(1123123,123, GMP_ROUND_PLUSINF)); +var_dump(gmp_div_q(1123123,123, GMP_ROUND_MINUSINF)); $fp = fopen(__FILE__, 'r'); @@ -41,31 +32,46 @@ NULL Warning: gmp_div_q() expects at least 2 parameters, 1 given in %s on line %d NULL -resource(%d) of type (GMP integer) -string(1) "0" +object(GMP)#%d (1) { + ["num"]=> + string(1) "0" +} Warning: gmp_div_q(): Zero operand not allowed in %s on line %d bool(false) -resource(%d) of type (GMP integer) -string(1) "0" -NULL +object(GMP)#%d (1) { + ["num"]=> + string(1) "0" +} -Warning: gmp_strval(): Unable to convert variable to GMP - wrong type in %s on line %d +Warning: gmp_div_q(): Invalid rounding mode %s on line %d bool(false) -resource(%d) of type (GMP integer) -string(4) "9131" -resource(%d) of type (GMP integer) -string(4) "9132" -resource(%d) of type (GMP integer) -string(4) "9131" -resource(%d) of type (GMP integer) -string(4) "9131" -resource(%d) of type (GMP integer) -string(4) "9132" -resource(%d) of type (GMP integer) -string(4) "9131" +object(GMP)#%d (1) { + ["num"]=> + string(4) "9131" +} +object(GMP)#%d (1) { + ["num"]=> + string(4) "9132" +} +object(GMP)#%d (1) { + ["num"]=> + string(4) "9131" +} +object(GMP)#%d (1) { + ["num"]=> + string(4) "9131" +} +object(GMP)#%d (1) { + ["num"]=> + string(4) "9132" +} +object(GMP)#%d (1) { + ["num"]=> + string(4) "9131" +} -Warning: gmp_div_q(): supplied resource is not a valid GMP integer resource in %s on line %d +Warning: gmp_div_q(): Unable to convert variable to GMP - wrong type in %s on line %d bool(false) Warning: gmp_div_q(): Unable to convert variable to GMP - wrong type in %s on line %d diff --git a/ext/gmp/tests/010.phpt b/ext/gmp/tests/010.phpt index 293a2a0bf2..e3f85ec44f 100644 --- a/ext/gmp/tests/010.phpt +++ b/ext/gmp/tests/010.phpt @@ -28,13 +28,22 @@ NULL Warning: gmp_mod() expects exactly 2 parameters, 1 given in %s on line %d NULL bool(false) -int(0) -resource(%d) of type (GMP integer) +object(GMP)#%d (1) { + ["num"]=> + string(1) "0" +} +object(GMP)#%d (1) { + ["num"]=> + string(1) "0" +} Warning: gmp_mod(): Zero operand not allowed in %s on line %d bool(false) Warning: gmp_mod(): Unable to convert variable to GMP - wrong type in %s on line %d bool(false) -resource(%d) of type (GMP integer) +object(GMP)#%d (1) { + ["num"]=> + string(5) "31161" +} Done diff --git a/ext/gmp/tests/014.phpt b/ext/gmp/tests/014.phpt index 40e10c6fbe..6afccaf936 100644 --- a/ext/gmp/tests/014.phpt +++ b/ext/gmp/tests/014.phpt @@ -43,7 +43,7 @@ string(19) "2432902008176640000" string(65) "30414093201713378043612608166064768844377641568960512000000000000" string(7) "3628800" string(1) "1" -string(11) "87178291200" +string(9) "479001600" Warning: gmp_fact(): Number has to be greater than or equal to 0 in %s on line %d string(1) "0" @@ -53,6 +53,9 @@ NULL Warning: gmp_fact() expects exactly 1 parameter, 2 given in %s on line %d NULL -resource(%d) of type (GMP integer) +object(GMP)#%d (1) { + ["num"]=> + string(1) "1" +} string(1) "1" Done diff --git a/ext/gmp/tests/016.phpt b/ext/gmp/tests/016.phpt index 44360865ca..8a0b34458f 100644 --- a/ext/gmp/tests/016.phpt +++ b/ext/gmp/tests/016.phpt @@ -69,5 +69,8 @@ NULL Warning: gmp_powm(): Second parameter cannot be less than 0 in %s on line %d bool(false) -resource(%d) of type (GMP integer) +object(GMP)#%d (1) { + ["num"]=> + string(1) "1" +} Done diff --git a/ext/gmp/tests/033.phpt b/ext/gmp/tests/033.phpt index 38ff5be5bf..99848959d5 100644 --- a/ext/gmp/tests/033.phpt +++ b/ext/gmp/tests/033.phpt @@ -52,13 +52,13 @@ string(12) "100008388608" string(12) "100000000000" string(12) "100000000008" -Warning: gmp_setbit(): supplied argument is not a valid GMP integer resource in %s on line %d +Warning: gmp_setbit() expects parameter 1 to be GMP, string given in %s on line %d Warning: gmp_setbit() expects at least 2 parameters, 1 given in %s on line %d Warning: gmp_setbit() expects at most 3 parameters, 4 given in %s on line %d -Warning: gmp_setbit() expects parameter 2 to be long, array given in %s on line %d +Warning: gmp_setbit() expects parameter 1 to be GMP, string given in %s on line %d -Warning: gmp_setbit() expects parameter 2 to be long, array given in %s on line %d +Warning: gmp_setbit() expects parameter 1 to be GMP, array given in %s on line %d Done diff --git a/ext/gmp/tests/034.phpt b/ext/gmp/tests/034.phpt index 6011029905..079d5d669f 100644 --- a/ext/gmp/tests/034.phpt +++ b/ext/gmp/tests/034.phpt @@ -46,7 +46,7 @@ string(7) "1000000" string(7) "1000000" string(30) "238462734628347239571822592658" -Warning: gmp_clrbit(): supplied argument is not a valid GMP integer resource in %s on line %d +Warning: gmp_clrbit() expects parameter 1 to be GMP, array given in %s on line %d Warning: gmp_clrbit() expects exactly 2 parameters, 3 given in %s on line %d diff --git a/ext/gmp/tests/040.phpt b/ext/gmp/tests/040.phpt index 3af18cce59..9cc497edc6 100644 --- a/ext/gmp/tests/040.phpt +++ b/ext/gmp/tests/040.phpt @@ -18,7 +18,10 @@ var_dump(gmp_strval(gmp_init("993247326237679187178",3))); echo "Done\n"; ?> --EXPECTF-- -resource(%d) of type (GMP integer) +object(GMP)#%d (1) { + ["num"]=> + string(8) "98765678" +} string(8) "98765678" Warning: gmp_init() expects at least 1 parameter, 0 given in %s on line %d diff --git a/ext/gmp/tests/bug659967.phpt b/ext/gmp/tests/bug659967.phpt new file mode 100644 index 0000000000..6ba220274c --- /dev/null +++ b/ext/gmp/tests/bug659967.phpt @@ -0,0 +1,15 @@ +--TEST-- +Bug #65997: Leak when using gc_collect_cycles with new GMP implementation +--SKIPIF-- +<?php if (!extension_loaded("gmp")) print "skip"; ?> +--FILE-- +<?php + +gc_enable(); +$gmp = gmp_init('10'); +gc_collect_cycles(); + +?> +===DONE=== +--EXPECT-- +===DONE=== diff --git a/ext/gmp/tests/cast.phpt b/ext/gmp/tests/cast.phpt new file mode 100644 index 0000000000..eb1832c4dd --- /dev/null +++ b/ext/gmp/tests/cast.phpt @@ -0,0 +1,22 @@ +--TEST-- +GMP casting using casting operators +--SKIPIF-- +<?php if (!extension_loaded("gmp")) print "skip"; ?> +--FILE-- +<?php + +$n = gmp_init(42); +echo $n, "\n"; +var_dump((string) $n); +var_dump((int) $n); +var_dump((float) $n); +var_dump((bool) $n); + +?> +--EXPECTF-- +42 +string(2) "42" +int(42) +float(42) + +Catchable fatal error: Object of class GMP could not be converted to boolean in %s on line %d diff --git a/ext/gmp/tests/clone.phpt b/ext/gmp/tests/clone.phpt new file mode 100644 index 0000000000..56b5ca3dfe --- /dev/null +++ b/ext/gmp/tests/clone.phpt @@ -0,0 +1,22 @@ +--TEST-- +Cloning GMP instances +--SKIPIF-- +<?php if (!extension_loaded("gmp")) print "skip"; ?> +--FILE-- +<?php + +$a = gmp_init(3); +$b = clone $a; +gmp_clrbit($a, 0); +var_dump($a, $b); // $b should be unaffected + +?> +--EXPECTF-- +object(GMP)#1 (1) { + ["num"]=> + string(1) "2" +} +object(GMP)#2 (1) { + ["num"]=> + string(1) "3" +} diff --git a/ext/gmp/tests/comparison.phpt b/ext/gmp/tests/comparison.phpt new file mode 100644 index 0000000000..1f3a423267 --- /dev/null +++ b/ext/gmp/tests/comparison.phpt @@ -0,0 +1,37 @@ +--TEST-- +Overloaded GMP comparison in sort() etc +--SKIPIF-- +<?php if (!extension_loaded("gmp")) print "skip"; ?> +--FILE-- +<?php + +$arr = [gmp_init(0), -3, gmp_init(2), 1]; +sort($arr); +var_dump($arr); + +var_dump(min(gmp_init(3), 4)); +var_dump(max(gmp_init(3), 4)); + +?> +--EXPECT-- +array(4) { + [0]=> + int(-3) + [1]=> + object(GMP)#1 (1) { + ["num"]=> + string(1) "0" + } + [2]=> + int(1) + [3]=> + object(GMP)#2 (1) { + ["num"]=> + string(1) "2" + } +} +object(GMP)#3 (1) { + ["num"]=> + string(1) "3" +} +int(4) diff --git a/ext/gmp/tests/overloading.phpt b/ext/gmp/tests/overloading.phpt new file mode 100644 index 0000000000..18e0bb2aa9 --- /dev/null +++ b/ext/gmp/tests/overloading.phpt @@ -0,0 +1,259 @@ +--TEST-- +GMP operator overloading +--SKIPIF-- +<?php if (!extension_loaded("gmp")) print "skip"; ?> +--FILE-- +<?php + +$a = gmp_init(42); +$b = gmp_init(17); + +var_dump($a + $b); +var_dump($a + 17); +var_dump(42 + $b); + +var_dump($a - $b); +var_dump($a - 17); +var_dump(42 - $b); + +var_dump($a / $b); +var_dump($a / 17); +var_dump(42 / $b); +var_dump($a / 0); + +var_dump($a % $b); +var_dump($a % 17); +var_dump(42 % $b); +var_dump($a % 0); + +// sl, sr + +var_dump($a | $b); +var_dump($a | 17); +var_dump(42 | $b); + +var_dump($a & $b); +var_dump($a & 17); +var_dump(42 & $b); + +var_dump($a ^ $b); +var_dump($a ^ 17); +var_dump(42 ^ $b); + +var_dump($a << $b); +var_dump($a << 17); +var_dump(42 << $b); + +var_dump($a >> 2); +var_dump(-$a >> 2); + +var_dump(~$a); +var_dump(-$a); +var_dump(+$a); + +var_dump($a == $b); +var_dump($a != $b); +var_dump($a < $b); +var_dump($a <= $b); +var_dump($a > $b); +var_dump($a >= $b); + +var_dump($a == $a); +var_dump($a != $a); + +var_dump($a == 42); +var_dump($a != 42); +var_dump($a < 42); +var_dump($a <= 42); +var_dump($a > 42); +var_dump($a >= 42); + +var_dump($a == new stdClass); + +$a += 1; +var_dump($a); +$a -= 1; +var_dump($a); + +var_dump(++$a); +var_dump($a++); +var_dump($a); + +var_dump(--$a); +var_dump($a--); +var_dump($a); + +?> +--EXPECTF-- +object(GMP)#%d (1) { + ["num"]=> + string(2) "59" +} +object(GMP)#%d (1) { + ["num"]=> + string(2) "59" +} +object(GMP)#%d (1) { + ["num"]=> + string(2) "59" +} +object(GMP)#%d (1) { + ["num"]=> + string(2) "25" +} +object(GMP)#%d (1) { + ["num"]=> + string(2) "25" +} +object(GMP)#%d (1) { + ["num"]=> + string(2) "25" +} +object(GMP)#%d (1) { + ["num"]=> + string(1) "2" +} +object(GMP)#%d (1) { + ["num"]=> + string(1) "2" +} +object(GMP)#%d (1) { + ["num"]=> + string(1) "2" +} + +Warning: main(): Zero operand not allowed in %s on line %d +bool(false) +object(GMP)#%d (1) { + ["num"]=> + string(1) "8" +} +object(GMP)#%d (1) { + ["num"]=> + string(1) "8" +} +object(GMP)#%d (1) { + ["num"]=> + string(1) "8" +} + +Warning: main(): Zero operand not allowed in %s on line %d +bool(false) +object(GMP)#%d (1) { + ["num"]=> + string(2) "59" +} +object(GMP)#%d (1) { + ["num"]=> + string(2) "59" +} +object(GMP)#%d (1) { + ["num"]=> + string(2) "59" +} +object(GMP)#%d (1) { + ["num"]=> + string(1) "0" +} +object(GMP)#%d (1) { + ["num"]=> + string(1) "0" +} +object(GMP)#%d (1) { + ["num"]=> + string(1) "0" +} +object(GMP)#%d (1) { + ["num"]=> + string(2) "59" +} +object(GMP)#%d (1) { + ["num"]=> + string(2) "59" +} +object(GMP)#%d (1) { + ["num"]=> + string(2) "59" +} +object(GMP)#%d (1) { + ["num"]=> + string(7) "5505024" +} +object(GMP)#%d (1) { + ["num"]=> + string(7) "5505024" +} +object(GMP)#%d (1) { + ["num"]=> + string(7) "5505024" +} +object(GMP)#%d (1) { + ["num"]=> + string(2) "10" +} +object(GMP)#%d (1) { + ["num"]=> + string(3) "-11" +} +object(GMP)#%d (1) { + ["num"]=> + string(3) "-43" +} +object(GMP)#%d (1) { + ["num"]=> + string(3) "-42" +} +object(GMP)#%d (1) { + ["num"]=> + string(2) "42" +} +bool(false) +bool(true) +bool(false) +bool(false) +bool(true) +bool(true) +bool(true) +bool(false) +bool(true) +bool(false) +bool(false) +bool(true) +bool(false) +bool(true) + +Warning: main(): Unable to convert variable to GMP - wrong type in %s on line %d +bool(false) +object(GMP)#%d (1) { + ["num"]=> + string(2) "43" +} +object(GMP)#%d (1) { + ["num"]=> + string(2) "42" +} +object(GMP)#%d (1) { + ["num"]=> + string(2) "43" +} +object(GMP)#%d (1) { + ["num"]=> + string(2) "43" +} +object(GMP)#%d (1) { + ["num"]=> + string(2) "44" +} +object(GMP)#%d (1) { + ["num"]=> + string(2) "43" +} +object(GMP)#%d (1) { + ["num"]=> + string(2) "43" +} +object(GMP)#%d (1) { + ["num"]=> + string(2) "42" +} + diff --git a/ext/gmp/tests/serialize.phpt b/ext/gmp/tests/serialize.phpt new file mode 100644 index 0000000000..208e0e9800 --- /dev/null +++ b/ext/gmp/tests/serialize.phpt @@ -0,0 +1,42 @@ +--TEST-- +GMP serialization and unserialization +--SKIPIF-- +<?php if (!extension_loaded("gmp")) print "skip"; ?> +--FILE-- +<?php + +var_dump($n = gmp_init(42)); +var_dump($s = serialize($n)); +var_dump(unserialize($s)); + +$n = gmp_init(13); +$n->foo = "bar"; +var_dump(unserialize(serialize($n))); + +try { + unserialize('C:3:"GMP":0:{}'); +} catch (Exception $e) { var_dump($e->getMessage()); } + +try { + unserialize('C:3:"GMP":8:{s:2:"42"}'); +} catch (Exception $e) { var_dump($e->getMessage()); } + +?> +--EXPECTF-- +object(GMP)#%d (1) { + ["num"]=> + string(2) "42" +} +string(30) "C:3:"GMP":15:{s:2:"42";a:0:{}}" +object(GMP)#%d (1) { + ["num"]=> + string(2) "42" +} +object(GMP)#%d (2) { + ["foo"]=> + string(3) "bar" + ["num"]=> + string(2) "13" +} +string(28) "Could not unserialize number" +string(32) "Could not unserialize properties" diff --git a/ext/hash/config.m4 b/ext/hash/config.m4 index 44c6d267bc..5174db3b71 100644 --- a/ext/hash/config.m4 +++ b/ext/hash/config.m4 @@ -31,7 +31,7 @@ if test "$PHP_HASH" != "no"; then EXT_HASH_HEADERS="php_hash.h php_hash_md.h php_hash_sha.h php_hash_ripemd.h \ php_hash_haval.h php_hash_tiger.h php_hash_gost.h php_hash_snefru.h \ php_hash_whirlpool.h php_hash_adler32.h php_hash_crc32.h \ - php_hash_fnv.h php_hash_joaat.h php_hash_types.h" + php_hash_fnv.h php_hash_joaat.h" PHP_NEW_EXTENSION(hash, $EXT_HASH_SOURCES, $ext_shared) ifdef([PHP_INSTALL_HEADERS], [ diff --git a/ext/hash/config.w32 b/ext/hash/config.w32 index abe8675f30..8e9d4c3d48 100644 --- a/ext/hash/config.w32 +++ b/ext/hash/config.w32 @@ -19,7 +19,6 @@ if (PHP_HASH != "no") { PHP_INSTALL_HEADERS("ext/hash/", "php_hash.h php_hash_md.h php_hash_sha.h php_hash_ripemd.h " + "php_hash_haval.h php_hash_tiger.h php_hash_gost.h php_hash_snefru.h " + - "php_hash_whirlpool.h php_hash_adler32.h php_hash_crc32.h " + - "php_hash_types.h"); + "php_hash_whirlpool.h php_hash_adler32.h php_hash_crc32.h"); } diff --git a/ext/hash/hash.c b/ext/hash/hash.c index 117221484e..87f19c5cac 100644 --- a/ext/hash/hash.c +++ b/ext/hash/hash.c @@ -986,6 +986,7 @@ PHP_MINIT_FUNCTION(hash) php_hash_register_algo("snefru", &php_hash_snefru_ops); php_hash_register_algo("snefru256", &php_hash_snefru_ops); php_hash_register_algo("gost", &php_hash_gost_ops); + php_hash_register_algo("gost-crypto", &php_hash_gost_crypto_ops); php_hash_register_algo("adler32", &php_hash_adler32_ops); php_hash_register_algo("crc32", &php_hash_crc32_ops); php_hash_register_algo("crc32b", &php_hash_crc32b_ops); diff --git a/ext/hash/hash_gost.c b/ext/hash/hash_gost.c index 3961c4f2d5..da65bb5903 100644 --- a/ext/hash/hash_gost.c +++ b/ext/hash/hash_gost.c @@ -27,7 +27,7 @@ * derived from gost_compress() by Markku-Juhani Saarinen <mjos@ssh.fi> */ -#define round(k1, k2) \ +#define round(tables, k1, k2) \ t = (k1) + r; \ l ^= tables[0][t & 0xff] ^ tables[1][(t >> 8) & 0xff] ^ \ tables[2][(t >> 16) & 0xff] ^ tables[3][t >> 24]; \ @@ -35,25 +35,25 @@ r ^= tables[0][t & 0xff] ^ tables[1][(t >> 8) & 0xff] ^ \ tables[2][(t >> 16) & 0xff] ^ tables[3][t >> 24]; -#define R(key, h, i, t, l, r) \ +#define R(tables, key, h, i, t, l, r) \ r = h[i]; \ l = h[i + 1]; \ - round(key[0], key[1]) \ - round(key[2], key[3]) \ - round(key[4], key[5]) \ - round(key[6], key[7]) \ - round(key[0], key[1]) \ - round(key[2], key[3]) \ - round(key[4], key[5]) \ - round(key[6], key[7]) \ - round(key[0], key[1]) \ - round(key[2], key[3]) \ - round(key[4], key[5]) \ - round(key[6], key[7]) \ - round(key[7], key[6]) \ - round(key[5], key[4]) \ - round(key[3], key[2]) \ - round(key[1], key[0]) \ + round(tables, key[0], key[1]) \ + round(tables, key[2], key[3]) \ + round(tables, key[4], key[5]) \ + round(tables, key[6], key[7]) \ + round(tables, key[0], key[1]) \ + round(tables, key[2], key[3]) \ + round(tables, key[4], key[5]) \ + round(tables, key[6], key[7]) \ + round(tables, key[0], key[1]) \ + round(tables, key[2], key[3]) \ + round(tables, key[4], key[5]) \ + round(tables, key[6], key[7]) \ + round(tables, key[7], key[6]) \ + round(tables, key[5], key[4]) \ + round(tables, key[3], key[2]) \ + round(tables, key[1], key[0]) \ t = r; \ r = l; \ l = t; \ @@ -194,10 +194,10 @@ (v[3] >> 16) ^ v[3] ^ (v[4] << 16) ^ v[4] ^ (v[5] >> 16) ^ v[5] ^ \ (v[6] << 16) ^ (v[6] >> 16) ^ (v[7] << 16) ^ v[7]; -#define PASS \ +#define PASS(tables) \ X(w, u, v); \ P(key, w); \ - R(key, h, i, t, l, r); \ + R((tables), key, h, i, t, l, r); \ S(s, l, r); \ if (i != 6) { \ A(u, l, r); \ @@ -207,16 +207,16 @@ AA(v, l, r); \ } -static inline void Gost(php_hash_uint32 state[8], php_hash_uint32 data[8]) +static inline void Gost(PHP_GOST_CTX *context, php_hash_uint32 data[8]) { int i; - php_hash_uint32 l, r, t, key[8], u[8], v[8], w[8], s[8], *h = state, *m = data; + php_hash_uint32 l, r, t, key[8], u[8], v[8], w[8], s[8], *h = context->state, *m = data; - memcpy(u, state, sizeof(u)); + memcpy(u, context->state, sizeof(u)); memcpy(v, data, sizeof(v)); for (i = 0; i < 8; i += 2) { - PASS; + PASS(*context->tables); } SHIFT12(u, m, s); SHIFT16(h, v, u); @@ -237,12 +237,19 @@ static inline void GostTransform(PHP_GOST_CTX *context, const unsigned char inpu temp = ((context->state[i + 8] < data[i]) || (context->state[i + 8] < save)) ? 1 : 0; } - Gost(context->state, data); + Gost(context, data); } PHP_HASH_API void PHP_GOSTInit(PHP_GOST_CTX *context) { memset(context, 0, sizeof(*context)); + context->tables = &tables_test; +} + +PHP_HASH_API void PHP_GOSTInitCrypto(PHP_GOST_CTX *context) +{ + PHP_GOSTInit(context); + context->tables = &tables_crypto; } static const php_hash_uint32 MAX32 = 0xffffffffLU; @@ -288,9 +295,9 @@ PHP_HASH_API void PHP_GOSTFinal(unsigned char digest[32], PHP_GOST_CTX *context) } memcpy(l, context->count, sizeof(context->count)); - Gost(context->state, l); + Gost(context, l); memcpy(l, &context->state[8], sizeof(l)); - Gost(context->state, l); + Gost(context, l); for (i = 0, j = 0; j < 32; i++, j += 4) { digest[j] = (unsigned char) (context->state[i] & 0xff); @@ -312,6 +319,16 @@ const php_hash_ops php_hash_gost_ops = { sizeof(PHP_GOST_CTX) }; +const php_hash_ops php_hash_gost_crypto_ops = { + (php_hash_init_func_t) PHP_GOSTInitCrypto, + (php_hash_update_func_t) PHP_GOSTUpdate, + (php_hash_final_func_t) PHP_GOSTFinal, + (php_hash_copy_func_t) php_hash_copy, + 32, + 32, + sizeof(PHP_GOST_CTX) +}; + /* * Local variables: * tab-width: 4 diff --git a/ext/hash/package.xml b/ext/hash/package.xml index 119cdd673d..25a598a4a1 100644 --- a/ext/hash/package.xml +++ b/ext/hash/package.xml @@ -42,7 +42,6 @@ Supported Algorithms: <file role="src" name="config.w32"/> <file role="src" name="hash.c"/> <file role="src" name="php_hash.h"/> - <file role="src" name="php_hash_types.h"/> <file role="src" name="hash_md.c"/> <file role="src" name="php_hash_md.h"/> <file role="src" name="hash_sha.c"/> diff --git a/ext/hash/php_hash.h b/ext/hash/php_hash.h index 4bfddbacd9..e92572216a 100644 --- a/ext/hash/php_hash.h +++ b/ext/hash/php_hash.h @@ -22,7 +22,6 @@ #define PHP_HASH_H #include "php.h" -#include "php_hash_types.h" #define PHP_HASH_EXTNAME "hash" #define PHP_HASH_EXTVER "1.0" @@ -30,6 +29,12 @@ #define PHP_HASH_HMAC 0x0001 +#define L64 INT64_C +#define php_hash_int32 int32_t +#define php_hash_uint32 uint32_t +#define php_hash_int64 int64_t +#define php_hash_uint64 uint64_t + typedef void (*php_hash_init_func_t)(void *context); typedef void (*php_hash_update_func_t)(void *context, const unsigned char *buf, unsigned int count); typedef void (*php_hash_final_func_t)(unsigned char *digest, void *context); @@ -75,6 +80,7 @@ extern const php_hash_ops php_hash_4tiger160_ops; extern const php_hash_ops php_hash_4tiger192_ops; extern const php_hash_ops php_hash_snefru_ops; extern const php_hash_ops php_hash_gost_ops; +extern const php_hash_ops php_hash_gost_crypto_ops; extern const php_hash_ops php_hash_adler32_ops; extern const php_hash_ops php_hash_crc32_ops; extern const php_hash_ops php_hash_crc32b_ops; diff --git a/ext/hash/php_hash_gost.h b/ext/hash/php_hash_gost.h index 6a4af310dc..a9c137530c 100644 --- a/ext/hash/php_hash_gost.h +++ b/ext/hash/php_hash_gost.h @@ -29,6 +29,7 @@ typedef struct { php_hash_uint32 count[2]; unsigned char length; unsigned char buffer[32]; + const php_hash_uint32 (*tables)[4][256]; } PHP_GOST_CTX; PHP_HASH_API void PHP_GOSTInit(PHP_GOST_CTX *); diff --git a/ext/hash/php_hash_gost_tables.h b/ext/hash/php_hash_gost_tables.h index 5d05e593cb..a00d8b7490 100644 --- a/ext/hash/php_hash_gost_tables.h +++ b/ext/hash/php_hash_gost_tables.h @@ -1,4 +1,4 @@ -static const php_hash_uint32 tables[4][256] = { +static const php_hash_uint32 tables_test[4][256] = { { /* table 1 */ 0x00072000LU, 0x00075000LU, 0x00074800LU, 0x00071000LU, 0x00076800LU, 0x00074000LU, 0x00070000LU, 0x00077000LU, 0x00073000LU, 0x00075800LU, 0x00070800LU, 0x00076000LU, 0x00073800LU, 0x00077800LU, 0x00072800LU, 0x00071800LU, @@ -136,3 +136,142 @@ static const php_hash_uint32 tables[4][256] = { 0x00000600LU, 0x00000650LU, 0x00000670LU, 0x00000638LU, 0x00000630LU, 0x00000640LU, 0x00000610LU, 0x00000660LU, }, }; + +static const php_hash_uint32 tables_crypto[4][256] = { + { /* table 1 */ + 0x0002d000LU, 0x0002a000LU, 0x0002a800LU, 0x0002b000LU, 0x0002c000LU, 0x00028800LU, 0x00029800LU, 0x0002b800LU, + 0x0002e800LU, 0x0002e000LU, 0x0002f000LU, 0x00028000LU, 0x0002c800LU, 0x00029000LU, 0x0002d800LU, 0x0002f800LU, + 0x0007d000LU, 0x0007a000LU, 0x0007a800LU, 0x0007b000LU, 0x0007c000LU, 0x00078800LU, 0x00079800LU, 0x0007b800LU, + 0x0007e800LU, 0x0007e000LU, 0x0007f000LU, 0x00078000LU, 0x0007c800LU, 0x00079000LU, 0x0007d800LU, 0x0007f800LU, + 0x00025000LU, 0x00022000LU, 0x00022800LU, 0x00023000LU, 0x00024000LU, 0x00020800LU, 0x00021800LU, 0x00023800LU, + 0x00026800LU, 0x00026000LU, 0x00027000LU, 0x00020000LU, 0x00024800LU, 0x00021000LU, 0x00025800LU, 0x00027800LU, + 0x00005000LU, 0x00002000LU, 0x00002800LU, 0x00003000LU, 0x00004000LU, 0x00000800LU, 0x00001800LU, 0x00003800LU, + 0x00006800LU, 0x00006000LU, 0x00007000LU, 0x00000000LU, 0x00004800LU, 0x00001000LU, 0x00005800LU, 0x00007800LU, + 0x00015000LU, 0x00012000LU, 0x00012800LU, 0x00013000LU, 0x00014000LU, 0x00010800LU, 0x00011800LU, 0x00013800LU, + 0x00016800LU, 0x00016000LU, 0x00017000LU, 0x00010000LU, 0x00014800LU, 0x00011000LU, 0x00015800LU, 0x00017800LU, + 0x0006d000LU, 0x0006a000LU, 0x0006a800LU, 0x0006b000LU, 0x0006c000LU, 0x00068800LU, 0x00069800LU, 0x0006b800LU, + 0x0006e800LU, 0x0006e000LU, 0x0006f000LU, 0x00068000LU, 0x0006c800LU, 0x00069000LU, 0x0006d800LU, 0x0006f800LU, + 0x0005d000LU, 0x0005a000LU, 0x0005a800LU, 0x0005b000LU, 0x0005c000LU, 0x00058800LU, 0x00059800LU, 0x0005b800LU, + 0x0005e800LU, 0x0005e000LU, 0x0005f000LU, 0x00058000LU, 0x0005c800LU, 0x00059000LU, 0x0005d800LU, 0x0005f800LU, + 0x0004d000LU, 0x0004a000LU, 0x0004a800LU, 0x0004b000LU, 0x0004c000LU, 0x00048800LU, 0x00049800LU, 0x0004b800LU, + 0x0004e800LU, 0x0004e000LU, 0x0004f000LU, 0x00048000LU, 0x0004c800LU, 0x00049000LU, 0x0004d800LU, 0x0004f800LU, + 0x0000d000LU, 0x0000a000LU, 0x0000a800LU, 0x0000b000LU, 0x0000c000LU, 0x00008800LU, 0x00009800LU, 0x0000b800LU, + 0x0000e800LU, 0x0000e000LU, 0x0000f000LU, 0x00008000LU, 0x0000c800LU, 0x00009000LU, 0x0000d800LU, 0x0000f800LU, + 0x0003d000LU, 0x0003a000LU, 0x0003a800LU, 0x0003b000LU, 0x0003c000LU, 0x00038800LU, 0x00039800LU, 0x0003b800LU, + 0x0003e800LU, 0x0003e000LU, 0x0003f000LU, 0x00038000LU, 0x0003c800LU, 0x00039000LU, 0x0003d800LU, 0x0003f800LU, + 0x00035000LU, 0x00032000LU, 0x00032800LU, 0x00033000LU, 0x00034000LU, 0x00030800LU, 0x00031800LU, 0x00033800LU, + 0x00036800LU, 0x00036000LU, 0x00037000LU, 0x00030000LU, 0x00034800LU, 0x00031000LU, 0x00035800LU, 0x00037800LU, + 0x0001d000LU, 0x0001a000LU, 0x0001a800LU, 0x0001b000LU, 0x0001c000LU, 0x00018800LU, 0x00019800LU, 0x0001b800LU, + 0x0001e800LU, 0x0001e000LU, 0x0001f000LU, 0x00018000LU, 0x0001c800LU, 0x00019000LU, 0x0001d800LU, 0x0001f800LU, + 0x00065000LU, 0x00062000LU, 0x00062800LU, 0x00063000LU, 0x00064000LU, 0x00060800LU, 0x00061800LU, 0x00063800LU, + 0x00066800LU, 0x00066000LU, 0x00067000LU, 0x00060000LU, 0x00064800LU, 0x00061000LU, 0x00065800LU, 0x00067800LU, + 0x00075000LU, 0x00072000LU, 0x00072800LU, 0x00073000LU, 0x00074000LU, 0x00070800LU, 0x00071800LU, 0x00073800LU, + 0x00076800LU, 0x00076000LU, 0x00077000LU, 0x00070000LU, 0x00074800LU, 0x00071000LU, 0x00075800LU, 0x00077800LU, + 0x00055000LU, 0x00052000LU, 0x00052800LU, 0x00053000LU, 0x00054000LU, 0x00050800LU, 0x00051800LU, 0x00053800LU, + 0x00056800LU, 0x00056000LU, 0x00057000LU, 0x00050000LU, 0x00054800LU, 0x00051000LU, 0x00055800LU, 0x00057800LU, + 0x00045000LU, 0x00042000LU, 0x00042800LU, 0x00043000LU, 0x00044000LU, 0x00040800LU, 0x00041800LU, 0x00043800LU, + 0x00046800LU, 0x00046000LU, 0x00047000LU, 0x00040000LU, 0x00044800LU, 0x00041000LU, 0x00045800LU, 0x00047800LU, + }, + { /* table 2 */ + 0x02380000LU, 0x02780000LU, 0x02600000LU, 0x02700000LU, 0x02480000LU, 0x02200000LU, 0x02080000LU, 0x02000000LU, + 0x02180000LU, 0x02580000LU, 0x02280000LU, 0x02100000LU, 0x02300000LU, 0x02500000LU, 0x02400000LU, 0x02680000LU, + 0x05380000LU, 0x05780000LU, 0x05600000LU, 0x05700000LU, 0x05480000LU, 0x05200000LU, 0x05080000LU, 0x05000000LU, + 0x05180000LU, 0x05580000LU, 0x05280000LU, 0x05100000LU, 0x05300000LU, 0x05500000LU, 0x05400000LU, 0x05680000LU, + 0x03b80000LU, 0x03f80000LU, 0x03e00000LU, 0x03f00000LU, 0x03c80000LU, 0x03a00000LU, 0x03880000LU, 0x03800000LU, + 0x03980000LU, 0x03d80000LU, 0x03a80000LU, 0x03900000LU, 0x03b00000LU, 0x03d00000LU, 0x03c00000LU, 0x03e80000LU, + 0x06380000LU, 0x06780000LU, 0x06600000LU, 0x06700000LU, 0x06480000LU, 0x06200000LU, 0x06080000LU, 0x06000000LU, + 0x06180000LU, 0x06580000LU, 0x06280000LU, 0x06100000LU, 0x06300000LU, 0x06500000LU, 0x06400000LU, 0x06680000LU, + 0x00380000LU, 0x00780000LU, 0x00600000LU, 0x00700000LU, 0x00480000LU, 0x00200000LU, 0x00080000LU, 0x00000000LU, + 0x00180000LU, 0x00580000LU, 0x00280000LU, 0x00100000LU, 0x00300000LU, 0x00500000LU, 0x00400000LU, 0x00680000LU, + 0x07b80000LU, 0x07f80000LU, 0x07e00000LU, 0x07f00000LU, 0x07c80000LU, 0x07a00000LU, 0x07880000LU, 0x07800000LU, + 0x07980000LU, 0x07d80000LU, 0x07a80000LU, 0x07900000LU, 0x07b00000LU, 0x07d00000LU, 0x07c00000LU, 0x07e80000LU, + 0x01380000LU, 0x01780000LU, 0x01600000LU, 0x01700000LU, 0x01480000LU, 0x01200000LU, 0x01080000LU, 0x01000000LU, + 0x01180000LU, 0x01580000LU, 0x01280000LU, 0x01100000LU, 0x01300000LU, 0x01500000LU, 0x01400000LU, 0x01680000LU, + 0x04380000LU, 0x04780000LU, 0x04600000LU, 0x04700000LU, 0x04480000LU, 0x04200000LU, 0x04080000LU, 0x04000000LU, + 0x04180000LU, 0x04580000LU, 0x04280000LU, 0x04100000LU, 0x04300000LU, 0x04500000LU, 0x04400000LU, 0x04680000LU, + 0x07380000LU, 0x07780000LU, 0x07600000LU, 0x07700000LU, 0x07480000LU, 0x07200000LU, 0x07080000LU, 0x07000000LU, + 0x07180000LU, 0x07580000LU, 0x07280000LU, 0x07100000LU, 0x07300000LU, 0x07500000LU, 0x07400000LU, 0x07680000LU, + 0x00b80000LU, 0x00f80000LU, 0x00e00000LU, 0x00f00000LU, 0x00c80000LU, 0x00a00000LU, 0x00880000LU, 0x00800000LU, + 0x00980000LU, 0x00d80000LU, 0x00a80000LU, 0x00900000LU, 0x00b00000LU, 0x00d00000LU, 0x00c00000LU, 0x00e80000LU, + 0x03380000LU, 0x03780000LU, 0x03600000LU, 0x03700000LU, 0x03480000LU, 0x03200000LU, 0x03080000LU, 0x03000000LU, + 0x03180000LU, 0x03580000LU, 0x03280000LU, 0x03100000LU, 0x03300000LU, 0x03500000LU, 0x03400000LU, 0x03680000LU, + 0x02b80000LU, 0x02f80000LU, 0x02e00000LU, 0x02f00000LU, 0x02c80000LU, 0x02a00000LU, 0x02880000LU, 0x02800000LU, + 0x02980000LU, 0x02d80000LU, 0x02a80000LU, 0x02900000LU, 0x02b00000LU, 0x02d00000LU, 0x02c00000LU, 0x02e80000LU, + 0x06b80000LU, 0x06f80000LU, 0x06e00000LU, 0x06f00000LU, 0x06c80000LU, 0x06a00000LU, 0x06880000LU, 0x06800000LU, + 0x06980000LU, 0x06d80000LU, 0x06a80000LU, 0x06900000LU, 0x06b00000LU, 0x06d00000LU, 0x06c00000LU, 0x06e80000LU, + 0x05b80000LU, 0x05f80000LU, 0x05e00000LU, 0x05f00000LU, 0x05c80000LU, 0x05a00000LU, 0x05880000LU, 0x05800000LU, + 0x05980000LU, 0x05d80000LU, 0x05a80000LU, 0x05900000LU, 0x05b00000LU, 0x05d00000LU, 0x05c00000LU, 0x05e80000LU, + 0x04b80000LU, 0x04f80000LU, 0x04e00000LU, 0x04f00000LU, 0x04c80000LU, 0x04a00000LU, 0x04880000LU, 0x04800000LU, + 0x04980000LU, 0x04d80000LU, 0x04a80000LU, 0x04900000LU, 0x04b00000LU, 0x04d00000LU, 0x04c00000LU, 0x04e80000LU, + 0x01b80000LU, 0x01f80000LU, 0x01e00000LU, 0x01f00000LU, 0x01c80000LU, 0x01a00000LU, 0x01880000LU, 0x01800000LU, + 0x01980000LU, 0x01d80000LU, 0x01a80000LU, 0x01900000LU, 0x01b00000LU, 0x01d00000LU, 0x01c00000LU, 0x01e80000LU, + }, + { /* table 3 */ + 0xb8000003LU, 0xb0000003LU, 0xa0000003LU, 0xd8000003LU, 0xc8000003LU, 0xe0000003LU, 0x90000003LU, 0xd0000003LU, + 0x88000003LU, 0xc0000003LU, 0x80000003LU, 0xf0000003LU, 0xf8000003LU, 0xe8000003LU, 0x98000003LU, 0xa8000003LU, + 0x38000003LU, 0x30000003LU, 0x20000003LU, 0x58000003LU, 0x48000003LU, 0x60000003LU, 0x10000003LU, 0x50000003LU, + 0x08000003LU, 0x40000003LU, 0x00000003LU, 0x70000003LU, 0x78000003LU, 0x68000003LU, 0x18000003LU, 0x28000003LU, + 0x38000001LU, 0x30000001LU, 0x20000001LU, 0x58000001LU, 0x48000001LU, 0x60000001LU, 0x10000001LU, 0x50000001LU, + 0x08000001LU, 0x40000001LU, 0x00000001LU, 0x70000001LU, 0x78000001LU, 0x68000001LU, 0x18000001LU, 0x28000001LU, + 0x38000002LU, 0x30000002LU, 0x20000002LU, 0x58000002LU, 0x48000002LU, 0x60000002LU, 0x10000002LU, 0x50000002LU, + 0x08000002LU, 0x40000002LU, 0x00000002LU, 0x70000002LU, 0x78000002LU, 0x68000002LU, 0x18000002LU, 0x28000002LU, + 0xb8000006LU, 0xb0000006LU, 0xa0000006LU, 0xd8000006LU, 0xc8000006LU, 0xe0000006LU, 0x90000006LU, 0xd0000006LU, + 0x88000006LU, 0xc0000006LU, 0x80000006LU, 0xf0000006LU, 0xf8000006LU, 0xe8000006LU, 0x98000006LU, 0xa8000006LU, + 0xb8000004LU, 0xb0000004LU, 0xa0000004LU, 0xd8000004LU, 0xc8000004LU, 0xe0000004LU, 0x90000004LU, 0xd0000004LU, + 0x88000004LU, 0xc0000004LU, 0x80000004LU, 0xf0000004LU, 0xf8000004LU, 0xe8000004LU, 0x98000004LU, 0xa8000004LU, + 0xb8000007LU, 0xb0000007LU, 0xa0000007LU, 0xd8000007LU, 0xc8000007LU, 0xe0000007LU, 0x90000007LU, 0xd0000007LU, + 0x88000007LU, 0xc0000007LU, 0x80000007LU, 0xf0000007LU, 0xf8000007LU, 0xe8000007LU, 0x98000007LU, 0xa8000007LU, + 0x38000000LU, 0x30000000LU, 0x20000000LU, 0x58000000LU, 0x48000000LU, 0x60000000LU, 0x10000000LU, 0x50000000LU, + 0x08000000LU, 0x40000000LU, 0x00000000LU, 0x70000000LU, 0x78000000LU, 0x68000000LU, 0x18000000LU, 0x28000000LU, + 0x38000005LU, 0x30000005LU, 0x20000005LU, 0x58000005LU, 0x48000005LU, 0x60000005LU, 0x10000005LU, 0x50000005LU, + 0x08000005LU, 0x40000005LU, 0x00000005LU, 0x70000005LU, 0x78000005LU, 0x68000005LU, 0x18000005LU, 0x28000005LU, + 0xb8000000LU, 0xb0000000LU, 0xa0000000LU, 0xd8000000LU, 0xc8000000LU, 0xe0000000LU, 0x90000000LU, 0xd0000000LU, + 0x88000000LU, 0xc0000000LU, 0x80000000LU, 0xf0000000LU, 0xf8000000LU, 0xe8000000LU, 0x98000000LU, 0xa8000000LU, + 0xb8000002LU, 0xb0000002LU, 0xa0000002LU, 0xd8000002LU, 0xc8000002LU, 0xe0000002LU, 0x90000002LU, 0xd0000002LU, + 0x88000002LU, 0xc0000002LU, 0x80000002LU, 0xf0000002LU, 0xf8000002LU, 0xe8000002LU, 0x98000002LU, 0xa8000002LU, + 0xb8000005LU, 0xb0000005LU, 0xa0000005LU, 0xd8000005LU, 0xc8000005LU, 0xe0000005LU, 0x90000005LU, 0xd0000005LU, + 0x88000005LU, 0xc0000005LU, 0x80000005LU, 0xf0000005LU, 0xf8000005LU, 0xe8000005LU, 0x98000005LU, 0xa8000005LU, + 0x38000004LU, 0x30000004LU, 0x20000004LU, 0x58000004LU, 0x48000004LU, 0x60000004LU, 0x10000004LU, 0x50000004LU, + 0x08000004LU, 0x40000004LU, 0x00000004LU, 0x70000004LU, 0x78000004LU, 0x68000004LU, 0x18000004LU, 0x28000004LU, + 0x38000007LU, 0x30000007LU, 0x20000007LU, 0x58000007LU, 0x48000007LU, 0x60000007LU, 0x10000007LU, 0x50000007LU, + 0x08000007LU, 0x40000007LU, 0x00000007LU, 0x70000007LU, 0x78000007LU, 0x68000007LU, 0x18000007LU, 0x28000007LU, + 0x38000006LU, 0x30000006LU, 0x20000006LU, 0x58000006LU, 0x48000006LU, 0x60000006LU, 0x10000006LU, 0x50000006LU, + 0x08000006LU, 0x40000006LU, 0x00000006LU, 0x70000006LU, 0x78000006LU, 0x68000006LU, 0x18000006LU, 0x28000006LU, + 0xb8000001LU, 0xb0000001LU, 0xa0000001LU, 0xd8000001LU, 0xc8000001LU, 0xe0000001LU, 0x90000001LU, 0xd0000001LU, + 0x88000001LU, 0xc0000001LU, 0x80000001LU, 0xf0000001LU, 0xf8000001LU, 0xe8000001LU, 0x98000001LU, 0xa8000001LU, + }, + { /* table 4 */ + 0x000000e8LU, 0x000000f0LU, 0x000000a0LU, 0x00000088LU, 0x000000b8LU, 0x00000080LU, 0x000000a8LU, 0x000000d0LU, + 0x00000098LU, 0x000000e0LU, 0x000000c0LU, 0x000000f8LU, 0x000000b0LU, 0x00000090LU, 0x000000c8LU, 0x000000d8LU, + 0x000001e8LU, 0x000001f0LU, 0x000001a0LU, 0x00000188LU, 0x000001b8LU, 0x00000180LU, 0x000001a8LU, 0x000001d0LU, + 0x00000198LU, 0x000001e0LU, 0x000001c0LU, 0x000001f8LU, 0x000001b0LU, 0x00000190LU, 0x000001c8LU, 0x000001d8LU, + 0x00000568LU, 0x00000570LU, 0x00000520LU, 0x00000508LU, 0x00000538LU, 0x00000500LU, 0x00000528LU, 0x00000550LU, + 0x00000518LU, 0x00000560LU, 0x00000540LU, 0x00000578LU, 0x00000530LU, 0x00000510LU, 0x00000548LU, 0x00000558LU, + 0x000004e8LU, 0x000004f0LU, 0x000004a0LU, 0x00000488LU, 0x000004b8LU, 0x00000480LU, 0x000004a8LU, 0x000004d0LU, + 0x00000498LU, 0x000004e0LU, 0x000004c0LU, 0x000004f8LU, 0x000004b0LU, 0x00000490LU, 0x000004c8LU, 0x000004d8LU, + 0x000002e8LU, 0x000002f0LU, 0x000002a0LU, 0x00000288LU, 0x000002b8LU, 0x00000280LU, 0x000002a8LU, 0x000002d0LU, + 0x00000298LU, 0x000002e0LU, 0x000002c0LU, 0x000002f8LU, 0x000002b0LU, 0x00000290LU, 0x000002c8LU, 0x000002d8LU, + 0x000005e8LU, 0x000005f0LU, 0x000005a0LU, 0x00000588LU, 0x000005b8LU, 0x00000580LU, 0x000005a8LU, 0x000005d0LU, + 0x00000598LU, 0x000005e0LU, 0x000005c0LU, 0x000005f8LU, 0x000005b0LU, 0x00000590LU, 0x000005c8LU, 0x000005d8LU, + 0x00000268LU, 0x00000270LU, 0x00000220LU, 0x00000208LU, 0x00000238LU, 0x00000200LU, 0x00000228LU, 0x00000250LU, + 0x00000218LU, 0x00000260LU, 0x00000240LU, 0x00000278LU, 0x00000230LU, 0x00000210LU, 0x00000248LU, 0x00000258LU, + 0x000007e8LU, 0x000007f0LU, 0x000007a0LU, 0x00000788LU, 0x000007b8LU, 0x00000780LU, 0x000007a8LU, 0x000007d0LU, + 0x00000798LU, 0x000007e0LU, 0x000007c0LU, 0x000007f8LU, 0x000007b0LU, 0x00000790LU, 0x000007c8LU, 0x000007d8LU, + 0x00000468LU, 0x00000470LU, 0x00000420LU, 0x00000408LU, 0x00000438LU, 0x00000400LU, 0x00000428LU, 0x00000450LU, + 0x00000418LU, 0x00000460LU, 0x00000440LU, 0x00000478LU, 0x00000430LU, 0x00000410LU, 0x00000448LU, 0x00000458LU, + 0x00000368LU, 0x00000370LU, 0x00000320LU, 0x00000308LU, 0x00000338LU, 0x00000300LU, 0x00000328LU, 0x00000350LU, + 0x00000318LU, 0x00000360LU, 0x00000340LU, 0x00000378LU, 0x00000330LU, 0x00000310LU, 0x00000348LU, 0x00000358LU, + 0x000003e8LU, 0x000003f0LU, 0x000003a0LU, 0x00000388LU, 0x000003b8LU, 0x00000380LU, 0x000003a8LU, 0x000003d0LU, + 0x00000398LU, 0x000003e0LU, 0x000003c0LU, 0x000003f8LU, 0x000003b0LU, 0x00000390LU, 0x000003c8LU, 0x000003d8LU, + 0x00000768LU, 0x00000770LU, 0x00000720LU, 0x00000708LU, 0x00000738LU, 0x00000700LU, 0x00000728LU, 0x00000750LU, + 0x00000718LU, 0x00000760LU, 0x00000740LU, 0x00000778LU, 0x00000730LU, 0x00000710LU, 0x00000748LU, 0x00000758LU, + 0x000006e8LU, 0x000006f0LU, 0x000006a0LU, 0x00000688LU, 0x000006b8LU, 0x00000680LU, 0x000006a8LU, 0x000006d0LU, + 0x00000698LU, 0x000006e0LU, 0x000006c0LU, 0x000006f8LU, 0x000006b0LU, 0x00000690LU, 0x000006c8LU, 0x000006d8LU, + 0x00000068LU, 0x00000070LU, 0x00000020LU, 0x00000008LU, 0x00000038LU, 0x00000000LU, 0x00000028LU, 0x00000050LU, + 0x00000018LU, 0x00000060LU, 0x00000040LU, 0x00000078LU, 0x00000030LU, 0x00000010LU, 0x00000048LU, 0x00000058LU, + 0x00000168LU, 0x00000170LU, 0x00000120LU, 0x00000108LU, 0x00000138LU, 0x00000100LU, 0x00000128LU, 0x00000150LU, + 0x00000118LU, 0x00000160LU, 0x00000140LU, 0x00000178LU, 0x00000130LU, 0x00000110LU, 0x00000148LU, 0x00000158LU, + 0x00000668LU, 0x00000670LU, 0x00000620LU, 0x00000608LU, 0x00000638LU, 0x00000600LU, 0x00000628LU, 0x00000650LU, + 0x00000618LU, 0x00000660LU, 0x00000640LU, 0x00000678LU, 0x00000630LU, 0x00000610LU, 0x00000648LU, 0x00000658LU, + }, +}; diff --git a/ext/hash/php_hash_types.h b/ext/hash/php_hash_types.h deleted file mode 100644 index 8793da55d6..0000000000 --- a/ext/hash/php_hash_types.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2013 The PHP Group | - +----------------------------------------------------------------------+ - | 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 | - | available through the world-wide-web at the following url: | - | http://www.php.net/license/3_01.txt | - | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Author: Michael Wallner <mike@php.net> | - +----------------------------------------------------------------------+ -*/ - -/* $Id$ */ - -#ifndef PHP_HASH_TYPES_H -#define PHP_HASH_TYPES_H - -#ifdef HAVE_CONFIG_H -#include "config.h" -#else -#ifndef PHP_WIN32 -#include "php_config.h" -#endif -#endif - -#ifndef PHP_WIN32 -#if SIZEOF_LONG == 8 -#define L64(x) x -typedef unsigned long php_hash_uint64; -#if SIZEOF_INT == 4 -typedef unsigned int php_hash_uint32; -#elif SIZEOF_SHORT == 4 -typedef unsigned short php_hash_uint32; -#else -#error "Need a 32bit integer type" -#endif -#elif SIZEOF_LONG_LONG == 8 -#define L64(x) x##LL -typedef unsigned long long php_hash_uint64; -#if SIZEOF_INT == 4 -typedef unsigned int php_hash_uint32; -#elif SIZEOF_LONG == 4 -typedef unsigned long php_hash_uint32; -#else -#error "Need a 32bit integer type" -#endif -#else -#error "Need a 64bit integer type" -#endif -#else -#define L64(x) x##i64 -typedef unsigned __int64 php_hash_uint64; -typedef unsigned __int32 php_hash_uint32; -#endif - -#endif - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/ext/hash/tests/gost.phpt b/ext/hash/tests/gost.phpt index b800e112e8..6ce00242b1 100644 --- a/ext/hash/tests/gost.phpt +++ b/ext/hash/tests/gost.phpt @@ -10,6 +10,13 @@ echo hash('gost', 'The quick brown fox jumps over the lazy cog'), "\n"; echo hash('gost', str_repeat('a', 31)), "\n"; echo hash('gost', str_repeat('a', 32)), "\n"; echo hash('gost', str_repeat('a', 33)), "\n"; + +echo hash('gost-crypto', ''), "\n"; +echo hash('gost-crypto', 'The quick brown fox jumps over the lazy dog'), "\n"; +echo hash('gost-crypto', 'The quick brown fox jumps over the lazy cog'), "\n"; +echo hash('gost-crypto', str_repeat('a', 31)), "\n"; +echo hash('gost-crypto', str_repeat('a', 32)), "\n"; +echo hash('gost-crypto', str_repeat('a', 33)), "\n"; ?> --EXPECT-- ce85b99cc46752fffee35cab9a7b0278abb4c2d2055cff685af4912c49490f8d @@ -18,3 +25,9 @@ a3ebc4daaab78b0be131dab5737a7f67e602670d543521319150d2e14eeec445 03840d6348763f11e28e7b1ecc4da0cdf7f898fa555b928ef684c6c5b8f46d9f fd1b746d9397e78edd311baef391450434271e02816caa37680d6d7381c79d4e 715e59cdc8ebde9fdf0fe2a2e811b3bf7f48209a01505e467d2cd2aa2bbb5ecf +981e5f3ca30c841487830f84fb433e13ac1101569b9c13584ac483234cd656c0 +9004294a361a508c586fe53d1f1b02746765e71b765472786e4770d565830a76 +a93124f5bf2c6d83c3bbf722bc55569310245ca5957541f4dbd7dfaf8137e6f2 +8978e06b0ecf54ea81ec51ca4e02bcb4eb390b3f04cb5f65ee8de195ffae591b +e121e3740ae94ca6d289e6d653ff31695783efff3dd960417a1098a0130fa720 +d3e8f22d9762a148ddfc84a6043d97a608604dae7c05baee72b55f559d03dd74 diff --git a/ext/hash/tests/hash_algos.phpt b/ext/hash/tests/hash_algos.phpt index 55796ecbce..7773fe979a 100644 --- a/ext/hash/tests/hash_algos.phpt +++ b/ext/hash/tests/hash_algos.phpt @@ -18,7 +18,7 @@ var_dump(hash_algos()); ===Done=== --EXPECTF-- *** Testing hash_algos() : basic functionality *** -array(43) { +array(44) { [%d]=> string(3) "md2" [%d]=> @@ -64,6 +64,8 @@ array(43) { [%d]=> string(4) "gost" [%d]=> + string(11) "gost-crypto" + [%d]=> string(7) "adler32" [%d]=> string(5) "crc32" @@ -106,4 +108,4 @@ array(43) { [%d]=> string(10) "haval256,5" } -===Done===
\ No newline at end of file +===Done=== diff --git a/ext/hash/tests/hash_copy_001.phpt b/ext/hash/tests/hash_copy_001.phpt index 638b7f5fc1..bb4a49da89 100644 --- a/ext/hash/tests/hash_copy_001.phpt +++ b/ext/hash/tests/hash_copy_001.phpt @@ -97,6 +97,9 @@ string(64) "fbe88daa74c89b9e29468fa3cd3a657d31845e21bb58dd3f8d806f5179a85c26" string(4) "gost" string(64) "5820c7c4a0650587538b30ef4099f2b5993069758d5c847a552e6ef7360766a5" string(64) "5820c7c4a0650587538b30ef4099f2b5993069758d5c847a552e6ef7360766a5" +string(11) "gost-crypto" +string(64) "f7c4e35548d66aabe2b106f20515d289fde90969225d3d7b83f6dd12d694f043" +string(64) "f7c4e35548d66aabe2b106f20515d289fde90969225d3d7b83f6dd12d694f043" string(7) "adler32" string(8) "6f7c0928" string(8) "6f7c0928" @@ -226,6 +229,9 @@ string(64) "614ca924864fa0e8fa309aa0944e047d5edbfd4964a35858f4d8ec66a0fb88b0" string(4) "gost" string(64) "5820c7c4a0650587538b30ef4099f2b5993069758d5c847a552e6ef7360766a5" string(64) "a00961e371287c71c527a41c14564f13b6ed12ac7cd9d5f5dfb3542a25e28d3b" +string(11) "gost-crypto" +string(64) "f7c4e35548d66aabe2b106f20515d289fde90969225d3d7b83f6dd12d694f043" +string(64) "68ca9aea6729dc07d995fbe071a4b5c6490bb27fc4dc65ec0e96200d5e082996" string(7) "adler32" string(8) "6f7c0928" string(8) "d9141747" diff --git a/ext/hash/tests/hash_file_basic.phpt b/ext/hash/tests/hash_file_basic.phpt index 9851c14b91..b16927d20e 100644 --- a/ext/hash/tests/hash_file_basic.phpt +++ b/ext/hash/tests/hash_file_basic.phpt @@ -15,7 +15,7 @@ Felix De Vliegher <felix.devliegher@gmail.com> echo "*** Testing hash_file() : basic functionality ***\n"; // Set up file -$filename = 'hash_file_example.txt'; +$filename = 'hash_file_basic_example.txt'; file_put_contents( $filename, 'The quick brown fox jumped over the lazy dog.' ); var_dump( hash_file( 'md5', $filename ) ); @@ -30,7 +30,7 @@ var_dump( base64_encode( hash_file( 'md5', $filename, true ) ) ); --CLEAN-- <?php -$filename = 'hash_file_example.txt'; +$filename = 'hash_file_basic_example.txt'; unlink( $filename ); ?> diff --git a/ext/hash/tests/hash_file_error.phpt b/ext/hash/tests/hash_file_error.phpt index de7ce55b10..96c41e6432 100644 --- a/ext/hash/tests/hash_file_error.phpt +++ b/ext/hash/tests/hash_file_error.phpt @@ -15,7 +15,7 @@ Felix De Vliegher <felix.devliegher@gmail.com> echo "*** Testing hash_file() : error conditions ***\n"; // Set up file -$filename = 'hash_file_example.txt'; +$filename = 'hash_file_error_example.txt'; file_put_contents( $filename, 'The quick brown fox jumped over the lazy dog.' ); @@ -38,7 +38,7 @@ var_dump( hash_file( 'md5', $filename, false, $extra_arg ) ); --CLEAN-- <?php -$filename = 'hash_file_example.txt'; +$filename = 'hash_file_error_example.txt'; unlink( $filename ); ?> diff --git a/ext/json/json.c b/ext/json/json.c index c3664b9ee9..80bbef7b7c 100644 --- a/ext/json/json.c +++ b/ext/json/json.c @@ -712,14 +712,14 @@ PHP_JSON_API void php_json_decode_ex(zval *return_value, char *str, int str_len, RETVAL_NULL(); if (trim_len == 4) { - if (!strncasecmp(trim, "null", trim_len)) { + if (!strncmp(trim, "null", trim_len)) { /* We need to explicitly clear the error because its an actual NULL and not an error */ jp->error_code = PHP_JSON_ERROR_NONE; RETVAL_NULL(); - } else if (!strncasecmp(trim, "true", trim_len)) { + } else if (!strncmp(trim, "true", trim_len)) { RETVAL_BOOL(1); } - } else if (trim_len == 5 && !strncasecmp(trim, "false", trim_len)) { + } else if (trim_len == 5 && !strncmp(trim, "false", trim_len)) { RETVAL_BOOL(0); } diff --git a/ext/json/tests/bug64874_part2.phpt b/ext/json/tests/bug64874_part2.phpt new file mode 100644 index 0000000000..338fc1141a --- /dev/null +++ b/ext/json/tests/bug64874_part2.phpt @@ -0,0 +1,69 @@ +--TEST-- +Case-sensitivity part of bug #64874 ("json_decode handles whitespace and case-sensitivity incorrectly") +--SKIPIF-- +<?php if (!extension_loaded("json")) print "skip"; ?> +--FILE-- +<?php +function decode($json) { + var_dump(json_decode($json)); + echo ((json_last_error() !== 0) ? 'ERROR' : 'SUCCESS') . PHP_EOL; +} + +// Only lowercase should work +decode('true'); +decode('True'); +decode('[true]'); +decode('[True]'); +echo PHP_EOL; + +decode('false'); +decode('False'); +decode('[false]'); +decode('[False]'); +echo PHP_EOL; + +decode('null'); +decode('Null'); +decode('[null]'); +decode('[Null]'); +echo PHP_EOL; + +echo "Done\n"; +--EXPECT-- +bool(true) +SUCCESS +NULL +ERROR +array(1) { + [0]=> + bool(true) +} +SUCCESS +NULL +ERROR + +bool(false) +SUCCESS +NULL +ERROR +array(1) { + [0]=> + bool(false) +} +SUCCESS +NULL +ERROR + +NULL +SUCCESS +NULL +ERROR +array(1) { + [0]=> + NULL +} +SUCCESS +NULL +ERROR + +Done diff --git a/ext/ldap/ldap.c b/ext/ldap/ldap.c index e95f898c15..d50b78321f 100644 --- a/ext/ldap/ldap.c +++ b/ext/ldap/ldap.c @@ -67,6 +67,9 @@ #include <sasl/sasl.h> #endif +#define PHP_LDAP_ESCAPE_FILTER 0x01 +#define PHP_LDAP_ESCAPE_DN 0x02 + typedef struct { LDAP *link; #if defined(LDAP_API_FEATURE_X_OPENLDAP) && defined(HAVE_3ARG_SETREBINDPROC) @@ -195,6 +198,9 @@ PHP_MINIT_FUNCTION(ldap) REGISTER_LONG_CONSTANT("GSLC_SSL_TWOWAY_AUTH", GSLC_SSL_TWOWAY_AUTH, CONST_PERSISTENT | CONST_CS); #endif + REGISTER_LONG_CONSTANT("LDAP_ESCAPE_FILTER", PHP_LDAP_ESCAPE_FILTER, CONST_PERSISTENT | CONST_CS); + REGISTER_LONG_CONSTANT("LDAP_ESCAPE_DN", PHP_LDAP_ESCAPE_DN, CONST_PERSISTENT | CONST_CS); + le_link = zend_register_list_destructors_ex(_close_ldap_link, NULL, "ldap link", module_number); le_result = zend_register_list_destructors_ex(_free_ldap_result, NULL, "ldap result", module_number); le_result_entry = zend_register_list_destructors_ex(_free_ldap_result_entry, NULL, "ldap result entry", module_number); @@ -2137,6 +2143,83 @@ PHP_FUNCTION(ldap_set_rebind_proc) /* }}} */ #endif +static void php_ldap_do_escape(const zend_bool *map, const char *value, size_t valuelen, char **result, size_t *resultlen) +{ + char hex[] = "0123456789abcdef"; + int i, p = 0; + size_t len = 0; + + for (i = 0; i < valuelen; i++) { + len += (map[(unsigned char) value[i]]) ? 3 : 1; + } + + (*result) = (char *) safe_emalloc(1, len, 1); + (*resultlen) = len; + + for (i = 0; i < valuelen; i++) { + unsigned char v = (unsigned char) value[i]; + + if (map[v]) { + (*result)[p++] = '\\'; + (*result)[p++] = hex[v >> 4]; + (*result)[p++] = hex[v & 0x0f]; + } else { + (*result)[p++] = v; + } + } + + (*result)[p++] = '\0'; +} + +static void php_ldap_escape_map_set_chars(zend_bool *map, const char *chars, const int charslen, char escape) +{ + int i = 0; + while (i < charslen) { + map[(unsigned char) chars[i++]] = escape; + } +} + +PHP_FUNCTION(ldap_escape) +{ + char *value, *ignores, *result; + int valuelen = 0, ignoreslen = 0, i; + size_t resultlen; + long flags = 0; + zend_bool map[256] = {0}, havecharlist = 0; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|sl", &value, &valuelen, &ignores, &ignoreslen, &flags) != SUCCESS) { + return; + } + + if (!valuelen) { + RETURN_EMPTY_STRING(); + } + + if (flags & PHP_LDAP_ESCAPE_FILTER) { + havecharlist = 1; + php_ldap_escape_map_set_chars(map, "\\*()\0", sizeof("\\*()\0") - 1, 1); + } + + if (flags & PHP_LDAP_ESCAPE_DN) { + havecharlist = 1; + php_ldap_escape_map_set_chars(map, "\\,=+<>;\"#", sizeof("\\,=+<>;\"#") - 1, 1); + } + + if (!havecharlist) { + for (i = 0; i < 256; i++) { + map[i] = 1; + } + } + + if (ignoreslen) { + php_ldap_escape_map_set_chars(map, ignores, ignoreslen, 0); + } + + php_ldap_do_escape(map, value, valuelen, &result, &resultlen); + + RETURN_STRINGL(result, resultlen, 0); +} + #ifdef STR_TRANSLATION /* {{{ php_ldap_do_translate */ @@ -2626,6 +2709,12 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_set_rebind_proc, 0, 0, 2) ZEND_END_ARG_INFO() #endif +ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_escape, 0, 0, 1) + ZEND_ARG_INFO(0, value) + ZEND_ARG_INFO(0, ignore) + ZEND_ARG_INFO(0, flags) +ZEND_END_ARG_INFO() + #ifdef STR_TRANSLATION ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_t61_to_8859, 0, 0, 1) ZEND_ARG_INFO(0, value) @@ -2704,6 +2793,8 @@ const zend_function_entry ldap_functions[] = { PHP_FE(ldap_set_rebind_proc, arginfo_ldap_set_rebind_proc) #endif + PHP_FE(ldap_escape, arginfo_ldap_escape) + #ifdef STR_TRANSLATION PHP_FE(ldap_t61_to_8859, arginfo_ldap_t61_to_8859) PHP_FE(ldap_8859_to_t61, arginfo_ldap_8859_to_t61) diff --git a/ext/ldap/tests/ldap_escape_all.phpt b/ext/ldap/tests/ldap_escape_all.phpt new file mode 100644 index 0000000000..a79be004ff --- /dev/null +++ b/ext/ldap/tests/ldap_escape_all.phpt @@ -0,0 +1,14 @@ +--TEST-- +ldap_escape() test all +--SKIPIF-- +<?php require_once('skipif.inc'); ?> +--FILE-- +<?php + +$subject = 'foo=bar(baz)*'; + +var_dump(ldap_escape($subject)); + +?> +--EXPECT-- +string(39) "\66\6f\6f\3d\62\61\72\28\62\61\7a\29\2a"
\ No newline at end of file diff --git a/ext/ldap/tests/ldap_escape_both.phpt b/ext/ldap/tests/ldap_escape_both.phpt new file mode 100644 index 0000000000..2169c0ad2e --- /dev/null +++ b/ext/ldap/tests/ldap_escape_both.phpt @@ -0,0 +1,14 @@ +--TEST-- +ldap_escape() test filter and DN +--SKIPIF-- +<?php require_once('skipif.inc'); ?> +--FILE-- +<?php + +$subject = 'foo=bar(baz)*'; + +var_dump(ldap_escape($subject, null, LDAP_ESCAPE_DN | LDAP_ESCAPE_FILTER)); + +?> +--EXPECT-- +string(21) "foo\3dbar\28baz\29\2a"
\ No newline at end of file diff --git a/ext/ldap/tests/ldap_escape_dn.phpt b/ext/ldap/tests/ldap_escape_dn.phpt new file mode 100644 index 0000000000..fbcb0545ae --- /dev/null +++ b/ext/ldap/tests/ldap_escape_dn.phpt @@ -0,0 +1,14 @@ +--TEST-- +ldap_escape() test DN +--SKIPIF-- +<?php require_once('skipif.inc'); ?> +--FILE-- +<?php + +$subject = 'foo=bar(baz)*'; + +var_dump(ldap_escape($subject, null, LDAP_ESCAPE_DN)); + +?> +--EXPECT-- +string(15) "foo\3dbar(baz)*"
\ No newline at end of file diff --git a/ext/ldap/tests/ldap_escape_filter.phpt b/ext/ldap/tests/ldap_escape_filter.phpt new file mode 100644 index 0000000000..e4540a452d --- /dev/null +++ b/ext/ldap/tests/ldap_escape_filter.phpt @@ -0,0 +1,14 @@ +--TEST-- +ldap_escape() test filter +--SKIPIF-- +<?php require_once('skipif.inc'); ?> +--FILE-- +<?php + +$subject = 'foo=bar(baz)*'; + +var_dump(ldap_escape($subject, null, LDAP_ESCAPE_FILTER)); + +?> +--EXPECT-- +string(19) "foo=bar\28baz\29\2a"
\ No newline at end of file diff --git a/ext/ldap/tests/ldap_escape_ignore.phpt b/ext/ldap/tests/ldap_escape_ignore.phpt new file mode 100644 index 0000000000..ab56aa2d0e --- /dev/null +++ b/ext/ldap/tests/ldap_escape_ignore.phpt @@ -0,0 +1,15 @@ +--TEST-- +ldap_escape() test ignore +--SKIPIF-- +<?php require_once('skipif.inc'); ?> +--FILE-- +<?php + +$subject = 'foo=bar(baz)*'; +$ignore = 'ao'; + +var_dump(ldap_escape($subject, $ignore)); + +?> +--EXPECT-- +string(31) "\66oo\3d\62a\72\28\62a\7a\29\2a"
\ No newline at end of file diff --git a/ext/libxml/libxml.c b/ext/libxml/libxml.c index 354cb548a7..05b8df4d0d 100644 --- a/ext/libxml/libxml.c +++ b/ext/libxml/libxml.c @@ -293,7 +293,8 @@ static void *php_libxml_streams_IO_open_wrapper(const char *filename, const char php_stream_statbuf ssbuf; php_stream_context *context = NULL; php_stream_wrapper *wrapper = NULL; - char *resolved_path, *path_to_open = NULL; + char *resolved_path; + const char *path_to_open = NULL; void *ret_val = NULL; int isescaped=0; xmlURI *uri; diff --git a/ext/libxml/tests/bug61367-read.phpt b/ext/libxml/tests/bug61367-read.phpt index 75d0006a3f..b4ecaa0324 100644 --- a/ext/libxml/tests/bug61367-read.phpt +++ b/ext/libxml/tests/bug61367-read.phpt @@ -32,10 +32,10 @@ XML } } -var_dump(mkdir('test_bug_61367')); -var_dump(mkdir('test_bug_61367/base')); -var_dump(file_put_contents('test_bug_61367/bad', 'blah')); -var_dump(chdir('test_bug_61367/base')); +var_dump(mkdir('test_bug_61367-read')); +var_dump(mkdir('test_bug_61367-read/base')); +var_dump(file_put_contents('test_bug_61367-read/bad', 'blah')); +var_dump(chdir('test_bug_61367-read/base')); stream_wrapper_register( 'exploit', 'StreamExploiter' ); $s = fopen( 'exploit://', 'r' ); @@ -43,9 +43,9 @@ $s = fopen( 'exploit://', 'r' ); ?> --CLEAN-- <?php -unlink('test_bug_61367/bad'); -rmdir('test_bug_61367/base'); -rmdir('test_bug_61367'); +unlink('test_bug_61367-read/bad'); +rmdir('test_bug_61367-read/base'); +rmdir('test_bug_61367-read'); ?> --EXPECTF-- bool(true) @@ -53,7 +53,7 @@ bool(true) int(4) bool(true) -Warning: DOMDocument::loadXML(): I/O warning : failed to load external entity "file:///%s/test_bug_61367/bad" in %s on line %d +Warning: DOMDocument::loadXML(): I/O warning : failed to load external entity "file:///%s/test_bug_61367-read/bad" in %s on line %d Warning: DOMDocument::loadXML(): Failure to process entity file in Entity, line: 4 in %s on line %d diff --git a/ext/libxml/tests/bug61367-write.phpt b/ext/libxml/tests/bug61367-write.phpt index e18b07149a..63e99a8e50 100644 --- a/ext/libxml/tests/bug61367-write.phpt +++ b/ext/libxml/tests/bug61367-write.phpt @@ -19,10 +19,10 @@ class StreamExploiter { } } -var_dump(mkdir('test_bug_61367')); -var_dump(mkdir('test_bug_61367/base')); -var_dump(file_put_contents('test_bug_61367/bad', 'blah')); -var_dump(chdir('test_bug_61367/base')); +var_dump(mkdir('test_bug_61367-write')); +var_dump(mkdir('test_bug_61367-write/base')); +var_dump(file_put_contents('test_bug_61367-write/bad', 'blah')); +var_dump(chdir('test_bug_61367-write/base')); stream_wrapper_register( 'exploit', 'StreamExploiter' ); $s = fopen( 'exploit://', 'r' ); @@ -30,9 +30,9 @@ $s = fopen( 'exploit://', 'r' ); ?> --CLEAN-- <?php -@unlink('test_bug_61367/bad'); -rmdir('test_bug_61367/base'); -rmdir('test_bug_61367'); +@unlink('test_bug_61367-write/bad'); +rmdir('test_bug_61367-write/base'); +rmdir('test_bug_61367-write'); ?> --EXPECTF-- bool(true) diff --git a/ext/mbstring/mb_gpc.c b/ext/mbstring/mb_gpc.c index 5ecc8f365e..30764dc807 100644 --- a/ext/mbstring/mb_gpc.c +++ b/ext/mbstring/mb_gpc.c @@ -364,6 +364,7 @@ SAPI_POST_HANDLER_FUNC(php_mb_post_handler) { const mbfl_encoding *detected; php_mb_encoding_handler_info_t info; + char *post_data_str = NULL; MBSTRG(http_input_identify_post) = NULL; @@ -376,7 +377,10 @@ SAPI_POST_HANDLER_FUNC(php_mb_post_handler) info.num_from_encodings = MBSTRG(http_input_list_size); info.from_language = MBSTRG(language); - detected = _php_mb_encoding_handler_ex(&info, arg, SG(request_info).post_data TSRMLS_CC); + php_stream_rewind(SG(request_info).request_body); + php_stream_copy_to_mem(SG(request_info).request_body, &post_data_str, PHP_STREAM_COPY_ALL, 0); + detected = _php_mb_encoding_handler_ex(&info, arg, post_data_str TSRMLS_CC); + STR_FREE(post_data_str); MBSTRG(http_input_identify) = detected; if (detected) { diff --git a/ext/mbstring/mbstring.c b/ext/mbstring/mbstring.c index 4e430b6ea2..168b133c64 100644 --- a/ext/mbstring/mbstring.c +++ b/ext/mbstring/mbstring.c @@ -402,10 +402,10 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_mb_convert_kana, 0, 0, 1) ZEND_ARG_INFO(0, encoding) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_INFO_EX(arginfo_mb_convert_variables, 1, 0, 3) +ZEND_BEGIN_ARG_INFO_EX(arginfo_mb_convert_variables, 0, 0, 3) ZEND_ARG_INFO(0, to) ZEND_ARG_INFO(0, from) - ZEND_ARG_INFO(1, ...) + ZEND_ARG_VARIADIC_INFO(1, vars) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_mb_encode_numericentity, 0, 0, 2) diff --git a/ext/mysqli/mysqli_fe.c b/ext/mysqli/mysqli_fe.c index 6f2e404087..eb94ff65bb 100644 --- a/ext/mysqli/mysqli_fe.c +++ b/ext/mysqli/mysqli_fe.c @@ -43,23 +43,28 @@ #define MYSQLI_ZEND_ARG_OBJ_INFO_STMT() ZEND_ARG_INFO(0, stmt) #endif -ZEND_BEGIN_ARG_INFO(arginfo_mysqli_stmt_bind_result, 1) +ZEND_BEGIN_ARG_INFO(arginfo_mysqli_stmt_bind_result, 0) MYSQLI_ZEND_ARG_OBJ_INFO_STMT() + ZEND_ARG_VARIADIC_INFO(1, vars) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_INFO(arginfo_mysqli_stmt_bind_param, 1) +ZEND_BEGIN_ARG_INFO(arginfo_mysqli_stmt_bind_param, 0) MYSQLI_ZEND_ARG_OBJ_INFO_STMT() ZEND_ARG_INFO(0, types) + ZEND_ARG_VARIADIC_INFO(1, vars) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_INFO(arginfo_class_mysqli_stmt_bind_result, 1) +ZEND_BEGIN_ARG_INFO(arginfo_class_mysqli_stmt_bind_result, 0) + ZEND_ARG_VARIADIC_INFO(1, vars) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_INFO(arginfo_class_mysqli_stmt_bind_param, 1) +ZEND_BEGIN_ARG_INFO(arginfo_class_mysqli_stmt_bind_param, 0) ZEND_ARG_INFO(0, types) + ZEND_ARG_VARIADIC_INFO(1, vars) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_INFO(all_args_force_by_ref, 1) +ZEND_BEGIN_ARG_INFO(all_args_force_by_ref, 0) + ZEND_ARG_VARIADIC_INFO(1, vars) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_mysqli_poll, 0, 0, 4) diff --git a/ext/mysqlnd/config9.m4 b/ext/mysqlnd/config9.m4 index 09aca5af8a..0e08b977af 100644 --- a/ext/mysqlnd/config9.m4 +++ b/ext/mysqlnd/config9.m4 @@ -48,16 +48,4 @@ fi if test "$PHP_MYSQLND" != "no" || test "$PHP_MYSQLND_ENABLED" = "yes" || test "$PHP_MYSQLI" != "no"; then PHP_ADD_BUILD_DIR([ext/mysqlnd], 1) - - dnl This creates a file so it has to be after above macros - PHP_CHECK_TYPES([int8 uint8 int16 uint16 int32 uint32 uchar ulong int8_t uint8_t int16_t uint16_t int32_t uint32_t int64_t uint64_t], [ - ext/mysqlnd/php_mysqlnd_config.h - ],[ -#ifdef HAVE_SYS_TYPES_H -#include <sys/types.h> -#endif -#ifdef HAVE_STDINT_H -#include <stdint.h> -#endif - ]) fi diff --git a/ext/mysqlnd/mysqlnd_enum_n_def.h b/ext/mysqlnd/mysqlnd_enum_n_def.h index 4ace69adcf..c9127ef93c 100644 --- a/ext/mysqlnd/mysqlnd_enum_n_def.h +++ b/ext/mysqlnd/mysqlnd_enum_n_def.h @@ -104,7 +104,7 @@ #define MYSQLND_CAPABILITIES (CLIENT_LONG_PASSWORD | CLIENT_LONG_FLAG | CLIENT_TRANSACTIONS | \ CLIENT_PROTOCOL_41 | CLIENT_SECURE_CONNECTION | \ - CLIENT_MULTI_RESULTS | CLIENT_PS_MULTI_RESULTS | CLIENT_LOCAL_FILES | CLIENT_PLUGIN_AUTH) + CLIENT_MULTI_RESULTS | CLIENT_LOCAL_FILES | CLIENT_PLUGIN_AUTH) #define MYSQLND_NET_FLAG_USE_COMPRESSION 1 diff --git a/ext/mysqlnd/mysqlnd_portability.h b/ext/mysqlnd/mysqlnd_portability.h index b9479150ae..72a156a795 100644 --- a/ext/mysqlnd/mysqlnd_portability.h +++ b/ext/mysqlnd/mysqlnd_portability.h @@ -36,8 +36,6 @@ This file is public domain and comes with NO WARRANTY of any kind */ #if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(WIN32) # include "ext/mysqlnd/config-win.h" -#else -# include <ext/mysqlnd/php_mysqlnd_config.h> #endif /* _WIN32... */ #if __STDC_VERSION__ < 199901L && !defined(atoll) @@ -45,14 +43,7 @@ This file is public domain and comes with NO WARRANTY of any kind */ #define atoll atol #endif - -#ifdef HAVE_SYS_TYPES_H -#include <sys/types.h> -#endif - -#ifdef HAVE_STDINT_H -#include <stdint.h> -#endif +#include "php_stdint.h" #if SIZEOF_LONG_LONG > 4 && !defined(_LONG_LONG) #define _LONG_LONG 1 /* For AIX string library */ @@ -70,102 +61,6 @@ This file is public domain and comes with NO WARRANTY of any kind */ #define HAVE_LONG_LONG 1 #endif - -/* Typdefs for easyier portability */ -#ifndef HAVE_INT8_T -#ifndef HAVE_INT8 -typedef signed char int8_t; /* Signed integer >= 8 bits */ -#else -typedef int8 int8_t; /* Signed integer >= 8 bits */ -#endif -#endif - -#ifndef HAVE_UINT8_T -#ifndef HAVE_UINT8 -typedef unsigned char uint8_t; /* Unsigned integer >= 8 bits */ -#else -typedef uint8 uint8_t; /* Signed integer >= 8 bits */ -#endif -#endif - -#ifndef HAVE_INT16_T -#ifndef HAVE_INT16 -typedef signed short int16_t; /* Signed integer >= 16 bits */ -#else -typedef int16 int16_t; /* Signed integer >= 16 bits */ -#endif -#endif - -#ifndef HAVE_UINT16_T -#ifndef HAVE_UINT16 -typedef unsigned short uint16_t; /* Signed integer >= 16 bits */ -#else -typedef uint16 uint16_t; /* Signed integer >= 16 bits */ -#endif -#endif - - -#ifndef HAVE_INT32_T -#ifdef HAVE_INT32 -typedef int32 int32_t; -#elif SIZEOF_INT == 4 -typedef signed int int32_t; -#elif SIZEOF_LONG == 4 -typedef signed long int32_t; -#else -error "Neither int nor long is of 4 bytes width" -#endif -#endif /* HAVE_INT32_T */ - -#ifndef HAVE_UINT32_T -#ifdef HAVE_UINT32 -typedef uint32 uint32_t; -#elif SIZEOF_INT == 4 -typedef unsigned int uint32_t; -#elif SIZEOF_LONG == 4 -typedef unsigned long uint32_t; -#else -#error "Neither int nor long is of 4 bytes width" -#endif -#endif /* HAVE_UINT32_T */ - -#ifndef HAVE_INT64_T -#ifdef HAVE_INT64 -typedef int64 int64_t; -#elif SIZEOF_INT == 8 -typedef signed int int64_t; -#elif SIZEOF_LONG == 8 -typedef signed long int64_t; -#elif SIZEOF_LONG_LONG == 8 -#ifdef PHP_WIN32 -typedef __int64 int64_t; -#else -typedef signed long long int64_t; -#endif -#else -#error "Neither int nor long nor long long is of 8 bytes width" -#endif -#endif /* HAVE_INT64_T */ - -#ifndef HAVE_UINT64_T -#ifdef HAVE_UINT64 -typedef uint64 uint64_t; -#elif SIZEOF_INT == 8 -typedef unsigned int uint64_t; -#elif SIZEOF_LONG == 8 -typedef unsigned long uint64_t; -#elif SIZEOF_LONG_LONG == 8 -#ifdef PHP_WIN32 -typedef unsigned __int64 uint64_t; -#else -typedef unsigned long long uint64_t; -#endif -#else -#error "Neither int nor long nor long long is of 8 bytes width" -#endif -#endif /* HAVE_INT64_T */ - - #ifdef PHP_WIN32 #define MYSQLND_LLU_SPEC "%I64u" #define MYSQLND_LL_SPEC "%I64d" diff --git a/ext/oci8/LICENSE b/ext/oci8/LICENSE new file mode 100644 index 0000000000..42536af320 --- /dev/null +++ b/ext/oci8/LICENSE @@ -0,0 +1,68 @@ +-------------------------------------------------------------------- + The PHP License, version 3.01 +Copyright (c) 1999 - 2012 The PHP Group. All rights reserved. +-------------------------------------------------------------------- + +Redistribution and use in source and binary forms, with or without +modification, is permitted provided that the following conditions +are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + 3. The name "PHP" must not be used to endorse or promote products + derived from this software without prior written permission. For + written permission, please contact group@php.net. + + 4. Products derived from this software may not be called "PHP", nor + may "PHP" appear in their name, without prior written permission + from group@php.net. You may indicate that your software works in + conjunction with PHP by saying "Foo for PHP" instead of calling + it "PHP Foo" or "phpfoo" + + 5. The PHP Group may publish revised and/or new versions of the + license from time to time. Each version will be given a + distinguishing version number. + Once covered code has been published under a particular version + of the license, you may always continue to use it under the terms + of that version. You may also choose to use such covered code + under the terms of any subsequent version of the license + published by the PHP Group. No one other than the PHP Group has + the right to modify the terms applicable to covered code created + under this License. + + 6. Redistributions of any form whatsoever must retain the following + acknowledgment: + "This product includes PHP software, freely available from + <http://www.php.net/software/>". + +THIS SOFTWARE IS PROVIDED BY THE PHP DEVELOPMENT TEAM ``AS IS'' AND +ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PHP +DEVELOPMENT TEAM OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +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. + +-------------------------------------------------------------------- + +This software consists of voluntary contributions made by many +individuals on behalf of the PHP Group. + +The PHP Group can be contacted via Email at group@php.net. + +For more information on the PHP Group and the PHP project, +please see <http://www.php.net>. + +PHP includes the Zend Engine, freely available at +<http://www.zend.com>. diff --git a/ext/oci8/README b/ext/oci8/README index 420d5dac58..d662072743 100644 --- a/ext/oci8/README +++ b/ext/oci8/README @@ -1,13 +1,20 @@ The OCI8 Extension ------------------ -Use the OCI8 extension to access Oracle Database. +Use the OCI8 extension to access Oracle Database. Documentation is at http://php.net/oci8 -The extension can be built with PHP versions 4.3.9 to 5.x using Oracle -9.2, 10, or 11 client libraries. Oracle's standard cross-version -connectivity applies. For example PHP linked with Oracle 11.2 client -libraries can connect to Oracle Database 9.2 onwards. See Oracle's -note "Oracle Client / Server Interoperability Support" (ID 207303.1) -for details. +The extension can be linked with Oracle client libraries from Oracle +Database 10.2, 11, or 12.1. These libraries are found in the database +installation, or in the free Oracle Instant Client available from +Oracle. + +Oracle's standard cross-version connectivity applies. For example, +PHP OCI8 linked with Instant Client 11.2 can connect to Oracle +Database 9.2 onward. See Oracle's note "Oracle Client / Server +Interoperability Support" (ID 207303.1) for details. + +PHP OCI8 2.0 can be built with PHP 5.2 onward. Use the older PHP OCI8 +1.4.10 when using PHP 4.3.9 through to PHP 5.1.x, or when only Oracle +Database 9.2 client libraries are available. diff --git a/ext/oci8/config.m4 b/ext/oci8/config.m4 index 39c037548a..0d08d21c29 100644 --- a/ext/oci8/config.m4 +++ b/ext/oci8/config.m4 @@ -15,22 +15,6 @@ else PHP_OCI8_TAIL1="tail -1" fi -AC_DEFUN([PHP_OCI_IF_DEFINED],[ - old_CPPFLAGS=$CPPFLAGS - CPPFLAGS=$3 - AC_EGREP_CPP(yes,[ -#include <oci.h> -#if defined($1) - yes -#endif - ],[ - CPPFLAGS=$old_CPPFLAGS - $2 - ],[ - CPPFLAGS=$old_CPPFLAGS - ]) -]) - AC_DEFUN([AC_OCI8_CHECK_LIB_DIR],[ AC_MSG_CHECKING([ORACLE_HOME library validity]) if test ! -d "$OCI8_DIR"; then @@ -98,13 +82,99 @@ AC_DEFUN([AC_OCI8_ORACLE_VERSION],[ AC_MSG_RESULT($OCI8_ORACLE_VERSION) ]) +dnl +dnl OCI8_INIT_DTRACE(providerdesc, header-file, sources) +dnl This mimics PHP_INIT_DTRACE from PHP 5.4's acinclude.m4. It is +dnl necessarily different from PHP_INIT_DTRACE which doesn't currently +dnl support DTrace for extensions. Creating OCI8_INIT_DTRACE +dnl independently instead of using a refactored PHP_INIT_DTRACE allows +dnl OCI8 to be DTraced on versions of PHP where core PHP DTrace support +dnl isn't available. +dnl +AC_DEFUN([OCI8_INIT_DTRACE],[ + ac_srcdir=[]PHP_EXT_SRCDIR([oci8])/ + ac_bdir=[]PHP_EXT_BUILDDIR([oci8])/ + +dnl providerdesc + ac_provsrc=$1 + +dnl header-file + ac_hdrobj=$2 + +dnl DTrace objects + old_IFS=[$]IFS + for ac_src in $3; do + IFS=. + set $ac_src + ac_obj=[$]1 + IFS=$old_IFS + + OCI8_DTRACE_OBJS="[$]OCI8_DTRACE_OBJS [$]ac_bdir[$]ac_obj.lo" + done; + + for ac_lo in $OCI8_DTRACE_OBJS; do + dtrace_oci8_objs="[$]dtrace_oci8_objs `echo $ac_lo | $SED -e 's,\.lo$,.o,' -e 's#\(.*\)\/#\1\/.libs\/#'`" + done; + +dnl Generate Makefile.objects entry +dnl The empty $ac_provsrc command stops an implicit circular dependency +dnl in GNU Make which causes the .d file to be overwritten (Bug 61268) + cat>>Makefile.objects<<EOF + +PHP_EXT_SRCDIR([oci8])/$ac_provsrc:; + +$ac_bdir[$]ac_hdrobj: $ac_srcdir[$]ac_provsrc + CFLAGS="\$(CFLAGS_CLEAN)" dtrace -h -C -s $ac_srcdir[$]ac_provsrc -o \$[]@.bak && \$(SED) -e 's,PHPOCI_,DTRACE_,g' \$[]@.bak > \$[]@ + +\$(OCI8_DTRACE_OBJS): $ac_bdir[$]ac_hdrobj + +EOF + + case $host_alias in + *solaris*|*linux*) + dtrace_prov_name="`echo $ac_provsrc | $SED -e 's#\(.*\)\/##'`.o" + dtrace_lib_dir="`echo $ac_bdir[$]ac_provsrc | $SED -e 's#\(.*\)/[^/]*#\1#'`/.libs" + dtrace_d_obj="`echo $ac_bdir[$]ac_provsrc | $SED -e 's#\(.*\)/\([^/]*\)#\1/.libs/\2#'`.o" + dtrace_nolib_objs='$(OCI8_DTRACE_OBJS:.lo=.o)' + for ac_lo in $OCI8_DTRACE_OBJS; do + dtrace_oci8_lib_objs="[$]dtrace_oci8_lib_objs `echo $ac_lo | $SED -e 's,\.lo$,.o,' -e 's#\(.*\)\/#\1\/.libs\/#'`" + done; +dnl Always attempt to create both PIC and non-PIC DTrace objects (Bug 63692) + cat>>Makefile.objects<<EOF +$ac_bdir[$]ac_provsrc.lo: \$(OCI8_DTRACE_OBJS) + echo "[#] Generated by Makefile for libtool" > \$[]@ + @test -d "$dtrace_lib_dir" || mkdir $dtrace_lib_dir + if CFLAGS="\$(CFLAGS_CLEAN)" dtrace -G -o $dtrace_d_obj -s $ac_srcdir[$]ac_provsrc $dtrace_oci8_lib_objs 2> /dev/null && test -f "$dtrace_d_obj"; then [\\] + echo "pic_object=['].libs/$dtrace_prov_name[']" >> \$[]@ [;\\] + else [\\] + echo "pic_object='none'" >> \$[]@ [;\\] + fi + if CFLAGS="\$(CFLAGS_CLEAN)" dtrace -G -o $ac_bdir[$]ac_provsrc.o -s $ac_srcdir[$]ac_provsrc $dtrace_nolib_objs 2> /dev/null && test -f "$ac_bdir[$]ac_provsrc.o"; then [\\] + echo "non_pic_object=[']$dtrace_prov_name[']" >> \$[]@ [;\\] + else [\\] + echo "non_pic_object='none'" >> \$[]@ [;\\] + fi + +EOF + ;; + *) + AC_MSG_WARN([OCI8 extension: OCI8 DTrace support is not confirmed on this platform]) +cat>>Makefile.objects<<EOF +$ac_bdir[$]ac_provsrc.o: \$(OCI8_DTRACE_OBJS) + CFLAGS="\$(CFLAGS_CLEAN)" dtrace -G -o \$[]@ -s $ac_srcdir[$]ac_provsrc $dtrace_oci8_objs + +EOF + ;; + esac +]) + dnl --with-oci8=shared,instantclient,/path/to/client/dir/lib dnl or dnl --with-oci8=shared,/path/to/oracle/home PHP_ARG_WITH(oci8, for Oracle Database OCI8 support, -[ --with-oci8[=DIR] Include Oracle Database OCI8 support. DIR defaults to \$ORACLE_HOME. - Use --with-oci8=instantclient,/path/to/instant/client/lib +[ --with-oci8[=DIR] Include Oracle Database OCI8 support. DIR defaults to [$]ORACLE_HOME. + Use --with-oci8=instantclient,/path/to/instant/client/lib to use an Oracle Instant Client installation]) if test "$PHP_OCI8" != "no"; then @@ -138,14 +208,38 @@ if test "$PHP_OCI8" != "no"; then IFS=$ac_IFS oci8_php_version=`expr [$]1 \* 1000000 + [$]2 \* 1000 + [$]3` - if test "$oci8_php_version" -lt "4003009"; then - AC_MSG_ERROR([You need at least PHP 4.3.9 to be able to use this version of OCI8. PHP $php_version found]) - elif test "$oci8_php_version" -ge "6000000"; then - AC_MSG_ERROR([This version of OCI8 is not compatible with PHP 6 or higher]) + if test "$oci8_php_version" -lt "5002000"; then + AC_MSG_ERROR([You need at least PHP 5.2.0 to be able to use this version of OCI8. PHP $php_version found]) else AC_MSG_RESULT([$php_version, ok]) fi + dnl Check whether --enable-dtrace was set. + dnl To use DTrace with a PECL install, extract the OCI8 archive, phpize it, and set + dnl PHP_DTRACE=yes before running configure + AC_MSG_CHECKING([OCI8 DTrace support]) + oci8_do_dtrace="`echo $PHP_OCI8 | cut -d, -f3`" + if test "$PHP_DTRACE" = "yes" -o "$oci8_do_dtrace" = "dtrace" ; then + AC_MSG_RESULT([yes]) + if test "$ext_shared" = "no"; then + AC_MSG_ERROR([For DTrace support OCI8 must be configured as a shared extension]) + else + AC_CHECK_HEADERS([sys/sdt.h], [ + OCI8_INIT_DTRACE([oci8_dtrace.d],[oci8_dtrace_gen.h],[oci8.c oci8_statement.c]) + + ], [ + AC_MSG_ERROR( + [Cannot find sys/sdt.h which is required for DTrace support]) + ]) + PHP_SUBST(OCI8_DTRACE_OBJS) + AC_DEFINE(HAVE_OCI8_DTRACE,1,[Defined to 1 if PHP OCI8 DTrace support was enabled during configuration]) + dnl Developer warning: hard coded extension is OK for the known supported environments + shared_objects_oci8="$shared_objects_oci8 PHP_EXT_BUILDDIR(oci8)/oci8_dtrace.d.lo" + fi + else + AC_MSG_RESULT([no]) + fi + dnl Set some port specific directory components for use later AC_CHECK_SIZEOF(long int, 4) @@ -238,31 +332,15 @@ if test "$PHP_OCI8" != "no"; then AC_OCI8_ORACLE_VERSION($OCI8_DIR) case $OCI8_ORACLE_VERSION in - 7.3|8.0|8.1) - AC_MSG_ERROR([Oracle client libraries < 9.2 are not supported]) - ;; - - 9.0) - PHP_CHECK_LIBRARY(clntsh, OCIEnvNlsCreate, - [ - OCI8_ORACLE_VERSION=9.2 - ], - [ - AC_MSG_ERROR([Oracle client libraries < 9.2 are not supported]) - ], [ - -L$OCI8_DIR/$OCI8_LIB_DIR $OCI8_SHARED_LIBADD - ]) - ;; - - *) - AC_DEFINE(HAVE_OCI_LOB_READ2,1,[ ]) + 7.3|8.0|8.1|9.0) + AC_MSG_ERROR([Oracle client libraries < 10 are not supported]) ;; esac PHP_ADD_LIBRARY(clntsh, 1, OCI8_SHARED_LIBADD) PHP_ADD_LIBPATH($OCI8_DIR/$OCI8_LIB_DIR, OCI8_SHARED_LIBADD) PHP_NEW_EXTENSION(oci8, oci8.c oci8_lob.c oci8_statement.c oci8_collection.c oci8_interface.c, $ext_shared) - AC_DEFINE(HAVE_OCI8,1,[ ]) + AC_DEFINE(HAVE_OCI8,1,[Defined to 1 if the PHP OCI8 extension for Oracle Database is configured]) PHP_SUBST_OLD(OCI8_SHARED_LIBADD) PHP_SUBST_OLD(OCI8_DIR) @@ -330,11 +408,10 @@ if test "$PHP_OCI8" != "no"; then PHP_ADD_LIBRARY(clntsh, 1, OCI8_SHARED_LIBADD) PHP_ADD_LIBPATH($PHP_OCI8_INSTANT_CLIENT, OCI8_SHARED_LIBADD) - AC_DEFINE(HAVE_OCI_INSTANT_CLIENT,1,[ ]) - AC_DEFINE(HAVE_OCI_LOB_READ2,1,[ ]) + AC_DEFINE(HAVE_OCI_INSTANT_CLIENT,1,[Defined to 1 if OCI8 configuration located Oracle's Instant Client libraries]) PHP_NEW_EXTENSION(oci8, oci8.c oci8_lob.c oci8_statement.c oci8_collection.c oci8_interface.c, $ext_shared) - AC_DEFINE(HAVE_OCI8,1,[ ]) + AC_DEFINE(HAVE_OCI8,1,[Defined to 1 if the PHP OCI8 extension for Oracle Database is configured]) PHP_SUBST_OLD(OCI8_SHARED_LIBADD) PHP_SUBST_OLD(OCI8_DIR) diff --git a/ext/oci8/config.w32 b/ext/oci8/config.w32 index fdd7fa5e48..d83bf3fbdb 100644 --- a/ext/oci8/config.w32 +++ b/ext/oci8/config.w32 @@ -5,6 +5,19 @@ if (PHP_OCI8 != "no" && PHP_OCI8_11G != "no") { if (!PHP_OCI8_SHARED && !PHP_OCI8_11G_SHARED) { WARNING("oci8 and oci8-11g provide the same extension and cannot both be built statically"); PHP_OCI8 = "no" + } +} + +if (PHP_OCI8 != "no" && PHP_OCI8_12C != "no") { + if (!PHP_OCI8_SHARED && !PHP_OCI8_12C_SHARED) { + WARNING("oci8 and oci8-12c provide the same extension and cannot both be built statically"); + PHP_OCI8 = "no" + } +} + +if (PHP_OCI8_11G != "no" && PHP_OCI8_12C != "no") { + if (!PHP_OCI8_11G_SHARED && !PHP_OCI8_12C_SHARED) { + WARNING("oci8-11g and oci8-12c provide the same extension and cannot both be built statically"); PHP_OCI8_11G = "no" } } @@ -37,10 +50,9 @@ if (PHP_OCI8 != "no") { AC_DEFINE('HAVE_OCI8', 1); AC_DEFINE('HAVE_OCI_INSTANT_CLIENT', 1); - AC_DEFINE('HAVE_OCI_LOB_READ2', 1); } else { - WARNING("oci8 not enabled: Oracle Database libraries or Oracle 10g Instant Client not found"); + WARNING("oci8 not enabled: Oracle Database client libraries or Oracle 10g Instant Client not found"); PHP_OCI8 = "no" } } @@ -73,10 +85,43 @@ if (PHP_OCI8_11G != "no") { AC_DEFINE('HAVE_OCI8', 1); AC_DEFINE('HAVE_OCI_INSTANT_CLIENT', 1); - AC_DEFINE('HAVE_OCI_LOB_READ2', 1); } else { - WARNING("oci8-11g not enabled: Oracle Database libraries or Oracle 11g Instant Client not found"); + WARNING("oci8-11g not enabled: Oracle Database client libraries or Oracle 11g Instant Client not found"); PHP_OCI8_11G = "no" } } + +ARG_WITH("oci8-12c", "OCI8 support using Oracle Database 12c Instant Client", "no"); + +if (PHP_OCI8_12C != "no") { + + oci8_12c_dirs = new Array( + PHP_OCI8_12C + ); + + oci8_12c_lib_paths = ""; + oci8_12c_inc_paths = ""; + + // find the Oracle install + for (i = 0; i < oci8_12c_dirs.length; i++) { + oci8_12c_lib_paths += oci8_12c_dirs[i] + "\\lib;"; + oci8_12c_lib_paths += oci8_12c_dirs[i] + "\\lib\\msvc;"; + oci8_12c_inc_paths += oci8_12c_dirs[i] + "\\include;"; + } + + oci8_12c_inc_paths += PHP_PHP_BUILD + "\\include\\instantclient_12;" + oci8_12c_lib_paths += PHP_PHP_BUILD + "\\lib\\instantclient_12;"; + + if (CHECK_HEADER_ADD_INCLUDE("oci.h", "CFLAGS_OCI8_12C", oci8_12c_inc_paths) && + CHECK_LIB("oci.lib", "oci8_12c", oci8_12c_lib_paths)) + { + EXTENSION('oci8_12c', 'oci8.c oci8_lob.c oci8_statement.c oci8_collection.c oci8_interface.c', null, null, null, "ext\\oci8_12c") + + AC_DEFINE('HAVE_OCI8', 1); + AC_DEFINE('HAVE_OCI_INSTANT_CLIENT', 1); + } else { + WARNING("oci8-12c not enabled: Oracle Database client libraries or Oracle Database 12c Instant Client not found"); + PHP_OCI8_12C = "no" + } +} diff --git a/ext/oci8/oci8.c b/ext/oci8/oci8.c index 44bfa71398..1e505f13e9 100644 --- a/ext/oci8/oci8.c +++ b/ext/oci8/oci8.c @@ -12,7 +12,7 @@ | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ - | Authors: Stig Sæther Bakken <ssb@php.net> | + | Authors: Stig Sæther Bakken <ssb@php.net> | | Thies C. Arntzen <thies@thieso.net> | | Maxim Maletsky <maxim@maxim.cx> | | | @@ -37,41 +37,34 @@ #include "php_ini.h" #include "ext/standard/php_smart_str.h" -#ifdef HAVE_STDINT_H -#include <stdint.h> -#endif -#ifdef PHP_WIN32 -#include "win32/php_stdint.h" -#endif - #if HAVE_OCI8 -#if PHP_MAJOR_VERSION > 5 -#error This version of the PHP OCI8 extension is not compatible with PHP 6 or later -#elif PHP_MAJOR_VERSION < 5 -#ifdef ZTS -#error The PHP OCI8 extension does not support ZTS mode in PHP 4 -#endif +/* PHP 5.2 is the minimum supported version for OCI8 2.0 */ +#if PHP_MAJOR_VERSION < 5 || (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION <= 1) +#error Use PHP OCI8 1.4 for your version of PHP #endif #include "php_oci8.h" #include "php_oci8_int.h" #include "zend_hash.h" -#if defined(HAVE_STDINT_H) || defined(PHP_WIN32) -#define OCI8_INT_TO_PTR(I) ((void *)(intptr_t)(I)) +#if defined(__PTRDIFF_TYPE__) +# define OCI8_INT_TO_PTR(I) ((void*)(__PTRDIFF_TYPE__)(I)) +# define OCI8_PTR_TO_INT(P) ((int)(__PTRDIFF_TYPE__)(P)) +#elif !defined(__GNUC__) +#define OCI8_INT_TO_PTR(I) ((void*)&((char*)0)[I]) +#define OCI8_PTR_TO_INT(P) ((int)(((char*)P)-(char*)0)) +#elif defined(HAVE_STDINT_H) +#define OCI8_INT_TO_PTR(I) ((void*)(intptr_t)(I)) #define OCI8_PTR_TO_INT(P) ((int)(intptr_t)(P)) #else -#define OCI8_INT_TO_PTR(I) ((void *)(I)) +#define OCI8_INT_TO_PTR(I) ((void*)(I)) #define OCI8_PTR_TO_INT(P) ((int)(P)) #endif ZEND_DECLARE_MODULE_GLOBALS(oci) -#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 1) || (PHP_MAJOR_VERSION > 5) -/* This "if" allows PECL builds from this file to be portable to older PHP releases */ static PHP_GINIT_FUNCTION(oci); static PHP_GSHUTDOWN_FUNCTION(oci); -#endif /* Allow PHP 5.3 branch to be used in PECL for 5.x compatible builds */ #ifndef Z_ADDREF_P @@ -128,7 +121,7 @@ zend_class_entry *oci_coll_class_entry_ptr; #define PHP_OCI_INIT_MODE (OCI_DEFAULT | OCI_OBJECT) #endif -/* static protos {{{ */ +/* {{{ static protos */ static void php_oci_connection_list_dtor (zend_rsrc_list_entry * TSRMLS_DC); static void php_oci_pconnection_list_dtor (zend_rsrc_list_entry * TSRMLS_DC); static void php_oci_pconnection_list_np_dtor (zend_rsrc_list_entry * TSRMLS_DC); @@ -152,7 +145,7 @@ static sword php_oci_ping_init(php_oci_connection *connection, OCIError *errh TS /* }}} */ /* {{{ dynamically loadable module stuff */ -#if defined(COMPILE_DL_OCI8) || defined(COMPILE_DL_OCI8_11G) +#if defined(COMPILE_DL_OCI8) || defined(COMPILE_DL_OCI8_11G) || defined(COMPILE_DL_OCI8_12C) ZEND_GET_MODULE(oci8) #endif /* COMPILE_DL */ /* }}} */ @@ -425,6 +418,10 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_parse, 0, 0, 2) ZEND_ARG_INFO(0, sql_text) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_get_implicit_resultset, 0, 0, 1) +ZEND_ARG_INFO(0, statement_resource) +ZEND_END_ARG_INFO() + ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_set_prefetch, 0, 0, 2) ZEND_ARG_INFO(0, statement_resource) ZEND_ARG_INFO(0, number_of_rows) @@ -454,6 +451,13 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_set_client_info, 0, 0, 2) ZEND_ARG_INFO(0, client_information) ZEND_END_ARG_INFO() +#ifdef WAITIING_ORACLE_BUG_16695981_FIX +ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_set_db_operation, 0, 0, 2) +ZEND_ARG_INFO(0, connection_resource) +ZEND_ARG_INFO(0, action) +ZEND_END_ARG_INFO() +#endif + ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_password_change, 0, 0, 4) ZEND_ARG_INFO(0, connection_resource_or_connection_string) ZEND_ARG_INFO(0, username) @@ -698,12 +702,16 @@ static unsigned char arginfo_oci_bind_array_by_name[] = { 3, BYREF_NONE, BYREF_N #define arginfo_oci_error NULL #define arginfo_oci_num_fields NULL #define arginfo_oci_parse NULL +#define arginfo_oci_get_implicit_resultset NULL #define arginfo_oci_set_prefetch NULL #define arginfo_oci_set_client_identifier NULL #define arginfo_oci_set_edition NULL #define arginfo_oci_set_module_name NULL #define arginfo_oci_set_action NULL #define arginfo_oci_set_client_info NULL +#ifdef WAITIING_ORACLE_BUG_16695981_FIX +#define arginfo_oci_set_db_operation NULL +#endif #define arginfo_oci_password_change NULL #define arginfo_oci_new_cursor NULL #define arginfo_oci_result NULL @@ -786,6 +794,7 @@ PHP_FUNCTION(oci_rollback); PHP_FUNCTION(oci_new_descriptor); PHP_FUNCTION(oci_num_fields); PHP_FUNCTION(oci_parse); +PHP_FUNCTION(oci_get_implicit_resultset); PHP_FUNCTION(oci_new_cursor); PHP_FUNCTION(oci_result); PHP_FUNCTION(oci_client_version); @@ -794,6 +803,9 @@ PHP_FUNCTION(oci_statement_type); PHP_FUNCTION(oci_num_rows); PHP_FUNCTION(oci_set_prefetch); PHP_FUNCTION(oci_set_client_identifier); +#ifdef WAITIING_ORACLE_BUG_16695981_FIX +PHP_FUNCTION(oci_set_db_operation); +#endif PHP_FUNCTION(oci_set_edition); PHP_FUNCTION(oci_set_module_name); PHP_FUNCTION(oci_set_action); @@ -862,6 +874,7 @@ zend_function_entry php_oci_functions[] = { PHP_FE(oci_internal_debug, arginfo_oci_internal_debug) PHP_FE(oci_num_fields, arginfo_oci_num_fields) PHP_FE(oci_parse, arginfo_oci_parse) + PHP_FE(oci_get_implicit_resultset, arginfo_oci_get_implicit_resultset) PHP_FE(oci_new_cursor, arginfo_oci_new_cursor) PHP_FE(oci_result, arginfo_oci_result) PHP_FE(oci_client_version, arginfo_oci_client_version) @@ -898,6 +911,9 @@ zend_function_entry php_oci_functions[] = { PHP_FE(oci_new_descriptor, arginfo_oci_new_descriptor) PHP_FE(oci_set_prefetch, arginfo_oci_set_prefetch) PHP_FE(oci_set_client_identifier, arginfo_oci_set_client_identifier) +#ifdef WAITIING_ORACLE_BUG_16695981_FIX + PHP_FE(oci_set_db_operation, arginfo_oci_set_db_operation) +#endif PHP_FE(oci_set_edition, arginfo_oci_set_edition) PHP_FE(oci_set_module_name, arginfo_oci_set_module_name) PHP_FE(oci_set_action, arginfo_oci_set_action) @@ -1033,16 +1049,11 @@ zend_module_entry oci8_module_entry = { PHP_RSHUTDOWN(oci), /* per-request shutdown function */ PHP_MINFO(oci), /* information function */ PHP_OCI8_VERSION, -#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 1) || (PHP_MAJOR_VERSION > 5) - /* This check allows PECL builds from this file to be portable to older PHP releases */ PHP_MODULE_GLOBALS(oci), /* globals descriptor */ PHP_GINIT(oci), /* globals ctor */ PHP_GSHUTDOWN(oci), /* globals dtor */ NULL, /* post deactivate */ STANDARD_MODULE_PROPERTIES_EX -#else - STANDARD_MODULE_PROPERTIES -#endif }; /* }}} */ @@ -1055,8 +1066,12 @@ PHP_INI_BEGIN() STD_PHP_INI_ENTRY( "oci8.statement_cache_size", "20", PHP_INI_SYSTEM, ONUPDATELONGFUNC, statement_cache_size, zend_oci_globals, oci_globals) STD_PHP_INI_ENTRY( "oci8.default_prefetch", "100", PHP_INI_SYSTEM, ONUPDATELONGFUNC, default_prefetch, zend_oci_globals, oci_globals) STD_PHP_INI_BOOLEAN("oci8.old_oci_close_semantics", "0", PHP_INI_SYSTEM, OnUpdateBool, old_oci_close_semantics,zend_oci_globals, oci_globals) +#if (OCI_MAJOR_VERSION >= 11) STD_PHP_INI_ENTRY( "oci8.connection_class", "", PHP_INI_ALL, OnUpdateString, connection_class, zend_oci_globals, oci_globals) +#endif +#if ((OCI_MAJOR_VERSION > 10) || ((OCI_MAJOR_VERSION == 10) && (OCI_MINOR_VERSION >= 2))) STD_PHP_INI_BOOLEAN("oci8.events", "0", PHP_INI_SYSTEM, OnUpdateBool, events, zend_oci_globals, oci_globals) +#endif PHP_INI_END() /* }}} */ @@ -1132,7 +1147,8 @@ static void php_oci_init_global_handles(TSRMLS_D) } } } -} /* }}} */ +} +/* }}} */ /* {{{ php_oci_cleanup_global_handles() * @@ -1149,18 +1165,14 @@ static void php_oci_cleanup_global_handles(TSRMLS_D) PHP_OCI_CALL(OCIHandleFree, ((dvoid *) OCI_G(env), OCI_HTYPE_ENV)); OCI_G(env) = NULL; } -} /* }}} */ +} +/* }}} */ /* {{{ PHP_GINIT_FUNCTION * * Zerofill globals during module init */ -#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 1) || (PHP_MAJOR_VERSION > 5) -/* This check allows PECL builds from this file to be portable to older PHP releases */ static PHP_GINIT_FUNCTION(oci) -#else -static void php_oci_init_globals(zend_oci_globals *oci_globals TSRMLS_DC) -#endif { memset(oci_globals, 0, sizeof(zend_oci_globals)); } @@ -1170,12 +1182,7 @@ static void php_oci_init_globals(zend_oci_globals *oci_globals TSRMLS_DC) * * Called for thread shutdown in ZTS, after module shutdown for non-ZTS */ -/* This check allows PECL builds from this file to be portable to older PHP releases */ -#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 1) || (PHP_MAJOR_VERSION > 5) static PHP_GSHUTDOWN_FUNCTION(oci) -#else -static void php_oci_shutdown_globals(zend_oci_globals *oci_globals TSRMLS_DC) -#endif { php_oci_cleanup_global_handles(TSRMLS_C); } @@ -1186,12 +1193,6 @@ PHP_MINIT_FUNCTION(oci) zend_class_entry oci_lob_class_entry; zend_class_entry oci_coll_class_entry; -#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 1) || (PHP_MAJOR_VERSION > 5) - /* This check allows PECL builds from this file to be portable to older PHP releases */ - /* this is handled by new globals management code */ -#else - ZEND_INIT_MODULE_GLOBALS(oci, php_oci_init_globals, php_oci_shutdown_globals); -#endif REGISTER_INI_ENTRIES(); le_statement = zend_register_list_destructors_ex(php_oci_statement_list_dtor, NULL, "oci8 statement", module_number); @@ -1294,7 +1295,6 @@ PHP_MINIT_FUNCTION(oci) PHP_RINIT_FUNCTION(oci) { - OCI_G(debug_mode) = 0; /* start "fresh" */ OCI_G(num_links) = OCI_G(num_persistent); OCI_G(errcode) = 0; OCI_G(edition) = NULL; @@ -1304,13 +1304,6 @@ PHP_RINIT_FUNCTION(oci) PHP_MSHUTDOWN_FUNCTION(oci) { -/* Work around PHP_GSHUTDOWN_FUNCTION not being called in older versions of PHP */ -#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION < 2) || (PHP_MAJOR_VERSION < 5) -#ifndef ZTS - php_oci_cleanup_global_handles(TSRMLS_C); -#endif -#endif - OCI_G(shutdown) = 1; UNREGISTER_INI_ENTRIES(); @@ -1336,22 +1329,26 @@ PHP_RSHUTDOWN_FUNCTION(oci) PHP_MINFO_FUNCTION(oci) { char buf[32]; +#if ((OCI_MAJOR_VERSION > 10) || ((OCI_MAJOR_VERSION == 10) && (OCI_MINOR_VERSION >= 2))) char *ver; +#endif php_info_print_table_start(); php_info_print_table_row(2, "OCI8 Support", "enabled"); - php_info_print_table_row(2, "Version", PHP_OCI8_VERSION); +#if defined(HAVE_OCI8_DTRACE) + php_info_print_table_row(2, "OCI8 DTrace Support", "enabled"); +#else + php_info_print_table_row(2, "OCI8 DTrace Support", "disabled"); +#endif + php_info_print_table_row(2, "OCI8 Version", PHP_OCI8_VERSION); php_info_print_table_row(2, "Revision", "$Id$"); - snprintf(buf, sizeof(buf), "%ld", OCI_G(num_persistent)); - php_info_print_table_row(2, "Active Persistent Connections", buf); - snprintf(buf, sizeof(buf), "%ld", OCI_G(num_links)); - php_info_print_table_row(2, "Active Connections", buf); - #if ((OCI_MAJOR_VERSION > 10) || ((OCI_MAJOR_VERSION == 10) && (OCI_MINOR_VERSION >= 2))) php_oci_client_get_version(&ver TSRMLS_CC); php_info_print_table_row(2, "Oracle Run-time Client Library Version", ver); efree(ver); +#else + php_info_print_table_row(2, "Oracle Run-time Client Library Version", "Unknown"); #endif #if defined(OCI_MAJOR_VERSION) && defined(OCI_MINOR_VERSION) snprintf(buf, sizeof(buf), "%d.%d", OCI_MAJOR_VERSION, OCI_MINOR_VERSION); @@ -1361,9 +1358,9 @@ PHP_MINFO_FUNCTION(oci) snprintf(buf, sizeof(buf), "Unknown"); #endif #if defined(HAVE_OCI_INSTANT_CLIENT) - php_info_print_table_row(2, "Oracle Instant Client Version", buf); + php_info_print_table_row(2, "Oracle Compile-time Instant Client Version", buf); #else - php_info_print_table_row(2, "Oracle Version", buf); + php_info_print_table_row(2, "Oracle Compile-time Version", buf); #endif #if !defined(PHP_WIN32) && !defined(HAVE_OCI_INSTANT_CLIENT) @@ -1375,14 +1372,22 @@ PHP_MINFO_FUNCTION(oci) #endif #endif - php_info_print_table_row(2, "Temporary Lob support", "enabled"); - php_info_print_table_row(2, "Collections support", "enabled"); + php_info_print_table_end(); + DISPLAY_INI_ENTRIES(); + + php_info_print_table_start(); + php_info_print_table_header(2, "Statistics", ""); + snprintf(buf, sizeof(buf), "%ld", OCI_G(num_persistent)); + php_info_print_table_row(2, "Active Persistent Connections", buf); + snprintf(buf, sizeof(buf), "%ld", OCI_G(num_links)); + php_info_print_table_row(2, "Active Connections", buf); + php_info_print_table_end(); } /* }}} */ -/* list destructors {{{ */ +/* {{{ list destructors */ /* {{{ php_oci_connection_list_dtor() * @@ -1396,7 +1401,8 @@ static void php_oci_connection_list_dtor(zend_rsrc_list_entry *entry TSRMLS_DC) php_oci_connection_close(connection TSRMLS_CC); OCI_G(num_links)--; } -} /* }}} */ +} +/* }}} */ /* {{{ php_oci_pconnection_list_dtor() * @@ -1411,7 +1417,8 @@ static void php_oci_pconnection_list_dtor(zend_rsrc_list_entry *entry TSRMLS_DC) OCI_G(num_persistent)--; OCI_G(num_links)--; } -} /* }}} */ +} +/* }}} */ /* {{{ php_oci_pconnection_list_np_dtor() * @@ -1449,11 +1456,12 @@ static void php_oci_pconnection_list_np_dtor(zend_rsrc_list_entry *entry TSRMLS_ OCI_G(num_persistent)--; } - if (OCI_G(debug_mode)) { - php_printf ("OCI8 DEBUG L1: np_dtor cleaning up: (%p) at (%s:%d) \n", connection, __FILE__, __LINE__); +#ifdef HAVE_OCI8_DTRACE + if (DTRACE_OCI8_CONNECT_P_DTOR_CLOSE_ENABLED()) { + DTRACE_OCI8_CONNECT_P_DTOR_CLOSE(connection); } - } - else { +#endif /* HAVE_OCI8_DTRACE */ + } else { /* * Release the connection to underlying pool. We do this unconditionally so that * out-of-scope pconnects are now consistent with oci_close and out-of-scope new connect @@ -1465,11 +1473,14 @@ static void php_oci_pconnection_list_np_dtor(zend_rsrc_list_entry *entry TSRMLS_ */ php_oci_connection_release(connection TSRMLS_CC); - if (OCI_G(debug_mode)) { - php_printf ("OCI8 DEBUG L1: np_dtor releasing: (%p) at (%s:%d) \n", connection, __FILE__, __LINE__); +#ifdef HAVE_OCI8_DTRACE + if (DTRACE_OCI8_CONNECT_P_DTOR_RELEASE_ENABLED()) { + DTRACE_OCI8_CONNECT_P_DTOR_RELEASE(connection); } +#endif /* HAVE_OCI8_DTRACE */ } -} /* }}} */ +} +/* }}} */ /* {{{ php_oci_statement_list_dtor() * @@ -1479,7 +1490,8 @@ static void php_oci_statement_list_dtor(zend_rsrc_list_entry *entry TSRMLS_DC) { php_oci_statement *statement = (php_oci_statement *)entry->ptr; php_oci_statement_free(statement TSRMLS_CC); -} /* }}} */ +} +/* }}} */ /* {{{ php_oci_descriptor_list_dtor() * @@ -1489,7 +1501,8 @@ static void php_oci_descriptor_list_dtor(zend_rsrc_list_entry *entry TSRMLS_DC) { php_oci_descriptor *descriptor = (php_oci_descriptor *)entry->ptr; php_oci_lob_free(descriptor TSRMLS_CC); -} /* }}} */ +} +/* }}} */ /* {{{ php_oci_collection_list_dtor() * @@ -1499,11 +1512,12 @@ static void php_oci_collection_list_dtor(zend_rsrc_list_entry *entry TSRMLS_DC) { php_oci_collection *collection = (php_oci_collection *)entry->ptr; php_oci_collection_close(collection TSRMLS_CC); -} /* }}} */ +} +/* }}} */ /* }}} */ -/* Hash Destructors {{{ */ +/* {{{ Hash Destructors */ /* {{{ php_oci_define_hash_dtor() * @@ -1605,18 +1619,17 @@ void php_oci_connection_descriptors_free(php_oci_connection *connection TSRMLS_D } /* }}} */ - /* {{{ php_oci_error() * * Fetch & print out error message if we get an error * Returns an Oracle error number */ -sb4 php_oci_error(OCIError *err_p, sword status TSRMLS_DC) +sb4 php_oci_error(OCIError *err_p, sword errstatus TSRMLS_DC) { text *errbuf = (text *)NULL; - sb4 errcode = 0; + sb4 errcode = 0; /* Oracle error number */ - switch (status) { + switch (errstatus) { case OCI_SUCCESS: break; case OCI_SUCCESS_WITH_INFO: @@ -1659,9 +1672,16 @@ sb4 php_oci_error(OCIError *err_p, sword status TSRMLS_DC) php_error_docref(NULL TSRMLS_CC, E_WARNING, "OCI_CONTINUE"); break; default: - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown OCI error code: %d", status); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown OCI error code: %d", errstatus); break; } + +#ifdef HAVE_OCI8_DTRACE + if (DTRACE_OCI8_ERROR_ENABLED()) { + DTRACE_OCI8_ERROR((int)errstatus, (long)errcode); + } +#endif /* HAVE_OCI8_DTRACE */ + return errcode; } /* }}} */ @@ -1690,7 +1710,8 @@ sb4 php_oci_fetch_errmsg(OCIError *error_handle, text **error_buf TSRMLS_DC) } } return error_code; -} /* }}} */ +} +/* }}} */ /* {{{ php_oci_fetch_sqltext_offset() * @@ -1718,7 +1739,8 @@ int php_oci_fetch_sqltext_offset(php_oci_statement *statement, text **sqltext, u return 1; } return 0; -} /* }}} */ +} +/* }}} */ /* {{{ php_oci_do_connect() * @@ -1738,18 +1760,32 @@ void php_oci_do_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent, int exclus return; } +#ifdef HAVE_OCI8_DTRACE + if (DTRACE_OCI8_CONNECT_ENTRY_ENABLED()) { + DTRACE_OCI8_CONNECT_ENTRY(username, dbname, charset, session_mode, persistent, exclusive); + } +#endif /* HAVE_OCI8_DTRACE */ + if (!charset_len) { charset = NULL; } connection = php_oci_do_connect_ex(username, username_len, password, password_len, NULL, 0, dbname, dbname_len, charset, session_mode, persistent, exclusive TSRMLS_CC); +#ifdef HAVE_OCI8_DTRACE + if (DTRACE_OCI8_CONNECT_RETURN_ENABLED()) { + DTRACE_OCI8_CONNECT_RETURN(connection); + } +#endif /* HAVE_OCI8_DTRACE */ + + if (!connection) { RETURN_FALSE; } - RETURN_RESOURCE(connection->rsrc_id); + RETURN_RESOURCE(connection->id); -} /* }}} */ +} +/* }}} */ /* {{{ php_oci_do_connect_ex() * @@ -1908,16 +1944,11 @@ php_oci_connection *php_oci_do_connect_ex(char *username, int username_len, char } } - /* Debug statements {{{ */ - if (OCI_G(debug_mode)) { - if (connection && connection->is_stub) { - php_printf ("OCI8 DEBUG L1: Got a cached stub: (%p) at (%s:%d) \n", connection, __FILE__, __LINE__); - } else if (connection) { - php_printf ("OCI8 DEBUG L1: Got a cached connection: (%p) at (%s:%d) \n", connection, __FILE__, __LINE__); - } else { - php_printf ("OCI8 DEBUG L1: Got NO cached connection at (%s:%d) \n", __FILE__, __LINE__); - } - } /* }}} */ +#ifdef HAVE_OCI8_DTRACE + if (DTRACE_OCI8_CONNECT_LOOKUP_ENABLED()) { + DTRACE_OCI8_CONNECT_LOOKUP(connection, connection && connection->is_stub ? 1 : 0); + } +#endif /* HAVE_OCI8_DTRACE */ /* If we got a pconnection stub, then 'load'(OCISessionGet) the real connection from its * private spool A connection is a stub if it is only a cached structure and the real @@ -1963,24 +1994,20 @@ php_oci_connection *php_oci_do_connect_ex(char *username, int username_len, char /* okay, the connection is open and the server is still alive */ connection->used_this_request = 1; - tmp = (php_oci_connection *)zend_list_find(connection->rsrc_id, &rsrc_type); + tmp = (php_oci_connection *)zend_list_find(connection->id, &rsrc_type); if (tmp != NULL && rsrc_type == le_pconnection && strlen(tmp->hash_key) == hashed_details.len && - memcmp(tmp->hash_key, hashed_details.c, hashed_details.len) == 0 && zend_list_addref(connection->rsrc_id) == SUCCESS) { + memcmp(tmp->hash_key, hashed_details.c, hashed_details.len) == 0 && zend_list_addref(connection->id) == SUCCESS) { /* do nothing */ } else { -#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 3) || (PHP_MAJOR_VERSION > 5) - connection->rsrc_id = zend_list_insert(connection, le_pconnection TSRMLS_CC); -#else - connection->rsrc_id = zend_list_insert(connection, le_pconnection); -#endif + PHP_OCI_REGISTER_RESOURCE(connection, le_pconnection); /* Persistent connections: For old close semantics we artificially * bump up the refcount to prevent the non-persistent destructor * from getting called until request shutdown. The refcount is * decremented in the persistent helper */ if (OCI_G(old_oci_close_semantics)) { - zend_list_addref(connection->rsrc_id); + zend_list_addref(connection->id); } } smart_str_free_ex(&hashed_details, 0); @@ -1991,7 +2018,7 @@ php_oci_connection *php_oci_do_connect_ex(char *username, int username_len, char } else { /* we do not ping non-persistent connections */ smart_str_free_ex(&hashed_details, 0); - zend_list_addref(connection->rsrc_id); + zend_list_addref(connection->id); return connection; } } /* is_open is true? */ @@ -2008,7 +2035,7 @@ php_oci_connection *php_oci_do_connect_ex(char *username, int username_len, char /* We have to do a hash_del but need to preserve the resource if there is a positive * refcount. Set the data pointer in the list entry to NULL */ - if (connection == zend_list_find(connection->rsrc_id, &rsrc_type) && rsrc_type == le_pconnection) { + if (connection == zend_list_find(connection->id, &rsrc_type) && rsrc_type == le_pconnection) { le->ptr = NULL; } @@ -2052,6 +2079,9 @@ php_oci_connection *php_oci_do_connect_ex(char *username, int username_len, char connection = (php_oci_connection *) ecalloc(1, sizeof(php_oci_connection)); connection->hash_key = estrndup(hashed_details.c, hashed_details.len); connection->is_persistent = 0; +#ifdef HAVE_OCI8_DTRACE + connection->client_id = NULL; +#endif } else { connection = (php_oci_connection *) calloc(1, sizeof(php_oci_connection)); if (connection == NULL) { @@ -2063,11 +2093,17 @@ php_oci_connection *php_oci_do_connect_ex(char *username, int username_len, char return NULL; } connection->is_persistent = 1; +#ifdef HAVE_OCI8_DTRACE + connection->client_id = NULL; +#endif } } else { connection = (php_oci_connection *) ecalloc(1, sizeof(php_oci_connection)); connection->hash_key = estrndup(hashed_details.c, hashed_details.len); connection->is_persistent = 0; +#ifdef HAVE_OCI8_DTRACE + connection->client_id = NULL; +#endif } /* {{{ Get the session pool that suits this connection request from the persistent list. This @@ -2085,7 +2121,8 @@ php_oci_connection *php_oci_do_connect_ex(char *username, int username_len, char smart_str_free_ex(&hashed_details, 0); return NULL; } - } /* }}} */ + } + /* }}} */ connection->idle_expiry = (OCI_G(persistent_timeout) > 0) ? (timestamp + OCI_G(persistent_timeout)) : 0; @@ -2124,50 +2161,34 @@ php_oci_connection *php_oci_do_connect_ex(char *username, int username_len, char new_le.ptr = connection; new_le.type = le_pconnection; connection->used_this_request = 1; -#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 3) || (PHP_MAJOR_VERSION > 5) - connection->rsrc_id = zend_list_insert(connection, le_pconnection TSRMLS_CC); -#else - connection->rsrc_id = zend_list_insert(connection, le_pconnection); -#endif + PHP_OCI_REGISTER_RESOURCE(connection, le_pconnection); /* Persistent connections: For old close semantics we artificially bump up the refcount to * prevent the non-persistent destructor from getting called until request shutdown. The * refcount is decremented in the persistent helper */ if (OCI_G(old_oci_close_semantics)) { - zend_list_addref(connection->rsrc_id); + zend_list_addref(connection->id); } zend_hash_update(&EG(persistent_list), connection->hash_key, strlen(connection->hash_key)+1, (void *)&new_le, sizeof(zend_rsrc_list_entry), NULL); OCI_G(num_persistent)++; OCI_G(num_links)++; } else if (!exclusive) { -#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 3) || (PHP_MAJOR_VERSION > 5) - connection->rsrc_id = zend_list_insert(connection, le_connection TSRMLS_CC); -#else - connection->rsrc_id = zend_list_insert(connection, le_connection); -#endif - new_le.ptr = OCI8_INT_TO_PTR(connection->rsrc_id); + PHP_OCI_REGISTER_RESOURCE(connection, le_connection); + new_le.ptr = OCI8_INT_TO_PTR(connection->id); new_le.type = le_index_ptr; zend_hash_update(&EG(regular_list), connection->hash_key, strlen(connection->hash_key)+1, (void *)&new_le, sizeof(zend_rsrc_list_entry), NULL); OCI_G(num_links)++; } else { -#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 3) || (PHP_MAJOR_VERSION > 5) - connection->rsrc_id = zend_list_insert(connection, le_connection TSRMLS_CC); -#else - connection->rsrc_id = zend_list_insert(connection, le_connection); -#endif + PHP_OCI_REGISTER_RESOURCE(connection, le_connection); OCI_G(num_links)++; } - /* Debug statements {{{ */ - if (OCI_G(debug_mode)) { - if (connection->is_persistent) { - php_printf ("OCI8 DEBUG L1: New Persistent Connection address: (%p) at (%s:%d) \n", connection, __FILE__, __LINE__); - } else { - php_printf ("OCI8 DEBUG L1: New Non-Persistent Connection address: (%p) at (%s:%d) \n", connection, __FILE__, __LINE__); - } - php_printf ("OCI8 DEBUG L1: num_persistent=(%ld), num_links=(%ld) at (%s:%d) \n", OCI_G(num_persistent), OCI_G(num_links), __FILE__, __LINE__); - } /* }}} */ +#ifdef HAVE_OCI8_DTRACE + if (DTRACE_OCI8_CONNECT_TYPE_ENABLED()) { + DTRACE_OCI8_CONNECT_TYPE(connection->is_persistent ? 1 : 0, exclusive ? 1 : 0, connection, OCI_G(num_persistent), OCI_G(num_links)); + } +#endif /* HAVE_OCI8_DTRACE */ return connection; } @@ -2179,20 +2200,26 @@ php_oci_connection *php_oci_do_connect_ex(char *username, int username_len, char */ static int php_oci_connection_ping(php_oci_connection *connection TSRMLS_DC) { + sword errstatus; +#if (!((OCI_MAJOR_VERSION > 10) || ((OCI_MAJOR_VERSION == 10) && (OCI_MINOR_VERSION >= 2)))) + char version[256]; +#endif + + OCI_G(errcode) = 0; /* assume ping is successful */ + /* Use OCIPing instead of OCIServerVersion. If OCIPing returns ORA-1010 (invalid OCI operation) * such as from Pre-10.1 servers, the error is still from the server and we would have * successfully performed a roundtrip and validated the connection. Use OCIServerVersion for * Pre-10.2 clients */ #if ((OCI_MAJOR_VERSION > 10) || ((OCI_MAJOR_VERSION == 10) && (OCI_MINOR_VERSION >= 2))) /* OCIPing available 10.2 onwards */ - PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIPing, (connection->svc, OCI_G(err), OCI_DEFAULT)); + PHP_OCI_CALL_RETURN(errstatus, OCIPing, (connection->svc, OCI_G(err), OCI_DEFAULT)); #else - char version[256]; /* use good old OCIServerVersion() */ - PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIServerVersion, (connection->svc, OCI_G(err), (text *)version, sizeof(version), OCI_HTYPE_SVCCTX)); + PHP_OCI_CALL_RETURN(errstatus, OCIServerVersion, (connection->svc, OCI_G(err), (text *)version, sizeof(version), OCI_HTYPE_SVCCTX)); #endif - if (OCI_G(errcode) == OCI_SUCCESS) { + if (errstatus == OCI_SUCCESS) { return 1; } else { sb4 error_code = 0; @@ -2203,10 +2230,9 @@ static int php_oci_connection_ping(php_oci_connection *connection TSRMLS_DC) if (error_code == 1010) { return 1; } + OCI_G(errcode) = error_code; } - /* ignore errors here, just return failure - * php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC); */ return 0; } /* }}} */ @@ -2217,17 +2243,17 @@ static int php_oci_connection_ping(php_oci_connection *connection TSRMLS_DC) */ static int php_oci_connection_status(php_oci_connection *connection TSRMLS_DC) { - ub4 ss = 0; + ub4 ss = OCI_SERVER_NOT_CONNECTED; + sword errstatus; /* get OCI_ATTR_SERVER_STATUS */ - PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIAttrGet, ((dvoid *)connection->server, OCI_HTYPE_SERVER, (dvoid *)&ss, (ub4 *)0, OCI_ATTR_SERVER_STATUS, OCI_G(err))); + PHP_OCI_CALL_RETURN(errstatus, OCIAttrGet, ((dvoid *)connection->server, OCI_HTYPE_SERVER, (dvoid *)&ss, (ub4 *)0, OCI_ATTR_SERVER_STATUS, OCI_G(err))); - if (OCI_G(errcode) == OCI_SUCCESS && ss == OCI_SERVER_NORMAL) { + if (errstatus == OCI_SUCCESS && ss == OCI_SERVER_NORMAL) { return 1; } - /* ignore errors here, just return failure - * php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC); */ + /* ignore errors here, just return failure */ return 0; } /* }}} */ @@ -2238,16 +2264,20 @@ static int php_oci_connection_status(php_oci_connection *connection TSRMLS_DC) */ int php_oci_connection_rollback(php_oci_connection *connection TSRMLS_DC) { - PHP_OCI_CALL_RETURN(connection->errcode, OCITransRollback, (connection->svc, connection->err, (ub4) 0)); - connection->needs_commit = 0; + sword errstatus; + + PHP_OCI_CALL_RETURN(errstatus, OCITransRollback, (connection->svc, connection->err, (ub4) 0)); + connection->rb_on_disconnect = 0; - if (connection->errcode != OCI_SUCCESS) { - connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC); + if (errstatus != OCI_SUCCESS) { + connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC); PHP_OCI_HANDLE_ERROR(connection, connection->errcode); return 1; } + connection->errcode = 0; /* retain backwards compat with OCI8 1.4 */ return 0; -} /* }}} */ +} +/* }}} */ /* {{{ php_oci_connection_commit() * @@ -2255,16 +2285,20 @@ int php_oci_connection_rollback(php_oci_connection *connection TSRMLS_DC) */ int php_oci_connection_commit(php_oci_connection *connection TSRMLS_DC) { - PHP_OCI_CALL_RETURN(connection->errcode, OCITransCommit, (connection->svc, connection->err, (ub4) 0)); - connection->needs_commit = 0; + sword errstatus; - if (connection->errcode != OCI_SUCCESS) { - connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC); + PHP_OCI_CALL_RETURN(errstatus, OCITransCommit, (connection->svc, connection->err, (ub4) 0)); + connection->rb_on_disconnect = 0; + + if (errstatus != OCI_SUCCESS) { + connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC); PHP_OCI_HANDLE_ERROR(connection, connection->errcode); return 1; } + connection->errcode = 0; /* retain backwards compat with OCI8 1.4 */ return 0; -} /* }}} */ +} +/* }}} */ /* {{{ php_oci_connection_close() * @@ -2275,13 +2309,19 @@ static int php_oci_connection_close(php_oci_connection *connection TSRMLS_DC) int result = 0; zend_bool in_call_save = OCI_G(in_call); +#ifdef HAVE_OCI8_DTRACE + if (DTRACE_OCI8_CONNECTION_CLOSE_ENABLED()) { + DTRACE_OCI8_CONNECTION_CLOSE(connection); + } +#endif /* HAVE_OCI8_DTRACE */ + if (!connection->is_stub) { /* Release resources associated with connection */ php_oci_connection_release(connection TSRMLS_CC); } if (!connection->using_spool && connection->svc) { - PHP_OCI_CALL(OCISessionEnd, (connection->svc, connection->err, connection->session, (ub4) 0)); + PHP_OCI_CALL(OCISessionEnd, (connection->svc, connection->err, connection->session, (ub4) 0)); } if (connection->err) { @@ -2302,7 +2342,7 @@ static int php_oci_connection_close(php_oci_connection *connection TSRMLS_DC) } if (connection->svc) { - PHP_OCI_CALL(OCIHandleFree, ((dvoid *) connection->svc, (ub4) OCI_HTYPE_SVCCTX)); + PHP_OCI_CALL(OCIHandleFree, ((dvoid *) connection->svc, (ub4) OCI_HTYPE_SVCCTX)); } if (connection->server) { @@ -2319,21 +2359,20 @@ static int php_oci_connection_close(php_oci_connection *connection TSRMLS_DC) php_oci_spool_close(connection->private_spool TSRMLS_CC); } - if (connection->is_persistent) { - if (connection->hash_key) { - free(connection->hash_key); - } - free(connection); - } else { - if (connection->hash_key) { - efree(connection->hash_key); - } - efree(connection); + if (connection->hash_key) { + pefree(connection->hash_key, connection->is_persistent); + } +#ifdef HAVE_OCI8_DTRACE + if (connection->client_id) { + pefree(connection->client_id, connection->is_persistent); } +#endif /* HAVE_OCI8_DTRACE */ + pefree(connection, connection->is_persistent); connection = NULL; OCI_G(in_call) = in_call_save; return result; -} /* }}} */ +} +/* }}} */ /* {{{ php_oci_connection_release() * @@ -2357,7 +2396,7 @@ int php_oci_connection_release(php_oci_connection *connection TSRMLS_DC) if (connection->svc) { /* rollback outstanding transactions */ - if (connection->needs_commit) { + if (connection->rb_on_disconnect) { if (php_oci_connection_rollback(connection TSRMLS_CC)) { /* rollback failed */ result = 1; @@ -2408,18 +2447,25 @@ int php_oci_connection_release(php_oci_connection *connection TSRMLS_DC) connection->server = NULL; connection->session = NULL; - connection->is_attached = connection->is_open = connection->needs_commit = connection->used_this_request = 0; + connection->is_attached = connection->is_open = connection->rb_on_disconnect = connection->used_this_request = 0; connection->is_stub = 1; /* Cut the link between the connection structure and the time_t structure allocated within * the OCI session */ connection->next_pingp = NULL; +#ifdef HAVE_OCI8_DTRACE + if (connection->client_id) { + pefree(connection->client_id, connection->is_persistent); + connection->client_id = NULL; + } +#endif /* HAVE_OCI8_DTRACE */ } OCI_G(in_call) = in_call_save; return result; -} /* }}} */ +} +/* }}} */ /* {{{ php_oci_password_change() * @@ -2427,17 +2473,20 @@ int php_oci_connection_release(php_oci_connection *connection TSRMLS_DC) */ int php_oci_password_change(php_oci_connection *connection, char *user, int user_len, char *pass_old, int pass_old_len, char *pass_new, int pass_new_len TSRMLS_DC) { - PHP_OCI_CALL_RETURN(connection->errcode, OCIPasswordChange, (connection->svc, connection->err, (text *)user, user_len, (text *)pass_old, pass_old_len, (text *)pass_new, pass_new_len, OCI_DEFAULT)); + sword errstatus; - if (connection->errcode != OCI_SUCCESS) { - connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC); + PHP_OCI_CALL_RETURN(errstatus, OCIPasswordChange, (connection->svc, connection->err, (text *)user, user_len, (text *)pass_old, pass_old_len, (text *)pass_new, pass_new_len, OCI_DEFAULT)); + + if (errstatus != OCI_SUCCESS) { + connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC); PHP_OCI_HANDLE_ERROR(connection, connection->errcode); return 1; } + connection->errcode = 0; /* retain backwards compat with OCI8 1.4 */ connection->passwd_changed = 1; return 0; -} /* }}} */ - +} +/* }}} */ /* {{{ php_oci_client_get_version() * @@ -2446,21 +2495,21 @@ int php_oci_password_change(php_oci_connection *connection, char *user, int user void php_oci_client_get_version(char **version TSRMLS_DC) { char version_buff[256]; +#if ((OCI_MAJOR_VERSION > 10) || ((OCI_MAJOR_VERSION == 10) && (OCI_MINOR_VERSION >= 2))) /* OCIClientVersion only available 10.2 onwards */ sword major_version = 0; sword minor_version = 0; sword update_num = 0; sword patch_num = 0; sword port_update_num = 0; -#if ((OCI_MAJOR_VERSION > 10) || ((OCI_MAJOR_VERSION == 10) && (OCI_MINOR_VERSION >= 2))) /* OCIClientVersion only available 10.2 onwards */ PHP_OCI_CALL(OCIClientVersion, (&major_version, &minor_version, &update_num, &patch_num, &port_update_num)); snprintf(version_buff, sizeof(version_buff), "%d.%d.%d.%d.%d", major_version, minor_version, update_num, patch_num, port_update_num); #else memcpy(version_buff, "Unknown", sizeof("Unknown")); #endif *version = estrdup(version_buff); -} /* }}} */ - +} +/* }}} */ /* {{{ php_oci_server_get_version() * @@ -2468,19 +2517,21 @@ void php_oci_client_get_version(char **version TSRMLS_DC) */ int php_oci_server_get_version(php_oci_connection *connection, char **version TSRMLS_DC) { + sword errstatus; char version_buff[256]; - PHP_OCI_CALL_RETURN(connection->errcode, OCIServerVersion, (connection->svc, connection->err, (text *)version_buff, sizeof(version_buff), OCI_HTYPE_SVCCTX)); + PHP_OCI_CALL_RETURN(errstatus, OCIServerVersion, (connection->svc, connection->err, (text *)version_buff, sizeof(version_buff), OCI_HTYPE_SVCCTX)); - if (connection->errcode != OCI_SUCCESS) { - connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC); + if (errstatus != OCI_SUCCESS) { + connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC); PHP_OCI_HANDLE_ERROR(connection, connection->errcode); return 1; } *version = estrdup(version_buff); return 0; -} /* }}} */ +} +/* }}} */ /* {{{ php_oci_column_to_zval() * @@ -2564,14 +2615,19 @@ int php_oci_column_to_zval(php_oci_out_column *column, zval *value, int mode TSR } /* }}} */ + /* {{{ php_oci_fetch_row() * * Fetch the next row from the given statement + * Has logic for Oracle 12c Implicit Result Sets */ void php_oci_fetch_row (INTERNAL_FUNCTION_PARAMETERS, int mode, int expected_args) { zval *z_statement, *array; - php_oci_statement *statement; + php_oci_statement *statement; /* statement that will be fetched from */ +#if (OCI_MAJOR_VERSION >= 12) + php_oci_statement *invokedstatement; /* statement this function was invoked with */ +#endif /* OCI_MAJOR_VERSION */ php_oci_out_column *column; ub4 nrows = 1; int i; @@ -2617,12 +2673,64 @@ void php_oci_fetch_row (INTERNAL_FUNCTION_PARAMETERS, int mode, int expected_arg } } +#if (OCI_MAJOR_VERSION < 12) PHP_OCI_ZVAL_TO_STATEMENT(z_statement, statement); if (php_oci_statement_fetch(statement, nrows TSRMLS_CC)) { - RETURN_FALSE; + RETURN_FALSE; /* end of fetch */ + } +#else /* OCI_MAJOR_VERSION */ + PHP_OCI_ZVAL_TO_STATEMENT(z_statement, invokedstatement); + + if (invokedstatement->impres_flag == PHP_OCI_IMPRES_NO_CHILDREN) { + /* Already know there are no Implicit Result Sets */ + statement = invokedstatement; + } else if (invokedstatement->impres_flag == PHP_OCI_IMPRES_HAS_CHILDREN) { + /* Previously saw an Implicit Result Set in an earlier invocation of php_oci_fetch_row */ + statement = (php_oci_statement *)invokedstatement->impres_child_stmt; + } else { + sword errstatus; + + /* Check for an Implicit Result Set on this statement handle */ + PHP_OCI_CALL_RETURN(errstatus, OCIAttrGet, ((dvoid *)invokedstatement->stmt, OCI_HTYPE_STMT, + (dvoid *) &invokedstatement->impres_count, + (ub4 *)NULL, OCI_ATTR_IMPLICIT_RESULT_COUNT, invokedstatement->err)); + if (errstatus) { + RETURN_FALSE; + } + if (invokedstatement->impres_count > 0) { + /* Make it so the fetch occurs on the first Implicit Result Set */ + statement = php_oci_get_implicit_resultset(invokedstatement TSRMLS_CC); + if (!statement || php_oci_statement_execute(statement, (ub4)OCI_DEFAULT TSRMLS_CC)) + RETURN_FALSE; + invokedstatement->impres_count--; + invokedstatement->impres_child_stmt = (struct php_oci_statement *)statement; + invokedstatement->impres_flag = PHP_OCI_IMPRES_HAS_CHILDREN; + } else { + statement = invokedstatement; /* didn't find Implicit Result Sets */ + invokedstatement->impres_flag = PHP_OCI_IMPRES_NO_CHILDREN; /* Don't bother checking again */ + } } + if (php_oci_statement_fetch(statement, nrows TSRMLS_CC)) { + /* End of fetch */ + if (invokedstatement->impres_count > 0) { + /* Check next Implicit Result Set */ + statement = php_oci_get_implicit_resultset(invokedstatement TSRMLS_CC); + if (!statement || php_oci_statement_execute(statement, (ub4)OCI_DEFAULT TSRMLS_CC)) + RETURN_FALSE; + invokedstatement->impres_count--; + invokedstatement->impres_child_stmt = (struct php_oci_statement *)statement; + if (php_oci_statement_fetch(statement, nrows TSRMLS_CC)) { + /* End of all fetches */ + RETURN_FALSE; + } + } else { + RETURN_FALSE; + } + } +#endif /* OCI_MAJOR_VERSION */ + array_init(return_value); for (i = 0; i < statement->ncolumns; i++) { @@ -2688,9 +2796,11 @@ static int php_oci_persistent_helper(zend_rsrc_list_entry *le TSRMLS_DC) connection = (php_oci_connection *)le->ptr; if (!connection->used_this_request && OCI_G(persistent_timeout) != -1) { - if (OCI_G(debug_mode)) { - php_printf ("OCI8 DEBUG L1: persistent_helper processing for timeout: (%p stub=%d) at (%s:%d) \n", connection, connection->is_stub, __FILE__, __LINE__); +#ifdef HAVE_OCI8_DTRACE + if (DTRACE_OCI8_CONNECT_EXPIRY_ENABLED()) { + DTRACE_OCI8_CONNECT_EXPIRY(connection, connection->is_stub ? 1 : 0, (long)connection->idle_expiry, (long)timestamp); } +#endif /* HAVE_OCI8_DTRACE */ if (connection->idle_expiry < timestamp) { /* connection has timed out */ return ZEND_HASH_APPLY_REMOVE; @@ -2698,7 +2808,8 @@ static int php_oci_persistent_helper(zend_rsrc_list_entry *le TSRMLS_DC) } } return ZEND_HASH_APPLY_KEEP; -} /* }}} */ +} +/* }}} */ /* {{{ php_oci_create_spool() * @@ -2710,6 +2821,7 @@ static php_oci_spool *php_oci_create_spool(char *username, int username_len, cha zend_bool iserror = 0; ub4 poolmode = OCI_DEFAULT; /* Mode to be passed to OCISessionPoolCreate */ OCIAuthInfo *spoolAuth = NULL; + sword errstatus; /* Allocate sessionpool out of persistent memory */ session_pool = (php_oci_spool *) calloc(1, sizeof(php_oci_spool)); @@ -2734,10 +2846,10 @@ static php_oci_spool *php_oci_create_spool(char *username, int username_len, cha } /* Allocate the pool handle */ - PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIHandleAlloc, (session_pool->env, (dvoid **) &session_pool->poolh, OCI_HTYPE_SPOOL, (size_t) 0, (dvoid **) 0)); + PHP_OCI_CALL_RETURN(errstatus, OCIHandleAlloc, (session_pool->env, (dvoid **) &session_pool->poolh, OCI_HTYPE_SPOOL, (size_t) 0, (dvoid **) 0)); - if (OCI_G(errcode) != OCI_SUCCESS) { - php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC); + if (errstatus != OCI_SUCCESS) { + OCI_G(errcode) = php_oci_error(OCI_G(err), errstatus TSRMLS_CC); iserror = 1; goto exit_create_spool; } @@ -2746,10 +2858,10 @@ static php_oci_spool *php_oci_create_spool(char *username, int username_len, cha * generic bug which can free up the OCI_G(err) variable before destroying connections. We * cannot use this for other roundtrip calls as there is no way the user can access this error */ - PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIHandleAlloc, ((dvoid *) session_pool->env, (dvoid **)&(session_pool->err), (ub4) OCI_HTYPE_ERROR,(size_t) 0, (dvoid **) 0)); + PHP_OCI_CALL_RETURN(errstatus, OCIHandleAlloc, ((dvoid *) session_pool->env, (dvoid **)&(session_pool->err), (ub4) OCI_HTYPE_ERROR,(size_t) 0, (dvoid **) 0)); - if (OCI_G(errcode) != OCI_SUCCESS) { - php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC); + if (errstatus != OCI_SUCCESS) { + OCI_G(errcode) = php_oci_error(OCI_G(err), errstatus TSRMLS_CC); iserror = 1; goto exit_create_spool; } @@ -2762,52 +2874,56 @@ static php_oci_spool *php_oci_create_spool(char *username, int username_len, cha #endif #if ((OCI_MAJOR_VERSION > 11) || ((OCI_MAJOR_VERSION == 11) && (OCI_MINOR_VERSION >= 2))) - /* Allocate auth handle for session pool {{{ */ - PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIHandleAlloc, (session_pool->env, (dvoid **)&(spoolAuth), OCI_HTYPE_AUTHINFO, 0, NULL)); + /* {{{ Allocate auth handle for session pool */ + PHP_OCI_CALL_RETURN(errstatus, OCIHandleAlloc, (session_pool->env, (dvoid **)&(spoolAuth), OCI_HTYPE_AUTHINFO, 0, NULL)); - if (OCI_G(errcode) != OCI_SUCCESS) { - php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC); + if (errstatus != OCI_SUCCESS) { + OCI_G(errcode) = php_oci_error(OCI_G(err), errstatus TSRMLS_CC); iserror = 1; goto exit_create_spool; - } /* }}} */ + } + /* }}} */ - /* Set the edition attribute on the auth handle {{{ */ + /* {{{ Set the edition attribute on the auth handle */ if (OCI_G(edition)) { - PHP_OCI_CALL_RETURN(OCI_G(errcode),OCIAttrSet, ((dvoid *) spoolAuth, (ub4) OCI_HTYPE_AUTHINFO, (dvoid *) OCI_G(edition), (ub4)(strlen(OCI_G(edition))), (ub4)OCI_ATTR_EDITION, OCI_G(err))); + PHP_OCI_CALL_RETURN(errstatus, OCIAttrSet, ((dvoid *) spoolAuth, (ub4) OCI_HTYPE_AUTHINFO, (dvoid *) OCI_G(edition), (ub4)(strlen(OCI_G(edition))), (ub4)OCI_ATTR_EDITION, OCI_G(err))); - if (OCI_G(errcode) != OCI_SUCCESS) { - php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC); + if (errstatus != OCI_SUCCESS) { + OCI_G(errcode) = php_oci_error(OCI_G(err), errstatus TSRMLS_CC); iserror = 1; goto exit_create_spool; } - } /* }}} */ + } + /* }}} */ - /* Set the driver name attribute on the auth handle {{{ */ - PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIAttrSet, ((dvoid *) spoolAuth, (ub4) OCI_HTYPE_AUTHINFO, (dvoid *) PHP_OCI8_DRIVER_NAME, (ub4) sizeof(PHP_OCI8_DRIVER_NAME)-1, (ub4) OCI_ATTR_DRIVER_NAME, OCI_G(err))); + /* {{{ Set the driver name attribute on the auth handle */ + PHP_OCI_CALL_RETURN(errstatus, OCIAttrSet, ((dvoid *) spoolAuth, (ub4) OCI_HTYPE_AUTHINFO, (dvoid *) PHP_OCI8_DRIVER_NAME, (ub4) sizeof(PHP_OCI8_DRIVER_NAME)-1, (ub4) OCI_ATTR_DRIVER_NAME, OCI_G(err))); - if (OCI_G(errcode) != OCI_SUCCESS) { - php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC); + if (errstatus != OCI_SUCCESS) { + OCI_G(errcode) = php_oci_error(OCI_G(err), errstatus TSRMLS_CC); iserror = 1; goto exit_create_spool; - } /* }}} */ + } + /* }}} */ - /* Set the auth handle on the session pool {{{ */ - PHP_OCI_CALL_RETURN(OCI_G(errcode),OCIAttrSet, ((dvoid *) (session_pool->poolh),(ub4) OCI_HTYPE_SPOOL, (dvoid *) spoolAuth, (ub4)0, (ub4)OCI_ATTR_SPOOL_AUTH, OCI_G(err))); + /* {{{ Set the auth handle on the session pool */ + PHP_OCI_CALL_RETURN(errstatus, OCIAttrSet, ((dvoid *) (session_pool->poolh),(ub4) OCI_HTYPE_SPOOL, (dvoid *) spoolAuth, (ub4)0, (ub4)OCI_ATTR_SPOOL_AUTH, OCI_G(err))); - if (OCI_G(errcode) != OCI_SUCCESS) { - php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC); + if (errstatus != OCI_SUCCESS) { + OCI_G(errcode) = php_oci_error(OCI_G(err), errstatus TSRMLS_CC); iserror = 1; goto exit_create_spool; - } /* }}} */ + } + /* }}} */ #endif /* Create the homogeneous session pool - We have different session pools for every different * username, password, charset and dbname. */ - PHP_OCI_CALL_RETURN(OCI_G(errcode), OCISessionPoolCreate,(session_pool->env, OCI_G(err), session_pool->poolh, (OraText **)&session_pool->poolname, &session_pool->poolname_len, (OraText *)dbname, (ub4)dbname_len, 0, UB4MAXVAL, 1,(OraText *)username, (ub4)username_len, (OraText *)password,(ub4)password_len, poolmode)); + PHP_OCI_CALL_RETURN(errstatus, OCISessionPoolCreate,(session_pool->env, OCI_G(err), session_pool->poolh, (OraText **)&session_pool->poolname, &session_pool->poolname_len, (OraText *)dbname, (ub4)dbname_len, 0, UB4MAXVAL, 1,(OraText *)username, (ub4)username_len, (OraText *)password,(ub4)password_len, poolmode)); - if (OCI_G(errcode) != OCI_SUCCESS) { - php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC); + if (errstatus != OCI_SUCCESS) { + OCI_G(errcode) = php_oci_error(OCI_G(err), errstatus TSRMLS_CC); iserror = 1; } @@ -2821,12 +2937,15 @@ exit_create_spool: PHP_OCI_CALL(OCIHandleFree, ((dvoid *) spoolAuth, (ub4) OCI_HTYPE_AUTHINFO)); } - if (OCI_G(debug_mode)) { - php_printf ("OCI8 DEBUG L1: create_spool: (%p) at (%s:%d) \n", session_pool, __FILE__, __LINE__); +#ifdef HAVE_OCI8_DTRACE + if (DTRACE_OCI8_SESSPOOL_CREATE_ENABLED()) { + DTRACE_OCI8_SESSPOOL_CREATE(session_pool); } +#endif /* HAVE_OCI8_DTRACE */ return session_pool; -} /* }}} */ +} +/* }}} */ /* {{{ php_oci_get_spool() * @@ -2841,7 +2960,7 @@ static php_oci_spool *php_oci_get_spool(char *username, int username_len, char * zend_rsrc_list_entry *spool_out_le = NULL; zend_bool iserror = 0; - /* Create the spool hash key {{{ */ + /* {{{ Create the spool hash key */ smart_str_appendl_ex(&spool_hashed_details, "oci8spool***", sizeof("oci8spool***") - 1, 0); smart_str_appendl_ex(&spool_hashed_details, username, username_len, 0); smart_str_appendl_ex(&spool_hashed_details, "**", sizeof("**") - 1, 0); @@ -2880,11 +2999,7 @@ static php_oci_spool *php_oci_get_spool(char *username, int username_len, char * } spool_le.ptr = session_pool; spool_le.type = le_psessionpool; -#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 3) || (PHP_MAJOR_VERSION > 5) - zend_list_insert(session_pool, le_psessionpool TSRMLS_CC); -#else - zend_list_insert(session_pool, le_psessionpool); -#endif + PHP_OCI_REGISTER_RESOURCE(session_pool, le_psessionpool); zend_hash_update(&EG(persistent_list), session_pool->spool_hash_key, strlen(session_pool->spool_hash_key)+1,(void *)&spool_le, sizeof(zend_rsrc_list_entry),NULL); } else if (spool_out_le->type == le_psessionpool && strlen(((php_oci_spool *)(spool_out_le->ptr))->spool_hash_key) == spool_hashed_details.len && @@ -2902,7 +3017,8 @@ exit_get_spool: return session_pool; -} /* }}} */ +} +/* }}} */ /* {{{ php_oci_create_env() * @@ -2933,7 +3049,8 @@ static OCIEnv *php_oci_create_env(ub2 charsetid TSRMLS_DC) return NULL; } return retenv; -}/* }}} */ +} +/* }}} */ /* {{{ php_oci_old_create_session() * @@ -2944,57 +3061,58 @@ static int php_oci_old_create_session(php_oci_connection *connection, char *dbna { ub4 statement_cache_size = (OCI_G(statement_cache_size) > 0) ? OCI_G(statement_cache_size) : 0; - if (OCI_G(debug_mode)) { - php_printf ("OCI8 DEBUG: Bypassing client-side session pool for session create at (%s:%d) \n", __FILE__, __LINE__); - } - /* Create the OCI environment separate for each connection */ if (!(connection->env = php_oci_create_env(connection->charset TSRMLS_CC))) { return 1; } - /* Allocate our server handle {{{ */ + /* {{{ Allocate our server handle */ PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIHandleAlloc, (connection->env, (dvoid **)&(connection->server), OCI_HTYPE_SERVER, 0, NULL)); if (OCI_G(errcode) != OCI_SUCCESS) { php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC); return 1; - } /* }}} */ + } + /* }}} */ - /* Attach to the server {{{ */ + /* {{{ Attach to the server */ PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIServerAttach, (connection->server, OCI_G(err), (text *)dbname, dbname_len, (ub4) OCI_DEFAULT)); if (OCI_G(errcode) != OCI_SUCCESS) { php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC); return 1; - } /* }}} */ + } + /* }}} */ connection->is_attached = 1; - /* Allocate our session handle {{{ */ + /* {{{ Allocate our session handle */ PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIHandleAlloc, (connection->env, (dvoid **)&(connection->session), OCI_HTYPE_SESSION, 0, NULL)); if (OCI_G(errcode) != OCI_SUCCESS) { php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC); return 1; - } /* }}} */ + } + /* }}} */ - /* Allocate our private error-handle {{{ */ + /* {{{ Allocate our private error-handle */ PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIHandleAlloc, (connection->env, (dvoid **)&(connection->err), OCI_HTYPE_ERROR, 0, NULL)); if (OCI_G(errcode) != OCI_SUCCESS) { php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC); return 1; - } /* }}} */ + } + /* }}} */ - /* Allocate our service-context {{{ */ + /* {{{ Allocate our service-context */ PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIHandleAlloc, (connection->env, (dvoid **)&(connection->svc), OCI_HTYPE_SVCCTX, 0, NULL)); if (OCI_G(errcode) != OCI_SUCCESS) { php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC); return 1; - } /* }}} */ + } + /* }}} */ - /* Set the username {{{ */ + /* {{{ Set the username */ if (username) { PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIAttrSet, ((dvoid *) connection->session, (ub4) OCI_HTYPE_SESSION, (dvoid *) username, (ub4) username_len, (ub4) OCI_ATTR_USERNAME, OCI_G(err))); @@ -3002,9 +3120,10 @@ static int php_oci_old_create_session(php_oci_connection *connection, char *dbna php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC); return 1; } - }/* }}} */ + } + /* }}} */ - /* Set the password {{{ */ + /* {{{ Set the password */ if (password) { PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIAttrSet, ((dvoid *) connection->session, (ub4) OCI_HTYPE_SESSION, (dvoid *) password, (ub4) password_len, (ub4) OCI_ATTR_PASSWORD, OCI_G(err))); @@ -3012,9 +3131,10 @@ static int php_oci_old_create_session(php_oci_connection *connection, char *dbna php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC); return 1; } - }/* }}} */ + } + /* }}} */ - /* Set the edition attribute on the session handle {{{ */ + /* {{{ Set the edition attribute on the session handle */ #if ((OCI_MAJOR_VERSION > 11) || ((OCI_MAJOR_VERSION == 11) && (OCI_MINOR_VERSION >= 2))) if (OCI_G(edition)) { PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIAttrSet, ((dvoid *) connection->session, (ub4) OCI_HTYPE_SESSION, (dvoid *) OCI_G(edition), (ub4) (strlen(OCI_G(edition))), (ub4) OCI_ATTR_EDITION, OCI_G(err))); @@ -3024,9 +3144,10 @@ static int php_oci_old_create_session(php_oci_connection *connection, char *dbna return 1; } } -#endif /* }}} */ +#endif +/* }}} */ - /* Set the driver name attribute on the session handle {{{ */ + /* {{{ Set the driver name attribute on the session handle */ #if (OCI_MAJOR_VERSION >= 11) PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIAttrSet, ((dvoid *) connection->session, (ub4) OCI_HTYPE_SESSION, (dvoid *) PHP_OCI8_DRIVER_NAME, (ub4) sizeof(PHP_OCI8_DRIVER_NAME)-1, (ub4) OCI_ATTR_DRIVER_NAME, OCI_G(err))); @@ -3034,26 +3155,29 @@ static int php_oci_old_create_session(php_oci_connection *connection, char *dbna php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC); return 1; } -#endif /* }}} */ +#endif +/* }}} */ - /* Set the server handle in the service handle {{{ */ + /* {{{ Set the server handle in the service handle */ PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIAttrSet, (connection->svc, OCI_HTYPE_SVCCTX, connection->server, 0, OCI_ATTR_SERVER, OCI_G(err))); if (OCI_G(errcode) != OCI_SUCCESS) { php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC); return 1; - } /* }}} */ + } + /* }}} */ - /* Set the authentication handle in the service handle {{{ */ + /* {{{ Set the authentication handle in the service handle */ PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIAttrSet, (connection->svc, OCI_HTYPE_SVCCTX, connection->session, 0, OCI_ATTR_SESSION, OCI_G(err))); if (OCI_G(errcode) != OCI_SUCCESS) { php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC); return 1; - } /* }}} */ + } + /* }}} */ if (new_password) { - /* Try to change password if new one was provided {{{ */ + /* {{{ Try to change password if new one was provided */ PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIPasswordChange, (connection->svc, OCI_G(err), (text *)username, username_len, (text *)password, password_len, (text *)new_password, new_password_len, OCI_AUTH)); if (OCI_G(errcode) != OCI_SUCCESS) { @@ -3066,9 +3190,10 @@ static int php_oci_old_create_session(php_oci_connection *connection, char *dbna if (OCI_G(errcode) != OCI_SUCCESS) { php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC); return 1; - } /* }}} */ + } + /* }}} */ } else { - /* start the session {{{ */ + /* {{{ start the session */ ub4 cred_type = OCI_CRED_RDBMS; /* Extract the overloaded session_mode parameter into valid Oracle credential and session mode values */ @@ -3089,7 +3214,8 @@ static int php_oci_old_create_session(php_oci_connection *connection, char *dbna if (OCI_G(errcode) != OCI_SUCCESS_WITH_INFO) { return 1; } - } /* }}} */ + } + /* }}} */ } /* Brand new connection: Init and update the next_ping in the connection */ @@ -3107,7 +3233,8 @@ static int php_oci_old_create_session(php_oci_connection *connection, char *dbna /* Successfully created session */ return 0; -} /* }}} */ +} +/* }}} */ /* {{{ php_oci_create_session() * @@ -3138,13 +3265,11 @@ static int php_oci_create_session(php_oci_connection *connection, php_oci_spool connection->using_spool = 1; } - if (OCI_G(debug_mode)) { - if (session_pool) { - php_printf ("OCI8 DEBUG L1: using shared pool: (%p) at (%s:%d) \n", session_pool, __FILE__, __LINE__); - } else { - php_printf ("OCI8 DEBUG L1: using private pool: (%p) at (%s:%d) \n", connection->private_spool, __FILE__, __LINE__); - } +#ifdef HAVE_OCI8_DTRACE + if (DTRACE_OCI8_SESSPOOL_TYPE_ENABLED()) { + DTRACE_OCI8_SESSPOOL_TYPE(session_pool ? 1 : 0, session_pool ? session_pool : connection->private_spool); } +#endif /* HAVE_OCI8_DTRACE */ /* The passed in "connection" can be a cached stub from plist or freshly created. In the former * case, we do not have to allocate any handles @@ -3170,7 +3295,7 @@ static int php_oci_create_session(php_oci_connection *connection, php_oci_spool /* Set the Connection class and purity if OCI client version >= 11g */ #if (OCI_MAJOR_VERSION > 10) - PHP_OCI_CALL_RETURN(OCI_G(errcode),OCIAttrSet, ((dvoid *) connection->authinfo,(ub4) OCI_HTYPE_SESSION, (dvoid *) OCI_G(connection_class), (ub4)(strlen(OCI_G(connection_class))), (ub4)OCI_ATTR_CONNECTION_CLASS, OCI_G(err))); + PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIAttrSet, ((dvoid *) connection->authinfo,(ub4) OCI_HTYPE_SESSION, (dvoid *) OCI_G(connection_class), (ub4)(strlen(OCI_G(connection_class))), (ub4)OCI_ATTR_CONNECTION_CLASS, OCI_G(err))); if (OCI_G(errcode) != OCI_SUCCESS) { php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC); @@ -3189,16 +3314,20 @@ static int php_oci_create_session(php_oci_connection *connection, php_oci_spool return 1; } #endif - } /* }}} */ + } + /* }}} */ - /* Debug statements {{{ */ - if (OCI_G(debug_mode)) { + /* {{{ Debug statements */ +#ifdef HAVE_OCI8_DTRACE + if (DTRACE_OCI8_SESSPOOL_STATS_ENABLED()) { ub4 numfree = 0, numbusy = 0, numopen = 0; PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIAttrGet, ((dvoid *)actual_spool->poolh, OCI_HTYPE_SPOOL, (dvoid *)&numopen, (ub4 *)0, OCI_ATTR_SPOOL_OPEN_COUNT, OCI_G(err))); PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIAttrGet, ((dvoid *)actual_spool->poolh, OCI_HTYPE_SPOOL, (dvoid *)&numbusy, (ub4 *)0, OCI_ATTR_SPOOL_BUSY_COUNT, OCI_G(err))); numfree = numopen - numbusy; /* number of free connections in the pool */ - php_printf ("OCI8 DEBUG L1: (numopen=%d)(numbusy=%d)(numfree=%d) at (%s:%d) \n", numopen, numbusy, numfree, __FILE__, __LINE__); - } /* }}} */ + DTRACE_OCI8_SESSPOOL_STATS(numfree, numbusy, numopen); + } +#endif /* HAVE_OCI8_DTRACE */ + /* }}} */ /* Ping loop: Ping and loop till we get a good connection. When a database instance goes * down, it can leave several bad connections that need to be flushed out before getting a @@ -3225,7 +3354,8 @@ static int php_oci_create_session(php_oci_connection *connection, php_oci_spool /* {{{ Populate the session and server fields of the connection */ PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIAttrGet, ((dvoid *)connection->svc, OCI_HTYPE_SVCCTX, (dvoid *)&(connection->server), (ub4 *)0, OCI_ATTR_SERVER, OCI_G(err))); - PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIAttrGet, ((dvoid *)connection->svc, OCI_HTYPE_SVCCTX, (dvoid *)&(connection->session), (ub4 *)0, OCI_ATTR_SESSION, OCI_G(err))); /* }}} */ + PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIAttrGet, ((dvoid *)connection->svc, OCI_HTYPE_SVCCTX, (dvoid *)&(connection->session), (ub4 *)0, OCI_ATTR_SESSION, OCI_G(err))); + /* }}} */ PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIContextGetValue, (connection->session, OCI_G(err), (ub1 *)"NEXT_PING", (ub1)sizeof("NEXT_PING"), (void **)&(connection->next_pingp))); if (OCI_G(errcode) != OCI_SUCCESS) { @@ -3265,7 +3395,8 @@ static int php_oci_create_session(php_oci_connection *connection, php_oci_spool connection->is_attached = connection->is_open = 1; return 0; -} /* }}} */ +} +/* }}} */ /* {{{ php_oci_spool_list_dtor() * @@ -3280,7 +3411,8 @@ static void php_oci_spool_list_dtor(zend_rsrc_list_entry *entry TSRMLS_DC) } return; -} /* }}} */ +} +/* }}} */ /* {{{ php_oci_spool_close() * @@ -3310,7 +3442,8 @@ static void php_oci_spool_close(php_oci_spool *session_pool TSRMLS_DC) } free(session_pool); -} /* }}} */ +} +/* }}} */ /* {{{ php_oci_ping_init() * @@ -3353,7 +3486,22 @@ static sword php_oci_ping_init(php_oci_connection *connection, OCIError *errh TS connection->next_pingp = next_pingp; return OCI_SUCCESS; -} /* }}} */ +} +/* }}} */ + +/* {{{ php_oci_dtrace_check_connection() + * + * DTrace output for connections that may have become invalid and marked for reopening + */ +void php_oci_dtrace_check_connection(php_oci_connection *connection, sb4 errcode, ub4 serverStatus) +{ +#ifdef HAVE_OCI8_DTRACE + if (DTRACE_OCI8_CHECK_CONNECTION_ENABLED()) { + DTRACE_OCI8_CHECK_CONNECTION(connection, connection->client_id, connection->is_open ? 1 : 0, (long)errcode, (unsigned long)serverStatus); + } +#endif /* HAVE_OCI8_DTRACE */ +} +/* }}} */ #endif /* HAVE_OCI8 */ diff --git a/ext/oci8/oci8_collection.c b/ext/oci8/oci8_collection.c index 763e12e924..35b70fa7af 100644 --- a/ext/oci8/oci8_collection.c +++ b/ext/oci8/oci8_collection.c @@ -44,21 +44,22 @@ /* {{{ php_oci_collection_create() Create and return connection handle */ -php_oci_collection * php_oci_collection_create(php_oci_connection *connection, char *tdo, int tdo_len, char *schema, int schema_len TSRMLS_DC) +php_oci_collection *php_oci_collection_create(php_oci_connection *connection, char *tdo, int tdo_len, char *schema, int schema_len TSRMLS_DC) { dvoid *dschp1 = NULL; dvoid *parmp1; dvoid *parmp2; php_oci_collection *collection; + sword errstatus; collection = emalloc(sizeof(php_oci_collection)); collection->connection = connection; collection->collection = NULL; - zend_list_addref(collection->connection->rsrc_id); + zend_list_addref(collection->connection->id); /* get type handle by name */ - PHP_OCI_CALL_RETURN(connection->errcode, OCITypeByName, + PHP_OCI_CALL_RETURN(errstatus, OCITypeByName, ( connection->env, connection->err, @@ -75,19 +76,19 @@ php_oci_collection * php_oci_collection_create(php_oci_connection *connection, c ) ); - if (connection->errcode != OCI_SUCCESS) { + if (errstatus != OCI_SUCCESS) { goto CLEANUP; } /* allocate describe handle */ - PHP_OCI_CALL_RETURN(connection->errcode, OCIHandleAlloc, (connection->env, (dvoid **) &dschp1, (ub4) OCI_HTYPE_DESCRIBE, (size_t) 0, (dvoid **) 0)); + PHP_OCI_CALL_RETURN(errstatus, OCIHandleAlloc, (connection->env, (dvoid **) &dschp1, (ub4) OCI_HTYPE_DESCRIBE, (size_t) 0, (dvoid **) 0)); - if (connection->errcode != OCI_SUCCESS) { + if (errstatus != OCI_SUCCESS) { goto CLEANUP; } /* describe TDO */ - PHP_OCI_CALL_RETURN(connection->errcode, OCIDescribeAny, + PHP_OCI_CALL_RETURN(errstatus, OCIDescribeAny, ( connection->svc, connection->err, @@ -100,19 +101,19 @@ php_oci_collection * php_oci_collection_create(php_oci_connection *connection, c ) ); - if (connection->errcode != OCI_SUCCESS) { + if (errstatus != OCI_SUCCESS) { goto CLEANUP; } /* get first parameter handle */ - PHP_OCI_CALL_RETURN(connection->errcode, OCIAttrGet, ((dvoid *) dschp1, (ub4) OCI_HTYPE_DESCRIBE, (dvoid *)&parmp1, (ub4 *)0, (ub4)OCI_ATTR_PARAM, connection->err)); + PHP_OCI_CALL_RETURN(errstatus, OCIAttrGet, ((dvoid *) dschp1, (ub4) OCI_HTYPE_DESCRIBE, (dvoid *)&parmp1, (ub4 *)0, (ub4)OCI_ATTR_PARAM, connection->err)); - if (connection->errcode != OCI_SUCCESS) { + if (errstatus != OCI_SUCCESS) { goto CLEANUP; } /* get the collection type code of the attribute */ - PHP_OCI_CALL_RETURN(connection->errcode, OCIAttrGet, + PHP_OCI_CALL_RETURN(errstatus, OCIAttrGet, ( (dvoid*) parmp1, (ub4) OCI_DTYPE_PARAM, @@ -123,7 +124,7 @@ php_oci_collection * php_oci_collection_create(php_oci_connection *connection, c ) ); - if (connection->errcode != OCI_SUCCESS) { + if (errstatus != OCI_SUCCESS) { goto CLEANUP; } @@ -131,7 +132,7 @@ php_oci_collection * php_oci_collection_create(php_oci_connection *connection, c case OCI_TYPECODE_TABLE: case OCI_TYPECODE_VARRAY: /* get collection element handle */ - PHP_OCI_CALL_RETURN(connection->errcode, OCIAttrGet, + PHP_OCI_CALL_RETURN(errstatus, OCIAttrGet, ( (dvoid*) parmp1, (ub4) OCI_DTYPE_PARAM, @@ -142,12 +143,12 @@ php_oci_collection * php_oci_collection_create(php_oci_connection *connection, c ) ); - if (connection->errcode != OCI_SUCCESS) { + if (errstatus != OCI_SUCCESS) { goto CLEANUP; } /* get REF of the TDO for the type */ - PHP_OCI_CALL_RETURN(connection->errcode, OCIAttrGet, + PHP_OCI_CALL_RETURN(errstatus, OCIAttrGet, ( (dvoid*) parmp2, (ub4) OCI_DTYPE_PARAM, @@ -158,12 +159,12 @@ php_oci_collection * php_oci_collection_create(php_oci_connection *connection, c ) ); - if (connection->errcode != OCI_SUCCESS) { + if (errstatus != OCI_SUCCESS) { goto CLEANUP; } /* get the TDO (only header) */ - PHP_OCI_CALL_RETURN(connection->errcode, OCITypeByRef, + PHP_OCI_CALL_RETURN(errstatus, OCITypeByRef, ( connection->env, connection->err, @@ -174,12 +175,12 @@ php_oci_collection * php_oci_collection_create(php_oci_connection *connection, c ) ); - if (connection->errcode != OCI_SUCCESS) { + if (errstatus != OCI_SUCCESS) { goto CLEANUP; } /* get typecode */ - PHP_OCI_CALL_RETURN(connection->errcode, OCIAttrGet, + PHP_OCI_CALL_RETURN(errstatus, OCIAttrGet, ( (dvoid*) parmp2, (ub4) OCI_DTYPE_PARAM, @@ -190,7 +191,7 @@ php_oci_collection * php_oci_collection_create(php_oci_connection *connection, c ) ); - if (connection->errcode != OCI_SUCCESS) { + if (errstatus != OCI_SUCCESS) { goto CLEANUP; } break; @@ -201,7 +202,7 @@ php_oci_collection * php_oci_collection_create(php_oci_connection *connection, c } /* Create object to hold return table */ - PHP_OCI_CALL_RETURN(connection->errcode, OCIObjectNew, + PHP_OCI_CALL_RETURN(errstatus, OCIObjectNew, ( connection->env, connection->err, @@ -215,13 +216,14 @@ php_oci_collection * php_oci_collection_create(php_oci_connection *connection, c ) ); - if (connection->errcode != OCI_SUCCESS) { + if (errstatus != OCI_SUCCESS) { goto CLEANUP; } /* free the describe handle (Bug #44113) */ PHP_OCI_CALL(OCIHandleFree, ((dvoid *) dschp1, OCI_HTYPE_DESCRIBE)); PHP_OCI_REGISTER_RESOURCE(collection, le_collection); + connection->errcode = 0; /* retain backwards compat with OCI8 1.4 */ return collection; CLEANUP: @@ -230,27 +232,31 @@ CLEANUP: /* free the describe handle (Bug #44113) */ PHP_OCI_CALL(OCIHandleFree, ((dvoid *) dschp1, OCI_HTYPE_DESCRIBE)); } - connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC); + connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC); PHP_OCI_HANDLE_ERROR(connection, connection->errcode); php_oci_collection_close(collection TSRMLS_CC); return NULL; -} /* }}} */ +} +/* }}} */ /* {{{ php_oci_collection_size() Return size of the collection */ int php_oci_collection_size(php_oci_collection *collection, sb4 *size TSRMLS_DC) { php_oci_connection *connection = collection->connection; + sword errstatus; - PHP_OCI_CALL_RETURN(connection->errcode, OCICollSize, (connection->env, connection->err, collection->collection, (sb4 *)size)); + PHP_OCI_CALL_RETURN(errstatus, OCICollSize, (connection->env, connection->err, collection->collection, (sb4 *)size)); - if (connection->errcode != OCI_SUCCESS) { - connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC); + if (errstatus != OCI_SUCCESS) { + connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC); PHP_OCI_HANDLE_ERROR(connection, connection->errcode); return 1; } + connection->errcode = 0; /* retain backwards compat with OCI8 1.4 */ return 0; -} /* }}} */ +} +/* }}} */ /* {{{ php_oci_collection_max() Return max number of elements in the collection */ @@ -262,23 +268,27 @@ int php_oci_collection_max(php_oci_collection *collection, long *max TSRMLS_DC) /* error handling is not necessary here? */ return 0; -} /* }}} */ +} +/* }}} */ /* {{{ php_oci_collection_trim() Trim collection to the given number of elements */ int php_oci_collection_trim(php_oci_collection *collection, long trim_size TSRMLS_DC) { php_oci_connection *connection = collection->connection; - - PHP_OCI_CALL_RETURN(connection->errcode, OCICollTrim, (connection->env, connection->err, trim_size, collection->collection)); + sword errstatus; + + PHP_OCI_CALL_RETURN(errstatus, OCICollTrim, (connection->env, connection->err, trim_size, collection->collection)); - if (connection->errcode != OCI_SUCCESS) { - connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC); + if (errstatus != OCI_SUCCESS) { + errstatus = php_oci_error(connection->err, errstatus TSRMLS_CC); PHP_OCI_HANDLE_ERROR(connection, connection->errcode); return 1; } + connection->errcode = 0; /* retain backwards compat with OCI8 1.4 */ return 0; -} /* }}} */ +} +/* }}} */ /* {{{ php_oci_collection_append_null() Append NULL element to the end of the collection */ @@ -286,17 +296,20 @@ int php_oci_collection_append_null(php_oci_collection *collection TSRMLS_DC) { OCIInd null_index = OCI_IND_NULL; php_oci_connection *connection = collection->connection; + sword errstatus; /* append NULL element */ - PHP_OCI_CALL_RETURN(connection->errcode, OCICollAppend, (connection->env, connection->err, (dvoid *)0, &null_index, collection->collection)); + PHP_OCI_CALL_RETURN(errstatus, OCICollAppend, (connection->env, connection->err, (dvoid *)0, &null_index, collection->collection)); - if (connection->errcode != OCI_SUCCESS) { - connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC); + if (errstatus != OCI_SUCCESS) { + errstatus = php_oci_error(connection->err, errstatus TSRMLS_CC); PHP_OCI_HANDLE_ERROR(connection, connection->errcode); return 1; } + connection->errcode = 0; /* retain backwards compat with OCI8 1.4 */ return 0; -} /* }}} */ +} +/* }}} */ /* {{{ php_oci_collection_append_date() Append DATE element to the end of the collection (use "DD-MON-YY" format) */ @@ -305,18 +318,19 @@ int php_oci_collection_append_date(php_oci_collection *collection, char *date, i OCIInd new_index = OCI_IND_NOTNULL; OCIDate oci_date; php_oci_connection *connection = collection->connection; + sword errstatus; /* format and language are NULLs, so format is "DD-MON-YY" and language is the default language of the session */ - PHP_OCI_CALL_RETURN(connection->errcode, OCIDateFromText, (connection->err, (CONST text *)date, date_len, NULL, 0, NULL, 0, &oci_date)); + PHP_OCI_CALL_RETURN(errstatus, OCIDateFromText, (connection->err, (CONST text *)date, date_len, NULL, 0, NULL, 0, &oci_date)); - if (connection->errcode != OCI_SUCCESS) { + if (errstatus != OCI_SUCCESS) { /* failed to convert string to date */ - connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC); + connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC); PHP_OCI_HANDLE_ERROR(connection, connection->errcode); return 1; } - PHP_OCI_CALL_RETURN(connection->errcode, OCICollAppend, + PHP_OCI_CALL_RETURN(errstatus, OCICollAppend, ( connection->env, connection->err, @@ -326,14 +340,16 @@ int php_oci_collection_append_date(php_oci_collection *collection, char *date, i ) ); - if (connection->errcode != OCI_SUCCESS) { - connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC); + if (errstatus != OCI_SUCCESS) { + connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC); PHP_OCI_HANDLE_ERROR(connection, connection->errcode); return 1; } + connection->errcode = 0; /* retain backwards compat with OCI8 1.4 */ return 0; -} /* }}} */ +} +/* }}} */ /* {{{ php_oci_collection_append_number() Append NUMBER to the end of the collection */ @@ -343,24 +359,19 @@ int php_oci_collection_append_number(php_oci_collection *collection, char *numbe double element_double; OCINumber oci_number; php_oci_connection *connection = collection->connection; + sword errstatus; -#if (PHP_MAJOR_VERSION == 4 && PHP_MINOR_VERSION == 3 && PHP_RELEASE_VERSION < 10) - /* minimum PHP version ext/oci8/config.m4 accepts is 4.3.9 */ - element_double = strtod(number, NULL); -#else - /* zend_strtod was introduced in PHP 4.3.10 */ element_double = zend_strtod(number, NULL); -#endif - PHP_OCI_CALL_RETURN(connection->errcode, OCINumberFromReal, (connection->err, &element_double, sizeof(double), &oci_number)); + PHP_OCI_CALL_RETURN(errstatus, OCINumberFromReal, (connection->err, &element_double, sizeof(double), &oci_number)); - if (connection->errcode != OCI_SUCCESS) { - connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC); + if (errstatus != OCI_SUCCESS) { + connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC); PHP_OCI_HANDLE_ERROR(connection, connection->errcode); return 1; } - PHP_OCI_CALL_RETURN(connection->errcode, OCICollAppend, + PHP_OCI_CALL_RETURN(errstatus, OCICollAppend, ( connection->env, connection->err, @@ -370,14 +381,16 @@ int php_oci_collection_append_number(php_oci_collection *collection, char *numbe ) ); - if (connection->errcode != OCI_SUCCESS) { - connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC); + if (errstatus != OCI_SUCCESS) { + connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC); PHP_OCI_HANDLE_ERROR(connection, connection->errcode); return 1; } + connection->errcode = 0; /* retain backwards compat with OCI8 1.4 */ return 0; -} /* }}} */ +} +/* }}} */ /* {{{ php_oci_collection_append_string() Append STRING to the end of the collection */ @@ -386,16 +399,17 @@ int php_oci_collection_append_string(php_oci_collection *collection, char *eleme OCIInd new_index = OCI_IND_NOTNULL; OCIString *ocistr = (OCIString *)0; php_oci_connection *connection = collection->connection; + sword errstatus; - PHP_OCI_CALL_RETURN(connection->errcode, OCIStringAssignText, (connection->env, connection->err, (CONST oratext *)element, element_len, &ocistr)); + PHP_OCI_CALL_RETURN(errstatus, OCIStringAssignText, (connection->env, connection->err, (CONST oratext *)element, element_len, &ocistr)); - if (connection->errcode != OCI_SUCCESS) { - connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC); + if (errstatus != OCI_SUCCESS) { + connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC); PHP_OCI_HANDLE_ERROR(connection, connection->errcode); return 1; } - PHP_OCI_CALL_RETURN(connection->errcode, OCICollAppend, + PHP_OCI_CALL_RETURN(errstatus, OCICollAppend, ( connection->env, connection->err, @@ -405,14 +419,16 @@ int php_oci_collection_append_string(php_oci_collection *collection, char *eleme ) ); - if (connection->errcode != OCI_SUCCESS) { - connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC); + if (errstatus != OCI_SUCCESS) { + connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC); PHP_OCI_HANDLE_ERROR(connection, connection->errcode); return 1; } + connection->errcode = 0; /* retain backwards compat with OCI8 1.4 */ return 0; -} /* }}} */ +} +/* }}} */ /* {{{ php_oci_collection_append() Append wrapper. Appends any supported element to the end of the collection */ @@ -452,7 +468,8 @@ int php_oci_collection_append(php_oci_collection *collection, char *element, int } /* never reached */ return 1; -} /* }}} */ +} +/* }}} */ /* {{{ php_oci_collection_element_get() Get the element with the given index */ @@ -464,11 +481,14 @@ int php_oci_collection_element_get(php_oci_collection *collection, long index, z boolean exists; oratext buff[1024]; ub4 buff_len = 1024; + sword errstatus; MAKE_STD_ZVAL(*result_element); ZVAL_NULL(*result_element); - PHP_OCI_CALL_RETURN(connection->errcode, OCICollGetElem, + connection->errcode = 0; /* retain backwards compat with OCI8 1.4 */ + + PHP_OCI_CALL_RETURN(errstatus, OCICollGetElem, ( connection->env, connection->err, @@ -480,8 +500,8 @@ int php_oci_collection_element_get(php_oci_collection *collection, long index, z ) ); - if (connection->errcode != OCI_SUCCESS) { - connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC); + if (errstatus != OCI_SUCCESS) { + connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC); PHP_OCI_HANDLE_ERROR(connection, connection->errcode); FREE_ZVAL(*result_element); return 1; @@ -500,10 +520,10 @@ int php_oci_collection_element_get(php_oci_collection *collection, long index, z switch (collection->element_typecode) { case OCI_TYPECODE_DATE: - PHP_OCI_CALL_RETURN(connection->errcode, OCIDateToText, (connection->err, element, 0, 0, 0, 0, &buff_len, buff)); + PHP_OCI_CALL_RETURN(errstatus, OCIDateToText, (connection->err, element, 0, 0, 0, 0, &buff_len, buff)); - if (connection->errcode != OCI_SUCCESS) { - connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC); + if (errstatus != OCI_SUCCESS) { + connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC); PHP_OCI_HANDLE_ERROR(connection, connection->errcode); FREE_ZVAL(*result_element); return 1; @@ -543,10 +563,10 @@ int php_oci_collection_element_get(php_oci_collection *collection, long index, z { double double_number; - PHP_OCI_CALL_RETURN(connection->errcode, OCINumberToReal, (connection->err, (CONST OCINumber *) element, (uword) sizeof(double), (dvoid *) &double_number)); + PHP_OCI_CALL_RETURN(errstatus, OCINumberToReal, (connection->err, (CONST OCINumber *) element, (uword) sizeof(double), (dvoid *) &double_number)); - if (connection->errcode != OCI_SUCCESS) { - connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC); + if (errstatus != OCI_SUCCESS) { + connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC); PHP_OCI_HANDLE_ERROR(connection, connection->errcode); FREE_ZVAL(*result_element); return 1; @@ -565,7 +585,8 @@ int php_oci_collection_element_get(php_oci_collection *collection, long index, z } /* never reached */ return 1; -} /* }}} */ +} +/* }}} */ /* {{{ php_oci_collection_element_set_null() Set the element with the given index to NULL */ @@ -573,17 +594,20 @@ int php_oci_collection_element_set_null(php_oci_collection *collection, long ind { OCIInd null_index = OCI_IND_NULL; php_oci_connection *connection = collection->connection; + sword errstatus; /* set NULL element */ - PHP_OCI_CALL_RETURN(connection->errcode, OCICollAssignElem, (connection->env, connection->err, (ub4) index, (dvoid *)"", &null_index, collection->collection)); + PHP_OCI_CALL_RETURN(errstatus, OCICollAssignElem, (connection->env, connection->err, (ub4) index, (dvoid *)"", &null_index, collection->collection)); - if (connection->errcode != OCI_SUCCESS) { - connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC); + if (errstatus != OCI_SUCCESS) { + connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC); PHP_OCI_HANDLE_ERROR(connection, connection->errcode); return 1; } + connection->errcode = 0; /* retain backwards compat with OCI8 1.4 */ return 0; -} /* }}} */ +} +/* }}} */ /* {{{ php_oci_collection_element_set_date() Change element's value to the given DATE */ @@ -592,18 +616,19 @@ int php_oci_collection_element_set_date(php_oci_collection *collection, long ind OCIInd new_index = OCI_IND_NOTNULL; OCIDate oci_date; php_oci_connection *connection = collection->connection; + sword errstatus; /* format and language are NULLs, so format is "DD-MON-YY" and language is the default language of the session */ - PHP_OCI_CALL_RETURN(connection->errcode, OCIDateFromText, (connection->err, (CONST text *)date, date_len, NULL, 0, NULL, 0, &oci_date)); + PHP_OCI_CALL_RETURN(errstatus, OCIDateFromText, (connection->err, (CONST text *)date, date_len, NULL, 0, NULL, 0, &oci_date)); - if (connection->errcode != OCI_SUCCESS) { + if (errstatus != OCI_SUCCESS) { /* failed to convert string to date */ - connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC); + connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC); PHP_OCI_HANDLE_ERROR(connection, connection->errcode); return 1; } - PHP_OCI_CALL_RETURN(connection->errcode, OCICollAssignElem, + PHP_OCI_CALL_RETURN(errstatus, OCICollAssignElem, ( connection->env, connection->err, @@ -614,14 +639,16 @@ int php_oci_collection_element_set_date(php_oci_collection *collection, long ind ) ); - if (connection->errcode != OCI_SUCCESS) { - connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC); + if (errstatus != OCI_SUCCESS) { + connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC); PHP_OCI_HANDLE_ERROR(connection, connection->errcode); return 1; } + connection->errcode = 0; /* retain backwards compat with OCI8 1.4 */ return 0; -} /* }}} */ +} +/* }}} */ /* {{{ php_oci_collection_element_set_number() Change element's value to the given NUMBER */ @@ -631,24 +658,19 @@ int php_oci_collection_element_set_number(php_oci_collection *collection, long i double element_double; OCINumber oci_number; php_oci_connection *connection = collection->connection; + sword errstatus; -#if (PHP_MAJOR_VERSION == 4 && PHP_MINOR_VERSION == 3 && PHP_RELEASE_VERSION < 10) - /* minimum PHP version ext/oci8/config.m4 accepts is 4.3.9 */ - element_double = strtod(number, NULL); -#else - /* zend_strtod was introduced in PHP 4.3.10 */ element_double = zend_strtod(number, NULL); -#endif - PHP_OCI_CALL_RETURN(connection->errcode, OCINumberFromReal, (connection->err, &element_double, sizeof(double), &oci_number)); + PHP_OCI_CALL_RETURN(errstatus, OCINumberFromReal, (connection->err, &element_double, sizeof(double), &oci_number)); - if (connection->errcode != OCI_SUCCESS) { - connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC); + if (errstatus != OCI_SUCCESS) { + connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC); PHP_OCI_HANDLE_ERROR(connection, connection->errcode); return 1; } - PHP_OCI_CALL_RETURN(connection->errcode, OCICollAssignElem, + PHP_OCI_CALL_RETURN(errstatus, OCICollAssignElem, ( connection->env, connection->err, @@ -659,14 +681,16 @@ int php_oci_collection_element_set_number(php_oci_collection *collection, long i ) ); - if (connection->errcode != OCI_SUCCESS) { - connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC); + if (errstatus != OCI_SUCCESS) { + connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC); PHP_OCI_HANDLE_ERROR(connection, connection->errcode); return 1; } + connection->errcode = 0; /* retain backwards compat with OCI8 1.4 */ return 0; -} /* }}} */ +} +/* }}} */ /* {{{ php_oci_collection_element_set_string() Change element's value to the given string */ @@ -675,16 +699,17 @@ int php_oci_collection_element_set_string(php_oci_collection *collection, long i OCIInd new_index = OCI_IND_NOTNULL; OCIString *ocistr = (OCIString *)0; php_oci_connection *connection = collection->connection; + sword errstatus; - PHP_OCI_CALL_RETURN(connection->errcode, OCIStringAssignText, (connection->env, connection->err, (CONST oratext *)element, element_len, &ocistr)); + PHP_OCI_CALL_RETURN(errstatus, OCIStringAssignText, (connection->env, connection->err, (CONST oratext *)element, element_len, &ocistr)); - if (connection->errcode != OCI_SUCCESS) { - connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC); + if (errstatus != OCI_SUCCESS) { + connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC); PHP_OCI_HANDLE_ERROR(connection, connection->errcode); return 1; } - PHP_OCI_CALL_RETURN(connection->errcode, OCICollAssignElem, + PHP_OCI_CALL_RETURN(errstatus, OCICollAssignElem, ( connection->env, connection->err, @@ -695,14 +720,16 @@ int php_oci_collection_element_set_string(php_oci_collection *collection, long i ) ); - if (connection->errcode != OCI_SUCCESS) { - connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC); + if (errstatus != OCI_SUCCESS) { + connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC); PHP_OCI_HANDLE_ERROR(connection, connection->errcode); return 1; } + connection->errcode = 0; /* retain backwards compat with OCI8 1.4 */ return 0; -} /* }}} */ +} +/* }}} */ /* {{{ php_oci_collection_element_set() Collection element setter */ @@ -742,44 +769,51 @@ int php_oci_collection_element_set(php_oci_collection *collection, long index, c } /* never reached */ return 1; -} /* }}} */ +} +/* }}} */ /* {{{ php_oci_collection_assign() Assigns a value to the collection from another collection */ int php_oci_collection_assign(php_oci_collection *collection_dest, php_oci_collection *collection_from TSRMLS_DC) { php_oci_connection *connection = collection_dest->connection; + sword errstatus; - PHP_OCI_CALL_RETURN(connection->errcode, OCICollAssign, (connection->env, connection->err, collection_from->collection, collection_dest->collection)); + PHP_OCI_CALL_RETURN(errstatus, OCICollAssign, (connection->env, connection->err, collection_from->collection, collection_dest->collection)); - if (connection->errcode != OCI_SUCCESS) { - connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC); + if (errstatus != OCI_SUCCESS) { + connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC); PHP_OCI_HANDLE_ERROR(connection, connection->errcode); return 1; } + connection->errcode = 0; /* retain backwards compat with OCI8 1.4 */ return 0; -} /* }}} */ +} +/* }}} */ /* {{{ php_oci_collection_close() Destroy collection and all associated resources */ void php_oci_collection_close(php_oci_collection *collection TSRMLS_DC) { php_oci_connection *connection = collection->connection; + sword errstatus; if (collection->collection) { - PHP_OCI_CALL_RETURN(connection->errcode, OCIObjectFree, (connection->env, connection->err, (dvoid *)collection->collection, (ub2)OCI_OBJECTFREE_FORCE)); + PHP_OCI_CALL_RETURN(errstatus, OCIObjectFree, (connection->env, connection->err, (dvoid *)collection->collection, (ub2)OCI_OBJECTFREE_FORCE)); - if (connection->errcode != OCI_SUCCESS) { - connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC); + if (errstatus != OCI_SUCCESS) { + connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC); PHP_OCI_HANDLE_ERROR(connection, connection->errcode); + } else { + connection->errcode = 0; /* retain backwards compat with OCI8 1.4 */ } } - zend_list_delete(collection->connection->rsrc_id); - + zend_list_delete(collection->connection->id); efree(collection); return; -} /* }}} */ +} +/* }}} */ #endif /* HAVE_OCI8 */ diff --git a/ext/oci8/oci8_dtrace.d b/ext/oci8/oci8_dtrace.d new file mode 100644 index 0000000000..30c98de912 --- /dev/null +++ b/ext/oci8/oci8_dtrace.d @@ -0,0 +1,36 @@ +/* + +----------------------------------------------------------------------+ + | Zend Engine | + +----------------------------------------------------------------------+ + | Copyright (c) 2013 Zend Technologies Ltd. (http://www.zend.com) | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the Zend license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.zend.com/license/3_01.txt. | + | If you did not receive a copy of the Zend license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@zend.com so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Author: Christopher Jones <christopher.jones@oracle.com> | + +----------------------------------------------------------------------+ +*/ + +provider phpoci { + probe oci8__check__connection(void *connection, char *client_id, int is_open, long errcode, unsigned long server_status); + probe oci8__connect__entry(char *username, char *dbname, char *charset, long session_mode, int persistent, int exclusive); + probe oci8__connect__return(void *connection); + probe oci8__connection__close(void *connection); + probe oci8__error(int status, long errcode); + probe oci8__execute__mode(void *connection, char *client_id, void *statement, unsigned int mode); + probe oci8__sqltext(void *connection, char *client_id, void *statement, char *sql); + + probe oci8__connect__p__dtor__close(void *connection); + probe oci8__connect__p__dtor__release(void *connection); + probe oci8__connect__lookup(void *connection, int is_stub); + probe oci8__connect__expiry(void *connection, int is_stub, long idle_expiry, long timestamp); + probe oci8__connect__type(int persistent, int exclusive, void *connection, long num_persistent, long num_connections); + probe oci8__sesspool__create(void *session_pool); + probe oci8__sesspool__stats(unsigned long free, unsigned long busy, unsigned long open); + probe oci8__sesspool__type(int type, void *session_pool); +}; diff --git a/ext/oci8/oci8_interface.c b/ext/oci8/oci8_interface.c index e51d3c92f5..ccaed79742 100644 --- a/ext/oci8/oci8_interface.c +++ b/ext/oci8/oci8_interface.c @@ -1308,12 +1308,7 @@ PHP_FUNCTION(oci_field_is_null) Toggle internal debugging output for the OCI extension */ PHP_FUNCTION(oci_internal_debug) { - zend_bool on_off; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "b", &on_off) == FAILURE) { - return; - } - OCI_G(debug_mode) = on_off; + /* NOP in OCI8 2.0. Obsoleted by DTrace probes */ } /* }}} */ @@ -1434,13 +1429,7 @@ PHP_FUNCTION(oci_fetch_all) if (flags & PHP_OCI_NUM) { zend_hash_next_index_insert(Z_ARRVAL_P(row), &element, sizeof(zval*), NULL); } else { /* default to ASSOC */ -#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 1) || (PHP_MAJOR_VERSION > 5) - /* zend_symtable_update is only available in 5.2+ */ zend_symtable_update(Z_ARRVAL_P(row), columns[ i ]->name, columns[ i ]->name_len+1, &element, sizeof(zval*), NULL); -#else - /* This code path means Bug #45458 will remain broken when OCI8 is built with PHP 4 */ - zend_hash_update(Z_ARRVAL_P(row), columns[ i ]->name, columns[ i ]->name_len+1, &element, sizeof(zval*), NULL); -#endif } } @@ -1472,13 +1461,7 @@ PHP_FUNCTION(oci_fetch_all) MAKE_STD_ZVAL(tmp); array_init(tmp); -#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 1) || (PHP_MAJOR_VERSION > 5) - /* zend_symtable_update is only available in 5.2+ */ zend_symtable_update(Z_ARRVAL_P(array), columns[ i ]->name, columns[ i ]->name_len+1, (void *) &tmp, sizeof(zval*), (void **) &(outarrs[ i ])); -#else - /* This code path means Bug #45458 will remain broken when OCI8 is built with PHP 4 */ - zend_hash_update(Z_ARRVAL_P(array), columns[ i ]->name, columns[ i ]->name_len+1, (void *) &tmp, sizeof(zval*), (void **) &(outarrs[ i ])); -#endif } } @@ -1583,7 +1566,7 @@ PHP_FUNCTION(oci_close) } PHP_OCI_ZVAL_TO_CONNECTION(z_connection, connection); - zend_list_delete(connection->rsrc_id); + zend_list_delete(connection->id); ZVAL_NULL(z_connection); @@ -1591,7 +1574,7 @@ PHP_FUNCTION(oci_close) } /* }}} */ -/* {{{ proto resource oci_new_connect(string user, string pass [, string db]) +/* {{{ proto resource oci_new_connect(string user, string pass [, string db, string charset [, int session_mode ]]) Connect to an Oracle database and log on. Returns a new session. */ PHP_FUNCTION(oci_new_connect) { @@ -1607,7 +1590,7 @@ PHP_FUNCTION(oci_connect) } /* }}} */ -/* {{{ proto resource oci_pconnect(string user, string pass [, string db [, string charset ]]) +/* {{{ proto resource oci_pconnect(string user, string pass [, string db [, string charset [, int session_mode ]]) Connect to an Oracle database using a persistent connection and log on. Returns a new session. */ PHP_FUNCTION(oci_pconnect) { @@ -1624,7 +1607,6 @@ PHP_FUNCTION(oci_error) php_oci_connection *connection; text *errbuf; sb4 errcode = 0; - sword error = OCI_SUCCESS; dvoid *errh = NULL; ub2 error_offset = 0; text *sqltext = NULL; @@ -1635,10 +1617,9 @@ PHP_FUNCTION(oci_error) if (ZEND_NUM_ARGS() > 0) { statement = (php_oci_statement *) zend_fetch_resource(&arg TSRMLS_CC, -1, NULL, NULL, 1, le_statement); - if (statement) { errh = statement->err; - error = statement->errcode; + errcode = statement->errcode; if (php_oci_fetch_sqltext_offset(statement, &sqltext, &error_offset TSRMLS_CC)) { RETURN_FALSE; @@ -1649,23 +1630,23 @@ PHP_FUNCTION(oci_error) connection = (php_oci_connection *) zend_fetch_resource(&arg TSRMLS_CC, -1, NULL, NULL, 1, le_connection); if (connection) { errh = connection->err; - error = connection->errcode; + errcode = connection->errcode; goto go_out; } connection = (php_oci_connection *) zend_fetch_resource(&arg TSRMLS_CC, -1, NULL, NULL, 1, le_pconnection); if (connection) { errh = connection->err; - error = connection->errcode; + errcode = connection->errcode; goto go_out; } } else { errh = OCI_G(err); - error = OCI_G(errcode); + errcode = OCI_G(errcode); } go_out: - if (error == OCI_SUCCESS) { /* no error set in the handle */ + if (errcode == 0) { /* no error set in the handle */ RETURN_FALSE; } @@ -1744,7 +1725,12 @@ PHP_FUNCTION(oci_set_prefetch) PHP_OCI_ZVAL_TO_STATEMENT(z_statement, statement); - if (php_oci_statement_set_prefetch(statement, size TSRMLS_CC)) { + if (size < 0) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Number of rows to be prefetched has to be greater than or equal to 0"); + return; + } + + if (php_oci_statement_set_prefetch(statement, (ub4)size TSRMLS_CC)) { RETURN_FALSE; } RETURN_TRUE; @@ -1759,6 +1745,7 @@ PHP_FUNCTION(oci_set_client_identifier) php_oci_connection *connection; char *client_id; int client_id_len; + sword errstatus; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &z_connection, &client_id, &client_id_len) == FAILURE) { return; @@ -1766,13 +1753,37 @@ PHP_FUNCTION(oci_set_client_identifier) PHP_OCI_ZVAL_TO_CONNECTION(z_connection, connection); - PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIAttrSet, ((dvoid *) connection->session, (ub4) OCI_HTYPE_SESSION, (dvoid *) client_id, (ub4) client_id_len, (ub4) OCI_ATTR_CLIENT_IDENTIFIER, OCI_G(err))); + PHP_OCI_CALL_RETURN(errstatus, OCIAttrSet, ((dvoid *) connection->session, (ub4) OCI_HTYPE_SESSION, (dvoid *) client_id, (ub4) client_id_len, (ub4) OCI_ATTR_CLIENT_IDENTIFIER, connection->err)); - if (OCI_G(errcode) != OCI_SUCCESS) { - php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC); + if (errstatus != OCI_SUCCESS) { + connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC); RETURN_FALSE; } +#ifdef HAVE_OCI8_DTRACE + /* The alternatives to storing client_id like done below are + i) display it in a probe here in oci_set_client_identifier and + let the user D script correlate the connection address probe + argument and the client_id. This would likely require user D + script variables, which would use kernel memory. + ii) call OCIAttrGet for each probe definition that uses + client_id. This would be slower than storing it. + */ + + if (connection->client_id) { + pefree(connection->client_id, connection->is_persistent); + } + + if (client_id) { + /* this long winded copy allows compatibility with older PHP versions */ + connection->client_id = (char *)pemalloc(client_id_len+1, connection->is_persistent); + memcpy(connection->client_id, client_id, client_id_len); + connection->client_id[client_id_len] = '\0'; + } else { + connection->client_id = NULL; + } +#endif /* HAVE_OCI8_DTRACE */ + RETURN_TRUE; } /* }}} */ @@ -1791,13 +1802,14 @@ PHP_FUNCTION(oci_set_edition) if (OCI_G(edition)) { efree(OCI_G(edition)); - OCI_G(edition) = NULL; } if (edition) { - OCI_G(edition) = (char *)safe_emalloc(edition_len+1, sizeof(text), 0); + OCI_G(edition) = (char *)safe_emalloc(edition_len+1, sizeof(char), 0); memcpy(OCI_G(edition), edition, edition_len); OCI_G(edition)[edition_len] = '\0'; + } else { + OCI_G(edition) = NULL; } RETURN_TRUE; @@ -1809,7 +1821,7 @@ PHP_FUNCTION(oci_set_edition) /* }}} */ /* {{{ proto bool oci_set_module_name(resource connection, string value) - Sets the module attribute on the connection */ + Sets the module attribute on the connection for end-to-end tracing */ PHP_FUNCTION(oci_set_module_name) { #if (OCI_MAJOR_VERSION >= 10) @@ -1817,6 +1829,7 @@ PHP_FUNCTION(oci_set_module_name) php_oci_connection *connection; char *module; int module_len; + sword errstatus; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &z_connection, &module, &module_len) == FAILURE) { return; @@ -1824,10 +1837,10 @@ PHP_FUNCTION(oci_set_module_name) PHP_OCI_ZVAL_TO_CONNECTION(z_connection, connection); - PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIAttrSet, ((dvoid *) connection->session, (ub4) OCI_HTYPE_SESSION, (dvoid *) module, (ub4) module_len, (ub4) OCI_ATTR_MODULE, OCI_G(err))); + PHP_OCI_CALL_RETURN(errstatus, OCIAttrSet, ((dvoid *) connection->session, (ub4) OCI_HTYPE_SESSION, (dvoid *) module, (ub4) module_len, (ub4) OCI_ATTR_MODULE, connection->err)); - if (OCI_G(errcode) != OCI_SUCCESS) { - php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC); + if (errstatus != OCI_SUCCESS) { + connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC); RETURN_FALSE; } @@ -1840,7 +1853,7 @@ PHP_FUNCTION(oci_set_module_name) /* }}} */ /* {{{ proto bool oci_set_action(resource connection, string value) - Sets the action attribute on the connection */ + Sets the action attribute on the connection for end-to-end tracing */ PHP_FUNCTION(oci_set_action) { #if (OCI_MAJOR_VERSION >= 10) @@ -1848,6 +1861,7 @@ PHP_FUNCTION(oci_set_action) php_oci_connection *connection; char *action; int action_len; + sword errstatus; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &z_connection, &action, &action_len) == FAILURE) { return; @@ -1855,10 +1869,10 @@ PHP_FUNCTION(oci_set_action) PHP_OCI_ZVAL_TO_CONNECTION(z_connection, connection); - PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIAttrSet, ((dvoid *) connection->session, (ub4) OCI_HTYPE_SESSION, (dvoid *) action, (ub4) action_len, (ub4) OCI_ATTR_ACTION, OCI_G(err))); + PHP_OCI_CALL_RETURN(errstatus, OCIAttrSet, ((dvoid *) connection->session, (ub4) OCI_HTYPE_SESSION, (dvoid *) action, (ub4) action_len, (ub4) OCI_ATTR_ACTION, connection->err)); - if (OCI_G(errcode) != OCI_SUCCESS) { - php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC); + if (errstatus != OCI_SUCCESS) { + connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC); RETURN_FALSE; } @@ -1871,7 +1885,7 @@ PHP_FUNCTION(oci_set_action) /* }}} */ /* {{{ proto bool oci_set_client_info(resource connection, string value) - Sets the client info attribute on the connection */ + Sets the client info attribute on the connection for end-to-end tracing */ PHP_FUNCTION(oci_set_client_info) { #if (OCI_MAJOR_VERSION >= 10) @@ -1879,6 +1893,7 @@ PHP_FUNCTION(oci_set_client_info) php_oci_connection *connection; char *client_info; int client_info_len; + sword errstatus; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &z_connection, &client_info, &client_info_len) == FAILURE) { return; @@ -1886,13 +1901,44 @@ PHP_FUNCTION(oci_set_client_info) PHP_OCI_ZVAL_TO_CONNECTION(z_connection, connection); - PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIAttrSet, ((dvoid *) connection->session, (ub4) OCI_HTYPE_SESSION, (dvoid *) client_info, (ub4) client_info_len, (ub4) OCI_ATTR_CLIENT_INFO, OCI_G(err))); + PHP_OCI_CALL_RETURN(errstatus, OCIAttrSet, ((dvoid *) connection->session, (ub4) OCI_HTYPE_SESSION, (dvoid *) client_info, (ub4) client_info_len, (ub4) OCI_ATTR_CLIENT_INFO, connection->err)); + + if (errstatus != OCI_SUCCESS) { + connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC); + RETURN_FALSE; + } + + RETURN_TRUE; +#else + php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Unsupported attribute type"); + RETURN_FALSE; +#endif +} +/* }}} */ + +#ifdef WAITIING_ORACLE_BUG_16695981_FIX +/* {{{ proto bool oci_set_db_operation(resource connection, string value) + Sets the "DB operation" on the connection for Oracle end-to-end tracing */ +PHP_FUNCTION(oci_set_db_operation) +{ +#if (OCI_MAJOR_VERSION > 11) + zval *z_connection; + php_oci_connection *connection; + char *dbop_name; + int dbop_name_len; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &z_connection, &dbop_name, &dbop_name_len) == FAILURE) { + return; + } + + PHP_OCI_ZVAL_TO_CONNECTION(z_connection, connection); + + PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIAttrSet, ((dvoid *) connection->session, (ub4) OCI_HTYPE_SESSION, (dvoid *) dbop_name, (ub4) dbop_name_len, (ub4) OCI_ATTR_DBOP, OCI_G(err))); if (OCI_G(errcode) != OCI_SUCCESS) { php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC); RETURN_FALSE; } - RETURN_TRUE; #else php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Unsupported attribute type"); @@ -1900,6 +1946,7 @@ PHP_FUNCTION(oci_set_client_info) #endif } /* }}} */ +#endif /* WAITIING_ORACLE_BUG_16695981_FIX */ /* {{{ proto bool oci_password_change(resource connection, string username, string old_password, string new_password) Changes the password of an account */ @@ -1957,7 +2004,7 @@ PHP_FUNCTION(oci_password_change) if (!connection) { RETURN_FALSE; } - RETURN_RESOURCE(connection->rsrc_id); + RETURN_RESOURCE(connection->id); } WRONG_PARAM_COUNT; } @@ -2395,6 +2442,32 @@ PHP_FUNCTION(oci_new_collection) } /* }}} */ +/* {{{ proto bool oci_get_implicit(resource stmt) + Get the next statement resource from an Oracle 12c PL/SQL Implicit Result Set */ +PHP_FUNCTION(oci_get_implicit_resultset) +{ + zval *z_statement; + php_oci_statement *statement; + php_oci_statement *imp_statement; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &z_statement) == FAILURE) { + return; + } + + PHP_OCI_ZVAL_TO_STATEMENT(z_statement, statement); + + imp_statement = php_oci_get_implicit_resultset(statement TSRMLS_CC); + + if (imp_statement) { + if (php_oci_statement_execute(imp_statement, (ub4)OCI_DEFAULT TSRMLS_CC)) + RETURN_FALSE; + RETURN_RESOURCE(imp_statement->id); + } + RETURN_FALSE; +} + +/* }}} */ + #endif /* HAVE_OCI8 */ /* diff --git a/ext/oci8/oci8_lob.c b/ext/oci8/oci8_lob.c index d05e053919..4f58c65737 100644 --- a/ext/oci8/oci8_lob.c +++ b/ext/oci8/oci8_lob.c @@ -54,6 +54,7 @@ php_oci_descriptor *php_oci_lob_create (php_oci_connection *connection, long type TSRMLS_DC) { php_oci_descriptor *descriptor; + sword errstatus; switch (type) { case OCI_DTYPE_FILE: @@ -70,15 +71,17 @@ php_oci_descriptor *php_oci_lob_create (php_oci_connection *connection, long typ descriptor = ecalloc(1, sizeof(php_oci_descriptor)); descriptor->type = type; descriptor->connection = connection; - zend_list_addref(descriptor->connection->rsrc_id); + zend_list_addref(descriptor->connection->id); - PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIDescriptorAlloc, (connection->env, (dvoid*)&(descriptor->descriptor), descriptor->type, (size_t) 0, (dvoid **) 0)); + PHP_OCI_CALL_RETURN(errstatus, OCIDescriptorAlloc, (connection->env, (dvoid*)&(descriptor->descriptor), descriptor->type, (size_t) 0, (dvoid **) 0)); - if (OCI_G(errcode) != OCI_SUCCESS) { - OCI_G(errcode) = php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC); + if (errstatus != OCI_SUCCESS) { + OCI_G(errcode) = php_oci_error(OCI_G(err), errstatus TSRMLS_CC); PHP_OCI_HANDLE_ERROR(connection, OCI_G(errcode)); efree(descriptor); return NULL; + } else { + OCI_G(errcode) = 0; /* retain backwards compat with OCI8 1.4 */ } PHP_OCI_REGISTER_RESOURCE(descriptor, le_descriptor); @@ -109,13 +112,15 @@ php_oci_descriptor *php_oci_lob_create (php_oci_connection *connection, long typ } return descriptor; -} /* }}} */ +} +/* }}} */ /* {{{ php_oci_lob_get_length() Get length of the LOB. The length is cached so we don't need to ask Oracle every time */ int php_oci_lob_get_length (php_oci_descriptor *descriptor, ub4 *length TSRMLS_DC) { php_oci_connection *connection = descriptor->connection; + sword errstatus; *length = 0; @@ -124,18 +129,18 @@ int php_oci_lob_get_length (php_oci_descriptor *descriptor, ub4 *length TSRMLS_D return 0; } else { if (descriptor->type == OCI_DTYPE_FILE) { - PHP_OCI_CALL_RETURN(connection->errcode, OCILobFileOpen, (connection->svc, connection->err, descriptor->descriptor, OCI_FILE_READONLY)); - if (connection->errcode != OCI_SUCCESS) { - connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC); + PHP_OCI_CALL_RETURN(errstatus, OCILobFileOpen, (connection->svc, connection->err, descriptor->descriptor, OCI_FILE_READONLY)); + if (errstatus != OCI_SUCCESS) { + connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC); PHP_OCI_HANDLE_ERROR(connection, connection->errcode); return 1; } } - PHP_OCI_CALL_RETURN(connection->errcode, OCILobGetLength, (connection->svc, connection->err, descriptor->descriptor, (ub4 *)length)); + PHP_OCI_CALL_RETURN(errstatus, OCILobGetLength, (connection->svc, connection->err, descriptor->descriptor, (ub4 *)length)); - if (connection->errcode != OCI_SUCCESS) { - connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC); + if (errstatus != OCI_SUCCESS) { + connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC); PHP_OCI_HANDLE_ERROR(connection, connection->errcode); return 1; } @@ -143,25 +148,24 @@ int php_oci_lob_get_length (php_oci_descriptor *descriptor, ub4 *length TSRMLS_D descriptor->lob_size = *length; if (descriptor->type == OCI_DTYPE_FILE) { - PHP_OCI_CALL_RETURN(connection->errcode, OCILobFileClose, (connection->svc, connection->err, descriptor->descriptor)); + PHP_OCI_CALL_RETURN(errstatus, OCILobFileClose, (connection->svc, connection->err, descriptor->descriptor)); - if (connection->errcode != OCI_SUCCESS) { - connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC); + if (errstatus != OCI_SUCCESS) { + connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC); PHP_OCI_HANDLE_ERROR(connection, connection->errcode); return 1; } } + + connection->errcode = 0; /* retain backwards compat with OCI8 1.4 */ } return 0; -} /* }}} */ +} +/* }}} */ /* {{{ php_oci_lob_callback() Append LOB portion to a memory buffer */ -#if defined(HAVE_OCI_LOB_READ2) sb4 php_oci_lob_callback (dvoid *ctxp, CONST dvoid *bufxp, oraub8 len, ub1 piece, dvoid **changed_bufpp, oraub8 *changed_lenp) -#else -sb4 php_oci_lob_callback (dvoid *ctxp, CONST dvoid *bufxp, ub4 len, ub1 piece) -#endif { ub4 lenp = (ub4) len; php_oci_lob_ctx *ctx = (php_oci_lob_ctx *)ctxp; @@ -203,25 +207,28 @@ sb4 php_oci_lob_callback (dvoid *ctxp, CONST dvoid *bufxp, ub4 len, ub1 piece) } /* }}} */ -/* {{{ php_oci_lob_calculate_buffer() */ +/* {{{ php_oci_lob_calculate_buffer() + Work out the size for LOB buffering */ static inline int php_oci_lob_calculate_buffer(php_oci_descriptor *descriptor, long read_length TSRMLS_DC) { php_oci_connection *connection = descriptor->connection; ub4 chunk_size; + sword errstatus; if (descriptor->type == OCI_DTYPE_FILE) { return read_length; } if (!descriptor->chunk_size) { - PHP_OCI_CALL_RETURN(connection->errcode, OCILobGetChunkSize, (connection->svc, connection->err, descriptor->descriptor, &chunk_size)); + PHP_OCI_CALL_RETURN(errstatus, OCILobGetChunkSize, (connection->svc, connection->err, descriptor->descriptor, &chunk_size)); - if (connection->errcode != OCI_SUCCESS) { - connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC); + if (errstatus != OCI_SUCCESS) { + connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC); PHP_OCI_HANDLE_ERROR(connection, connection->errcode); return read_length; /* we have to return original length here */ } descriptor->chunk_size = chunk_size; + connection->errcode = 0; /* retain backwards compat with OCI8 1.4 */ } if ((read_length % descriptor->chunk_size) != 0) { @@ -240,16 +247,12 @@ int php_oci_lob_read (php_oci_descriptor *descriptor, long read_length, long ini int buffer_size = PHP_OCI_LOB_BUFFER_SIZE; php_oci_lob_ctx ctx; ub1 *bufp; -#if defined(HAVE_OCI_LOB_READ2) oraub8 bytes_read, offset = 0; oraub8 requested_len = read_length; /* this is by default */ oraub8 chars_read = 0; -#else - int bytes_read, offset = 0; - int requested_len = read_length; /* this is by default */ -#endif int is_clob = 0; sb4 bytes_per_char = 1; + sword errstatus; *data_len = 0; *data = NULL; @@ -286,20 +289,20 @@ int php_oci_lob_read (php_oci_descriptor *descriptor, long read_length, long ini offset = initial_offset; if (descriptor->type == OCI_DTYPE_FILE) { - PHP_OCI_CALL_RETURN(connection->errcode, OCILobFileOpen, (connection->svc, connection->err, descriptor->descriptor, OCI_FILE_READONLY)); + PHP_OCI_CALL_RETURN(errstatus, OCILobFileOpen, (connection->svc, connection->err, descriptor->descriptor, OCI_FILE_READONLY)); - if (connection->errcode != OCI_SUCCESS) { - connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC); + if (errstatus != OCI_SUCCESS) { + connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC); PHP_OCI_HANDLE_ERROR(connection, connection->errcode); return 1; } } else { ub2 charset_id = 0; - PHP_OCI_CALL_RETURN(connection->errcode, OCILobCharSetId, (connection->env, connection->err, descriptor->descriptor, &charset_id)); + PHP_OCI_CALL_RETURN(errstatus, OCILobCharSetId, (connection->env, connection->err, descriptor->descriptor, &charset_id)); - if (connection->errcode != OCI_SUCCESS) { - connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC); + if (errstatus != OCI_SUCCESS) { + connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC); PHP_OCI_HANDLE_ERROR(connection, connection->errcode); return 1; } @@ -310,10 +313,10 @@ int php_oci_lob_read (php_oci_descriptor *descriptor, long read_length, long ini } if (is_clob) { - PHP_OCI_CALL_RETURN(connection->errcode, OCINlsNumericInfoGet, (connection->env, connection->err, &bytes_per_char, OCI_NLS_CHARSET_MAXBYTESZ)); + PHP_OCI_CALL_RETURN(errstatus, OCINlsNumericInfoGet, (connection->env, connection->err, &bytes_per_char, OCI_NLS_CHARSET_MAXBYTESZ)); - if (connection->errcode != OCI_SUCCESS) { - connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC); + if (errstatus != OCI_SUCCESS) { + connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC); PHP_OCI_HANDLE_ERROR(connection, connection->errcode); return 1; } @@ -324,7 +327,6 @@ int php_oci_lob_read (php_oci_descriptor *descriptor, long read_length, long ini ctx.alloc_len = (requested_len + 1) * bytes_per_char; *data = ecalloc(bytes_per_char, requested_len + 1); -#ifdef HAVE_OCI_LOB_READ2 if (is_clob) { chars_read = requested_len; bytes_read = 0; @@ -337,7 +339,7 @@ int php_oci_lob_read (php_oci_descriptor *descriptor, long read_length, long ini buffer_size = php_oci_lob_calculate_buffer(descriptor, buffer_size TSRMLS_CC); /* use chunk size */ bufp = (ub1 *) ecalloc(1, buffer_size); - PHP_OCI_CALL_RETURN(connection->errcode, OCILobRead2, + PHP_OCI_CALL_RETURN(errstatus, OCILobRead2, ( connection->svc, connection->err, @@ -362,37 +364,9 @@ int php_oci_lob_read (php_oci_descriptor *descriptor, long read_length, long ini } else { offset = descriptor->lob_current_position + bytes_read; } - -#else - - bytes_read = requested_len; - buffer_size = (requested_len < buffer_size ) ? requested_len : buffer_size; /* optimize buffer size */ - buffer_size = php_oci_lob_calculate_buffer(descriptor, buffer_size TSRMLS_CC); /* use chunk size */ - - bufp = (ub1 *) ecalloc(1, buffer_size); - PHP_OCI_CALL_RETURN(connection->errcode, OCILobRead, - ( - connection->svc, - connection->err, - descriptor->descriptor, - &bytes_read, /* IN/OUT bytes toread/read */ - offset + 1, /* offset (starts with 1) */ - (dvoid *) bufp, - (ub4) buffer_size, /* size of buffer */ - (dvoid *)&ctx, - (OCICallbackLobRead) php_oci_lob_callback, /* callback... */ - (ub2) descriptor->charset_id, /* The character set ID of the buffer data. */ - (ub1) descriptor->charset_form /* The character set form of the buffer data. */ - ) - ); - - efree(bufp); - offset = descriptor->lob_current_position + bytes_read; - -#endif - if (connection->errcode != OCI_SUCCESS) { - connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC); + if (errstatus != OCI_SUCCESS) { + connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC); PHP_OCI_HANDLE_ERROR(connection, connection->errcode); if (*data) { efree(*data); @@ -405,10 +379,10 @@ int php_oci_lob_read (php_oci_descriptor *descriptor, long read_length, long ini descriptor->lob_current_position = (int)offset; if (descriptor->type == OCI_DTYPE_FILE) { - PHP_OCI_CALL_RETURN(connection->errcode, OCILobFileClose, (connection->svc, connection->err, descriptor->descriptor)); + PHP_OCI_CALL_RETURN(errstatus, OCILobFileClose, (connection->svc, connection->err, descriptor->descriptor)); - if (connection->errcode != OCI_SUCCESS) { - connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC); + if (errstatus != OCI_SUCCESS) { + connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC); PHP_OCI_HANDLE_ERROR(connection, connection->errcode); if (*data) { efree(*data); @@ -419,8 +393,10 @@ int php_oci_lob_read (php_oci_descriptor *descriptor, long read_length, long ini } } + connection->errcode = 0; /* retain backwards compat with OCI8 1.4 */ return 0; -} /* }}} */ +} +/* }}} */ /* {{{ php_oci_lob_write() Write data to the LOB */ @@ -429,6 +405,7 @@ int php_oci_lob_write (php_oci_descriptor *descriptor, ub4 offset, char *data, i OCILobLocator *lob = (OCILobLocator *) descriptor->descriptor; php_oci_connection *connection = (php_oci_connection *) descriptor->connection; ub4 lob_length; + sword errstatus; *bytes_written = 0; if (php_oci_lob_get_length(descriptor, &lob_length TSRMLS_CC)) { @@ -447,7 +424,7 @@ int php_oci_lob_write (php_oci_descriptor *descriptor, ub4 offset, char *data, i offset = descriptor->lob_current_position; } - PHP_OCI_CALL_RETURN(connection->errcode, OCILobWrite, + PHP_OCI_CALL_RETURN(errstatus, OCILobWrite, ( connection->svc, connection->err, @@ -464,8 +441,8 @@ int php_oci_lob_write (php_oci_descriptor *descriptor, ub4 offset, char *data, i ) ); - if (connection->errcode) { - connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC); + if (errstatus) { + connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC); PHP_OCI_HANDLE_ERROR(connection, connection->errcode); *bytes_written = 0; return 1; @@ -482,14 +459,17 @@ int php_oci_lob_write (php_oci_descriptor *descriptor, ub4 offset, char *data, i descriptor->buffering = PHP_OCI_LOB_BUFFER_USED; } + connection->errcode = 0; /* retain backwards compat with OCI8 1.4 */ return 0; -} /* }}} */ +} +/* }}} */ /* {{{ php_oci_lob_set_buffering() Turn buffering off/onn for this particular LOB */ int php_oci_lob_set_buffering (php_oci_descriptor *descriptor, int on_off TSRMLS_DC) { php_oci_connection *connection = descriptor->connection; + sword errstatus; if (!on_off && descriptor->buffering == PHP_OCI_LOB_BUFFER_DISABLED) { /* disabling when it's already off */ @@ -502,19 +482,21 @@ int php_oci_lob_set_buffering (php_oci_descriptor *descriptor, int on_off TSRMLS } if (on_off) { - PHP_OCI_CALL_RETURN(connection->errcode, OCILobEnableBuffering, (connection->svc, connection->err, descriptor->descriptor)); + PHP_OCI_CALL_RETURN(errstatus, OCILobEnableBuffering, (connection->svc, connection->err, descriptor->descriptor)); } else { - PHP_OCI_CALL_RETURN(connection->errcode, OCILobDisableBuffering, (connection->svc, connection->err, descriptor->descriptor)); + PHP_OCI_CALL_RETURN(errstatus, OCILobDisableBuffering, (connection->svc, connection->err, descriptor->descriptor)); } - if (connection->errcode != OCI_SUCCESS) { - connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC); + if (errstatus != OCI_SUCCESS) { + connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC); PHP_OCI_HANDLE_ERROR(connection, connection->errcode); return 1; } descriptor->buffering = on_off ? PHP_OCI_LOB_BUFFER_ENABLED : PHP_OCI_LOB_BUFFER_DISABLED; + connection->errcode = 0; /* retain backwards compat with OCI8 1.4 */ return 0; -} /* }}} */ +} +/* }}} */ /* {{{ php_oci_lob_get_buffering() Return current buffering state for the LOB */ @@ -525,7 +507,8 @@ int php_oci_lob_get_buffering (php_oci_descriptor *descriptor) } else { return 0; } -} /* }}} */ +} +/* }}} */ /* {{{ php_oci_lob_copy() Copy one LOB (or its part) to another one */ @@ -533,6 +516,7 @@ int php_oci_lob_copy (php_oci_descriptor *descriptor_dest, php_oci_descriptor *d { php_oci_connection *connection = descriptor_dest->connection; ub4 length_dest, length_from, copy_len; + sword errstatus; if (php_oci_lob_get_length(descriptor_dest, &length_dest TSRMLS_CC)) { return 1; @@ -553,7 +537,7 @@ int php_oci_lob_copy (php_oci_descriptor *descriptor_dest, php_oci_descriptor *d return 1; } - PHP_OCI_CALL_RETURN(connection->errcode, OCILobCopy, + PHP_OCI_CALL_RETURN(errstatus, OCILobCopy, ( connection->svc, connection->err, @@ -565,29 +549,33 @@ int php_oci_lob_copy (php_oci_descriptor *descriptor_dest, php_oci_descriptor *d ) ); - if (connection->errcode != OCI_SUCCESS) { - connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC); + if (errstatus != OCI_SUCCESS) { + connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC); PHP_OCI_HANDLE_ERROR(connection, connection->errcode); return 1; } + connection->errcode = 0; /* retain backwards compat with OCI8 1.4 */ return 0; -} /* }}} */ +} +/* }}} */ /* {{{ php_oci_lob_close() Close LOB */ int php_oci_lob_close (php_oci_descriptor *descriptor TSRMLS_DC) { php_oci_connection *connection = descriptor->connection; - + sword errstatus; + if (descriptor->is_open) { - PHP_OCI_CALL_RETURN(connection->errcode, OCILobClose, (connection->svc, connection->err, descriptor->descriptor)); - } + PHP_OCI_CALL_RETURN(errstatus, OCILobClose, (connection->svc, connection->err, descriptor->descriptor)); - if (connection->errcode != OCI_SUCCESS) { - connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC); - PHP_OCI_HANDLE_ERROR(connection, connection->errcode); - return 1; + if (errstatus != OCI_SUCCESS) { + connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC); + PHP_OCI_HANDLE_ERROR(connection, connection->errcode); + return 1; + } + connection->errcode = 0; /* retain backwards compat with OCI8 1.4 */ } if (php_oci_temp_lob_close(descriptor TSRMLS_CC)) { @@ -595,7 +583,8 @@ int php_oci_lob_close (php_oci_descriptor *descriptor TSRMLS_DC) } return 0; -} /* }}} */ +} +/* }}} */ /* {{{ php_oci_temp_lob_close() Close Temporary LOB */ @@ -603,27 +592,29 @@ int php_oci_temp_lob_close (php_oci_descriptor *descriptor TSRMLS_DC) { php_oci_connection *connection = descriptor->connection; int is_temporary; + sword errstatus; - PHP_OCI_CALL_RETURN(connection->errcode, OCILobIsTemporary, (connection->env,connection->err, descriptor->descriptor, &is_temporary)); + PHP_OCI_CALL_RETURN(errstatus, OCILobIsTemporary, (connection->env,connection->err, descriptor->descriptor, &is_temporary)); - if (connection->errcode != OCI_SUCCESS) { - connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC); + if (errstatus != OCI_SUCCESS) { + connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC); PHP_OCI_HANDLE_ERROR(connection, connection->errcode); return 1; } if (is_temporary) { - PHP_OCI_CALL_RETURN(connection->errcode, OCILobFreeTemporary, (connection->svc, connection->err, descriptor->descriptor)); + PHP_OCI_CALL_RETURN(errstatus, OCILobFreeTemporary, (connection->svc, connection->err, descriptor->descriptor)); - if (connection->errcode != OCI_SUCCESS) { - connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC); + if (errstatus != OCI_SUCCESS) { + connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC); PHP_OCI_HANDLE_ERROR(connection, connection->errcode); return 1; } } + connection->errcode = 0; /* retain backwards compat with OCI8 1.4 */ return 0; -} /* }}} */ - +} +/* }}} */ /* {{{ php_oci_lob_flush() Flush buffers for the LOB (only if they have been used) */ @@ -631,7 +622,8 @@ int php_oci_lob_flush(php_oci_descriptor *descriptor, long flush_flag TSRMLS_DC) { OCILobLocator *lob = descriptor->descriptor; php_oci_connection *connection = descriptor->connection; - + sword errstatus; + if (!lob) { return 1; } @@ -654,18 +646,20 @@ int php_oci_lob_flush(php_oci_descriptor *descriptor, long flush_flag TSRMLS_DC) return 0; } - PHP_OCI_CALL_RETURN(connection->errcode, OCILobFlushBuffer, (connection->svc, connection->err, lob, flush_flag)); + PHP_OCI_CALL_RETURN(errstatus, OCILobFlushBuffer, (connection->svc, connection->err, lob, flush_flag)); - if (connection->errcode != OCI_SUCCESS) { - connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC); + if (errstatus != OCI_SUCCESS) { + connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC); PHP_OCI_HANDLE_ERROR(connection, connection->errcode); return 1; } /* marking buffer as enabled and not used */ descriptor->buffering = PHP_OCI_LOB_BUFFER_ENABLED; + connection->errcode = 0; /* retain backwards compat with OCI8 1.4 */ return 0; -} /* }}} */ +} +/* }}} */ /* {{{ php_oci_lob_free() Close LOB descriptor and free associated resources */ @@ -709,9 +703,10 @@ void php_oci_lob_free (php_oci_descriptor *descriptor TSRMLS_DC) PHP_OCI_CALL(OCIDescriptorFree, (descriptor->descriptor, descriptor->type)); - zend_list_delete(descriptor->connection->rsrc_id); + zend_list_delete(descriptor->connection->id); efree(descriptor); -} /* }}} */ +} +/* }}} */ /* {{{ php_oci_lob_import() Import LOB contents from the given file */ @@ -723,6 +718,7 @@ int php_oci_lob_import (php_oci_descriptor *descriptor, char *filename TSRMLS_DC php_oci_connection *connection = descriptor->connection; char buf[8192]; ub4 offset = 1; + sword errstatus; #if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 3) || (PHP_MAJOR_VERSION > 5) /* Safe mode has been removed in PHP 5.4 */ @@ -739,7 +735,7 @@ int php_oci_lob_import (php_oci_descriptor *descriptor, char *filename TSRMLS_DC } while ((loblen = read(fp, &buf, sizeof(buf))) > 0) { - PHP_OCI_CALL_RETURN(connection->errcode, + PHP_OCI_CALL_RETURN(errstatus, OCILobWrite, ( connection->svc, @@ -757,18 +753,21 @@ int php_oci_lob_import (php_oci_descriptor *descriptor, char *filename TSRMLS_DC ) ); - if (connection->errcode != OCI_SUCCESS) { - connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC); + if (errstatus != OCI_SUCCESS) { + connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC); PHP_OCI_HANDLE_ERROR(connection, connection->errcode); close(fp); return 1; + } else { + connection->errcode = 0; /* retain backwards compat with OCI8 1.4 */ } offset += loblen; } close(fp); return 0; -} /* }}} */ +} + /* }}} */ /* {{{ php_oci_lob_append() Append data to the end of the LOB */ @@ -778,6 +777,7 @@ int php_oci_lob_append (php_oci_descriptor *descriptor_dest, php_oci_descriptor OCILobLocator *lob_dest = descriptor_dest->descriptor; OCILobLocator *lob_from = descriptor_from->descriptor; ub4 dest_len, from_len; + sword errstatus; if (php_oci_lob_get_length(descriptor_dest, &dest_len TSRMLS_CC)) { return 1; @@ -791,15 +791,17 @@ int php_oci_lob_append (php_oci_descriptor *descriptor_dest, php_oci_descriptor return 0; } - PHP_OCI_CALL_RETURN(connection->errcode, OCILobAppend, (connection->svc, connection->err, lob_dest, lob_from)); + PHP_OCI_CALL_RETURN(errstatus, OCILobAppend, (connection->svc, connection->err, lob_dest, lob_from)); - if (connection->errcode != OCI_SUCCESS) { - connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC); + if (errstatus != OCI_SUCCESS) { + connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC); PHP_OCI_HANDLE_ERROR(connection, connection->errcode); return 1; } + connection->errcode = 0; /* retain backwards compat with OCI8 1.4 */ return 0; -} /* }}} */ +} +/* }}} */ /* {{{ php_oci_lob_truncate() Truncate LOB to the given length */ @@ -808,6 +810,7 @@ int php_oci_lob_truncate (php_oci_descriptor *descriptor, long new_lob_length TS php_oci_connection *connection = descriptor->connection; OCILobLocator *lob = descriptor->descriptor; ub4 lob_length; + sword errstatus; if (php_oci_lob_get_length(descriptor, &lob_length TSRMLS_CC)) { return 1; @@ -827,17 +830,20 @@ int php_oci_lob_truncate (php_oci_descriptor *descriptor, long new_lob_length TS return 1; } - PHP_OCI_CALL_RETURN(connection->errcode, OCILobTrim, (connection->svc, connection->err, lob, new_lob_length)); + PHP_OCI_CALL_RETURN(errstatus, OCILobTrim, (connection->svc, connection->err, lob, new_lob_length)); - if (connection->errcode != OCI_SUCCESS) { - connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC); + if (errstatus != OCI_SUCCESS) { + connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC); PHP_OCI_HANDLE_ERROR(connection, connection->errcode); return 1; } descriptor->lob_size = new_lob_length; + connection->errcode = 0; /* retain backwards compat with OCI8 1.4 */ + return 0; -} /* }}} */ +} +/* }}} */ /* {{{ php_oci_lob_erase() Erase (or fill with whitespaces, depending on LOB type) the LOB (or its part) */ @@ -846,6 +852,7 @@ int php_oci_lob_erase (php_oci_descriptor *descriptor, long offset, ub4 length, php_oci_connection *connection = descriptor->connection; OCILobLocator *lob = descriptor->descriptor; ub4 lob_length; + sword errstatus; *bytes_erased = 0; @@ -861,17 +868,19 @@ int php_oci_lob_erase (php_oci_descriptor *descriptor, long offset, ub4 length, length = lob_length; } - PHP_OCI_CALL_RETURN(connection->errcode, OCILobErase, (connection->svc, connection->err, lob, (ub4 *)&length, offset+1)); + PHP_OCI_CALL_RETURN(errstatus, OCILobErase, (connection->svc, connection->err, lob, (ub4 *)&length, offset+1)); - if (connection->errcode != OCI_SUCCESS) { - connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC); + if (errstatus != OCI_SUCCESS) { + connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC); PHP_OCI_HANDLE_ERROR(connection, connection->errcode); return 1; } *bytes_erased = length; + connection->errcode = 0; /* retain backwards compat with OCI8 1.4 */ return 0; -} /* }}} */ +} +/* }}} */ /* {{{ php_oci_lob_is_equal() Compare two LOB descriptors and figure out if they are pointing to the same LOB */ @@ -880,16 +889,19 @@ int php_oci_lob_is_equal (php_oci_descriptor *descriptor_first, php_oci_descript php_oci_connection *connection = descriptor_first->connection; OCILobLocator *first_lob = descriptor_first->descriptor; OCILobLocator *second_lob = descriptor_second->descriptor; + sword errstatus; - PHP_OCI_CALL_RETURN(connection->errcode, OCILobIsEqual, (connection->env, first_lob, second_lob, result)); + PHP_OCI_CALL_RETURN(errstatus, OCILobIsEqual, (connection->env, first_lob, second_lob, result)); - if (connection->errcode) { - connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC); + if (errstatus) { + connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC); PHP_OCI_HANDLE_ERROR(connection, connection->errcode); return 1; } + connection->errcode = 0; /* retain backwards compat with OCI8 1.4 */ return 0; -} /* }}} */ +} +/* }}} */ /* {{{ php_oci_lob_write_tmp() Create temporary LOB and write data to it */ @@ -898,6 +910,7 @@ int php_oci_lob_write_tmp (php_oci_descriptor *descriptor, long type, char *data php_oci_connection *connection = descriptor->connection; OCILobLocator *lob = descriptor->descriptor; ub4 bytes_written = 0; + sword errstatus; switch (type) { case OCI_TEMP_BLOB: @@ -914,7 +927,7 @@ int php_oci_lob_write_tmp (php_oci_descriptor *descriptor, long type, char *data return 1; } - PHP_OCI_CALL_RETURN(connection->errcode, OCILobCreateTemporary, + PHP_OCI_CALL_RETURN(errstatus, OCILobCreateTemporary, ( connection->svc, connection->err, @@ -927,24 +940,26 @@ int php_oci_lob_write_tmp (php_oci_descriptor *descriptor, long type, char *data ) ); - if (connection->errcode) { - connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC); + if (errstatus) { + connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC); PHP_OCI_HANDLE_ERROR(connection, connection->errcode); return 1; } - PHP_OCI_CALL_RETURN(connection->errcode, OCILobOpen, (connection->svc, connection->err, lob, OCI_LOB_READWRITE)); + PHP_OCI_CALL_RETURN(errstatus, OCILobOpen, (connection->svc, connection->err, lob, OCI_LOB_READWRITE)); - if (connection->errcode) { - connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC); + if (errstatus) { + connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC); PHP_OCI_HANDLE_ERROR(connection, connection->errcode); return 1; } descriptor->is_open = 1; + connection->errcode = 0; /* retain backwards compat with OCI8 1.4 */ return php_oci_lob_write(descriptor, 0, data, data_len, &bytes_written TSRMLS_CC); -} /* }}} */ +} +/* }}} */ #endif /* HAVE_OCI8 */ diff --git a/ext/oci8/oci8_statement.c b/ext/oci8/oci8_statement.c index 89facb0703..1e66308e53 100644 --- a/ext/oci8/oci8_statement.c +++ b/ext/oci8/oci8_statement.c @@ -43,21 +43,24 @@ /* {{{ php_oci_statement_create() Create statemend handle and allocate necessary resources */ -php_oci_statement *php_oci_statement_create (php_oci_connection *connection, char *query, int query_len TSRMLS_DC) +php_oci_statement *php_oci_statement_create(php_oci_connection *connection, char *query, int query_len TSRMLS_DC) { php_oci_statement *statement; - + sword errstatus; + + connection->errcode = 0; /* retain backwards compat with OCI8 1.4 */ + statement = ecalloc(1,sizeof(php_oci_statement)); if (!query_len) { /* do not allocate stmt handle for refcursors, we'll get it from OCIStmtPrepare2() */ PHP_OCI_CALL(OCIHandleAlloc, (connection->env, (dvoid **)&(statement->stmt), OCI_HTYPE_STMT, 0, NULL)); } - + PHP_OCI_CALL(OCIHandleAlloc, (connection->env, (dvoid **)&(statement->err), OCI_HTYPE_ERROR, 0, NULL)); if (query_len > 0) { - PHP_OCI_CALL_RETURN(connection->errcode, OCIStmtPrepare2, + PHP_OCI_CALL_RETURN(errstatus, OCIStmtPrepare2, ( connection->svc, &(statement->stmt), @@ -70,14 +73,19 @@ php_oci_statement *php_oci_statement_create (php_oci_connection *connection, cha OCI_DEFAULT ) ); - if (connection->errcode != OCI_SUCCESS) { - connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC); +#ifdef HAVE_OCI8_DTRACE + if (DTRACE_OCI8_SQLTEXT_ENABLED()) { + DTRACE_OCI8_SQLTEXT(connection, connection->client_id, statement, query); + } +#endif /* HAVE_OCI8_DTRACE */ - PHP_OCI_CALL(OCIStmtRelease, (statement->stmt, statement->err, NULL, 0, statement->errcode ? OCI_STRLS_CACHE_DELETE : OCI_DEFAULT)); + if (errstatus != OCI_SUCCESS) { + connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC); + + PHP_OCI_CALL(OCIStmtRelease, (statement->stmt, statement->err, NULL, 0, OCI_STRLS_CACHE_DELETE)); PHP_OCI_CALL(OCIHandleFree,(statement->err, OCI_HTYPE_ERROR)); - - efree(statement); PHP_OCI_HANDLE_ERROR(connection, connection->errcode); + efree(statement); return NULL; } } @@ -95,10 +103,15 @@ php_oci_statement *php_oci_statement_create (php_oci_connection *connection, cha statement->has_data = 0; statement->has_descr = 0; statement->parent_stmtid = 0; - zend_list_addref(statement->connection->rsrc_id); + statement->impres_child_stmt = NULL; + statement->impres_count = 0; + statement->impres_flag = PHP_OCI_IMPRES_UNKNOWN; /* may or may not have Implicit Result Set children */ + zend_list_addref(statement->connection->id); if (OCI_G(default_prefetch) >= 0) { - php_oci_statement_set_prefetch(statement, OCI_G(default_prefetch) TSRMLS_CC); + php_oci_statement_set_prefetch(statement, (ub4)OCI_G(default_prefetch) TSRMLS_CC); + } else { + php_oci_statement_set_prefetch(statement, (ub4)100 TSRMLS_CC); /* semi-arbitrary, "sensible default" */ } PHP_OCI_REGISTER_RESOURCE(statement, le_statement); @@ -109,25 +122,85 @@ php_oci_statement *php_oci_statement_create (php_oci_connection *connection, cha } /* }}} */ +/* {{{ php_oci_get_implicit_resultset() + Fetch implicit result set statement resource */ +php_oci_statement *php_oci_get_implicit_resultset(php_oci_statement *statement TSRMLS_DC) +{ +#if (OCI_MAJOR_VERSION < 12) + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Implicit results are available in Oracle Database 12c onwards"); + return NULL; +#else + void *result; + ub4 rtype; + php_oci_statement *statement2; /* implicit result set statement handle */ + sword errstatus; + + PHP_OCI_CALL_RETURN(errstatus, OCIStmtGetNextResult, (statement->stmt, statement->err, &result, &rtype, OCI_DEFAULT)); + if (errstatus == OCI_NO_DATA) { + return NULL; + } + + if (rtype != OCI_RESULT_TYPE_SELECT) { + /* Only OCI_RESULT_TYPE_SELECT is supported by Oracle DB 12cR1 */ + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unexpected implicit result type returned from Oracle Database"); + return NULL; + } else { + statement2 = ecalloc(1,sizeof(php_oci_statement)); + + PHP_OCI_CALL(OCIHandleAlloc, (statement->connection->env, (dvoid **)&(statement2->err), OCI_HTYPE_ERROR, 0, NULL)); + statement2->stmt = (OCIStmt *)result; + statement2->parent_stmtid = statement->id; + statement2->impres_child_stmt = NULL; + statement2->impres_count = 0; + statement2->impres_flag = PHP_OCI_IMPRES_IS_CHILD; + statement2->connection = statement->connection; + statement2->errcode = 0; + statement2->last_query = NULL; + statement2->last_query_len = 0; + statement2->columns = NULL; + statement2->binds = NULL; + statement2->defines = NULL; + statement2->ncolumns = 0; + statement2->executed = 0; + statement2->has_data = 0; + statement2->has_descr = 0; + statement2->stmttype = 0; + + zend_list_addref(statement->id); + zend_list_addref(statement2->connection->id); + + php_oci_statement_set_prefetch(statement2, statement->prefetch_count TSRMLS_CC); + + PHP_OCI_REGISTER_RESOURCE(statement2, le_statement); + + OCI_G(num_statements)++; + + return statement2; + } +#endif /* OCI_MAJOR_VERSION < 12 */ +} +/* }}} */ + /* {{{ php_oci_statement_set_prefetch() - Set prefetch buffer size for the statement (we're assuming that one row is ~1K sized) */ -int php_oci_statement_set_prefetch(php_oci_statement *statement, long size TSRMLS_DC) + Set prefetch buffer size for the statement */ +int php_oci_statement_set_prefetch(php_oci_statement *statement, ub4 prefetch TSRMLS_DC) { - ub4 prefetch = size; + sword errstatus; - if (size < 0) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Number of rows to be prefetched has to be greater than or equal to 0"); - return 1; + if (prefetch > 20000) { + prefetch = 20000; /* keep it somewhat sane */ } + + PHP_OCI_CALL_RETURN(errstatus, OCIAttrSet, (statement->stmt, OCI_HTYPE_STMT, &prefetch, 0, OCI_ATTR_PREFETCH_ROWS, statement->err)); - PHP_OCI_CALL_RETURN(statement->errcode, OCIAttrSet, (statement->stmt, OCI_HTYPE_STMT, &prefetch, 0, OCI_ATTR_PREFETCH_ROWS, statement->err)); - - if (statement->errcode != OCI_SUCCESS) { - statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC); + if (errstatus != OCI_SUCCESS) { + statement->errcode = php_oci_error(statement->err, errstatus TSRMLS_CC); PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode); + statement->prefetch_count = 0; return 1; } - + statement->prefetch_count = prefetch; + statement->errcode = 0; /* retain backwards compat with OCI8 1.4 */ return 0; } /* }}} */ @@ -163,8 +236,8 @@ int php_oci_cleanup_pre_fetch(void *data TSRMLS_DC) } return ZEND_HASH_APPLY_KEEP; -} /* }}} */ - +} +/* }}} */ /* {{{ php_oci_statement_fetch() Fetch a row from the statement */ @@ -175,16 +248,18 @@ int php_oci_statement_fetch(php_oci_statement *statement, ub4 nrows TSRMLS_DC) ub4 typep, iterp, idxp; ub1 in_outp, piecep; zend_bool piecewisecols = 0; - php_oci_out_column *column; + sword errstatus; + + statement->errcode = 0; /* retain backwards compat with OCI8 1.4 */ if (statement->has_descr && statement->columns) { zend_hash_apply(statement->columns, (apply_func_t) php_oci_cleanup_pre_fetch TSRMLS_CC); } - PHP_OCI_CALL_RETURN(statement->errcode, OCIStmtFetch, (statement->stmt, statement->err, nrows, OCI_FETCH_NEXT, OCI_DEFAULT)); + PHP_OCI_CALL_RETURN(errstatus, OCIStmtFetch, (statement->stmt, statement->err, nrows, OCI_FETCH_NEXT, OCI_DEFAULT)); - if ( statement->errcode == OCI_NO_DATA || nrows == 0 ) { + if (errstatus == OCI_NO_DATA || nrows == 0) { if (statement->last_query == NULL) { /* reset define-list for refcursors */ if (statement->columns) { @@ -196,7 +271,6 @@ int php_oci_statement_fetch(php_oci_statement *statement, ub4 nrows TSRMLS_DC) statement->executed = 0; } - statement->errcode = 0; /* OCI_NO_DATA is NO error for us!!! */ statement->has_data = 0; if (nrows == 0) { @@ -209,15 +283,15 @@ int php_oci_statement_fetch(php_oci_statement *statement, ub4 nrows TSRMLS_DC) /* reset length for all piecewise columns */ for (i = 0; i < statement->ncolumns; i++) { column = php_oci_statement_get_column(statement, i + 1, NULL, 0 TSRMLS_CC); - if (column->piecewise) { + if (column && column->piecewise) { column->retlen4 = 0; piecewisecols = 1; } } - while (statement->errcode == OCI_NEED_DATA) { + while (errstatus == OCI_NEED_DATA) { if (piecewisecols) { - PHP_OCI_CALL_RETURN(statement->errcode, + PHP_OCI_CALL_RETURN(errstatus, OCIStmtGetPieceInfo, ( statement->stmt, @@ -234,7 +308,7 @@ int php_oci_statement_fetch(php_oci_statement *statement, ub4 nrows TSRMLS_DC) /* scan through our columns for a piecewise column with a matching handle */ for (i = 0; i < statement->ncolumns; i++) { column = php_oci_statement_get_column(statement, i + 1, NULL, 0 TSRMLS_CC); - if (column->piecewise && handlepp == column->oci_define) { + if (column && column->piecewise && handlepp == column->oci_define) { if (!column->data) { column->data = (text *) ecalloc(1, PHP_OCI_PIECE_SIZE + 1); } else { @@ -259,7 +333,7 @@ int php_oci_statement_fetch(php_oci_statement *statement, ub4 nrows TSRMLS_DC) } } - PHP_OCI_CALL_RETURN(statement->errcode, OCIStmtFetch, (statement->stmt, statement->err, nrows, OCI_FETCH_NEXT, OCI_DEFAULT)); + PHP_OCI_CALL_RETURN(errstatus, OCIStmtFetch, (statement->stmt, statement->err, nrows, OCI_FETCH_NEXT, OCI_DEFAULT)); if (piecewisecols) { for (i = 0; i < statement->ncolumns; i++) { @@ -271,7 +345,7 @@ int php_oci_statement_fetch(php_oci_statement *statement, ub4 nrows TSRMLS_DC) } } - if (statement->errcode == OCI_SUCCESS_WITH_INFO || statement->errcode == OCI_SUCCESS) { + if (errstatus == OCI_SUCCESS_WITH_INFO || errstatus == OCI_SUCCESS) { statement->has_data = 1; /* do the stuff needed for OCIDefineByName */ @@ -292,7 +366,7 @@ int php_oci_statement_fetch(php_oci_statement *statement, ub4 nrows TSRMLS_DC) return 0; } - statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC); + statement->errcode = php_oci_error(statement->err, errstatus TSRMLS_CC); PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode); statement->has_data = 0; @@ -332,7 +406,7 @@ php_oci_out_column *php_oci_statement_get_column(php_oci_statement *statement, l } /* }}} */ -/* php_oci_define_callback() {{{ */ +/* {{{ php_oci_define_callback() */ sb4 php_oci_define_callback(dvoid *ctx, OCIDefine *define, ub4 iter, dvoid **bufpp, ub4 **alenpp, ub1 *piecep, dvoid **indpp, ub2 **rcpp) { php_oci_out_column *outcol = (php_oci_out_column *)ctx; @@ -415,12 +489,18 @@ int php_oci_statement_execute(php_oci_statement *statement, ub4 mode TSRMLS_DC) ub4 colcount; ub2 dynamic; dvoid *buf; + sword errstatus; switch (mode) { case OCI_COMMIT_ON_SUCCESS: case OCI_DESCRIBE_ONLY: case OCI_DEFAULT: /* only these are allowed */ +#ifdef HAVE_OCI8_DTRACE + if (DTRACE_OCI8_EXECUTE_MODE_ENABLED()) { + DTRACE_OCI8_EXECUTE_MODE(statement->connection, statement->connection->client_id, statement, mode); + } +#endif /* HAVE_OCI8_DTRACE */ break; default: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid execute mode given: %d", mode); @@ -430,12 +510,14 @@ int php_oci_statement_execute(php_oci_statement *statement, ub4 mode TSRMLS_DC) if (!statement->stmttype) { /* get statement type */ - PHP_OCI_CALL_RETURN(statement->errcode, OCIAttrGet, ((dvoid *)statement->stmt, OCI_HTYPE_STMT, (ub2 *)&statement->stmttype, (ub4 *)0, OCI_ATTR_STMT_TYPE, statement->err)); + PHP_OCI_CALL_RETURN(errstatus, OCIAttrGet, ((dvoid *)statement->stmt, OCI_HTYPE_STMT, (ub2 *)&statement->stmttype, (ub4 *)0, OCI_ATTR_STMT_TYPE, statement->err)); - if (statement->errcode != OCI_SUCCESS) { - statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC); + if (errstatus != OCI_SUCCESS) { + statement->errcode = php_oci_error(statement->err, errstatus TSRMLS_CC); PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode); return 1; + } else { + statement->errcode = 0; /* retain backwards compat with OCI8 1.4 */ } } @@ -445,9 +527,7 @@ int php_oci_statement_execute(php_oci_statement *statement, ub4 mode TSRMLS_DC) iters = 1; } - if (statement->last_query) { - /* if we execute refcursors we don't have a query and - we don't want to execute!!! */ + if (statement->last_query) { /* Don't execute REFCURSORS or Implicit Result Set handles */ if (statement->binds) { int result = 0; @@ -458,10 +538,10 @@ int php_oci_statement_execute(php_oci_statement *statement, ub4 mode TSRMLS_DC) } /* execute statement */ - PHP_OCI_CALL_RETURN(statement->errcode, OCIStmtExecute, (statement->connection->svc, statement->stmt, statement->err, iters, 0, NULL, NULL, mode)); + PHP_OCI_CALL_RETURN(errstatus, OCIStmtExecute, (statement->connection->svc, statement->stmt, statement->err, iters, 0, NULL, NULL, mode)); - if (statement->errcode != OCI_SUCCESS) { - statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC); + if (errstatus != OCI_SUCCESS) { + statement->errcode = php_oci_error(statement->err, errstatus TSRMLS_CC); PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode); return 1; } @@ -471,10 +551,20 @@ int php_oci_statement_execute(php_oci_statement *statement, ub4 mode TSRMLS_DC) } if (mode & OCI_COMMIT_ON_SUCCESS) { - statement->connection->needs_commit = 0; - } else { - statement->connection->needs_commit = 1; + /* No need to rollback on disconnect */ + statement->connection->rb_on_disconnect = 0; + } else if (statement->stmttype != OCI_STMT_SELECT) { + /* Assume some uncommitted DML occurred */ + statement->connection->rb_on_disconnect = 1; } + /* else for SELECT with OCI_NO_AUTO_COMMIT, leave + * "rb_on_disconnect" at its previous value. SELECT can't + * initiate uncommitted DML. (An AUTONOMOUS_TRANSACTION in + * invoked PL/SQL must explicitly rollback/commit else the + * SELECT fails). + */ + + statement->errcode = 0; /* retain backwards compat with OCI8 1.4 */ } if (statement->stmttype == OCI_STMT_SELECT && statement->executed == 0) { @@ -487,10 +577,10 @@ int php_oci_statement_execute(php_oci_statement *statement, ub4 mode TSRMLS_DC) counter = 1; /* get number of columns */ - PHP_OCI_CALL_RETURN(statement->errcode, OCIAttrGet, ((dvoid *)statement->stmt, OCI_HTYPE_STMT, (dvoid *)&colcount, (ub4 *)0, OCI_ATTR_PARAM_COUNT, statement->err)); + PHP_OCI_CALL_RETURN(errstatus, OCIAttrGet, ((dvoid *)statement->stmt, OCI_HTYPE_STMT, (dvoid *)&colcount, (ub4 *)0, OCI_ATTR_PARAM_COUNT, statement->err)); - if (statement->errcode != OCI_SUCCESS) { - statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC); + if (errstatus != OCI_SUCCESS) { + statement->errcode = php_oci_error(statement->err, errstatus TSRMLS_CC); PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode); return 1; } @@ -507,50 +597,50 @@ int php_oci_statement_execute(php_oci_statement *statement, ub4 mode TSRMLS_DC) } /* get column */ - PHP_OCI_CALL_RETURN(statement->errcode, OCIParamGet, ((dvoid *)statement->stmt, OCI_HTYPE_STMT, statement->err, (dvoid**)¶m, counter)); + PHP_OCI_CALL_RETURN(errstatus, OCIParamGet, ((dvoid *)statement->stmt, OCI_HTYPE_STMT, statement->err, (dvoid**)¶m, counter)); - if (statement->errcode != OCI_SUCCESS) { - statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC); + if (errstatus != OCI_SUCCESS) { + statement->errcode = php_oci_error(statement->err, errstatus TSRMLS_CC); PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode); return 1; } /* get column datatype */ - PHP_OCI_CALL_RETURN(statement->errcode, OCIAttrGet, ((dvoid *)param, OCI_DTYPE_PARAM, (dvoid *)&outcol->data_type, (ub4 *)0, OCI_ATTR_DATA_TYPE, statement->err)); + PHP_OCI_CALL_RETURN(errstatus, OCIAttrGet, ((dvoid *)param, OCI_DTYPE_PARAM, (dvoid *)&outcol->data_type, (ub4 *)0, OCI_ATTR_DATA_TYPE, statement->err)); - if (statement->errcode != OCI_SUCCESS) { + if (errstatus != OCI_SUCCESS) { PHP_OCI_CALL(OCIDescriptorFree, (param, OCI_DTYPE_PARAM)); - statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC); + statement->errcode = php_oci_error(statement->err, errstatus TSRMLS_CC); PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode); return 1; } /* get character set form */ - PHP_OCI_CALL_RETURN(statement->errcode, OCIAttrGet, ((dvoid *)param, OCI_DTYPE_PARAM, (dvoid *)&outcol->charset_form, (ub4 *)0, OCI_ATTR_CHARSET_FORM, statement->err)); + PHP_OCI_CALL_RETURN(errstatus, OCIAttrGet, ((dvoid *)param, OCI_DTYPE_PARAM, (dvoid *)&outcol->charset_form, (ub4 *)0, OCI_ATTR_CHARSET_FORM, statement->err)); - if (statement->errcode != OCI_SUCCESS) { + if (errstatus != OCI_SUCCESS) { PHP_OCI_CALL(OCIDescriptorFree, (param, OCI_DTYPE_PARAM)); - statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC); + statement->errcode = php_oci_error(statement->err, errstatus TSRMLS_CC); PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode); return 1; } /* get character set id */ - PHP_OCI_CALL_RETURN(statement->errcode, OCIAttrGet, ((dvoid *)param, OCI_DTYPE_PARAM, (dvoid *)&outcol->charset_id, (ub4 *)0, OCI_ATTR_CHARSET_ID, statement->err)); + PHP_OCI_CALL_RETURN(errstatus, OCIAttrGet, ((dvoid *)param, OCI_DTYPE_PARAM, (dvoid *)&outcol->charset_id, (ub4 *)0, OCI_ATTR_CHARSET_ID, statement->err)); - if (statement->errcode != OCI_SUCCESS) { + if (errstatus != OCI_SUCCESS) { PHP_OCI_CALL(OCIDescriptorFree, (param, OCI_DTYPE_PARAM)); - statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC); + statement->errcode = php_oci_error(statement->err, errstatus TSRMLS_CC); PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode); return 1; } /* get size of the column */ - PHP_OCI_CALL_RETURN(statement->errcode, OCIAttrGet, ((dvoid *)param, OCI_DTYPE_PARAM, (dvoid *)&outcol->data_size, (dvoid *)0, OCI_ATTR_DATA_SIZE, statement->err)); + PHP_OCI_CALL_RETURN(errstatus, OCIAttrGet, ((dvoid *)param, OCI_DTYPE_PARAM, (dvoid *)&outcol->data_size, (dvoid *)0, OCI_ATTR_DATA_SIZE, statement->err)); - if (statement->errcode != OCI_SUCCESS) { + if (errstatus != OCI_SUCCESS) { PHP_OCI_CALL(OCIDescriptorFree, (param, OCI_DTYPE_PARAM)); - statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC); + statement->errcode = php_oci_error(statement->err, errstatus TSRMLS_CC); PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode); return 1; } @@ -559,31 +649,31 @@ int php_oci_statement_execute(php_oci_statement *statement, ub4 mode TSRMLS_DC) outcol->retlen = outcol->data_size; /* get scale of the column */ - PHP_OCI_CALL_RETURN(statement->errcode, OCIAttrGet, ((dvoid *)param, OCI_DTYPE_PARAM, (dvoid *)&outcol->scale, (dvoid *)0, OCI_ATTR_SCALE, statement->err)); + PHP_OCI_CALL_RETURN(errstatus, OCIAttrGet, ((dvoid *)param, OCI_DTYPE_PARAM, (dvoid *)&outcol->scale, (dvoid *)0, OCI_ATTR_SCALE, statement->err)); - if (statement->errcode != OCI_SUCCESS) { + if (errstatus != OCI_SUCCESS) { PHP_OCI_CALL(OCIDescriptorFree, (param, OCI_DTYPE_PARAM)); - statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC); + statement->errcode = php_oci_error(statement->err, errstatus TSRMLS_CC); PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode); return 1; } /* get precision of the column */ - PHP_OCI_CALL_RETURN(statement->errcode, OCIAttrGet, ((dvoid *)param, OCI_DTYPE_PARAM, (dvoid *)&outcol->precision, (dvoid *)0, OCI_ATTR_PRECISION, statement->err)); + PHP_OCI_CALL_RETURN(errstatus, OCIAttrGet, ((dvoid *)param, OCI_DTYPE_PARAM, (dvoid *)&outcol->precision, (dvoid *)0, OCI_ATTR_PRECISION, statement->err)); - if (statement->errcode != OCI_SUCCESS) { + if (errstatus != OCI_SUCCESS) { PHP_OCI_CALL(OCIDescriptorFree, (param, OCI_DTYPE_PARAM)); - statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC); + statement->errcode = php_oci_error(statement->err, errstatus TSRMLS_CC); PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode); return 1; } /* get name of the column */ - PHP_OCI_CALL_RETURN(statement->errcode, OCIAttrGet, ((dvoid *)param, OCI_DTYPE_PARAM, (dvoid **)&colname, (ub4 *)&outcol->name_len, (ub4)OCI_ATTR_NAME, statement->err)); + PHP_OCI_CALL_RETURN(errstatus, OCIAttrGet, ((dvoid *)param, OCI_DTYPE_PARAM, (dvoid **)&colname, (ub4 *)&outcol->name_len, (ub4)OCI_ATTR_NAME, statement->err)); - if (statement->errcode != OCI_SUCCESS) { + if (errstatus != OCI_SUCCESS) { PHP_OCI_CALL(OCIDescriptorFree, (param, OCI_DTYPE_PARAM)); - statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC); + statement->errcode = php_oci_error(statement->err, errstatus TSRMLS_CC); PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode); return 1; } @@ -591,7 +681,7 @@ int php_oci_statement_execute(php_oci_statement *statement, ub4 mode TSRMLS_DC) outcol->name = estrndup((char*) colname, outcol->name_len); - /* find a user-setted define */ + /* find a user-set define */ if (statement->defines) { if (zend_hash_find(statement->defines,outcol->name,outcol->name_len,(void **) &outcol->define) == SUCCESS) { if (outcol->define->type) { @@ -679,7 +769,7 @@ int php_oci_statement_execute(php_oci_statement *statement, ub4 mode TSRMLS_DC) } if (dynamic == OCI_DYNAMIC_FETCH) { - PHP_OCI_CALL_RETURN(statement->errcode, + PHP_OCI_CALL_RETURN(errstatus, OCIDefineByPos, ( statement->stmt, /* IN/OUT handle to the requested SQL query */ @@ -697,7 +787,7 @@ int php_oci_statement_execute(php_oci_statement *statement, ub4 mode TSRMLS_DC) ); } else { - PHP_OCI_CALL_RETURN(statement->errcode, + PHP_OCI_CALL_RETURN(errstatus, OCIDefineByPos, ( statement->stmt, /* IN/OUT handle to the requested SQL query */ @@ -716,10 +806,10 @@ int php_oci_statement_execute(php_oci_statement *statement, ub4 mode TSRMLS_DC) } - if (statement->errcode != OCI_SUCCESS) { - statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC); + if (errstatus != OCI_SUCCESS) { + statement->errcode = php_oci_error(statement->err, errstatus TSRMLS_CC); PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode); - return 0; + return 1; } /* additional OCIDefineDynamic() call */ @@ -729,7 +819,7 @@ int php_oci_statement_execute(php_oci_statement *statement, ub4 mode TSRMLS_DC) case SQLT_BLOB: case SQLT_CLOB: case SQLT_BFILE: - PHP_OCI_CALL_RETURN(statement->errcode, + PHP_OCI_CALL_RETURN(errstatus, OCIDefineDynamic, ( outcol->oci_define, @@ -739,9 +829,15 @@ int php_oci_statement_execute(php_oci_statement *statement, ub4 mode TSRMLS_DC) ) ); + if (errstatus != OCI_SUCCESS) { + statement->errcode = php_oci_error(statement->err, errstatus TSRMLS_CC); + PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode); + return 1; + } break; } } + statement->errcode = 0; /* retain backwards compat with OCI8 1.4 */ } return 0; @@ -752,10 +848,9 @@ int php_oci_statement_execute(php_oci_statement *statement, ub4 mode TSRMLS_DC) Cancel statement */ int php_oci_statement_cancel(php_oci_statement *statement TSRMLS_DC) { - return php_oci_statement_fetch(statement, 0 TSRMLS_CC); - -} /* }}} */ +} +/* }}} */ /* {{{ php_oci_statement_free() Destroy statement handle and free associated resources */ @@ -764,15 +859,15 @@ void php_oci_statement_free(php_oci_statement *statement TSRMLS_DC) if (statement->stmt) { if (statement->last_query_len) { /* FIXME: magical */ PHP_OCI_CALL(OCIStmtRelease, (statement->stmt, statement->err, NULL, 0, statement->errcode ? OCI_STRLS_CACHE_DELETE : OCI_DEFAULT)); - } else { + } else if (statement->impres_flag != PHP_OCI_IMPRES_IS_CHILD) { /* Oracle doc says don't free Implicit Result Set handles */ PHP_OCI_CALL(OCIHandleFree, (statement->stmt, OCI_HTYPE_STMT)); } - statement->stmt = 0; + statement->stmt = NULL; } if (statement->err) { PHP_OCI_CALL(OCIHandleFree, (statement->err, OCI_HTYPE_ERROR)); - statement->err = 0; + statement->err = NULL; } if (statement->last_query) { @@ -798,11 +893,12 @@ void php_oci_statement_free(php_oci_statement *statement TSRMLS_DC) zend_list_delete(statement->parent_stmtid); } - zend_list_delete(statement->connection->rsrc_id); + zend_list_delete(statement->connection->id); efree(statement); OCI_G(num_statements)--; -} /* }}} */ +} +/* }}} */ /* {{{ php_oci_bind_pre_exec() Helper function */ @@ -872,6 +968,7 @@ int php_oci_bind_post_exec(void *data TSRMLS_DC) { php_oci_bind *bind = (php_oci_bind *) data; php_oci_connection *connection = bind->parent_statement->connection; + sword errstatus; if (bind->indicator == -1) { /* NULL */ zval *val = bind->zval; @@ -931,24 +1028,26 @@ int php_oci_bind_post_exec(void *data TSRMLS_DC) memset((void*)buff,0,sizeof(buff)); if ((i < bind->array.old_length) && (zend_hash_get_current_data(hash, (void **) &entry) != FAILURE)) { - PHP_OCI_CALL_RETURN(connection->errcode, OCIDateToText, (connection->err, &(((OCIDate *)(bind->array.elements))[i]), 0, 0, 0, 0, &buff_len, buff)); + PHP_OCI_CALL_RETURN(errstatus, OCIDateToText, (connection->err, &(((OCIDate *)(bind->array.elements))[i]), 0, 0, 0, 0, &buff_len, buff)); zval_dtor(*entry); - if (connection->errcode != OCI_SUCCESS) { - connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC); + if (errstatus != OCI_SUCCESS) { + connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC); PHP_OCI_HANDLE_ERROR(connection, connection->errcode); ZVAL_NULL(*entry); } else { + connection->errcode = 0; /* retain backwards compat with OCI8 1.4 */ ZVAL_STRINGL(*entry, (char *)buff, buff_len, 1); } zend_hash_move_forward(hash); } else { - PHP_OCI_CALL_RETURN(connection->errcode, OCIDateToText, (connection->err, &(((OCIDate *)(bind->array.elements))[i]), 0, 0, 0, 0, &buff_len, buff)); - if (connection->errcode != OCI_SUCCESS) { - connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC); + PHP_OCI_CALL_RETURN(errstatus, OCIDateToText, (connection->err, &(((OCIDate *)(bind->array.elements))[i]), 0, 0, 0, 0, &buff_len, buff)); + if (errstatus != OCI_SUCCESS) { + connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC); PHP_OCI_HANDLE_ERROR(connection, connection->errcode); add_next_index_null(bind->zval); } else { + connection->errcode = 0; /* retain backwards compat with OCI8 1.4 */ add_next_index_stringl(bind->zval, (char *)buff, buff_len, 1); } } @@ -982,7 +1081,7 @@ int php_oci_bind_post_exec(void *data TSRMLS_DC) /* {{{ php_oci_bind_by_name() Bind zval to the given placeholder */ -int php_oci_bind_by_name(php_oci_statement *statement, char *name, int name_len, zval* var, long maxlength, ub2 type TSRMLS_DC) +int php_oci_bind_by_name(php_oci_statement *statement, char *name, int name_len, zval *var, long maxlength, ub2 type TSRMLS_DC) { php_oci_collection *bind_collection = NULL; php_oci_descriptor *bind_descriptor = NULL; @@ -994,6 +1093,7 @@ int php_oci_bind_by_name(php_oci_statement *statement, char *name, int name_len, php_oci_bind bind, *old_bind, *bindp; int mode = OCI_DATA_AT_EXEC; sb4 value_sz = -1; + sword errstatus; switch (type) { case SQLT_NTY: @@ -1117,7 +1217,7 @@ int php_oci_bind_by_name(php_oci_statement *statement, char *name, int name_len, bindp->type = type; zval_add_ref(&var); - PHP_OCI_CALL_RETURN(statement->errcode, + PHP_OCI_CALL_RETURN(errstatus, OCIBindByName, ( statement->stmt, /* statement handle */ @@ -1137,14 +1237,14 @@ int php_oci_bind_by_name(php_oci_statement *statement, char *name, int name_len, ) ); - if (statement->errcode != OCI_SUCCESS) { - statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC); + if (errstatus != OCI_SUCCESS) { + statement->errcode = php_oci_error(statement->err, errstatus TSRMLS_CC); PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode); return 1; } if (mode == OCI_DATA_AT_EXEC) { - PHP_OCI_CALL_RETURN(statement->errcode, OCIBindDynamic, + PHP_OCI_CALL_RETURN(errstatus, OCIBindDynamic, ( bindp->bind, statement->err, @@ -1155,8 +1255,8 @@ int php_oci_bind_by_name(php_oci_statement *statement, char *name, int name_len, ) ); - if (statement->errcode != OCI_SUCCESS) { - statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC); + if (errstatus != OCI_SUCCESS) { + statement->errcode = php_oci_error(statement->err, errstatus TSRMLS_CC); PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode); return 1; } @@ -1164,7 +1264,7 @@ int php_oci_bind_by_name(php_oci_statement *statement, char *name, int name_len, if (type == SQLT_NTY) { /* Bind object */ - PHP_OCI_CALL_RETURN(statement->errcode, OCIBindObject, + PHP_OCI_CALL_RETURN(errstatus, OCIBindObject, ( bindp->bind, statement->err, @@ -1176,15 +1276,17 @@ int php_oci_bind_by_name(php_oci_statement *statement, char *name, int name_len, ) ); - if (statement->errcode) { - statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC); + if (errstatus) { + statement->errcode = php_oci_error(statement->err, errstatus TSRMLS_CC); PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode); return 1; } } + statement->errcode = 0; /* retain backwards compat with OCI8 1.4 */ return 0; -} /* }}} */ +} +/* }}} */ /* {{{ php_oci_bind_in_callback() Callback used when binding LOBs and VARCHARs */ @@ -1235,7 +1337,8 @@ sb4 php_oci_bind_in_callback( *piecep = OCI_ONE_PIECE; /* pass all data in one go */ return OCI_CONTINUE; -}/* }}} */ +} +/* }}} */ /* {{{ php_oci_bind_out_callback() Callback used when binding LOBs and VARCHARs */ @@ -1358,55 +1461,61 @@ php_oci_out_column *php_oci_statement_get_column_helper(INTERNAL_FUNCTION_PARAME zval_dtor(&tmp); } return column; -} /* }}} */ +} +/* }}} */ /* {{{ php_oci_statement_get_type() Return type of the statement */ int php_oci_statement_get_type(php_oci_statement *statement, ub2 *type TSRMLS_DC) { ub2 statement_type; + sword errstatus; *type = 0; - PHP_OCI_CALL_RETURN(statement->errcode, OCIAttrGet, ((dvoid *)statement->stmt, OCI_HTYPE_STMT, (ub2 *)&statement_type, (ub4 *)0, OCI_ATTR_STMT_TYPE, statement->err)); + PHP_OCI_CALL_RETURN(errstatus, OCIAttrGet, ((dvoid *)statement->stmt, OCI_HTYPE_STMT, (ub2 *)&statement_type, (ub4 *)0, OCI_ATTR_STMT_TYPE, statement->err)); - if (statement->errcode != OCI_SUCCESS) { - statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC); + if (errstatus != OCI_SUCCESS) { + statement->errcode = php_oci_error(statement->err, errstatus TSRMLS_CC); PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode); return 1; } - + statement->errcode = 0; /* retain backwards compat with OCI8 1.4 */ *type = statement_type; return 0; -} /* }}} */ +} +/* }}} */ /* {{{ php_oci_statement_get_numrows() Get the number of rows fetched to the clientside (NOT the number of rows in the result set) */ int php_oci_statement_get_numrows(php_oci_statement *statement, ub4 *numrows TSRMLS_DC) { ub4 statement_numrows; + sword errstatus; *numrows = 0; - PHP_OCI_CALL_RETURN(statement->errcode, OCIAttrGet, ((dvoid *)statement->stmt, OCI_HTYPE_STMT, (ub4 *)&statement_numrows, (ub4 *)0, OCI_ATTR_ROW_COUNT, statement->err)); + PHP_OCI_CALL_RETURN(errstatus, OCIAttrGet, ((dvoid *)statement->stmt, OCI_HTYPE_STMT, (ub4 *)&statement_numrows, (ub4 *)0, OCI_ATTR_ROW_COUNT, statement->err)); - if (statement->errcode != OCI_SUCCESS) { - statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC); + if (errstatus != OCI_SUCCESS) { + statement->errcode = php_oci_error(statement->err, errstatus TSRMLS_CC); PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode); return 1; } - + statement->errcode = 0; /* retain backwards compat with OCI8 1.4 */ *numrows = statement_numrows; return 0; -} /* }}} */ +} +/* }}} */ /* {{{ php_oci_bind_array_by_name() Bind arrays to PL/SQL types */ -int php_oci_bind_array_by_name(php_oci_statement *statement, char *name, int name_len, zval* var, long max_table_length, long maxlength, long type TSRMLS_DC) +int php_oci_bind_array_by_name(php_oci_statement *statement, char *name, int name_len, zval *var, long max_table_length, long maxlength, long type TSRMLS_DC) { php_oci_bind *bind, *bindp; + sword errstatus; convert_to_array(var); @@ -1470,7 +1579,7 @@ int php_oci_bind_array_by_name(php_oci_statement *statement, char *name, int nam zval_add_ref(&var); - PHP_OCI_CALL_RETURN(statement->errcode, + PHP_OCI_CALL_RETURN(errstatus, OCIBindByName, ( statement->stmt, @@ -1491,19 +1600,21 @@ int php_oci_bind_array_by_name(php_oci_statement *statement, char *name, int nam ); - if (statement->errcode != OCI_SUCCESS) { + if (errstatus != OCI_SUCCESS) { efree(bind); - statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC); + statement->errcode = php_oci_error(statement->err, errstatus TSRMLS_CC); PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode); return 1; } + statement->errcode = 0; /* retain backwards compat with OCI8 1.4 */ efree(bind); return 0; -} /* }}} */ +} +/* }}} */ /* {{{ php_oci_bind_array_helper_string() Bind arrays to PL/SQL types */ -php_oci_bind *php_oci_bind_array_helper_string(zval* var, long max_table_length, long maxlength TSRMLS_DC) +php_oci_bind *php_oci_bind_array_helper_string(zval *var, long max_table_length, long maxlength TSRMLS_DC) { php_oci_bind *bind; ub4 i; @@ -1568,11 +1679,12 @@ php_oci_bind *php_oci_bind_array_helper_string(zval* var, long max_table_length, zend_hash_internal_pointer_reset(hash); return bind; -} /* }}} */ +} +/* }}} */ /* {{{ php_oci_bind_array_helper_number() Bind arrays to PL/SQL types */ -php_oci_bind *php_oci_bind_array_helper_number(zval* var, long max_table_length TSRMLS_DC) +php_oci_bind *php_oci_bind_array_helper_number(zval *var, long max_table_length TSRMLS_DC) { php_oci_bind *bind; ub4 i; @@ -1606,11 +1718,12 @@ php_oci_bind *php_oci_bind_array_helper_number(zval* var, long max_table_length zend_hash_internal_pointer_reset(hash); return bind; -} /* }}} */ +} +/* }}} */ /* {{{ php_oci_bind_array_helper_double() Bind arrays to PL/SQL types */ -php_oci_bind *php_oci_bind_array_helper_double(zval* var, long max_table_length TSRMLS_DC) +php_oci_bind *php_oci_bind_array_helper_double(zval *var, long max_table_length TSRMLS_DC) { php_oci_bind *bind; ub4 i; @@ -1644,16 +1757,18 @@ php_oci_bind *php_oci_bind_array_helper_double(zval* var, long max_table_length zend_hash_internal_pointer_reset(hash); return bind; -} /* }}} */ +} +/* }}} */ /* {{{ php_oci_bind_array_helper_date() Bind arrays to PL/SQL types */ -php_oci_bind *php_oci_bind_array_helper_date(zval* var, long max_table_length, php_oci_connection *connection TSRMLS_DC) +php_oci_bind *php_oci_bind_array_helper_date(zval *var, long max_table_length, php_oci_connection *connection TSRMLS_DC) { php_oci_bind *bind; ub4 i; HashTable *hash; zval **entry; + sword errstatus; hash = HASH_OF(var); @@ -1675,14 +1790,14 @@ php_oci_bind *php_oci_bind_array_helper_date(zval* var, long max_table_length, p if ((i < bind->array.current_length) && (zend_hash_get_current_data(hash, (void **) &entry) != FAILURE)) { convert_to_string_ex(entry); - PHP_OCI_CALL_RETURN(connection->errcode, OCIDateFromText, (connection->err, (CONST text *)Z_STRVAL_PP(entry), Z_STRLEN_PP(entry), NULL, 0, NULL, 0, &oci_date)); + PHP_OCI_CALL_RETURN(errstatus, OCIDateFromText, (connection->err, (CONST text *)Z_STRVAL_PP(entry), Z_STRLEN_PP(entry), NULL, 0, NULL, 0, &oci_date)); - if (connection->errcode != OCI_SUCCESS) { + if (errstatus != OCI_SUCCESS) { /* failed to convert string to date */ efree(bind->array.element_lengths); efree(bind->array.elements); efree(bind); - connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC); + connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC); PHP_OCI_HANDLE_ERROR(connection, connection->errcode); return NULL; } @@ -1690,25 +1805,27 @@ php_oci_bind *php_oci_bind_array_helper_date(zval* var, long max_table_length, p ((OCIDate *)bind->array.elements)[i] = oci_date; zend_hash_move_forward(hash); } else { - PHP_OCI_CALL_RETURN(connection->errcode, OCIDateFromText, (connection->err, (CONST text *)"01-JAN-00", sizeof("01-JAN-00")-1, NULL, 0, NULL, 0, &oci_date)); + PHP_OCI_CALL_RETURN(errstatus, OCIDateFromText, (connection->err, (CONST text *)"01-JAN-00", sizeof("01-JAN-00")-1, NULL, 0, NULL, 0, &oci_date)); - if (connection->errcode != OCI_SUCCESS) { + if (errstatus != OCI_SUCCESS) { /* failed to convert string to date */ efree(bind->array.element_lengths); efree(bind->array.elements); efree(bind); - connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC); + connection->errcode = php_oci_error(connection->err, errstatus TSRMLS_CC); PHP_OCI_HANDLE_ERROR(connection, connection->errcode); return NULL; } ((OCIDate *)bind->array.elements)[i] = oci_date; } + connection->errcode = 0; /* retain backwards compat with OCI8 1.4 */ } zend_hash_internal_pointer_reset(hash); return bind; -} /* }}} */ +} +/* }}} */ #endif /* HAVE_OCI8 */ diff --git a/ext/oci8/package.xml b/ext/oci8/package.xml index feadf1907b..8e55b9abd5 100644 --- a/ext/oci8/package.xml +++ b/ext/oci8/package.xml @@ -6,7 +6,19 @@ http://pear.php.net/dtd/package-2.0.xsd"> <name>oci8</name> <channel>pecl.php.net</channel> <summary>Extension for Oracle Database</summary> - <description>This extension allows you to access Oracle databases. It can be built with PHP 4.3.9 to 5.x. It can be linked with Oracle 9.2, 10, 11, or 12.1 client libraries. + + <description> +Use the OCI8 extension to access Oracle Database. The extension can +be linked with Oracle client libraries from Oracle Database 10.2, 11, +or 12.1. These libraries are found in the database installation, or +in the free Oracle Instant Client available from Oracle. Oracle's +standard cross-version connectivity applies. For example, PHP OCI8 +linked with Instant Client 11.2 can connect to Oracle Database 9.2 +onward. See Oracle's note "Oracle Client / Server Interoperability +Support" (ID 207303.1) for details. PHP OCI8 2.0 can be built with +PHP 5.2 onward. Use the older PHP OCI8 1.4.10 when using PHP 4.3.9 +through to PHP 5.1.x, or when only Oracle Database 9.2 client +libraries are available. </description> <lead> <name>Christopher Jones</name> @@ -18,7 +30,7 @@ http://pear.php.net/dtd/package-2.0.xsd"> <name>Antony Dovgal</name> <user>tony2001</user> <email>tony2001@php.net</email> - <active>yes</active> + <active>no</active> </lead> <lead> <name>Wez Furlong</name> @@ -33,21 +45,21 @@ http://pear.php.net/dtd/package-2.0.xsd"> <active>no</active> </lead> - <date>2013-07-08</date> + <date>2013-10-22</date> <time>12:00:00</time> - <version> - <release>1.4.10</release> - <api>1.4.10</api> - </version> - <stability> - <release>stable</release> - <api>stable</api> - </stability> - <license uri="http://www.php.net/license">PHP</license> - <notes> - Bump PECL package info version check to allow PECL installs with PHP 5.5+ - </notes> + <version> + <release>2.0.7</release> + <api>2.0.7</api> + </version> + <stability> + <release>stable</release> + <api>stable</api> + </stability> + <license uri="http://www.php.net/license">PHP</license> + <notes> + Build change: Fix source variable definition for C89 compatibility + </notes> <contents> <dir name="/"> <dir name="tests"> @@ -94,6 +106,7 @@ http://pear.php.net/dtd/package-2.0.xsd"> <file name="bind_misccoltypes.phpt" role="test" /> <file name="bind_number.phpt" role="test" /> <file name="bind_query.phpt" role="test" /> + <file name="bind_raw_2.phpt" role="test" /> <file name="bind_raw.phpt" role="test" /> <file name="bind_rowid.phpt" role="test" /> <file name="bind_sqltafc.phpt" role="test" /> @@ -131,7 +144,6 @@ http://pear.php.net/dtd/package-2.0.xsd"> <file name="bug42841.phpt" role="test" /> <file name="bug43492_2.phpt" role="test" /> <file name="bug43492.phpt" role="test" /> - <file name="bug43497_92.phpt" role="test" /> <file name="bug43497.phpt" role="test" /> <file name="bug44008.phpt" role="test" /> <file name="bug44113.phpt" role="test" /> @@ -144,7 +156,6 @@ http://pear.php.net/dtd/package-2.0.xsd"> <file name="bug51253.phpt" role="test" /> <file name="bug51291_1.phpt" role="test" /> <file name="bug51291_2.phpt" role="test" /> - <file name="clientversion_92.phpt" role="test" /> <file name="clientversion.phpt" role="test" /> <file name="close.phpt" role="test" /> <file name="coll_001.phpt" role="test" /> @@ -213,6 +224,8 @@ http://pear.php.net/dtd/package-2.0.xsd"> <file name="cursors_old.phpt" role="test" /> <file name="cursors.phpt" role="test" /> <file name="dbmsoutput.phpt" role="test" /> + <file name="db_op_1.phpt" role="test" /> + <file name="db_op_2.phpt" role="test" /> <file name="debug.phpt" role="test" /> <file name="default_prefetch0.phpt" role="test" /> <file name="default_prefetch1.phpt" role="test" /> @@ -258,6 +271,7 @@ http://pear.php.net/dtd/package-2.0.xsd"> <file name="error_old.phpt" role="test" /> <file name="error_parse.phpt" role="test" /> <file name="error.phpt" role="test" /> + <file name="error_set.phpt" role="test" /> <file name="exec_fetch.phpt" role="test" /> <file name="execute_mode.phpt" role="test" /> <file name="extauth_01.phpt" role="test" /> @@ -287,6 +301,38 @@ http://pear.php.net/dtd/package-2.0.xsd"> <file name="field_funcs_old.phpt" role="test" /> <file name="field_funcs.phpt" role="test" /> <file name="function_aliases.phpt" role="test" /> + <file name="imp_res_1.phpt" role="test" /> + <file name="imp_res_2.phpt" role="test" /> + <file name="imp_res_3.phpt" role="test" /> + <file name="imp_res_4.phpt" role="test" /> + <file name="imp_res_5.phpt" role="test" /> + <file name="imp_res_6.phpt" role="test" /> + <file name="imp_res_7.phpt" role="test" /> + <file name="imp_res_call_error.phpt" role="test" /> + <file name="imp_res_cancel.phpt" role="test" /> + <file name="imp_res_close.phpt" role="test" /> + <file name="imp_res_cursor.phpt" role="test" /> + <file name="imp_res_dbmsoutput.phpt" role="test" /> + <file name="imp_res_field.phpt" role="test" /> + <file name="imp_res_func_error.phpt" role="test" /> + <file name="imp_res_get_1.phpt" role="test" /> + <file name="imp_res_get_2.phpt" role="test" /> + <file name="imp_res_get_3.phpt" role="test" /> + <file name="imp_res_get_4.phpt" role="test" /> + <file name="imp_res_get_5.phpt" role="test" /> + <file name="imp_res_get_all.phpt" role="test" /> + <file name="imp_res_get_cancel.phpt" role="test" /> + <file name="imp_res_get_close_1.phpt" role="test" /> + <file name="imp_res_get_close_2.phpt" role="test" /> + <file name="imp_res_get_close_3.phpt" role="test" /> + <file name="imp_res_get_cursor.phpt" role="test" /> + <file name="imp_res_get_dbmsoutput.phpt" role="test" /> + <file name="imp_res_get_exec.phpt" role="test" /> + <file name="imp_res_get_none.phpt" role="test" /> + <file name="imp_res_insert.phpt" role="test" /> + <file name="imp_res_lob.phpt" role="test" /> + <file name="imp_res_prefetch.phpt" role="test" /> + <file name="ini_1.phpt" role="test" /> <file name="lob_001.phpt" role="test" /> <file name="lob_002.phpt" role="test" /> <file name="lob_003.phpt" role="test" /> @@ -335,6 +381,7 @@ http://pear.php.net/dtd/package-2.0.xsd"> <file name="lob_aliases.phpt" role="test" /> <file name="lob_null.phpt" role="test" /> <file name="lob_temp1.phpt" role="test" /> + <file name="lob_temp2.phpt" role="test" /> <file name="lob_temp.phpt" role="test" /> <file name="minfo.phpt" role="test" /> <file name="null_byte_1.phpt" role="test" /> @@ -383,21 +430,21 @@ http://pear.php.net/dtd/package-2.0.xsd"> <file name="config.w32" role="src" /> <file name="CREDITS" role="doc" /> <file name="oci8.c" role="src" /> - <file name="oci8.dsp" role="src" /> + <file name="oci8_dtrace.d" role="src" /> <file name="oci8_collection.c" role="src" /> <file name="oci8_interface.c" role="src" /> <file name="oci8_lob.c" role="src" /> <file name="oci8_statement.c" role="src" /> <file name="php_oci8.h" role="src" /> <file name="php_oci8_int.h" role="src" /> + <file name="oci8.dsp" role="src" /> <file name="README" role="doc" /> </dir> <!-- / --> </contents> <dependencies> <required> <php> - <min>4.3.9</min> - <max>6.0.0</max> + <min>5.2.0</min> </php> <pearinstaller> <min>1.4.0b1</min> @@ -412,6 +459,203 @@ http://pear.php.net/dtd/package-2.0.xsd"> <release> <version> + <release>2.0.6</release> + <api>2.0.6</api> + </version> + <stability> + <release>stable</release> + <api>stable</api> + </stability> + <license uri="http://www.php.net/license">PHP</license> + <notes> +Added a LICENSE file to make it easier for PECL binary distributions +to conform with the license. + </notes> +</release> + +<release> + <version> + <release>2.0.5</release> + <api>2.0.5</api> + </version> + <stability> + <release>stable</release> + <api>stable</api> + </stability> + <license uri="http://www.php.net/license">PHP</license> + <notes> +Bump PHP OCI8 2.0 mininum requirements to PHP 5.2 and Oracle client +library 10.2. (Use OCI8 1.4 for older PHP version support or if only +Oracle 9.2 client libraries are available.) + +Re-enable php_oci8.dll and php_oci8_11g.dll for Windows builds so URL +links work in the new Windows PECL infrastructure. + </notes> +</release> + +<release> + <version> + <release>2.0.4</release> + <api>2.0.4</api> + </version> + <stability> + <release>devel</release> + <api>devel</api> + </stability> + <license uri="http://www.php.net/license">PHP</license> + <notes> +Fix persistent memory usage with --enable-dtrace +Export get_module() for Windows php_oci8_12c.dll + </notes> +</release> + +<release> + <version> + <release>2.0.3</release> + <api>2.0.3</api> + </version> + <stability> + <release>devel</release> + <api>devel</api> + </stability> + <license uri="http://www.php.net/license">PHP</license> + <notes> +Add the oci_set_client_identifier() value and statement structure pointer to several DTrace probes. +Use 'phpoci' as the DTrace provider name since uniqueness is required by the Linux fasttrap module. +Update Windows builds to create only php_oci8_12c.dll. + </notes> +</release> + +<release> + <version> + <release>2.0.2</release> + <api>2.0.2</api> + </version> + <stability> + <release>devel</release> + <api>devel</api> + </stability> + <license uri="http://www.php.net/license">PHP</license> + <notes> +Review and improve error handling code and data types. +Fix oci_set_*($connection, ...) error handling so oci_error($connection) works. +Add DTrace oci8-connection-close probe +Add the connection handle to several DTrace probes. + </notes> +</release> + +<release> + <version> + <release>2.0.1</release> + <api>2.0.1</api> + </version> + <stability> + <release>devel</release> + <api>devel</api> + </stability> + <license uri="http://www.php.net/license">PHP</license> + <notes> +Fixed --enable-maintainer-zts mode. +Allow Implicit Result Set statement resources to inherit the parent's current prefetch count. +Allow OCI8 to be DTrace-enabled independently from core PHP. +Require OCI8 to be configured 'shared' when enabling DTrace support. + </notes> +</release> + +<release> + <version> + <release>2.0.0</release> + <api>2.0.0</api> + </version> + <stability> + <release>devel</release> + <api>devel</api> + </stability> + <license uri="http://www.php.net/license">PHP</license> + <notes> +- NEW FUNCTIONALITY: + + - Added Implicit Result Set support for Oracle Database 12c. + Streaming of all IRS's returned from a PL/SQL block is available + via oci_fetch_array, oci_fetch_assoc, oci_fetch_object and + oci_fetch_row (but not oci_fetch or oci_fetch_all). + Alternatively individual IRS statement resources can be obtained + with the new function 'oci_get_implicit_resultset' and passed to + any oci_fetch_* function. + + - Added DTrace probes enabled with PHP's generic --enable-dtrace + +- IMPROVED FUNCTIONALITY: + + - Using 'oci_execute($s, OCI_NO_AUTO_COMMIT)' for a SELECT no + longer unnecessarily initiates an internal ROLLBACK during + connection close. This can improve overall scalability by + reducing "round trips" between PHP and the database. + +- CHANGED FUNCTIONALITY: + + - PHPINFO() CHANGES: + + - The oci8.event and oci8.connection_class values are now shown + only when the Oracle client libraries support the respective + functionality. + + - Connection statistics are now in a separate phpinfo() table. + + - Temporary LOB and Collection support status lines in + phpinfo() were removed. These features have always been + enabled since 2007. + + - OCI_INTERNAL_DEBUG() CHANGES: + + - The oci_internal_debug() function is now a no-op. Use PHP's + --enable-dtrace functionality with DTrace or SystemTap instead. + +- INTERNAL CHANGES: + + - Fixed a potential NULL pointer dereference flagged by Parfait + static code analysis. + + - Extended testing of existing OCI8 functionality. + + - Improved test output portability when using the PHP development + web server to run tests. + + - Removed no-longer necessary Unicode patterns from tests + (vestiges of PHP's previous PHP 6 project) + + - Improved build portability by removing compilation type cast + warnings with some compilers. + + - Fixed compilation warnings when building with Oracle 9.2 + client libraries. + + - Updated code to use internal macro PHP_OCI_REGISTER_RESOURCE. + + - Regularized code prototypes and fixed some in-line documentation + prototypes. + + - Fixed code folding. + </notes> +</release> + +<release> + <version> + <release>1.4.10</release> + <api>1.4.10</api> + </version> + <stability> + <release>stable</release> + <api>stable</api> + </stability> + <license uri="http://www.php.net/license">PHP</license> + <notes> + Bump PECL package info version check to allow PECL installs with PHP 5.5+ + </notes> +</release> + +<release> + <version> <release>1.4.9</release> <api>1.4.9</api> </version> @@ -457,7 +701,7 @@ http://pear.php.net/dtd/package-2.0.xsd"> Fixed OCI8 part of bug #55748 (CVE-2011-4153: multiple NULL pointer dereferences with zend_strndup) Fixed OCI8 part of bug #55301 (multiple null pointer dereferences with calloc) Increased maximum Oracle error message buffer length for new Oracle 11.2.0.3 size - Improve internal initalization failure error messages + Improve internal initialization failure error messages </notes> </release> @@ -472,7 +716,7 @@ http://pear.php.net/dtd/package-2.0.xsd"> </stability> <license uri="http://www.php.net/license">PHP</license> <notes> - Added oci_client_version() returning the runtime Oracle client library version + Added oci_client_version() returning the run time Oracle client library version Made OCI8 extension buildable with PHP 5.4-development code </notes> </release> @@ -846,7 +1090,7 @@ Fixed bug #36820 (Privileged connection with an Oracle password file fails) <date>2006-03-16</date> <license uri="http://www.php.net/license">PHP</license> <notes>Changed OCI8 code to use OCIServerVersion() instead of OCIPing(), which may crash Oracle server of version < 10.2 -Fixed bug #36235 (ocicolumnname returns false before a successfull fetch) +Fixed bug #36235 (ocicolumnname returns false before a successful fetch) Fixed bug #36096 (oci_result() returns garbage after oci_fetch() failed) Fixed bug #36055 (possible OCI8 crash in multithreaded environment) Fixed bug #36010 (Segfault when re-creating and re-executing statements with bound parameters) diff --git a/ext/oci8/php_oci8.h b/ext/oci8/php_oci8.h index f1079526f6..86c5abfa89 100644 --- a/ext/oci8/php_oci8.h +++ b/ext/oci8/php_oci8.h @@ -41,12 +41,11 @@ */ #ifdef PHP_OCI8_VERSION /* The definition of PHP_OCI8_VERSION changed in PHP 5.3 and building - * this code with PHP 5.2 and earlier (e.g. when using OCI8 from PECL) - * will conflict. + * this code with PHP 5.2 (e.g. when using OCI8 from PECL) will conflict. */ #undef PHP_OCI8_VERSION #endif -#define PHP_OCI8_VERSION "1.4.10" +#define PHP_OCI8_VERSION "2.0.7-dev" extern zend_module_entry oci8_module_entry; #define phpext_oci8_ptr &oci8_module_entry diff --git a/ext/oci8/php_oci8_int.h b/ext/oci8/php_oci8_int.h index 155e57d2cd..e50983d75e 100644 --- a/ext/oci8/php_oci8_int.h +++ b/ext/oci8/php_oci8_int.h @@ -31,7 +31,7 @@ # ifndef PHP_OCI8_INT_H # define PHP_OCI8_INT_H -/* misc defines {{{ */ +/* {{{ misc defines */ # if (defined(__osf__) && defined(__alpha)) # ifndef A_OSF # define A_OSF @@ -44,6 +44,10 @@ # endif # endif /* osf alpha */ +#ifdef HAVE_OCI8_DTRACE +#include "oci8_dtrace_gen.h" +#endif + #if defined(min) #undef min #endif @@ -66,7 +70,7 @@ extern int le_session; extern zend_class_entry *oci_lob_class_entry_ptr; extern zend_class_entry *oci_coll_class_entry_ptr; -/* constants {{{ */ +/* {{{ constants */ #define PHP_OCI_SEEK_SET 0 #define PHP_OCI_SEEK_CUR 1 #define PHP_OCI_SEEK_END 2 @@ -101,6 +105,11 @@ extern zend_class_entry *oci_coll_class_entry_ptr; #error Invalid value for PHP_OCI_CRED_EXT #endif +#define PHP_OCI_IMPRES_UNKNOWN 0 +#define PHP_OCI_IMPRES_NO_CHILDREN 1 +#define PHP_OCI_IMPRES_HAS_CHILDREN 2 +#define PHP_OCI_IMPRES_IS_CHILD 3 + /* * Name passed to Oracle for tracing. Note some DB views only show * the first nine characters of the driver name. @@ -109,16 +118,21 @@ extern zend_class_entry *oci_coll_class_entry_ptr; /* }}} */ -typedef struct { /* php_oci_spool {{{ */ - OCIEnv *env; /*env of this session pool */ +/* {{{ php_oci_spool */ +typedef struct { + int id; /* resource id */ + OCIEnv *env; /* env of this session pool */ OCIError *err; /* pool's error handle */ OCISPool *poolh; /* pool handle */ void *poolname; /* session pool name */ unsigned int poolname_len; /* length of session pool name */ char *spool_hash_key; /* Hash key for session pool in plist */ -} php_oci_spool; /* }}} */ +} php_oci_spool; +/* }}} */ -typedef struct { /* php_oci_connection {{{ */ +/* {{{ php_oci_connection */ +typedef struct { + int id; /* resource ID */ OCIEnv *env; /* private env handle */ ub2 charset; /* charset ID */ OCIServer *server; /* private server handle */ @@ -127,7 +141,7 @@ typedef struct { /* php_oci_connection {{{ */ OCIAuthInfo *authinfo; /* Cached authinfo handle for OCISessionGet */ OCIError *err; /* private error handle */ php_oci_spool *private_spool; /* private session pool (for persistent) */ - sword errcode; /* last errcode */ + sb4 errcode; /* last ORA- error number */ HashTable *descriptors; /* descriptors hash, used to flush all the LOBs using this connection on commit */ ulong descriptor_count; /* used to index the descriptors hash table. Not an accurate count */ @@ -135,17 +149,21 @@ typedef struct { /* php_oci_connection {{{ */ unsigned is_attached:1; /* hels to determine if we should detach from the server when closing/freeing the connection */ unsigned is_persistent:1; /* self-descriptive */ unsigned used_this_request:1; /* helps to determine if we should reset connection's next ping time and check its timeout */ - unsigned needs_commit:1; /* helps to determine if we should rollback this connection on close/shutdown */ + unsigned rb_on_disconnect:1; /* helps to determine if we should rollback this connection on close/shutdown */ unsigned passwd_changed:1; /* helps determine if a persistent connection hash should be invalidated after a password change */ unsigned is_stub:1; /* flag to keep track whether the connection structure has a real OCI connection associated */ unsigned using_spool:1; /* Is this connection from session pool? */ - int rsrc_id; /* resource ID */ time_t idle_expiry; /* time when the connection will be considered as expired */ time_t *next_pingp; /* (pointer to) time of the next ping */ char *hash_key; /* hashed details of the connection */ -} php_oci_connection; /* }}} */ +#ifdef HAVE_OCI8_DTRACE + char *client_id; /* The oci_set_client_identifier() value */ +#endif +} php_oci_connection; +/* }}} */ -typedef struct { /* php_oci_descriptor {{{ */ +/* {{{ php_oci_descriptor */ +typedef struct { int id; ulong index; /* descriptors hash table index */ php_oci_connection *connection; /* parent connection handle */ @@ -158,15 +176,19 @@ typedef struct { /* php_oci_descriptor {{{ */ ub1 charset_form; /* charset form, required for NCLOBs */ ub2 charset_id; /* charset ID */ unsigned is_open:1; /* helps to determine if lob is open or not */ -} php_oci_descriptor; /* }}} */ +} php_oci_descriptor; +/* }}} */ -typedef struct { /* php_oci_lob_ctx {{{ */ +/* {{{ php_oci_lob_ctx */ +typedef struct { char **lob_data; /* address of pointer to LOB data */ ub4 *lob_len; /* address of LOB length variable (bytes) */ ub4 alloc_len; -} php_oci_lob_ctx; /* }}} */ +} php_oci_lob_ctx; +/* }}} */ -typedef struct { /* php_oci_collection {{{ */ +/* {{{ php_oci_collection */ +typedef struct { int id; php_oci_connection *connection; /* parent connection handle */ OCIType *tdo; /* collection's type handle */ @@ -175,23 +197,30 @@ typedef struct { /* php_oci_collection {{{ */ OCIType *element_type; /* element's type handle */ OCITypeCode element_typecode; /* element's typecode handle */ OCIColl *collection; /* collection handle */ -} php_oci_collection; /* }}} */ +} php_oci_collection; +/* }}} */ -typedef struct { /* php_oci_define {{{ */ +/* {{{ php_oci_define */ +typedef struct { zval *zval; /* zval used in define */ text *name; /* placeholder's name */ ub4 name_len; /* placeholder's name length */ ub4 type; /* define type */ -} php_oci_define; /* }}} */ +} php_oci_define; +/* }}} */ -typedef struct { /* php_oci_statement {{{ */ +/* {{{ php_oci_statement */ +typedef struct { int id; int parent_stmtid; /* parent statement id */ + struct php_oci_statement *impres_child_stmt;/* child of current Implicit Result Set statement handle */ + ub4 impres_count; /* count of remaining Implicit Result children on parent statement handle */ php_oci_connection *connection; /* parent connection handle */ - sword errcode; /* last errcode*/ + sb4 errcode; /* last ORA- error number */ OCIError *err; /* private error handle */ OCIStmt *stmt; /* statement handle */ - char *last_query; /* last query issued. also used to determine if this is a statement or a refcursor received from Oracle */ + char *last_query; /* last query issued. also used to determine if this is a statement or a refcursor recieved from Oracle */ + char impres_flag; /* PHP_OCI_IMPRES_*_ */ long last_query_len; /* last query length */ HashTable *columns; /* hash containing all the result columns */ HashTable *binds; /* binds hash */ @@ -201,9 +230,12 @@ typedef struct { /* php_oci_statement {{{ */ unsigned has_data:1; /* statement has more data flag */ unsigned has_descr:1; /* statement has at least one descriptor or cursor column */ ub2 stmttype; /* statement type */ -} php_oci_statement; /* }}} */ + ub4 prefetch_count; /* current prefetch count */ +} php_oci_statement; +/* }}} */ -typedef struct { /* php_oci_bind {{{ */ +/* {{{ php_oci_bind */ +typedef struct { OCIBind *bind; /* bind handle */ zval *zval; /* value */ dvoid *descriptor; /* used for binding of LOBS etc */ @@ -222,9 +254,11 @@ typedef struct { /* php_oci_bind {{{ */ sb2 indicator; /* -1 means NULL */ ub2 retcode; ub4 dummy_len; /* a dummy var to store alenpp value in bind OUT callback */ -} php_oci_bind; /* }}} */ +} php_oci_bind; +/* }}} */ -typedef struct { /* php_oci_out_column {{{ */ +/* {{{ php_oci_out_column */ +typedef struct { php_oci_statement *statement; /* statement handle. used when fetching REFCURSORS */ php_oci_statement *nested_statement; /* statement handle. used when fetching REFCURSORS */ OCIDefine *oci_define; /* define handle */ @@ -249,28 +283,23 @@ typedef struct { /* php_oci_out_column {{{ */ sb2 precision; /* column precision */ ub1 charset_form; /* charset form, required for NCLOBs */ ub2 charset_id; /* charset ID */ -} php_oci_out_column; /* }}} */ +} php_oci_out_column; +/* }}} */ /* {{{ macros */ -#define PHP_OCI_CALL(func, params) \ - do { \ - if (OCI_G(debug_mode)) { \ - php_printf ("OCI8 DEBUG: " #func " at (%s:%d) \n", __FILE__, __LINE__); \ - } \ - OCI_G(in_call) = 1; \ - func params; \ - OCI_G(in_call) = 0; \ +#define PHP_OCI_CALL(func, params) \ + do { \ + OCI_G(in_call) = 1; \ + func params; \ + OCI_G(in_call) = 0; \ } while (0) -#define PHP_OCI_CALL_RETURN(__retval, func, params) \ - do { \ - if (OCI_G(debug_mode)) { \ - php_printf ("OCI8 DEBUG: " #func " at (%s:%d) \n", __FILE__, __LINE__); \ - } \ - OCI_G(in_call) = 1; \ - __retval = func params; \ - OCI_G(in_call) = 0; \ +#define PHP_OCI_CALL_RETURN(__retval, func, params) \ + do { \ + OCI_G(in_call) = 1; \ + __retval = func params; \ + OCI_G(in_call) = 0; \ } while (0) /* Check for errors that indicate the connection to the DB is no @@ -284,6 +313,7 @@ typedef struct { /* php_oci_out_column {{{ */ */ #define PHP_OCI_HANDLE_ERROR(connection, errcode) \ do { \ + ub4 serverStatus = OCI_SERVER_NORMAL; \ switch (errcode) { \ case 1013: \ zend_bailout(); \ @@ -313,7 +343,6 @@ typedef struct { /* php_oci_out_column {{{ */ break; \ default: \ { \ - ub4 serverStatus = OCI_SERVER_NORMAL; \ PHP_OCI_CALL(OCIAttrGet, ((dvoid *)(connection)->server, OCI_HTYPE_SERVER, (dvoid *)&serverStatus, \ (ub4 *)0, OCI_ATTR_SERVER_STATUS, (connection)->err)); \ if (serverStatus != OCI_SERVER_NORMAL) { \ @@ -322,6 +351,7 @@ typedef struct { /* php_oci_out_column {{{ */ } \ break; \ } \ + php_oci_dtrace_check_connection(connection, errcode, serverStatus); \ } while (0) #define PHP_OCI_REGISTER_RESOURCE(resource, le_resource) \ @@ -365,117 +395,106 @@ typedef struct { /* php_oci_out_column {{{ */ /* PROTOS */ -/* main prototypes {{{ */ - -void php_oci_column_hash_dtor (void *data); -void php_oci_define_hash_dtor (void *data); -void php_oci_bind_hash_dtor (void *data); -void php_oci_descriptor_flush_hash_dtor (void *data); +/* {{{ main prototypes */ +void php_oci_column_hash_dtor(void *data); +void php_oci_define_hash_dtor(void *data); +void php_oci_bind_hash_dtor(void *data); +void php_oci_descriptor_flush_hash_dtor(void *data); void php_oci_connection_descriptors_free(php_oci_connection *connection TSRMLS_DC); - -sb4 php_oci_error (OCIError *, sword TSRMLS_DC); -sb4 php_oci_fetch_errmsg(OCIError *, text ** TSRMLS_DC); -int php_oci_fetch_sqltext_offset(php_oci_statement *, text **, ub2 * TSRMLS_DC); - -void php_oci_do_connect (INTERNAL_FUNCTION_PARAMETERS, int , int); +sb4 php_oci_error(OCIError *err_p, sword status TSRMLS_DC); +sb4 php_oci_fetch_errmsg(OCIError *error_handle, text **error_buf TSRMLS_DC); +int php_oci_fetch_sqltext_offset(php_oci_statement *statement, text **sqltext, ub2 *error_offset TSRMLS_DC); +void php_oci_do_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent, int exclusive); php_oci_connection *php_oci_do_connect_ex(char *username, int username_len, char *password, int password_len, char *new_password, int new_password_len, char *dbname, int dbname_len, char *charset, long session_mode, int persistent, int exclusive TSRMLS_DC); - -int php_oci_connection_rollback(php_oci_connection * TSRMLS_DC); -int php_oci_connection_commit(php_oci_connection * TSRMLS_DC); +int php_oci_connection_rollback(php_oci_connection *connection TSRMLS_DC); +int php_oci_connection_commit(php_oci_connection *connection TSRMLS_DC); int php_oci_connection_release(php_oci_connection *connection TSRMLS_DC); - -int php_oci_password_change(php_oci_connection *, char *, int, char *, int, char *, int TSRMLS_DC); -void php_oci_client_get_version(char ** TSRMLS_DC); -int php_oci_server_get_version(php_oci_connection *, char ** TSRMLS_DC); - -void php_oci_fetch_row(INTERNAL_FUNCTION_PARAMETERS, int, int); -int php_oci_column_to_zval(php_oci_out_column *, zval *, int TSRMLS_DC); +int php_oci_password_change(php_oci_connection *connection, char *user, int user_len, char *pass_old, int pass_old_len, char *pass_new, int pass_new_len TSRMLS_DC); +void php_oci_client_get_version(char **version TSRMLS_DC); +int php_oci_server_get_version(php_oci_connection *connection, char **version TSRMLS_DC); +void php_oci_fetch_row(INTERNAL_FUNCTION_PARAMETERS, int mode, int expected_args); +int php_oci_column_to_zval(php_oci_out_column *column, zval *value, int mode TSRMLS_DC); +void php_oci_dtrace_check_connection(php_oci_connection *connection, sb4 errcode, ub4 serverStatus); /* }}} */ -/* lob related prototypes {{{ */ - -php_oci_descriptor * php_oci_lob_create (php_oci_connection *, long TSRMLS_DC); -int php_oci_lob_get_length (php_oci_descriptor *, ub4 * TSRMLS_DC); -int php_oci_lob_read (php_oci_descriptor *, long, long, char **, ub4 * TSRMLS_DC); -int php_oci_lob_write (php_oci_descriptor *, ub4, char *, int, ub4 * TSRMLS_DC); -int php_oci_lob_flush (php_oci_descriptor *, long TSRMLS_DC); -int php_oci_lob_set_buffering (php_oci_descriptor *, int TSRMLS_DC); -int php_oci_lob_get_buffering (php_oci_descriptor *); -int php_oci_lob_copy (php_oci_descriptor *, php_oci_descriptor *, long TSRMLS_DC); -int php_oci_lob_close (php_oci_descriptor * TSRMLS_DC); -int php_oci_temp_lob_close (php_oci_descriptor * TSRMLS_DC); -int php_oci_lob_write_tmp (php_oci_descriptor *, long, char *, int TSRMLS_DC); -void php_oci_lob_free(php_oci_descriptor * TSRMLS_DC); -int php_oci_lob_import(php_oci_descriptor *descriptor, char * TSRMLS_DC); -int php_oci_lob_append (php_oci_descriptor *, php_oci_descriptor * TSRMLS_DC); -int php_oci_lob_truncate (php_oci_descriptor *, long TSRMLS_DC); -int php_oci_lob_erase (php_oci_descriptor *, long, ub4, ub4 * TSRMLS_DC); -int php_oci_lob_is_equal (php_oci_descriptor *, php_oci_descriptor *, boolean * TSRMLS_DC); -#if defined(HAVE_OCI_LOB_READ2) -sb4 php_oci_lob_callback (dvoid *ctxp, CONST dvoid *bufxp, oraub8 len, ub1 piece, dvoid **changed_bufpp, oraub8 *changed_lenp); -#else -sb4 php_oci_lob_callback (dvoid *ctxp, CONST dvoid *bufxp, ub4 len, ub1 piece); -#endif +/* {{{ lob related prototypes */ + +php_oci_descriptor *php_oci_lob_create(php_oci_connection *connection, long type TSRMLS_DC); +int php_oci_lob_get_length(php_oci_descriptor *descriptor, ub4 *length TSRMLS_DC); +int php_oci_lob_read(php_oci_descriptor *descriptor, long read_length, long inital_offset, char **data, ub4 *data_len TSRMLS_DC); +int php_oci_lob_write(php_oci_descriptor *descriptor, ub4 offset, char *data, int data_len, ub4 *bytes_written TSRMLS_DC); +int php_oci_lob_flush(php_oci_descriptor *descriptor, long flush_flag TSRMLS_DC); +int php_oci_lob_set_buffering(php_oci_descriptor *descriptor, int on_off TSRMLS_DC); +int php_oci_lob_get_buffering(php_oci_descriptor *descriptor); +int php_oci_lob_copy(php_oci_descriptor *descriptor, php_oci_descriptor *descriptor_from, long length TSRMLS_DC); +int php_oci_lob_close(php_oci_descriptor *descriptor TSRMLS_DC); +int php_oci_temp_lob_close(php_oci_descriptor *descriptor TSRMLS_DC); +int php_oci_lob_write_tmp(php_oci_descriptor *descriptor, long type, char *data, int data_len TSRMLS_DC); +void php_oci_lob_free(php_oci_descriptor *descriptor TSRMLS_DC); +int php_oci_lob_import(php_oci_descriptor *descriptor, char *filename TSRMLS_DC); +int php_oci_lob_append(php_oci_descriptor *descriptor_dest, php_oci_descriptor *descriptor_from TSRMLS_DC); +int php_oci_lob_truncate(php_oci_descriptor *descriptor, long new_lob_length TSRMLS_DC); +int php_oci_lob_erase(php_oci_descriptor *descriptor, long offset, ub4 length, ub4 *bytes_erased TSRMLS_DC); +int php_oci_lob_is_equal(php_oci_descriptor *descriptor_first, php_oci_descriptor *descriptor_second, boolean *result TSRMLS_DC); +sb4 php_oci_lob_callback(dvoid *ctxp, CONST dvoid *bufxp, oraub8 len, ub1 piece, dvoid **changed_bufpp, oraub8 *changed_lenp); /* }}} */ -/* collection related prototypes {{{ */ - -php_oci_collection * php_oci_collection_create(php_oci_connection *, char *, int, char *, int TSRMLS_DC); -int php_oci_collection_size(php_oci_collection *, sb4 * TSRMLS_DC); -int php_oci_collection_max(php_oci_collection *, long * TSRMLS_DC); -int php_oci_collection_trim(php_oci_collection *, long TSRMLS_DC); -int php_oci_collection_append(php_oci_collection *, char *, int TSRMLS_DC); -int php_oci_collection_element_get(php_oci_collection *, long, zval** TSRMLS_DC); -int php_oci_collection_element_set(php_oci_collection *, long, char *, int TSRMLS_DC); -int php_oci_collection_element_set_null(php_oci_collection *, long TSRMLS_DC); -int php_oci_collection_element_set_date(php_oci_collection *, long, char *, int TSRMLS_DC); -int php_oci_collection_element_set_number(php_oci_collection *, long, char *, int TSRMLS_DC); -int php_oci_collection_element_set_string(php_oci_collection *, long, char *, int TSRMLS_DC); -int php_oci_collection_assign(php_oci_collection *, php_oci_collection * TSRMLS_DC); -void php_oci_collection_close(php_oci_collection * TSRMLS_DC); -int php_oci_collection_append_null(php_oci_collection * TSRMLS_DC); -int php_oci_collection_append_date(php_oci_collection *, char *, int TSRMLS_DC); -int php_oci_collection_append_number(php_oci_collection *, char *, int TSRMLS_DC); -int php_oci_collection_append_string(php_oci_collection *, char *, int TSRMLS_DC); +/* {{{ collection related prototypes */ + +php_oci_collection *php_oci_collection_create(php_oci_connection *connection, char *tdo, int tdo_len, char *schema, int schema_len TSRMLS_DC); +int php_oci_collection_size(php_oci_collection *collection, sb4 *size TSRMLS_DC); +int php_oci_collection_max(php_oci_collection *collection, long *max TSRMLS_DC); +int php_oci_collection_trim(php_oci_collection *collection, long trim_size TSRMLS_DC); +int php_oci_collection_append(php_oci_collection *collection, char *element, int element_len TSRMLS_DC); +int php_oci_collection_element_get(php_oci_collection *collection, long index, zval **result_element TSRMLS_DC); +int php_oci_collection_element_set(php_oci_collection *collection, long index, char *value, int value_len TSRMLS_DC); +int php_oci_collection_element_set_null(php_oci_collection *collection, long index TSRMLS_DC); +int php_oci_collection_element_set_date(php_oci_collection *collection, long index, char *date, int date_len TSRMLS_DC); +int php_oci_collection_element_set_number(php_oci_collection *collection, long index, char *number, int number_len TSRMLS_DC); +int php_oci_collection_element_set_string(php_oci_collection *collection, long index, char *element, int element_len TSRMLS_DC); +int php_oci_collection_assign(php_oci_collection *collection_dest, php_oci_collection *collection_from TSRMLS_DC); +void php_oci_collection_close(php_oci_collection *collection TSRMLS_DC); +int php_oci_collection_append_null(php_oci_collection *collection TSRMLS_DC); +int php_oci_collection_append_date(php_oci_collection *collection, char *date, int date_len TSRMLS_DC); +int php_oci_collection_append_number(php_oci_collection *collection, char *number, int number_len TSRMLS_DC); +int php_oci_collection_append_string(php_oci_collection *collection, char *element, int element_len TSRMLS_DC); /* }}} */ -/* statement related prototypes {{{ */ +/* {{{ statement related prototypes */ -php_oci_statement * php_oci_statement_create (php_oci_connection *, char *, int TSRMLS_DC); -int php_oci_statement_set_prefetch (php_oci_statement *, long TSRMLS_DC); -int php_oci_statement_fetch (php_oci_statement *, ub4 TSRMLS_DC); -php_oci_out_column * php_oci_statement_get_column (php_oci_statement *, long, char *, int TSRMLS_DC); -int php_oci_statement_execute (php_oci_statement *, ub4 TSRMLS_DC); -int php_oci_statement_cancel (php_oci_statement * TSRMLS_DC); -void php_oci_statement_free (php_oci_statement * TSRMLS_DC); +php_oci_statement *php_oci_statement_create(php_oci_connection *connection, char *query, int query_len TSRMLS_DC); +php_oci_statement *php_oci_get_implicit_resultset(php_oci_statement *statement TSRMLS_DC); +int php_oci_statement_set_prefetch(php_oci_statement *statement, ub4 prefetch TSRMLS_DC); +int php_oci_statement_fetch(php_oci_statement *statement, ub4 nrows TSRMLS_DC); +php_oci_out_column *php_oci_statement_get_column(php_oci_statement *statement, long column_index, char *column_name, int column_name_len TSRMLS_DC); +int php_oci_statement_execute(php_oci_statement *statement, ub4 mode TSRMLS_DC); +int php_oci_statement_cancel(php_oci_statement *statement TSRMLS_DC); +void php_oci_statement_free(php_oci_statement *statement TSRMLS_DC); int php_oci_bind_pre_exec(void *data, void *result TSRMLS_DC); int php_oci_bind_post_exec(void *data TSRMLS_DC); -int php_oci_bind_by_name(php_oci_statement *, char *, int, zval*, long, ub2 TSRMLS_DC); -sb4 php_oci_bind_in_callback(dvoid *, OCIBind *, ub4, ub4, dvoid **, ub4 *, ub1 *, dvoid **); -sb4 php_oci_bind_out_callback(dvoid *, OCIBind *, ub4, ub4, dvoid **, ub4 **, ub1 *, dvoid **, ub2 **); +int php_oci_bind_by_name(php_oci_statement *statement, char *name, int name_len, zval *var, long maxlength, ub2 type TSRMLS_DC); +sb4 php_oci_bind_in_callback(dvoid *ictxp, OCIBind *bindp, ub4 iter, ub4 index, dvoid **bufpp, ub4 *alenp, ub1 *piecep, dvoid **indpp); +sb4 php_oci_bind_out_callback(dvoid *octxp, OCIBind *bindp, ub4 iter, ub4 index, dvoid **bufpp, ub4 **alenpp, ub1 *piecep, dvoid **indpp, ub2 **rcodepp); php_oci_out_column *php_oci_statement_get_column_helper(INTERNAL_FUNCTION_PARAMETERS, int need_data); int php_oci_cleanup_pre_fetch(void *data TSRMLS_DC); - -int php_oci_statement_get_type(php_oci_statement *, ub2 * TSRMLS_DC); -int php_oci_statement_get_numrows(php_oci_statement *, ub4 * TSRMLS_DC); -int php_oci_bind_array_by_name(php_oci_statement *statement, char *name, int name_len, zval* var, long max_table_length, long maxlength, long type TSRMLS_DC); -php_oci_bind *php_oci_bind_array_helper_number(zval* var, long max_table_length TSRMLS_DC); -php_oci_bind *php_oci_bind_array_helper_double(zval* var, long max_table_length TSRMLS_DC); -php_oci_bind *php_oci_bind_array_helper_string(zval* var, long max_table_length, long maxlength TSRMLS_DC); -php_oci_bind *php_oci_bind_array_helper_date(zval* var, long max_table_length, php_oci_connection *connection TSRMLS_DC); +int php_oci_statement_get_type(php_oci_statement *statement, ub2 *type TSRMLS_DC); +int php_oci_statement_get_numrows(php_oci_statement *statement, ub4 *numrows TSRMLS_DC); +int php_oci_bind_array_by_name(php_oci_statement *statement, char *name, int name_len, zval *var, long max_table_length, long maxlength, long type TSRMLS_DC); +php_oci_bind *php_oci_bind_array_helper_number(zval *var, long max_table_length TSRMLS_DC); +php_oci_bind *php_oci_bind_array_helper_double(zval *var, long max_table_length TSRMLS_DC); +php_oci_bind *php_oci_bind_array_helper_string(zval *var, long max_table_length, long maxlength TSRMLS_DC); +php_oci_bind *php_oci_bind_array_helper_date(zval *var, long max_table_length, php_oci_connection *connection TSRMLS_DC); /* }}} */ -ZEND_BEGIN_MODULE_GLOBALS(oci) /* {{{ */ - sword errcode; /* global last error code (used when connect fails, for example) */ +ZEND_BEGIN_MODULE_GLOBALS(oci) /* {{{ Module globals */ + sb4 errcode; /* global last ORA- error number. Used when connect fails, for example */ OCIError *err; /* global error handle */ - zend_bool debug_mode; /* debug mode flag */ - long max_persistent; /* maximum number of persistent connections per process */ long num_persistent; /* number of existing persistent connections */ long num_links; /* non-persistent + persistent connections */ diff --git a/ext/oci8/tests/bind_char_1.phpt b/ext/oci8/tests/bind_char_1.phpt index 91fa4b75b7..dc162ff943 100644 --- a/ext/oci8/tests/bind_char_1.phpt +++ b/ext/oci8/tests/bind_char_1.phpt @@ -5,13 +5,9 @@ SELECT oci_bind_by_name with SQLT_AFC aka CHAR if (!extension_loaded('oci8')) die ("skip no oci8 extension"); require(dirname(__FILE__)."/connect.inc"); // The bind buffer size edge cases seem to change each DB version. -if (preg_match('/Release 10\.2\./', oci_server_version($c), $matches) !== 1) { - if (preg_match('/Release 11\.2\.0\.2/', oci_server_version($c), $matches) !== 2) { - die("skip expected output only valid when using Oracle 10gR2 or 11.2.0.2 databases"); - } -} -if (preg_match('/^11\./', oci_client_version()) != 1) { - die("skip test expected to work only with Oracle 11g or greater version of client"); +preg_match('/.*Release ([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)*/', oci_server_version($c), $matches); +if (!(isset($matches[0]) && $matches[1] >= 12)) { + die("skip expected output only valid when using Oracle 12c database"); } ?> --ENV-- diff --git a/ext/oci8/tests/bind_char_1_11gR1.phpt b/ext/oci8/tests/bind_char_1_11gR1.phpt index a7feff9f6a..bdc29f766d 100644 --- a/ext/oci8/tests/bind_char_1_11gR1.phpt +++ b/ext/oci8/tests/bind_char_1_11gR1.phpt @@ -5,10 +5,9 @@ SELECT oci_bind_by_name with SQLT_AFC aka CHAR if (!extension_loaded('oci8')) die ("skip no oci8 extension"); require(dirname(__FILE__)."/connect.inc"); // The bind buffer size edge cases seem to change each DB version. -if (preg_match('/Release 11\.1\./', oci_server_version($c), $matches) !== 1) { - if (preg_match('/Release 11\.2\.0\.3/', oci_server_version($c), $matches) !== 1) { - die("skip expected output only valid when using Oracle 11gR1 or 11.2.0.3 databases"); - } +preg_match('/.*Release ([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)*/', oci_server_version($c), $matches); +if (!(isset($matches[0]) && $matches[1] < 12)) { + die("skip expected output only valid when using pre-Oracle 12c database"); } ?> --ENV-- diff --git a/ext/oci8/tests/bind_char_2.phpt b/ext/oci8/tests/bind_char_2.phpt index 43661a065d..9c61a858c8 100644 --- a/ext/oci8/tests/bind_char_2.phpt +++ b/ext/oci8/tests/bind_char_2.phpt @@ -5,13 +5,9 @@ SELECT oci_bind_by_name with SQLT_AFC aka CHAR and dates if (!extension_loaded('oci8')) die ("skip no oci8 extension"); require(dirname(__FILE__)."/connect.inc"); // The bind buffer size edge cases seem to change each DB version. -if (preg_match('/Release 10\.2\./', oci_server_version($c), $matches) !== 1) { - if (preg_match('/Release 11\.2\.0\.2/', oci_server_version($c), $matches) !== 2) { - die("skip expected output only valid when using Oracle 10gR2 or 11.2.0.2 databases"); - } -} -if (preg_match('/^11\./', oci_client_version()) != 1) { - die("skip test expected to work only with Oracle 11g or greater version of client"); +preg_match('/.*Release ([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)*/', oci_server_version($c), $matches); +if (!(isset($matches[0]) && $matches[1] >= 12)) { + die("skip expected output only valid when using Oracle 12c database"); } ?> --ENV-- diff --git a/ext/oci8/tests/bind_char_2_11gR1.phpt b/ext/oci8/tests/bind_char_2_11gR1.phpt index edb2a12ff0..06c37afc93 100644 --- a/ext/oci8/tests/bind_char_2_11gR1.phpt +++ b/ext/oci8/tests/bind_char_2_11gR1.phpt @@ -5,10 +5,9 @@ SELECT oci_bind_by_name with SQLT_AFC aka CHAR and dates if (!extension_loaded('oci8')) die ("skip no oci8 extension"); require(dirname(__FILE__)."/connect.inc"); // The bind buffer size edge cases seem to change each DB version. -if (preg_match('/Release 11\.1\./', oci_server_version($c), $matches) !== 1) { - if (preg_match('/Release 11\.2\.0\.3/', oci_server_version($c), $matches) !== 1) { - die("skip expected output only valid when using Oracle 11gR1 or 11.2.0.3 databases"); - } +preg_match('/.*Release ([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)*/', oci_server_version($c), $matches); +if (!(isset($matches[0]) && $matches[1] < 12)) { + die("skip expected output only valid when using pre-Oracle 12c database"); } ?> --ENV-- diff --git a/ext/oci8/tests/bind_char_3.phpt b/ext/oci8/tests/bind_char_3.phpt index 25115836df..177676e25c 100644 --- a/ext/oci8/tests/bind_char_3.phpt +++ b/ext/oci8/tests/bind_char_3.phpt @@ -5,13 +5,9 @@ PL/SQL oci_bind_by_name with SQLT_AFC aka CHAR to CHAR parameter if (!extension_loaded('oci8')) die ("skip no oci8 extension"); require(dirname(__FILE__)."/connect.inc"); // The bind buffer size edge cases seem to change each DB version. -if (preg_match('/Release 10\.2\./', oci_server_version($c), $matches) !== 1) { - if (preg_match('/Release 11\.2\.0\.2/', oci_server_version($c), $matches) !== 2) { - die("skip expected output only valid when using Oracle 10gR2 or 11.2.0.2 databases"); - } -} -if (preg_match('/^11\./', oci_client_version()) != 1) { - die("skip test expected to work only with Oracle 11g or greater version of client"); +preg_match('/.*Release ([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)*/', oci_server_version($c), $matches); +if (!(isset($matches[0]) && $matches[1] >= 12)) { + die("skip expected output only valid when using Oracle 12c database"); } ?> --ENV-- diff --git a/ext/oci8/tests/bind_char_3_11gR1.phpt b/ext/oci8/tests/bind_char_3_11gR1.phpt index fea77754d1..c3ec999d0f 100644 --- a/ext/oci8/tests/bind_char_3_11gR1.phpt +++ b/ext/oci8/tests/bind_char_3_11gR1.phpt @@ -5,10 +5,9 @@ PL/SQL oci_bind_by_name with SQLT_AFC aka CHAR to CHAR parameter if (!extension_loaded('oci8')) die ("skip no oci8 extension"); require(dirname(__FILE__)."/connect.inc"); // The bind buffer size edge cases seem to change each DB version. -if (preg_match('/Release 11\.1\./', oci_server_version($c), $matches) !== 1) { - if (preg_match('/Release 11\.2\.0\.3/', oci_server_version($c), $matches) !== 1) { - die("skip expected output only valid when using Oracle 11gR1 or 11.2.0.3 databases"); - } +preg_match('/.*Release ([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)*/', oci_server_version($c), $matches); +if (!(isset($matches[0]) && $matches[1] < 12)) { + die("skip expected output only valid when using pre-Oracle 12c database"); } ?> --ENV-- diff --git a/ext/oci8/tests/bind_char_4.phpt b/ext/oci8/tests/bind_char_4.phpt index 36765f8137..b4d3e089b1 100644 --- a/ext/oci8/tests/bind_char_4.phpt +++ b/ext/oci8/tests/bind_char_4.phpt @@ -5,13 +5,9 @@ PL/SQL oci_bind_by_name with SQLT_AFC aka CHAR to VARCHAR2 parameter if (!extension_loaded('oci8')) die ("skip no oci8 extension"); require(dirname(__FILE__)."/connect.inc"); // The bind buffer size edge cases seem to change each DB version. -if (preg_match('/Release 10\.2\./', oci_server_version($c), $matches) !== 1) { - if (preg_match('/Release 11\.2\.0\.2/', oci_server_version($c), $matches) !== 2) { - die("skip expected output only valid when using Oracle 10gR2 or 11.2.0.2 databases"); - } -} -if (preg_match('/^11\./', oci_client_version()) != 1) { - die("skip test expected to work only with Oracle 11g or greater version of client"); +preg_match('/.*Release ([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)*/', oci_server_version($c), $matches); +if (!(isset($matches[0]) && $matches[1] >= 12)) { + die("skip expected output only valid when using Oracle 12c database"); } ?> --ENV-- diff --git a/ext/oci8/tests/bind_char_4_11gR1.phpt b/ext/oci8/tests/bind_char_4_11gR1.phpt index 2bc2f14246..ccad2cb789 100644 --- a/ext/oci8/tests/bind_char_4_11gR1.phpt +++ b/ext/oci8/tests/bind_char_4_11gR1.phpt @@ -5,10 +5,9 @@ PL/SQL oci_bind_by_name with SQLT_AFC aka CHAR to VARCHAR2 parameter if (!extension_loaded('oci8')) die ("skip no oci8 extension"); require(dirname(__FILE__)."/connect.inc"); // The bind buffer size edge cases seem to change each DB version. -if (preg_match('/Release 11\.1\./', oci_server_version($c), $matches) !== 1) { - if (preg_match('/Release 11\.2\.0\.3/', oci_server_version($c), $matches) !== 1) { - die("skip expected output only valid when using Oracle 11gR1 or 11.2.0.3 databases"); - } +preg_match('/.*Release ([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)*/', oci_server_version($c), $matches); +if (!(isset($matches[0]) && $matches[1] < 12)) { + die("skip expected output only valid when using pre-Oracle 12c database"); } ?> --ENV-- diff --git a/ext/oci8/tests/bind_misccoltypes.phpt b/ext/oci8/tests/bind_misccoltypes.phpt index 0da8c8bf88..9e55b3b1ff 100644 --- a/ext/oci8/tests/bind_misccoltypes.phpt +++ b/ext/oci8/tests/bind_misccoltypes.phpt @@ -4,9 +4,6 @@ Bind miscellaneous column types using default types <?php $target_dbs = array('oracledb' => true, 'timesten' => false); // test runs on these DBs require(dirname(__FILE__).'/skipif.inc'); -if (preg_match('/^1[012]\./', oci_client_version()) != 1) { - die("skip test expected to work only with Oracle 10g or greater version of client"); -} ?> --FILE-- <?php diff --git a/ext/oci8/tests/bind_number.phpt b/ext/oci8/tests/bind_number.phpt index 6412b5f82e..4ae085b4d1 100644 --- a/ext/oci8/tests/bind_number.phpt +++ b/ext/oci8/tests/bind_number.phpt @@ -3,9 +3,6 @@ Bind with NUMBER column variants --SKIPIF-- <?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); -if (preg_match('/^1[012]\./', oci_client_version()) != 1) { - die("skip test expected to work only with Oracle 10g or greater version of client"); -} ?> --INI-- precision = 14 diff --git a/ext/oci8/tests/bind_sqltnum.phpt b/ext/oci8/tests/bind_sqltnum.phpt index d3828b73ee..93fc4809ec 100644 --- a/ext/oci8/tests/bind_sqltnum.phpt +++ b/ext/oci8/tests/bind_sqltnum.phpt @@ -3,9 +3,6 @@ Bind with SQLT_NUM --SKIPIF-- <?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); -if (preg_match('/^1[012]\./', oci_client_version()) != 1) { - die("skip test expected to work only with Oracle 10g or greater version of client"); -} ?> --FILE-- <?php diff --git a/ext/oci8/tests/bind_unsupported_2.phpt b/ext/oci8/tests/bind_unsupported_2.phpt index d3e5375df6..b4e2c9b43d 100644 --- a/ext/oci8/tests/bind_unsupported_2.phpt +++ b/ext/oci8/tests/bind_unsupported_2.phpt @@ -3,9 +3,6 @@ Bind with various unsupported 10g+ bind types --SKIPIF-- <?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); -if (preg_match('/^1[01]\./', oci_client_version()) !== 1) { - die ("skip expected output only valid for Oracle 10g+ clients"); -} ?> --FILE-- <?php diff --git a/ext/oci8/tests/bug27303_1.phpt b/ext/oci8/tests/bug27303_1.phpt index 40ab4ebed2..0b9d2b99e0 100644 --- a/ext/oci8/tests/bug27303_1.phpt +++ b/ext/oci8/tests/bug27303_1.phpt @@ -5,13 +5,9 @@ Bug #27303 (OCIBindByName binds numeric PHP values as characters) if (!extension_loaded('oci8')) die ("skip no oci8 extension"); require(dirname(__FILE__)."/connect.inc"); // The bind buffer size edge cases seem to change each DB version. -if (preg_match('/Release 10\.2\.0\.2/', oci_server_version($c), $matches) !== 1 && - preg_match('/Release 11\.2\.0\.2/', oci_server_version($c), $matches) !== 1) { - die("skip expected output only valid when using Oracle 10.2.0.2 or 11.2.0.2 databases"); - // Other point releases may also work -} -if (preg_match('/^11\./', oci_client_version()) != 1) { - die("skip test expected to work only with Oracle 11g or greater version of client"); +preg_match('/.*Release ([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)*/', oci_server_version($c), $matches); +if (!(isset($matches[0]) && $matches[1] >= 12)) { + die("skip expected output only valid when using Oracle 12c database"); } ?> --ENV-- diff --git a/ext/oci8/tests/bug27303_1_11gR1.phpt b/ext/oci8/tests/bug27303_1_11gR1.phpt index 6de9b99378..d2018783bc 100644 --- a/ext/oci8/tests/bug27303_1_11gR1.phpt +++ b/ext/oci8/tests/bug27303_1_11gR1.phpt @@ -5,12 +5,9 @@ Bug #27303 (OCIBindByName binds numeric PHP values as characters) if (!extension_loaded('oci8')) die ("skip no oci8 extension"); require(dirname(__FILE__)."/connect.inc"); // The bind buffer size edge cases seem to change each DB version. -if (preg_match('/Release 10\.2\.0\.3/', oci_server_version($c), $matches) !== 1) { - if (preg_match('/Release 11\.1\.0\.6/', oci_server_version($c), $matches) !== 1) { - if (preg_match('/Release 11\.2\.0\.3/', oci_server_version($c), $matches) !== 1) { - die("skip expected output only valid when using specific Oracle database versions"); - } - } +preg_match('/.*Release ([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)*/', oci_server_version($c), $matches); +if (!(isset($matches[0]) && $matches[1] < 12)) { + die("skip expected output only valid when using pre-Oracle 12c database"); } ?> --FILE-- diff --git a/ext/oci8/tests/bug27303_2.phpt b/ext/oci8/tests/bug27303_2.phpt index 1fb2b31682..ee2f7b52aa 100644 --- a/ext/oci8/tests/bug27303_2.phpt +++ b/ext/oci8/tests/bug27303_2.phpt @@ -5,13 +5,9 @@ Bug #27303 (OCIBindByName binds numeric PHP values as characters) if (!extension_loaded('oci8')) die ("skip no oci8 extension"); require(dirname(__FILE__)."/connect.inc"); // The bind buffer size edge cases seem to change each DB version. -if (preg_match('/Release 10\.2\.0\.2/', oci_server_version($c), $matches) !== 1 && - preg_match('/Release 11\.2\.0\.2/', oci_server_version($c), $matches) !== 1) { - die("skip expected output only valid when using Oracle 10.2.0.2 or 11.2.0.2 databases"); - // Other point releases may also work -} -if (preg_match('/^11\./', oci_client_version()) != 1) { - die("skip test expected to work only with Oracle 11g or greater version of client"); +preg_match('/.*Release ([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)*/', oci_server_version($c), $matches); +if (!(isset($matches[0]) && $matches[1] >= 12)) { + die("skip expected output only valid when using Oracle 12c database"); } ?> --ENV-- diff --git a/ext/oci8/tests/bug27303_2_11gR1.phpt b/ext/oci8/tests/bug27303_2_11gR1.phpt index 1e3e3105ad..06133e0115 100644 --- a/ext/oci8/tests/bug27303_2_11gR1.phpt +++ b/ext/oci8/tests/bug27303_2_11gR1.phpt @@ -5,12 +5,9 @@ Bug #27303 (OCIBindByName binds numeric PHP values as characters) if (!extension_loaded('oci8')) die ("skip no oci8 extension"); require(dirname(__FILE__)."/connect.inc"); // The bind buffer size edge cases seem to change each DB version. -if (preg_match('/Release 10\.2\.0\.3/', oci_server_version($c), $matches) !== 1) { - if (preg_match('/Release 11\.1\.0\.6/', oci_server_version($c), $matches) !== 1) { - if (preg_match('/Release 11\.2\.0\.3/', oci_server_version($c), $matches) !== 1) { - die("skip expected output only valid when using specific Oracle database versions"); - } - } +preg_match('/.*Release ([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)*/', oci_server_version($c), $matches); +if (!(isset($matches[0]) && $matches[1] < 12)) { + die("skip expected output only valid when using pre-Oracle 12c database"); } ?> --FILE-- diff --git a/ext/oci8/tests/bug27303_4.phpt b/ext/oci8/tests/bug27303_4.phpt index 3137db8659..ed9d5a1fe6 100644 --- a/ext/oci8/tests/bug27303_4.phpt +++ b/ext/oci8/tests/bug27303_4.phpt @@ -5,13 +5,9 @@ Bug #27303 (OCIBindByName binds numeric PHP values as characters) if (!extension_loaded('oci8')) die ("skip no oci8 extension"); require(dirname(__FILE__)."/connect.inc"); // The bind buffer size edge cases seem to change each DB version. -if (preg_match('/Release 10\.2\.0\.2/', oci_server_version($c), $matches) !== 1 && - preg_match('/Release 11\.2\.0\.2/', oci_server_version($c), $matches) !== 1) { - die("skip expected output only valid when using Oracle 10.2.0.2 or 11.2.0.2 databases"); - // Other point releases may also work -} -if (preg_match('/^11\./', oci_client_version()) != 1) { - die("skip test expected to work only with Oracle 11g or greater version of client"); +preg_match('/.*Release ([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)*/', oci_server_version($c), $matches); +if (!(isset($matches[0]) && $matches[1] >= 12)) { + die("skip expected output only valid when using Oracle 12c database"); } ?> --ENV-- diff --git a/ext/oci8/tests/bug27303_4_11gR1.phpt b/ext/oci8/tests/bug27303_4_11gR1.phpt index f9bc2da8a2..550d89fdcc 100644 --- a/ext/oci8/tests/bug27303_4_11gR1.phpt +++ b/ext/oci8/tests/bug27303_4_11gR1.phpt @@ -5,12 +5,9 @@ Bug #27303 (OCIBindByName binds numeric PHP values as characters) if (!extension_loaded('oci8')) die ("skip no oci8 extension"); require(dirname(__FILE__)."/connect.inc"); // The bind buffer size edge cases seem to change each DB version. -if (preg_match('/Release 10\.2\.0\.3/', oci_server_version($c), $matches) !== 1) { - if (preg_match('/Release 11\.1\.0\.6/', oci_server_version($c), $matches) !== 1) { - if (preg_match('/Release 11\.2\.0\.3/', oci_server_version($c), $matches) !== 1) { - die("skip expected output only valid when using specific Oracle database versions"); - } - } +preg_match('/.*Release ([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)*/', oci_server_version($c), $matches); +if (!(isset($matches[0]) && $matches[1] < 12)) { + die("skip expected output only valid when using pre-Oracle 12c database"); } ?> --FILE-- diff --git a/ext/oci8/tests/bug36403.phpt b/ext/oci8/tests/bug36403.phpt index 53dae694ec..122b06bbfa 100644 --- a/ext/oci8/tests/bug36403.phpt +++ b/ext/oci8/tests/bug36403.phpt @@ -3,9 +3,6 @@ Bug #36403 (oci_execute no longer supports OCI_DESCRIBE_ONLY) --SKIPIF-- <?php if (!extension_loaded('oci8')) die ("skip no oci8 extension"); -if (preg_match('/^1[01]\./', oci_client_version()) != 1) { - die("skip expected output only valid with Oracle 10g or greater version of client"); -} ?> --FILE-- <?php diff --git a/ext/oci8/tests/bug43497.phpt b/ext/oci8/tests/bug43497.phpt index 8c57fabeef..e3e68aac33 100644 --- a/ext/oci8/tests/bug43497.phpt +++ b/ext/oci8/tests/bug43497.phpt @@ -5,9 +5,6 @@ Bug #43497 (OCI8 XML/getClobVal aka temporary LOBs leak UGA memory) $target_dbs = array('oracledb' => true, 'timesten' => false); // test runs on these DBs require(dirname(__FILE__).'/skipif.inc'); if (getenv('SKIP_SLOW_TESTS')) die('skip slow tests excluded by request'); -if (preg_match('/^1[01]\./', oci_client_version()) != 1) { - die("skip expected output only valid with Oracle 10g or greater version of client"); -} ?> --FILE-- <?php diff --git a/ext/oci8/tests/bug43497_92.phpt b/ext/oci8/tests/bug43497_92.phpt deleted file mode 100644 index cc2a96318c..0000000000 --- a/ext/oci8/tests/bug43497_92.phpt +++ /dev/null @@ -1,305 +0,0 @@ ---TEST-- -Bug #43497 (OCI8 XML/getClobVal aka temporary LOBs leak UGA memory) ---SKIPIF-- -<?php -$target_dbs = array('oracledb' => true, 'timesten' => false); // test runs on these DBs -require(dirname(__FILE__).'/skipif.inc'); -if (getenv('SKIP_SLOW_TESTS')) die('skip slow tests excluded by request'); -ob_start(); -phpinfo(INFO_MODULES); -$phpinfo = ob_get_clean(); -$iv = preg_match('/Oracle .*Version => (9\.2)/', $phpinfo); -if ($iv != 1) { - die ("skip tests a feature that works only with Oracle 9iR2 client"); -} -?> ---FILE-- -<?php - -require dirname(__FILE__).'/connect.inc'; - -function sessionid($c) // determines and returns current session ID -{ - $query = "select sid from v\$session where audsid = userenv('sessionid')"; - - $stmt = oci_parse($c, $query); - - if (oci_execute($stmt, OCI_DEFAULT)) { - $row = oci_fetch($stmt); - return oci_result($stmt, 1); - } - - return null; -} - - -function templobs($c, $sid) // returns number of temporary LOBs -{ - $query = "select abstract_lobs from v\$temporary_lobs where sid = " . $sid; - - $stmt = oci_parse($c, $query); - - if (oci_execute($stmt, OCI_DEFAULT)) { - $row = oci_fetch($stmt); - $val = oci_result($stmt, 1); - oci_free_statement($stmt); - return $val; - } - return null; -} - - -// Read all XML data using explicit LOB locator -function readxmltab_ex($c) -{ - $stmt = oci_parse($c, "select extract(xml, '/').getclobval() from bug43497_tab"); - - $cntchk = 0; - if (oci_execute($stmt)) { - while ($result = oci_fetch_array($stmt, OCI_NUM)) { - $result[0]->free(); // cleanup properly - ++$cntchk; - } - } - echo "Loop count check = $cntchk\n"; -} - -// Read all XML data using explicit LOB locator but without freeing the temp lobs -function readxmltab_ex_nofree($c) -{ - $stmt = oci_parse($c, "select extract(xml, '/').getclobval() from bug43497_tab"); - - $cntchk = 0; - if (oci_execute($stmt)) { - while ($result = oci_fetch_array($stmt, OCI_NUM)) { - ++$cntchk; - } - } - echo "Loop count check = $cntchk\n"; -} - -// Read all XML data using implicit LOB locator -function readxmltab_im($c) -{ - $stmt = oci_parse($c, "select extract(xml, '/').getclobval() from bug43497_tab"); - - $cntchk = 0; - if (oci_execute($stmt)) { - while ($result = oci_fetch_array($stmt, OCI_NUM+OCI_RETURN_LOBS)) { - ++$cntchk; - } - } - echo "Loop count check = $cntchk\n"; -} - -function createxmltab($c) // create table w/ field of XML type -{ - @dropxmltab($c); - $stmt = oci_parse($c, "create table bug43497_tab (id number primary key, xml xmltype)"); - oci_execute($stmt); -} - -function dropxmltab($c) // delete table -{ - $stmt = oci_parse($c, "drop table bug43497_tab"); - oci_execute($stmt); -} - - -function fillxmltab($c) -{ - for ($id = 1; $id <= 100; $id++) { - - // create an XML element string with random data - $s = "<data>"; - for ($j = 0; $j < 128; $j++) { - $s .= rand(); - } - $s .= "</data>\n"; - for ($j = 0; $j < 4; $j++) { - $s .= $s; - } - $data = "<?xml version=\"1.0\"?><records>" . $s . "</records>"; - - // insert XML data into database - - $stmt = oci_parse($c, "insert into bug43497_tab(id, xml) values (:id, sys.xmltype.createxml(:xml))"); - oci_bind_by_name($stmt, ":id", $id); - $clob = oci_new_descriptor($c, OCI_D_LOB); - oci_bind_by_name($stmt, ":xml", $clob, -1, OCI_B_CLOB); - $clob->writetemporary($data); - oci_execute($stmt); - - $clob->close(); - $clob->free(); - } -} - - -// Initialize - -createxmltab($c); -fillxmltab($c); - -// Run Test - -$sid = sessionid($c); - -echo "Explicit LOB use\n"; -for ($i = 1; $i <= 10; $i++) { - echo "\nRun = " . $i . "\n"; - echo "Temporary LOBs = " . templobs($c, $sid) . "\n"; - readxmltab_ex($c); -} - -echo "\nImplicit LOB use\n"; -for ($i = 1; $i <= 10; $i++) { - echo "\nRun = " . $i . "\n"; - echo "Temporary LOBs = " . templobs($c, $sid) . "\n"; - readxmltab_im($c); -} - -echo "\nExplicit LOB with no free (i.e. a temp lob leak)\n"; -for ($i = 1; $i <= 10; $i++) { - echo "\nRun = " . $i . "\n"; - echo "Temporary LOBs = " . templobs($c, $sid) . "\n"; - readxmltab_ex_nofree($c); -} - - - -// Cleanup - -dropxmltab($c); - -oci_close($c); - -echo "Done\n"; -?> ---EXPECT-- -Explicit LOB use - -Run = 1 -Temporary LOBs = 0 -Loop count check = 100 - -Run = 2 -Temporary LOBs = 100 -Loop count check = 100 - -Run = 3 -Temporary LOBs = 200 -Loop count check = 100 - -Run = 4 -Temporary LOBs = 300 -Loop count check = 100 - -Run = 5 -Temporary LOBs = 400 -Loop count check = 100 - -Run = 6 -Temporary LOBs = 500 -Loop count check = 100 - -Run = 7 -Temporary LOBs = 600 -Loop count check = 100 - -Run = 8 -Temporary LOBs = 700 -Loop count check = 100 - -Run = 9 -Temporary LOBs = 800 -Loop count check = 100 - -Run = 10 -Temporary LOBs = 900 -Loop count check = 100 - -Implicit LOB use - -Run = 1 -Temporary LOBs = 1000 -Loop count check = 100 - -Run = 2 -Temporary LOBs = 1100 -Loop count check = 100 - -Run = 3 -Temporary LOBs = 1200 -Loop count check = 100 - -Run = 4 -Temporary LOBs = 1300 -Loop count check = 100 - -Run = 5 -Temporary LOBs = 1400 -Loop count check = 100 - -Run = 6 -Temporary LOBs = 1500 -Loop count check = 100 - -Run = 7 -Temporary LOBs = 1600 -Loop count check = 100 - -Run = 8 -Temporary LOBs = 1700 -Loop count check = 100 - -Run = 9 -Temporary LOBs = 1800 -Loop count check = 100 - -Run = 10 -Temporary LOBs = 1900 -Loop count check = 100 - -Explicit LOB with no free (i.e. a temp lob leak) - -Run = 1 -Temporary LOBs = 2000 -Loop count check = 100 - -Run = 2 -Temporary LOBs = 2100 -Loop count check = 100 - -Run = 3 -Temporary LOBs = 2200 -Loop count check = 100 - -Run = 4 -Temporary LOBs = 2300 -Loop count check = 100 - -Run = 5 -Temporary LOBs = 2400 -Loop count check = 100 - -Run = 6 -Temporary LOBs = 2500 -Loop count check = 100 - -Run = 7 -Temporary LOBs = 2600 -Loop count check = 100 - -Run = 8 -Temporary LOBs = 2700 -Loop count check = 100 - -Run = 9 -Temporary LOBs = 2800 -Loop count check = 100 - -Run = 10 -Temporary LOBs = 2900 -Loop count check = 100 -Done
\ No newline at end of file diff --git a/ext/oci8/tests/bug47281.phpt b/ext/oci8/tests/bug47281.phpt index d0e0023537..00c43c22da 100644 --- a/ext/oci8/tests/bug47281.phpt +++ b/ext/oci8/tests/bug47281.phpt @@ -6,11 +6,12 @@ $target_dbs = array('oracledb' => true, 'timesten' => false); // test runs on t require(dirname(__FILE__).'/skipif.inc'); // error3.phpt obsoletes this test for newer Oracle client versions // Assume runtime client version is >= compile time client version -$cv = explode('.', oci_client_version()); -if ($cv[0] > 11 || ($cv[0] == 11 && $cv[1] > 2) || ($cv[0] == 11 && $cv[1] == 2 && $cv[3] >= 3)) { +preg_match('/^([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)/', oci_client_version(), $matches); +if (!isset($matches[0]) || + ($matches[1] > 11 || ($matches[1] == 11 && $matches[2] > 2) || ($matches[1] == 11 && $matches[2] == 2 && $matches[4] >= 3) + )) { die("skip test works only with Oracle 11.2.0.2 or earlier Oracle client libraries"); } - ?> --ENV-- NLS_LANG=.AL32UTF8 diff --git a/ext/oci8/tests/clientversion.phpt b/ext/oci8/tests/clientversion.phpt index db70b5affc..262ded462f 100644 --- a/ext/oci8/tests/clientversion.phpt +++ b/ext/oci8/tests/clientversion.phpt @@ -3,9 +3,6 @@ oci_client_version() --SKIPIF-- <?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); -if (preg_match('/^1[012]\./', oci_client_version()) != 1) { - die("skip test expected to work only with Oracle 10g or greater version of client"); -} ?> --FILE-- <?php diff --git a/ext/oci8/tests/clientversion_92.phpt b/ext/oci8/tests/clientversion_92.phpt deleted file mode 100644 index d4b92cd354..0000000000 --- a/ext/oci8/tests/clientversion_92.phpt +++ /dev/null @@ -1,20 +0,0 @@ ---TEST-- -oci_client_version() for Oracle 9.2 client libraries ---SKIPIF-- -<?php -if (!extension_loaded('oci8')) die("skip no oci8 extension"); -if (preg_match('/Unknown/', oci_client_version()) != 1) { - die("skip test expected to work only with Oracle 9gR2 client libraries"); -} -?> ---FILE-- -<?php - -echo oci_client_version(), "\n"; - -?> -===DONE=== -<?php exit(0); ?> ---EXPECTF-- -Unknown -===DONE=== diff --git a/ext/oci8/tests/commit_001.phpt b/ext/oci8/tests/commit_001.phpt index 806fb193a0..ef4018118e 100644 --- a/ext/oci8/tests/commit_001.phpt +++ b/ext/oci8/tests/commit_001.phpt @@ -81,48 +81,48 @@ echo "Done\n"; bool(true) int(0) array(5) { - [%u|b%"ID"]=> + ["ID"]=> array(0) { } - [%u|b%"VALUE"]=> + ["VALUE"]=> array(0) { } - [%u|b%"BLOB"]=> + ["BLOB"]=> array(0) { } - [%u|b%"CLOB"]=> + ["CLOB"]=> array(0) { } - [%u|b%"STRING"]=> + ["STRING"]=> array(0) { } } bool(true) int(4) array(5) { - [%u|b%"ID"]=> + ["ID"]=> array(4) { [0]=> - %string|unicode%(1) "1" + string(1) "1" [1]=> - %string|unicode%(1) "1" + string(1) "1" [2]=> - %string|unicode%(1) "1" + string(1) "1" [3]=> - %string|unicode%(1) "1" + string(1) "1" } - [%u|b%"VALUE"]=> + ["VALUE"]=> array(4) { [0]=> - %string|unicode%(1) "1" + string(1) "1" [1]=> - %string|unicode%(1) "1" + string(1) "1" [2]=> - %string|unicode%(1) "1" + string(1) "1" [3]=> - %string|unicode%(1) "1" + string(1) "1" } - [%u|b%"BLOB"]=> + ["BLOB"]=> array(4) { [0]=> NULL @@ -133,7 +133,7 @@ array(5) { [3]=> NULL } - [%u|b%"CLOB"]=> + ["CLOB"]=> array(4) { [0]=> NULL @@ -144,7 +144,7 @@ array(5) { [3]=> NULL } - [%u|b%"STRING"]=> + ["STRING"]=> array(4) { [0]=> NULL diff --git a/ext/oci8/tests/conn_attr.inc b/ext/oci8/tests/conn_attr.inc index 220e688210..2edc1c9552 100644 --- a/ext/oci8/tests/conn_attr.inc +++ b/ext/oci8/tests/conn_attr.inc @@ -2,30 +2,28 @@ require(dirname(__FILE__)."/connect.inc"); -$sv = oci_server_version($c); -$sv = preg_match('/Release (11\.2|12)\./', $sv, $matches); -if ($sv == 1) { +preg_match('/.*Release ([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)*/', oci_server_version($c), $matches); +if ((isset($matches[1]) && $matches[1] >= 11)) { // Server is Oracle 11.2+ $stmtarray = array( - "drop user testuser cascade", - "create user testuser identified by testuser", - "grant connect,resource,dba to testuser", - "alter user testuser enable editions", - "drop edition myedition1", - "drop edition myedition", - "grant create any edition to testuser", + "drop user $testuser cascade", + "create user $testuser identified by $testpassword", // $testuser should be set by the file that includes conn_attr.inc + "grant connect,resource,dba to $testuser", + "alter user $testuser enable editions", + "drop edition myedition1 cascade", + "drop edition myedition cascade", + "grant create any edition to $testuser", "create edition myedition", "create edition myedition1 as child of myedition", - "grant use on edition myedition to testuser", - "grant use on edition myedition1 to testuser", + "grant use on edition myedition to $testuser", + "grant use on edition myedition1 to $testuser", ); -} -else { +} else { // Server is Pre 11.2 $stmtarray = array( - "drop user testuser cascade", - "create user testuser identified by testuser", - "grant connect,resource,dba to testuser", + "drop user $testuser cascade", + "create user $testuser identified by $testpassword", + "grant connect,resource,dba to $testuser", ); } @@ -68,8 +66,8 @@ function get_attr($conn,$attr) function get_conn($conn_type) { - $user = 'testuser'; - $password = 'testuser'; + $user = $GLOBALS['testuser']; + $password = $GLOBALS['testpassword']; $dbase = $GLOBALS['dbase']; switch($conn_type) { case 1: @@ -139,9 +137,9 @@ function get_sys_attr($conn,$attr) function clean_up($c) { $stmtarray = array( - "drop user testuser cascade", - "drop edition myedition1", - "drop edition myedition", + "drop edition myedition1 cascade", + "drop edition myedition cascade", + "drop user " . $GLOBALS['testuser'] . " cascade", ); foreach ($stmtarray as $stmt) { diff --git a/ext/oci8/tests/conn_attr_1.phpt b/ext/oci8/tests/conn_attr_1.phpt index ad508a2ed2..745b1cd93f 100644 --- a/ext/oci8/tests/conn_attr_1.phpt +++ b/ext/oci8/tests/conn_attr_1.phpt @@ -9,15 +9,17 @@ if (strcasecmp($user, "system") && strcasecmp($user, "sys")) die("skip needs to be run as a DBA user"); if ($test_drcp) die("skip output might vary with DRCP"); -if (preg_match('/Release 1[01]\./', oci_server_version($c), $matches) !== 1) { +preg_match('/.*Release ([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)*/', oci_server_version($c), $matches); +if (!(isset($matches[0]) && $matches[1] >= 10)) { die("skip expected output only valid when using Oracle 10g or greater database server"); -} else if (preg_match('/^1[01]\./', oci_client_version()) != 1) { - die("skip test expected to work only with Oracle 10g or greater version of client"); } - ?> --FILE-- <?php + +$testuser = 'testuser_attr_1'; // Used in conn_attr.inc +$testpassword = 'testuser'; + require(dirname(__FILE__)."/conn_attr.inc"); $attr_array = array('MODULE','ACTION','CLIENT_INFO','CLIENT_IDENTIFIER'); diff --git a/ext/oci8/tests/conn_attr_2.phpt b/ext/oci8/tests/conn_attr_2.phpt index 1072503529..ad83f70c20 100644 --- a/ext/oci8/tests/conn_attr_2.phpt +++ b/ext/oci8/tests/conn_attr_2.phpt @@ -8,40 +8,41 @@ require(dirname(__FILE__).'/skipif.inc'); if (strcasecmp($user, "system") && strcasecmp($user, "sys")) die("skip needs to be run as a DBA user"); if ($test_drcp) die("skip output might vary with DRCP"); -if (preg_match('/Release 1[01]\./', oci_server_version($c), $matches) !== 1) { +preg_match('/.*Release ([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)*/', oci_server_version($c), $matches); +if (!(isset($matches[0]) && $matches[1] >= 10)) { die("skip expected output only valid when using Oracle 10g or greater database server"); -} else if (preg_match('/^1[01]\./', oci_client_version()) != 1) { - die("skip test expected to work only with Oracle 10g or greater version of client"); } - ?> --INI-- oci8.privileged_connect = On --FILE-- <?php + +$testuser = 'testuser_attr_2'; // Used in conn_attr.inc +$testpassword = 'testuser'; + require(dirname(__FILE__)."/conn_attr.inc"); -$user='testuser'; -$password='testuser'; + $attr_array = array('MODULE','ACTION','CLIENT_INFO','CLIENT_IDENTIFIER'); echo"**Set values using pconnect-1**\n"; -var_dump($pc1 = oci_pconnect($user,$password,$dbase)); +var_dump($pc1 = oci_pconnect($testuser,$testpassword,$dbase)); foreach($attr_array as $attr) { set_attr($pc1,$attr,100); } // using pc1 again echo"\n**Get values using pconnect-2**\n"; -var_dump($pc3 = oci_pconnect($user,$password,$dbase)); +var_dump($pc3 = oci_pconnect($testuser,$testpassword,$dbase)); foreach($attr_array as $attr) { get_attr($pc3,$attr); } // Get with different pconnect echo"\n**Get values using pconnect-3**\n"; -var_dump($pc2 = oci_pconnect($user,$password,$dbase,'UTF8')); +var_dump($pc2 = oci_pconnect($testuser,$testpassword,$dbase,'UTF8')); foreach($attr_array as $attr) { get_attr($pc2,$attr); } @@ -52,15 +53,22 @@ oci_close($pc3); // Re-open a persistent connection and check for the attr values. echo "\n**Re-open a pconnect()**\n"; -var_dump($pc4 = oci_pconnect($user,$password,$dbase)); +var_dump($pc4 = oci_pconnect($testuser,$testpassword,$dbase)); foreach($attr_array as $attr) { get_attr($pc4,$attr); } oci_close($pc4); // Test with SYSDBA connection. -var_dump($sys_c1 = oci_pconnect($user,$password,$dbase,false,OCI_SYSDBA)); -if ($sys_c1) { +echo "\n**Test with SYSDBA connection**\n"; +$sys_c1 = @oci_pconnect($testuser,$testpassword,$dbase,false,OCI_SYSDBA); +var_dump($sys_c1); +if (!$sys_c1) { + $e = oci_error(); + if ($e['code'] != 1031 && $e['code'] != 1017) { + var_dump($e); + } +} else { set_attr($sys_c1,'ACTION',10); get_sys_attr($sys_c1,'ACTION'); get_attr($pc2,'ACTION'); @@ -100,6 +108,6 @@ The value of ACTION is TASK100 The value of CLIENT_INFO is INFO1100 The value of CLIENT_IDENTIFIER is ID00100 -Warning: oci_pconnect(): ORA-01031: %s on line %d +**Test with SYSDBA connection** bool(false) Done diff --git a/ext/oci8/tests/conn_attr_3.phpt b/ext/oci8/tests/conn_attr_3.phpt index be8d3306de..1b00ac5a4f 100644 --- a/ext/oci8/tests/conn_attr_3.phpt +++ b/ext/oci8/tests/conn_attr_3.phpt @@ -8,14 +8,17 @@ require(dirname(__FILE__).'/skipif.inc'); if (strcasecmp($user, "system") && strcasecmp($user, "sys")) die("skip needs to be run as a DBA user"); if ($test_drcp) die("skip output might vary with DRCP"); -if (preg_match('/Release 1[01]\./', oci_server_version($c), $matches) !== 1) { +preg_match('/.*Release ([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)*/', oci_server_version($c), $matches); +if (!(isset($matches[0]) && $matches[1] >= 10)) { die("skip expected output only valid when using Oracle 10g or greater database server"); -} else if (preg_match('/^1[01]\./', oci_client_version()) != 1) { - die("skip test expected to work only with Oracle 10g or greater version of client"); } ?> --FILE-- <?php + +$testuser = 'testuser_attr_3'; // Used in conn_attr.inc +$testpassword = 'testuser'; + require(dirname(__FILE__)."/conn_attr.inc"); echo"**Test Set and get values for the attributes with oci_close() ************\n"; diff --git a/ext/oci8/tests/conn_attr_4.phpt b/ext/oci8/tests/conn_attr_4.phpt index 4885f80b71..0a6b814e4b 100644 --- a/ext/oci8/tests/conn_attr_4.phpt +++ b/ext/oci8/tests/conn_attr_4.phpt @@ -9,21 +9,23 @@ if (getenv('SKIP_SLOW_TESTS')) die('skip slow tests excluded by request'); if (strcasecmp($user, "system") && strcasecmp($user, "sys")) die("skip needs to be run as a DBA user"); if ($test_drcp) die("skip output might vary with DRCP"); -if (preg_match('/Release (11\.2|12)\./', oci_server_version($c), $matches) !== 1) { - // Bug fixed in 11.2 prevents client_info being rest +preg_match('/.*Release ([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)*/', oci_server_version($c), $matches); +if (!(isset($matches[0]) && + (($matches[1] == 11 && $matches[2] >= 2) || + ($matches[1] >= 12) + ))) { + // Bug fixed in 11.2 prevents client_info being reset die("skip expected output only valid when using Oracle 11gR2 or greater database server"); -} else if (preg_match('/^1[01]\./', oci_client_version()) != 1) { - die("skip test expected to work only with Oracle 10g or greater version of client"); } ?> --FILE-- <?php +$testuser = 'testuser_attr_4'; // Used in conn_attr.inc +$testpassword = 'testuser'; require(dirname(__FILE__)."/conn_attr.inc"); -$user='testuser'; -$password='testuser'; $attr_array = array('MODULE','ACTION','CLIENT_INFO','CLIENT_IDENTIFIER'); echo"**Test Negative cases************\n"; @@ -40,7 +42,7 @@ var_dump(oci_set_client_info($str1,$str1)); // Setting an Invalid value. echo "\nInvalid Value \n"; -$c1=oci_connect($user,$password,$dbase); +$c1=oci_connect($testuser,$testpassword,$dbase); var_dump(oci_set_action($c1,$c1)); // Setting values multiple times. diff --git a/ext/oci8/tests/conn_attr_5.phpt b/ext/oci8/tests/conn_attr_5.phpt index d694ec06a5..70a6d2b096 100644 --- a/ext/oci8/tests/conn_attr_5.phpt +++ b/ext/oci8/tests/conn_attr_5.phpt @@ -8,14 +8,17 @@ require(dirname(__FILE__).'/skipif.inc'); if (strcasecmp($user, "system") && strcasecmp($user, "sys")) die("skip needs to be run as a DBA user"); if ($test_drcp) die("skip output might vary with DRCP"); -if (preg_match('/Release 1[01]\./', oci_server_version($c), $matches) !== 1) { +preg_match('/.*Release ([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)*/', oci_server_version($c), $matches); +if (!(isset($matches[0]) && $matches[1] >= 10)) { die("skip expected output only valid when using Oracle 10g or greater database server"); -} else if (preg_match('/^1[01]\./', oci_client_version()) != 1) { - die("skip test expected to work only with Oracle 10g or greater version of client"); } ?> --FILE-- <?php + +$testuser = 'testuser_attr_5'; // Used in conn_attr.inc +$testpassword = 'testuser'; + require(dirname(__FILE__)."/conn_attr.inc"); echo"**Test - Set and get values for the attributes with scope end ************\n"; diff --git a/ext/oci8/tests/connect_without_oracle_home.phpt b/ext/oci8/tests/connect_without_oracle_home.phpt index e14fb93695..831fc23d61 100644 --- a/ext/oci8/tests/connect_without_oracle_home.phpt +++ b/ext/oci8/tests/connect_without_oracle_home.phpt @@ -10,9 +10,9 @@ $ov = preg_match('/Compile-time ORACLE_HOME/', $phpinfo); if ($ov !== 1) { die ("skip Test only valid when OCI8 is built with an ORACLE_HOME"); } -$iv = preg_match('/Oracle .*Version => (10\.2)/', $phpinfo); -if ($iv != 1) { - die ("skip tests a feature that works only with Oracle 10gR2"); +preg_match('/^([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)/', oci_client_version(), $matches); +if (!isset($matches[0]) || !($matches[1] == 10 && $matches[2] == 2)) { + die ("skip tests a feature that works only with Oracle 10gR2 client"); } ?> --ENV-- diff --git a/ext/oci8/tests/connect_without_oracle_home_11.phpt b/ext/oci8/tests/connect_without_oracle_home_11.phpt index 1620803dbb..42c4564456 100644 --- a/ext/oci8/tests/connect_without_oracle_home_11.phpt +++ b/ext/oci8/tests/connect_without_oracle_home_11.phpt @@ -10,7 +10,11 @@ $ov = preg_match('/Compile-time ORACLE_HOME/', $phpinfo); if ($ov != 1) { die ("skip Test only valid when OCI8 is built with an ORACLE_HOME"); } -if (preg_match('/^11\.2|12\./', oci_client_version()) != 1) { +preg_match('/^([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)/', oci_client_version(), $matches); +if (!(isset($matches[0]) && + (($matches[1] == 11 && $matches[2] >= 2) || + ($matches[1] >= 12) + ))) { die("skip test expected to work only with Oracle 11gR2 or greater version of client"); } ?> diff --git a/ext/oci8/tests/connect_without_oracle_home_old.phpt b/ext/oci8/tests/connect_without_oracle_home_old.phpt index 5a731337af..d6d12b47ba 100644 --- a/ext/oci8/tests/connect_without_oracle_home_old.phpt +++ b/ext/oci8/tests/connect_without_oracle_home_old.phpt @@ -10,9 +10,6 @@ $ov = preg_match('/Compile-time ORACLE_HOME/', $phpinfo); if ($ov !== 1) { die ("skip Test only valid when OCI8 is built with an ORACLE_HOME"); } -if (preg_match('/^10\.2\./', oci_client_version()) != 1) { - die("skip test expected to work only with Oracle 10gR2 client libraries"); -} ?> --ENV-- ORACLE_HOME="" @@ -33,5 +30,8 @@ else { <?php exit(0); ?> --EXPECTF-- Warning: ocilogon(): OCIEnvNlsCreate() failed. There is something wrong with your system - please check that ORACLE_HOME and %s are set and point to the right directories in %s on line %d + +Warning: ocilogon(): %s ORA-01804 + in %s on line %d bool(false) ===DONE=== diff --git a/ext/oci8/tests/connect_without_oracle_home_old_11.phpt b/ext/oci8/tests/connect_without_oracle_home_old_11.phpt index c7cfecf396..eb5fb0cc4d 100644 --- a/ext/oci8/tests/connect_without_oracle_home_old_11.phpt +++ b/ext/oci8/tests/connect_without_oracle_home_old_11.phpt @@ -10,7 +10,11 @@ $ov = preg_match('/Compile-time ORACLE_HOME/', $phpinfo); if ($ov !== 1) { die ("skip Test only valid when OCI8 is built with an ORACLE_HOME"); } -if (preg_match('/^11\.2|12\./', oci_client_version()) != 1) { +preg_match('/^([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)/', oci_client_version(), $matches); +if (!(isset($matches[0]) && + (($matches[1] == 11 && $matches[2] >= 2) || + ($matches[1] >= 12) + ))) { die("skip test expected to work only with Oracle 11gR2 or greater version of client"); } ?> diff --git a/ext/oci8/tests/cursors_old.phpt b/ext/oci8/tests/cursors_old.phpt index d60e2ff1ea..aa25937570 100644 --- a/ext/oci8/tests/cursors_old.phpt +++ b/ext/oci8/tests/cursors_old.phpt @@ -52,19 +52,19 @@ echo "Done\n"; ?> --EXPECTF-- array(2) { - [%u|b%"ID"]=> - %unicode|string%(1) "1" - [%u|b%"VALUE"]=> - %unicode|string%(1) "1" + ["ID"]=> + string(1) "1" + ["VALUE"]=> + string(1) "1" } bool(true) Warning: ocifetchinto():%sORA-01002: %s in %scursors_old.php on line %d array(2) { - [%u|b%"ID"]=> - %unicode|string%(1) "1" - [%u|b%"VALUE"]=> - %unicode|string%(1) "1" + ["ID"]=> + string(1) "1" + ["VALUE"]=> + string(1) "1" } bool(true) Done diff --git a/ext/oci8/tests/db_op_1.phpt b/ext/oci8/tests/db_op_1.phpt new file mode 100644 index 0000000000..f645cf80ff --- /dev/null +++ b/ext/oci8/tests/db_op_1.phpt @@ -0,0 +1,61 @@ +--TEST-- +oci_set_db_operation: basic test for end-to-end tracing +--SKIPIF-- +<?php +if (!extension_loaded('oci8')) die ("skip no oci8 extension"); +$target_dbs = array('oracledb' => true, 'timesten' => false); // test runs on these DBs +require(dirname(__FILE__).'/skipif.inc'); +if (strcasecmp($user, "system") && strcasecmp($user, "sys")) { + die("skip needs to be run as a DBA user"); +} +preg_match('/.*Release ([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)*/', oci_server_version($c), $matches); +if (!(isset($matches[0]) && $matches[1] >= 12)) { + die("skip expected output only valid when using Oracle Database 12c or greater"); +} +preg_match('/^[[:digit:]]+/', oci_client_version(), $matches); +if (!(isset($matches[0]) && $matches[0] >= 12)) { + die("skip works only with Oracle 12c or greater version of Oracle client libraries"); +} +if (!function_exists('oci_set_db_operation')) +{ + die("skip function oci_set_db_operation() does not exist"); +} +?> +--FILE-- +<?php + +require(dirname(__FILE__).'/connect.inc'); + +// Run Test + +echo "Test 1\n"; + +// Test setting the "DB operation" used by Oracle DB for end-to-end application tracing + +function dq($c, $q) +{ + $s = oci_parse($c, $q); + oci_execute($s); + var_dump(oci_fetch_assoc($s)); +} + +oci_set_db_operation($c, "db_op_1"); +dq($c, 'select * from dual'); + +dq($c, 'select dbop_name from v$sql_monitor where dbop_name is not null order by dbop_exec_id desc'); + +?> +===DONE=== +<?php exit(0); ?> +--EXPECTF-- +Test 1 +array(1) { + ["DUMMY"]=> + string(1) "X" +} +array(1) { + ["DBOP_NAME"]=> + string(7) "db_op_1" +} +===DONE=== + diff --git a/ext/oci8/tests/db_op_2.phpt b/ext/oci8/tests/db_op_2.phpt new file mode 100644 index 0000000000..05c2269ae0 --- /dev/null +++ b/ext/oci8/tests/db_op_2.phpt @@ -0,0 +1,69 @@ +--TEST-- +oci_set_db_operation: basic test for end-to-end tracing +--SKIPIF-- +<?php +if (!extension_loaded('oci8')) die ("skip no oci8 extension"); +$target_dbs = array('oracledb' => true, 'timesten' => false); // test runs on these DBs +require(dirname(__FILE__).'/skipif.inc'); +if (strcasecmp($user, "system") && strcasecmp($user, "sys")) { + die("skip needs to be run as a DBA user"); +} +preg_match('/.*Release ([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)*/', oci_server_version($c), $matches); +if (!(isset($matches[0]) && $matches[1] >= 12)) { + die("skip expected output only valid when using Oracle Database 12c or greater"); +} +preg_match('/^[[:digit:]]+/', oci_client_version(), $matches); +if (!(isset($matches[0]) && $matches[0] >= 12)) { + die("skip works only with Oracle 12c or greater version of Oracle client libraries"); +} +if (!function_exists('oci_set_db_operation')) +{ + die("skip function oci_set_db_operation() does not exist"); +} +?> +--FILE-- +<?php + +require(dirname(__FILE__).'/connect.inc'); + +function dq($c, $q) +{ + $s = oci_parse($c, $q); + oci_execute($s); + var_dump(oci_fetch_assoc($s)); +} + +echo "Test 1\n"; +oci_set_db_operation($c, "db_op_2_a"); +dq($c, 'select * from dual'); + +echo "Test 2\n"; +oci_set_db_operation($c, "db_op_2_b"); +dq($c, 'select * from dual'); + +echo "Test 3\n"; +dq($c, 'select dbop_name from v$sql_monitor where dbop_name like \'db_op2%\' order by dbop_exec_id desc'); + +?> +===DONE=== +<?php exit(0); ?> +--XFAIL-- +Fails due to Oracle Bug 16695981 +--EXPECTF-- +Test 1 +array(1) { + ["DUMMY"]=> + string(1) "X" +} +Test 2 +array(1) { + ["DUMMY"]=> + string(1) "X" +} +Test 3 +array(2) { + ["DBOP_NAME"]=> + string(7) "db_op_2a" +} +===DONE=== + diff --git a/ext/oci8/tests/debug.phpt b/ext/oci8/tests/debug.phpt index fe96e6e87e..66ab0f0d00 100644 --- a/ext/oci8/tests/debug.phpt +++ b/ext/oci8/tests/debug.phpt @@ -16,10 +16,9 @@ else { oci_connect($user, $password); } -echo "Done\n"; - oci_internal_debug(false); ?> ---EXPECTREGEX-- -^OCI8 DEBUG: .*Done$ +===DONE=== +--EXPECT-- +===DONE=== diff --git a/ext/oci8/tests/define.phpt b/ext/oci8/tests/define.phpt index c6ce7bd9b3..b78f698e7c 100644 --- a/ext/oci8/tests/define.phpt +++ b/ext/oci8/tests/define.phpt @@ -44,5 +44,5 @@ echo "Done\n"; ?> --EXPECTF-- -%unicode|string%(%d) "some" +string(%d) "some" Done diff --git a/ext/oci8/tests/define1.phpt b/ext/oci8/tests/define1.phpt index 6e4b74e3ba..be16271d5b 100644 --- a/ext/oci8/tests/define1.phpt +++ b/ext/oci8/tests/define1.phpt @@ -55,5 +55,5 @@ bool(false) Warning: oci_define_by_name() expects at least 3 parameters, 2 given in %s on line %d NULL -%unicode|string%(4) "some" +string(4) "some" Done diff --git a/ext/oci8/tests/define4.phpt b/ext/oci8/tests/define4.phpt index 266fd7edd7..3114a73937 100644 --- a/ext/oci8/tests/define4.phpt +++ b/ext/oci8/tests/define4.phpt @@ -58,15 +58,15 @@ echo "Done\n"; Test 1 bool(true) Test 2 -%unicode|string%(4) "1234" -%unicode|string%(4) "some" -%unicode|string%(4) "some" -%unicode|string%(4) "some" -%unicode|string%(4) "1234" -%unicode|string%(4) "some" +string(4) "1234" +string(4) "some" +string(4) "some" +string(4) "some" +string(4) "1234" +string(4) "some" Test 3 bool(true) -%unicode|string%(4) "some" +string(4) "some" Warning: oci_result(): %d is not a valid oci8 statement resource in %s on line %d bool(false) diff --git a/ext/oci8/tests/define5.phpt b/ext/oci8/tests/define5.phpt index 68fa01d09a..978d66b260 100644 --- a/ext/oci8/tests/define5.phpt +++ b/ext/oci8/tests/define5.phpt @@ -61,12 +61,12 @@ echo "Done\n"; Test 1 - must do define before execute bool(true) NULL -%unicode|string%(4) "some" +string(4) "some" Test 2 - normal define order bool(true) -%unicode|string%(4) "some" +string(4) "some" Test 3 - no new define done -%unicode|string%(4) "some" -%unicode|string%(5) "thing" +string(4) "some" +string(5) "thing" Done diff --git a/ext/oci8/tests/define_old.phpt b/ext/oci8/tests/define_old.phpt index f65e6b8080..cc07e2ea94 100644 --- a/ext/oci8/tests/define_old.phpt +++ b/ext/oci8/tests/define_old.phpt @@ -44,5 +44,5 @@ echo "Done\n"; ?> --EXPECTF-- -%unicode|string%(4) "some" +string(4) "some" Done diff --git a/ext/oci8/tests/details.inc b/ext/oci8/tests/details.inc index 9a86c46868..e54ea84abd 100644 --- a/ext/oci8/tests/details.inc +++ b/ext/oci8/tests/details.inc @@ -52,7 +52,7 @@ if (!function_exists('oci8_test_sql_execute')) { $s = oci_parse($c, $stmt); if (!$s) { $m = oci_error($c); - echo $stmt . PHP_EOL . $m['message'] . PHP_EOL; + echo "oci8_test_sql_execute() error:". PHP_EOL . $stmt . PHP_EOL . $m['message'] . PHP_EOL; } else { $r = @oci_execute($s); @@ -66,7 +66,7 @@ if (!function_exists('oci8_test_sql_execute')) { , 4080 // trigger does not exist , 38802 // edition does not exist ))) { - echo $stmt . PHP_EOL . $m['message'] . PHP_EOL; + echo "oci8_test_sql_execute() error:". PHP_EOL . $stmt . PHP_EOL . $m['message'] . PHP_EOL; } } } diff --git a/ext/oci8/tests/drcp_cclass1.phpt b/ext/oci8/tests/drcp_cclass1.phpt index 068331e5a9..5c78a2943e 100644 --- a/ext/oci8/tests/drcp_cclass1.phpt +++ b/ext/oci8/tests/drcp_cclass1.phpt @@ -3,9 +3,21 @@ DRCP: Test setting connection class inline --SKIPIF-- <?php if (!extension_loaded('oci8')) die ("skip no oci8 extension"); -require(dirname(__FILE__)."/details.inc"); +require(dirname(__FILE__).'/connect.inc'); if (!$test_drcp) die("skip testing DRCP connection class only works in DRCP mode"); if (strcasecmp($user, "system") && strcasecmp($user, "sys")) die("skip needs to be run as a DBA user"); + +preg_match('/.*Release ([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)*/', oci_server_version($c), $matches_sv); +// This test in Oracle 12c needs a non-CDB or the root container +if (isset($matches_sv[0]) && $matches_sv[1] >= 12) { + $s = oci_parse($c, "select nvl(sys_context('userenv', 'con_name'), 'notacdb') as dbtype from dual"); + $r = @oci_execute($s); + if (!$r) + die('skip could not identify container type'); + $r = oci_fetch_array($s); + if ($r['DBTYPE'] !== 'CDB$ROOT') + die('skip cannot run test using a PDB'); +} ?> --FILE-- <?php diff --git a/ext/oci8/tests/drcp_connection_class.phpt b/ext/oci8/tests/drcp_connection_class.phpt index 2aed131c14..c01c144d23 100644 --- a/ext/oci8/tests/drcp_connection_class.phpt +++ b/ext/oci8/tests/drcp_connection_class.phpt @@ -1,7 +1,13 @@ --TEST-- DRCP: oci8.connection_class with ini_get() and ini_set() --SKIPIF-- -<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?> +<?php +if (!extension_loaded('oci8')) die("skip no oci8 extension"); +preg_match('/^[[:digit:]]+/', oci_client_version(), $matches); +if (!(isset($matches[0]) && $matches[0] >= 11)) { + die("skip works only with Oracle 11g or greater version of Oracle client libraries"); +} +?> --INI-- oci8.connection_class=test --FILE-- diff --git a/ext/oci8/tests/drcp_privileged.phpt b/ext/oci8/tests/drcp_privileged.phpt index da8702e3c9..3871341bc5 100644 --- a/ext/oci8/tests/drcp_privileged.phpt +++ b/ext/oci8/tests/drcp_privileged.phpt @@ -3,7 +3,8 @@ DRCP: privileged connect --SKIPIF-- <?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); -require(dirname(__FILE__)."/details.inc"); +require(dirname(__FILE__)."/connect.inc"); +if (!$test_drcp) die("skip requires DRCP connection"); if (strcasecmp($user, "system") && strcasecmp($user, "sys")) die("skip needs to be run as a DBA user"); ob_start(); phpinfo(INFO_MODULES); @@ -12,6 +13,18 @@ if (preg_match('/Compile-time ORACLE_HOME/', $phpinfo) !== 1) { // Assume building PHP with an ORACLE_HOME means the tested DB is on the same machine as PHP die("skip this test is unlikely to work with a remote database - unless an Oracle password file has been created"); } + +preg_match('/.*Release ([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)*/', oci_server_version($c), $matches_sv); +// This test in Oracle 12c needs a non-CDB or the root container +if (isset($matches_sv[0]) && $matches_sv[1] >= 12) { + $s = oci_parse($c, "select nvl(sys_context('userenv', 'con_name'), 'notacdb') as dbtype from dual"); + $r = @oci_execute($s); + if (!$r) + die('skip could not identify container type'); + $r = oci_fetch_array($s); + if ($r['DBTYPE'] !== 'CDB$ROOT') + die('skip cannot run test using a PDB'); +} ?> --INI-- oci8.privileged_connect=1 diff --git a/ext/oci8/tests/driver_name.phpt b/ext/oci8/tests/driver_name.phpt index bf86e66e7b..f63979d6b5 100644 --- a/ext/oci8/tests/driver_name.phpt +++ b/ext/oci8/tests/driver_name.phpt @@ -7,10 +7,19 @@ require(dirname(__FILE__)."/connect.inc"); if (strcasecmp($user, "system") && strcasecmp($user, "sys")) die("skip needs to be run as a DBA user"); if ($test_drcp) die("skip as Output might vary with DRCP"); -if (preg_match('/Release (11\.2|12)/', oci_server_version($c), $matches) !== 1) { - die("skip expected output only valid when using Oracle 11gR2 or greater databases"); -} else if (preg_match('/^(11\.2|12\.)/', oci_client_version()) != 1) { - die("skip test expected to work only with Oracle 11g or greater version of client"); +preg_match('/.*Release ([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)*/', oci_server_version($c), $matches); +if (!(isset($matches[0]) && + (($matches[1] == 11 && $matches[2] >= 2) || + ($matches[1] >= 12) + ))) { + die("skip expected output only valid when using Oracle 11gR2 or greater database server"); +} +preg_match('/^([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)/', oci_client_version(), $matches); +if (!(isset($matches[0]) && + (($matches[1] == 11 && $matches[2] >= 2) || + ($matches[1] >= 12) + ))) { + die("skip test expected to work only with Oracle 11gR2 or greater version of client"); } ?> diff --git a/ext/oci8/tests/edition_1.phpt b/ext/oci8/tests/edition_1.phpt index b9c8fd817e..3e55ee902c 100644 --- a/ext/oci8/tests/edition_1.phpt +++ b/ext/oci8/tests/edition_1.phpt @@ -10,9 +10,18 @@ if (strcasecmp($user, "system") && strcasecmp($user, "sys")) { if ($test_drcp) { die("skip as Output might vary with DRCP"); } -if (preg_match('/Release (1[1]\.2|12)\./', oci_server_version($c), $matches) !== 1) { - die("skip expected output only valid when using Oracle 11gR2 or greater databases"); -} else if (preg_match('/^(11\.2|12)\./', oci_client_version()) != 1) { +preg_match('/.*Release ([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)*/', oci_server_version($c), $matches); +if (!(isset($matches[0]) && + (($matches[1] == 11 && $matches[2] >= 2) || + ($matches[1] >= 12) + ))) { + die("skip expected output only valid when using Oracle 11gR2 or greater database server"); +} +preg_match('/^([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)/', oci_client_version(), $matches); +if (!(isset($matches[0]) && + (($matches[1] == 11 && $matches[2] >= 2) || + ($matches[1] >= 12) + ))) { die("skip test expected to work only with Oracle 11gR2 or greater version of client"); } ?> @@ -24,6 +33,9 @@ if (preg_match('/Release (1[1]\.2|12)\./', oci_server_version($c), $matches) !== * already */ +$testuser = 'testuser_attr_1'; // Used in conn_attr.inc +$testpassword = 'testuser'; + require(dirname(__FILE__)."/conn_attr.inc"); function select_fn($conn) { @@ -39,7 +51,7 @@ function select_fn($conn) { select from both the editions and verify the contents. */ set_edit_attr('MYEDITION'); -$conn = oci_connect('testuser','testuser',$dbase); +$conn = oci_connect($testuser,$testpassword,$dbase); if ($conn === false) { $m = oci_error(); die("Error:" . $m['message']); @@ -61,7 +73,7 @@ select_fn($conn); // Create a different version of view_ed in MYEDITION1. set_edit_attr('MYEDITION1'); -$conn2 = oci_new_connect('testuser','testuser',$dbase); +$conn2 = oci_new_connect($testuser,$testpassword,$dbase); $stmt = "create or replace editioning view view_ed as select name,age,job,salary from edit_tab"; $s = oci_parse($conn2, $stmt); oci_execute($s); @@ -87,58 +99,58 @@ The value of edition has been successfully set The value of current EDITION is MYEDITION array(3) { [0]=> - %unicode|string%(%d) "mike" + string(%d) "mike" [1]=> - %unicode|string%(%d) "30" + string(%d) "30" [2]=> - %unicode|string%(%d) "Senior engineer" + string(%d) "Senior engineer" } array(3) { [0]=> - %unicode|string%(%d) "juan" + string(%d) "juan" [1]=> - %unicode|string%(%d) "25" + string(%d) "25" [2]=> - %unicode|string%(%d) "engineer" + string(%d) "engineer" } The value of edition has been successfully set The value of current EDITION is MYEDITION1 array(4) { [0]=> - %unicode|string%(%d) "mike" + string(%d) "mike" [1]=> - %unicode|string%(%d) "30" + string(%d) "30" [2]=> - %unicode|string%(%d) "Senior engineer" + string(%d) "Senior engineer" [3]=> - %unicode|string%(%d) "200" + string(%d) "200" } array(4) { [0]=> - %unicode|string%(%d) "juan" + string(%d) "juan" [1]=> - %unicode|string%(%d) "25" + string(%d) "25" [2]=> - %unicode|string%(%d) "engineer" + string(%d) "engineer" [3]=> - %unicode|string%(%d) "100" + string(%d) "100" } version of view_ed in MYEDITION The value of current EDITION is MYEDITION array(3) { [0]=> - %unicode|string%(%d) "mike" + string(%d) "mike" [1]=> - %unicode|string%(%d) "30" + string(%d) "30" [2]=> - %unicode|string%(%d) "Senior engineer" + string(%d) "Senior engineer" } array(3) { [0]=> - %unicode|string%(%d) "juan" + string(%d) "juan" [1]=> - %unicode|string%(%d) "25" + string(%d) "25" [2]=> - %unicode|string%(%d) "engineer" + string(%d) "engineer" } Done diff --git a/ext/oci8/tests/edition_2.phpt b/ext/oci8/tests/edition_2.phpt index 030e6a673c..12e902667e 100644 --- a/ext/oci8/tests/edition_2.phpt +++ b/ext/oci8/tests/edition_2.phpt @@ -8,10 +8,18 @@ if (strcasecmp($user, "system") && strcasecmp($user, "sys")) die("skip needs to be run as a DBA user"); if ($test_drcp) die("skip as Output might vary with DRCP"); - -if (preg_match('/Release (1[1]\.2|12)\./', oci_server_version($c), $matches) !== 1) { - die("skip expected output only valid when using Oracle 11gR2 or greater databases"); -} else if (preg_match('/^(11\.2|12)\./', oci_client_version()) != 1) { +preg_match('/.*Release ([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)*/', oci_server_version($c), $matches); +if (!(isset($matches[0]) && + (($matches[1] == 11 && $matches[2] >= 2) || + ($matches[1] >= 12) + ))) { + die("skip expected output only valid when using Oracle 11gR2 or greater database server"); +} +preg_match('/^([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)/', oci_client_version(), $matches); +if (!(isset($matches[0]) && + (($matches[1] == 11 && $matches[2] >= 2) || + ($matches[1] >= 12) + ))) { die("skip test expected to work only with Oracle 11gR2 or greater version of client"); } @@ -24,10 +32,10 @@ if (preg_match('/Release (1[1]\.2|12)\./', oci_server_version($c), $matches) !== * already */ -require(dirname(__FILE__)."/conn_attr.inc"); +$testuser = 'testuser_ed_2'; // Used in conn_attr.inc +$testpassword = 'testuser'; -$user = 'testuser'; -$password = 'testuser'; +require(dirname(__FILE__)."/conn_attr.inc"); echo"**Test 1.1 - Default value for the attribute **************\n"; get_edit_attr($c); @@ -50,7 +58,7 @@ get_edit_attr($conn3); oci_close($conn1); // With a oci_pconnect with a different charset. -$pc1 = oci_pconnect($user,$password,$dbase,"utf8"); +$pc1 = oci_pconnect($testuser,$testpassword,$dbase,"utf8"); get_edit_attr($pc1); oci_close($pc1); @@ -145,7 +153,7 @@ function set_scope() { } function get_scope() { - $sc1 = oci_connect($GLOBALS['user'],$GLOBALS['password'],$GLOBALS['dbase']); + $sc1 = oci_connect($GLOBALS['testuser'],$GLOBALS['testpassword'],$GLOBALS['dbase']); if ($sc1 === false) { $m = oci_error(); die("Error:" . $m['message']); diff --git a/ext/oci8/tests/error_set.phpt b/ext/oci8/tests/error_set.phpt new file mode 100644 index 0000000000..ad56e8aefa --- /dev/null +++ b/ext/oci8/tests/error_set.phpt @@ -0,0 +1,72 @@ +--TEST-- +Check oci_set_{action,client_identifier,module_name,client_info} error handling +--SKIPIF-- +<?php if (!extension_loaded('oci8')) die ("skip no oci8 extension"); ?> +--FILE-- +<?php + +require(dirname(__FILE__).'/connect.inc'); + +error_reporting(E_ALL); +ini_set('display_errors', 'Off'); + +echo "Test 1\n"; + +// Generates "ORA-24960: the attribute OCI_ATTR_* is greater than the maximum allowable length of 64" +$s = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; + +$r = oci_set_action($c, $s); +var_dump($r); +$m = oci_error($c); +echo $m['code'] , "\n"; + +$r = oci_set_client_identifier($c, $s); +var_dump($r); +$m = oci_error($c); +echo $m['code'] , "\n"; + +$r = oci_set_module_name($c, $s); +var_dump($r); +$m = oci_error($c); +echo $m['code'] , "\n"; + +$r = oci_set_client_info($c, $s); +var_dump($r); +$m = oci_error($c); +echo $m['code'] , "\n"; + +echo "\nTest 2\n"; +$s = "x"; + +$r = oci_set_action($c, $s); +var_dump($r); + +$r = oci_set_client_identifier($c, $s); +var_dump($r); + +$r = oci_set_module_name($c, $s); +var_dump($r); + +$r = oci_set_client_info($c, $s); +var_dump($r); + +?> +===DONE=== +<?php exit(0); ?> +--EXPECTF-- +Test 1 +bool(false) +24960 +bool(false) +24960 +bool(false) +24960 +bool(false) +24960 + +Test 2 +bool(true) +bool(true) +bool(true) +bool(true) +===DONE=== diff --git a/ext/oci8/tests/extauth_01.phpt b/ext/oci8/tests/extauth_01.phpt index 37f8f3834d..1194ae180d 100644 --- a/ext/oci8/tests/extauth_01.phpt +++ b/ext/oci8/tests/extauth_01.phpt @@ -143,56 +143,56 @@ Test 7 Warning: oci_connect(): ORA-12154: %s in %s on line %d array(4) { - [%u|b%"code"]=> + ["code"]=> int(12154) - [%u|b%"message"]=> - %unicode|string%(%d) "ORA-12154: %s" - [%u|b%"offset"]=> + ["message"]=> + string(%d) "ORA-12154: %s" + ["offset"]=> int(0) - [%u|b%"sqltext"]=> - %unicode|string%(0) "" + ["sqltext"]=> + string(0) "" } bool(false) Test 8 Warning: oci_connect(): ORA-12154: %s in %s on line %d array(4) { - [%u|b%"code"]=> + ["code"]=> int(12154) - [%u|b%"message"]=> - %unicode|string%(%d) "ORA-12154: %s" - [%u|b%"offset"]=> + ["message"]=> + string(%d) "ORA-12154: %s" + ["offset"]=> int(0) - [%u|b%"sqltext"]=> - %unicode|string%(0) "" + ["sqltext"]=> + string(0) "" } bool(false) Test 9 Warning: oci_connect(): ORA-%d: TNS:%s in %s on line %d array(4) { - [%u|b%"code"]=> + ["code"]=> int(%d) - [%u|b%"message"]=> - %unicode|string%(%d) "ORA-%d: %s" - [%u|b%"offset"]=> + ["message"]=> + string(%d) "ORA-%d: %s" + ["offset"]=> int(0) - [%u|b%"sqltext"]=> - %unicode|string%(0) "" + ["sqltext"]=> + string(0) "" } bool(false) Test 10 Warning: oci_connect(): ORA-%d: TNS:%s in %s on line %d array(4) { - [%u|b%"code"]=> + ["code"]=> int(%d) - [%u|b%"message"]=> - %unicode|string%(%d) "ORA-%d: %s" - [%u|b%"offset"]=> + ["message"]=> + string(%d) "ORA-%d: %s" + ["offset"]=> int(0) - [%u|b%"sqltext"]=> - %unicode|string%(0) "" + ["sqltext"]=> + string(0) "" } bool(false) ===DONE=== diff --git a/ext/oci8/tests/extauth_02.phpt b/ext/oci8/tests/extauth_02.phpt index f3b517f730..0a3227019c 100644 --- a/ext/oci8/tests/extauth_02.phpt +++ b/ext/oci8/tests/extauth_02.phpt @@ -142,56 +142,56 @@ Test 7 Warning: oci_new_connect(): ORA-12154: %s in %s on line %d array(4) { - [%u|b%"code"]=> + ["code"]=> int(12154) - [%u|b%"message"]=> - %unicode|string%(%d) "ORA-12154: %s" - [%u|b%"offset"]=> + ["message"]=> + string(%d) "ORA-12154: %s" + ["offset"]=> int(0) - [%u|b%"sqltext"]=> - %unicode|string%(0) "" + ["sqltext"]=> + string(0) "" } bool(false) Test 8 Warning: oci_new_connect(): ORA-12154: %s in %s on line %d array(4) { - [%u|b%"code"]=> + ["code"]=> int(12154) - [%u|b%"message"]=> - %unicode|string%(%d) "ORA-12154: %s" - [%u|b%"offset"]=> + ["message"]=> + string(%d) "ORA-12154: %s" + ["offset"]=> int(0) - [%u|b%"sqltext"]=> - %unicode|string%(0) "" + ["sqltext"]=> + string(0) "" } bool(false) Test 9 Warning: oci_new_connect(): ORA-%d: TNS:%s %s on line %d array(4) { - [%u|b%"code"]=> + ["code"]=> int(%d) - [%u|b%"message"]=> - %unicode|string%(%d) "ORA-%d: %s" - [%u|b%"offset"]=> + ["message"]=> + string(%d) "ORA-%d: %s" + ["offset"]=> int(0) - [%u|b%"sqltext"]=> - %unicode|string%(0) "" + ["sqltext"]=> + string(0) "" } bool(false) Test 10 Warning: oci_new_connect(): ORA-%d: TNS:%s %s on line %d array(4) { - [%u|b%"code"]=> + ["code"]=> int(%d) - [%u|b%"message"]=> - %unicode|string%(%d) "ORA-%d: %s" - [%u|b%"offset"]=> + ["message"]=> + string(%d) "ORA-%d: %s" + ["offset"]=> int(0) - [%u|b%"sqltext"]=> - %unicode|string%(0) "" + ["sqltext"]=> + string(0) "" } bool(false) ===DONE=== diff --git a/ext/oci8/tests/extauth_03.phpt b/ext/oci8/tests/extauth_03.phpt index e6685eb176..d7884ce6b4 100644 --- a/ext/oci8/tests/extauth_03.phpt +++ b/ext/oci8/tests/extauth_03.phpt @@ -142,56 +142,56 @@ Test 7 Warning: oci_pconnect(): ORA-12154: %s in %s on line %d array(4) { - [%u|b%"code"]=> + ["code"]=> int(12154) - [%u|b%"message"]=> - %unicode|string%(%d) "ORA-12154: %s" - [%u|b%"offset"]=> + ["message"]=> + string(%d) "ORA-12154: %s" + ["offset"]=> int(0) - [%u|b%"sqltext"]=> - %unicode|string%(0) "" + ["sqltext"]=> + string(0) "" } bool(false) Test 8 Warning: oci_pconnect(): ORA-12154: %s in %s on line %d array(4) { - [%u|b%"code"]=> + ["code"]=> int(12154) - [%u|b%"message"]=> - %unicode|string%(%d) "ORA-12154: %s" - [%u|b%"offset"]=> + ["message"]=> + string(%d) "ORA-12154: %s" + ["offset"]=> int(0) - [%u|b%"sqltext"]=> - %unicode|string%(0) "" + ["sqltext"]=> + string(0) "" } bool(false) Test 9 Warning: oci_pconnect(): ORA-%d: TNS:%s in %s on line %d array(4) { - [%u|b%"code"]=> + ["code"]=> int(%d) - [%u|b%"message"]=> - %unicode|string%(%d) "ORA-%d: %s" - [%u|b%"offset"]=> + ["message"]=> + string(%d) "ORA-%d: %s" + ["offset"]=> int(0) - [%u|b%"sqltext"]=> - %unicode|string%(0) "" + ["sqltext"]=> + string(0) "" } bool(false) Test 10 Warning: oci_pconnect(): ORA-%d: TNS:%s in %s on line %d array(4) { - [%u|b%"code"]=> + ["code"]=> int(%d) - [%u|b%"message"]=> - %unicode|string%(%d) "ORA-%d: %s" - [%u|b%"offset"]=> + ["message"]=> + string(%d) "ORA-%d: %s" + ["offset"]=> int(0) - [%u|b%"sqltext"]=> - %unicode|string%(0) "" + ["sqltext"]=> + string(0) "" } bool(false) ===DONE=== diff --git a/ext/oci8/tests/fetch.phpt b/ext/oci8/tests/fetch.phpt index e48aeefd87..b968ae4bf6 100644 --- a/ext/oci8/tests/fetch.phpt +++ b/ext/oci8/tests/fetch.phpt @@ -47,10 +47,10 @@ oci8_test_sql_execute($c, $stmtarray); echo "Done\n"; ?> --EXPECTF-- -%unicode|string%(1) "1" -%unicode|string%(1) "1" -%unicode|string%(1) "1" -%unicode|string%(1) "1" -%unicode|string%(1) "1" -%unicode|string%(1) "1" +string(1) "1" +string(1) "1" +string(1) "1" +string(1) "1" +string(1) "1" +string(1) "1" Done diff --git a/ext/oci8/tests/fetch_all.phpt b/ext/oci8/tests/fetch_all.phpt index 4fc41daad4..b8155b170b 100644 --- a/ext/oci8/tests/fetch_all.phpt +++ b/ext/oci8/tests/fetch_all.phpt @@ -51,44 +51,44 @@ echo "Done\n"; --EXPECTF-- int(3) array(2) { - [%u|b%"ID"]=> + ["ID"]=> array(3) { [0]=> - %unicode|string%(1) "1" + string(1) "1" [1]=> - %unicode|string%(1) "1" + string(1) "1" [2]=> - %unicode|string%(1) "1" + string(1) "1" } - [%u|b%"VALUE"]=> + ["VALUE"]=> array(3) { [0]=> - %unicode|string%(1) "1" + string(1) "1" [1]=> - %unicode|string%(1) "1" + string(1) "1" [2]=> - %unicode|string%(1) "1" + string(1) "1" } } int(3) array(2) { - [%u|b%"ID"]=> + ["ID"]=> array(3) { [0]=> - %unicode|string%(1) "1" + string(1) "1" [1]=> - %unicode|string%(1) "1" + string(1) "1" [2]=> - %unicode|string%(1) "1" + string(1) "1" } - [%u|b%"VALUE"]=> + ["VALUE"]=> array(3) { [0]=> - %unicode|string%(1) "1" + string(1) "1" [1]=> - %unicode|string%(1) "1" + string(1) "1" [2]=> - %unicode|string%(1) "1" + string(1) "1" } } Done diff --git a/ext/oci8/tests/fetch_all1.phpt b/ext/oci8/tests/fetch_all1.phpt index 4fc41daad4..b8155b170b 100644 --- a/ext/oci8/tests/fetch_all1.phpt +++ b/ext/oci8/tests/fetch_all1.phpt @@ -51,44 +51,44 @@ echo "Done\n"; --EXPECTF-- int(3) array(2) { - [%u|b%"ID"]=> + ["ID"]=> array(3) { [0]=> - %unicode|string%(1) "1" + string(1) "1" [1]=> - %unicode|string%(1) "1" + string(1) "1" [2]=> - %unicode|string%(1) "1" + string(1) "1" } - [%u|b%"VALUE"]=> + ["VALUE"]=> array(3) { [0]=> - %unicode|string%(1) "1" + string(1) "1" [1]=> - %unicode|string%(1) "1" + string(1) "1" [2]=> - %unicode|string%(1) "1" + string(1) "1" } } int(3) array(2) { - [%u|b%"ID"]=> + ["ID"]=> array(3) { [0]=> - %unicode|string%(1) "1" + string(1) "1" [1]=> - %unicode|string%(1) "1" + string(1) "1" [2]=> - %unicode|string%(1) "1" + string(1) "1" } - [%u|b%"VALUE"]=> + ["VALUE"]=> array(3) { [0]=> - %unicode|string%(1) "1" + string(1) "1" [1]=> - %unicode|string%(1) "1" + string(1) "1" [2]=> - %unicode|string%(1) "1" + string(1) "1" } } Done diff --git a/ext/oci8/tests/fetch_all3.phpt b/ext/oci8/tests/fetch_all3.phpt index 1748ea5658..4c0be1cc07 100644 --- a/ext/oci8/tests/fetch_all3.phpt +++ b/ext/oci8/tests/fetch_all3.phpt @@ -129,105 +129,105 @@ echo "Done\n"; None int(4) array(2) { - [%u|b%"ID"]=> + ["ID"]=> array(4) { [0]=> - %unicode|string%(1) "1" + string(1) "1" [1]=> - %unicode|string%(1) "2" + string(1) "2" [2]=> - %unicode|string%(1) "3" + string(1) "3" [3]=> - %unicode|string%(1) "4" + string(1) "4" } - [%u|b%"VALUE"]=> + ["VALUE"]=> array(4) { [0]=> - %unicode|string%(2) "-1" + string(2) "-1" [1]=> - %unicode|string%(2) "-2" + string(2) "-2" [2]=> - %unicode|string%(2) "-3" + string(2) "-3" [3]=> - %unicode|string%(2) "-4" + string(2) "-4" } } OCI_ASSOC int(4) array(2) { - [%u|b%"ID"]=> + ["ID"]=> array(4) { [0]=> - %unicode|string%(1) "1" + string(1) "1" [1]=> - %unicode|string%(1) "2" + string(1) "2" [2]=> - %unicode|string%(1) "3" + string(1) "3" [3]=> - %unicode|string%(1) "4" + string(1) "4" } - [%u|b%"VALUE"]=> + ["VALUE"]=> array(4) { [0]=> - %unicode|string%(2) "-1" + string(2) "-1" [1]=> - %unicode|string%(2) "-2" + string(2) "-2" [2]=> - %unicode|string%(2) "-3" + string(2) "-3" [3]=> - %unicode|string%(2) "-4" + string(2) "-4" } } OCI_FETCHSTATEMENT_BY_COLUMN int(4) array(2) { - [%u|b%"ID"]=> + ["ID"]=> array(4) { [0]=> - %unicode|string%(1) "1" + string(1) "1" [1]=> - %unicode|string%(1) "2" + string(1) "2" [2]=> - %unicode|string%(1) "3" + string(1) "3" [3]=> - %unicode|string%(1) "4" + string(1) "4" } - [%u|b%"VALUE"]=> + ["VALUE"]=> array(4) { [0]=> - %unicode|string%(2) "-1" + string(2) "-1" [1]=> - %unicode|string%(2) "-2" + string(2) "-2" [2]=> - %unicode|string%(2) "-3" + string(2) "-3" [3]=> - %unicode|string%(2) "-4" + string(2) "-4" } } OCI_FETCHSTATEMENT_BY_COLUMN|OCI_ASSOC int(4) array(2) { - [%u|b%"ID"]=> + ["ID"]=> array(4) { [0]=> - %unicode|string%(1) "1" + string(1) "1" [1]=> - %unicode|string%(1) "2" + string(1) "2" [2]=> - %unicode|string%(1) "3" + string(1) "3" [3]=> - %unicode|string%(1) "4" + string(1) "4" } - [%u|b%"VALUE"]=> + ["VALUE"]=> array(4) { [0]=> - %unicode|string%(2) "-1" + string(2) "-1" [1]=> - %unicode|string%(2) "-2" + string(2) "-2" [2]=> - %unicode|string%(2) "-3" + string(2) "-3" [3]=> - %unicode|string%(2) "-4" + string(2) "-4" } } OCI_FETCHSTATEMENT_BY_COLUMN|OCI_NUM @@ -236,24 +236,24 @@ array(2) { [0]=> array(4) { [0]=> - %unicode|string%(1) "1" + string(1) "1" [1]=> - %unicode|string%(1) "2" + string(1) "2" [2]=> - %unicode|string%(1) "3" + string(1) "3" [3]=> - %unicode|string%(1) "4" + string(1) "4" } [1]=> array(4) { [0]=> - %unicode|string%(2) "-1" + string(2) "-1" [1]=> - %unicode|string%(2) "-2" + string(2) "-2" [2]=> - %unicode|string%(2) "-3" + string(2) "-3" [3]=> - %unicode|string%(2) "-4" + string(2) "-4" } } OCI_FETCHSTATEMENT_BY_COLUMN|OCI_NUM|OCI_ASSOC @@ -262,24 +262,24 @@ array(2) { [0]=> array(4) { [0]=> - %unicode|string%(1) "1" + string(1) "1" [1]=> - %unicode|string%(1) "2" + string(1) "2" [2]=> - %unicode|string%(1) "3" + string(1) "3" [3]=> - %unicode|string%(1) "4" + string(1) "4" } [1]=> array(4) { [0]=> - %unicode|string%(2) "-1" + string(2) "-1" [1]=> - %unicode|string%(2) "-2" + string(2) "-2" [2]=> - %unicode|string%(2) "-3" + string(2) "-3" [3]=> - %unicode|string%(2) "-4" + string(2) "-4" } } OCI_FETCHSTATEMENT_BY_ROW @@ -287,31 +287,31 @@ int(4) array(4) { [0]=> array(2) { - [%u|b%"ID"]=> - %unicode|string%(1) "1" - [%u|b%"VALUE"]=> - %unicode|string%(2) "-1" + ["ID"]=> + string(1) "1" + ["VALUE"]=> + string(2) "-1" } [1]=> array(2) { - [%u|b%"ID"]=> - %unicode|string%(1) "2" - [%u|b%"VALUE"]=> - %unicode|string%(2) "-2" + ["ID"]=> + string(1) "2" + ["VALUE"]=> + string(2) "-2" } [2]=> array(2) { - [%u|b%"ID"]=> - %unicode|string%(1) "3" - [%u|b%"VALUE"]=> - %unicode|string%(2) "-3" + ["ID"]=> + string(1) "3" + ["VALUE"]=> + string(2) "-3" } [3]=> array(2) { - [%u|b%"ID"]=> - %unicode|string%(1) "4" - [%u|b%"VALUE"]=> - %unicode|string%(2) "-4" + ["ID"]=> + string(1) "4" + ["VALUE"]=> + string(2) "-4" } } OCI_FETCHSTATEMENT_BY_ROW|OCI_ASSOC @@ -319,31 +319,31 @@ int(4) array(4) { [0]=> array(2) { - [%u|b%"ID"]=> - %unicode|string%(1) "1" - [%u|b%"VALUE"]=> - %unicode|string%(2) "-1" + ["ID"]=> + string(1) "1" + ["VALUE"]=> + string(2) "-1" } [1]=> array(2) { - [%u|b%"ID"]=> - %unicode|string%(1) "2" - [%u|b%"VALUE"]=> - %unicode|string%(2) "-2" + ["ID"]=> + string(1) "2" + ["VALUE"]=> + string(2) "-2" } [2]=> array(2) { - [%u|b%"ID"]=> - %unicode|string%(1) "3" - [%u|b%"VALUE"]=> - %unicode|string%(2) "-3" + ["ID"]=> + string(1) "3" + ["VALUE"]=> + string(2) "-3" } [3]=> array(2) { - [%u|b%"ID"]=> - %unicode|string%(1) "4" - [%u|b%"VALUE"]=> - %unicode|string%(2) "-4" + ["ID"]=> + string(1) "4" + ["VALUE"]=> + string(2) "-4" } } OCI_FETCHSTATEMENT_BY_ROW|OCI_FETCHSTATEMENT_BY_COLUMN @@ -351,31 +351,31 @@ int(4) array(4) { [0]=> array(2) { - [%u|b%"ID"]=> - %unicode|string%(1) "1" - [%u|b%"VALUE"]=> - %unicode|string%(2) "-1" + ["ID"]=> + string(1) "1" + ["VALUE"]=> + string(2) "-1" } [1]=> array(2) { - [%u|b%"ID"]=> - %unicode|string%(1) "2" - [%u|b%"VALUE"]=> - %unicode|string%(2) "-2" + ["ID"]=> + string(1) "2" + ["VALUE"]=> + string(2) "-2" } [2]=> array(2) { - [%u|b%"ID"]=> - %unicode|string%(1) "3" - [%u|b%"VALUE"]=> - %unicode|string%(2) "-3" + ["ID"]=> + string(1) "3" + ["VALUE"]=> + string(2) "-3" } [3]=> array(2) { - [%u|b%"ID"]=> - %unicode|string%(1) "4" - [%u|b%"VALUE"]=> - %unicode|string%(2) "-4" + ["ID"]=> + string(1) "4" + ["VALUE"]=> + string(2) "-4" } } OCI_FETCHSTATEMENT_BY_ROW|OCI_FETCHSTATEMENT_BY_COLUMN|OCI_ASSOC @@ -383,31 +383,31 @@ int(4) array(4) { [0]=> array(2) { - [%u|b%"ID"]=> - %unicode|string%(1) "1" - [%u|b%"VALUE"]=> - %unicode|string%(2) "-1" + ["ID"]=> + string(1) "1" + ["VALUE"]=> + string(2) "-1" } [1]=> array(2) { - [%u|b%"ID"]=> - %unicode|string%(1) "2" - [%u|b%"VALUE"]=> - %unicode|string%(2) "-2" + ["ID"]=> + string(1) "2" + ["VALUE"]=> + string(2) "-2" } [2]=> array(2) { - [%u|b%"ID"]=> - %unicode|string%(1) "3" - [%u|b%"VALUE"]=> - %unicode|string%(2) "-3" + ["ID"]=> + string(1) "3" + ["VALUE"]=> + string(2) "-3" } [3]=> array(2) { - [%u|b%"ID"]=> - %unicode|string%(1) "4" - [%u|b%"VALUE"]=> - %unicode|string%(2) "-4" + ["ID"]=> + string(1) "4" + ["VALUE"]=> + string(2) "-4" } } OCI_FETCHSTATEMENT_BY_ROW|OCI_FETCHSTATEMENT_BY_COLUMN|OCI_NUM @@ -416,30 +416,30 @@ array(4) { [0]=> array(2) { [0]=> - %unicode|string%(1) "1" + string(1) "1" [1]=> - %unicode|string%(2) "-1" + string(2) "-1" } [1]=> array(2) { [0]=> - %unicode|string%(1) "2" + string(1) "2" [1]=> - %unicode|string%(2) "-2" + string(2) "-2" } [2]=> array(2) { [0]=> - %unicode|string%(1) "3" + string(1) "3" [1]=> - %unicode|string%(2) "-3" + string(2) "-3" } [3]=> array(2) { [0]=> - %unicode|string%(1) "4" + string(1) "4" [1]=> - %unicode|string%(2) "-4" + string(2) "-4" } } OCI_FETCHSTATEMENT_BY_ROW|OCI_FETCHSTATEMENT_BY_COLUMN|OCI_NUM|OCI_ASSOC @@ -448,30 +448,30 @@ array(4) { [0]=> array(2) { [0]=> - %unicode|string%(1) "1" + string(1) "1" [1]=> - %unicode|string%(2) "-1" + string(2) "-1" } [1]=> array(2) { [0]=> - %unicode|string%(1) "2" + string(1) "2" [1]=> - %unicode|string%(2) "-2" + string(2) "-2" } [2]=> array(2) { [0]=> - %unicode|string%(1) "3" + string(1) "3" [1]=> - %unicode|string%(2) "-3" + string(2) "-3" } [3]=> array(2) { [0]=> - %unicode|string%(1) "4" + string(1) "4" [1]=> - %unicode|string%(2) "-4" + string(2) "-4" } } OCI_FETCHSTATEMENT_BY_ROW|OCI_NUM @@ -480,30 +480,30 @@ array(4) { [0]=> array(2) { [0]=> - %unicode|string%(1) "1" + string(1) "1" [1]=> - %unicode|string%(2) "-1" + string(2) "-1" } [1]=> array(2) { [0]=> - %unicode|string%(1) "2" + string(1) "2" [1]=> - %unicode|string%(2) "-2" + string(2) "-2" } [2]=> array(2) { [0]=> - %unicode|string%(1) "3" + string(1) "3" [1]=> - %unicode|string%(2) "-3" + string(2) "-3" } [3]=> array(2) { [0]=> - %unicode|string%(1) "4" + string(1) "4" [1]=> - %unicode|string%(2) "-4" + string(2) "-4" } } OCI_FETCHSTATEMENT_BY_ROW|OCI_NUM|OCI_ASSOC @@ -512,30 +512,30 @@ array(4) { [0]=> array(2) { [0]=> - %unicode|string%(1) "1" + string(1) "1" [1]=> - %unicode|string%(2) "-1" + string(2) "-1" } [1]=> array(2) { [0]=> - %unicode|string%(1) "2" + string(1) "2" [1]=> - %unicode|string%(2) "-2" + string(2) "-2" } [2]=> array(2) { [0]=> - %unicode|string%(1) "3" + string(1) "3" [1]=> - %unicode|string%(2) "-3" + string(2) "-3" } [3]=> array(2) { [0]=> - %unicode|string%(1) "4" + string(1) "4" [1]=> - %unicode|string%(2) "-4" + string(2) "-4" } } OCI_NUM @@ -544,24 +544,24 @@ array(2) { [0]=> array(4) { [0]=> - %unicode|string%(1) "1" + string(1) "1" [1]=> - %unicode|string%(1) "2" + string(1) "2" [2]=> - %unicode|string%(1) "3" + string(1) "3" [3]=> - %unicode|string%(1) "4" + string(1) "4" } [1]=> array(4) { [0]=> - %unicode|string%(2) "-1" + string(2) "-1" [1]=> - %unicode|string%(2) "-2" + string(2) "-2" [2]=> - %unicode|string%(2) "-3" + string(2) "-3" [3]=> - %unicode|string%(2) "-4" + string(2) "-4" } } OCI_NUM|OCI_ASSOC @@ -570,24 +570,24 @@ array(2) { [0]=> array(4) { [0]=> - %unicode|string%(1) "1" + string(1) "1" [1]=> - %unicode|string%(1) "2" + string(1) "2" [2]=> - %unicode|string%(1) "3" + string(1) "3" [3]=> - %unicode|string%(1) "4" + string(1) "4" } [1]=> array(4) { [0]=> - %unicode|string%(2) "-1" + string(2) "-1" [1]=> - %unicode|string%(2) "-2" + string(2) "-2" [2]=> - %unicode|string%(2) "-3" + string(2) "-3" [3]=> - %unicode|string%(2) "-4" + string(2) "-4" } } Done diff --git a/ext/oci8/tests/fetch_all4.phpt b/ext/oci8/tests/fetch_all4.phpt index 1d3c9677ee..1d4a8df7b7 100644 --- a/ext/oci8/tests/fetch_all4.phpt +++ b/ext/oci8/tests/fetch_all4.phpt @@ -51,10 +51,10 @@ oci8_test_sql_execute($c, $stmtarray); Test 1 int(0) array(2) { - [%u|b%"MYCOL1"]=> + ["MYCOL1"]=> array(0) { } - [%u|b%"MYCOL2"]=> + ["MYCOL2"]=> array(0) { } } diff --git a/ext/oci8/tests/fetch_all5.phpt b/ext/oci8/tests/fetch_all5.phpt index a6bb3c3f18..d82fd30e41 100644 --- a/ext/oci8/tests/fetch_all5.phpt +++ b/ext/oci8/tests/fetch_all5.phpt @@ -62,45 +62,45 @@ oci_close($c); Test 1 int(3) array(2) { - [%u|b%"MYCOL1"]=> + ["MYCOL1"]=> array(3) { [0]=> - %unicode|string%(1) "1" + string(1) "1" [1]=> - %unicode|string%(1) "2" + string(1) "2" [2]=> - %unicode|string%(1) "3" + string(1) "3" } - [%u|b%"MYCOL2"]=> + ["MYCOL2"]=> array(3) { [0]=> - %unicode|string%(3) "abc" + string(3) "abc" [1]=> - %unicode|string%(3) "def" + string(3) "def" [2]=> - %unicode|string%(3) "ghi" + string(3) "ghi" } } Test 1 int(3) array(2) { - [%u|b%"MYCOL1"]=> + ["MYCOL1"]=> array(3) { [0]=> - %unicode|string%(1) "1" + string(1) "1" [1]=> - %unicode|string%(1) "2" + string(1) "2" [2]=> - %unicode|string%(1) "3" + string(1) "3" } - [%u|b%"MYCOL2"]=> + ["MYCOL2"]=> array(3) { [0]=> - %unicode|string%(3) "abc" + string(3) "abc" [1]=> - %unicode|string%(3) "def" + string(3) "def" [2]=> - %unicode|string%(3) "ghi" + string(3) "ghi" } } Test 3 diff --git a/ext/oci8/tests/fetch_into.phpt b/ext/oci8/tests/fetch_into.phpt index 45a6a8132e..d90c4d95dc 100644 --- a/ext/oci8/tests/fetch_into.phpt +++ b/ext/oci8/tests/fetch_into.phpt @@ -53,19 +53,19 @@ echo "Done\n"; int(2) array(2) { [0]=> - %unicode|string%(1) "1" + string(1) "1" [1]=> - %unicode|string%(1) "1" + string(1) "1" } int(2) array(4) { [0]=> - %unicode|string%(1) "1" - [%u|b%"ID"]=> - %unicode|string%(1) "1" + string(1) "1" + ["ID"]=> + string(1) "1" [1]=> - %unicode|string%(1) "1" - [%u|b%"VALUE"]=> - %unicode|string%(1) "1" + string(1) "1" + ["VALUE"]=> + string(1) "1" } Done diff --git a/ext/oci8/tests/fetch_object.phpt b/ext/oci8/tests/fetch_object.phpt index 1c290d5e95..73711baa18 100644 --- a/ext/oci8/tests/fetch_object.phpt +++ b/ext/oci8/tests/fetch_object.phpt @@ -82,28 +82,28 @@ oci8_test_sql_execute($c, $stmtarray); --EXPECTF-- Test 1 object(stdClass)#1 (3) { - [%u|b%"caseSensitive"]=> - %unicode|string%(3) "123" - [%u|b%"SECONDCOL"]=> - %unicode|string%(19) "1st row col2 string" - [%u|b%"ANOTHERCOL"]=> - %unicode|string%(15) "1 more text " + ["caseSensitive"]=> + string(3) "123" + ["SECONDCOL"]=> + string(19) "1st row col2 string" + ["ANOTHERCOL"]=> + string(15) "1 more text " } object(stdClass)#2 (3) { - [%u|b%"caseSensitive"]=> - %unicode|string%(3) "456" - [%u|b%"SECONDCOL"]=> - %unicode|string%(19) "2nd row col2 string" - [%u|b%"ANOTHERCOL"]=> - %unicode|string%(15) "2 more text " + ["caseSensitive"]=> + string(3) "456" + ["SECONDCOL"]=> + string(19) "2nd row col2 string" + ["ANOTHERCOL"]=> + string(15) "2 more text " } object(stdClass)#1 (3) { - [%u|b%"caseSensitive"]=> - %unicode|string%(3) "789" - [%u|b%"SECONDCOL"]=> - %unicode|string%(19) "3rd row col2 string" - [%u|b%"ANOTHERCOL"]=> - %unicode|string%(15) "3 more text " + ["caseSensitive"]=> + string(3) "789" + ["SECONDCOL"]=> + string(19) "3rd row col2 string" + ["ANOTHERCOL"]=> + string(15) "3 more text " } Test 2 123 diff --git a/ext/oci8/tests/fetch_row.phpt b/ext/oci8/tests/fetch_row.phpt index 2b28634ab3..40bc4f893c 100644 --- a/ext/oci8/tests/fetch_row.phpt +++ b/ext/oci8/tests/fetch_row.phpt @@ -46,20 +46,20 @@ echo "Done\n"; --EXPECTF-- array(2) { [0]=> - %unicode|string%(1) "1" + string(1) "1" [1]=> - %unicode|string%(1) "1" + string(1) "1" } array(2) { [0]=> - %unicode|string%(1) "1" + string(1) "1" [1]=> - %unicode|string%(1) "1" + string(1) "1" } array(2) { [0]=> - %unicode|string%(1) "1" + string(1) "1" [1]=> - %unicode|string%(1) "1" + string(1) "1" } Done diff --git a/ext/oci8/tests/field_funcs1.phpt b/ext/oci8/tests/field_funcs1.phpt index c14ee8957e..41d8627ce4 100644 --- a/ext/oci8/tests/field_funcs1.phpt +++ b/ext/oci8/tests/field_funcs1.phpt @@ -85,9 +85,9 @@ echo "Done\n"; --EXPECTF-- array(2) { [0]=> - %unicode|string%(1) "1" + string(1) "1" [1]=> - %unicode|string%(1) "1" + string(1) "1" } Test 1 diff --git a/ext/oci8/tests/function_aliases.phpt b/ext/oci8/tests/function_aliases.phpt index 4c6ce83759..2c890d6403 100644 --- a/ext/oci8/tests/function_aliases.phpt +++ b/ext/oci8/tests/function_aliases.phpt @@ -104,8 +104,6 @@ NULL Warning: ocifreestatement() expects exactly 1 parameter, 0 given in %s on line %d NULL - -Warning: ociinternaldebug() expects exactly 1 parameter, 0 given in %s on line %d NULL Warning: ocinumcols() expects exactly 1 parameter, 0 given in %s on line %d diff --git a/ext/oci8/tests/imp_res_1.phpt b/ext/oci8/tests/imp_res_1.phpt new file mode 100644 index 0000000000..a36f89f4da --- /dev/null +++ b/ext/oci8/tests/imp_res_1.phpt @@ -0,0 +1,630 @@ +--TEST-- +Oracle Database 12c Implicit Result Sets: basic test +--SKIPIF-- +<?php +if (!extension_loaded('oci8')) die ("skip no oci8 extension"); +$target_dbs = array('oracledb' => true, 'timesten' => false); // test runs on these DBs +require(dirname(__FILE__).'/skipif.inc'); +preg_match('/.*Release ([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)*/', oci_server_version($c), $matches); +if (!(isset($matches[0]) && $matches[1] >= 12)) { + die("skip expected output only valid when using Oracle Database 12c or greater"); +} +preg_match('/^[[:digit:]]+/', oci_client_version(), $matches); +if (!(isset($matches[0]) && $matches[0] >= 12)) { + die("skip works only with Oracle 12c or greater version of Oracle client libraries"); +} +?> +--FILE-- +<?php + +require(dirname(__FILE__).'/connect.inc'); + +// Initialization + +$stmtarray = array( + "drop table imp_res_1_tab_1", + "create table imp_res_1_tab_1 (c1 number, c2 varchar2(10))", + "insert into imp_res_1_tab_1 values (1, 'abcde')", + "insert into imp_res_1_tab_1 values (2, 'fghij')", + "insert into imp_res_1_tab_1 values (3, 'klmno')", + + "drop table imp_res_1_tab_2", + "create table imp_res_1_tab_2 (c3 varchar2(1))", + "insert into imp_res_1_tab_2 values ('t')", + "insert into imp_res_1_tab_2 values ('u')", + "insert into imp_res_1_tab_2 values ('v')", + + "create or replace procedure imp_res_1_proc as + c1 sys_refcursor; + begin + open c1 for select * from imp_res_1_tab_1 order by 1; + dbms_sql.return_result(c1); + + open c1 for select * from imp_res_1_tab_2 where rownum < 3 order by 1; + dbms_sql.return_result(c1); + + open c1 for select 99 from dual; + dbms_sql.return_result (c1); + + open c1 for select NULL, 'Z' from dual; + dbms_sql.return_result (c1); + + open c1 for select * from imp_res_1_tab_1 order by 1; + dbms_sql.return_result(c1); + end;" +); + +oci8_test_sql_execute($c, $stmtarray); + +// Run Test + +echo "Test 1 - oci_fetch_assoc\n"; +$s = oci_parse($c, "begin imp_res_1_proc(); end;"); +oci_execute($s); +while (($row = oci_fetch_assoc($s)) != false) + var_dump($row); + +echo "\nTest 2 - oci_fetch_object\n"; +$s = oci_parse($c, "begin imp_res_1_proc(); end;"); +oci_execute($s); +while (($row = oci_fetch_object($s)) != false) + var_dump($row); + +echo "\nTest 3 - oci_fetch_row\n"; +$s = oci_parse($c, "begin imp_res_1_proc(); end;"); +oci_execute($s); +while (($row = oci_fetch_row($s)) != false) + var_dump($row); + +echo "\nTest 4 - oci_fetch_array(OCI_ASSOC+OCI_RETURN_NULLS)\n"; +$s = oci_parse($c, "begin imp_res_1_proc(); end;"); +oci_execute($s); +while (($row = oci_fetch_array($s, OCI_ASSOC+OCI_RETURN_NULLS)) != false) + var_dump($row); + +echo "\nTest 5 - oci_fetch_array(OCI_ASSOC)\n"; +$s = oci_parse($c, "begin imp_res_1_proc(); end;"); +oci_execute($s); +while (($row = oci_fetch_array($s, OCI_ASSOC)) != false) + var_dump($row); + +echo "\nTest 6 - oci_fetch_array(OCI_NUM)\n"; +$s = oci_parse($c, "begin imp_res_1_proc(); end;"); +oci_execute($s); +while (($row = oci_fetch_array($s, OCI_NUM)) != false) + var_dump($row); + +echo "\nTest 7 - oci_fetch_array(OCI_BOTH)\n"; +$s = oci_parse($c, "begin imp_res_1_proc(); end;"); +oci_execute($s); +while (($row = oci_fetch_array($s, OCI_BOTH)) != false) + var_dump($row); + +echo "\nTest 8 - oci_fetch_array(OCI_BOTH+OCI_RETURN_NULLS)\n"; +$s = oci_parse($c, "begin imp_res_1_proc(); end;"); +oci_execute($s); +while (($row = oci_fetch_array($s, OCI_BOTH+OCI_RETURN_NULLS)) != false) + var_dump($row); + +// Clean up + +$stmtarray = array( + "drop procedure imp_res_1_proc", + "drop table imp_res_1_tab_1", + "drop table imp_res_1_tab_2" +); + +oci8_test_sql_execute($c, $stmtarray); + +?> +===DONE=== +<?php exit(0); ?> +--EXPECTF-- +Test 1 - oci_fetch_assoc +array(2) { + ["C1"]=> + string(1) "1" + ["C2"]=> + string(5) "abcde" +} +array(2) { + ["C1"]=> + string(1) "2" + ["C2"]=> + string(5) "fghij" +} +array(2) { + ["C1"]=> + string(1) "3" + ["C2"]=> + string(5) "klmno" +} +array(1) { + ["C3"]=> + string(1) "t" +} +array(1) { + ["C3"]=> + string(1) "u" +} +array(1) { + [99]=> + string(2) "99" +} +array(2) { + ["NULL"]=> + NULL + ["'Z'"]=> + string(1) "Z" +} +array(2) { + ["C1"]=> + string(1) "1" + ["C2"]=> + string(5) "abcde" +} +array(2) { + ["C1"]=> + string(1) "2" + ["C2"]=> + string(5) "fghij" +} +array(2) { + ["C1"]=> + string(1) "3" + ["C2"]=> + string(5) "klmno" +} + +Test 2 - oci_fetch_object +object(stdClass)#%d (2) { + ["C1"]=> + string(1) "1" + ["C2"]=> + string(5) "abcde" +} +object(stdClass)#%d (2) { + ["C1"]=> + string(1) "2" + ["C2"]=> + string(5) "fghij" +} +object(stdClass)#%d (2) { + ["C1"]=> + string(1) "3" + ["C2"]=> + string(5) "klmno" +} +object(stdClass)#%d (1) { + ["C3"]=> + string(1) "t" +} +object(stdClass)#%d (1) { + ["C3"]=> + string(1) "u" +} +object(stdClass)#%d (1) { + [99]=> + string(2) "99" +} +object(stdClass)#%d (2) { + ["NULL"]=> + NULL + ["'Z'"]=> + string(1) "Z" +} +object(stdClass)#%d (2) { + ["C1"]=> + string(1) "1" + ["C2"]=> + string(5) "abcde" +} +object(stdClass)#%d (2) { + ["C1"]=> + string(1) "2" + ["C2"]=> + string(5) "fghij" +} +object(stdClass)#%d (2) { + ["C1"]=> + string(1) "3" + ["C2"]=> + string(5) "klmno" +} + +Test 3 - oci_fetch_row +array(2) { + [0]=> + string(1) "1" + [1]=> + string(5) "abcde" +} +array(2) { + [0]=> + string(1) "2" + [1]=> + string(5) "fghij" +} +array(2) { + [0]=> + string(1) "3" + [1]=> + string(5) "klmno" +} +array(1) { + [0]=> + string(1) "t" +} +array(1) { + [0]=> + string(1) "u" +} +array(1) { + [0]=> + string(2) "99" +} +array(2) { + [0]=> + NULL + [1]=> + string(1) "Z" +} +array(2) { + [0]=> + string(1) "1" + [1]=> + string(5) "abcde" +} +array(2) { + [0]=> + string(1) "2" + [1]=> + string(5) "fghij" +} +array(2) { + [0]=> + string(1) "3" + [1]=> + string(5) "klmno" +} + +Test 4 - oci_fetch_array(OCI_ASSOC+OCI_RETURN_NULLS) +array(2) { + ["C1"]=> + string(1) "1" + ["C2"]=> + string(5) "abcde" +} +array(2) { + ["C1"]=> + string(1) "2" + ["C2"]=> + string(5) "fghij" +} +array(2) { + ["C1"]=> + string(1) "3" + ["C2"]=> + string(5) "klmno" +} +array(1) { + ["C3"]=> + string(1) "t" +} +array(1) { + ["C3"]=> + string(1) "u" +} +array(1) { + [99]=> + string(2) "99" +} +array(2) { + ["NULL"]=> + NULL + ["'Z'"]=> + string(1) "Z" +} +array(2) { + ["C1"]=> + string(1) "1" + ["C2"]=> + string(5) "abcde" +} +array(2) { + ["C1"]=> + string(1) "2" + ["C2"]=> + string(5) "fghij" +} +array(2) { + ["C1"]=> + string(1) "3" + ["C2"]=> + string(5) "klmno" +} + +Test 5 - oci_fetch_array(OCI_ASSOC) +array(2) { + ["C1"]=> + string(1) "1" + ["C2"]=> + string(5) "abcde" +} +array(2) { + ["C1"]=> + string(1) "2" + ["C2"]=> + string(5) "fghij" +} +array(2) { + ["C1"]=> + string(1) "3" + ["C2"]=> + string(5) "klmno" +} +array(1) { + ["C3"]=> + string(1) "t" +} +array(1) { + ["C3"]=> + string(1) "u" +} +array(1) { + [99]=> + string(2) "99" +} +array(1) { + ["'Z'"]=> + string(1) "Z" +} +array(2) { + ["C1"]=> + string(1) "1" + ["C2"]=> + string(5) "abcde" +} +array(2) { + ["C1"]=> + string(1) "2" + ["C2"]=> + string(5) "fghij" +} +array(2) { + ["C1"]=> + string(1) "3" + ["C2"]=> + string(5) "klmno" +} + +Test 6 - oci_fetch_array(OCI_NUM) +array(2) { + [0]=> + string(1) "1" + [1]=> + string(5) "abcde" +} +array(2) { + [0]=> + string(1) "2" + [1]=> + string(5) "fghij" +} +array(2) { + [0]=> + string(1) "3" + [1]=> + string(5) "klmno" +} +array(1) { + [0]=> + string(1) "t" +} +array(1) { + [0]=> + string(1) "u" +} +array(1) { + [0]=> + string(2) "99" +} +array(1) { + [1]=> + string(1) "Z" +} +array(2) { + [0]=> + string(1) "1" + [1]=> + string(5) "abcde" +} +array(2) { + [0]=> + string(1) "2" + [1]=> + string(5) "fghij" +} +array(2) { + [0]=> + string(1) "3" + [1]=> + string(5) "klmno" +} + +Test 7 - oci_fetch_array(OCI_BOTH) +array(4) { + [0]=> + string(1) "1" + ["C1"]=> + string(1) "1" + [1]=> + string(5) "abcde" + ["C2"]=> + string(5) "abcde" +} +array(4) { + [0]=> + string(1) "2" + ["C1"]=> + string(1) "2" + [1]=> + string(5) "fghij" + ["C2"]=> + string(5) "fghij" +} +array(4) { + [0]=> + string(1) "3" + ["C1"]=> + string(1) "3" + [1]=> + string(5) "klmno" + ["C2"]=> + string(5) "klmno" +} +array(2) { + [0]=> + string(1) "t" + ["C3"]=> + string(1) "t" +} +array(2) { + [0]=> + string(1) "u" + ["C3"]=> + string(1) "u" +} +array(2) { + [0]=> + string(2) "99" + [99]=> + string(2) "99" +} +array(2) { + [1]=> + string(1) "Z" + ["'Z'"]=> + string(1) "Z" +} +array(4) { + [0]=> + string(1) "1" + ["C1"]=> + string(1) "1" + [1]=> + string(5) "abcde" + ["C2"]=> + string(5) "abcde" +} +array(4) { + [0]=> + string(1) "2" + ["C1"]=> + string(1) "2" + [1]=> + string(5) "fghij" + ["C2"]=> + string(5) "fghij" +} +array(4) { + [0]=> + string(1) "3" + ["C1"]=> + string(1) "3" + [1]=> + string(5) "klmno" + ["C2"]=> + string(5) "klmno" +} + +Test 8 - oci_fetch_array(OCI_BOTH+OCI_RETURN_NULLS) +array(4) { + [0]=> + string(1) "1" + ["C1"]=> + string(1) "1" + [1]=> + string(5) "abcde" + ["C2"]=> + string(5) "abcde" +} +array(4) { + [0]=> + string(1) "2" + ["C1"]=> + string(1) "2" + [1]=> + string(5) "fghij" + ["C2"]=> + string(5) "fghij" +} +array(4) { + [0]=> + string(1) "3" + ["C1"]=> + string(1) "3" + [1]=> + string(5) "klmno" + ["C2"]=> + string(5) "klmno" +} +array(2) { + [0]=> + string(1) "t" + ["C3"]=> + string(1) "t" +} +array(2) { + [0]=> + string(1) "u" + ["C3"]=> + string(1) "u" +} +array(2) { + [0]=> + string(2) "99" + [99]=> + string(2) "99" +} +array(4) { + [0]=> + NULL + ["NULL"]=> + NULL + [1]=> + string(1) "Z" + ["'Z'"]=> + string(1) "Z" +} +array(4) { + [0]=> + string(1) "1" + ["C1"]=> + string(1) "1" + [1]=> + string(5) "abcde" + ["C2"]=> + string(5) "abcde" +} +array(4) { + [0]=> + string(1) "2" + ["C1"]=> + string(1) "2" + [1]=> + string(5) "fghij" + ["C2"]=> + string(5) "fghij" +} +array(4) { + [0]=> + string(1) "3" + ["C1"]=> + string(1) "3" + [1]=> + string(5) "klmno" + ["C2"]=> + string(5) "klmno" +} +===DONE=== diff --git a/ext/oci8/tests/imp_res_2.phpt b/ext/oci8/tests/imp_res_2.phpt new file mode 100644 index 0000000000..860a5fbb34 --- /dev/null +++ b/ext/oci8/tests/imp_res_2.phpt @@ -0,0 +1,99 @@ +--TEST-- +Oracle Database 12c Implicit Result Sets: Zero Rows +--SKIPIF-- +<?php +if (!extension_loaded('oci8')) die ("skip no oci8 extension"); +$target_dbs = array('oracledb' => true, 'timesten' => false); // test runs on these DBs +require(dirname(__FILE__).'/skipif.inc'); +preg_match('/.*Release ([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)*/', oci_server_version($c), $matches); +if (!(isset($matches[0]) && $matches[1] >= 12)) { + die("skip expected output only valid when using Oracle Database 12c or greater"); +} +preg_match('/^[[:digit:]]+/', oci_client_version(), $matches); +if (!(isset($matches[0]) && $matches[0] >= 12)) { + die("skip works only with Oracle 12c or greater version of Oracle client libraries"); +} +?> +--FILE-- +<?php + +require(dirname(__FILE__).'/connect.inc'); + +// Initialization + +$stmtarray = array( + "create or replace procedure imp_res_2_proc_a as + c1 sys_refcursor; + begin + open c1 for select * from dual where 1 = 0; + dbms_sql.return_result(c1); + end;", + + "create or replace procedure imp_res_2_proc_b as + c1 sys_refcursor; + begin + open c1 for select * from dual; + dbms_sql.return_result(c1); + open c1 for select * from dual where 1 = 0; + dbms_sql.return_result(c1); + end;", + + "create or replace procedure imp_res_2_proc_c as + c1 sys_refcursor; + begin + open c1 for select * from dual where 1 = 0; + dbms_sql.return_result(c1); + open c1 for select * from dual; + dbms_sql.return_result(c1); + end;" + +); + +oci8_test_sql_execute($c, $stmtarray); + +// Run Test + +echo "Test 1\n"; +$s = oci_parse($c, "begin imp_res_2_proc_a(); end;"); +oci_execute($s); +while (($row = oci_fetch_row($s)) != false) + var_dump($row); + +echo "Test 2\n"; +$s = oci_parse($c, "begin imp_res_2_proc_b(); end;"); +oci_execute($s); +while (($row = oci_fetch_row($s)) != false) + var_dump($row); + +echo "Test 2\n"; +$s = oci_parse($c, "begin imp_res_2_proc_c(); end;"); +oci_execute($s); +while (($row = oci_fetch_row($s)) != false) + var_dump($row); + +// Clean up + +$stmtarray = array( + "drop procedure imp_res_2_proc_a", + "drop procedure imp_res_2_proc_b", + "drop procedure imp_res_2_proc_c" +); + +oci8_test_sql_execute($c, $stmtarray); + +?> +===DONE=== +<?php exit(0); ?> +--EXPECTF-- +Test 1 +Test 2 +array(1) { + [0]=> + string(1) "X" +} +Test 2 +array(1) { + [0]=> + string(1) "X" +} +===DONE=== diff --git a/ext/oci8/tests/imp_res_3.phpt b/ext/oci8/tests/imp_res_3.phpt new file mode 100644 index 0000000000..0fc4815893 --- /dev/null +++ b/ext/oci8/tests/imp_res_3.phpt @@ -0,0 +1,1257 @@ +--TEST-- +Oracle Database 12c Implicit Result Sets: bigger data size +--SKIPIF-- +<?php +if (!extension_loaded('oci8')) die ("skip no oci8 extension"); +$target_dbs = array('oracledb' => true, 'timesten' => false); // test runs on these DBs +require(dirname(__FILE__).'/skipif.inc'); +preg_match('/.*Release ([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)*/', oci_server_version($c), $matches); +if (!(isset($matches[0]) && $matches[1] >= 12)) { + die("skip expected output only valid when using Oracle Database 12c or greater"); +} +preg_match('/^[[:digit:]]+/', oci_client_version(), $matches); +if (!(isset($matches[0]) && $matches[0] >= 12)) { + die("skip works only with Oracle 12c or greater version of Oracle client libraries"); +} +?> +--FILE-- +<?php + +require(dirname(__FILE__).'/connect.inc'); + +// Initialization + +$stmtarray = array( + "drop table imp_res_3_tab_1", + "create table imp_res_3_tab_1 (c1 number, c2 varchar2(10))", + "insert into imp_res_3_tab_1 values (1, 'a')", + "insert into imp_res_3_tab_1 values (2, 'f')", + + "drop table imp_res_3_tab_2", + "create table imp_res_3_tab_2 (c3 varchar2(1))", + "insert into imp_res_3_tab_2 values ('t')", + "insert into imp_res_3_tab_2 values ('u')", + "insert into imp_res_3_tab_2 values ('v')", + "insert into imp_res_3_tab_2 values ('w')", + + "create or replace procedure imp_res_3_proc as + c1 sys_refcursor; + i pls_integer; + begin + for i in 1..30 loop -- if this value is too big for Oracle's open_cursors, calling imp_res_3_proc() can fail with ORA-1000 + open c1 for select t1.*, t2.*, t3.*, t4.*, t5.* + from imp_res_3_tab_1 t1, imp_res_3_tab_1 t2, imp_res_3_tab_1 t3, + imp_res_3_tab_1 t4, imp_res_3_tab_1 t5 order by 1,3,5,7,9,2,4,6,8,10; + dbms_sql.return_result(c1); + open c1 for select c2 from imp_res_3_tab_1 order by 1; + dbms_sql.return_result(c1); + open c1 for select * from imp_res_3_tab_2 order by 1; + dbms_sql.return_result(c1); + open c1 for select * from dual; + dbms_sql.return_result (c1); + end loop; + end;" +); + +oci8_test_sql_execute($c, $stmtarray); + +// Run Test + +echo "Test 1\n"; + +$s = oci_parse($c, "begin imp_res_3_proc(); end;"); +oci_execute($s); + +while (($row = oci_fetch_array($s, OCI_NUM+OCI_RETURN_NULLS)) != false) { + foreach ($row as $item) { + echo " ".$item; + } + echo "\n"; +} + +// Clean up + +$stmtarray = array( + "drop procedure imp_res_3_proc", + "drop table imp_res_3_tab_1", + "drop table imp_res_3_tab_2" +); + +oci8_test_sql_execute($c, $stmtarray); + +?> +===DONE=== +<?php exit(0); ?> +--EXPECTF-- +Test 1 + 1 a 1 a 1 a 1 a 1 a + 1 a 1 a 1 a 1 a 2 f + 1 a 1 a 1 a 2 f 1 a + 1 a 1 a 1 a 2 f 2 f + 1 a 1 a 2 f 1 a 1 a + 1 a 1 a 2 f 1 a 2 f + 1 a 1 a 2 f 2 f 1 a + 1 a 1 a 2 f 2 f 2 f + 1 a 2 f 1 a 1 a 1 a + 1 a 2 f 1 a 1 a 2 f + 1 a 2 f 1 a 2 f 1 a + 1 a 2 f 1 a 2 f 2 f + 1 a 2 f 2 f 1 a 1 a + 1 a 2 f 2 f 1 a 2 f + 1 a 2 f 2 f 2 f 1 a + 1 a 2 f 2 f 2 f 2 f + 2 f 1 a 1 a 1 a 1 a + 2 f 1 a 1 a 1 a 2 f + 2 f 1 a 1 a 2 f 1 a + 2 f 1 a 1 a 2 f 2 f + 2 f 1 a 2 f 1 a 1 a + 2 f 1 a 2 f 1 a 2 f + 2 f 1 a 2 f 2 f 1 a + 2 f 1 a 2 f 2 f 2 f + 2 f 2 f 1 a 1 a 1 a + 2 f 2 f 1 a 1 a 2 f + 2 f 2 f 1 a 2 f 1 a + 2 f 2 f 1 a 2 f 2 f + 2 f 2 f 2 f 1 a 1 a + 2 f 2 f 2 f 1 a 2 f + 2 f 2 f 2 f 2 f 1 a + 2 f 2 f 2 f 2 f 2 f + a + f + t + u + v + w + X + 1 a 1 a 1 a 1 a 1 a + 1 a 1 a 1 a 1 a 2 f + 1 a 1 a 1 a 2 f 1 a + 1 a 1 a 1 a 2 f 2 f + 1 a 1 a 2 f 1 a 1 a + 1 a 1 a 2 f 1 a 2 f + 1 a 1 a 2 f 2 f 1 a + 1 a 1 a 2 f 2 f 2 f + 1 a 2 f 1 a 1 a 1 a + 1 a 2 f 1 a 1 a 2 f + 1 a 2 f 1 a 2 f 1 a + 1 a 2 f 1 a 2 f 2 f + 1 a 2 f 2 f 1 a 1 a + 1 a 2 f 2 f 1 a 2 f + 1 a 2 f 2 f 2 f 1 a + 1 a 2 f 2 f 2 f 2 f + 2 f 1 a 1 a 1 a 1 a + 2 f 1 a 1 a 1 a 2 f + 2 f 1 a 1 a 2 f 1 a + 2 f 1 a 1 a 2 f 2 f + 2 f 1 a 2 f 1 a 1 a + 2 f 1 a 2 f 1 a 2 f + 2 f 1 a 2 f 2 f 1 a + 2 f 1 a 2 f 2 f 2 f + 2 f 2 f 1 a 1 a 1 a + 2 f 2 f 1 a 1 a 2 f + 2 f 2 f 1 a 2 f 1 a + 2 f 2 f 1 a 2 f 2 f + 2 f 2 f 2 f 1 a 1 a + 2 f 2 f 2 f 1 a 2 f + 2 f 2 f 2 f 2 f 1 a + 2 f 2 f 2 f 2 f 2 f + a + f + t + u + v + w + X + 1 a 1 a 1 a 1 a 1 a + 1 a 1 a 1 a 1 a 2 f + 1 a 1 a 1 a 2 f 1 a + 1 a 1 a 1 a 2 f 2 f + 1 a 1 a 2 f 1 a 1 a + 1 a 1 a 2 f 1 a 2 f + 1 a 1 a 2 f 2 f 1 a + 1 a 1 a 2 f 2 f 2 f + 1 a 2 f 1 a 1 a 1 a + 1 a 2 f 1 a 1 a 2 f + 1 a 2 f 1 a 2 f 1 a + 1 a 2 f 1 a 2 f 2 f + 1 a 2 f 2 f 1 a 1 a + 1 a 2 f 2 f 1 a 2 f + 1 a 2 f 2 f 2 f 1 a + 1 a 2 f 2 f 2 f 2 f + 2 f 1 a 1 a 1 a 1 a + 2 f 1 a 1 a 1 a 2 f + 2 f 1 a 1 a 2 f 1 a + 2 f 1 a 1 a 2 f 2 f + 2 f 1 a 2 f 1 a 1 a + 2 f 1 a 2 f 1 a 2 f + 2 f 1 a 2 f 2 f 1 a + 2 f 1 a 2 f 2 f 2 f + 2 f 2 f 1 a 1 a 1 a + 2 f 2 f 1 a 1 a 2 f + 2 f 2 f 1 a 2 f 1 a + 2 f 2 f 1 a 2 f 2 f + 2 f 2 f 2 f 1 a 1 a + 2 f 2 f 2 f 1 a 2 f + 2 f 2 f 2 f 2 f 1 a + 2 f 2 f 2 f 2 f 2 f + a + f + t + u + v + w + X + 1 a 1 a 1 a 1 a 1 a + 1 a 1 a 1 a 1 a 2 f + 1 a 1 a 1 a 2 f 1 a + 1 a 1 a 1 a 2 f 2 f + 1 a 1 a 2 f 1 a 1 a + 1 a 1 a 2 f 1 a 2 f + 1 a 1 a 2 f 2 f 1 a + 1 a 1 a 2 f 2 f 2 f + 1 a 2 f 1 a 1 a 1 a + 1 a 2 f 1 a 1 a 2 f + 1 a 2 f 1 a 2 f 1 a + 1 a 2 f 1 a 2 f 2 f + 1 a 2 f 2 f 1 a 1 a + 1 a 2 f 2 f 1 a 2 f + 1 a 2 f 2 f 2 f 1 a + 1 a 2 f 2 f 2 f 2 f + 2 f 1 a 1 a 1 a 1 a + 2 f 1 a 1 a 1 a 2 f + 2 f 1 a 1 a 2 f 1 a + 2 f 1 a 1 a 2 f 2 f + 2 f 1 a 2 f 1 a 1 a + 2 f 1 a 2 f 1 a 2 f + 2 f 1 a 2 f 2 f 1 a + 2 f 1 a 2 f 2 f 2 f + 2 f 2 f 1 a 1 a 1 a + 2 f 2 f 1 a 1 a 2 f + 2 f 2 f 1 a 2 f 1 a + 2 f 2 f 1 a 2 f 2 f + 2 f 2 f 2 f 1 a 1 a + 2 f 2 f 2 f 1 a 2 f + 2 f 2 f 2 f 2 f 1 a + 2 f 2 f 2 f 2 f 2 f + a + f + t + u + v + w + X + 1 a 1 a 1 a 1 a 1 a + 1 a 1 a 1 a 1 a 2 f + 1 a 1 a 1 a 2 f 1 a + 1 a 1 a 1 a 2 f 2 f + 1 a 1 a 2 f 1 a 1 a + 1 a 1 a 2 f 1 a 2 f + 1 a 1 a 2 f 2 f 1 a + 1 a 1 a 2 f 2 f 2 f + 1 a 2 f 1 a 1 a 1 a + 1 a 2 f 1 a 1 a 2 f + 1 a 2 f 1 a 2 f 1 a + 1 a 2 f 1 a 2 f 2 f + 1 a 2 f 2 f 1 a 1 a + 1 a 2 f 2 f 1 a 2 f + 1 a 2 f 2 f 2 f 1 a + 1 a 2 f 2 f 2 f 2 f + 2 f 1 a 1 a 1 a 1 a + 2 f 1 a 1 a 1 a 2 f + 2 f 1 a 1 a 2 f 1 a + 2 f 1 a 1 a 2 f 2 f + 2 f 1 a 2 f 1 a 1 a + 2 f 1 a 2 f 1 a 2 f + 2 f 1 a 2 f 2 f 1 a + 2 f 1 a 2 f 2 f 2 f + 2 f 2 f 1 a 1 a 1 a + 2 f 2 f 1 a 1 a 2 f + 2 f 2 f 1 a 2 f 1 a + 2 f 2 f 1 a 2 f 2 f + 2 f 2 f 2 f 1 a 1 a + 2 f 2 f 2 f 1 a 2 f + 2 f 2 f 2 f 2 f 1 a + 2 f 2 f 2 f 2 f 2 f + a + f + t + u + v + w + X + 1 a 1 a 1 a 1 a 1 a + 1 a 1 a 1 a 1 a 2 f + 1 a 1 a 1 a 2 f 1 a + 1 a 1 a 1 a 2 f 2 f + 1 a 1 a 2 f 1 a 1 a + 1 a 1 a 2 f 1 a 2 f + 1 a 1 a 2 f 2 f 1 a + 1 a 1 a 2 f 2 f 2 f + 1 a 2 f 1 a 1 a 1 a + 1 a 2 f 1 a 1 a 2 f + 1 a 2 f 1 a 2 f 1 a + 1 a 2 f 1 a 2 f 2 f + 1 a 2 f 2 f 1 a 1 a + 1 a 2 f 2 f 1 a 2 f + 1 a 2 f 2 f 2 f 1 a + 1 a 2 f 2 f 2 f 2 f + 2 f 1 a 1 a 1 a 1 a + 2 f 1 a 1 a 1 a 2 f + 2 f 1 a 1 a 2 f 1 a + 2 f 1 a 1 a 2 f 2 f + 2 f 1 a 2 f 1 a 1 a + 2 f 1 a 2 f 1 a 2 f + 2 f 1 a 2 f 2 f 1 a + 2 f 1 a 2 f 2 f 2 f + 2 f 2 f 1 a 1 a 1 a + 2 f 2 f 1 a 1 a 2 f + 2 f 2 f 1 a 2 f 1 a + 2 f 2 f 1 a 2 f 2 f + 2 f 2 f 2 f 1 a 1 a + 2 f 2 f 2 f 1 a 2 f + 2 f 2 f 2 f 2 f 1 a + 2 f 2 f 2 f 2 f 2 f + a + f + t + u + v + w + X + 1 a 1 a 1 a 1 a 1 a + 1 a 1 a 1 a 1 a 2 f + 1 a 1 a 1 a 2 f 1 a + 1 a 1 a 1 a 2 f 2 f + 1 a 1 a 2 f 1 a 1 a + 1 a 1 a 2 f 1 a 2 f + 1 a 1 a 2 f 2 f 1 a + 1 a 1 a 2 f 2 f 2 f + 1 a 2 f 1 a 1 a 1 a + 1 a 2 f 1 a 1 a 2 f + 1 a 2 f 1 a 2 f 1 a + 1 a 2 f 1 a 2 f 2 f + 1 a 2 f 2 f 1 a 1 a + 1 a 2 f 2 f 1 a 2 f + 1 a 2 f 2 f 2 f 1 a + 1 a 2 f 2 f 2 f 2 f + 2 f 1 a 1 a 1 a 1 a + 2 f 1 a 1 a 1 a 2 f + 2 f 1 a 1 a 2 f 1 a + 2 f 1 a 1 a 2 f 2 f + 2 f 1 a 2 f 1 a 1 a + 2 f 1 a 2 f 1 a 2 f + 2 f 1 a 2 f 2 f 1 a + 2 f 1 a 2 f 2 f 2 f + 2 f 2 f 1 a 1 a 1 a + 2 f 2 f 1 a 1 a 2 f + 2 f 2 f 1 a 2 f 1 a + 2 f 2 f 1 a 2 f 2 f + 2 f 2 f 2 f 1 a 1 a + 2 f 2 f 2 f 1 a 2 f + 2 f 2 f 2 f 2 f 1 a + 2 f 2 f 2 f 2 f 2 f + a + f + t + u + v + w + X + 1 a 1 a 1 a 1 a 1 a + 1 a 1 a 1 a 1 a 2 f + 1 a 1 a 1 a 2 f 1 a + 1 a 1 a 1 a 2 f 2 f + 1 a 1 a 2 f 1 a 1 a + 1 a 1 a 2 f 1 a 2 f + 1 a 1 a 2 f 2 f 1 a + 1 a 1 a 2 f 2 f 2 f + 1 a 2 f 1 a 1 a 1 a + 1 a 2 f 1 a 1 a 2 f + 1 a 2 f 1 a 2 f 1 a + 1 a 2 f 1 a 2 f 2 f + 1 a 2 f 2 f 1 a 1 a + 1 a 2 f 2 f 1 a 2 f + 1 a 2 f 2 f 2 f 1 a + 1 a 2 f 2 f 2 f 2 f + 2 f 1 a 1 a 1 a 1 a + 2 f 1 a 1 a 1 a 2 f + 2 f 1 a 1 a 2 f 1 a + 2 f 1 a 1 a 2 f 2 f + 2 f 1 a 2 f 1 a 1 a + 2 f 1 a 2 f 1 a 2 f + 2 f 1 a 2 f 2 f 1 a + 2 f 1 a 2 f 2 f 2 f + 2 f 2 f 1 a 1 a 1 a + 2 f 2 f 1 a 1 a 2 f + 2 f 2 f 1 a 2 f 1 a + 2 f 2 f 1 a 2 f 2 f + 2 f 2 f 2 f 1 a 1 a + 2 f 2 f 2 f 1 a 2 f + 2 f 2 f 2 f 2 f 1 a + 2 f 2 f 2 f 2 f 2 f + a + f + t + u + v + w + X + 1 a 1 a 1 a 1 a 1 a + 1 a 1 a 1 a 1 a 2 f + 1 a 1 a 1 a 2 f 1 a + 1 a 1 a 1 a 2 f 2 f + 1 a 1 a 2 f 1 a 1 a + 1 a 1 a 2 f 1 a 2 f + 1 a 1 a 2 f 2 f 1 a + 1 a 1 a 2 f 2 f 2 f + 1 a 2 f 1 a 1 a 1 a + 1 a 2 f 1 a 1 a 2 f + 1 a 2 f 1 a 2 f 1 a + 1 a 2 f 1 a 2 f 2 f + 1 a 2 f 2 f 1 a 1 a + 1 a 2 f 2 f 1 a 2 f + 1 a 2 f 2 f 2 f 1 a + 1 a 2 f 2 f 2 f 2 f + 2 f 1 a 1 a 1 a 1 a + 2 f 1 a 1 a 1 a 2 f + 2 f 1 a 1 a 2 f 1 a + 2 f 1 a 1 a 2 f 2 f + 2 f 1 a 2 f 1 a 1 a + 2 f 1 a 2 f 1 a 2 f + 2 f 1 a 2 f 2 f 1 a + 2 f 1 a 2 f 2 f 2 f + 2 f 2 f 1 a 1 a 1 a + 2 f 2 f 1 a 1 a 2 f + 2 f 2 f 1 a 2 f 1 a + 2 f 2 f 1 a 2 f 2 f + 2 f 2 f 2 f 1 a 1 a + 2 f 2 f 2 f 1 a 2 f + 2 f 2 f 2 f 2 f 1 a + 2 f 2 f 2 f 2 f 2 f + a + f + t + u + v + w + X + 1 a 1 a 1 a 1 a 1 a + 1 a 1 a 1 a 1 a 2 f + 1 a 1 a 1 a 2 f 1 a + 1 a 1 a 1 a 2 f 2 f + 1 a 1 a 2 f 1 a 1 a + 1 a 1 a 2 f 1 a 2 f + 1 a 1 a 2 f 2 f 1 a + 1 a 1 a 2 f 2 f 2 f + 1 a 2 f 1 a 1 a 1 a + 1 a 2 f 1 a 1 a 2 f + 1 a 2 f 1 a 2 f 1 a + 1 a 2 f 1 a 2 f 2 f + 1 a 2 f 2 f 1 a 1 a + 1 a 2 f 2 f 1 a 2 f + 1 a 2 f 2 f 2 f 1 a + 1 a 2 f 2 f 2 f 2 f + 2 f 1 a 1 a 1 a 1 a + 2 f 1 a 1 a 1 a 2 f + 2 f 1 a 1 a 2 f 1 a + 2 f 1 a 1 a 2 f 2 f + 2 f 1 a 2 f 1 a 1 a + 2 f 1 a 2 f 1 a 2 f + 2 f 1 a 2 f 2 f 1 a + 2 f 1 a 2 f 2 f 2 f + 2 f 2 f 1 a 1 a 1 a + 2 f 2 f 1 a 1 a 2 f + 2 f 2 f 1 a 2 f 1 a + 2 f 2 f 1 a 2 f 2 f + 2 f 2 f 2 f 1 a 1 a + 2 f 2 f 2 f 1 a 2 f + 2 f 2 f 2 f 2 f 1 a + 2 f 2 f 2 f 2 f 2 f + a + f + t + u + v + w + X + 1 a 1 a 1 a 1 a 1 a + 1 a 1 a 1 a 1 a 2 f + 1 a 1 a 1 a 2 f 1 a + 1 a 1 a 1 a 2 f 2 f + 1 a 1 a 2 f 1 a 1 a + 1 a 1 a 2 f 1 a 2 f + 1 a 1 a 2 f 2 f 1 a + 1 a 1 a 2 f 2 f 2 f + 1 a 2 f 1 a 1 a 1 a + 1 a 2 f 1 a 1 a 2 f + 1 a 2 f 1 a 2 f 1 a + 1 a 2 f 1 a 2 f 2 f + 1 a 2 f 2 f 1 a 1 a + 1 a 2 f 2 f 1 a 2 f + 1 a 2 f 2 f 2 f 1 a + 1 a 2 f 2 f 2 f 2 f + 2 f 1 a 1 a 1 a 1 a + 2 f 1 a 1 a 1 a 2 f + 2 f 1 a 1 a 2 f 1 a + 2 f 1 a 1 a 2 f 2 f + 2 f 1 a 2 f 1 a 1 a + 2 f 1 a 2 f 1 a 2 f + 2 f 1 a 2 f 2 f 1 a + 2 f 1 a 2 f 2 f 2 f + 2 f 2 f 1 a 1 a 1 a + 2 f 2 f 1 a 1 a 2 f + 2 f 2 f 1 a 2 f 1 a + 2 f 2 f 1 a 2 f 2 f + 2 f 2 f 2 f 1 a 1 a + 2 f 2 f 2 f 1 a 2 f + 2 f 2 f 2 f 2 f 1 a + 2 f 2 f 2 f 2 f 2 f + a + f + t + u + v + w + X + 1 a 1 a 1 a 1 a 1 a + 1 a 1 a 1 a 1 a 2 f + 1 a 1 a 1 a 2 f 1 a + 1 a 1 a 1 a 2 f 2 f + 1 a 1 a 2 f 1 a 1 a + 1 a 1 a 2 f 1 a 2 f + 1 a 1 a 2 f 2 f 1 a + 1 a 1 a 2 f 2 f 2 f + 1 a 2 f 1 a 1 a 1 a + 1 a 2 f 1 a 1 a 2 f + 1 a 2 f 1 a 2 f 1 a + 1 a 2 f 1 a 2 f 2 f + 1 a 2 f 2 f 1 a 1 a + 1 a 2 f 2 f 1 a 2 f + 1 a 2 f 2 f 2 f 1 a + 1 a 2 f 2 f 2 f 2 f + 2 f 1 a 1 a 1 a 1 a + 2 f 1 a 1 a 1 a 2 f + 2 f 1 a 1 a 2 f 1 a + 2 f 1 a 1 a 2 f 2 f + 2 f 1 a 2 f 1 a 1 a + 2 f 1 a 2 f 1 a 2 f + 2 f 1 a 2 f 2 f 1 a + 2 f 1 a 2 f 2 f 2 f + 2 f 2 f 1 a 1 a 1 a + 2 f 2 f 1 a 1 a 2 f + 2 f 2 f 1 a 2 f 1 a + 2 f 2 f 1 a 2 f 2 f + 2 f 2 f 2 f 1 a 1 a + 2 f 2 f 2 f 1 a 2 f + 2 f 2 f 2 f 2 f 1 a + 2 f 2 f 2 f 2 f 2 f + a + f + t + u + v + w + X + 1 a 1 a 1 a 1 a 1 a + 1 a 1 a 1 a 1 a 2 f + 1 a 1 a 1 a 2 f 1 a + 1 a 1 a 1 a 2 f 2 f + 1 a 1 a 2 f 1 a 1 a + 1 a 1 a 2 f 1 a 2 f + 1 a 1 a 2 f 2 f 1 a + 1 a 1 a 2 f 2 f 2 f + 1 a 2 f 1 a 1 a 1 a + 1 a 2 f 1 a 1 a 2 f + 1 a 2 f 1 a 2 f 1 a + 1 a 2 f 1 a 2 f 2 f + 1 a 2 f 2 f 1 a 1 a + 1 a 2 f 2 f 1 a 2 f + 1 a 2 f 2 f 2 f 1 a + 1 a 2 f 2 f 2 f 2 f + 2 f 1 a 1 a 1 a 1 a + 2 f 1 a 1 a 1 a 2 f + 2 f 1 a 1 a 2 f 1 a + 2 f 1 a 1 a 2 f 2 f + 2 f 1 a 2 f 1 a 1 a + 2 f 1 a 2 f 1 a 2 f + 2 f 1 a 2 f 2 f 1 a + 2 f 1 a 2 f 2 f 2 f + 2 f 2 f 1 a 1 a 1 a + 2 f 2 f 1 a 1 a 2 f + 2 f 2 f 1 a 2 f 1 a + 2 f 2 f 1 a 2 f 2 f + 2 f 2 f 2 f 1 a 1 a + 2 f 2 f 2 f 1 a 2 f + 2 f 2 f 2 f 2 f 1 a + 2 f 2 f 2 f 2 f 2 f + a + f + t + u + v + w + X + 1 a 1 a 1 a 1 a 1 a + 1 a 1 a 1 a 1 a 2 f + 1 a 1 a 1 a 2 f 1 a + 1 a 1 a 1 a 2 f 2 f + 1 a 1 a 2 f 1 a 1 a + 1 a 1 a 2 f 1 a 2 f + 1 a 1 a 2 f 2 f 1 a + 1 a 1 a 2 f 2 f 2 f + 1 a 2 f 1 a 1 a 1 a + 1 a 2 f 1 a 1 a 2 f + 1 a 2 f 1 a 2 f 1 a + 1 a 2 f 1 a 2 f 2 f + 1 a 2 f 2 f 1 a 1 a + 1 a 2 f 2 f 1 a 2 f + 1 a 2 f 2 f 2 f 1 a + 1 a 2 f 2 f 2 f 2 f + 2 f 1 a 1 a 1 a 1 a + 2 f 1 a 1 a 1 a 2 f + 2 f 1 a 1 a 2 f 1 a + 2 f 1 a 1 a 2 f 2 f + 2 f 1 a 2 f 1 a 1 a + 2 f 1 a 2 f 1 a 2 f + 2 f 1 a 2 f 2 f 1 a + 2 f 1 a 2 f 2 f 2 f + 2 f 2 f 1 a 1 a 1 a + 2 f 2 f 1 a 1 a 2 f + 2 f 2 f 1 a 2 f 1 a + 2 f 2 f 1 a 2 f 2 f + 2 f 2 f 2 f 1 a 1 a + 2 f 2 f 2 f 1 a 2 f + 2 f 2 f 2 f 2 f 1 a + 2 f 2 f 2 f 2 f 2 f + a + f + t + u + v + w + X + 1 a 1 a 1 a 1 a 1 a + 1 a 1 a 1 a 1 a 2 f + 1 a 1 a 1 a 2 f 1 a + 1 a 1 a 1 a 2 f 2 f + 1 a 1 a 2 f 1 a 1 a + 1 a 1 a 2 f 1 a 2 f + 1 a 1 a 2 f 2 f 1 a + 1 a 1 a 2 f 2 f 2 f + 1 a 2 f 1 a 1 a 1 a + 1 a 2 f 1 a 1 a 2 f + 1 a 2 f 1 a 2 f 1 a + 1 a 2 f 1 a 2 f 2 f + 1 a 2 f 2 f 1 a 1 a + 1 a 2 f 2 f 1 a 2 f + 1 a 2 f 2 f 2 f 1 a + 1 a 2 f 2 f 2 f 2 f + 2 f 1 a 1 a 1 a 1 a + 2 f 1 a 1 a 1 a 2 f + 2 f 1 a 1 a 2 f 1 a + 2 f 1 a 1 a 2 f 2 f + 2 f 1 a 2 f 1 a 1 a + 2 f 1 a 2 f 1 a 2 f + 2 f 1 a 2 f 2 f 1 a + 2 f 1 a 2 f 2 f 2 f + 2 f 2 f 1 a 1 a 1 a + 2 f 2 f 1 a 1 a 2 f + 2 f 2 f 1 a 2 f 1 a + 2 f 2 f 1 a 2 f 2 f + 2 f 2 f 2 f 1 a 1 a + 2 f 2 f 2 f 1 a 2 f + 2 f 2 f 2 f 2 f 1 a + 2 f 2 f 2 f 2 f 2 f + a + f + t + u + v + w + X + 1 a 1 a 1 a 1 a 1 a + 1 a 1 a 1 a 1 a 2 f + 1 a 1 a 1 a 2 f 1 a + 1 a 1 a 1 a 2 f 2 f + 1 a 1 a 2 f 1 a 1 a + 1 a 1 a 2 f 1 a 2 f + 1 a 1 a 2 f 2 f 1 a + 1 a 1 a 2 f 2 f 2 f + 1 a 2 f 1 a 1 a 1 a + 1 a 2 f 1 a 1 a 2 f + 1 a 2 f 1 a 2 f 1 a + 1 a 2 f 1 a 2 f 2 f + 1 a 2 f 2 f 1 a 1 a + 1 a 2 f 2 f 1 a 2 f + 1 a 2 f 2 f 2 f 1 a + 1 a 2 f 2 f 2 f 2 f + 2 f 1 a 1 a 1 a 1 a + 2 f 1 a 1 a 1 a 2 f + 2 f 1 a 1 a 2 f 1 a + 2 f 1 a 1 a 2 f 2 f + 2 f 1 a 2 f 1 a 1 a + 2 f 1 a 2 f 1 a 2 f + 2 f 1 a 2 f 2 f 1 a + 2 f 1 a 2 f 2 f 2 f + 2 f 2 f 1 a 1 a 1 a + 2 f 2 f 1 a 1 a 2 f + 2 f 2 f 1 a 2 f 1 a + 2 f 2 f 1 a 2 f 2 f + 2 f 2 f 2 f 1 a 1 a + 2 f 2 f 2 f 1 a 2 f + 2 f 2 f 2 f 2 f 1 a + 2 f 2 f 2 f 2 f 2 f + a + f + t + u + v + w + X + 1 a 1 a 1 a 1 a 1 a + 1 a 1 a 1 a 1 a 2 f + 1 a 1 a 1 a 2 f 1 a + 1 a 1 a 1 a 2 f 2 f + 1 a 1 a 2 f 1 a 1 a + 1 a 1 a 2 f 1 a 2 f + 1 a 1 a 2 f 2 f 1 a + 1 a 1 a 2 f 2 f 2 f + 1 a 2 f 1 a 1 a 1 a + 1 a 2 f 1 a 1 a 2 f + 1 a 2 f 1 a 2 f 1 a + 1 a 2 f 1 a 2 f 2 f + 1 a 2 f 2 f 1 a 1 a + 1 a 2 f 2 f 1 a 2 f + 1 a 2 f 2 f 2 f 1 a + 1 a 2 f 2 f 2 f 2 f + 2 f 1 a 1 a 1 a 1 a + 2 f 1 a 1 a 1 a 2 f + 2 f 1 a 1 a 2 f 1 a + 2 f 1 a 1 a 2 f 2 f + 2 f 1 a 2 f 1 a 1 a + 2 f 1 a 2 f 1 a 2 f + 2 f 1 a 2 f 2 f 1 a + 2 f 1 a 2 f 2 f 2 f + 2 f 2 f 1 a 1 a 1 a + 2 f 2 f 1 a 1 a 2 f + 2 f 2 f 1 a 2 f 1 a + 2 f 2 f 1 a 2 f 2 f + 2 f 2 f 2 f 1 a 1 a + 2 f 2 f 2 f 1 a 2 f + 2 f 2 f 2 f 2 f 1 a + 2 f 2 f 2 f 2 f 2 f + a + f + t + u + v + w + X + 1 a 1 a 1 a 1 a 1 a + 1 a 1 a 1 a 1 a 2 f + 1 a 1 a 1 a 2 f 1 a + 1 a 1 a 1 a 2 f 2 f + 1 a 1 a 2 f 1 a 1 a + 1 a 1 a 2 f 1 a 2 f + 1 a 1 a 2 f 2 f 1 a + 1 a 1 a 2 f 2 f 2 f + 1 a 2 f 1 a 1 a 1 a + 1 a 2 f 1 a 1 a 2 f + 1 a 2 f 1 a 2 f 1 a + 1 a 2 f 1 a 2 f 2 f + 1 a 2 f 2 f 1 a 1 a + 1 a 2 f 2 f 1 a 2 f + 1 a 2 f 2 f 2 f 1 a + 1 a 2 f 2 f 2 f 2 f + 2 f 1 a 1 a 1 a 1 a + 2 f 1 a 1 a 1 a 2 f + 2 f 1 a 1 a 2 f 1 a + 2 f 1 a 1 a 2 f 2 f + 2 f 1 a 2 f 1 a 1 a + 2 f 1 a 2 f 1 a 2 f + 2 f 1 a 2 f 2 f 1 a + 2 f 1 a 2 f 2 f 2 f + 2 f 2 f 1 a 1 a 1 a + 2 f 2 f 1 a 1 a 2 f + 2 f 2 f 1 a 2 f 1 a + 2 f 2 f 1 a 2 f 2 f + 2 f 2 f 2 f 1 a 1 a + 2 f 2 f 2 f 1 a 2 f + 2 f 2 f 2 f 2 f 1 a + 2 f 2 f 2 f 2 f 2 f + a + f + t + u + v + w + X + 1 a 1 a 1 a 1 a 1 a + 1 a 1 a 1 a 1 a 2 f + 1 a 1 a 1 a 2 f 1 a + 1 a 1 a 1 a 2 f 2 f + 1 a 1 a 2 f 1 a 1 a + 1 a 1 a 2 f 1 a 2 f + 1 a 1 a 2 f 2 f 1 a + 1 a 1 a 2 f 2 f 2 f + 1 a 2 f 1 a 1 a 1 a + 1 a 2 f 1 a 1 a 2 f + 1 a 2 f 1 a 2 f 1 a + 1 a 2 f 1 a 2 f 2 f + 1 a 2 f 2 f 1 a 1 a + 1 a 2 f 2 f 1 a 2 f + 1 a 2 f 2 f 2 f 1 a + 1 a 2 f 2 f 2 f 2 f + 2 f 1 a 1 a 1 a 1 a + 2 f 1 a 1 a 1 a 2 f + 2 f 1 a 1 a 2 f 1 a + 2 f 1 a 1 a 2 f 2 f + 2 f 1 a 2 f 1 a 1 a + 2 f 1 a 2 f 1 a 2 f + 2 f 1 a 2 f 2 f 1 a + 2 f 1 a 2 f 2 f 2 f + 2 f 2 f 1 a 1 a 1 a + 2 f 2 f 1 a 1 a 2 f + 2 f 2 f 1 a 2 f 1 a + 2 f 2 f 1 a 2 f 2 f + 2 f 2 f 2 f 1 a 1 a + 2 f 2 f 2 f 1 a 2 f + 2 f 2 f 2 f 2 f 1 a + 2 f 2 f 2 f 2 f 2 f + a + f + t + u + v + w + X + 1 a 1 a 1 a 1 a 1 a + 1 a 1 a 1 a 1 a 2 f + 1 a 1 a 1 a 2 f 1 a + 1 a 1 a 1 a 2 f 2 f + 1 a 1 a 2 f 1 a 1 a + 1 a 1 a 2 f 1 a 2 f + 1 a 1 a 2 f 2 f 1 a + 1 a 1 a 2 f 2 f 2 f + 1 a 2 f 1 a 1 a 1 a + 1 a 2 f 1 a 1 a 2 f + 1 a 2 f 1 a 2 f 1 a + 1 a 2 f 1 a 2 f 2 f + 1 a 2 f 2 f 1 a 1 a + 1 a 2 f 2 f 1 a 2 f + 1 a 2 f 2 f 2 f 1 a + 1 a 2 f 2 f 2 f 2 f + 2 f 1 a 1 a 1 a 1 a + 2 f 1 a 1 a 1 a 2 f + 2 f 1 a 1 a 2 f 1 a + 2 f 1 a 1 a 2 f 2 f + 2 f 1 a 2 f 1 a 1 a + 2 f 1 a 2 f 1 a 2 f + 2 f 1 a 2 f 2 f 1 a + 2 f 1 a 2 f 2 f 2 f + 2 f 2 f 1 a 1 a 1 a + 2 f 2 f 1 a 1 a 2 f + 2 f 2 f 1 a 2 f 1 a + 2 f 2 f 1 a 2 f 2 f + 2 f 2 f 2 f 1 a 1 a + 2 f 2 f 2 f 1 a 2 f + 2 f 2 f 2 f 2 f 1 a + 2 f 2 f 2 f 2 f 2 f + a + f + t + u + v + w + X + 1 a 1 a 1 a 1 a 1 a + 1 a 1 a 1 a 1 a 2 f + 1 a 1 a 1 a 2 f 1 a + 1 a 1 a 1 a 2 f 2 f + 1 a 1 a 2 f 1 a 1 a + 1 a 1 a 2 f 1 a 2 f + 1 a 1 a 2 f 2 f 1 a + 1 a 1 a 2 f 2 f 2 f + 1 a 2 f 1 a 1 a 1 a + 1 a 2 f 1 a 1 a 2 f + 1 a 2 f 1 a 2 f 1 a + 1 a 2 f 1 a 2 f 2 f + 1 a 2 f 2 f 1 a 1 a + 1 a 2 f 2 f 1 a 2 f + 1 a 2 f 2 f 2 f 1 a + 1 a 2 f 2 f 2 f 2 f + 2 f 1 a 1 a 1 a 1 a + 2 f 1 a 1 a 1 a 2 f + 2 f 1 a 1 a 2 f 1 a + 2 f 1 a 1 a 2 f 2 f + 2 f 1 a 2 f 1 a 1 a + 2 f 1 a 2 f 1 a 2 f + 2 f 1 a 2 f 2 f 1 a + 2 f 1 a 2 f 2 f 2 f + 2 f 2 f 1 a 1 a 1 a + 2 f 2 f 1 a 1 a 2 f + 2 f 2 f 1 a 2 f 1 a + 2 f 2 f 1 a 2 f 2 f + 2 f 2 f 2 f 1 a 1 a + 2 f 2 f 2 f 1 a 2 f + 2 f 2 f 2 f 2 f 1 a + 2 f 2 f 2 f 2 f 2 f + a + f + t + u + v + w + X + 1 a 1 a 1 a 1 a 1 a + 1 a 1 a 1 a 1 a 2 f + 1 a 1 a 1 a 2 f 1 a + 1 a 1 a 1 a 2 f 2 f + 1 a 1 a 2 f 1 a 1 a + 1 a 1 a 2 f 1 a 2 f + 1 a 1 a 2 f 2 f 1 a + 1 a 1 a 2 f 2 f 2 f + 1 a 2 f 1 a 1 a 1 a + 1 a 2 f 1 a 1 a 2 f + 1 a 2 f 1 a 2 f 1 a + 1 a 2 f 1 a 2 f 2 f + 1 a 2 f 2 f 1 a 1 a + 1 a 2 f 2 f 1 a 2 f + 1 a 2 f 2 f 2 f 1 a + 1 a 2 f 2 f 2 f 2 f + 2 f 1 a 1 a 1 a 1 a + 2 f 1 a 1 a 1 a 2 f + 2 f 1 a 1 a 2 f 1 a + 2 f 1 a 1 a 2 f 2 f + 2 f 1 a 2 f 1 a 1 a + 2 f 1 a 2 f 1 a 2 f + 2 f 1 a 2 f 2 f 1 a + 2 f 1 a 2 f 2 f 2 f + 2 f 2 f 1 a 1 a 1 a + 2 f 2 f 1 a 1 a 2 f + 2 f 2 f 1 a 2 f 1 a + 2 f 2 f 1 a 2 f 2 f + 2 f 2 f 2 f 1 a 1 a + 2 f 2 f 2 f 1 a 2 f + 2 f 2 f 2 f 2 f 1 a + 2 f 2 f 2 f 2 f 2 f + a + f + t + u + v + w + X + 1 a 1 a 1 a 1 a 1 a + 1 a 1 a 1 a 1 a 2 f + 1 a 1 a 1 a 2 f 1 a + 1 a 1 a 1 a 2 f 2 f + 1 a 1 a 2 f 1 a 1 a + 1 a 1 a 2 f 1 a 2 f + 1 a 1 a 2 f 2 f 1 a + 1 a 1 a 2 f 2 f 2 f + 1 a 2 f 1 a 1 a 1 a + 1 a 2 f 1 a 1 a 2 f + 1 a 2 f 1 a 2 f 1 a + 1 a 2 f 1 a 2 f 2 f + 1 a 2 f 2 f 1 a 1 a + 1 a 2 f 2 f 1 a 2 f + 1 a 2 f 2 f 2 f 1 a + 1 a 2 f 2 f 2 f 2 f + 2 f 1 a 1 a 1 a 1 a + 2 f 1 a 1 a 1 a 2 f + 2 f 1 a 1 a 2 f 1 a + 2 f 1 a 1 a 2 f 2 f + 2 f 1 a 2 f 1 a 1 a + 2 f 1 a 2 f 1 a 2 f + 2 f 1 a 2 f 2 f 1 a + 2 f 1 a 2 f 2 f 2 f + 2 f 2 f 1 a 1 a 1 a + 2 f 2 f 1 a 1 a 2 f + 2 f 2 f 1 a 2 f 1 a + 2 f 2 f 1 a 2 f 2 f + 2 f 2 f 2 f 1 a 1 a + 2 f 2 f 2 f 1 a 2 f + 2 f 2 f 2 f 2 f 1 a + 2 f 2 f 2 f 2 f 2 f + a + f + t + u + v + w + X + 1 a 1 a 1 a 1 a 1 a + 1 a 1 a 1 a 1 a 2 f + 1 a 1 a 1 a 2 f 1 a + 1 a 1 a 1 a 2 f 2 f + 1 a 1 a 2 f 1 a 1 a + 1 a 1 a 2 f 1 a 2 f + 1 a 1 a 2 f 2 f 1 a + 1 a 1 a 2 f 2 f 2 f + 1 a 2 f 1 a 1 a 1 a + 1 a 2 f 1 a 1 a 2 f + 1 a 2 f 1 a 2 f 1 a + 1 a 2 f 1 a 2 f 2 f + 1 a 2 f 2 f 1 a 1 a + 1 a 2 f 2 f 1 a 2 f + 1 a 2 f 2 f 2 f 1 a + 1 a 2 f 2 f 2 f 2 f + 2 f 1 a 1 a 1 a 1 a + 2 f 1 a 1 a 1 a 2 f + 2 f 1 a 1 a 2 f 1 a + 2 f 1 a 1 a 2 f 2 f + 2 f 1 a 2 f 1 a 1 a + 2 f 1 a 2 f 1 a 2 f + 2 f 1 a 2 f 2 f 1 a + 2 f 1 a 2 f 2 f 2 f + 2 f 2 f 1 a 1 a 1 a + 2 f 2 f 1 a 1 a 2 f + 2 f 2 f 1 a 2 f 1 a + 2 f 2 f 1 a 2 f 2 f + 2 f 2 f 2 f 1 a 1 a + 2 f 2 f 2 f 1 a 2 f + 2 f 2 f 2 f 2 f 1 a + 2 f 2 f 2 f 2 f 2 f + a + f + t + u + v + w + X + 1 a 1 a 1 a 1 a 1 a + 1 a 1 a 1 a 1 a 2 f + 1 a 1 a 1 a 2 f 1 a + 1 a 1 a 1 a 2 f 2 f + 1 a 1 a 2 f 1 a 1 a + 1 a 1 a 2 f 1 a 2 f + 1 a 1 a 2 f 2 f 1 a + 1 a 1 a 2 f 2 f 2 f + 1 a 2 f 1 a 1 a 1 a + 1 a 2 f 1 a 1 a 2 f + 1 a 2 f 1 a 2 f 1 a + 1 a 2 f 1 a 2 f 2 f + 1 a 2 f 2 f 1 a 1 a + 1 a 2 f 2 f 1 a 2 f + 1 a 2 f 2 f 2 f 1 a + 1 a 2 f 2 f 2 f 2 f + 2 f 1 a 1 a 1 a 1 a + 2 f 1 a 1 a 1 a 2 f + 2 f 1 a 1 a 2 f 1 a + 2 f 1 a 1 a 2 f 2 f + 2 f 1 a 2 f 1 a 1 a + 2 f 1 a 2 f 1 a 2 f + 2 f 1 a 2 f 2 f 1 a + 2 f 1 a 2 f 2 f 2 f + 2 f 2 f 1 a 1 a 1 a + 2 f 2 f 1 a 1 a 2 f + 2 f 2 f 1 a 2 f 1 a + 2 f 2 f 1 a 2 f 2 f + 2 f 2 f 2 f 1 a 1 a + 2 f 2 f 2 f 1 a 2 f + 2 f 2 f 2 f 2 f 1 a + 2 f 2 f 2 f 2 f 2 f + a + f + t + u + v + w + X + 1 a 1 a 1 a 1 a 1 a + 1 a 1 a 1 a 1 a 2 f + 1 a 1 a 1 a 2 f 1 a + 1 a 1 a 1 a 2 f 2 f + 1 a 1 a 2 f 1 a 1 a + 1 a 1 a 2 f 1 a 2 f + 1 a 1 a 2 f 2 f 1 a + 1 a 1 a 2 f 2 f 2 f + 1 a 2 f 1 a 1 a 1 a + 1 a 2 f 1 a 1 a 2 f + 1 a 2 f 1 a 2 f 1 a + 1 a 2 f 1 a 2 f 2 f + 1 a 2 f 2 f 1 a 1 a + 1 a 2 f 2 f 1 a 2 f + 1 a 2 f 2 f 2 f 1 a + 1 a 2 f 2 f 2 f 2 f + 2 f 1 a 1 a 1 a 1 a + 2 f 1 a 1 a 1 a 2 f + 2 f 1 a 1 a 2 f 1 a + 2 f 1 a 1 a 2 f 2 f + 2 f 1 a 2 f 1 a 1 a + 2 f 1 a 2 f 1 a 2 f + 2 f 1 a 2 f 2 f 1 a + 2 f 1 a 2 f 2 f 2 f + 2 f 2 f 1 a 1 a 1 a + 2 f 2 f 1 a 1 a 2 f + 2 f 2 f 1 a 2 f 1 a + 2 f 2 f 1 a 2 f 2 f + 2 f 2 f 2 f 1 a 1 a + 2 f 2 f 2 f 1 a 2 f + 2 f 2 f 2 f 2 f 1 a + 2 f 2 f 2 f 2 f 2 f + a + f + t + u + v + w + X + 1 a 1 a 1 a 1 a 1 a + 1 a 1 a 1 a 1 a 2 f + 1 a 1 a 1 a 2 f 1 a + 1 a 1 a 1 a 2 f 2 f + 1 a 1 a 2 f 1 a 1 a + 1 a 1 a 2 f 1 a 2 f + 1 a 1 a 2 f 2 f 1 a + 1 a 1 a 2 f 2 f 2 f + 1 a 2 f 1 a 1 a 1 a + 1 a 2 f 1 a 1 a 2 f + 1 a 2 f 1 a 2 f 1 a + 1 a 2 f 1 a 2 f 2 f + 1 a 2 f 2 f 1 a 1 a + 1 a 2 f 2 f 1 a 2 f + 1 a 2 f 2 f 2 f 1 a + 1 a 2 f 2 f 2 f 2 f + 2 f 1 a 1 a 1 a 1 a + 2 f 1 a 1 a 1 a 2 f + 2 f 1 a 1 a 2 f 1 a + 2 f 1 a 1 a 2 f 2 f + 2 f 1 a 2 f 1 a 1 a + 2 f 1 a 2 f 1 a 2 f + 2 f 1 a 2 f 2 f 1 a + 2 f 1 a 2 f 2 f 2 f + 2 f 2 f 1 a 1 a 1 a + 2 f 2 f 1 a 1 a 2 f + 2 f 2 f 1 a 2 f 1 a + 2 f 2 f 1 a 2 f 2 f + 2 f 2 f 2 f 1 a 1 a + 2 f 2 f 2 f 1 a 2 f + 2 f 2 f 2 f 2 f 1 a + 2 f 2 f 2 f 2 f 2 f + a + f + t + u + v + w + X + 1 a 1 a 1 a 1 a 1 a + 1 a 1 a 1 a 1 a 2 f + 1 a 1 a 1 a 2 f 1 a + 1 a 1 a 1 a 2 f 2 f + 1 a 1 a 2 f 1 a 1 a + 1 a 1 a 2 f 1 a 2 f + 1 a 1 a 2 f 2 f 1 a + 1 a 1 a 2 f 2 f 2 f + 1 a 2 f 1 a 1 a 1 a + 1 a 2 f 1 a 1 a 2 f + 1 a 2 f 1 a 2 f 1 a + 1 a 2 f 1 a 2 f 2 f + 1 a 2 f 2 f 1 a 1 a + 1 a 2 f 2 f 1 a 2 f + 1 a 2 f 2 f 2 f 1 a + 1 a 2 f 2 f 2 f 2 f + 2 f 1 a 1 a 1 a 1 a + 2 f 1 a 1 a 1 a 2 f + 2 f 1 a 1 a 2 f 1 a + 2 f 1 a 1 a 2 f 2 f + 2 f 1 a 2 f 1 a 1 a + 2 f 1 a 2 f 1 a 2 f + 2 f 1 a 2 f 2 f 1 a + 2 f 1 a 2 f 2 f 2 f + 2 f 2 f 1 a 1 a 1 a + 2 f 2 f 1 a 1 a 2 f + 2 f 2 f 1 a 2 f 1 a + 2 f 2 f 1 a 2 f 2 f + 2 f 2 f 2 f 1 a 1 a + 2 f 2 f 2 f 1 a 2 f + 2 f 2 f 2 f 2 f 1 a + 2 f 2 f 2 f 2 f 2 f + a + f + t + u + v + w + X + 1 a 1 a 1 a 1 a 1 a + 1 a 1 a 1 a 1 a 2 f + 1 a 1 a 1 a 2 f 1 a + 1 a 1 a 1 a 2 f 2 f + 1 a 1 a 2 f 1 a 1 a + 1 a 1 a 2 f 1 a 2 f + 1 a 1 a 2 f 2 f 1 a + 1 a 1 a 2 f 2 f 2 f + 1 a 2 f 1 a 1 a 1 a + 1 a 2 f 1 a 1 a 2 f + 1 a 2 f 1 a 2 f 1 a + 1 a 2 f 1 a 2 f 2 f + 1 a 2 f 2 f 1 a 1 a + 1 a 2 f 2 f 1 a 2 f + 1 a 2 f 2 f 2 f 1 a + 1 a 2 f 2 f 2 f 2 f + 2 f 1 a 1 a 1 a 1 a + 2 f 1 a 1 a 1 a 2 f + 2 f 1 a 1 a 2 f 1 a + 2 f 1 a 1 a 2 f 2 f + 2 f 1 a 2 f 1 a 1 a + 2 f 1 a 2 f 1 a 2 f + 2 f 1 a 2 f 2 f 1 a + 2 f 1 a 2 f 2 f 2 f + 2 f 2 f 1 a 1 a 1 a + 2 f 2 f 1 a 1 a 2 f + 2 f 2 f 1 a 2 f 1 a + 2 f 2 f 1 a 2 f 2 f + 2 f 2 f 2 f 1 a 1 a + 2 f 2 f 2 f 1 a 2 f + 2 f 2 f 2 f 2 f 1 a + 2 f 2 f 2 f 2 f 2 f + a + f + t + u + v + w + X + 1 a 1 a 1 a 1 a 1 a + 1 a 1 a 1 a 1 a 2 f + 1 a 1 a 1 a 2 f 1 a + 1 a 1 a 1 a 2 f 2 f + 1 a 1 a 2 f 1 a 1 a + 1 a 1 a 2 f 1 a 2 f + 1 a 1 a 2 f 2 f 1 a + 1 a 1 a 2 f 2 f 2 f + 1 a 2 f 1 a 1 a 1 a + 1 a 2 f 1 a 1 a 2 f + 1 a 2 f 1 a 2 f 1 a + 1 a 2 f 1 a 2 f 2 f + 1 a 2 f 2 f 1 a 1 a + 1 a 2 f 2 f 1 a 2 f + 1 a 2 f 2 f 2 f 1 a + 1 a 2 f 2 f 2 f 2 f + 2 f 1 a 1 a 1 a 1 a + 2 f 1 a 1 a 1 a 2 f + 2 f 1 a 1 a 2 f 1 a + 2 f 1 a 1 a 2 f 2 f + 2 f 1 a 2 f 1 a 1 a + 2 f 1 a 2 f 1 a 2 f + 2 f 1 a 2 f 2 f 1 a + 2 f 1 a 2 f 2 f 2 f + 2 f 2 f 1 a 1 a 1 a + 2 f 2 f 1 a 1 a 2 f + 2 f 2 f 1 a 2 f 1 a + 2 f 2 f 1 a 2 f 2 f + 2 f 2 f 2 f 1 a 1 a + 2 f 2 f 2 f 1 a 2 f + 2 f 2 f 2 f 2 f 1 a + 2 f 2 f 2 f 2 f 2 f + a + f + t + u + v + w + X +===DONE=== diff --git a/ext/oci8/tests/imp_res_4.phpt b/ext/oci8/tests/imp_res_4.phpt new file mode 100644 index 0000000000..762ae77224 --- /dev/null +++ b/ext/oci8/tests/imp_res_4.phpt @@ -0,0 +1,82 @@ +--TEST-- +Oracle Database 12c Implicit Result Sets: oci_fetch +--SKIPIF-- +<?php +if (!extension_loaded('oci8')) die ("skip no oci8 extension"); +$target_dbs = array('oracledb' => true, 'timesten' => false); // test runs on these DBs +require(dirname(__FILE__).'/skipif.inc'); +preg_match('/.*Release ([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)*/', oci_server_version($c), $matches); +if (!(isset($matches[0]) && $matches[1] >= 12)) { + die("skip expected output only valid when using Oracle Database 12c or greater"); +} +preg_match('/^[[:digit:]]+/', oci_client_version(), $matches); +if (!(isset($matches[0]) && $matches[0] >= 12)) { + die("skip works only with Oracle 12c or greater version of Oracle client libraries"); +} +?> +--FILE-- +<?php + +require(dirname(__FILE__).'/connect.inc'); + +// Initialization + +$stmtarray = array( + "create or replace procedure imp_res_4_proc as + c1 sys_refcursor; + begin + open c1 for select 1 from dual union select 2 from dual; + dbms_sql.return_result (c1); + end;" +); + +oci8_test_sql_execute($c, $stmtarray); + +// Run Test + +echo "Test 1\n"; +$s = oci_parse($c, "begin imp_res_4_proc(); end;"); +oci_execute($s); +oci_fetch($s); // This will fail with ORA-24374 +var_dump(oci_result($s, 1)); + +echo "\nTest 2\n"; +$s = oci_parse($c, "begin imp_res_4_proc(); end;"); +oci_execute($s); +$r = oci_fetch_row($s); +var_dump($r); +oci_fetch($s); // This will fail with ORA-24374 +var_dump(oci_result($s, 1)); +$r = oci_fetch_row($s); +var_dump($r); + +// Clean up + +$stmtarray = array( + "drop procedure imp_res_4_proc", +); + +oci8_test_sql_execute($c, $stmtarray); + +?> +===DONE=== +<?php exit(0); ?> +--EXPECTF-- +Test 1 + +Warning: oci_fetch(): ORA-24374: %s in %simp_res_4.php on line %d +bool(false) + +Test 2 +array(1) { + [0]=> + string(1) "1" +} + +Warning: oci_fetch(): ORA-24374: %s in %simp_res_4.php on line %d +bool(false) +array(1) { + [0]=> + string(1) "2" +} +===DONE=== diff --git a/ext/oci8/tests/imp_res_5.phpt b/ext/oci8/tests/imp_res_5.phpt new file mode 100644 index 0000000000..564a7a3740 --- /dev/null +++ b/ext/oci8/tests/imp_res_5.phpt @@ -0,0 +1,84 @@ +--TEST-- +Oracle Database 12c Implicit Result Sets: oci_fetch_all +--SKIPIF-- +<?php +if (!extension_loaded('oci8')) die ("skip no oci8 extension"); +$target_dbs = array('oracledb' => true, 'timesten' => false); // test runs on these DBs +require(dirname(__FILE__).'/skipif.inc'); +preg_match('/.*Release ([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)*/', oci_server_version($c), $matches); +if (!(isset($matches[0]) && $matches[1] >= 12)) { + die("skip expected output only valid when using Oracle Database 12c or greater"); +} +preg_match('/^[[:digit:]]+/', oci_client_version(), $matches); +if (!(isset($matches[0]) && $matches[0] >= 12)) { + die("skip works only with Oracle 12c or greater version of Oracle client libraries"); +} +?> +--FILE-- +<?php + +require(dirname(__FILE__).'/connect.inc'); + +// Initialization + +$stmtarray = array( + "create or replace procedure imp_res_5_proc as + c1 sys_refcursor; + begin + open c1 for select 1 from dual union select 2 from dual; + dbms_sql.return_result (c1); + end;" +); + +oci8_test_sql_execute($c, $stmtarray); + +// Run Test + +echo "Test 1\n"; +$s = oci_parse($c, "begin imp_res_5_proc(); end;"); +oci_execute($s); +oci_fetch_all($s,$res); // This will fail with ORA-24374 +var_dump($res); + +echo "\nTest 2\n"; +$s = oci_parse($c, "begin imp_res_5_proc(); end;"); +oci_execute($s); +$r = oci_fetch_row($s); +var_dump($r); +oci_fetch_all($s, $res); // This will fail with ORA-24374 +var_dump($res); +$r = oci_fetch_row($s); +var_dump($r); + +// Clean up + +$stmtarray = array( + "drop procedure imp_res_5_proc", +); + +oci8_test_sql_execute($c, $stmtarray); + +?> +===DONE=== +<?php exit(0); ?> +--EXPECTF-- +Test 1 + +Warning: oci_fetch_all(): ORA-24374: %s in %simp_res_5.php on line %d +array(0) { +} + +Test 2 +array(1) { + [0]=> + string(1) "1" +} + +Warning: oci_fetch_all(): ORA-24374: %s in %simp_res_5.php on line %d +array(0) { +} +array(1) { + [0]=> + string(1) "2" +} +===DONE=== diff --git a/ext/oci8/tests/imp_res_6.phpt b/ext/oci8/tests/imp_res_6.phpt new file mode 100644 index 0000000000..f94efe70db --- /dev/null +++ b/ext/oci8/tests/imp_res_6.phpt @@ -0,0 +1,118 @@ +--TEST-- +Oracle Database 12c Implicit Result Sets: alternating oci_fetch_* calls +--SKIPIF-- +<?php +if (!extension_loaded('oci8')) die ("skip no oci8 extension"); +$target_dbs = array('oracledb' => true, 'timesten' => false); // test runs on these DBs +require(dirname(__FILE__).'/skipif.inc'); +preg_match('/.*Release ([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)*/', oci_server_version($c), $matches); +if (!(isset($matches[0]) && $matches[1] >= 12)) { + die("skip expected output only valid when using Oracle Database 12c or greater"); +} +preg_match('/^[[:digit:]]+/', oci_client_version(), $matches); +if (!(isset($matches[0]) && $matches[0] >= 12)) { + die("skip works only with Oracle 12c or greater version of Oracle client libraries"); +} +?> +--FILE-- +<?php + +require(dirname(__FILE__).'/connect.inc'); + +// Initialization + +$stmtarray = array( + "drop table imp_res_6_tab", + "create table imp_res_6_tab (c1 number, c2 varchar2(10))", + "insert into imp_res_6_tab values (1, 'a')", + "insert into imp_res_6_tab values (2, 'b')", + "insert into imp_res_6_tab values (3, 'c')", + "insert into imp_res_6_tab values (4, 'd')", + "insert into imp_res_6_tab values (5, 'e')", + "insert into imp_res_6_tab values (6, 'f')", + + "create or replace procedure imp_res_6_proc as + c1 sys_refcursor; + begin + open c1 for select * from imp_res_6_tab order by 1; + dbms_sql.return_result(c1); + end;" +); + +oci8_test_sql_execute($c, $stmtarray); + +// Run Test + +echo "Test 1\n"; +$s = oci_parse($c, "begin imp_res_6_proc(); end;"); +oci_execute($s); + +$row = oci_fetch_assoc($s); +var_dump($row); +$row = oci_fetch_row($s); +var_dump($row); +$row = oci_fetch_object($s); +var_dump($row); +$row = oci_fetch_array($s); +var_dump($row); +$row = oci_fetch_array($s, OCI_NUM); +var_dump($row); +$row = oci_fetch_array($s, OCI_ASSOC); +var_dump($row); + + +// Clean up + +$stmtarray = array( + "drop procedure imp_res_6_proc", + "drop table imp_res_6_tab", +); + +oci8_test_sql_execute($c, $stmtarray); + +?> +===DONE=== +<?php exit(0); ?> +--EXPECTF-- +Test 1 +array(2) { + ["C1"]=> + string(1) "1" + ["C2"]=> + string(1) "a" +} +array(2) { + [0]=> + string(1) "2" + [1]=> + string(1) "b" +} +object(stdClass)#%d (2) { + ["C1"]=> + string(1) "3" + ["C2"]=> + string(1) "c" +} +array(4) { + [0]=> + string(1) "4" + ["C1"]=> + string(1) "4" + [1]=> + string(1) "d" + ["C2"]=> + string(1) "d" +} +array(2) { + [0]=> + string(1) "5" + [1]=> + string(1) "e" +} +array(2) { + ["C1"]=> + string(1) "6" + ["C2"]=> + string(1) "f" +} +===DONE=== diff --git a/ext/oci8/tests/imp_res_7.phpt b/ext/oci8/tests/imp_res_7.phpt new file mode 100644 index 0000000000..05ae5e6857 --- /dev/null +++ b/ext/oci8/tests/imp_res_7.phpt @@ -0,0 +1,873 @@ +--TEST-- +Oracle Database 12c Implicit Result Sets: bigger data size +--SKIPIF-- +<?php +if (!extension_loaded('oci8')) die ("skip no oci8 extension"); +$target_dbs = array('oracledb' => true, 'timesten' => false); // test runs on these DBs +require(dirname(__FILE__).'/skipif.inc'); +preg_match('/.*Release ([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)*/', oci_server_version($c), $matches); +if (!(isset($matches[0]) && $matches[1] >= 12)) { + die("skip expected output only valid when using Oracle Database 12c or greater"); +} +preg_match('/^[[:digit:]]+/', oci_client_version(), $matches); +if (!(isset($matches[0]) && $matches[0] >= 12)) { + die("skip works only with Oracle 12c or greater version of Oracle client libraries"); +} +?> +--FILE-- +<?php + +require(dirname(__FILE__).'/connect.inc'); + +// Initialization + +$stmt = + "declare + c1 sys_refcursor; + begin + open c1 for select 1 from dual; + dbms_sql.return_result(c1); + open c1 for select 2 from dual; + dbms_sql.return_result(c1); + open c1 for select 3 from dual; + dbms_sql.return_result(c1); + open c1 for select 4 from dual; + dbms_sql.return_result(c1); + open c1 for select 5 from dual; + dbms_sql.return_result(c1); + open c1 for select 6 from dual; + dbms_sql.return_result(c1); + open c1 for select 7 from dual; + dbms_sql.return_result(c1); + open c1 for select 8 from dual; + dbms_sql.return_result(c1); + open c1 for select 9 from dual; + dbms_sql.return_result(c1); + open c1 for select 10 from dual; + dbms_sql.return_result(c1); + open c1 for select 11 from dual; + dbms_sql.return_result(c1); + open c1 for select 12 from dual; + dbms_sql.return_result(c1); + open c1 for select 13 from dual; + dbms_sql.return_result(c1); + open c1 for select 14 from dual; + dbms_sql.return_result(c1); + open c1 for select 15 from dual; + dbms_sql.return_result(c1); + open c1 for select 16 from dual; + dbms_sql.return_result(c1); + open c1 for select 17 from dual; + dbms_sql.return_result(c1); + open c1 for select 18 from dual; + dbms_sql.return_result(c1); + open c1 for select 19 from dual; + dbms_sql.return_result(c1); + open c1 for select 20 from dual; + dbms_sql.return_result(c1); + open c1 for select 21 from dual; + dbms_sql.return_result(c1); + open c1 for select 22 from dual; + dbms_sql.return_result(c1); + open c1 for select 23 from dual; + dbms_sql.return_result(c1); + open c1 for select 24 from dual; + dbms_sql.return_result(c1); + open c1 for select 25 from dual; + dbms_sql.return_result(c1); + open c1 for select 26 from dual; + dbms_sql.return_result(c1); + open c1 for select 27 from dual; + dbms_sql.return_result(c1); + open c1 for select 28 from dual; + dbms_sql.return_result(c1); + open c1 for select 29 from dual; + dbms_sql.return_result(c1); + open c1 for select 30 from dual; + dbms_sql.return_result(c1); + open c1 for select 31 from dual; + dbms_sql.return_result(c1); + open c1 for select 32 from dual; + dbms_sql.return_result(c1); + open c1 for select 33 from dual; + dbms_sql.return_result(c1); + open c1 for select 34 from dual; + dbms_sql.return_result(c1); + open c1 for select 35 from dual; + dbms_sql.return_result(c1); + open c1 for select 36 from dual; + dbms_sql.return_result(c1); + open c1 for select 37 from dual; + dbms_sql.return_result(c1); + open c1 for select 38 from dual; + dbms_sql.return_result(c1); + open c1 for select 39 from dual; + dbms_sql.return_result(c1); + open c1 for select 40 from dual; + dbms_sql.return_result(c1); + open c1 for select 41 from dual; + dbms_sql.return_result(c1); + open c1 for select 42 from dual; + dbms_sql.return_result(c1); + open c1 for select 43 from dual; + dbms_sql.return_result(c1); + open c1 for select 44 from dual; + dbms_sql.return_result(c1); + open c1 for select 45 from dual; + dbms_sql.return_result(c1); + open c1 for select 46 from dual; + dbms_sql.return_result(c1); + open c1 for select 47 from dual; + dbms_sql.return_result(c1); + open c1 for select 48 from dual; + dbms_sql.return_result(c1); + open c1 for select 49 from dual; + dbms_sql.return_result(c1); + open c1 for select 50 from dual; + dbms_sql.return_result(c1); + open c1 for select 51 from dual; + dbms_sql.return_result(c1); + open c1 for select 52 from dual; + dbms_sql.return_result(c1); + open c1 for select 53 from dual; + dbms_sql.return_result(c1); + open c1 for select 54 from dual; + dbms_sql.return_result(c1); + open c1 for select 55 from dual; + dbms_sql.return_result(c1); + open c1 for select 56 from dual; + dbms_sql.return_result(c1); + open c1 for select 57 from dual; + dbms_sql.return_result(c1); + open c1 for select 58 from dual; + dbms_sql.return_result(c1); + open c1 for select 59 from dual; + dbms_sql.return_result(c1); + open c1 for select 60 from dual; + dbms_sql.return_result(c1); + open c1 for select 61 from dual; + dbms_sql.return_result(c1); + open c1 for select 62 from dual; + dbms_sql.return_result(c1); + open c1 for select 63 from dual; + dbms_sql.return_result(c1); + open c1 for select 64 from dual; + dbms_sql.return_result(c1); + open c1 for select 65 from dual; + dbms_sql.return_result(c1); + open c1 for select 66 from dual; + dbms_sql.return_result(c1); + open c1 for select 67 from dual; + dbms_sql.return_result(c1); + open c1 for select 68 from dual; + dbms_sql.return_result(c1); + open c1 for select 69 from dual; + dbms_sql.return_result(c1); + open c1 for select 70 from dual; + dbms_sql.return_result(c1); + open c1 for select 71 from dual; + dbms_sql.return_result(c1); + open c1 for select 72 from dual; + dbms_sql.return_result(c1); + open c1 for select 73 from dual; + dbms_sql.return_result(c1); + open c1 for select 74 from dual; + dbms_sql.return_result(c1); + open c1 for select 75 from dual; + dbms_sql.return_result(c1); + open c1 for select 76 from dual; + dbms_sql.return_result(c1); + open c1 for select 77 from dual; + dbms_sql.return_result(c1); + open c1 for select 78 from dual; + dbms_sql.return_result(c1); + open c1 for select 79 from dual; + dbms_sql.return_result(c1); + open c1 for select 80 from dual; + dbms_sql.return_result(c1); + open c1 for select 81 from dual; + dbms_sql.return_result(c1); + open c1 for select 82 from dual; + dbms_sql.return_result(c1); + open c1 for select 83 from dual; + dbms_sql.return_result(c1); + open c1 for select 84 from dual; + dbms_sql.return_result(c1); + open c1 for select 85 from dual; + dbms_sql.return_result(c1); + open c1 for select 86 from dual; + dbms_sql.return_result(c1); + open c1 for select 87 from dual; + dbms_sql.return_result(c1); + open c1 for select 88 from dual; + dbms_sql.return_result(c1); + open c1 for select 89 from dual; + dbms_sql.return_result(c1); + open c1 for select 90 from dual; + dbms_sql.return_result(c1); + open c1 for select 91 from dual; + dbms_sql.return_result(c1); + open c1 for select 92 from dual; + dbms_sql.return_result(c1); + open c1 for select 93 from dual; + dbms_sql.return_result(c1); + open c1 for select 94 from dual; + dbms_sql.return_result(c1); + open c1 for select 95 from dual; + dbms_sql.return_result(c1); + open c1 for select 96 from dual; + dbms_sql.return_result(c1); + open c1 for select 97 from dual; + dbms_sql.return_result(c1); + open c1 for select 98 from dual; + dbms_sql.return_result(c1); + open c1 for select 99 from dual; + dbms_sql.return_result(c1); + open c1 for select 100 from dual; + dbms_sql.return_result(c1); + open c1 for select 101 from dual; + dbms_sql.return_result(c1); + open c1 for select 102 from dual; + dbms_sql.return_result(c1); + open c1 for select 103 from dual; + dbms_sql.return_result(c1); + open c1 for select 104 from dual; + dbms_sql.return_result(c1); + open c1 for select 105 from dual; + dbms_sql.return_result(c1); + open c1 for select 106 from dual; + dbms_sql.return_result(c1); + open c1 for select 107 from dual; + dbms_sql.return_result(c1); + open c1 for select 108 from dual; + dbms_sql.return_result(c1); + open c1 for select 109 from dual; + dbms_sql.return_result(c1); + open c1 for select 110 from dual; + dbms_sql.return_result(c1); + open c1 for select 111 from dual; + dbms_sql.return_result(c1); + open c1 for select 112 from dual; + dbms_sql.return_result(c1); + open c1 for select 113 from dual; + dbms_sql.return_result(c1); + open c1 for select 114 from dual; + dbms_sql.return_result(c1); + open c1 for select 115 from dual; + dbms_sql.return_result(c1); + open c1 for select 116 from dual; + dbms_sql.return_result(c1); + open c1 for select 117 from dual; + dbms_sql.return_result(c1); + open c1 for select 118 from dual; + dbms_sql.return_result(c1); + open c1 for select 119 from dual; + dbms_sql.return_result(c1); + open c1 for select 120 from dual; + dbms_sql.return_result(c1); + open c1 for select 121 from dual; + dbms_sql.return_result(c1); + open c1 for select 122 from dual; + dbms_sql.return_result(c1); + open c1 for select 123 from dual; + dbms_sql.return_result(c1); + open c1 for select 124 from dual; + dbms_sql.return_result(c1); + open c1 for select 125 from dual; + dbms_sql.return_result(c1); + open c1 for select 126 from dual; + dbms_sql.return_result(c1); + open c1 for select 127 from dual; + dbms_sql.return_result(c1); + open c1 for select 128 from dual; + dbms_sql.return_result(c1); + open c1 for select 129 from dual; + dbms_sql.return_result(c1); + open c1 for select 130 from dual; + dbms_sql.return_result(c1); + open c1 for select 131 from dual; + dbms_sql.return_result(c1); + open c1 for select 132 from dual; + dbms_sql.return_result(c1); + open c1 for select 133 from dual; + dbms_sql.return_result(c1); + open c1 for select 134 from dual; + dbms_sql.return_result(c1); + open c1 for select 135 from dual; + dbms_sql.return_result(c1); + open c1 for select 136 from dual; + dbms_sql.return_result(c1); + open c1 for select 137 from dual; + dbms_sql.return_result(c1); + open c1 for select 138 from dual; + dbms_sql.return_result(c1); + open c1 for select 139 from dual; + dbms_sql.return_result(c1); + open c1 for select 140 from dual; + dbms_sql.return_result(c1); + open c1 for select 141 from dual; + dbms_sql.return_result(c1); + open c1 for select 142 from dual; + dbms_sql.return_result(c1); + open c1 for select 143 from dual; + dbms_sql.return_result(c1); + open c1 for select 144 from dual; + dbms_sql.return_result(c1); + open c1 for select 145 from dual; + dbms_sql.return_result(c1); + open c1 for select 146 from dual; + dbms_sql.return_result(c1); + open c1 for select 147 from dual; + dbms_sql.return_result(c1); + open c1 for select 148 from dual; + dbms_sql.return_result(c1); + open c1 for select 149 from dual; + dbms_sql.return_result(c1); + open c1 for select 150 from dual; + dbms_sql.return_result(c1); + open c1 for select 151 from dual; + dbms_sql.return_result(c1); + open c1 for select 152 from dual; + dbms_sql.return_result(c1); + open c1 for select 153 from dual; + dbms_sql.return_result(c1); + open c1 for select 154 from dual; + dbms_sql.return_result(c1); + open c1 for select 155 from dual; + dbms_sql.return_result(c1); + open c1 for select 156 from dual; + dbms_sql.return_result(c1); + open c1 for select 157 from dual; + dbms_sql.return_result(c1); + open c1 for select 158 from dual; + dbms_sql.return_result(c1); + open c1 for select 159 from dual; + dbms_sql.return_result(c1); + open c1 for select 160 from dual; + dbms_sql.return_result(c1); + open c1 for select 161 from dual; + dbms_sql.return_result(c1); + open c1 for select 162 from dual; + dbms_sql.return_result(c1); + open c1 for select 163 from dual; + dbms_sql.return_result(c1); + open c1 for select 164 from dual; + dbms_sql.return_result(c1); + open c1 for select 165 from dual; + dbms_sql.return_result(c1); + open c1 for select 166 from dual; + dbms_sql.return_result(c1); + open c1 for select 167 from dual; + dbms_sql.return_result(c1); + open c1 for select 168 from dual; + dbms_sql.return_result(c1); + open c1 for select 169 from dual; + dbms_sql.return_result(c1); + open c1 for select 170 from dual; + dbms_sql.return_result(c1); + open c1 for select 171 from dual; + dbms_sql.return_result(c1); + open c1 for select 172 from dual; + dbms_sql.return_result(c1); + open c1 for select 173 from dual; + dbms_sql.return_result(c1); + open c1 for select 174 from dual; + dbms_sql.return_result(c1); + open c1 for select 175 from dual; + dbms_sql.return_result(c1); + open c1 for select 176 from dual; + dbms_sql.return_result(c1); + open c1 for select 177 from dual; + dbms_sql.return_result(c1); + open c1 for select 178 from dual; + dbms_sql.return_result(c1); + open c1 for select 179 from dual; + dbms_sql.return_result(c1); + open c1 for select 180 from dual; + dbms_sql.return_result(c1); + open c1 for select 181 from dual; + dbms_sql.return_result(c1); + open c1 for select 182 from dual; + dbms_sql.return_result(c1); + open c1 for select 183 from dual; + dbms_sql.return_result(c1); + open c1 for select 184 from dual; + dbms_sql.return_result(c1); + open c1 for select 185 from dual; + dbms_sql.return_result(c1); + open c1 for select 186 from dual; + dbms_sql.return_result(c1); + open c1 for select 187 from dual; + dbms_sql.return_result(c1); + open c1 for select 188 from dual; + dbms_sql.return_result(c1); + open c1 for select 189 from dual; + dbms_sql.return_result(c1); + open c1 for select 190 from dual; + dbms_sql.return_result(c1); + open c1 for select 191 from dual; + dbms_sql.return_result(c1); + open c1 for select 192 from dual; + dbms_sql.return_result(c1); + open c1 for select 193 from dual; + dbms_sql.return_result(c1); + open c1 for select 194 from dual; + dbms_sql.return_result(c1); + open c1 for select 195 from dual; + dbms_sql.return_result(c1); + open c1 for select 196 from dual; + dbms_sql.return_result(c1); + open c1 for select 197 from dual; + dbms_sql.return_result(c1); + open c1 for select 198 from dual; + dbms_sql.return_result(c1); + open c1 for select 199 from dual; + dbms_sql.return_result(c1); + open c1 for select 200 from dual; + dbms_sql.return_result(c1); + open c1 for select 201 from dual; + dbms_sql.return_result(c1); + open c1 for select 202 from dual; + dbms_sql.return_result(c1); + open c1 for select 203 from dual; + dbms_sql.return_result(c1); + open c1 for select 204 from dual; + dbms_sql.return_result(c1); + open c1 for select 205 from dual; + dbms_sql.return_result(c1); + open c1 for select 206 from dual; + dbms_sql.return_result(c1); + open c1 for select 207 from dual; + dbms_sql.return_result(c1); + open c1 for select 208 from dual; + dbms_sql.return_result(c1); + open c1 for select 209 from dual; + dbms_sql.return_result(c1); + open c1 for select 210 from dual; + dbms_sql.return_result(c1); + open c1 for select 211 from dual; + dbms_sql.return_result(c1); + open c1 for select 212 from dual; + dbms_sql.return_result(c1); + open c1 for select 213 from dual; + dbms_sql.return_result(c1); + open c1 for select 214 from dual; + dbms_sql.return_result(c1); + open c1 for select 215 from dual; + dbms_sql.return_result(c1); + open c1 for select 216 from dual; + dbms_sql.return_result(c1); + open c1 for select 217 from dual; + dbms_sql.return_result(c1); + open c1 for select 218 from dual; + dbms_sql.return_result(c1); + open c1 for select 219 from dual; + dbms_sql.return_result(c1); + open c1 for select 220 from dual; + dbms_sql.return_result(c1); + open c1 for select 221 from dual; + dbms_sql.return_result(c1); + open c1 for select 222 from dual; + dbms_sql.return_result(c1); + open c1 for select 223 from dual; + dbms_sql.return_result(c1); + open c1 for select 224 from dual; + dbms_sql.return_result(c1); + open c1 for select 225 from dual; + dbms_sql.return_result(c1); + open c1 for select 226 from dual; + dbms_sql.return_result(c1); + open c1 for select 227 from dual; + dbms_sql.return_result(c1); + open c1 for select 228 from dual; + dbms_sql.return_result(c1); + open c1 for select 229 from dual; + dbms_sql.return_result(c1); + open c1 for select 230 from dual; + dbms_sql.return_result(c1); + open c1 for select 231 from dual; + dbms_sql.return_result(c1); + open c1 for select 232 from dual; + dbms_sql.return_result(c1); + open c1 for select 233 from dual; + dbms_sql.return_result(c1); + open c1 for select 234 from dual; + dbms_sql.return_result(c1); + open c1 for select 235 from dual; + dbms_sql.return_result(c1); + open c1 for select 236 from dual; + dbms_sql.return_result(c1); + open c1 for select 237 from dual; + dbms_sql.return_result(c1); + open c1 for select 238 from dual; + dbms_sql.return_result(c1); + open c1 for select 239 from dual; + dbms_sql.return_result(c1); + open c1 for select 240 from dual; + dbms_sql.return_result(c1); + open c1 for select 241 from dual; + dbms_sql.return_result(c1); + open c1 for select 242 from dual; + dbms_sql.return_result(c1); + open c1 for select 243 from dual; + dbms_sql.return_result(c1); + open c1 for select 244 from dual; + dbms_sql.return_result(c1); + open c1 for select 245 from dual; + dbms_sql.return_result(c1); + open c1 for select 246 from dual; + dbms_sql.return_result(c1); + open c1 for select 247 from dual; + dbms_sql.return_result(c1); + open c1 for select 248 from dual; + dbms_sql.return_result(c1); + open c1 for select 249 from dual; + dbms_sql.return_result(c1); + open c1 for select 250 from dual; + dbms_sql.return_result(c1); + open c1 for select 251 from dual; + dbms_sql.return_result(c1); + open c1 for select 252 from dual; + dbms_sql.return_result(c1); + open c1 for select 253 from dual; + dbms_sql.return_result(c1); + open c1 for select 254 from dual; + dbms_sql.return_result(c1); + open c1 for select 255 from dual; + dbms_sql.return_result(c1); + open c1 for select 256 from dual; + dbms_sql.return_result(c1); + open c1 for select 257 from dual; + dbms_sql.return_result(c1); + open c1 for select 258 from dual; + dbms_sql.return_result(c1); + open c1 for select 259 from dual; + dbms_sql.return_result(c1); + open c1 for select 260 from dual; + dbms_sql.return_result(c1); + open c1 for select 261 from dual; + dbms_sql.return_result(c1); + open c1 for select 262 from dual; + dbms_sql.return_result(c1); + open c1 for select 263 from dual; + dbms_sql.return_result(c1); + open c1 for select 264 from dual; + dbms_sql.return_result(c1); + open c1 for select 265 from dual; + dbms_sql.return_result(c1); + open c1 for select 266 from dual; + dbms_sql.return_result(c1); + open c1 for select 267 from dual; + dbms_sql.return_result(c1); + open c1 for select 268 from dual; + dbms_sql.return_result(c1); + open c1 for select 269 from dual; + dbms_sql.return_result(c1); + open c1 for select 270 from dual; + dbms_sql.return_result(c1); + open c1 for select 271 from dual; + dbms_sql.return_result(c1); + open c1 for select 272 from dual; + dbms_sql.return_result(c1); + open c1 for select 273 from dual; + dbms_sql.return_result(c1); + open c1 for select 274 from dual; + dbms_sql.return_result(c1); + open c1 for select 275 from dual; + dbms_sql.return_result(c1); + end;"; + +// Run Test + +echo "Test 1\n"; +$s = oci_parse($c, $stmt); +oci_execute($s); + +while (($row = oci_fetch_row($s)) != false) { + foreach ($row as $item) { + echo " ".$item; + } + echo "\n"; +} + +?> +===DONE=== +<?php exit(0); ?> +--EXPECTF-- +Test 1 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16 + 17 + 18 + 19 + 20 + 21 + 22 + 23 + 24 + 25 + 26 + 27 + 28 + 29 + 30 + 31 + 32 + 33 + 34 + 35 + 36 + 37 + 38 + 39 + 40 + 41 + 42 + 43 + 44 + 45 + 46 + 47 + 48 + 49 + 50 + 51 + 52 + 53 + 54 + 55 + 56 + 57 + 58 + 59 + 60 + 61 + 62 + 63 + 64 + 65 + 66 + 67 + 68 + 69 + 70 + 71 + 72 + 73 + 74 + 75 + 76 + 77 + 78 + 79 + 80 + 81 + 82 + 83 + 84 + 85 + 86 + 87 + 88 + 89 + 90 + 91 + 92 + 93 + 94 + 95 + 96 + 97 + 98 + 99 + 100 + 101 + 102 + 103 + 104 + 105 + 106 + 107 + 108 + 109 + 110 + 111 + 112 + 113 + 114 + 115 + 116 + 117 + 118 + 119 + 120 + 121 + 122 + 123 + 124 + 125 + 126 + 127 + 128 + 129 + 130 + 131 + 132 + 133 + 134 + 135 + 136 + 137 + 138 + 139 + 140 + 141 + 142 + 143 + 144 + 145 + 146 + 147 + 148 + 149 + 150 + 151 + 152 + 153 + 154 + 155 + 156 + 157 + 158 + 159 + 160 + 161 + 162 + 163 + 164 + 165 + 166 + 167 + 168 + 169 + 170 + 171 + 172 + 173 + 174 + 175 + 176 + 177 + 178 + 179 + 180 + 181 + 182 + 183 + 184 + 185 + 186 + 187 + 188 + 189 + 190 + 191 + 192 + 193 + 194 + 195 + 196 + 197 + 198 + 199 + 200 + 201 + 202 + 203 + 204 + 205 + 206 + 207 + 208 + 209 + 210 + 211 + 212 + 213 + 214 + 215 + 216 + 217 + 218 + 219 + 220 + 221 + 222 + 223 + 224 + 225 + 226 + 227 + 228 + 229 + 230 + 231 + 232 + 233 + 234 + 235 + 236 + 237 + 238 + 239 + 240 + 241 + 242 + 243 + 244 + 245 + 246 + 247 + 248 + 249 + 250 + 251 + 252 + 253 + 254 + 255 + 256 + 257 + 258 + 259 + 260 + 261 + 262 + 263 + 264 + 265 + 266 + 267 + 268 + 269 + 270 + 271 + 272 + 273 + 274 + 275 +===DONE=== diff --git a/ext/oci8/tests/imp_res_call_error.phpt b/ext/oci8/tests/imp_res_call_error.phpt new file mode 100644 index 0000000000..8b0fa78db9 --- /dev/null +++ b/ext/oci8/tests/imp_res_call_error.phpt @@ -0,0 +1,61 @@ +--TEST-- +Oracle Database 12c Implicit Result Sets: using SQL 'CALL' +--SKIPIF-- +<?php +if (!extension_loaded('oci8')) die ("skip no oci8 extension"); +$target_dbs = array('oracledb' => true, 'timesten' => false); // test runs on these DBs +require(dirname(__FILE__).'/skipif.inc'); +preg_match('/.*Release ([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)*/', oci_server_version($c), $matches); +if (!(isset($matches[0]) && $matches[1] >= 12)) { + die("skip expected output only valid when using Oracle Database 12c or greater"); +} +preg_match('/^[[:digit:]]+/', oci_client_version(), $matches); +if (!(isset($matches[0]) && $matches[0] >= 12)) { + die("skip works only with Oracle 12c or greater version of Oracle client libraries"); +} +?> +--FILE-- +<?php + +require(dirname(__FILE__).'/connect.inc'); + +// Initialization + +$stmtarray = array( + "create or replace procedure imp_res_call_err_proc as + c1 sys_refcursor; + begin + open c1 for select * from dual; + dbms_sql.return_result(c1); + open c1 for select * from dual; + dbms_sql.return_result (c1); + end;"); + +oci8_test_sql_execute($c, $stmtarray); + +// Run Test + +echo "Test 1\n"; + +$s = oci_parse($c, "call imp_res_call_err_proc()"); +oci_execute($s); + +// Clean up + +$stmtarray = array( + "drop procedure imp_res_call_err_proc" +); + +oci8_test_sql_execute($c, $stmtarray); + +?> +===DONE=== +<?php exit(0); ?> +--EXPECTF-- +Test 1 + +Warning: oci_execute(): ORA-29478: %s +ORA-06512: at "SYS.DBMS_SQL", line %d +ORA-06512: at "SYS.DBMS_SQL", line %d +ORA-06512: at "SYSTEM.IMP_RES_CALL_ERR_PROC", line %d in %simp_res_call_error.php on line %d +===DONE=== diff --git a/ext/oci8/tests/imp_res_cancel.phpt b/ext/oci8/tests/imp_res_cancel.phpt new file mode 100644 index 0000000000..663d630dfb --- /dev/null +++ b/ext/oci8/tests/imp_res_cancel.phpt @@ -0,0 +1,68 @@ +--TEST-- +Oracle Database 12c Implicit Result Sets: oci_cancel +--SKIPIF-- +<?php +if (!extension_loaded('oci8')) die ("skip no oci8 extension"); +$target_dbs = array('oracledb' => true, 'timesten' => false); // test runs on these DBs +require(dirname(__FILE__).'/skipif.inc'); +preg_match('/.*Release ([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)*/', oci_server_version($c), $matches); +if (!(isset($matches[0]) && $matches[1] >= 12)) { + die("skip expected output only valid when using Oracle Database 12c or greater"); +} +preg_match('/^[[:digit:]]+/', oci_client_version(), $matches); +if (!(isset($matches[0]) && $matches[0] >= 12)) { + die("skip works only with Oracle 12c or greater version of Oracle client libraries"); +} +?> +--FILE-- +<?php + +require(dirname(__FILE__).'/connect.inc'); + +$stmtarray = array( + "create or replace procedure imp_res_cancel_proc as + c1 sys_refcursor; + c2 sys_refcursor; + begin + open c1 for select 1 from dual union all select 2 from dual; + dbms_sql.return_result(c1); + open c2 for select 3 from dual; + dbms_sql.return_result (c2); + end;" +); + +oci8_test_sql_execute($c, $stmtarray); + +// Run Test + +echo "Test 1\n"; +$s = oci_parse($c, "begin imp_res_cancel_proc(); end;"); +oci_execute($s); +while (($row = oci_fetch_array($s, OCI_ASSOC+OCI_RETURN_NULLS)) != false) { + foreach ($row as $item) { + echo " ".$item; + } + echo "\n"; + var_dump(oci_cancel($s)); +} + +// Clean up + +$stmtarray = array( + "drop procedure imp_res_cancel_proc" +); + +oci8_test_sql_execute($c, $stmtarray); + +?> +===DONE=== +<?php exit(0); ?> +--EXPECTF-- +Test 1 + 1 +bool(true) + 2 +bool(true) + 3 +bool(true) +===DONE=== diff --git a/ext/oci8/tests/imp_res_close.phpt b/ext/oci8/tests/imp_res_close.phpt new file mode 100644 index 0000000000..01ac2c75e0 --- /dev/null +++ b/ext/oci8/tests/imp_res_close.phpt @@ -0,0 +1,69 @@ +--TEST-- +Oracle Database 12c Implicit Result Sets: oci_free_statement #1 +--SKIPIF-- +<?php +if (!extension_loaded('oci8')) die ("skip no oci8 extension"); +$target_dbs = array('oracledb' => true, 'timesten' => false); // test runs on these DBs +require(dirname(__FILE__).'/skipif.inc'); +preg_match('/.*Release ([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)*/', oci_server_version($c), $matches); +if (!(isset($matches[0]) && $matches[1] >= 12)) { + die("skip expected output only valid when using Oracle Database 12c or greater"); +} +preg_match('/^[[:digit:]]+/', oci_client_version(), $matches); +if (!(isset($matches[0]) && $matches[0] >= 12)) { + die("skip works only with Oracle 12c or greater version of Oracle client libraries"); +} +?> +--FILE-- +<?php + +require(dirname(__FILE__).'/connect.inc'); + +// Initialization + +$stmtarray = array( + "create or replace procedure imp_res_close_proc as + c1 sys_refcursor; + begin + open c1 for select 1 from dual union all select 2 from dual order by 1; + dbms_sql.return_result(c1); + open c1 for select 3 from dual union all select 4 from dual order by 1; + dbms_sql.return_result(c1); + open c1 for select 5 from dual union all select 6 from dual order by 1; + dbms_sql.return_result(c1); + end;" +); + +oci8_test_sql_execute($c, $stmtarray); + +// Run Test + +echo "Test 1\n"; +$s = oci_parse($c, "begin imp_res_close_proc(); end;"); +oci_execute($s); +while (($row = oci_fetch_array($s, OCI_ASSOC+OCI_RETURN_NULLS)) != false) { + foreach ($row as $item) { + echo " ".$item; + } + echo "\n"; + oci_free_statement($s); // Free the implicit result handle +} + +// Clean up + +$stmtarray = array( + "drop procedure imp_res_close_proc" +); + +oci8_test_sql_execute($c, $stmtarray); + +?> +===DONE=== +<?php exit(0); ?> +--EXPECTF-- +Test 1 + 1 + 2 + +Warning: oci_fetch_array(): %d is not a valid oci8 statement resource in %simp_res_close.php on line %d +===DONE=== diff --git a/ext/oci8/tests/imp_res_cursor.phpt b/ext/oci8/tests/imp_res_cursor.phpt new file mode 100644 index 0000000000..cac0a5d1c0 --- /dev/null +++ b/ext/oci8/tests/imp_res_cursor.phpt @@ -0,0 +1,99 @@ +--TEST-- +Oracle Database 12c Implicit Result Sets: nested cursor +--SKIPIF-- +<?php +if (!extension_loaded('oci8')) die ("skip no oci8 extension"); +$target_dbs = array('oracledb' => true, 'timesten' => false); // test runs on these DBs +require(dirname(__FILE__).'/skipif.inc'); +preg_match('/.*Release ([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)*/', oci_server_version($c), $matches); +if (!(isset($matches[0]) && $matches[1] >= 12)) { + die("skip expected output only valid when using Oracle Database 12c or greater"); +} +preg_match('/^[[:digit:]]+/', oci_client_version(), $matches); +if (!(isset($matches[0]) && $matches[0] >= 12)) { + die("skip works only with Oracle 12c or greater version of Oracle client libraries"); +} +?> +--FILE-- +<?php + +require(dirname(__FILE__).'/connect.inc'); + +// Initialization + +$stmtarray = array( + "drop table imp_res_cursor_tab_1", + "create table imp_res_cursor_tab_1 (c1 number, c2 varchar2(10))", + "insert into imp_res_cursor_tab_1 values (1, 'abcde')", + "insert into imp_res_cursor_tab_1 values (2, 'fghij')", + "insert into imp_res_cursor_tab_1 values (3, 'klmno')", + + "drop table imp_res_cursor_tab_2", + "create table imp_res_cursor_tab_2 (c3 varchar2(1))", + "insert into imp_res_cursor_tab_2 values ('t')", + "insert into imp_res_cursor_tab_2 values ('u')", + "insert into imp_res_cursor_tab_2 values ('v')", + + "create or replace procedure imp_res_cursor_proc as + c1 sys_refcursor; + begin + open c1 for select * from dual; + dbms_sql.return_result (c1); + + open c1 for select cursor(select c1, c2 from imp_res_cursor_tab_1 order by 1) as curs from dual; + dbms_sql.return_result(c1); + + open c1 for select * from imp_res_cursor_tab_2 where rownum < 3 order by 1; + dbms_sql.return_result(c1); + end;" +); + +oci8_test_sql_execute($c, $stmtarray); + +function do_fetch($s) +{ + while (($row = oci_fetch_assoc($s)) != false) { + foreach ($row as $item) { + if (is_resource($item)) { // Nested cursor + oci_execute($item); + do_fetch($item); + } else { + echo " ".$item; + } + } + echo "\n"; + } +} + +// Run Test + +echo "Test 1\n"; + +$s = oci_parse($c, "begin imp_res_cursor_proc(); end;"); +oci_execute($s); + +do_fetch($s); + +// Clean up + +$stmtarray = array( + "drop procedure imp_res_cursor_proc", + "drop table imp_res_cursor_tab_1", + "drop table imp_res_cursor_tab_2" +); + +oci8_test_sql_execute($c, $stmtarray); + +?> +===DONE=== +<?php exit(0); ?> +--EXPECTF-- +Test 1 + X + 1 abcde + 2 fghij + 3 klmno + + t + u +===DONE=== diff --git a/ext/oci8/tests/imp_res_dbmsoutput.phpt b/ext/oci8/tests/imp_res_dbmsoutput.phpt new file mode 100644 index 0000000000..8c9808d96c --- /dev/null +++ b/ext/oci8/tests/imp_res_dbmsoutput.phpt @@ -0,0 +1,136 @@ +--TEST-- +Oracle Database 12c Implicit Result Sets: interleaved with DBMS_OUTPUT +--SKIPIF-- +<?php +if (!extension_loaded('oci8')) die ("skip no oci8 extension"); +$target_dbs = array('oracledb' => true, 'timesten' => false); // test runs on these DBs +require(dirname(__FILE__).'/skipif.inc'); +preg_match('/.*Release ([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)*/', oci_server_version($c), $matches); +if (!(isset($matches[0]) && $matches[1] >= 12)) { + die("skip expected output only valid when using Oracle Database 12c or greater"); +} +preg_match('/^[[:digit:]]+/', oci_client_version(), $matches); +if (!(isset($matches[0]) && $matches[0] >= 12)) { + die("skip works only with Oracle 12c or greater version of Oracle client libraries"); +} +?> +--FILE-- +<?php + +require(dirname(__FILE__).'/connect.inc'); + +// Initialization + +$stmtarray = array( + "drop table imp_res_dbmsoutput_tab_1", + "create table imp_res_dbmsoutput_tab_1 (c1 number, c2 varchar2(10))", + "insert into imp_res_dbmsoutput_tab_1 values (1, 'abcde')", + "insert into imp_res_dbmsoutput_tab_1 values (2, 'fghij')", + "insert into imp_res_dbmsoutput_tab_1 values (3, 'klmno')", + + "drop table imp_res_dbmsoutput_tab_2", + "create table imp_res_dbmsoutput_tab_2 (c3 varchar2(1))", + "insert into imp_res_dbmsoutput_tab_2 values ('t')", + "insert into imp_res_dbmsoutput_tab_2 values ('u')", + "insert into imp_res_dbmsoutput_tab_2 values ('v')", + + "create or replace procedure imp_res_dbmsoutput_proc as + c1 sys_refcursor; + begin + dbms_output.put_line('dbms_output Line 1'); + open c1 for select * from imp_res_dbmsoutput_tab_1 order by 1; + dbms_sql.return_result(c1); + dbms_output.put_line('dbms_output Line 2'); + open c1 for select * from imp_res_dbmsoutput_tab_2 order by 1; + dbms_sql.return_result(c1); + end;" +); + +oci8_test_sql_execute($c, $stmtarray); + +function setserveroutputon($c) +{ + $s = oci_parse($c, "begin dbms_output.enable(null); end;"); + oci_execute($s); +} + +function getdbmsoutput_do($c) +{ + $s = oci_parse($c, "begin dbms_output.get_line(:ln, :st); end;"); + oci_bind_by_name($s, ":ln", $ln, 100); + oci_bind_by_name($s, ":st", $st, -1, SQLT_INT); + $res = false; + while (($succ = oci_execute($s)) && !$st) { + $res[] = $ln; // append each line to the array + } + return $res; +} + +setserveroutputon($c); + +// Run Test + +echo "Test 1\n"; +$s = oci_parse($c, "begin imp_res_dbmsoutput_proc(); end;"); +oci_execute($s); +var_dump(getdbmsoutput_do($c)); +while (($row = oci_fetch_array($s, OCI_ASSOC+OCI_RETURN_NULLS)) != false) { + foreach ($row as $item) { + echo " ".$item; + } + echo "\n"; +} + +echo "\nTest 2\n"; +$s = oci_parse($c, "begin imp_res_dbmsoutput_proc(); end;"); +oci_execute($s); +while (($row = oci_fetch_array($s, OCI_ASSOC+OCI_RETURN_NULLS)) != false) { + foreach ($row as $item) { + echo " ".$item; + } + echo "\n"; +} +var_dump(getdbmsoutput_do($c)); + +// Clean up + +$stmtarray = array( + "drop procedure imp_res_dbmsoutput_proc", + "drop table imp_res_dbmsoutput_tab_1", + "drop table imp_res_dbmsoutput_tab_2" +); + +oci8_test_sql_execute($c, $stmtarray); + +?> +===DONE=== +<?php exit(0); ?> +--EXPECTF-- +Test 1 +array(2) { + [0]=> + string(18) "dbms_output Line 1" + [1]=> + string(18) "dbms_output Line 2" +} + 1 abcde + 2 fghij + 3 klmno + t + u + v + +Test 2 + 1 abcde + 2 fghij + 3 klmno + t + u + v +array(2) { + [0]=> + string(18) "dbms_output Line 1" + [1]=> + string(18) "dbms_output Line 2" +} +===DONE=== diff --git a/ext/oci8/tests/imp_res_field.phpt b/ext/oci8/tests/imp_res_field.phpt new file mode 100644 index 0000000000..54b8295cf9 --- /dev/null +++ b/ext/oci8/tests/imp_res_field.phpt @@ -0,0 +1,227 @@ +--TEST-- +Oracle Database 12c Implicit Result Sets: field tests +--SKIPIF-- +<?php +if (!extension_loaded('oci8')) die ("skip no oci8 extension"); +$target_dbs = array('oracledb' => true, 'timesten' => false); // test runs on these DBs +require(dirname(__FILE__).'/skipif.inc'); +preg_match('/.*Release ([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)*/', oci_server_version($c), $matches); +if (!(isset($matches[0]) && $matches[1] >= 12)) { + die("skip expected output only valid when using Oracle Database 12c or greater"); +} +preg_match('/^[[:digit:]]+/', oci_client_version(), $matches); +if (!(isset($matches[0]) && $matches[0] >= 12)) { + die("skip works only with Oracle 12c or greater version of Oracle client libraries"); +} +?> +--FILE-- +<?php + +require(dirname(__FILE__).'/connect.inc'); + +// Initialization + +$stmtarray = array( + "drop table imp_res_field_tab_1", + "create table imp_res_field_tab_1 (c1_number number, c2_varchar210 varchar2(10))", + "insert into imp_res_field_tab_1 values (1111, 'abcde')", + + "drop table imp_res_field_tab_2", + "create table imp_res_field_tab_2 (c3_varchar21 varchar2(4))", + "insert into imp_res_field_tab_2 values ('tttt')", + + "drop table imp_res_field_tab_3", + "create table imp_res_field_tab_3 (c4_number52 number(5,2))", + "insert into imp_res_field_tab_3 values (33)", + "insert into imp_res_field_tab_3 values (NULL)", + + "create or replace procedure imp_res_field_proc as + c1 sys_refcursor; + begin + open c1 for select * from imp_res_field_tab_1 order by 1; + dbms_sql.return_result(c1); + + open c1 for select * from imp_res_field_tab_2 order by 1; + dbms_sql.return_result(c1); + + open c1 for select * from imp_res_field_tab_3 order by 1; + dbms_sql.return_result(c1); + end;" +); + +oci8_test_sql_execute($c, $stmtarray); + +function print_fields($s) +{ + echo "num fields : " . oci_num_fields($s) . "\n"; + for ($i = 1; $i <= oci_num_fields($s); $i++) { + $is_null = oci_field_is_null($s, $i) ? "T" : "F"; + $name = oci_field_name($s, $i); + $precision = oci_field_precision($s, $i); + $scale = oci_field_scale($s, $i); + $size = oci_field_size($s, $i); + $typeraw = oci_field_type_raw($s, $i); + $type = oci_field_type($s, $i); + echo "$name\t: is_null $is_null, precision $precision, scale $scale, size $size, typeraw $typeraw, type $type\n"; + } +} + +// Run Test + +echo "Test 1 - can't get IRS fields from parent\n"; +$s = oci_parse($c, "begin imp_res_field_proc(); end;"); +oci_execute($s); +print_fields($s); + +echo "\nTest 2 - can't get IRS fields from parent when fetching\n"; +$s = oci_parse($c, "begin imp_res_field_proc(); end;"); +oci_execute($s); +while (($r = oci_fetch_row($s))) { + var_dump($r); + print_fields($s); +} + +echo "\nTest 3 - get IRS fields\n"; +$s = oci_parse($c, "begin imp_res_field_proc(); end;"); +oci_execute($s); +while (($s1 = oci_get_implicit_resultset($s))) { + print_fields($s1); +} + +echo "\nTest 4 - get IRS fields before fetching rows\n"; +$s = oci_parse($c, "begin imp_res_field_proc(); end;"); +oci_execute($s); +$i = 0; +while (($s1 = oci_get_implicit_resultset($s))) { + echo "===> Result set ".++$i."\n"; + print_fields($s1); + while (($r = oci_fetch_row($s1)) !== false) { + var_dump($r); + } +} + +echo "\nTest 5 - get IRS fields when fetching rows\n"; +$s = oci_parse($c, "begin imp_res_field_proc(); end;"); +oci_execute($s); +$i = 0; +while (($s1 = oci_get_implicit_resultset($s))) { + echo "===> Result set ".++$i."\n"; + while (($r = oci_fetch_row($s1)) !== false) { + var_dump($r); + print_fields($s1); + } +} + +// Clean up + +$stmtarray = array( + "drop procedure imp_res_field_proc", + "drop table imp_res_field_tab_1", + "drop table imp_res_field_tab_2", + "drop table imp_res_field_tab_3" +); + +oci8_test_sql_execute($c, $stmtarray); + +?> +===DONE=== +<?php exit(0); ?> +--EXPECTF-- +Test 1 - can't get IRS fields from parent +num fields : 0 + +Test 2 - can't get IRS fields from parent when fetching +array(2) { + [0]=> + string(4) "1111" + [1]=> + string(5) "abcde" +} +num fields : 0 +array(1) { + [0]=> + string(4) "tttt" +} +num fields : 0 +array(1) { + [0]=> + string(2) "33" +} +num fields : 0 +array(1) { + [0]=> + NULL +} +num fields : 0 + +Test 3 - get IRS fields +num fields : 2 +C1_NUMBER : is_null F, precision 0, scale -127, size 22, typeraw 2, type NUMBER +C2_VARCHAR210 : is_null F, precision 0, scale 0, size 10, typeraw 1, type VARCHAR2 +num fields : 1 +C3_VARCHAR21 : is_null F, precision 0, scale 0, size 4, typeraw 1, type VARCHAR2 +num fields : 1 +C4_NUMBER52 : is_null F, precision 5, scale 2, size 22, typeraw 2, type NUMBER + +Test 4 - get IRS fields before fetching rows +===> Result set 1 +num fields : 2 +C1_NUMBER : is_null F, precision 0, scale -127, size 22, typeraw 2, type NUMBER +C2_VARCHAR210 : is_null F, precision 0, scale 0, size 10, typeraw 1, type VARCHAR2 +array(2) { + [0]=> + string(4) "1111" + [1]=> + string(5) "abcde" +} +===> Result set 2 +num fields : 1 +C3_VARCHAR21 : is_null F, precision 0, scale 0, size 4, typeraw 1, type VARCHAR2 +array(1) { + [0]=> + string(4) "tttt" +} +===> Result set 3 +num fields : 1 +C4_NUMBER52 : is_null F, precision 5, scale 2, size 22, typeraw 2, type NUMBER +array(1) { + [0]=> + string(2) "33" +} +array(1) { + [0]=> + NULL +} + +Test 5 - get IRS fields when fetching rows +===> Result set 1 +array(2) { + [0]=> + string(4) "1111" + [1]=> + string(5) "abcde" +} +num fields : 2 +C1_NUMBER : is_null F, precision 0, scale -127, size 22, typeraw 2, type NUMBER +C2_VARCHAR210 : is_null F, precision 0, scale 0, size 10, typeraw 1, type VARCHAR2 +===> Result set 2 +array(1) { + [0]=> + string(4) "tttt" +} +num fields : 1 +C3_VARCHAR21 : is_null F, precision 0, scale 0, size 4, typeraw 1, type VARCHAR2 +===> Result set 3 +array(1) { + [0]=> + string(2) "33" +} +num fields : 1 +C4_NUMBER52 : is_null F, precision 5, scale 2, size 22, typeraw 2, type NUMBER +array(1) { + [0]=> + NULL +} +num fields : 1 +C4_NUMBER52 : is_null T, precision 5, scale 2, size 22, typeraw 2, type NUMBER +===DONE=== diff --git a/ext/oci8/tests/imp_res_func_error.phpt b/ext/oci8/tests/imp_res_func_error.phpt new file mode 100644 index 0000000000..73c0557930 --- /dev/null +++ b/ext/oci8/tests/imp_res_func_error.phpt @@ -0,0 +1,67 @@ +--TEST-- +Oracle Database 12c Implicit Result Sets: test with a PL/SQL function +--SKIPIF-- +<?php +if (!extension_loaded('oci8')) die ("skip no oci8 extension"); +$target_dbs = array('oracledb' => true, 'timesten' => false); // test runs on these DBs +require(dirname(__FILE__).'/skipif.inc'); +preg_match('/.*Release ([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)*/', oci_server_version($c), $matches); +if (!(isset($matches[0]) && $matches[1] >= 12)) { + die("skip expected output only valid when using Oracle Database 12c or greater"); +} +preg_match('/^[[:digit:]]+/', oci_client_version(), $matches); +if (!(isset($matches[0]) && $matches[0] >= 12)) { + die("skip works only with Oracle 12c or greater version of Oracle client libraries"); +} +?> +--FILE-- +<?php + +require(dirname(__FILE__).'/connect.inc'); + +// Initialization + +$stmtarray = array( + "create or replace function imp_res_func_error return number as + c1 sys_refcursor; + begin + open c1 for select * from dual; + dbms_sql.return_result(c1); + return 1234; + end;" +); + +oci8_test_sql_execute($c, $stmtarray); + +// Run Test + +echo "Test 1\n"; +$s = oci_parse($c, "select imp_res_func_error from dual"); +$r = oci_execute($s); // This will fail with ORA-29478 in Oracle 12.1 +if ($r) { + while (($row = oci_fetch_array($s, OCI_ASSOC+OCI_RETURN_NULLS)) != false) { + foreach ($row as $item) { + echo " ".$item; + } + echo "\n"; + } +} +// Clean up + +$stmtarray = array( + "drop function imp_res_func_error", +); + +oci8_test_sql_execute($c, $stmtarray); + +?> +===DONE=== +<?php exit(0); ?> +--EXPECTF-- +Test 1 + +Warning: oci_execute(): ORA-29478: %s +ORA-06512: %s +ORA-06512: %s +ORA-06512: %s +===DONE=== diff --git a/ext/oci8/tests/imp_res_get_1.phpt b/ext/oci8/tests/imp_res_get_1.phpt new file mode 100644 index 0000000000..665f773b57 --- /dev/null +++ b/ext/oci8/tests/imp_res_get_1.phpt @@ -0,0 +1,109 @@ +--TEST-- +Oracle Database 12c Implicit Result Sets: oci_get_implicit_resultset: basic test +--SKIPIF-- +<?php +if (!extension_loaded('oci8')) die ("skip no oci8 extension"); +$target_dbs = array('oracledb' => true, 'timesten' => false); // test runs on these DBs +require(dirname(__FILE__).'/skipif.inc'); +preg_match('/.*Release ([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)*/', oci_server_version($c), $matches); +if (!(isset($matches[0]) && $matches[1] >= 12)) { + die("skip expected output only valid when using Oracle Database 12c or greater"); +} +preg_match('/^[[:digit:]]+/', oci_client_version(), $matches); +if (!(isset($matches[0]) && $matches[0] >= 12)) { + die("skip works only with Oracle 12c or greater version of Oracle client libraries"); +} +?> +--FILE-- +<?php + +require(dirname(__FILE__).'/connect.inc'); + +// Initialization + +$stmtarray = array( + "drop table imp_res_get_1_tab_1", + "create table imp_res_get_1_tab_1 (c1 number, c2 varchar2(10))", + "insert into imp_res_get_1_tab_1 values (1, 'abcde')", + "insert into imp_res_get_1_tab_1 values (2, 'fghij')", + "insert into imp_res_get_1_tab_1 values (3, 'klmno')", + + "drop table imp_res_get_1_tab_2", + "create table imp_res_get_1_tab_2 (c3 varchar2(1))", + "insert into imp_res_get_1_tab_2 values ('t')", + "insert into imp_res_get_1_tab_2 values ('u')", + "insert into imp_res_get_1_tab_2 values ('v')", + + "create or replace procedure imp_res_get_1_proc as + c1 sys_refcursor; + begin + open c1 for select * from imp_res_get_1_tab_1 order by 1; + dbms_sql.return_result(c1); + + open c1 for select * from imp_res_get_1_tab_2 where rownum < 3 order by 1; + dbms_sql.return_result(c1); + + open c1 for select * from dual; + dbms_sql.return_result (c1); + end;" +); + +oci8_test_sql_execute($c, $stmtarray); + +// Run Test + +echo "Test 1\n"; +$s = oci_parse($c, "begin imp_res_get_1_proc(); end;"); +oci_execute($s); +while (($s1 = oci_get_implicit_resultset($s))) { + while (($row = oci_fetch_array($s1, OCI_ASSOC+OCI_RETURN_NULLS)) != false) { + foreach ($row as $item) { + echo " ".$item; + } + echo "\n"; + } +} + +echo "\nTest 2 - with execute\n"; +$s = oci_parse($c, "begin imp_res_get_1_proc(); end;"); +oci_execute($s); +while (($s1 = oci_get_implicit_resultset($s))) { + oci_execute($s1); // no op + while (($row = oci_fetch_array($s1, OCI_ASSOC+OCI_RETURN_NULLS)) != false) { + foreach ($row as $item) { + echo " ".$item; + } + echo "\n"; + } +} + +// Clean up + +$stmtarray = array( + "drop procedure imp_res_get_1_proc", + "drop table imp_res_get_1_tab_1", + "drop table imp_res_get_1_tab_2" +); + +oci8_test_sql_execute($c, $stmtarray); + +?> +===DONE=== +<?php exit(0); ?> +--EXPECTF-- +Test 1 + 1 abcde + 2 fghij + 3 klmno + t + u + X + +Test 2 - with execute + 1 abcde + 2 fghij + 3 klmno + t + u + X +===DONE=== diff --git a/ext/oci8/tests/imp_res_get_2.phpt b/ext/oci8/tests/imp_res_get_2.phpt new file mode 100644 index 0000000000..b20b8dd397 --- /dev/null +++ b/ext/oci8/tests/imp_res_get_2.phpt @@ -0,0 +1,107 @@ +--TEST-- +Oracle Database 12c Implicit Result Sets: oci_get_implicit_resultset: similar to imp_res_get_1 but with unrolled loop +--SKIPIF-- +<?php +if (!extension_loaded('oci8')) die ("skip no oci8 extension"); +$target_dbs = array('oracledb' => true, 'timesten' => false); // test runs on these DBs +require(dirname(__FILE__).'/skipif.inc'); +preg_match('/.*Release ([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)*/', oci_server_version($c), $matches); +if (!(isset($matches[0]) && $matches[1] >= 12)) { + die("skip expected output only valid when using Oracle Database 12c or greater"); +} +preg_match('/^[[:digit:]]+/', oci_client_version(), $matches); +if (!(isset($matches[0]) && $matches[0] >= 12)) { + die("skip works only with Oracle 12c or greater version of Oracle client libraries"); +} +?> +--FILE-- +<?php + +require(dirname(__FILE__).'/connect.inc'); + +// Initialization + +$stmtarray = array( + "drop table imp_res_get_2_tab_1", + "create table imp_res_get_2_tab_1 (c1 number, c2 varchar2(10))", + "insert into imp_res_get_2_tab_1 values (1, 'abcde')", + "insert into imp_res_get_2_tab_1 values (2, 'fghij')", + "insert into imp_res_get_2_tab_1 values (3, 'klmno')", + + "drop table imp_res_get_2_tab_2", + "create table imp_res_get_2_tab_2 (c3 varchar2(1))", + "insert into imp_res_get_2_tab_2 values ('t')", + "insert into imp_res_get_2_tab_2 values ('u')", + "insert into imp_res_get_2_tab_2 values ('v')", + + "create or replace procedure imp_res_get_2_proc as + c1 sys_refcursor; + begin + open c1 for select * from imp_res_get_2_tab_1 order by 1; + dbms_sql.return_result(c1); + + open c1 for select * from imp_res_get_2_tab_2 where rownum < 3 order by 1; + dbms_sql.return_result(c1); + + open c1 for select * from dual; + dbms_sql.return_result (c1); + end;" +); + +oci8_test_sql_execute($c, $stmtarray); + +// Run Test + +echo "Test 1\n"; + +$s = oci_parse($c, "begin imp_res_get_2_proc(); end;"); +oci_execute($s); + +$s1 = oci_get_implicit_resultset($s); +while (($row = oci_fetch_array($s1, OCI_ASSOC+OCI_RETURN_NULLS))) { + foreach ($row as $item) { + echo " ".$item; + } + echo "\n"; +} + +$s2 = oci_get_implicit_resultset($s); +while (($row = oci_fetch_array($s2, OCI_ASSOC+OCI_RETURN_NULLS))) { + foreach ($row as $item) { + echo " ".$item; + } + echo "\n"; +} +oci_free_statement($s2); + +$s3 = oci_get_implicit_resultset($s); +while (($row = oci_fetch_array($s3, OCI_ASSOC+OCI_RETURN_NULLS))) { + foreach ($row as $item) { + echo " ".$item; + } + echo "\n"; +} +oci_free_statement($s3); + +// Clean up + +$stmtarray = array( + "drop procedure imp_res_get_2_proc", + "drop table imp_res_get_2_tab_1", + "drop table imp_res_get_2_tab_2" +); + +oci8_test_sql_execute($c, $stmtarray); + +?> +===DONE=== +<?php exit(0); ?> +--EXPECTF-- +Test 1 + 1 abcde + 2 fghij + 3 klmno + t + u + X +===DONE=== diff --git a/ext/oci8/tests/imp_res_get_3.phpt b/ext/oci8/tests/imp_res_get_3.phpt new file mode 100644 index 0000000000..15b2efaef0 --- /dev/null +++ b/ext/oci8/tests/imp_res_get_3.phpt @@ -0,0 +1,267 @@ +--TEST-- +Oracle Database 12c Implicit Result Sets: oci_get_implicit_resultset: basic test 3 +--SKIPIF-- +<?php +if (!extension_loaded('oci8')) die ("skip no oci8 extension"); +$target_dbs = array('oracledb' => true, 'timesten' => false); // test runs on these DBs +require(dirname(__FILE__).'/skipif.inc'); +preg_match('/.*Release ([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)*/', oci_server_version($c), $matches); +if (!(isset($matches[0]) && $matches[1] >= 12)) { + die("skip expected output only valid when using Oracle Database 12c or greater"); +} +preg_match('/^[[:digit:]]+/', oci_client_version(), $matches); +if (!(isset($matches[0]) && $matches[0] >= 12)) { + die("skip works only with Oracle 12c or greater version of Oracle client libraries"); +} +?> +--INI-- +oci8.statement_cache_size = 0 +--FILE-- +<?php + +require(dirname(__FILE__).'/connect.inc'); + +// Initialization + +$stmtarray = array( + "drop table imp_res_get_3_tab_1", + "create table imp_res_get_3_tab_1 (c1 number, c2 varchar2(10))", + "insert into imp_res_get_3_tab_1 values (1, 'abcde')", + "insert into imp_res_get_3_tab_1 values (2, 'fghij')", + "insert into imp_res_get_3_tab_1 values (3, 'klmno')", + + "drop table imp_res_get_3_tab_2", + "create table imp_res_get_3_tab_2 (c3 varchar2(1))", + "insert into imp_res_get_3_tab_2 values ('t')", + "insert into imp_res_get_3_tab_2 values ('u')", + "insert into imp_res_get_3_tab_2 values ('v')", + + "create or replace procedure imp_res_get_3_proc as + c1 sys_refcursor; + i pls_integer; + begin + for i in 1..30 loop -- if this value is too big for Oracle's open_cursors, calling imp_res_get_3_proc() can fail with ORA-1000 + open c1 for select * from imp_res_get_3_tab_1 order by 1; + dbms_sql.return_result(c1); + open c1 for select * from imp_res_get_3_tab_2 where rownum < 3 order by 1; + dbms_sql.return_result(c1); + open c1 for select * from dual; + dbms_sql.return_result (c1); + end loop; + end;" +); + +oci8_test_sql_execute($c, $stmtarray); + +// Run Test + +echo "Test 1\n"; + +$s = oci_parse($c, "begin imp_res_get_3_proc(); end;"); +oci_execute($s); + +while (($s1 = oci_get_implicit_resultset($s))) { + while (($row = oci_fetch_array($s1, OCI_ASSOC+OCI_RETURN_NULLS)) != false) { + foreach ($row as $item) { + echo " ".$item; + } + echo "\n"; + } +} + +// Clean up + +$stmtarray = array( + "drop procedure imp_res_get_3_proc", + "drop table imp_res_get_3_tab_1", + "drop table imp_res_get_3_tab_2" +); + +oci8_test_sql_execute($c, $stmtarray); + +?> +===DONE=== +<?php exit(0); ?> +--EXPECTF-- +Test 1 + 1 abcde + 2 fghij + 3 klmno + t + u + X + 1 abcde + 2 fghij + 3 klmno + t + u + X + 1 abcde + 2 fghij + 3 klmno + t + u + X + 1 abcde + 2 fghij + 3 klmno + t + u + X + 1 abcde + 2 fghij + 3 klmno + t + u + X + 1 abcde + 2 fghij + 3 klmno + t + u + X + 1 abcde + 2 fghij + 3 klmno + t + u + X + 1 abcde + 2 fghij + 3 klmno + t + u + X + 1 abcde + 2 fghij + 3 klmno + t + u + X + 1 abcde + 2 fghij + 3 klmno + t + u + X + 1 abcde + 2 fghij + 3 klmno + t + u + X + 1 abcde + 2 fghij + 3 klmno + t + u + X + 1 abcde + 2 fghij + 3 klmno + t + u + X + 1 abcde + 2 fghij + 3 klmno + t + u + X + 1 abcde + 2 fghij + 3 klmno + t + u + X + 1 abcde + 2 fghij + 3 klmno + t + u + X + 1 abcde + 2 fghij + 3 klmno + t + u + X + 1 abcde + 2 fghij + 3 klmno + t + u + X + 1 abcde + 2 fghij + 3 klmno + t + u + X + 1 abcde + 2 fghij + 3 klmno + t + u + X + 1 abcde + 2 fghij + 3 klmno + t + u + X + 1 abcde + 2 fghij + 3 klmno + t + u + X + 1 abcde + 2 fghij + 3 klmno + t + u + X + 1 abcde + 2 fghij + 3 klmno + t + u + X + 1 abcde + 2 fghij + 3 klmno + t + u + X + 1 abcde + 2 fghij + 3 klmno + t + u + X + 1 abcde + 2 fghij + 3 klmno + t + u + X + 1 abcde + 2 fghij + 3 klmno + t + u + X + 1 abcde + 2 fghij + 3 klmno + t + u + X + 1 abcde + 2 fghij + 3 klmno + t + u + X +===DONE=== diff --git a/ext/oci8/tests/imp_res_get_4.phpt b/ext/oci8/tests/imp_res_get_4.phpt new file mode 100644 index 0000000000..ea7fb8775a --- /dev/null +++ b/ext/oci8/tests/imp_res_get_4.phpt @@ -0,0 +1,146 @@ +--TEST-- +Oracle Database 12c Implicit Result Sets: oci_get_implicit_resultset: interleaved fetches +--SKIPIF-- +<?php +if (!extension_loaded('oci8')) die ("skip no oci8 extension"); +$target_dbs = array('oracledb' => true, 'timesten' => false); // test runs on these DBs +require(dirname(__FILE__).'/skipif.inc'); +preg_match('/.*Release ([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)*/', oci_server_version($c), $matches); +if (!(isset($matches[0]) && $matches[1] >= 12)) { + die("skip expected output only valid when using Oracle Database 12c or greater"); +} +preg_match('/^[[:digit:]]+/', oci_client_version(), $matches); +if (!(isset($matches[0]) && $matches[0] >= 12)) { + die("skip works only with Oracle 12c or greater version of Oracle client libraries"); +} +?> +--FILE-- +<?php + +require(dirname(__FILE__).'/connect.inc'); + +// Initialization + +$stmtarray = array( + "drop table imp_res_get_4_tab_1", + "create table imp_res_get_4_tab_1 (c1 number, c2 varchar2(10))", + "insert into imp_res_get_4_tab_1 values (1, 'abcde')", + "insert into imp_res_get_4_tab_1 values (2, 'fghij')", + "insert into imp_res_get_4_tab_1 values (3, 'klmno')", + + "drop table imp_res_get_4_tab_2", + "create table imp_res_get_4_tab_2 (c3 varchar2(1))", + "insert into imp_res_get_4_tab_2 values ('t')", + "insert into imp_res_get_4_tab_2 values ('u')", + "insert into imp_res_get_4_tab_2 values ('v')", + + "create or replace procedure imp_res_get_4_proc as + c1 sys_refcursor; + begin + open c1 for select * from imp_res_get_4_tab_1 order by 1; + dbms_sql.return_result(c1); + + open c1 for select * from imp_res_get_4_tab_2 order by 1; + dbms_sql.return_result(c1); + end;" +); + +oci8_test_sql_execute($c, $stmtarray); + +function print_row($row) +{ + if ($row === false) { + print "Return is false\n"; + return; + } + foreach ($row as $item) { + echo " ".$item; + } + echo "\n"; +} + +// Run Test + +echo "Test 1\n"; + +$s = oci_parse($c, "begin imp_res_get_4_proc(); end;"); +oci_execute($s); +$s1 = oci_get_implicit_resultset($s); +$s2 = oci_get_implicit_resultset($s); +$row = oci_fetch_array($s1, OCI_ASSOC+OCI_RETURN_NULLS); +print_row($row); +$row = oci_fetch_array($s2, OCI_ASSOC+OCI_RETURN_NULLS); +print_row($row); +$row = oci_fetch_array($s1, OCI_ASSOC+OCI_RETURN_NULLS); +print_row($row); +$row = oci_fetch_array($s2, OCI_ASSOC+OCI_RETURN_NULLS); +print_row($row); +$row = oci_fetch_array($s1, OCI_ASSOC+OCI_RETURN_NULLS); +print_row($row); +$row = oci_fetch_array($s2, OCI_ASSOC+OCI_RETURN_NULLS); +print_row($row); + +echo "Test 2 - too many fetches\n"; + +$s = oci_parse($c, "begin imp_res_get_4_proc(); end;"); +oci_execute($s); +$s1 = oci_get_implicit_resultset($s); +$s2 = oci_get_implicit_resultset($s); +$row = oci_fetch_array($s1, OCI_ASSOC+OCI_RETURN_NULLS); +print_row($row); +$row = oci_fetch_array($s2, OCI_ASSOC+OCI_RETURN_NULLS); +print_row($row); +$row = oci_fetch_array($s1, OCI_ASSOC+OCI_RETURN_NULLS); +print_row($row); +$row = oci_fetch_array($s2, OCI_ASSOC+OCI_RETURN_NULLS); +print_row($row); +$row = oci_fetch_array($s1, OCI_ASSOC+OCI_RETURN_NULLS); +print_row($row); +$row = oci_fetch_array($s2, OCI_ASSOC+OCI_RETURN_NULLS); +print_row($row); +$row = oci_fetch_array($s1, OCI_ASSOC+OCI_RETURN_NULLS); +print_row($row); +$row = oci_fetch_array($s2, OCI_ASSOC+OCI_RETURN_NULLS); +print_row($row); +$row = oci_fetch_array($s1, OCI_ASSOC+OCI_RETURN_NULLS); +print_row($row); +$row = oci_fetch_array($s2, OCI_ASSOC+OCI_RETURN_NULLS); +print_row($row); + +// Clean up + +$stmtarray = array( + "drop procedure imp_res_get_4_proc", + "drop table imp_res_get_4_tab_1", + "drop table imp_res_get_4_tab_2" +); + +oci8_test_sql_execute($c, $stmtarray); + +?> +===DONE=== +<?php exit(0); ?> +--EXPECTF-- +Test 1 + 1 abcde + t + 2 fghij + u + 3 klmno + v +Test 2 - too many fetches + 1 abcde + t + 2 fghij + u + 3 klmno + v +Return is false +Return is false + +Warning: oci_fetch_array(): ORA-01002: %s in %simp_res_get_4.php on line %d +Return is false + +Warning: oci_fetch_array(): ORA-01002: %s in %simp_res_get_4.php on line %d +Return is false +===DONE=== diff --git a/ext/oci8/tests/imp_res_get_5.phpt b/ext/oci8/tests/imp_res_get_5.phpt new file mode 100644 index 0000000000..3cfa0967a2 --- /dev/null +++ b/ext/oci8/tests/imp_res_get_5.phpt @@ -0,0 +1,124 @@ +--TEST-- +Oracle Database 12c Implicit Result Sets: oci_get_implicit_resultset: get from wrong statement +--SKIPIF-- +<?php +if (!extension_loaded('oci8')) die ("skip no oci8 extension"); +$target_dbs = array('oracledb' => true, 'timesten' => false); // test runs on these DBs +require(dirname(__FILE__).'/skipif.inc'); +preg_match('/.*Release ([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)*/', oci_server_version($c), $matches); +if (!(isset($matches[0]) && $matches[1] >= 12)) { + die("skip expected output only valid when using Oracle Database 12c or greater"); +} +preg_match('/^[[:digit:]]+/', oci_client_version(), $matches); +if (!(isset($matches[0]) && $matches[0] >= 12)) { + die("skip works only with Oracle 12c or greater version of Oracle client libraries"); +} +?> +--FILE-- +<?php + +require(dirname(__FILE__).'/connect.inc'); + +function print_row($row) +{ + foreach ($row as $item) { + echo " ".$item; + } + echo "\n"; +} + +$plsql = + "declare + c1 sys_refcursor; + begin + open c1 for select 1 from dual union all select 2 from dual; + dbms_sql.return_result(c1); + open c1 for select 3 from dual union all select 4 from dual; + dbms_sql.return_result(c1); + open c1 for select 5 from dual union all select 6 from dual; + dbms_sql.return_result(c1); + end;"; + +// Run Test + +echo "Test 1\n"; +// This test effectively discards all the first IRS results +$s = oci_parse($c, $plsql); +oci_execute($s); +while (($s1 = oci_get_implicit_resultset($s))) { // $s1 is never used again so its results are lost + while (($row = oci_fetch_array($s, OCI_ASSOC+OCI_RETURN_NULLS)) != false) { // use parent $s instead of $s1 + print_row($row); + } +} +oci_free_statement($s); + +echo "\nTest 2 - fetch first IRS explicitly\n"; +$s = oci_parse($c, $plsql); +oci_execute($s); +$s1 = oci_get_implicit_resultset($s); +while (($row = oci_fetch_row($s1)) != false) { + print_row($row); +} +while (($row = oci_fetch_row($s)) != false) { + print_row($row); +} +oci_free_statement($s); + +echo "\nTest 3 - fetch part of IRS explicitly\n"; +$s = oci_parse($c, $plsql); +oci_execute($s); +$s1 = oci_get_implicit_resultset($s); +while (($row = oci_fetch_row($s1)) != false) { + print_row($row); +} +$row = oci_fetch_row($s); +print_row($row); +$s1 = oci_get_implicit_resultset($s); +while (($row = oci_fetch_row($s1)) != false) { + print_row($row); +} +while (($row = oci_fetch_row($s)) != false) { + print_row($row); +} +oci_free_statement($s); + +echo "\nTest 4 - skip IRSs\n"; +$s = oci_parse($c, $plsql); +oci_execute($s); +$s1 = oci_get_implicit_resultset($s); +$s1 = oci_get_implicit_resultset($s); +while (($row = oci_fetch_row($s)) != false) { // parent + print_row($row); +} +oci_free_statement($s); + +?> +===DONE=== +<?php exit(0); ?> +--EXPECTF-- +Test 1 + 3 + 4 + 5 + 6 + +Test 2 - fetch first IRS explicitly + 1 + 2 + 3 + 4 + 5 + 6 + +Test 3 - fetch part of IRS explicitly + 1 + 2 + 3 + 5 + 6 + 4 + +Test 4 - skip IRSs + 5 + 6 +===DONE=== diff --git a/ext/oci8/tests/imp_res_get_all.phpt b/ext/oci8/tests/imp_res_get_all.phpt new file mode 100644 index 0000000000..d2dcbea6c7 --- /dev/null +++ b/ext/oci8/tests/imp_res_get_all.phpt @@ -0,0 +1,120 @@ +--TEST-- +Oracle Database 12c Implicit Result Sets: oci_get_implicit_resultset: oci_fetch_all +--SKIPIF-- +<?php +if (!extension_loaded('oci8')) die ("skip no oci8 extension"); +$target_dbs = array('oracledb' => true, 'timesten' => false); // test runs on these DBs +require(dirname(__FILE__).'/skipif.inc'); +preg_match('/.*Release ([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)*/', oci_server_version($c), $matches); +if (!(isset($matches[0]) && $matches[1] >= 12)) { + die("skip expected output only valid when using Oracle Database 12c or greater"); +} +preg_match('/^[[:digit:]]+/', oci_client_version(), $matches); +if (!(isset($matches[0]) && $matches[0] >= 12)) { + die("skip works only with Oracle 12c or greater version of Oracle client libraries"); +} +?> +--FILE-- +<?php + +require(dirname(__FILE__).'/connect.inc'); + +$plsql = "declare + c1 sys_refcursor; + begin + open c1 for select 1 from dual union all select 2 from dual; + dbms_sql.return_result(c1); + open c1 for select 3 from dual union all select 4 from dual; + dbms_sql.return_result(c1); + open c1 for select 5 from dual union all select 6 from dual; + dbms_sql.return_result(c1); + end;"; + +// Run Test + +echo "Test 1\n"; +$s = oci_parse($c, $plsql); +oci_execute($s); + +$s1 = oci_get_implicit_resultset($s); +oci_fetch_all($s1, $res); +var_dump($res); + +$s2 = oci_get_implicit_resultset($s); +oci_fetch_all($s2, $res); +var_dump($res); + +$s3 = oci_get_implicit_resultset($s); +oci_fetch_all($s3, $res); +var_dump($res); + +echo "\nTest 2\n"; +$s = oci_parse($c, $plsql); +oci_execute($s); +while (($s1 = oci_get_implicit_resultset($s))) { + $r = oci_fetch_all($s1, $res); + var_dump($res); +} + +?> +===DONE=== +<?php exit(0); ?> +--EXPECTF-- +Test 1 +array(1) { + [1]=> + array(2) { + [0]=> + string(1) "1" + [1]=> + string(1) "2" + } +} +array(1) { + [3]=> + array(2) { + [0]=> + string(1) "3" + [1]=> + string(1) "4" + } +} +array(1) { + [5]=> + array(2) { + [0]=> + string(1) "5" + [1]=> + string(1) "6" + } +} + +Test 2 +array(1) { + [1]=> + array(2) { + [0]=> + string(1) "1" + [1]=> + string(1) "2" + } +} +array(1) { + [3]=> + array(2) { + [0]=> + string(1) "3" + [1]=> + string(1) "4" + } +} +array(1) { + [5]=> + array(2) { + [0]=> + string(1) "5" + [1]=> + string(1) "6" + } +} +===DONE=== diff --git a/ext/oci8/tests/imp_res_get_cancel.phpt b/ext/oci8/tests/imp_res_get_cancel.phpt new file mode 100644 index 0000000000..7dbcecbfe9 --- /dev/null +++ b/ext/oci8/tests/imp_res_get_cancel.phpt @@ -0,0 +1,56 @@ +--TEST-- +Oracle Database 12c Implicit Result Sets: oci_get_implicit_resultset: oci_cancel +--SKIPIF-- +<?php +if (!extension_loaded('oci8')) die ("skip no oci8 extension"); +$target_dbs = array('oracledb' => true, 'timesten' => false); // test runs on these DBs +require(dirname(__FILE__).'/skipif.inc'); +preg_match('/.*Release ([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)*/', oci_server_version($c), $matches); +if (!(isset($matches[0]) && $matches[1] >= 12)) { + die("skip expected output only valid when using Oracle Database 12c or greater"); +} +preg_match('/^[[:digit:]]+/', oci_client_version(), $matches); +if (!(isset($matches[0]) && $matches[0] >= 12)) { + die("skip works only with Oracle 12c or greater version of Oracle client libraries"); +} +?> +--FILE-- +<?php + +require(dirname(__FILE__).'/connect.inc'); + +$plsql = + "declare + c1 sys_refcursor; + c2 sys_refcursor; + begin + open c1 for select 1 from dual union all select 2 from dual; + dbms_sql.return_result(c1); + open c2 for select 3 from dual; + dbms_sql.return_result (c2); + end;"; + +// Run Test + +echo "Test 1\n"; +$s = oci_parse($c, $plsql); +oci_execute($s); +while (($s1 = oci_get_implicit_resultset($s))) { + while (($row = oci_fetch_array($s1, OCI_ASSOC+OCI_RETURN_NULLS)) != false) { + foreach ($row as $item) { + echo " ".$item; + } + echo "\n"; + oci_cancel($s1); + } +} + +?> +===DONE=== +<?php exit(0); ?> +--EXPECTF-- +Test 1 + 1 + 3 +===DONE=== + diff --git a/ext/oci8/tests/imp_res_get_close_1.phpt b/ext/oci8/tests/imp_res_get_close_1.phpt new file mode 100644 index 0000000000..2edc8bf604 --- /dev/null +++ b/ext/oci8/tests/imp_res_get_close_1.phpt @@ -0,0 +1,68 @@ +--TEST-- +Oracle Database 12c Implicit Result Sets: oci_get_implicit_resultset: oci_free_statement #1 +--SKIPIF-- +<?php +if (!extension_loaded('oci8')) die ("skip no oci8 extension"); +$target_dbs = array('oracledb' => true, 'timesten' => false); // test runs on these DBs +require(dirname(__FILE__).'/skipif.inc'); +preg_match('/.*Release ([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)*/', oci_server_version($c), $matches); +if (!(isset($matches[0]) && $matches[1] >= 12)) { + die("skip expected output only valid when using Oracle Database 12c or greater"); +} +preg_match('/^[[:digit:]]+/', oci_client_version(), $matches); +if (!(isset($matches[0]) && $matches[0] >= 12)) { + die("skip works only with Oracle 12c or greater version of Oracle client libraries"); +} +?> +--FILE-- +<?php + +require(dirname(__FILE__).'/connect.inc'); + +// Initialization + +$plsql = + "declare + c1 sys_refcursor; + begin + open c1 for select 1 from dual union all select 2 from dual; + dbms_sql.return_result(c1); + open c1 for select 3 from dual union all select 4 from dual; + dbms_sql.return_result(c1); + open c1 for select 5 from dual union all select 6 from dual; + dbms_sql.return_result(c1); + end;"; + +// Run Test + +echo "Test 1\n"; + +$s = oci_parse($c, $plsql); +oci_execute($s); + +while (($s1 = oci_get_implicit_resultset($s))) { + while (($row = oci_fetch_array($s1, OCI_ASSOC+OCI_RETURN_NULLS)) != false) { + foreach ($row as $item) { + echo " ".$item; + } + echo "\n"; + oci_free_statement($s1); // Free the implicit result handle + } +} +oci_free_statement($s); + +?> +===DONE=== +<?php exit(0); ?> +--EXPECTF-- +Test 1 + 1 + +Warning: oci_fetch_array(): %d is not a valid oci8 statement resource in %s on line %d + 3 + +Warning: oci_fetch_array(): %d is not a valid oci8 statement resource in %s on line %d + 5 + +Warning: oci_fetch_array(): %d is not a valid oci8 statement resource in %s on line %d +===DONE=== diff --git a/ext/oci8/tests/imp_res_get_close_2.phpt b/ext/oci8/tests/imp_res_get_close_2.phpt new file mode 100644 index 0000000000..b3153834ba --- /dev/null +++ b/ext/oci8/tests/imp_res_get_close_2.phpt @@ -0,0 +1,64 @@ +--TEST-- +Oracle Database 12c Implicit Result Sets: oci_get_implicit_resultset: oci_free_statement #2 +--SKIPIF-- +<?php +if (!extension_loaded('oci8')) die ("skip no oci8 extension"); +$target_dbs = array('oracledb' => true, 'timesten' => false); // test runs on these DBs +require(dirname(__FILE__).'/skipif.inc'); +preg_match('/.*Release ([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)*/', oci_server_version($c), $matches); +if (!(isset($matches[0]) && $matches[1] >= 12)) { + die("skip expected output only valid when using Oracle Database 12c or greater"); +} +preg_match('/^[[:digit:]]+/', oci_client_version(), $matches); +if (!(isset($matches[0]) && $matches[0] >= 12)) { + die("skip works only with Oracle 12c or greater version of Oracle client libraries"); +} +?> +--FILE-- +<?php + +require(dirname(__FILE__).'/connect.inc'); + +// Initialization + +$plsql = + "declare + c1 sys_refcursor; + begin + open c1 for select 1 from dual union all select 2 from dual; + dbms_sql.return_result(c1); + open c1 for select 3 from dual union all select 4 from dual; + dbms_sql.return_result(c1); + open c1 for select 5 from dual union all select 6 from dual; + dbms_sql.return_result(c1); + end;"; + +// Run Test + +echo "Test 1\n"; + +$s = oci_parse($c, $plsql); +oci_execute($s); + +while (($s1 = oci_get_implicit_resultset($s))) { + while (($row = oci_fetch_array($s1, OCI_ASSOC+OCI_RETURN_NULLS)) != false) { + foreach ($row as $item) { + echo " ".$item; + } + echo "\n"; + oci_free_statement($s); // close parent + } +} + +?> +===DONE=== +<?php exit(0); ?> +--EXPECTF-- +Test 1 + 1 + 2 + +Warning: oci_fetch_array(): OCI_INVALID_HANDLE in %s on line %d + +Warning: oci_get_implicit_resultset(): %d is not a valid oci8 statement resource in %s on line %d +===DONE=== diff --git a/ext/oci8/tests/imp_res_get_close_3.phpt b/ext/oci8/tests/imp_res_get_close_3.phpt new file mode 100644 index 0000000000..4793a6c882 --- /dev/null +++ b/ext/oci8/tests/imp_res_get_close_3.phpt @@ -0,0 +1,65 @@ +--TEST-- +Oracle Database 12c Implicit Result Sets: oci_get_implicit_resultset: oci_free_statement #3 +--SKIPIF-- +<?php +if (!extension_loaded('oci8')) die ("skip no oci8 extension"); +$target_dbs = array('oracledb' => true, 'timesten' => false); // test runs on these DBs +require(dirname(__FILE__).'/skipif.inc'); +preg_match('/.*Release ([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)*/', oci_server_version($c), $matches); +if (!(isset($matches[0]) && $matches[1] >= 12)) { + die("skip expected output only valid when using Oracle Database 12c or greater"); +} +preg_match('/^[[:digit:]]+/', oci_client_version(), $matches); +if (!(isset($matches[0]) && $matches[0] >= 12)) { + die("skip works only with Oracle 12c or greater version of Oracle client libraries"); +} +?> +--FILE-- +<?php + +require(dirname(__FILE__).'/connect.inc'); + +// Initialization + +$plsql = + "declare + c1 sys_refcursor; + begin + open c1 for select 1 from dual union all select 2 from dual; + dbms_sql.return_result(c1); + open c1 for select 3 from dual union all select 4 from dual; + dbms_sql.return_result(c1); + open c1 for select 5 from dual union all select 6 from dual; + dbms_sql.return_result(c1); + end;"; + +// Run Test + +echo "Test 1\n"; + +$s = oci_parse($c, $plsql); +oci_execute($s); + +while (($s1 = oci_get_implicit_resultset($s))) { + while (($row = oci_fetch_array($s1, OCI_ASSOC+OCI_RETURN_NULLS)) != false) { + foreach ($row as $item) { + echo " ".$item; + } + echo "\n"; + } + oci_free_statement($s1); +} +oci_free_statement($s); + +?> +===DONE=== +<?php exit(0); ?> +--EXPECTF-- +Test 1 + 1 + 2 + 3 + 4 + 5 + 6 +===DONE=== diff --git a/ext/oci8/tests/imp_res_get_cursor.phpt b/ext/oci8/tests/imp_res_get_cursor.phpt new file mode 100644 index 0000000000..ccdb6f5490 --- /dev/null +++ b/ext/oci8/tests/imp_res_get_cursor.phpt @@ -0,0 +1,101 @@ +--TEST-- +Oracle Database 12c Implicit Result Sets: oci_get_implicit_resultset: nested cursor +--SKIPIF-- +<?php +if (!extension_loaded('oci8')) die ("skip no oci8 extension"); +$target_dbs = array('oracledb' => true, 'timesten' => false); // test runs on these DBs +require(dirname(__FILE__).'/skipif.inc'); +preg_match('/.*Release ([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)*/', oci_server_version($c), $matches); +if (!(isset($matches[0]) && $matches[1] >= 12)) { + die("skip expected output only valid when using Oracle Database 12c or greater"); +} +preg_match('/^[[:digit:]]+/', oci_client_version(), $matches); +if (!(isset($matches[0]) && $matches[0] >= 12)) { + die("skip works only with Oracle 12c or greater version of Oracle client libraries"); +} +?> +--FILE-- +<?php + +require(dirname(__FILE__).'/connect.inc'); + +// Initialization + +$stmtarray = array( + "drop table imp_res_get_cursor_tab_1", + "create table imp_res_get_cursor_tab_1 (c1 number, c2 varchar2(10))", + "insert into imp_res_get_cursor_tab_1 values (1, 'abcde')", + "insert into imp_res_get_cursor_tab_1 values (2, 'fghij')", + "insert into imp_res_get_cursor_tab_1 values (3, 'klmno')", + + "drop table imp_res_get_cursor_tab_2", + "create table imp_res_get_cursor_tab_2 (c3 varchar2(1))", + "insert into imp_res_get_cursor_tab_2 values ('t')", + "insert into imp_res_get_cursor_tab_2 values ('u')", + "insert into imp_res_get_cursor_tab_2 values ('v')", + + "create or replace procedure imp_res_get_cursor_proc as + c1 sys_refcursor; + begin + open c1 for select cursor(select c1, c2 from imp_res_get_cursor_tab_1 order by 1) as curs from dual; + dbms_sql.return_result(c1); + + open c1 for select * from imp_res_get_cursor_tab_2 where rownum < 3 order by 1; + dbms_sql.return_result(c1); + + open c1 for select * from dual; + dbms_sql.return_result (c1); + end;" +); + +oci8_test_sql_execute($c, $stmtarray); + +function do_fetch($s) +{ + while (($row = oci_fetch_assoc($s)) != false) { + foreach ($row as $item) { + if (is_resource($item)) { // Nested cursor + oci_execute($item); + do_fetch($item); + } else { + echo " ".$item; + } + } + echo "\n"; + } +} + +// Run Test + +echo "Test 1\n"; + +$s = oci_parse($c, "begin imp_res_get_cursor_proc(); end;"); +oci_execute($s); + +while (($s1 = oci_get_implicit_resultset($s))) { + do_fetch($s1); +} + +// Clean up + +$stmtarray = array( + "drop procedure imp_res_get_cursor_proc", + "drop table imp_res_get_cursor_tab_1", + "drop table imp_res_get_cursor_tab_2" +); + +oci8_test_sql_execute($c, $stmtarray); + +?> +===DONE=== +<?php exit(0); ?> +--EXPECTF-- +Test 1 + 1 abcde + 2 fghij + 3 klmno + + t + u + X +===DONE=== diff --git a/ext/oci8/tests/imp_res_get_dbmsoutput.phpt b/ext/oci8/tests/imp_res_get_dbmsoutput.phpt new file mode 100644 index 0000000000..cbc2389e46 --- /dev/null +++ b/ext/oci8/tests/imp_res_get_dbmsoutput.phpt @@ -0,0 +1,156 @@ +--TEST-- +Oracle Database 12c Implicit Result Sets: oci_get_implicit_resultset: interleaved with DBMS_OUTPUT +--SKIPIF-- +<?php +if (!extension_loaded('oci8')) die ("skip no oci8 extension"); +$target_dbs = array('oracledb' => true, 'timesten' => false); // test runs on these DBs +require(dirname(__FILE__).'/skipif.inc'); +preg_match('/.*Release ([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)*/', oci_server_version($c), $matches); +if (!(isset($matches[0]) && $matches[1] >= 12)) { + die("skip expected output only valid when using Oracle Database 12c or greater"); +} +preg_match('/^[[:digit:]]+/', oci_client_version(), $matches); +if (!(isset($matches[0]) && $matches[0] >= 12)) { + die("skip works only with Oracle 12c or greater version of Oracle client libraries"); +} +?> +--FILE-- +<?php + +require(dirname(__FILE__).'/connect.inc'); + +// Initialization + +$stmtarray = array( + "drop table imp_res_get_dbmsoutput_tab_1", + "create table imp_res_get_dbmsoutput_tab_1 (c1 number, c2 varchar2(10))", + "insert into imp_res_get_dbmsoutput_tab_1 values (1, 'abcde')", + "insert into imp_res_get_dbmsoutput_tab_1 values (2, 'fghij')", + "insert into imp_res_get_dbmsoutput_tab_1 values (3, 'klmno')", + + "drop table imp_res_get_dbmsoutput_tab_2", + "create table imp_res_get_dbmsoutput_tab_2 (c3 varchar2(1))", + "insert into imp_res_get_dbmsoutput_tab_2 values ('t')", + "insert into imp_res_get_dbmsoutput_tab_2 values ('u')", + "insert into imp_res_get_dbmsoutput_tab_2 values ('v')", + + "create or replace procedure imp_res_get_dbmsoutput_proc as + c1 sys_refcursor; + begin + dbms_output.put_line('Line 1'); + open c1 for select * from imp_res_get_dbmsoutput_tab_1 order by 1; + dbms_sql.return_result(c1); + dbms_output.put_line('Line 2'); + open c1 for select * from imp_res_get_dbmsoutput_tab_2 order by 1; + dbms_sql.return_result(c1); + dbms_output.put_line('Line 3'); + open c1 for select * from dual; + dbms_sql.return_result (c1); + end;" +); + +oci8_test_sql_execute($c, $stmtarray); + +// Turn DBMS_OUTPUT on +function setserveroutputon($c) +{ + $s = oci_parse($c, "begin dbms_output.enable(null); end;"); + oci_execute($s); +} + +function getdbmsoutput_do($c) +{ + $s = oci_parse($c, "begin dbms_output.get_line(:ln, :st); end;"); + oci_bind_by_name($s, ":ln", $ln, 100); + oci_bind_by_name($s, ":st", $st, -1, SQLT_INT); + $res = false; + while (($succ = oci_execute($s)) && !$st) { + $res[] = $ln; // append each line to the array + } + return $res; +} + +setserveroutputon($c); + +// Run Test + +echo "Test 1\n"; + +$s = oci_parse($c, "begin imp_res_get_dbmsoutput_proc(); end;"); +oci_execute($s); + +var_dump(getdbmsoutput_do($c)); + +while (($s1 = oci_get_implicit_resultset($s))) { + while (($row = oci_fetch_array($s1, OCI_ASSOC+OCI_RETURN_NULLS)) != false) { + foreach ($row as $item) { + echo " ".$item; + } + echo "\n"; + } +} + +echo "Test 2\n"; + +$s = oci_parse($c, "begin imp_res_get_dbmsoutput_proc(); end;"); +oci_execute($s); + +while (($s1 = oci_get_implicit_resultset($s))) { + while (($row = oci_fetch_array($s1, OCI_ASSOC+OCI_RETURN_NULLS)) != false) { + foreach ($row as $item) { + echo " ".$item; + } + echo "\n"; + } +} + +var_dump(getdbmsoutput_do($c)); + +// Clean up + +$stmtarray = array( + "drop procedure imp_res_get_dbmsoutput_proc", + "drop table imp_res_get_dbmsoutput_tab_1", + "drop table imp_res_get_dbmsoutput_tab_2" +); + +oci8_test_sql_execute($c, $stmtarray); + +?> +===DONE=== +<?php exit(0); ?> +--EXPECTF-- +Test 1 +array(3) { + [0]=> + string(6) "Line 1" + [1]=> + string(6) "Line 2" + [2]=> + string(6) "Line 3" +} + 1 abcde + 2 fghij + 3 klmno + t + u + v + X +Test 2 + 1 abcde + 2 fghij + 3 klmno + t + u + v + X +array(3) { + [0]=> + string(6) "Line 1" + [1]=> + string(6) "Line 2" + [2]=> + string(6) "Line 3" +} +===DONE=== + diff --git a/ext/oci8/tests/imp_res_get_exec.phpt b/ext/oci8/tests/imp_res_get_exec.phpt new file mode 100644 index 0000000000..dbd8f3ef3a --- /dev/null +++ b/ext/oci8/tests/imp_res_get_exec.phpt @@ -0,0 +1,55 @@ +--TEST-- +Oracle Database 12c Implicit Result Sets: oci_get_implicit_resultset: Execute twice +--SKIPIF-- +<?php +if (!extension_loaded('oci8')) die ("skip no oci8 extension"); +$target_dbs = array('oracledb' => true, 'timesten' => false); // test runs on these DBs +require(dirname(__FILE__).'/skipif.inc'); +preg_match('/.*Release ([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)*/', oci_server_version($c), $matches); +if (!(isset($matches[0]) && $matches[1] >= 12)) { + die("skip expected output only valid when using Oracle Database 12c or greater"); +} +preg_match('/^[[:digit:]]+/', oci_client_version(), $matches); +if (!(isset($matches[0]) && $matches[0] >= 12)) { + die("skip works only with Oracle 12c or greater version of Oracle client libraries"); +} +?> +--FILE-- +<?php + +require(dirname(__FILE__).'/connect.inc'); + +$plsql = "declare + c1 sys_refcursor; + begin + open c1 for select 1 from dual union all select 2 from dual; + dbms_sql.return_result(c1); + end;"; + +// Run Test + +echo "Test 1\n"; + +$s = oci_parse($c, $plsql); +oci_execute($s); + +$s1 = oci_get_implicit_resultset($s); +oci_execute($s1); +oci_execute($s1); // execute twice; should be NOP +while (($row = oci_fetch_array($s1, OCI_ASSOC+OCI_RETURN_NULLS)) != false) { + foreach ($row as $item) { + echo " ".$item; + } + echo "\n"; +} +oci_free_statement($s); + + +?> +===DONE=== +<?php exit(0); ?> +--EXPECTF-- +Test 1 + 1 + 2 +===DONE=== diff --git a/ext/oci8/tests/imp_res_get_none.phpt b/ext/oci8/tests/imp_res_get_none.phpt new file mode 100644 index 0000000000..981f4945e2 --- /dev/null +++ b/ext/oci8/tests/imp_res_get_none.phpt @@ -0,0 +1,46 @@ +--TEST-- +Oracle Database 12c Implicit Result Sets: oci_get_implicit_resultset: no implicit results +--SKIPIF-- +<?php +if (!extension_loaded('oci8')) die ("skip no oci8 extension"); +$target_dbs = array('oracledb' => true, 'timesten' => false); // test runs on these DBs +require(dirname(__FILE__).'/skipif.inc'); +preg_match('/.*Release ([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)*/', oci_server_version($c), $matches); +if (!(isset($matches[0]) && $matches[1] >= 12)) { + die("skip expected output only valid when using Oracle Database 12c or greater"); +} +preg_match('/^[[:digit:]]+/', oci_client_version(), $matches); +if (!(isset($matches[0]) && $matches[0] >= 12)) { + die("skip works only with Oracle 12c or greater version of Oracle client libraries"); +} +?> +--FILE-- +<?php + +require(dirname(__FILE__).'/connect.inc'); + +// Run Test + +echo "Test 1\n"; + +$s = oci_parse($c, "select * from dual"); +oci_execute($s); + +while (($s1 = oci_get_implicit_resultset($s))) { + while (($row = oci_fetch_array($s1, OCI_ASSOC+OCI_RETURN_NULLS)) != false) { + foreach ($row as $item) { + echo " ".$item; + } + echo "\n"; + } +} + +var_dump($s1); + +?> +===DONE=== +<?php exit(0); ?> +--EXPECTF-- +Test 1 +bool(false) +===DONE=== diff --git a/ext/oci8/tests/imp_res_insert.phpt b/ext/oci8/tests/imp_res_insert.phpt new file mode 100644 index 0000000000..d9c0705b55 --- /dev/null +++ b/ext/oci8/tests/imp_res_insert.phpt @@ -0,0 +1,152 @@ +--TEST-- +Oracle Database 12c Implicit Result Sets: Commit modes +--SKIPIF-- +<?php +if (!extension_loaded('oci8')) die ("skip no oci8 extension"); +$target_dbs = array('oracledb' => true, 'timesten' => false); // test runs on these DBs +require(dirname(__FILE__).'/skipif.inc'); +preg_match('/.*Release ([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)*/', oci_server_version($c), $matches); +if (!(isset($matches[0]) && $matches[1] >= 12)) { + die("skip expected output only valid when using Oracle Database 12c or greater"); +} +preg_match('/^[[:digit:]]+/', oci_client_version(), $matches); +if (!(isset($matches[0]) && $matches[0] >= 12)) { + die("skip works only with Oracle 12c or greater version of Oracle client libraries"); +} +?> +--FILE-- +<?php + +require(dirname(__FILE__).'/connect.inc'); + +// Initialization + +$c2 = oci_new_connect($user, $password, $dbase); + +$stmtarray = array( + "drop table imp_res_insert_tab", + "create table imp_res_insert_tab (c1 number)", + + "create or replace procedure imp_res_insert_proc_nc (p1 in number) as + c1 sys_refcursor; + begin + execute immediate 'insert into imp_res_insert_tab values ('||p1||')'; + open c1 for select * from imp_res_insert_tab order by 1; + dbms_sql.return_result(c1); + end;", + + "create or replace procedure imp_res_insert_proc_c (p1 in number) as + c1 sys_refcursor; + begin + execute immediate 'insert into imp_res_insert_tab values ('||p1||')'; + commit; + open c1 for select * from imp_res_insert_tab order by 1; + dbms_sql.return_result(c1); + end;" + +); + +oci8_test_sql_execute($c, $stmtarray); + +// Run Test + +echo "Test 1 - No commit in procedure, OCI_COMMIT_ON_SUCCESS mode\n"; +$s = oci_parse($c, "begin imp_res_insert_proc_nc(111); end;"); +oci_execute($s, OCI_COMMIT_ON_SUCCESS); +while (($row = oci_fetch_row($s)) !== false) + echo $row[0], "\n"; +$s2 = oci_parse($c2, "select * from imp_res_insert_tab order by 1"); +oci_execute($s2, OCI_NO_AUTO_COMMIT); +oci_fetch_all($s2, $res); +var_dump($res['C1']); + +echo "\nTest 2 - No commit in procedure, OCI_NO_AUTO_COMMIT mode\n"; +$s = oci_parse($c, "begin imp_res_insert_proc_nc(222); end;"); +oci_execute($s, OCI_NO_AUTO_COMMIT); +while (($row = oci_fetch_row($s)) !== false) + echo $row[0], "\n"; +// The 2nd connection won't see the newly inserted data +$s2 = oci_parse($c2, "select * from imp_res_insert_tab order by 1"); +oci_execute($s2, OCI_NO_AUTO_COMMIT); +oci_fetch_all($s2, $res); +var_dump($res['C1']); + +echo "\nTest 3 - Commit in procedure, OCI_COMMIT_ON_SUCCESS mode\n"; +$s = oci_parse($c, "begin imp_res_insert_proc_c(333); end;"); +oci_execute($s, OCI_COMMIT_ON_SUCCESS); +// The 2nd connection will now see the previously uncommitted data inserted in the previous test +while (($row = oci_fetch_row($s)) !== false) + echo $row[0], "\n"; +$s2 = oci_parse($c2, "select * from imp_res_insert_tab order by 1"); +oci_execute($s2, OCI_NO_AUTO_COMMIT); +oci_fetch_all($s2, $res); +var_dump($res['C1']); + +echo "\nTest 4 - Commit in procedure, OCI_NO_AUTO_COMMIT mode\n"; +$s = oci_parse($c, "begin imp_res_insert_proc_c(444); end;"); +oci_execute($s, OCI_NO_AUTO_COMMIT); +while (($row = oci_fetch_row($s)) !== false) + echo $row[0], "\n"; +$s2 = oci_parse($c2, "select * from imp_res_insert_tab order by 1"); +oci_execute($s2, OCI_NO_AUTO_COMMIT); +oci_fetch_all($s2, $res); +var_dump($res['C1']); + +// Clean up + +$stmtarray = array( + "drop procedure imp_res_insert_proc_nc", + "drop procedure imp_res_insert_proc_c", + "drop table imp_res_insert_tab", +); + +oci8_test_sql_execute($c, $stmtarray); + +?> +===DONE=== +<?php exit(0); ?> +--EXPECTF-- +Test 1 - No commit in procedure, OCI_COMMIT_ON_SUCCESS mode +111 +array(1) { + [0]=> + string(3) "111" +} + +Test 2 - No commit in procedure, OCI_NO_AUTO_COMMIT mode +111 +222 +array(1) { + [0]=> + string(3) "111" +} + +Test 3 - Commit in procedure, OCI_COMMIT_ON_SUCCESS mode +111 +222 +333 +array(3) { + [0]=> + string(3) "111" + [1]=> + string(3) "222" + [2]=> + string(3) "333" +} + +Test 4 - Commit in procedure, OCI_NO_AUTO_COMMIT mode +111 +222 +333 +444 +array(4) { + [0]=> + string(3) "111" + [1]=> + string(3) "222" + [2]=> + string(3) "333" + [3]=> + string(3) "444" +} +===DONE=== diff --git a/ext/oci8/tests/imp_res_lob.phpt b/ext/oci8/tests/imp_res_lob.phpt new file mode 100644 index 0000000000..247803581d --- /dev/null +++ b/ext/oci8/tests/imp_res_lob.phpt @@ -0,0 +1,101 @@ +--TEST-- +Oracle Database 12c Implicit Result Sets: LOBs +--SKIPIF-- +<?php +if (!extension_loaded('oci8')) die ("skip no oci8 extension"); +$target_dbs = array('oracledb' => true, 'timesten' => false); // test runs on these DBs +require(dirname(__FILE__).'/skipif.inc'); +preg_match('/.*Release ([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)*/', oci_server_version($c), $matches); +if (!(isset($matches[0]) && $matches[1] >= 12)) { + die("skip expected output only valid when using Oracle Database 12c or greater"); +} +preg_match('/^[[:digit:]]+/', oci_client_version(), $matches); +if (!(isset($matches[0]) && $matches[0] >= 12)) { + die("skip works only with Oracle 12c or greater version of Oracle client libraries"); +} +?> +--FILE-- +<?php + +require(dirname(__FILE__).'/connect.inc'); + +// Initialization + +$stmtarray = array( + "drop table imp_res_lob_tab", + "create table imp_res_lob_tab (c1 number, c2 clob, c3 varchar2(10))", + "insert into imp_res_lob_tab values (1, 'aaaaa', 'a')", + "insert into imp_res_lob_tab values (2, 'bbbbb', 'b')", + "insert into imp_res_lob_tab values (3, 'ccccc', 'c')", + "insert into imp_res_lob_tab values (4, 'ddddd', 'd')", + + "create or replace procedure imp_res_lob_proc as + c1 sys_refcursor; + begin + open c1 for select * from imp_res_lob_tab order by 1; + dbms_sql.return_result(c1); + open c1 for select * from dual; + dbms_sql.return_result(c1); + open c1 for select c2 from imp_res_lob_tab order by c1; + dbms_sql.return_result(c1); + end;" +); + +oci8_test_sql_execute($c, $stmtarray); + +// Run Test + +echo "Test 1\n"; +$s = oci_parse($c, "begin imp_res_lob_proc(); end;"); +oci_execute($s); +while (($row = oci_fetch_row($s)) != false) { + foreach ($row as $item) { + if (is_object($item)) { + echo " " . $item->load(); + } else { + echo " " . $item; + } + } + echo "\n"; +} + +echo "\nTest 2 - don't fetch all rows\n"; +$s = oci_parse($c, "begin imp_res_lob_proc(); end;"); +oci_execute($s); +$row = oci_fetch_row($s); +foreach ($row as $item) { + if (is_object($item)) { + echo " " . $item->load(); + } else { + echo " " . $item; + } +} +echo "\n"; + +// Clean up + +$stmtarray = array( + "drop procedure imp_res_lob_proc", + "drop table imp_res_lob_tab", +); + +oci8_test_sql_execute($c, $stmtarray); + +?> +===DONE=== +<?php exit(0); ?> +--EXPECTF-- +Test 1 + 1 aaaaa a + 2 bbbbb b + 3 ccccc c + 4 ddddd d + X + aaaaa + bbbbb + ccccc + ddddd + +Test 2 - don't fetch all rows + 1 aaaaa a +===DONE=== diff --git a/ext/oci8/tests/imp_res_prefetch.phpt b/ext/oci8/tests/imp_res_prefetch.phpt new file mode 100644 index 0000000000..5acdd518e5 --- /dev/null +++ b/ext/oci8/tests/imp_res_prefetch.phpt @@ -0,0 +1,185 @@ +--TEST-- +Oracle Database 12c Implicit Result Sets: basic test +--SKIPIF-- +<?php +if (!extension_loaded('oci8')) die ("skip no oci8 extension"); +$target_dbs = array('oracledb' => true, 'timesten' => false); // test runs on these DBs +require(dirname(__FILE__).'/skipif.inc'); +preg_match('/.*Release ([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)*/', oci_server_version($c), $matches); +if (!(isset($matches[0]) && $matches[1] >= 12)) { + die("skip expected output only valid when using Oracle Database 12c or greater"); +} +preg_match('/^[[:digit:]]+/', oci_client_version(), $matches); +if (!(isset($matches[0]) && $matches[0] >= 12)) { + die("skip works only with Oracle 12c or greater version of Oracle client libraries"); +} +?> +--FILE-- +<?php + +require(dirname(__FILE__).'/connect.inc'); + +// Initialization + +$stmtarray = array( + "drop table imp_res_prefetch_tab_1", + "create table imp_res_prefetch_tab_1 (c1 number, c2 varchar2(10))", + "insert into imp_res_prefetch_tab_1 values (1, 'abcde')", + "insert into imp_res_prefetch_tab_1 values (2, 'fghij')", + "insert into imp_res_prefetch_tab_1 values (3, 'klmno')", + + "drop table imp_res_prefetch_tab_2", + "create table imp_res_prefetch_tab_2 (c3 varchar2(1))", + "insert into imp_res_prefetch_tab_2 values ('t')", + "insert into imp_res_prefetch_tab_2 values ('u')", + "insert into imp_res_prefetch_tab_2 values ('v')", + + "create or replace procedure imp_res_prefetch_proc as + c1 sys_refcursor; + begin + open c1 for select * from imp_res_prefetch_tab_1 order by 1; + dbms_sql.return_result(c1); + + open c1 for select * from imp_res_prefetch_tab_2 order by 1; + dbms_sql.return_result(c1); + end;" +); + +oci8_test_sql_execute($c, $stmtarray); + +// Run Test + +echo "Test 1 - prefetch 0\n"; +$s = oci_parse($c, "begin imp_res_prefetch_proc(); end;"); +oci_execute($s); +var_dump(oci_set_prefetch($s, 0)); +while (($row = oci_fetch_row($s)) != false) + var_dump($row); + +echo "\nTest 1 - prefetch 1\n"; +$s = oci_parse($c, "begin imp_res_prefetch_proc(); end;"); +oci_execute($s); +var_dump(oci_set_prefetch($s, 1)); +while (($row = oci_fetch_row($s)) != false) + var_dump($row); + +echo "\nTest 1 - prefetch 2\n"; +$s = oci_parse($c, "begin imp_res_prefetch_proc(); end;"); +oci_execute($s); +var_dump(oci_set_prefetch($s, 2)); +while (($row = oci_fetch_row($s)) != false) + var_dump($row); + +// Clean up + +$stmtarray = array( + "drop procedure imp_res_prefetch_proc", + "drop table imp_res_prefetch_tab_1", + "drop table imp_res_prefetch_tab_2" +); + +oci8_test_sql_execute($c, $stmtarray); + +?> +===DONE=== +<?php exit(0); ?> +--EXPECTF-- +Test 1 - prefetch 0 +bool(true) +array(2) { + [0]=> + string(1) "1" + [1]=> + string(5) "abcde" +} +array(2) { + [0]=> + string(1) "2" + [1]=> + string(5) "fghij" +} +array(2) { + [0]=> + string(1) "3" + [1]=> + string(5) "klmno" +} +array(1) { + [0]=> + string(1) "t" +} +array(1) { + [0]=> + string(1) "u" +} +array(1) { + [0]=> + string(1) "v" +} + +Test 1 - prefetch 1 +bool(true) +array(2) { + [0]=> + string(1) "1" + [1]=> + string(5) "abcde" +} +array(2) { + [0]=> + string(1) "2" + [1]=> + string(5) "fghij" +} +array(2) { + [0]=> + string(1) "3" + [1]=> + string(5) "klmno" +} +array(1) { + [0]=> + string(1) "t" +} +array(1) { + [0]=> + string(1) "u" +} +array(1) { + [0]=> + string(1) "v" +} + +Test 1 - prefetch 2 +bool(true) +array(2) { + [0]=> + string(1) "1" + [1]=> + string(5) "abcde" +} +array(2) { + [0]=> + string(1) "2" + [1]=> + string(5) "fghij" +} +array(2) { + [0]=> + string(1) "3" + [1]=> + string(5) "klmno" +} +array(1) { + [0]=> + string(1) "t" +} +array(1) { + [0]=> + string(1) "u" +} +array(1) { + [0]=> + string(1) "v" +} +===DONE=== diff --git a/ext/oci8/tests/ini_1.phpt b/ext/oci8/tests/ini_1.phpt index 4c23b72b41..2fba79813e 100644 --- a/ext/oci8/tests/ini_1.phpt +++ b/ext/oci8/tests/ini_1.phpt @@ -1,7 +1,13 @@ --TEST-- Test OCI8 php.ini settings --SKIPIF-- -<?php if (!extension_loaded('oci8')) die ("skip no oci8 extension"); ?> +<?php +if (!extension_loaded('oci8')) die ("skip no oci8 extension"); +preg_match('/^[[:digit:]]+/', oci_client_version(), $matches); +if (!(isset($matches[0]) && $matches[0] >= 11)) { + die("skip works only with Oracle 11g or greater version of Oracle client libraries"); +} +?> --INI-- oci8.privileged_connect = On oci8.max_persistent = 111 diff --git a/ext/oci8/tests/lob_015.phpt b/ext/oci8/tests/lob_015.phpt index b4a19684a3..59e8fec42a 100644 --- a/ext/oci8/tests/lob_015.phpt +++ b/ext/oci8/tests/lob_015.phpt @@ -48,7 +48,7 @@ Warning: oci_bind_by_name() expects at least 3 parameters, 2 given in %s on line Warning: oci_bind_by_name() expects at least 3 parameters, 1 given in %s on line %d -Warning: oci_execute(): ORA-00932: %s NUMBER %s BLOB in %s on line %d +Warning: oci_execute(): ORA-00932: %s on line %d object(OCI-Lob)#%d (1) { ["descriptor"]=> resource(%d) of type (oci8 descriptor) diff --git a/ext/oci8/tests/lob_temp2.phpt b/ext/oci8/tests/lob_temp2.phpt new file mode 100644 index 0000000000..d774b4d724 --- /dev/null +++ b/ext/oci8/tests/lob_temp2.phpt @@ -0,0 +1,40 @@ +--TEST-- +Writing temporary lob before binding +--SKIPIF-- +<?php +if (!extension_loaded('oci8')) die ("skip no oci8 extension"); +$target_dbs = array('oracledb' => true, 'timesten' => false); // test runs on these DBs +require(dirname(__FILE__).'/skipif.inc'); +?> +--FILE-- +<?php + +require(dirname(__FILE__).'/connect.inc'); +require(dirname(__FILE__).'/create_table.inc'); + +$ora_sql = "INSERT INTO ".$schema.$table_name." (clob) VALUES (:v_clob)"; + +$clob = oci_new_descriptor($c, OCI_D_LOB); +var_dump($clob->writeTemporary("test")); + +$statement = oci_parse($c, $ora_sql); +oci_bind_by_name($statement, ":v_clob", $clob, -1, OCI_B_CLOB); +oci_execute($statement, OCI_DEFAULT); + +$s = oci_parse($c, "select clob from ". $schema.$table_name); +oci_execute($s); +oci_fetch_all($s, $res); +var_dump($res); + +?> +===DONE=== +--EXPECTF-- +bool(true) +array(1) { + ["CLOB"]=> + array(1) { + [0]=> + string(4) "test" + } +} +===DONE=== diff --git a/ext/oci8/tests/minfo.phpt b/ext/oci8/tests/minfo.phpt index f6b95ff296..34a19ca693 100644 --- a/ext/oci8/tests/minfo.phpt +++ b/ext/oci8/tests/minfo.phpt @@ -8,12 +8,12 @@ Code coverage for PHP_MINFO_FUNCTION(oci) ob_start(); phpinfo(INFO_MODULES); $v = ob_get_clean(); -$r = strpos($v, 'OCI8 Support => enabled'); -var_dump($r); +$r = preg_match('/OCI8 Support .* enabled/', $v); +if ($r !== 1) + var_dump($r); echo "Done\n"; ?> --EXPECTF-- -int(%d) Done diff --git a/ext/oci8/tests/password.phpt b/ext/oci8/tests/password.phpt index 1738702cb6..8ea81d3fc0 100644 --- a/ext/oci8/tests/password.phpt +++ b/ext/oci8/tests/password.phpt @@ -14,28 +14,28 @@ if ($test_drcp) die("skip password change not supported in DRCP Mode"); require(dirname(__FILE__)."/connect.inc"); $stmtarray = array( - "drop user testuser cascade", - "create user testuser identified by testuserpwd", - "grant connect, create session to testuser" + "drop user testuser_pw cascade", + "create user testuser_pw identified by testuserpwd", + "grant connect, create session to testuser_pw" ); oci8_test_sql_execute($c, $stmtarray); // Connect and change the password -$c1 = oci_connect("testuser", "testuserpwd", $dbase); +$c1 = oci_connect("testuser_pw", "testuserpwd", $dbase); var_dump($c1); $rn1 = (int)$c1; -oci_password_change($c1, "testuser", "testuserpwd", "testuserpwd2"); +oci_password_change($c1, "testuser_pw", "testuserpwd", "testuserpwd2"); // Second connect should return a new resource because the hash string will be different from $c1 -$c2 = oci_connect("testuser", "testuserpwd2", $dbase); +$c2 = oci_connect("testuser_pw", "testuserpwd2", $dbase); var_dump($c2); $rn2 = (int)$c2; // Despite using the old password this connect should succeed and return the original resource -$c3 = oci_connect("testuser", "testuserpwd", $dbase); +$c3 = oci_connect("testuser_pw", "testuserpwd", $dbase); var_dump($c3); $rn3 = (int)$c3; @@ -67,7 +67,7 @@ echo "Done\n"; require(dirname(__FILE__)."/connect.inc"); $stmtarray = array( - "drop user testuser cascade" + "drop user testuser_pw cascade" ); oci8_test_sql_execute($c, $stmtarray); diff --git a/ext/oci8/tests/password_2.phpt b/ext/oci8/tests/password_2.phpt index ceba0bba80..13da9ff7b2 100644 --- a/ext/oci8/tests/password_2.phpt +++ b/ext/oci8/tests/password_2.phpt @@ -14,27 +14,27 @@ if ($test_drcp) die("skip password change not supported in DRCP Mode"); require(dirname(__FILE__)."/connect.inc"); $stmtarray = array( - "drop user testuser cascade", - "create user testuser identified by testuserpwd", - "grant connect, create session to testuser" + "drop user testuser_pw2 cascade", + "create user testuser_pw2 identified by testuserpwd", + "grant connect, create session to testuser_pw2" ); oci8_test_sql_execute($c, $stmtarray); // Connect (persistent) and change the password -$c1 = oci_pconnect("testuser", "testuserpwd", $dbase); +$c1 = oci_pconnect("testuser_pw2", "testuserpwd", $dbase); var_dump($c1); $rn1 = (int)$c1; -oci_password_change($c1, "testuser", "testuserpwd", "testuserpwd2"); +oci_password_change($c1, "testuser_pw2", "testuserpwd", "testuserpwd2"); // Second connect should return a new resource because the hash string will be different from $c1 -$c2 = oci_pconnect("testuser", "testuserpwd2", $dbase); +$c2 = oci_pconnect("testuser_pw2", "testuserpwd2", $dbase); var_dump($c2); $rn2 = (int)$c2; // Despite using the old password this connect should succeed and return the original resource -$c3 = oci_pconnect("testuser", "testuserpwd", $dbase); +$c3 = oci_pconnect("testuser_pw2", "testuserpwd", $dbase); var_dump($c3); $rn3 = (int)$c3; @@ -66,7 +66,7 @@ echo "Done\n"; require(dirname(__FILE__)."/connect.inc"); $stmtarray = array( - "drop user testuser cascade" + "drop user testuser_pw2 cascade" ); oci8_test_sql_execute($c, $stmtarray); diff --git a/ext/oci8/tests/password_new.phpt b/ext/oci8/tests/password_new.phpt index c218d904fa..a29fb8f52f 100644 --- a/ext/oci8/tests/password_new.phpt +++ b/ext/oci8/tests/password_new.phpt @@ -3,36 +3,40 @@ oci_password_change() --SKIPIF-- <?php $target_dbs = array('oracledb' => true, 'timesten' => false); // test runs on thes -require(dirname(__FILE__).'/skipif.inc'); +require(dirname(__FILE__).'/connect.inc'); if (empty($dbase)) die ("skip requires database connection string be set"); if ($test_drcp) die("skip password change not supported in DRCP Mode"); -// This test is known to fail with Oracle 10.2.0.4 client libraries -// connecting to Oracle Database 11 (Oracle bug 6277160, fixed 10.2.0.5) -if (preg_match('/Release (11|12)\./', oci_server_version($c), $matches) === 1 && - preg_match('/^10\.2\.0\.[1234]/', oci_client_version()) === 1) { - die ("skip test known to fail using Oracle 10.2.0.4 client libs connecting to Oracle 11 (6277160)"); +preg_match('/.*Release ([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)*/', oci_server_version($c), $matches_sv); +preg_match('/([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)/', oci_client_version(), $matches); +if (!(isset($matches_sv[0]) && isset($matches[0]) + && $matches_sv[1] == $matches[1] + && $matches_sv[2] == $matches[2] + && $matches_sv[3] == $matches[3] + && $matches_sv[4] == $matches[4])) { + // Avoid diffs due to cross version protocol changes (e.g. like 11.2.0.2-11.2.0.3) and bugs like Oracle bug: 6277160 + die ("skip test only runs when database client libraries and database server are the same version"); +} + +// This test in Oracle 12c needs a non-CDB or the root container +if (isset($matches_sv[0]) && $matches_sv[1] >= 12) { + $s = oci_parse($c, "select nvl(sys_context('userenv', 'con_name'), 'notacdb') as dbtype from dual"); + $r = @oci_execute($s); + if (!$r) + die('skip could not identify container type'); + $r = oci_fetch_array($s); + if ($r['DBTYPE'] !== 'CDB$ROOT') + die('skip cannot run test using a PDB'); } ?> --FILE-- <?php -// This test will diff if either the client or the server is 11.2.0.3 -// (or greater) and the other is 11.2.0.2 (or earlier). Both client -// and server must be upgraded at the same time. - require dirname(__FILE__)."/connect.inc"; $new_password = "test"; var_dump(oci_password_change($dbase, $user, $password, $new_password)); - -if (!empty($dbase)) { - var_dump($new_c = ocilogon($user,$new_password,$dbase)); -} -else { - var_dump($new_c = ocilogon($user,$new_password)); -} - +var_dump($new_c = ocilogon($user,$new_password,$dbase)); var_dump(oci_password_change($dbase, $user, $new_password, $password)); diff --git a/ext/oci8/tests/password_old.phpt b/ext/oci8/tests/password_old.phpt index fdbb1f9e89..873fd4f595 100644 --- a/ext/oci8/tests/password_old.phpt +++ b/ext/oci8/tests/password_old.phpt @@ -3,41 +3,42 @@ ocipasswordchange() --SKIPIF-- <?php $target_dbs = array('oracledb' => true, 'timesten' => false); // test runs on thes -require(dirname(__FILE__).'/skipif.inc'); +require(dirname(__FILE__).'/connect.inc'); if (empty($dbase)) die ("skip requires database connection string be set"); if ($test_drcp) die("skip password change not supported in DRCP Mode"); -// This test is known to fail with Oracle 10.2.0.4 client libraries -// connecting to Oracle Database 11 (Oracle bug 6277160, fixed 10.2.0.5) -if (preg_match('/Release (11|12)\./', oci_server_version($c), $matches) === 1 && - preg_match('/^10\.2\.0\.[1234]/', oci_client_version()) === 1) { - die ("skip test known to fail using Oracle 10.2.0.4 client libs connecting to Oracle 11 (6277160)"); +preg_match('/.*Release ([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)*/', oci_server_version($c), $matches_sv); +preg_match('/([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)/', oci_client_version(), $matches); +if (!(isset($matches_sv[0]) && isset($matches[0]) + && $matches_sv[1] == $matches[1] + && $matches_sv[2] == $matches[2] + && $matches_sv[3] == $matches[3] + && $matches_sv[4] == $matches[4])) { + // Avoid diffs due to cross version protocol changes (e.g. like 11.2.0.2-11.2.0.3) and bugs like Oracle bug: 6277160 + die ("skip test only runs when database client libraries and database server are the same version"); } - +// This test in Oracle 12c needs a non-CDB or the root container +if (isset($matches_sv[0]) && $matches_sv[1] >= 12) { + $s = oci_parse($c, "select nvl(sys_context('userenv', 'con_name'), 'notacdb') as dbtype from dual"); + $r = @oci_execute($s); + if (!$r) + die('skip could not identify container type'); + $r = oci_fetch_array($s); + if ($r['DBTYPE'] !== 'CDB$ROOT') + die('skip cannot run test using a PDB'); +} ?> --FILE-- <?php -// This test will diff if either the client or the server is 11.2.0.3 -// (or greater) and the other is 11.2.0.2 (or earlier). Both client -// and server must be upgraded at the same time. - require dirname(__FILE__)."/connect.inc"; $new_password = "test"; var_dump(ocipasswordchange($dbase, $user, $password, $new_password)); - -if (!empty($dbase)) { - var_dump($new_c = ocilogon($user,$new_password,$dbase)); -} -else { - var_dump($new_c = ocilogon($user,$new_password)); -} - +var_dump($new_c = ocilogon($user,$new_password,$dbase)); var_dump(ocipasswordchange($dbase, $user, $new_password, $password)); - echo "Done\n"; ?> diff --git a/ext/oci8/tests/pecl_bug16035.phpt b/ext/oci8/tests/pecl_bug16035.phpt index ddd0038de1..29ff6439d1 100644 --- a/ext/oci8/tests/pecl_bug16035.phpt +++ b/ext/oci8/tests/pecl_bug16035.phpt @@ -10,9 +10,6 @@ $ov = preg_match('/Compile-time ORACLE_HOME/', $phpinfo); if ($ov !== 1) { die ("skip Test only valid when OCI8 is built with an ORACLE_HOME"); } -if (preg_match('/Unknown/', oci_client_version()) == 1) { - die("skip expected output only valid with Oracle clients > 9gR2"); -} ?> --ENV-- ORACLE_HOME="" diff --git a/ext/oci8/tests/refcur_prefetch_1.phpt b/ext/oci8/tests/refcur_prefetch_1.phpt index ea09fbcd97..c7e200932a 100644 --- a/ext/oci8/tests/refcur_prefetch_1.phpt +++ b/ext/oci8/tests/refcur_prefetch_1.phpt @@ -4,9 +4,16 @@ Prefetch with REF cursor. Test different values for prefetch with oci_set_prefet <?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); if (!extension_loaded('oci8')) die("skip no oci8 extension"); require(dirname(__FILE__)."/connect.inc"); -if (preg_match('/Release 1[012]\./', oci_server_version($c), $matches) !== 1) { - die("skip expected output only valid when using Oracle 10g or greater databases"); -} else if (preg_match('/^(11\.2|12)\./', oci_client_version()) != 1) { +preg_match('/.*Release ([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)*/', oci_server_version($c), $matches); +if (!(isset($matches[0]) && + ($matches[1] >= 10))) { + die("skip expected output only valid when using Oracle 10g or greater database server"); +} +preg_match('/^([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)/', oci_client_version(), $matches); +if (!(isset($matches[0]) && + (($matches[1] == 11 && $matches[2] >= 2) || + ($matches[1] >= 12) + ))) { die("skip test expected to work only with Oracle 11gR2 or greater version of client"); } ?> diff --git a/ext/oci8/tests/refcur_prefetch_2.phpt b/ext/oci8/tests/refcur_prefetch_2.phpt index 8d65251077..9b2472db5d 100644 --- a/ext/oci8/tests/refcur_prefetch_2.phpt +++ b/ext/oci8/tests/refcur_prefetch_2.phpt @@ -4,9 +4,16 @@ Prefetch with REF cursor. Test No 2 <?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); if (!extension_loaded('oci8')) die("skip no oci8 extension"); require(dirname(__FILE__)."/connect.inc"); -if (preg_match('/Release 1[012]\./', oci_server_version($c), $matches) !== 1) { - die("skip expected output only valid when using Oracle 10g or greater databases"); -} else if (preg_match('/^(11\.2|12)\./', oci_client_version()) != 1) { +preg_match('/.*Release ([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)*/', oci_server_version($c), $matches); +if (!(isset($matches[0]) && + ($matches[1] >= 10))) { + die("skip expected output only valid when using Oracle 10g or greater database server"); +} +preg_match('/^([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)/', oci_client_version(), $matches); +if (!(isset($matches[0]) && + (($matches[1] == 11 && $matches[2] >= 2) || + ($matches[1] >= 12) + ))) { die("skip test expected to work only with Oracle 11gR2 or greater version of client"); } ?> diff --git a/ext/oci8/tests/refcur_prefetch_3.phpt b/ext/oci8/tests/refcur_prefetch_3.phpt index 8c0414042b..f29345e515 100644 --- a/ext/oci8/tests/refcur_prefetch_3.phpt +++ b/ext/oci8/tests/refcur_prefetch_3.phpt @@ -6,12 +6,20 @@ oci8.default_prefetch=5 <?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); if (!extension_loaded('oci8')) die("skip no oci8 extension"); require(dirname(__FILE__)."/connect.inc"); -if (preg_match('/Release (11\.2|12)\./', oci_server_version($c), $matches) !== 1) { - die("skip expected output only valid when using Oracle 11gR2 or greater databases"); -} else if (preg_match('/^(11\.2|12)\./', oci_client_version()) != 1) { +preg_match('/.*Release ([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)*/', oci_server_version($c), $matches); +if (!(isset($matches[0]) && + (($matches[1] == 11 && $matches[2] >= 2) || + ($matches[1] >= 12) + ))) { + die("skip expected output only valid when using Oracle 11gR2 or greater database server"); +} +preg_match('/^([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)/', oci_client_version(), $matches); +if (!(isset($matches[0]) && + (($matches[1] == 11 && $matches[2] >= 2) || + ($matches[1] >= 12) + ))) { die("skip test expected to work only with Oracle 11gR2 or greater version of client"); } - ?> --FILE-- <?php @@ -86,52 +94,52 @@ Test with Nested Cursors Fetch Row using Nested cursor Query array(1) { [0]=> - %unicode|string%(%d) "test0" + string(%d) "test0" } Fetch Row using Nested cursor Query array(1) { [0]=> - %unicode|string%(%d) "test1" + string(%d) "test1" } Fetch Row using Nested cursor Query array(1) { [0]=> - %unicode|string%(%d) "test2" + string(%d) "test2" } Fetch Row using Nested cursor Query array(1) { [0]=> - %unicode|string%(%d) "test3" + string(%d) "test3" } Fetch Row using Nested cursor Query array(1) { [0]=> - %unicode|string%(%d) "test4" + string(%d) "test4" } Fetch Row using Nested cursor Query array(1) { [0]=> - %unicode|string%(%d) "test5" + string(%d) "test5" } Fetch Row using Nested cursor Query array(1) { [0]=> - %unicode|string%(%d) "test6" + string(%d) "test6" } Fetch Row using Nested cursor Query array(1) { [0]=> - %unicode|string%(%d) "test7" + string(%d) "test7" } Fetch Row using Nested cursor Query array(1) { [0]=> - %unicode|string%(%d) "test8" + string(%d) "test8" } Fetch Row using Nested cursor Query array(1) { [0]=> - %unicode|string%(%d) "test9" + string(%d) "test9" } Number of roundtrips made with prefetch count 5 for 10 rows is 3 Done diff --git a/ext/oci8/tests/refcur_prefetch_4.phpt b/ext/oci8/tests/refcur_prefetch_4.phpt index d24398c00e..f0c7183d0e 100644 --- a/ext/oci8/tests/refcur_prefetch_4.phpt +++ b/ext/oci8/tests/refcur_prefetch_4.phpt @@ -4,9 +4,16 @@ Prefetch with REF cursor. Test No 4 <?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); if (!extension_loaded('oci8')) die("skip no oci8 extension"); require(dirname(__FILE__)."/connect.inc"); -if (preg_match('/Release 1[012]\./', oci_server_version($c), $matches) !== 1) { - die("skip expected output only valid when using Oracle 10g or greater databases"); -} else if (preg_match('/^(11\.2|12)\./', oci_client_version()) != 1) { +preg_match('/.*Release ([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)*/', oci_server_version($c), $matches); +if (!(isset($matches[0]) && + ($matches[1] >= 10))) { + die("skip expected output only valid when using Oracle 10g or greater database server"); +} +preg_match('/^([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)/', oci_client_version(), $matches); +if (!(isset($matches[0]) && + (($matches[1] == 11 && $matches[2] >= 2) || + ($matches[1] >= 12) + ))) { die("skip test expected to work only with Oracle 11gR2 or greater version of client"); } ?> diff --git a/ext/oci8/tests/reflection1.phpt b/ext/oci8/tests/reflection1.phpt index 5f2e73d80b..f76d7261aa 100644 --- a/ext/oci8/tests/reflection1.phpt +++ b/ext/oci8/tests/reflection1.phpt @@ -126,6 +126,7 @@ reflection::export(new reflectionfunction('oci_set_module_name')); reflection::export(new reflectionfunction('oci_set_action')); reflection::export(new reflectionfunction('oci_set_client_info')); reflection::export(new reflectionfunction('oci_set_client_identifier')); +reflection::export(new reflectionfunction('oci_get_implicit_resultset')); ?> ===DONE=== @@ -1093,4 +1094,11 @@ Function [ <internal%s> function oci_set_client_identifier ] { } } +Function [ <internal%s> function oci_get_implicit_resultset ] { + + - Parameters [1] { + Parameter #0 [ <required> $statement_resource ] + } +} + ===DONE=== diff --git a/ext/odbc/config.m4 b/ext/odbc/config.m4 index eaed212cd7..7bc06715dd 100644 --- a/ext/odbc/config.m4 +++ b/ext/odbc/config.m4 @@ -365,7 +365,7 @@ fi if test -z "$ODBC_TYPE"; then PHP_ARG_WITH(iodbc,, -[ --with-iodbc[=DIR] Include iODBC support [/usr/local]]) +[ --with-iodbc[=DIR] Include iODBC support]) if test "$PHP_IODBC" != "no"; then AC_MSG_CHECKING(for iODBC support) diff --git a/ext/opcache/Optimizer/block_pass.c b/ext/opcache/Optimizer/block_pass.c index 8c4c58e493..0a7b1ded0f 100644 --- a/ext/opcache/Optimizer/block_pass.c +++ b/ext/opcache/Optimizer/block_pass.c @@ -1862,7 +1862,7 @@ next_target_znz: #endif /* Find a set of variables which are used outside of the block where they are - * defined. We won't apply some optimization patterns for sush variables. */ + * defined. We won't apply some optimization patterns for such variables. */ static void zend_t_usage(zend_code_block *block, zend_op_array *op_array, char *used_ext) { zend_code_block *next_block = block->next; @@ -1894,6 +1894,7 @@ static void zend_t_usage(zend_code_block *block, zend_op_array *op_array, char * if (RESULT_USED(opline)) { if (!defined_here[VAR_NUM(ZEND_RESULT(opline).var)] && !used_ext[VAR_NUM(ZEND_RESULT(opline).var)] && (opline->opcode == ZEND_RECV || opline->opcode == ZEND_RECV_INIT || + opline->opcode == ZEND_RECV_VARIADIC || (opline->opcode == ZEND_OP_DATA && ZEND_RESULT_TYPE(opline) == IS_TMP_VAR) || opline->opcode == ZEND_ADD_ARRAY_ELEMENT)) { /* these opcodes use the result as argument */ @@ -1978,6 +1979,7 @@ static void zend_t_usage(zend_code_block *block, zend_op_array *op_array, char * if (opline->opcode == ZEND_RECV || opline->opcode == ZEND_RECV_INIT || + opline->opcode == ZEND_RECV_VARIADIC || opline->opcode == ZEND_ADD_ARRAY_ELEMENT) { if (ZEND_OP1_TYPE(opline) == IS_VAR || ZEND_OP1_TYPE(opline) == IS_TMP_VAR) { usage[VAR_NUM(ZEND_RESULT(opline).var)] = 1; diff --git a/ext/opcache/Optimizer/compact_literals.c b/ext/opcache/Optimizer/compact_literals.c new file mode 100644 index 0000000000..b29241344c --- /dev/null +++ b/ext/opcache/Optimizer/compact_literals.c @@ -0,0 +1,481 @@ +/* pass 11 + * - compact literals table + */ +#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO + +#define DEBUG_COMPACT_LITERALS 0 + +#define LITERAL_VALUE 0x0100 +#define LITERAL_FUNC 0x0200 +#define LITERAL_CLASS 0x0300 +#define LITERAL_CONST 0x0400 +#define LITERAL_CLASS_CONST 0x0500 +#define LITERAL_STATIC_METHOD 0x0600 +#define LITERAL_STATIC_PROPERTY 0x0700 +#define LITERAL_METHOD 0x0800 +#define LITERAL_PROPERTY 0x0900 + +#define LITERAL_EX_CLASS 0x4000 +#define LITERAL_EX_OBJ 0x2000 +#define LITERAL_MAY_MERGE 0x1000 +#define LITERAL_KIND_MASK 0x0f00 +#define LITERAL_NUM_RELATED_MASK 0x000f +#define LITERAL_NUM_SLOTS_MASK 0x00f0 +#define LITERAL_NUM_SLOTS_SHIFT 4 + +#define LITERAL_NUM_RELATED(info) (info & LITERAL_NUM_RELATED_MASK) +#define LITERAL_NUM_SLOTS(info) ((info & LITERAL_NUM_SLOTS_MASK) >> LITERAL_NUM_SLOTS_SHIFT) + +typedef struct _literal_info { + zend_uint flags; /* bitmask (see defines above) */ + union { + int num; /* variable number or class name literal number */ + } u; +} literal_info; + +#define LITERAL_FLAGS(kind, slots, related) \ + ((kind) | ((slots) << LITERAL_NUM_SLOTS_SHIFT) | (related)) + +#define LITERAL_INFO(n, kind, merge, slots, related) do { \ + info[n].flags = (((merge) ? LITERAL_MAY_MERGE : 0) | LITERAL_FLAGS(kind, slots, related)); \ + } while (0) + +#define LITERAL_INFO_CLASS(n, kind, merge, slots, related, _num) do { \ + info[n].flags = (LITERAL_EX_CLASS | ((merge) ? LITERAL_MAY_MERGE : 0) | LITERAL_FLAGS(kind, slots, related)); \ + info[n].u.num = (_num); \ + } while (0) + +#define LITERAL_INFO_OBJ(n, kind, merge, slots, related, _num) do { \ + info[n].flags = (LITERAL_EX_OBJ | ((merge) ? LITERAL_MAY_MERGE : 0) | LITERAL_FLAGS(kind, slots, related)); \ + info[n].u.num = (_num); \ + } while (0) + +static void optimizer_literal_obj_info(literal_info *info, + zend_uchar op_type, + znode_op op, + int constant, + zend_uint kind, + zend_uint slots, + zend_uint related, + zend_op_array *op_array) +{ + /* For now we merge only $this object properties and methods. + * In general it's also possible to do it for any CV variable as well, + * but it would require complex dataflow and/or type analysis. + */ + if (Z_TYPE(op_array->literals[constant].constant) == IS_STRING && + op_type == IS_UNUSED) { + LITERAL_INFO_OBJ(constant, kind, 1, slots, related, op_array->this_var); + } else { + LITERAL_INFO(constant, kind, 0, slots, related); + } +} + +static void optimizer_literal_class_info(literal_info *info, + zend_uchar op_type, + znode_op op, + int constant, + zend_uint kind, + zend_uint slots, + zend_uint related, + zend_op_array *op_array) +{ + if (op_type == IS_CONST) { + LITERAL_INFO_CLASS(constant, kind, 1, slots, related, op.constant); + } else { + LITERAL_INFO(constant, kind, 0, slots, related); + } +} + +static void optimizer_compact_literals(zend_op_array *op_array TSRMLS_DC) +{ + zend_op *opline, *end; + int i, j, n, *pos, *map, cache_slots; + ulong h; + literal_info *info; + int l_null = -1; + int l_false = -1; + int l_true = -1; + HashTable hash; + char *key; + int key_len; + + if (op_array->last_literal) { + info = (literal_info*)ecalloc(op_array->last_literal, sizeof(literal_info)); + + /* Mark literals of specific types */ + opline = op_array->opcodes; + end = opline + op_array->last; + while (opline < end) { + switch (opline->opcode) { + case ZEND_DO_FCALL: + LITERAL_INFO(opline->op1.constant, LITERAL_FUNC, 1, 1, 1); + break; + case ZEND_INIT_FCALL_BY_NAME: + if (ZEND_OP2_TYPE(opline) == IS_CONST) { + LITERAL_INFO(opline->op2.constant, LITERAL_FUNC, 1, 1, 2); + } + break; + case ZEND_INIT_NS_FCALL_BY_NAME: + LITERAL_INFO(opline->op2.constant, LITERAL_FUNC, 1, 1, 3); + break; + case ZEND_INIT_METHOD_CALL: + if (ZEND_OP2_TYPE(opline) == IS_CONST) { + optimizer_literal_obj_info( + info, + opline->op1_type, + opline->op1, + opline->op2.constant, + LITERAL_METHOD, 2, 2, + op_array); + } + break; + case ZEND_INIT_STATIC_METHOD_CALL: + if (ZEND_OP1_TYPE(opline) == IS_CONST) { + LITERAL_INFO(opline->op1.constant, LITERAL_CLASS, 1, 1, 2); + } + if (ZEND_OP2_TYPE(opline) == IS_CONST) { + optimizer_literal_class_info( + info, + opline->op1_type, + opline->op1, + opline->op2.constant, + LITERAL_STATIC_METHOD, (ZEND_OP1_TYPE(opline) == IS_CONST) ? 1 : 2, 2, + op_array); + } + break; + case ZEND_CATCH: + LITERAL_INFO(opline->op1.constant, LITERAL_CLASS, 1, 1, 2); + break; + case ZEND_FETCH_CONSTANT: + if (ZEND_OP1_TYPE(opline) == IS_UNUSED) { + if ((opline->extended_value & (IS_CONSTANT_IN_NAMESPACE|IS_CONSTANT_UNQUALIFIED)) == (IS_CONSTANT_IN_NAMESPACE|IS_CONSTANT_UNQUALIFIED)) { + LITERAL_INFO(opline->op2.constant, LITERAL_CONST, 1, 1, 5); + } else { + LITERAL_INFO(opline->op2.constant, LITERAL_CONST, 1, 1, 3); + } + } else { + if (ZEND_OP1_TYPE(opline) == IS_CONST) { + LITERAL_INFO(opline->op1.constant, LITERAL_CLASS, 1, 1, 2); + } + optimizer_literal_class_info( + info, + opline->op1_type, + opline->op1, + opline->op2.constant, + LITERAL_CLASS_CONST, (ZEND_OP1_TYPE(opline) == IS_CONST) ? 1 : 2, 1, + op_array); + } + break; + case ZEND_FETCH_R: + case ZEND_FETCH_W: + case ZEND_FETCH_RW: + case ZEND_FETCH_IS: + case ZEND_FETCH_UNSET: + case ZEND_FETCH_FUNC_ARG: + case ZEND_UNSET_VAR: + case ZEND_ISSET_ISEMPTY_VAR: + if (ZEND_OP2_TYPE(opline) == IS_UNUSED) { + if (ZEND_OP1_TYPE(opline) == IS_CONST) { + LITERAL_INFO(opline->op1.constant, LITERAL_VALUE, 1, 0, 1); + } + } else { + if (ZEND_OP2_TYPE(opline) == IS_CONST) { + LITERAL_INFO(opline->op2.constant, LITERAL_CLASS, 1, 1, 2); + } + if (ZEND_OP1_TYPE(opline) == IS_CONST) { + optimizer_literal_class_info( + info, + opline->op2_type, + opline->op2, + opline->op1.constant, + LITERAL_STATIC_PROPERTY, 2, 1, + op_array); + } + } + break; + case ZEND_FETCH_CLASS: + case ZEND_ADD_INTERFACE: + case ZEND_ADD_TRAIT: + if (ZEND_OP2_TYPE(opline) == IS_CONST) { + LITERAL_INFO(opline->op2.constant, LITERAL_CLASS, 1, 1, 2); + } + break; + case ZEND_ASSIGN_OBJ: + case ZEND_FETCH_OBJ_R: + case ZEND_FETCH_OBJ_W: + case ZEND_FETCH_OBJ_RW: + case ZEND_FETCH_OBJ_IS: + case ZEND_FETCH_OBJ_UNSET: + case ZEND_FETCH_OBJ_FUNC_ARG: + case ZEND_UNSET_OBJ: + case ZEND_PRE_INC_OBJ: + case ZEND_PRE_DEC_OBJ: + case ZEND_POST_INC_OBJ: + case ZEND_POST_DEC_OBJ: + case ZEND_ISSET_ISEMPTY_PROP_OBJ: + if (ZEND_OP2_TYPE(opline) == IS_CONST) { + optimizer_literal_obj_info( + info, + opline->op1_type, + opline->op1, + opline->op2.constant, + LITERAL_PROPERTY, 2, 1, + op_array); + } + break; + case ZEND_ASSIGN_ADD: + case ZEND_ASSIGN_SUB: + case ZEND_ASSIGN_MUL: + case ZEND_ASSIGN_DIV: + case ZEND_ASSIGN_MOD: + case ZEND_ASSIGN_SL: + case ZEND_ASSIGN_SR: + case ZEND_ASSIGN_CONCAT: + case ZEND_ASSIGN_BW_OR: + case ZEND_ASSIGN_BW_AND: + case ZEND_ASSIGN_BW_XOR: + if (ZEND_OP2_TYPE(opline) == IS_CONST) { + if (opline->extended_value == ZEND_ASSIGN_OBJ) { + optimizer_literal_obj_info( + info, + opline->op1_type, + opline->op1, + opline->op2.constant, + LITERAL_PROPERTY, 2, 1, + op_array); + } else { + LITERAL_INFO(opline->op2.constant, LITERAL_VALUE, 1, 0, 1); + } + } + break; + default: + if (ZEND_OP1_TYPE(opline) == IS_CONST) { + LITERAL_INFO(opline->op1.constant, LITERAL_VALUE, 1, 0, 1); + } + if (ZEND_OP2_TYPE(opline) == IS_CONST) { + LITERAL_INFO(opline->op2.constant, LITERAL_VALUE, 1, 0, 1); + } + break; + } + opline++; + } + +#if DEBUG_COMPACT_LITERALS + { + int i, use_copy; + fprintf(stderr, "File %s func %s\n", op_array->filename, + op_array->function_name? op_array->function_name : "main"); + fprintf(stderr, "Literlas table size %d\n", op_array->last_literal); + + for (i = 0; i < op_array->last_literal; i++) { + zval zv = op_array->literals[i].constant; + zend_make_printable_zval(&op_array->literals[i].constant, &zv, &use_copy); + fprintf(stderr, "Literal %d, val (%d):%s\n", i, Z_STRLEN(zv), Z_STRVAL(zv)); + if (use_copy) { + zval_dtor(&zv); + } + } + fflush(stderr); + } +#endif + + /* Merge equal constants */ + j = 0; cache_slots = 0; + zend_hash_init(&hash, 16, NULL, NULL, 0); + map = (int*)ecalloc(op_array->last_literal, sizeof(int)); + for (i = 0; i < op_array->last_literal; i++) { + if (!info[i].flags) { + /* unsed literal */ + zval_dtor(&op_array->literals[i].constant); + continue; + } + switch (Z_TYPE(op_array->literals[i].constant)) { + case IS_NULL: + if (l_null < 0) { + l_null = j; + if (i != j) { + op_array->literals[j] = op_array->literals[i]; + info[j] = info[i]; + } + j++; + } + map[i] = l_null; + break; + case IS_BOOL: + if (Z_LVAL(op_array->literals[i].constant)) { + if (l_true < 0) { + l_true = j; + if (i != j) { + op_array->literals[j] = op_array->literals[i]; + info[j] = info[i]; + } + j++; + } + map[i] = l_true; + } else { + if (l_false < 0) { + l_false = j; + if (i != j) { + op_array->literals[j] = op_array->literals[i]; + info[j] = info[i]; + } + j++; + } + map[i] = l_false; + } + break; + case IS_LONG: + if (zend_hash_index_find(&hash, Z_LVAL(op_array->literals[i].constant), (void**)&pos) == SUCCESS) { + map[i] = *pos; + } else { + map[i] = j; + zend_hash_index_update(&hash, Z_LVAL(op_array->literals[i].constant), (void**)&j, sizeof(int), NULL); + if (i != j) { + op_array->literals[j] = op_array->literals[i]; + info[j] = info[i]; + } + j++; + } + break; + case IS_DOUBLE: + if (zend_hash_find(&hash, (char*)&Z_DVAL(op_array->literals[i].constant), sizeof(double), (void**)&pos) == SUCCESS) { + map[i] = *pos; + } else { + map[i] = j; + zend_hash_add(&hash, (char*)&Z_DVAL(op_array->literals[i].constant), sizeof(double), (void**)&j, sizeof(int), NULL); + if (i != j) { + op_array->literals[j] = op_array->literals[i]; + info[j] = info[i]; + } + j++; + } + break; + case IS_STRING: + case IS_CONSTANT: + if (info[i].flags & LITERAL_MAY_MERGE) { + if (info[i].flags & LITERAL_EX_OBJ) { + key_len = MAX_LENGTH_OF_LONG + sizeof("->") + Z_STRLEN(op_array->literals[i].constant); + key = emalloc(key_len); + key_len = snprintf(key, key_len-1, "%d->%s", info[i].u.num, Z_STRVAL(op_array->literals[i].constant)); + } else if (info[i].flags & LITERAL_EX_CLASS) { + zval *class_name = &op_array->literals[(info[i].u.num < i) ? map[info[i].u.num] : info[i].u.num].constant; + key_len = Z_STRLEN_P(class_name) + sizeof("::") + Z_STRLEN(op_array->literals[i].constant); + key = emalloc(key_len); + memcpy(key, Z_STRVAL_P(class_name), Z_STRLEN_P(class_name)); + memcpy(key + Z_STRLEN_P(class_name), "::", sizeof("::") - 1); + memcpy(key + Z_STRLEN_P(class_name) + sizeof("::") - 1, + Z_STRVAL(op_array->literals[i].constant), + Z_STRLEN(op_array->literals[i].constant) + 1); + } else { + key = Z_STRVAL(op_array->literals[i].constant); + key_len = Z_STRLEN(op_array->literals[i].constant)+1; + } + h = zend_hash_func(key, key_len); + h += info[i].flags; + } + if ((info[i].flags & LITERAL_MAY_MERGE) && + zend_hash_quick_find(&hash, key, key_len, h, (void**)&pos) == SUCCESS && + Z_TYPE(op_array->literals[i].constant) == Z_TYPE(op_array->literals[*pos].constant) && + info[i].flags == info[*pos].flags) { + + if (info[i].flags & (LITERAL_EX_OBJ|LITERAL_EX_CLASS)) { + efree(key); + } + map[i] = *pos; + zval_dtor(&op_array->literals[i].constant); + n = LITERAL_NUM_RELATED(info[i].flags); + while (n > 1) { + i++; + zval_dtor(&op_array->literals[i].constant); + n--; + } + } else { + map[i] = j; + if (info[i].flags & LITERAL_MAY_MERGE) { + zend_hash_quick_add(&hash, key, key_len, h, (void**)&j, sizeof(int), NULL); + if (info[i].flags & (LITERAL_EX_OBJ|LITERAL_EX_CLASS)) { + efree(key); + } + } + if (i != j) { + op_array->literals[j] = op_array->literals[i]; + info[j] = info[i]; + } + if (!op_array->literals[j].hash_value) { + if (IS_INTERNED(Z_STRVAL(op_array->literals[j].constant))) { + op_array->literals[j].hash_value = INTERNED_HASH(Z_STRVAL(op_array->literals[j].constant)); + } else { + op_array->literals[j].hash_value = zend_hash_func(Z_STRVAL(op_array->literals[j].constant), Z_STRLEN(op_array->literals[j].constant)+1); + } + } + if (LITERAL_NUM_SLOTS(info[i].flags)) { + op_array->literals[j].cache_slot = cache_slots; + cache_slots += LITERAL_NUM_SLOTS(info[i].flags); + } + j++; + n = LITERAL_NUM_RELATED(info[i].flags); + while (n > 1) { + i++; + if (i != j) op_array->literals[j] = op_array->literals[i]; + if (!op_array->literals[j].hash_value) { + if (IS_INTERNED(Z_STRVAL(op_array->literals[j].constant))) { + op_array->literals[j].hash_value = INTERNED_HASH(Z_STRVAL(op_array->literals[j].constant)); + } else { + op_array->literals[j].hash_value = zend_hash_func(Z_STRVAL(op_array->literals[j].constant), Z_STRLEN(op_array->literals[j].constant)+1); + } + } + j++; + n--; + } + } + break; + default: + /* don't merge other types */ + map[i] = j; + if (i != j) { + op_array->literals[j] = op_array->literals[i]; + info[j] = info[i]; + } + j++; + break; + } + } + zend_hash_destroy(&hash); + op_array->last_literal = j; + op_array->last_cache_slot = cache_slots; + + /* Update opcodes to use new literals table */ + opline = op_array->opcodes; + end = opline + op_array->last; + while (opline < end) { + if (ZEND_OP1_TYPE(opline) == IS_CONST) { + opline->op1.constant = map[opline->op1.constant]; + } + if (ZEND_OP2_TYPE(opline) == IS_CONST) { + opline->op2.constant = map[opline->op2.constant]; + } + opline++; + } + efree(map); + efree(info); + +#if DEBUG_COMPACT_LITERALS + { + int i, use_copy; + fprintf(stderr, "Optimized literlas table size %d\n", op_array->last_literal); + + for (i = 0; i < op_array->last_literal; i++) { + zval zv = op_array->literals[i].constant; + zend_make_printable_zval(&op_array->literals[i].constant, &zv, &use_copy); + fprintf(stderr, "Literal %d, val (%d):%s\n", i, Z_STRLEN(zv), Z_STRVAL(zv)); + if (use_copy) { + zval_dtor(&zv); + } + } + fflush(stderr); + } +#endif + } +} +#endif diff --git a/ext/opcache/Optimizer/optimize_func_calls.c b/ext/opcache/Optimizer/optimize_func_calls.c new file mode 100644 index 0000000000..98bfc1e99e --- /dev/null +++ b/ext/opcache/Optimizer/optimize_func_calls.c @@ -0,0 +1,138 @@ +/* pass 4 + * - optimize INIT_FCALL_BY_NAME to DO_FCALL + */ +#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO + +typedef struct _optimizer_call_info { + zend_function *func; + zend_op *opline; +} optimizer_call_info; + +static void optimize_func_calls(zend_op_array *op_array, zend_persistent_script *script TSRMLS_DC) { + zend_op *opline = op_array->opcodes; + zend_op *end = opline + op_array->last; + int call = 0; +#if ZEND_EXTENSION_API_NO > PHP_5_4_X_API_NO + optimizer_call_info *call_stack = ecalloc(op_array->nested_calls + 1, sizeof(optimizer_call_info)); +#else + int stack_size = 4; + optimizer_call_info *call_stack = ecalloc(stack_size, sizeof(optimizer_call_info)); +#endif + + while (opline < end) { + switch (opline->opcode) { + case ZEND_INIT_FCALL_BY_NAME: + case ZEND_INIT_NS_FCALL_BY_NAME: + if (ZEND_OP2_TYPE(opline) == IS_CONST) { + zend_function *func; + zval *function_name = &op_array->literals[opline->op2.constant + 1].constant; + if ((zend_hash_quick_find(&script->function_table, + Z_STRVAL_P(function_name), Z_STRLEN_P(function_name) + 1, + Z_HASH_P(function_name), (void **)&func) == SUCCESS)) { + call_stack[call].func = func; + } + } + /* break missing intentionally */ + case ZEND_NEW: + case ZEND_INIT_METHOD_CALL: + case ZEND_INIT_STATIC_METHOD_CALL: + call_stack[call].opline = opline; + call++; +#if ZEND_EXTENSION_API_NO < PHP_5_5_X_API_NO + if (call == stack_size) { + stack_size += 4; + call_stack = erealloc(call_stack, sizeof(optimizer_call_info) * stack_size); + memset(call_stack + 4, 0, 4 * sizeof(optimizer_call_info)); + } +#endif + break; + case ZEND_DO_FCALL_BY_NAME: + call--; + if (call_stack[call].func && call_stack[call].opline) { + zend_op *fcall = call_stack[call].opline; + + opline->opcode = ZEND_DO_FCALL; + ZEND_OP1_TYPE(opline) = IS_CONST; + opline->op1.constant = fcall->op2.constant + 1; + op_array->literals[fcall->op2.constant + 1].cache_slot = op_array->literals[fcall->op2.constant].cache_slot; + literal_dtor(&ZEND_OP2_LITERAL(fcall)); + if (fcall->opcode == ZEND_INIT_NS_FCALL_BY_NAME) { + literal_dtor(&op_array->literals[fcall->op2.constant + 2].constant); + } + MAKE_NOP(fcall); + } else if (opline->extended_value == 0 && + call_stack[call].opline && + call_stack[call].opline->opcode == ZEND_INIT_FCALL_BY_NAME && + ZEND_OP2_TYPE(call_stack[call].opline) == IS_CONST) { + + zend_op *fcall = call_stack[call].opline; + + opline->opcode = ZEND_DO_FCALL; + ZEND_OP1_TYPE(opline) = IS_CONST; + opline->op1.constant = fcall->op2.constant + 1; + op_array->literals[fcall->op2.constant + 1].cache_slot = op_array->literals[fcall->op2.constant].cache_slot; + literal_dtor(&ZEND_OP2_LITERAL(fcall)); + MAKE_NOP(fcall); + } + call_stack[call].func = NULL; + call_stack[call].opline = NULL; + break; + case ZEND_FETCH_FUNC_ARG: + case ZEND_FETCH_OBJ_FUNC_ARG: + case ZEND_FETCH_DIM_FUNC_ARG: + if (call_stack[call - 1].func) { + if (ARG_SHOULD_BE_SENT_BY_REF(call_stack[call - 1].func, (opline->extended_value & ZEND_FETCH_ARG_MASK))) { + opline->extended_value = 0; + opline->opcode -= 9; + } else { + opline->extended_value = 0; + opline->opcode -= 12; + } + } + break; + case ZEND_SEND_VAL: + if (opline->extended_value == ZEND_DO_FCALL_BY_NAME && call_stack[call - 1].func) { + if (ARG_MUST_BE_SENT_BY_REF(call_stack[call - 1].func, opline->op2.num)) { + /* We won't convert it into_DO_FCALL to emit error at run-time */ + call_stack[call - 1].opline = NULL; + } else { + opline->extended_value = ZEND_DO_FCALL; + } + } + break; + case ZEND_SEND_VAR: + if (opline->extended_value == ZEND_DO_FCALL_BY_NAME && call_stack[call - 1].func) { + if (ARG_SHOULD_BE_SENT_BY_REF(call_stack[call - 1].func, opline->op2.num)) { + opline->opcode = ZEND_SEND_REF; + } + opline->extended_value = ZEND_DO_FCALL; + } + break; + case ZEND_SEND_VAR_NO_REF: + if (!(opline->extended_value & ZEND_ARG_COMPILE_TIME_BOUND) && call_stack[call - 1].func) { + if (ARG_SHOULD_BE_SENT_BY_REF(call_stack[call - 1].func, opline->op2.num)) { + opline->extended_value |= ZEND_ARG_COMPILE_TIME_BOUND | ZEND_ARG_SEND_BY_REF; + } else if (opline->extended_value) { + opline->extended_value |= ZEND_ARG_COMPILE_TIME_BOUND; + } else { + opline->opcode = ZEND_SEND_VAR; + opline->extended_value = ZEND_DO_FCALL; + } + } + break; + case ZEND_SEND_REF: + if (opline->extended_value == ZEND_DO_FCALL_BY_NAME && call_stack[call - 1].func) { + /* We won't handle run-time pass by reference */ + call_stack[call - 1].opline = NULL; + } + break; + + default: + break; + } + opline++; + } + + efree(call_stack); +} +#endif diff --git a/ext/opcache/Optimizer/pass1_5.c b/ext/opcache/Optimizer/pass1_5.c index ca5b882901..f173c3f657 100644 --- a/ext/opcache/Optimizer/pass1_5.c +++ b/ext/opcache/Optimizer/pass1_5.c @@ -3,13 +3,20 @@ * - perform compile-time evaluation of constant binary and unary operations * - optimize series of ADD_STRING and/or ADD_CHAR * - convert CAST(IS_BOOL,x) into BOOL(x) - * - convert INTI_FCALL_BY_NAME, DO_FCALL_BY_NAME into DO_FCALL + * - pre-evaluate constant function calls */ +#if ZEND_EXTENSION_API_NO > PHP_5_2_X_API_NO +# define ZEND_IS_CONSTANT_TYPE(t) (((t) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT) +#else +# define ZEND_IS_CONSTANT_TYPE(t) ((t) == IS_CONSTANT) +#endif + if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) { int i = 0; zend_op *opline = op_array->opcodes; zend_op *end = opline + op_array->last; + zend_bool collect_constants = (op_array == &script->main_op_array); while (opline < end) { switch (opline->opcode) { @@ -238,31 +245,260 @@ if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) { zval c; if (!zend_get_persistent_constant(Z_STRVAL(ZEND_OP2_LITERAL(opline)), Z_STRLEN(ZEND_OP2_LITERAL(opline)), &c, 1 TSRMLS_CC)) { - break; + if (!*constants || !zend_optimizer_get_collected_constant(*constants, &ZEND_OP2_LITERAL(opline), &c)) { + break; + } } literal_dtor(&ZEND_OP2_LITERAL(opline)); MAKE_NOP(opline); replace_tmp_by_const(op_array, opline, tv, &c TSRMLS_CC); } - break; - case ZEND_INIT_FCALL_BY_NAME: - if (opline->extended_value == 0 /* not method */ && - ZEND_OP1_TYPE(opline) == IS_UNUSED && - ZEND_OP2_TYPE(opline) == IS_CONST) { - if ((opline + 1)->opcode == ZEND_DO_FCALL_BY_NAME && - (opline + 1)->extended_value == 0) { - (opline + 1)->opcode = ZEND_DO_FCALL; - COPY_NODE((opline + 1)->op1, opline->op2); - zend_str_tolower(Z_STRVAL(ZEND_OP1_LITERAL(opline + 1)), Z_STRLEN(ZEND_OP1_LITERAL(opline + 1))); #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO - Z_HASH_P(&ZEND_OP1_LITERAL(opline + 1)) = zend_hash_func(Z_STRVAL(ZEND_OP1_LITERAL(opline + 1)), Z_STRLEN(ZEND_OP1_LITERAL(opline + 1)) + 1); - op_array->literals[(opline + 1)->op1.constant].cache_slot = op_array->last_cache_slot++; + /* class constant */ + if (ZEND_OP1_TYPE(opline) != IS_UNUSED && + ZEND_OP2_TYPE(opline) == IS_CONST && + ZEND_OP2_LITERAL(opline).type == IS_STRING) { + + zend_class_entry **pce = NULL; + + if (ZEND_OP1_TYPE(opline) == IS_CONST && + ZEND_OP1_LITERAL(opline).type == IS_STRING) { + /* for A::B */ + if (op_array->scope && + !strncasecmp(Z_STRVAL(ZEND_OP1_LITERAL(opline)), + op_array->scope->name, Z_STRLEN(ZEND_OP1_LITERAL(opline)) + 1)) { + pce = &op_array->scope; + } else { + if (zend_hash_quick_find(EG(class_table), + Z_STRVAL(op_array->literals[opline->op1.constant + 1].constant), + Z_STRLEN(op_array->literals[opline->op1.constant].constant) + 1, + Z_HASH_P(&op_array->literals[opline->op1.constant + 1].constant), + (void **)&pce) == FAILURE) { + break; + } + } + } else if (op_array->scope && + ZEND_OP1_TYPE(opline) == IS_VAR && + (opline - 1)->opcode == ZEND_FETCH_CLASS && + (ZEND_OP1_TYPE(opline - 1) == IS_UNUSED && + ((opline - 1)->extended_value & ~ZEND_FETCH_CLASS_NO_AUTOLOAD) == ZEND_FETCH_CLASS_SELF) && + ZEND_RESULT((opline - 1)).var == ZEND_OP1(opline).var) { + /* for self::B */ + pce = &op_array->scope; + } + + if (pce) { + zend_uint tv = ZEND_RESULT(opline).var; + zval **c, t; + + if (zend_hash_find(&(*pce)->constants_table, + Z_STRVAL(ZEND_OP2_LITERAL(opline)), + Z_STRLEN(ZEND_OP2_LITERAL(opline)) + 1, + (void **) &c) == SUCCESS) { + if (ZEND_IS_CONSTANT_TYPE(Z_TYPE_PP(c))) { + if (!zend_get_persistent_constant(Z_STRVAL_PP(c), Z_STRLEN_PP(c), &t, 1 TSRMLS_CC) || + ZEND_IS_CONSTANT_TYPE(Z_TYPE(t))) { + break; + } + } else { + t = **c; + zval_copy_ctor(&t); + } + + if (ZEND_OP1_TYPE(opline) == IS_CONST) { + literal_dtor(&ZEND_OP1_LITERAL(opline)); + } else { + MAKE_NOP((opline - 1)); + } + literal_dtor(&ZEND_OP2_LITERAL(opline)); + MAKE_NOP(opline); + replace_tmp_by_const(op_array, opline, tv, &t TSRMLS_CC); + } + } + } #endif - MAKE_NOP(opline); + break; + + case ZEND_DO_FCALL: + /* define("name", scalar); */ + if (collect_constants && + opline->extended_value == 2 && + ZEND_OP1_TYPE(opline) == IS_CONST && + Z_TYPE(ZEND_OP1_LITERAL(opline)) == IS_STRING && + Z_STRLEN(ZEND_OP1_LITERAL(opline)) == sizeof("define")-1 && + zend_binary_strcasecmp(Z_STRVAL(ZEND_OP1_LITERAL(opline)), Z_STRLEN(ZEND_OP1_LITERAL(opline)), "define", sizeof("define")-1) == 0 && + (opline-1)->opcode == ZEND_SEND_VAL && + ZEND_OP1_TYPE(opline-1) == IS_CONST && + (Z_TYPE(ZEND_OP1_LITERAL(opline-1)) <= IS_BOOL || + Z_TYPE(ZEND_OP1_LITERAL(opline-1)) == IS_STRING) && + (opline-2)->opcode == ZEND_SEND_VAL && + ZEND_OP1_TYPE(opline-2) == IS_CONST && + Z_TYPE(ZEND_OP1_LITERAL(opline-2)) == IS_STRING) { + zend_optimizer_collect_constant(constants, &ZEND_OP1_LITERAL(opline-2), &ZEND_OP1_LITERAL(opline-1)); + break; + } else { + /* don't colllect constants after any other function call */ + collect_constants = 0; + } + + /* pre-evaluate constant functions: + defined(x) + constant(x) + function_exists(x) + is_callable(x) + extension_loaded(x) + */ + if (opline->extended_value == 1 && (opline - 1)->opcode == ZEND_SEND_VAL && + ZEND_OP1_TYPE(opline - 1) == IS_CONST && ZEND_OP1_LITERAL(opline - 1).type == IS_STRING && + ZEND_OP1_TYPE(opline) == IS_CONST && ZEND_OP1_LITERAL(opline).type == IS_STRING) { + if ((Z_STRLEN(ZEND_OP1_LITERAL(opline)) == sizeof("function_exists")-1 && + !memcmp(Z_STRVAL(ZEND_OP1_LITERAL(opline)), + "function_exists", sizeof("function_exists")-1)) || + (Z_STRLEN(ZEND_OP1_LITERAL(opline)) == sizeof("is_callable")-1 && + !memcmp(Z_STRVAL(ZEND_OP1_LITERAL(opline)), + "is_callable", sizeof("is_callable")))) { + zend_internal_function *func; + char *lc_name = zend_str_tolower_dup( + Z_STRVAL(ZEND_OP1_LITERAL(opline - 1)), Z_STRLEN(ZEND_OP1_LITERAL(opline - 1))); + + if (zend_hash_find(EG(function_table), lc_name, Z_STRLEN(ZEND_OP1_LITERAL(opline - 1)) + 1, + (void *)&func) == SUCCESS && + func->type == ZEND_INTERNAL_FUNCTION && + func->module->type == MODULE_PERSISTENT) { + zval t; + ZVAL_BOOL(&t, 1); + if (replace_var_by_const(op_array, opline + 1, ZEND_RESULT(opline).var, &t TSRMLS_CC)) { + literal_dtor(&ZEND_OP1_LITERAL(opline - 1)); + MAKE_NOP((opline - 1)); + literal_dtor(&ZEND_OP1_LITERAL(opline)); + MAKE_NOP(opline); + } + } + efree(lc_name); + } else if (Z_STRLEN(ZEND_OP1_LITERAL(opline)) == sizeof("extension_loaded")-1 && + !memcmp(Z_STRVAL(ZEND_OP1_LITERAL(opline)), + "extension_loaded", sizeof("extension_loaded")-1)) { + zval t; + zend_module_entry *m; + char *lc_name = zend_str_tolower_dup( + Z_STRVAL(ZEND_OP1_LITERAL(opline - 1)), Z_STRLEN(ZEND_OP1_LITERAL(opline - 1))); + + if (zend_hash_find(&module_registry, + lc_name, Z_STRLEN(ZEND_OP1_LITERAL(opline - 1)) + 1, (void *)&m) == FAILURE) { + if (!PG(enable_dl)) { + break; + } else { + ZVAL_BOOL(&t, 0); + } + } else { + if (m->type == MODULE_PERSISTENT) { + ZVAL_BOOL(&t, 1); + } else { + break; + } + } + + if (replace_var_by_const(op_array, opline + 1, ZEND_RESULT(opline).var, &t TSRMLS_CC)) { + literal_dtor(&ZEND_OP1_LITERAL(opline - 1)); + MAKE_NOP((opline - 1)); + literal_dtor(&ZEND_OP1_LITERAL(opline)); + MAKE_NOP(opline); + } + efree(lc_name); + } else if (Z_STRLEN(ZEND_OP1_LITERAL(opline)) == sizeof("defined")-1 && + !memcmp(Z_STRVAL(ZEND_OP1_LITERAL(opline)), + "defined", sizeof("defined")-1)) { + zval t; + + if (zend_get_persistent_constant(Z_STRVAL(ZEND_OP1_LITERAL(opline - 1)), + Z_STRLEN(ZEND_OP1_LITERAL(opline - 1)), &t, 0 TSRMLS_CC)) { + + ZVAL_BOOL(&t, 1); + if (replace_var_by_const(op_array, opline + 1, ZEND_RESULT(opline).var, &t TSRMLS_CC)) { + literal_dtor(&ZEND_OP1_LITERAL(opline - 1)); + MAKE_NOP((opline - 1)); + literal_dtor(&ZEND_OP1_LITERAL(opline)); + MAKE_NOP(opline); + } + } + } else if (Z_STRLEN(ZEND_OP1_LITERAL(opline)) == sizeof("constant")-1 && + !memcmp(Z_STRVAL(ZEND_OP1_LITERAL(opline)), + "constant", sizeof("constant")-1)) { + zval t; + + if (zend_get_persistent_constant(Z_STRVAL(ZEND_OP1_LITERAL(opline - 1)), + Z_STRLEN(ZEND_OP1_LITERAL(opline - 1)), &t, 0 TSRMLS_CC)) { + if (replace_var_by_const(op_array, opline + 1, ZEND_RESULT(opline).var, &t TSRMLS_CC)) { + literal_dtor(&ZEND_OP1_LITERAL(opline - 1)); + MAKE_NOP((opline - 1)); + literal_dtor(&ZEND_OP1_LITERAL(opline)); + MAKE_NOP(opline); + } + } + } else if (Z_STRLEN(ZEND_OP1_LITERAL(opline)) == sizeof("strlen")-1 && + !memcmp(Z_STRVAL(ZEND_OP1_LITERAL(opline)), + "strlen", sizeof("strlen")-1)) { + zval t; + + ZVAL_LONG(&t, Z_STRLEN(ZEND_OP1_LITERAL(opline - 1))); + if (replace_var_by_const(op_array, opline + 1, ZEND_RESULT(opline).var, &t TSRMLS_CC)) { + literal_dtor(&ZEND_OP1_LITERAL(opline - 1)); + MAKE_NOP((opline - 1)); + literal_dtor(&ZEND_OP1_LITERAL(opline)); + MAKE_NOP(opline); + } } + } + break; +#if ZEND_EXTENSION_API_NO > PHP_5_2_X_API_NO + case ZEND_DECLARE_CONST: + if (collect_constants && + Z_TYPE(ZEND_OP1_LITERAL(opline)) == IS_STRING && + (Z_TYPE(ZEND_OP2_LITERAL(opline)) <= IS_BOOL || + Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_STRING)) { + zend_optimizer_collect_constant(constants, &ZEND_OP1_LITERAL(opline), &ZEND_OP2_LITERAL(opline)); } break; +#endif + + case ZEND_RETURN: +#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO + case ZEND_RETURN_BY_REF: +#endif +#if ZEND_EXTENSION_API_NO > PHP_5_4_X_API_NO + case ZEND_GENERATOR_RETURN: +#endif + case ZEND_EXIT: + case ZEND_THROW: + case ZEND_CATCH: + case ZEND_BRK: + case ZEND_CONT: +#if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO + case ZEND_GOTO: +#endif +#if ZEND_EXTENSION_API_NO > PHP_5_4_X_API_NO + case ZEND_FAST_CALL: + case ZEND_FAST_RET: +#endif + case ZEND_JMP: + case ZEND_JMPZNZ: + case ZEND_JMPZ: + case ZEND_JMPNZ: + case ZEND_JMPZ_EX: + case ZEND_JMPNZ_EX: + case ZEND_FE_RESET: + case ZEND_FE_FETCH: + case ZEND_NEW: + case ZEND_DO_FCALL_BY_NAME: +#if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO + case ZEND_JMP_SET: +#endif +#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO + case ZEND_JMP_SET_VAR: +#endif + collect_constants = 0; + break; #if ZEND_EXTENSION_API_NO >= PHP_5_5_X_API_NO case ZEND_FETCH_R: diff --git a/ext/opcache/Optimizer/zend_optimizer.c b/ext/opcache/Optimizer/zend_optimizer.c index c932530128..0426f63514 100644 --- a/ext/opcache/Optimizer/zend_optimizer.c +++ b/ext/opcache/Optimizer/zend_optimizer.c @@ -25,10 +25,41 @@ #include "zend_API.h"
#include "zend_constants.h"
#include "zend_execute.h"
+#include "zend_vm.h"
#define OPTIMIZATION_LEVEL \
ZCG(accel_directives).optimization_level
+static void zend_optimizer_zval_dtor_wrapper(zval *zvalue)
+{
+ zval_dtor(zvalue);
+}
+
+static void zend_optimizer_collect_constant(HashTable **constants, zval *name, zval* value)
+{
+ zval val;
+
+ if (!*constants) {
+ *constants = emalloc(sizeof(HashTable));
+ zend_hash_init(*constants, 16, NULL, (void (*)(void *))zend_optimizer_zval_dtor_wrapper, 0);
+ }
+ val = *value;
+ zval_copy_ctor(&val);
+ zend_hash_add(*constants, Z_STRVAL_P(name), Z_STRLEN_P(name)+1, (void**)&val, sizeof(zval), NULL);
+}
+
+static int zend_optimizer_get_collected_constant(HashTable *constants, zval *name, zval* value)
+{
+ zval *val;
+
+ if (zend_hash_find(constants, Z_STRVAL_P(name), Z_STRLEN_P(name)+1, (void**)&val) == SUCCESS) {
+ *value = *val;
+ zval_copy_ctor(value);
+ return 1;
+ }
+ return 0;
+}
+
#if ZEND_EXTENSION_API_NO >= PHP_5_5_X_API_NO
static int zend_optimizer_lookup_cv(zend_op_array *op_array, char* name, int name_len)
{
@@ -63,10 +94,7 @@ int zend_optimizer_add_literal(zend_op_array *op_array, const zval *zv TSRMLS_DC {
int i = op_array->last_literal;
op_array->last_literal++;
- if (i >= CG(context).literals_size) {
- CG(context).literals_size += 16; /* FIXME */
- op_array->literals = (zend_literal*)erealloc(op_array->literals, CG(context).literals_size * sizeof(zend_literal));
- }
+ op_array->literals = (zend_literal*)erealloc(op_array->literals, op_array->last_literal * sizeof(zend_literal));
op_array->literals[i].constant = *zv;
op_array->literals[i].hash_value = 0;
op_array->literals[i].cache_slot = -1;
@@ -272,6 +300,61 @@ check_numeric: #endif
}
+static int replace_var_by_const(zend_op_array *op_array,
+ zend_op *opline,
+ zend_uint var,
+ zval *val TSRMLS_DC)
+{
+ zend_op *end = op_array->opcodes + op_array->last;
+
+ while (opline < end) {
+ if (ZEND_OP1_TYPE(opline) == IS_VAR &&
+ ZEND_OP1(opline).var == var) {
+ switch (opline->opcode) {
+ case ZEND_FETCH_DIM_W:
+ case ZEND_FETCH_DIM_RW:
+ case ZEND_FETCH_DIM_FUNC_ARG:
+ case ZEND_FETCH_DIM_UNSET:
+ case ZEND_ASSIGN_DIM:
+#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
+ case ZEND_SEPARATE:
+#endif
+ return 0;
+ case ZEND_SEND_VAR_NO_REF:
+ if (opline->extended_value & ZEND_ARG_COMPILE_TIME_BOUND) {
+ if (opline->extended_value & ZEND_ARG_SEND_BY_REF) {
+ return 0;
+ }
+ opline->extended_value = ZEND_DO_FCALL;
+ } else {
+ opline->extended_value = ZEND_DO_FCALL_BY_NAME;
+ }
+ opline->opcode = ZEND_SEND_VAL;
+ break;
+ default:
+ break;
+ }
+ update_op1_const(op_array, opline, val TSRMLS_CC);
+ break;
+ }
+
+ if (ZEND_OP2_TYPE(opline) == IS_VAR &&
+ ZEND_OP2(opline).var == var) {
+ switch (opline->opcode) {
+ case ZEND_ASSIGN_REF:
+ return 0;
+ default:
+ break;
+ }
+ update_op2_const(op_array, opline, val TSRMLS_CC);
+ break;
+ }
+ opline++;
+ }
+
+ return 1;
+}
+
static void replace_tmp_by_const(zend_op_array *op_array,
zend_op *opline,
zend_uint var,
@@ -303,8 +386,12 @@ static void replace_tmp_by_const(zend_op_array *op_array, #include "Optimizer/nop_removal.c"
#include "Optimizer/block_pass.c"
#include "Optimizer/optimize_temp_vars_5.c"
+#include "Optimizer/compact_literals.c"
+#include "Optimizer/optimize_func_calls.c"
-void zend_optimizer(zend_op_array *op_array TSRMLS_DC)
+static void zend_optimize(zend_op_array *op_array,
+ zend_persistent_script *script,
+ HashTable **constants TSRMLS_DC)
{
if (op_array->type == ZEND_EVAL_CODE ||
(op_array->fn_flags & ZEND_ACC_INTERACTIVE)) {
@@ -316,7 +403,6 @@ void zend_optimizer(zend_op_array *op_array TSRMLS_DC) * - perform compile-time evaluation of constant binary and unary operations
* - optimize series of ADD_STRING and/or ADD_CHAR
* - convert CAST(IS_BOOL,x) into BOOL(x)
- * - convert INTI_FCALL_BY_NAME + DO_FCALL_BY_NAME into DO_FCALL
*/
#include "Optimizer/pass1_5.c"
@@ -324,6 +410,7 @@ void zend_optimizer(zend_op_array *op_array TSRMLS_DC) * - convert non-numeric constants to numeric constants in numeric operators
* - optimize constant conditional JMPs
* - optimize static BRKs and CONTs
+ * - pre-evaluate constant function calls
*/
#include "Optimizer/pass2.c"
@@ -334,12 +421,21 @@ void zend_optimizer(zend_op_array *op_array TSRMLS_DC) */
#include "Optimizer/pass3.c"
+#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
+ /* pass 4:
+ * - INIT_FCALL_BY_NAME -> DO_FCALL
+ */
+ if (ZEND_OPTIMIZER_PASS_4 & OPTIMIZATION_LEVEL) {
+ optimize_func_calls(op_array, script TSRMLS_CC);
+ }
+#endif
+
/* pass 5:
* - CFG optimization
*/
#include "Optimizer/pass5.c"
- /* pass 9:
+ /* pass 9:
* - Optimize temp variables usage
*/
#include "Optimizer/pass9.c"
@@ -348,4 +444,143 @@ void zend_optimizer(zend_op_array *op_array TSRMLS_DC) * - remove NOPs
*/
#include "Optimizer/pass10.c"
+
+#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
+ /* pass 11:
+ * - Compact literals table
+ */
+ if (ZEND_OPTIMIZER_PASS_11 & OPTIMIZATION_LEVEL) {
+ optimizer_compact_literals(op_array TSRMLS_CC);
+ }
+#endif
+}
+
+static void zend_accel_optimize(zend_op_array *op_array,
+ zend_persistent_script *script,
+ HashTable **constants TSRMLS_DC)
+{
+ zend_op *opline, *end;
+
+ /* Revert pass_two() */
+ opline = op_array->opcodes;
+ end = opline + op_array->last;
+ while (opline < end) {
+#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
+ if (opline->op1_type == IS_CONST) {
+ opline->op1.constant = opline->op1.literal - op_array->literals;
+ }
+ if (opline->op2_type == IS_CONST) {
+ opline->op2.constant = opline->op2.literal - op_array->literals;
+ }
+#endif
+ switch (opline->opcode) {
+ case ZEND_JMP:
+#if ZEND_EXTENSION_API_NO > PHP_5_2_X_API_NO
+ case ZEND_GOTO:
+#endif
+#if ZEND_EXTENSION_API_NO > PHP_5_4_X_API_NO
+ case ZEND_FAST_CALL:
+#endif
+ ZEND_OP1(opline).opline_num = ZEND_OP1(opline).jmp_addr - op_array->opcodes;
+ break;
+ case ZEND_JMPZ:
+ case ZEND_JMPNZ:
+ case ZEND_JMPZ_EX:
+ case ZEND_JMPNZ_EX:
+#if ZEND_EXTENSION_API_NO > PHP_5_2_X_API_NO
+ case ZEND_JMP_SET:
+#endif
+#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
+ case ZEND_JMP_SET_VAR:
+#endif
+ ZEND_OP2(opline).opline_num = ZEND_OP2(opline).jmp_addr - op_array->opcodes;
+ break;
+ }
+ opline++;
+ }
+
+ /* Do actual optimizations */
+ zend_optimize(op_array, script, constants TSRMLS_CC);
+
+ /* Redo pass_two() */
+ opline = op_array->opcodes;
+ end = opline + op_array->last;
+ while (opline < end) {
+#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
+ if (opline->op1_type == IS_CONST) {
+ opline->op1.zv = &op_array->literals[opline->op1.constant].constant;
+ }
+ if (opline->op2_type == IS_CONST) {
+ opline->op2.zv = &op_array->literals[opline->op2.constant].constant;
+ }
+#endif
+ switch (opline->opcode) {
+ case ZEND_JMP:
+#if ZEND_EXTENSION_API_NO > PHP_5_2_X_API_NO
+ case ZEND_GOTO:
+#endif
+#if ZEND_EXTENSION_API_NO > PHP_5_4_X_API_NO
+ case ZEND_FAST_CALL:
+#endif
+ ZEND_OP1(opline).jmp_addr = &op_array->opcodes[ZEND_OP1(opline).opline_num];
+ break;
+ case ZEND_JMPZ:
+ case ZEND_JMPNZ:
+ case ZEND_JMPZ_EX:
+ case ZEND_JMPNZ_EX:
+#if ZEND_EXTENSION_API_NO > PHP_5_2_X_API_NO
+ case ZEND_JMP_SET:
+#endif
+#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
+ case ZEND_JMP_SET_VAR:
+#endif
+ ZEND_OP2(opline).jmp_addr = &op_array->opcodes[ZEND_OP2(opline).opline_num];
+ break;
+ }
+ ZEND_VM_SET_OPCODE_HANDLER(opline);
+ opline++;
+ }
+}
+
+int zend_accel_script_optimize(zend_persistent_script *script TSRMLS_DC)
+{
+ Bucket *p, *q;
+ HashTable *constants = NULL;
+
+ zend_accel_optimize(&script->main_op_array, script, &constants TSRMLS_CC);
+
+ p = script->function_table.pListHead;
+ while (p) {
+ zend_op_array *op_array = (zend_op_array*)p->pData;
+ zend_accel_optimize(op_array, script, &constants TSRMLS_CC);
+ p = p->pListNext;
+ }
+
+ p = script->class_table.pListHead;
+ while (p) {
+ zend_class_entry *ce = (zend_class_entry*)p->pDataPtr;
+ q = ce->function_table.pListHead;
+ while (q) {
+ zend_op_array *op_array = (zend_op_array*)q->pData;
+ if (op_array->scope == ce) {
+ zend_accel_optimize(op_array, script, &constants TSRMLS_CC);
+ } else if (op_array->type == ZEND_USER_FUNCTION) {
+ zend_op_array *orig_op_array;
+ if (zend_hash_find(&op_array->scope->function_table, q->arKey, q->nKeyLength, (void**)&orig_op_array) == SUCCESS) {
+ HashTable *ht = op_array->static_variables;
+ *op_array = *orig_op_array;
+ op_array->static_variables = ht;
+ }
+ }
+ q = q->pListNext;
+ }
+ p = p->pListNext;
+ }
+
+ if (constants) {
+ zend_hash_destroy(constants);
+ efree(constants);
+ }
+
+ return 1;
}
diff --git a/ext/opcache/Optimizer/zend_optimizer.h b/ext/opcache/Optimizer/zend_optimizer.h index 98275a20aa..5a3d715ac9 100644 --- a/ext/opcache/Optimizer/zend_optimizer.h +++ b/ext/opcache/Optimizer/zend_optimizer.h @@ -28,14 +28,14 @@ #define ZEND_OPTIMIZER_PASS_1 (1<<0) /* CSE, STRING construction */
#define ZEND_OPTIMIZER_PASS_2 (1<<1) /* Constant conversion and jumps */
#define ZEND_OPTIMIZER_PASS_3 (1<<2) /* ++, +=, series of jumps */
-#define ZEND_OPTIMIZER_PASS_4 (1<<3)
+#define ZEND_OPTIMIZER_PASS_4 (1<<3) /* INIT_FCALL_BY_NAME -> DO_FCALL */
#define ZEND_OPTIMIZER_PASS_5 (1<<4) /* CFG based optimization */
#define ZEND_OPTIMIZER_PASS_6 (1<<5)
#define ZEND_OPTIMIZER_PASS_7 (1<<6)
#define ZEND_OPTIMIZER_PASS_8 (1<<7)
#define ZEND_OPTIMIZER_PASS_9 (1<<8) /* TMP VAR usage */
#define ZEND_OPTIMIZER_PASS_10 (1<<9) /* NOP removal */
-#define ZEND_OPTIMIZER_PASS_11 (1<<10)
+#define ZEND_OPTIMIZER_PASS_11 (1<<10) /* Merge equal constants */
#define ZEND_OPTIMIZER_PASS_12 (1<<11)
#define ZEND_OPTIMIZER_PASS_13 (1<<12)
#define ZEND_OPTIMIZER_PASS_14 (1<<13)
@@ -44,6 +44,4 @@ #define DEFAULT_OPTIMIZATION_LEVEL "0xFFFFFFFF"
-void zend_optimizer(zend_op_array *op_array TSRMLS_DC);
-
#endif
diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c index c0edf7e477..9398b58ac6 100644 --- a/ext/opcache/ZendAccelerator.c +++ b/ext/opcache/ZendAccelerator.c @@ -36,7 +36,7 @@ #include "main/php_open_temporary_file.h" #include "zend_API.h" #include "zend_ini.h" -#include "TSRM/tsrm_virtual_cwd.h" +#include "zend_virtual_cwd.h" #include "zend_accelerator_util_funcs.h" #include "zend_accelerator_hash.h" @@ -1130,6 +1130,10 @@ static zend_persistent_script *cache_script_in_shared_memory(zend_persistent_scr return new_persistent_script; } + if (!zend_accel_script_optimize(new_persistent_script TSRMLS_CC)) { + return new_persistent_script; + } + if (!compact_persistent_script(new_persistent_script)) { return new_persistent_script; } @@ -2784,19 +2788,6 @@ void accelerator_shm_read_unlock(TSRMLS_D) } } -static void accel_op_array_handler(zend_op_array *op_array) -{ - TSRMLS_FETCH(); - - if (ZCG(enabled) && - accel_startup_ok && - ZCSG(accelerator_enabled) && - !ZSMMG(memory_exhausted) && - !ZCSG(restart_pending)) { - zend_optimizer(op_array TSRMLS_CC); - } -} - ZEND_EXT_API zend_extension zend_extension_entry = { ACCELERATOR_PRODUCT_NAME, /* name */ ACCELERATOR_VERSION, /* version */ @@ -2808,7 +2799,7 @@ ZEND_EXT_API zend_extension zend_extension_entry = { accel_activate, /* per-script activation */ accel_deactivate, /* per-script deactivation */ NULL, /* message handler */ - accel_op_array_handler, /* op_array handler */ + NULL, /* op_array handler */ NULL, /* extended statement handler */ NULL, /* extended fcall begin handler */ NULL, /* extended fcall end handler */ diff --git a/ext/opcache/ZendAccelerator.h b/ext/opcache/ZendAccelerator.h index cbc50d2b71..487010ba27 100644 --- a/ext/opcache/ZendAccelerator.h +++ b/ext/opcache/ZendAccelerator.h @@ -331,6 +331,7 @@ void accel_shutdown(TSRMLS_D); void zend_accel_schedule_restart(zend_accel_restart_reason reason TSRMLS_DC); void zend_accel_schedule_restart_if_necessary(zend_accel_restart_reason reason TSRMLS_DC); int zend_accel_invalidate(const char *filename, int filename_len, zend_bool force TSRMLS_DC); +int zend_accel_script_optimize(zend_persistent_script *persistent_script TSRMLS_DC); int accelerator_shm_read_lock(TSRMLS_D); void accelerator_shm_read_unlock(TSRMLS_D); diff --git a/ext/opcache/tests/bug66251.phpt b/ext/opcache/tests/bug66251.phpt new file mode 100644 index 0000000000..23a5165234 --- /dev/null +++ b/ext/opcache/tests/bug66251.phpt @@ -0,0 +1,17 @@ +--TEST-- +Bug #66251 (Constants get statically bound at compile time when Optimized) +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.optimization_level=-1 +--SKIPIF-- +<?php if (!extension_loaded('Zend OPcache') || php_sapi_name() != "cli") die("skip CLI only"); ?> +--FILE-- +<?php +printf ("A=%s\n", getA()); +const A="hello"; +function getA() {return A;} +?> +--EXPECTF-- +Notice: Use of undefined constant A - assumed 'A' in %sbug66251.php on line 4 +A=A diff --git a/ext/opcache/tests/compact_literals.phpt b/ext/opcache/tests/compact_literals.phpt new file mode 100644 index 0000000000..367331f742 --- /dev/null +++ b/ext/opcache/tests/compact_literals.phpt @@ -0,0 +1,215 @@ +--TEST-- +Test with compact literals +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.optimization_level=-1 +--SKIPIF-- +<?php require_once('skipif.inc'); ?> +--FILE-- +<?php + +echo "array key hash" . ":" . PHP_EOL; +$array = array( + "1" => "one", + "2" => "two", + "one" => 1, + "two" => 2, +); + +unset($array["one"]); +unset($array["2"]); + +print_r($array); + +echo "function define" . ":" . PHP_EOL; +if (!function_exists("dummy")) { + function dummy() { + var_dump(__FUNCTION__); + } +} + +dummy(); + +$dummy = function () { var_dump("lambda" . "dummy"); }; +$dummy(); + +if (!class_exists("A")) { + class A { + public static $name = "A"; + public static function say($n = "name") { + var_dump(static::$name); + } + } +} + +class B extends A { + public static $name = "B"; +} + +if (!class_exists("C")) { + class C extends B { + public static $name = "C"; + } +} + +A::say(); +B::Say(); +A::say(); +B::say(); +C::say(); + +function get_eol_define() { + define("MY_EOL", PHP_EOL); +} +get_eol_define(); +define("EOL", MY_EOL); + +echo "constants define" . ":" . EOL; + +echo "define " . "TEST" . EOL; +define("TEST", "TEST"); + +class E { + public static $E="EP"; + const E="E"; + const TEST="NULL"; +} + +class F { + const F="F"; + public static $E="FEP"; + const E="FE"; + const TEST="FALSE"; + public static $F = "FP"; +} + +var_dump(TEST); //"TEST" +var_dump(E::E); //"E" +var_dump(F::E); //"FE" +var_dump(F::F); //"F" +var_dump(E::TEST); //"NULL" +var_dump(F::TEST); //"FALSE" +var_dump(E::$E); //"EP" +var_dumP(F::$F); //"FP" +var_dumP(F::$E); //"FEP" + +echo "propertes and methods" . EOL; + +class CH { + const H = "H"; + public function h() { + var_dump(self::H); + } +} + +class CI { + const H = "I"; + public function h() { + var_dump(self::H); + } +} + +function change(&$obj) { + $obj = new CH; +} + +function geti() { + return new CI; +} + +$h = new CH; + +echo "-->H" . PHP_EOL; +$h->H(); +var_dump($h::H); +var_dump(CH::H); + +$h->H(); +var_dump($h::H); +var_dump(CH::H); + +echo "-->I" . PHP_EOL; +$h = new CI; +$h->H(); +var_dump($h::H); +var_dump(CI::H); +$h->H(); +var_dump($h::H); +var_dump(CI::H); + +echo "-->H" . PHP_EOL; +change($h); + +$h->H(); +var_dump($h::H); +var_dump(CH::H); + +$h->H(); +var_dump($h::H); +var_dump(CH::H); + +echo "-->I" . PHP_EOL; +$h = geti(); +$h->H(); +var_dump($h::H); +var_dump(CI::H); +$h->H(); +var_dump($h::H); +var_dump(CI::H); +?> +--EXPECT-- +array key hash: +Array +( + [1] => one + [two] => 2 +) +function define: +string(5) "dummy" +string(11) "lambdadummy" +string(1) "A" +string(1) "B" +string(1) "A" +string(1) "B" +string(1) "C" +constants define: +define TEST +string(4) "TEST" +string(1) "E" +string(2) "FE" +string(1) "F" +string(4) "NULL" +string(5) "FALSE" +string(2) "EP" +string(2) "FP" +string(3) "FEP" +propertes and methods +-->H +string(1) "H" +string(1) "H" +string(1) "H" +string(1) "H" +string(1) "H" +string(1) "H" +-->I +string(1) "I" +string(1) "I" +string(1) "I" +string(1) "I" +string(1) "I" +string(1) "I" +-->H +string(1) "H" +string(1) "H" +string(1) "H" +string(1) "H" +string(1) "H" +string(1) "H" +-->I +string(1) "I" +string(1) "I" +string(1) "I" +string(1) "I" +string(1) "I" +string(1) "I" diff --git a/ext/opcache/tests/optimize_func_calls.phpt b/ext/opcache/tests/optimize_func_calls.phpt new file mode 100644 index 0000000000..b3bc8da6a9 --- /dev/null +++ b/ext/opcache/tests/optimize_func_calls.phpt @@ -0,0 +1,130 @@ +--TEST-- +Test with optimization of function calls +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.optimization_level=-1 +--SKIPIF-- +<?php require_once('skipif.inc'); ?> +--FILE-- +<?php + +class A { + public $obj; + public function test($a) { + } +} + +function a(&$b) { + $b = "changed"; + return "done"; +} + +$a = "a"; +$b = "b"; +$c = "c"; +$f = "a"; + +/* + * INIT_FCALL_BY_NAME + * SEND_VAR + * DO_FCALL + * DO_FCALL_BY_NAME + */ +foo(a($a)); +var_dump($a); +$a = "a"; + +/* + * INIT_FCALL_BY_NAME + * INIT_FCALL_BY_NAME -- un-optimizable + * DO_FCALL_BY_NAME -- un-optimizable + * DO_FCALL_BY_NAME + */ +foo($f($a)); +var_dump($a); + +/* + * INIT_FCALL_BY_NAME + * ZEND_NEW + * DO_FCALL_BY_NAME + * DO_FCALL_BY_NAME + */ +foo(new A()); + +/* + * INIT_FCALL_BY_NAME + * FETCH_OBJ_FUNC_ARG + * ZEND_SEND_VAR + * DO_FCALL_BY_NAME + */ +foo((new A)->obj); +$obj = new A; +ref($obj->obj); +var_dump($obj->obj); + +ref(retarray()[0]); + +$a = "a"; +foo(a($a), $a, ref($b, $c), $obj); +var_dump($a); +var_dump($b); + +/* + * INIT_FCALL_BY_NAME + * SEND_VAL + * DO_FCALL_BY_NAME + */ +ref("xxx"); + +function retarray() { + return array("retarray"); +} + +function foo($a) { + print_r(func_get_args()); +} + +function ref(&$b) { + $b = "changed"; + return "ref"; +} +--EXPECTF-- +Array +( + [0] => done +) +string(7) "changed" +Array +( + [0] => done +) +string(7) "changed" +Array +( + [0] => A Object + ( + [obj] => + ) + +) +Array +( + [0] => +) +string(7) "changed" +Array +( + [0] => done + [1] => changed + [2] => ref + [3] => A Object + ( + [obj] => changed + ) + +) +string(7) "changed" +string(7) "changed" + +Fatal error: Cannot pass parameter 1 by reference in %soptimize_func_calls.php on line %d diff --git a/ext/opcache/zend_accelerator_module.c b/ext/opcache/zend_accelerator_module.c index c3df1a68f7..cd840fd7dd 100644 --- a/ext/opcache/zend_accelerator_module.c +++ b/ext/opcache/zend_accelerator_module.c @@ -28,7 +28,7 @@ #include "zend_accelerator_blacklist.h" #include "php_ini.h" #include "SAPI.h" -#include "TSRM/tsrm_virtual_cwd.h" +#include "zend_virtual_cwd.h" #include "ext/standard/info.h" #include "ext/standard/php_filestat.h" diff --git a/ext/opcache/zend_accelerator_util_funcs.c b/ext/opcache/zend_accelerator_util_funcs.c index 85d5a05fa2..e9582324c4 100644 --- a/ext/opcache/zend_accelerator_util_funcs.c +++ b/ext/opcache/zend_accelerator_util_funcs.c @@ -222,6 +222,52 @@ static void zend_destroy_property_info(zend_property_info *property_info) } } +#if ZEND_EXTENSION_API_NO > PHP_5_5_X_API_NO +static zend_ast *zend_ast_clone(zend_ast *ast TSRMLS_DC) +{ + int i; + zend_ast *node; + + if (ast->kind == ZEND_CONST) { + node = emalloc(sizeof(zend_ast) + sizeof(zval)); + node->kind = ZEND_CONST; + node->children = 0; + node->u.val = (zval*)(node + 1); + *node->u.val = *ast->u.val; + if ((Z_TYPE_P(ast->u.val) & IS_CONSTANT_TYPE_MASK) >= IS_ARRAY) { + switch ((Z_TYPE_P(ast->u.val) & IS_CONSTANT_TYPE_MASK)) { + case IS_STRING: + case IS_CONSTANT: + Z_STRVAL_P(node->u.val) = (char *) interned_estrndup(Z_STRVAL_P(ast->u.val), Z_STRLEN_P(ast->u.val)); + break; + case IS_ARRAY: + case IS_CONSTANT_ARRAY: + if (ast->u.val->value.ht && ast->u.val->value.ht != &EG(symbol_table)) { + ALLOC_HASHTABLE(node->u.val->value.ht); + zend_hash_clone_zval(node->u.val->value.ht, ast->u.val->value.ht, 0); + } + break; + case IS_CONSTANT_AST: + Z_AST_P(node->u.val) = zend_ast_clone(Z_AST_P(ast->u.val) TSRMLS_CC); + break; + } + } + } else { + node = emalloc(sizeof(zend_ast) + sizeof(zend_ast*) * (ast->children - 1)); + node->kind = ast->kind; + node->children = ast->children; + for (i = 0; i < ast->children; i++) { + if ((&ast->u.child)[i]) { + (&node->u.child)[i] = zend_ast_clone((&ast->u.child)[i] TSRMLS_CC); + } else { + (&node->u.child)[i] = NULL; + } + } + } + return node; +} +#endif + static inline zval* zend_clone_zval(zval *src, int bind TSRMLS_DC) { zval *ret, **ret_ptr = NULL; @@ -259,6 +305,11 @@ static inline zval* zend_clone_zval(zval *src, int bind TSRMLS_DC) zend_hash_clone_zval(ret->value.ht, src->value.ht, 0); } break; +#if ZEND_EXTENSION_API_NO > PHP_5_5_X_API_NO + case IS_CONSTANT_AST: + Z_AST_P(ret) = zend_ast_clone(Z_AST_P(ret) TSRMLS_CC); + break; +#endif } } return ret; @@ -376,6 +427,11 @@ static void zend_hash_clone_zval(HashTable *ht, HashTable *source, int bind) zend_hash_clone_zval(ppz->value.ht, ((zval*)p->pDataPtr)->value.ht, 0); } break; +#if ZEND_EXTENSION_API_NO > PHP_5_5_X_API_NO + case IS_CONSTANT_AST: + Z_AST_P(ppz) = zend_ast_clone(Z_AST_P(ppz) TSRMLS_CC); + break; +#endif } } diff --git a/ext/opcache/zend_persist.c b/ext/opcache/zend_persist.c index 9f1940e061..17147ac34f 100644 --- a/ext/opcache/zend_persist.c +++ b/ext/opcache/zend_persist.c @@ -51,6 +51,7 @@ typedef void (*zend_persist_func_t)(void * TSRMLS_DC); static void zend_persist_zval_ptr(zval **zp TSRMLS_DC); +static void zend_persist_zval(zval *z TSRMLS_DC); #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO static const Bucket *uninitialized_bucket = NULL; @@ -138,6 +139,29 @@ static void zend_hash_persist(HashTable *ht, void (*pPersistElement)(void *pElem #endif } +#if ZEND_EXTENSION_API_NO > PHP_5_5_X_API_NO +static zend_ast *zend_persist_ast(zend_ast *ast TSRMLS_DC) +{ + int i; + zend_ast *node; + + if (ast->kind == ZEND_CONST) { + node = zend_accel_memdup(ast, sizeof(zend_ast) + sizeof(zval)); + node->u.val = (zval*)(node + 1); + zend_persist_zval(node->u.val TSRMLS_CC); + } else { + node = zend_accel_memdup(ast, sizeof(zend_ast) + sizeof(zend_ast*) * (ast->children - 1)); + for (i = 0; i < ast->children; i++) { + if ((&node->u.child)[i]) { + (&node->u.child)[i] = zend_persist_ast((&node->u.child)[i] TSRMLS_CC); + } + } + } + efree(ast); + return node; +} +#endif + static void zend_persist_zval(zval *z TSRMLS_DC) { #if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO @@ -154,6 +178,11 @@ static void zend_persist_zval(zval *z TSRMLS_DC) zend_accel_store(z->value.ht, sizeof(HashTable)); zend_hash_persist(z->value.ht, (zend_persist_func_t) zend_persist_zval_ptr, sizeof(zval**) TSRMLS_CC); break; +#if ZEND_EXTENSION_API_NO > PHP_5_5_X_API_NO + case IS_CONSTANT_AST: + Z_AST_P(z) = zend_persist_ast(Z_AST_P(z) TSRMLS_CC); + break; +#endif } } diff --git a/ext/opcache/zend_persist_calc.c b/ext/opcache/zend_persist_calc.c index 18af756f6e..8947c72ddc 100644 --- a/ext/opcache/zend_persist_calc.c +++ b/ext/opcache/zend_persist_calc.c @@ -45,6 +45,7 @@ #endif static uint zend_persist_zval_ptr_calc(zval **zp TSRMLS_DC); +static uint zend_persist_zval_calc(zval *z TSRMLS_DC); static uint zend_hash_persist_calc(HashTable *ht, int (*pPersistElement)(void *pElement TSRMLS_DC), size_t el_size TSRMLS_DC) { @@ -91,6 +92,27 @@ static uint zend_hash_persist_calc(HashTable *ht, int (*pPersistElement)(void *p RETURN_SIZE(); } +#if ZEND_EXTENSION_API_NO > PHP_5_5_X_API_NO +static uint zend_persist_ast_calc(zend_ast *ast TSRMLS_DC) +{ + int i; + START_SIZE(); + + if (ast->kind == ZEND_CONST) { + ADD_SIZE(sizeof(zend_ast) + sizeof(zval)); + ADD_SIZE(zend_persist_zval_calc(ast->u.val TSRMLS_CC)); + } else { + ADD_SIZE(sizeof(zend_ast) + sizeof(zend_ast*) * (ast->children - 1)); + for (i = 0; i < ast->children; i++) { + if ((&ast->u.child)[i]) { + ADD_SIZE(zend_persist_ast_calc((&ast->u.child)[i] TSRMLS_CC)); + } + } + } + RETURN_SIZE(); +} +#endif + static uint zend_persist_zval_calc(zval *z TSRMLS_DC) { START_SIZE(); @@ -109,6 +131,11 @@ static uint zend_persist_zval_calc(zval *z TSRMLS_DC) ADD_DUP_SIZE(z->value.ht, sizeof(HashTable)); ADD_SIZE(zend_hash_persist_calc(z->value.ht, (int (*)(void* TSRMLS_DC)) zend_persist_zval_ptr_calc, sizeof(zval**) TSRMLS_CC)); break; +#if ZEND_EXTENSION_API_NO > PHP_5_5_X_API_NO + case IS_CONSTANT_AST: + ADD_SIZE(zend_persist_ast_calc(Z_AST_P(z) TSRMLS_CC)); + break; +#endif } RETURN_SIZE(); } diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c index 90ef9b035f..8d033035e2 100644 --- a/ext/openssl/openssl.c +++ b/ext/openssl/openssl.c @@ -129,6 +129,12 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_openssl_x509_export, 0, 0, 2) ZEND_ARG_INFO(0, notext) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_INFO_EX(arginfo_openssl_x509_fingerprint, 0, 0, 1) + ZEND_ARG_INFO(0, x509) + ZEND_ARG_INFO(0, method) + ZEND_ARG_INFO(0, raw_output) +ZEND_END_ARG_INFO() + ZEND_BEGIN_ARG_INFO(arginfo_openssl_x509_check_private_key, 0) ZEND_ARG_INFO(0, cert) ZEND_ARG_INFO(0, key) @@ -394,11 +400,35 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_openssl_random_pseudo_bytes, 0, 0, 1) ZEND_ARG_INFO(0, length) ZEND_ARG_INFO(1, result_is_strong) ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_openssl_spki_new, 0, 0, 2) + ZEND_ARG_INFO(0, privkey) + ZEND_ARG_INFO(0, challenge) + ZEND_ARG_INFO(0, algo) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO(arginfo_openssl_spki_verify, 0) + ZEND_ARG_INFO(0, spki) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO(arginfo_openssl_spki_export, 0) + ZEND_ARG_INFO(0, spki) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO(arginfo_openssl_spki_export_challenge, 0) + ZEND_ARG_INFO(0, spki) +ZEND_END_ARG_INFO() /* }}} */ /* {{{ openssl_functions[] */ const zend_function_entry openssl_functions[] = { +/* spki functions */ + PHP_FE(openssl_spki_new, arginfo_openssl_spki_new) + PHP_FE(openssl_spki_verify, arginfo_openssl_spki_verify) + PHP_FE(openssl_spki_export, arginfo_openssl_spki_export) + PHP_FE(openssl_spki_export_challenge, arginfo_openssl_spki_export_challenge) + /* public/private key functions */ PHP_FE(openssl_pkey_free, arginfo_openssl_pkey_free) PHP_FE(openssl_pkey_new, arginfo_openssl_pkey_new) @@ -419,6 +449,7 @@ const zend_function_entry openssl_functions[] = { PHP_FE(openssl_x509_checkpurpose, arginfo_openssl_x509_checkpurpose) PHP_FE(openssl_x509_check_private_key, arginfo_openssl_x509_check_private_key) PHP_FE(openssl_x509_export, arginfo_openssl_x509_export) + PHP_FE(openssl_x509_fingerprint, arginfo_openssl_x509_fingerprint) PHP_FE(openssl_x509_export_to_file, arginfo_openssl_x509_export_to_file) /* PKCS12 funcs */ @@ -791,6 +822,7 @@ static int add_oid_section(struct php_x509_request * req TSRMLS_DC) /* {{{ */ static const EVP_CIPHER * php_openssl_get_evp_cipher_from_algo(long algo); +int openssl_spki_cleanup(const char *src, char *dest); static int php_openssl_parse_config(struct php_x509_request * req, zval * optional_args TSRMLS_DC) /* {{{ */ { @@ -1161,6 +1193,10 @@ PHP_MINIT_FUNCTION(openssl) php_stream_xport_register("sslv2", php_openssl_ssl_socket_factory TSRMLS_CC); #endif php_stream_xport_register("tls", php_openssl_ssl_socket_factory TSRMLS_CC); +#if OPENSSL_VERSION_NUMBER >= 0x10001001L + php_stream_xport_register("tlsv1.1", php_openssl_ssl_socket_factory TSRMLS_CC); + php_stream_xport_register("tlsv1.2", php_openssl_ssl_socket_factory TSRMLS_CC); +#endif /* override the default tcp socket provider */ php_stream_xport_register("tcp", php_openssl_ssl_socket_factory TSRMLS_CC); @@ -1199,6 +1235,10 @@ PHP_MSHUTDOWN_FUNCTION(openssl) #endif php_stream_xport_unregister("sslv3" TSRMLS_CC); php_stream_xport_unregister("tls" TSRMLS_CC); +#if OPENSSL_VERSION_NUMBER >= 0x10001001L + php_stream_xport_unregister("tlsv1.1" TSRMLS_CC); + php_stream_xport_unregister("tlsv1.2" TSRMLS_CC); +#endif /* reinstate the default tcp handler */ php_stream_xport_register("tcp", php_stream_generic_socket_factory TSRMLS_CC); @@ -1335,6 +1375,279 @@ PHP_FUNCTION(openssl_x509_export_to_file) } /* }}} */ +/* {{{ proto string openssl_spki_new(mixed zpkey, string challenge [, mixed method]) + Creates new private key (or uses existing) and creates a new spki cert + outputting results to var */ +PHP_FUNCTION(openssl_spki_new) +{ + int challenge_len; + char * challenge = NULL, * spkstr = NULL, * s = NULL; + long keyresource = -1; + const char *spkac = "SPKAC="; + long algo = OPENSSL_ALGO_MD5; + + zval *method = NULL; + zval * zpkey = NULL; + EVP_PKEY * pkey = NULL; + NETSCAPE_SPKI *spki=NULL; + const EVP_MD *mdtype; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|z", &zpkey, &challenge, &challenge_len, &method) == FAILURE) { + return; + } + RETVAL_FALSE; + + pkey = php_openssl_evp_from_zval(&zpkey, 0, challenge, 1, &keyresource TSRMLS_CC); + + if (pkey == NULL) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to use supplied private key"); + goto cleanup; + } + + if (method != NULL) { + if (Z_TYPE_P(method) == IS_LONG) { + algo = Z_LVAL_P(method); + } else { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Algorithm must be of supported type"); + goto cleanup; + } + } + mdtype = php_openssl_get_evp_md_from_algo(algo); + + if (!mdtype) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown signature algorithm"); + goto cleanup; + } + + if ((spki = NETSCAPE_SPKI_new()) == NULL) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to create new SPKAC"); + goto cleanup; + } + + if (challenge) { + ASN1_STRING_set(spki->spkac->challenge, challenge, challenge_len); + } + + if (!NETSCAPE_SPKI_set_pubkey(spki, pkey)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to embed public key"); + goto cleanup; + } + + if (!NETSCAPE_SPKI_sign(spki, pkey, mdtype)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to sign with specified algorithm"); + goto cleanup; + } + + spkstr = NETSCAPE_SPKI_b64_encode(spki); + if (!spkstr){ + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to encode SPKAC"); + goto cleanup; + } + + s = emalloc(strlen(spkac) + strlen(spkstr) + 1); + sprintf(s, "%s%s", spkac, spkstr); + + RETVAL_STRINGL(s, strlen(s), 0); + goto cleanup; + +cleanup: + + if (keyresource == -1 && spki != NULL) { + NETSCAPE_SPKI_free(spki); + } + if (keyresource == -1 && pkey != NULL) { + EVP_PKEY_free(pkey); + } + if (keyresource == -1 && spkstr != NULL) { + efree(spkstr); + } + + if (strlen(s) <= 0) { + RETVAL_FALSE; + } + + if (keyresource == -1 && s != NULL) { + efree(s); + } +} +/* }}} */ + +/* {{{ proto bool openssl_spki_verify(string spki) + Verifies spki returns boolean */ +PHP_FUNCTION(openssl_spki_verify) +{ + int spkstr_len, i = 0; + char *spkstr = NULL, * spkstr_cleaned = NULL; + + EVP_PKEY *pkey = NULL; + NETSCAPE_SPKI *spki = NULL; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &spkstr, &spkstr_len) == FAILURE) { + return; + } + RETVAL_FALSE; + + if (spkstr == NULL) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to use supplied SPKAC"); + goto cleanup; + } + + spkstr_cleaned = emalloc(spkstr_len + 1); + openssl_spki_cleanup(spkstr, spkstr_cleaned); + + if (strlen(spkstr_cleaned)<=0) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid SPKAC"); + goto cleanup; + } + + spki = NETSCAPE_SPKI_b64_decode(spkstr_cleaned, strlen(spkstr_cleaned)); + if (spki == NULL) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to decode supplied SPKAC"); + goto cleanup; + } + + pkey = X509_PUBKEY_get(spki->spkac->pubkey); + if (pkey == NULL) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to acquire signed public key"); + goto cleanup; + } + + i = NETSCAPE_SPKI_verify(spki, pkey); + goto cleanup; + +cleanup: + if (spki != NULL) { + NETSCAPE_SPKI_free(spki); + } + if (pkey != NULL) { + EVP_PKEY_free(pkey); + } + if (spkstr_cleaned != NULL) { + efree(spkstr_cleaned); + } + + if (i > 0) { + RETVAL_TRUE; + } +} +/* }}} */ + +/* {{{ proto string openssl_spki_export(string spki) + Exports public key from existing spki to var */ +PHP_FUNCTION(openssl_spki_export) +{ + int spkstr_len; + char *spkstr = NULL, * spkstr_cleaned = NULL, * s = NULL; + + EVP_PKEY *pkey = NULL; + NETSCAPE_SPKI *spki = NULL; + BIO *out = BIO_new(BIO_s_mem()); + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &spkstr, &spkstr_len) == FAILURE) { + return; + } + RETVAL_FALSE; + + if (spkstr == NULL) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to use supplied SPKAC"); + goto cleanup; + } + + spkstr_cleaned = emalloc(spkstr_len + 1); + openssl_spki_cleanup(spkstr, spkstr_cleaned); + + spki = NETSCAPE_SPKI_b64_decode(spkstr_cleaned, strlen(spkstr_cleaned)); + if (spki == NULL) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to decode supplied SPKAC"); + goto cleanup; + } + + pkey = X509_PUBKEY_get(spki->spkac->pubkey); + if (pkey == NULL) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to acquire signed public key"); + goto cleanup; + } + + out = BIO_new_fp(stdout, BIO_NOCLOSE); + PEM_write_bio_PUBKEY(out, pkey); + goto cleanup; + +cleanup: + + if (spki != NULL) { + NETSCAPE_SPKI_free(spki); + } + if (out != NULL) { + BIO_free_all(out); + } + if (pkey != NULL) { + EVP_PKEY_free(pkey); + } + if (spkstr_cleaned != NULL) { + efree(spkstr_cleaned); + } + if (s != NULL) { + efree(s); + } +} +/* }}} */ + +/* {{{ proto string openssl_spki_export_challenge(string spki) + Exports spkac challenge from existing spki to var */ +PHP_FUNCTION(openssl_spki_export_challenge) +{ + int spkstr_len; + char *spkstr = NULL, * spkstr_cleaned = NULL; + + NETSCAPE_SPKI *spki = NULL; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &spkstr, &spkstr_len) == FAILURE) { + return; + } + RETVAL_FALSE; + + if (spkstr == NULL) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to use supplied SPKAC"); + goto cleanup; + } + + spkstr_cleaned = emalloc(spkstr_len + 1); + openssl_spki_cleanup(spkstr, spkstr_cleaned); + + spki = NETSCAPE_SPKI_b64_decode(spkstr_cleaned, strlen(spkstr_cleaned)); + if (spki == NULL) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to decode SPKAC"); + goto cleanup; + } + + RETVAL_STRING((char *) ASN1_STRING_data(spki->spkac->challenge), 1); + goto cleanup; + +cleanup: + if (spkstr_cleaned != NULL) { + efree(spkstr_cleaned); + } +} +/* }}} */ + +/* {{{ strip line endings from spkac */ +int openssl_spki_cleanup(const char *src, char *dest) +{ + int removed=0; + + while (*src) { + if (*src!='\n'&&*src!='\r') { + *dest++=*src; + } else { + ++removed; + } + ++src; + } + *dest=0; + return removed; +} +/* }}} */ + /* {{{ proto bool openssl_x509_export(mixed x509, string &out [, bool notext = true]) Exports a CERT to file or a var */ PHP_FUNCTION(openssl_x509_export) @@ -1377,6 +1690,121 @@ PHP_FUNCTION(openssl_x509_export) } /* }}} */ +static int php_openssl_x509_fingerprint(X509 *peer, const char *method, zend_bool raw, char **out, int *out_len TSRMLS_DC) +{ + unsigned char md[EVP_MAX_MD_SIZE]; + const EVP_MD *mdtype; + unsigned int n; + + if (!(mdtype = EVP_get_digestbyname(method))) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown signature algorithm"); + return FAILURE; + } else if (!X509_digest(peer, mdtype, md, &n)) { + php_error_docref(NULL TSRMLS_CC, E_ERROR, "Could not generate signature"); + return FAILURE; + } + + if (raw) { + *out_len = n; + *out = estrndup((char *) md, n); + } else { + *out_len = n * 2; + *out = emalloc(*out_len + 1); + + make_digest_ex(*out, md, n); + } + + return SUCCESS; +} + +static int php_x509_fingerprint_cmp(X509 *peer, const char *method, const char *expected TSRMLS_DC) +{ + char *fingerprint; + int fingerprint_len; + int result = -1; + + if (php_openssl_x509_fingerprint(peer, method, 0, &fingerprint, &fingerprint_len TSRMLS_CC) == SUCCESS) { + result = strcmp(expected, fingerprint); + efree(fingerprint); + } + + return result; +} + +static zend_bool php_x509_fingerprint_match(X509 *peer, zval *val TSRMLS_DC) +{ + if (Z_TYPE_P(val) == IS_STRING) { + const char *method = NULL; + + switch (Z_STRLEN_P(val)) { + case 32: + method = "md5"; + break; + + case 40: + method = "sha1"; + break; + } + + return method && php_x509_fingerprint_cmp(peer, method, Z_STRVAL_P(val) TSRMLS_CC) == 0; + } else if (Z_TYPE_P(val) == IS_ARRAY) { + HashPosition pos; + zval **current; + char *key; + uint key_len; + ulong key_index; + + for (zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(val), &pos); + zend_hash_get_current_data_ex(Z_ARRVAL_P(val), (void **)¤t, &pos) == SUCCESS; + zend_hash_move_forward_ex(Z_ARRVAL_P(val), &pos) + ) { + int key_type = zend_hash_get_current_key_ex(Z_ARRVAL_P(val), &key, &key_len, &key_index, 0, &pos); + + if (key_type == HASH_KEY_IS_STRING + && Z_TYPE_PP(current) == IS_STRING + && php_x509_fingerprint_cmp(peer, key, Z_STRVAL_PP(current) TSRMLS_CC) != 0 + ) { + return 0; + } + } + return 1; + } + return 0; +} + +PHP_FUNCTION(openssl_x509_fingerprint) +{ + X509 *cert; + zval **zcert; + long certresource; + zend_bool raw_output = 0; + char *method = "sha1"; + int method_len; + + char *fingerprint; + int fingerprint_len; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z|sb", &zcert, &method, &method_len, &raw_output) == FAILURE) { + return; + } + + cert = php_openssl_x509_from_zval(zcert, 0, &certresource TSRMLS_CC); + if (cert == NULL) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "cannot get cert from parameter 1"); + RETURN_FALSE; + } + + if (php_openssl_x509_fingerprint(cert, method, raw_output, &fingerprint, &fingerprint_len TSRMLS_CC) == SUCCESS) { + RETVAL_STRINGL(fingerprint, fingerprint_len, 0); + } else { + RETVAL_FALSE; + } + + if (certresource == -1 && cert) { + X509_free(cert); + } +} + /* {{{ proto bool openssl_x509_check_private_key(mixed cert, mixed key) Checks if a private key corresponds to a CERT */ PHP_FUNCTION(openssl_x509_check_private_key) @@ -4506,14 +4934,12 @@ static int verify_callback(int preverify_ok, X509_STORE_CTX *ctx) /* {{{ */ { php_stream *stream; SSL *ssl; - X509 *err_cert; int err, depth, ret; zval **val; ret = preverify_ok; /* determine the status for the current cert */ - err_cert = X509_STORE_CTX_get_current_cert(ctx); err = X509_STORE_CTX_get_error(ctx); depth = X509_STORE_CTX_get_error_depth(ctx); @@ -4541,12 +4967,91 @@ static int verify_callback(int preverify_ok, X509_STORE_CTX *ctx) /* {{{ */ } /* }}} */ +static zend_bool matches_wildcard_name(const char *subjectname, const char *certname) +{ + char *wildcard; + int prefix_len, suffix_len, subject_len; + + if (strcasecmp(subjectname, certname) == 0) { + return 1; + } + + if (!(wildcard = strchr(certname, '*'))) { + return 0; + } + + // 1) prefix, if not empty, must match subject + prefix_len = wildcard - certname; + if (prefix_len && strncasecmp(subjectname, certname, prefix_len) != 0) { + return 0; + } + + suffix_len = strlen(wildcard + 1); + subject_len = strlen(subjectname); + if (suffix_len <= subject_len) { + /* 2) suffix must match + * 3) no . between prefix and suffix + **/ + return strcasecmp(wildcard + 1, subjectname + subject_len - suffix_len) == 0 && + memchr(subjectname + prefix_len, '.', subject_len - suffix_len - prefix_len) == NULL; + } + + return 0; +} + +static zend_bool matches_san_list(X509 *peer, const char *subject_name) +{ + int i; + zend_bool is_match = 0; + unsigned char *cert_name; + + GENERAL_NAMES *alt_names = X509_get_ext_d2i(peer, NID_subject_alt_name, 0, 0); + int alt_name_count = sk_GENERAL_NAME_num(alt_names); + + for (i = 0; i < alt_name_count; i++) { + GENERAL_NAME *san = sk_GENERAL_NAME_value(alt_names, i); + + if (GEN_DNS == san->type) { + ASN1_STRING_to_UTF8(&cert_name, san->d.dNSName); + is_match = matches_wildcard_name(subject_name, (char *) cert_name); + OPENSSL_free(cert_name); + } + + if (is_match) { + break; + } + } + + return is_match; +} + +static zend_bool matches_common_name(X509 *peer, const char *subject_name TSRMLS_DC) +{ + char buf[1024]; + X509_NAME *cert_name; + zend_bool is_match = 0; + int cert_name_len; + + cert_name = X509_get_subject_name(peer); + cert_name_len = X509_NAME_get_text_by_NID(cert_name, NID_commonName, buf, sizeof(buf)); + + if (cert_name_len == -1) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to locate peer certificate CN"); + } else if (cert_name_len != strlen(buf)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Peer certificate CN=`%.*s' is malformed", cert_name_len, buf); + } else if (matches_wildcard_name(subject_name, buf)) { + is_match = 1; + } else { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Peer certificate CN=`%.*s' did not match expected CN=`%s'", cert_name_len, buf, subject_name); + } + + return is_match; +} + int php_openssl_apply_verification_policy(SSL *ssl, X509 *peer, php_stream *stream TSRMLS_DC) /* {{{ */ { zval **val = NULL; char *cnmatch = NULL; - X509_NAME *name; - char buf[1024]; int err; /* verification is turned off */ @@ -4577,36 +5082,25 @@ int php_openssl_apply_verification_policy(SSL *ssl, X509 *peer, php_stream *stre /* if the cert passed the usual checks, apply our own local policies now */ - name = X509_get_subject_name(peer); - - /* Does the common name match ? (used primarily for https://) */ - GET_VER_OPT_STRING("CN_match", cnmatch); - if (cnmatch) { - int match = 0; - int name_len = X509_NAME_get_text_by_NID(name, NID_commonName, buf, sizeof(buf)); - - if (name_len == -1) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to locate peer certificate CN"); - return FAILURE; - } else if (name_len != strlen(buf)) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Peer certificate CN=`%.*s' is malformed", name_len, buf); - return FAILURE; - } - - match = strcmp(cnmatch, buf) == 0; - if (!match && strlen(buf) > 3 && buf[0] == '*' && buf[1] == '.') { - /* Try wildcard */ - - if (strchr(buf+2, '.')) { - char *tmp = strstr(cnmatch, buf+1); - - match = tmp && strcmp(tmp, buf+2) && tmp == strchr(cnmatch, '.'); + if (GET_VER_OPT("peer_fingerprint")) { + if (Z_TYPE_PP(val) == IS_STRING || Z_TYPE_PP(val) == IS_ARRAY) { + if (!php_x509_fingerprint_match(peer, *val TSRMLS_CC)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Peer fingerprint doesn't match"); + return FAILURE; } + } else { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Expected peer fingerprint must be a string or an array"); } + } - if (!match) { - /* didn't match */ - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Peer certificate CN=`%.*s' did not match expected CN=`%s'", name_len, buf, cnmatch); + GET_VER_OPT_STRING("CN_match", cnmatch); + + if (cnmatch) { + if (matches_san_list(peer, cnmatch)) { + return SUCCESS; + } else if (matches_common_name(peer, cnmatch TSRMLS_CC)) { + return SUCCESS; + } else { return FAILURE; } } diff --git a/ext/openssl/php_openssl.h b/ext/openssl/php_openssl.h index e6b064a277..a06e43db1c 100644 --- a/ext/openssl/php_openssl.h +++ b/ext/openssl/php_openssl.h @@ -66,6 +66,7 @@ PHP_FUNCTION(openssl_x509_free); PHP_FUNCTION(openssl_x509_parse); PHP_FUNCTION(openssl_x509_checkpurpose); PHP_FUNCTION(openssl_x509_export); +PHP_FUNCTION(openssl_x509_fingerprint); PHP_FUNCTION(openssl_x509_export_to_file); PHP_FUNCTION(openssl_x509_check_private_key); @@ -79,6 +80,11 @@ PHP_FUNCTION(openssl_csr_export_to_file); PHP_FUNCTION(openssl_csr_sign); PHP_FUNCTION(openssl_csr_get_subject); PHP_FUNCTION(openssl_csr_get_public_key); + +PHP_FUNCTION(openssl_spki_new); +PHP_FUNCTION(openssl_spki_verify); +PHP_FUNCTION(openssl_spki_export); +PHP_FUNCTION(openssl_spki_export_challenge); #else #define phpext_openssl_ptr NULL diff --git a/ext/openssl/tests/bug65729.pem b/ext/openssl/tests/bug65729.pem new file mode 100644 index 0000000000..dbeed6efd3 --- /dev/null +++ b/ext/openssl/tests/bug65729.pem @@ -0,0 +1,28 @@ +-----BEGIN CERTIFICATE----- +MIICCTCCAXICCQDNMI29sowT7TANBgkqhkiG9w0BAQUFADBJMQswCQYDVQQGEwJT +RzESMBAGA1UECBMJVGVzdHZpbGxlMREwDwYDVQQKEwhkYXRpYmJhdzETMBEGA1UE +AxQKKi50ZXN0LmNvbTAeFw0xMzA5MjEwNzUyMjRaFw0xNDA5MjEwNzUyMjRaMEkx +CzAJBgNVBAYTAlNHMRIwEAYDVQQIEwlUZXN0dmlsbGUxETAPBgNVBAoTCGRhdGli +YmF3MRMwEQYDVQQDFAoqLnRlc3QuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCB +iQKBgQCdzVnic8K5W4SVbwVuqezcTjeqVLoQ91vVNZB0Jnsuz6q3DoK03oAd1jTe +Vd0k+MQDbXpHoc37lA4+8z/g5Bs0UXxNx+nkbFTE7Ba2/G24caI9/cOXZPG3UViD +rtqXKL6h5/umqRG9Dt5liF2MVP9XFAesVC7B8+Ca+PbPlQoYzwIDAQABMA0GCSqG +SIb3DQEBBQUAA4GBAAS07u/Ke+EhEHidz6CG3Qcr+zg483JKRgZFyGz+YUKyyKKy +fmLs7JieGJxYQjOmIpj/6X9Gnb2HjIPDnI6A+MV1emXDTnnmsgf2/lZGcthhpZn2 +rMbj9bI0iH6HwOVGtp4ZJA5fB7nj3J+gWNTCQzDDOxwX36d2LL9ua+UMnk/g +-----END CERTIFICATE----- +-----BEGIN RSA PRIVATE KEY----- +MIICXQIBAAKBgQCdzVnic8K5W4SVbwVuqezcTjeqVLoQ91vVNZB0Jnsuz6q3DoK0 +3oAd1jTeVd0k+MQDbXpHoc37lA4+8z/g5Bs0UXxNx+nkbFTE7Ba2/G24caI9/cOX +ZPG3UViDrtqXKL6h5/umqRG9Dt5liF2MVP9XFAesVC7B8+Ca+PbPlQoYzwIDAQAB +AoGAeyzTwKPDl5QMRejHQL57GOwlH1vLcXrjv+VzwHZZKQ0IoKM++5fCQYf29KXp +XPahaluGW2u9sWa8R/7wGcd0Q4RtquGzsgT3+AQsIc5KfIamyOyDaRVM/ymX3fWg +gHIU7OOzB+ihOU8sHyRIwfbk01/kmrBXLRj8E31sy3i3PIECQQDQQYE+aN7Acrdt +yN5CaqvbkiCGjRvASlemiTzPosgOtndyp21w1gakJwKYhYDk1N6A6Qb8REMZqM/U +wFypldV/AkEAwfq6NFuhpGL6hDA7MvlyY1KiZ0cHetPUX+PgdNqy2DA+1Sv4i7gm +Wd/uA651K7aPXuUaf9dKtPCmZwI4M6SEsQJBALW89HTqP7niYoDEEnITdPaghxHk +gptERUln6lGo1L1CLus3gSI/JHyMLo+7scgAnEwTD62GRKhX0Ubwt+ymfTECQAY5 +fHYnppU20+EgBxZIqOIFCc8UmWnYmE0Ha/Fz/x8u1SVUBuK84wYpSGL32yyu7ATY +hzQo/W229zABAzqtAdECQQCUdB7IBFpPnsfv/EUBFX7X/7zAc9JpACmu9It5ju8C +KIsMuz/02D+TQoJNjdAngBM+4AJDIaGFgTMIfaDMh5L7 +-----END RSA PRIVATE KEY----- diff --git a/ext/openssl/tests/bug65729.phpt b/ext/openssl/tests/bug65729.phpt new file mode 100644 index 0000000000..c0ee4443eb --- /dev/null +++ b/ext/openssl/tests/bug65729.phpt @@ -0,0 +1,54 @@ +--TEST-- +Bug #65729: CN_match gives false positive when wildcard is used +--SKIPIF-- +<?php +if (!extension_loaded("openssl")) die("skip"); +if (!function_exists('pcntl_fork')) die("skip no fork"); +--FILE-- +<?php +$context = stream_context_create(); + +stream_context_set_option($context, 'ssl', 'local_cert', __DIR__ . "/bug65729.pem"); +stream_context_set_option($context, 'ssl', 'allow_self_signed', true); +$server = stream_socket_server('ssl://127.0.0.1:64321', $errno, $errstr, + STREAM_SERVER_BIND|STREAM_SERVER_LISTEN, $context); + +$expected_names = array('foo.test.com.sg', 'foo.test.com', 'FOO.TEST.COM', 'foo.bar.test.com'); + +$pid = pcntl_fork(); +if ($pid == -1) { + die('could not fork'); +} else if ($pid) { + foreach ($expected_names as $expected_name) { + $contextC = stream_context_create(array( + 'ssl' => array( + 'verify_peer' => true, + 'allow_self_signed' => true, + 'CN_match' => $expected_name, + ) + )); + var_dump(stream_socket_client("ssl://127.0.0.1:64321", $errno, $errstr, 1, + STREAM_CLIENT_CONNECT, $contextC)); + } +} else { + @pcntl_wait($status); + foreach ($expected_names as $name) { + @stream_socket_accept($server, 1); + } +} +--EXPECTF-- +Warning: stream_socket_client(): Peer certificate CN=`*.test.com' did not match expected CN=`foo.test.com.sg' in %s on line %d + +Warning: stream_socket_client(): Failed to enable crypto in %s on line %d + +Warning: stream_socket_client(): unable to connect to ssl://127.0.0.1:64321 (Unknown error) in %s on line %d +bool(false) +resource(%d) of type (stream) +resource(%d) of type (stream) + +Warning: stream_socket_client(): Peer certificate CN=`*.test.com' did not match expected CN=`foo.bar.test.com' in %s on line %d + +Warning: stream_socket_client(): Failed to enable crypto in %s on line %d + +Warning: stream_socket_client(): unable to connect to ssl://127.0.0.1:64321 (Unknown error) in %s on line %d +bool(false) diff --git a/ext/openssl/tests/openssl_peer_fingerprint.phpt b/ext/openssl/tests/openssl_peer_fingerprint.phpt new file mode 100644 index 0000000000..2960dffae5 --- /dev/null +++ b/ext/openssl/tests/openssl_peer_fingerprint.phpt @@ -0,0 +1,62 @@ +--TEST-- +Testing peer fingerprint on connection +--SKIPIF-- +<?php +if (!extension_loaded("openssl")) die("skip"); +if (!function_exists('pcntl_fork')) die("skip no fork"); +--FILE-- +<?php +$context = stream_context_create(); + +stream_context_set_option($context, 'ssl', 'local_cert', __DIR__ . "/bug54992.pem"); +stream_context_set_option($context, 'ssl', 'allow_self_signed', true); +$server = stream_socket_server('ssl://127.0.0.1:64321', $errno, $errstr, + STREAM_SERVER_BIND|STREAM_SERVER_LISTEN, $context); + + +$pid = pcntl_fork(); +if ($pid == -1) { + die('could not fork'); +} else if ($pid) { + $contextC = stream_context_create( + array( + 'ssl' => array( + 'verify_peer' => true, + 'cafile' => __DIR__ . '/bug54992-ca.pem', + 'capture_peer_cert' => true, + 'peer_fingerprint' => '81cafc260aa8d82956ebc6212a362ece', + ) + ) + ); + // should be: 81cafc260aa8d82956ebc6212a362ecc + var_dump(stream_socket_client("ssl://127.0.0.1:64321", $errno, $errstr, 1, + STREAM_CLIENT_CONNECT, $contextC)); + + $contextC = stream_context_create( + array( + 'ssl' => array( + 'verify_peer' => true, + 'cafile' => __DIR__ . '/bug54992-ca.pem', + 'capture_peer_cert' => true, + 'peer_fingerprint' => array( + 'sha256' => '78ea579f2c3b439359dec5dac9d445108772927427c4780037e87df3799a0aa0', + ), + ) + ) + ); + + var_dump(stream_socket_client("ssl://127.0.0.1:64321", $errno, $errstr, 1, + STREAM_CLIENT_CONNECT, $contextC)); +} else { + @pcntl_wait($status); + @stream_socket_accept($server, 1); + @stream_socket_accept($server, 1); +} +--EXPECTF-- +Warning: stream_socket_client(): Peer fingerprint doesn't match in %s on line %d + +Warning: stream_socket_client(): Failed to enable crypto in %s on line %d + +Warning: stream_socket_client(): unable to connect to ssl://127.0.0.1:64321 (Unknown error) in %s on line %d +bool(false) +resource(9) of type (stream) diff --git a/ext/openssl/tests/openssl_spki_export.phpt b/ext/openssl/tests/openssl_spki_export.phpt new file mode 100644 index 0000000000..59332f70a5 --- /dev/null +++ b/ext/openssl/tests/openssl_spki_export.phpt @@ -0,0 +1,62 @@ +--TEST-- +Testing openssl_spki_export() +Creates SPKAC for all available key sizes & signature algorithms and exports public key +--SKIPIF-- +<?php +if (!extension_loaded("openssl")) die("skip"); +if (!@openssl_pkey_new()) die("skip cannot create private key"); +?> +--FILE-- +<?php + +/* array of private key sizes to test */ +$ksize = array('1024'=>1024, + '2048'=>2048, + '4096'=>4096); + +/* array of available hashings to test */ +$algo = array('md4'=>OPENSSL_ALGO_MD4, + 'md5'=>OPENSSL_ALGO_MD5, + 'sha1'=>OPENSSL_ALGO_SHA1, + 'sha224'=>OPENSSL_ALGO_SHA224, + 'sha256'=>OPENSSL_ALGO_SHA256, + 'sha384'=>OPENSSL_ALGO_SHA384, + 'sha512'=>OPENSSL_ALGO_SHA512, + 'rmd160'=>OPENSSL_ALGO_RMD160); + +/* loop over key sizes for test */ +foreach($ksize as $k => $v) { + + /* generate new private key of specified size to use for tests */ + $pkey = openssl_pkey_new(array('digest_alg' => 'sha512', + 'private_key_type' => OPENSSL_KEYTYPE_RSA, + 'private_key_bits' => $v)); + openssl_pkey_export($pkey, $pass); + + /* loop to create and verify results */ + foreach($algo as $key => $value) { + $spkac = openssl_spki_new($pkey, _uuid(), $value); + echo openssl_spki_export(preg_replace('/SPKAC=/', '', $spkac)); + } + openssl_free_key($pkey); +} + +/* generate a random challenge */ +function _uuid() +{ + return sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x', mt_rand(0, 0xffff), + mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0x0fff) | 0x4000, + mt_rand(0, 0x3fff) | 0x8000, mt_rand(0, 0xffff), + mt_rand(0, 0xffff), mt_rand(0, 0xffff)); +} + +?> +--EXPECTREGEX-- +\-\-\-\-\-BEGIN PUBLIC KEY\-\-\-\-\-.*\-\-\-\-\-END PUBLIC KEY\-\-\-\-\- +\-\-\-\-\-BEGIN PUBLIC KEY\-\-\-\-\-.*\-\-\-\-\-END PUBLIC KEY\-\-\-\-\- +\-\-\-\-\-BEGIN PUBLIC KEY\-\-\-\-\-.*\-\-\-\-\-END PUBLIC KEY\-\-\-\-\- +\-\-\-\-\-BEGIN PUBLIC KEY\-\-\-\-\-.*\-\-\-\-\-END PUBLIC KEY\-\-\-\-\- +\-\-\-\-\-BEGIN PUBLIC KEY\-\-\-\-\-.*\-\-\-\-\-END PUBLIC KEY\-\-\-\-\- +\-\-\-\-\-BEGIN PUBLIC KEY\-\-\-\-\-.*\-\-\-\-\-END PUBLIC KEY\-\-\-\-\- +\-\-\-\-\-BEGIN PUBLIC KEY\-\-\-\-\-.*\-\-\-\-\-END PUBLIC KEY\-\-\-\-\- +\-\-\-\-\-BEGIN PUBLIC KEY\-\-\-\-\-.*\-\-\-\-\-END PUBLIC KEY\-\-\-\-\- diff --git a/ext/openssl/tests/openssl_spki_export_challenge.phpt b/ext/openssl/tests/openssl_spki_export_challenge.phpt new file mode 100644 index 0000000000..71ef62edd5 --- /dev/null +++ b/ext/openssl/tests/openssl_spki_export_challenge.phpt @@ -0,0 +1,105 @@ +--TEST-- +Testing openssl_spki_export_challenge() +Creates SPKAC for all available key sizes & signature algorithms and exports challenge +--INI-- +error_reporting=0 +--SKIPIF-- +<?php +if (!extension_loaded("openssl")) die("skip"); +if (!@openssl_pkey_new()) die("skip cannot create private key"); +?> +--FILE-- +<?php + +/* array of private key sizes to test */ +$ksize = array('1024'=>1024, + '2048'=>2048, + '4096'=>4096); + +/* array of available hashings to test */ +$algo = array('md4'=>OPENSSL_ALGO_MD4, + 'md5'=>OPENSSL_ALGO_MD5, + 'sha1'=>OPENSSL_ALGO_SHA1, + 'sha224'=>OPENSSL_ALGO_SHA224, + 'sha256'=>OPENSSL_ALGO_SHA256, + 'sha384'=>OPENSSL_ALGO_SHA384, + 'sha512'=>OPENSSL_ALGO_SHA512, + 'rmd160'=>OPENSSL_ALGO_RMD160); + +/* loop over key sizes for test */ +foreach($ksize as $k => $v) { + + /* generate new private key of specified size to use for tests */ + $pkey = openssl_pkey_new(array('digest_alg' => 'sha512', + 'private_key_type' => OPENSSL_KEYTYPE_RSA, + 'private_key_bits' => $v)); + openssl_pkey_export($pkey, $pass); + + /* loop to create and verify results */ + foreach($algo as $key => $value) { + $spkac = openssl_spki_new($pkey, _uuid(), $value); + var_dump(openssl_spki_export_challenge(preg_replace('/SPKAC=/', '', $spkac))); + var_dump(openssl_spki_export_challenge($spkac.'Make it fail')); + } + openssl_free_key($pkey); +} + +/* generate a random challenge */ +function _uuid() +{ + return sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x', mt_rand(0, 0xffff), + mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0x0fff) | 0x4000, + mt_rand(0, 0x3fff) | 0x8000, mt_rand(0, 0xffff), + mt_rand(0, 0xffff), mt_rand(0, 0xffff)); +} + +?> +--EXPECTREGEX-- +string\(36\) \"[0-9a-f]{8}\-([0-9a-f]{4}\-){3}[0-9a-f]{12}\" +bool\(false\) +string\(36\) \"[0-9a-f]{8}\-([0-9a-f]{4}\-){3}[0-9a-f]{12}\" +bool\(false\) +string\(36\) \"[0-9a-f]{8}\-([0-9a-f]{4}\-){3}[0-9a-f]{12}\" +bool\(false\) +string\(36\) \"[0-9a-f]{8}\-([0-9a-f]{4}\-){3}[0-9a-f]{12}\" +bool\(false\) +string\(36\) \"[0-9a-f]{8}\-([0-9a-f]{4}\-){3}[0-9a-f]{12}\" +bool\(false\) +string\(36\) \"[0-9a-f]{8}\-([0-9a-f]{4}\-){3}[0-9a-f]{12}\" +bool\(false\) +string\(36\) \"[0-9a-f]{8}\-([0-9a-f]{4}\-){3}[0-9a-f]{12}\" +bool\(false\) +string\(36\) \"[0-9a-f]{8}\-([0-9a-f]{4}\-){3}[0-9a-f]{12}\" +bool\(false\) +string\(36\) \"[0-9a-f]{8}\-([0-9a-f]{4}\-){3}[0-9a-f]{12}\" +bool\(false\) +string\(36\) \"[0-9a-f]{8}\-([0-9a-f]{4}\-){3}[0-9a-f]{12}\" +bool\(false\) +string\(36\) \"[0-9a-f]{8}\-([0-9a-f]{4}\-){3}[0-9a-f]{12}\" +bool\(false\) +string\(36\) \"[0-9a-f]{8}\-([0-9a-f]{4}\-){3}[0-9a-f]{12}\" +bool\(false\) +string\(36\) \"[0-9a-f]{8}\-([0-9a-f]{4}\-){3}[0-9a-f]{12}\" +bool\(false\) +string\(36\) \"[0-9a-f]{8}\-([0-9a-f]{4}\-){3}[0-9a-f]{12}\" +bool\(false\) +string\(36\) \"[0-9a-f]{8}\-([0-9a-f]{4}\-){3}[0-9a-f]{12}\" +bool\(false\) +string\(36\) \"[0-9a-f]{8}\-([0-9a-f]{4}\-){3}[0-9a-f]{12}\" +bool\(false\) +string\(36\) \"[0-9a-f]{8}\-([0-9a-f]{4}\-){3}[0-9a-f]{12}\" +bool\(false\) +string\(36\) \"[0-9a-f]{8}\-([0-9a-f]{4}\-){3}[0-9a-f]{12}\" +bool\(false\) +string\(36\) \"[0-9a-f]{8}\-([0-9a-f]{4}\-){3}[0-9a-f]{12}\" +bool\(false\) +string\(36\) \"[0-9a-f]{8}\-([0-9a-f]{4}\-){3}[0-9a-f]{12}\" +bool\(false\) +string\(36\) \"[0-9a-f]{8}\-([0-9a-f]{4}\-){3}[0-9a-f]{12}\" +bool\(false\) +string\(36\) \"[0-9a-f]{8}\-([0-9a-f]{4}\-){3}[0-9a-f]{12}\" +bool\(false\) +string\(36\) \"[0-9a-f]{8}\-([0-9a-f]{4}\-){3}[0-9a-f]{12}\" +bool\(false\) +string\(36\) \"[0-9a-f]{8}\-([0-9a-f]{4}\-){3}[0-9a-f]{12}\" +bool\(false\) diff --git a/ext/openssl/tests/openssl_spki_new.phpt b/ext/openssl/tests/openssl_spki_new.phpt new file mode 100644 index 0000000000..e40f9bf28e --- /dev/null +++ b/ext/openssl/tests/openssl_spki_new.phpt @@ -0,0 +1,77 @@ +--TEST-- +Testing openssl_spki_new() +Tests SPKAC for all available private key sizes & hashing algorithms +--SKIPIF-- +<?php +if (!extension_loaded("openssl")) die("skip"); +if (!@openssl_pkey_new()) die("skip cannot create private key"); +?> +--FILE-- +<?php + +/* array of private key sizes to test */ +$ksize = array('1024'=>1024, + '2048'=>2048, + '4096'=>4096); + +/* array of available hashings to test */ +$algo = array('md4'=>OPENSSL_ALGO_MD4, + 'md5'=>OPENSSL_ALGO_MD5, + 'sha1'=>OPENSSL_ALGO_SHA1, + 'sha224'=>OPENSSL_ALGO_SHA224, + 'sha256'=>OPENSSL_ALGO_SHA256, + 'sha384'=>OPENSSL_ALGO_SHA384, + 'sha512'=>OPENSSL_ALGO_SHA512, + 'rmd160'=>OPENSSL_ALGO_RMD160); + +/* loop over key sizes for test */ +foreach($ksize as $k => $v) { + + /* generate new private key of specified size to use for tests */ + $pkey = openssl_pkey_new(array('digest_alg' => 'sha512', + 'private_key_type' => OPENSSL_KEYTYPE_RSA, + 'private_key_bits' => $v)); + openssl_pkey_export($pkey, $pass); + + /* loop to create and verify results */ + foreach($algo as $key => $value) { + var_dump(openssl_spki_new($pkey, _uuid(), $value)); + } + openssl_free_key($pkey); +} + +/* generate a random challenge */ +function _uuid() +{ + return sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x', mt_rand(0, 0xffff), + mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0x0fff) | 0x4000, + mt_rand(0, 0x3fff) | 0x8000, mt_rand(0, 0xffff), + mt_rand(0, 0xffff), mt_rand(0, 0xffff)); +} + +?> +--EXPECTF-- +string(478) "%s" +string(478) "%s" +string(478) "%s" +string(478) "%s" +string(478) "%s" +string(478) "%s" +string(478) "%s" +string(474) "%s" +string(830) "%s" +string(830) "%s" +string(830) "%s" +string(830) "%s" +string(830) "%s" +string(830) "%s" +string(830) "%s" +string(826) "%s" +string(1510) "%s" +string(1510) "%s" +string(1510) "%s" +string(1510) "%s" +string(1510) "%s" +string(1510) "%s" +string(1510) "%s" +string(1506) "%s" diff --git a/ext/openssl/tests/openssl_spki_verify.phpt b/ext/openssl/tests/openssl_spki_verify.phpt new file mode 100644 index 0000000000..1ee573fd3f --- /dev/null +++ b/ext/openssl/tests/openssl_spki_verify.phpt @@ -0,0 +1,105 @@ +--TEST-- +Testing openssl_spki_verify() +Creates SPKAC for all available key sizes & signature algorithms and tests for valid signature +--INI-- +error_reporting=0 +--SKIPIF-- +<?php +if (!extension_loaded("openssl")) die("skip"); +if (!@openssl_pkey_new()) die("skip cannot create private key"); +?> +--FILE-- +<?php + +/* array of private key sizes to test */ +$ksize = array('1024'=>1024, + '2048'=>2048, + '4096'=>4096); + +/* array of available hashings to test */ +$algo = array('md4'=>OPENSSL_ALGO_MD4, + 'md5'=>OPENSSL_ALGO_MD5, + 'sha1'=>OPENSSL_ALGO_SHA1, + 'sha224'=>OPENSSL_ALGO_SHA224, + 'sha256'=>OPENSSL_ALGO_SHA256, + 'sha384'=>OPENSSL_ALGO_SHA384, + 'sha512'=>OPENSSL_ALGO_SHA512, + 'rmd160'=>OPENSSL_ALGO_RMD160); + +/* loop over key sizes for test */ +foreach($ksize as $k => $v) { + + /* generate new private key of specified size to use for tests */ + $pkey = openssl_pkey_new(array('digest_alg' => 'sha512', + 'private_key_type' => OPENSSL_KEYTYPE_RSA, + 'private_key_bits' => $v)); + openssl_pkey_export($pkey, $pass); + + /* loop to create and verify results */ + foreach($algo as $key => $value) { + $spkac = openssl_spki_new($pkey, _uuid(), $value); + var_dump(openssl_spki_verify(preg_replace('/SPKAC=/', '', $spkac))); + var_dump(openssl_spki_verify($spkac.'Make it fail')); + } + openssl_free_key($pkey); +} + +/* generate a random challenge */ +function _uuid() +{ + return sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x', mt_rand(0, 0xffff), + mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0x0fff) | 0x4000, + mt_rand(0, 0x3fff) | 0x8000, mt_rand(0, 0xffff), + mt_rand(0, 0xffff), mt_rand(0, 0xffff)); +} + +?> +--EXPECT-- +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false)
\ No newline at end of file diff --git a/ext/openssl/tests/openssl_x509_fingerprint.phpt b/ext/openssl/tests/openssl_x509_fingerprint.phpt new file mode 100644 index 0000000000..6cd464a894 --- /dev/null +++ b/ext/openssl/tests/openssl_x509_fingerprint.phpt @@ -0,0 +1,47 @@ +--TEST-- +Testing openssl_x509_fingerprint() +--SKIPIF-- +<?php +if (!extension_loaded("openssl")) die("skip"); +?> +--FILE-- +<?php + +$cert = "file://" . dirname(__FILE__) . "/cert.crt"; + +echo "** Testing with no parameters **\n"; +var_dump(openssl_x509_fingerprint()); + +echo "** Testing default functionality **\n"; +var_dump(openssl_x509_fingerprint($cert)); + +echo "** Testing hash method md5 **\n"; +var_dump(openssl_x509_fingerprint($cert, 'md5')); + +echo "**Testing raw output md5 **\n"; +var_dump(bin2hex(openssl_x509_fingerprint($cert, 'md5', true))); + +echo "** Testing bad certification **\n"; +var_dump(openssl_x509_fingerprint('123')); +echo "** Testing bad hash method **\n"; +var_dump(openssl_x509_fingerprint($cert, 'xx45')); +--EXPECTF-- +** Testing with no parameters ** + +Warning: openssl_x509_fingerprint() expects at least 1 parameter, 0 given in %s on line %d +NULL +** Testing default functionality ** +string(40) "6e6fd1ea10a5a23071d61c728ee9b40df6dbc33c" +** Testing hash method md5 ** +string(32) "ac77008e172897e06c0b065294487a67" +**Testing raw output md5 ** +string(32) "ac77008e172897e06c0b065294487a67" +** Testing bad certification ** + +Warning: openssl_x509_fingerprint(): cannot get cert from parameter 1 in %s on line %d +bool(false) +** Testing bad hash method ** + +Warning: openssl_x509_fingerprint(): Unknown signature algorithm in %s on line %d +bool(false) + diff --git a/ext/openssl/tests/san-ca.pem b/ext/openssl/tests/san-ca.pem new file mode 100644 index 0000000000..88682ba2dc --- /dev/null +++ b/ext/openssl/tests/san-ca.pem @@ -0,0 +1,15 @@ +-----BEGIN CERTIFICATE----- +MIICYTCCAcqgAwIBAgIJAIaqxtY5dwjtMA0GCSqGSIb3DQEBBQUAMFMxCzAJBgNV +BAYTAlVTMQswCQYDVQQIEwJNTjEUMBIGA1UEBxMLTWlubmVhcG9saXMxITAfBgNV +BAsTGERvbWFpbiBDb250cm9sIFZhbGlkYXRlZDAeFw0xMzA5MjQwODA1NTFaFw0y +MTEyMTEwODA1NTFaMFMxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJNTjEUMBIGA1UE +BxMLTWlubmVhcG9saXMxITAfBgNVBAsTGERvbWFpbiBDb250cm9sIFZhbGlkYXRl +ZDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAsFGqfbU/8D+KjroQl4XMyt9m +dcSP7iZtqphOu9nVZxYAAqfaqj8FnC/pwYV3TU6ZHndLTQAllwYT3sQBQPPGmZQ9 +clSIMEL003t3pi4ZVXkttG6Vvr+Z9PBcHhlKLQ7WMHnn4qctllWXTSoyTQpkETF3 +Fc3mrG5G37BhoUno7NECAwEAAaM9MDswOQYDVR0RBDIwMIILZXhhbXBsZS5vcmeC +D3d3dy5leGFtcGxlLm9yZ4IQdGVzdC5leGFtcGxlLm9yZzANBgkqhkiG9w0BAQUF +AAOBgQBf/FZhzheIcQJ+dyTk8xQ/nJLvpmBhbd1LNtfwk/MsC9UHsz4QXs9sBw1k +rH0FjoqgM6avj7zKHJFTj6q7Rd+OX5V4HynYPhX67sWbN3KWEHffL98nGGd/bo3X +pSjNk5vnyKYiwdUUe11Ac9csh0HcSBbhOYjy0T/i9AlQcKbuCg== +-----END CERTIFICATE----- diff --git a/ext/openssl/tests/san-cert.pem b/ext/openssl/tests/san-cert.pem new file mode 100644 index 0000000000..923d490e72 --- /dev/null +++ b/ext/openssl/tests/san-cert.pem @@ -0,0 +1,31 @@ +-----BEGIN CERTIFICATE----- +MIICYTCCAcqgAwIBAgIJAIaqxtY5dwjtMA0GCSqGSIb3DQEBBQUAMFMxCzAJBgNV +BAYTAlVTMQswCQYDVQQIEwJNTjEUMBIGA1UEBxMLTWlubmVhcG9saXMxITAfBgNV +BAsTGERvbWFpbiBDb250cm9sIFZhbGlkYXRlZDAeFw0xMzA5MjQwODA1NTFaFw0y +MTEyMTEwODA1NTFaMFMxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJNTjEUMBIGA1UE +BxMLTWlubmVhcG9saXMxITAfBgNVBAsTGERvbWFpbiBDb250cm9sIFZhbGlkYXRl +ZDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAsFGqfbU/8D+KjroQl4XMyt9m +dcSP7iZtqphOu9nVZxYAAqfaqj8FnC/pwYV3TU6ZHndLTQAllwYT3sQBQPPGmZQ9 +clSIMEL003t3pi4ZVXkttG6Vvr+Z9PBcHhlKLQ7WMHnn4qctllWXTSoyTQpkETF3 +Fc3mrG5G37BhoUno7NECAwEAAaM9MDswOQYDVR0RBDIwMIILZXhhbXBsZS5vcmeC +D3d3dy5leGFtcGxlLm9yZ4IQdGVzdC5leGFtcGxlLm9yZzANBgkqhkiG9w0BAQUF +AAOBgQBf/FZhzheIcQJ+dyTk8xQ/nJLvpmBhbd1LNtfwk/MsC9UHsz4QXs9sBw1k +rH0FjoqgM6avj7zKHJFTj6q7Rd+OX5V4HynYPhX67sWbN3KWEHffL98nGGd/bo3X +pSjNk5vnyKYiwdUUe11Ac9csh0HcSBbhOYjy0T/i9AlQcKbuCg== +-----END CERTIFICATE----- +-----BEGIN PRIVATE KEY----- +MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBALBRqn21P/A/io66 +EJeFzMrfZnXEj+4mbaqYTrvZ1WcWAAKn2qo/BZwv6cGFd01OmR53S00AJZcGE97E +AUDzxpmUPXJUiDBC9NN7d6YuGVV5LbRulb6/mfTwXB4ZSi0O1jB55+KnLZZVl00q +Mk0KZBExdxXN5qxuRt+wYaFJ6OzRAgMBAAECgYB11e5iWvqjPmQEZRdnnJU0VD8u +n7ItT+Nk6qtb4gY8Abj6DWIW+01th5vqqJ8FvGyartFVYa69kuM+srG/zevAZWeu +fGZtwiwZR4DRSyRcPp4rnNiksK3dkAZA6UewmRDPv8uyHJlXc5i+Ft1ILJ5Q5jgn +UkC4z3EJP5Se9KZywQJBAOO4lRq42wLsYr2SDrQDSs4leie3FKc2bgvjF7Djosh1 +ZYbf55F5b9w1zgnccmni2HkqOnyFu4SKarmXyCsYxrkCQQDGNvnUh7/zZswrdWZ/ +PMp9zVDTh/5Oc2B4ByNLw1ERDwYhjchKgPRlQvn4cp3Pwf3UYPQ/8XGXzzEJey3A +r0rZAkBf/tDEOgcBPXsGZQrTscuYCU5sbY5ESvqrAilbhSp7DJom+D5bIfEYyIm5 +uHd20Yzlzvpmwc1huyPwZt6X5FLpAkATDReoGMAXSesXxjnqwtIHk2NQYYLM0YQV +JUJ8NrKk/Bevw+vbVVeoH+7ctU97t36JGiR/vNoZKD3jVmaIXZDJAkEA4wJbwzIo +L32mu9VmZa7wjmfkraQEmXTPaA5D9lNC0AwRTgkj+x2Qe1vawNblNK9PPLBDdplQ +L//53ADq/wv5rA== +-----END PRIVATE KEY----- diff --git a/ext/openssl/tests/san_peer_matching.phpt b/ext/openssl/tests/san_peer_matching.phpt new file mode 100644 index 0000000000..4e6531d6cc --- /dev/null +++ b/ext/openssl/tests/san_peer_matching.phpt @@ -0,0 +1,60 @@ +--TEST-- +Peer verification matches SAN names +--SKIPIF-- +<?php +if (!extension_loaded("openssl")) die("skip"); +if (!function_exists('pcntl_fork')) die("skip no fork"); +--FILE-- +<?php +$context = stream_context_create(array( + 'ssl' => array( + 'local_cert' => __DIR__ . '/san-cert.pem', + 'allow_self_signed' => true, + ), +)); + +$server = stream_socket_server('ssl://127.0.0.1:64321', $errno, $errstr, + STREAM_SERVER_BIND|STREAM_SERVER_LISTEN, $context); + + +$pid = pcntl_fork(); +if ($pid == -1) { + die('could not fork'); +} else if ($pid) { + $contextC = stream_context_create( + array( + 'ssl' => array( + 'verify_peer' => true, + 'cafile' => __DIR__ . '/san-ca.pem', + 'CN_match' => 'example.org', + ) + ) + ); + var_dump(stream_socket_client("ssl://127.0.0.1:64321", $errno, $errstr, 1, + STREAM_CLIENT_CONNECT, $contextC)); + + $contextC = stream_context_create(array( + 'ssl' => array( + 'verify_peer' => true, + 'cafile' => __DIR__ . '/san-ca.pem', + 'CN_match' => 'moar.example.org', + ) + )); + + var_dump(stream_socket_client("ssl://127.0.0.1:64321", $errno, $errstr, 1, + STREAM_CLIENT_CONNECT, $contextC)); + +} else { + @pcntl_wait($status); + @stream_socket_accept($server, 1); + @stream_socket_accept($server, 1); +} +--EXPECTF-- +resource(%d) of type (stream) + +Warning: stream_socket_client(): Unable to locate peer certificate CN in %s on line %d + +Warning: stream_socket_client(): Failed to enable crypto in %s on line %d + +Warning: stream_socket_client(): unable to connect to ssl://127.0.0.1:64321 (Unknown error) in %s on line %d +bool(false) diff --git a/ext/openssl/tests/streams_crypto_method.pem b/ext/openssl/tests/streams_crypto_method.pem new file mode 100644 index 0000000000..9d754d460d --- /dev/null +++ b/ext/openssl/tests/streams_crypto_method.pem @@ -0,0 +1,33 @@ +-----BEGIN CERTIFICATE----- +MIIC5jCCAk+gAwIBAgIBADANBgkqhkiG9w0BAQQFADBcMQswCQYDVQQGEwJBVTET +MBEGA1UECBMKUXVlZW5zbGFuZDEaMBgGA1UEChMRQ3J5cHRTb2Z0IFB0eSBMdGQx +HDAaBgNVBAMTE1Rlc3QgUENBICgxMDI0IGJpdCkwHhcNOTkxMjAyMjEzNTQ4WhcN +MDUwNzExMjEzNTQ4WjBcMQswCQYDVQQGEwJBVTETMBEGA1UECBMKUXVlZW5zbGFu +ZDEaMBgGA1UEChMRQ3J5cHRTb2Z0IFB0eSBMdGQxHDAaBgNVBAMTE1Rlc3QgUENB +ICgxMDI0IGJpdCkwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAJ2haT/f5Zwy +V+MiuSDjSR62adBoSiBB7Usty44lXqsp9RICw+DCCxpsn/CfxPEDXLLd4olsWXc6 +JRcxGynbYmnzk+Z6aIPPJQhK3CTvaqGnWKZsA1m+WaUIUqJCuNTK4N+7hMAGaf6S +S3e9HVgEQ4a34gXJ7VQFVIBNV1EnZRWHAgMBAAGjgbcwgbQwHQYDVR0OBBYEFE0R +aEcrj18q1dw+G6nJbsTWR213MIGEBgNVHSMEfTB7gBRNEWhHK49fKtXcPhupyW7E +1kdtd6FgpF4wXDELMAkGA1UEBhMCQVUxEzARBgNVBAgTClF1ZWVuc2xhbmQxGjAY +BgNVBAoTEUNyeXB0U29mdCBQdHkgTHRkMRwwGgYDVQQDExNUZXN0IFBDQSAoMTAy +NCBiaXQpggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEEBQADgYEAUa8B3pho ++Mvxeq9HsEzJxHIFQla05S5J/e/V+DQTYoKiRFchKPrDAdrzYSEvP3h4QJEtsNqQ +JfOxg5M42uLFq7aPGWkF6ZZqZsYS+zA9IVT14g7gNA6Ne+5QtJqQtH9HA24st0T0 +Tga/lZ9M2ovImovaxSL/kRHbpCWcqWVxpOw= +-----END CERTIFICATE----- +-----BEGIN RSA PRIVATE KEY----- +MIICXAIBAAKBgQCdoWk/3+WcMlfjIrkg40ketmnQaEogQe1LLcuOJV6rKfUSAsPg +wgsabJ/wn8TxA1yy3eKJbFl3OiUXMRsp22Jp85PmemiDzyUIStwk72qhp1imbANZ +vlmlCFKiQrjUyuDfu4TABmn+kkt3vR1YBEOGt+IFye1UBVSATVdRJ2UVhwIDAQAB +AoGAba4fTtuap5l7/8ZsbE7Z1O32KJY4ZcOZukLOLUUhXxXduT+FTgGWujc0/rgc +z9qYCLlNZHOouMYTgtSfYvuMuLZ11VIt0GYH+nRioLShE59Yy+zCRyC+gPigS1kz +xvo14AsOIPYV14Tk/SsHyq6E0eTk7VzaIE197giiINUERPECQQDSKmtPTh/lRKw7 +HSZSM0I1mFWn/1zqrAbontRQY5w98QWIOe5qmzYyFbPXYT3d9BzlsMyhgiRNoBbD +yvohSHXJAkEAwAHx6ezAZeWWzD5yXD36nyjpkVCw7Tk7TSmOceLJMWt1QcrCfqlS +xA5jjpQ6Z8suU5DdtWAryM2sAir1WisYzwJAd6Zcx56jvAQ3xcPXsE6scBTVFzrj +7FqZ6E+cclPzfLQ+QQsyOBE7bpI6e/FJppY26XGZXo3YGzV8IGXrt40oOQJALETG +h86EFXo3qGOFbmsDy4pdP5nBERCu8X1xUCSfintiD4c2DInxgS5oGclnJeMcjTvL +QjQoJCX3UJCi/OUO1QJBAKgcDHWjMvt+l1pjJBsSEZ0HX9AAIIVx0RQmbFGS+F2Q +hhu5l77WnnZOQ9vvhV5u7NPCUF9nhU3jh60qWWO8mkc= +-----END RSA PRIVATE KEY----- diff --git a/ext/openssl/tests/streams_crypto_method.phpt b/ext/openssl/tests/streams_crypto_method.phpt new file mode 100644 index 0000000000..97a6e9ee8b --- /dev/null +++ b/ext/openssl/tests/streams_crypto_method.phpt @@ -0,0 +1,77 @@ +--TEST-- +Specific crypto method for ssl:// transports. +--SKIPIF-- +<?php +if (!extension_loaded('openssl')) die('skip, openssl required'); +if (!extension_loaded('pcntl')) die('skip, pcntl required'); +?> +--FILE-- +<?php +function client($port, $method) { + $ctx = stream_context_create(); + stream_context_set_option($ctx, 'ssl', 'crypto_method', $method); + + $fp = @fopen('https://127.0.0.1:' . $port . '/', 'r', false, $ctx); + if ($fp) { + fpassthru($fp); + fclose($fp); + } +} + +function server($port, $transport) { + $context = stream_context_create(); + + stream_context_set_option($context, 'ssl', 'local_cert', dirname(__FILE__) . '/streams_crypto_method.pem'); + stream_context_set_option($context, 'ssl', 'allow_self_signed', true); + stream_context_set_option($context, 'ssl', 'verify_peer', false); + + $server = stream_socket_server($transport . '127.0.0.1:' . $port, $errno, $errstr, STREAM_SERVER_BIND|STREAM_SERVER_LISTEN, $context); + + $client = @stream_socket_accept($server); + + if ($client) { + $in = ''; + while (!preg_match('/\r?\n\r?\n/', $in)) { + $in .= fread($client, 2048); + } + + $response = <<<EOS +HTTP/1.1 200 OK +Content-Type: text/plain +Content-Length: 13 +Connection: close + +Hello World! + +EOS; + + fwrite($client, $response); + fclose($client); + exit(); + } +} + +$port1 = rand(15000, 16000); +$port2 = rand(16001, 17000); + +$pid1 = pcntl_fork(); +$pid2 = pcntl_fork(); + +if ($pid1 == 0 && $pid2 != 0) { + server($port1, 'sslv3://'); + exit; +} + +if ($pid1 != 0 && $pid2 == 0) { + server($port2, 'sslv3://'); + exit; +} + +client($port1, STREAM_CRYPTO_METHOD_SSLv3_CLIENT); +client($port2, STREAM_CRYPTO_METHOD_SSLv2_CLIENT); + +pcntl_waitpid($pid1, $status); +pcntl_waitpid($pid2, $status); +?> +--EXPECTF-- +Hello World! diff --git a/ext/openssl/tests/tlsv1.1_wrapper_001.phpt b/ext/openssl/tests/tlsv1.1_wrapper_001.phpt new file mode 100644 index 0000000000..56211f0b96 --- /dev/null +++ b/ext/openssl/tests/tlsv1.1_wrapper_001.phpt @@ -0,0 +1,46 @@ +--TEST-- +tlsv1.1 stream wrapper +--SKIPIF-- +<?php +if (!extension_loaded("openssl")) die("skip"); +if (OPENSSL_VERSION_NUMBER < 0x10001001) die("skip OpenSSL 1.0.1 required"); +if (!function_exists('pcntl_fork')) die("skip no fork"); +--FILE-- +<?php +$flags = STREAM_SERVER_BIND|STREAM_SERVER_LISTEN; +$ctx = stream_context_create(array('ssl' => array( + 'local_cert' => __DIR__ . '/streams_crypto_method.pem', +))); + +$server = stream_socket_server('tlsv1.1://127.0.0.1:64321', $errno, $errstr, $flags, $ctx); +var_dump($server); + +$pid = pcntl_fork(); +if ($pid == -1) { + die('could not fork'); +} elseif ($pid) { + $flags = STREAM_CLIENT_CONNECT; + $ctx = stream_context_create(array('ssl' => array( + 'verify_peer' => false + ))); + + $client = stream_socket_client("tlsv1.1://127.0.0.1:64321", $errno, $errstr, 1, $flags, $ctx); + var_dump($client); + + $client = @stream_socket_client("sslv3://127.0.0.1:64321", $errno, $errstr, 1, $flags, $ctx); + var_dump($client); + + $client = @stream_socket_client("tlsv1.2://127.0.0.1:64321", $errno, $errstr, 1, $flags, $ctx); + var_dump($client); + +} else { + @pcntl_wait($status); + for ($i=0; $i < 3; $i++) { + @stream_socket_accept($server, 1); + } +} +--EXPECTF-- +resource(%d) of type (stream) +resource(%d) of type (stream) +bool(false) +bool(false) diff --git a/ext/openssl/tests/tlsv1.2_wrapper_002.phpt b/ext/openssl/tests/tlsv1.2_wrapper_002.phpt new file mode 100644 index 0000000000..cb3f4106c7 --- /dev/null +++ b/ext/openssl/tests/tlsv1.2_wrapper_002.phpt @@ -0,0 +1,46 @@ +--TEST-- +tlsv1.2 stream wrapper +--SKIPIF-- +<?php +if (!extension_loaded("openssl")) die("skip"); +if (OPENSSL_VERSION_NUMBER < 0x10001001) die("skip OpenSSL 1.0.1 required"); +if (!function_exists('pcntl_fork')) die("skip no fork"); +--FILE-- +<?php +$flags = STREAM_SERVER_BIND|STREAM_SERVER_LISTEN; +$ctx = stream_context_create(array('ssl' => array( + 'local_cert' => __DIR__ . '/streams_crypto_method.pem', +))); + +$server = stream_socket_server('tlsv1.2://127.0.0.1:64321', $errno, $errstr, $flags, $ctx); +var_dump($server); + +$pid = pcntl_fork(); +if ($pid == -1) { + die('could not fork'); +} elseif ($pid) { + $flags = STREAM_CLIENT_CONNECT; + $ctx = stream_context_create(array('ssl' => array( + 'verify_peer' => false + ))); + + $client = stream_socket_client("tlsv1.2://127.0.0.1:64321", $errno, $errstr, 1, $flags, $ctx); + var_dump($client); + + $client = @stream_socket_client("sslv3://127.0.0.1:64321", $errno, $errstr, 1, $flags, $ctx); + var_dump($client); + + $client = @stream_socket_client("tlsv1.1://127.0.0.1:64321", $errno, $errstr, 1, $flags, $ctx); + var_dump($client); + +} else { + @pcntl_wait($status); + for ($i=0; $i < 3; $i++) { + @stream_socket_accept($server, 1); + } +} +--EXPECTF-- +resource(%d) of type (stream) +resource(%d) of type (stream) +bool(false) +bool(false) diff --git a/ext/openssl/xp_ssl.c b/ext/openssl/xp_ssl.c index 1d1c91f132..9c9f2a3592 100644 --- a/ext/openssl/xp_ssl.c +++ b/ext/openssl/xp_ssl.c @@ -309,7 +309,7 @@ static inline int php_openssl_setup_crypto(php_stream *stream, php_stream_xport_crypto_param *cparam TSRMLS_DC) { - SSL_METHOD *method; + const SSL_METHOD *method; long ssl_ctx_options = SSL_OP_ALL; if (sslsock->ssl_handle) { @@ -346,6 +346,24 @@ static inline int php_openssl_setup_crypto(php_stream *stream, sslsock->is_client = 1; method = TLSv1_client_method(); break; + case STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT: +#if OPENSSL_VERSION_NUMBER >= 0x10001001L + sslsock->is_client = 1; + method = TLSv1_1_client_method(); + break; +#else + php_error_docref(NULL TSRMLS_CC, E_WARNING, "TLSv1.1 support is not compiled into the OpenSSL library PHP is linked against"); + return -1; +#endif + case STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT: +#if OPENSSL_VERSION_NUMBER >= 0x10001001L + sslsock->is_client = 1; + method = TLSv1_2_client_method(); + break; +#else + php_error_docref(NULL TSRMLS_CC, E_WARNING, "TLSv1.2 support is not compiled into the OpenSSL library PHP is linked against"); + return -1; +#endif case STREAM_CRYPTO_METHOD_SSLv23_SERVER: sslsock->is_client = 0; method = SSLv23_server_method(); @@ -367,6 +385,24 @@ static inline int php_openssl_setup_crypto(php_stream *stream, sslsock->is_client = 0; method = TLSv1_server_method(); break; + case STREAM_CRYPTO_METHOD_TLSv1_1_SERVER: +#if OPENSSL_VERSION_NUMBER >= 0x10001001L + sslsock->is_client = 0; + method = TLSv1_1_server_method(); + break; +#else + php_error_docref(NULL TSRMLS_CC, E_WARNING, "TLSv1.1 support is not compiled into the OpenSSL library PHP is linked against"); + return -1; +#endif + case STREAM_CRYPTO_METHOD_TLSv1_2_SERVER: +#if OPENSSL_VERSION_NUMBER >= 0x10001001L + sslsock->is_client = 0; + method = TLSv1_2_server_method(); + break; +#else + php_error_docref(NULL TSRMLS_CC, E_WARNING, "TLSv1.2 support is not compiled into the OpenSSL library PHP is linked against"); + return -1; +#endif default: return -1; @@ -667,6 +703,12 @@ static inline int php_openssl_tcp_sockop_accept(php_stream *stream, php_openssl_ case STREAM_CRYPTO_METHOD_TLS_CLIENT: sock->method = STREAM_CRYPTO_METHOD_TLS_SERVER; break; + case STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT: + sock->method = STREAM_CRYPTO_METHOD_TLSv1_1_SERVER; + break; + case STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT: + sock->method = STREAM_CRYPTO_METHOD_TLSv1_2_SERVER; + break; default: break; } @@ -853,8 +895,32 @@ php_stream_ops php_openssl_socket_ops = { php_openssl_sockop_set_option, }; -static char * get_sni(php_stream_context *ctx, char *resourcename, long resourcenamelen, int is_persistent TSRMLS_DC) { +static int get_crypto_method(php_stream_context *ctx) { + if (ctx) { + zval **val = NULL; + long crypto_method; + + if (php_stream_context_get_option(ctx, "ssl", "crypto_method", &val) == SUCCESS) { + convert_to_long_ex(val); + crypto_method = (long)Z_LVAL_PP(val); + + switch (crypto_method) { + case STREAM_CRYPTO_METHOD_SSLv2_CLIENT: + case STREAM_CRYPTO_METHOD_SSLv3_CLIENT: + case STREAM_CRYPTO_METHOD_SSLv23_CLIENT: + case STREAM_CRYPTO_METHOD_TLS_CLIENT: + case STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT: + case STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT: + return crypto_method; + } + + } + } + + return STREAM_CRYPTO_METHOD_SSLv23_CLIENT; +} +static char * get_sni(php_stream_context *ctx, const char *resourcename, size_t resourcenamelen, int is_persistent TSRMLS_DC) { php_url *url; if (ctx) { @@ -900,8 +966,8 @@ static char * get_sni(php_stream_context *ctx, char *resourcename, long resource return NULL; } -php_stream *php_openssl_ssl_socket_factory(const char *proto, long protolen, - char *resourcename, long resourcenamelen, +php_stream *php_openssl_ssl_socket_factory(const char *proto, size_t protolen, + const char *resourcename, size_t resourcenamelen, const char *persistent_id, int options, int flags, struct timeval *timeout, php_stream_context *context STREAMS_DC TSRMLS_DC) @@ -939,7 +1005,12 @@ php_stream *php_openssl_ssl_socket_factory(const char *proto, long protolen, if (strncmp(proto, "ssl", protolen) == 0) { sslsock->enable_on_connect = 1; - sslsock->method = STREAM_CRYPTO_METHOD_SSLv23_CLIENT; + + /* General ssl:// transports can use a number + * of crypto methods. The actual methhod can be + * provided in the streams context options. + */ + sslsock->method = get_crypto_method(context); } else if (strncmp(proto, "sslv2", protolen) == 0) { #ifdef OPENSSL_NO_SSL2 php_error_docref(NULL TSRMLS_CC, E_WARNING, "SSLv2 support is not compiled into the OpenSSL library PHP is linked against"); @@ -954,8 +1025,24 @@ php_stream *php_openssl_ssl_socket_factory(const char *proto, long protolen, } else if (strncmp(proto, "tls", protolen) == 0) { sslsock->enable_on_connect = 1; sslsock->method = STREAM_CRYPTO_METHOD_TLS_CLIENT; + } else if (strncmp(proto, "tlsv1.1", protolen) == 0) { +#if OPENSSL_VERSION_NUMBER >= 0x10001001L + sslsock->enable_on_connect = 1; + sslsock->method = STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT; +#else + php_error_docref(NULL TSRMLS_CC, E_WARNING, "TLSv1.1 support is not compiled into the OpenSSL library PHP is linked against"); + return NULL; +#endif + } else if (strncmp(proto, "tlsv1.2", protolen) == 0) { +#if OPENSSL_VERSION_NUMBER >= 0x10001001L + sslsock->enable_on_connect = 1; + sslsock->method = STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT; +#else + php_error_docref(NULL TSRMLS_CC, E_WARNING, "TLSv1.2 support is not compiled into the OpenSSL library PHP is linked against"); + return NULL; +#endif } - + return stream; } diff --git a/ext/pcre/php_pcre.c b/ext/pcre/php_pcre.c index 7d34d9feb1..1e882910d4 100644 --- a/ext/pcre/php_pcre.c +++ b/ext/pcre/php_pcre.c @@ -1343,6 +1343,7 @@ static void preg_replace_impl(INTERNAL_FUNCTION_PARAMETERS, int is_callable_repl int limit_val = -1; long limit = -1; char *string_key; + uint string_key_len; ulong num_key; char *callback_name; int replace_count=0, old_replace_count; @@ -1394,10 +1395,10 @@ static void preg_replace_impl(INTERNAL_FUNCTION_PARAMETERS, int is_callable_repl if ((result = php_replace_in_subject(*regex, *replace, subject_entry, &result_len, limit_val, is_callable_replace, &replace_count TSRMLS_CC)) != NULL) { if (!is_filter || replace_count > old_replace_count) { /* Add to return array */ - switch(zend_hash_get_current_key(Z_ARRVAL_PP(subject), &string_key, &num_key, 0)) + switch(zend_hash_get_current_key_ex(Z_ARRVAL_PP(subject), &string_key, &string_key_len, &num_key, 0, NULL)) { case HASH_KEY_IS_STRING: - add_assoc_stringl(return_value, string_key, result, result_len, 0); + add_assoc_stringl_ex(return_value, string_key, string_key_len, result, result_len, 0); break; case HASH_KEY_IS_LONG: @@ -1770,6 +1771,7 @@ PHPAPI void php_pcre_grep_impl(pcre_cache_entry *pce, zval *input, zval *return int size_offsets; /* Size of the offsets array */ int count = 0; /* Count of matched subpatterns */ char *string_key; + uint string_key_len; ulong num_key; zend_bool invert; /* Whether to return non-matching entries */ @@ -1828,11 +1830,11 @@ PHPAPI void php_pcre_grep_impl(pcre_cache_entry *pce, zval *input, zval *return Z_ADDREF_PP(entry); /* Add to return array */ - switch (zend_hash_get_current_key(Z_ARRVAL_P(input), &string_key, &num_key, 0)) + switch (zend_hash_get_current_key_ex(Z_ARRVAL_P(input), &string_key, &string_key_len, &num_key, 0, NULL)) { case HASH_KEY_IS_STRING: zend_hash_update(Z_ARRVAL_P(return_value), string_key, - strlen(string_key)+1, entry, sizeof(zval *), NULL); + string_key_len, entry, sizeof(zval *), NULL); break; case HASH_KEY_IS_LONG: diff --git a/ext/pdo/Makefile.frag b/ext/pdo/Makefile.frag index 5ba5f80840..dc25c9f70b 100644 --- a/ext/pdo/Makefile.frag +++ b/ext/pdo/Makefile.frag @@ -2,7 +2,8 @@ phpincludedir=$(prefix)/include/php PDO_HEADER_FILES= \ php_pdo.h \ - php_pdo_driver.h + php_pdo_driver.h \ + php_pdo_error.h $(srcdir)/pdo_sql_parser.c: $(srcdir)/pdo_sql_parser.re diff --git a/ext/pdo/pdo_dbh.c b/ext/pdo/pdo_dbh.c index ac8d29a95c..67c6c58ed9 100644 --- a/ext/pdo/pdo_dbh.c +++ b/ext/pdo/pdo_dbh.c @@ -101,7 +101,7 @@ void pdo_raise_impl_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt, const char *sqlstate } /* }}} */ -void pdo_handle_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt TSRMLS_DC) /* {{{ */ +PDO_API void pdo_handle_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt TSRMLS_DC) /* {{{ */ { pdo_error_type *pdo_err = &dbh->error_code; const char *msg = "<<Unknown>>"; @@ -1328,16 +1328,12 @@ int pdo_hash_methods(pdo_dbh_t *dbh, int kind TSRMLS_DC) } else { ifunc->required_num_args = info->required_num_args; } - if (info->pass_rest_by_reference) { - if (info->pass_rest_by_reference == ZEND_SEND_PREFER_REF) { - ifunc->fn_flags |= ZEND_ACC_PASS_REST_PREFER_REF; - } else { - ifunc->fn_flags |= ZEND_ACC_PASS_REST_BY_REFERENCE; - } - } if (info->return_reference) { ifunc->fn_flags |= ZEND_ACC_RETURN_REFERENCE; } + if (funcs->arg_info[funcs->num_args].is_variadic) { + ifunc->fn_flags |= ZEND_ACC_VARIADIC; + } } else { ifunc->arg_info = NULL; ifunc->num_args = 0; diff --git a/ext/pdo/php_pdo_error.h b/ext/pdo/php_pdo_error.h new file mode 100644 index 0000000000..387436af8f --- /dev/null +++ b/ext/pdo/php_pdo_error.h @@ -0,0 +1,47 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 5 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997-2013 The PHP Group | + +----------------------------------------------------------------------+ + | 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 | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Author: Wez Furlong <wez@php.net> | + +----------------------------------------------------------------------+ +*/ + +/* $Id$ */ + +#ifndef PHP_PDO_ERROR_H +#define PHP_PDO_ERROR_H + +#include "php_pdo_driver.h" + +PDO_API void pdo_handle_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt TSRMLS_DC); + +#define PDO_DBH_CLEAR_ERR() do { \ + strlcpy(dbh->error_code, PDO_ERR_NONE, sizeof(PDO_ERR_NONE)); \ + if (dbh->query_stmt) { \ + dbh->query_stmt = NULL; \ + zend_objects_store_del_ref(&dbh->query_stmt_zval TSRMLS_CC); \ + } \ +} while (0) +#define PDO_STMT_CLEAR_ERR() strcpy(stmt->error_code, PDO_ERR_NONE) +#define PDO_HANDLE_DBH_ERR() if (strcmp(dbh->error_code, PDO_ERR_NONE)) { pdo_handle_error(dbh, NULL TSRMLS_CC); } +#define PDO_HANDLE_STMT_ERR() if (strcmp(stmt->error_code, PDO_ERR_NONE)) { pdo_handle_error(stmt->dbh, stmt TSRMLS_CC); } + +#endif /* PHP_PDO_ERROR_H */ +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim600: noet sw=4 ts=4 fdm=marker + * vim<600: noet sw=4 ts=4 + */ diff --git a/ext/pdo/php_pdo_int.h b/ext/pdo/php_pdo_int.h index 91d0bf0412..59dbaf9b01 100644 --- a/ext/pdo/php_pdo_int.h +++ b/ext/pdo/php_pdo_int.h @@ -23,6 +23,8 @@ /* Stuff private to the PDO extension and not for consumption by PDO drivers * */ +#include "php_pdo_error.h" + extern HashTable pdo_driver_hash; extern zend_class_entry *pdo_exception_ce; PDO_API zend_class_entry *php_pdo_get_exception_base(int root TSRMLS_DC); @@ -55,19 +57,6 @@ zend_object_iterator *php_pdo_dbstmt_iter_get(zend_class_entry *ce, zval *object extern pdo_driver_t *pdo_find_driver(const char *name, int namelen); -extern void pdo_handle_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt TSRMLS_DC); - -#define PDO_DBH_CLEAR_ERR() do { \ - strlcpy(dbh->error_code, PDO_ERR_NONE, sizeof(PDO_ERR_NONE)); \ - if (dbh->query_stmt) { \ - dbh->query_stmt = NULL; \ - zend_objects_store_del_ref(&dbh->query_stmt_zval TSRMLS_CC); \ - } \ -} while (0) -#define PDO_STMT_CLEAR_ERR() strcpy(stmt->error_code, PDO_ERR_NONE) -#define PDO_HANDLE_DBH_ERR() if (strcmp(dbh->error_code, PDO_ERR_NONE)) { pdo_handle_error(dbh, NULL TSRMLS_CC); } -#define PDO_HANDLE_STMT_ERR() if (strcmp(stmt->error_code, PDO_ERR_NONE)) { pdo_handle_error(stmt->dbh, stmt TSRMLS_CC); } - int pdo_sqlstate_init_error_table(void); void pdo_sqlstate_fini_error_table(void); const char *pdo_sqlstate_state_to_description(char *state); diff --git a/ext/pdo_firebird/CREDITS b/ext/pdo_firebird/CREDITS index a33294b69c..60b917415d 100644 --- a/ext/pdo_firebird/CREDITS +++ b/ext/pdo_firebird/CREDITS @@ -1,2 +1,2 @@ -Firebird/InterBase driver for PDO +Firebird driver for PDO Ard Biesheuvel diff --git a/ext/pdo_firebird/package2.xml b/ext/pdo_firebird/package2.xml index 5b5984c80f..b744d388bc 100644 --- a/ext/pdo_firebird/package2.xml +++ b/ext/pdo_firebird/package2.xml @@ -5,9 +5,9 @@ http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd"> <name>PDO_FIREBIRD</name> <channel>pecl.php.net</channel> - <summary>Firebird/InterBase 6 driver for PDO</summary> - <description>This extension provides a Firebird/InterBase driver for PDO. It supports -all versions of Firebird and InterBase versions 6 and up. + <summary>Firebird driver for PDO</summary> + <description>This extension provides a Firebird driver for PDO. It supports +all versions of Firebird 2.1 and up. </description> <lead> <name>Ard Biesheuvel</name> @@ -15,18 +15,17 @@ all versions of Firebird and InterBase versions 6 and up. <email>abies@php.net</email> <active>yes</active> </lead> - <date>2006-05-01</date> + <date>2013-09-01</date> <version> - <release>0.3</release> - <api>0.3</api> + <release>1.0</release> + <api>1.0</api> </version> <stability> - <release>beta</release> - <api>beta</api> + <release>stable</release> + <api>stable</api> </stability> <license uri="http://www.php.net/license">PHP</license> - <notes>To compile and run this module, you will need to have the main PDO module and Firebird's -or InterBase's client library installed on your system. + <notes>To compile and run this module, you will need to have the main PDO module and Firebird's client library installed on your system. Hope it works! </notes> <contents> @@ -49,7 +48,7 @@ Hope it works! <dependencies> <required> <php> - <min>5.0.3</min> + <min>5.3.27</min> </php> <pearinstaller> <min>1.4.0</min> diff --git a/ext/pdo_pgsql/pgsql_driver.c b/ext/pdo_pgsql/pgsql_driver.c index 50136430a0..cb89809f02 100644 --- a/ext/pdo_pgsql/pgsql_driver.c +++ b/ext/pdo_pgsql/pgsql_driver.c @@ -27,8 +27,10 @@ #include "php.h" #include "php_ini.h" #include "ext/standard/info.h" +#include "main/php_network.h" #include "pdo/php_pdo.h" #include "pdo/php_pdo_driver.h" +#include "pdo/php_pdo_error.h" #include "ext/standard/file.h" #undef PACKAGE_BUGREPORT @@ -60,7 +62,7 @@ static char * _pdo_pgsql_trim_message(const char *message, int persistent) return tmp; } -int _pdo_pgsql_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt, int errcode, const char *sqlstate, const char *file, int line TSRMLS_DC) /* {{{ */ +int _pdo_pgsql_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt, int errcode, const char *sqlstate, const char *msg, const char *file, int line TSRMLS_DC) /* {{{ */ { pdo_pgsql_db_handle *H = (pdo_pgsql_db_handle *)dbh->driver_data; pdo_error_type *pdo_err = stmt ? &stmt->error_code : &dbh->error_code; @@ -83,7 +85,10 @@ int _pdo_pgsql_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt, int errcode, const char * strcpy(*pdo_err, sqlstate); } - if (errmsg) { + if (msg) { + einfo->errmsg = estrdup(msg); + } + else if (errmsg) { einfo->errmsg = _pdo_pgsql_trim_message(errmsg, dbh->is_persistent); } @@ -91,7 +96,7 @@ int _pdo_pgsql_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt, int errcode, const char * zend_throw_exception_ex(php_pdo_get_exception(), einfo->errcode TSRMLS_CC, "SQLSTATE[%s] [%d] %s", *pdo_err, einfo->errcode, einfo->errmsg); } - + return errcode; } /* }}} */ @@ -535,11 +540,13 @@ static PHP_METHOD(PDO, pgsqlCopyFromArray) dbh = zend_object_store_get_object(getThis() TSRMLS_CC); PDO_CONSTRUCT_CHECK; + PDO_DBH_CLEAR_ERR(); + /* using pre-9.0 syntax as PDO_pgsql is 7.4+ compatible */ if (pg_fields) { - spprintf(&query, 0, "COPY %s (%s) FROM STDIN DELIMITERS E'%c' WITH NULL AS E'%s'", table_name, pg_fields, (pg_delim_len ? *pg_delim : '\t'), (pg_null_as_len ? pg_null_as : "\\\\N")); + spprintf(&query, 0, "COPY %s (%s) FROM STDIN WITH DELIMITER E'%c' NULL AS E'%s'", table_name, pg_fields, (pg_delim_len ? *pg_delim : '\t'), (pg_null_as_len ? pg_null_as : "\\\\N")); } else { - spprintf(&query, 0, "COPY %s FROM STDIN DELIMITERS E'%c' WITH NULL AS E'%s'", table_name, (pg_delim_len ? *pg_delim : '\t'), (pg_null_as_len ? pg_null_as : "\\\\N")); + spprintf(&query, 0, "COPY %s FROM STDIN WITH DELIMITER E'%c' NULL AS E'%s'", table_name, (pg_delim_len ? *pg_delim : '\t'), (pg_null_as_len ? pg_null_as : "\\\\N")); } /* Obtain db Handle */ @@ -583,7 +590,8 @@ static PHP_METHOD(PDO, pgsqlCopyFromArray) query[query_len] = '\0'; if (PQputCopyData(H->server, query, query_len) != 1) { efree(query); - pdo_pgsql_error(dbh, PGRES_FATAL_ERROR, "copy failed"); + pdo_pgsql_error(dbh, PGRES_FATAL_ERROR, NULL); + PDO_HANDLE_DBH_ERR(); RETURN_FALSE; } zend_hash_move_forward_ex(Z_ARRVAL_P(pg_rows), &pos); @@ -593,22 +601,25 @@ static PHP_METHOD(PDO, pgsqlCopyFromArray) } if (PQputCopyEnd(H->server, NULL) != 1) { - pdo_pgsql_error(dbh, PGRES_FATAL_ERROR, "putcopyend failed"); + pdo_pgsql_error(dbh, PGRES_FATAL_ERROR, NULL); + PDO_HANDLE_DBH_ERR(); RETURN_FALSE; } while ((pgsql_result = PQgetResult(H->server))) { if (PGRES_COMMAND_OK != PQresultStatus(pgsql_result)) { - pdo_pgsql_error(dbh, PGRES_FATAL_ERROR, "Copy command failed"); + pdo_pgsql_error(dbh, PGRES_FATAL_ERROR, pdo_pgsql_sqlstate(pgsql_result)); command_failed = 1; } PQclear(pgsql_result); } + PDO_HANDLE_DBH_ERR(); RETURN_BOOL(!command_failed); } else { + pdo_pgsql_error(dbh, PGRES_FATAL_ERROR, pdo_pgsql_sqlstate(pgsql_result)); PQclear(pgsql_result); - pdo_pgsql_error(dbh, PGRES_FATAL_ERROR, "Copy command failed"); + PDO_HANDLE_DBH_ERR(); RETURN_FALSE; } } @@ -637,17 +648,20 @@ static PHP_METHOD(PDO, pgsqlCopyFromFile) /* Obtain db Handler */ dbh = zend_object_store_get_object(getThis() TSRMLS_CC); PDO_CONSTRUCT_CHECK; + PDO_DBH_CLEAR_ERR(); - stream = php_stream_open_wrapper_ex(filename, "rb", ENFORCE_SAFE_MODE | REPORT_ERRORS, NULL, FG(default_context)); + stream = php_stream_open_wrapper_ex(filename, "rb", ENFORCE_SAFE_MODE, NULL, FG(default_context)); if (!stream) { - pdo_pgsql_error(dbh, PGRES_FATAL_ERROR, "Unable to open the file"); + pdo_pgsql_error_msg(dbh, PGRES_FATAL_ERROR, "Unable to open the file"); + PDO_HANDLE_DBH_ERR(); RETURN_FALSE; } + /* using pre-9.0 syntax as PDO_pgsql is 7.4+ compatible */ if (pg_fields) { - spprintf(&query, 0, "COPY %s (%s) FROM STDIN DELIMITERS E'%c' WITH NULL AS E'%s'", table_name, pg_fields, (pg_delim_len ? *pg_delim : '\t'), (pg_null_as_len ? pg_null_as : "\\\\N")); + spprintf(&query, 0, "COPY %s (%s) FROM STDIN WITH DELIMITER E'%c' NULL AS E'%s'", table_name, pg_fields, (pg_delim_len ? *pg_delim : '\t'), (pg_null_as_len ? pg_null_as : "\\\\N")); } else { - spprintf(&query, 0, "COPY %s FROM STDIN DELIMITERS E'%c' WITH NULL AS E'%s'", table_name, (pg_delim_len ? *pg_delim : '\t'), (pg_null_as_len ? pg_null_as : "\\\\N")); + spprintf(&query, 0, "COPY %s FROM STDIN WITH DELIMITER E'%c' NULL AS E'%s'", table_name, (pg_delim_len ? *pg_delim : '\t'), (pg_null_as_len ? pg_null_as : "\\\\N")); } H = (pdo_pgsql_db_handle *)dbh->driver_data; @@ -674,8 +688,9 @@ static PHP_METHOD(PDO, pgsqlCopyFromFile) while ((buf = php_stream_get_line(stream, NULL, 0, &line_len)) != NULL) { if (PQputCopyData(H->server, buf, line_len) != 1) { efree(buf); - pdo_pgsql_error(dbh, PGRES_FATAL_ERROR, "copy failed"); + pdo_pgsql_error(dbh, PGRES_FATAL_ERROR, NULL); php_stream_close(stream); + PDO_HANDLE_DBH_ERR(); RETURN_FALSE; } efree(buf); @@ -683,23 +698,26 @@ static PHP_METHOD(PDO, pgsqlCopyFromFile) php_stream_close(stream); if (PQputCopyEnd(H->server, NULL) != 1) { - pdo_pgsql_error(dbh, PGRES_FATAL_ERROR, "putcopyend failed"); + pdo_pgsql_error(dbh, PGRES_FATAL_ERROR, NULL); + PDO_HANDLE_DBH_ERR(); RETURN_FALSE; } while ((pgsql_result = PQgetResult(H->server))) { if (PGRES_COMMAND_OK != PQresultStatus(pgsql_result)) { - pdo_pgsql_error(dbh, PGRES_FATAL_ERROR, "Copy command failed"); + pdo_pgsql_error(dbh, PGRES_FATAL_ERROR, pdo_pgsql_sqlstate(pgsql_result)); command_failed = 1; } PQclear(pgsql_result); } + PDO_HANDLE_DBH_ERR(); RETURN_BOOL(!command_failed); } else { - PQclear(pgsql_result); php_stream_close(stream); - pdo_pgsql_error(dbh, PGRES_FATAL_ERROR, "Copy command failed"); + pdo_pgsql_error(dbh, PGRES_FATAL_ERROR, pdo_pgsql_sqlstate(pgsql_result)); + PQclear(pgsql_result); + PDO_HANDLE_DBH_ERR(); RETURN_FALSE; } } @@ -730,12 +748,14 @@ static PHP_METHOD(PDO, pgsqlCopyToFile) dbh = zend_object_store_get_object(getThis() TSRMLS_CC); PDO_CONSTRUCT_CHECK; + PDO_DBH_CLEAR_ERR(); H = (pdo_pgsql_db_handle *)dbh->driver_data; - stream = php_stream_open_wrapper_ex(filename, "wb", ENFORCE_SAFE_MODE | REPORT_ERRORS, NULL, FG(default_context)); + stream = php_stream_open_wrapper_ex(filename, "wb", ENFORCE_SAFE_MODE, NULL, FG(default_context)); if (!stream) { - pdo_pgsql_error(dbh, PGRES_FATAL_ERROR, "Unable to open the file for writing"); + pdo_pgsql_error_msg(dbh, PGRES_FATAL_ERROR, "Unable to open the file for writing"); + PDO_HANDLE_DBH_ERR(); RETURN_FALSE; } @@ -743,10 +763,11 @@ static PHP_METHOD(PDO, pgsqlCopyToFile) PQclear(pgsql_result); } + /* using pre-9.0 syntax as PDO_pgsql is 7.4+ compatible */ if (pg_fields) { - spprintf(&query, 0, "COPY %s (%s) TO STDIN DELIMITERS E'%c' WITH NULL AS E'%s'", table_name, pg_fields, (pg_delim_len ? *pg_delim : '\t'), (pg_null_as_len ? pg_null_as : "\\\\N")); + spprintf(&query, 0, "COPY %s (%s) TO STDIN WITH DELIMITER E'%c' NULL AS E'%s'", table_name, pg_fields, (pg_delim_len ? *pg_delim : '\t'), (pg_null_as_len ? pg_null_as : "\\\\N")); } else { - spprintf(&query, 0, "COPY %s TO STDIN DELIMITERS E'%c' WITH NULL AS E'%s'", table_name, (pg_delim_len ? *pg_delim : '\t'), (pg_null_as_len ? pg_null_as : "\\\\N")); + spprintf(&query, 0, "COPY %s TO STDIN WITH DELIMITER E'%c' NULL AS E'%s'", table_name, (pg_delim_len ? *pg_delim : '\t'), (pg_null_as_len ? pg_null_as : "\\\\N")); } pgsql_result = PQexec(H->server, query); efree(query); @@ -767,16 +788,18 @@ static PHP_METHOD(PDO, pgsqlCopyToFile) break; /* done */ } else if (ret > 0) { if (php_stream_write(stream, csv, ret) != ret) { - pdo_pgsql_error(dbh, PGRES_FATAL_ERROR, "Unable to write to file"); + pdo_pgsql_error_msg(dbh, PGRES_FATAL_ERROR, "Unable to write to file"); PQfreemem(csv); php_stream_close(stream); + PDO_HANDLE_DBH_ERR(); RETURN_FALSE; } else { PQfreemem(csv); } } else { - pdo_pgsql_error(dbh, PGRES_FATAL_ERROR, "Copy command failed: getline failed"); + pdo_pgsql_error(dbh, PGRES_FATAL_ERROR, NULL); php_stream_close(stream); + PDO_HANDLE_DBH_ERR(); RETURN_FALSE; } } @@ -788,8 +811,9 @@ static PHP_METHOD(PDO, pgsqlCopyToFile) RETURN_TRUE; } else { php_stream_close(stream); + pdo_pgsql_error(dbh, PGRES_FATAL_ERROR, pdo_pgsql_sqlstate(pgsql_result)); PQclear(pgsql_result); - pdo_pgsql_error(dbh, PGRES_FATAL_ERROR, "Copy command failed"); + PDO_HANDLE_DBH_ERR(); RETURN_FALSE; } } @@ -817,6 +841,7 @@ static PHP_METHOD(PDO, pgsqlCopyToArray) dbh = zend_object_store_get_object(getThis() TSRMLS_CC); PDO_CONSTRUCT_CHECK; + PDO_DBH_CLEAR_ERR(); H = (pdo_pgsql_db_handle *)dbh->driver_data; @@ -824,10 +849,11 @@ static PHP_METHOD(PDO, pgsqlCopyToArray) PQclear(pgsql_result); } + /* using pre-9.0 syntax as PDO_pgsql is 7.4+ compatible */ if (pg_fields) { - spprintf(&query, 0, "COPY %s (%s) TO STDIN DELIMITERS E'%c' WITH NULL AS E'%s'", table_name, pg_fields, (pg_delim_len ? *pg_delim : '\t'), (pg_null_as_len ? pg_null_as : "\\\\N")); + spprintf(&query, 0, "COPY %s (%s) TO STDIN WITH DELIMITER E'%c' NULL AS E'%s'", table_name, pg_fields, (pg_delim_len ? *pg_delim : '\t'), (pg_null_as_len ? pg_null_as : "\\\\N")); } else { - spprintf(&query, 0, "COPY %s TO STDIN DELIMITERS E'%c' WITH NULL AS E'%s'", table_name, (pg_delim_len ? *pg_delim : '\t'), (pg_null_as_len ? pg_null_as : "\\\\N")); + spprintf(&query, 0, "COPY %s TO STDIN WITH DELIMITER E'%c' NULL AS E'%s'", table_name, (pg_delim_len ? *pg_delim : '\t'), (pg_null_as_len ? pg_null_as : "\\\\N")); } pgsql_result = PQexec(H->server, query); efree(query); @@ -851,7 +877,8 @@ static PHP_METHOD(PDO, pgsqlCopyToArray) add_next_index_stringl(return_value, csv, ret, 1); PQfreemem(csv); } else { - pdo_pgsql_error(dbh, PGRES_FATAL_ERROR, "Copy command failed: getline failed"); + pdo_pgsql_error(dbh, PGRES_FATAL_ERROR, NULL); + PDO_HANDLE_DBH_ERR(); RETURN_FALSE; } } @@ -860,8 +887,9 @@ static PHP_METHOD(PDO, pgsqlCopyToArray) PQclear(pgsql_result); } } else { + pdo_pgsql_error(dbh, PGRES_FATAL_ERROR, pdo_pgsql_sqlstate(pgsql_result)); PQclear(pgsql_result); - pdo_pgsql_error(dbh, PGRES_FATAL_ERROR, "Copy command failed"); + PDO_HANDLE_DBH_ERR(); RETURN_FALSE; } } @@ -878,6 +906,7 @@ static PHP_METHOD(PDO, pgsqlLOBCreate) dbh = zend_object_store_get_object(getThis() TSRMLS_CC); PDO_CONSTRUCT_CHECK; + PDO_DBH_CLEAR_ERR(); H = (pdo_pgsql_db_handle *)dbh->driver_data; lfd = lo_creat(H->server, INV_READ|INV_WRITE); @@ -887,8 +916,9 @@ static PHP_METHOD(PDO, pgsqlLOBCreate) spprintf(&buf, 0, "%lu", (long) lfd); RETURN_STRING(buf, 0); } - - pdo_pgsql_error(dbh, PGRES_FATAL_ERROR, "HY000"); + + pdo_pgsql_error(dbh, PGRES_FATAL_ERROR, NULL); + PDO_HANDLE_DBH_ERR(); RETURN_FALSE; } /* }}} */ @@ -924,6 +954,7 @@ static PHP_METHOD(PDO, pgsqlLOBOpen) dbh = zend_object_store_get_object(getThis() TSRMLS_CC); PDO_CONSTRUCT_CHECK; + PDO_DBH_CLEAR_ERR(); H = (pdo_pgsql_db_handle *)dbh->driver_data; @@ -936,8 +967,10 @@ static PHP_METHOD(PDO, pgsqlLOBOpen) return; } } else { - pdo_pgsql_error(dbh, PGRES_FATAL_ERROR, "HY000"); + pdo_pgsql_error(dbh, PGRES_FATAL_ERROR, NULL); } + + PDO_HANDLE_DBH_ERR(); RETURN_FALSE; } /* }}} */ @@ -964,17 +997,98 @@ static PHP_METHOD(PDO, pgsqlLOBUnlink) dbh = zend_object_store_get_object(getThis() TSRMLS_CC); PDO_CONSTRUCT_CHECK; + PDO_DBH_CLEAR_ERR(); H = (pdo_pgsql_db_handle *)dbh->driver_data; - + if (1 == lo_unlink(H->server, oid)) { RETURN_TRUE; } - pdo_pgsql_error(dbh, PGRES_FATAL_ERROR, "HY000"); + + pdo_pgsql_error(dbh, PGRES_FATAL_ERROR, NULL); + PDO_HANDLE_DBH_ERR(); RETURN_FALSE; } /* }}} */ +/* {{{ proto mixed PDO::pgsqlGetNotify([ int $result_type = PDO::FETCH_USE_DEFAULT] [, int $ms_timeout = 0 ]]) + Get asyncronous notification */ +static PHP_METHOD(PDO, pgsqlGetNotify) +{ + pdo_dbh_t *dbh; + pdo_pgsql_db_handle *H; + long result_type = PDO_FETCH_USE_DEFAULT; + long ms_timeout = 0; + PGnotify *pgsql_notify; + + if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|ll", + &result_type, &ms_timeout)) { + RETURN_FALSE; + } + + dbh = zend_object_store_get_object(getThis() TSRMLS_CC); + PDO_CONSTRUCT_CHECK; + + if (result_type == PDO_FETCH_USE_DEFAULT) { + result_type = dbh->default_fetch_type; + } + + if (result_type != PDO_FETCH_BOTH && result_type != PDO_FETCH_ASSOC && result_type != PDO_FETCH_NUM) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid result type"); + RETURN_FALSE; + } + + if (ms_timeout < 0) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid timeout"); + RETURN_FALSE; + } + + H = (pdo_pgsql_db_handle *)dbh->driver_data; + + PQconsumeInput(H->server); + pgsql_notify = PQnotifies(H->server); + + if (ms_timeout && !pgsql_notify) { + php_pollfd_for_ms(PQsocket(H->server), PHP_POLLREADABLE, ms_timeout); + + PQconsumeInput(H->server); + pgsql_notify = PQnotifies(H->server); + } + + if (!pgsql_notify) { + RETURN_FALSE; + } + + array_init(return_value); + if (result_type == PDO_FETCH_NUM || result_type == PDO_FETCH_BOTH) { + add_index_string(return_value, 0, pgsql_notify->relname, 1); + add_index_long(return_value, 1, pgsql_notify->be_pid); + } + if (result_type == PDO_FETCH_ASSOC || result_type == PDO_FETCH_BOTH) { + add_assoc_string(return_value, "message", pgsql_notify->relname, 1); + add_assoc_long(return_value, "pid", pgsql_notify->be_pid); + } + + PQfreemem(pgsql_notify); +} +/* }}} */ + +/* {{{ proto int PDO::pgsqlGetPid() + Get backend(server) pid */ +static PHP_METHOD(PDO, pgsqlGetPid) +{ + pdo_dbh_t *dbh; + pdo_pgsql_db_handle *H; + + dbh = zend_object_store_get_object(getThis() TSRMLS_CC); + PDO_CONSTRUCT_CHECK; + + H = (pdo_pgsql_db_handle *)dbh->driver_data; + + RETURN_LONG(PQbackendPID(H->server)); +} +/* }}} */ + static const zend_function_entry dbh_methods[] = { PHP_ME(PDO, pgsqlLOBCreate, NULL, ZEND_ACC_PUBLIC) @@ -984,6 +1098,8 @@ static const zend_function_entry dbh_methods[] = { PHP_ME(PDO, pgsqlCopyFromFile, NULL, ZEND_ACC_PUBLIC) PHP_ME(PDO, pgsqlCopyToArray, NULL, ZEND_ACC_PUBLIC) PHP_ME(PDO, pgsqlCopyToFile, NULL, ZEND_ACC_PUBLIC) + PHP_ME(PDO, pgsqlGetNotify, NULL, ZEND_ACC_PUBLIC) + PHP_ME(PDO, pgsqlGetPid, NULL, ZEND_ACC_PUBLIC) PHP_FE_END }; diff --git a/ext/pdo_pgsql/php_pdo_pgsql_int.h b/ext/pdo_pgsql/php_pdo_pgsql_int.h index 02a6717760..5600a92541 100644 --- a/ext/pdo_pgsql/php_pdo_pgsql_int.h +++ b/ext/pdo_pgsql/php_pdo_pgsql_int.h @@ -83,9 +83,11 @@ typedef struct { extern pdo_driver_t pdo_pgsql_driver; -extern int _pdo_pgsql_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt, int errcode, const char *sqlstate, const char *file, int line TSRMLS_DC); -#define pdo_pgsql_error(d,e,z) _pdo_pgsql_error(d, NULL, e, z, __FILE__, __LINE__ TSRMLS_CC) -#define pdo_pgsql_error_stmt(s,e,z) _pdo_pgsql_error(s->dbh, s, e, z, __FILE__, __LINE__ TSRMLS_CC) +extern int _pdo_pgsql_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt, int errcode, const char *sqlstate, const char *msg, const char *file, int line TSRMLS_DC); +#define pdo_pgsql_error(d,e,z) _pdo_pgsql_error(d, NULL, e, z, NULL, __FILE__, __LINE__ TSRMLS_CC) +#define pdo_pgsql_error_msg(d,e,m) _pdo_pgsql_error(d, NULL, e, NULL, m, __FILE__, __LINE__ TSRMLS_CC) +#define pdo_pgsql_error_stmt(s,e,z) _pdo_pgsql_error(s->dbh, s, e, z, NULL, __FILE__, __LINE__ TSRMLS_CC) +#define pdo_pgsql_error_stmt_msg(s,e,m) _pdo_pgsql_error(s->dbh, s, e, NULL, m, __FILE__, __LINE__ TSRMLS_CC) extern struct pdo_stmt_methods pgsql_stmt_methods; diff --git a/ext/pdo_pgsql/tests/copy_from.phpt b/ext/pdo_pgsql/tests/copy_from.phpt index 10967b0fe9..de1140dfea 100644 --- a/ext/pdo_pgsql/tests/copy_from.phpt +++ b/ext/pdo_pgsql/tests/copy_from.phpt @@ -16,8 +16,6 @@ $db->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, false); $db->exec('CREATE TABLE test (a integer not null primary key, b text, c integer)'); -try { - echo "Preparing test file and array for CopyFrom tests\n"; $tableRows = array(); @@ -68,10 +66,13 @@ $db->rollback(); echo "Testing pgsqlCopyFromArray() with error\n"; $db->beginTransaction(); -var_dump($db->pgsqlCopyFromArray('test_error',$tableRowsWithDifferentNullValuesAndSelectedFields,";","NULL",'a,c')); +try { + var_dump($db->pgsqlCopyFromArray('test_error',$tableRowsWithDifferentNullValuesAndSelectedFields,";","NULL",'a,c')); +} catch (Exception $e) { + echo "Exception: {$e->getMessage()}\n"; +} $db->rollback(); - echo "Testing pgsqlCopyFromFile() with default parameters\n"; $db->beginTransaction(); var_dump($db->pgsqlCopyFromFile('test',$filename)); @@ -102,14 +103,21 @@ $db->rollback(); echo "Testing pgsqlCopyFromFile() with error\n"; $db->beginTransaction(); -var_dump($db->pgsqlCopyFromFile('test_error',$filenameWithDifferentNullValuesAndSelectedFields,";","NULL",'a,c')); +try { + var_dump($db->pgsqlCopyFromFile('test_error',$filenameWithDifferentNullValuesAndSelectedFields,";","NULL",'a,c')); +} catch (Exception $e) { + echo "Exception: {$e->getMessage()}\n"; +} $db->rollback(); +echo "Testing pgsqlCopyFromFile() with non existing file\n"; +$db->beginTransaction(); +try { + var_dump($db->pgsqlCopyFromFile('test',"nonexisting/foo.csv",";","NULL",'a,c')); } catch (Exception $e) { - /* catch exceptions so that we can show the relative error */ - echo "Exception! at line ", $e->getLine(), "\n"; - var_dump($e->getMessage()); + echo "Exception: {$e->getMessage()}\n"; } +$db->rollback(); // Clean up foreach (array($filename, $filenameWithDifferentNullValues, $filenameWithDifferentNullValuesAndSelectedFields) as $f) { @@ -251,7 +259,7 @@ array(6) { NULL } Testing pgsqlCopyFromArray() with error -bool(false) +Exception: SQLSTATE[42P01]: Undefined table: 7 ERROR: relation "test_error" does not exist Testing pgsqlCopyFromFile() with default parameters bool(true) array(6) { @@ -385,4 +393,7 @@ array(6) { NULL } Testing pgsqlCopyFromFile() with error -bool(false) +Exception: SQLSTATE[42P01]: Undefined table: 7 ERROR: relation "test_error" does not exist +Testing pgsqlCopyFromFile() with non existing file +Exception: SQLSTATE[HY000]: General error: 7 Unable to open the file + diff --git a/ext/pdo_pgsql/tests/copy_to.phpt b/ext/pdo_pgsql/tests/copy_to.phpt index 1dc7d1de33..7bc46c6e0b 100644 --- a/ext/pdo_pgsql/tests/copy_to.phpt +++ b/ext/pdo_pgsql/tests/copy_to.phpt @@ -17,7 +17,6 @@ $db->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, false); $db->exec('CREATE TABLE test (a integer not null primary key, b text, c integer)'); $db->beginTransaction(); -try { echo "Preparing test table for CopyTo tests\n"; $stmt = $db->prepare("INSERT INTO test (a, b, c) values (?, ?, ?)"); @@ -42,8 +41,11 @@ echo "Testing pgsqlCopyToArray() with only selected fields\n"; var_dump($db->pgsqlCopyToArray('test',";","NULL",'a,c')); echo "Testing pgsqlCopyToArray() with error\n"; -var_dump($db->pgsqlCopyToArray('test_error')); - +try { + var_dump($db->pgsqlCopyToArray('test_error')); +} catch (Exception $e) { + echo "Exception: {$e->getMessage()}\n"; +} echo "Testing pgsqlCopyToFile() with default parameters\n"; @@ -58,14 +60,19 @@ var_dump($db->pgsqlCopyToFile('test',$filename,";","NULL",'a,c')); echo file_get_contents($filename); echo "Testing pgsqlCopyToFile() with error\n"; -var_dump($db->pgsqlCopyToFile('test_error',$filename)); - +try { + var_dump($db->pgsqlCopyToFile('test_error',$filename)); +} catch (Exception $e) { + echo "Exception: {$e->getMessage()}\n"; +} +echo "Testing pgsqlCopyToFile() to unwritable file\n"; +try { + var_dump($db->pgsqlCopyToFile('test', 'nonexistent/foo.csv')); } catch (Exception $e) { - /* catch exceptions so that we can show the relative error */ - echo "Exception! at line ", $e->getLine(), "\n"; - var_dump($e->getMessage()); + echo "Exception: {$e->getMessage()}\n"; } + if(isset($filename)) { @unlink($filename); } @@ -109,7 +116,7 @@ array(3) { " } Testing pgsqlCopyToArray() with error -bool(false) +Exception: SQLSTATE[42P01]: Undefined table: 7 ERROR: relation "test_error" does not exist Testing pgsqlCopyToFile() with default parameters bool(true) 0 test insert 0 \N @@ -126,4 +133,7 @@ bool(true) 1;NULL 2;NULL Testing pgsqlCopyToFile() with error -bool(false)
\ No newline at end of file +Exception: SQLSTATE[42P01]: Undefined table: 7 ERROR: relation "test_error" does not exist +Testing pgsqlCopyToFile() to unwritable file +Exception: SQLSTATE[HY000]: General error: 7 Unable to open the file for writing + diff --git a/ext/pdo_pgsql/tests/getnotify.phpt b/ext/pdo_pgsql/tests/getnotify.phpt new file mode 100644 index 0000000000..c093e0357a --- /dev/null +++ b/ext/pdo_pgsql/tests/getnotify.phpt @@ -0,0 +1,109 @@ +--TEST-- +PDO PgSQL LISTEN/NOTIFY support +--SKIPIF-- +<?php # vim:se ft=php: +if (!extension_loaded('pdo') || !extension_loaded('pdo_pgsql')) die('skip not loaded'); +require dirname(__FILE__) . '/config.inc'; +require dirname(__FILE__) . '/../../../ext/pdo/tests/pdo_test.inc'; +PDOTest::skip(); +?> +--FILE-- +<?php +require dirname(__FILE__) . '/../../../ext/pdo/tests/pdo_test.inc'; +$db = PDOTest::test_factory(dirname(__FILE__) . '/common.phpt'); +$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + +// pgsqlGetPid should return something meaningful +$pid = $db->pgsqlGetPid(); +var_dump($pid > 0); + +// No listen, no notifies +var_dump($db->pgsqlGetNotify()); + +// Listen started, no notifies +$db->exec("LISTEN notifies_phpt"); +var_dump($db->pgsqlGetNotify()); + +// No parameters, use default PDO::FETCH_NUM +$db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_NUM); +$db->exec("NOTIFY notifies_phpt"); +$notify = $db->pgsqlGetNotify(); +var_dump(count($notify)); +var_dump($notify[0]); +var_dump($notify[1] == $pid); + +// No parameters, use default PDO::FETCH_ASSOC +$db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC); +$db->exec("NOTIFY notifies_phpt"); +$notify = $db->pgsqlGetNotify(); +var_dump(count($notify)); +var_dump($notify['message']); +var_dump($notify['pid'] == $pid); + +// Test PDO::FETCH_NUM as parameter +$db->exec("NOTIFY notifies_phpt"); +$notify = $db->pgsqlGetNotify(PDO::FETCH_NUM); +var_dump(count($notify)); +var_dump($notify[0]); +var_dump($notify[1] == $pid); + +// Test PDO::FETCH_ASSOC as parameter +$db->exec("NOTIFY notifies_phpt"); +$notify = $db->pgsqlGetNotify(PDO::FETCH_ASSOC); +var_dump(count($notify)); +var_dump($notify['message']); +var_dump($notify['pid'] == $pid); + +// Test PDO::FETCH_BOTH as parameter +$db->exec("NOTIFY notifies_phpt"); +$notify = $db->pgsqlGetNotify(PDO::FETCH_BOTH); +var_dump(count($notify)); +var_dump($notify['message']); +var_dump($notify['pid'] == $pid); +var_dump($notify[0]); +var_dump($notify[1] == $pid); + +// Verify that there are no notifies queued +var_dump($db->pgsqlGetNotify()); + + +// Test second parameter, should wait 2 seconds because no notify is queued +$t = microtime(1); +$notify = $db->pgsqlGetNotify(PDO::FETCH_ASSOC, 1000); +var_dump((microtime(1) - $t) >= 1); +var_dump($notify); + +// Test second parameter, should return immediately because a notify is queued +$db->exec("NOTIFY notifies_phpt"); +$t = microtime(1); +$notify = $db->pgsqlGetNotify(PDO::FETCH_ASSOC, 5000); +var_dump((microtime(1) - $t) < 1); +var_dump(count($notify)); + +?> +--EXPECT-- +bool(true) +bool(false) +bool(false) +int(2) +string(13) "notifies_phpt" +bool(true) +int(2) +string(13) "notifies_phpt" +bool(true) +int(2) +string(13) "notifies_phpt" +bool(true) +int(2) +string(13) "notifies_phpt" +bool(true) +int(4) +string(13) "notifies_phpt" +bool(true) +string(13) "notifies_phpt" +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +int(2) diff --git a/ext/pgsql/tests/00version.phpt b/ext/pgsql/tests/00version.phpt new file mode 100644 index 0000000000..d72d9e1f21 --- /dev/null +++ b/ext/pgsql/tests/00version.phpt @@ -0,0 +1,30 @@ +--TEST-- +PostgreSQL version +--SKIPIF-- +<?php include("skipif.inc"); ?> +--FILE-- +<?php +// Get postgresql version for easier debugging. +// Execute run-test.php with --keep-all to get version string in 00version.log or 00version.out +include('config.inc'); + +$db = pg_connect($conn_str); +var_dump(pg_version($db)); +pg_close($db); + +// Get environment vars for debugging +var_dump(serialize($_ENV)); + +echo "OK"; +?> +--EXPECTF-- +array(3) { + ["client"]=> + string(%d) "%s" + ["protocol"]=> + int(%d) + ["server"]=> + string(%d) "%s" +} +string(%d) "%s" +OK diff --git a/ext/pgsql/tests/14pg_update_9.phpt b/ext/pgsql/tests/14pg_update_9.phpt index e766c1f380..c33f1afbd6 100644 --- a/ext/pgsql/tests/14pg_update_9.phpt +++ b/ext/pgsql/tests/14pg_update_9.phpt @@ -1,5 +1,5 @@ --TEST-- -PostgreSQL pg_update() (9.0) +PostgreSQL pg_update() (9.0+) --SKIPIF-- <?php include("skipif.inc"); diff --git a/ext/pgsql/tests/80_bug14383.phpt b/ext/pgsql/tests/80_bug14383.phpt index a736f34c90..cb54aa8dfb 100644 --- a/ext/pgsql/tests/80_bug14383.phpt +++ b/ext/pgsql/tests/80_bug14383.phpt @@ -1,5 +1,5 @@ --TEST-- -Bug #14383 (using postgres with DBA causes DBA not to be able to find any keys) +Bug #14383 (8.0+) (using postgres with DBA causes DBA not to be able to find any keys) --SKIPIF-- <?php require_once(dirname(__FILE__).'/../../dba/tests/skipif.inc'); diff --git a/ext/pgsql/tests/80_bug36625.phpt b/ext/pgsql/tests/80_bug36625.phpt index 9cc8a1d4fd..e1b7fa1b50 100644 --- a/ext/pgsql/tests/80_bug36625.phpt +++ b/ext/pgsql/tests/80_bug36625.phpt @@ -1,5 +1,5 @@ --TEST-- -Bug #36625 (pg_trace() does not work) +Bug #36625 (8.0+) (pg_trace() does not work) --SKIPIF-- <?php require_once('skipif.inc'); diff --git a/ext/pgsql/tests/80_bug39971.phpt b/ext/pgsql/tests/80_bug39971.phpt index 45d26319d3..49f370b88d 100644 --- a/ext/pgsql/tests/80_bug39971.phpt +++ b/ext/pgsql/tests/80_bug39971.phpt @@ -1,5 +1,5 @@ --TEST-- -Bug #39971 (pg_insert/pg_update do not allow now() to be used for timestamp fields) +Bug #39971 (8.0+) (pg_insert/pg_update do not allow now() to be used for timestamp fields) --SKIPIF-- <?php require_once('skipif.inc'); diff --git a/ext/pgsql/tests/config.inc b/ext/pgsql/tests/config.inc index d4bbb33824..ffe31a875e 100644 --- a/ext/pgsql/tests/config.inc +++ b/ext/pgsql/tests/config.inc @@ -2,8 +2,10 @@ // These vars are used to connect db and create test table. // values can be set to meet your environment +// "test" database must be existed. i.e. "createdb test" before testing +// PostgreSQL uses login name as username, user must have access to "test" database. $conn_str = "host=localhost dbname=test port=5432"; // connection string -$table_name = "php_pgsql_test"; // test table that should be exist +$table_name = "php_pgsql_test"; // test table that will be created $num_test_record = 1000; // Number of records to create $table_def = "CREATE TABLE php_pgsql_test (num int, str text, bin bytea);"; // Test table diff --git a/ext/phar/dirstream.c b/ext/phar/dirstream.c index 98af1bffc2..0f2580000d 100644 --- a/ext/phar/dirstream.c +++ b/ext/phar/dirstream.c @@ -94,31 +94,23 @@ static size_t phar_dir_read(php_stream *stream, char *buf, size_t count TSRMLS_D { size_t to_read; HashTable *data = (HashTable *)stream->abstract; - phar_zstr key; char *str_key; uint keylen; ulong unused; - if (FAILURE == zend_hash_has_more_elements(data)) { + if (HASH_KEY_NON_EXISTENT == zend_hash_get_current_key_ex(data, &str_key, &keylen, &unused, 0, NULL)) { return 0; } - if (HASH_KEY_NON_EXISTENT == zend_hash_get_current_key_ex(data, &key, &keylen, &unused, 0, NULL)) { - return 0; - } - - PHAR_STR(key, str_key); zend_hash_move_forward(data); to_read = MIN(keylen, count); if (to_read == 0 || count < keylen) { - PHAR_STR_FREE(str_key); return 0; } memset(buf, 0, sizeof(php_stream_dirent)); memcpy(((php_stream_dirent *) buf)->d_name, str_key, to_read); - PHAR_STR_FREE(str_key); ((php_stream_dirent *) buf)->d_name[to_read + 1] = '\0'; return sizeof(php_stream_dirent); @@ -189,13 +181,12 @@ static php_stream *phar_make_dirstream(char *dir, HashTable *manifest TSRMLS_DC) { HashTable *data; int dirlen = strlen(dir); - phar_zstr key; char *entry, *found, *save, *str_key; uint keylen; ulong unused; ALLOC_HASHTABLE(data); - zend_hash_init(data, 64, zend_get_hash_value, NULL, 0); + zend_hash_init(data, 64, NULL, NULL, 0); if ((*dir == '/' && dirlen == 1 && (manifest->nNumOfElements == 0)) || (dirlen >= sizeof(".phar")-1 && !memcmp(dir, ".phar", sizeof(".phar")-1))) { /* make empty root directory for empty phar */ @@ -207,15 +198,12 @@ static php_stream *phar_make_dirstream(char *dir, HashTable *manifest TSRMLS_DC) zend_hash_internal_pointer_reset(manifest); while (FAILURE != zend_hash_has_more_elements(manifest)) { - if (HASH_KEY_NON_EXISTENT == zend_hash_get_current_key_ex(manifest, &key, &keylen, &unused, 0, NULL)) { + if (HASH_KEY_NON_EXISTENT == zend_hash_get_current_key_ex(manifest, &str_key, &keylen, &unused, 0, NULL)) { break; } - PHAR_STR(key, str_key); - if (keylen <= (uint)dirlen) { if (keylen < (uint)dirlen || !strncmp(str_key, dir, dirlen)) { - PHAR_STR_FREE(str_key); if (SUCCESS != zend_hash_move_forward(manifest)) { break; } @@ -226,7 +214,6 @@ static php_stream *phar_make_dirstream(char *dir, HashTable *manifest TSRMLS_DC) if (*dir == '/') { /* root directory */ if (keylen >= sizeof(".phar")-1 && !memcmp(str_key, ".phar", sizeof(".phar")-1)) { - PHAR_STR_FREE(str_key); /* do not add any magic entries to this directory */ if (SUCCESS != zend_hash_move_forward(manifest)) { break; @@ -246,19 +233,16 @@ static php_stream *phar_make_dirstream(char *dir, HashTable *manifest TSRMLS_DC) entry[keylen] = '\0'; } - PHAR_STR_FREE(str_key); goto PHAR_ADD_ENTRY; } else { if (0 != memcmp(str_key, dir, dirlen)) { /* entry in directory not found */ - PHAR_STR_FREE(str_key); if (SUCCESS != zend_hash_move_forward(manifest)) { break; } continue; } else { if (str_key[dirlen] != '/') { - PHAR_STR_FREE(str_key); if (SUCCESS != zend_hash_move_forward(manifest)) { break; } @@ -285,7 +269,6 @@ static php_stream *phar_make_dirstream(char *dir, HashTable *manifest TSRMLS_DC) entry[keylen - dirlen - 1] = '\0'; keylen = keylen - dirlen - 1; } - PHAR_STR_FREE(str_key); PHAR_ADD_ENTRY: if (keylen) { phar_add_empty(data, entry, keylen); @@ -315,12 +298,11 @@ PHAR_ADD_ENTRY: /** * Open a directory handle within a phar archive */ -php_stream *phar_wrapper_open_dir(php_stream_wrapper *wrapper, char *path, char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC) /* {{{ */ +php_stream *phar_wrapper_open_dir(php_stream_wrapper *wrapper, const char *path, const char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC) /* {{{ */ { php_url *resource = NULL; php_stream *ret; char *internal_file, *error, *str_key; - phar_zstr key; uint keylen; ulong unused; phar_archive_data *phar; @@ -401,17 +383,14 @@ php_stream *phar_wrapper_open_dir(php_stream_wrapper *wrapper, char *path, char while (FAILURE != zend_hash_has_more_elements(&phar->manifest)) { if (HASH_KEY_NON_EXISTENT != zend_hash_get_current_key_ex( - &phar->manifest, &key, &keylen, &unused, 0, NULL)) { - PHAR_STR(key, str_key); + &phar->manifest, &str_key, &keylen, &unused, 0, NULL)) { if (keylen > (uint)i_len && 0 == memcmp(str_key, internal_file, i_len)) { - PHAR_STR_FREE(str_key); /* directory found */ internal_file = estrndup(internal_file, i_len); php_url_free(resource); return phar_make_dirstream(internal_file, &phar->manifest TSRMLS_CC); } - PHAR_STR_FREE(str_key); } if (SUCCESS != zend_hash_move_forward(&phar->manifest)) { @@ -428,7 +407,7 @@ php_stream *phar_wrapper_open_dir(php_stream_wrapper *wrapper, char *path, char /** * Make a new directory within a phar archive */ -int phar_wrapper_mkdir(php_stream_wrapper *wrapper, char *url_from, int mode, int options, php_stream_context *context TSRMLS_DC) /* {{{ */ +int phar_wrapper_mkdir(php_stream_wrapper *wrapper, const char *url_from, int mode, int options, php_stream_context *context TSRMLS_DC) /* {{{ */ { phar_entry_info entry, *e; phar_archive_data *phar = NULL; @@ -560,7 +539,7 @@ int phar_wrapper_mkdir(php_stream_wrapper *wrapper, char *url_from, int mode, in /** * Remove a directory within a phar archive */ -int phar_wrapper_rmdir(php_stream_wrapper *wrapper, char *url, int options, php_stream_context *context TSRMLS_DC) /* {{{ */ +int phar_wrapper_rmdir(php_stream_wrapper *wrapper, const char *url, int options, php_stream_context *context TSRMLS_DC) /* {{{ */ { phar_entry_info *entry; phar_archive_data *phar = NULL; @@ -568,7 +547,6 @@ int phar_wrapper_rmdir(php_stream_wrapper *wrapper, char *url, int options, php_ int arch_len, entry_len; php_url *resource = NULL; uint host_len; - phar_zstr key; char *str_key; uint key_len; ulong unused; @@ -633,15 +611,12 @@ int phar_wrapper_rmdir(php_stream_wrapper *wrapper, char *url, int options, php_ if (!entry->is_deleted) { for (zend_hash_internal_pointer_reset(&phar->manifest); - HASH_KEY_NON_EXISTENT != zend_hash_get_current_key_ex(&phar->manifest, &key, &key_len, &unused, 0, NULL); - zend_hash_move_forward(&phar->manifest)) { - - PHAR_STR(key, str_key); - + HASH_KEY_NON_EXISTENT != zend_hash_get_current_key_ex(&phar->manifest, &str_key, &key_len, &unused, 0, NULL); + zend_hash_move_forward(&phar->manifest) + ) { if (key_len > path_len && memcmp(str_key, resource->path+1, path_len) == 0 && IS_SLASH(str_key[path_len])) { - PHAR_STR_FREE(str_key); php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: Directory not empty"); if (entry->is_temp_dir) { efree(entry->filename); @@ -650,19 +625,15 @@ int phar_wrapper_rmdir(php_stream_wrapper *wrapper, char *url, int options, php_ php_url_free(resource); return 0; } - PHAR_STR_FREE(str_key); } for (zend_hash_internal_pointer_reset(&phar->virtual_dirs); - HASH_KEY_NON_EXISTENT != zend_hash_get_current_key_ex(&phar->virtual_dirs, &key, &key_len, &unused, 0, NULL); + HASH_KEY_NON_EXISTENT != zend_hash_get_current_key_ex(&phar->virtual_dirs, &str_key, &key_len, &unused, 0, NULL); zend_hash_move_forward(&phar->virtual_dirs)) { - PHAR_STR(key, str_key); - if (key_len > path_len && memcmp(str_key, resource->path+1, path_len) == 0 && IS_SLASH(str_key[path_len])) { - PHAR_STR_FREE(str_key); php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: Directory not empty"); if (entry->is_temp_dir) { efree(entry->filename); @@ -671,7 +642,6 @@ int phar_wrapper_rmdir(php_stream_wrapper *wrapper, char *url, int options, php_ php_url_free(resource); return 0; } - PHAR_STR_FREE(str_key); } } diff --git a/ext/phar/dirstream.h b/ext/phar/dirstream.h index 9b07c9d799..030fe6536e 100644 --- a/ext/phar/dirstream.h +++ b/ext/phar/dirstream.h @@ -20,11 +20,11 @@ /* $Id$ */ BEGIN_EXTERN_C() -int phar_wrapper_mkdir(php_stream_wrapper *wrapper, char *url_from, int mode, int options, php_stream_context *context TSRMLS_DC); -int phar_wrapper_rmdir(php_stream_wrapper *wrapper, char *url, int options, php_stream_context *context TSRMLS_DC); +int phar_wrapper_mkdir(php_stream_wrapper *wrapper, const char *url_from, int mode, int options, php_stream_context *context TSRMLS_DC); +int phar_wrapper_rmdir(php_stream_wrapper *wrapper, const char *url, int options, php_stream_context *context TSRMLS_DC); #ifdef PHAR_DIRSTREAM -php_url* phar_parse_url(php_stream_wrapper *wrapper, char *filename, char *mode, int options TSRMLS_DC); +php_url* phar_parse_url(php_stream_wrapper *wrapper, const char *filename, const char *mode, int options TSRMLS_DC); /* directory handlers */ static size_t phar_dir_write(php_stream *stream, const char *buf, size_t count TSRMLS_DC); @@ -33,7 +33,7 @@ static int phar_dir_close(php_stream *stream, int close_handle TSRMLS_DC); static int phar_dir_flush(php_stream *stream TSRMLS_DC); static int phar_dir_seek( php_stream *stream, off_t offset, int whence, off_t *newoffset TSRMLS_DC); #else -php_stream* phar_wrapper_open_dir(php_stream_wrapper *wrapper, char *path, char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC); +php_stream* phar_wrapper_open_dir(php_stream_wrapper *wrapper, const char *path, const char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC); #endif END_EXTERN_C() diff --git a/ext/phar/phar.c b/ext/phar/phar.c index 13b3d6428e..d4716bca91 100644 --- a/ext/phar/phar.c +++ b/ext/phar/phar.c @@ -1639,7 +1639,7 @@ static int phar_open_from_fp(php_stream* fp, char *fname, int fname_len, char *a php_stream_filter_append(&temp->writefilters, filter); - if (SUCCESS != phar_stream_copy_to_stream(fp, temp, PHP_STREAM_COPY_ALL, NULL)) { + if (SUCCESS != php_stream_copy_to_stream_ex(fp, temp, PHP_STREAM_COPY_ALL, NULL)) { if (err) { php_stream_close(temp); MAPPHAR_ALLOC_FAIL("unable to decompress gzipped phar archive \"%s\", ext/zlib is buggy in PHP versions older than 5.2.6") @@ -1681,7 +1681,7 @@ static int phar_open_from_fp(php_stream* fp, char *fname, int fname_len, char *a php_stream_filter_append(&temp->writefilters, filter); - if (SUCCESS != phar_stream_copy_to_stream(fp, temp, PHP_STREAM_COPY_ALL, NULL)) { + if (SUCCESS != php_stream_copy_to_stream_ex(fp, temp, PHP_STREAM_COPY_ALL, NULL)) { php_stream_close(temp); MAPPHAR_ALLOC_FAIL("unable to decompress bzipped phar archive \"%s\" to temporary file") } @@ -1954,67 +1954,45 @@ woohoo: goto woohoo; } } else { - phar_zstr key; char *str_key; uint keylen; ulong unused; - zend_hash_internal_pointer_reset(&(PHAR_GLOBALS->phar_fname_map)); - - while (FAILURE != zend_hash_has_more_elements(&(PHAR_GLOBALS->phar_fname_map))) { - if (HASH_KEY_NON_EXISTENT == zend_hash_get_current_key_ex(&(PHAR_GLOBALS->phar_fname_map), &key, &keylen, &unused, 0, NULL)) { - break; - } - - PHAR_STR(key, str_key); - + for (zend_hash_internal_pointer_reset(&(PHAR_GLOBALS->phar_fname_map)); + HASH_KEY_NON_EXISTENT != zend_hash_get_current_key_ex(&(PHAR_GLOBALS->phar_fname_map), &str_key, &keylen, &unused, 0, NULL); + zend_hash_move_forward(&(PHAR_GLOBALS->phar_fname_map)) + ) { if (keylen > (uint) filename_len) { - zend_hash_move_forward(&(PHAR_GLOBALS->phar_fname_map)); - PHAR_STR_FREE(str_key); continue; } if (!memcmp(filename, str_key, keylen) && ((uint)filename_len == keylen || filename[keylen] == '/' || filename[keylen] == '\0')) { - PHAR_STR_FREE(str_key); if (FAILURE == zend_hash_get_current_data(&(PHAR_GLOBALS->phar_fname_map), (void **) &pphar)) { break; } *ext_str = filename + (keylen - (*pphar)->ext_len); goto woohoo; } - - PHAR_STR_FREE(str_key); - zend_hash_move_forward(&(PHAR_GLOBALS->phar_fname_map)); } if (PHAR_G(manifest_cached)) { - zend_hash_internal_pointer_reset(&cached_phars); - - while (FAILURE != zend_hash_has_more_elements(&cached_phars)) { - if (HASH_KEY_NON_EXISTENT == zend_hash_get_current_key_ex(&cached_phars, &key, &keylen, &unused, 0, NULL)) { - break; - } - - PHAR_STR(key, str_key); - + for (zend_hash_internal_pointer_reset(&cached_phars); + HASH_KEY_NON_EXISTENT != zend_hash_get_current_key_ex(&cached_phars, &str_key, &keylen, &unused, 0, NULL); + zend_hash_move_forward(&cached_phars) + ) { if (keylen > (uint) filename_len) { - zend_hash_move_forward(&cached_phars); - PHAR_STR_FREE(str_key); continue; } if (!memcmp(filename, str_key, keylen) && ((uint)filename_len == keylen || filename[keylen] == '/' || filename[keylen] == '\0')) { - PHAR_STR_FREE(str_key); if (FAILURE == zend_hash_get_current_data(&cached_phars, (void **) &pphar)) { break; } *ext_str = filename + (keylen - (*pphar)->ext_len); goto woohoo; } - PHAR_STR_FREE(str_key); - zend_hash_move_forward(&cached_phars); } } } @@ -2249,13 +2227,13 @@ last_time: * * This is used by phar_parse_url() */ -int phar_split_fname(char *filename, int filename_len, char **arch, int *arch_len, char **entry, int *entry_len, int executable, int for_create TSRMLS_DC) /* {{{ */ +int phar_split_fname(const char *filename, int filename_len, char **arch, int *arch_len, char **entry, int *entry_len, int executable, int for_create TSRMLS_DC) /* {{{ */ { const char *ext_str; #ifdef PHP_WIN32 char *save; #endif - int ext_len, free_filename = 0; + int ext_len; if (!strncasecmp(filename, "phar://", 7)) { filename += 7; @@ -2264,7 +2242,6 @@ int phar_split_fname(char *filename, int filename_len, char **arch, int *arch_le ext_len = 0; #ifdef PHP_WIN32 - free_filename = 1; save = filename; filename = estrndup(filename, filename_len); phar_unixify_path_separators(filename, filename_len); @@ -2280,10 +2257,9 @@ int phar_split_fname(char *filename, int filename_len, char **arch, int *arch_le #endif } - if (free_filename) { - efree(filename); - } - +#ifdef PHP_WIN32 + efree(filename); +#endif return FAILURE; } @@ -2306,9 +2282,9 @@ int phar_split_fname(char *filename, int filename_len, char **arch, int *arch_le *entry = estrndup("/", 1); } - if (free_filename) { - efree(filename); - } +#ifdef PHP_WIN32 + efree(filename); +#endif return SUCCESS; } @@ -2701,7 +2677,7 @@ int phar_flush(phar_archive_data *phar, char *user_stub, long len, int convert, size_t written; if (!user_stub && phar->halt_offset && oldfile && !phar->is_brandnew) { - phar_stream_copy_to_stream(oldfile, newfile, phar->halt_offset, &written); + php_stream_copy_to_stream_ex(oldfile, newfile, phar->halt_offset, &written); newstub = NULL; } else { /* this is either a brand new phar or a default stub overwrite */ @@ -2889,7 +2865,7 @@ int phar_flush(phar_archive_data *phar, char *user_stub, long len, int convert, return EOF; } php_stream_filter_append((&entry->cfp->writefilters), filter); - if (SUCCESS != phar_stream_copy_to_stream(file, entry->cfp, entry->uncompressed_filesize, NULL)) { + if (SUCCESS != php_stream_copy_to_stream_ex(file, entry->cfp, entry->uncompressed_filesize, NULL)) { if (closeoldfile) { php_stream_close(oldfile); } @@ -3121,7 +3097,7 @@ int phar_flush(phar_archive_data *phar, char *user_stub, long len, int convert, /* this will have changed for all files that have either changed compression or been modified */ entry->offset = entry->offset_abs = offset; offset += entry->compressed_filesize; - if (phar_stream_copy_to_stream(file, newfile, entry->compressed_filesize, &wrote) == FAILURE) { + if (php_stream_copy_to_stream_ex(file, newfile, entry->compressed_filesize, &wrote) == FAILURE) { if (closeoldfile) { php_stream_close(oldfile); } @@ -3267,7 +3243,7 @@ int phar_flush(phar_archive_data *phar, char *user_stub, long len, int convert, } php_stream_filter_append(&phar->fp->writefilters, filter); - phar_stream_copy_to_stream(newfile, phar->fp, PHP_STREAM_COPY_ALL, NULL); + php_stream_copy_to_stream_ex(newfile, phar->fp, PHP_STREAM_COPY_ALL, NULL); php_stream_filter_flush(filter, 1); php_stream_filter_remove(filter, 1 TSRMLS_CC); php_stream_close(phar->fp); @@ -3276,14 +3252,14 @@ int phar_flush(phar_archive_data *phar, char *user_stub, long len, int convert, } else if (phar->flags & PHAR_FILE_COMPRESSED_BZ2) { filter = php_stream_filter_create("bzip2.compress", NULL, php_stream_is_persistent(phar->fp) TSRMLS_CC); php_stream_filter_append(&phar->fp->writefilters, filter); - phar_stream_copy_to_stream(newfile, phar->fp, PHP_STREAM_COPY_ALL, NULL); + php_stream_copy_to_stream_ex(newfile, phar->fp, PHP_STREAM_COPY_ALL, NULL); php_stream_filter_flush(filter, 1); php_stream_filter_remove(filter, 1 TSRMLS_CC); php_stream_close(phar->fp); /* use the temp stream as our base */ phar->fp = newfile; } else { - phar_stream_copy_to_stream(newfile, phar->fp, PHP_STREAM_COPY_ALL, NULL); + php_stream_copy_to_stream_ex(newfile, phar->fp, PHP_STREAM_COPY_ALL, NULL); /* we could also reopen the file in "rb" mode but there is no need for that */ php_stream_close(newfile); } diff --git a/ext/phar/phar_internal.h b/ext/phar/phar_internal.h index fcfb647184..359f25b4c6 100644 --- a/ext/phar/phar_internal.h +++ b/ext/phar/phar_internal.h @@ -54,7 +54,7 @@ #ifndef PHP_WIN32 #include "TSRM/tsrm_strtok_r.h" #endif -#include "TSRM/tsrm_virtual_cwd.h" +#include "Zend/zend_virtual_cwd.h" #if HAVE_SPL #include "ext/spl/spl_array.h" #include "ext/spl/spl_directory.h" @@ -63,27 +63,11 @@ #include "ext/spl/spl_iterators.h" #endif #include "php_phar.h" -#ifdef HAVE_STDINT_H -#include <stdint.h> -#endif #ifdef PHAR_HASH_OK #include "ext/hash/php_hash.h" #include "ext/hash/php_hash_sha.h" #endif -#ifndef E_RECOVERABLE_ERROR -# define E_RECOVERABLE_ERROR E_ERROR -#endif - -#ifndef pestrndup -# define pestrndup(s, length, persistent) ((persistent)?zend_strndup((s),(length)):estrndup((s),(length))) -#endif - -#ifndef ALLOC_PERMANENT_ZVAL -# define ALLOC_PERMANENT_ZVAL(z) \ - (z) = (zval*)malloc(sizeof(zval)) -#endif - /* PHP_ because this is public information via MINFO */ #define PHP_PHAR_API_VERSION "1.1.1" /* x.y.z maps to 0xyz0 */ @@ -519,15 +503,6 @@ union _phar_entry_object { extern char *(*phar_save_resolve_path)(const char *filename, int filename_len TSRMLS_DC); #endif -# define phar_stream_copy_to_stream(src, dest, maxlen, len) _php_stream_copy_to_stream_ex((src), (dest), (maxlen), (len) STREAMS_CC TSRMLS_CC) - -typedef char *phar_zstr; -#define PHAR_STR(a, b) \ - b = a; -#define PHAR_ZSTR(a, b) \ - b = a; -#define PHAR_STR_FREE(a) - BEGIN_EXTERN_C() #ifdef PHP_WIN32 @@ -631,11 +606,11 @@ int phar_entry_delref(phar_entry_data *idata TSRMLS_DC); phar_entry_info *phar_get_entry_info(phar_archive_data *phar, char *path, int path_len, char **error, int security TSRMLS_DC); phar_entry_info *phar_get_entry_info_dir(phar_archive_data *phar, char *path, int path_len, char dir, char **error, int security TSRMLS_DC); -phar_entry_data *phar_get_or_create_entry_data(char *fname, int fname_len, char *path, int path_len, char *mode, char allow_dir, char **error, int security TSRMLS_DC); -int phar_get_entry_data(phar_entry_data **ret, char *fname, int fname_len, char *path, int path_len, char *mode, char allow_dir, char **error, int security TSRMLS_DC); +phar_entry_data *phar_get_or_create_entry_data(char *fname, int fname_len, char *path, int path_len, const char *mode, char allow_dir, char **error, int security TSRMLS_DC); +int phar_get_entry_data(phar_entry_data **ret, char *fname, int fname_len, char *path, int path_len, const char *mode, char allow_dir, char **error, int security TSRMLS_DC); int phar_flush(phar_archive_data *archive, char *user_stub, long len, int convert, char **error TSRMLS_DC); int phar_detect_phar_fname_ext(const char *filename, int filename_len, const char **ext_str, int *ext_len, int executable, int for_create, int is_complete TSRMLS_DC); -int phar_split_fname(char *filename, int filename_len, char **arch, int *arch_len, char **entry, int *entry_len, int executable, int for_create TSRMLS_DC); +int phar_split_fname(const char *filename, int filename_len, char **arch, int *arch_len, char **entry, int *entry_len, int executable, int for_create TSRMLS_DC); typedef enum { pcr_use_query, diff --git a/ext/phar/phar_object.c b/ext/phar/phar_object.c index 7d2922fbaa..7c11a48f9c 100644 --- a/ext/phar/phar_object.c +++ b/ext/phar/phar_object.c @@ -1707,7 +1707,7 @@ after_open_fp: data->internal_file->fp_type = PHAR_UFP; data->internal_file->offset_abs = data->internal_file->offset = php_stream_tell(p_obj->fp); data->fp = NULL; - phar_stream_copy_to_stream(fp, p_obj->fp, PHP_STREAM_COPY_ALL, &contents_len); + php_stream_copy_to_stream_ex(fp, p_obj->fp, PHP_STREAM_COPY_ALL, &contents_len); data->internal_file->uncompressed_filesize = data->internal_file->compressed_filesize = php_stream_tell(p_obj->fp) - data->internal_file->offset; } @@ -1997,7 +1997,7 @@ static int phar_copy_file_contents(phar_entry_info *entry, php_stream *fp TSRMLS link = entry; } - if (SUCCESS != phar_stream_copy_to_stream(phar_get_efp(link, 0 TSRMLS_CC), fp, link->uncompressed_filesize, NULL)) { + if (SUCCESS != php_stream_copy_to_stream_ex(phar_get_efp(link, 0 TSRMLS_CC), fp, link->uncompressed_filesize, NULL)) { zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Cannot convert phar archive \"%s\", unable to copy entry \"%s\" contents", entry->phar->fname, entry->filename); return FAILURE; @@ -3651,7 +3651,7 @@ static void phar_add_file(phar_archive_data **pphar, char *filename, int filenam zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Entry %s could not be written to", filename); return; } - phar_stream_copy_to_stream(contents_file, data->fp, PHP_STREAM_COPY_ALL, &contents_len); + php_stream_copy_to_stream_ex(contents_file, data->fp, PHP_STREAM_COPY_ALL, &contents_len); } data->internal_file->compressed_filesize = data->internal_file->uncompressed_filesize = contents_len; @@ -4224,7 +4224,7 @@ static int phar_extract_file(zend_bool overwrite, phar_entry_info *entry, char * return FAILURE; } - if (SUCCESS != phar_stream_copy_to_stream(phar_get_efp(entry, 0 TSRMLS_CC), fp, entry->uncompressed_filesize, NULL)) { + if (SUCCESS != php_stream_copy_to_stream_ex(phar_get_efp(entry, 0 TSRMLS_CC), fp, entry->uncompressed_filesize, NULL)) { spprintf(error, 4096, "Cannot extract \"%s\" to \"%s\", copying contents failed", entry->filename, fullpath); efree(fullpath); php_stream_close(fp); diff --git a/ext/phar/stream.c b/ext/phar/stream.c index f4197a5b11..1b353e0d18 100644 --- a/ext/phar/stream.c +++ b/ext/phar/stream.c @@ -56,7 +56,7 @@ php_stream_wrapper php_stream_phar_wrapper = { /** * Open a phar file for streams API */ -php_url* phar_parse_url(php_stream_wrapper *wrapper, char *filename, char *mode, int options TSRMLS_DC) /* {{{ */ +php_url* phar_parse_url(php_stream_wrapper *wrapper, const char *filename, const char *mode, int options TSRMLS_DC) /* {{{ */ { php_url *resource; char *arch = NULL, *entry = NULL, *error; @@ -155,7 +155,7 @@ php_url* phar_parse_url(php_stream_wrapper *wrapper, char *filename, char *mode, /** * used for fopen('phar://...') and company */ -static php_stream * phar_wrapper_open_url(php_stream_wrapper *wrapper, char *path, char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC) /* {{{ */ +static php_stream * phar_wrapper_open_url(php_stream_wrapper *wrapper, const char *path, const char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC) /* {{{ */ { phar_archive_data *phar; phar_entry_data *idata; @@ -563,7 +563,7 @@ static int phar_stream_stat(php_stream *stream, php_stream_statbuf *ssb TSRMLS_D /** * Stream wrapper stat implementation of stat() */ -static int phar_wrapper_stat(php_stream_wrapper *wrapper, char *url, int flags, +static int phar_wrapper_stat(php_stream_wrapper *wrapper, const char *url, int flags, php_stream_statbuf *ssb, php_stream_context *context TSRMLS_DC) /* {{{ */ { php_url *resource = NULL; @@ -627,21 +627,16 @@ static int phar_wrapper_stat(php_stream_wrapper *wrapper, char *url, int flags, } /* check for mounted directories */ if (phar->mounted_dirs.arBuckets && zend_hash_num_elements(&phar->mounted_dirs)) { - phar_zstr key; char *str_key; ulong unused; uint keylen; HashPosition pos; - zend_hash_internal_pointer_reset_ex(&phar->mounted_dirs, &pos); - while (FAILURE != zend_hash_has_more_elements_ex(&phar->mounted_dirs, &pos)) { - if (HASH_KEY_NON_EXISTENT == zend_hash_get_current_key_ex(&phar->mounted_dirs, &key, &keylen, &unused, 0, &pos)) { - break; - } - PHAR_STR(key, str_key); + for (zend_hash_internal_pointer_reset_ex(&phar->mounted_dirs, &pos); + HASH_KEY_NON_EXISTENT != zend_hash_get_current_key_ex(&phar->mounted_dirs, &str_key, &keylen, &unused, 0, &pos); + zend_hash_move_forward_ex(&phar->mounted_dirs, &pos) + ) { if ((int)keylen >= internal_file_len || strncmp(str_key, internal_file, keylen)) { - zend_hash_move_forward_ex(&phar->mounted_dirs, &pos); - PHAR_STR_FREE(str_key); continue; } else { char *test; @@ -649,17 +644,14 @@ static int phar_wrapper_stat(php_stream_wrapper *wrapper, char *url, int flags, php_stream_statbuf ssbi; if (SUCCESS != zend_hash_find(&phar->manifest, str_key, keylen, (void **) &entry)) { - PHAR_STR_FREE(str_key); goto free_resource; } - PHAR_STR_FREE(str_key); if (!entry->tmp || !entry->is_mounted) { goto free_resource; } test_len = spprintf(&test, MAXPATHLEN, "%s%s", entry->tmp, internal_file + keylen); if (SUCCESS != php_stream_stat_path(test, &ssbi)) { efree(test); - zend_hash_move_forward_ex(&phar->mounted_dirs, &pos); continue; } /* mount the file/directory just in time */ @@ -686,7 +678,7 @@ free_resource: /** * Unlink a file within a phar archive */ -static int phar_wrapper_unlink(php_stream_wrapper *wrapper, char *url, int options, php_stream_context *context TSRMLS_DC) /* {{{ */ +static int phar_wrapper_unlink(php_stream_wrapper *wrapper, const char *url, int options, php_stream_context *context TSRMLS_DC) /* {{{ */ { php_url *resource; char *internal_file, *error; @@ -762,7 +754,7 @@ static int phar_wrapper_unlink(php_stream_wrapper *wrapper, char *url, int optio } /* }}} */ -static int phar_wrapper_rename(php_stream_wrapper *wrapper, char *url_from, char *url_to, int options, php_stream_context *context TSRMLS_DC) /* {{{ */ +static int phar_wrapper_rename(php_stream_wrapper *wrapper, const char *url_from, const char *url_to, int options, php_stream_context *context TSRMLS_DC) /* {{{ */ { php_url *resource_from, *resource_to; char *error; @@ -910,7 +902,6 @@ static int phar_wrapper_rename(php_stream_wrapper *wrapper, char *url_from, char /* Rename directory. Update all nested paths */ if (is_dir) { int key_type; - phar_zstr key, new_key; char *str_key, *new_str_key; uint key_len, new_key_len; ulong unused; @@ -918,12 +909,10 @@ static int phar_wrapper_rename(php_stream_wrapper *wrapper, char *url_from, char uint to_len = strlen(resource_to->path+1); for (zend_hash_internal_pointer_reset(&phar->manifest); - HASH_KEY_NON_EXISTENT != (key_type = zend_hash_get_current_key_ex(&phar->manifest, &key, &key_len, &unused, 0, NULL)) && + HASH_KEY_NON_EXISTENT != (key_type = zend_hash_get_current_key_ex(&phar->manifest, &str_key, &key_len, &unused, 0, NULL)) && SUCCESS == zend_hash_get_current_data(&phar->manifest, (void **) &entry); - zend_hash_move_forward(&phar->manifest)) { - - PHAR_STR(key, str_key); - + zend_hash_move_forward(&phar->manifest) + ) { if (!entry->is_deleted && key_len > from_len && memcmp(str_key, resource_from->path+1, from_len) == 0 && @@ -941,18 +930,14 @@ static int phar_wrapper_rename(php_stream_wrapper *wrapper, char *url_from, char entry->filename = new_str_key; entry->filename_len = new_key_len; - PHAR_ZSTR(new_str_key, new_key); - zend_hash_update_current_key_ex(&phar->manifest, key_type, new_key, new_key_len, 0, HASH_UPDATE_KEY_ANYWAY, NULL); + zend_hash_update_current_key_ex(&phar->manifest, key_type, new_str_key, new_key_len, 0, HASH_UPDATE_KEY_ANYWAY, NULL); } - PHAR_STR_FREE(str_key); } for (zend_hash_internal_pointer_reset(&phar->virtual_dirs); - HASH_KEY_NON_EXISTENT != (key_type = zend_hash_get_current_key_ex(&phar->virtual_dirs, &key, &key_len, &unused, 0, NULL)); - zend_hash_move_forward(&phar->virtual_dirs)) { - - PHAR_STR(key, str_key); - + HASH_KEY_NON_EXISTENT != (key_type = zend_hash_get_current_key_ex(&phar->virtual_dirs, &str_key, &key_len, &unused, 0, NULL)); + zend_hash_move_forward(&phar->virtual_dirs) + ) { if (key_len >= from_len && memcmp(str_key, resource_from->path+1, from_len) == 0 && (key_len == from_len || IS_SLASH(str_key[from_len]))) { @@ -963,20 +948,16 @@ static int phar_wrapper_rename(php_stream_wrapper *wrapper, char *url_from, char memcpy(new_str_key + to_len, str_key + from_len, key_len - from_len); new_str_key[new_key_len] = 0; - PHAR_ZSTR(new_str_key, new_key); - zend_hash_update_current_key_ex(&phar->virtual_dirs, key_type, new_key, new_key_len, 0, HASH_UPDATE_KEY_ANYWAY, NULL); + zend_hash_update_current_key_ex(&phar->virtual_dirs, key_type, new_str_key, new_key_len, 0, HASH_UPDATE_KEY_ANYWAY, NULL); efree(new_str_key); } - PHAR_STR_FREE(str_key); } for (zend_hash_internal_pointer_reset(&phar->mounted_dirs); - HASH_KEY_NON_EXISTENT != (key_type = zend_hash_get_current_key_ex(&phar->mounted_dirs, &key, &key_len, &unused, 0, NULL)) && + HASH_KEY_NON_EXISTENT != (key_type = zend_hash_get_current_key_ex(&phar->mounted_dirs, &str_key, &key_len, &unused, 0, NULL)) && SUCCESS == zend_hash_get_current_data(&phar->mounted_dirs, (void **) &entry); - zend_hash_move_forward(&phar->mounted_dirs)) { - - PHAR_STR(key, str_key); - + zend_hash_move_forward(&phar->mounted_dirs) + ) { if (key_len >= from_len && memcmp(str_key, resource_from->path+1, from_len) == 0 && (key_len == from_len || IS_SLASH(str_key[from_len]))) { @@ -987,11 +968,9 @@ static int phar_wrapper_rename(php_stream_wrapper *wrapper, char *url_from, char memcpy(new_str_key + to_len, str_key + from_len, key_len - from_len); new_str_key[new_key_len] = 0; - PHAR_ZSTR(new_str_key, new_key); - zend_hash_update_current_key_ex(&phar->mounted_dirs, key_type, new_key, new_key_len, 0, HASH_UPDATE_KEY_ANYWAY, NULL); + zend_hash_update_current_key_ex(&phar->mounted_dirs, key_type, new_str_key, new_key_len, 0, HASH_UPDATE_KEY_ANYWAY, NULL); efree(new_str_key); } - PHAR_STR_FREE(str_key); } } diff --git a/ext/phar/stream.h b/ext/phar/stream.h index b22b67ab01..0155759d12 100644 --- a/ext/phar/stream.h +++ b/ext/phar/stream.h @@ -21,13 +21,13 @@ BEGIN_EXTERN_C() -php_url* phar_parse_url(php_stream_wrapper *wrapper, char *filename, char *mode, int options TSRMLS_DC); +php_url* phar_parse_url(php_stream_wrapper *wrapper, const char *filename, const char *mode, int options TSRMLS_DC); void phar_entry_remove(phar_entry_data *idata, char **error TSRMLS_DC); -static php_stream* phar_wrapper_open_url(php_stream_wrapper *wrapper, char *path, char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC); -static int phar_wrapper_rename(php_stream_wrapper *wrapper, char *url_from, char *url_to, int options, php_stream_context *context TSRMLS_DC); -static int phar_wrapper_unlink(php_stream_wrapper *wrapper, char *url, int options, php_stream_context *context TSRMLS_DC); -static int phar_wrapper_stat(php_stream_wrapper *wrapper, char *url, int flags, php_stream_statbuf *ssb, php_stream_context *context TSRMLS_DC); +static php_stream* phar_wrapper_open_url(php_stream_wrapper *wrapper, const char *path, const char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC); +static int phar_wrapper_rename(php_stream_wrapper *wrapper, const char *url_from, const char *url_to, int options, php_stream_context *context TSRMLS_DC); +static int phar_wrapper_unlink(php_stream_wrapper *wrapper, const char *url, int options, php_stream_context *context TSRMLS_DC); +static int phar_wrapper_stat(php_stream_wrapper *wrapper, const char *url, int flags, php_stream_statbuf *ssb, php_stream_context *context TSRMLS_DC); /* file/stream handlers */ static size_t phar_stream_write(php_stream *stream, const char *buf, size_t count TSRMLS_DC); diff --git a/ext/phar/tar.c b/ext/phar/tar.c index 0e60e3db13..180675a9d2 100644 --- a/ext/phar/tar.c +++ b/ext/phar/tar.c @@ -783,7 +783,7 @@ static int phar_tar_writeheaders(void *pDest, void *argument TSRMLS_DC) /* {{{ * return ZEND_HASH_APPLY_STOP; } - if (SUCCESS != phar_stream_copy_to_stream(phar_get_efp(entry, 0 TSRMLS_CC), fp->new, entry->uncompressed_filesize, NULL)) { + if (SUCCESS != php_stream_copy_to_stream_ex(phar_get_efp(entry, 0 TSRMLS_CC), fp->new, entry->uncompressed_filesize, NULL)) { if (fp->error) { spprintf(fp->error, 4096, "tar-based phar \"%s\" cannot be created, contents of file \"%s\" could not be written", entry->phar->fname, entry->filename); } @@ -1288,7 +1288,7 @@ nostub: if (!filter) { /* copy contents uncompressed rather than lose them */ - phar_stream_copy_to_stream(newfile, phar->fp, PHP_STREAM_COPY_ALL, NULL); + php_stream_copy_to_stream_ex(newfile, phar->fp, PHP_STREAM_COPY_ALL, NULL); php_stream_close(newfile); if (error) { spprintf(error, 4096, "unable to compress all contents of phar \"%s\" using zlib, PHP versions older than 5.2.6 have a buggy zlib", phar->fname); @@ -1297,7 +1297,7 @@ nostub: } php_stream_filter_append(&phar->fp->writefilters, filter); - phar_stream_copy_to_stream(newfile, phar->fp, PHP_STREAM_COPY_ALL, NULL); + php_stream_copy_to_stream_ex(newfile, phar->fp, PHP_STREAM_COPY_ALL, NULL); php_stream_filter_flush(filter, 1); php_stream_filter_remove(filter, 1 TSRMLS_CC); php_stream_close(phar->fp); @@ -1308,14 +1308,14 @@ nostub: filter = php_stream_filter_create("bzip2.compress", NULL, php_stream_is_persistent(phar->fp) TSRMLS_CC); php_stream_filter_append(&phar->fp->writefilters, filter); - phar_stream_copy_to_stream(newfile, phar->fp, PHP_STREAM_COPY_ALL, NULL); + php_stream_copy_to_stream_ex(newfile, phar->fp, PHP_STREAM_COPY_ALL, NULL); php_stream_filter_flush(filter, 1); php_stream_filter_remove(filter, 1 TSRMLS_CC); php_stream_close(phar->fp); /* use the temp stream as our base */ phar->fp = newfile; } else { - phar_stream_copy_to_stream(newfile, phar->fp, PHP_STREAM_COPY_ALL, NULL); + php_stream_copy_to_stream_ex(newfile, phar->fp, PHP_STREAM_COPY_ALL, NULL); /* we could also reopen the file in "rb" mode but there is no need for that */ php_stream_close(newfile); } diff --git a/ext/phar/tests/031.phpt b/ext/phar/tests/031.phpt index 4d5988621d..d458f068f5 100644 --- a/ext/phar/tests/031.phpt +++ b/ext/phar/tests/031.phpt @@ -22,10 +22,10 @@ require $pname; ===DONE=== --CLEAN-- <?php -unlink(dirname(__FILE__) . '/files/phar_oo_test.phar.php'); +unlink(dirname(__FILE__) . '/files/031.phar.php'); __halt_compiler(); ?> --EXPECTF-- string(25) "<?php echo new new class;" -Parse error: %s in phar://%sphar_oo_test.phar.php/a.php on line %d +Parse error: %s in phar://%s031.phar.php/a.php on line %d diff --git a/ext/phar/tests/032.phpt b/ext/phar/tests/032.phpt index faf3dcbf58..4df6cc32b0 100644 --- a/ext/phar/tests/032.phpt +++ b/ext/phar/tests/032.phpt @@ -21,9 +21,9 @@ echo $e->getMessage(); ===DONE=== --CLEAN-- <?php -unlink(dirname(__FILE__) . '/files/phar_oo_test.phar.php'); +unlink(dirname(__FILE__) . '/files/032.phar.php'); __halt_compiler(); ?> --EXPECTF-- -phar "%sphar_oo_test.phar.php" does not have a signature===DONE===
\ No newline at end of file +phar "%s032.phar.php" does not have a signature===DONE===
\ No newline at end of file diff --git a/ext/phar/tests/files/phar_oo_test.inc b/ext/phar/tests/files/phar_oo_test.inc index e92b4444c1..45421568de 100644 --- a/ext/phar/tests/files/phar_oo_test.inc +++ b/ext/phar/tests/files/phar_oo_test.inc @@ -2,7 +2,8 @@ ini_set('date.timezone', 'GMT'); -$fname = dirname(__FILE__) . '/phar_oo_test.phar.php'; +$tname = basename(current(get_included_files()), ".php"); +$fname = dirname(__FILE__) . "/$tname.phar.php"; $pname = 'phar://' . $fname; $file = (binary)'<?php include "' . $pname . '/a.php"; __HALT_COMPILER(); ?>'; diff --git a/ext/phar/tests/phar_buildfromdirectory1.phpt b/ext/phar/tests/phar_buildfromdirectory1.phpt index 63e06fa474..957f246664 100644 --- a/ext/phar/tests/phar_buildfromdirectory1.phpt +++ b/ext/phar/tests/phar_buildfromdirectory1.phpt @@ -7,7 +7,7 @@ phar.require_hash=0 phar.readonly=0 --FILE-- <?php -$phar = new Phar(dirname(__FILE__) . '/buildfromdirectory.phar'); +$phar = new Phar(dirname(__FILE__) . '/buildfromdirectory1.phar'); try { ini_set('phar.readonly', 1); $phar->buildFromDirectory(1); @@ -19,7 +19,7 @@ try { ===DONE=== --CLEAN-- <?php -unlink(dirname(__FILE__) . '/buildfromdirectory.phar'); +unlink(dirname(__FILE__) . '/buildfromdirectory1.phar'); __HALT_COMPILER(); ?> --EXPECTF-- diff --git a/ext/phar/tests/phar_buildfromdirectory2-win.phpt b/ext/phar/tests/phar_buildfromdirectory2-win.phpt index 9dbcf965e3..5ed890a48b 100644 --- a/ext/phar/tests/phar_buildfromdirectory2-win.phpt +++ b/ext/phar/tests/phar_buildfromdirectory2-win.phpt @@ -11,7 +11,7 @@ phar.readonly=0 --FILE-- <?php try { - $phar = new Phar(dirname(__FILE__) . '/buildfromdirectory.phar'); + $phar = new Phar(dirname(__FILE__) . '/buildfromdirectory2.phar'); $phar->buildFromDirectory(1); } catch (Exception $e) { var_dump(get_class($e)); @@ -21,7 +21,7 @@ try { ===DONE=== --CLEAN-- <?php -unlink(dirname(__FILE__) . '/buildfromdirectory.phar'); +unlink(dirname(__FILE__) . '/buildfromdirectory2.phar'); __HALT_COMPILER(); ?> --EXPECTF-- diff --git a/ext/phar/tests/phar_buildfromdirectory2.phpt b/ext/phar/tests/phar_buildfromdirectory2.phpt index 639ff0bd4b..a33e50abbb 100644 --- a/ext/phar/tests/phar_buildfromdirectory2.phpt +++ b/ext/phar/tests/phar_buildfromdirectory2.phpt @@ -11,7 +11,7 @@ phar.readonly=0 --FILE-- <?php try { - $phar = new Phar(dirname(__FILE__) . '/buildfromdirectory.phar'); + $phar = new Phar(dirname(__FILE__) . '/buildfromdirectory2.phar'); $phar->buildFromDirectory(1); } catch (Exception $e) { var_dump(get_class($e)); @@ -21,7 +21,7 @@ try { ===DONE=== --CLEAN-- <?php -unlink(dirname(__FILE__) . '/buildfromdirectory.phar'); +unlink(dirname(__FILE__) . '/buildfromdirectory2.phar'); __HALT_COMPILER(); ?> --EXPECTF-- diff --git a/ext/phar/tests/phar_buildfromdirectory3.phpt b/ext/phar/tests/phar_buildfromdirectory3.phpt index 2134cbdb53..921e39593d 100644 --- a/ext/phar/tests/phar_buildfromdirectory3.phpt +++ b/ext/phar/tests/phar_buildfromdirectory3.phpt @@ -9,7 +9,7 @@ phar.readonly=0 <?php try { - $phar = new Phar(dirname(__FILE__) . '/buildfromiterator.phar'); + $phar = new Phar(dirname(__FILE__) . '/buildfromdirectory3.phar'); $phar->buildFromDirectory('files', new stdClass); } catch (Exception $e) { var_dump(get_class($e)); @@ -19,7 +19,7 @@ try { ===DONE=== --CLEAN-- <?php -unlink(dirname(__FILE__) . '/buildfromiterator.phar'); +unlink(dirname(__FILE__) . '/buildfromdirectory3.phar'); __HALT_COMPILER(); ?> --EXPECTF-- diff --git a/ext/phar/tests/phar_buildfromdirectory4.phpt b/ext/phar/tests/phar_buildfromdirectory4.phpt index 683ac4bbc8..5ee2c33871 100644 --- a/ext/phar/tests/phar_buildfromdirectory4.phpt +++ b/ext/phar/tests/phar_buildfromdirectory4.phpt @@ -9,14 +9,14 @@ open_basedir= --FILE-- <?php -mkdir(dirname(__FILE__).'/testdir'); +mkdir(dirname(__FILE__).'/testdir4'); foreach(range(1, 4) as $i) { - file_put_contents(dirname(__FILE__)."/testdir/file$i.txt", "some content for file $i"); + file_put_contents(dirname(__FILE__)."/testdir4/file$i.txt", "some content for file $i"); } try { - $phar = new Phar(dirname(__FILE__) . '/buildfromdirectory.phar'); - $a = $phar->buildFromDirectory(dirname(__FILE__) . '/testdir'); + $phar = new Phar(dirname(__FILE__) . '/buildfromdirectory4.phar'); + $a = $phar->buildFromDirectory(dirname(__FILE__) . '/testdir4'); asort($a); var_dump($a); } catch (Exception $e) { @@ -24,28 +24,28 @@ try { echo $e->getMessage() . "\n"; } -var_dump(file_exists(dirname(__FILE__) . '/buildfromdirectory.phar')); +var_dump(file_exists(dirname(__FILE__) . '/buildfromdirectory4.phar')); ?> ===DONE=== --CLEAN-- <?php -unlink(dirname(__FILE__) . '/buildfromdirectory.phar'); +unlink(dirname(__FILE__) . '/buildfromdirectory4.phar'); foreach(range(1, 4) as $i) { - unlink(dirname(__FILE__) . "/testdir/file$i.txt"); + unlink(dirname(__FILE__) . "/testdir4/file$i.txt"); } -rmdir(dirname(__FILE__) . '/testdir'); +rmdir(dirname(__FILE__) . '/testdir4'); ?> --EXPECTF-- array(4) { ["file1.txt"]=> - string(%d) "%stestdir%cfile1.txt" + string(%d) "%stestdir4%cfile1.txt" ["file2.txt"]=> - string(%d) "%stestdir%cfile2.txt" + string(%d) "%stestdir4%cfile2.txt" ["file3.txt"]=> - string(%d) "%stestdir%cfile3.txt" + string(%d) "%stestdir4%cfile3.txt" ["file4.txt"]=> - string(%d) "%stestdir%cfile4.txt" + string(%d) "%stestdir4%cfile4.txt" } bool(true) ===DONE=== diff --git a/ext/phar/tests/phar_buildfromdirectory5.phpt b/ext/phar/tests/phar_buildfromdirectory5.phpt index 51e5cec691..f20c52ab91 100644 --- a/ext/phar/tests/phar_buildfromdirectory5.phpt +++ b/ext/phar/tests/phar_buildfromdirectory5.phpt @@ -8,14 +8,14 @@ phar.readonly=0 --FILE-- <?php -mkdir(dirname(__FILE__).'/testdir'); +mkdir(dirname(__FILE__).'/testdir5'); foreach(range(1, 4) as $i) { - file_put_contents(dirname(__FILE__)."/testdir/file$i.txt", "some content for file $i"); + file_put_contents(dirname(__FILE__)."/testdir5/file$i.txt", "some content for file $i"); } try { - $phar = new Phar(dirname(__FILE__) . '/buildfromdirectory.phar'); - $a = $phar->buildFromDirectory(dirname(__FILE__) . '/testdir', '/\.txt/'); + $phar = new Phar(dirname(__FILE__) . '/buildfromdirectory5.phar'); + $a = $phar->buildFromDirectory(dirname(__FILE__) . '/testdir5', '/\.txt/'); asort($a); var_dump($a); } catch (Exception $e) { @@ -23,28 +23,28 @@ try { echo $e->getMessage() . "\n"; } -var_dump(file_exists(dirname(__FILE__) . '/buildfromdirectory.phar')); +var_dump(file_exists(dirname(__FILE__) . '/buildfromdirectory5.phar')); ?> ===DONE=== --CLEAN-- <?php -unlink(dirname(__FILE__) . '/buildfromdirectory.phar'); +unlink(dirname(__FILE__) . '/buildfromdirectory5.phar'); foreach(range(1, 4) as $i) { - unlink(dirname(__FILE__) . "/testdir/file$i.txt"); + unlink(dirname(__FILE__) . "/testdir5/file$i.txt"); } -rmdir(dirname(__FILE__) . '/testdir'); +rmdir(dirname(__FILE__) . '/testdir5'); ?> --EXPECTF-- array(4) { ["file1.txt"]=> - string(%d) "%stestdir%cfile1.txt" + string(%d) "%stestdir5%cfile1.txt" ["file2.txt"]=> - string(%d) "%stestdir%cfile2.txt" + string(%d) "%stestdir5%cfile2.txt" ["file3.txt"]=> - string(%d) "%stestdir%cfile3.txt" + string(%d) "%stestdir5%cfile3.txt" ["file4.txt"]=> - string(%d) "%stestdir%cfile4.txt" + string(%d) "%stestdir5%cfile4.txt" } bool(true) ===DONE=== diff --git a/ext/phar/tests/phar_buildfromdirectory6.phpt b/ext/phar/tests/phar_buildfromdirectory6.phpt index 99566c1926..5537ebac23 100644 --- a/ext/phar/tests/phar_buildfromdirectory6.phpt +++ b/ext/phar/tests/phar_buildfromdirectory6.phpt @@ -8,30 +8,30 @@ phar.readonly=0 --FILE-- <?php -mkdir(dirname(__FILE__).'/testdir', 0777); +mkdir(dirname(__FILE__).'/testdir6', 0777); foreach(range(1, 4) as $i) { - file_put_contents(dirname(__FILE__)."/testdir/file$i.txt", "some content for file $i"); + file_put_contents(dirname(__FILE__)."/testdir6/file$i.txt", "some content for file $i"); } try { - $phar = new Phar(dirname(__FILE__) . '/buildfromdirectory.phar'); - var_dump($phar->buildFromDirectory(dirname(__FILE__) . '/testdir', '/\.php$/')); + $phar = new Phar(dirname(__FILE__) . '/buildfromdirectory6.phar'); + var_dump($phar->buildFromDirectory(dirname(__FILE__) . '/testdir6', '/\.php$/')); } catch (Exception $e) { var_dump(get_class($e)); echo $e->getMessage() . "\n"; } -var_dump(file_exists(dirname(__FILE__) . '/buildfromdirectory.phar')); +var_dump(file_exists(dirname(__FILE__) . '/buildfromdirectory6.phar')); ?> ===DONE=== --CLEAN-- <?php -unlink(dirname(__FILE__) . '/buildfromdirectory.phar'); +unlink(dirname(__FILE__) . '/buildfromdirectory6.phar'); foreach(range(1, 4) as $i) { - unlink(dirname(__FILE__) . "/testdir/file$i.txt"); + unlink(dirname(__FILE__) . "/testdir6/file$i.txt"); } -rmdir(dirname(__FILE__) . '/testdir'); +rmdir(dirname(__FILE__) . '/testdir6'); ?> --EXPECT-- array(0) { diff --git a/ext/phar/tests/phar_buildfromiterator1.phpt b/ext/phar/tests/phar_buildfromiterator1.phpt index 238ede6cbe..0f656b64f2 100644 --- a/ext/phar/tests/phar_buildfromiterator1.phpt +++ b/ext/phar/tests/phar_buildfromiterator1.phpt @@ -7,7 +7,7 @@ phar.require_hash=0 phar.readonly=0 --FILE-- <?php -$phar = new Phar(dirname(__FILE__) . '/buildfromiterator.phar'); +$phar = new Phar(dirname(__FILE__) . '/buildfromiterator1.phar'); try { ini_set('phar.readonly', 1); $phar->buildFromIterator(1); @@ -19,7 +19,7 @@ try { ===DONE=== --CLEAN-- <?php -unlink(dirname(__FILE__) . '/buildfromiterator.phar'); +unlink(dirname(__FILE__) . '/buildfromiterator1.phar'); __HALT_COMPILER(); ?> --EXPECTF-- diff --git a/ext/phar/tests/phar_buildfromiterator10.phpt b/ext/phar/tests/phar_buildfromiterator10.phpt index 024277ed0a..e6b9c025da 100644 --- a/ext/phar/tests/phar_buildfromiterator10.phpt +++ b/ext/phar/tests/phar_buildfromiterator10.phpt @@ -11,7 +11,7 @@ phar.readonly=0 <?php try { chdir(dirname(__FILE__)); - $phar = new Phar(dirname(__FILE__) . '/buildfromiterator.phar'); + $phar = new Phar(dirname(__FILE__) . '/buildfromiterator10.phar'); $dir = new RecursiveDirectoryIterator('.'); $iter = new RecursiveIteratorIterator($dir); $a = $phar->buildFromIterator(new RegexIterator($iter, '/_\d{3}\.phpt$/'), dirname(__FILE__) . DIRECTORY_SEPARATOR); @@ -25,7 +25,7 @@ try { ===DONE=== --CLEAN-- <?php -unlink(dirname(__FILE__) . '/buildfromiterator.phar'); +unlink(dirname(__FILE__) . '/buildfromiterator10.phar'); __HALT_COMPILER(); ?> --EXPECTF-- diff --git a/ext/phar/tests/phar_buildfromiterator2.phpt b/ext/phar/tests/phar_buildfromiterator2.phpt index cdc2df1050..e9dd26e9de 100644 --- a/ext/phar/tests/phar_buildfromiterator2.phpt +++ b/ext/phar/tests/phar_buildfromiterator2.phpt @@ -8,7 +8,7 @@ phar.readonly=0 --FILE-- <?php try { - $phar = new Phar(dirname(__FILE__) . '/buildfromiterator.phar'); + $phar = new Phar(dirname(__FILE__) . '/buildfromiterator2.phar'); $phar->buildFromIterator(new stdClass); } catch (Exception $e) { var_dump(get_class($e)); @@ -18,7 +18,7 @@ try { ===DONE=== --CLEAN-- <?php -unlink(dirname(__FILE__) . '/buildfromiterator.phar'); +unlink(dirname(__FILE__) . '/buildfromiterator2.phar'); __HALT_COMPILER(); ?> --EXPECTF-- diff --git a/ext/phar/tests/phar_buildfromiterator3.phpt b/ext/phar/tests/phar_buildfromiterator3.phpt index 4a3bc7c0a5..1603631278 100644 --- a/ext/phar/tests/phar_buildfromiterator3.phpt +++ b/ext/phar/tests/phar_buildfromiterator3.phpt @@ -36,7 +36,7 @@ class myIterator implements Iterator } } try { - $phar = new Phar(dirname(__FILE__) . '/buildfromiterator.phar'); + $phar = new Phar(dirname(__FILE__) . '/buildfromiterator3.phar'); $phar->buildFromIterator(new myIterator(array()), new stdClass); } catch (Exception $e) { var_dump(get_class($e)); @@ -46,7 +46,7 @@ try { ===DONE=== --CLEAN-- <?php -unlink(dirname(__FILE__) . '/buildfromiterator.phar'); +unlink(dirname(__FILE__) . '/buildfromiterator3.phar'); __HALT_COMPILER(); ?> --EXPECTF-- diff --git a/ext/phar/tests/phar_buildfromiterator4.phpt b/ext/phar/tests/phar_buildfromiterator4.phpt index cd261386d5..9277db562b 100644 --- a/ext/phar/tests/phar_buildfromiterator4.phpt +++ b/ext/phar/tests/phar_buildfromiterator4.phpt @@ -37,7 +37,7 @@ class myIterator implements Iterator } try { chdir(dirname(__FILE__)); - $phar = new Phar(dirname(__FILE__) . '/buildfromiterator.phar'); + $phar = new Phar(dirname(__FILE__) . '/buildfromiterator4.phar'); var_dump($phar->buildFromIterator(new myIterator( array( 'a' => basename(__FILE__, 'php') . 'phpt', @@ -54,7 +54,7 @@ try { ===DONE=== --CLEAN-- <?php -unlink(dirname(__FILE__) . '/buildfromiterator.phar'); +unlink(dirname(__FILE__) . '/buildfromiterator4.phar'); __HALT_COMPILER(); ?> --EXPECTF-- diff --git a/ext/phar/tests/phar_buildfromiterator5.phpt b/ext/phar/tests/phar_buildfromiterator5.phpt index 8431c12a7c..b6fafec6f4 100644 --- a/ext/phar/tests/phar_buildfromiterator5.phpt +++ b/ext/phar/tests/phar_buildfromiterator5.phpt @@ -37,7 +37,7 @@ class myIterator implements Iterator } try { chdir(dirname(__FILE__)); - $phar = new Phar(dirname(__FILE__) . '/buildfromiterator.phar'); + $phar = new Phar(dirname(__FILE__) . '/buildfromiterator5.phar'); var_dump($phar->buildFromIterator(new myIterator(array('a' => new stdClass)))); } catch (Exception $e) { var_dump(get_class($e)); @@ -47,7 +47,7 @@ try { ===DONE=== --CLEAN-- <?php -unlink(dirname(__FILE__) . '/buildfromiterator.phar'); +unlink(dirname(__FILE__) . '/buildfromiterator5.phar'); __HALT_COMPILER(); ?> --EXPECTF-- diff --git a/ext/phar/tests/phar_buildfromiterator6.phpt b/ext/phar/tests/phar_buildfromiterator6.phpt index 9c506c8528..3a315fae4d 100644 --- a/ext/phar/tests/phar_buildfromiterator6.phpt +++ b/ext/phar/tests/phar_buildfromiterator6.phpt @@ -37,7 +37,7 @@ class myIterator implements Iterator } try { chdir(dirname(__FILE__)); - $phar = new Phar(dirname(__FILE__) . '/buildfromiterator.phar'); + $phar = new Phar(dirname(__FILE__) . '/buildfromiterator6.phar'); var_dump($phar->buildFromIterator(new myIterator(array(basename(__FILE__, 'php') . 'phpt')))); } catch (Exception $e) { var_dump(get_class($e)); @@ -47,7 +47,7 @@ try { ===DONE=== --CLEAN-- <?php -unlink(dirname(__FILE__) . '/buildfromiterator.phar'); +unlink(dirname(__FILE__) . '/buildfromiterator6.phar'); __HALT_COMPILER(); ?> --EXPECTF-- diff --git a/ext/phar/tests/phar_buildfromiterator7.phpt b/ext/phar/tests/phar_buildfromiterator7.phpt index 2bac4c8269..3dd8fc1b00 100644 --- a/ext/phar/tests/phar_buildfromiterator7.phpt +++ b/ext/phar/tests/phar_buildfromiterator7.phpt @@ -37,7 +37,7 @@ class myIterator implements Iterator } try { chdir(dirname(__FILE__)); - $phar = new Phar(dirname(__FILE__) . '/buildfromiterator.phar'); + $phar = new Phar(dirname(__FILE__) . '/buildfromiterator7.phar'); var_dump($phar->buildFromIterator(new myIterator(array('a' => basename(__FILE__, 'php') . '/oopsie/there.phpt')))); } catch (Exception $e) { var_dump(get_class($e)); @@ -47,7 +47,7 @@ try { ===DONE=== --CLEAN-- <?php -unlink(dirname(__FILE__) . '/buildfromiterator.phar'); +unlink(dirname(__FILE__) . '/buildfromiterator7.phar'); __HALT_COMPILER(); ?> --EXPECTF-- diff --git a/ext/phar/tests/phar_buildfromiterator8.phpt b/ext/phar/tests/phar_buildfromiterator8.phpt index bb1b780d75..de37ee8687 100644 --- a/ext/phar/tests/phar_buildfromiterator8.phpt +++ b/ext/phar/tests/phar_buildfromiterator8.phpt @@ -8,7 +8,7 @@ phar.readonly=0 <?php try { chdir(dirname(__FILE__)); - $phar = new Phar(dirname(__FILE__) . '/buildfromiterator.phar'); + $phar = new Phar(dirname(__FILE__) . '/buildfromiterator8.phar'); $a = $phar->buildFromIterator(new RegexIterator(new DirectoryIterator('.'), '/^\d{0,3}\.phpt\\z|^\.\\z|^\.\.\\z/'), dirname(__FILE__) . DIRECTORY_SEPARATOR); asort($a); var_dump($a); @@ -20,7 +20,7 @@ try { ===DONE=== --CLEAN-- <?php -unlink(dirname(__FILE__) . '/buildfromiterator.phar'); +unlink(dirname(__FILE__) . '/buildfromiterator8.phar'); __HALT_COMPILER(); ?> --EXPECTF-- diff --git a/ext/phar/tests/phar_buildfromiterator9.phpt b/ext/phar/tests/phar_buildfromiterator9.phpt index 0b56307545..2c9306b6cc 100644 --- a/ext/phar/tests/phar_buildfromiterator9.phpt +++ b/ext/phar/tests/phar_buildfromiterator9.phpt @@ -37,7 +37,7 @@ class myIterator implements Iterator } try { chdir(dirname(__FILE__)); - $phar = new Phar(dirname(__FILE__) . '/buildfromiterator.phar'); + $phar = new Phar(dirname(__FILE__) . '/buildfromiterator9.phar'); var_dump($phar->buildFromIterator(new myIterator(array('a' => $a = fopen(basename(__FILE__, 'php') . 'phpt', 'r'))))); fclose($a); } catch (Exception $e) { @@ -48,7 +48,7 @@ try { ===DONE=== --CLEAN-- <?php -unlink(dirname(__FILE__) . '/buildfromiterator.phar'); +unlink(dirname(__FILE__) . '/buildfromiterator9.phar'); __HALT_COMPILER(); ?> --EXPECTF-- diff --git a/ext/phar/tests/phar_extract.phpt b/ext/phar/tests/phar_extract.phpt index 01d65f9091..bc545236fd 100644 --- a/ext/phar/tests/phar_extract.phpt +++ b/ext/phar/tests/phar_extract.phpt @@ -38,9 +38,9 @@ var_dump(file_get_contents(dirname(__FILE__) . '/extract1/file1.txt')); $a->extractTo(dirname(__FILE__) . '/extract1', 'subdir/ectory/file.txt'); var_dump(file_get_contents(dirname(__FILE__) . '/extract1/subdir/ectory/file.txt')); -$a->extractTo(dirname(__FILE__) . '/extract2', array('file2.txt', 'one/level')); -var_dump(file_get_contents(dirname(__FILE__) . '/extract2/file2.txt')); -var_dump(is_dir(dirname(__FILE__) . '/extract2/one/level')); +$a->extractTo(dirname(__FILE__) . '/extract1-2', array('file2.txt', 'one/level')); +var_dump(file_get_contents(dirname(__FILE__) . '/extract1-2/file2.txt')); +var_dump(is_dir(dirname(__FILE__) . '/extract1-2/one/level')); try { $a->extractTo(dirname(__FILE__) . '/whatever', 134); @@ -119,7 +119,7 @@ $e = dirname(__FILE__) . '/extract1/'; @rmdir($e . 'subdir/ectory'); @rmdir($e . 'subdir'); @rmdir($e); -$e = dirname(__FILE__) . '/extract2/'; +$e = dirname(__FILE__) . '/extract1-2/'; @unlink($e . 'file2.txt'); @rmdir($e . 'one/level'); @rmdir($e . 'one'); diff --git a/ext/phar/tests/phar_extract2.phpt b/ext/phar/tests/phar_extract2.phpt index cac509f9dc..7de8cee5b0 100644 --- a/ext/phar/tests/phar_extract2.phpt +++ b/ext/phar/tests/phar_extract2.phpt @@ -16,14 +16,14 @@ $phar->setAlias('fred'); $phar['file1.txt'] = 'hi'; $phar['file2.txt'] = 'hi2'; $phar['subdir/ectory/file.txt'] = 'hi3'; -$phar->mount($pname . '/mount', __FILE__); +$phar->mount($pname . '/mount2', __FILE__); $phar->addEmptyDir('one/level'); -$phar->extractTo(dirname(__FILE__) . '/extract', 'mount'); -$phar->extractTo(dirname(__FILE__) . '/extract'); +$phar->extractTo(dirname(__FILE__) . '/extract2', 'mount2'); +$phar->extractTo(dirname(__FILE__) . '/extract2'); $out = array(); -foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator(dirname(__FILE__) . '/extract', 0x00003000), RecursiveIteratorIterator::CHILD_FIRST) as $path => $file) { +foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator(dirname(__FILE__) . '/extract2', 0x00003000), RecursiveIteratorIterator::CHILD_FIRST) as $path => $file) { $extracted[] = $path; } @@ -38,7 +38,7 @@ foreach ($extracted as $out) { --CLEAN-- <?php @unlink(dirname(__FILE__) . '/tempmanifest2.phar.php'); -$dir = dirname(__FILE__) . '/extract/'; +$dir = dirname(__FILE__) . '/extract2/'; @unlink($dir . 'file1.txt'); @unlink($dir . 'file2.txt'); @unlink($dir . 'subdir/ectory/file.txt'); @@ -51,10 +51,10 @@ $dir = dirname(__FILE__) . '/extract1/'; @rmdir($dir); ?> --EXPECTF-- -%sextract%cfile1.txt -%sextract%cfile2.txt -%sextract%cone -%sextract%csubdir -%sextract%csubdir%cectory -%sextract%csubdir%cectory%cfile.txt +%sextract2%cfile1.txt +%sextract2%cfile2.txt +%sextract2%cone +%sextract2%csubdir +%sextract2%csubdir%cectory +%sextract2%csubdir%cectory%cfile.txt ===DONE=== diff --git a/ext/phar/tests/phar_extract3.phpt b/ext/phar/tests/phar_extract3.phpt index df85211a23..475583938b 100644 --- a/ext/phar/tests/phar_extract3.phpt +++ b/ext/phar/tests/phar_extract3.phpt @@ -9,7 +9,7 @@ phar.readonly=0 $fname = dirname(__FILE__) . '/files/bogus.zip'; $fname2 = dirname(__FILE__) . '/files/notbogus.zip'; -$extract = dirname(__FILE__) . '/test'; +$extract = dirname(__FILE__) . '/test-extract3'; $phar = new PharData($fname); @@ -34,7 +34,7 @@ try { ===DONE=== --CLEAN-- <?php -$dir = dirname(__FILE__) . '/test/'; +$dir = dirname(__FILE__) . '/test-extract3/'; @unlink($dir . 'stuff.txt'); @unlink($dir . 'nonsense.txt'); @rmdir($dir); diff --git a/ext/phar/tests/phar_oo_001.phpt b/ext/phar/tests/phar_oo_001.phpt index 7a81bbb4b8..bb4c9d7188 100644 --- a/ext/phar/tests/phar_oo_001.phpt +++ b/ext/phar/tests/phar_oo_001.phpt @@ -46,7 +46,7 @@ try { ===DONE=== --CLEAN-- <?php -unlink(dirname(__FILE__) . '/files/phar_oo_test.phar.php'); +unlink(dirname(__FILE__) . '/files/phar_oo_001.phar.php'); __halt_compiler(); ?> --EXPECT-- diff --git a/ext/phar/tests/phar_oo_001U.phpt b/ext/phar/tests/phar_oo_001U.phpt index f13ddd4b0b..a21026a5b6 100644 --- a/ext/phar/tests/phar_oo_001U.phpt +++ b/ext/phar/tests/phar_oo_001U.phpt @@ -46,7 +46,7 @@ try { ===DONE=== --CLEAN-- <?php -unlink(dirname(__FILE__) . '/files/phar_oo_test.phar.php'); +unlink(dirname(__FILE__) . '/files/phar_oo_001U.phar.php'); __halt_compiler(); ?> --EXPECT-- diff --git a/ext/phar/tests/phar_oo_002.phpt b/ext/phar/tests/phar_oo_002.phpt index 3754151d42..476cd7d3c2 100644 --- a/ext/phar/tests/phar_oo_002.phpt +++ b/ext/phar/tests/phar_oo_002.phpt @@ -50,11 +50,11 @@ foreach(new RecursiveIteratorIterator($phar) as $name => $ent) ===DONE=== --CLEAN-- <?php -unlink(dirname(__FILE__) . '/files/phar_oo_test.phar.php'); +unlink(dirname(__FILE__) . '/files/phar_oo_002.phar.php'); __halt_compiler(); ?> --EXPECTF-- -string(42) "phar://*/files/phar_oo_test.phar.php%ca.php" +string(41) "phar://*/files/phar_oo_002.phar.php%ca.php" string(5) "a.php" int(32) string(4) "file" @@ -67,7 +67,7 @@ bool(false) int(%d) int(%d) int(%d) -string(38) "phar://*/files/phar_oo_test.phar.php%cb" +string(37) "phar://*/files/phar_oo_002.phar.php%cb" string(1) "b" int(0) string(3) "dir" @@ -80,7 +80,7 @@ bool(false) int(%d) int(%d) int(%d) -string(42) "phar://*/files/phar_oo_test.phar.php%cb.php" +string(41) "phar://*/files/phar_oo_002.phar.php%cb.php" string(5) "b.php" int(32) string(4) "file" @@ -93,7 +93,7 @@ bool(false) int(%d) int(%d) int(%d) -string(42) "phar://*/files/phar_oo_test.phar.php%ce.php" +string(41) "phar://*/files/phar_oo_002.phar.php%ce.php" string(5) "e.php" int(32) string(4) "file" @@ -107,31 +107,31 @@ int(%d) int(%d) int(%d) ==RECURSIVE== -string(42) "phar://*/files/phar_oo_test.phar.php%ca.php" +string(41) "phar://*/files/phar_oo_002.phar.php%ca.php" string(5) "a.php" int(32) bool(false) NULL int(0) -string(44) "phar://*/files/phar_oo_test.phar.php/b%cc.php" +string(43) "phar://*/files/phar_oo_002.phar.php/b%cc.php" string(5) "c.php" int(34) bool(false) NULL int(0) -string(44) "phar://*/files/phar_oo_test.phar.php/b%cd.php" +string(43) "phar://*/files/phar_oo_002.phar.php/b%cd.php" string(5) "d.php" int(34) bool(false) NULL int(0) -string(42) "phar://*/files/phar_oo_test.phar.php%cb.php" +string(41) "phar://*/files/phar_oo_002.phar.php%cb.php" string(5) "b.php" int(32) bool(false) NULL int(0) -string(42) "phar://*/files/phar_oo_test.phar.php%ce.php" +string(41) "phar://*/files/phar_oo_002.phar.php%ce.php" string(5) "e.php" int(32) bool(false) diff --git a/ext/phar/tests/phar_oo_002U.phpt b/ext/phar/tests/phar_oo_002U.phpt index 26d0d68d97..da17152b32 100644 --- a/ext/phar/tests/phar_oo_002U.phpt +++ b/ext/phar/tests/phar_oo_002U.phpt @@ -50,11 +50,11 @@ foreach(new RecursiveIteratorIterator($phar) as $name => $ent) ===DONE=== --CLEAN-- <?php -unlink(dirname(__FILE__) . '/files/phar_oo_test.phar.php'); +unlink(dirname(__FILE__) . '/files/phar_oo_002U.phar.php'); __halt_compiler(); ?> --EXPECTF-- -unicode(42) "phar://*/files/phar_oo_test.phar.php%ca.php" +unicode(42) "phar://*/files/phar_oo_002.phar.php%ca.php" string(5) "a.php" int(32) unicode(4) "file" @@ -67,7 +67,7 @@ bool(false) int(%d) int(%d) int(%d) -unicode(38) "phar://*/files/phar_oo_test.phar.php%cb" +unicode(38) "phar://*/files/phar_oo_002.phar.php%cb" string(1) "b" int(0) unicode(3) "dir" @@ -80,7 +80,7 @@ bool(false) int(%d) int(%d) int(%d) -unicode(42) "phar://*/files/phar_oo_test.phar.php%cb.php" +unicode(42) "phar://*/files/phar_oo_002.phar.php%cb.php" string(5) "b.php" int(32) unicode(4) "file" @@ -93,7 +93,7 @@ bool(false) int(%d) int(%d) int(%d) -unicode(42) "phar://*/files/phar_oo_test.phar.php%ce.php" +unicode(42) "phar://*/files/phar_oo_002.phar.php%ce.php" string(5) "e.php" int(32) unicode(4) "file" @@ -107,31 +107,31 @@ int(%d) int(%d) int(%d) ==RECURSIVE== -unicode(42) "phar://*/files/phar_oo_test.phar.php%ca.php" +unicode(42) "phar://*/files/phar_oo_002.phar.php%ca.php" unicode(5) "a.php" int(32) bool(false) NULL int(0) -unicode(44) "phar://*/files/phar_oo_test.phar.php/b%cc.php" +unicode(44) "phar://*/files/phar_oo_002.phar.php/b%cc.php" unicode(5) "c.php" int(34) bool(false) NULL int(0) -unicode(44) "phar://*/files/phar_oo_test.phar.php/b%cd.php" +unicode(44) "phar://*/files/phar_oo_002.phar.php/b%cd.php" unicode(5) "d.php" int(34) bool(false) NULL int(0) -unicode(42) "phar://*/files/phar_oo_test.phar.php%cb.php" +unicode(42) "phar://*/files/phar_oo_002.phar.php%cb.php" unicode(5) "b.php" int(32) bool(false) NULL int(0) -unicode(42) "phar://*/files/phar_oo_test.phar.php%ce.php" +unicode(42) "phar://*/files/phar_oo_002.phar.php%ce.php" unicode(5) "e.php" int(32) bool(false) diff --git a/ext/phar/tests/phar_oo_003.phpt b/ext/phar/tests/phar_oo_003.phpt index ccaf7c65f8..4395792632 100644 --- a/ext/phar/tests/phar_oo_003.phpt +++ b/ext/phar/tests/phar_oo_003.phpt @@ -27,7 +27,7 @@ foreach($phar as $name => $ent) ===DONE=== --CLEAN-- <?php -unlink(dirname(__FILE__) . '/files/phar_oo_test.phar.php'); +unlink(dirname(__FILE__) . '/files/phar_oo_003.phar.php'); __halt_compiler(); ?> --EXPECTF-- diff --git a/ext/phar/tests/phar_oo_004.phpt b/ext/phar/tests/phar_oo_004.phpt index ba67749843..3e4581992e 100644 --- a/ext/phar/tests/phar_oo_004.phpt +++ b/ext/phar/tests/phar_oo_004.phpt @@ -78,7 +78,7 @@ foreach($it as $name => $ent) ===DONE=== --CLEAN-- <?php -unlink(dirname(__FILE__) . '/files/phar_oo_test.phar.php'); +unlink(dirname(__FILE__) . '/files/phar_oo_004.phar.php'); __halt_compiler(); ?> --EXPECT-- diff --git a/ext/phar/tests/phar_oo_004U.phpt b/ext/phar/tests/phar_oo_004U.phpt index 2762ee3c35..51be9dab2e 100644 --- a/ext/phar/tests/phar_oo_004U.phpt +++ b/ext/phar/tests/phar_oo_004U.phpt @@ -78,7 +78,7 @@ foreach($it as $name => $ent) ===DONE=== --CLEAN-- <?php -unlink(dirname(__FILE__) . '/files/phar_oo_test.phar.php'); +unlink(dirname(__FILE__) . '/files/phar_oo_004U.phar.php'); __halt_compiler(); ?> --EXPECT-- diff --git a/ext/phar/tests/phar_oo_005.phpt b/ext/phar/tests/phar_oo_005.phpt index cb3f298728..b01231e9c2 100644 --- a/ext/phar/tests/phar_oo_005.phpt +++ b/ext/phar/tests/phar_oo_005.phpt @@ -32,7 +32,7 @@ foreach($it as $name => $ent) ===DONE=== --CLEAN-- <?php -unlink(dirname(__FILE__) . '/files/phar_oo_test.phar.php'); +unlink(dirname(__FILE__) . '/files/phar_oo_005.phar.php'); __halt_compiler(); ?> --EXPECT-- diff --git a/ext/phar/tests/phar_oo_005U.phpt b/ext/phar/tests/phar_oo_005U.phpt index bcdcb08b0d..9c04b93cef 100644 --- a/ext/phar/tests/phar_oo_005U.phpt +++ b/ext/phar/tests/phar_oo_005U.phpt @@ -31,7 +31,7 @@ foreach($it as $name => $ent) ===DONE=== --CLEAN-- <?php -unlink(dirname(__FILE__) . '/files/phar_oo_test.phar.php'); +unlink(dirname(__FILE__) . '/files/phar_oo_005U.phar.php'); __halt_compiler(); ?> --EXPECT-- diff --git a/ext/phar/tests/phar_oo_005_5.2.phpt b/ext/phar/tests/phar_oo_005_5.2.phpt index 9e509d94b7..399edb0dd3 100644 --- a/ext/phar/tests/phar_oo_005_5.2.phpt +++ b/ext/phar/tests/phar_oo_005_5.2.phpt @@ -31,7 +31,7 @@ foreach($it as $name => $ent) ===DONE=== --CLEAN-- <?php -unlink(dirname(__FILE__) . '/files/phar_oo_test.phar.php'); +unlink(dirname(__FILE__) . '/files/phar_oo_005_5.2.phar.php'); __halt_compiler(); ?> --EXPECT-- diff --git a/ext/phar/tests/phar_oo_006.phpt b/ext/phar/tests/phar_oo_006.phpt index 556c98ce0b..5d1d705206 100644 --- a/ext/phar/tests/phar_oo_006.phpt +++ b/ext/phar/tests/phar_oo_006.phpt @@ -38,7 +38,7 @@ echo $phar['b.php']->getFilename() . "\n"; ===DONE=== --CLEAN-- <?php -unlink(dirname(__FILE__) . '/files/phar_oo_test.phar.php'); +unlink(dirname(__FILE__) . '/files/phar_oo_006.phar.php'); __halt_compiler(); ?> --EXPECTF-- diff --git a/ext/phar/tests/phar_oo_007.phpt b/ext/phar/tests/phar_oo_007.phpt index 788b11f1f8..d0b5aa5eca 100644 --- a/ext/phar/tests/phar_oo_007.phpt +++ b/ext/phar/tests/phar_oo_007.phpt @@ -59,11 +59,11 @@ var_dump($f->eof()); ===DONE=== --CLEAN-- <?php -unlink(dirname(__FILE__) . '/files/phar_oo_test.phar.php'); +unlink(dirname(__FILE__) . '/files/phar_oo_007.phar.php'); __halt_compiler(); ?> --EXPECTF-- -MyFile::__construct(phar://*/files/phar_oo_test.phar.php/a.php) +MyFile::__construct(phar://*/files/phar_oo_007.phar.php/a.php) int(%d) int(%d) int(%d) @@ -79,7 +79,7 @@ int(0) string(32) "<?php echo "This is a.php\n"; ?>" int(32) ===AGAIN=== -MyFile::__construct(phar://*/files/phar_oo_test.phar.php/a.php) +MyFile::__construct(phar://*/files/phar_oo_007.phar.php/a.php) int(0) bool(false) string(32) "<?php echo "This is a.php\n"; ?>" diff --git a/ext/phar/tests/phar_oo_008.phpt b/ext/phar/tests/phar_oo_008.phpt index 80d1ece0ca..d95af571b3 100644 --- a/ext/phar/tests/phar_oo_008.phpt +++ b/ext/phar/tests/phar_oo_008.phpt @@ -83,7 +83,7 @@ foreach($v as $k => $d) ===DONE=== --CLEAN-- <?php -unlink(dirname(__FILE__) . '/files/phar_oo_test.phar.php'); +unlink(dirname(__FILE__) . '/files/phar_oo_008.phar.php'); __halt_compiler(); ?> --EXPECTF-- diff --git a/ext/phar/tests/phar_oo_009.phpt b/ext/phar/tests/phar_oo_009.phpt index 6abd03ee30..3c842fabed 100644 --- a/ext/phar/tests/phar_oo_009.phpt +++ b/ext/phar/tests/phar_oo_009.phpt @@ -36,7 +36,7 @@ foreach($f as $k => $v) ===DONE=== --CLEAN-- <?php -unlink(dirname(__FILE__) . '/files/phar_oo_test.phar.php'); +unlink(dirname(__FILE__) . '/files/phar_oo_009.phar.php'); __halt_compiler(); ?> --EXPECTF-- diff --git a/ext/phar/tests/phar_oo_010.phpt b/ext/phar/tests/phar_oo_010.phpt index 1d3ff73242..331d300a8c 100644 --- a/ext/phar/tests/phar_oo_010.phpt +++ b/ext/phar/tests/phar_oo_010.phpt @@ -36,7 +36,7 @@ var_dump(isset($phar['b'])); ===DONE=== --CLEAN-- <?php -unlink(dirname(__FILE__) . '/files/phar_oo_test.phar.php'); +unlink(dirname(__FILE__) . '/files/phar_oo_010.phar.php'); __halt_compiler(); ?> --EXPECTF-- diff --git a/ext/phar/tests/phar_oo_011.phpt b/ext/phar/tests/phar_oo_011.phpt index cfbab702ad..01fa9f01e6 100644 --- a/ext/phar/tests/phar_oo_011.phpt +++ b/ext/phar/tests/phar_oo_011.phpt @@ -26,7 +26,7 @@ echo "\n"; ===DONE=== --CLEAN-- <?php -unlink(dirname(__FILE__) . '/files/phar_oo_test.phar.php'); +unlink(dirname(__FILE__) . '/files/phar_oo_011.phar.php'); __halt_compiler(); ?> --EXPECT-- diff --git a/ext/phar/tests/phar_oo_011b.phpt b/ext/phar/tests/phar_oo_011b.phpt index 36d9963a22..34cae0e760 100644 --- a/ext/phar/tests/phar_oo_011b.phpt +++ b/ext/phar/tests/phar_oo_011b.phpt @@ -31,7 +31,7 @@ catch (BadMethodCallException $e) ===DONE=== --CLEAN-- <?php -unlink(dirname(__FILE__) . '/files/phar_oo_test.phar.php'); +unlink(dirname(__FILE__) . '/files/phar_oo_011b.phar.php'); __halt_compiler(); ?> --EXPECTF-- diff --git a/ext/phar/tests/phar_oo_012.phpt b/ext/phar/tests/phar_oo_012.phpt index e79ac0960e..b6f9f44b1e 100644 --- a/ext/phar/tests/phar_oo_012.phpt +++ b/ext/phar/tests/phar_oo_012.phpt @@ -27,7 +27,7 @@ var_dump(isset($phar['f.php'])); ===DONE=== --CLEAN-- <?php -unlink(dirname(__FILE__) . '/files/phar_oo_test.phar.php'); +unlink(dirname(__FILE__) . '/files/phar_oo_012.phar.php'); __halt_compiler(); ?> --EXPECT-- diff --git a/ext/phar/tests/phar_oo_012_confirm.phpt b/ext/phar/tests/phar_oo_012_confirm.phpt index 58a3be87b3..ce5a58f212 100644 --- a/ext/phar/tests/phar_oo_012_confirm.phpt +++ b/ext/phar/tests/phar_oo_012_confirm.phpt @@ -30,7 +30,7 @@ var_dump(isset($phar['f.php'])); ===DONE=== --CLEAN-- <?php -unlink(dirname(__FILE__) . '/files/phar_oo_test.phar.php'); +unlink(dirname(__FILE__) . '/files/phar_oo_012_confirm.phar.php'); __halt_compiler(); ?> --EXPECT-- diff --git a/ext/phar/tests/phar_oo_012b.phpt b/ext/phar/tests/phar_oo_012b.phpt index 80d8ed8dc4..066d3bc068 100644 --- a/ext/phar/tests/phar_oo_012b.phpt +++ b/ext/phar/tests/phar_oo_012b.phpt @@ -34,7 +34,7 @@ catch (BadMethodCallException $e) ===DONE=== --CLEAN-- <?php -unlink(dirname(__FILE__) . '/files/phar_oo_test.phar.php'); +unlink(dirname(__FILE__) . '/files/phar_oo_012b.phar.php'); __halt_compiler(); ?> --EXPECTF-- diff --git a/ext/phar/tests/phpinfo_004.phpt b/ext/phar/tests/phpinfo_004.phpt index 24263f07be..c57e850d82 100644 --- a/ext/phar/tests/phpinfo_004.phpt +++ b/ext/phar/tests/phpinfo_004.phpt @@ -23,9 +23,9 @@ phpinfo(INFO_MODULES); ?> ===DONE=== --EXPECTF-- -%a<br /> +%a <h2><a name="module_Phar">Phar</a></h2> -<table border="0" cellpadding="3" width="600"> +<table> <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> @@ -36,20 +36,20 @@ phpinfo(INFO_MODULES); <tr><td class="e">gzip compression </td><td class="v">enabled </td></tr> <tr><td class="e">bzip2 compression </td><td class="v">enabled </td></tr> <tr><td class="e">OpenSSL support </td><td class="v">disabled (install ext/openssl) </td></tr> -</table><br /> -<table border="0" cellpadding="3" width="600"> +</table> +<table> <tr class="v"><td> Phar based on pear/PHP_Archive, original concept by Davey Shafik.<br />Phar fully realized by Gregory Beaver and Marcus Boerger.<br />Portions of tar implementation Copyright (c) %d-%d Tim Kientzle.</td></tr> -</table><br /> -<table border="0" cellpadding="3" width="600"> +</table> +<table> <tr class="h"><th>Directive</th><th>Local Value</th><th>Master Value</th></tr> <tr><td class="e">phar.cache_list</td><td class="v"><i>no value</i></td><td class="v"><i>no value</i></td></tr> <tr><td class="e">phar.readonly</td><td class="v">Off</td><td class="v">Off</td></tr> <tr><td class="e">phar.require_hash</td><td class="v">Off</td><td class="v">Off</td></tr> -</table><br /> -%a<br /> +</table> +%a <h2><a name="module_Phar">Phar</a></h2> -<table border="0" cellpadding="3" width="600"> +<table> <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> @@ -60,16 +60,16 @@ Phar based on pear/PHP_Archive, original concept by Davey Shafik.<br />Phar full <tr><td class="e">gzip compression </td><td class="v">enabled </td></tr> <tr><td class="e">bzip2 compression </td><td class="v">enabled </td></tr> <tr><td class="e">OpenSSL support </td><td class="v">disabled (install ext/openssl) </td></tr> -</table><br /> -<table border="0" cellpadding="3" width="600"> +</table> +<table> <tr class="v"><td> Phar based on pear/PHP_Archive, original concept by Davey Shafik.<br />Phar fully realized by Gregory Beaver and Marcus Boerger.<br />Portions of tar implementation Copyright (c) %d-%d Tim Kientzle.</td></tr> -</table><br /> -<table border="0" cellpadding="3" width="600"> +</table> +<table> <tr class="h"><th>Directive</th><th>Local Value</th><th>Master Value</th></tr> <tr><td class="e">phar.cache_list</td><td class="v"><i>no value</i></td><td class="v"><i>no value</i></td></tr> <tr><td class="e">phar.readonly</td><td class="v">On</td><td class="v">Off</td></tr> <tr><td class="e">phar.require_hash</td><td class="v">On</td><td class="v">Off</td></tr> -</table><br /> -%a<br /> +</table> +%a </div></body></html>===DONE=== diff --git a/ext/phar/util.c b/ext/phar/util.c index 31d12e3da7..a887daecdc 100644 --- a/ext/phar/util.c +++ b/ext/phar/util.c @@ -350,7 +350,7 @@ splitted: * appended, truncated, or read. For read, if the entry is marked unmodified, it is * assumed that the file pointer, if present, is opened for reading */ -int phar_get_entry_data(phar_entry_data **ret, char *fname, int fname_len, char *path, int path_len, char *mode, char allow_dir, char **error, int security TSRMLS_DC) /* {{{ */ +int phar_get_entry_data(phar_entry_data **ret, char *fname, int fname_len, char *path, int path_len, const char *mode, char allow_dir, char **error, int security TSRMLS_DC) /* {{{ */ { phar_archive_data *phar; phar_entry_info *entry; @@ -511,7 +511,7 @@ really_get_entry: /** * Create a new dummy file slot within a writeable phar for a newly created file */ -phar_entry_data *phar_get_or_create_entry_data(char *fname, int fname_len, char *path, int path_len, char *mode, char allow_dir, char **error, int security TSRMLS_DC) /* {{{ */ +phar_entry_data *phar_get_or_create_entry_data(char *fname, int fname_len, char *path, int path_len, const char *mode, char allow_dir, char **error, int security TSRMLS_DC) /* {{{ */ { phar_archive_data *phar; phar_entry_info *entry, etemp; @@ -673,7 +673,7 @@ int phar_copy_entry_fp(phar_entry_info *source, phar_entry_info *dest, char **er link = source; } - if (SUCCESS != phar_stream_copy_to_stream(phar_get_efp(link, 0 TSRMLS_CC), dest->fp, link->uncompressed_filesize, NULL)) { + if (SUCCESS != php_stream_copy_to_stream_ex(phar_get_efp(link, 0 TSRMLS_CC), dest->fp, link->uncompressed_filesize, NULL)) { php_stream_close(dest->fp); dest->fp_type = PHAR_FP; if (error) { @@ -775,7 +775,7 @@ int phar_open_entry_fp(phar_entry_info *entry, char **error, int follow_links TS php_stream_seek(phar_get_entrypfp(entry TSRMLS_CC), phar_get_fp_offset(entry TSRMLS_CC), SEEK_SET); if (entry->uncompressed_filesize) { - if (SUCCESS != phar_stream_copy_to_stream(phar_get_entrypfp(entry TSRMLS_CC), ufp, entry->compressed_filesize, NULL)) { + if (SUCCESS != php_stream_copy_to_stream_ex(phar_get_entrypfp(entry TSRMLS_CC), ufp, entry->compressed_filesize, NULL)) { spprintf(error, 4096, "phar error: internal corruption of phar \"%s\" (actual filesize mismatch on file \"%s\")", phar->fname, entry->filename); php_stream_filter_remove(filter, 1 TSRMLS_CC); return FAILURE; @@ -882,7 +882,7 @@ int phar_separate_entry_fp(phar_entry_info *entry, char **error TSRMLS_DC) /* {{ link = entry; } - if (SUCCESS != phar_stream_copy_to_stream(phar_get_efp(link, 0 TSRMLS_CC), fp, link->uncompressed_filesize, NULL)) { + if (SUCCESS != php_stream_copy_to_stream_ex(phar_get_efp(link, 0 TSRMLS_CC), fp, link->uncompressed_filesize, NULL)) { if (error) { spprintf(error, 4096, "phar error: cannot separate entry file \"%s\" contents in phar archive \"%s\" for write access", entry->filename, entry->phar->fname); } @@ -1299,21 +1299,17 @@ phar_entry_info *phar_get_entry_info_dir(phar_archive_data *phar, char *path, in } if (phar->mounted_dirs.arBuckets && zend_hash_num_elements(&phar->mounted_dirs)) { - phar_zstr key; char *str_key; ulong unused; uint keylen; zend_hash_internal_pointer_reset(&phar->mounted_dirs); while (FAILURE != zend_hash_has_more_elements(&phar->mounted_dirs)) { - if (HASH_KEY_NON_EXISTENT == zend_hash_get_current_key_ex(&phar->mounted_dirs, &key, &keylen, &unused, 0, NULL)) { + if (HASH_KEY_NON_EXISTENT == zend_hash_get_current_key_ex(&phar->mounted_dirs, &str_key, &keylen, &unused, 0, NULL)) { break; } - PHAR_STR(key, str_key); - if ((int)keylen >= path_len || strncmp(str_key, path, keylen)) { - PHAR_STR_FREE(str_key); continue; } else { char *test; @@ -1324,7 +1320,6 @@ phar_entry_info *phar_get_entry_info_dir(phar_archive_data *phar, char *path, in if (error) { spprintf(error, 4096, "phar internal error: mounted path \"%s\" could not be retrieved from manifest", str_key); } - PHAR_STR_FREE(str_key); return NULL; } @@ -1332,10 +1327,8 @@ phar_entry_info *phar_get_entry_info_dir(phar_archive_data *phar, char *path, in if (error) { spprintf(error, 4096, "phar internal error: mounted path \"%s\" is not properly initialized as a mounted path", str_key); } - PHAR_STR_FREE(str_key); return NULL; } - PHAR_STR_FREE(str_key); test_len = spprintf(&test, MAXPATHLEN, "%s%s", entry->tmp, path + keylen); diff --git a/ext/phar/zip.c b/ext/phar/zip.c index e3b64859b8..2e977b8840 100644 --- a/ext/phar/zip.c +++ b/ext/phar/zip.c @@ -417,11 +417,11 @@ foundit: php_stream_seek(fp, 0, SEEK_SET); /* copy file contents + local headers and zip comment, if any, to be hashed for signature */ - phar_stream_copy_to_stream(fp, sigfile, entry.header_offset, NULL); + php_stream_copy_to_stream_ex(fp, sigfile, entry.header_offset, NULL); /* seek to central directory */ php_stream_seek(fp, PHAR_GET_32(locator.cdir_offset), SEEK_SET); /* copy central directory header */ - phar_stream_copy_to_stream(fp, sigfile, beforeus - PHAR_GET_32(locator.cdir_offset), NULL); + php_stream_copy_to_stream_ex(fp, sigfile, beforeus - PHAR_GET_32(locator.cdir_offset), NULL); if (metadata) { php_stream_write(sigfile, metadata, PHAR_GET_16(locator.comment_len)); } @@ -905,7 +905,7 @@ static int phar_zip_changed_apply(void *data, void *arg TSRMLS_DC) /* {{{ */ php_stream_filter_append((&entry->cfp->writefilters), filter); - if (SUCCESS != phar_stream_copy_to_stream(efp, entry->cfp, entry->uncompressed_filesize, NULL)) { + if (SUCCESS != php_stream_copy_to_stream_ex(efp, entry->cfp, entry->uncompressed_filesize, NULL)) { spprintf(p->error, 0, "unable to copy compressed file contents of file \"%s\" while creating new phar \"%s\"", entry->filename, entry->phar->fname); return ZEND_HASH_APPLY_STOP; } @@ -1010,7 +1010,7 @@ continue_dir: if (!not_really_modified && entry->is_modified) { if (entry->cfp) { - if (SUCCESS != phar_stream_copy_to_stream(entry->cfp, p->filefp, entry->compressed_filesize, NULL)) { + if (SUCCESS != php_stream_copy_to_stream_ex(entry->cfp, p->filefp, entry->compressed_filesize, NULL)) { spprintf(p->error, 0, "unable to write compressed contents of file \"%s\" in zip-based phar \"%s\"", entry->filename, entry->phar->fname); return ZEND_HASH_APPLY_STOP; } @@ -1024,7 +1024,7 @@ continue_dir: phar_seek_efp(entry, 0, SEEK_SET, 0, 0 TSRMLS_CC); - if (SUCCESS != phar_stream_copy_to_stream(phar_get_efp(entry, 0 TSRMLS_CC), p->filefp, entry->uncompressed_filesize, NULL)) { + if (SUCCESS != php_stream_copy_to_stream_ex(phar_get_efp(entry, 0 TSRMLS_CC), p->filefp, entry->uncompressed_filesize, NULL)) { spprintf(p->error, 0, "unable to write contents of file \"%s\" in zip-based phar \"%s\"", entry->filename, entry->phar->fname); return ZEND_HASH_APPLY_STOP; } @@ -1050,7 +1050,7 @@ continue_dir: } } - if (!entry->is_dir && entry->compressed_filesize && SUCCESS != phar_stream_copy_to_stream(p->old, p->filefp, entry->compressed_filesize, NULL)) { + if (!entry->is_dir && entry->compressed_filesize && SUCCESS != php_stream_copy_to_stream_ex(p->old, p->filefp, entry->compressed_filesize, NULL)) { spprintf(p->error, 0, "unable to copy contents of file \"%s\" while creating zip-based phar \"%s\"", entry->filename, entry->phar->fname); return ZEND_HASH_APPLY_STOP; } @@ -1093,10 +1093,10 @@ static int phar_zip_applysignature(phar_archive_data *phar, struct _phar_zip_pas st = tell = php_stream_tell(pass->filefp); /* copy the local files, central directory, and the zip comment to generate the hash */ php_stream_seek(pass->filefp, 0, SEEK_SET); - phar_stream_copy_to_stream(pass->filefp, newfile, tell, NULL); + php_stream_copy_to_stream_ex(pass->filefp, newfile, tell, NULL); tell = php_stream_tell(pass->centralfp); php_stream_seek(pass->centralfp, 0, SEEK_SET); - phar_stream_copy_to_stream(pass->centralfp, newfile, tell, NULL); + php_stream_copy_to_stream_ex(pass->centralfp, newfile, tell, NULL); if (metadata->c) { php_stream_write(newfile, metadata->c, metadata->len); } @@ -1431,7 +1431,7 @@ nocentralerror: { size_t clen; - int ret = phar_stream_copy_to_stream(pass.centralfp, pass.filefp, PHP_STREAM_COPY_ALL, &clen); + int ret = php_stream_copy_to_stream_ex(pass.centralfp, pass.filefp, PHP_STREAM_COPY_ALL, &clen); if (SUCCESS != ret || clen != cdir_size) { if (error) { spprintf(error, 4096, "phar zip flush of \"%s\" failed: unable to write central-directory", phar->fname); @@ -1501,7 +1501,7 @@ nocentralerror: return EOF; } php_stream_rewind(pass.filefp); - phar_stream_copy_to_stream(pass.filefp, phar->fp, PHP_STREAM_COPY_ALL, NULL); + php_stream_copy_to_stream_ex(pass.filefp, phar->fp, PHP_STREAM_COPY_ALL, NULL); /* we could also reopen the file in "rb" mode but there is no need for that */ php_stream_close(pass.filefp); } diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c index e6cef1dfed..15cfec98c0 100644 --- a/ext/reflection/php_reflection.c +++ b/ext/reflection/php_reflection.c @@ -681,8 +681,8 @@ static zend_op* _get_recv_op(zend_op_array *op_array, zend_uint offset) ++offset; while (op < end) { - if ((op->opcode == ZEND_RECV || op->opcode == ZEND_RECV_INIT) - && op->op1.num == (long)offset) + if ((op->opcode == ZEND_RECV || op->opcode == ZEND_RECV_INIT + || op->opcode == ZEND_RECV_VARIADIC) && op->op1.num == (long)offset) { return op; } @@ -715,6 +715,9 @@ static void _parameter_string(string *str, zend_function *fptr, struct _zend_arg if (arg_info->pass_by_reference) { string_write(str, "&", sizeof("&")-1); } + if (arg_info->is_variadic) { + string_write(str, "...", sizeof("...")-1); + } if (arg_info->name) { string_printf(str, "$%s", arg_info->name); } else { @@ -2593,8 +2596,7 @@ ZEND_METHOD(reflection_parameter, getDefaultValue) *return_value = *precv->op2.zv; INIT_PZVAL(return_value); - if ((Z_TYPE_P(return_value) & IS_CONSTANT_TYPE_MASK) != IS_CONSTANT - && (Z_TYPE_P(return_value) & IS_CONSTANT_TYPE_MASK) != IS_CONSTANT_ARRAY) { + if (!IS_CONSTANT_TYPE(Z_TYPE_P(return_value))) { zval_copy_ctor(return_value); } zval_update_constant_ex(&return_value, (void*)0, param->fptr->common.scope TSRMLS_CC); @@ -2649,6 +2651,22 @@ ZEND_METHOD(reflection_parameter, getDefaultValueConstantName) } /* }}} */ +/* {{{ proto public bool ReflectionParameter::isVariadic() + Returns whether this parameter is a variadic parameter */ +ZEND_METHOD(reflection_parameter, isVariadic) +{ + reflection_object *intern; + parameter_reference *param; + + if (zend_parse_parameters_none() == FAILURE) { + return; + } + GET_REFLECTION_OBJECT_PTR(param); + + RETVAL_BOOL(param->arg_info->is_variadic); +} +/* }}} */ + /* {{{ proto public static mixed ReflectionMethod::export(mixed class, string name [, bool return]) throws ReflectionException Exports a reflection object. Returns the output if TRUE is specified for return, printing it otherwise. */ ZEND_METHOD(reflection_method, export) @@ -3092,6 +3110,14 @@ ZEND_METHOD(reflection_function, isGenerator) } /* }}} */ +/* {{{ proto public bool ReflectionFunction::isVariadic() + Returns whether this function is variadic */ +ZEND_METHOD(reflection_function, isVariadic) +{ + _function_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_VARIADIC); +} +/* }}} */ + /* {{{ proto public bool ReflectionFunction::inNamespace() Returns whether this function is defined in namespace */ ZEND_METHOD(reflection_function, inNamespace) @@ -3384,7 +3410,7 @@ static void add_class_vars(zend_class_entry *ce, int statics, zval *return_value /* this is necessary to make it able to work with default array * properties, returned to user */ - if (Z_TYPE_P(prop_copy) == IS_CONSTANT_ARRAY || (Z_TYPE_P(prop_copy) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT) { + if (IS_CONSTANT_TYPE(Z_TYPE_P(prop_copy))) { zval_update_constant(&prop_copy, (void *) 1 TSRMLS_CC); } @@ -5706,6 +5732,7 @@ static const zend_function_entry reflection_function_abstract_functions[] = { ZEND_ME(reflection_function, isInternal, arginfo_reflection__void, 0) ZEND_ME(reflection_function, isUserDefined, arginfo_reflection__void, 0) ZEND_ME(reflection_function, isGenerator, arginfo_reflection__void, 0) + ZEND_ME(reflection_function, isVariadic, arginfo_reflection__void, 0) ZEND_ME(reflection_function, getClosureThis, arginfo_reflection__void, 0) ZEND_ME(reflection_function, getClosureScopeClass, arginfo_reflection__void, 0) ZEND_ME(reflection_function, getDocComment, arginfo_reflection__void, 0) @@ -6008,6 +6035,7 @@ static const zend_function_entry reflection_parameter_functions[] = { ZEND_ME(reflection_parameter, getDefaultValue, arginfo_reflection__void, 0) ZEND_ME(reflection_parameter, isDefaultValueConstant, arginfo_reflection__void, 0) ZEND_ME(reflection_parameter, getDefaultValueConstantName, arginfo_reflection__void, 0) + ZEND_ME(reflection_parameter, isVariadic, arginfo_reflection__void, 0) PHP_FE_END }; diff --git a/ext/reflection/tests/ReflectionFunction_isVariadic_basic.phpt b/ext/reflection/tests/ReflectionFunction_isVariadic_basic.phpt new file mode 100644 index 0000000000..50b6bb495e --- /dev/null +++ b/ext/reflection/tests/ReflectionFunction_isVariadic_basic.phpt @@ -0,0 +1,18 @@ +--TEST-- +ReflectionFunction::isVariadic() +--FILE-- +<?php + +function test1($args) {} +function test2(...$args) {} +function test3($arg, ...$args) {} + +var_dump((new ReflectionFunction('test1'))->isVariadic()); +var_dump((new ReflectionFunction('test2'))->isVariadic()); +var_dump((new ReflectionFunction('test3'))->isVariadic()); + +?> +--EXPECT-- +bool(false) +bool(true) +bool(true) diff --git a/ext/reflection/tests/ReflectionParameter_canBePassedByValue.phpt b/ext/reflection/tests/ReflectionParameter_canBePassedByValue.phpt index 82c6200122..4772f6548d 100644 --- a/ext/reflection/tests/ReflectionParameter_canBePassedByValue.phpt +++ b/ext/reflection/tests/ReflectionParameter_canBePassedByValue.phpt @@ -61,6 +61,10 @@ Name: SORT_REGULAR_or_SORT_NUMERIC_or_SORT_STRING Is passed by reference: yes
Can be passed by value: yes
+Name: more_array_and_sort_options
+Is passed by reference: yes
+Can be passed by value: yes
+
=> sort:
Name: arg
diff --git a/ext/reflection/tests/ReflectionParameter_isVariadic_basic.phpt b/ext/reflection/tests/ReflectionParameter_isVariadic_basic.phpt new file mode 100644 index 0000000000..370edc388d --- /dev/null +++ b/ext/reflection/tests/ReflectionParameter_isVariadic_basic.phpt @@ -0,0 +1,24 @@ +--TEST-- +ReflectionParameter::isVariadic() +--FILE-- +<?php + +function test1($args) {} +function test2(...$args) {} +function test3($arg, ...$args) {} + +$r1 = new ReflectionFunction('test1'); +$r2 = new ReflectionFunction('test2'); +$r3 = new ReflectionFunction('test3'); + +var_dump($r1->getParameters()[0]->isVariadic()); +var_dump($r2->getParameters()[0]->isVariadic()); +var_dump($r3->getParameters()[0]->isVariadic()); +var_dump($r3->getParameters()[1]->isVariadic()); + +?> +--EXPECT-- +bool(false) +bool(true) +bool(false) +bool(true) diff --git a/ext/reflection/tests/ReflectionParameter_toString_basic.phpt b/ext/reflection/tests/ReflectionParameter_toString_basic.phpt index 268ced15ec..d1a23c758d 100644 --- a/ext/reflection/tests/ReflectionParameter_toString_basic.phpt +++ b/ext/reflection/tests/ReflectionParameter_toString_basic.phpt @@ -4,7 +4,7 @@ ReflectionParameter::__toString() Stefan Koopmanschap <stefan@stefankoopmanschap.nl> --FILE-- <?php -function ReflectionParameterTest($test, $test2 = null) { +function ReflectionParameterTest($test, $test2 = null, ...$test3) { echo $test; } $reflect = new ReflectionFunction('ReflectionParameterTest'); @@ -17,4 +17,5 @@ foreach($params as $key => $value) { --EXPECT-- Parameter #0 [ <required> $test ] Parameter #1 [ <optional> $test2 = NULL ] +Parameter #2 [ <optional> ...$test3 ] ==DONE== diff --git a/ext/session/php_session.h b/ext/session/php_session.h index e8e79f0fa6..4307e6afc5 100644 --- a/ext/session/php_session.h +++ b/ext/session/php_session.h @@ -180,6 +180,7 @@ typedef struct _php_ps_globals { double rfc1867_min_freq; /* session.upload_progress.min_freq */ zend_bool use_strict_mode; /* whether or not PHP accepts unknown session ids */ + unsigned char session_data_hash[16]; /* binary MD5 hash length */ } php_ps_globals; typedef php_ps_globals zend_ps_globals; diff --git a/ext/session/session.c b/ext/session/session.c index 7bb6584621..5b4820a65c 100644 --- a/ext/session/session.c +++ b/ext/session/session.c @@ -505,8 +505,17 @@ static void php_session_initialize(TSRMLS_D) /* {{{ */ */ } if (val) { + PHP_MD5_CTX context; + + /* Store read data's MD5 hash */ + PHP_MD5Init(&context); + PHP_MD5Update(&context, val, vallen); + PHP_MD5Final(PS(session_data_hash), &context); + php_session_decode(val, vallen TSRMLS_CC); efree(val); + } else { + memset(PS(session_data_hash),'\0', 16); } if (!PS(use_cookies) && PS(send_cookie)) { @@ -529,7 +538,19 @@ static void php_session_save_current_state(TSRMLS_D) /* {{{ */ val = php_session_encode(&vallen TSRMLS_CC); if (val) { - ret = PS(mod)->s_write(&PS(mod_data), PS(id), val, vallen TSRMLS_CC); + PHP_MD5_CTX context; + unsigned char digest[16]; + + /* Generate data's MD5 hash */ + PHP_MD5Init(&context); + PHP_MD5Update(&context, val, vallen); + PHP_MD5Final(digest, &context); + /* Write only when save is required */ + if (memcmp(digest, PS(session_data_hash), 16)) { + ret = PS(mod)->s_write(&PS(mod_data), PS(id), val, vallen TSRMLS_CC); + } else { + ret = SUCCESS; + } efree(val); } else { ret = PS(mod)->s_write(&PS(mod_data), PS(id), "", 0 TSRMLS_CC); @@ -727,6 +748,7 @@ static PHP_INI_MH(OnUpdateHashFunc) /* {{{ */ } #endif /* HAVE_HASH_EXT }}} */ + php_error_docref(NULL TSRMLS_CC, E_WARNING, "session.configuration 'session.hash_function' must be existing hash function. %s does not exist.", new_value); return FAILURE; } /* }}} */ @@ -1567,6 +1589,26 @@ static void php_session_flush(TSRMLS_D) /* {{{ */ } /* }}} */ +static void php_session_abort(TSRMLS_D) /* {{{ */ +{ + if (PS(session_status) == php_session_active) { + PS(session_status) = php_session_none; + if (PS(mod_data) || PS(mod_user_implemented)) { + PS(mod)->s_close(&PS(mod_data) TSRMLS_CC); + } + } +} +/* }}} */ + +static void php_session_reset(TSRMLS_D) /* {{{ */ +{ + if (PS(session_status) == php_session_active) { + php_session_initialize(TSRMLS_C); + } +} +/* }}} */ + + PHPAPI void session_adapt_url(const char *url, size_t urllen, char **new, size_t *newlen TSRMLS_DC) /* {{{ */ { if (PS(apply_trans_sid) && (PS(session_status) == php_session_active)) { @@ -1685,6 +1727,31 @@ static PHP_FUNCTION(session_module_name) } /* }}} */ +/* {{{ proto mixed session_serializer_name([string newname]) + Return the current serializer name used for encode/decode session data. If newname is given, the serialzer name is replaced with newname and return bool */ +static PHP_FUNCTION(session_serializer_name) +{ + char *name = NULL; + int name_len; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &name, &name_len) == FAILURE) { + return; + } + + /* Return serializer name */ + if (!name) { + RETURN_STRING(zend_ini_string("session.serialize_handler", sizeof("session.serialize_handler"), 0), 1); + } + + /* Set serializer name */ + if (zend_alter_ini_entry("session.serialize_handler", sizeof("session.serialize_handler"), name, name_len, PHP_INI_USER, PHP_INI_STAGE_RUNTIME) == SUCCESS) { + RETURN_TRUE; + } else { + RETURN_FALSE; + } +} +/* }}} */ + /* {{{ proto void session_set_save_handler(string open, string close, string read, string write, string destroy, string gc, string create_sid) Sets user-level functions */ static PHP_FUNCTION(session_set_save_handler) @@ -2048,6 +2115,22 @@ static PHP_FUNCTION(session_write_close) } /* }}} */ +/* {{{ proto void session_abort(void) + Abort session and end session. Session data will not be written */ +static PHP_FUNCTION(session_abort) +{ + php_session_abort(TSRMLS_C); +} +/* }}} */ + +/* {{{ proto void session_reset(void) + Reset session data from saved session data */ +static PHP_FUNCTION(session_reset) +{ + php_session_reset(TSRMLS_C); +} +/* }}} */ + /* {{{ proto int session_status(void) Returns the current session status */ static PHP_FUNCTION(session_status) @@ -2060,6 +2143,39 @@ static PHP_FUNCTION(session_status) } /* }}} */ +/* {{{ proto int session_gc([int maxlifetime]) + Execute garbage collection returns number of deleted data */ +static PHP_FUNCTION(session_gc) +{ + int nrdels = -1; + long maxlifetime = PS(gc_maxlifetime); + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &maxlifetime) == FAILURE) { + return; + } + + /* Session must be active to have PS(mod) */ + if (PS(session_status) != php_session_active) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Trying to garbage collect without active session"); + RETURN_FALSE; + } + + if (!PS(mod) || !PS(mod)->s_gc) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Session save handler does not have gc()"); + RETURN_FALSE; + } + PS(mod)->s_gc(&PS(mod_data), maxlifetime, &nrdels TSRMLS_CC); + + if (nrdels < 0) { + /* Files save handler return -1 if there is not a permission to remove. + Save handlder should return negative nrdels when something wrong. */ + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Session gc failed. Check permission or session storage"); + RETURN_FALSE; + } + RETURN_LONG((long)nrdels); +} +/* }}} */ + /* {{{ proto void session_register_shutdown(void) Registers session_write_close() as a shutdown function */ static PHP_FUNCTION(session_register_shutdown) @@ -2106,6 +2222,10 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_session_module_name, 0, 0, 0) ZEND_ARG_INFO(0, module) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_INFO_EX(arginfo_session_serializer_name, 0, 0, 0) + ZEND_ARG_INFO(0, module) +ZEND_END_ARG_INFO() + ZEND_BEGIN_ARG_INFO_EX(arginfo_session_save_path, 0, 0, 0) ZEND_ARG_INFO(0, path) ZEND_END_ARG_INFO() @@ -2151,6 +2271,10 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_session_set_cookie_params, 0, 0, 1) ZEND_ARG_INFO(0, httponly) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_INFO(arginfo_session_gc, 0) + ZEND_ARG_INFO(0, maxlifetime) +ZEND_END_ARG_INFO() + ZEND_BEGIN_ARG_INFO(arginfo_session_class_open, 0) ZEND_ARG_INFO(0, save_path) ZEND_ARG_INFO(0, session_name) @@ -2185,6 +2309,7 @@ ZEND_END_ARG_INFO() static const zend_function_entry session_functions[] = { PHP_FE(session_name, arginfo_session_name) PHP_FE(session_module_name, arginfo_session_module_name) + PHP_FE(session_serializer_name, arginfo_session_serializer_name) PHP_FE(session_save_path, arginfo_session_save_path) PHP_FE(session_id, arginfo_session_id) PHP_FE(session_regenerate_id, arginfo_session_regenerate_id) @@ -2199,7 +2324,10 @@ static const zend_function_entry session_functions[] = { PHP_FE(session_set_cookie_params, arginfo_session_set_cookie_params) PHP_FE(session_get_cookie_params, arginfo_session_void) PHP_FE(session_write_close, arginfo_session_void) + PHP_FE(session_abort, arginfo_session_void) + PHP_FE(session_reset, arginfo_session_void) PHP_FE(session_status, arginfo_session_void) + PHP_FE(session_gc, arginfo_session_gc) PHP_FE(session_register_shutdown, arginfo_session_void) PHP_FALIAS(session_commit, session_write_close, arginfo_session_void) PHP_FE_END diff --git a/ext/session/tests/session_abort_basic.phpt b/ext/session/tests/session_abort_basic.phpt new file mode 100644 index 0000000000..4a6702f0dc --- /dev/null +++ b/ext/session/tests/session_abort_basic.phpt @@ -0,0 +1,51 @@ +--TEST-- +Test session_abort() function : basic functionality +--SKIPIF-- +<?php include('skipif.inc'); ?> +--INI-- +session.save_path= +session.name=PHPSESSID +--FILE-- +<?php + +ob_start(); + +/* + * Prototype : void session_abort(void) + * Description : Should abort session. Session data should not be written. + * Source code : ext/session/session.c + */ + +echo "*** Testing session_abort() : basic functionality ***\n"; + +session_start(); +$session_id = session_id(); +$_SESSION['foo'] = 123; +session_commit(); + +session_id($session_id); +session_start(); +$_SESSION['bar'] = 456; +var_dump($_SESSION); +session_abort(); + +session_id($session_id); +session_start(); +var_dump($_SESSION); // Should only have 'foo' + +echo "Done".PHP_EOL; + +?> +--EXPECTF-- +*** Testing session_abort() : basic functionality *** +array(2) { + ["foo"]=> + int(123) + ["bar"]=> + int(456) +} +array(1) { + ["foo"]=> + int(123) +} +Done diff --git a/ext/session/tests/session_gc_basic.phpt b/ext/session/tests/session_gc_basic.phpt new file mode 100644 index 0000000000..f0726ce93b --- /dev/null +++ b/ext/session/tests/session_gc_basic.phpt @@ -0,0 +1,56 @@ +--TEST-- +Test session_gc() function : basic functionality +--SKIPIF-- +<?php include('skipif.inc'); ?> +--INI-- +session.serialize_handler=php +session.save_handler=files +session.maxlifetime=782000 +--FILE-- +<?php +error_reporting(E_ALL); + +ob_start(); + +/* + * Prototype : int session_gc([int maxlifetime]) + * Description : Execute gc and return number of deleted data + * Source code : ext/session/session.c + */ + +echo "*** Testing session_gc() : basic functionality ***\n"; + +// Should fail. It requires active session. +var_dump(session_gc()); + +session_start(); +// Should succeed with some number +var_dump(session_gc()); +// Secound time must be int(0) +var_dump(session_gc()); +session_write_close(); + +// Start&stop session to generate +session_start(); +session_write_close(); +session_start(); +session_write_close(); +session_start(); +session_write_close(); + +session_start(); +$ndeleted = session_gc(0); // Delete all +var_dump($ndeleted >= 3); + +echo "Done".PHP_EOL; + +?> +--EXPECTF-- +*** Testing session_gc() : basic functionality *** + +Warning: session_gc(): Trying to garbage collect without active session in %s on line 15 +bool(false) +int(%d) +int(0) +bool(true) +Done diff --git a/ext/session/tests/session_hash_function_basic.phpt b/ext/session/tests/session_hash_function_basic.phpt new file mode 100644 index 0000000000..663852d9d1 --- /dev/null +++ b/ext/session/tests/session_hash_function_basic.phpt @@ -0,0 +1,52 @@ +--TEST-- +Test session.hash_function ini setting : basic functionality +--SKIPIF-- +<?php include('skipif.inc'); ?> +--INI-- +session.hash_bits_per_character=4 +--FILE-- +<?php + +ob_start(); + +echo "*** Testing session.hash_function : basic functionality ***\n"; + +var_dump(ini_set('session.hash_function', 'md5')); +var_dump(session_start()); +var_dump(!empty(session_id()), session_id()); +var_dump(session_destroy()); + +var_dump(ini_set('session.hash_function', 'sha1')); +var_dump(session_start()); +var_dump(!empty(session_id()), session_id()); +var_dump(session_destroy()); + +var_dump(ini_set('session.hash_function', 'none')); // Should fail +var_dump(session_start()); +var_dump(!empty(session_id()), session_id()); +var_dump(session_destroy()); + + +echo "Done"; +ob_end_flush(); +?> +--EXPECTF-- +*** Testing session.hash_function : basic functionality *** +string(1) "0" +bool(true) +bool(true) +string(32) "%s" +bool(true) +string(3) "md5" +bool(true) +bool(true) +string(40) "%s" +bool(true) + +Warning: ini_set(): session.configuration 'session.hash_function' must be existing hash function. none does not exist. in %s/session_hash_function_basic.php on line 17 +bool(false) +bool(true) +bool(true) +string(40) "%s" +bool(true) +Done diff --git a/ext/session/tests/session_reset_basic.phpt b/ext/session/tests/session_reset_basic.phpt new file mode 100644 index 0000000000..75c6a04119 --- /dev/null +++ b/ext/session/tests/session_reset_basic.phpt @@ -0,0 +1,49 @@ +--TEST-- +Test session_reset() function : basic functionality +--SKIPIF-- +<?php include('skipif.inc'); ?> +--INI-- +session.save_path= +session.name=PHPSESSID +--FILE-- +<?php + +ob_start(); + +/* + * Prototype : void session_reset(void) + * Description : Should abort session. Session data should not be written. + * Source code : ext/session/session.c + */ + +echo "*** Testing session_abort() : basic functionality ***\n"; + +session_start(); +$session_id = session_id(); +$_SESSION['foo'] = 123; +session_commit(); + +session_id($session_id); +session_start(); +$_SESSION['bar'] = 456; +var_dump($_SESSION); +session_reset(); + +var_dump($_SESSION); // Should only have 'foo' + +echo "Done".PHP_EOL; + +?> +--EXPECTF-- +*** Testing session_abort() : basic functionality *** +array(2) { + ["foo"]=> + int(123) + ["bar"]=> + int(456) +} +array(1) { + ["foo"]=> + int(123) +} +Done diff --git a/ext/session/tests/session_serializer_name_basic.phpt b/ext/session/tests/session_serializer_name_basic.phpt new file mode 100644 index 0000000000..ca292dd36f --- /dev/null +++ b/ext/session/tests/session_serializer_name_basic.phpt @@ -0,0 +1,37 @@ +--TEST-- +Test session_serializer_name() function : basic functionality +--SKIPIF-- +<?php include('skipif.inc'); ?> +--FILE-- +<?php + +ob_start(); + +/* + * Prototype : mixed session_serializer_name([string name]) + * Description : Change/get serialize handler name + * Source code : ext/session/session.c + */ + +echo "*** Testing session_serializer_name() : basic functionality ***\n"; + +var_dump(session_serializer_name()); +var_dump(session_serializer_name('php')); +var_dump(session_serializer_name('php_binary')); +var_dump(session_serializer_name('none')); +var_dump(session_serializer_name()); + +echo "Done"; +ob_end_flush(); +?> +--EXPECTF-- +*** Testing session_serializer_name() : basic functionality *** +string(3) "php" +bool(true) +bool(true) + +Warning: session_serializer_name(): Cannot find serialization handler 'none' in %s/session_serializer_name_basic.php on line 16 +bool(false) +string(10) "php_binary" +Done + diff --git a/ext/session/tests/session_set_save_handler_basic.phpt b/ext/session/tests/session_set_save_handler_basic.phpt index 3897ba9a92..e8496e8afb 100644 --- a/ext/session/tests/session_set_save_handler_basic.phpt +++ b/ext/session/tests/session_set_save_handler_basic.phpt @@ -43,6 +43,7 @@ session_id($session_id); session_set_save_handler("open", "close", "read", "write", "destroy", "gc"); session_start(); var_dump($_SESSION); +$_SESSION['Bar'] = 'Foo'; session_write_close(); ob_end_flush(); @@ -91,5 +92,5 @@ array(3) { ["Guff"]=> int(1234567890) } -Write [%s,%s,Blah|s:12:"Hello World!";Foo|b:0;Guff|i:1234567890;] +Write [%s,%s,Blah|s:12:"Hello World!";Foo|b:0;Guff|i:1234567890;Bar|s:3:"Foo";] Close [%s,PHPSESSID] diff --git a/ext/session/tests/session_set_save_handler_class_003.phpt b/ext/session/tests/session_set_save_handler_class_003.phpt index e9a3cc2feb..29b3846851 100644 --- a/ext/session/tests/session_set_save_handler_class_003.phpt +++ b/ext/session/tests/session_set_save_handler_class_003.phpt @@ -58,6 +58,7 @@ session_set_save_handler($handler); session_start(); +$_SESSION['bar'] = 'hello'; session_write_close(); session_unset(); @@ -71,8 +72,10 @@ array(1) { } int(4) string(%d) "%s" -array(1) { +array(2) { ["foo"]=> string(5) "hello" + ["bar"]=> + string(5) "hello" } string(3) "hai" diff --git a/ext/session/tests/session_set_save_handler_class_007.phpt b/ext/session/tests/session_set_save_handler_class_007.phpt index 7344ae1ef3..55f722515e 100644 --- a/ext/session/tests/session_set_save_handler_class_007.phpt +++ b/ext/session/tests/session_set_save_handler_class_007.phpt @@ -56,6 +56,7 @@ $handler = new MySession(2); session_set_save_handler($handler); session_start(); +$_SESSION['abc'] = 'xyz'; // implicit close (called by shutdown function) echo "done\n"; ob_end_flush(); @@ -69,6 +70,6 @@ ob_end_flush(); (#2) constructor called (#1) destructor called done -(#2) writing %s = foo|s:3:"bar"; +(#2) writing %s = foo|s:3:"bar";abc|s:3:"xyz"; (#2) closing %s (#2) destructor called diff --git a/ext/session/tests/session_set_save_handler_closures.phpt b/ext/session/tests/session_set_save_handler_closures.phpt index 21b2c68737..1251886b01 100644 --- a/ext/session/tests/session_set_save_handler_closures.phpt +++ b/ext/session/tests/session_set_save_handler_closures.phpt @@ -42,6 +42,7 @@ echo "Starting session again..!\n"; session_id($session_id); session_set_save_handler($open_closure, $close_closure, $read_closure, $write_closure, $destroy_closure, $gc_closure); session_start(); +$_SESSION['Bar'] = 'Foo'; var_dump($_SESSION); session_write_close(); @@ -83,13 +84,15 @@ array(3) { Starting session again..! Open [%s,PHPSESSID] Read [%s,%s] -array(3) { +array(4) { ["Blah"]=> string(12) "Hello World!" ["Foo"]=> bool(false) ["Guff"]=> int(1234567890) + ["Bar"]=> + string(3) "Foo" } -Write [%s,%s,Blah|s:12:"Hello World!";Foo|b:0;Guff|i:1234567890;] +Write [%s,%s,Blah|s:12:"Hello World!";Foo|b:0;Guff|i:1234567890;Bar|s:3:"Foo";] Close [%s,PHPSESSID] diff --git a/ext/session/tests/session_set_save_handler_write_short_circuit.phpt b/ext/session/tests/session_set_save_handler_write_short_circuit.phpt new file mode 100644 index 0000000000..02ca182ec6 --- /dev/null +++ b/ext/session/tests/session_set_save_handler_write_short_circuit.phpt @@ -0,0 +1,104 @@ +--TEST-- +Test session_set_save_handler() function : test write short circuit +--INI-- +session.save_path= +session.name=PHPSESSID +--SKIPIF-- +<?php include('skipif.inc'); ?> +--FILE-- +<?php + +ob_start(); + +/* + * Prototype : bool session_set_save_handler(callback $open, callback $close, callback $read, callback $write, callback $destroy, callback $gc) + * Description : Sets user-level session storage functions + * Source code : ext/session/session.c + */ + +echo "*** Testing session_set_save_handler() : test write short circuit ***\n"; + +require_once "save_handler.inc"; +$path = dirname(__FILE__); +session_save_path($path); +session_set_save_handler("open", "close", "read", "write", "destroy", "gc"); + +session_start(); +$session_id = session_id(); +$_SESSION["Blah"] = "Hello World!"; +$_SESSION["Foo"] = FALSE; +$_SESSION["Guff"] = 1234567890; +var_dump($_SESSION); + +session_write_close(); +session_unset(); +var_dump($_SESSION); + +echo "Starting session again..!\n"; +session_id($session_id); +session_set_save_handler("open", "close", "read", "write", "destroy", "gc"); +session_start(); +var_dump($_SESSION); +$_SESSION['Bar'] = 'Foo'; +session_write_close(); + +echo "Starting session again..!\n"; +session_id($session_id); +session_set_save_handler("open", "close", "read", "write", "destroy", "gc"); +session_start(); +var_dump($_SESSION); +// $_SESSION should be the same and should skip write() +session_write_close(); + +ob_end_flush(); +?> +--EXPECTF-- +*** Testing session_set_save_handler() : test write short circuit *** + +Open [%s,PHPSESSID] +Read [%s,%s] +array(3) { + ["Blah"]=> + string(12) "Hello World!" + ["Foo"]=> + bool(false) + ["Guff"]=> + int(1234567890) +} +Write [%s,%s,Blah|s:12:"Hello World!";Foo|b:0;Guff|i:1234567890;] +Close [%s,PHPSESSID] +array(3) { + ["Blah"]=> + string(12) "Hello World!" + ["Foo"]=> + bool(false) + ["Guff"]=> + int(1234567890) +} +Starting session again..! +Open [%s,PHPSESSID] +Read [%s,%s] +array(3) { + ["Blah"]=> + string(12) "Hello World!" + ["Foo"]=> + bool(false) + ["Guff"]=> + int(1234567890) +} +Write [%s,%s,Blah|s:12:"Hello World!";Foo|b:0;Guff|i:1234567890;Bar|s:3:"Foo";] +Close [%s,PHPSESSID] +Starting session again..! +Open [%s,PHPSESSID] +Read [%s,%s] +array(4) { + ["Blah"]=> + string(12) "Hello World!" + ["Foo"]=> + bool(false) + ["Guff"]=> + int(1234567890) + ["Bar"]=> + string(3) "Foo" +} +Close [%s,PHPSESSID]
\ No newline at end of file diff --git a/ext/simplexml/config.m4 b/ext/simplexml/config.m4 index 387a24ea21..b06f5b00f0 100644 --- a/ext/simplexml/config.m4 +++ b/ext/simplexml/config.m4 @@ -18,6 +18,7 @@ if test "$PHP_SIMPLEXML" != "no"; then PHP_SETUP_LIBXML(SIMPLEXML_SHARED_LIBADD, [ AC_DEFINE(HAVE_SIMPLEXML,1,[ ]) PHP_NEW_EXTENSION(simplexml, simplexml.c sxe.c, $ext_shared) + PHP_INSTALL_HEADERS([ext/simplexml/php_simplexml.h ext/simplexml/php_simplexml_exports.h]) PHP_SUBST(SIMPLEXML_SHARED_LIBADD) ], [ AC_MSG_ERROR([xml2-config not found. Please check your libxml2 installation.]) diff --git a/ext/simplexml/config.w32 b/ext/simplexml/config.w32 index 2d2ed285eb..a02f3dded3 100644 --- a/ext/simplexml/config.w32 +++ b/ext/simplexml/config.w32 @@ -16,6 +16,7 @@ if (PHP_SIMPLEXML == "yes") { MESSAGE("\tSPL support in simplexml disabled"); } ADD_FLAG("CFLAGS_SIMPLEXML", "/D PHP_SIMPLEXML_EXPORTS "); + PHP_INSTALL_HEADERS("ext/simplexml/", "php_simplexml.h php_simplexml_exports.h"); } else { PHP_SIMPLEXML = "no"; WARNING("simplexml not enabled; libraries and headers not found"); diff --git a/ext/skeleton/php_skeleton.h b/ext/skeleton/php_skeleton.h index 0716ae05e6..d0ba6f04ab 100644 --- a/ext/skeleton/php_skeleton.h +++ b/ext/skeleton/php_skeleton.h @@ -20,15 +20,6 @@ extern zend_module_entry extname_module_entry; #include "TSRM.h" #endif -PHP_MINIT_FUNCTION(extname); -PHP_MSHUTDOWN_FUNCTION(extname); -PHP_RINIT_FUNCTION(extname); -PHP_RSHUTDOWN_FUNCTION(extname); -PHP_MINFO_FUNCTION(extname); - -PHP_FUNCTION(confirm_extname_compiled); /* For testing, remove later. */ -/* __function_declarations_here__ */ - /* Declare any global variables you may need between the BEGIN and END macros here: diff --git a/ext/skeleton/skeleton.c b/ext/skeleton/skeleton.c index 2e373442d8..462e48756f 100644 --- a/ext/skeleton/skeleton.c +++ b/ext/skeleton/skeleton.c @@ -16,41 +16,6 @@ ZEND_DECLARE_MODULE_GLOBALS(extname) /* True global resources - no need for thread safety here */ static int le_extname; -/* {{{ extname_functions[] - * - * Every user visible function must have an entry in extname_functions[]. - */ -const zend_function_entry extname_functions[] = { - PHP_FE(confirm_extname_compiled, NULL) /* For testing, remove later. */ - /* __function_entries_here__ */ - PHP_FE_END /* Must be the last line in extname_functions[] */ -}; -/* }}} */ - -/* {{{ extname_module_entry - */ -zend_module_entry extname_module_entry = { -#if ZEND_MODULE_API_NO >= 20010901 - STANDARD_MODULE_HEADER, -#endif - "extname", - extname_functions, - PHP_MINIT(extname), - PHP_MSHUTDOWN(extname), - PHP_RINIT(extname), /* Replace with NULL if there's nothing to do at request start */ - PHP_RSHUTDOWN(extname), /* Replace with NULL if there's nothing to do at request end */ - PHP_MINFO(extname), -#if ZEND_MODULE_API_NO >= 20010901 - PHP_EXTNAME_VERSION, -#endif - STANDARD_MODULE_PROPERTIES -}; -/* }}} */ - -#ifdef COMPILE_DL_EXTNAME -ZEND_GET_MODULE(extname) -#endif - /* {{{ PHP_INI */ /* Remove comments and fill if you need to have entries in php.ini @@ -61,6 +26,35 @@ PHP_INI_END() */ /* }}} */ +/* Remove the following function when you have successfully modified config.m4 + so that your module can be compiled into PHP, it exists only for testing + purposes. */ + +/* Every user-visible function in PHP should document itself in the source */ +/* {{{ proto string confirm_extname_compiled(string arg) + Return a string to confirm that the module is compiled in */ +PHP_FUNCTION(confirm_extname_compiled) +{ + char *arg = NULL; + int arg_len, len; + char *strg; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &arg, &arg_len) == FAILURE) { + return; + } + + len = spprintf(&strg, 0, "Congratulations! You have successfully modified ext/%.78s/config.m4. Module %.78s is now compiled into PHP.", "extname", arg); + RETURN_STRINGL(strg, len, 0); +} +/* }}} */ +/* The previous line is meant for vim and emacs, so it can correctly fold and + unfold functions in source code. See the corresponding marks just before + function definition, where the functions purpose is also documented. Please + follow this convention for the convenience of others editing your code. +*/ + +/* __function_stubs_here__ */ + /* {{{ php_extname_init_globals */ /* Uncomment this function if you have INI entries @@ -126,35 +120,36 @@ PHP_MINFO_FUNCTION(extname) } /* }}} */ +/* {{{ extname_functions[] + * + * Every user visible function must have an entry in extname_functions[]. + */ +const zend_function_entry extname_functions[] = { + PHP_FE(confirm_extname_compiled, NULL) /* For testing, remove later. */ + /* __function_entries_here__ */ + PHP_FE_END /* Must be the last line in extname_functions[] */ +}; +/* }}} */ -/* Remove the following function when you have successfully modified config.m4 - so that your module can be compiled into PHP, it exists only for testing - purposes. */ - -/* Every user-visible function in PHP should document itself in the source */ -/* {{{ proto string confirm_extname_compiled(string arg) - Return a string to confirm that the module is compiled in */ -PHP_FUNCTION(confirm_extname_compiled) -{ - char *arg = NULL; - int arg_len, len; - char *strg; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &arg, &arg_len) == FAILURE) { - return; - } - - len = spprintf(&strg, 0, "Congratulations! You have successfully modified ext/%.78s/config.m4. Module %.78s is now compiled into PHP.", "extname", arg); - RETURN_STRINGL(strg, len, 0); -} +/* {{{ extname_module_entry + */ +zend_module_entry extname_module_entry = { + STANDARD_MODULE_HEADER, + "extname", + extname_functions, + PHP_MINIT(extname), + PHP_MSHUTDOWN(extname), + PHP_RINIT(extname), /* Replace with NULL if there's nothing to do at request start */ + PHP_RSHUTDOWN(extname), /* Replace with NULL if there's nothing to do at request end */ + PHP_MINFO(extname), + PHP_EXTNAME_VERSION, + STANDARD_MODULE_PROPERTIES +}; /* }}} */ -/* The previous line is meant for vim and emacs, so it can correctly fold and - unfold functions in source code. See the corresponding marks just before - function definition, where the functions purpose is also documented. Please - follow this convention for the convenience of others editing your code. -*/ -/* __function_stubs_here__ */ +#ifdef COMPILE_DL_EXTNAME +ZEND_GET_MODULE(extname) +#endif /* * Local variables: diff --git a/ext/soap/php_http.c b/ext/soap/php_http.c index 86ab03d9c8..14366f12cc 100644 --- a/ext/soap/php_http.c +++ b/ext/soap/php_http.c @@ -807,6 +807,7 @@ try_again: if (zend_hash_find(Z_OBJPROP_P(this_ptr), "_cookies", sizeof("_cookies"), (void **)&cookies) == SUCCESS) { zval **data; char *key; + uint key_len; int i, n; has_cookies = 1; @@ -816,7 +817,7 @@ try_again: smart_str_append_const(&soap_headers, "Cookie: "); for (i = 0; i < n; i++) { zend_hash_get_current_data(Z_ARRVAL_PP(cookies), (void **)&data); - zend_hash_get_current_key(Z_ARRVAL_PP(cookies), &key, NULL, FALSE); + zend_hash_get_current_key_ex(Z_ARRVAL_PP(cookies), &key, &key_len, NULL, 0, NULL); if (Z_TYPE_PP(data) == IS_ARRAY) { zval** value; @@ -829,7 +830,7 @@ try_again: (zend_hash_index_find(Z_ARRVAL_PP(data), 2, (void**)&tmp) == FAILURE || in_domain(phpurl->host,Z_STRVAL_PP(tmp))) && (use_ssl || zend_hash_index_find(Z_ARRVAL_PP(data), 3, (void**)&tmp) == FAILURE)) { - smart_str_appendl(&soap_headers, key, strlen(key)); + smart_str_appendl(&soap_headers, key, key_len); smart_str_appendc(&soap_headers, '='); smart_str_appendl(&soap_headers, Z_STRVAL_PP(value), Z_STRLEN_PP(value)); smart_str_appendc(&soap_headers, ';'); diff --git a/ext/soap/php_sdl.c b/ext/soap/php_sdl.c index a7a5071c08..f8c6940c1f 100644 --- a/ext/soap/php_sdl.c +++ b/ext/soap/php_sdl.c @@ -24,7 +24,7 @@ #include "libxml/uri.h" #include "ext/standard/md5.h" -#include "tsrm_virtual_cwd.h" +#include "zend_virtual_cwd.h" #include <sys/types.h> #include <sys/stat.h> diff --git a/ext/soap/soap.c b/ext/soap/soap.c index 3448df4ea7..90cd67fdaf 100644 --- a/ext/soap/soap.c +++ b/ext/soap/soap.c @@ -1560,48 +1560,45 @@ PHP_METHOD(SoapServer, handle) } if (ZEND_NUM_ARGS() == 0) { - if (SG(request_info).raw_post_data) { - char *post_data = SG(request_info).raw_post_data; - int post_data_length = SG(request_info).raw_post_data_length; + if (SG(request_info).request_body && 0 == php_stream_rewind(SG(request_info).request_body)) { zval **server_vars, **encoding; + php_stream_filter *zf = NULL; zend_is_auto_global("_SERVER", sizeof("_SERVER")-1 TSRMLS_CC); if (zend_hash_find(&EG(symbol_table), "_SERVER", sizeof("_SERVER"), (void **) &server_vars) == SUCCESS && Z_TYPE_PP(server_vars) == IS_ARRAY && zend_hash_find(Z_ARRVAL_PP(server_vars), "HTTP_CONTENT_ENCODING", sizeof("HTTP_CONTENT_ENCODING"), (void **) &encoding)==SUCCESS && Z_TYPE_PP(encoding) == IS_STRING) { - zval func; - zval retval; - zval param; - zval *params[1]; - - if ((strcmp(Z_STRVAL_PP(encoding),"gzip") == 0 || - strcmp(Z_STRVAL_PP(encoding),"x-gzip") == 0) && - zend_hash_exists(EG(function_table), "gzinflate", sizeof("gzinflate"))) { - ZVAL_STRING(&func, "gzinflate", 0); - params[0] = ¶m; - ZVAL_STRINGL(params[0], post_data+10, post_data_length-10, 0); - INIT_PZVAL(params[0]); - } else if (strcmp(Z_STRVAL_PP(encoding),"deflate") == 0 && - zend_hash_exists(EG(function_table), "gzuncompress", sizeof("gzuncompress"))) { - ZVAL_STRING(&func, "gzuncompress", 0); - params[0] = ¶m; - ZVAL_STRINGL(params[0], post_data, post_data_length, 0); - INIT_PZVAL(params[0]); + + if (strcmp(Z_STRVAL_PP(encoding),"gzip") == 0 + || strcmp(Z_STRVAL_PP(encoding),"x-gzip") == 0 + || strcmp(Z_STRVAL_PP(encoding),"deflate") == 0 + ) { + zval filter_params; + + INIT_PZVAL(&filter_params); + array_init_size(&filter_params, 1); + add_assoc_long_ex(&filter_params, ZEND_STRS("window"), 0x2f); /* ANY WBITS */ + + zf = php_stream_filter_create("zlib.inflate", &filter_params, 0 TSRMLS_CC); + zval_dtor(&filter_params); + + if (zf) { + php_stream_filter_append(&SG(request_info).request_body->readfilters, zf); + } else { + php_error_docref(NULL TSRMLS_CC, E_WARNING,"Can't uncompress compressed request"); + return; + } } else { php_error_docref(NULL TSRMLS_CC, E_WARNING,"Request is compressed with unknown compression '%s'",Z_STRVAL_PP(encoding)); return; } - if (call_user_function(CG(function_table), (zval**)NULL, &func, &retval, 1, params TSRMLS_CC) == SUCCESS && - Z_TYPE(retval) == IS_STRING) { - doc_request = soap_xmlParseMemory(Z_STRVAL(retval),Z_STRLEN(retval)); - zval_dtor(&retval); - } else { - php_error_docref(NULL TSRMLS_CC, E_WARNING,"Can't uncompress compressed request"); - return; - } - } else { - doc_request = soap_xmlParseMemory(post_data, post_data_length); + } + + doc_request = soap_xmlParseFile("php://input" TSRMLS_CC); + + if (zf) { + php_stream_filter_remove(zf, 1 TSRMLS_CC); } } else { zval_ptr_dtor(&retval); diff --git a/ext/sockets/tests/ipv4loop.phpt b/ext/sockets/tests/ipv4loop.phpt index 9fdcc17dad..920b27b66e 100644 --- a/ext/sockets/tests/ipv4loop.phpt +++ b/ext/sockets/tests/ipv4loop.phpt @@ -13,8 +13,15 @@ IPv4 Loopback test if (!$server) { die('Unable to create AF_INET socket [server]'); } - if (!socket_bind($server, '127.0.0.1', 31337)) { - die('Unable to bind to 127.0.0.1:31337'); + $bound = false; + for($port = 31337; $port < 31357; ++$port) { + if (socket_bind($server, '127.0.0.1', $port)) { + $bound = true; + break; + } + } + if (!$bound) { + die("Unable to bind to 127.0.0.1"); } if (!socket_listen($server, 2)) { die('Unable to listen on socket'); @@ -25,7 +32,7 @@ IPv4 Loopback test if (!$client) { die('Unable to create AF_INET socket [client]'); } - if (!socket_connect($client, '127.0.0.1', 31337)) { + if (!socket_connect($client, '127.0.0.1', $port)) { die('Unable to connect to server socket'); } diff --git a/ext/sockets/tests/ipv6loop.phpt b/ext/sockets/tests/ipv6loop.phpt index 6967605ffa..4720cb49e4 100644 --- a/ext/sockets/tests/ipv6loop.phpt +++ b/ext/sockets/tests/ipv6loop.phpt @@ -14,8 +14,15 @@ IPv6 Loopback test if (!$server) { die('Unable to create AF_INET6 socket [server]'); } - if (!socket_bind($server, '::1', 31337)) { - die('Unable to bind to [::1]:31337'); + $bound = false; + for($port = 31337; $port < 31357; ++$port) { + if (socket_bind($server, '::1', $port)) { + $bound = true; + break; + } + } + if (!$bound) { + die("Unable to bind to [::1]:$port"); } if (!socket_listen($server, 2)) { die('Unable to listen on socket'); @@ -26,7 +33,7 @@ IPv6 Loopback test if (!$client) { die('Unable to create AF_INET6 socket [client]'); } - if (!socket_connect($client, '::1', 31337)) { + if (!socket_connect($client, '::1', $port)) { die('Unable to connect to server socket'); } diff --git a/ext/sockets/tests/socket_getpeername_ipv4loop.phpt b/ext/sockets/tests/socket_getpeername_ipv4loop.phpt index aa59abb8da..b948e0e7f4 100644 --- a/ext/sockets/tests/socket_getpeername_ipv4loop.phpt +++ b/ext/sockets/tests/socket_getpeername_ipv4loop.phpt @@ -14,17 +14,23 @@ ext/sockets - socket_getpeername_ipv4loop - basic test /* Bind and connect sockets to localhost */ $localhost = '127.0.0.1'; - /* Hold the port associated to address */ - $port = 31337; - /* Setup socket server */ $server = socket_create(AF_INET, SOCK_STREAM, getprotobyname('tcp')); if (!$server) { die('Unable to create AF_INET socket [server]'); } - - if (!socket_bind($server, $localhost, $port)) { - die('Unable to bind to '.$localhost.':'.$port); + + $minport = 31337; + $maxport = 31356; + $bound = false; + for($port = $minport; $port <= $maxport; ++$port) { + if (socket_bind($server, $localhost, $port)) { + $bound = true; + break; + } + } + if (!$bound) { + die('Unable to bind to '.$localhost); } if (!socket_listen($server, 2)) { die('Unable to listen on socket'); @@ -45,10 +51,10 @@ ext/sockets - socket_getpeername_ipv4loop - basic test die('Unable to accept connection'); } - if (!socket_getpeername($client, $address, $port)) { + if (!socket_getpeername($client, $address, $peerport)) { die('Unable to retrieve peer name'); } - var_dump($address, $port); + var_dump($address, $port === $peerport); socket_close($client); socket_close($socket); @@ -56,4 +62,4 @@ ext/sockets - socket_getpeername_ipv4loop - basic test ?> --EXPECT-- string(9) "127.0.0.1" -int(31337) +bool(true) diff --git a/ext/sockets/tests/socket_getpeername_ipv6loop.phpt b/ext/sockets/tests/socket_getpeername_ipv6loop.phpt index e865f3e064..5d03e32ce0 100644 --- a/ext/sockets/tests/socket_getpeername_ipv6loop.phpt +++ b/ext/sockets/tests/socket_getpeername_ipv6loop.phpt @@ -15,17 +15,23 @@ require 'ipv6_skipif.inc'; /* Bind and connect sockets to localhost */ $localhost = '::1'; - /* Hold the port associated to address */ - $port = 31337; - /* Setup socket server */ $server = socket_create(AF_INET6, SOCK_STREAM, getprotobyname('tcp')); if (!$server) { die('Unable to create AF_INET6 socket [server]'); } - - if (!socket_bind($server, $localhost, $port)) { - die('Unable to bind to '.$localhost.':'.$port); + + $minport = 31337; + $maxport = 31356; + $bound = false; + for($port = $minport; $port <= $maxport; ++$port) { + if (socket_bind($server, $localhost, $port)) { + $bound = true; + break; + } + } + if (!$bound) { + die('Unable to bind to '.$localhost); } if (!socket_listen($server, 2)) { die('Unable to listen on socket'); @@ -46,10 +52,10 @@ require 'ipv6_skipif.inc'; die('Unable to accept connection'); } - if (!socket_getpeername($client, $address, $port)) { + if (!socket_getpeername($client, $address, $peerport)) { die('Unable to retrieve peer name'); } - var_dump($address, $port); + var_dump($address, $port === $peerport); socket_close($client); socket_close($socket); @@ -57,4 +63,4 @@ require 'ipv6_skipif.inc'; ?> --EXPECT-- string(3) "::1" -int(31337) +bool(true) diff --git a/ext/spl/php_spl.h b/ext/spl/php_spl.h index 4794f12443..28aa19def3 100644 --- a/ext/spl/php_spl.h +++ b/ext/spl/php_spl.h @@ -20,11 +20,6 @@ #define PHP_SPL_H #include "php.h" -#if defined(PHP_WIN32) -# include "win32/php_stdint.h" -#elif defined(HAVE_STDINT_H) -# include <stdint.h> -#endif #include <stdarg.h> #if 0 diff --git a/ext/spl/spl_directory.c b/ext/spl/spl_directory.c index 3dc7b7925c..f73e8ee9f0 100644 --- a/ext/spl/spl_directory.c +++ b/ext/spl/spl_directory.c @@ -2938,8 +2938,9 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_file_object_fgetss, 0, 0, 0) ZEND_ARG_INFO(0, allowable_tags) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_INFO_EX(arginfo_file_object_fscanf, 1, 0, 1) +ZEND_BEGIN_ARG_INFO_EX(arginfo_file_object_fscanf, 0, 0, 1) ZEND_ARG_INFO(0, format) + ZEND_ARG_VARIADIC_INFO(1, vars) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_file_object_fwrite, 0, 0, 1) diff --git a/ext/spl/spl_dllist.c b/ext/spl/spl_dllist.c index 273bc7506a..d5a9f83ae1 100644 --- a/ext/spl/spl_dllist.c +++ b/ext/spl/spl_dllist.c @@ -603,7 +603,7 @@ SPL_METHOD(SplDoublyLinkedList, pop) zval *value; spl_dllist_object *intern; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) { + if (zend_parse_parameters_none() == FAILURE) { return; } @@ -626,7 +626,7 @@ SPL_METHOD(SplDoublyLinkedList, shift) zval *value; spl_dllist_object *intern; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) { + if (zend_parse_parameters_none() == FAILURE) { return; } @@ -649,7 +649,7 @@ SPL_METHOD(SplDoublyLinkedList, top) zval *value; spl_dllist_object *intern; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) { + if (zend_parse_parameters_none() == FAILURE) { return; } @@ -672,7 +672,7 @@ SPL_METHOD(SplDoublyLinkedList, bottom) zval *value; spl_dllist_object *intern; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) { + if (zend_parse_parameters_none() == FAILURE) { return; } @@ -695,7 +695,7 @@ SPL_METHOD(SplDoublyLinkedList, count) long count; spl_dllist_object *intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) { + if (zend_parse_parameters_none() == FAILURE) { return; } @@ -710,7 +710,7 @@ SPL_METHOD(SplDoublyLinkedList, isEmpty) { long count; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) { + if (zend_parse_parameters_none() == FAILURE) { return; } @@ -750,7 +750,7 @@ SPL_METHOD(SplDoublyLinkedList, getIteratorMode) { spl_dllist_object *intern; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) { + if (zend_parse_parameters_none() == FAILURE) { return; } diff --git a/ext/spl/spl_fixedarray.c b/ext/spl/spl_fixedarray.c index 86a5371ed3..8624b35a4b 100644 --- a/ext/spl/spl_fixedarray.c +++ b/ext/spl/spl_fixedarray.c @@ -583,7 +583,7 @@ SPL_METHOD(SplFixedArray, __construct) spl_fixedarray_object *intern; long size = 0; - if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &size)) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &size) == FAILURE) { return; } @@ -613,7 +613,7 @@ SPL_METHOD(SplFixedArray, __wakeup) HashTable *intern_ht = zend_std_get_properties(getThis() TSRMLS_CC); zval **data; - if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "")) { + if (zend_parse_parameters_none() == FAILURE) { return; } @@ -643,7 +643,7 @@ SPL_METHOD(SplFixedArray, count) zval *object = getThis(); spl_fixedarray_object *intern; - if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "")) { + if (zend_parse_parameters_none() == FAILURE) { return; } @@ -661,7 +661,7 @@ SPL_METHOD(SplFixedArray, toArray) { spl_fixedarray_object *intern; - if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "")) { + if (zend_parse_parameters_none() == FAILURE) { return; } @@ -693,7 +693,7 @@ SPL_METHOD(SplFixedArray, fromArray) int num; zend_bool save_indexes = 1; - if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|b", &data, &save_indexes)) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|b", &data, &save_indexes) == FAILURE) { return; } @@ -777,7 +777,7 @@ SPL_METHOD(SplFixedArray, getSize) zval *object = getThis(); spl_fixedarray_object *intern; - if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "")) { + if (zend_parse_parameters_none() == FAILURE) { return; } @@ -797,7 +797,7 @@ SPL_METHOD(SplFixedArray, setSize) spl_fixedarray_object *intern; long size; - if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &size)) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &size) == FAILURE) { return; } diff --git a/ext/spl/spl_heap.c b/ext/spl/spl_heap.c index cb1f68dcf1..77b31c06dc 100644 --- a/ext/spl/spl_heap.c +++ b/ext/spl/spl_heap.c @@ -587,7 +587,7 @@ SPL_METHOD(SplHeap, count) long count; spl_heap_object *intern = (spl_heap_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) { + if (zend_parse_parameters_none() == FAILURE) { return; } @@ -602,7 +602,7 @@ SPL_METHOD(SplHeap, isEmpty) { spl_heap_object *intern = (spl_heap_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) { + if (zend_parse_parameters_none() == FAILURE) { return; } @@ -643,7 +643,7 @@ SPL_METHOD(SplHeap, extract) zval *value; spl_heap_object *intern; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) { + if (zend_parse_parameters_none() == FAILURE) { return; } @@ -705,7 +705,7 @@ SPL_METHOD(SplPriorityQueue, extract) zval *value, *value_out, **value_out_pp; spl_heap_object *intern; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) { + if (zend_parse_parameters_none() == FAILURE) { return; } @@ -748,7 +748,7 @@ SPL_METHOD(SplPriorityQueue, top) zval *value, **value_out; spl_heap_object *intern; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) { + if (zend_parse_parameters_none() == FAILURE) { return; } @@ -802,7 +802,7 @@ SPL_METHOD(SplHeap, recoverFromCorruption) { spl_heap_object *intern; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) { + if (zend_parse_parameters_none() == FAILURE) { return; } @@ -835,7 +835,7 @@ SPL_METHOD(SplHeap, top) zval *value; spl_heap_object *intern; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) { + if (zend_parse_parameters_none() == FAILURE) { return; } diff --git a/ext/spl/tests/DirectoryIterator_getBasename_basic_test.phpt b/ext/spl/tests/DirectoryIterator_getBasename_basic_test.phpt index ed1f473be9..d4f22f68a1 100644 --- a/ext/spl/tests/DirectoryIterator_getBasename_basic_test.phpt +++ b/ext/spl/tests/DirectoryIterator_getBasename_basic_test.phpt @@ -4,7 +4,7 @@ DirectoryIterator::getBasename() - Basic Test PHPNW Testfest 2009 - Adrian Hardy --FILE-- <?php - $targetDir = __DIR__.DIRECTORY_SEPARATOR.md5('directoryIterator::getbasename'); + $targetDir = __DIR__.DIRECTORY_SEPARATOR.md5('directoryIterator::getbasename1'); mkdir($targetDir); touch($targetDir.DIRECTORY_SEPARATOR.'getBasename_test.txt'); $dir = new DirectoryIterator($targetDir.DIRECTORY_SEPARATOR); @@ -15,7 +15,7 @@ PHPNW Testfest 2009 - Adrian Hardy ?> --CLEAN-- <?php - $targetDir = __DIR__.DIRECTORY_SEPARATOR.md5('directoryIterator::getbasename'); + $targetDir = __DIR__.DIRECTORY_SEPARATOR.md5('directoryIterator::getbasename1'); unlink($targetDir.DIRECTORY_SEPARATOR.'getBasename_test.txt'); rmdir($targetDir); ?> diff --git a/ext/spl/tests/DirectoryIterator_getBasename_pass_array.phpt b/ext/spl/tests/DirectoryIterator_getBasename_pass_array.phpt index b2df8a55c9..ef13520237 100644 --- a/ext/spl/tests/DirectoryIterator_getBasename_pass_array.phpt +++ b/ext/spl/tests/DirectoryIterator_getBasename_pass_array.phpt @@ -4,7 +4,7 @@ DirectoryIterator::getBasename() - Pass unexpected array PHPNW Testfest 2009 - Adrian Hardy --FILE-- <?php - $targetDir = __DIR__.DIRECTORY_SEPARATOR.md5('directoryIterator::getbasename'); + $targetDir = __DIR__.DIRECTORY_SEPARATOR.md5('directoryIterator::getbasename2'); mkdir($targetDir); touch($targetDir.DIRECTORY_SEPARATOR.'getBasename_test.txt'); $dir = new DirectoryIterator($targetDir.DIRECTORY_SEPARATOR); @@ -15,7 +15,7 @@ PHPNW Testfest 2009 - Adrian Hardy ?> --CLEAN-- <?php - $targetDir = __DIR__.DIRECTORY_SEPARATOR.md5('directoryIterator::getbasename'); + $targetDir = __DIR__.DIRECTORY_SEPARATOR.md5('directoryIterator::getbasename2'); unlink($targetDir.DIRECTORY_SEPARATOR.'getBasename_test.txt'); rmdir($targetDir); ?> diff --git a/ext/spl/tests/RecursiveDirectoryIterator_getSubPath_basic.phpt b/ext/spl/tests/RecursiveDirectoryIterator_getSubPath_basic.phpt index f0b2b0182c..f6bc266cb1 100644 --- a/ext/spl/tests/RecursiveDirectoryIterator_getSubPath_basic.phpt +++ b/ext/spl/tests/RecursiveDirectoryIterator_getSubPath_basic.phpt @@ -5,7 +5,7 @@ Pawel Krynicki <pawel [dot] krynicki [at] xsolve [dot] pl> #testfest AmsterdamPHP 2012-06-23 --FILE-- <?php -$depth0 = "depth0"; +$depth0 = "depth01"; $depth1 = 'depth1'; $depth2 = 'depth2'; $targetDir = __DIR__ . DIRECTORY_SEPARATOR . $depth0 . DIRECTORY_SEPARATOR . $depth1 . DIRECTORY_SEPARATOR . $depth2; @@ -38,7 +38,7 @@ function rrmdir($dir) { rmdir($dir); } -$targetDir = __DIR__.DIRECTORY_SEPARATOR . "depth0"; +$targetDir = __DIR__.DIRECTORY_SEPARATOR . "depth01"; rrmdir($targetDir); ?> diff --git a/ext/spl/tests/RecursiveDirectoryIterator_getSubPathname_basic.phpt b/ext/spl/tests/RecursiveDirectoryIterator_getSubPathname_basic.phpt index 7b12672e14..6527d84bfe 100644 --- a/ext/spl/tests/RecursiveDirectoryIterator_getSubPathname_basic.phpt +++ b/ext/spl/tests/RecursiveDirectoryIterator_getSubPathname_basic.phpt @@ -5,7 +5,7 @@ Pawel Krynicki <pawel [dot] krynicki [at] xsolve [dot] pl> #testfest AmsterdamPHP 2012-06-23 --FILE-- <?php -$depth0 = "depth0"; +$depth0 = "depth02"; $depth1 = "depth1"; $depth2 = "depth2"; $targetDir = __DIR__ . DIRECTORY_SEPARATOR . $depth0 . DIRECTORY_SEPARATOR . $depth1 . DIRECTORY_SEPARATOR . $depth2; @@ -41,7 +41,7 @@ function rrmdir($dir) { rmdir($dir); } -$targetDir = __DIR__ . DIRECTORY_SEPARATOR . "depth0"; +$targetDir = __DIR__ . DIRECTORY_SEPARATOR . "depth02"; rrmdir($targetDir); ?> --EXPECTF-- diff --git a/ext/spl/tests/SplFileObject_fgetcsv_basic.phpt b/ext/spl/tests/SplFileObject_fgetcsv_basic.phpt index abfe5f235f..84b5403698 100644 --- a/ext/spl/tests/SplFileObject_fgetcsv_basic.phpt +++ b/ext/spl/tests/SplFileObject_fgetcsv_basic.phpt @@ -2,7 +2,7 @@ SplFileObject::fgetcsv default path --FILE-- <?php -$fp = fopen('SplFileObject__fgetcsv.csv', 'w+'); +$fp = fopen('SplFileObject__fgetcsv1.csv', 'w+'); fputcsv($fp, array( 'field1', 'field2', @@ -11,12 +11,12 @@ fputcsv($fp, array( )); fclose($fp); -$fo = new SplFileObject('SplFileObject__fgetcsv.csv'); +$fo = new SplFileObject('SplFileObject__fgetcsv1.csv'); var_dump($fo->fgetcsv()); ?> --CLEAN-- <?php -unlink('SplFileObject__fgetcsv.csv'); +unlink('SplFileObject__fgetcsv1.csv'); ?> --EXPECTF-- array(4) { diff --git a/ext/spl/tests/SplFileObject_fgetcsv_delimiter_basic.phpt b/ext/spl/tests/SplFileObject_fgetcsv_delimiter_basic.phpt index 4402d6ca4c..a8125a0257 100644 --- a/ext/spl/tests/SplFileObject_fgetcsv_delimiter_basic.phpt +++ b/ext/spl/tests/SplFileObject_fgetcsv_delimiter_basic.phpt @@ -2,7 +2,7 @@ SplFileObject::fgetcsv with alternative delimiter --FILE-- <?php -$fp = fopen('SplFileObject__fgetcsv.csv', 'w+'); +$fp = fopen('SplFileObject__fgetcsv2.csv', 'w+'); fputcsv($fp, array( 'field1', 'field2', @@ -11,12 +11,12 @@ fputcsv($fp, array( ), '|'); fclose($fp); -$fo = new SplFileObject('SplFileObject__fgetcsv.csv'); +$fo = new SplFileObject('SplFileObject__fgetcsv2.csv'); var_dump($fo->fgetcsv('|')); ?> --CLEAN-- <?php -unlink('SplFileObject__fgetcsv.csv'); +unlink('SplFileObject__fgetcsv2.csv'); ?> --EXPECTF-- array(4) { diff --git a/ext/spl/tests/SplFileObject_fgetcsv_delimiter_error.phpt b/ext/spl/tests/SplFileObject_fgetcsv_delimiter_error.phpt index 64d6514a29..169ded7dc3 100644 --- a/ext/spl/tests/SplFileObject_fgetcsv_delimiter_error.phpt +++ b/ext/spl/tests/SplFileObject_fgetcsv_delimiter_error.phpt @@ -2,7 +2,7 @@ SplFileObject::fgetcsv with alternative delimiter --FILE-- <?php -$fp = fopen('SplFileObject__fgetcsv.csv', 'w+'); +$fp = fopen('SplFileObject__fgetcsv3.csv', 'w+'); fputcsv($fp, array( 'field1', 'field2', @@ -11,12 +11,12 @@ fputcsv($fp, array( ), '|'); fclose($fp); -$fo = new SplFileObject('SplFileObject__fgetcsv.csv'); +$fo = new SplFileObject('SplFileObject__fgetcsv3.csv'); var_dump($fo->fgetcsv('invalid')); ?> --CLEAN-- <?php -unlink('SplFileObject__fgetcsv.csv'); +unlink('SplFileObject__fgetcsv3.csv'); ?> --EXPECTF-- Warning: SplFileObject::fgetcsv(): delimiter must be a character in %s on line %d diff --git a/ext/spl/tests/SplFileObject_fgetcsv_enclosure_basic.phpt b/ext/spl/tests/SplFileObject_fgetcsv_enclosure_basic.phpt index efbb5fb685..efe765cbf8 100644 --- a/ext/spl/tests/SplFileObject_fgetcsv_enclosure_basic.phpt +++ b/ext/spl/tests/SplFileObject_fgetcsv_enclosure_basic.phpt @@ -2,7 +2,7 @@ SplFileObject::fgetcsv with alternative delimiter --FILE-- <?php -$fp = fopen('SplFileObject__fgetcsv.csv', 'w+'); +$fp = fopen('SplFileObject__fgetcsv4.csv', 'w+'); fputcsv($fp, array( 'field1', 'field2', @@ -11,12 +11,12 @@ fputcsv($fp, array( ), ',', '"'); fclose($fp); -$fo = new SplFileObject('SplFileObject__fgetcsv.csv'); +$fo = new SplFileObject('SplFileObject__fgetcsv4.csv'); var_dump($fo->fgetcsv(',', '"')); ?> --CLEAN-- <?php -unlink('SplFileObject__fgetcsv.csv'); +unlink('SplFileObject__fgetcsv4.csv'); ?> --EXPECTF-- array(4) { diff --git a/ext/spl/tests/SplFileObject_fgetcsv_enclosure_error.phpt b/ext/spl/tests/SplFileObject_fgetcsv_enclosure_error.phpt index 7487b8353c..f8c14f0e35 100644 --- a/ext/spl/tests/SplFileObject_fgetcsv_enclosure_error.phpt +++ b/ext/spl/tests/SplFileObject_fgetcsv_enclosure_error.phpt @@ -2,7 +2,7 @@ SplFileObject::fgetcsv with alternative delimiter --FILE-- <?php -$fp = fopen('SplFileObject__fgetcsv.csv', 'w+'); +$fp = fopen('SplFileObject__fgetcsv5.csv', 'w+'); fputcsv($fp, array( 'field1', 'field2', @@ -11,12 +11,12 @@ fputcsv($fp, array( ), ',', '"'); fclose($fp); -$fo = new SplFileObject('SplFileObject__fgetcsv.csv'); +$fo = new SplFileObject('SplFileObject__fgetcsv5.csv'); var_dump($fo->fgetcsv(',', 'invalid')); ?> --CLEAN-- <?php -unlink('SplFileObject__fgetcsv.csv'); +unlink('SplFileObject__fgetcsv5.csv'); ?> --EXPECTF-- Warning: SplFileObject::fgetcsv(): enclosure must be a character in %s on line %d diff --git a/ext/spl/tests/SplFileObject_fgetcsv_escape_basic.phpt b/ext/spl/tests/SplFileObject_fgetcsv_escape_basic.phpt index 1a94532b2b..960f36d63f 100644 --- a/ext/spl/tests/SplFileObject_fgetcsv_escape_basic.phpt +++ b/ext/spl/tests/SplFileObject_fgetcsv_escape_basic.phpt @@ -2,16 +2,16 @@ SplFileObject::fgetcsv with alternative delimiter --FILE-- <?php -$fp = fopen('SplFileObject__fgetcsv.csv', 'w+'); +$fp = fopen('SplFileObject__fgetcsv6.csv', 'w+'); fwrite($fp, '"aaa","b""bb","ccc"'); fclose($fp); -$fo = new SplFileObject('SplFileObject__fgetcsv.csv'); +$fo = new SplFileObject('SplFileObject__fgetcsv6.csv'); var_dump($fo->fgetcsv(',', '"', '"')); ?> --CLEAN-- <?php -unlink('SplFileObject__fgetcsv.csv'); +unlink('SplFileObject__fgetcsv6.csv'); ?> --EXPECTF-- array(3) { diff --git a/ext/spl/tests/SplFileObject_fgetcsv_escape_default.phpt b/ext/spl/tests/SplFileObject_fgetcsv_escape_default.phpt index c628ac043d..69089636c1 100644 --- a/ext/spl/tests/SplFileObject_fgetcsv_escape_default.phpt +++ b/ext/spl/tests/SplFileObject_fgetcsv_escape_default.phpt @@ -2,16 +2,16 @@ SplFileObject::fgetcsv with default escape character --FILE-- <?php -$fp = fopen('SplFileObject__fgetcsv.csv', 'w+'); +$fp = fopen('SplFileObject__fgetcsv7.csv', 'w+'); fwrite($fp, '"aa\"","bb","\"c"'); fclose($fp); -$fo = new SplFileObject('SplFileObject__fgetcsv.csv'); +$fo = new SplFileObject('SplFileObject__fgetcsv7.csv'); var_dump($fo->fgetcsv()); ?> --CLEAN-- <?php -unlink('SplFileObject__fgetcsv.csv'); +unlink('SplFileObject__fgetcsv7.csv'); ?> --EXPECTF-- array(3) { diff --git a/ext/spl/tests/SplFileObject_fgetcsv_escape_error.phpt b/ext/spl/tests/SplFileObject_fgetcsv_escape_error.phpt index fd90103bfa..b49bcdd13c 100644 --- a/ext/spl/tests/SplFileObject_fgetcsv_escape_error.phpt +++ b/ext/spl/tests/SplFileObject_fgetcsv_escape_error.phpt @@ -2,16 +2,16 @@ SplFileObject::fgetcsv with alternative delimiter --FILE-- <?php -$fp = fopen('SplFileObject__fgetcsv.csv', 'w+'); +$fp = fopen('SplFileObject__fgetcsv8.csv', 'w+'); fwrite($fp, '"aaa","b""bb","ccc"'); fclose($fp); -$fo = new SplFileObject('SplFileObject__fgetcsv.csv'); +$fo = new SplFileObject('SplFileObject__fgetcsv8.csv'); var_dump($fo->fgetcsv(',', '"', 'invalid')); ?> --CLEAN-- <?php -unlink('SplFileObject__fgetcsv.csv'); +unlink('SplFileObject__fgetcsv8.csv'); ?> --EXPECTF-- Warning: SplFileObject::fgetcsv(): escape must be a character in %s on line %d diff --git a/ext/spl/tests/SplFileObject_fputcsv_002.phpt b/ext/spl/tests/SplFileObject_fputcsv_002.phpt index db174931f7..fdd4112ee6 100644 --- a/ext/spl/tests/SplFileObject_fputcsv_002.phpt +++ b/ext/spl/tests/SplFileObject_fputcsv_002.phpt @@ -2,7 +2,7 @@ SplFileObject::fputcsv(): Checking data after calling the function --FILE-- <?php -$fo = new SplFileObject(__DIR__ . '/SplFileObject_fputcsv.csv', 'w'); +$fo = new SplFileObject(__DIR__ . '/SplFileObject_fputcsv1.csv', 'w'); $data = array(1, 2, 'foo', 'haha', array(4, 5, 6), 1.3, null); @@ -12,7 +12,7 @@ var_dump($data); ?> --CLEAN-- <?php -$file = __DIR__ . '/SplFileObject_fputcsv.csv'; +$file = __DIR__ . '/SplFileObject_fputcsv1.csv'; unlink($file); ?> --EXPECTF-- diff --git a/ext/spl/tests/SplFileObject_fputcsv_error.phpt b/ext/spl/tests/SplFileObject_fputcsv_error.phpt index 8368e4211d..cdee48c874 100644 --- a/ext/spl/tests/SplFileObject_fputcsv_error.phpt +++ b/ext/spl/tests/SplFileObject_fputcsv_error.phpt @@ -2,7 +2,7 @@ SplFileObject::fputcsv(): error conditions --FILE-- <?php -$fo = new SplFileObject(__DIR__ . '/SplFileObject_fputcsv.csv', 'w'); +$fo = new SplFileObject(__DIR__ . '/SplFileObject_fputcsv2.csv', 'w'); echo "*** Testing error conditions ***\n"; // zero argument @@ -19,7 +19,7 @@ var_dump( $fo->fputcsv($fields, $delim, $enclosure, $fo) ); echo "Done\n"; --CLEAN-- <?php -$file = __DIR__ . '/SplFileObject_fputcsv.csv'; +$file = __DIR__ . '/SplFileObject_fputcsv2.csv'; unlink($file); ?> --EXPECTF-- diff --git a/ext/spl/tests/bug51532.phpt b/ext/spl/tests/bug51532.phpt index 3a0722b2af..26eaa8f82f 100644 --- a/ext/spl/tests/bug51532.phpt +++ b/ext/spl/tests/bug51532.phpt @@ -4,7 +4,7 @@ SPL: Allow valid extension of SplFileObject::fscanf <?php class A extends SplFileObject { - public function fscanf($format) { + public function fscanf($format, &...$vars) { } } diff --git a/ext/spl/tests/dit_006.phpt b/ext/spl/tests/dit_006.phpt index 1e627a20e0..9edbb9f157 100644 --- a/ext/spl/tests/dit_006.phpt +++ b/ext/spl/tests/dit_006.phpt @@ -2,7 +2,7 @@ SPL: DirectoryIterator and seek --FILE-- <?php -$di = new DirectoryIterator(__DIR__); +$di = new DirectoryIterator(__DIR__."/.."); $di->seek(2); $n = 0; diff --git a/ext/sqlite3/config.w32 b/ext/sqlite3/config.w32 index 01e4625fed..8ddb6b9ac8 100644 --- a/ext/sqlite3/config.w32 +++ b/ext/sqlite3/config.w32 @@ -4,7 +4,7 @@ ARG_WITH("sqlite3", "SQLite 3 support", "no"); if (PHP_SQLITE3 != "no") { - ADD_FLAG("CFLAGS_SQLITE3", "/D SQLITE_THREADSAFE=" + (PHP_ZTS == "yes" ? "1" : "0") + " /D SQLITE_ENABLE_FTS3=1 /D SQLITE_ENABLE_COLUMN_METADATA=1 /D SQLITE_CORE=1 "); + ADD_FLAG("CFLAGS_SQLITE3", "/D SQLITE_THREADSAFE=" + (PHP_ZTS == "yes" ? "1" : "0") + " /D SQLITE_ENABLE_FTS3=1 /D SQLITE_ENABLE_COLUMN_METADATA=1 /D SQLITE_CORE=1 /D SQLITE_API=__declspec(dllexport) "); EXTENSION("sqlite3", "sqlite3.c", null, "/I" + configure_module_dirname + "/libsqlite /I" + configure_module_dirname); ADD_SOURCES(configure_module_dirname + "/libsqlite", "sqlite3.c", "sqlite3"); diff --git a/ext/sqlite3/sqlite3.c b/ext/sqlite3/sqlite3.c index 2aef0414aa..19bf58deb8 100644 --- a/ext/sqlite3/sqlite3.c +++ b/ext/sqlite3/sqlite3.c @@ -1890,7 +1890,7 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite3stmt_bindvalue, 0, 0, 2) ZEND_ARG_INFO(0, type) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_INFO(arginfo_sqlite3stmt_construct, 1) +ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite3stmt_construct, 0, 0, 1) ZEND_ARG_INFO(0, sqlite3) ZEND_END_ARG_INFO() diff --git a/ext/standard/array.c b/ext/standard/array.c index 360a691d38..d21badc87c 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -127,6 +127,9 @@ PHP_MINIT_FUNCTION(array) /* {{{ */ REGISTER_LONG_CONSTANT("COUNT_NORMAL", COUNT_NORMAL, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("COUNT_RECURSIVE", COUNT_RECURSIVE, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("ARRAY_FILTER_USE_BOTH", ARRAY_FILTER_USE_BOTH, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("ARRAY_FILTER_USE_KEY", ARRAY_FILTER_USE_KEY, CONST_CS | CONST_PERSISTENT); + return SUCCESS; } /* }}} */ @@ -830,7 +833,7 @@ PHP_FUNCTION(end) RETURN_FALSE; } - RETURN_ZVAL(*entry, 1, 0); + RETURN_ZVAL_FAST(*entry); } } /* }}} */ @@ -853,7 +856,7 @@ PHP_FUNCTION(prev) RETURN_FALSE; } - RETURN_ZVAL(*entry, 1, 0); + RETURN_ZVAL_FAST(*entry); } } /* }}} */ @@ -876,7 +879,7 @@ PHP_FUNCTION(next) RETURN_FALSE; } - RETURN_ZVAL(*entry, 1, 0); + RETURN_ZVAL_FAST(*entry); } } /* }}} */ @@ -899,7 +902,7 @@ PHP_FUNCTION(reset) RETURN_FALSE; } - RETURN_ZVAL(*entry, 1, 0); + RETURN_ZVAL_FAST(*entry); } } /* }}} */ @@ -918,7 +921,8 @@ PHP_FUNCTION(current) if (zend_hash_get_current_data(array, (void **) &entry) == FAILURE) { RETURN_FALSE; } - RETURN_ZVAL(*entry, 1, 0); + + RETURN_ZVAL_FAST(*entry); } /* }}} */ @@ -958,7 +962,7 @@ PHP_FUNCTION(min) RETVAL_NULL(); } else { if (zend_hash_minmax(Z_ARRVAL_PP(args[0]), php_array_data_compare, 0, (void **) &result TSRMLS_CC) == SUCCESS) { - RETVAL_ZVAL(*result, 1, 0); + RETVAL_ZVAL_FAST(*result); } else { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Array must contain at least one element"); RETVAL_FALSE; @@ -978,7 +982,7 @@ PHP_FUNCTION(min) } } - RETVAL_ZVAL(*min, 1, 0); + RETVAL_ZVAL_FAST(*min); } if (args) { @@ -1009,7 +1013,7 @@ PHP_FUNCTION(max) RETVAL_NULL(); } else { if (zend_hash_minmax(Z_ARRVAL_PP(args[0]), php_array_data_compare, 1, (void **) &result TSRMLS_CC) == SUCCESS) { - RETVAL_ZVAL(*result, 1, 0); + RETVAL_ZVAL_FAST(*result); } else { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Array must contain at least one element"); RETVAL_FALSE; @@ -1029,7 +1033,7 @@ PHP_FUNCTION(max) } } - RETVAL_ZVAL(*max, 1, 0); + RETVAL_ZVAL_FAST(*max); } if (args) { @@ -1517,14 +1521,18 @@ PHP_FUNCTION(array_fill) return; } - if (num < 1) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Number of elements must be positive"); + if (num < 0) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Number of elements can't be negative"); RETURN_FALSE; } /* allocate an array for return */ array_init_size(return_value, num); + if (num == 0) { + return; + } + num--; zend_hash_index_update(Z_ARRVAL_P(return_value), start_key, &val, sizeof(zval *), NULL); zval_add_ref(&val); @@ -1955,7 +1963,7 @@ static void _phpi_pop(INTERNAL_FUNCTION_PARAMETERS, int off_the_end) zend_hash_internal_pointer_reset(Z_ARRVAL_P(stack)); } zend_hash_get_current_data(Z_ARRVAL_P(stack), (void **)&val); - RETVAL_ZVAL(*val, 1, 0); + RETVAL_ZVAL_FAST(*val); /* Delete the first or last value */ zend_hash_get_current_key_ex(Z_ARRVAL_P(stack), &key, &key_len, &index, 0, NULL); @@ -4204,9 +4212,11 @@ PHP_FUNCTION(array_filter) { zval *array; zval **operand; - zval **args[1]; + zval **args[2]; zval *retval = NULL; + zval *key = NULL; zend_bool have_callback = 0; + long use_type = 0; char *string_key; zend_fcall_info fci = empty_fcall_info; zend_fcall_info_cache fci_cache = empty_fcall_info_cache; @@ -4214,7 +4224,7 @@ PHP_FUNCTION(array_filter) ulong num_key; HashPosition pos; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|f", &array, &fci, &fci_cache) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|fl", &array, &fci, &fci_cache, &use_type) == FAILURE) { return; } @@ -4227,23 +4237,54 @@ PHP_FUNCTION(array_filter) have_callback = 1; fci.no_separation = 0; fci.retval_ptr_ptr = &retval; - fci.param_count = 1; + + if (use_type == ARRAY_FILTER_USE_BOTH) { + fci.param_count = 2; + args[1] = &key; + } else { + fci.param_count = 1; + if (use_type == ARRAY_FILTER_USE_KEY) { + args[0] = &key; + } + } } for (zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(array), &pos); zend_hash_get_current_data_ex(Z_ARRVAL_P(array), (void **)&operand, &pos) == SUCCESS; zend_hash_move_forward_ex(Z_ARRVAL_P(array), &pos) ) { + int key_type = zend_hash_get_current_key_ex(Z_ARRVAL_P(array), &string_key, &string_key_len, &num_key, 0, &pos); + if (have_callback) { - args[0] = operand; + if (use_type) { + MAKE_STD_ZVAL(key); + /* Set up the key */ + switch (key_type) { + case HASH_KEY_IS_LONG: + Z_TYPE_P(key) = IS_LONG; + Z_LVAL_P(key) = num_key; + break; + + case HASH_KEY_IS_STRING: + ZVAL_STRINGL(key, string_key, string_key_len - 1, 1); + break; + } + } + + if (use_type != ARRAY_FILTER_USE_KEY) { + args[0] = operand; + } fci.params = args; if (zend_call_function(&fci, &fci_cache TSRMLS_CC) == SUCCESS && retval) { - if (!zend_is_true(retval)) { - zval_ptr_dtor(&retval); + int retval_true = zend_is_true(retval); + + zval_ptr_dtor(&retval); + if (use_type) { + zval_ptr_dtor(&key); + } + if (!retval_true) { continue; - } else { - zval_ptr_dtor(&retval); } } else { php_error_docref(NULL TSRMLS_CC, E_WARNING, "An error occurred while invoking the filter callback"); @@ -4254,7 +4295,7 @@ PHP_FUNCTION(array_filter) } zval_add_ref(operand); - switch (zend_hash_get_current_key_ex(Z_ARRVAL_P(array), &string_key, &string_key_len, &num_key, 0, &pos)) { + switch (key_type) { case HASH_KEY_IS_STRING: zend_hash_update(Z_ARRVAL_P(return_value), string_key, string_key_len, operand, sizeof(zval *), NULL); break; diff --git a/ext/standard/assert.c b/ext/standard/assert.c index 631834c97c..1a24ade79e 100644 --- a/ext/standard/assert.c +++ b/ext/standard/assert.c @@ -200,7 +200,7 @@ PHP_FUNCTION(assert) } if (ASSERTG(callback)) { - zval **args = safe_emalloc(description_len == 0 ? 3 : 4, sizeof(zval **), 0); + zval **args = safe_emalloc(description_len == 0 ? 3 : 4, sizeof(zval *), 0); zval *retval; int i; uint lineno = zend_get_executed_lineno(TSRMLS_C); diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c index 96b3c30bbd..f55925f315 100644 --- a/ext/standard/basic_functions.c +++ b/ext/standard/basic_functions.c @@ -288,11 +288,11 @@ ZEND_BEGIN_ARG_INFO(arginfo_reset, 0) ZEND_ARG_INFO(1, arg) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_INFO(arginfo_current, ZEND_SEND_PREFER_REF) +ZEND_BEGIN_ARG_INFO(arginfo_current, 0) ZEND_ARG_INFO(ZEND_SEND_PREFER_REF, arg) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_INFO(arginfo_key, ZEND_SEND_PREFER_REF) +ZEND_BEGIN_ARG_INFO(arginfo_key, 0) ZEND_ARG_INFO(ZEND_SEND_PREFER_REF, arg) ZEND_END_ARG_INFO() @@ -564,13 +564,14 @@ ZEND_BEGIN_ARG_INFO(arginfo_array_udiff_uassoc, 0) ZEND_ARG_INFO(0, callback_key_comp_func) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_INFO_EX(arginfo_array_multisort, ZEND_SEND_PREFER_REF, 0, 1) +ZEND_BEGIN_ARG_INFO_EX(arginfo_array_multisort, 0, 0, 1) ZEND_ARG_INFO(ZEND_SEND_PREFER_REF, arr1) /* ARRAY_INFO(0, arg1, 0) */ ZEND_ARG_INFO(ZEND_SEND_PREFER_REF, SORT_ASC_or_SORT_DESC) ZEND_ARG_INFO(ZEND_SEND_PREFER_REF, SORT_REGULAR_or_SORT_NUMERIC_or_SORT_STRING) ZEND_ARG_INFO(ZEND_SEND_PREFER_REF, arr2) ZEND_ARG_INFO(ZEND_SEND_PREFER_REF, SORT_ASC_or_SORT_DESC) ZEND_ARG_INFO(ZEND_SEND_PREFER_REF, SORT_REGULAR_or_SORT_NUMERIC_or_SORT_STRING) + ZEND_ARG_VARIADIC_INFO(ZEND_SEND_PREFER_REF, more_array_and_sort_options) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_array_rand, 0, 0, 1) @@ -595,6 +596,7 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_array_filter, 0, 0, 1) ZEND_ARG_INFO(0, arg) /* ARRAY_INFO(0, arg, 0) */ ZEND_ARG_INFO(0, callback) + ZEND_ARG_INFO(0, use_keys) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_array_map, 0, 0, 2) @@ -1139,10 +1141,10 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_fgetss, 0, 0, 1) ZEND_ARG_INFO(0, allowable_tags) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_INFO_EX(arginfo_fscanf, 1, 0, 2) +ZEND_BEGIN_ARG_INFO_EX(arginfo_fscanf, 0, 0, 2) ZEND_ARG_INFO(0, stream) ZEND_ARG_INFO(0, format) - ZEND_ARG_INFO(1, ...) + ZEND_ARG_VARIADIC_INFO(1, vars) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_fwrite, 0, 0, 2) @@ -2450,10 +2452,10 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_str_pad, 0, 0, 2) ZEND_ARG_INFO(0, pad_type) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_INFO_EX(arginfo_sscanf, 1, 0, 2) +ZEND_BEGIN_ARG_INFO_EX(arginfo_sscanf, 0, 0, 2) ZEND_ARG_INFO(0, str) ZEND_ARG_INFO(0, format) - ZEND_ARG_INFO(1, ...) + ZEND_ARG_VARIADIC_INFO(1, vars) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO(arginfo_str_rot13, 0) @@ -2679,6 +2681,7 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO(arginfo_unserialize, 0) ZEND_ARG_INFO(0, variable_representation) + ZEND_ARG_INFO(1, consumed) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_memory_get_usage, 0, 0, 0) diff --git a/ext/standard/credits_ext.h b/ext/standard/credits_ext.h index 2770d162fb..382e70e7d7 100644 --- a/ext/standard/credits_ext.h +++ b/ext/standard/credits_ext.h @@ -42,8 +42,8 @@ CREDIT_LINE("MS SQL", "Frank M. Kromann"); CREDIT_LINE("Multibyte String Functions", "Tsukada Takuya, Rui Hirokawa"); CREDIT_LINE("MySQL driver for PDO", "George Schlossnagle, Wez Furlong, Ilia Alshanetsky, Johannes Schlueter"); CREDIT_LINE("MySQLi", "Zak Greant, Georg Richter, Andrey Hristov, Ulf Wendel"); -CREDIT_LINE("MySQLnd", "Andrey Hristov, Ulf Wendel, Georg Richter, Johannes Schlueter"); -CREDIT_LINE("MySQL", "Zeev Suraski, Zak Greant, Georg Richter, Andrey Hristov"); +CREDIT_LINE("MySQLnd", "Andrey Hristov, Ulf Wendel, Georg Richter"); +CREDIT_LINE("MySQL", "Zeev Suraski, Zak Greant, Georg Richter"); CREDIT_LINE("OCI8", "Stig Bakken, Thies C. Arntzen, Andy Sautins, David Benson, Maxim Maletsky, Harald Radi, Antony Dovgal, Andi Gutmans, Wez Furlong, Christopher Jones, Oracle Corporation"); CREDIT_LINE("ODBC driver for PDO", "Wez Furlong"); CREDIT_LINE("ODBC", "Stig Bakken, Andreas Karajannis, Frank M. Kromann, Daniel R. Kalowsky"); diff --git a/ext/standard/crypt.c b/ext/standard/crypt.c index 113a5bd0f5..354c263afb 100644 --- a/ext/standard/crypt.c +++ b/ext/standard/crypt.c @@ -272,6 +272,8 @@ PHP_FUNCTION(crypt) if (salt_in) { memcpy(salt, salt_in, MIN(PHP_MAX_SALT_LEN, salt_in_len)); + } else { + php_error_docref(NULL TSRMLS_CC, E_NOTICE, "No salt parameter was specified. You must use a randomly generated salt and a strong hash function to produce a secure hash."); } /* The automatic salt generation covers standard DES, md5-crypt and Blowfish (simple) */ diff --git a/ext/standard/crypt_freesec.h b/ext/standard/crypt_freesec.h index a87663d4fe..860462a2dd 100644 --- a/ext/standard/crypt_freesec.h +++ b/ext/standard/crypt_freesec.h @@ -4,26 +4,13 @@ #define _CRYPT_FREESEC_H #if PHP_WIN32 -# include "win32/php_stdint.h" # ifndef inline # define inline __inline # endif -#else -# include "php_config.h" -# if HAVE_INTTYPES_H -# include <inttypes.h> -# elif HAVE_STDINT_H -# include <stdint.h> -# endif -# ifndef HAVE_UINT32_T -# if SIZEOF_INT == 4 -typedef unsigned int uint32_t; -# elif SIZEOF_LONG == 4 -typedef unsigned long int uint32_t; -# endif -# endif #endif +#include "php_stdint.h" + #define MD5_HASH_MAX_LEN 120 struct php_crypt_extended_data { diff --git a/ext/standard/crypt_sha256.c b/ext/standard/crypt_sha256.c index d334e3d477..ccfa66bd60 100644 --- a/ext/standard/crypt_sha256.c +++ b/ext/standard/crypt_sha256.c @@ -9,15 +9,9 @@ #include <limits.h> #ifdef PHP_WIN32 -# include "win32/php_stdint.h" # define __alignof__ __alignof # define alloca _alloca #else -# if HAVE_INTTYPES_H -# include <inttypes.h> -# elif HAVE_STDINT_H -# include <stdint.h> -# endif # ifndef HAVE_ALIGNOF # include <stddef.h> # define __alignof__(type) offsetof (struct { char c; type member;}, member) diff --git a/ext/standard/crypt_sha512.c b/ext/standard/crypt_sha512.c index 0955532131..ebabed9d24 100644 --- a/ext/standard/crypt_sha512.c +++ b/ext/standard/crypt_sha512.c @@ -8,15 +8,9 @@ #include <errno.h> #include <limits.h> #ifdef PHP_WIN32 -# include "win32/php_stdint.h" # define __alignof__ __alignof # define alloca _alloca #else -# if HAVE_INTTYPES_H -# include <inttypes.h> -# elif HAVE_STDINT_H -# include <stdint.h> -# endif # ifndef HAVE_ALIGNOF # include <stddef.h> # define __alignof__(type) offsetof (struct { char c; type member;}, member) diff --git a/ext/standard/css.c b/ext/standard/css.c index d76f9ee662..459a7bfc30 100644 --- a/ext/standard/css.c +++ b/ext/standard/css.c @@ -1,4 +1,4 @@ -/* +/* +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ @@ -12,7 +12,7 @@ | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ - | Authors: Colin Viebrock <colin@easydns.com> | + | Authors: Colin Viebrock <colin@viebrock.ca> | +----------------------------------------------------------------------+ */ @@ -23,25 +23,24 @@ PHPAPI void php_info_print_css(TSRMLS_D) /* {{{ */ { - PUTS("body {background-color: #ffffff; color: #000000;}\n"); - PUTS("body, td, th, h1, h2 {font-family: sans-serif;}\n"); - PUTS("pre {margin: 0px; font-family: monospace;}\n"); - PUTS("a:link {color: #000099; text-decoration: none; background-color: #ffffff;}\n"); + PUTS("body {background-color: #fff; color: #222; font-family: sans-serif;}\n"); + PUTS("pre {margin: 0; font-family: monospace;}\n"); + PUTS("a:link {color: #009; text-decoration: none; background-color: #fff;}\n"); PUTS("a:hover {text-decoration: underline;}\n"); - PUTS("table {border-collapse: collapse;}\n"); + PUTS("table {border-collapse: collapse; border: 0; width: 934px; box-shadow: 1px 2px 3px #ccc;}\n"); PUTS(".center {text-align: center;}\n"); - PUTS(".center table { margin-left: auto; margin-right: auto; text-align: left;}\n"); - PUTS(".center th { text-align: center !important; }\n"); - PUTS("td, th { border: 1px solid #000000; font-size: 75%; vertical-align: baseline;}\n"); + PUTS(".center table {margin: 1em auto; text-align: left;}\n"); + PUTS(".center th {text-align: center !important;}\n"); + PUTS("td, th {border: 1px solid #666; font-size: 75%; vertical-align: baseline; padding: 4px 5px;}\n"); PUTS("h1 {font-size: 150%;}\n"); PUTS("h2 {font-size: 125%;}\n"); PUTS(".p {text-align: left;}\n"); - PUTS(".e {background-color: #ccccff; font-weight: bold; color: #000000;}\n"); - PUTS(".h {background-color: #9999cc; font-weight: bold; color: #000000;}\n"); - PUTS(".v {background-color: #cccccc; color: #000000;}\n"); - PUTS(".vr {background-color: #cccccc; text-align: right; color: #000000;}\n"); - PUTS("img {float: right; border: 0px;}\n"); - PUTS("hr {width: 600px; background-color: #cccccc; border: 0px; height: 1px; color: #000000;}\n"); + PUTS(".e {background-color: #ccf; width: 300px; font-weight: bold;}\n"); + PUTS(".h {background-color: #99c; font-weight: bold;}\n"); + PUTS(".v {background-color: #ddd; max-width: 300px; overflow-x: auto;}\n"); + PUTS(".v i {color: #999;}\n"); + PUTS("img {float: right; border: 0;}\n"); + PUTS("hr {width: 934px; background-color: #ccc; border: 0; height: 1px;}\n"); } /* }}} */ diff --git a/ext/standard/css.h b/ext/standard/css.h index d7275e08ef..0b3ae87cbd 100644 --- a/ext/standard/css.h +++ b/ext/standard/css.h @@ -1,4 +1,4 @@ -/* +/* +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ @@ -12,7 +12,7 @@ | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ - | Authors: Colin Viebrock <colin@easydns.com> | + | Authors: Colin Viebrock <colin@viebrock.ca> | +----------------------------------------------------------------------+ */ diff --git a/ext/standard/dir.c b/ext/standard/dir.c index ef28e9feaf..ca7e576c92 100644 --- a/ext/standard/dir.c +++ b/ext/standard/dir.c @@ -491,13 +491,18 @@ PHP_FUNCTION(glob) /* now catch the FreeBSD style of "no matches" */ if (!globbuf.gl_pathc || !globbuf.gl_pathv) { no_results: +#ifndef PHP_WIN32 + /* Paths containing '*', '?' and some other chars are + illegal on Windows but legit on other platforms. For + this reason the direct basedir check against the glob + query is senseless on windows. For instance while *.txt + is a pretty valid filename on EXT3, it's invalid on NTFS. */ if (PG(open_basedir) && *PG(open_basedir)) { - struct stat s; - - if (0 != VCWD_STAT(pattern, &s) || S_IFDIR != (s.st_mode & S_IFMT)) { + if (php_check_open_basedir_ex(pattern, 0 TSRMLS_CC)) { RETURN_FALSE; } } +#endif array_init(return_value); return; } diff --git a/ext/standard/file.c b/ext/standard/file.c index ad6bdad34f..2bd35bf894 100644 --- a/ext/standard/file.c +++ b/ext/standard/file.c @@ -223,10 +223,14 @@ PHP_MINIT_FUNCTION(file) REGISTER_LONG_CONSTANT("STREAM_CRYPTO_METHOD_SSLv3_CLIENT", STREAM_CRYPTO_METHOD_SSLv3_CLIENT, CONST_CS|CONST_PERSISTENT); REGISTER_LONG_CONSTANT("STREAM_CRYPTO_METHOD_SSLv23_CLIENT", STREAM_CRYPTO_METHOD_SSLv23_CLIENT, CONST_CS|CONST_PERSISTENT); REGISTER_LONG_CONSTANT("STREAM_CRYPTO_METHOD_TLS_CLIENT", STREAM_CRYPTO_METHOD_TLS_CLIENT, CONST_CS|CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT", STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT, CONST_CS|CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT", STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT, CONST_CS|CONST_PERSISTENT); REGISTER_LONG_CONSTANT("STREAM_CRYPTO_METHOD_SSLv2_SERVER", STREAM_CRYPTO_METHOD_SSLv2_SERVER, CONST_CS|CONST_PERSISTENT); REGISTER_LONG_CONSTANT("STREAM_CRYPTO_METHOD_SSLv3_SERVER", STREAM_CRYPTO_METHOD_SSLv3_SERVER, CONST_CS|CONST_PERSISTENT); REGISTER_LONG_CONSTANT("STREAM_CRYPTO_METHOD_SSLv23_SERVER", STREAM_CRYPTO_METHOD_SSLv23_SERVER, CONST_CS|CONST_PERSISTENT); REGISTER_LONG_CONSTANT("STREAM_CRYPTO_METHOD_TLS_SERVER", STREAM_CRYPTO_METHOD_TLS_SERVER, CONST_CS|CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("STREAM_CRYPTO_METHOD_TLSv1_1_SERVER", STREAM_CRYPTO_METHOD_TLSv1_1_SERVER, CONST_CS|CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("STREAM_CRYPTO_METHOD_TLSv1_2_SERVER", STREAM_CRYPTO_METHOD_TLSv1_2_SERVER, CONST_CS|CONST_PERSISTENT); REGISTER_LONG_CONSTANT("STREAM_SHUT_RD", STREAM_SHUT_RD, CONST_CS|CONST_PERSISTENT); REGISTER_LONG_CONSTANT("STREAM_SHUT_WR", STREAM_SHUT_WR, CONST_CS|CONST_PERSISTENT); @@ -1284,7 +1288,7 @@ PHPAPI PHP_FUNCTION(fseek) */ /* DEPRECATED APIs: Use php_stream_mkdir() instead */ -PHPAPI int php_mkdir_ex(char *dir, long mode, int options TSRMLS_DC) +PHPAPI int php_mkdir_ex(const char *dir, long mode, int options TSRMLS_DC) { int ret; @@ -1299,7 +1303,7 @@ PHPAPI int php_mkdir_ex(char *dir, long mode, int options TSRMLS_DC) return ret; } -PHPAPI int php_mkdir(char *dir, long mode TSRMLS_DC) +PHPAPI int php_mkdir(const char *dir, long mode TSRMLS_DC) { return php_mkdir_ex(dir, mode, REPORT_ERRORS TSRMLS_CC); } @@ -1623,7 +1627,7 @@ PHP_FUNCTION(copy) /* {{{ php_copy_file */ -PHPAPI int php_copy_file(char *src, char *dest TSRMLS_DC) +PHPAPI int php_copy_file(const char *src, const char *dest TSRMLS_DC) { return php_copy_file_ctx(src, dest, 0, NULL TSRMLS_CC); } @@ -1631,7 +1635,7 @@ PHPAPI int php_copy_file(char *src, char *dest TSRMLS_DC) /* {{{ php_copy_file_ex */ -PHPAPI int php_copy_file_ex(char *src, char *dest, int src_flg TSRMLS_DC) +PHPAPI int php_copy_file_ex(const char *src, const char *dest, int src_flg TSRMLS_DC) { return php_copy_file_ctx(src, dest, 0, NULL TSRMLS_CC); } @@ -1639,7 +1643,7 @@ PHPAPI int php_copy_file_ex(char *src, char *dest, int src_flg TSRMLS_DC) /* {{{ php_copy_file_ctx */ -PHPAPI int php_copy_file_ctx(char *src, char *dest, int src_flg, php_stream_context *ctx TSRMLS_DC) +PHPAPI int php_copy_file_ctx(const char *src, const char *dest, int src_flg, php_stream_context *ctx TSRMLS_DC) { php_stream *srcstream = NULL, *deststream = NULL; int ret = FAILURE; diff --git a/ext/standard/file.h b/ext/standard/file.h index 2bcdfd64bf..d6f142a769 100644 --- a/ext/standard/file.h +++ b/ext/standard/file.h @@ -74,11 +74,11 @@ PHP_MINIT_FUNCTION(user_streams); PHPAPI int php_le_stream_context(TSRMLS_D); PHPAPI int php_set_sock_blocking(int socketd, int block TSRMLS_DC); -PHPAPI int php_copy_file(char *src, char *dest TSRMLS_DC); -PHPAPI int php_copy_file_ex(char *src, char *dest, int src_chk TSRMLS_DC); -PHPAPI int php_copy_file_ctx(char *src, char *dest, int src_chk, php_stream_context *ctx TSRMLS_DC); -PHPAPI int php_mkdir_ex(char *dir, long mode, int options TSRMLS_DC); -PHPAPI int php_mkdir(char *dir, long mode TSRMLS_DC); +PHPAPI int php_copy_file(const char *src, const char *dest TSRMLS_DC); +PHPAPI int php_copy_file_ex(const char *src, const char *dest, int src_chk TSRMLS_DC); +PHPAPI int php_copy_file_ctx(const char *src, const char *dest, int src_chk, php_stream_context *ctx TSRMLS_DC); +PHPAPI int php_mkdir_ex(const char *dir, long mode, int options TSRMLS_DC); +PHPAPI int php_mkdir(const char *dir, long mode TSRMLS_DC); PHPAPI void php_fgetcsv(php_stream *stream, char delimiter, char enclosure, char escape_char, size_t buf_len, char *buf, zval *return_value TSRMLS_DC); PHPAPI int php_fputcsv(php_stream *stream, zval *fields, char delimiter, char enclosure, char escape_char TSRMLS_DC); @@ -121,7 +121,7 @@ typedef struct { long default_socket_timeout; char *user_agent; /* for the http wrapper */ char *from_address; /* for the ftp and http wrappers */ - char *user_stream_current_filename; /* for simple recursion protection */ + const char *user_stream_current_filename; /* for simple recursion protection */ php_stream_context *default_context; HashTable *stream_wrappers; /* per-request copy of url_stream_wrappers_hash */ HashTable *stream_filters; /* per-request copy of stream_filters_hash */ diff --git a/ext/standard/filestat.c b/ext/standard/filestat.c index 2713d23f1d..0b40e7319b 100644 --- a/ext/standard/filestat.c +++ b/ext/standard/filestat.c @@ -857,7 +857,7 @@ PHPAPI void php_stat(const char *filename, php_stat_len filename_length, int typ "dev", "ino", "mode", "nlink", "uid", "gid", "rdev", "size", "atime", "mtime", "ctime", "blksize", "blocks" }; - char *local; + const char *local; php_stream_wrapper *wrapper; if (!filename_length) { diff --git a/ext/standard/ftp_fopen_wrapper.c b/ext/standard/ftp_fopen_wrapper.c index 86975d7f5b..d04ef52be7 100644 --- a/ext/standard/ftp_fopen_wrapper.c +++ b/ext/standard/ftp_fopen_wrapper.c @@ -130,8 +130,9 @@ static int php_stream_ftp_stream_close(php_stream_wrapper *wrapper, php_stream * /* {{{ php_ftp_fopen_connect */ -static php_stream *php_ftp_fopen_connect(php_stream_wrapper *wrapper, char *path, char *mode, int options, char **opened_path, php_stream_context *context, - php_stream **preuseid, php_url **presource, int *puse_ssl, int *puse_ssl_on_data TSRMLS_DC) +static php_stream *php_ftp_fopen_connect(php_stream_wrapper *wrapper, const char *path, const char *mode, int options, + char **opened_path, php_stream_context *context, php_stream **preuseid, + php_url **presource, int *puse_ssl, int *puse_ssl_on_data TSRMLS_DC) { php_stream *stream = NULL, *reuseid = NULL; php_url *resource = NULL; @@ -410,7 +411,8 @@ static unsigned short php_fopen_do_pasv(php_stream *stream, char *ip, size_t ip_ /* {{{ php_fopen_url_wrap_ftp */ -php_stream * php_stream_url_wrap_ftp(php_stream_wrapper *wrapper, char *path, char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC) +php_stream * php_stream_url_wrap_ftp(php_stream_wrapper *wrapper, const char *path, const char *mode, + int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC) { php_stream *stream = NULL, *datastream = NULL; php_url *resource = NULL; @@ -691,7 +693,8 @@ static php_stream_ops php_ftp_dirstream_ops = { /* {{{ php_stream_ftp_opendir */ -php_stream * php_stream_ftp_opendir(php_stream_wrapper *wrapper, char *path, char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC) +php_stream * php_stream_ftp_opendir(php_stream_wrapper *wrapper, const char *path, const char *mode, int options, + char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC) { php_stream *stream, *reuseid, *datastream = NULL; php_ftp_dirstream_data *dirsdata; @@ -780,7 +783,7 @@ opendir_errexit: /* {{{ php_stream_ftp_url_stat */ -static int php_stream_ftp_url_stat(php_stream_wrapper *wrapper, char *url, int flags, php_stream_statbuf *ssb, php_stream_context *context TSRMLS_DC) +static int php_stream_ftp_url_stat(php_stream_wrapper *wrapper, const char *url, int flags, php_stream_statbuf *ssb, php_stream_context *context TSRMLS_DC) { php_stream *stream = NULL; php_url *resource = NULL; @@ -903,7 +906,7 @@ stat_errexit: /* {{{ php_stream_ftp_unlink */ -static int php_stream_ftp_unlink(php_stream_wrapper *wrapper, char *url, int options, php_stream_context *context TSRMLS_DC) +static int php_stream_ftp_unlink(php_stream_wrapper *wrapper, const char *url, int options, php_stream_context *context TSRMLS_DC) { php_stream *stream = NULL; php_url *resource = NULL; @@ -953,7 +956,7 @@ unlink_errexit: /* {{{ php_stream_ftp_rename */ -static int php_stream_ftp_rename(php_stream_wrapper *wrapper, char *url_from, char *url_to, int options, php_stream_context *context TSRMLS_DC) +static int php_stream_ftp_rename(php_stream_wrapper *wrapper, const char *url_from, const char *url_to, int options, php_stream_context *context TSRMLS_DC) { php_stream *stream = NULL; php_url *resource_from = NULL, *resource_to = NULL; @@ -1032,7 +1035,7 @@ rename_errexit: /* {{{ php_stream_ftp_mkdir */ -static int php_stream_ftp_mkdir(php_stream_wrapper *wrapper, char *url, int mode, int options, php_stream_context *context TSRMLS_DC) +static int php_stream_ftp_mkdir(php_stream_wrapper *wrapper, const char *url, int mode, int options, php_stream_context *context TSRMLS_DC) { php_stream *stream = NULL; php_url *resource = NULL; @@ -1126,7 +1129,7 @@ mkdir_errexit: /* {{{ php_stream_ftp_rmdir */ -static int php_stream_ftp_rmdir(php_stream_wrapper *wrapper, char *url, int options, php_stream_context *context TSRMLS_DC) +static int php_stream_ftp_rmdir(php_stream_wrapper *wrapper, const char *url, int options, php_stream_context *context TSRMLS_DC) { php_stream *stream = NULL; php_url *resource = NULL; diff --git a/ext/standard/http_fopen_wrapper.c b/ext/standard/http_fopen_wrapper.c index 4605e7494f..f5184ceec6 100644 --- a/ext/standard/http_fopen_wrapper.c +++ b/ext/standard/http_fopen_wrapper.c @@ -80,6 +80,7 @@ #define HTTP_HEADER_FROM 8 #define HTTP_HEADER_CONTENT_LENGTH 16 #define HTTP_HEADER_TYPE 32 +#define HTTP_HEADER_CONNECTION 64 #define HTTP_WRAPPER_HEADER_INIT 1 #define HTTP_WRAPPER_REDIRECTED 2 @@ -108,7 +109,9 @@ static inline void strip_header(char *header_bag, char *lc_header_bag, } } -php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper, char *path, char *mode, int options, char **opened_path, php_stream_context *context, int redirect_max, int flags STREAMS_DC TSRMLS_DC) /* {{{ */ +php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper, + const char *path, const char *mode, int options, char **opened_path, + php_stream_context *context, int redirect_max, int flags STREAMS_DC TSRMLS_DC) /* {{{ */ { php_stream *stream = NULL; php_url *resource = NULL; @@ -409,8 +412,6 @@ finish: strlcat(scratch, " HTTP/", scratch_len); strlcat(scratch, protocol_version, scratch_len); strlcat(scratch, "\r\n", scratch_len); - efree(protocol_version); - protocol_version = NULL; } else { strlcat(scratch, " HTTP/1.0\r\n", scratch_len); } @@ -490,6 +491,11 @@ finish: *(s-1) == '\t' || *(s-1) == ' ')) { have_header |= HTTP_HEADER_TYPE; } + if ((s = strstr(tmp, "connection:")) && + (s == tmp || *(s-1) == '\r' || *(s-1) == '\n' || + *(s-1) == '\t' || *(s-1) == ' ')) { + have_header |= HTTP_HEADER_CONNECTION; + } /* remove Proxy-Authorization header */ if (use_proxy && use_ssl && (s = strstr(tmp, "proxy-authorization:")) && (s == tmp || *(s-1) == '\r' || *(s-1) == '\n' || @@ -563,6 +569,16 @@ finish: } } + /* Send a Connection: close header when using HTTP 1.1 or later to avoid + * hanging when the server interprets the RFC literally and establishes a + * keep-alive connection, unless the user specifically requests something + * else by specifying a Connection header in the context options. */ + if (protocol_version && + ((have_header & HTTP_HEADER_CONNECTION) == 0) && + (strncmp(protocol_version, "1.0", MIN(protocol_version_len, 3)) > 0)) { + php_stream_write_string(stream, "Connection: close\r\n"); + } + if (context && php_stream_context_get_option(context, "http", "user_agent", &ua_zval) == SUCCESS && Z_TYPE_PP(ua_zval) == IS_STRING) { @@ -922,7 +938,7 @@ out: } /* }}} */ -php_stream *php_stream_url_wrap_http(php_stream_wrapper *wrapper, char *path, char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC) /* {{{ */ +php_stream *php_stream_url_wrap_http(php_stream_wrapper *wrapper, const char *path, const char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC) /* {{{ */ { return php_stream_url_wrap_http_ex(wrapper, path, mode, options, opened_path, context, PHP_URL_REDIRECT_MAX, HTTP_WRAPPER_HEADER_INIT STREAMS_CC TSRMLS_CC); } diff --git a/ext/standard/info.c b/ext/standard/info.c index 48e0e85cc5..cfff023afa 100644 --- a/ext/standard/info.c +++ b/ext/standard/info.c @@ -1,4 +1,4 @@ -/* +/* +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ @@ -14,7 +14,7 @@ +----------------------------------------------------------------------+ | Authors: Rasmus Lerdorf <rasmus@php.net> | | Zeev Suraski <zeev@zend.com> | - | Colin Viebrock <colin@easydns.com> | + | Colin Viebrock <colin@viebrock.ca> | +----------------------------------------------------------------------+ */ @@ -67,7 +67,7 @@ static int php_info_print_html_esc(const char *str, int len) /* {{{ */ int written; char *new_str; TSRMLS_FETCH(); - + new_str = php_escape_html_entities((unsigned char *) str, len, &new_len, 0, ENT_QUOTES, "utf-8" TSRMLS_CC); written = php_output_write(new_str, new_len TSRMLS_CC); efree(new_str); @@ -81,11 +81,11 @@ static int php_info_printf(const char *fmt, ...) /* {{{ */ int len, written; va_list argv; TSRMLS_FETCH(); - + va_start(argv, fmt); len = vspprintf(&buf, 0, fmt, argv); va_end(argv); - + written = php_output_write(buf, len TSRMLS_CC); efree(buf); return written; @@ -103,7 +103,7 @@ static void php_info_print_stream_hash(const char *name, HashTable *ht TSRMLS_DC { char *key; uint len; - + if (ht) { if (zend_hash_num_elements(ht)) { HashPosition pos; @@ -113,7 +113,7 @@ static void php_info_print_stream_hash(const char *name, HashTable *ht TSRMLS_DC } else { php_info_printf("\nRegistered %s => ", name); } - + zend_hash_internal_pointer_reset_ex(ht, &pos); while (zend_hash_get_current_key_ex(ht, &key, &len, NULL, 0, &pos) == HASH_KEY_IS_STRING) { @@ -129,7 +129,7 @@ static void php_info_print_stream_hash(const char *name, HashTable *ht TSRMLS_DC break; } } - + if (!sapi_module.phpinfo_as_text) { php_info_print("</td></tr>\n"); } @@ -164,10 +164,10 @@ PHPAPI void php_info_print_module(zend_module_entry *zend_module TSRMLS_DC) /* { } } else { if (!sapi_module.phpinfo_as_text) { - php_info_printf("<tr><td>%s</td></tr>\n", zend_module->name); + php_info_printf("<tr><td class=\"v\">%s</td></tr>\n", zend_module->name); } else { php_info_printf("%s\n", zend_module->name); - } + } } } /* }}} */ @@ -212,7 +212,7 @@ static void php_print_gpcse_array(char *name, uint name_length TSRMLS_DC) php_info_print(name); php_info_print("[\""); - + switch (zend_hash_get_current_key_ex(Z_ARRVAL_PP(data), &string_key, &string_len, &num_key, 0, NULL)) { case HASH_KEY_IS_STRING: if (!sapi_module.phpinfo_as_text) { @@ -442,7 +442,7 @@ char* php_get_windows_name() sub = "Web Edition"; else sub = "Standard Edition"; } - } + } } if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1 ) { @@ -535,7 +535,7 @@ PHPAPI char *php_get_uname(char mode) DWORD dwWindowsMinorVersion = (DWORD)(HIBYTE(LOWORD(dwVersion))); DWORD dwSize = MAX_COMPUTERNAME_LENGTH + 1; char ComputerName[MAX_COMPUTERNAME_LENGTH + 1]; - + GetComputerName(ComputerName, &dwSize); if (mode == 's') { @@ -584,7 +584,7 @@ PHPAPI char *php_get_uname(char mode) if (mode == 's') { php_uname = buf.sysname; } else if (mode == 'r') { - snprintf(tmp_uname, sizeof(tmp_uname), "%d.%d.%d", + snprintf(tmp_uname, sizeof(tmp_uname), "%d.%d.%d", buf.netware_major, buf.netware_minor, buf.netware_revision); php_uname = tmp_uname; } else if (mode == 'n') { @@ -674,7 +674,7 @@ PHPAPI void php_print_info(int flag TSRMLS_DC) char temp_api[10]; php_uname = php_get_uname('a'); - + if (!sapi_module.phpinfo_as_text) { php_info_print_box_start(1); } @@ -698,7 +698,7 @@ PHPAPI void php_print_info(int flag TSRMLS_DC) php_info_printf("<h1 class=\"p\">PHP Version %s</h1>\n", PHP_VERSION); } else { php_info_print_table_row(2, "PHP Version", PHP_VERSION); - } + } php_info_print_box_end(); php_info_print_table_start(); php_info_print_table_row(2, "System", php_uname ); @@ -783,7 +783,7 @@ PHPAPI void php_print_info(int flag TSRMLS_DC) #else php_info_print_table_row(2, "DTrace Support", "disabled" ); #endif - + php_info_print_stream_hash("PHP Streams", php_stream_get_url_stream_wrappers_hash() TSRMLS_CC); php_info_print_stream_hash("Stream Socket Transports", php_stream_xport_get_hash() TSRMLS_CC); php_info_print_stream_hash("Stream Filters", php_get_stream_filters_hash() TSRMLS_CC); @@ -815,7 +815,7 @@ PHPAPI void php_print_info(int flag TSRMLS_DC) php_info_print("<h1>Configuration</h1>\n"); } else { SECTION("Configuration"); - } + } if (!(flag & PHP_INFO_MODULES)) { SECTION("PHP Core"); display_ini_entries(NULL); @@ -889,7 +889,7 @@ PHPAPI void php_print_info(int flag TSRMLS_DC) } - if ((flag & PHP_INFO_CREDITS) && !sapi_module.phpinfo_as_text) { + if ((flag & PHP_INFO_CREDITS) && !sapi_module.phpinfo_as_text) { php_info_print_hr(); php_print_credits(PHP_CREDITS_ALL & ~PHP_CREDITS_FULLPAGE TSRMLS_CC); } @@ -930,24 +930,24 @@ PHPAPI void php_print_info(int flag TSRMLS_DC) if (!sapi_module.phpinfo_as_text) { php_info_print("</div></body></html>"); - } + } } /* }}} */ PHPAPI void php_info_print_table_start(void) /* {{{ */ { if (!sapi_module.phpinfo_as_text) { - php_info_print("<table border=\"0\" cellpadding=\"3\" width=\"600\">\n"); + php_info_print("<table>\n"); } else { php_info_print("\n"); - } + } } /* }}} */ PHPAPI void php_info_print_table_end(void) /* {{{ */ { if (!sapi_module.phpinfo_as_text) { - php_info_print("</table><br />\n"); + php_info_print("</table>\n"); } } @@ -965,7 +965,7 @@ PHPAPI void php_info_print_box_start(int flag) /* {{{ */ php_info_print("<tr class=\"v\"><td>\n"); } else { php_info_print("\n"); - } + } } } /* }}} */ @@ -998,7 +998,7 @@ PHPAPI void php_info_print_table_colspan_header(int num_cols, char *header) /* { } else { spaces = (74 - strlen(header)); php_info_printf("%*s%s%*s\n", (int)(spaces/2), " ", header, (int)(spaces/2), " "); - } + } } /* }}} */ @@ -1013,7 +1013,7 @@ PHPAPI void php_info_print_table_header(int num_cols, ...) va_start(row_elements, num_cols); if (!sapi_module.phpinfo_as_text) { php_info_print("<tr class=\"h\">"); - } + } for (i=0; i<num_cols; i++) { row_element = va_arg(row_elements, char *); if (!row_element || !*row_element) { @@ -1042,7 +1042,7 @@ PHPAPI void php_info_print_table_header(int num_cols, ...) /* {{{ php_info_print_table_row_internal */ -static void php_info_print_table_row_internal(int num_cols, +static void php_info_print_table_row_internal(int num_cols, const char *value_class, va_list row_elements) { int i; @@ -1050,13 +1050,13 @@ static void php_info_print_table_row_internal(int num_cols, if (!sapi_module.phpinfo_as_text) { php_info_print("<tr>"); - } + } for (i=0; i<num_cols; i++) { if (!sapi_module.phpinfo_as_text) { php_info_printf("<td class=\"%s\">", (i==0 ? "e" : value_class ) ); - } + } row_element = va_arg(row_elements, char *); if (!row_element || !*row_element) { if (!sapi_module.phpinfo_as_text) { @@ -1071,7 +1071,7 @@ static void php_info_print_table_row_internal(int num_cols, php_info_print(row_element); if (i < num_cols-1) { php_info_print(" => "); - } + } } } if (!sapi_module.phpinfo_as_text) { @@ -1091,7 +1091,7 @@ static void php_info_print_table_row_internal(int num_cols, PHPAPI void php_info_print_table_row(int num_cols, ...) { va_list row_elements; - + va_start(row_elements, num_cols); php_info_print_table_row_internal(num_cols, "v", row_elements); va_end(row_elements); @@ -1100,11 +1100,11 @@ PHPAPI void php_info_print_table_row(int num_cols, ...) /* {{{ php_info_print_table_row_ex */ -PHPAPI void php_info_print_table_row_ex(int num_cols, const char *value_class, +PHPAPI void php_info_print_table_row_ex(int num_cols, const char *value_class, ...) { va_list row_elements; - + va_start(row_elements, value_class); php_info_print_table_row_internal(num_cols, value_class, row_elements); va_end(row_elements); @@ -1232,7 +1232,7 @@ PHP_FUNCTION(php_ini_scanned_files) if (zend_parse_parameters_none() == FAILURE) { return; } - + if (strlen(PHP_CONFIG_FILE_SCAN_DIR) && php_ini_scanned_files) { RETURN_STRING(php_ini_scanned_files, 1); } else { @@ -1248,7 +1248,7 @@ PHP_FUNCTION(php_ini_loaded_file) if (zend_parse_parameters_none() == FAILURE) { return; } - + if (php_ini_opened_path) { RETURN_STRING(php_ini_opened_path, 1); } else { diff --git a/ext/standard/info.h b/ext/standard/info.h index 46a0dfc240..b616204b30 100644 --- a/ext/standard/info.h +++ b/ext/standard/info.h @@ -1,4 +1,4 @@ -/* +/* +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ @@ -14,6 +14,7 @@ +----------------------------------------------------------------------+ | Authors: Rasmus Lerdorf <rasmus@php.net> | | Zeev Suraski <zeev@zend.com> | + | Colin Viebrock <colin@viebrock.ca> | +----------------------------------------------------------------------+ */ @@ -22,9 +23,9 @@ #ifndef INFO_H #define INFO_H -#define PHP_ENTRY_NAME_COLOR "#ccccff" -#define PHP_CONTENTS_COLOR "#cccccc" -#define PHP_HEADER_COLOR "#9999cc" +#define PHP_ENTRY_NAME_COLOR "#ccf" +#define PHP_CONTENTS_COLOR "#ccc" +#define PHP_HEADER_COLOR "#99c" #define PHP_INFO_GENERAL (1<<0) #define PHP_INFO_CREDITS (1<<1) @@ -50,9 +51,9 @@ #endif /* HAVE_CREDITS_DEFS */ -#define PHP_LOGO_DATA_URI "data:image/gif;base64,R0lGODlheABDAOZqAH+CuDk3RyglKszN4qGky9PV57K01ENCWIOGuYKDs1JScpCSwsLE3qqs0ExLY1tcg93e7Ds4PG5xpWptnWFjjXV5sXt+teXm8JmcxoyNwbm62Wtrkk5Oa3F0qXp6o4iLvXJ0o3RzmI6QwVpbfuLj73t9raSl0G1wonJ2rJWWyLu92XR4roWIu5KVw9jZ6pKSxGRmkmtun6WozpSWxS4rL1NRaLO012xqjFxbdoqNv2ZolmhqmpyfyDEuOa6w05yczVVWeJ6hypaZxYGCr2dplz89ULy+2l5giZiZyIyOv4mKuldYfLa319XX6CIeIGxvns7Q5L/A3Hd7tHZ4p19efZmZzG5vmHN3riIeH////5COj1lWV8fGx+7u9dXU1fb2+oKAgayqq3Ryc/Hw8Z6cnePi40tISbm4uWdkZYmJtgD/AEdGX9/g7ZuczGlrnG9zp4yMuri52bi615qbzKeqz9vc65qcyWZkhGhniaeo0m5woIuLucbH4MfJ4WlsnJeYyyH5BAEAAGoALAAAAAB4AEMAAAf/gGqCg4SFhoeIiYqLjI2Oj5CRkpOUlZaXlm0/bXOYnp+gP3l5Nj4acUwaGkwGPj4NMgRBPBhCLQtJIjkfGTkiLymgwqENGgx9TQVQUAN9fAxRUSpyrK90sbNCMy26HwgAFhYVVyglFgkZwcPrjCZxfC5sbBAQdS7JA9QysyIf/iwAEQgEQLDgN4LhpKxA8UbCCT87nkwZkoSdRTVBbAxgQ+KCRxIk8jUQskCKyZMoU6pceXJcBwkTduiAQeEIBStDRFzEFIQJFI4eL7gwQqcFy6NIk6K88iYGjCNHHoxYcsSDzp2Qfmh0AYEjBCMEWCgdSzbplRM6HiwBokDBiCkz/7AuMqGhQBMXdQoYSFK2r1+kHWAsUcCBgwM8CeQayhNlAJQCA3zk+LtyAYbLmDF8oJz0DQUFDtasUeBBsZo8Rvj0GcBkBueVH7JwmU2bS5fXSt0sWXPggIMQO91FYcCgAQLcKzFwwcK8uZnbyJN22F2kyJrSw374kGNEBQ8L0VeqINO8uZgC4ZVeeXAgQAAOcECZMMBEDgEA6VcWEFOeORkV+Sn1hgLu9XAHJnPQ4YMBMhwXoEpdmNEfFlwQ8KBSMazRQw8H7FHJDzI00EBJF6YEQBYTYpHFZiUm9UAAGwInSRsE7ONgiycpN6EZX+ColB9F0EADFZHYEQQBM4CH1P8HmTXZJItHqRDGhGJc0CSJLDHp5Jb4jYWCAzQIUMMjSGAQBJRHffBFFmy26eabWXRRQANdolQAGBOSAWebFwxg4UkL7Ckom10M0IBSQAgggAONzCAEBmIpRcByKVZqBhhcfAEgSl1sUWmKNGyhRRldkGjAlJ9OuAUYXnRxKFIjCOAEo4psI8SNSY2X6qdbeAFBlyfu+ikYY2AgxQB4CqtqGQMkNYITTuCQSAoitIBmUhDwp2yKYUBgEgZebJsiGrdd4Km45dHgRbNIrQEtdoX84ctkZX0hIbr9eQGglPjm2wCK/TZHQxl/HhWAEwIsYEg/9JIVW8DlbdHjnRAzp8X/BeFWjIUY0B3VgaxjEpICAh/UOdakO8I5xhnaTugFAZ1OyMWbY3CBRopaZIFqxHCWcca5E5aBJUsKQJsGId7gOpau/YnhLUoLNNAFeRNqwQDA/a2IEgYNfBFB1VloUTW7gBrwRbL9hWGAUjTMOsgfACCgZFnZ5rmpiVl83XQWGZfH40oQAN1czoIzd8baKn0wBs53H7UEtAqrIYIFJpNlr8wFpxS4qjpT+XRKMfd3RhY0BG3sSqGXp0XjLHUA7Q2CsJBQXw9POMa1J23eHxpZoN3cfyoFG3QZE9KQxVGpD846S0W4rUY4c5OFcn8R9MjS5f0RjrlK4BafxRmqXnAU/9blAa8UB070IEgFlDFdHhqfp1R72uQ3d7tK/Pa3Rdhjs4QB8dtTCgWgJYgVUKZu2VueSQwAvqD1rTnV04/vmAOGLBQOC4djCQOo1p/7CZCAKbgC+/yCvfJUiCXJY04EOre7+J0khVgIA+lMtxIAeG1C5CLLAJ0gCBQYsC/C6yDujkWp7PWuassLYnm8AMB0HU8/HCxPGBS4kh0KogMoGCFZdES9J6LkAwXwQun6Q4MxfOGCJ0xJ9yb0vfBxDwJinFD1KncUK6phIVpcWhSZQy4V+FEFEOjCGLQwRtENoH7M8SBK8sczsWWvC38EZBfK4EiZUXEl6FPf8zpwhb7sR/9VWghlKMVwrxSJ4QsEeKAKvWinCWKhghcUlSi1QMphia8szaPVB97Qgb5ESGNo+MICToVDF5rEXBOSYSEDdsqhSed1gkiBBN7wQ6UosV/NPJYrrbYSRGKBiRoDgzD78jgnRO55EujlWNbYLxqcYZxSQGZ/uPCqramSOW0MWATOcAFnss15gnjBCSTQSaUwUlxmIMMYBlCnGXbQn8TUH//wZQYZMoCOSSmaE45GiCGc4A1joZj+ZjlLMnBhDIVCU6BIGkpWnkQFXGDp6C4oBpaG0qQoZcAQpQMyQ6TgBCdQJ1JgyIUL0IMeBfgjAfxpEkAe9aiZA9QAnkqPQy6TOV7/MOpRk+pHAux0LAdL2CGSEIMToAAp10wkU30khQU0sTxZwChy3OUEeBkiAWUtaHLuuUK2sqQBDYxYx/JTTmkpogR5ZclB+WhMv0qBAZVsDhjQE6By0moRiDWrBKvGAMeqRHdSvCRlNHpZRpRgAjHoQB6lQNR6etYkeXPZ6aLTgQNAq7SNSABqJaDFtGJhDGv10QIWx0a5+oUIPYCWYSOhhCdMQLNS+N8Wpktd3r3WntSlLhgG+xoFyEoAMprEC0DghxjwFgAFoCo9EHddKaBXvRBwLWWIcDAnRICjlkiAG1D7htW2168nsK1yQfGCKfgBtar9r19RwAFZOaEI+AWF/xL04IYD91fBJTrBGhzcg/CygwUUPrAEzorh8BzhAIoSQA9gpxgWgGAHbnBDDKhZYsr4gQMBCJMAAsBi0wgiCSUgwg5gPAEa1zgpEyBQD4QkJrv6eBApSIAedEAEIbshqP7F8BuOgOMNLbkIeHjBkxfxAinr4Mxn3sFHSXzdHRxBAe2B0YYOcAMPjfkRL0DAFIgAgz77mQh++KhQ8zMBIjwANNVxj6JxEAI735kSIhjCnilA6UpT+gh9rnCg38BpTkvg058GKlCJcGm2iKY3B6hOEQJwABxsIDGPFkYKPlACEFgBKlB5gK53PZUlrAUIbGkLYQpjmNCcujdFUAAVbjgwBDHHWjEpUAICPOCBDWwgLb4GdrDbQmzDcIAKIxiBFaxQgmY/+9yLEEEaEHAVdLv73fCOd7wDAQA7AA==" -#define PHP_EGG_LOGO_DATA_URI "data:image/gif;base64,R0lGODlheABDAOf/ABIZISAeIhwhLA8jRwYlVSUoLyIpNSkoKwkvbR4tRBUwVDMuNysxOx87Yg89gDo3RTI5SgBCkDg6PDY7RyBCcTxBQz9BVD9ETxxPkQ9SoktIYkROVkpNWDJSeilVhkxObEZTZQVevgBfxVZQZRxcn1BUYFNTc1FXWRZht1ZYVQBm0ghlzBhksVVafyNlqSpkn1hcZwBr2EVfhABs0lRdcF5adRJpyWBcaVlgYl5dh15efh5q0gdw3iFsxhBy2Rtxxhhx0Ttsn2BkigB45SxwtDFwq0dslGNoc1pqfRtz6GRmkypzwFZuiQl772psaWlpiiF25Ax94zB10BB+3iV44BR96yN71TJ5vit7zih73GluoDt6tk53nix66QOG+nBwl0l7r3F2cjOAzSKB9guI9SKC8HF1lW90pm93jTCC3SaE6zWC12F8knR6fHV5gzaC5SmH6ESC3y6H9kGGyiqJ8UuDzXx5oWV9v1aA0nl6qWmAnXl6tHJ8tV6AyVGGuS6K/EyHwyKO/D6J5T+K2SGQ9zqL3ziN9jaP6jmP8WaHwYGCsHqIkC6U/C2V9naFv0GS50mS2IGFuYeHnEWU4iyZ/16P2ISIr1iSz4mLiF2SxV+TvImLlmiSsnqPrIeLvzmc/kOa9Uaa74aNtHWRyXiSvk+a6YyNvIGQwo6OsImTnFib3lKd5l2d2kKi/WSd0k2h9zeo/1Gi8ZSUw5GVyn+czE2m/46bsY2ZyHugwUmr/12n8GCn6pieoGWn5Hekzpueq26n25yby1ms/ICk25ejrlGy/56iymav+V2y+2yv7Wex9KaopWG2/1e5/5Wu2H216265/HW3/qus0aavxWe+/66wvYy33YC4+Hi7+bO0uHPB/aq3wa6112vF/4e/9pfA27u31YDF/XnK/5PG77y/25TI/MDBxYbN/qvH7LfH2qPP+47V/57T/cPN2abT9c3M5Jna/77S7LrU57HV+KLg/7zd+tbb3dbb6a7l/sbh99Hi+Lrp++Pm7+Hx/P3//P///yH5BAEKAP8ALAAAAAB4AEMAAAj+AP8JHEiwoMGDCBMqXMiwocOHECNKnEixosWLFoNpDIaxo8ePwaRJ4yaNHDhw5EySFCnNmEtjt2TJMmXKk01PpmbN+sgTZEly7+7de0eUaMqj4FaKfBlzps1IkfZI3cMnzx5Fnnb23MrQGLig/PgJHTvUZEtjNZ9CXcu2bVSpfPicOaOlrpY8ikxx3fvPGLd3YQOHfUdOWkw+jkaNEjVtquPHkCNLnVtXieUcSr7k5YvRK2DB9wrLctSnUi9dxYpRo6atEy/JsGM7pqskh+0WLXLY0csZYrC/QsOGNubplrNkxWq1Wp6rObNu53y5kU2dupbaLUxob5FHVu+Fxsj+kb3HzdTUc/TonWtWrLnqXMWaiQvnC031+7LPKMn+4YOGJ4p8Z1BJRA0ljSeQ1XMOPOt00wx7xYhDjWrinDNOEFzQwgd+HEamnwkahGiCHQL+QyBR4MgSWzjw0CNOM+4xKN868FhjhB/PqIMON844c8spp6zlSSSexIXYUx06pkULGlhggQZfcObVUdK8FRs70NCzDnvNUeNgN+vQ4w4XfvSizDHIQAMNM8LooosyaWqDDTbhhOPNnc9g88www/RIHH5nMOmkBiT2FNJRxuBXjzAMTghLK/IVAyY843TgAhaHIKIpIXDQgUgjhwjySCijllLKKrqssssuqaqaTDL+e57CYQ4WPPDAB7x15BdKxlgp2zi9JBPLOetQkwsssBTTYDPwwMMOBSRYgQghdMhRxrVl0AHHG9xuO0UWghRSyCOlTCJuIZNAoq4qwMh63xkm2LrAExiFNFKV96GzyyOICPNIOfRQs9wnucCjTTf07OMOBREAQQcZZXhRxcTYUmExFVFEkUUWaXTscRqhlDuIGGJA0ssoHGqhwQILWJCrRPZKo+J9z5xpCBnUNtrKJwTjc4426bHTQQQzVHFtFU00AUUXEw8BxRBUDBHFtnAIksYUVpOLzDGpTjLIIJA40mEOD7AcJczGtORrbJ48E8orn8jhhRyv4AMPMrBQAkv+M14ijI/QRHeBLdJdMA3F0jzwAIUPb2iKCBwbTwHHI6PqEoub6c6xYcoWHHCADhEF49LM1UWyCyigEMIIIYY0EY56xeycCzO5NAP0PoDPEDG2XSR9eBeHQ8GDD3CUk4862AgD+cZZwAHHIY/EEssqkGjeIR8aeD7CQ6L/eZ8jlWg6hxVkQFxFi8bunOze4tCDzzgNOFB0E9c2UcUYSRd++BA++JCFPm5wwjLKcQjnZcEHQJjcuB6BKl2oQmwdMoHnNNAQWdyiV/iJRB2yoAY1vOEFVbBWFegBD3HkYjmtaI+X4PG++PmgfnKIobXKEDWnDWF4abgHBwzgBG/AQXL+kANCGg6RBitYAQtrgMQqVgFBDrXgAAGgoEJkcou1xeYWdZjCFKKghiqQQAr4o0N61hG7T+gtF+IQBz7wYQ0FEG0M12IEz0DBM001QlNU8EEa2nEBA7QBG5ATxLeAgMRChGINP0jkD7AghkQ08T4tCEAAapCQWZhCFgi6zyjWIAhr2MIFQ5DaD4bQBUS4Dx7NeJQZYQGdfdDjGQOIQAzo14h5yCMf+ahHPfIhj3ZsQx7QgMMg2jEBAbQBecd4xSOIuIZmkguJWFDkJWiRJA1IslAFmQVOMkmdSFxiDYfQhz/8gYQodMFpwAsFPlzZjJ0xohVoPMc+4OEKAkSACnL+IMQxsnGBC3DgnyXgwAYusIFslGMV1SjmAU6AAzfwIh3YCMUkelEKcj0CXWuI5hzmYA0ryuYBATiAdwqSlvvwQRVYyMI8xumPVKTBaEgrwzHWCI/YMeKdxdBG+9jBBQJkoAqBQAQ2NlECGJSABjCgwVEDygBzeGMTEyiAAUrQTwYUIAzeCIUtiPGNZ+jCVI9Iww/EcAlX+OIWHDoDFLdHkFkQyaORuURKB5GCaoxTD4gog7WaMAZvjJE9rUjWg9JTKQKggAyMaEQ53FDUauAyl/r4RQkY0AZ+HOECASBGNX7BWAEAYBGlYAJBcRAGTGBiG8oQK1kzwQpSbK46JpD+5MuGBFfI3AELQKBCEAxQgHbYwwWNKB+22JEeF7WHldQIEzy8kQAEZOETO5sHDU5Qgm08QxiNgEMhzFGCAlTgHiWYgATycad52KKYJ3gGCATAgA1woJ8GwEQpevCDQQACEHMwqzPuA0Up/sOttX0MH3oAhBn4wAPTOAANNpEFMuyVfuxoETy6cSxJSXgdroglHGbXCnnQwA1HSIcyJhaFQqSjuwzYBgcYcIRywCENkPhFAQBwAmJ+Nh7TIAYaeAsMIPRADHPwwxKuAAhXkOIUpJNMJAMwUvMEeCoDtsEKVjADEhQgAAIggRrIUIXCNYEM7KARPNIHC3Gs48zhkIH+YUEhDIGlgwM3cIMtjlEFKrzhEe1Y8QIka4BFxEINgngGGjy7iGp4Fhe64Fo8DAAATkyhB1iYQxBcsAQiXGELW8iENcwjmTNIkl7/ePJUPLEEKatABTsAAgUSgAE43OxavVMDO85h5mZANxfJPbM3GoCANLyiGMyAxDQ4AINNWEMYhEDEIdTxiwsU4AhouIAAqoEINWTBGRAAAAC2MWgGJEOZj7hEAgDAhTSgAAtXeIELWMBuEpCACJl2RqIiY4EoCsSkgOjBCmIQgx34GwiF4CAhhHutRqwjjetABnRhQawzZ2IAGXiFMNqjilT8MxvooAYzoMGObBxhAgywBxL++oiODmahE4xmQDuyvQFtvCIUhfCDZzlxiB8sYQ5bIAG7WeBuF5CgCGDwAy6SLJUPBGAB967OKbBggx3wIAYq4PcOfBAFOljdwVXwAjPCcY5uSCgXyulGs8rRAQLUgRlsyoU30MCBEpjjHubYBjGcQGwIpOIeMJjABp5BBzVYAQmePcI0ZkwMbQgjFpDoxKHhIIYrXKEIL3gBEdTtbgz8HNOcgIwSJCmQ18LGE3MAwgpUwIMh8LvfPqBCsgcOMTLQ6WDnmBB75lOODDsgFhpnRivmAYK2X4AGE7hA8IvqhnhUY8Vt8IYa6FAHC2h7G0gAwAbkMQ49pYMGAJAAKwT+MYgrECEIHog8vOHt7hcUYQuZf8zmA/Df6owCC1OOOg/KUIWnx2AIjYCbIT5BBkNwHRoVcg7MkFPUcA7eUHZigAy0Iwy5IA8QAGdHAGJHAAMw4AbbMA+PIAkcMAG8UA5UoAaJwGgXkA7ZJgG8cIK8AAOYlQrmMgiWFgQyAAZbQAQu4AKRB35BEARbgAvqx3n/EBeyUQdSIAKoFgM+MARkoAZPFwWH8AqtMC37Bw3noCZmdg51Uid+AHG6gAwMWAu5sA0TcAMlwA+5VA/zEA/qcAyIUArtQAzEcA/XQAVwgAsW0Ge2IAEAwADvBVAX0AbPUAhgA29GgAZ2wARgAHn+JPACYLAhlsAFXOAr6ycQZ+B5kDEKPzADoxcDw/OBZaAGqfcKyAAKzNEKwhAOycMiB5cM4QAMCuAAk6ANtOOF0PALxOYG/XAMn9B3VmcI1vYK0VAO0QAKQwAH4xAP98APSMBb9rANqbAIbpAK1gU9I+MCWyADViEVXAAGL+ABMiAKsBGJP0iJjnEKYtB0UcdvPEAFj1MGQ6AGsRAO0KANasIMyKAM2nAMUpgMu6AKl0ABCPADCrgzlNAKi1UCJbAJ/SAMhlAG+1M+VJAtjUAIVMADnggEVkAKHCAAOOANwrAL3lAOyhAKhyAujQdvLeAYkZAJWwAGRgAGcGV0SPf+D3twBrBBCz+wbzvQb5rYjocACogQCsKgDcmgDXUiDtCADLrQC7twCYDgARRAAAhgA8sBC59wU69QDzTQdsSQD7kgQkNQBWRAB1FTOFUwAxTpAzbQA53AAABADNAACj8EB8o2koUwB5dABGBwkpDhB2DABeIoFfUmRZ4wF5FhCnNgAyIweudYenCgBqUQC6FwDMpwCZcQDuIgj/QoBhjgAAiAABGAAoeAQq1ACYxACbnQD8SQCr/AD+wACnJgOF0gB0l4Q1BABTuAhFQABGswaAXwDcIACm8ABEAgOWmALqswB98nBJEBhJ32aQIxC3MhjqfwAzbgA5mYOFDzBnD+AIqxIAzQoApqgg0AGA7FgJRr0ANWIIrKwTNVeVOtcA7lwA7qUA6toFdlADwhlIRwIDw8MAO46QOq4EvtgA1PSAVU9i1TAIjdRwQyQJMdsmQjJZOE+RiJgJgr4G85eYRcBAehoAxvogtzIJnHsHU/U570CAqUMJDtGQgsGghyEAipwQgLKTiFwwP0Y3VUUAVQwG/0wz9AEAq6IAwF6gMxMAPDmQZYMDLw9gFJsgf91VZa4KCOIQYhMGX+dkOpJwiv0ITSswu9sAXKoAxrwnVT2Aq0U5Us6gVj4AV/4AVuOgayWQZKMzFQwJD2Uwaf0nemN0sMOQPVyYSgoAZRMAT+MzADWWBESep9QWACSRJbAfAy/6AIUeoYjrAEISACiTkDVAAFHVQ1QJoqqpAJXHAJpRCPxGKFDLgzaKqmY7Cmc+OirZo099llWVcGhNAIPlkFQ5CTE8MDK2ADUfAKjaAGX9mffmoDRyQGRFAEMpAkahUAbAWlkyoVpmCpU9ZviVMFzgMKoTA9quAHIAABMgAJukAnVmh4yqGqjOCmavoHbeqmMeQFhuAFSUM/clAFt5o6N6QCsUkGUGCkbNYKXMY/MxACBktfiiql+AFSInUQplAXm3MLV2ChM8BvnKpsoCA9q8AKIBB8MNAJvYCU0BAOsEg7N0WagcCmf7CmcqP+pl4AMU3AA0nQBHNDBqCAq4SgBjwKMTxgA3Bws2QQCOwIBDZgsCGAAijAAkSgBNV0TQkhqVowFXOgb5m4A3KIOofQravgCv2EBlFxCqzwJtigDfIopGj6B4HgroHACHLQpoaAPxGTOE0gm4QgiohQBToLBS/bBf0JBy5KCOzoA/SFAkeLtCwQBEmyZJSkEHlQF1LhCjeZiUaoBoggCC9WCKWgCRNgBo7BB6OwC8rAdfLoTmzrru46BmjLqknjBUkws0GLq69QbVRQNLLZBLs6BNlSBVNjBT2AtL7LAi7AtE4kSf7FuHWRB7TAdIrJb4VKdVlwCLqgCRcQGZ+rU/D+eEJoOgaBsKauCqdkUK/1ijOgkAtwmUcvVD4xW3p0ADxRAASYerRLkAEZcLgRRLwP0bhaUK02UKinJzwW8wbQK72SMQracK4Tdyw8Q7ot6qJyUK9dVgafAAqxCwdRcIQvS69OYzQ8oAJWWqg2sAQukAFXcI3VcQb1Zm8QIamKMLGYuJMTmXocmgycML2S8QxXCA0a1x7tWQvIgAyyA13r6gVlkITQlSkV/JDcGzx1+nSh5KOEdAUukAj4oQQLIEmLGxGm8AWQ0AP7u2+lJ4eI8AqSKcCScQrnYIXUIAxww6JoGwitADe31go3VZVPyK2QY2CqI1zAMwR0QH+h9IH+U1CckxBk3ghbUHQAZzMRwcAKkXuhBna1r/AmmUDDNUyy2oAMuVCVbfsHhCAHhvAHMbS2awu7W3oIUmADWYAIrdAImlwGjdAIgWAIA2d1zyNRG8uD1KEEIBUAEgCpEjEOa4CJ+5Z6VysM9QgMG/CXUvEM2kANOCwMtcAIaXtT0iw3oMyilEAwuRAKoVBEaTC+ckzNN5VPrEctcNAIo7IKyYDLsKEFJzxJHjEIUubFX6nKbaIMwEADlgAbySMMbCIM0tyiN+WibhrL7vnGsaAMkDAIsXAMwgCUzQE30izN5UMHyQYqDJQMvgAbfPABUBQALvMRqmAFhXqbH6jKDo3+DL2ABJIgGXygDasskC1qCIbwogu8ttCVQuWpDZegCvdYCkRZtlXpYMJl0VGgbJfTC8DwGKjAByrz0QuQyB6RDGlQqM2rBuf8CpezC5xwBPy8xmRwzS4a0HLzou7phWhXjy/ACspQCshAlOGgxmgaCLOJt3J4CKai1L5CK55zAPPCFX/opzPgb1RXy6WwC5oAA9z0GL0Qzg7WtgtsCGlr0+8kDJYdJx6wBazQCw7NDNpQC+tJCSwqm4aAMbU8CaowCuahBR/wAH39AKC2F5NAtBc6dVQXBYJwKq4AA5bwl6uQOgHNrnJQzaBs1gMZ0bmgDcrQAAPgAZcgppg5MIb+cFMQcy1yuAZ9cAd7oAXxsgB9PQLYxBeQUGAVW7H9EwVTcNjAUAJfYBdS6gmlgAhBG7RuSgij3bY2nc21wIC58ArQoAsNoAAYAAbQIJ7Q0B7qKt9VkAXYLRc50Nos490W8ARa8R2qQJ3XqpPEk9DJgARmYBkgXheTeAd9sAZxoAbWPDdqet9yBE8nlAv/TQEUcAWqMLbNDM2fQDl4kN3bnQMmUCtlwzIT7su9AbnzvLw+MAXKgA3JwAZu4FZ5AOJSrgQifgYk3gd4YOLc4jgRLJqX45R2yQp8MgqOsCHX4eNNAuS28gA18AVEXiLleKmJqQIGlgXlus4wQBCmoAjAUT7lII4ZVO7eczHohG4X13EZ2hEiTrLotWIBbR4gJaIQl0C4mBp/SV4KSQkMOIAQ2pQHefAFthHqop4DuIEb2nHq2tEf/REirM7oJqADAFLhkc4QlI6pdH6kupAMu+0QlhQJdmAHX/AF2JEdqJ7qqq4BH6ADuBHseCHrs/4QkEu4iJlqFrkGk8AKrrABPEETkfDmz94RgEC4IWCkVpAG4eKlmiAB377uFeEKS4ACNvADQpQG5LILwMAE7J7vAhEQADs=" -#define ZEND_LOGO_DATA_URI "data:image/gif;base64,R0lGODlhcQBIANUAAA0NDgEDBgIFCS5EXhUdJwUPGgQKER0rOgABAgkZKiZpqxhDbQ0kOwobLQkZKSNgnSBXjh1PghpGchQ2Vx1NfAoaKiJYjQoYJgsaKQECAzdQaS0/UTE1OQUPGAkaKh5ViiFclRpJdQocLSBZjh5UhhpIcw8qQxc+YwwgMwcVIQkaKQgXIwcZJTM6PwIEBRkaGjEyMv9mAP///8zMzMfHx7+/v6urq5KSknNzc1VVVTw8PDc3NyYmJgcHBwMDAwAAACwAAAAAcQBIAAAG/8CZcEgsGo/IpHJ5/DGf0KiU+Ks6p9Kr0KrFer9GbReM7IrJ6O95Zt262durUy5uD8/rtL58h7vlf3+AcHlsdoR7iU12eIhzbXVVfpOTgGOKiWNrkpKUhZ99iJijl4d5kFSdXKmdb6OvsFOXsbS1oba4ubq7vL1DNjg6ODW+xVg3OTw/AisCOMbQSsA6AD8FDAsjIwwv0d5DNcnLIhMU2uclPzbf3jwC2Ofx585MwTfssD8n8vwjKDpLcggo8OMZPkw8GPSTN6HKCxg5hhHJ8WOCv4IHFeEwsDAeiQULJjBYUQXGM4oWtTU0mDGNjR/mOi48gcJKynMrW+oBcFNmP/8SJnri/JFDJ5kaL0T4XLqwYVGjWGy8MFCCqVWGRKFKsQGgAImrYIc+1bqEq9ewaEc0vEc2CdKzacOmY9vWxjoiMAx81Sajr9+/MhaE2Iu2hAAexPraJUbGxo3HkB/f/XKjCgBhwH5kOwcYsAoU5dKSMIBYSN8cOSZvxRGjtevXOnREZDwFhogSE1AYqKIwXl8VBlKoUNHXgAEUJwhfJVGgtGkZsek+Afa6uvUY0bFUjEdhgnJtIUwwmLDAb4cU3tM2pz2jb/YnN67Lr/4eSuWYPkmEGDyiL4MODITgm1+CkdBZgSh00xkMOkiHRHzWxSahDvNJyN4SG6HV1wSfJcf/GWAMdObfCQv8IOILDUoj34QTrhgbS0zAgEJYfqGgQnp8yXACA8N9NkFfHQRX4wl+6cADDH2h6KBdz7jIYosRShjFdmD5B6CAH/JIHkgh9JUCeuXJAOBpPDTYF4MO4mDCAU5KmMMNxNDAWpSx2QdTlTJwiNxeIhbYnwzDZeMlcTLAAAOc7qVIxAsVsrjkdRNCkeFVNd5ImIgqmCDgbyoICiihZd5gQ189KDoDDTcYcN1lE+JAgxE2QCrlEzLi+V+Af+4XpnHCafpnoL8SWugNOwD5gqg4oMbDCtahkAGD9RUBIX2xjbUElUyJ6BcDJoQJ2AldfuppoCJe0IEOB5hw/wIEKFRQnQgesJrDhUTI+iJ8d2arbXGdjhDub6BxOm6nJvzVwMEMSCDBAw+AwIAHr3kgQgdl5vAqEjXYq4NqSeAgAFjd2djjyL7qJ9JwDCQXnq/+mqBpCQXsWIEHKVPwQcMgOOyAaw4k0EAKGCmhsbVKVLbCBFUtte+GC+ylH5df6cffCFIbKAMJJ5A4GARcdz2BA2CH3YAIDABA7y8aO1g0NeOEttDSgLJMowwuh9D13VwDFTbYCZjQMEBIDO3FNACY0NFvwY3M72ZoLWCACRTgLfnXYTPwAQgKmFAUDjjQ1SbHtfXWz29gggSSSHKHRcIKJkAAguR4R/C1CJFD8P+AAiykABoCQrQJoxc4FHC4uPLod+DUfxI4mF8O/AhYgXj/JdjNEUSgwAMY1ECDxjpcDEZl330IrDzapvyViCn7FUD5yXXdWcqXg3D7CdPCNqHaWNSA7YDPIw+kkH1BTo3OA6QA9UUAIvhfCoZEAgj0ZUdhA03tRvAAEvhuDzpQCj8wJTcvgamAVgqYDIQTpgIkcIQfFFOAHCgDBjTPdFvj2gPaRDQy4CBf5JMBr4bTQeINinTe+U0BCiYDBzSgL2BbAAtT4IA+xbBrIODe2cDwghltEIVb8p8PPyWwPxlAAERsgAeQ6AAlklFEDtAUFKNIp9iADlXJQs2bbuA9Jdz/ED/i69eHwgUsTvkFPVb7QQUk0BcPNLGIZWRhEsPFqzTazXUzbKOphBCrNnaujkUwS/jgFqItkqszCKDdGRFpRlJa7VuDiaQliVBJ7t0LVl0JX/K0ZYAuCuyUfrEGBUaZREUmEgL/KiJoIqBKagljCPUz5pN+N4MaxLIj4RmZNINSN/BUE2s86gsADBABEJSgbit7ZDjzFgKRgC1lEJgPdiw2g2Ta70lvOkINeACXhTzNdPgUDAX24zR+asN4MjiSAS73AX5WjZxPhMA9Q/ABdbYGVY1aJuiGsBFZxqUjhhFGDlwgP4aN4HWwC2nXLOjQiLJIInbUy0Wt4pQa2IUH/ydQwARmKr8RiDSkJW3T/TCJMXpadKX/ZEBWKEqAFgDgBjCYgAJAetO75VSZjuKpEuYpgKQBlR8lYqZdhsCBhTG1qSR96pMkREcvUNWq/CBPXOixBA5QIGdN5dpTsTPWBkk1CmftR0N+YACkhUUEgJOGD0jwVa7l7LCvy2ld33TXKeQ1HiuxQQ5eUIUVoEBdS5kAAJ7gghM84G45Y9jtSgCCCHjAA2PzwGHqOqF4KuKxagkaJTmngxcIzycU+AH+iFADFCwVtCAgTwRQEIALQEAEIlBBB15QJtbKZrdpqAEMqhrbGiIThx0pgHWJgAMJ/NawDxhADzj3DBioSwQGAIfADpyLUloIpCbbHQJPlsIAGCxhBxa4HcM6at865qCcRFlsWXORA5MwIYMyWQADBBBfIdzgBRpAwVtvpzkjhCM1lHQMZKb4DY/xozsiEMAPeNDeJNDAMT/YwAkkwICJcpgsL9mMgglyGRxMlAmiAoCN2zIFeoZ4xK6NLo+nYIMX3XjISNZKEAAAOw==" +#define PHP_LOGO_DATA_URI "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHkAAABACAYAAAA+j9gsAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAD4BJREFUeNrsnXtwXFUdx8/dBGihmE21QCrQDY6oZZykon/gY5qizjgM2KQMfzFAOioOA5KEh+j4R9oZH7zT6MAMKrNphZFSQreKHRgZmspLHSCJ2Co6tBtJk7Zps7tJs5t95F5/33PvWU4293F29ybdlPzaM3df2XPv+Zzf4/zOuWc1tkjl+T0HQ3SQC6SBSlD6WKN4rusGm9F1ps/o5mPriOf8dd0YoNfi0nt4ntB1PT4zYwzQkf3kR9/sW4xtpS0CmE0SyPUFUJXFMIxZcM0jAZ4xrKMudQT7963HBF0n6EaUjkP0vI9K9OEHWqJLkNW1s8mC2WgVTwGAqWTafJzTWTKZmQuZ/k1MpAi2+eys6mpWfVaAPzcILu8EVKoCAaYFtPxrAXo8qyNwzZc7gSgzgN9Hx0Ecn3j8xr4lyHOhNrlpaJIgptM5DjCdzrJ0Jmce6bWFkOpqs0MErA4gXIBuAmY53gFmOPCcdaTXCbq+n16PPLXjewMfGcgEttECeouTpk5MplhyKsPBTiXNYyULtwIW7Cx1vlwuJyDLR9L0mQiVPb27fhA54yBbGttMpc1OWwF1cmKaH2FSF7vAjGezOZZJZ9j0dIZlMhnuRiToMO0c+N4X7oksasgEt9XS2KZCHzoem2Ixq5zpAuDTqTR14FMslZyepeEI4Ogj26n0vLj33uiigExgMWRpt+CGCsEePZqoePM738BPTaJzT7CpU0nu1yXpAXCC3VeRkCW4bfJYFZo6dmJyQTW2tvZc1nb719iyZWc5fmZ6Osu6H3uVzit52oBnMll2YizGxk8muFZLAshb/YKtzQdcaO3Y2CQ7eiy+YNGvLN+4+nJetm3bxhKJxJz316xZw1pbW9kLew+w1944XBEaPj6eYCeOx1gqNe07bK1MwIDbKcOFOR49GuePT5fcfOMX2drPXcQ0zf7y2tvbWVdXF/v1k2+yQ4dPVpQ5P0Um/NjoCX6UBMFZR6k+u7qMYVBYDIEqBW7eXAfPZX19zp2/oaGBHysNMGTFinPZik9fWggbI5Omb13zUDeB3lLsdwaK/YPeyAFU0i8Aw9/2Dwyx4SPjFQEYUlf3MTYw4Jx7CIVCbHR0oqIDNMD+FMG+ZE0dO/tsHlvAWnYS6H4qjfMC+Zld/wg92/tuv2WeeYT87j+H2aFDxysGLuSy+o/z49DQkONnmpqa2MjRyoYsZOXKGnb5Z+vZqlUrxUsAvI9At/oK+elnBpoNw+Dai9TekSMxDrgSh0KrSYshTprc2NhoRf1JtlikqirAVl98AddsSavDBDrsC+QdT7/TSoB344tzOZ39+70RbporVerqasyw1MEnC8iV6I9VTDi0uqbmfPFSq2W+gyUHXuEdb3WR5rab5jnD3i/BNMN8ChNaqsTiKa55KmBWX+Tuj0XQdQVF307nhTH0CPls+O0UPbaT5TQG/8qX68u6LpV67LQ6dNknaYgaYyPDx2TzvYGCsnhRkH8b/rsF2GDj1MCInkvxvRjOuCUlipWD/zrKx7ZOwBF0vfSSM2ShyaqAAOC1Nw+zt9/5YNbrN1zfwIdpfgnqebv/A6pnWAn4qlW1HPgHQ6OeoG3N9RO/+StMdDtmV2LxJPfBpQCGfwTgrVu38jFrKaW2tpZt2LCBdXR0sEgkwhv21u9cxQsyW3ZB1+DgoOM54btU6tu8eTPr6elhy5fr7IZNDey+e76e9/fCLcAllHpdKKinpaUlX8+111xB9VzNrYxqUAY/XVVVJYMOekLu2fFGM8VWYQRYiYkU9bD4vPlHFYnH4/zvkb1CgwACHgMoUpdyw3sFXcXUh4YHaNSHDqaxdL5jwVTXBpeXVY9oF3RcUQ+O09NT7Cayfld+4RJlP42gTIq8w66Qf/X4a6FTSSMMDcaE/NhYecMM+MdyG90OAhodWoAGkTUaSZByO5WdiA4GqwStrrM6k5vFKEXQserr63l7oR5V0NBojKctaSZtbneErOtGmFxwkGewjk0UzpCUlJSIRqMcjN8CkHLDqyRByq0PEGBBhDmdj7rQVujAaLfrrlk7xyW5gUaxpEtOmOQDr0e799NYmDVBi0+OT7FcbsaXxEQk8qprEBQMBm0vVKUBRcNjskFE8W71lSt79uzhda1d6w4ZGTUUp3NWAQ3TvW/fPvbVq+rZH/ceULOcF1/I06CY3QJohCCzNJnYdgEwwvpUKuNbUsLNpO3evZtfSGHp7+/nS2pw3LLFPVWLoA5yHQUtXvXFYjH+vU4F5yOibzsRUL38MTqC3XWh8GCWziMcDjt2BNEZUIfoUOpJkwvziT3S5ua8Jj/4yD5E0yERbPkhKv4RF4mhkN1wCMHN2rWfYZ2dnWz9+vXchNkJzBoaQ8Bxqg91wWo41YdO2dzczD+3bt06Rw0rBG4nOF8oi9M0Jsw9OgLqQ124BifLgeuHyVbN0NXUrODBmDWxgRR0pNrUYqMNgDOZGZbNzvgCuc4j0kX+GPJ2//CcMagQmKkbrm/knwVEp++SIXulM1+nhj9AY207QRDnpsnye24WA59DkuPlV/5j+z5eB2hE0W1tbTyQdNJmDpksRzFp2E9csFJAboRvDvz8gZdJgw2ek55KZphfAv+Inu8UdKnmkEUHQK93EjEZ4Rbkifq8JiactEpYAy9Nli2Gm6CjIZPn1qlKFWizleOG3BIwdKNZ+KRMxr9VHKvr1NKLXo2BhlAVFRPq1qlWW6MBr3NWyY2rTGXO5ySJlN9uDuiGsV7XTVPtl8CHYGizf/9+V5Om0hAwVV4ahuU8qia03HP26kyqFkMOTudDzjs/P/QKBUiBYa5ZNucfZJUkCG/0IhpCxYyqBF3lnLOII8q1GKqdStQ3rTh5MStwXX5O/nE1metGQzPHUH6JatA1OppQ8u1eUbpX44tO4GY5vM5Z9sduFgOfG1GwUOK6VFzaSAmrWCSfzGCuuT/O+bi6QwRdTtqXN2keJ4/ejgkJ5HedRARkbkGe6ARulgMWQ+Wc3cDAWohhoZdcue7ifJ7crfP6Me8dELd0Mv8U2begC2k9SHd3t+NnNm7cqKwRbiYUkykqvlZlmOYVLIq5bHRep46JzotOc9BhuFc0ZHGLph+CJIaXr1FZSIfxsdBiN1+LpALEK2By61Aqs0rwtV7DNBU3BMCYixYTLU6C8bM5hBwum0k1mesBpmPtlj+qXFenFsAgCVLon9DYeIxUnmh05HCdBIkCVRP6ussiepVZJZXIutCHwt2I0YGY2Kiz3AIyeG5aLNooVULQBbHy1/nAK2oEtEanheil+GO3aFg0FnwSilNC4q6OrXzywc0XCy1WMaFu/tgrCBLRuWpHuP+n1zqmRXFN0GAnwKgHeW1E1C/86UDJHFKptATZMPZTafbLXHtN3OPixKRC4ev4GwB2Gy6JxhQNEYul+KoKp79RMaGqKzy9ovzt27c7pidVZtYAGJMYOP7u6bdK1mLI1GQ+/ogSZBahwKuLO2jSZt0odw65xrUhAMNrZskLsGiIXz72F3bTjV+ixvtbWcMQr3NWCbog5VyXAIy63PLrqpJITIqHkcD9P7suSiYbG53wvTLKDbr8WBbjZqIF4F3PD3ItRn1eQd5CBF3lCM5RAIYfVp0/dgZ8SvbJ2/l8MmlvNw+8qJTjm+drWQwaAXO9KMuWncc1GBMXKkGeV/pU5ZxFIsTvzovOCu3HvDnOE7NTu3rLr+PE8fy6+IEX9947YM4n/+LbPT/88R8QqoYAuVSDrZLFKcYso2AcLBIeGDPu6h3M+yqvIE/4Y6w4LdUfi+jcr86L75KvC9+PcbVfd1hCi6U7Innwk1/+Q5rcoetsdyBg3s9aCmivBsNFifGfG9zCJUFiztmpEXAbqhMgr6SLWBPu9R1enRfm1ktrC6cVYWH+/Mqg43x6sYK1edaCex7vkRZHZkF+6P6NkXvvi/TpLNBUaqTtdcsoLtIrVTcem2EHDh7m2uq0ikMINBvafOmazzt+BkGMW9CF70DndPsOaJqb38Y1oXjdCYHOiqwbPofrKid6thMAlnxxPtMy6w4K0ubNhq73U5wd5PtVleCTd+50D2CEafLloqixyv0ufMcOGq64CVaMYN2119gfAdPpuscKOxWgCMDwxfm0pvzBhx9siRLoFt3ca7Ikf+x2yygaYzHdTSi7IT9y8fMJ2Lpdhg+ZCPA2+f05d1A88mBLHzQaoA1dL6ohVLJGi+1uQj8XQMyHIMgaGT6eDxuozMkD294LRaB7CPI27DLHQSskSFRvGa30O/zndF4fF0DMhwa//9//iZ2DcILqN7xBHn1oUweNn7eJ3WO9QHvdMlrMsphKEj8XQPgpuHVVMtGOgF0hC9CGTqbb2kHOzXx73aKiuiymEv2x22ICMYYeWSALBQ7RQ0fkoZIr4DnRtS3ohzf1dNzTG9d0PcwMLahZO8UyKTMm38wteratSVtkplq4oWj0PcfrEinPhYg14H+hvdIwCVs1bvb6O+UBMYFGl90d0LRGLRDgoHEUwYnXDniQStocTVUwfPLaKQGA/RoWOmkvtnsaG8unK+PWMKlH5e+Lznp03N27RdO0TkxmYNZKszYBlyfI3RpjsQkmMOo8ls4Wsx1EKcEVAEvayyNoeRzsO2RI+93PNRLesGYtNpBhL4l/prlgZz5ob0mbtZVFhWC301d0EuQgAHPgS7D9hssTHKyMbRfLptF213NBDRuoaqxNA2yh2VUBDnxJ1M1yRW6gOgt2x64gqXK7ht1yOWyW1+wl7bYXvhUygQXgit4KuVDuBGzSbA2bmmtayNzpRgJOGu7XosHFChZzvrGTiUKt5UMiVsmbmtsCb3+2lZmwm3hFNsA/CiYdKyfhYx3Aws8urp8nsJM72naGCG8zYwZMecjk/WHVVRbsMwU6tBVQsWJS2sNDlrgVTO0RE/vzKQtuN2+/85k5PxlUaL75D3BZwKss+JUqSFRAO/F7Eqlkmj+2gbrgYE8rZFluu+P3pOGsyWCG/Y9/GR8exC+vYfc5flxgzRdDGsDEz/8AJsxwQcBUKPCtmKOMFJO8OKMgF8r3b3sKkAm69TN+2OZCAm5ID/g9XPypwX29ufWgudq0urrKes/8nPkxgy1bdg6z/or/SFc2mzV/xs+6HwySTmdYJp2dpaWKEregYrVfn9/B0xkD2U6+e+sOaHqImTfLrycUOIZM1hJwC3oemPXbi/y5PnsrJ136bUa8pxu69BklmANWwDRkgR1wmwVaglyi3Nz6JLQ+ZG5NxQsgNdAhmIfJN7wxgoWg9fxzPQ+c/g9YAIXgeUKCyipJO4uR/wswAOIwB/5IgxvbAAAAAElFTkSuQmCC" +#define PHP_EGG_LOGO_DATA_URI "data:image/gif;base64,R0lGODlheQBAAOZ/AB0BAHB0r0xPkMmMdtjXu9CYh2sxAquv1pJsTmUCAKyQaaVnA6lwVYOGvJM1ANvbwYlPMJubzVYCAGgRAJhqLm9BCq99aLetkqpMAKJCAJdvYqtzHZZWAnNsmIUjAHdKNW8bALqST3ABAJpjEVYnA08xU5JLBG1FU8fKtIhcS4d0kYJFBLiQgkABAIQwAd3h0eDm2sXCpdXYxIiKwG05M7CtuH4UAVNGdNPWwJ5dAcB+ZOjv6NrdxqRMAN7ZuH1qeXZYYszQunp9toxRBJ2dz5yHaa6ANoVYHrWgebK54M28jdfbxpGTxpWWyY8tAJqFl6hHANzUr5J+UqOm0Z47AI9eG9LKolo1IEASAkNIjJSczVkUAYyPw1NNTqSdrYNgZ3hMGK9XAa5KAJNKGaGdv3k6BVgZE6BTGmVopNrezIJhNGgeFpJCKFogM9DTvpiQrm1afpiYxZxQClZZmKJSBaNGAWsnItLQscC8p7NaEI47BpdhQGwVFy0bH18LAJmZzCH5BAEAAH8ALAAAAAB5AEAAAAf/gH+Cg4SFhoeIiYIRRERTj48HkgeQU40Rf3FNm5yLEZ+YhnFeTYqmp6ipioyOU5OSSbGys0mTkERaTUxcM729XExMpaCYTTU+NaWqy8yoo3Gtk7SxlGRvT08qPz9f3UBAX0A/KuQNXOfnMw0NQu3t5n+YNQ9RXs33+IOfeFE1B7MHyGTjdoLGGjN+JChcyLChHz981tixQ+MEEDhwOgRoFyAAmo1C3rh5gEdZvpOnHB2Y56ZGkilvfpyws6WFzRYMH+rcOaGnz58+/UwQ2lPiiYxokqLpgIKHlSeXUEolpPLfgRgv8KQw6CdBAoU3cUp4OHanWbNA06aleOIGGjw8/x4gQSOkCZFQU+9FcPWv1hsvBF4g6fpwKNiwDRMvPMu4sdk1F+IqgZNFABoujPDmTemK2pOZWyKnKVK4Z8KwYhXnHLvYsWudSNLQ+5KltoA5Qv7c3axIZSwyKuwstBMkLgKipv2gVpjw9Vm1yNWajv3gAYUtbW7UzoLbLm9DRGAleUIjYQKyCNLwwKEG6OmbzBlLTwtiPlAQ+CdQ5xGiPog1JWwngBCMfKdbZweoUF5ZO8XGwx0QIEcWYqVF9xMILtyHX349bejhh/ghERcPSHjgIYDacdfAJ5t1Np5w551lRwxpLGEFGNG9J5aFaq2wAYge+gQkkBfI9oASZXw4VP+AtaHhHUrhxfIGDa2ZJcEHbvBgI44/6cicWkFWYcSQHE5ApodlxLBEdVasoGRXZjA54G74IPiFYlYisISWN+YoAXxjgbnhBBT0ZyaQQx16JghgBFHdA3dU8eZXEmTX5JPMdPbEGsw15NWnEmjAQ1wQJpCcjjgVxhNQRoRggIb1NafokBMggMMDa95BwZtfgsDkHDMQscxektzZqQSfeoWsskUYecceySrbAgA2MRhtshO0WoYEIng1galDyXpmTwrI8AAPBBBAQYemLXRoAm3Y1oCwqBBLBg2pqdYQC6M+QAAD0f5J4bXRghBCCCssS3CgIPbUrVcX4IruvwG7G6v/QiUIkIUQ9JriSBxt5JvQQoAudMGe/iqQ2HJdUaqYAQeboNBXyi503qz1PfzVGjFInC4CoDaUn8tMzmvKXm/wIYIIEzDdU9AuM3dyXAQM1tByyJJc7UJlGLEBByNrXa1QSlJqEwIEnLsEAVEgIHa1Zo58U8Ybd3wIEW+wYYMHfPftgQ2ABy444HigTIASeizddIw6PV1z1BKUscACOYBwNXxEefjVTWZckLaWBDx7GLXUtlDf6DYFKAAXdg8ShxZxsOGEA7TX7sTtuOeOux6F93uHER444ffwfA8uOAhl5LBB5QnYIILzDzO9oYlDK5uCGwTsuQQOpb5NFKo2aTdH/xOa/bGJFinMXvv66jvQvu28S+wvEnrYjrv77Ot++wqFhrCBCSAI3u36pjsXuGCAfkNC2s4lAxzEYAzG6xDfQGCDpz0kAXzQDhpaxwQtaOB96wuhCGmnh5OtyV9WoID6bjfCEbqgAmBQgxQUoIYKkAALIGwh+xhwh8+thwB4GIP+cHdA3fmNBrUxmiCCMYO/8c2AUDQg3+7nAD1Y8YoXkIHhohAC/OVOh7SjggGwcAUjrIAEN7yhC6gARhGeQQnpekCNcIAD+rURjOIjn/m4oIUTLG1pftjCFu4zqydKEQky0GJ1CJDCvf3NkQSkogNWYAADgEEKBiiDCVZgAgNgqP+NbGSjHhT4uTm6QQE5vGPtylAbjkVgFypQWAKmBYDSoQZrCtFAIlHmgygowQM6+9QfB5dJTnLABENYAAdykIMVlMGTASTeFIXnBAX0sDppSIMM3BAECghQdyS84gipQIUTZGGDfwDGCa5Wy1rS0p3tbOdNUoADLcall1ycwJ/2abMELC0BWzCACUzAzMkpcwQcoMMxDbCFlkXrYR6wQA8/94LtuSEGegPch55oABd0NIDRdEEVkbi6JsyAC21gpzzjyVKWXgEFu6wOPkNwy5IF1Jg5MKgyc8CBZXLgjDWpaQs+cIEoxPEBL3hBA4OABH1m7ZZYiKpUWyBVQYKABNr/CQAvhOBQf4pAJ6wRGE5ustIWZNGe94xCFJCAr5pKIKBlOMIQlpnTyXFgBENg5k9dQIKatNMMNEAAEqxg1AWmAQZL2GYQ9gCod7b0se0MEBp6oQLBCXB4FOxJBSvYpYQgwA27vCc+rRCCD5hBrG8lQRlWMIS5Us6gd6XrT58pyCsUAQlKIGwvCeCD6vAABtrEgRsusIZbQva4tezDbRowgy+Q87nQfa77vjhCJ4whBvVcAsoe4IPu9tIKSkACEsZw1UyWYa50hS1e9brJZ5YBCdxVa3cXeC4YKFW4QUBATZF7XOUKYB3OzYCAB0xgAUe3wASmAhLckN1+ydS7vVXC/wIqUIFiznUIIzBCMimHUMod05mrDQF3e/soXB0Wsfi9QBlq9jaBwROyfagMgKmA4BrbuMBUoAAKGIzWuDy4u0agwAoqvNqecqAKajDA5HiazGNucgWsNcKtSoyrF+xgB4nFQRBQsAf9+S2a1PMQ4CZQwYfE678NCPCN12zjBdezxz5GqhKMgAAwEBkMHEjmCI4wgg0sYAQddjKUh3CEDVghLtrdEwyuHFxu0i/BNM5AdKVbO3LSDnckXccPqFCHTnu6DgMGNZsLfIYY8BjOcYEBEqRAATBU0gAryPMCNkBrP+N1BMoc6KCrQIEi7SkNL1g0lhvIzQuMIdI2FnUGQP/d6Rt/gDszEEIH9NCDalv72tX+tLa3DWoG7PjN2h0VD9QjBSkcwYYGqEAVWjvrWucA0Lh28mqHUIUqKGAJSRU2YokdBDzswQFrbnaoPW1jc86BCe2ggR4GynCGy8EEcpADtieO7TooIAinTvQSYBCDctuQBOmWKwfaTWtAVyGnFAYxvdWAABRc+cr7xq+/HaDsAn9awNyucVb/IIQGlEBRJuooFMtQBhdcUQ9QbnjDHy4HJGCcx4lWtRTUcIU+AMCS6+ZArUsO6MlVGOQkgKEMLwDzRgeh3/+GArc9rfZtt13tOK8DFNhQmxlEINpw8OofFee0n1Rwo5W8KsgreXH/jGd3CaMpQpLRmO5193kDXtvACCjA668N4eNhl2ERkppI/AbhAhAAOIHrQPHSX5vtUDD4JxAuhDbofe+wj33sN1c6P7TcDbiXQRpQUO4roLECZahAax9vBK8hNAdVQOgQKPn7GEoBBdrk5pYVYIdDmcgDRh9oxOVAh+7TYfveD3/45aAdjgmiHR1owetlz/7Zw6cFKbjA2d2QBjyUGwxXgOERKECBIVCA1sW3AYVCAUbQZ3jlTBQGBmBAVGlwdp+HAEFFISBQSURXBkd3gWNgAhmYgQxnTgLABJjwSu1QAgDALe13grH3fmZQBDEQBDJwAWpQQxUGQzBUBZLHa17D/2uUdwRHAAaU9GowpIB4cFFFYAaP9X5YECiD8zyD4zc2YAcaY36L0AAdYXUmmCwoyH4lcyVFgAJFgEaMl3IrMAL1FgL8t3WS11o/CIZYgEZqUAQf4Fjy9H7IkoWyJz6agQntgAbU4k8EQzB/tH4SQC0MgRMfAAFt2IbpBgaERnlqQEMh0CqRRwE5sHzPBIYkcAWl8ydHmC92KHt0wzqFEAFN0A5zgBN/mIrC9EeDaEtjFTljBHL6t39HQGeCFV5IEIn8VwVQdolYAAZGYAC21IoshRjr94nxkgVKNIpcsBFwsCzBpIoPNUvFeBMhcASKGENqoIBgcARqQAEIgAD8h/8AVcCDdvZ1NwQGFIAF7mQTR0g66vdPWPh6WNgGGhMArUMIEdCMQgAHLuCExrNZ7ceJLTVUaOR7QdiNPMhy4RiOu1iOllhJNxRVAIAFQdWJ7uRVgBiNCcAkAcAiiXB3G6ECxyZpk8ZG04VAxIMfVlUfE7AFUZV5e7AHDMAAFnCTLJCTOWkBNbkHEPCTdiaR7EhVQ+mO03JLsiSNXkE3aACSq9CMGwEBUDCVVAkFGHCVVZmVU3lzBQYCZJQCNqkDOjAAZEmWBXCWaHmWAyCWOsCTDIAAKQAGE7kYp0IWwqSUXuEHKYKP5ROSCNcRKQAFYmCVV1mYhjmVhpmYislXYGn/AWwplmWZlgVQlo8pljX5llcQVSAgSbkDkIHzPLJnKXPCDKQoBCMplYqZmqqpmCZwBY3pmGUZmWpplmSpAwzAlpe5B5qIBVQgBoO5lYSZlaJ2kuSkB+YEbflYLxFAhR3xBWcgBqsZnalpAGAZjrc5AJKZnWt5mbfJkzO5m78JnNKplWJQBx+QIk6SnKpQmh0RACmAAdApnfK5AofIcimQAjSJnZJpmxqwBw2JADTplhBgdSQQnlQpn4Q5mBCQIv9FJyeBCdHWER2QAnIQn/KZmnnwAR9wnxrQoRoKlpFpARqQAh9AAynQoXAJljWpiR/AABmglYIZnb6JAQtqGwGA/ylTgQnMCZjPaaEXepUZ+gEacJMpEA5AwKFrWQA8eZ9F2qE3qQE2iYgAcJts8KJZuZq+CQU12iRM4KC8QYo7GgA/sAcx+qMYEAZlkAIsYAE0IA5X0AVF0KFoKaL3+QNv2gU0wAAswAA0AAEf0Ad7oANsQAVZ6aNX6ZtiMAZtYRuX4aUG8glNEKYTegY9YKiqGQYGIKQIoKFf0AU/0KEpYAGTeZ/hqAKe+gUfgAAaYKIWgIhUSqhVGZ+IigFjsKWV0ah9aSCekE6m2Z4d8AUQQAfwGZ1jQKIMsAcc2qEasKEDwABCKqKqOqIpgACOaZt+OpmDGp6I6puKmiK10R2Oqv+rh7B67NCeAfCrM3kGYbCu7LquNokANnmT8moBV8AAa+ma88qTN1kAlgkBGjCZepAB21oHtbqo2zEHaLAi4SquIUmuHfERH9EB3CCOW2cEPXmbY0mWzmqvOnCiZKmTFoAAYymWezAGgcoAhFoHbPABBnuwAWB3jcCw+MAiTBChSqEUErsNnzqvbbmWPmmZNJmxssmvx/oB4AAEbeGt30oXDaAb6imzpEmz5XqzVNsBHUAOKoAN3XCZRWoB2PC124ARAqAx2yEglvGydhEVUPsdoPAHuxChHoEGczC3dFu3c3sbY0u2Zbu3t/ERQnBSaeuUayuzoLAbTcALU6sUdnsSt2Nrt0mxETPABE57Cbmqq4EAADs=" +#define ZEND_LOGO_DATA_URI "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAPoAAAAvCAYAAADKH9ehAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAEWJJREFUeNrsXQl0VNUZvjNJSAgEAxHCGsNitSBFxB1l0boUW1pp3VAUrKLWKgUPUlEB13K0Yq1alaXWuh5EadWK1F0s1gJaoaCgQDRKBBJDVhKSzPR+zPfg5vLevCUzmZnwvnP+k8ybN3fevfff73/vBAJTHxc+khL5kr6T1ODk5nAgTRTWloghFVtEg/zfh2PkSvq9pJGSKiX9SdKittbJoD/PSYkrJD0vKeB4IsNNotfuUtHk/CM+IvijpF9KGiDpGEkLJZ3lC7qPeKKTpD9IWiDpUOfWPCi61ZeLvD2VIhTwp9QlTjK5NsIXdB/xxHmSpvD/OucWPSAyQw2+LfeG1SbXVra1Tqb785xUaNdMel0g7Iu5V1zPv6dJqpD0kKR/+ILuI55o8oeg1bFT0kWSOkraQxK+oPvw0TZR3ZY758foyQXf//ZxUFh0Q/GEfNf9gHkaJ6m7pHJJSyTt9tnXhxtBR2EGlnHCMbZMaHuHzX19JZ0u6VRJh0k6hM+BpMjnklZIelPSNhff3V5StkNlEWBMFm+3LcC+BW3GuZP2GvfmiEiCCMUzxZIKRGSt9zeML/fdGAW9JB3O8c6SlMZ+b5f0qaQiF7EpnieXY1auvZfG7zhSUk8RSS428F7M5xfsh1eAV/vxOzoq16sklZBqbdpo5H2qDPRQXoP3Ki0+20FSFyrZUgt+Rt/7KH2vZb8/t/iMG2Sy/0dI6sbvgHGoV8a3xErQb5Q0iTfHCplkzlkW7w+VNF3ST7QJUzFK0pVkDFiw+yV95uC7r5Z0k3CW2ApwIkrJ9B9IelfSh2SIlqC/pDFUZAVk0rQoMhk2GYswx+AtWvMKPtcyEckW37pPwsIHNAuBniDpYhEpBMmJwvibJL0gIlVh39r0C8UlczkXQ/mM6OtEzuf3RfPVAxUY47f5PStcGKPxpOMldbbxiBptPMavJX1PuQ/P/olyz12S7rD4PLyqBTQ8gyXVSOot6VK+dxR53wyl7POjkv7pkpcwpleJSCHP4eQjM0BB/ZuG4Hl9EO8mQx4ZQ0FfL+k+k+t4wNlULpkO24IGnSzpQklzKPDRAMvZ1eXz9uXfH/Pvx5Ie44C5zYQXUgDPj6LEnMCQ3AFkjjupjGF9/kJmxPw1oiquz+6dalXcCRSmYxwK0kDSRI71azb3Y+6GiMi6P/5ey3F3YpExjxdQoG61uX8gBetkh2OWFkUIVGUT1pS9yosZNu1nkl8uZH+mikhxkx1wz7mkB0WkXsKJFw1ZuSWKotY9wjNJS6mUy41JK5P0c2qCnBgIeQWZvEK7Dnf6WUljTT5TS7d0KwezkJShdWIeGeuKKJo7FktUQylcl0i6RtL/HH4OjP+wB0UTLTGHfubRDWyi1g7SaoZQ495z9w7RpaHKqHEfLeklEyWzk+7dl3TTu1KQCpV7+pBB4IWstFFAgvOpJnTL6DoW0xPbw3k/nIYkW+kbmHeXhUEABklazrBDBdzTDfyuBo5DPq1eoUk7ZbSk70l6n3MZjUdCDpQvMF/rezn7/hX7Xs8wsj/7rsrWdQxnZtrwwENUosJkDDZxTjOUkEH1ds6lzJyDZzGScRsonGNcMCIG+WgRKTRQ8Su2p7uRi/mlKjZKekREChS2KIOcTvfqp3RZDlM+cxnfv8Thc75Pt8kqo92VzNTbxBqcQlceivAdByHDIxbvFTMOLovyHAGGK3qc/jJDoDc4hpjABzBm4UAglBFqEAOqt8mB29ss4uJnNCHfSK/tVZMYEfMykt7Bcco1eDLDHCT8gmzzRdLHZL6wRSgzg6GIgVl8Xj2uhPA+oQn53yTdK2mVMC8NzuJ8zaSyM/ApxyzWCFJRvUQ3eQ29BTNFcRgt+FTl2g30zDZZtD/ZRMifE5ES6Y9MxqAHQ7XZikI9nd97j5p1f83GZTPr6Crt2sOcOB1zTYT8HrqjVRZx4wbSAt47SXn/YsZV9zp4zuvJgNGQRaszmoN1rBY6IH4dHiVHcA5dZd2zeIbPv8ZBkghYTQFTx/h1WvSz6c3kM5ewGG8Prvxc5DZWS2u+dypnM5Y3sIJMXmbxfXW0misZN56oxITnWsyl2fg+6+C+zWTefMWr68RwaYF271htHBZqCsKqL28wB/ACjYShrE9nUjfWmEU33A7woqbR4k5UlNk4yoYOzOHvtGs30KO1QgnlZC2VohGOIGn7WEvW0ZdoMeCHfBgdo8X++m3V+s2wEHKzJMblJom92+ne2SHDwT1gknUispPpJLrrVZqwLxTmy5F5jOdVS72F/b6UwlbrcEytrD00+a8l/ZUM82jEZd8peu8uNYS8JxNWqis5IYqQCy1rPUULh8Y7fOYal3zzmPb6aJN7zlf+32bBV9ESclNE85WUX4j4oNbl/fM1b2eoxX3jyXNqiDTP4Xe8Rm9ItfSjvAr6DM0d+o5MXW/CuHO0a7eZTLYT3KF9LktYZ/WdCI+IkoV+lFZ6l3J9OF14HdM0F3MrhXxFjJmqhh5FBera24XqxaCqL0UosK97Z2ku+yJaEqf4D62ByoROcjZuN78Xaa9zTBSzKvxvC+vlrmgWVPU2h4j4FCO5lZ+vNBnpYHHfOOX/PfR83eApTaGM8CLop5l88WSLWAOu4AiNme5owcBO1xhlLGO/eGAFkyYqrtFe5zKzqU7KBE5o/BAIiv7VJSK7qV4GhEF1XtSk0YseWl6lWYI+cXj6pigJLkH3Vk0qfebxe4q0JGOGSDxCWn/Nchk9qJgMfGKS87LDes1IHeVW0LszgaC6sPMYE5lBt4CzRcuy4lVMLKlWfWwcJ+YpxtcGjtOYfzRjTgNIlv0rnpyCveeHNFSJ/jUlonH/3nNYqyOU28qYhHOLbzVPqFc81JQDKxnQ5twLdmjfmQzlxU6eoZ/mma3y8D3VonlhUr6bElhMwJ81RseSxW+jfOYULdYGAw5s4WBtpeU0ijKwxnp/HCfn70piCNlMFEUU8/WpmnZe1Bq80r96m5yMkIwx9nnNHTWFs114q0ArM1HsiUY7j5/rKFIThdrrzR7agHyoy9vd3Ag64uEfKa+xjIKlLqtTUBB7FWgJrQ9joFl1d2cQ2wzHaeDXa6/ztO9Wx+OT+FrzSAKuV12ptOZp+ljnaVawk8uxDpnMZXYCGB3PXqe5sl7QQ5ubhhQR9B4mQpvjIR+gJgrbOxV0rK/rVUyXmyRWdI2a2YLEhVP3BwmN9sJ9BtQpKkxiSDOrUeUhaeQaPevKzKQ3oIVTSGatcynoRl29sIkh440a8pURNoz00Ab4Ts1obxCps1FKl8k5IpKbcmsgu6nz6ETQC+iSqoKKOPmVJBmYnDjHX4EozB9s7TgwykkyYS13URAHpmstYIloOP/HEi6Wx5a4+DwSpH2V18tTyHUPm3iQeS1s09ai4/0ntVgNRQmzHTRulGwaQNnei3FgHqPcMBEJlXrNioAaE8AcupKBd7ElBu1uTxCzg+dmKB4TahiQNX/OxssAb00Uzdeci4S3FYhEQdfkWCrc1cI2K+2EDhsP1OUxZGUnOWTmcgphV0UgZ4jUR1hLlBiuJfqJpb61CXimOrq8RqiEeu6TU3iMwdzYgWhUnWHDDKr0ptLar6USqmOfYYiGMMTUN/KgziGVTo+pNJHBBfF0zVAQc6N2DUL+tcO2Yc1Rk2ss+yBmOko43yCSCljJXAWA7PD4eAt6MBy2yiNACRvVVN05t40pPLYPsT+zlRDpOLG/Jt8OSGKhmnBpivV7q/Y6JkucVgkyWKb52rVZwl0tvNDi+AzRvKjfK1Dnjvpd1FhPEc1LBVsbqENXN35cFaPY2BIVGdlWYZKqgPPj/RythNtpcNycpoOxwAae0bGwhAkAQg01cfiDWDRqZtHhCqFQ5FAtOXKXh/Yh6Ci2N5YMUDW2SHg/N3scn02N++cnMIZCBdwS9gtApRxqDc6OlzWtSrdc8cJGlzP5fzZDri1tQNixISWL/5fSQvcVzfe/wzXfSG8Kuw03pHB/t5KMik+EYJ1EC1d0zCw6fofqRI2ZJwpvyxN4uPs0q/6UR2szyESobxatf3aa7jvfrT0DGPNpYV3H3CI0BYLGllQdy7TX14rUP/zzDHpuRp0EPLnJvH68Qij/RXnyIyku5Ea+5S3NO7s01q77eMY1qqY8T7Qs+4qtq+o2UWhjZO6HuWhjJBlZXWbAHvbFSTAxqMW+RbuG3VfviAP36tshujINh6Tr3kE0BNMl5x8Qq6+mVTdwrMlzpRrGaGPzVpw9NDNFngjoFZZzRCS/FRPXHRZT31X2MgfYTQYX1WE1moaaQJfKEFTs/camkXnUwt9YtNWPiuc67VmRlb0yiRgS/cAe7is0QXuTAm9kikM2DNc5OkeGRaMU8tq0TJHbUCOtezMeRfITiSv1PLLbGE5gb/NOB/1AuR1KlLETDltidyR4XIPasyEnc6eIbRa9kfNifFeXJOAnVJBiKfFCvobcLKccLHWojHJpIPH3iXQlpoNLrdcH44sucvmQOHHjZ9rDrGdbixVmbk/XGy4mtiKuoQDjmQpFJLs6wuSZvqKmL0ky6zOZLry+420UKUaue5ooyeqy9+iopgM989cp1Dcp16bSU1tOJbyFyjedTID5wOk6OAUFFXUDKFRLkmBM3xH7fzIJwPLsxexDMWP2b8g38DqN45ywCuH0VNuv+XmjwOYCjtUakbg6AkGlNoQGBMB5A9g8hh2g7zFE2U4F35FxfHfmwwbxcz3Yl32C/oAwPwDAS6UXdpOhXPZ27Trc9R/SLTla0zzGoXl2QAexnLVZJB/CZMpV7HthfL4lJIrb54u+tdv3/rCiSbw+k88yM9ZxXgKwlHmZycq13iSr0KeMHmUZw6r1VICrLT4D5fy4wq/5DAvfjaWC9oAd9KxwTNUJynUjL+EqpwSTME1zOWMBuIxmZ7p9RCsNq+NmdxW09I1MdNkJeYZNHsIt0qKEO2Z4kvmHadS+Xqv2cqzc93rpuhdl54tg2DISuJljBW3uZjMHrAPqHOYK6zPIM23G2+14Rts4cyLbdxo3Y667UskOo/W/m/PwRhQBwZFkT2vXzDbTtLMZCyfP1155bbfDrpjKZoYH41bO+d97jmEgMPVxFMF0iHESIkiNtDhKuwV058cw0dBZNP+lFsSU/6VWf0E4P/x+IF2eJnokr4uW/2jAKPYjjRb7Cxef70c3qsCl0im1Gj/Uu2eF6sWo0rUiTQq7zS+pYjywnXYwcyOZfI4mKgHj9N2ttHqbRfSlQXhjw5XXy4S7ZbzOovkxVRsphHp8ia3HlyleZS1zHcvoVrdjuNFdEe7edGHzSbpSria/WZ3+cxYV5DCx/4w7FUfyfTW0WO+i7x2YrzKUXZFw/sut+OxJDGkHUxEZPwgCquQcIgxZR9oXekDQk8FF60bqwocupaIoEz6EmaC3C+0Ro6Wgp4eb2tpPJqN+4xXFXQ3TfUfCc5PDNnLZDpLIV1NADKyjZa87mHgmWX57bYdIfIY3pdCGf43xQUXI62kBn3fZxi4SPC8crIjDQ4yzFAaz/XcPJn7xf03VRzIB5Z7qCbBzPQi5jga2E9bCD+ELug8ficEZCk/Cmj8Ro3aLtLxDR1/QffhIHNRTUZCf+S5G7SJBp2b7G31B9+EjcVAFEInZQ2LU7jiN1zf4gu7DR+KwTvkfO9bGx6BNnEQ8XXmN5cT3fEH34SNxwN4A9dgknIEwyWNbeRTwV7WYHBVwFQfbwKb7vOUjiYAiKVT1PczXqCLD/n5UbuLcNxTKoCgExSFNmsFCHI6iJBQFnUbqqbWPHyFceDAOrC/oPpIN+FVaVLrNUa6dLPbvoEQdO4pd1OUylBVkCutsOkqosbNvwcE6qL6g+0hG3MY4ejots1pT3kE4P9QDdfuLKeDfHswD6gu6j2TF2yQcLoqEGurre9EdP1QTfmxJRdn0NlrvD+jmY69Egz+UQvxfgAEALJ4EcRDa/toAAAAASUVORK5CYII=" BEGIN_EXTERN_C() PHP_FUNCTION(phpversion); @@ -84,3 +85,4 @@ void register_phpinfo_constants(INIT_FUNC_ARGS); END_EXTERN_C() #endif /* INFO_H */ + diff --git a/ext/standard/password.c b/ext/standard/password.c index ca852038a6..9c5280a4cb 100644 --- a/ext/standard/password.c +++ b/ext/standard/password.c @@ -183,7 +183,7 @@ PHP_FUNCTION(password_get_info) return; } - if (hash_len < 0 || (size_t) hash_len < 0) { + if (hash_len < 0) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Supplied password hash too long to safely identify"); RETURN_FALSE; } diff --git a/ext/standard/php_array.h b/ext/standard/php_array.h index 1cf2779071..ef43cddfcc 100644 --- a/ext/standard/php_array.h +++ b/ext/standard/php_array.h @@ -117,6 +117,9 @@ PHPAPI int php_multisort_compare(const void *a, const void *b TSRMLS_DC); #define PHP_SORT_NATURAL 6 #define PHP_SORT_FLAG_CASE 8 +#define ARRAY_FILTER_USE_BOTH 1 +#define ARRAY_FILTER_USE_KEY 2 + ZEND_BEGIN_MODULE_GLOBALS(array) int *multisort_flags[2]; int (*compare_func)(zval *result, zval *op1, zval *op2 TSRMLS_DC); diff --git a/ext/standard/php_fopen_wrapper.c b/ext/standard/php_fopen_wrapper.c index f8d7bda482..0adb1e0529 100644 --- a/ext/standard/php_fopen_wrapper.c +++ b/ext/standard/php_fopen_wrapper.c @@ -63,6 +63,12 @@ php_stream_ops php_stream_output_ops = { NULL /* set_option */ }; +typedef struct php_stream_input { /* {{{ */ + php_stream **body_ptr; + off_t position; +} php_stream_input_t; +/* }}} */ + static size_t php_stream_input_write(php_stream *stream, const char *buf, size_t count TSRMLS_DC) /* {{{ */ { return -1; @@ -71,42 +77,36 @@ static size_t php_stream_input_write(php_stream *stream, const char *buf, size_t static size_t php_stream_input_read(php_stream *stream, char *buf, size_t count TSRMLS_DC) /* {{{ */ { - off_t *position = (off_t*)stream->abstract; - size_t read_bytes = 0; - - if (!stream->eof) { - if (SG(request_info).raw_post_data) { /* data has already been read by a post handler */ - read_bytes = SG(request_info).raw_post_data_length - *position; - if (read_bytes <= count) { - stream->eof = 1; - } else { - read_bytes = count; - } - if (read_bytes) { - memcpy(buf, SG(request_info).raw_post_data + *position, read_bytes); - } - } else if (sapi_module.read_post) { - read_bytes = sapi_module.read_post(buf, count TSRMLS_CC); - if (read_bytes <= 0) { - stream->eof = 1; - read_bytes = 0; - } - /* Increment SG(read_post_bytes) only when something was actually read. */ - SG(read_post_bytes) += read_bytes; - } else { - stream->eof = 1; + php_stream_input_t *input = stream->abstract; + size_t read; + + if (!SG(post_read) && SG(read_post_bytes) < input->position + count) { + /* read requested data from SAPI */ + int read_bytes = sapi_read_post_block(buf, count TSRMLS_CC); + + if (read_bytes > 0) { + php_stream_seek(*input->body_ptr, 0, SEEK_END); + php_stream_write(*input->body_ptr, buf, read_bytes); } } - *position += read_bytes; + php_stream_seek(*input->body_ptr, input->position, SEEK_SET); + read = php_stream_read(*input->body_ptr, buf, count); + + if (!read || read == (size_t) -1) { + stream->eof = 1; + } else { + input->position += read; + } - return read_bytes; + return read; } /* }}} */ static int php_stream_input_close(php_stream *stream, int close_handle TSRMLS_DC) /* {{{ */ { efree(stream->abstract); + stream->abstract = NULL; return 0; } @@ -118,13 +118,27 @@ static int php_stream_input_flush(php_stream *stream TSRMLS_DC) /* {{{ */ } /* }}} */ +static int php_stream_input_seek(php_stream *stream, off_t offset, int whence, off_t *newoffset TSRMLS_DC) /* {{{ */ +{ + php_stream_input_t *input = stream->abstract; + + if (*input->body_ptr) { + int sought = php_stream_seek(*input->body_ptr, offset, whence); + *newoffset = (*input->body_ptr)->position; + return sought; + } + + return -1; +} +/* }}} */ + php_stream_ops php_stream_input_ops = { php_stream_input_write, php_stream_input_read, php_stream_input_close, php_stream_input_flush, "Input", - NULL, /* seek */ + php_stream_input_seek, NULL, /* cast */ NULL, /* stat */ NULL /* set_option */ @@ -157,7 +171,8 @@ static void php_stream_apply_filter_list(php_stream *stream, char *filterlist, i } /* }}} */ -php_stream * php_stream_url_wrap_php(php_stream_wrapper *wrapper, char *path, char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC) /* {{{ */ +php_stream * php_stream_url_wrap_php(php_stream_wrapper *wrapper, const char *path, const char *mode, int options, + char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC) /* {{{ */ { int fd = -1; int mode_rw = 0; @@ -203,13 +218,23 @@ php_stream * php_stream_url_wrap_php(php_stream_wrapper *wrapper, char *path, ch } if (!strcasecmp(path, "input")) { + php_stream_input_t *input; + if ((options & STREAM_OPEN_FOR_INCLUDE) && !PG(allow_url_include) ) { if (options & REPORT_ERRORS) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "URL file-access is disabled in the server configuration"); } return NULL; } - return php_stream_alloc(&php_stream_input_ops, ecalloc(1, sizeof(off_t)), 0, "rb"); + + input = ecalloc(1, sizeof(*input)); + if (*(input->body_ptr = &SG(request_info).request_body)) { + php_stream_rewind(*input->body_ptr); + } else { + *input->body_ptr = php_stream_temp_create(TEMP_STREAM_DEFAULT, SAPI_POST_BLOCK_SIZE); + } + + return php_stream_alloc(&php_stream_input_ops, input, 0, "rb"); } if (!strcasecmp(path, "stdin")) { @@ -258,8 +283,8 @@ php_stream * php_stream_url_wrap_php(php_stream_wrapper *wrapper, char *path, ch fd = dup(STDERR_FILENO); } } else if (!strncasecmp(path, "fd/", 3)) { - char *start, - *end; + const char *start; + char *end; long fildes_ori; int dtablesize; diff --git a/ext/standard/php_fopen_wrappers.h b/ext/standard/php_fopen_wrappers.h index 5f78256bcb..366a1295b3 100644 --- a/ext/standard/php_fopen_wrappers.h +++ b/ext/standard/php_fopen_wrappers.h @@ -23,8 +23,8 @@ #ifndef PHP_FOPEN_WRAPPERS_H #define PHP_FOPEN_WRAPPERS_H -php_stream *php_stream_url_wrap_http(php_stream_wrapper *wrapper, char *path, char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC); -php_stream *php_stream_url_wrap_ftp(php_stream_wrapper *wrapper, char *path, char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC); +php_stream *php_stream_url_wrap_http(php_stream_wrapper *wrapper, const char *path, const char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC); +php_stream *php_stream_url_wrap_ftp(php_stream_wrapper *wrapper, const char *path, const char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC); extern PHPAPI php_stream_wrapper php_stream_http_wrapper; extern PHPAPI php_stream_wrapper php_stream_ftp_wrapper; extern php_stream_wrapper php_stream_php_wrapper; diff --git a/ext/standard/string.c b/ext/standard/string.c index b9d7427eb9..2f05b65bb9 100644 --- a/ext/standard/string.c +++ b/ext/standard/string.c @@ -13,7 +13,7 @@ | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Authors: Rasmus Lerdorf <rasmus@php.net> | - | Stig Sæther Bakken <ssb@php.net> | + | Stig S�ther Bakken <ssb@php.net> | | Zeev Suraski <zeev@zend.com> | +----------------------------------------------------------------------+ */ @@ -23,11 +23,6 @@ /* Synced with php 3.0 revision 1.193 1999-06-16 [ssb] */ #include <stdio.h> -#ifdef PHP_WIN32 -# include "win32/php_stdint.h" -#else -# include <stdint.h> -#endif #include "php.h" #include "php_rand.h" #include "php_string.h" diff --git a/ext/standard/tests/array/array_fill.phpt b/ext/standard/tests/array/array_fill.phpt index 1de7c31420..c6c7e1e457 100644 --- a/ext/standard/tests/array/array_fill.phpt +++ b/ext/standard/tests/array/array_fill.phpt @@ -23,34 +23,28 @@ echo '== Done =='; --EXPECTF-- =========================== start: 0 num: 0 value: 1 - -Warning: array_fill(): Number of elements must be positive in %s on line %d -bool(false) +array(0) { +} =========================== start: 0 num: 0 value: - -Warning: array_fill(): Number of elements must be positive in %s on line %d -bool(false) +array(0) { +} =========================== start: 0 num: 0 value: - -Warning: array_fill(): Number of elements must be positive in %s on line %d -bool(false) +array(0) { +} =========================== start: 0 num: 0 value: d - -Warning: array_fill(): Number of elements must be positive in %s on line %d -bool(false) +array(0) { +} =========================== start: 0 num: 0 value: e - -Warning: array_fill(): Number of elements must be positive in %s on line %d -bool(false) +array(0) { +} =========================== start: 0 num: 0 value: f - -Warning: array_fill(): Number of elements must be positive in %s on line %d -bool(false) +array(0) { +} =========================== start: 0 num: 1 value: 1 array(1) { @@ -137,34 +131,28 @@ array(2) { } =========================== start: 1 num: 0 value: 1 - -Warning: array_fill(): Number of elements must be positive in %s on line %d -bool(false) +array(0) { +} =========================== start: 1 num: 0 value: - -Warning: array_fill(): Number of elements must be positive in %s on line %d -bool(false) +array(0) { +} =========================== start: 1 num: 0 value: - -Warning: array_fill(): Number of elements must be positive in %s on line %d -bool(false) +array(0) { +} =========================== start: 1 num: 0 value: d - -Warning: array_fill(): Number of elements must be positive in %s on line %d -bool(false) +array(0) { +} =========================== start: 1 num: 0 value: e - -Warning: array_fill(): Number of elements must be positive in %s on line %d -bool(false) +array(0) { +} =========================== start: 1 num: 0 value: f - -Warning: array_fill(): Number of elements must be positive in %s on line %d -bool(false) +array(0) { +} =========================== start: 1 num: 1 value: 1 array(1) { @@ -251,34 +239,28 @@ array(2) { } =========================== start: 2.5 num: 0 value: 1 - -Warning: array_fill(): Number of elements must be positive in %s on line %d -bool(false) +array(0) { +} =========================== start: 2.5 num: 0 value: - -Warning: array_fill(): Number of elements must be positive in %s on line %d -bool(false) +array(0) { +} =========================== start: 2.5 num: 0 value: - -Warning: array_fill(): Number of elements must be positive in %s on line %d -bool(false) +array(0) { +} =========================== start: 2.5 num: 0 value: d - -Warning: array_fill(): Number of elements must be positive in %s on line %d -bool(false) +array(0) { +} =========================== start: 2.5 num: 0 value: e - -Warning: array_fill(): Number of elements must be positive in %s on line %d -bool(false) +array(0) { +} =========================== start: 2.5 num: 0 value: f - -Warning: array_fill(): Number of elements must be positive in %s on line %d -bool(false) +array(0) { +} =========================== start: 2.5 num: 1 value: 1 array(1) { diff --git a/ext/standard/tests/array/array_fill_error.phpt b/ext/standard/tests/array/array_fill_error.phpt index 167163228d..33ee2b3858 100644 --- a/ext/standard/tests/array/array_fill_error.phpt +++ b/ext/standard/tests/array/array_fill_error.phpt @@ -32,10 +32,6 @@ var_dump( array_fill($start_key,$num) ); $num = -1; var_dump( array_fill($start_key,$num,$val) ); -//callin array_fill with 'num' equal to zero value -$num = 0; -var_dump( array_fill($start_key,$num,$val) ); - echo "Done"; ?> --EXPECTF-- @@ -53,9 +49,6 @@ NULL Warning: array_fill() expects exactly 3 parameters, 2 given in %s on line %d NULL -Warning: array_fill(): Number of elements must be positive in %s on line %d -bool(false) - -Warning: array_fill(): Number of elements must be positive in %s on line %d +Warning: array_fill(): Number of elements can't be negative in %s on line %d bool(false) Done diff --git a/ext/standard/tests/array/array_fill_variation2.phpt b/ext/standard/tests/array/array_fill_variation2.phpt index 9e9df29b0b..ecf4ef435e 100644 --- a/ext/standard/tests/array/array_fill_variation2.phpt +++ b/ext/standard/tests/array/array_fill_variation2.phpt @@ -106,7 +106,7 @@ array(2) { } -- Iteration 2 -- -Warning: array_fill(): Number of elements must be positive in %s on line %d +Warning: array_fill(): Number of elements can't be negative in %s on line %d bool(false) -- Iteration 3 -- array(5) { @@ -122,13 +122,11 @@ array(5) { int(100) } -- Iteration 4 -- - -Warning: array_fill(): Number of elements must be positive in %s on line %d -bool(false) +array(0) { +} -- Iteration 5 -- - -Warning: array_fill(): Number of elements must be positive in %s on line %d -bool(false) +array(0) { +} -- Iteration 6 -- Warning: array_fill() expects parameter 2 to be long, array given in %s on line %d @@ -150,31 +148,27 @@ NULL Warning: array_fill() expects parameter 2 to be long, array given in %s on line %d NULL -- Iteration 11 -- - -Warning: array_fill(): Number of elements must be positive in %s on line %d -bool(false) +array(0) { +} -- Iteration 12 -- - -Warning: array_fill(): Number of elements must be positive in %s on line %d -bool(false) +array(0) { +} -- Iteration 13 -- array(1) { [0]=> int(100) } -- Iteration 14 -- - -Warning: array_fill(): Number of elements must be positive in %s on line %d -bool(false) +array(0) { +} -- Iteration 15 -- array(1) { [0]=> int(100) } -- Iteration 16 -- - -Warning: array_fill(): Number of elements must be positive in %s on line %d -bool(false) +array(0) { +} -- Iteration 17 -- Warning: array_fill() expects parameter 2 to be long, string given in %s on line %d @@ -196,11 +190,9 @@ NULL Warning: array_fill() expects parameter 2 to be long, object given in %s on line %d NULL -- Iteration 22 -- - -Warning: array_fill(): Number of elements must be positive in %s on line %d -bool(false) +array(0) { +} -- Iteration 23 -- - -Warning: array_fill(): Number of elements must be positive in %s on line %d -bool(false) +array(0) { +} Done diff --git a/ext/standard/tests/array/array_filter_error.phpt b/ext/standard/tests/array/array_filter_error.phpt index 20e89aa4b7..3f8f51bc14 100644 --- a/ext/standard/tests/array/array_filter_error.phpt +++ b/ext/standard/tests/array/array_filter_error.phpt @@ -28,7 +28,7 @@ $extra_arg = 10; // with one more than the expected number of arguments echo "-- Testing array_filter() function with more than expected no. of arguments --"; -var_dump( array_filter($input, "odd", $extra_arg) ); +var_dump( array_filter($input, "odd", $extra_arg, $extra_arg) ); // with incorrect callback function echo "-- Testing array_filter() function with incorrect callback --"; @@ -42,7 +42,7 @@ echo "Done" Warning: array_filter() expects at least 1 parameter, 0 given in %s on line %d NULL -- Testing array_filter() function with more than expected no. of arguments -- -Warning: array_filter() expects at most 2 parameters, 3 given in %s on line %d +Warning: array_filter() expects at most 3 parameters, 4 given in %s on line %d NULL -- Testing array_filter() function with incorrect callback -- Warning: array_filter() expects parameter 2 to be a valid callback, function 'even' not found or invalid function name in %s on line %d diff --git a/ext/standard/tests/array/array_filter_variation10.phpt b/ext/standard/tests/array/array_filter_variation10.phpt new file mode 100644 index 0000000000..f0a6115f79 --- /dev/null +++ b/ext/standard/tests/array/array_filter_variation10.phpt @@ -0,0 +1,103 @@ +--TEST-- +Test array_filter() function : usage variations - using the array keys inside 'callback' +--FILE-- +<?php +/* Prototype : array array_filter(array $input [, callback $callback [, bool $use_type = ARRAY_FILTER_USE_VALUE]]) + * Description: Filters elements from the array via the callback. + * Source code: ext/standard/array.c +*/ + +/* +* Using array keys as an argument to the 'callback' +*/ + +echo "*** Testing array_filter() : usage variations - using array keys in 'callback' ***\n"; + +$input = array(0, 1, -1, 10, 100, 1000, 'Hello', null); +$small = array(123); + +function dump($value, $key) +{ + echo "$key = $value\n"; +} + +var_dump( array_filter($input, 'dump', true) ); + +echo "*** Testing array_filter() : usage variations - 'callback' filters based on key value ***\n"; + +function dump2($value, $key) +{ + return $key > 4; +} + +var_dump( array_filter($input, 'dump2', true) ); + +echo "*** Testing array_filter() : usage variations - 'callback' expecting second argument ***\n"; + +var_dump( array_filter($small, 'dump', false) ); + +echo "*** Testing array_filter() with various use types ***\n"; + +$mixed = array(1 => 'a', 2 => 'b', 'a' => 1, 'b' => 2); + +var_dump(array_filter($mixed, 'is_numeric', ARRAY_FILTER_USE_KEY)); + +var_dump(array_filter($mixed, 'is_numeric', 0)); + +var_dump(array_filter($mixed, 'is_numeric', ARRAY_FILTER_USE_BOTH)); + +echo "Done" +?> +--EXPECTF-- +*** Testing array_filter() : usage variations - using array keys in 'callback' *** +0 = 0 +1 = 1 +2 = -1 +3 = 10 +4 = 100 +5 = 1000 +6 = Hello +7 = +array(0) { +} +*** Testing array_filter() : usage variations - 'callback' filters based on key value *** +array(3) { + [5]=> + int(1000) + [6]=> + string(5) "Hello" + [7]=> + NULL +} +*** Testing array_filter() : usage variations - 'callback' expecting second argument *** + +Warning: Missing argument 2 for dump() in %s on line %d + +Notice: Undefined variable: key in %s on line %d + = 123 +array(0) { +} +*** Testing array_filter() with various use types *** +array(2) { + [1]=> + string(1) "a" + [2]=> + string(1) "b" +} +array(2) { + ["a"]=> + int(1) + ["b"]=> + int(2) +} + +Warning: is_numeric() expects exactly 1 parameter, 2 given in %s on line 44 + +Warning: is_numeric() expects exactly 1 parameter, 2 given in %s on line 44 + +Warning: is_numeric() expects exactly 1 parameter, 2 given in %s on line 44 + +Warning: is_numeric() expects exactly 1 parameter, 2 given in %s on line 44 +array(0) { +} +Done diff --git a/ext/standard/tests/dir/chdir_basic.phpt b/ext/standard/tests/dir/chdir_basic.phpt index 5fc0e5b886..81d3c7c9d1 100644 --- a/ext/standard/tests/dir/chdir_basic.phpt +++ b/ext/standard/tests/dir/chdir_basic.phpt @@ -14,40 +14,40 @@ Test chdir() function : basic functionality echo "*** Testing chdir() : basic functionality ***\n"; $base_dir_path = dirname(__FILE__); -$level_one_dir_name = "level_one"; -$level_one_dir_path = "$base_dir_path/$level_one_dir_name"; +$level1_one_dir_name = "level1_one"; +$level1_one_dir_path = "$base_dir_path/$level1_one_dir_name"; -$level_two_dir_name = "level_two"; -$level_two_dir_path = "$base_dir_path/$level_one_dir_name/$level_two_dir_name"; +$level1_two_dir_name = "level1_two"; +$level1_two_dir_path = "$base_dir_path/$level1_one_dir_name/$level1_two_dir_name"; // create directories -mkdir($level_one_dir_path); -mkdir($level_two_dir_path); +mkdir($level1_one_dir_path); +mkdir($level1_two_dir_path); echo "\n-- Testing chdir() with absolute path: --\n"; chdir($base_dir_path); -var_dump(chdir($level_one_dir_path)); +var_dump(chdir($level1_one_dir_path)); var_dump(getcwd()); echo "\n-- Testing chdir() with relative paths: --\n"; -var_dump(chdir($level_two_dir_name)); +var_dump(chdir($level1_two_dir_name)); var_dump(getcwd()); ?> ===DONE=== --CLEAN-- <?php $file_path = dirname(__FILE__); -rmdir("$file_path/level_one/level_two"); -rmdir("$file_path/level_one"); +rmdir("$file_path/level1_one/level1_two"); +rmdir("$file_path/level1_one"); ?> --EXPECTF-- *** Testing chdir() : basic functionality *** -- Testing chdir() with absolute path: -- bool(true) -string(%d) "%slevel_one" +string(%d) "%slevel1_one" -- Testing chdir() with relative paths: -- bool(true) -string(%d) "%slevel_one%elevel_two" +string(%d) "%slevel1_one%elevel1_two" ===DONE=== diff --git a/ext/standard/tests/dir/chdir_variation2.phpt b/ext/standard/tests/dir/chdir_variation2.phpt index fa70f9e104..9ca6a97748 100644 --- a/ext/standard/tests/dir/chdir_variation2.phpt +++ b/ext/standard/tests/dir/chdir_variation2.phpt @@ -15,32 +15,32 @@ echo "*** Testing chdir() : usage variations ***\n"; $base_dir_path = dirname(__FILE__); -$level_one_dir_name = "level_one"; -$level_one_dir_path = "$base_dir_path/$level_one_dir_name"; +$level2_one_dir_name = "level2_one"; +$level2_one_dir_path = "$base_dir_path/$level2_one_dir_name"; -$level_two_dir_name = "level_two"; -$level_two_dir_path = "$base_dir_path/$level_one_dir_name/$level_two_dir_name"; +$level2_two_dir_name = "level2_two"; +$level2_two_dir_path = "$base_dir_path/$level2_one_dir_name/$level2_two_dir_name"; // create directories -mkdir($level_one_dir_path); -mkdir($level_two_dir_path); +mkdir($level2_one_dir_path); +mkdir($level2_two_dir_path); -echo "\n-- \$directory = './level_one': --\n"; +echo "\n-- \$directory = './level2_one': --\n"; var_dump(chdir($base_dir_path)); -var_dump(chdir("./$level_one_dir_name")); +var_dump(chdir("./$level2_one_dir_name")); var_dump(getcwd()); -echo "\n-- \$directory = 'level_one/level_two': --\n"; +echo "\n-- \$directory = 'level2_one/level2_two': --\n"; var_dump(chdir($base_dir_path)); -var_dump(chdir("$level_one_dir_name/$level_two_dir_name")); +var_dump(chdir("$level2_one_dir_name/$level2_two_dir_name")); var_dump(getcwd()); echo "\n-- \$directory = '..': --\n"; var_dump(chdir('..')); var_dump(getcwd()); -echo "\n-- \$directory = 'level_two', '.': --\n"; -var_dump(chdir($level_two_dir_path)); +echo "\n-- \$directory = 'level2_two', '.': --\n"; +var_dump(chdir($level2_two_dir_path)); var_dump(chdir('.')); var_dump(getcwd()); @@ -49,13 +49,13 @@ var_dump(chdir('../')); var_dump(getcwd()); echo "\n-- \$directory = './': --\n"; -var_dump(chdir($level_two_dir_path)); +var_dump(chdir($level2_two_dir_path)); var_dump(chdir('./')); var_dump(getcwd()); -echo "\n-- \$directory = '../../'level_one': --\n"; -var_dump(chdir($level_two_dir_path)); -var_dump(chdir("../../$level_one_dir_name")); +echo "\n-- \$directory = '../../'level2_one': --\n"; +var_dump(chdir($level2_two_dir_path)); +var_dump(chdir("../../$level2_one_dir_name")); var_dump(getcwd()); ?> @@ -63,42 +63,42 @@ var_dump(getcwd()); --CLEAN-- <?php $file_path = dirname(__FILE__); -rmdir("$file_path/level_one/level_two"); -rmdir("$file_path/level_one"); +rmdir("$file_path/level2_one/level2_two"); +rmdir("$file_path/level2_one"); ?> --EXPECTF-- *** Testing chdir() : usage variations *** --- $directory = './level_one': -- +-- $directory = './level2_one': -- bool(true) bool(true) -string(%d) "%slevel_one" +string(%d) "%slevel2_one" --- $directory = 'level_one/level_two': -- +-- $directory = 'level2_one/level2_two': -- bool(true) bool(true) -string(%d) "%slevel_one%elevel_two" +string(%d) "%slevel2_one%elevel2_two" -- $directory = '..': -- bool(true) -string(%d) "%slevel_one" +string(%d) "%slevel2_one" --- $directory = 'level_two', '.': -- +-- $directory = 'level2_two', '.': -- bool(true) bool(true) -string(%d) "%slevel_one%elevel_two" +string(%d) "%slevel2_one%elevel2_two" -- $directory = '../': -- bool(true) -string(%d) "%slevel_one" +string(%d) "%slevel2_one" -- $directory = './': -- bool(true) bool(true) -string(%d) "%slevel_one%elevel_two" +string(%d) "%slevel2_one%elevel2_two" --- $directory = '../../'level_one': -- +-- $directory = '../../'level2_one': -- bool(true) bool(true) -string(%d) "%slevel_one" +string(%d) "%slevel2_one" ===DONE=== diff --git a/ext/standard/tests/file/bug41655_2.phpt b/ext/standard/tests/file/bug41655_2.phpt index d406f1ba04..96f5cc86f0 100644 --- a/ext/standard/tests/file/bug41655_2.phpt +++ b/ext/standard/tests/file/bug41655_2.phpt @@ -5,11 +5,13 @@ open_basedir=/ --FILE-- <?php $dir = dirname(__FILE__); - $a=glob($dir . "/test.*"); + $a=glob($dir . "/test*csv"); print_r($a); ?> --EXPECTF-- Array ( [0] => %stest.csv + [1] => %stest2.csv + [2] => %stest3.csv ) diff --git a/ext/standard/tests/file/copy_variation16-win32.phpt b/ext/standard/tests/file/copy_variation16-win32.phpt index 7688f5eeab..d95d24adac 100644 --- a/ext/standard/tests/file/copy_variation16-win32.phpt +++ b/ext/standard/tests/file/copy_variation16-win32.phpt @@ -22,7 +22,7 @@ mkdir($base_dir); $sub_dir = $base_dir."/copy_variation16_sub"; mkdir($sub_dir); -$dirname_with_blank = $sub_dir."/copy variation6"; +$dirname_with_blank = $sub_dir."/copy variation16"; mkdir($dirname_with_blank); $src_file_name = dirname(__FILE__)."/copy_variation16.tmp"; @@ -139,6 +139,6 @@ Existence of destination file => bool(false) Size of source file => int(3500) Copy operation => bool(true) Existence of destination file => bool(true) -Destination file name is => %s/copy_variation16/copy_variation16_sub/copy variation6/copy_copy_variation16.tmp +Destination file name is => %s/copy_variation16/copy_variation16_sub/copy variation16/copy_copy_variation16.tmp Size of destination file => int(3500) *** Done *** diff --git a/ext/standard/tests/file/copy_variation16.phpt b/ext/standard/tests/file/copy_variation16.phpt index 9ad834bdb4..e36fee1d66 100644 --- a/ext/standard/tests/file/copy_variation16.phpt +++ b/ext/standard/tests/file/copy_variation16.phpt @@ -22,7 +22,7 @@ mkdir($base_dir); $sub_dir = $base_dir."/copy_variation16_sub"; mkdir($sub_dir); -$dirname_with_blank = $sub_dir."/copy variation6"; +$dirname_with_blank = $sub_dir."/copy variation16"; mkdir($dirname_with_blank); $src_file_name = dirname(__FILE__)."/copy_variation16.tmp"; @@ -138,6 +138,6 @@ Size of destination file => int(3500) Size of source file => int(3500) Copy operation => bool(true) Existence of destination file => bool(true) -Destination file name is => %s/copy_variation16/copy_variation16_sub/copy variation6/copy_copy_variation16.tmp +Destination file name is => %s/copy_variation16/copy_variation16_sub/copy variation16/copy_copy_variation16.tmp Size of destination file => int(3500) *** Done *** diff --git a/ext/standard/tests/file/disk_free_space_basic.phpt b/ext/standard/tests/file/disk_free_space_basic.phpt index 200e92ab43..2904ff9a5b 100644 --- a/ext/standard/tests/file/disk_free_space_basic.phpt +++ b/ext/standard/tests/file/disk_free_space_basic.phpt @@ -29,7 +29,7 @@ $space1 = disk_free_space($file_path.$dir); var_dump( $space1 ); $fh = fopen($file_path.$dir."/disk_free_space.tmp", "a"); -$data = str_repeat("x", 4096); +$data = str_repeat("x", 0xffff); fwrite($fh, (binary)$data); fclose($fh); @@ -39,8 +39,10 @@ var_dump( $space2 ); if($space1 > $space2 ) echo "\n Free Space Value Is Correct\n"; -else +else { echo "\n Free Space Value Is Incorrect\n"; + var_dump($space1, $space2); +} echo "*** Testing with Binary Input ***\n"; var_dump( disk_free_space(b"$file_path") ); diff --git a/ext/standard/tests/file/fopen_include_path.inc b/ext/standard/tests/file/fopen_include_path.inc index 7d6723a815..5bc9b6ce3b 100644 --- a/ext/standard/tests/file/fopen_include_path.inc +++ b/ext/standard/tests/file/fopen_include_path.inc @@ -1,6 +1,6 @@ <?php $pwd = getcwd(); -$f = basename(__FILE__); +$f = basename(current(get_included_files()), ".php"); $dir1 = $pwd."/".$f.".dir1"; $dir2 = $pwd."/".$f.".dir2"; $dir3 = $pwd."/".$f.".dir3"; diff --git a/ext/standard/tests/file/fopen_variation16.phpt b/ext/standard/tests/file/fopen_variation16.phpt index 3f220aa7c0..e14f2e1c16 100644 --- a/ext/standard/tests/file/fopen_variation16.phpt +++ b/ext/standard/tests/file/fopen_variation16.phpt @@ -32,7 +32,7 @@ rmdir($thisTestDir); function runtest() { global $dir1; - $extraDir = "extraDir"; + $extraDir = "extraDir16"; mkdir($dir1.'/'.$extraDir); mkdir($extraDir); diff --git a/ext/standard/tests/file/fopen_variation17.phpt b/ext/standard/tests/file/fopen_variation17.phpt index bc75c11c90..8abae0fbe5 100644 --- a/ext/standard/tests/file/fopen_variation17.phpt +++ b/ext/standard/tests/file/fopen_variation17.phpt @@ -32,7 +32,7 @@ rmdir($thisTestDir); function runtest() { global $dir1; - $extraDir = "extraDir"; + $extraDir = "extraDir17"; mkdir($dir1.'/'.$extraDir); mkdir($extraDir); diff --git a/ext/standard/tests/file/fscanf_variation53.phpt b/ext/standard/tests/file/fscanf_variation53.phpt index b65bccf8fd..a553a96693 100644 --- a/ext/standard/tests/file/fscanf_variation53.phpt +++ b/ext/standard/tests/file/fscanf_variation53.phpt @@ -30,7 +30,7 @@ $counter = 1; foreach($modes as $mode) { // create an empty file - $filename = "$file_path/fscanf_variation52.tmp"; + $filename = "$file_path/fscanf_variation53.tmp"; $file_handle = fopen($filename, "w"); if($file_handle == false) exit("Error:failed to open file $filename"); diff --git a/ext/standard/tests/file/glob_variation3.phpt b/ext/standard/tests/file/glob_variation3.phpt index 9e1e28baf9..c50f8a81b8 100644 --- a/ext/standard/tests/file/glob_variation3.phpt +++ b/ext/standard/tests/file/glob_variation3.phpt @@ -5,15 +5,29 @@ Test glob() function: ensure no platform difference $path = dirname(__FILE__); ini_set('open_basedir', NULL); -var_dump(glob("$path/*.none")); -ini_set('open_basedir', $path); var_dump(glob("$path/*.none")); +var_dump(glob("$path/?.none")); +var_dump(glob("$path/*{hello,world}.none")); +var_dump(glob("$path/*/nothere")); +var_dump(glob("$path/[aoeu]*.none")); +var_dump(glob("$path/directly_not_exists")); +var_dump(empty(ini_get('open_basedir'))); ?> ==DONE== --EXPECT-- array(0) { } -bool(false) +array(0) { +} +array(0) { +} +array(0) { +} +array(0) { +} +array(0) { +} +bool(true) ==DONE== diff --git a/ext/standard/tests/file/glob_variation4.phpt b/ext/standard/tests/file/glob_variation4.phpt new file mode 100644 index 0000000000..00d8f648aa --- /dev/null +++ b/ext/standard/tests/file/glob_variation4.phpt @@ -0,0 +1,33 @@ +--TEST-- +Test glob() function: ensure no platform difference, variation 2 +--FILE-- +<?php +$path = dirname(__FILE__); + +ini_set('open_basedir', $path); + +var_dump(glob("$path/*.none")); +var_dump(glob("$path/?.none")); +var_dump(glob("$path/*{hello,world}.none")); +var_dump(glob("$path/*/nothere")); +var_dump(glob("$path/[aoeu]*.none")); +var_dump(glob("$path/directly_not_exists")); + +var_dump($path == ini_get('open_basedir')); +?> +==DONE== +--EXPECT-- +array(0) { +} +array(0) { +} +array(0) { +} +array(0) { +} +array(0) { +} +array(0) { +} +bool(true) +==DONE== diff --git a/ext/standard/tests/file/glob_variation5.phpt b/ext/standard/tests/file/glob_variation5.phpt new file mode 100644 index 0000000000..10db40099b --- /dev/null +++ b/ext/standard/tests/file/glob_variation5.phpt @@ -0,0 +1,29 @@ +--TEST-- +Test glob() function: ensure no platform difference, variation 3 +--SKIPIF-- +<?php if( substr(PHP_OS, 0, 3) == "WIN" ) {die('skip not valid on Windows');} ?> +--FILE-- +<?php +$path = dirname(__FILE__); + +ini_set('open_basedir', '/tmp'); + +var_dump(glob("$path/*.none")); +var_dump(glob("$path/?.none")); +var_dump(glob("$path/*{hello,world}.none")); +var_dump(glob("$path/*/nothere")); +var_dump(glob("$path/[aoeu]*.none")); +var_dump(glob("$path/directly_not_exists")); + +var_dump('/tmp' == ini_get('open_basedir')); +?> +==DONE== +--EXPECT-- +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(true) +==DONE== diff --git a/ext/standard/tests/file/glob_variation6.phpt b/ext/standard/tests/file/glob_variation6.phpt new file mode 100644 index 0000000000..9cd9c2b353 --- /dev/null +++ b/ext/standard/tests/file/glob_variation6.phpt @@ -0,0 +1,35 @@ +--TEST-- +Test glob() function: ensure no platform difference, variation 4 +--SKIPIF-- +<?php if( substr(PHP_OS, 0, 3) != "WIN" ) {die('skip only valid on Windows');} ?> +--FILE-- +<?php +$path = dirname(__FILE__); + +ini_set('open_basedir', 'c:\\windows'); + +var_dump(glob("$path/*.none")); +var_dump(glob("$path/?.none")); +var_dump(glob("$path/*{hello,world}.none")); +var_dump(glob("$path/*/nothere")); +var_dump(glob("$path/[aoeu]*.none")); +var_dump(glob("$path/directly_not_exists")); + +var_dump('c:\\windows' == ini_get('open_basedir')); +?> +==DONE== +--EXPECT-- +array(0) { +} +array(0) { +} +array(0) { +} +array(0) { +} +array(0) { +} +array(0) { +} +bool(true) +==DONE== diff --git a/ext/standard/tests/file/rename_variation1.phpt b/ext/standard/tests/file/rename_variation1.phpt index 0f7321e205..54338d7460 100644 --- a/ext/standard/tests/file/rename_variation1.phpt +++ b/ext/standard/tests/file/rename_variation1.phpt @@ -16,16 +16,16 @@ $file_path = dirname(__FILE__); echo "\n*** Testing rename() : renaming directory across directories ***\n"; $src_dirs = array ( /* Testing simple directory tree */ - "$file_path/rename_variation/", + "$file_path/rename_variation1/", /* Testing a dir with trailing slash */ - "$file_path/rename_variation/", + "$file_path/rename_variation1/", /* Testing dir with double trailing slashes */ - "$file_path//rename_variation//", + "$file_path//rename_variation1//", ); -$dest_dir = "$file_path/rename_variation_dir"; +$dest_dir = "$file_path/rename_variation1_dir"; // create the $dest_dir mkdir($dest_dir); @@ -35,7 +35,7 @@ foreach($src_dirs as $src_dir) { echo "-- Iteration $counter --\n"; // create the src dir - mkdir("$file_path/rename_variation/"); + mkdir("$file_path/rename_variation1/"); // rename the src dir to a new dir in dest dir var_dump( rename($src_dir, $dest_dir."/new_dir") ); // ensure that dir was renamed @@ -52,7 +52,7 @@ echo "Done\n"; --CLEAN-- <?php $file_path = dirname(__FILE__); -rmdir($file_path."/rename_variation_dir"); +rmdir($file_path."/rename_variation1_dir"); ?> --EXPECTF-- *** Testing rename() : renaming directory across directories *** diff --git a/ext/standard/tests/file/rename_variation2-win32.phpt b/ext/standard/tests/file/rename_variation2-win32.phpt index 87f4e7ddb1..9627a9fa53 100644 --- a/ext/standard/tests/file/rename_variation2-win32.phpt +++ b/ext/standard/tests/file/rename_variation2-win32.phpt @@ -15,27 +15,27 @@ if (substr(PHP_OS, 0, 3) != 'WIN') { require dirname(__FILE__).'/file.inc'; $file_path = dirname(__FILE__); -mkdir("$file_path/rename_variation_dir"); +mkdir("$file_path/rename_variation2_dir"); /* Renaming a file and directory to numeric name */ echo "\n*** Testing rename() by renaming a file and directory to numeric name ***\n"; -$fp = fopen($file_path."/rename_variation.tmp", "w"); +$fp = fopen($file_path."/rename_variation2.tmp", "w"); fclose($fp); // renaming existing file to numeric name -var_dump( rename($file_path."/rename_variation.tmp", $file_path."/12345") ); +var_dump( rename($file_path."/rename_variation2.tmp", $file_path."/12345") ); // ensure that rename worked fine -var_dump( file_exists($file_path."/rename_variation.tmp" ) ); // expecting false +var_dump( file_exists($file_path."/rename_variation2.tmp" ) ); // expecting false var_dump( file_exists($file_path."/12345" ) ); // expecting true unlink($file_path."/12345"); // renaming a directory to numeric name -var_dump( rename($file_path."/rename_variation_dir/", $file_path."/12345") ); +var_dump( rename($file_path."/rename_variation2_dir/", $file_path."/12345") ); // ensure that rename worked fine -var_dump( file_exists($file_path."/rename_variation_dir" ) ); // expecting false +var_dump( file_exists($file_path."/rename_variation2_dir" ) ); // expecting false var_dump( file_exists($file_path."/12345" ) ); // expecting true rmdir($file_path."/12345"); @@ -45,9 +45,9 @@ echo "Done\n"; --CLEAN-- <?php $file_path = dirname(__FILE__); -unlink($file_path."/rename_variation_link.tmp"); -unlink($file_path."/rename_variation.tmp"); -rmdir($file_path."/rename_variation_dir"); +unlink($file_path."/rename_variation2_link.tmp"); +unlink($file_path."/rename_variation2.tmp"); +rmdir($file_path."/rename_variation2_dir"); ?> --EXPECTF-- *** Testing rename() by renaming a file and directory to numeric name *** diff --git a/ext/standard/tests/file/rename_variation2.phpt b/ext/standard/tests/file/rename_variation2.phpt index fa3ee1e017..1e0a5d9edd 100644 --- a/ext/standard/tests/file/rename_variation2.phpt +++ b/ext/standard/tests/file/rename_variation2.phpt @@ -11,7 +11,7 @@ if (substr(PHP_OS, 0, 3) == 'WIN') { $file_path = dirname(__FILE__); -$dest_dir = "$file_path/rename_variation_dir"; +$dest_dir = "$file_path/rename_variation2_dir"; // create the $dest_dir mkdir($dest_dir); @@ -23,11 +23,11 @@ $filename = $file_path."/rename_variation2.tmp"; var_dump(touch($filename)); // create the soft links to the file -$linkname = $file_path."/rename_variation_soft_link1.tmp"; +$linkname = $file_path."/rename_variation2_soft_link1.tmp"; var_dump(symlink($filename, $linkname)); //rename the link to a new name in the same dir -$dest_linkname = $file_path."/rename_variation_soft_link2.tmp"; +$dest_linkname = $file_path."/rename_variation2_soft_link2.tmp"; var_dump( rename( $linkname, $dest_linkname) ); //ensure that link was renamed clearstatcache(); @@ -35,14 +35,14 @@ var_dump( file_exists($linkname) ); // expecting false var_dump( file_exists($dest_linkname) ); // expecting true // rename a link across dir -var_dump( rename($dest_linkname, $dest_dir."/rename_variation_soft_link2.tmp")); +var_dump( rename($dest_linkname, $dest_dir."/rename_variation2_soft_link2.tmp")); //ensure that link got renamed clearstatcache(); var_dump( file_exists($dest_linkname) ); // expecting false -var_dump( file_exists($dest_dir."/rename_variation_soft_link2.tmp") ); // expecting true +var_dump( file_exists($dest_dir."/rename_variation2_soft_link2.tmp") ); // expecting true // delete the link file now -unlink($dest_dir."/rename_variation_soft_link2.tmp"); +unlink($dest_dir."/rename_variation2_soft_link2.tmp"); echo "Done\n"; ?> @@ -50,7 +50,7 @@ echo "Done\n"; <?php $file_path = dirname(__FILE__); unlink($file_path."/rename_variation2.tmp"); -rmdir($file_path."/rename_variation_dir"); +rmdir($file_path."/rename_variation2_dir"); ?> --EXPECTF-- *** Testing rename() on soft links *** diff --git a/ext/standard/tests/file/rename_variation3.phpt b/ext/standard/tests/file/rename_variation3.phpt index ce8921630b..7c47040729 100644 --- a/ext/standard/tests/file/rename_variation3.phpt +++ b/ext/standard/tests/file/rename_variation3.phpt @@ -11,41 +11,41 @@ if (substr(PHP_OS, 0, 3) == 'WIN') { $file_path = dirname(__FILE__); -$dest_dir = "$file_path/rename_variation_dir"; +$dest_dir = "$file_path/rename_variation3_dir"; // create the $dest_dir mkdir($dest_dir); echo "\n*** Testing rename() on hard links ***\n"; -$filename = $file_path."/rename_variation1.tmp"; +$filename = $file_path."/rename_variation31.tmp"; @unlink($filename); var_dump(touch($filename)); -$linkname = $file_path."/rename_variation_hard_link1.tmp"; +$linkname = $file_path."/rename_variation3_hard_link1.tmp"; var_dump(link($filename, $linkname)); //rename the link to a new name in the same dir -$dest_linkname = $file_path."/rename_variation_hard_link2.tmp"; +$dest_linkname = $file_path."/rename_variation3_hard_link2.tmp"; var_dump( rename( $filename, $dest_linkname) ); //ensure that link was renamed var_dump( file_exists($filename) ); // expecting false var_dump( file_exists($dest_linkname) ); // expecting true // rename a hard link across dir -var_dump( rename($dest_linkname, $dest_dir."/rename_variation_hard_link2.tmp") ); +var_dump( rename($dest_linkname, $dest_dir."/rename_variation3_hard_link2.tmp") ); //ensure that link got renamed var_dump( file_exists($dest_linkname) ); // expecting false -var_dump( file_exists($dest_dir."/rename_variation_hard_link2.tmp") ); // expecting true +var_dump( file_exists($dest_dir."/rename_variation3_hard_link2.tmp") ); // expecting true // delete the link file now -unlink($dest_dir."/rename_variation_hard_link2.tmp"); +unlink($dest_dir."/rename_variation3_hard_link2.tmp"); echo "Done\n"; ?> --CLEAN-- <?php $file_path = dirname(__FILE__); -unlink($file_path."/rename_variation_hard_link1.tmp"); -rmdir($file_path."/rename_variation_dir"); +unlink($file_path."/rename_variation3_hard_link1.tmp"); +rmdir($file_path."/rename_variation3_dir"); ?> --EXPECTF-- *** Testing rename() on hard links *** diff --git a/ext/standard/tests/file/rename_variation4.phpt b/ext/standard/tests/file/rename_variation4.phpt index 2965f7534a..69753bc322 100644 --- a/ext/standard/tests/file/rename_variation4.phpt +++ b/ext/standard/tests/file/rename_variation4.phpt @@ -15,22 +15,22 @@ require dirname(__FILE__).'/file.inc'; /* Renaming a file, link and directory to numeric name */ echo "\n*** Testing rename() by renaming a file, link and directory to numeric name ***\n"; -$fp = fopen($file_path."/rename_variation.tmp", "w"); +$fp = fopen($file_path."/rename_variation4.tmp", "w"); fclose($fp); // renaming existing file to numeric name -var_dump( rename($file_path."/rename_variation.tmp", $file_path."/12345") ); +var_dump( rename($file_path."/rename_variation4.tmp", $file_path."/12345") ); // ensure that rename worked fine -var_dump( file_exists($file_path."/rename_variation.tmp" ) ); // expecting false +var_dump( file_exists($file_path."/rename_variation4.tmp" ) ); // expecting false var_dump( file_exists($file_path."/12345" ) ); // expecting true // remove the file unlink($file_path."/12345"); -mkdir($file_path."/rename_variation_dir"); +mkdir($file_path."/rename_variation4_dir"); // renaming a directory to numeric name -var_dump( rename($file_path."/rename_variation_dir/", $file_path."/12345") ); +var_dump( rename($file_path."/rename_variation4_dir/", $file_path."/12345") ); // ensure that rename worked fine -var_dump( file_exists($file_path."/rename_variation_dir" ) ); // expecting false +var_dump( file_exists($file_path."/rename_variation4_dir" ) ); // expecting false var_dump( file_exists($file_path."/12345" ) ); // expecting true echo "Done\n"; diff --git a/ext/standard/tests/file/rename_variation5.phpt b/ext/standard/tests/file/rename_variation5.phpt index bf43e49510..2518cf48ea 100644 --- a/ext/standard/tests/file/rename_variation5.phpt +++ b/ext/standard/tests/file/rename_variation5.phpt @@ -13,14 +13,14 @@ if (substr(PHP_OS, 0, 3) == 'WIN') { and one another */ // create a dir $file_path = dirname(__FILE__); -$dirname = "$file_path/rename_variation_dir"; +$dirname = "$file_path/rename_variation5_dir"; mkdir($dirname); //create a file -$filename = "$file_path/rename_variation.tmp"; +$filename = "$file_path/rename_variation5.tmp"; $fp = fopen($filename, "w"); fclose($fp); // create a link -$linkname = "$file_path/rename_variation_link.tmp"; +$linkname = "$file_path/rename_variation5_link.tmp"; symlink($filename, $linkname); echo "\n-- Renaming link to same link name --\n"; @@ -54,9 +54,9 @@ echo "Done\n"; --CLEAN-- <?php $file_path = dirname(__FILE__); -unlink($file_path."/rename_variation_link.tmp"); -unlink($file_path."/rename_variation.tmp"); -rmdir($file_path."/rename_variation_dir"); +unlink($file_path."/rename_variation5_link.tmp"); +unlink($file_path."/rename_variation5.tmp"); +rmdir($file_path."/rename_variation5_dir"); ?> --EXPECTF-- -- Renaming link to same link name -- diff --git a/ext/standard/tests/http/bug65634.phpt b/ext/standard/tests/http/bug65634.phpt new file mode 100644 index 0000000000..8f358cc6cf --- /dev/null +++ b/ext/standard/tests/http/bug65634.phpt @@ -0,0 +1,81 @@ +--TEST-- +Bug #65634 (HTTP wrapper is very slow with protocol_version 1.1) +--INI-- +allow_url_fopen=1 +--SKIPIF-- +<?php require 'server.inc'; http_server_skipif('tcp://127.0.0.1:12342'); ?> +--FILE-- +<?php +require 'server.inc'; + +function do_test($version, $connection) { + $options = [ + 'http' => [ + 'protocol_version' => $version, + ], + ]; + + if ($connection) { + $options['http']['header'] = "Connection: $connection"; + } + + $ctx = stream_context_create($options); + + $responses = ["data://text/plain,HTTP/$version 204 No Content\r\n\r\n"]; + $pid = http_server('tcp://127.0.0.1:12342', $responses, $output); + + $fd = fopen('http://127.0.0.1:12342/', 'rb', false, $ctx); + fseek($output, 0, SEEK_SET); + echo stream_get_contents($output); + + http_server_kill($pid); +} + +echo "HTTP/1.0, default behaviour:\n"; +do_test('1.0', null); + +echo "HTTP/1.0, connection: close:\n"; +do_test('1.0', 'close'); + +echo "HTTP/1.0, connection: keep-alive:\n"; +do_test('1.0', 'keep-alive'); + +echo "HTTP/1.1, default behaviour:\n"; +do_test('1.1', null); + +echo "HTTP/1.1, connection: close:\n"; +do_test('1.1', 'close'); + +echo "HTTP/1.1, connection: keep-alive:\n"; +do_test('1.1', 'keep-alive'); +?> +--EXPECT-- +HTTP/1.0, default behaviour: +GET / HTTP/1.0 +Host: 127.0.0.1:12342 + +HTTP/1.0, connection: close: +GET / HTTP/1.0 +Host: 127.0.0.1:12342 +Connection: close + +HTTP/1.0, connection: keep-alive: +GET / HTTP/1.0 +Host: 127.0.0.1:12342 +Connection: keep-alive + +HTTP/1.1, default behaviour: +GET / HTTP/1.1 +Host: 127.0.0.1:12342 +Connection: close + +HTTP/1.1, connection: close: +GET / HTTP/1.1 +Host: 127.0.0.1:12342 +Connection: close + +HTTP/1.1, connection: keep-alive: +GET / HTTP/1.1 +Host: 127.0.0.1:12342 +Connection: keep-alive + diff --git a/ext/standard/tests/serialize/serialization_error_001.phpt b/ext/standard/tests/serialize/serialization_error_001.phpt index da6f50cc02..c6c17512f3 100644 --- a/ext/standard/tests/serialize/serialization_error_001.phpt +++ b/ext/standard/tests/serialize/serialization_error_001.phpt @@ -21,7 +21,7 @@ var_dump( unserialize() ); //Test serialize with one more than the expected number of arguments var_dump( serialize(1,2) ); -var_dump( unserialize(1,2) ); +var_dump( unserialize(1,$x,2) ); echo "Done"; ?> @@ -31,12 +31,12 @@ echo "Done"; Warning: serialize() expects exactly 1 parameter, 0 given in %s on line 16 NULL -Warning: unserialize() expects exactly 1 parameter, 0 given in %s on line 17 +Warning: unserialize() expects at least 1 parameter, 0 given in %s on line 17 bool(false) Warning: serialize() expects exactly 1 parameter, 2 given in %s on line 20 NULL -Warning: unserialize() expects exactly 1 parameter, 2 given in %s on line 21 +Warning: unserialize() expects at most 2 parameters, 3 given in %s on line 21 bool(false) Done diff --git a/ext/standard/tests/serialize/unserialize_consumed.phpt b/ext/standard/tests/serialize/unserialize_consumed.phpt new file mode 100644 index 0000000000..6cc11e273f --- /dev/null +++ b/ext/standard/tests/serialize/unserialize_consumed.phpt @@ -0,0 +1,27 @@ +--TEST-- +Unserialization of partial strings +--FILE-- +<?php +$data = [123,4.56,true]; +$ser = serialize($data); +$serlen = strlen($ser); + +$unser = unserialize($ser, $consumed); +echo "Consume full string: "; +var_dump($serlen == $consumed); +echo "Return original data: "; +var_dump($unser === $data); + +$ser .= "junk\x01data"; +$unser = unserialize($ser, $consumed); +echo "Consume full string(junk): "; +var_dump($serlen == $consumed); +echo "Return original data(junk): "; +var_dump($unser === $data); + +--EXPECT-- +Consume full string: bool(true) +Return original data: bool(true) +Consume full string(junk): bool(true) +Return original data(junk): bool(true) + diff --git a/ext/standard/tests/streams/stream_get_meta_data_socket_basic.phpt b/ext/standard/tests/streams/stream_get_meta_data_socket_basic.phpt index 86056114b8..86c9cd77c8 100644 --- a/ext/standard/tests/streams/stream_get_meta_data_socket_basic.phpt +++ b/ext/standard/tests/streams/stream_get_meta_data_socket_basic.phpt @@ -3,7 +3,7 @@ stream_get_meta_data() on a udp socket --FILE-- <?php -$tcp_socket = stream_socket_server('tcp://127.0.0.1:31337'); +$tcp_socket = stream_socket_server('tcp://127.0.0.1:31330'); var_dump(stream_get_meta_data($tcp_socket)); fclose($tcp_socket); diff --git a/ext/standard/tests/streams/stream_get_meta_data_socket_variation1.phpt b/ext/standard/tests/streams/stream_get_meta_data_socket_variation1.phpt index 16b38d9a1b..88d354b378 100644 --- a/ext/standard/tests/streams/stream_get_meta_data_socket_variation1.phpt +++ b/ext/standard/tests/streams/stream_get_meta_data_socket_variation1.phpt @@ -4,10 +4,10 @@ Testing stream_get_meta_data() "unread_bytes" field on a udp socket <?php /* Setup socket server */ -$server = stream_socket_server('tcp://127.0.0.1:31337'); +$server = stream_socket_server('tcp://127.0.0.1:31331'); /* Connect to it */ -$client = fsockopen('tcp://127.0.0.1:31337'); +$client = fsockopen('tcp://127.0.0.1:31331'); if (!$client) { die("Unable to create socket"); } diff --git a/ext/standard/tests/streams/stream_get_meta_data_socket_variation2.phpt b/ext/standard/tests/streams/stream_get_meta_data_socket_variation2.phpt index d30fec7056..e8e39209c9 100644 --- a/ext/standard/tests/streams/stream_get_meta_data_socket_variation2.phpt +++ b/ext/standard/tests/streams/stream_get_meta_data_socket_variation2.phpt @@ -4,10 +4,10 @@ Testing stream_get_meta_data() "timed_out" field on a udp socket <?php /* Setup socket server */ -$server = stream_socket_server('tcp://127.0.0.1:31337'); +$server = stream_socket_server('tcp://127.0.0.1:31332'); /* Connect to it */ -$client = fsockopen('tcp://127.0.0.1:31337'); +$client = fsockopen('tcp://127.0.0.1:31332'); if (!$client) { die("Unable to create socket"); } diff --git a/ext/standard/tests/streams/stream_get_meta_data_socket_variation3.phpt b/ext/standard/tests/streams/stream_get_meta_data_socket_variation3.phpt index 0b079ccf7c..5b68eba25d 100644 --- a/ext/standard/tests/streams/stream_get_meta_data_socket_variation3.phpt +++ b/ext/standard/tests/streams/stream_get_meta_data_socket_variation3.phpt @@ -4,10 +4,10 @@ Testing stream_get_meta_data() "blocked" field on a udp socket <?php /* Setup socket server */ -$server = stream_socket_server('tcp://127.0.0.1:31337'); +$server = stream_socket_server('tcp://127.0.0.1:31333'); /* Connect to it */ -$client = fsockopen('tcp://127.0.0.1:31337'); +$client = fsockopen('tcp://127.0.0.1:31333'); if (!$client) { die("Unable to create socket"); } diff --git a/ext/standard/tests/streams/stream_get_meta_data_socket_variation4.phpt b/ext/standard/tests/streams/stream_get_meta_data_socket_variation4.phpt index f9ef747987..e3f59d10dc 100644 --- a/ext/standard/tests/streams/stream_get_meta_data_socket_variation4.phpt +++ b/ext/standard/tests/streams/stream_get_meta_data_socket_variation4.phpt @@ -4,10 +4,10 @@ Testing stream_get_meta_data() "eof" field on a udp socket <?php /* Setup socket server */ -$server = stream_socket_server('tcp://127.0.0.1:31337'); +$server = stream_socket_server('tcp://127.0.0.1:31334'); /* Connect to it */ -$client = fsockopen('tcp://127.0.0.1:31337'); +$client = fsockopen('tcp://127.0.0.1:31334'); if (!$client) { die("Unable to create socket"); } diff --git a/ext/standard/tests/strings/crypt.phpt b/ext/standard/tests/strings/crypt.phpt index ce178f684e..3dcff2eaf2 100644 --- a/ext/standard/tests/strings/crypt.phpt +++ b/ext/standard/tests/strings/crypt.phpt @@ -34,6 +34,8 @@ STD EXT MD5 BLO + +Notice: crypt(): No salt parameter was specified. You must use a randomly generated salt and a strong hash function to produce a secure hash. in %s on line %d string(%d) "%s" Warning: crypt() expects at least 1 parameter, 0 given in %s on line %d diff --git a/ext/standard/var.c b/ext/standard/var.c index fb2a310f4c..a7ece7fb5c 100644 --- a/ext/standard/var.c +++ b/ext/standard/var.c @@ -453,7 +453,7 @@ PHPAPI void php_var_export_ex(zval **struc, int level, smart_str *buf TSRMLS_DC) break; case IS_ARRAY: myht = Z_ARRVAL_PP(struc); - if(myht && myht->nApplyCount > 0){ + if (myht->nApplyCount > 0){ smart_str_appendl(buf, "NULL", 4); zend_error(E_WARNING, "var_export does not handle circular references"); return; @@ -943,7 +943,7 @@ PHP_FUNCTION(serialize) } /* }}} */ -/* {{{ proto mixed unserialize(string variable_representation) +/* {{{ proto mixed unserialize(string variable_representation[, int &consumed]) Takes a string representation of variable and recreates it */ PHP_FUNCTION(unserialize) { @@ -951,8 +951,9 @@ PHP_FUNCTION(unserialize) int buf_len; const unsigned char *p; php_unserialize_data_t var_hash; + zval *consumed = NULL; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &buf, &buf_len) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|z", &buf, &buf_len, &consumed) == FAILURE) { RETURN_FALSE; } @@ -971,6 +972,11 @@ PHP_FUNCTION(unserialize) RETURN_FALSE; } PHP_VAR_UNSERIALIZE_DESTROY(var_hash); + + if (consumed) { + zval_dtor(consumed); + ZVAL_LONG(consumed, ((char*)p) - buf); + } } /* }}} */ diff --git a/ext/tokenizer/tokenizer_data.c b/ext/tokenizer/tokenizer_data.c index 57b29e1dd7..8c4786575e 100644 --- a/ext/tokenizer/tokenizer_data.c +++ b/ext/tokenizer/tokenizer_data.c @@ -38,6 +38,7 @@ void tokenizer_register_constants(INIT_FUNC_ARGS) { REGISTER_LONG_CONSTANT("T_LOGICAL_XOR", T_LOGICAL_XOR, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("T_LOGICAL_AND", T_LOGICAL_AND, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("T_PRINT", T_PRINT, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("T_YIELD", T_YIELD, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("T_SR_EQUAL", T_SR_EQUAL, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("T_SL_EQUAL", T_SL_EQUAL, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("T_XOR_EQUAL", T_XOR_EQUAL, CONST_CS | CONST_PERSISTENT); @@ -108,7 +109,6 @@ void tokenizer_register_constants(INIT_FUNC_ARGS) { REGISTER_LONG_CONSTANT("T_FUNCTION", T_FUNCTION, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("T_CONST", T_CONST, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("T_RETURN", T_RETURN, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("T_YIELD", T_YIELD, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("T_TRY", T_TRY, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("T_CATCH", T_CATCH, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("T_FINALLY", T_FINALLY, CONST_CS | CONST_PERSISTENT); @@ -158,6 +158,7 @@ void tokenizer_register_constants(INIT_FUNC_ARGS) { REGISTER_LONG_CONSTANT("T_NS_C", T_NS_C, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("T_DIR", T_DIR, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("T_NS_SEPARATOR", T_NS_SEPARATOR, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("T_ELLIPSIS", T_ELLIPSIS, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("T_DOUBLE_COLON", T_PAAMAYIM_NEKUDOTAYIM, CONST_CS | CONST_PERSISTENT); } @@ -174,6 +175,7 @@ char *get_token_type_name(int token_type) case T_LOGICAL_XOR: return "T_LOGICAL_XOR"; case T_LOGICAL_AND: return "T_LOGICAL_AND"; case T_PRINT: return "T_PRINT"; + case T_YIELD: return "T_YIELD"; case T_SR_EQUAL: return "T_SR_EQUAL"; case T_SL_EQUAL: return "T_SL_EQUAL"; case T_XOR_EQUAL: return "T_XOR_EQUAL"; @@ -244,7 +246,6 @@ char *get_token_type_name(int token_type) case T_FUNCTION: return "T_FUNCTION"; case T_CONST: return "T_CONST"; case T_RETURN: return "T_RETURN"; - case T_YIELD: return "T_YIELD"; case T_TRY: return "T_TRY"; case T_CATCH: return "T_CATCH"; case T_FINALLY: return "T_FINALLY"; @@ -294,6 +295,7 @@ char *get_token_type_name(int token_type) case T_NS_C: return "T_NS_C"; case T_DIR: return "T_DIR"; case T_NS_SEPARATOR: return "T_NS_SEPARATOR"; + case T_ELLIPSIS: return "T_ELLIPSIS"; } return "UNKNOWN"; diff --git a/ext/xmlreader/php_xmlreader.c b/ext/xmlreader/php_xmlreader.c index aae55c8b3e..76cd56f144 100644 --- a/ext/xmlreader/php_xmlreader.c +++ b/ext/xmlreader/php_xmlreader.c @@ -588,9 +588,6 @@ PHP_METHOD(xmlreader, getAttributeNo) if (retchar) { RETVAL_STRING(retchar, 1); xmlFree(retchar); - return; - } else { - RETURN_EMPTY_STRING(); } } /* }}} */ @@ -622,9 +619,6 @@ PHP_METHOD(xmlreader, getAttributeNs) if (retchar) { RETVAL_STRING(retchar, 1); xmlFree(retchar); - return; - } else { - RETURN_EMPTY_STRING(); } } /* }}} */ diff --git a/ext/zip/CREDITS b/ext/zip/CREDITS index 6c7e42d417..59b7ef097e 100644 --- a/ext/zip/CREDITS +++ b/ext/zip/CREDITS @@ -1,2 +1,2 @@ Zip -Pierre-Alain Joye +Pierre-Alain Joye, Remi Collet diff --git a/ext/zip/config.m4 b/ext/zip/config.m4 index 805d92442e..83e32feca7 100644 --- a/ext/zip/config.m4 +++ b/ext/zip/config.m4 @@ -11,10 +11,14 @@ if test -z "$PHP_ZLIB_DIR"; then fi PHP_ARG_WITH(pcre-dir, pcre install prefix, -[ --with-pcre-dir ZIP: pcre install prefix], no, no) +[ --with-pcre-dir ZIP: pcre install prefix], no, no) + +PHP_ARG_WITH(libzip, libzip, +[ --with-libzip[=DIR] ZIP: use libzip], no, no) if test "$PHP_ZIP" != "no"; then + dnl libzip, depends on zlib if test "$PHP_ZLIB_DIR" != "no" && test "$PHP_ZLIB_DIR" != "yes"; then if test -f "$PHP_ZLIB_DIR/include/zlib/zlib.h"; then PHP_ZLIB_DIR="$PHP_ZLIB_DIR" @@ -47,61 +51,124 @@ if test "$PHP_ZIP" != "no"; then PHP_ADD_INCLUDE($PHP_ZLIB_INCDIR) fi - dnl This is PECL build, check if bundled PCRE library is used - old_CPPFLAGS=$CPPFLAGS - CPPFLAGS=$INCLUDES - AC_EGREP_CPP(yes,[ -#include <main/php_config.h> -#if defined(HAVE_BUNDLED_PCRE) && !defined(COMPILE_DL_PCRE) -yes -#endif - ],[ - PHP_PCRE_REGEX=yes - ],[ - AC_EGREP_CPP(yes,[ -#include <main/php_config.h> -#if defined(HAVE_PCRE) && !defined(COMPILE_DL_PCRE) -yes -#endif - ],[ - PHP_PCRE_REGEX=pecl - ],[ - PHP_PCRE_REGEX=no + if test "$PHP_LIBZIP" != "no"; then + + AC_PATH_PROG(PKG_CONFIG, pkg-config, no) + + dnl system libzip, depends on libzip + AC_MSG_CHECKING(for libzip) + if test -r $PHP_LIBZIP/include/zip.h; then + LIBZIP_CFLAGS="-I$PHP_LIBZIP/include" + LIBZIP_LIBDIR="$PHP_LIBZIP/$PHP_LIBDIR" + AC_MSG_RESULT(from option: found in $PHP_LIBZIP) + + elif test -x "$PKG_CONFIG" && $PKG_CONFIG --exists libzip; then + LIBZIP_CFLAGS=`$PKG_CONFIG libzip --cflags` + LIBZIP_LIBDIR=`$PKG_CONFIG libzip --variable=libdir` + AC_MSG_RESULT(from pkgconfig: found in $LIBZIP_LIBDIR) + + else + for i in /usr/local /usr; do + if test -r $i/include/zip.h; then + LIBZIP_CFLAGS="-I$i/include" + LIBZIP_LIBDIR="$i/$PHP_LIBDIR" + AC_MSG_RESULT(in default path: found in $i) + break + fi + done + fi + + if test -z "$LIBZIP_LIBDIR"; then + AC_MSG_RESULT(not found) + AC_MSG_ERROR(Please reinstall the libzip distribution) + fi + + dnl Could not think of a simple way to check libzip for overwrite support + PHP_CHECK_LIBRARY(zip, zip_open, + [ + PHP_ADD_LIBRARY_WITH_PATH(zip, $LIBZIP_LIBDIR, ZIP_SHARED_LIBADD) + AC_DEFINE(HAVE_LIBZIP,1,[ ]) + ], [ + AC_MSG_ERROR(could not find usable libzip) + ], [ + -L$LIBZIP_LIBDIR ]) - ]) - CPPFLAGS=$old_CPPFLAGS - - PHP_ZIP_SOURCES="$PHP_ZIP_SOURCES lib/zip_add.c lib/zip_error.c lib/zip_fclose.c \ - lib/zip_fread.c lib/zip_open.c lib/zip_source_filep.c \ - lib/zip_strerror.c lib/zip_close.c lib/zip_error_get.c \ - lib/zip_file_error_get.c lib/zip_free.c lib/zip_rename.c \ - lib/zip_source_free.c lib/zip_unchange_all.c lib/zip_delete.c \ - lib/zip_error_get_sys_type.c lib/zip_file_get_offset.c \ - lib/zip_get_name.c lib/zip_replace.c lib/zip_source_function.c \ - lib/zip_unchange.c lib/zip_dirent.c lib/zip_error_strerror.c \ - lib/zip_filerange_crc.c lib/zip_file_strerror.c lib/zip_get_num_files.c \ - lib/zip_get_archive_flag.c lib/zip_set_archive_flag.c \ - lib/zip_set_name.c lib/zip_source_zip.c lib/zip_unchange_data.c \ - lib/zip_entry_free.c lib/zip_error_to_str.c lib/zip_fopen.c \ - lib/zip_name_locate.c lib/zip_source_buffer.c lib/zip_stat.c \ - lib/zip_entry_new.c lib/zip_err_str.c lib/zip_fopen_index.c \ - lib/zip_get_archive_comment.c lib/zip_get_file_comment.c \ - lib/zip_new.c lib/zip_source_file.c lib/zip_stat_index.c \ - lib/zip_set_archive_comment.c lib/zip_set_file_comment.c \ - lib/zip_unchange_archive.c lib/zip_memdup.c lib/zip_stat_init.c lib/zip_add_dir.c \ - lib/zip_error_clear.c lib/zip_file_error_clear.c \ - lib/zip_fdopen.c lib/zip_fopen_encrypted.c lib/zip_fopen_index_encrypted.c \ - lib/zip_get_compression_implementation.c lib/zip_get_encryption_implementation.c \ - lib/zip_get_file_extra.c lib/zip_get_num_entries.c lib/zip_set_default_password.c \ - lib/zip_set_file_extra.c lib/zip_source_close.c lib/zip_source_crc.c \ - lib/zip_source_deflate.c lib/zip_source_error.c lib/zip_source_layered.c \ - lib/zip_source_open.c lib/zip_source_pkware.c lib/zip_source_pop.c \ - lib/zip_source_read.c lib/zip_source_stat.c" + + AC_DEFINE(HAVE_ZIP,1,[ ]) + PHP_NEW_EXTENSION(zip, php_zip.c zip_stream.c, $ext_shared,, $LIBZIP_CFLAGS) + PHP_SUBST(ZIP_SHARED_LIBADD) + else + + + PHP_ZIP_SOURCES="$PHP_ZIP_SOURCES lib/zip_add.c lib/zip_add_dir.c lib/zip_add_entry.c\ + lib/zip_close.c lib/zip_delete.c lib/zip_dir_add.c lib/zip_dirent.c lib/zip_discard.c lib/zip_entry.c\ + lib/zip_err_str.c lib/zip_error.c lib/zip_error_clear.c lib/zip_error_get.c lib/zip_error_get_sys_type.c\ + lib/zip_error_strerror.c lib/zip_error_to_str.c lib/zip_extra_field.c lib/zip_extra_field_api.c\ + lib/zip_fclose.c lib/zip_fdopen.c lib/zip_file_add.c lib/zip_file_error_clear.c lib/zip_file_error_get.c\ + lib/zip_file_get_comment.c lib/zip_file_get_offset.c lib/zip_file_rename.c lib/zip_file_replace.c\ + lib/zip_file_set_comment.c lib/zip_file_strerror.c lib/zip_filerange_crc.c lib/zip_fopen.c\ + lib/zip_fopen_encrypted.c lib/zip_fopen_index.c lib/zip_fopen_index_encrypted.c lib/zip_fread.c\ + lib/zip_get_archive_comment.c lib/zip_get_archive_flag.c lib/zip_get_compression_implementation.c\ + lib/zip_get_encryption_implementation.c lib/zip_get_file_comment.c lib/zip_get_name.c lib/zip_get_num_entries.c \ + lib/zip_get_num_files.c lib/zip_memdup.c lib/zip_name_locate.c lib/zip_new.c lib/zip_open.c lib/zip_rename.c lib/zip_replace.c\ + lib/zip_set_archive_comment.c lib/zip_set_archive_flag.c lib/zip_set_default_password.c lib/zip_set_file_comment.c\ + lib/zip_set_file_compression.c lib/zip_set_name.c lib/zip_source_buffer.c lib/zip_source_close.c lib/zip_source_crc.c\ + lib/zip_source_deflate.c lib/zip_source_error.c lib/zip_source_file.c lib/zip_source_filep.c lib/zip_source_free.c\ + lib/zip_source_function.c lib/zip_source_layered.c lib/zip_source_open.c lib/zip_source_pkware.c lib/zip_source_pop.c\ + lib/zip_source_read.c lib/zip_source_stat.c lib/zip_source_window.c lib/zip_source_zip.c lib/zip_source_zip_new.c\ + lib/zip_stat.c lib/zip_stat_index.c lib/zip_stat_init.c lib/zip_strerror.c lib/zip_string.c lib/zip_unchange.c lib/zip_unchange_all.c\ + lib/zip_unchange_archive.c lib/zip_unchange_data.c lib/zip_utf-8.c lib/mkstemp.c" AC_DEFINE(HAVE_ZIP,1,[ ]) PHP_NEW_EXTENSION(zip, php_zip.c zip_stream.c $PHP_ZIP_SOURCES, $ext_shared) PHP_ADD_BUILD_DIR($ext_builddir/lib, 1) PHP_SUBST(ZIP_SHARED_LIBADD) +fi + + +AC_CHECK_TYPES([int8_t]) +AC_CHECK_TYPES([int16_t]) +AC_CHECK_TYPES([int32_t]) +AC_CHECK_TYPES([int64_t]) +AC_CHECK_TYPES([uint8_t]) +AC_CHECK_TYPES([uint16_t]) +AC_CHECK_TYPES([uint32_t]) +AC_CHECK_TYPES([uint64_t]) +AC_CHECK_TYPES([ssize_t]) + +AC_CHECK_SIZEOF([short]) +AC_CHECK_SIZEOF([int]) +AC_CHECK_SIZEOF([long]) +AC_CHECK_SIZEOF([long long]) +AC_CHECK_SIZEOF([off_t]) +AC_CHECK_SIZEOF([size_t]) + +AC_PATH_PROG([TOUCH], [touch]) +AC_PATH_PROG([UNZIP], [unzip]) + +AC_STRUCT_TIMEZONE + +case $host_os +in + *bsd*) MANFMT=mdoc;; + *) MANFMT=man;; +esac +AC_SUBST([MANFMT]) + +AH_BOTTOM([ +#ifndef HAVE_SSIZE_T +# if SIZEOF_SIZE_T == SIZEOF_INT +typedef int ssize_t; +# elif SIZEOF_SIZE_T == SIZEOF_LONG +typedef long ssize_t; +# elif SIZEOF_SIZE_T == SIZEOF_LONG_LONG +typedef long long ssize_t; +# else +#error no suitable type for ssize_t found +# endif +#endif +]) + dnl so we always include the known-good working hack. PHP_ADD_MAKEFILE_FRAGMENT diff --git a/ext/zip/config.w32 b/ext/zip/config.w32 index fa0a5180df..5b9f09575a 100644 --- a/ext/zip/config.w32 +++ b/ext/zip/config.w32 @@ -9,36 +9,28 @@ if (PHP_ZIP != "no") { (PHP_ZLIB_SHARED && CHECK_LIB("zlib.lib", "zip", PHP_ZIP)) || (PHP_ZLIB == "yes" && (!PHP_ZLIB_SHARED))) ) { EXTENSION('zip', 'php_zip.c zip_stream.c'); - ADD_SOURCES(configure_module_dirname + "/lib", "zip_add.c zip_error.c zip_fclose.c \ - zip_fread.c zip_open.c zip_source_filep.c \ - zip_strerror.c zip_close.c zip_error_get.c \ - zip_file_error_get.c zip_free.c zip_rename.c \ - zip_source_free.c zip_unchange_all.c zip_delete.c \ - zip_error_get_sys_type.c zip_file_get_offset.c \ - zip_get_name.c zip_replace.c zip_source_function.c \ - zip_unchange.c zip_dirent.c zip_error_strerror.c \ - zip_filerange_crc.c zip_file_strerror.c zip_get_num_files.c \ - zip_get_archive_flag.c zip_set_archive_flag.c \ - zip_set_name.c zip_source_zip.c zip_unchange_data.c \ - zip_entry_free.c zip_error_to_str.c zip_fopen.c \ - zip_name_locate.c zip_source_buffer.c zip_stat.c \ - zip_entry_new.c zip_err_str.c zip_fopen_index.c \ - zip_new.c zip_source_file.c zip_stat_index.c \ - zip_get_archive_comment.c zip_get_file_comment.c \ - zip_set_archive_comment.c zip_set_file_comment.c \ - zip_unchange_archive.c zip_memdup.c zip_stat_init.c \ - zip_add_dir.c zip_file_error_clear.c zip_error_clear.c \ - zip_fdopen.c zip_fopen_encrypted.c zip_fopen_index_encrypted.c \ - zip_get_compression_implementation.c zip_get_encryption_implementation.c \ - zip_get_file_extra.c zip_get_num_entries.c zip_set_default_password.c \ - zip_set_file_extra.c zip_source_close.c zip_source_crc.c \ - zip_source_deflate.c zip_source_error.c zip_source_layered.c \ - zip_source_open.c zip_source_pkware.c zip_source_pop.c \ - zip_source_read.c zip_source_stat.c", "zip"); + ADD_SOURCES(configure_module_dirname + "/lib", "zip_add.c zip_add_dir.c zip_add_entry.c\ + zip_close.c zip_delete.c zip_dir_add.c zip_dirent.c zip_discard.c zip_entry.c\ + zip_err_str.c zip_error.c zip_error_clear.c zip_error_get.c zip_error_get_sys_type.c\ + zip_error_strerror.c zip_error_to_str.c zip_extra_field.c zip_extra_field_api.c\ + zip_fclose.c zip_fdopen.c zip_file_add.c zip_file_error_clear.c zip_file_error_get.c\ + zip_file_get_comment.c zip_file_get_offset.c zip_file_rename.c zip_file_replace.c\ + zip_file_set_comment.c zip_file_strerror.c zip_filerange_crc.c zip_fopen.c\ + zip_fopen_encrypted.c zip_fopen_index.c zip_fopen_index_encrypted.c zip_fread.c\ + zip_get_archive_comment.c zip_get_archive_flag.c zip_get_compression_implementation.c\ + zip_get_encryption_implementation.c zip_get_file_comment.c zip_get_name.c zip_get_num_entries.c \ + zip_get_num_files.c zip_memdup.c zip_name_locate.c zip_new.c zip_open.c zip_rename.c zip_replace.c\ + zip_set_archive_comment.c zip_set_archive_flag.c zip_set_default_password.c zip_set_file_comment.c\ + zip_set_file_compression.c zip_set_name.c zip_source_buffer.c zip_source_close.c zip_source_crc.c\ + zip_source_deflate.c zip_source_error.c zip_source_file.c zip_source_filep.c zip_source_free.c\ + zip_source_function.c zip_source_layered.c zip_source_open.c zip_source_pkware.c zip_source_pop.c\ + zip_source_read.c zip_source_stat.c zip_source_window.c zip_source_zip.c zip_source_zip_new.c\ + zip_stat.c zip_stat_index.c zip_stat_init.c zip_strerror.c zip_string.c zip_unchange.c zip_unchange_all.c\ + zip_unchange_archive.c zip_unchange_data.c zip_utf-8.c mkstemp.c", "zip"); AC_DEFINE('HAVE_ZIP', 1); + ADD_FLAG("CFLAGS_ZIP", "/D _WIN32"); } else { WARNING("zip not enabled; libraries and headers not found"); } } - diff --git a/ext/zip/examples/addglob.php b/ext/zip/examples/addglob.php new file mode 100644 index 0000000000..790312b4d5 --- /dev/null +++ b/ext/zip/examples/addglob.php @@ -0,0 +1,14 @@ +<?php + +$z = new ZipArchive; +$z->open('a.zip', ZIPARCHIVE::CREATE); + +/* or 'remove_all_path' => 0*/ +$options = array( + 'remove_path' => '/home/francis/myimages', + 'add_path' => 'images/', +); +$found = $z->addGlob("/home/pierre/cvs/gd/libgd/tests/*.png", 0, $options); +var_dump($found); +$z->close(); + diff --git a/ext/zip/examples/addpattern.php b/ext/zip/examples/addpattern.php new file mode 100644 index 0000000000..a1a9b12291 --- /dev/null +++ b/ext/zip/examples/addpattern.php @@ -0,0 +1,13 @@ +<?php +$z = new ZipArchive; +$z->open('a.zip', ZIPARCHIVE::CREATE); + +/* or 'remove_all_path' => 0*/ +$options = array('remove_path' => '/home/pierre/cvs/gd/libgd/tests', +'add_path' => 'images/', +); + +$found = $z->addPattern("/(\.png)$/i", "/home/pierre/cvs/gd/libgd/tests", $options); +var_dump($found); +$z->close(); + diff --git a/ext/zip/lib/config.h b/ext/zip/lib/config.h new file mode 100644 index 0000000000..f9132ba439 --- /dev/null +++ b/ext/zip/lib/config.h @@ -0,0 +1,25 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 5 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997-2013 The PHP Group | + +----------------------------------------------------------------------+ + | 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 | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt. | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Author: Pierre-Alain Joye <pajoye@php.net> | + +----------------------------------------------------------------------+ +*/ +#ifdef HAVE_CONFIG_H +/* Building in PECL */ +#include "../config.h" + +#else +/* Building in PHP tree */ +#include "php_config.h" +#endif diff --git a/ext/zip/lib/mkstemp.c b/ext/zip/lib/mkstemp.c new file mode 100644 index 0000000000..843d5e3613 --- /dev/null +++ b/ext/zip/lib/mkstemp.c @@ -0,0 +1,151 @@ +/* Adapted from NetBSB libc by Dieter Baron */ + +/* NetBSD: gettemp.c,v 1.13 2003/12/05 00:57:36 uebayasi Exp */ + +/* + * Copyright (c) 1987, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR 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. + */ + +#include <sys/types.h> +#include <sys/stat.h> + +#include <assert.h> +#include <ctype.h> +#include <errno.h> +#include <fcntl.h> +#ifdef _WIN32 +#include <io.h> +#endif +#include <stdio.h> +#include <stdlib.h> + +#ifndef O_BINARY +#define O_BINARY 0 +#endif + + + +int +_zip_mkstemp(char *path) +{ +#ifdef _WIN32 + int ret; + ret = _creat(_mktemp(path), _S_IREAD|_S_IWRITE); + if (ret == -1) { + return 0; + } else { + return ret; + } +#else + int fd; + char *start, *trv; + struct stat sbuf; + pid_t pid; + + /* To guarantee multiple calls generate unique names even if + the file is not created. 676 different possibilities with 7 + or more X's, 26 with 6 or less. */ + static char xtra[2] = "aa"; + int xcnt = 0; + + pid = getpid(); + + /* Move to end of path and count trailing X's. */ + for (trv = path; *trv; ++trv) + if (*trv == 'X') + xcnt++; + else + xcnt = 0; + + /* Use at least one from xtra. Use 2 if more than 6 X's. */ + if (*(trv - 1) == 'X') + *--trv = xtra[0]; + if (xcnt > 6 && *(trv - 1) == 'X') + *--trv = xtra[1]; + + /* Set remaining X's to pid digits with 0's to the left. */ + while (*--trv == 'X') { + *trv = (pid % 10) + '0'; + pid /= 10; + } + + /* update xtra for next call. */ + if (xtra[0] != 'z') + xtra[0]++; + else { + xtra[0] = 'a'; + if (xtra[1] != 'z') + xtra[1]++; + else + xtra[1] = 'a'; + } + + /* + * check the target directory; if you have six X's and it + * doesn't exist this runs for a *very* long time. + */ + for (start = trv + 1;; --trv) { + if (trv <= path) + break; + if (*trv == '/') { + *trv = '\0'; + if (stat(path, &sbuf)) + return (0); + if (!S_ISDIR(sbuf.st_mode)) { + errno = ENOTDIR; + return (0); + } + *trv = '/'; + break; + } + } + + for (;;) { + if ((fd=open(path, O_CREAT|O_EXCL|O_RDWR|O_BINARY, 0600)) >= 0) + return (fd); + if (errno != EEXIST) + return (0); + + /* tricky little algorithm for backward compatibility */ + for (trv = start;;) { + if (!*trv) + return (0); + if (*trv == 'z') + *trv++ = 'a'; + else { + if (isdigit((unsigned char)*trv)) + *trv = 'a'; + else + ++*trv; + break; + } + } + } + /*NOTREACHED*/ +#endif +} diff --git a/ext/zip/lib/php_zip_config.w32.h b/ext/zip/lib/php_zip_config.w32.h new file mode 100644 index 0000000000..8956839c62 --- /dev/null +++ b/ext/zip/lib/php_zip_config.w32.h @@ -0,0 +1,57 @@ +#ifndef HAD_CONFIG_H
+#define HAD_CONFIG_H
+#define HAVE__CLOSE
+#define HAVE__DUP
+#define HAVE__FDOPEN
+#define HAVE__FILENO
+#define HAVE__OPEN
+#define HAVE__SNPRINTF
+/* #undef HAVE__STRCMPI */
+#define HAVE__STRDUP
+#define HAVE__STRICMP
+/* #undef HAVE_FSEEKO */
+/* #undef HAVE_FTELLO */
+/* #undef HAVE_MKSTEMP */
+#define HAVE_MOVEFILEEXA
+/* #undef HAVE_SNPRINTF */
+/* #undef HAVE_STRCASECMP */
+/* #undef HAVE_STRINGS_H */
+/* #undef HAVE_STRUCT_TM_TM_ZONE */
+/* #undef HAVE_UNISTD_H */
+#define PACKAGE "libzip"
+#define VERSION "0.10.b"
+
+/* #undef HAVE_SSIZE_T */
+
+#ifndef HAVE_SSIZE_T
+
+#ifndef SIZE_T_LIBZIP
+#define SIZE_T_LIBZIP 4
+#endif
+#ifndef INT_LIBZIP
+#define INT_LIBZIP 4
+#endif
+#ifndef LONG_LIBZIP
+#define LONG_LIBZIP 4
+#endif
+#ifndef LONG_LONG_LIBZIP
+#define LONG_LONG_LIBZIP 8
+#endif
+#ifndef SIZEOF_OFF_T
+#define SIZEOF_OFF_T 4
+#endif
+
+# if SIZE_T_LIBZIP == INT_LIBZIP
+# ifndef ssize_t
+typedef int ssize_t;
+# endif
+# elif SIZE_T_LIBZIP == LONG_LIBZIP
+typedef long ssize_t;
+# elif SIZE_T_LIBZIP == LONG_LONG_LIBZIP
+typedef long long ssize_t;
+# else
+#error no suitable type for ssize_t found
+# endif
+#endif
+
+#endif /* HAD_CONFIG_H */
diff --git a/ext/zip/lib/zip.h b/ext/zip/lib/zip.h index f11c9aba7f..1fb1dbf5e0 100644 --- a/ext/zip/lib/zip.h +++ b/ext/zip/lib/zip.h @@ -3,7 +3,7 @@ /* zip.h -- exported declarations. - Copyright (C) 1999-2011 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2012 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -38,18 +38,30 @@ #include "main/php.h" #ifdef PHP_WIN32 -# include "zip_win32.h" -# ifdef PHP_ZIP_EXPORTS -# define ZIP_EXTERN(rt) __declspec(dllexport)rt _stdcall -# else -# define ZIP_EXTERN(rt) rt -# endif +#ifdef PHP_ZIP_EXPORTS +# define ZIP_EXTERN __declspec(dllexport) _stdcall +# else +# define ZIP_EXTERN +# endif #elif defined(__GNUC__) && __GNUC__ >= 4 -# define ZIP_EXTERN(rt) __attribute__ ((visibility("default"))) rt +# define ZIP_EXTERN __attribute__ ((visibility("default"))) #else -# define ZIP_EXTERN(rt) rt +# define ZIP_EXTERN #endif + +#ifndef ZIP_EXTERN +#ifdef _WIN32 +#define ZIP_EXTERN __declspec(dllimport) +#elif defined(__GNUC__) && __GNUC__ >= 4 +#define ZIP_EXTERN __attribute__ ((visibility ("default"))) +#else +#define ZIP_EXTERN +#endif +#endif + + + BEGIN_EXTERN_C() #include "zipconf.h" @@ -63,27 +75,40 @@ BEGIN_EXTERN_C() #define ZIP_CREATE 1 #define ZIP_EXCL 2 #define ZIP_CHECKCONS 4 -#define ZIP_OVERWRITE 8 - +#define ZIP_TRUNCATE 8 /* flags for zip_name_locate, zip_fopen, zip_stat, ... */ -#define ZIP_FL_NOCASE 1 /* ignore case on name lookup */ -#define ZIP_FL_NODIR 2 /* ignore directory component */ -#define ZIP_FL_COMPRESSED 4 /* read compressed data */ -#define ZIP_FL_UNCHANGED 8 /* use original data, ignoring changes */ -#define ZIP_FL_RECOMPRESS 16 /* force recompression of data */ -#define ZIP_FL_ENCRYPTED 32 /* read encrypted data - (implies ZIP_FL_COMPRESSED) */ +#define ZIP_FL_NOCASE 1u /* ignore case on name lookup */ +#define ZIP_FL_NODIR 2u /* ignore directory component */ +#define ZIP_FL_COMPRESSED 4u /* read compressed data */ +#define ZIP_FL_UNCHANGED 8u /* use original data, ignoring changes */ +#define ZIP_FL_RECOMPRESS 16u /* force recompression of data */ +#define ZIP_FL_ENCRYPTED 32u /* read encrypted data (implies ZIP_FL_COMPRESSED) */ +#define ZIP_FL_ENC_GUESS 0u /* guess string encoding (is default) */ +#define ZIP_FL_ENC_RAW 64u /* get unmodified string */ +#define ZIP_FL_ENC_STRICT 128u /* follow specification strictly */ +#define ZIP_FL_LOCAL 256u /* in local header */ +#define ZIP_FL_CENTRAL 512u /* in central directory */ +/* 1024u reserved for internal use */ +#define ZIP_FL_ENC_UTF_8 2048u /* string is UTF-8 encoded */ +#define ZIP_FL_ENC_CP437 4096u /* string is CP437 encoded */ +#define ZIP_FL_OVERWRITE 8192u /* zip_file_add: if file with name exists, overwrite (replace) it */ /* archive global flags flags */ -#define ZIP_AFL_TORRENT 1 /* torrent zipped */ -#define ZIP_AFL_RDONLY 2 /* read only -- cannot be cleared */ +#define ZIP_AFL_TORRENT 1u /* torrent zipped */ +#define ZIP_AFL_RDONLY 2u /* read only -- cannot be cleared */ + +/* create a new extra field */ + +#define ZIP_EXTRA_FIELD_ALL ZIP_UINT16_MAX +#define ZIP_EXTRA_FIELD_NEW ZIP_UINT16_MAX /* flags for compression and encryption sources */ +#define ZIP_CODEC_DECODE 0 /* decompress/decrypt (encode flag not set) */ #define ZIP_CODEC_ENCODE 1 /* compress/encrypt */ @@ -178,15 +203,15 @@ enum zip_source_cmd { #define ZIP_SOURCE_ERR_LOWER -2 -#define ZIP_STAT_NAME 0x0001 -#define ZIP_STAT_INDEX 0x0002 -#define ZIP_STAT_SIZE 0x0004 -#define ZIP_STAT_COMP_SIZE 0x0008 -#define ZIP_STAT_MTIME 0x0010 -#define ZIP_STAT_CRC 0x0020 -#define ZIP_STAT_COMP_METHOD 0x0040 -#define ZIP_STAT_ENCRYPTION_METHOD 0x0080 -#define ZIP_STAT_FLAGS 0x0100 +#define ZIP_STAT_NAME 0x0001u +#define ZIP_STAT_INDEX 0x0002u +#define ZIP_STAT_SIZE 0x0004u +#define ZIP_STAT_COMP_SIZE 0x0008u +#define ZIP_STAT_MTIME 0x0010u +#define ZIP_STAT_CRC 0x0020u +#define ZIP_STAT_COMP_METHOD 0x0040u +#define ZIP_STAT_ENCRYPTION_METHOD 0x0080u +#define ZIP_STAT_FLAGS 0x0100u struct zip_stat { zip_uint64_t valid; /* which fields have valid values */ @@ -205,72 +230,78 @@ struct zip; struct zip_file; struct zip_source; +typedef zip_uint32_t zip_flags_t; + typedef zip_int64_t (*zip_source_callback)(void *, void *, zip_uint64_t, enum zip_source_cmd); -ZIP_EXTERN(zip_int64_t) zip_add(struct zip *, const char *, struct zip_source *); -ZIP_EXTERN(zip_int64_t) zip_add_dir(struct zip *, const char *); -ZIP_EXTERN(int) zip_close(struct zip *); -ZIP_EXTERN(int) zip_delete(struct zip *, zip_uint64_t); -ZIP_EXTERN(void) zip_error_clear(struct zip *); -ZIP_EXTERN(void) zip_error_get(struct zip *, int *, int *); -ZIP_EXTERN(int) zip_error_get_sys_type(int); -ZIP_EXTERN(int) zip_error_to_str(char *, zip_uint64_t, int, int); -ZIP_EXTERN(int) zip_fclose(struct zip_file *); -ZIP_EXTERN(struct zip *)zip_fdopen(int, int, int *); -ZIP_EXTERN(void) zip_file_error_clear(struct zip_file *); -ZIP_EXTERN(void) zip_file_error_get(struct zip_file *, int *, int *); -ZIP_EXTERN(const char *)zip_file_strerror(struct zip_file *); -ZIP_EXTERN(struct) zip_file *zip_fopen(struct zip *, const char *, int); -ZIP_EXTERN(struct) zip_file *zip_fopen_encrypted(struct zip *, const char *, - int, const char *); -ZIP_EXTERN(struct zip_file *)zip_fopen_index(struct zip *, zip_uint64_t, int); -ZIP_EXTERN(struct zip_file *)zip_fopen_index_encrypted(struct zip *, - zip_uint64_t, int, - const char *); -ZIP_EXTERN(zip_int64_t) zip_fread(struct zip_file *, void *, zip_uint64_t); -ZIP_EXTERN(const char *)zip_get_archive_comment(struct zip *, int *, int); -ZIP_EXTERN(int) zip_get_archive_flag(struct zip *, int, int); -ZIP_EXTERN(const char *)zip_get_file_comment(struct zip *, zip_uint64_t, - int *, int); -ZIP_EXTERN(const char *)zip_get_file_extra(struct zip *, zip_uint64_t, - int *, int); -ZIP_EXTERN(const char *)zip_get_name(struct zip *, zip_uint64_t, int); -ZIP_EXTERN(zip_uint64_t) zip_get_num_entries(struct zip *, int); -ZIP_EXTERN(int) zip_get_num_files(struct zip *); /* deprecated, use zip_get_num_entries instead */ -ZIP_EXTERN(int) zip_name_locate(struct zip *, const char *, int); -ZIP_EXTERN(struct zip *)zip_open(const char *, int, int *); -ZIP_EXTERN(int) zip_rename(struct zip *, zip_uint64_t, const char *); -ZIP_EXTERN(int) zip_replace(struct zip *, zip_uint64_t, struct zip_source *); -ZIP_EXTERN(int) zip_set_archive_comment(struct zip *, const char *, int); -ZIP_EXTERN(int) zip_set_archive_flag(struct zip *, int, int); -ZIP_EXTERN(int) zip_set_default_password(struct zip *, const char *); -ZIP_EXTERN(int) zip_set_file_comment(struct zip *, zip_uint64_t, - const char *, int); -ZIP_EXTERN(int) zip_set_file_extra(struct zip *, zip_uint64_t, - const char *, int); -ZIP_EXTERN(struct) zip_source *zip_source_buffer(struct zip *, const void *, - zip_uint64_t, int); -ZIP_EXTERN(struct) zip_source *zip_source_file(struct zip *, const char *, - zip_uint64_t, zip_int64_t); -ZIP_EXTERN(struct) zip_source *zip_source_filep(struct zip *, FILE *, - zip_uint64_t, zip_int64_t); -ZIP_EXTERN(void) zip_source_free(struct zip_source *); -ZIP_EXTERN(struct zip_source *)zip_source_function(struct zip *, - zip_source_callback, void *); -ZIP_EXTERN(struct zip_source *)zip_source_zip(struct zip *, struct zip *, - zip_uint64_t, int, - zip_uint64_t, zip_int64_t); -ZIP_EXTERN(int) zip_stat(struct zip *, const char *, int, struct zip_stat *); -ZIP_EXTERN(int) zip_stat_index(struct zip *, zip_uint64_t, int, - struct zip_stat *); -ZIP_EXTERN(void) zip_stat_init(struct zip_stat *); -ZIP_EXTERN(const char *)zip_strerror(struct zip *); -ZIP_EXTERN(int) zip_unchange(struct zip *, zip_uint64_t); -ZIP_EXTERN(int) zip_unchange_all(struct zip *); -ZIP_EXTERN(int) zip_unchange_archive(struct zip *); +#ifndef ZIP_DISABLE_DEPRECATED +ZIP_EXTERN zip_int64_t zip_add(struct zip *, const char *, struct zip_source *); /* use zip_file_add */ +ZIP_EXTERN zip_int64_t zip_add_dir(struct zip *, const char *); /* use zip_dir_add */ +ZIP_EXTERN const char *zip_get_file_comment(struct zip *, zip_uint64_t, int *, int); /* use zip_file_get_comment */ +ZIP_EXTERN int zip_get_num_files(struct zip *); /* use zip_get_num_entries instead */ +ZIP_EXTERN int zip_rename(struct zip *, zip_uint64_t, const char *); /* use zip_file_rename */ +ZIP_EXTERN int zip_replace(struct zip *, zip_uint64_t, struct zip_source *); /* use zip_file_replace */ +ZIP_EXTERN int zip_set_file_comment(struct zip *, zip_uint64_t, const char *, int); /* use zip_file_set_comment */ +#endif + +ZIP_EXTERN int zip_archive_set_tempdir(struct zip *, const char *); +ZIP_EXTERN zip_int64_t zip_file_add(struct zip *, const char *, struct zip_source *, zip_flags_t); +ZIP_EXTERN zip_int64_t zip_dir_add(struct zip *, const char *, zip_flags_t); +ZIP_EXTERN int zip_close(struct zip *); +ZIP_EXTERN void zip_discard(struct zip *); +ZIP_EXTERN int zip_delete(struct zip *, zip_uint64_t); +ZIP_EXTERN int zip_file_extra_field_delete(struct zip *, zip_uint64_t, zip_uint16_t, zip_flags_t); +ZIP_EXTERN int zip_file_extra_field_delete_by_id(struct zip *, zip_uint64_t, zip_uint16_t, zip_uint16_t, zip_flags_t); +ZIP_EXTERN void zip_error_clear(struct zip *); +ZIP_EXTERN void zip_error_get(struct zip *, int *, int *); +ZIP_EXTERN int zip_error_get_sys_type(int); +ZIP_EXTERN int zip_error_to_str(char *, zip_uint64_t, int, int); +ZIP_EXTERN int zip_fclose(struct zip_file *); +ZIP_EXTERN struct zip *zip_fdopen(int, int, int *); +ZIP_EXTERN void zip_file_error_clear(struct zip_file *); +ZIP_EXTERN void zip_file_error_get(struct zip_file *, int *, int *); +ZIP_EXTERN const char *zip_file_strerror(struct zip_file *); +ZIP_EXTERN struct zip_file *zip_fopen(struct zip *, const char *, zip_flags_t); +ZIP_EXTERN struct zip_file *zip_fopen_encrypted(struct zip *, const char *, zip_flags_t, const char *); +ZIP_EXTERN struct zip_file *zip_fopen_index(struct zip *, zip_uint64_t, zip_flags_t); +ZIP_EXTERN struct zip_file *zip_fopen_index_encrypted(struct zip *, zip_uint64_t, zip_flags_t, const char *); +ZIP_EXTERN zip_int64_t zip_fread(struct zip_file *, void *, zip_uint64_t); +ZIP_EXTERN const char *zip_get_archive_comment(struct zip *, int *, zip_flags_t); +ZIP_EXTERN int zip_get_archive_flag(struct zip *, zip_flags_t, zip_flags_t); +ZIP_EXTERN const char *zip_file_get_comment(struct zip *, zip_uint64_t, zip_uint32_t *, zip_flags_t); +ZIP_EXTERN const zip_uint8_t *zip_file_extra_field_get(struct zip *, zip_uint64_t, zip_uint16_t, zip_uint16_t *, zip_uint16_t *, zip_flags_t); +ZIP_EXTERN const zip_uint8_t *zip_file_extra_field_get_by_id(struct zip *, zip_uint64_t, zip_uint16_t, zip_uint16_t, zip_uint16_t *, zip_flags_t); +ZIP_EXTERN zip_int16_t zip_file_extra_fields_count(struct zip *, zip_uint64_t, zip_flags_t); +ZIP_EXTERN zip_int16_t zip_file_extra_fields_count_by_id(struct zip *, zip_uint64_t, zip_uint16_t, zip_flags_t); +ZIP_EXTERN const char *zip_get_name(struct zip *, zip_uint64_t, zip_flags_t); +ZIP_EXTERN zip_int64_t zip_get_num_entries(struct zip *, zip_flags_t); +ZIP_EXTERN zip_int64_t zip_name_locate(struct zip *, const char *, zip_flags_t); +ZIP_EXTERN struct zip *zip_open(const char *, int, int *); +ZIP_EXTERN int zip_file_rename(struct zip *, zip_uint64_t, const char *, zip_flags_t); +ZIP_EXTERN int zip_file_replace(struct zip *, zip_uint64_t, struct zip_source *, zip_flags_t); +ZIP_EXTERN int zip_set_archive_comment(struct zip *, const char *, zip_uint16_t); +ZIP_EXTERN int zip_set_archive_flag(struct zip *, zip_flags_t, int); +ZIP_EXTERN int zip_set_default_password(struct zip *, const char *); +ZIP_EXTERN int zip_file_set_comment(struct zip *, zip_uint64_t, const char *, zip_uint16_t, zip_flags_t); +ZIP_EXTERN int zip_set_file_compression(struct zip *, zip_uint64_t, zip_int32_t, zip_uint32_t); +ZIP_EXTERN int zip_file_extra_field_set(struct zip *, zip_uint64_t, zip_uint16_t, zip_uint16_t, const zip_uint8_t *, zip_uint16_t, zip_flags_t); +ZIP_EXTERN struct zip_source *zip_source_buffer(struct zip *, const void *, zip_uint64_t, int); +ZIP_EXTERN struct zip_source *zip_source_file(struct zip *, const char *, zip_uint64_t, zip_int64_t); +ZIP_EXTERN struct zip_source *zip_source_filep(struct zip *, FILE *, zip_uint64_t, zip_int64_t); +ZIP_EXTERN void zip_source_free(struct zip_source *); +ZIP_EXTERN struct zip_source *zip_source_function(struct zip *, zip_source_callback, void *); +ZIP_EXTERN struct zip_source *zip_source_zip(struct zip *, struct zip *, zip_uint64_t, zip_flags_t, zip_uint64_t, zip_int64_t); +ZIP_EXTERN int zip_stat(struct zip *, const char *, zip_flags_t, struct zip_stat *); +ZIP_EXTERN int zip_stat_index(struct zip *, zip_uint64_t, zip_flags_t, struct zip_stat *); +ZIP_EXTERN void zip_stat_init(struct zip_stat *); +ZIP_EXTERN const char *zip_strerror(struct zip *); +ZIP_EXTERN int zip_unchange(struct zip *, zip_uint64_t); +ZIP_EXTERN int zip_unchange_all(struct zip *); +ZIP_EXTERN int zip_unchange_archive(struct zip *); + END_EXTERN_C(); #endif /* _HAD_ZIP_H */ diff --git a/ext/zip/lib/zip_add.c b/ext/zip/lib/zip_add.c index 6067abbac4..4bce3fd4af 100644 --- a/ext/zip/lib/zip_add.c +++ b/ext/zip/lib/zip_add.c @@ -1,6 +1,6 @@ /* zip_add.c -- add file via callback function - Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2012 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -33,6 +33,7 @@ +#define _ZIP_COMPILING_DEPRECATED #include "zipint.h" @@ -44,13 +45,8 @@ ZIP_UINT64_MAX, and each entry is larger than 2 bytes. */ -ZIP_EXTERN(zip_int64_t) +ZIP_EXTERN zip_int64_t zip_add(struct zip *za, const char *name, struct zip_source *source) { - if (name == NULL || source == NULL) { - _zip_error_set(&za->error, ZIP_ER_INVAL, 0); - return -1; - } - - return _zip_replace(za, ZIP_UINT64_MAX, name, source); + return zip_file_add(za, name, source, 0); } diff --git a/ext/zip/lib/zip_add_dir.c b/ext/zip/lib/zip_add_dir.c index 0a9d7f4863..22a28bd856 100644 --- a/ext/zip/lib/zip_add_dir.c +++ b/ext/zip/lib/zip_add_dir.c @@ -1,6 +1,6 @@ /* zip_add_dir.c -- add directory - Copyright (C) 1999-2009 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2013 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -33,56 +33,15 @@ -#include <stdlib.h> -#include <string.h> - +#define _ZIP_COMPILING_DEPRECATED #include "zipint.h" /* NOTE: Signed due to -1 on error. See zip_add.c for more details. */ -ZIP_EXTERN(zip_int64_t) +ZIP_EXTERN zip_int64_t zip_add_dir(struct zip *za, const char *name) { - int len; - zip_int64_t ret; - char *s; - struct zip_source *source; - - if (ZIP_IS_RDONLY(za)) { - _zip_error_set(&za->error, ZIP_ER_RDONLY, 0); - return -1; - } - - if (name == NULL) { - _zip_error_set(&za->error, ZIP_ER_INVAL, 0); - return -1; - } - - s = NULL; - len = strlen(name); - - if (name[len-1] != '/') { - if ((s=(char *)malloc(len+2)) == NULL) { - _zip_error_set(&za->error, ZIP_ER_MEMORY, 0); - return -1; - } - strcpy(s, name); - s[len] = '/'; - s[len+1] = '\0'; - } - - if ((source=zip_source_buffer(za, NULL, 0, 0)) == NULL) { - free(s); - return -1; - } - - ret = _zip_replace(za, -1, s ? s : name, source); - - free(s); - if (ret < 0) - zip_source_free(source); - - return ret; + return zip_dir_add(za, name, 0); } diff --git a/ext/zip/lib/zip_add_entry.c b/ext/zip/lib/zip_add_entry.c new file mode 100644 index 0000000000..3a7e2ccbe9 --- /dev/null +++ b/ext/zip/lib/zip_add_entry.c @@ -0,0 +1,66 @@ +/* + zip_add_entry.c -- create and init struct zip_entry + Copyright (C) 1999-2012 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR 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. +*/ + + + +#include <stdlib.h> + +#include "zipint.h" + + + +/* NOTE: Signed due to -1 on error. See zip_add.c for more details. */ + +zip_int64_t +_zip_add_entry(struct zip *za) +{ + zip_uint64_t idx; + + if (za->nentry+1 >= za->nentry_alloc) { + struct zip_entry *rentries; + zip_uint64_t nalloc = za->nentry_alloc + 16; + rentries = (struct zip_entry *)realloc(za->entry, sizeof(struct zip_entry) * nalloc); + if (!rentries) { + _zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return -1; + } + za->entry = rentries; + za->nentry_alloc = nalloc; + } + + idx = za->nentry++; + + _zip_entry_init(za->entry+idx); + + return (zip_int64_t)idx; +} diff --git a/ext/zip/lib/zip_close.c b/ext/zip/lib/zip_close.c index 576be3b353..c9c7e58088 100644 --- a/ext/zip/lib/zip_close.c +++ b/ext/zip/lib/zip_close.c @@ -38,6 +38,9 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#ifdef HAVE_STRINGS_H +#include <strings.h> +#endif #include <errno.h> #ifdef HAVE_UNISTD_H #include <unistd.h> @@ -49,110 +52,106 @@ #include <fcntl.h> #endif -static int add_data(struct zip *, struct zip_source *, struct zip_dirent *, - FILE *); -static int copy_data(FILE *, off_t, FILE *, struct zip_error *); + + +/* max deflate size increase: size + ceil(size/16k)*5+6 */ +#define MAX_DEFLATE_SIZE_32 4293656963u + +static int add_data(struct zip *, struct zip_source *, struct zip_dirent *, FILE *); +static int copy_data(FILE *, zip_uint64_t, FILE *, struct zip_error *); static int copy_source(struct zip *, struct zip_source *, FILE *); -static int write_cdir(struct zip *, struct zip_cdir *, FILE *); -static int _zip_cdir_set_comment(struct zip_cdir *, struct zip *); +static int write_cdir(struct zip *, const struct zip_filelist *, zip_uint64_t, FILE *); static char *_zip_create_temp_output(struct zip *, FILE **); static int _zip_torrentzip_cmp(const void *, const void *); -struct filelist { - int idx; - const char *name; -}; - - - -ZIP_EXTERN(int) +ZIP_EXTERN int zip_close(struct zip *za) { - int survivors; - int i, j, error; + zip_uint64_t i, j, survivors; + int error; char *temp; FILE *out; #ifndef PHP_WIN32 mode_t mask; #endif - struct zip_cdir *cd; - struct zip_dirent de; - struct filelist *filelist; + struct zip_filelist *filelist; int reopen_on_error; int new_torrentzip; + int changed; reopen_on_error = 0; if (za == NULL) return -1; - if (!_zip_changed(za, &survivors)) { - _zip_free(za); - return 0; - } + changed = _zip_changed(za, &survivors); /* don't create zip files with no entries */ if (survivors == 0) { - if (za->zn && za->zp) { + if (za->zn && ((za->open_flags & ZIP_TRUNCATE) || (changed && za->zp))) { if (remove(za->zn) != 0) { _zip_error_set(&za->error, ZIP_ER_REMOVE, errno); return -1; } } - _zip_free(za); + zip_discard(za); return 0; } - if ((filelist=(struct filelist *)malloc(sizeof(filelist[0])*survivors)) - == NULL) - return -1; - - if ((cd=_zip_cdir_new(survivors, &za->error)) == NULL) { - free(filelist); - return -1; + if (!changed) { + zip_discard(za); + return 0; } - for (i=0; i<survivors; i++) - _zip_dirent_init(&cd->entry[i]); + if (survivors > za->nentry) { + _zip_error_set(&za->error, ZIP_ER_INTERNAL, 0); + return -1; + } + + if ((filelist=(struct zip_filelist *)malloc(sizeof(filelist[0])*survivors)) == NULL) + return -1; /* archive comment is special for torrentzip */ if (zip_get_archive_flag(za, ZIP_AFL_TORRENT, 0)) { - cd->comment = _zip_memdup(TORRENT_SIG "XXXXXXXX", - TORRENT_SIG_LEN + TORRENT_CRC_LEN, - &za->error); - if (cd->comment == NULL) { - _zip_cdir_free(cd); - free(filelist); - return -1; - } - cd->comment_len = TORRENT_SIG_LEN + TORRENT_CRC_LEN; - } - else if (zip_get_archive_flag(za, ZIP_AFL_TORRENT, ZIP_FL_UNCHANGED) == 0) { - if (_zip_cdir_set_comment(cd, za) == -1) { - _zip_cdir_free(cd); + /* XXX: use internal function when zip_set_archive_comment clears TORRENT flag */ + if (zip_set_archive_comment(za, TORRENT_SIG "XXXXXXXX", TORRENT_SIG_LEN + TORRENT_CRC_LEN) < 0) { free(filelist); return -1; } } - - if ((temp=_zip_create_temp_output(za, &out)) == NULL) { - _zip_cdir_free(cd); - free(filelist); - return -1; - } + /* XXX: if no longer torrentzip and archive comment not changed by user, delete it */ /* create list of files with index into original archive */ for (i=j=0; i<za->nentry; i++) { - if (za->entry[i].state == ZIP_ST_DELETED) + if (za->entry[i].deleted) continue; + if (j >= survivors) { + free(filelist); + _zip_error_set(&za->error, ZIP_ER_INTERNAL, 0); + return -1; + } + filelist[j].idx = i; filelist[j].name = zip_get_name(za, i, 0); j++; } + if (j < survivors) { + free(filelist); + _zip_error_set(&za->error, ZIP_ER_INTERNAL, 0); + return -1; + } + + + if ((temp=_zip_create_temp_output(za, &out)) == NULL) { + free(filelist); + return -1; + } + + if (zip_get_archive_flag(za, ZIP_AFL_TORRENT, 0)) qsort(filelist, survivors, sizeof(filelist[0]), _zip_torrentzip_cmp); @@ -162,106 +161,49 @@ zip_close(struct zip *za) ZIP_FL_UNCHANGED) == 0); error = 0; for (j=0; j<survivors; j++) { + int new_data; + struct zip_entry *entry; + struct zip_dirent *de; + i = filelist[j].idx; + entry = za->entry+i; - _zip_dirent_init(&de); + new_data = (ZIP_ENTRY_DATA_CHANGED(entry) || new_torrentzip || ZIP_ENTRY_CHANGED(entry, ZIP_DIRENT_COMP_METHOD)); /* create new local directory entry */ - if (ZIP_ENTRY_DATA_CHANGED(za->entry+i) || new_torrentzip) { - - if (zip_get_archive_flag(za, ZIP_AFL_TORRENT, 0)) - _zip_dirent_torrent_normalize(&de); - - /* use it as central directory entry */ - memcpy(cd->entry+j, &de, sizeof(cd->entry[j])); - - /* set/update file name */ - if (za->entry[i].ch_filename == NULL) { - if (za->entry[i].state == ZIP_ST_ADDED) { - de.filename = strdup("-"); - de.filename_len = 1; - cd->entry[j].filename = "-"; - cd->entry[j].filename_len = 1; - } - else { - de.filename = strdup(za->cdir->entry[i].filename); - de.filename_len = strlen(de.filename); - cd->entry[j].filename = za->cdir->entry[i].filename; - cd->entry[j].filename_len = de.filename_len; - } + if (entry->changes == NULL) { + if ((entry->changes=_zip_dirent_clone(entry->orig)) == NULL) { + _zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + error = 1; + break; } } - else { - /* copy existing directory entries */ - 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; - } - if (_zip_dirent_read(&de, za->zp, NULL, NULL, 1, - &za->error) != 0) { - error = 1; - break; - } - memcpy(cd->entry+j, za->cdir->entry+i, sizeof(cd->entry[j])); - if (de.bitflags & ZIP_GPBF_DATA_DESCRIPTOR) { - de.crc = za->cdir->entry[i].crc; - de.comp_size = za->cdir->entry[i].comp_size; - de.uncomp_size = za->cdir->entry[i].uncomp_size; - de.bitflags &= ~ZIP_GPBF_DATA_DESCRIPTOR; - cd->entry[j].bitflags &= ~ZIP_GPBF_DATA_DESCRIPTOR; - } - } + de = entry->changes; - if (za->entry[i].ch_filename) { - free(de.filename); - if ((de.filename=strdup(za->entry[i].ch_filename)) == NULL) { - error = 1; - break; - } - de.filename_len = strlen(de.filename); - cd->entry[j].filename = za->entry[i].ch_filename; - cd->entry[j].filename_len = de.filename_len; + if (_zip_read_local_ef(za, i) < 0) { + error = 1; + break; } - if (za->entry[i].ch_extra_len != -1) { - free(de.extrafield); - if ((de.extrafield=malloc(za->entry[i].ch_extra_len)) == NULL) { - error = 1; - break; - } - memcpy(de.extrafield, za->entry[i].ch_extra, za->entry[i].ch_extra_len); - de.extrafield_len = za->entry[i].ch_extra_len; - /* as the rest of cd entries, its malloc/free is done by za */ - /* TODO unsure if this should also be set in the CD -- - * not done for now - cd->entry[j].extrafield = za->entry[i].ch_extra; - cd->entry[j].extrafield_len = za->entry[i].ch_extra_len; - */ - } + if (zip_get_archive_flag(za, ZIP_AFL_TORRENT, 0)) + _zip_dirent_torrent_normalize(entry->changes); - if (zip_get_archive_flag(za, ZIP_AFL_TORRENT, 0) == 0 - && za->entry[i].ch_comment_len != -1) { - /* as the rest of cd entries, its malloc/free is done by za */ - cd->entry[j].comment = za->entry[i].ch_comment; - cd->entry[j].comment_len = za->entry[i].ch_comment_len; - } - cd->entry[j].offset = ftello(out); + de->offset = (zip_uint64_t)ftello(out); /* XXX: check for errors */ - if (ZIP_ENTRY_DATA_CHANGED(za->entry+i) || new_torrentzip) { + if (new_data) { struct zip_source *zs; zs = NULL; - if (!ZIP_ENTRY_DATA_CHANGED(za->entry+i)) { - if ((zs=zip_source_zip(za, za, i, ZIP_FL_RECOMPRESS, 0, -1)) - == NULL) { + if (!ZIP_ENTRY_DATA_CHANGED(entry)) { + if ((zs=_zip_source_zip_new(za, za, i, ZIP_FL_UNCHANGED, 0, 0, NULL)) == NULL) { error = 1; break; } } - if (add_data(za, zs ? zs : za->entry[i].source, &de, out) < 0) { + /* add_data writes dirent */ + if (add_data(za, zs ? zs : entry->source, de, out) < 0) { error = 1; if (zs) zip_source_free(zs); @@ -269,51 +211,49 @@ zip_close(struct zip *za) } if (zs) zip_source_free(zs); - - cd->entry[j].last_mod = de.last_mod; - cd->entry[j].comp_method = de.comp_method; - cd->entry[j].comp_size = de.comp_size; - cd->entry[j].uncomp_size = de.uncomp_size; - cd->entry[j].crc = de.crc; } else { - if (_zip_dirent_write(&de, out, 1, &za->error) < 0) { + zip_uint64_t offset; + + /* when copying data, all sizes are known -> no data descriptor needed */ + de->bitflags &= ~ZIP_GPBF_DATA_DESCRIPTOR; + if (_zip_dirent_write(de, out, ZIP_FL_LOCAL, &za->error) < 0) { error = 1; break; } - /* we just read the local dirent, file is at correct position */ - if (copy_data(za->zp, cd->entry[j].comp_size, out, - &za->error) < 0) { + if ((offset=_zip_file_get_offset(za, i, &za->error)) == 0) { + error = 1; + break; + } + if ((fseek(za->zp, (off_t)offset, SEEK_SET) < 0)) { + _zip_error_set(&za->error, ZIP_ER_SEEK, errno); + error = 1; + break; + } + if (copy_data(za->zp, de->comp_size, out, &za->error) < 0) { error = 1; break; } } - - _zip_dirent_finalize(&de); } - free(filelist); - if (!error) { - if (write_cdir(za, cd, out) < 0) + if (write_cdir(za, filelist, survivors, out) < 0) error = 1; } - /* pointers in cd entries are owned by za */ - cd->nentry = 0; - _zip_cdir_free(cd); + free(filelist); if (error) { - _zip_dirent_finalize(&de); fclose(out); - remove(temp); + (void)remove(temp); free(temp); return -1; } if (fclose(out) != 0) { _zip_error_set(&za->error, ZIP_ER_CLOSE, errno); - remove(temp); + (void)remove(temp); free(temp); return -1; } @@ -325,7 +265,7 @@ zip_close(struct zip *za) } if (_zip_rename(temp, za->zn) != 0) { _zip_error_set(&za->error, ZIP_ER_RENAME, errno); - remove(temp); + (void)remove(temp); free(temp); if (reopen_on_error) { /* ignore errors, since we're already in an error case */ @@ -339,56 +279,112 @@ zip_close(struct zip *za) chmod(za->zn, 0666&~mask); #endif - _zip_free(za); - free(temp); - + zip_discard(za); + free(temp); + return 0; } static int -add_data(struct zip *za, struct zip_source *src, struct zip_dirent *de, - FILE *ft) +add_data(struct zip *za, struct zip_source *src, struct zip_dirent *de, FILE *ft) { off_t offstart, offdata, offend; struct zip_stat st; struct zip_source *s2; - zip_compression_implementation comp_impl; int ret; + int is_zip64; + zip_flags_t flags; if (zip_source_stat(src, &st) < 0) { _zip_error_set_from_source(&za->error, src); return -1; } + if ((st.valid & ZIP_STAT_COMP_METHOD) == 0) { + st.valid |= ZIP_STAT_COMP_METHOD; + st.comp_method = ZIP_CM_STORE; + } + + if (ZIP_CM_IS_DEFAULT(de->comp_method) && st.comp_method != ZIP_CM_STORE) + de->comp_method = st.comp_method; + else if (de->comp_method == ZIP_CM_STORE && (st.valid & ZIP_STAT_SIZE)) { + st.valid |= ZIP_STAT_COMP_SIZE; + st.comp_size = st.size; + } + else { + /* we'll recompress */ + st.valid &= ~ZIP_STAT_COMP_SIZE; + } + + + flags = ZIP_EF_LOCAL; + + if ((st.valid & ZIP_STAT_SIZE) == 0) + flags |= ZIP_FL_FORCE_ZIP64; + else { + de->uncomp_size = st.size; + + if ((st.valid & ZIP_STAT_COMP_SIZE) == 0) { + if (( ((de->comp_method == ZIP_CM_DEFLATE || ZIP_CM_IS_DEFAULT(de->comp_method)) && st.size > MAX_DEFLATE_SIZE_32) + || (de->comp_method != ZIP_CM_STORE && de->comp_method != ZIP_CM_DEFLATE && !ZIP_CM_IS_DEFAULT(de->comp_method)))) + flags |= ZIP_FL_FORCE_ZIP64; + } + else + de->comp_size = st.comp_size; + } + + offstart = ftello(ft); - if (_zip_dirent_write(de, ft, 1, &za->error) < 0) + /* as long as we don't support non-seekable output, clear data descriptor bit */ + de->bitflags &= ~ZIP_GPBF_DATA_DESCRIPTOR; + if ((is_zip64=_zip_dirent_write(de, ft, flags, &za->error)) < 0) return -1; - if ((s2=zip_source_crc(za, src, 0)) == NULL) { - zip_source_pop(s2); - return -1; - } - - /* XXX: deflate 0-byte files for torrentzip? */ - if (((st.valid & ZIP_STAT_COMP_METHOD) == 0 - || st.comp_method == ZIP_CM_STORE) - && ((st.valid & ZIP_STAT_SIZE) == 0 || st.size != 0)) { - comp_impl = NULL; - if ((comp_impl=zip_get_compression_implementation(ZIP_CM_DEFLATE)) - == NULL) { - _zip_error_set(&za->error, ZIP_ER_COMPNOTSUPP, 0); - zip_source_pop(s2); - return -1; + + if (st.comp_method == ZIP_CM_STORE || (ZIP_CM_IS_DEFAULT(de->comp_method) && st.comp_method != de->comp_method)) { + struct zip_source *s_store, *s_crc; + zip_compression_implementation comp_impl; + + if (st.comp_method != ZIP_CM_STORE) { + if ((comp_impl=_zip_get_compression_implementation(st.comp_method)) == NULL) { + _zip_error_set(&za->error, ZIP_ER_COMPNOTSUPP, 0); + return -1; + } + if ((s_store=comp_impl(za, src, st.comp_method, ZIP_CODEC_DECODE)) == NULL) { + /* error set by comp_impl */ + return -1; + } } - if ((s2=comp_impl(za, s2, ZIP_CM_DEFLATE, ZIP_CODEC_ENCODE)) - == NULL) { - /* XXX: set error? */ - zip_source_pop(s2); + else + s_store = src; + + if ((s_crc=zip_source_crc(za, s_store, 0)) == NULL) { + if (s_store != src) + zip_source_pop(s_store); return -1; } + + /* XXX: deflate 0-byte files for torrentzip? */ + if (de->comp_method != ZIP_CM_STORE && ((st.valid & ZIP_STAT_SIZE) == 0 || st.size != 0)) { + if ((comp_impl=_zip_get_compression_implementation(de->comp_method)) == NULL) { + _zip_error_set(&za->error, ZIP_ER_COMPNOTSUPP, 0); + zip_source_pop(s_crc); + if (s_store != src) + zip_source_pop(s_store); + return -1; + } + if ((s2=comp_impl(za, s_crc, de->comp_method, ZIP_CODEC_ENCODE)) == NULL) { + zip_source_pop(s_crc); + if (s_store != src) + zip_source_pop(s_store); + return -1; + } + } + else + s2 = s_crc; } else s2 = src; @@ -418,18 +414,33 @@ add_data(struct zip *za, struct zip_source *src, struct zip_dirent *de, return -1; } - de->last_mod = st.mtime; + if ((st.valid & (ZIP_STAT_COMP_METHOD|ZIP_STAT_CRC|ZIP_STAT_SIZE)) != (ZIP_STAT_COMP_METHOD|ZIP_STAT_CRC|ZIP_STAT_SIZE)) { + _zip_error_set(&za->error, ZIP_ER_INTERNAL, 0); + return -1; + } + + if (st.valid & ZIP_STAT_MTIME) + de->last_mod = st.mtime; + else + time(&de->last_mod); de->comp_method = st.comp_method; de->crc = st.crc; de->uncomp_size = st.size; - de->comp_size = offend - offdata; + de->comp_size = (zip_uint64_t)(offend - offdata); if (zip_get_archive_flag(za, ZIP_AFL_TORRENT, 0)) _zip_dirent_torrent_normalize(de); - if (_zip_dirent_write(de, ft, 1, &za->error) < 0) + if ((ret=_zip_dirent_write(de, ft, flags, &za->error)) < 0) return -1; - + + if (is_zip64 != ret) { + /* Zip64 mismatch between preliminary file header written before data and final file header written afterwards */ + _zip_error_set(&za->error, ZIP_ER_INTERNAL, 0); + return -1; + } + + if (fseeko(ft, offend, SEEK_SET) < 0) { _zip_error_set(&za->error, ZIP_ER_SEEK, errno); return -1; @@ -441,24 +452,26 @@ add_data(struct zip *za, struct zip_source *src, struct zip_dirent *de, static int -copy_data(FILE *fs, off_t len, FILE *ft, struct zip_error *error) +copy_data(FILE *fs, zip_uint64_t len, FILE *ft, struct zip_error *error) { char buf[BUFSIZE]; - int n, nn; + size_t n, nn; if (len == 0) return 0; while (len > 0) { nn = len > sizeof(buf) ? sizeof(buf) : len; - if ((n=fread(buf, 1, nn, fs)) < 0) { - _zip_error_set(error, ZIP_ER_READ, errno); - return -1; - } - else if (n == 0) { - _zip_error_set(error, ZIP_ER_EOF, 0); - return -1; - } + if ((n=fread(buf, 1, nn, fs)) == 0) { + if (ferror(fs)) { + _zip_error_set(error, ZIP_ER_READ, errno); + return -1; + } + else { + _zip_error_set(error, ZIP_ER_EOF, 0); + return -1; + } + } if (fwrite(buf, 1, n, ft) != (size_t)n) { _zip_error_set(error, ZIP_ER_WRITE, errno); @@ -487,7 +500,7 @@ copy_source(struct zip *za, struct zip_source *src, FILE *ft) ret = 0; while ((n=zip_source_read(src, buf, sizeof(buf))) > 0) { - if (fwrite(buf, 1, n, ft) != (size_t)n) { + if (fwrite(buf, 1, (size_t)n, ft) != (size_t)n) { _zip_error_set(&za->error, ZIP_ER_WRITE, errno); ret = -1; break; @@ -508,29 +521,32 @@ copy_source(struct zip *za, struct zip_source *src, FILE *ft) static int -write_cdir(struct zip *za, struct zip_cdir *cd, FILE *out) +write_cdir(struct zip *za, const struct zip_filelist *filelist, zip_uint64_t survivors, FILE *out) { - off_t offset; + off_t cd_start, end; + zip_int64_t size; uLong crc; char buf[TORRENT_CRC_LEN+1]; - if (_zip_cdir_write(cd, out, &za->error) < 0) + cd_start = ftello(out); + + if ((size=_zip_cdir_write(za, filelist, survivors, out)) < 0) return -1; + end = ftello(out); + if (zip_get_archive_flag(za, ZIP_AFL_TORRENT, 0) == 0) return 0; /* fix up torrentzip comment */ - offset = ftello(out); - - if (_zip_filerange_crc(out, cd->offset, cd->size, &crc, &za->error) < 0) + if (_zip_filerange_crc(out, cd_start, size, &crc, &za->error) < 0) return -1; snprintf(buf, sizeof(buf), "%08lX", (long)crc); - if (fseeko(out, offset-TORRENT_CRC_LEN, SEEK_SET) < 0) { + if (fseeko(out, end-TORRENT_CRC_LEN, SEEK_SET) < 0) { _zip_error_set(&za->error, ZIP_ER_SEEK, errno); return -1; } @@ -545,47 +561,22 @@ write_cdir(struct zip *za, struct zip_cdir *cd, FILE *out) -static int -_zip_cdir_set_comment(struct zip_cdir *dest, struct zip *src) -{ - if (src->ch_comment_len != -1) { - dest->comment = _zip_memdup(src->ch_comment, - src->ch_comment_len, &src->error); - if (dest->comment == NULL) - return -1; - dest->comment_len = src->ch_comment_len; - } else { - if (src->cdir && src->cdir->comment) { - dest->comment = _zip_memdup(src->cdir->comment, - src->cdir->comment_len, &src->error); - if (dest->comment == NULL) - return -1; - dest->comment_len = src->cdir->comment_len; - } - } - - return 0; -} - - - int -_zip_changed(struct zip *za, int *survivorsp) +_zip_changed(const struct zip *za, zip_uint64_t *survivorsp) { - int changed, i, survivors; + int changed; + zip_uint64_t i, survivors; - changed = survivors = 0; + changed = 0; + survivors = 0; - if (za->ch_comment_len != -1 - || za->ch_flags != za->flags) + if (za->comment_changed || za->ch_flags != za->flags) changed = 1; for (i=0; i<za->nentry; i++) { - if ((za->entry[i].state != ZIP_ST_UNCHANGED) - || (za->entry[i].ch_extra_len != -1) - || (za->entry[i].ch_comment_len != -1)) + if (za->entry[i].deleted || za->entry[i].source || (za->entry[i].changes && za->entry[i].changes->changed != 0)) changed = 1; - if (za->entry[i].state != ZIP_ST_DELETED) + if (!za->entry[i].deleted) survivors++; } @@ -603,14 +594,21 @@ _zip_create_temp_output(struct zip *za, FILE **outp) char *temp; int tfd; FILE *tfp; - int len = strlen(za->zn) + 8; - - if ((temp=(char *)malloc(len)) == NULL) { - _zip_error_set(&za->error, ZIP_ER_MEMORY, 0); - return NULL; + + if (za->tempdir) { + if ((temp=(char *)malloc(strlen(za->tempdir)+13)) == NULL) { + _zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return NULL; + } + sprintf(temp, "%s/.zip.XXXXXX", za->tempdir); + } + else { + if ((temp=(char *)malloc(strlen(za->zn)+8)) == NULL) { + _zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return NULL; + } + sprintf(temp, "%s.XXXXXX", za->zn); } - - snprintf(temp, len, "%s.XXXXXX", za->zn); if ((tfd=mkstemp(temp)) == -1) { _zip_error_set(&za->error, ZIP_ER_TMPOPEN, errno); @@ -621,7 +619,7 @@ _zip_create_temp_output(struct zip *za, FILE **outp) if ((tfp=fdopen(tfd, "r+b")) == NULL) { _zip_error_set(&za->error, ZIP_ER_TMPOPEN, errno); close(tfd); - remove(temp); + (void)remove(temp); free(temp); return NULL; } @@ -630,7 +628,7 @@ _zip_create_temp_output(struct zip *za, FILE **outp) According to Pierre Joye, Windows in some environments per default creates text files, so force binary mode. */ - _setmode(_fileno(tfp), _O_BINARY ); + _setmode(_fileno(tfp), _O_BINARY ); #endif *outp = tfp; @@ -642,6 +640,13 @@ _zip_create_temp_output(struct zip *za, FILE **outp) static int _zip_torrentzip_cmp(const void *a, const void *b) { - return strcasecmp(((const struct filelist *)a)->name, - ((const struct filelist *)b)->name); + const char *aname = ((const struct zip_filelist *)a)->name; + const char *bname = ((const struct zip_filelist *)b)->name; + + if (aname == NULL) + return (bname != NULL) * -1; + else if (bname == NULL) + return 1; + + return strcasecmp(aname, bname); } diff --git a/ext/zip/lib/zip_delete.c b/ext/zip/lib/zip_delete.c index 131d444124..cb769367cc 100644 --- a/ext/zip/lib/zip_delete.c +++ b/ext/zip/lib/zip_delete.c @@ -37,7 +37,7 @@ -ZIP_EXTERN(int) +ZIP_EXTERN int zip_delete(struct zip *za, zip_uint64_t idx) { if (idx >= za->nentry) { @@ -55,7 +55,7 @@ zip_delete(struct zip *za, zip_uint64_t idx) if (_zip_unchange(za, idx, 1) != 0) return -1; - za->entry[idx].state = ZIP_ST_DELETED; + za->entry[idx].deleted = 1; return 0; } diff --git a/ext/zip/lib/zip_entry_new.c b/ext/zip/lib/zip_dir_add.c index ad5d59975a..0a74bd6087 100644 --- a/ext/zip/lib/zip_entry_new.c +++ b/ext/zip/lib/zip_dir_add.c @@ -1,6 +1,6 @@ /* - zip_entry_new.c -- create and init struct zip_entry - Copyright (C) 1999-2009 Dieter Baron and Thomas Klausner + zip_dir_add.c -- add directory + Copyright (C) 1999-2012 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -34,48 +34,55 @@ #include <stdlib.h> +#include <string.h> #include "zipint.h" -struct zip_entry * -_zip_entry_new(struct zip *za) +/* NOTE: Signed due to -1 on error. See zip_add.c for more details. */ + +ZIP_EXTERN zip_int64_t +zip_dir_add(struct zip *za, const char *name, zip_flags_t flags) { - struct zip_entry *ze; - if (!za) { - ze = (struct zip_entry *)malloc(sizeof(struct zip_entry)); - if (!ze) { - return NULL; - } + size_t len; + zip_int64_t ret; + char *s; + struct zip_source *source; + + if (ZIP_IS_RDONLY(za)) { + _zip_error_set(&za->error, ZIP_ER_RDONLY, 0); + return -1; } - else { - if (za->nentry+1 >= za->nentry_alloc) { - struct zip_entry *rentries; - za->nentry_alloc += 16; - rentries = (struct zip_entry *)realloc(za->entry, - sizeof(struct zip_entry) - * za->nentry_alloc); - if (!rentries) { - _zip_error_set(&za->error, ZIP_ER_MEMORY, 0); - return NULL; - } - za->entry = rentries; - } - ze = za->entry+za->nentry; + + if (name == NULL) { + _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; } - ze->state = ZIP_ST_UNCHANGED; + s = NULL; + len = strlen(name); - ze->ch_filename = NULL; - ze->ch_extra = NULL; - ze->ch_extra_len = -1; - ze->ch_comment = NULL; - ze->ch_comment_len = -1; - ze->source = NULL; + if (name[len-1] != '/') { + if ((s=(char *)malloc(len+2)) == NULL) { + _zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return -1; + } + strcpy(s, name); + s[len] = '/'; + s[len+1] = '\0'; + } + + if ((source=zip_source_buffer(za, NULL, 0, 0)) == NULL) { + free(s); + return -1; + } + + ret = _zip_file_replace(za, ZIP_UINT64_MAX, s ? s : name, source, flags); - if (za) - za->nentry++; + free(s); + if (ret < 0) + zip_source_free(source); - return ze; + return ret; } diff --git a/ext/zip/lib/zip_dirent.c b/ext/zip/lib/zip_dirent.c index b9dac5c989..f4f2deb6fc 100644 --- a/ext/zip/lib/zip_dirent.c +++ b/ext/zip/lib/zip_dirent.c @@ -1,6 +1,6 @@ /* zip_dirent.c -- read directory entry (local or central), clean dirent - Copyright (C) 1999-2009 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2013 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -42,48 +42,54 @@ #include "zipint.h" -static time_t _zip_d2u_time(int, int); -static char *_zip_readfpstr(FILE *, unsigned int, int, struct zip_error *); -static char *_zip_readstr(unsigned char **, int, int, struct zip_error *); -static void _zip_write2(unsigned short, FILE *); -static void _zip_write4(unsigned int, FILE *); +static time_t _zip_d2u_time(zip_uint16_t, zip_uint16_t); +static struct zip_string *_zip_read_string(const unsigned char **, FILE *, zip_uint16_t, int, struct zip_error *); +static struct zip_string *_zip_dirent_process_ef_utf_8(const struct zip_dirent *, zip_uint16_t, struct zip_string *); +static struct zip_extra_field *_zip_ef_utf8(zip_uint16_t, struct zip_string *, struct zip_error *); void _zip_cdir_free(struct zip_cdir *cd) { - int i; + zip_uint64_t i; if (!cd) return; for (i=0; i<cd->nentry; i++) - _zip_dirent_finalize(cd->entry+i); - free(cd->comment); + _zip_entry_finalize(cd->entry+i); free(cd->entry); + _zip_string_free(cd->comment); free(cd); } int -_zip_cdir_grow(struct zip_cdir *cd, int nentry, struct zip_error *error) +_zip_cdir_grow(struct zip_cdir *cd, zip_uint64_t nentry, struct zip_error *error) { - struct zip_dirent *entry; + struct zip_entry *entry; + zip_uint64_t i; - if (nentry < cd->nentry) { + if (nentry < cd->nentry_alloc) { _zip_error_set(error, ZIP_ER_INTERNAL, 0); return -1; } - if ((entry=((struct zip_dirent *) + if (nentry == cd->nentry_alloc) + return 0; + + if ((entry=((struct zip_entry *) realloc(cd->entry, sizeof(*(cd->entry))*nentry))) == NULL) { _zip_error_set(error, ZIP_ER_MEMORY, 0); return -1; } + + for (i=cd->nentry_alloc; i<nentry; i++) + _zip_entry_init(entry+i); - cd->nentry = nentry; + cd->nentry_alloc = nentry; cd->entry = entry; return 0; @@ -92,64 +98,132 @@ _zip_cdir_grow(struct zip_cdir *cd, int nentry, struct zip_error *error) struct zip_cdir * -_zip_cdir_new(int nentry, struct zip_error *error) +_zip_cdir_new(zip_uint64_t nentry, struct zip_error *error) { struct zip_cdir *cd; + zip_uint64_t i; if ((cd=(struct zip_cdir *)malloc(sizeof(*cd))) == NULL) { _zip_error_set(error, ZIP_ER_MEMORY, 0); return NULL; } - if ((cd->entry=(struct zip_dirent *)malloc(sizeof(*(cd->entry))*nentry)) - == NULL) { + if (nentry == 0) + cd->entry = NULL; + else if ((cd->entry=(struct zip_entry *)malloc(sizeof(*(cd->entry))*nentry)) == NULL) { _zip_error_set(error, ZIP_ER_MEMORY, 0); free(cd); return NULL; } - /* entries must be initialized by caller */ + for (i=0; i<nentry; i++) + _zip_entry_init(cd->entry+i); - cd->nentry = nentry; + cd->nentry = cd->nentry_alloc = nentry; cd->size = cd->offset = 0; cd->comment = NULL; - cd->comment_len = 0; return cd; } -int -_zip_cdir_write(struct zip_cdir *cd, FILE *fp, struct zip_error *error) +zip_int64_t +_zip_cdir_write(struct zip *za, const struct zip_filelist *filelist, zip_uint64_t survivors, FILE *fp) { - int i; + off_t off; + zip_uint64_t offset, size; + struct zip_string *comment; + zip_uint64_t i; + int is_zip64; + int ret; + + if ((off=ftello(fp)) < 0) { + _zip_error_set(&za->error, ZIP_ER_READ, errno); + return -1; + } + offset = (zip_uint64_t)off; - cd->offset = ftello(fp); + is_zip64 = 0; - for (i=0; i<cd->nentry; i++) { - if (_zip_dirent_write(cd->entry+i, fp, 0, error) != 0) + for (i=0; i<survivors; i++) { + struct zip_entry *entry = za->entry+filelist[i].idx; + + if ((ret=_zip_dirent_write(entry->changes ? entry->changes : entry->orig, fp, ZIP_FL_CENTRAL, &za->error)) < 0) return -1; + if (ret) + is_zip64 = 1; + } + + if ((off=ftello(fp)) < 0) { + _zip_error_set(&za->error, ZIP_ER_READ, errno); + return -1; + } + size = (zip_uint64_t)off - offset; + + if (offset > ZIP_UINT32_MAX || survivors > ZIP_UINT16_MAX) + is_zip64 = 1; + + if (is_zip64) { + fwrite(EOCD64_MAGIC, 1, 4, fp); + _zip_write8(EOCD64LEN-12, fp); + _zip_write2(45, fp); + _zip_write2(45, fp); + _zip_write4(0, fp); + _zip_write4(0, fp); + _zip_write8(survivors, fp); + _zip_write8(survivors, fp); + _zip_write8(size, fp); + _zip_write8(offset, fp); + + fwrite(EOCD64LOC_MAGIC, 1, 4, fp); + _zip_write4(0, fp); + _zip_write8(offset+size, fp); + _zip_write4(1, fp); + } - cd->size = ftello(fp) - cd->offset; - /* clearerr(fp); */ fwrite(EOCD_MAGIC, 1, 4, fp); _zip_write4(0, fp); - _zip_write2((unsigned short)cd->nentry, fp); - _zip_write2((unsigned short)cd->nentry, fp); - _zip_write4(cd->size, fp); - _zip_write4(cd->offset, fp); - _zip_write2(cd->comment_len, fp); - fwrite(cd->comment, 1, cd->comment_len, fp); + _zip_write2(survivors >= ZIP_UINT16_MAX ? ZIP_UINT16_MAX : (zip_uint16_t)survivors, fp); + _zip_write2(survivors >= ZIP_UINT16_MAX ? ZIP_UINT16_MAX : (zip_uint16_t)survivors, fp); + _zip_write4(size >= ZIP_UINT32_MAX ? ZIP_UINT32_MAX : (zip_uint32_t)size, fp); + _zip_write4(offset >= ZIP_UINT32_MAX ? ZIP_UINT32_MAX : (zip_uint32_t)offset, fp); + + comment = za->comment_changed ? za->comment_changes : za->comment_orig; + + _zip_write2(comment ? comment->length : 0, fp); + if (comment) + fwrite(comment->raw, 1, comment->length, fp); if (ferror(fp)) { - _zip_error_set(error, ZIP_ER_WRITE, errno); + _zip_error_set(&za->error, ZIP_ER_WRITE, errno); return -1; } - return 0; + return (zip_int64_t)size; +} + + + +struct zip_dirent * +_zip_dirent_clone(const struct zip_dirent *sde) +{ + struct zip_dirent *tde; + + if ((tde=(struct zip_dirent *)malloc(sizeof(*tde))) == NULL) + return NULL; + + if (sde) + memcpy(tde, sde, sizeof(*sde)); + else + _zip_dirent_init(tde); + + tde->changed = 0; + tde->cloned = 1; + + return tde; } @@ -157,18 +231,24 @@ _zip_cdir_write(struct zip_cdir *cd, FILE *fp, struct zip_error *error) void _zip_dirent_finalize(struct zip_dirent *zde) { - if (zde->filename_len > 0) { - free(zde->filename); - } - zde->filename = NULL; - if (zde->extrafield_len > 0) { - free(zde->extrafield); - } - zde->extrafield = NULL; - if (zde->comment_len > 0) { - free(zde->comment); - } - zde->comment = NULL; + if (!zde->cloned || zde->changed & ZIP_DIRENT_FILENAME) + _zip_string_free(zde->filename); + if (!zde->cloned || zde->changed & ZIP_DIRENT_EXTRA_FIELD) + _zip_ef_free(zde->extra_fields); + if (!zde->cloned || zde->changed & ZIP_DIRENT_COMMENT) + _zip_string_free(zde->comment); +} + + + +void +_zip_dirent_free(struct zip_dirent *zde) +{ + if (zde == NULL) + return; + + _zip_dirent_finalize(zde); + free(zde); } @@ -176,20 +256,21 @@ _zip_dirent_finalize(struct zip_dirent *zde) void _zip_dirent_init(struct zip_dirent *de) { - de->version_madeby = 0; + de->changed = 0; + de->local_extra_fields_read = 0; + de->cloned = 0; + + de->version_madeby = 20; de->version_needed = 20; /* 2.0 */ de->bitflags = 0; - de->comp_method = 0; + de->comp_method = ZIP_CM_DEFAULT; de->last_mod = 0; de->crc = 0; de->comp_size = 0; de->uncomp_size = 0; de->filename = NULL; - de->filename_len = 0; - de->extrafield = NULL; - de->extrafield_len = 0; + de->extra_fields = NULL; de->comment = NULL; - de->comment_len = 0; de->disk_number = 0; de->int_attrib = 0; de->ext_attrib = 0; @@ -198,6 +279,32 @@ _zip_dirent_init(struct zip_dirent *de) +int +_zip_dirent_needs_zip64(const struct zip_dirent *de, zip_flags_t flags) +{ + if (de->uncomp_size >= ZIP_UINT32_MAX || de->comp_size >= ZIP_UINT32_MAX + || ((flags & ZIP_FL_CENTRAL) && de->offset >= ZIP_UINT32_MAX)) + return 1; + + return 0; +} + + + +struct zip_dirent * +_zip_dirent_new(void) +{ + struct zip_dirent *de; + + if ((de=(struct zip_dirent *)malloc(sizeof(*de))) == NULL) + return NULL; + + _zip_dirent_init(de); + return de; +} + + + /* _zip_dirent_read(zde, fp, bufp, left, localp, error): Fills the zip directory entry zde. @@ -218,13 +325,14 @@ _zip_dirent_init(struct zip_dirent *de) int _zip_dirent_read(struct zip_dirent *zde, FILE *fp, - unsigned char **bufp, zip_uint32_t *leftp, int local, + const unsigned char **bufp, zip_uint64_t *leftp, int local, struct zip_error *error) { unsigned char buf[CDENTRYSIZE]; - unsigned char *cur; - unsigned short dostime, dosdate; + const unsigned char *cur; + zip_uint16_t dostime, dosdate; zip_uint32_t size; + zip_uint16_t filename_len, comment_len, ef_len; if (local) size = LENTRYSIZE; @@ -255,9 +363,10 @@ _zip_dirent_read(struct zip_dirent *zde, FILE *fp, } cur += 4; - + /* convert buffercontents to zip_dirent */ - + + _zip_dirent_init(zde); if (!local) zde->version_madeby = _zip_read2(&cur); else @@ -275,17 +384,17 @@ _zip_dirent_read(struct zip_dirent *zde, FILE *fp, zde->comp_size = _zip_read4(&cur); zde->uncomp_size = _zip_read4(&cur); - zde->filename_len = _zip_read2(&cur); - zde->extrafield_len = _zip_read2(&cur); + filename_len = _zip_read2(&cur); + ef_len = _zip_read2(&cur); if (local) { - zde->comment_len = 0; + comment_len = 0; zde->disk_number = 0; zde->int_attrib = 0; zde->ext_attrib = 0; zde->offset = 0; } else { - zde->comment_len = _zip_read2(&cur); + comment_len = _zip_read2(&cur); zde->disk_number = _zip_read2(&cur); zde->int_attrib = _zip_read2(&cur); zde->ext_attrib = _zip_read4(&cur); @@ -293,56 +402,102 @@ _zip_dirent_read(struct zip_dirent *zde, FILE *fp, } zde->filename = NULL; - zde->extrafield = NULL; + zde->extra_fields = NULL; zde->comment = NULL; - size += zde->filename_len+zde->extrafield_len+zde->comment_len; + size += filename_len+ef_len+comment_len; if (leftp && (*leftp < size)) { - _zip_error_set(error, ZIP_ER_NOZIP, 0); + _zip_error_set(error, ZIP_ER_INCONS, 0); return -1; } - if (bufp) { - if (zde->filename_len) { - zde->filename = _zip_readstr(&cur, zde->filename_len, 1, error); - if (!zde->filename) - return -1; - } + if (filename_len) { + zde->filename = _zip_read_string(bufp ? &cur : NULL, fp, filename_len, 1, error); + if (!zde->filename) + return -1; - if (zde->extrafield_len) { - zde->extrafield = _zip_readstr(&cur, zde->extrafield_len, 0, - error); - if (!zde->extrafield) + if (zde->bitflags & ZIP_GPBF_ENCODING_UTF_8) { + if (_zip_guess_encoding(zde->filename, ZIP_ENCODING_UTF8_KNOWN) == ZIP_ENCODING_ERROR) { + _zip_error_set(error, ZIP_ER_INCONS, 0); return -1; + } } + } - if (zde->comment_len) { - zde->comment = _zip_readstr(&cur, zde->comment_len, 0, error); - if (!zde->comment) - return -1; + if (ef_len) { + zip_uint8_t *ef = _zip_read_data(bufp ? &cur : NULL, fp, ef_len, 0, error); + + if (ef == NULL) + return -1; + if ((zde->extra_fields=_zip_ef_parse(ef, ef_len, local ? ZIP_EF_LOCAL : ZIP_EF_CENTRAL, error)) == NULL) { + free(ef); + return -1; } + free(ef); + if (local) + zde->local_extra_fields_read = 1; } - else { - if (zde->filename_len) { - zde->filename = _zip_readfpstr(fp, zde->filename_len, 1, error); - if (!zde->filename) - return -1; - } - if (zde->extrafield_len) { - zde->extrafield = _zip_readfpstr(fp, zde->extrafield_len, 0, - error); - if (!zde->extrafield) + if (comment_len) { + zde->comment = _zip_read_string(bufp ? &cur : NULL, fp, comment_len, 0, error); + if (!zde->comment) + return -1; + + if (zde->bitflags & ZIP_GPBF_ENCODING_UTF_8) { + if (_zip_guess_encoding(zde->comment, ZIP_ENCODING_UTF8_KNOWN) == ZIP_ENCODING_ERROR) { + _zip_error_set(error, ZIP_ER_INCONS, 0); return -1; + } } + } - if (zde->comment_len) { - zde->comment = _zip_readfpstr(fp, zde->comment_len, 0, error); - if (!zde->comment) - return -1; + zde->filename = _zip_dirent_process_ef_utf_8(zde, ZIP_EF_UTF_8_NAME, zde->filename); + zde->comment = _zip_dirent_process_ef_utf_8(zde, ZIP_EF_UTF_8_COMMENT, zde->comment); + + /* Zip64 */ + + if (zde->uncomp_size == ZIP_UINT32_MAX || zde->comp_size == ZIP_UINT32_MAX || zde->offset == ZIP_UINT32_MAX) { + zip_uint16_t got_len, needed_len; + const zip_uint8_t *ef = _zip_ef_get_by_id(zde->extra_fields, &got_len, ZIP_EF_ZIP64, 0, local ? ZIP_EF_LOCAL : ZIP_EF_CENTRAL, error); + /* XXX: if got_len == 0 && !ZIP64_EOCD: no error, 0xffffffff is valid value */ + if (ef == NULL) + return -1; + + + if (local) + needed_len = 16; + else + needed_len = ((zde->uncomp_size == ZIP_UINT32_MAX) + (zde->comp_size == ZIP_UINT32_MAX) + (zde->offset == ZIP_UINT32_MAX)) * 8 + + (zde->disk_number == ZIP_UINT16_MAX) * 4; + + if (got_len != needed_len) { + _zip_error_set(error, ZIP_ER_INCONS, 0); + return -1; } + + if (zde->uncomp_size == ZIP_UINT32_MAX) + zde->uncomp_size = _zip_read8(&ef); + else if (local) + ef += 8; + if (zde->comp_size == ZIP_UINT32_MAX) + zde->comp_size = _zip_read8(&ef); + if (!local) { + if (zde->offset == ZIP_UINT32_MAX) + zde->offset = _zip_read8(&ef); + if (zde->disk_number == ZIP_UINT16_MAX) + zde->disk_number = _zip_read4(&ef); + } + } + + if (!local) { + if (zde->offset > ZIP_OFF_MAX) { + _zip_error_set(error, ZIP_ER_SEEK, EFBIG); + return -1; + } } + + zde->extra_fields = _zip_ef_remove_internal(zde->extra_fields); if (bufp) *bufp = cur; @@ -354,6 +509,65 @@ _zip_dirent_read(struct zip_dirent *zde, FILE *fp, +static struct zip_string * +_zip_dirent_process_ef_utf_8(const struct zip_dirent *de, zip_uint16_t id, struct zip_string *str) +{ + zip_uint16_t ef_len; + zip_uint32_t ef_crc; + + const zip_uint8_t *ef = _zip_ef_get_by_id(de->extra_fields, &ef_len, id, 0, ZIP_EF_BOTH, NULL); + + if (ef == NULL || ef_len < 5 || ef[0] != 1) + return str; + + ef++; + ef_crc = _zip_read4(&ef); + + if (_zip_string_crc32(str) == ef_crc) { + struct zip_string *ef_str = _zip_string_new(ef, ef_len-5, ZIP_ENCODING_UTF8_KNOWN, NULL); + + if (ef_str != NULL) { + _zip_string_free(str); + str = ef_str; + } + } + + return str; +} + + + +zip_int32_t +_zip_dirent_size(FILE *f, zip_uint16_t flags, struct zip_error *error) +{ + zip_int32_t size; + int local = (flags & ZIP_EF_LOCAL); + int i; + unsigned char b[6]; + const unsigned char *p; + + size = local ? LENTRYSIZE : CDENTRYSIZE; + + if (fseek(f, local ? 26 : 28, SEEK_CUR) < 0) { + _zip_error_set(error, ZIP_ER_SEEK, errno); + return -1; + } + + if (fread(b, (local ? 4 : 6), 1, f) != 1) { + _zip_error_set(error, ZIP_ER_READ, errno); + return -1; + } + + p = b; + for (i=0; i<(local ? 2 : 3); i++) { + size += _zip_read2(&p); + } + + return size; +} + + + /* _zip_dirent_torrent_normalize(de); Set values suitable for torrentzip. */ @@ -399,84 +613,157 @@ _zip_dirent_torrent_normalize(struct zip_dirent *de) de->disk_number = 0; de->int_attrib = 0; de->ext_attrib = 0; - de->offset = 0; - free(de->extrafield); - de->extrafield = NULL; - de->extrafield_len = 0; - free(de->comment); + _zip_ef_free(de->extra_fields); + de->extra_fields = NULL; + _zip_string_free(de->comment); de->comment = NULL; - de->comment_len = 0; } -/* _zip_dirent_write(zde, fp, localp, error): +/* _zip_dirent_write(zde, fp, flags, error): Writes zip directory entry zde to file fp. - If localp != 0, it writes a local header instead of a central - directory entry. + If flags & ZIP_EF_LOCAL, it writes a local header instead of a central + directory entry. If flags & ZIP_EF_FORCE_ZIP64, a ZIP64 extra field is written, even if not needed. - Returns 0 if successful. On error, error is filled in and -1 is + Returns 0 if successful, 1 if successful and wrote ZIP64 extra field. On error, error is filled in and -1 is returned. */ int -_zip_dirent_write(struct zip_dirent *zde, FILE *fp, int localp, - struct zip_error *error) +_zip_dirent_write(struct zip_dirent *de, FILE *fp, zip_flags_t flags, struct zip_error *error) { unsigned short dostime, dosdate; + enum zip_encoding_type com_enc, name_enc; + struct zip_extra_field *ef; + zip_uint8_t ef_zip64[24], *ef_zip64_p; + int is_zip64; + int is_really_zip64; + + ef = NULL; - fwrite(localp ? LOCAL_MAGIC : CENTRAL_MAGIC, 1, 4, fp); + is_zip64 = 0; - if (!localp) - _zip_write2(zde->version_madeby, fp); - _zip_write2(zde->version_needed, fp); - _zip_write2(zde->bitflags, fp); - _zip_write2(zde->comp_method, fp); + fwrite((flags & ZIP_FL_LOCAL) ? LOCAL_MAGIC : CENTRAL_MAGIC, 1, 4, fp); - _zip_u2d_time(zde->last_mod, &dostime, &dosdate); + name_enc = _zip_guess_encoding(de->filename, ZIP_ENCODING_UNKNOWN); + com_enc = _zip_guess_encoding(de->comment, ZIP_ENCODING_UNKNOWN); + + if ((name_enc == ZIP_ENCODING_UTF8_KNOWN && com_enc == ZIP_ENCODING_ASCII) || + (name_enc == ZIP_ENCODING_ASCII && com_enc == ZIP_ENCODING_UTF8_KNOWN) || + (name_enc == ZIP_ENCODING_UTF8_KNOWN && com_enc == ZIP_ENCODING_UTF8_KNOWN)) + de->bitflags |= ZIP_GPBF_ENCODING_UTF_8; + else { + de->bitflags &= ~ZIP_GPBF_ENCODING_UTF_8; + if (name_enc == ZIP_ENCODING_UTF8_KNOWN) { + ef = _zip_ef_utf8(ZIP_EF_UTF_8_NAME, de->filename, error); + if (ef == NULL) + return -1; + } + if ((flags & ZIP_FL_LOCAL) == 0 && com_enc == ZIP_ENCODING_UTF8_KNOWN){ + struct zip_extra_field *ef2 = _zip_ef_utf8(ZIP_EF_UTF_8_COMMENT, de->comment, error); + if (ef2 == NULL) { + _zip_ef_free(ef); + return -1; + } + ef2->next = ef; + ef = ef2; + } + } + + ef_zip64_p = ef_zip64; + if (flags & ZIP_FL_LOCAL) { + if ((flags & ZIP_FL_FORCE_ZIP64) || de->comp_size > ZIP_UINT32_MAX || de->uncomp_size > ZIP_UINT32_MAX) { + _zip_poke8(de->comp_size, &ef_zip64_p); + _zip_poke8(de->uncomp_size, &ef_zip64_p); + } + } + else { + if ((flags & ZIP_FL_FORCE_ZIP64) || de->comp_size > ZIP_UINT32_MAX || de->uncomp_size > ZIP_UINT32_MAX || de->offset > ZIP_UINT32_MAX) { + if (de->comp_size >= ZIP_UINT32_MAX) + _zip_poke8(de->comp_size, &ef_zip64_p); + if (de->uncomp_size >= ZIP_UINT32_MAX) + _zip_poke8(de->uncomp_size, &ef_zip64_p); + if (de->offset >= ZIP_UINT32_MAX) + _zip_poke8(de->offset, &ef_zip64_p); + } + } + + if (ef_zip64_p != ef_zip64) { + struct zip_extra_field *ef64 = _zip_ef_new(ZIP_EF_ZIP64, (zip_uint16_t)(ef_zip64_p-ef_zip64), ef_zip64, ZIP_EF_BOTH); + ef64->next = ef; + ef = ef64; + is_zip64 = 1; + } + + if ((flags & (ZIP_FL_LOCAL|ZIP_FL_FORCE_ZIP64)) == (ZIP_FL_LOCAL|ZIP_FL_FORCE_ZIP64)) + is_really_zip64 = _zip_dirent_needs_zip64(de, flags); + else + is_really_zip64 = is_zip64; + + if ((flags & ZIP_FL_LOCAL) == 0) + _zip_write2(is_really_zip64 ? 45 : de->version_madeby, fp); + _zip_write2(is_really_zip64 ? 45 : de->version_needed, fp); + _zip_write2(de->bitflags&0xfff9, fp); /* clear compression method specific flags */ + _zip_write2((zip_uint16_t)de->comp_method, fp); /* XXX: can it be ZIP_CM_DEFAULT? */ + + _zip_u2d_time(de->last_mod, &dostime, &dosdate); _zip_write2(dostime, fp); _zip_write2(dosdate, fp); + + _zip_write4(de->crc, fp); + if (de->comp_size < ZIP_UINT32_MAX) + _zip_write4((zip_uint32_t)de->comp_size, fp); + else + _zip_write4(ZIP_UINT32_MAX, fp); + if (de->uncomp_size < ZIP_UINT32_MAX) + _zip_write4((zip_uint32_t)de->uncomp_size, fp); + else + _zip_write4(ZIP_UINT32_MAX, fp); + + _zip_write2(_zip_string_length(de->filename), fp); + _zip_write2(_zip_ef_size(de->extra_fields, flags) + _zip_ef_size(ef, ZIP_EF_BOTH), fp); - _zip_write4(zde->crc, fp); - _zip_write4(zde->comp_size, fp); - _zip_write4(zde->uncomp_size, fp); - - _zip_write2(zde->filename_len, fp); - _zip_write2(zde->extrafield_len, fp); - - if (!localp) { - _zip_write2(zde->comment_len, fp); - _zip_write2(zde->disk_number, fp); - _zip_write2(zde->int_attrib, fp); - _zip_write4(zde->ext_attrib, fp); - _zip_write4(zde->offset, fp); + if ((flags & ZIP_FL_LOCAL) == 0) { + _zip_write2(_zip_string_length(de->comment), fp); + _zip_write2((zip_uint16_t)de->disk_number, fp); + _zip_write2(de->int_attrib, fp); + _zip_write4(de->ext_attrib, fp); + if (de->offset < ZIP_UINT32_MAX) + _zip_write4((zip_uint32_t)de->offset, fp); + else + _zip_write4(ZIP_UINT32_MAX, fp); } - if (zde->filename_len) - fwrite(zde->filename, 1, zde->filename_len, fp); + if (de->filename) + _zip_string_write(de->filename, fp); - if (zde->extrafield_len) - fwrite(zde->extrafield, 1, zde->extrafield_len, fp); + if (ef) + _zip_ef_write(ef, ZIP_EF_BOTH, fp); + if (de->extra_fields) + _zip_ef_write(de->extra_fields, flags, fp); - if (!localp) { - if (zde->comment_len) - fwrite(zde->comment, 1, zde->comment_len, fp); + if ((flags & ZIP_FL_LOCAL) == 0) { + if (de->comment) + _zip_string_write(de->comment, fp); } + _zip_ef_free(ef); + if (ferror(fp)) { _zip_error_set(error, ZIP_ER_WRITE, errno); return -1; } - return 0; + return is_zip64; } static time_t -_zip_d2u_time(int dtime, int ddate) +_zip_d2u_time(zip_uint16_t dtime, zip_uint16_t ddate) { struct tm tm; @@ -498,12 +785,72 @@ _zip_d2u_time(int dtime, int ddate) -unsigned short -_zip_read2(unsigned char **a) +static struct zip_extra_field * +_zip_ef_utf8(zip_uint16_t id, struct zip_string *str, struct zip_error *error) { - unsigned short ret; + const zip_uint8_t *raw; + zip_uint8_t *data, *p; + zip_uint32_t len; + struct zip_extra_field *ef; + + raw = _zip_string_get(str, &len, ZIP_FL_ENC_RAW, NULL); + + if (len+5 > ZIP_UINT16_MAX) { + /* XXX: error */ + } + + if ((data=(zip_uint8_t *)malloc(len+5)) == NULL) { + _zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; + } + + p = data; + *(p++) = 1; + _zip_poke4(_zip_string_crc32(str), &p); + memcpy(p, raw, len); + p += len; + + ef = _zip_ef_new(id, (zip_uint16_t)(p-data), data, ZIP_EF_BOTH); + free(data); + return ef; +} + + + +struct zip_dirent * +_zip_get_dirent(struct zip *za, zip_uint64_t idx, zip_flags_t flags, struct zip_error *error) +{ + if (error == NULL) + error = &za->error; + + if (idx >= za->nentry) { + _zip_error_set(error, ZIP_ER_INVAL, 0); + return NULL; + } + + if ((flags & ZIP_FL_UNCHANGED) || za->entry[idx].changes == NULL) { + if (za->entry[idx].orig == NULL) { + _zip_error_set(error, ZIP_ER_INVAL, 0); + return NULL; + } + if (za->entry[idx].deleted && (flags & ZIP_FL_UNCHANGED) == 0) { + _zip_error_set(error, ZIP_ER_DELETED, 0); + return NULL; + } + return za->entry[idx].orig; + } + else + return za->entry[idx].changes; +} + + - ret = (*a)[0]+((*a)[1]<<8); +zip_uint16_t +_zip_read2(const zip_uint8_t **a) +{ + zip_uint16_t ret; + + ret = (zip_uint16_t)((*a)[0]+((*a)[1]<<8)); *a += 2; return ret; @@ -511,12 +858,12 @@ _zip_read2(unsigned char **a) -unsigned int -_zip_read4(unsigned char **a) +zip_uint32_t +_zip_read4(const zip_uint8_t **a) { - unsigned int ret; + zip_uint32_t ret; - ret = ((((((*a)[3]<<8)+(*a)[2])<<8)+(*a)[1])<<8)+(*a)[0]; + ret = ((((((zip_uint32_t)(*a)[3]<<8)+(*a)[2])<<8)+(*a)[1])<<8)+(*a)[0]; *a += 4; return ret; @@ -524,65 +871,108 @@ _zip_read4(unsigned char **a) -static char * -_zip_readfpstr(FILE *fp, unsigned int len, int nulp, struct zip_error *error) +zip_uint64_t +_zip_read8(const zip_uint8_t **a) { - char *r, *o; + zip_uint64_t x, y; + + x = ((((((zip_uint64_t)(*a)[3]<<8)+(*a)[2])<<8)+(*a)[1])<<8)+(*a)[0]; + *a += 4; + y = ((((((zip_uint64_t)(*a)[3]<<8)+(*a)[2])<<8)+(*a)[1])<<8)+(*a)[0]; + *a += 4; + + return x+(y<<32); +} - r = (char *)malloc(nulp ? len+1 : len); + + +zip_uint8_t * +_zip_read_data(const zip_uint8_t **buf, FILE *fp, size_t len, int nulp, struct zip_error *error) +{ + zip_uint8_t *r; + + if (len == 0 && nulp == 0) + return NULL; + + r = (zip_uint8_t *)malloc(nulp ? len+1 : len); if (!r) { _zip_error_set(error, ZIP_ER_MEMORY, 0); return NULL; } - if (fread(r, 1, len, fp)<len) { - free(r); - _zip_error_set(error, ZIP_ER_READ, errno); - return NULL; + if (buf) { + memcpy(r, *buf, len); + *buf += len; + } + else { + if (fread(r, 1, len, fp)<len) { + free(r); + if (ferror(fp)) + _zip_error_set(error, ZIP_ER_READ, errno); + else + _zip_error_set(error, ZIP_ER_INCONS, 0); + return NULL; + } } if (nulp) { + zip_uint8_t *o; /* replace any in-string NUL characters with spaces */ r[len] = 0; for (o=r; o<r+len; o++) if (*o == '\0') *o = ' '; } - + return r; } -static char * -_zip_readstr(unsigned char **buf, int len, int nulp, struct zip_error *error) +static struct zip_string * +_zip_read_string(const zip_uint8_t **buf, FILE *fp, zip_uint16_t len, int nulp, struct zip_error *error) { - char *r, *o; + zip_uint8_t *raw; + struct zip_string *s; - r = (char *)malloc(nulp ? len+1 : len); - if (!r) { - _zip_error_set(error, ZIP_ER_MEMORY, 0); + if ((raw=_zip_read_data(buf, fp, len, nulp, error)) == NULL) return NULL; - } - - memcpy(r, *buf, len); - *buf += len; - if (nulp) { - /* replace any in-string NUL characters with spaces */ - r[len] = 0; - for (o=r; o<r+len; o++) - if (*o == '\0') - *o = ' '; - } + s = _zip_string_new(raw, len, ZIP_FL_ENC_GUESS, error); + free(raw); + return s; +} - return r; + + +void +_zip_poke4(zip_uint32_t i, zip_uint8_t **p) +{ + *((*p)++) = i&0xff; + *((*p)++) = (i>>8)&0xff; + *((*p)++) = (i>>16)&0xff; + *((*p)++) = (i>>24)&0xff; +} + + + +void +_zip_poke8(zip_uint64_t i, zip_uint8_t **p) +{ + *((*p)++) = i&0xff; + *((*p)++) = (i>>8)&0xff; + *((*p)++) = (i>>16)&0xff; + *((*p)++) = (i>>24)&0xff; + *((*p)++) = (i>>32)&0xff; + *((*p)++) = (i>>40)&0xff; + *((*p)++) = (i>>48)&0xff; + *((*p)++) = (i>>56)&0xff; } -static void -_zip_write2(unsigned short i, FILE *fp) +void +_zip_write2(zip_uint16_t i, FILE *fp) { putc(i&0xff, fp); putc((i>>8)&0xff, fp); @@ -592,13 +982,30 @@ _zip_write2(unsigned short i, FILE *fp) -static void -_zip_write4(unsigned int i, FILE *fp) +void +_zip_write4(zip_uint32_t i, FILE *fp) +{ + putc(i&0xff, fp); + putc((i>>8)&0xff, fp); + putc((i>>16)&0xff, fp); + putc((i>>24)&0xff, fp); + + return; +} + + + +void +_zip_write8(zip_uint64_t i, FILE *fp) { putc(i&0xff, fp); putc((i>>8)&0xff, fp); putc((i>>16)&0xff, fp); putc((i>>24)&0xff, fp); + putc((i>>32)&0xff, fp); + putc((i>>40)&0xff, fp); + putc((i>>48)&0xff, fp); + putc((i>>56)&0xff, fp); return; } @@ -606,15 +1013,13 @@ _zip_write4(unsigned int i, FILE *fp) void -_zip_u2d_time(time_t time, unsigned short *dtime, unsigned short *ddate) +_zip_u2d_time(time_t time, zip_uint16_t *dtime, zip_uint16_t *ddate) { struct tm *tm; tm = localtime(&time); - *ddate = ((tm->tm_year+1900-1980)<<9) + ((tm->tm_mon+1)<<5) - + tm->tm_mday; - *dtime = ((tm->tm_hour)<<11) + ((tm->tm_min)<<5) - + ((tm->tm_sec)>>1); + *ddate = (zip_uint16_t)(((tm->tm_year+1900-1980)<<9) + ((tm->tm_mon+1)<<5) + tm->tm_mday); + *dtime = (zip_uint16_t)(((tm->tm_hour)<<11) + ((tm->tm_min)<<5) + ((tm->tm_sec)>>1)); return; } diff --git a/ext/zip/lib/zip_free.c b/ext/zip/lib/zip_discard.c index 9932c14fec..37ba8c2ea6 100644 --- a/ext/zip/lib/zip_free.c +++ b/ext/zip/lib/zip_discard.c @@ -1,6 +1,6 @@ /* - zip_free.c -- free struct zip - Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner + zip_discard.c -- discard and free struct zip + Copyright (C) 1999-2012 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -39,14 +39,14 @@ -/* _zip_free: +/* zip_discard: frees the space allocated to a zipfile struct, and closes the corresponding file. */ void -_zip_free(struct zip *za) +zip_discard(struct zip *za) { - int i; + zip_uint64_t i; if (za == NULL) return; @@ -58,13 +58,12 @@ _zip_free(struct zip *za) fclose(za->zp); free(za->default_password); - _zip_cdir_free(za->cdir); - free(za->ch_comment); + _zip_string_free(za->comment_orig); + _zip_string_free(za->comment_changes); if (za->entry) { - for (i=0; i<za->nentry; i++) { - _zip_entry_free(za->entry+i); - } + for (i=0; i<za->nentry; i++) + _zip_entry_finalize(za->entry+i); free(za->entry); } diff --git a/ext/zip/lib/zip_entry_free.c b/ext/zip/lib/zip_entry.c index e8a77707f0..58663e8d0c 100644 --- a/ext/zip/lib/zip_entry_free.c +++ b/ext/zip/lib/zip_entry.c @@ -1,6 +1,6 @@ /* - zip_entry_free.c -- free struct zip_entry - Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner + zip_entry.c -- struct zip_entry helper functions + Copyright (C) 1999-2012 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -33,23 +33,23 @@ -#include <stdlib.h> - #include "zipint.h" +void +_zip_entry_finalize(struct zip_entry *e) +{ + _zip_unchange_data(e); + _zip_dirent_free(e->orig); + _zip_dirent_free(e->changes); +} + void -_zip_entry_free(struct zip_entry *ze) +_zip_entry_init(struct zip_entry *e) { - free(ze->ch_filename); - ze->ch_filename = NULL; - free(ze->ch_extra); - ze->ch_extra = NULL; - ze->ch_extra_len = -1; - free(ze->ch_comment); - ze->ch_comment = NULL; - ze->ch_comment_len = -1; - - _zip_unchange_data(ze); + e->orig = NULL; + e->changes = NULL; + e->source = NULL; + e->deleted = 0; } diff --git a/ext/zip/lib/zip_error.c b/ext/zip/lib/zip_error.c index b8d907abf4..4b1f27921a 100644 --- a/ext/zip/lib/zip_error.c +++ b/ext/zip/lib/zip_error.c @@ -1,6 +1,6 @@ /* zip_error.c -- struct zip_error helper functions - Copyright (C) 1999-2009 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2013 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -42,6 +42,9 @@ void _zip_error_clear(struct zip_error *err) { + if (err == NULL) + return; + err->zip_err = ZIP_ER_OK; err->sys_err = 0; } @@ -49,7 +52,7 @@ _zip_error_clear(struct zip_error *err) void -_zip_error_copy(struct zip_error *dst, struct zip_error *src) +_zip_error_copy(struct zip_error *dst, const struct zip_error *src) { dst->zip_err = src->zip_err; dst->sys_err = src->sys_err; @@ -67,7 +70,7 @@ _zip_error_fini(struct zip_error *err) void -_zip_error_get(struct zip_error *err, int *zep, int *sep) +_zip_error_get(const struct zip_error *err, int *zep, int *sep) { if (zep) *zep = err->zip_err; diff --git a/ext/zip/lib/zip_error_clear.c b/ext/zip/lib/zip_error_clear.c index 34e7dea48e..b4ff103912 100644 --- a/ext/zip/lib/zip_error_clear.c +++ b/ext/zip/lib/zip_error_clear.c @@ -37,8 +37,11 @@ -ZIP_EXTERN(void) +ZIP_EXTERN void zip_error_clear(struct zip *za) { + if (za == NULL) + return; + _zip_error_clear(&za->error); } diff --git a/ext/zip/lib/zip_error_get.c b/ext/zip/lib/zip_error_get.c index c15705e32f..6d1c958c17 100644 --- a/ext/zip/lib/zip_error_get.c +++ b/ext/zip/lib/zip_error_get.c @@ -37,7 +37,7 @@ -ZIP_EXTERN(void) +ZIP_EXTERN void zip_error_get(struct zip *za, int *zep, int *sep) { _zip_error_get(&za->error, zep, sep); diff --git a/ext/zip/lib/zip_error_get_sys_type.c b/ext/zip/lib/zip_error_get_sys_type.c index 47aa93e69b..6c6f380740 100644 --- a/ext/zip/lib/zip_error_get_sys_type.c +++ b/ext/zip/lib/zip_error_get_sys_type.c @@ -37,7 +37,7 @@ -ZIP_EXTERN(int) +ZIP_EXTERN int zip_error_get_sys_type(int ze) { if (ze < 0 || ze >= _zip_nerr_str) diff --git a/ext/zip/lib/zip_error_to_str.c b/ext/zip/lib/zip_error_to_str.c index bafe74335a..11a0cd2bb0 100644 --- a/ext/zip/lib/zip_error_to_str.c +++ b/ext/zip/lib/zip_error_to_str.c @@ -42,7 +42,7 @@ -ZIP_EXTERN(int) +ZIP_EXTERN int zip_error_to_str(char *buf, zip_uint64_t len, int ze, int se) { const char *zs, *ss; diff --git a/ext/zip/lib/zip_extra_field.c b/ext/zip/lib/zip_extra_field.c new file mode 100644 index 0000000000..41fd2b1d90 --- /dev/null +++ b/ext/zip/lib/zip_extra_field.c @@ -0,0 +1,386 @@ +/* + zip_extra_field.c -- manipulate extra fields + Copyright (C) 2012-2013 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR 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. +*/ + + + +#include "zipint.h" + +#include <errno.h> +#include <stdlib.h> +#include <string.h> + + + +struct zip_extra_field * +_zip_ef_clone(const struct zip_extra_field *ef, struct zip_error *error) +{ + struct zip_extra_field *head, *prev, *def; + + head = prev = NULL; + + while (ef) { + if ((def=_zip_ef_new(ef->id, ef->size, ef->data, ef->flags)) == NULL) { + _zip_error_set(error, ZIP_ER_MEMORY, 0); + _zip_ef_free(head); + return NULL; + } + + if (head == NULL) + head = def; + if (prev) + prev->next = def; + prev = def; + + ef = ef->next; + } + + return head; +} + + +struct zip_extra_field * +_zip_ef_delete_by_id(struct zip_extra_field *ef, zip_uint16_t id, zip_uint16_t id_idx, zip_flags_t flags) +{ + struct zip_extra_field *head, *prev; + int i; + + i = 0; + head = ef; + prev = NULL; + for (; ef; ef=(prev ? prev->next : head)) { + if ((ef->flags & flags & ZIP_EF_BOTH) && ef->id == id) { + if (id_idx == ZIP_EXTRA_FIELD_ALL || i == id_idx) { + ef->flags &= ~(flags & ZIP_EF_BOTH); + if ((ef->flags & ZIP_EF_BOTH) == 0) { + if (prev) + prev->next = ef->next; + else + head = ef->next; + ef->next = NULL; + _zip_ef_free(ef); + + if (id_idx == ZIP_EXTRA_FIELD_ALL) + continue; + } + } + + i++; + if (i > id_idx) + break; + } + prev = ef; + } + + return head; +} + + + + +void +_zip_ef_free(struct zip_extra_field *ef) +{ + struct zip_extra_field *ef2; + + while (ef) { + ef2 = ef->next; + free(ef->data); + free(ef); + ef = ef2; + } +} + + + +const zip_uint8_t * +_zip_ef_get_by_id(const struct zip_extra_field *ef, zip_uint16_t *lenp, zip_uint16_t id, zip_uint16_t id_idx, zip_flags_t flags, struct zip_error *error) +{ + static const zip_uint8_t empty[1] = { '\0' }; + + int i; + + i = 0; + for (; ef; ef=ef->next) { + if (ef->id == id && (ef->flags & flags & ZIP_EF_BOTH)) { + if (i < id_idx) { + i++; + continue; + } + + if (lenp) + *lenp = ef->size; + if (ef->size > 0) + return ef->data; + else + return empty; + } + } + + _zip_error_set(error, ZIP_ER_NOENT, 0); + return NULL; +} + + + +struct zip_extra_field * +_zip_ef_merge(struct zip_extra_field *to, struct zip_extra_field *from) +{ + struct zip_extra_field *ef2, *tt, *tail; + int duplicate; + + if (to == NULL) + return from; + + for (tail=to; tail->next; tail=tail->next) + ; + + for (; from; from=ef2) { + ef2 = from->next; + + duplicate = 0; + for (tt=to; tt; tt=tt->next) { + if (tt->id == from->id && tt->size == from->size && memcmp(tt->data, from->data, tt->size) == 0) { + tt->flags |= (from->flags & ZIP_EF_BOTH); + duplicate = 1; + break; + } + } + + from->next = NULL; + if (duplicate) + _zip_ef_free(from); + else + tail = tail->next = from; + } + + return to; +} + + + +struct zip_extra_field * +_zip_ef_new(zip_uint16_t id, zip_uint16_t size, const zip_uint8_t *data, zip_flags_t flags) +{ + struct zip_extra_field *ef; + + if ((ef=(struct zip_extra_field *)malloc(sizeof(*ef))) == NULL) + return NULL; + + ef->next = NULL; + ef->flags = flags; + ef->id = id; + ef->size = size; + if (size > 0) { + if ((ef->data=(zip_uint8_t *)_zip_memdup(data, size, NULL)) == NULL) { + free(ef); + return NULL; + } + } + else + ef->data = NULL; + + return ef; +} + + + +struct zip_extra_field * +_zip_ef_parse(const zip_uint8_t *data, zip_uint16_t len, zip_flags_t flags, struct zip_error *error) +{ + struct zip_extra_field *ef, *ef2, *ef_head; + const zip_uint8_t *p; + zip_uint16_t fid, flen; + + ef_head = NULL; + for (p=data; p<data+len; p+=flen) { + if (p+4 > data+len) { + _zip_error_set(error, ZIP_ER_INCONS, 0); + _zip_ef_free(ef_head); + return NULL; + } + + fid = _zip_read2(&p); + flen = _zip_read2(&p); + + if (p+flen > data+len) { + _zip_error_set(error, ZIP_ER_INCONS, 0); + _zip_ef_free(ef_head); + return NULL; + } + + if ((ef2=_zip_ef_new(fid, flen, p, flags)) == NULL) { + _zip_error_set(error, ZIP_ER_MEMORY, 0); + _zip_ef_free(ef_head); + return NULL; + } + + if (ef_head) { + ef->next = ef2; + ef = ef2; + } + else + ef_head = ef = ef2; + } + + return ef_head; +} + + + +struct zip_extra_field * +_zip_ef_remove_internal(struct zip_extra_field *ef) +{ + struct zip_extra_field *ef_head; + struct zip_extra_field *prev, *next; + + ef_head = ef; + prev = NULL; + + while (ef) { + if (ZIP_EF_IS_INTERNAL(ef->id)) { + next = ef->next; + if (ef_head == ef) + ef_head = next; + ef->next = NULL; + _zip_ef_free(ef); + if (prev) + prev->next = next; + ef = next; + } + else { + prev = ef; + ef = ef->next; + } + } + + return ef_head; +} + + +zip_uint16_t +_zip_ef_size(const struct zip_extra_field *ef, zip_flags_t flags) +{ + zip_uint16_t size; + + size = 0; + for (; ef; ef=ef->next) { + if (ef->flags & flags & ZIP_EF_BOTH) + size += 4+ef->size; + } + + return size; +} + + + +void +_zip_ef_write(const struct zip_extra_field *ef, zip_flags_t flags, FILE *f) +{ + for (; ef; ef=ef->next) { + if (ef->flags & flags & ZIP_EF_BOTH) { + _zip_write2(ef->id, f); + _zip_write2(ef->size, f); + if (ef->size > 0) + fwrite(ef->data, ef->size, 1, f); + } + } +} + + + +int +_zip_read_local_ef(struct zip *za, zip_uint64_t idx) +{ + struct zip_entry *e; + unsigned char b[4]; + const unsigned char *p; + zip_uint16_t fname_len, ef_len; + + if (idx >= za->nentry) { + _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + e = za->entry+idx; + + if (e->orig == NULL || e->orig->local_extra_fields_read) + return 0; + + + if (fseeko(za->zp, (off_t)(e->orig->offset + 26), SEEK_SET) < 0) { + _zip_error_set(&za->error, ZIP_ER_SEEK, errno); + return -1; + } + + if (fread(b, sizeof(b), 1, za->zp) != 1) { + _zip_error_set(&za->error, ZIP_ER_READ, errno); + return -1; + } + + p = b; + fname_len = _zip_read2(&p); + ef_len = _zip_read2(&p); + + if (ef_len > 0) { + struct zip_extra_field *ef; + zip_uint8_t *ef_raw; + + if (fseek(za->zp, fname_len, SEEK_CUR) < 0) { + _zip_error_set(&za->error, ZIP_ER_SEEK, errno); + return -1; + } + + ef_raw = _zip_read_data(NULL, za->zp, ef_len, 0, &za->error); + + if (ef_raw == NULL) + return -1; + + if ((ef=_zip_ef_parse(ef_raw, ef_len, ZIP_EF_LOCAL, &za->error)) == NULL) { + free(ef_raw); + return -1; + } + free(ef_raw); + + ef = _zip_ef_remove_internal(ef); + e->orig->extra_fields = _zip_ef_merge(e->orig->extra_fields, ef); + } + + e->orig->local_extra_fields_read = 1; + + if (e->changes && e->changes->local_extra_fields_read == 0) { + e->changes->extra_fields = e->orig->extra_fields; + e->changes->local_extra_fields_read = 1; + } + + return 0; +} diff --git a/ext/zip/lib/zip_extra_field_api.c b/ext/zip/lib/zip_extra_field_api.c new file mode 100644 index 0000000000..02ed4555e0 --- /dev/null +++ b/ext/zip/lib/zip_extra_field_api.c @@ -0,0 +1,364 @@ +/* + zip_extra_field_api.c -- public extra fields API functions + Copyright (C) 2012-2013 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR 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. +*/ + + + +#include "zipint.h" + + + +ZIP_EXTERN int +zip_file_extra_field_delete(struct zip *za, zip_uint64_t idx, zip_uint16_t ef_idx, zip_flags_t flags) +{ + struct zip_dirent *de; + + if ((flags & ZIP_EF_BOTH) == 0) { + _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + if (_zip_get_dirent(za, idx, 0, NULL) == NULL) + return -1; + + if (ZIP_IS_RDONLY(za)) { + _zip_error_set(&za->error, ZIP_ER_RDONLY, 0); + return -1; + } + + if (_zip_file_extra_field_prepare_for_change(za, idx) < 0) + return -1; + + de = za->entry[idx].changes; + + de->extra_fields = _zip_ef_delete_by_id(de->extra_fields, ZIP_EXTRA_FIELD_ALL, ef_idx, flags); + return 0; +} + + + +ZIP_EXTERN int +zip_file_extra_field_delete_by_id(struct zip *za, zip_uint64_t idx, zip_uint16_t ef_id, zip_uint16_t ef_idx, zip_flags_t flags) +{ + struct zip_dirent *de; + + if ((flags & ZIP_EF_BOTH) == 0) { + _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + if (_zip_get_dirent(za, idx, 0, NULL) == NULL) + return -1; + + if (ZIP_IS_RDONLY(za)) { + _zip_error_set(&za->error, ZIP_ER_RDONLY, 0); + return -1; + } + + if (_zip_file_extra_field_prepare_for_change(za, idx) < 0) + return -1; + + de = za->entry[idx].changes; + + de->extra_fields = _zip_ef_delete_by_id(de->extra_fields, ef_id, ef_idx, flags); + return 0; +} + + + +ZIP_EXTERN const zip_uint8_t * +zip_file_extra_field_get(struct zip *za, zip_uint64_t idx, zip_uint16_t ef_idx, zip_uint16_t *idp, zip_uint16_t *lenp, zip_flags_t flags) +{ + static const zip_uint8_t empty[1] = { '\0' }; + + struct zip_dirent *de; + struct zip_extra_field *ef; + int i; + + if ((flags & ZIP_EF_BOTH) == 0) { + _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return NULL; + } + + if ((de=_zip_get_dirent(za, idx, flags, &za->error)) == NULL) + return NULL; + + if (flags & ZIP_FL_LOCAL) + if (_zip_read_local_ef(za, idx) < 0) + return NULL; + + i = 0; + for (ef=de->extra_fields; ef; ef=ef->next) { + if (ef->flags & flags & ZIP_EF_BOTH) { + if (i < ef_idx) { + i++; + continue; + } + + if (idp) + *idp = ef->id; + if (lenp) + *lenp = ef->size; + if (ef->size > 0) + return ef->data; + else + return empty; + } + } + + _zip_error_set(&za->error, ZIP_ER_NOENT, 0); + return NULL; + +} + + + +ZIP_EXTERN const zip_uint8_t * +zip_file_extra_field_get_by_id(struct zip *za, zip_uint64_t idx, zip_uint16_t ef_id, zip_uint16_t ef_idx, zip_uint16_t *lenp, zip_flags_t flags) +{ + struct zip_dirent *de; + + if ((flags & ZIP_EF_BOTH) == 0) { + _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return NULL; + } + + if ((de=_zip_get_dirent(za, idx, flags, &za->error)) == NULL) + return NULL; + + if (flags & ZIP_FL_LOCAL) + if (_zip_read_local_ef(za, idx) < 0) + return NULL; + + return _zip_ef_get_by_id(de->extra_fields, lenp, ef_id, ef_idx, flags, &za->error); +} + + + +ZIP_EXTERN zip_int16_t +zip_file_extra_fields_count(struct zip *za, zip_uint64_t idx, zip_flags_t flags) +{ + struct zip_dirent *de; + struct zip_extra_field *ef; + zip_uint16_t n; + + if ((flags & ZIP_EF_BOTH) == 0) { + _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + if ((de=_zip_get_dirent(za, idx, flags, &za->error)) == NULL) + return -1; + + if (flags & ZIP_FL_LOCAL) + if (_zip_read_local_ef(za, idx) < 0) + return -1; + + n = 0; + for (ef=de->extra_fields; ef; ef=ef->next) + if (ef->flags & flags & ZIP_EF_BOTH) + n++; + + return (zip_int16_t)n; +} + + + +ZIP_EXTERN zip_int16_t +zip_file_extra_fields_count_by_id(struct zip *za, zip_uint64_t idx, zip_uint16_t ef_id, zip_flags_t flags) +{ + struct zip_dirent *de; + struct zip_extra_field *ef; + zip_uint16_t n; + + if ((flags & ZIP_EF_BOTH) == 0) { + _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + if ((de=_zip_get_dirent(za, idx, flags, &za->error)) == NULL) + return -1; + + if (flags & ZIP_FL_LOCAL) + if (_zip_read_local_ef(za, idx) < 0) + return -1; + + n = 0; + for (ef=de->extra_fields; ef; ef=ef->next) + if (ef->id == ef_id && (ef->flags & flags & ZIP_EF_BOTH)) + n++; + + return (zip_int16_t)n; +} + + + +ZIP_EXTERN int +zip_file_extra_field_set(struct zip *za, zip_uint64_t idx, zip_uint16_t ef_id, zip_uint16_t ef_idx, const zip_uint8_t *data, zip_uint16_t len, zip_flags_t flags) +{ + struct zip_dirent *de; + zip_uint16_t ls, cs; + struct zip_extra_field *ef, *ef_prev, *ef_new; + int i, found, new_len; + + if ((flags & ZIP_EF_BOTH) == 0) { + _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + if (_zip_get_dirent(za, idx, 0, NULL) == NULL) + return -1; + + if (ZIP_IS_RDONLY(za)) { + _zip_error_set(&za->error, ZIP_ER_RDONLY, 0); + return -1; + } + + if (ZIP_EF_IS_INTERNAL(ef_id)) { + _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + if (_zip_file_extra_field_prepare_for_change(za, idx) < 0) + return -1; + + de = za->entry[idx].changes; + + ef = de->extra_fields; + ef_prev = NULL; + i = 0; + found = 0; + + for (; ef; ef=ef->next) { + if (ef->id == ef_id && (ef->flags & flags & ZIP_EF_BOTH)) { + if (i == ef_idx) { + found = 1; + break; + } + i++; + } + ef_prev = ef; + } + + if (i < ef_idx && ef_idx != ZIP_EXTRA_FIELD_NEW) { + _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + if (flags & ZIP_EF_LOCAL) + ls = _zip_ef_size(de->extra_fields, ZIP_EF_LOCAL); + else + ls = 0; + if (flags & ZIP_EF_CENTRAL) + cs = _zip_ef_size(de->extra_fields, ZIP_EF_CENTRAL); + else + cs = 0; + + new_len = ls > cs ? ls : cs; + if (found) + new_len -= ef->size + 4; + new_len += len + 4; + + if (new_len > ZIP_UINT16_MAX) { + _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + if ((ef_new=_zip_ef_new(ef_id, len, data, flags)) == NULL) { + _zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return -1; + } + + if (found) { + if ((ef->flags & ZIP_EF_BOTH) == (flags & ZIP_EF_BOTH)) { + ef_new->next = ef->next; + ef->next = NULL; + _zip_ef_free(ef); + if (ef_prev) + ef_prev->next = ef_new; + else + de->extra_fields = ef_new; + } + else { + ef->flags &= ~(flags & ZIP_EF_BOTH); + ef_new->next = ef->next; + ef->next = ef_new; + } + } + else if (ef_prev) { + ef_new->next = ef_prev->next; + ef_prev->next = ef_new; + } + else + de->extra_fields = ef_new; + + return 0; +} + + + +int +_zip_file_extra_field_prepare_for_change(struct zip *za, zip_uint64_t idx) +{ + struct zip_entry *e; + + if (idx >= za->nentry) { + _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + e = za->entry+idx; + + if (e->changes && (e->changes->changed & ZIP_DIRENT_EXTRA_FIELD)) + return 0; + + if (e->orig) { + if (_zip_read_local_ef(za, idx) < 0) + return -1; + } + + if (e->changes == NULL) { + if ((e->changes=_zip_dirent_clone(e->orig)) == NULL) { + _zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return -1; + } + } + + if (e->orig && e->orig->extra_fields) { + if ((e->changes->extra_fields=_zip_ef_clone(e->orig->extra_fields, &za->error)) == NULL) + return -1; + } + e->changes->changed |= ZIP_DIRENT_EXTRA_FIELD; + + return 0; +} + diff --git a/ext/zip/lib/zip_fclose.c b/ext/zip/lib/zip_fclose.c index eb55ddbcea..093c30eada 100644 --- a/ext/zip/lib/zip_fclose.c +++ b/ext/zip/lib/zip_fclose.c @@ -39,20 +39,23 @@ -ZIP_EXTERN(int) +ZIP_EXTERN int zip_fclose(struct zip_file *zf) { - int i, ret; + int ret; + unsigned int i; if (zf->src) zip_source_free(zf->src); - for (i=0; i<zf->za->nfile; i++) { - if (zf->za->file[i] == zf) { - zf->za->file[i] = zf->za->file[zf->za->nfile-1]; - zf->za->nfile--; - break; - } + if (zf->za) { + for (i=0; i<zf->za->nfile; i++) { + if (zf->za->file[i] == zf) { + zf->za->file[i] = zf->za->file[zf->za->nfile-1]; + zf->za->nfile--; + break; + } + } } ret = 0; diff --git a/ext/zip/lib/zip_fdopen.c b/ext/zip/lib/zip_fdopen.c index df70f27561..bda9aabac4 100644 --- a/ext/zip/lib/zip_fdopen.c +++ b/ext/zip/lib/zip_fdopen.c @@ -37,11 +37,24 @@ -ZIP_EXTERN(struct zip *) -zip_fdopen(int fd_orig, int flags, int *zep) +ZIP_EXTERN struct zip * +zip_fdopen(int fd_orig, int _flags, int *zep) { int fd; FILE *fp; + unsigned int flags; + + if (_flags < 0) { + if (zep) + *zep = ZIP_ER_INVAL; + return NULL; + } + flags = (unsigned int)_flags; + + if (flags & ZIP_TRUNCATE) { + *zep = ZIP_ER_INVAL; + return NULL; + } /* We dup() here to avoid messing with the passed in fd. We could not restore it to the original state in case of error. */ @@ -58,5 +71,5 @@ zip_fdopen(int fd_orig, int flags, int *zep) } close(fd_orig); - return _zip_open(NULL, fp, flags, ZIP_AFL_RDONLY, zep); + return _zip_open(NULL, fp, flags, zep); } diff --git a/ext/zip/lib/zip_file_add.c b/ext/zip/lib/zip_file_add.c new file mode 100644 index 0000000000..995cb91c1a --- /dev/null +++ b/ext/zip/lib/zip_file_add.c @@ -0,0 +1,55 @@ +/* + zip_file_add.c -- add file via callback function + Copyright (C) 1999-2012 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR 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. +*/ + + + +#include "zipint.h" + + +/* + NOTE: Return type is signed so we can return -1 on error. + The index can not be larger than ZIP_INT64_MAX since the size + of the central directory cannot be larger than + ZIP_UINT64_MAX, and each entry is larger than 2 bytes. +*/ + +ZIP_EXTERN zip_int64_t +zip_file_add(struct zip *za, const char *name, struct zip_source *source, zip_flags_t flags) +{ + if (name == NULL || source == NULL) { + _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + return _zip_file_replace(za, ZIP_UINT64_MAX, name, source, flags); +} diff --git a/ext/zip/lib/zip_file_error_clear.c b/ext/zip/lib/zip_file_error_clear.c index 6c9c2a02b3..ce8b6cbd94 100644 --- a/ext/zip/lib/zip_file_error_clear.c +++ b/ext/zip/lib/zip_file_error_clear.c @@ -37,8 +37,11 @@ -ZIP_EXTERN(void) +ZIP_EXTERN void zip_file_error_clear(struct zip_file *zf) { + if (zf == NULL) + return; + _zip_error_clear(&zf->error); } diff --git a/ext/zip/lib/zip_file_error_get.c b/ext/zip/lib/zip_file_error_get.c index a53fa7e003..f20e011fc7 100644 --- a/ext/zip/lib/zip_file_error_get.c +++ b/ext/zip/lib/zip_file_error_get.c @@ -37,7 +37,7 @@ -ZIP_EXTERN(void) +ZIP_EXTERN void zip_file_error_get(struct zip_file *zf, int *zep, int *sep) { _zip_error_get(&zf->error, zep, sep); diff --git a/ext/zip/lib/zip_get_file_extra.c b/ext/zip/lib/zip_file_get_comment.c index a27edd8ee9..766731ea26 100644 --- a/ext/zip/lib/zip_get_file_extra.c +++ b/ext/zip/lib/zip_file_get_comment.c @@ -1,6 +1,6 @@ /* - zip_get_file_extra.c -- get file extra field - Copyright (C) 2006-2010 Dieter Baron and Thomas Klausner + zip_file_get_comment.c -- get file comment + Copyright (C) 2006-2012 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -17,7 +17,7 @@ 3. The names of the authors may not be used to endorse or promote products derived from this software without specific prior written permission. - + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -31,28 +31,28 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - + #include "zipint.h" + +/* lenp is 32 bit because converted comment can be longer than ZIP_UINT16_MAX */ - -ZIP_EXTERN(const char *) -zip_get_file_extra(struct zip *za, zip_uint64_t idx, int *lenp, int flags) +ZIP_EXTERN const char * +zip_file_get_comment(struct zip *za, zip_uint64_t idx, zip_uint32_t *lenp, zip_flags_t flags) { - if (idx >= za->nentry) { - _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + struct zip_dirent *de; + zip_uint32_t len; + const zip_uint8_t *str; + + if ((de=_zip_get_dirent(za, idx, flags, NULL)) == NULL) return NULL; - } - - if ((flags & ZIP_FL_UNCHANGED) - || (za->entry[idx].ch_extra_len == -1)) { - if (lenp != NULL) - *lenp = za->cdir->entry[idx].extrafield_len; - return za->cdir->entry[idx].extrafield; - } - - if (lenp != NULL) - *lenp = za->entry[idx].ch_extra_len; - return za->entry[idx].ch_extra; + + if ((str=_zip_string_get(de->comment, &len, flags, &za->error)) == NULL) + return NULL; + + if (lenp) + *lenp = len; + + return (const char *)str; } diff --git a/ext/zip/lib/zip_file_get_offset.c b/ext/zip/lib/zip_file_get_offset.c index b96fd5e480..65a011fc07 100644 --- a/ext/zip/lib/zip_file_get_offset.c +++ b/ext/zip/lib/zip_file_get_offset.c @@ -50,25 +50,27 @@ On error, fills in za->error and returns 0. */ -unsigned int -_zip_file_get_offset(struct zip *za, int idx) +zip_uint64_t +_zip_file_get_offset(const struct zip *za, zip_uint64_t idx, struct zip_error *error) { - struct zip_dirent de; - unsigned int offset; + zip_uint64_t offset; + zip_int32_t size; - offset = za->cdir->entry[idx].offset; + offset = za->entry[idx].orig->offset; - if (fseeko(za->zp, offset, SEEK_SET) != 0) { - _zip_error_set(&za->error, ZIP_ER_SEEK, errno); + if (fseeko(za->zp, (off_t)offset, SEEK_SET) != 0) { + _zip_error_set(error, ZIP_ER_SEEK, errno); return 0; } - if (_zip_dirent_read(&de, za->zp, NULL, NULL, 1, &za->error) != 0) + /* XXX: cache? */ + if ((size=_zip_dirent_size(za->zp, ZIP_EF_LOCAL, error)) < 0) return 0; - offset += LENTRYSIZE + de.filename_len + de.extrafield_len; - - _zip_dirent_finalize(&de); - - return offset; + if (offset+(zip_uint32_t)size > ZIP_OFF_MAX) { + _zip_error_set(error, ZIP_ER_SEEK, EFBIG); + return 0; + } + + return offset + (zip_uint32_t)size; } diff --git a/ext/zip/lib/zip_set_file_extra.c b/ext/zip/lib/zip_file_rename.c index db829e2e0a..383a52adae 100644 --- a/ext/zip/lib/zip_set_file_extra.c +++ b/ext/zip/lib/zip_file_rename.c @@ -1,6 +1,6 @@ /* - zip_set_file_extra.c -- set extra field for file in archive - Copyright (C) 2006-2010 Dieter Baron and Thomas Klausner + zip_file_rename.c -- rename file in zip archive + Copyright (C) 1999-2012 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -17,7 +17,7 @@ 3. The names of the authors may not be used to endorse or promote products derived from this software without specific prior written permission. - + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -31,23 +31,21 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + - -#include <stdlib.h> +#include <string.h> #include "zipint.h" + - -ZIP_EXTERN(int) -zip_set_file_extra(struct zip *za, zip_uint64_t idx, - const char *extra, int len) +ZIP_EXTERN int +zip_file_rename(struct zip *za, zip_uint64_t idx, const char *name, zip_flags_t flags) { - char *tmpext; - - if (idx >= za->nentry - || len < 0 || len > MAXEXTLEN - || (len > 0 && extra == NULL)) { + const char *old_name; + int old_is_dir, new_is_dir; + + if (idx >= za->nentry || (name != NULL && strlen(name) > ZIP_UINT16_MAX)) { _zip_error_set(&za->error, ZIP_ER_INVAL, 0); return -1; } @@ -57,16 +55,16 @@ zip_set_file_extra(struct zip *za, zip_uint64_t idx, return -1; } - if (len > 0) { - if ((tmpext=(char *)_zip_memdup(extra, len, &za->error)) == NULL) - return -1; - } - else - tmpext = NULL; + if ((old_name=zip_get_name(za, idx, 0)) == NULL) + return -1; + + new_is_dir = (name != NULL && name[strlen(name)-1] == '/'); + old_is_dir = (old_name[strlen(old_name)-1] == '/'); - free(za->entry[idx].ch_extra); - za->entry[idx].ch_extra = tmpext; - za->entry[idx].ch_extra_len = len; + if (new_is_dir != old_is_dir) { + _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } - return 0; + return _zip_set_name(za, idx, name, flags); } diff --git a/ext/zip/lib/zip_file_replace.c b/ext/zip/lib/zip_file_replace.c new file mode 100644 index 0000000000..7e7e942168 --- /dev/null +++ b/ext/zip/lib/zip_file_replace.c @@ -0,0 +1,111 @@ +/* + zip_file_replace.c -- replace file via callback function + Copyright (C) 1999-2012 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR 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. +*/ + + + +#include "zipint.h" + + + +ZIP_EXTERN int +zip_file_replace(struct zip *za, zip_uint64_t idx, struct zip_source *source, zip_flags_t flags) +{ + if (idx >= za->nentry || source == NULL) { + _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + if (_zip_file_replace(za, idx, NULL, source, flags) == -1) + return -1; + + return 0; +} + + + + +/* NOTE: Signed due to -1 on error. See zip_add.c for more details. */ + +zip_int64_t +_zip_file_replace(struct zip *za, zip_uint64_t idx, const char *name, struct zip_source *source, zip_flags_t flags) +{ + zip_uint64_t za_nentry_prev; + + if (ZIP_IS_RDONLY(za)) { + _zip_error_set(&za->error, ZIP_ER_RDONLY, 0); + return -1; + } + + za_nentry_prev = za->nentry; + if (idx == ZIP_UINT64_MAX) { + zip_int64_t i = -1; + + if (flags & ZIP_FL_OVERWRITE) + i = _zip_name_locate(za, name, flags, NULL); + + if (i == -1) { + /* create and use new entry, used by zip_add */ + if ((i=_zip_add_entry(za)) < 0) + return -1; + } + idx = (zip_uint64_t)i; + } + + if (name && _zip_set_name(za, idx, name, flags) != 0) { + if (za->nentry != za_nentry_prev) { + _zip_entry_finalize(za->entry+idx); + za->nentry = za_nentry_prev; + } + return -1; + } + + /* does not change any name related data, so we can do it here; + * needed for a double add of the same file name */ + _zip_unchange_data(za->entry+idx); + + if (za->entry[idx].orig != NULL && (za->entry[idx].changes == NULL || (za->entry[idx].changes->changed & ZIP_DIRENT_COMP_METHOD) == 0)) { + if (za->entry[idx].changes == NULL) { + if ((za->entry[idx].changes=_zip_dirent_clone(za->entry[idx].orig)) == NULL) { + _zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return -1; + } + } + + za->entry[idx].changes->comp_method = ZIP_CM_REPLACED_DEFAULT; + za->entry[idx].changes->changed |= ZIP_DIRENT_COMP_METHOD; + } + + za->entry[idx].source = source; + + return (zip_int64_t)idx; +} diff --git a/ext/zip/lib/zip_file_set_comment.c b/ext/zip/lib/zip_file_set_comment.c new file mode 100644 index 0000000000..722f3d43cc --- /dev/null +++ b/ext/zip/lib/zip_file_set_comment.c @@ -0,0 +1,105 @@ +/* + zip_file_set_comment.c -- set comment for file in archive + Copyright (C) 2006-2012 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR 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. +*/ + + + +#include <stdlib.h> + +#include "zipint.h" + + + +ZIP_EXTERN int +zip_file_set_comment(struct zip *za, zip_uint64_t idx, + const char *comment, zip_uint16_t len, zip_flags_t flags) +{ + struct zip_entry *e; + struct zip_string *cstr; + int changed; + + if (_zip_get_dirent(za, idx, 0, NULL) == NULL) + return -1; + + if (ZIP_IS_RDONLY(za)) { + _zip_error_set(&za->error, ZIP_ER_RDONLY, 0); + return -1; + } + + if (len > 0 && comment == NULL) { + _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + if (len > 0) { + if ((cstr=_zip_string_new((const zip_uint8_t *)comment, len, flags, &za->error)) == NULL) + return -1; + if ((flags & ZIP_FL_ENCODING_ALL) == ZIP_FL_ENC_GUESS && _zip_guess_encoding(cstr, ZIP_ENCODING_UNKNOWN) == ZIP_ENCODING_UTF8_GUESSED) + cstr->encoding = ZIP_ENCODING_UTF8_KNOWN; + } + else + cstr = NULL; + + e = za->entry+idx; + + if (e->changes) { + _zip_string_free(e->changes->comment); + e->changes->comment = NULL; + e->changes->changed &= ~ZIP_DIRENT_COMMENT; + } + + if (e->orig && e->orig->comment) + changed = !_zip_string_equal(e->orig->comment, cstr); + else + changed = (cstr != NULL); + + if (changed) { + if (e->changes == NULL) { + if ((e->changes=_zip_dirent_clone(e->orig)) == NULL) { + _zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + _zip_string_free(cstr); + return -1; + } + } + e->changes->comment = cstr; + e->changes->changed |= ZIP_DIRENT_COMMENT; + } + else { + _zip_string_free(cstr); + if (e->changes && e->changes->changed == 0) { + _zip_dirent_free(e->changes); + e->changes = NULL; + } + } + + return 0; +} diff --git a/ext/zip/lib/zip_file_strerror.c b/ext/zip/lib/zip_file_strerror.c index c2864f2ba1..9ba70f14ff 100644 --- a/ext/zip/lib/zip_file_strerror.c +++ b/ext/zip/lib/zip_file_strerror.c @@ -37,7 +37,7 @@ -ZIP_EXTERN(const char *) +ZIP_EXTERN const char * zip_file_strerror(struct zip_file *zf) { return _zip_error_strerror(&zf->error); diff --git a/ext/zip/lib/zip_filerange_crc.c b/ext/zip/lib/zip_filerange_crc.c index 4d1ad56692..3b1c868407 100644 --- a/ext/zip/lib/zip_filerange_crc.c +++ b/ext/zip/lib/zip_filerange_crc.c @@ -1,6 +1,6 @@ /* zip_filerange_crc.c -- compute CRC32 for a range of a file - Copyright (C) 2008 Dieter Baron and Thomas Klausner + Copyright (C) 2008-2013 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -56,13 +56,13 @@ _zip_filerange_crc(FILE *fp, off_t start, off_t len, uLong *crcp, } while (len > 0) { - n = len > BUFSIZE ? BUFSIZE : len; - if ((n=fread(buf, 1, n, fp)) <= 0) { + n = len > BUFSIZE ? BUFSIZE : (size_t)len; + if ((n=fread(buf, 1, n, fp)) == 0) { _zip_error_set(errp, ZIP_ER_READ, errno); return -1; } - *crcp = crc32(*crcp, buf, n); + *crcp = crc32(*crcp, buf, (uInt)n); len-= n; } diff --git a/ext/zip/lib/zip_fopen.c b/ext/zip/lib/zip_fopen.c index f62adbbf92..331f79ea36 100644 --- a/ext/zip/lib/zip_fopen.c +++ b/ext/zip/lib/zip_fopen.c @@ -37,13 +37,13 @@ -ZIP_EXTERN(struct zip_file *) -zip_fopen(struct zip *za, const char *fname, int flags) +ZIP_EXTERN struct zip_file * +zip_fopen(struct zip *za, const char *fname, zip_flags_t flags) { - int idx; + zip_int64_t idx; if ((idx=zip_name_locate(za, fname, flags)) < 0) return NULL; - return zip_fopen_index_encrypted(za, idx, flags, za->default_password); + return zip_fopen_index_encrypted(za, (zip_uint64_t)idx, flags, za->default_password); } diff --git a/ext/zip/lib/zip_fopen_encrypted.c b/ext/zip/lib/zip_fopen_encrypted.c index 8aba062567..34230f00d7 100644 --- a/ext/zip/lib/zip_fopen_encrypted.c +++ b/ext/zip/lib/zip_fopen_encrypted.c @@ -37,14 +37,13 @@ -ZIP_EXTERN(struct zip_file *) -zip_fopen_encrypted(struct zip *za, const char *fname, int flags, - const char *password) +ZIP_EXTERN struct zip_file * +zip_fopen_encrypted(struct zip *za, const char *fname, zip_flags_t flags, const char *password) { - int idx; + zip_int64_t idx; if ((idx=zip_name_locate(za, fname, flags)) < 0) return NULL; - return zip_fopen_index_encrypted(za, idx, flags, password); + return zip_fopen_index_encrypted(za, (zip_uint64_t)idx, flags, password); } diff --git a/ext/zip/lib/zip_fopen_index.c b/ext/zip/lib/zip_fopen_index.c index b60fd33e8f..30466ffa19 100644 --- a/ext/zip/lib/zip_fopen_index.c +++ b/ext/zip/lib/zip_fopen_index.c @@ -1,6 +1,6 @@ /* zip_fopen_index.c -- open file in zip archive for reading by index - Copyright (C) 1999-2009 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2013 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -41,8 +41,8 @@ -ZIP_EXTERN(struct zip_file *) -zip_fopen_index(struct zip *za, zip_uint64_t fileno, int flags) +ZIP_EXTERN struct zip_file * +zip_fopen_index(struct zip *za, zip_uint64_t index, zip_flags_t flags) { - return zip_fopen_index_encrypted(za, fileno, flags, za->default_password); + return zip_fopen_index_encrypted(za, index, flags, za->default_password); } diff --git a/ext/zip/lib/zip_fopen_index_encrypted.c b/ext/zip/lib/zip_fopen_index_encrypted.c index 988a78fe03..cc81ca7f53 100644 --- a/ext/zip/lib/zip_fopen_index_encrypted.c +++ b/ext/zip/lib/zip_fopen_index_encrypted.c @@ -1,6 +1,6 @@ /* zip_fopen_index_encrypted.c -- open file for reading by index w/ password - Copyright (C) 1999-2009 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2013 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -43,103 +43,15 @@ static struct zip_file *_zip_file_new(struct zip *za); -ZIP_EXTERN(struct zip_file *) -zip_fopen_index_encrypted(struct zip *za, zip_uint64_t fileno, int flags, +ZIP_EXTERN struct zip_file * +zip_fopen_index_encrypted(struct zip *za, zip_uint64_t index, zip_flags_t flags, const char *password) { struct zip_file *zf; - zip_compression_implementation comp_impl; - zip_encryption_implementation enc_impl; - struct zip_source *src, *s2; - zip_uint64_t start; - struct zip_stat st; - - if (fileno >= za->nentry) { - _zip_error_set(&za->error, ZIP_ER_INVAL, 0); - return NULL; - } + struct zip_source *src; - if ((flags & ZIP_FL_UNCHANGED) == 0 - && ZIP_ENTRY_DATA_CHANGED(za->entry+fileno)) { - _zip_error_set(&za->error, ZIP_ER_CHANGED, 0); + if ((src=_zip_source_zip_new(za, za, index, flags, 0, 0, password)) == NULL) return NULL; - } - - if (fileno >= za->cdir->nentry) { - _zip_error_set(&za->error, ZIP_ER_INVAL, 0); - return NULL; - } - - if (flags & ZIP_FL_ENCRYPTED) - flags |= ZIP_FL_COMPRESSED; - - zip_stat_index(za, fileno, flags, &st); - - enc_impl = NULL; - if ((flags & ZIP_FL_ENCRYPTED) == 0) { - if (st.encryption_method != ZIP_EM_NONE) { - if (password == NULL) { - _zip_error_set(&za->error, ZIP_ER_NOPASSWD, 0); - return NULL; - } - if ((enc_impl=zip_get_encryption_implementation( - st.encryption_method)) == NULL) { - _zip_error_set(&za->error, ZIP_ER_ENCRNOTSUPP, 0); - return NULL; - } - } - } - - comp_impl = NULL; - if ((flags & ZIP_FL_COMPRESSED) == 0) { - if (st.comp_method != ZIP_CM_STORE) { - if ((comp_impl=zip_get_compression_implementation( - st.comp_method)) == NULL) { - _zip_error_set(&za->error, ZIP_ER_COMPNOTSUPP, 0); - return NULL; - } - } - } - - if ((start=_zip_file_get_offset(za, fileno)) == 0) - return NULL; - - if (st.comp_size == 0) { - if ((src=zip_source_buffer(za, NULL, 0, 0)) == NULL) - return NULL; - } - else { - if ((src=_zip_source_file_or_p(za, NULL, za->zp, start, st.comp_size, - 0, &st)) == NULL) - return NULL; - if (enc_impl) { - if ((s2=enc_impl(za, src, ZIP_EM_TRAD_PKWARE, 0, - password)) == NULL) { - zip_source_free(src); - /* XXX: set error (how?) */ - return NULL; - } - src = s2; - } - if (comp_impl) { - if ((s2=comp_impl(za, src, za->cdir->entry[fileno].comp_method, - 0)) == NULL) { - zip_source_free(src); - /* XXX: set error (how?) */ - return NULL; - } - src = s2; - } - if ((flags & ZIP_FL_COMPRESSED) == 0 - || st.comp_method == ZIP_CM_STORE ) { - if ((s2=zip_source_crc(za, src, 1)) == NULL) { - zip_source_free(src); - /* XXX: set error (how?) */ - return NULL; - } - src = s2; - } - } if (zip_source_open(src) < 0) { _zip_error_set_from_source(&za->error, src); @@ -147,7 +59,10 @@ zip_fopen_index_encrypted(struct zip *za, zip_uint64_t fileno, int flags, return NULL; } - zf = _zip_file_new(za); + if ((zf=_zip_file_new(za)) == NULL) { + zip_source_free(src); + return NULL; + } zf->src = src; @@ -160,14 +75,14 @@ static struct zip_file * _zip_file_new(struct zip *za) { struct zip_file *zf, **file; - int n; if ((zf=(struct zip_file *)malloc(sizeof(struct zip_file))) == NULL) { _zip_error_set(&za->error, ZIP_ER_MEMORY, 0); return NULL; } - if (za->nfile >= za->nfile_alloc-1) { + if (za->nfile+1 >= za->nfile_alloc) { + unsigned int n; n = za->nfile_alloc + 10; file = (struct zip_file **)realloc(za->file, n*sizeof(struct zip_file *)); diff --git a/ext/zip/lib/zip_fread.c b/ext/zip/lib/zip_fread.c index a6c0851b0a..8235c6dfac 100644 --- a/ext/zip/lib/zip_fread.c +++ b/ext/zip/lib/zip_fread.c @@ -37,7 +37,7 @@ -ZIP_EXTERN(zip_int64_t) +ZIP_EXTERN zip_int64_t zip_fread(struct zip_file *zf, void *outbuf, zip_uint64_t toread) { zip_int64_t n; diff --git a/ext/zip/lib/zip_get_archive_comment.c b/ext/zip/lib/zip_get_archive_comment.c index fe97e6e8c1..202f761f4e 100644 --- a/ext/zip/lib/zip_get_archive_comment.c +++ b/ext/zip/lib/zip_get_archive_comment.c @@ -1,6 +1,6 @@ /* zip_get_archive_comment.c -- get archive comment - Copyright (C) 2006-2007 Dieter Baron and Thomas Klausner + Copyright (C) 2006-2012 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -33,28 +33,29 @@ +#include <string.h> + #include "zipint.h" -ZIP_EXTERN(const char *) -zip_get_archive_comment(struct zip *za, int *lenp, int flags) +ZIP_EXTERN const char * +zip_get_archive_comment(struct zip *za, int *lenp, zip_flags_t flags) { - if ((flags & ZIP_FL_UNCHANGED) - || (za->ch_comment_len == -1)) { - if (za->cdir) { - if (lenp != NULL) - *lenp = za->cdir->comment_len; - return za->cdir->comment; - } - else { - if (lenp != NULL) - *lenp = -1; - return NULL; - } - } - - if (lenp != NULL) - *lenp = za->ch_comment_len; - return za->ch_comment; + struct zip_string *comment; + zip_uint32_t len; + const zip_uint8_t *str; + + if ((flags & ZIP_FL_UNCHANGED) || (za->comment_changes == NULL)) + comment = za->comment_orig; + else + comment = za->comment_changes; + + if ((str=_zip_string_get(comment, &len, flags, &za->error)) == NULL) + return NULL; + + if (lenp) + *lenp = (int)len; + + return (const char *)str; } diff --git a/ext/zip/lib/zip_get_archive_flag.c b/ext/zip/lib/zip_get_archive_flag.c index 2d46aa39ff..c3be5c14fe 100644 --- a/ext/zip/lib/zip_get_archive_flag.c +++ b/ext/zip/lib/zip_get_archive_flag.c @@ -37,10 +37,10 @@ -ZIP_EXTERN(int) -zip_get_archive_flag(struct zip *za, int flag, int flags) +ZIP_EXTERN int +zip_get_archive_flag(struct zip *za, unsigned int flag, zip_flags_t flags) { - int fl; + unsigned int fl; fl = (flags & ZIP_FL_UNCHANGED) ? za->flags : za->ch_flags; diff --git a/ext/zip/lib/zip_get_compression_implementation.c b/ext/zip/lib/zip_get_compression_implementation.c index 197cd49635..aa4a1605c0 100644 --- a/ext/zip/lib/zip_get_compression_implementation.c +++ b/ext/zip/lib/zip_get_compression_implementation.c @@ -37,10 +37,10 @@ -ZIP_EXTERN(zip_compression_implementation) -zip_get_compression_implementation(zip_uint16_t cm) +zip_compression_implementation +_zip_get_compression_implementation(zip_int32_t cm) { - if (cm == ZIP_CM_DEFLATE) + if (cm == ZIP_CM_DEFLATE || ZIP_CM_IS_DEFAULT(cm)) return zip_source_deflate; return NULL; } diff --git a/ext/zip/lib/zip_get_encryption_implementation.c b/ext/zip/lib/zip_get_encryption_implementation.c index 783d538d3f..7dcb99210d 100644 --- a/ext/zip/lib/zip_get_encryption_implementation.c +++ b/ext/zip/lib/zip_get_encryption_implementation.c @@ -37,8 +37,8 @@ -ZIP_EXTERN(zip_encryption_implementation) -zip_get_encryption_implementation(zip_uint16_t em) +zip_encryption_implementation +_zip_get_encryption_implementation(zip_uint16_t em) { if (em == ZIP_EM_TRAD_PKWARE) return zip_source_pkware; diff --git a/ext/zip/lib/zip_get_file_comment.c b/ext/zip/lib/zip_get_file_comment.c index 43c1520e1d..3be459d4da 100644 --- a/ext/zip/lib/zip_get_file_comment.c +++ b/ext/zip/lib/zip_get_file_comment.c @@ -1,6 +1,6 @@ /* zip_get_file_comment.c -- get file comment - Copyright (C) 2006-2007 Dieter Baron and Thomas Klausner + Copyright (C) 2006-2012 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -33,26 +33,21 @@ +#define _ZIP_COMPILING_DEPRECATED #include "zipint.h" -ZIP_EXTERN(const char *) +ZIP_EXTERN const char * zip_get_file_comment(struct zip *za, zip_uint64_t idx, int *lenp, int flags) { - if (idx >= za->nentry) { - _zip_error_set(&za->error, ZIP_ER_INVAL, 0); - return NULL; - } + zip_uint32_t len; + const char *s; - if ((flags & ZIP_FL_UNCHANGED) - || (za->entry[idx].ch_comment_len == -1)) { - if (lenp != NULL) - *lenp = za->cdir->entry[idx].comment_len; - return za->cdir->entry[idx].comment; + if ((s=zip_file_get_comment(za, idx, &len, (zip_flags_t)flags)) != NULL) { + if (lenp) + *lenp = (int)len; } - - if (lenp != NULL) - *lenp = za->entry[idx].ch_comment_len; - return za->entry[idx].ch_comment; + + return s; } diff --git a/ext/zip/lib/zip_get_name.c b/ext/zip/lib/zip_get_name.c index 945e24e150..f67c7caf43 100644 --- a/ext/zip/lib/zip_get_name.c +++ b/ext/zip/lib/zip_get_name.c @@ -1,6 +1,6 @@ /* zip_get_name.c -- get filename for a file in zip file - Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2012 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -33,12 +33,14 @@ +#include <string.h> + #include "zipint.h" -ZIP_EXTERN(const char *) -zip_get_name(struct zip *za, zip_uint64_t idx, int flags) +ZIP_EXTERN const char * +zip_get_name(struct zip *za, zip_uint64_t idx, zip_flags_t flags) { return _zip_get_name(za, idx, flags, &za->error); } @@ -46,27 +48,16 @@ zip_get_name(struct zip *za, zip_uint64_t idx, int flags) const char * -_zip_get_name(struct zip *za, zip_uint64_t idx, int flags, - struct zip_error *error) +_zip_get_name(struct zip *za, zip_uint64_t idx, zip_flags_t flags, struct zip_error *error) { - if (idx >= za->nentry) { - _zip_error_set(error, ZIP_ER_INVAL, 0); - return NULL; - } + struct zip_dirent *de; + const zip_uint8_t *str; - if ((flags & ZIP_FL_UNCHANGED) == 0) { - if (za->entry[idx].state == ZIP_ST_DELETED) { - _zip_error_set(error, ZIP_ER_DELETED, 0); - return NULL; - } - if (za->entry[idx].ch_filename) - return za->entry[idx].ch_filename; - } + if ((de=_zip_get_dirent(za, idx, flags, error)) == NULL) + return NULL; - if (za->cdir == NULL || idx >= za->cdir->nentry) { - _zip_error_set(error, ZIP_ER_INVAL, 0); + if ((str=_zip_string_get(de->filename, NULL, flags, error)) == NULL) return NULL; - } - - return za->cdir->entry[idx].filename; + + return (const char *)str; } diff --git a/ext/zip/lib/zip_get_num_entries.c b/ext/zip/lib/zip_get_num_entries.c index dd392e9095..26484baff2 100644 --- a/ext/zip/lib/zip_get_num_entries.c +++ b/ext/zip/lib/zip_get_num_entries.c @@ -37,16 +37,19 @@ -ZIP_EXTERN(zip_uint64_t) -zip_get_num_entries(struct zip *za, int flags) +ZIP_EXTERN zip_int64_t +zip_get_num_entries(struct zip *za, zip_flags_t flags) { + zip_uint64_t n; + if (za == NULL) return -1; if (flags & ZIP_FL_UNCHANGED) { - if (za->cdir == NULL) - return 0; - return za->cdir->nentry; + n = za->nentry; + while (n>0 && za->entry[n-1].orig == NULL) + --n; + return (zip_int64_t)n; } - return za->nentry; + return (zip_int64_t)za->nentry; } diff --git a/ext/zip/lib/zip_get_num_files.c b/ext/zip/lib/zip_get_num_files.c index a442f293ec..29b06dc819 100644 --- a/ext/zip/lib/zip_get_num_files.c +++ b/ext/zip/lib/zip_get_num_files.c @@ -33,15 +33,17 @@ +#define _ZIP_COMPILING_DEPRECATED #include "zipint.h" -ZIP_EXTERN(int) +ZIP_EXTERN int zip_get_num_files(struct zip *za) { if (za == NULL) return -1; - return za->nentry; + /* XXX: check for overflow */ + return (int)za->nentry; } diff --git a/ext/zip/lib/zip_memdup.c b/ext/zip/lib/zip_memdup.c index 641125ed2d..06af2dabd3 100644 --- a/ext/zip/lib/zip_memdup.c +++ b/ext/zip/lib/zip_memdup.c @@ -1,6 +1,6 @@ /* zip_memdup.c -- internal zip function, "strdup" with len - Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2012 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -43,6 +43,9 @@ _zip_memdup(const void *mem, size_t len, struct zip_error *error) { void *ret; + if (len == 0) + return NULL; + ret = malloc(len); if (!ret) { _zip_error_set(error, ZIP_ER_MEMORY, 0); diff --git a/ext/zip/lib/zip_name_locate.c b/ext/zip/lib/zip_name_locate.c index 8cdd2c4d7e..3cac110543 100644 --- a/ext/zip/lib/zip_name_locate.c +++ b/ext/zip/lib/zip_name_locate.c @@ -34,26 +34,28 @@ #include <string.h> +#ifdef HAVE_STRINGS_H +#include <strings.h> +#endif #include "zipint.h" -ZIP_EXTERN(int) -zip_name_locate(struct zip *za, const char *fname, int flags) +ZIP_EXTERN zip_int64_t +zip_name_locate(struct zip *za, const char *fname, zip_flags_t flags) { return _zip_name_locate(za, fname, flags, &za->error); } -int -_zip_name_locate(struct zip *za, const char *fname, int flags, - struct zip_error *error) +zip_int64_t +_zip_name_locate(struct zip *za, const char *fname, zip_flags_t flags, struct zip_error *error) { int (*cmp)(const char *, const char *); const char *fn, *p; - int i, n; + zip_uint64_t i; if (za == NULL) return -1; @@ -63,21 +65,12 @@ _zip_name_locate(struct zip *za, const char *fname, int flags, return -1; } - if ((flags & ZIP_FL_UNCHANGED) && za->cdir == NULL) { - _zip_error_set(error, ZIP_ER_NOENT, 0); - return -1; - } - - cmp = (flags & ZIP_FL_NOCASE) ? strcmpi : strcmp; + cmp = (flags & ZIP_FL_NOCASE) ? strcasecmp : strcmp; - n = (flags & ZIP_FL_UNCHANGED) ? za->cdir->nentry : za->nentry; - for (i=0; i<n; i++) { - if (flags & ZIP_FL_UNCHANGED) - fn = za->cdir->entry[i].filename; - else - fn = _zip_get_name(za, i, flags, error); + for (i=0; i<za->nentry; i++) { + fn = _zip_get_name(za, i, flags, error); - /* newly added (partially filled) entry */ + /* newly added (partially filled) entry or error */ if (fn == NULL) continue; @@ -87,11 +80,12 @@ _zip_name_locate(struct zip *za, const char *fname, int flags, fn = p+1; } - if (cmp(fname, fn) == 0) - return i; + if (cmp(fname, fn) == 0) { + _zip_error_clear(error); + return (zip_int64_t)i; + } } -/* Look for an entry should not raise an error */ -/* _zip_error_set(error, ZIP_ER_NOENT, 0);*/ + _zip_error_set(error, ZIP_ER_NOENT, 0); return -1; } diff --git a/ext/zip/lib/zip_new.c b/ext/zip/lib/zip_new.c index 7ce1237cdb..f77634a389 100644 --- a/ext/zip/lib/zip_new.c +++ b/ext/zip/lib/zip_new.c @@ -1,6 +1,6 @@ /* zip_new.c -- create and init struct zip - Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2012 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -56,16 +56,17 @@ _zip_new(struct zip_error *error) za->zn = NULL; za->zp = NULL; + za->open_flags = 0; _zip_error_init(&za->error); - za->cdir = NULL; - za->ch_comment = NULL; - za->ch_comment_len = -1; + za->flags = za->ch_flags = 0; + za->default_password = NULL; + za->comment_orig = za->comment_changes = NULL; + za->comment_changed = 0; za->nentry = za->nentry_alloc = 0; za->entry = NULL; za->nfile = za->nfile_alloc = 0; za->file = NULL; - za->flags = za->ch_flags = 0; - za->default_password = NULL; + za->tempdir = NULL; return za; } diff --git a/ext/zip/lib/zip_open.c b/ext/zip/lib/zip_open.c index 5ce1c1070a..e6a30d5ae7 100644 --- a/ext/zip/lib/zip_open.c +++ b/ext/zip/lib/zip_open.c @@ -1,6 +1,6 @@ /* zip_open.c -- open zip archive by name - Copyright (C) 1999-2011 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2012 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -42,38 +42,53 @@ #include "zipint.h" -static void set_error(int *, struct zip_error *, int); -static struct zip *_zip_allocate_new(const char *, int *); -static int _zip_checkcons(FILE *, struct zip_cdir *, struct zip_error *); -static void _zip_check_torrentzip(struct zip *); -static struct zip_cdir *_zip_find_central_dir(FILE *, int, int *, off_t); -static int _zip_file_exists(const char *, int, int *); -static int _zip_headercomp(struct zip_dirent *, int, - struct zip_dirent *, int); -static unsigned char *_zip_memmem(const unsigned char *, int, - const unsigned char *, int); -static struct zip_cdir *_zip_readcdir(FILE *, off_t, unsigned char *, unsigned char *, - int, int, struct zip_error *); +static void set_error(int *, const struct zip_error *, int); +static struct zip *_zip_allocate_new(const char *, unsigned int, int *); +static zip_int64_t _zip_checkcons(FILE *, struct zip_cdir *, struct zip_error *); +static void _zip_check_torrentzip(struct zip *, const struct zip_cdir *); +static struct zip_cdir *_zip_find_central_dir(FILE *, unsigned int, int *, off_t); +static int _zip_file_exists(const char *, unsigned int, int *); +static int _zip_headercomp(const struct zip_dirent *, const struct zip_dirent *); +static unsigned char *_zip_memmem(const unsigned char *, size_t, + const unsigned char *, size_t); +static struct zip_cdir *_zip_readcdir(FILE *, off_t, unsigned char *, const unsigned char *, + size_t, unsigned int, struct zip_error *); +static struct zip_cdir *_zip_read_eocd(const unsigned char *, const unsigned char *, off_t, + size_t, unsigned int, struct zip_error *); +static struct zip_cdir *_zip_read_eocd64(FILE *, const unsigned char *, const unsigned char *, + off_t, size_t, unsigned int, struct zip_error *); -ZIP_EXTERN(struct zip *) -zip_open(const char *fn, int flags, int *zep) +ZIP_EXTERN struct zip * +zip_open(const char *fn, int _flags, int *zep) { FILE *fp; - - if (flags & ZIP_OVERWRITE) { - return _zip_allocate_new(fn, zep); + unsigned int flags; + + if (_flags < 0) { + if (zep) + *zep = ZIP_ER_INVAL; + return NULL; } - + flags = (unsigned int)_flags; + switch (_zip_file_exists(fn, flags, zep)) { case -1: - if (!(flags & ZIP_OVERWRITE)) { - return NULL; - } + return NULL; case 0: - return _zip_allocate_new(fn, zep); + return _zip_allocate_new(fn, flags, zep); default: + if (flags & ZIP_TRUNCATE) { + FILE *f; + + if ((f = fopen(fn, "rb")) == NULL) { + set_error(zep, NULL, ZIP_ER_OPEN); + return NULL; + } + fclose(f); + return _zip_allocate_new(fn, flags, zep); + } break; } @@ -82,17 +97,36 @@ zip_open(const char *fn, int flags, int *zep) return NULL; } - return _zip_open(fn, fp, flags, 0, zep); + return _zip_open(fn, fp, flags, zep); } + +ZIP_EXTERN int +zip_archive_set_tempdir(struct zip *za, const char *tempdir) +{ + char *new_tempdir; + + if (tempdir) { + if ((new_tempdir = strdup(tempdir)) == NULL) { + _zip_error_set(&za->error, ZIP_ER_MEMORY, errno); + return -1; + } + } + else + new_tempdir = NULL; + + free(za->tempdir); + za->tempdir = new_tempdir; + + return 0; +} struct zip * -_zip_open(const char *fn, FILE *fp, int flags, int aflags, int *zep) +_zip_open(const char *fn, FILE *fp, unsigned int flags, int *zep) { struct zip *za; struct zip_cdir *cdir; - int i; off_t len; if (fseeko(fp, 0, SEEK_END) < 0) { @@ -103,7 +137,7 @@ _zip_open(const char *fn, FILE *fp, int flags, int aflags, int *zep) /* treat empty files as empty archives */ if (len == 0) { - if ((za=_zip_allocate_new(fn, zep)) == NULL) + if ((za=_zip_allocate_new(fn, flags, zep)) == NULL) fclose(fp); else za->zp = fp; @@ -116,34 +150,32 @@ _zip_open(const char *fn, FILE *fp, int flags, int aflags, int *zep) return NULL; } - if ((za=_zip_allocate_new(fn, zep)) == NULL) { + if ((za=_zip_allocate_new(fn, flags, zep)) == NULL) { _zip_cdir_free(cdir); fclose(fp); return NULL; } - za->cdir = cdir; + za->entry = cdir->entry; + za->nentry = cdir->nentry; + za->nentry_alloc = cdir->nentry_alloc; + za->comment_orig = cdir->comment; + za->zp = fp; - if ((za->entry=(struct zip_entry *)malloc(sizeof(*(za->entry)) - * cdir->nentry)) == NULL) { - set_error(zep, NULL, ZIP_ER_MEMORY); - _zip_free(za); - return NULL; - } - for (i=0; i<cdir->nentry; i++) - _zip_entry_new(za); + _zip_check_torrentzip(za, cdir); - _zip_check_torrentzip(za); za->ch_flags = za->flags; + free(cdir); + return za; } static void -set_error(int *zep, struct zip_error *err, int ze) +set_error(int *zep, const struct zip_error *err, int ze) { int se; @@ -166,16 +198,17 @@ set_error(int *zep, struct zip_error *err, int ze) entries, or NULL if unsuccessful. */ static struct zip_cdir * -_zip_readcdir(FILE *fp, off_t buf_offset, unsigned char *buf, unsigned char *eocd, int buflen, - int flags, struct zip_error *error) +_zip_readcdir(FILE *fp, off_t buf_offset, unsigned char *buf, const unsigned char *eocd, size_t buflen, + unsigned int flags, struct zip_error *error) { struct zip_cdir *cd; - unsigned char *cdp, **bufp; - int i, comlen, nentry; - zip_uint32_t left; + const unsigned char *cdp; + const unsigned char **bufp; + zip_int64_t tail_len, comment_len; + zip_uint64_t i, left; - comlen = buf + buflen - eocd - EOCDLEN; - if (comlen < 0) { + tail_len = buf + buflen - eocd - EOCDLEN; + if (tail_len < 0) { /* not enough bytes left for comment */ _zip_error_set(error, ZIP_ER_NOZIP, 0); return NULL; @@ -192,46 +225,32 @@ _zip_readcdir(FILE *fp, off_t buf_offset, unsigned char *buf, unsigned char *eoc return NULL; } - cdp = eocd + 8; - /* number of cdir-entries on this disk */ - i = _zip_read2(&cdp); - /* number of cdir-entries */ - nentry = _zip_read2(&cdp); + if (eocd-EOCD64LOCLEN >= buf && memcmp(eocd-EOCD64LOCLEN, EOCD64LOC_MAGIC, 4) == 0) + cd = _zip_read_eocd64(fp, eocd-EOCD64LOCLEN, buf, buf_offset, buflen, flags, error); + else + cd = _zip_read_eocd(eocd, buf, buf_offset, buflen, flags, error); - if ((cd=_zip_cdir_new(nentry, error)) == NULL) + if (cd == NULL) return NULL; - cd->size = _zip_read4(&cdp); - cd->offset = _zip_read4(&cdp); - cd->comment = NULL; - cd->comment_len = _zip_read2(&cdp); + cdp = eocd + 20; + comment_len = _zip_read2(&cdp); - if (((zip_uint64_t)cd->offset)+cd->size > buf_offset + (eocd-buf)) { + if ((zip_uint64_t)cd->offset+(zip_uint64_t)cd->size > (zip_uint64_t)buf_offset + (zip_uint64_t)(eocd-buf)) { /* cdir spans past EOCD record */ _zip_error_set(error, ZIP_ER_INCONS, 0); - cd->nentry = 0; _zip_cdir_free(cd); return NULL; } - if ((comlen < cd->comment_len) || (cd->nentry != i)) { - _zip_error_set(error, ZIP_ER_NOZIP, 0); - cd->nentry = 0; - _zip_cdir_free(cd); - return NULL; - } - if ((flags & ZIP_CHECKCONS) && comlen != cd->comment_len) { + if (tail_len < comment_len || ((flags & ZIP_CHECKCONS) && tail_len != comment_len)) { _zip_error_set(error, ZIP_ER_INCONS, 0); - cd->nentry = 0; _zip_cdir_free(cd); return NULL; } - if (cd->comment_len) { - if ((cd->comment=(char *)_zip_memdup(eocd+EOCDLEN, - cd->comment_len, error)) - == NULL) { - cd->nentry = 0; + if (comment_len) { + if ((cd->comment=_zip_string_new(eocd+EOCDLEN, (zip_uint16_t)comment_len, ZIP_FL_ENC_GUESS, error)) == NULL) { _zip_cdir_free(cd); return NULL; } @@ -249,40 +268,32 @@ _zip_readcdir(FILE *fp, off_t buf_offset, unsigned char *buf, unsigned char *eoc fseeko(fp, cd->offset, SEEK_SET); /* possible consistency check: cd->offset = len-(cd->size+cd->comment_len+EOCDLEN) ? */ - if (ferror(fp) || ((unsigned long)ftello(fp) != cd->offset)) { + if (ferror(fp) || (ftello(fp) != cd->offset)) { /* seek error or offset of cdir wrong */ if (ferror(fp)) _zip_error_set(error, ZIP_ER_SEEK, errno); else _zip_error_set(error, ZIP_ER_NOZIP, 0); - cd->nentry = 0; _zip_cdir_free(cd); return NULL; } } - left = cd->size; + left = (zip_uint64_t)cd->size; i=0; while (i<cd->nentry && left > 0) { - if ((_zip_dirent_read(cd->entry+i, fp, bufp, &left, 0, error)) < 0) { - cd->nentry = i; + if ((cd->entry[i].orig=_zip_dirent_new()) == NULL + || (_zip_dirent_read(cd->entry[i].orig, fp, bufp, &left, 0, error)) < 0) { _zip_cdir_free(cd); return NULL; } i++; - - if (i == cd->nentry && left > 0) { - /* Infozip extension for more than 64k entries: - nentries wraps around, size indicates correct EOCD */ - if (_zip_cdir_grow(cd, cd->nentry+ZIP_UINT16_MAX, error) < 0) { - cd->nentry = i; - _zip_cdir_free(cd); - return NULL; - } - } } - - cd->nentry = i; + if (i != cd->nentry || ((flags & ZIP_CHECKCONS) && left != 0)) { + _zip_error_set(error, ZIP_ER_INCONS, 0); + _zip_cdir_free(cd); + return NULL; + } return cd; } @@ -295,84 +306,88 @@ _zip_readcdir(FILE *fp, off_t buf_offset, unsigned char *buf, unsigned char *eoc file and header offsets. Returns -1 if not plausible, else the difference between the lowest and the highest fileposition reached */ -static int +static zip_int64_t _zip_checkcons(FILE *fp, struct zip_cdir *cd, struct zip_error *error) { - int i; - unsigned int min, max, j; + zip_uint64_t i; + zip_uint64_t min, max, j; struct zip_dirent temp; if (cd->nentry) { - max = cd->entry[0].offset; - min = cd->entry[0].offset; + max = cd->entry[0].orig->offset; + min = cd->entry[0].orig->offset; } else min = max = 0; for (i=0; i<cd->nentry; i++) { - if (cd->entry[i].offset < min) - min = cd->entry[i].offset; - if (min > cd->offset) { + if (cd->entry[i].orig->offset < min) + min = cd->entry[i].orig->offset; + if (min > (zip_uint64_t)cd->offset) { _zip_error_set(error, ZIP_ER_NOZIP, 0); return -1; } - j = cd->entry[i].offset + cd->entry[i].comp_size - + cd->entry[i].filename_len + LENTRYSIZE; + j = cd->entry[i].orig->offset + cd->entry[i].orig->comp_size + + _zip_string_length(cd->entry[i].orig->filename) + LENTRYSIZE; if (j > max) max = j; - if (max > cd->offset) { + if (max > (zip_uint64_t)cd->offset) { _zip_error_set(error, ZIP_ER_NOZIP, 0); return -1; } - if (fseeko(fp, cd->entry[i].offset, SEEK_SET) != 0) { - _zip_error_set(error, ZIP_ER_SEEK, 0); + if (fseeko(fp, (off_t)cd->entry[i].orig->offset, SEEK_SET) != 0) { + _zip_error_set(error, ZIP_ER_SEEK, errno); return -1; } if (_zip_dirent_read(&temp, fp, NULL, NULL, 1, error) == -1) return -1; - if (_zip_headercomp(cd->entry+i, 0, &temp, 1) != 0) { + if (_zip_headercomp(cd->entry[i].orig, &temp) != 0) { _zip_error_set(error, ZIP_ER_INCONS, 0); _zip_dirent_finalize(&temp); return -1; } + + cd->entry[i].orig->extra_fields = _zip_ef_merge(cd->entry[i].orig->extra_fields, temp.extra_fields); + cd->entry[i].orig->local_extra_fields_read = 1; + temp.extra_fields = NULL; + _zip_dirent_finalize(&temp); } - return max - min; + return (max-min) < ZIP_INT64_MAX ? (zip_int64_t)(max-min) : ZIP_INT64_MAX; } /* _zip_check_torrentzip: - check whether ZA has a valid TORRENTZIP comment, i.e. is torrentzipped */ + check wether ZA has a valid TORRENTZIP comment, i.e. is torrentzipped */ static void -_zip_check_torrentzip(struct zip *za) +_zip_check_torrentzip(struct zip *za, const struct zip_cdir *cdir) { uLong crc_got, crc_should; char buf[8+1]; char *end; - if (za->zp == NULL || za->cdir == NULL) + if (za->zp == NULL || cdir == NULL) return; - if (za->cdir->comment_len != TORRENT_SIG_LEN+8 - || strncmp(za->cdir->comment, TORRENT_SIG, TORRENT_SIG_LEN) != 0) + if (_zip_string_length(cdir->comment) != TORRENT_SIG_LEN+8 + || strncmp((const char *)cdir->comment->raw, TORRENT_SIG, TORRENT_SIG_LEN) != 0) return; - memcpy(buf, za->cdir->comment+TORRENT_SIG_LEN, 8); + memcpy(buf, cdir->comment->raw+TORRENT_SIG_LEN, 8); buf[8] = '\0'; errno = 0; crc_should = strtoul(buf, &end, 16); if ((crc_should == UINT_MAX && errno != 0) || (end && *end)) return; - if (_zip_filerange_crc(za->zp, za->cdir->offset, za->cdir->size, - &crc_got, NULL) < 0) + if (_zip_filerange_crc(za->zp, cdir->offset, cdir->size, &crc_got, NULL) < 0) return; if (crc_got == crc_should) @@ -383,68 +398,32 @@ _zip_check_torrentzip(struct zip *za) /* _zip_headercomp: - compares two headers h1 and h2; if they are local headers, set - local1p or local2p respectively to 1, else 0. Return 0 if they - are identical, -1 if not. */ + compares a central directory entry and a local file header + Return 0 if they are consistent, -1 if not. */ static int -_zip_headercomp(struct zip_dirent *h1, int local1p, struct zip_dirent *h2, - int local2p) +_zip_headercomp(const struct zip_dirent *central, const struct zip_dirent *local) { - if ((h1->version_needed != h2->version_needed) + if ((central->version_needed != local->version_needed) #if 0 /* some zip-files have different values in local and global headers for the bitflags */ - || (h1->bitflags != h2->bitflags) + || (central->bitflags != local->bitflags) #endif - || (h1->comp_method != h2->comp_method) - || (h1->last_mod != h2->last_mod) - || (h1->filename_len != h2->filename_len) - || !h1->filename || !h2->filename - || strcmp(h1->filename, h2->filename)) + || (central->comp_method != local->comp_method) + || (central->last_mod != local->last_mod) + || !_zip_string_equal(central->filename, local->filename)) return -1; - /* check that CRC and sizes are zero if data descriptor is used */ - if ((h1->bitflags & ZIP_GPBF_DATA_DESCRIPTOR) && local1p - && (h1->crc != 0 - || h1->comp_size != 0 - || h1->uncomp_size != 0)) - return -1; - if ((h2->bitflags & ZIP_GPBF_DATA_DESCRIPTOR) && local2p - && (h2->crc != 0 - || h2->comp_size != 0 - || h2->uncomp_size != 0)) - return -1; - - /* check that CRC and sizes are equal if no data descriptor is used */ - if (((h1->bitflags & ZIP_GPBF_DATA_DESCRIPTOR) == 0 || local1p == 0) - && ((h2->bitflags & ZIP_GPBF_DATA_DESCRIPTOR) == 0 || local2p == 0)) { - if ((h1->crc != h2->crc) - || (h1->comp_size != h2->comp_size) - || (h1->uncomp_size != h2->uncomp_size)) + + if ((central->crc != local->crc) || (central->comp_size != local->comp_size) + || (central->uncomp_size != local->uncomp_size)) { + /* InfoZip stores valid values in local header even when data descriptor is used. + This is in violation of the appnote. */ + if (((local->bitflags & ZIP_GPBF_DATA_DESCRIPTOR) == 0 + || local->crc != 0 || local->comp_size != 0 || local->uncomp_size != 0)) return -1; } - - if ((local1p == local2p) - && ((h1->extrafield_len != h2->extrafield_len) - || (h1->extrafield_len && h2->extrafield - && memcmp(h1->extrafield, h2->extrafield, - h1->extrafield_len)))) - return -1; - - /* if either is local, nothing more to check */ - if (local1p || local2p) - return 0; - - if ((h1->version_madeby != h2->version_madeby) - || (h1->disk_number != h2->disk_number) - || (h1->int_attrib != h2->int_attrib) - || (h1->ext_attrib != h2->ext_attrib) - || (h1->offset != h2->offset) - || (h1->comment_len != h2->comment_len) - || (h1->comment_len && h2->comment - && memcmp(h1->comment, h2->comment, h1->comment_len))) - return -1; return 0; } @@ -452,7 +431,7 @@ _zip_headercomp(struct zip_dirent *h1, int local1p, struct zip_dirent *h2, static struct zip * -_zip_allocate_new(const char *fn, int *zep) +_zip_allocate_new(const char *fn, unsigned int flags, int *zep) { struct zip *za; struct zip_error error; @@ -467,18 +446,19 @@ _zip_allocate_new(const char *fn, int *zep) else { za->zn = strdup(fn); if (!za->zn) { - _zip_free(za); + zip_discard(za); set_error(zep, NULL, ZIP_ER_MEMORY); return NULL; } } + za->open_flags = flags; return za; } static int -_zip_file_exists(const char *fn, int flags, int *zep) +_zip_file_exists(const char *fn, unsigned int flags, int *zep) { struct stat st; @@ -488,7 +468,7 @@ _zip_file_exists(const char *fn, int flags, int *zep) } if (stat(fn, &st) != 0) { - if (flags & ZIP_CREATE || flags & ZIP_OVERWRITE) + if (flags & ZIP_CREATE) return 0; else { set_error(zep, NULL, ZIP_ER_OPEN); @@ -508,12 +488,14 @@ _zip_file_exists(const char *fn, int flags, int *zep) static struct zip_cdir * -_zip_find_central_dir(FILE *fp, int flags, int *zep, off_t len) +_zip_find_central_dir(FILE *fp, unsigned int flags, int *zep, off_t len) { struct zip_cdir *cdir, *cdirnew; unsigned char *buf, *match; off_t buf_offset; - int a, best, buflen, i; + size_t buflen; + zip_int64_t a, i; + zip_int64_t best; struct zip_error zerr; i = fseeko(fp, -(len < CDBUFSIZE ? len : CDBUFSIZE), SEEK_END); @@ -541,10 +523,10 @@ _zip_find_central_dir(FILE *fp, int flags, int *zep, off_t len) best = -1; cdir = NULL; - match = buf; + match = buf+ (buflen < CDBUFSIZE ? 0 : EOCD64LOCLEN); _zip_error_set(&zerr, ZIP_ER_NOZIP, 0); - while ((match=_zip_memmem(match, buflen-(match-buf)-18, + while ((match=_zip_memmem(match, buflen-(size_t)(match-buf)-(EOCDLEN-4), (const unsigned char *)EOCD_MAGIC, 4))!=NULL) { /* found match -- check, if good */ /* to avoid finding the same match all over again */ @@ -589,8 +571,7 @@ _zip_find_central_dir(FILE *fp, int flags, int *zep, off_t len) static unsigned char * -_zip_memmem(const unsigned char *big, int biglen, const unsigned char *little, - int littlelen) +_zip_memmem(const unsigned char *big, size_t biglen, const unsigned char *little, size_t littlelen) { const unsigned char *p; @@ -598,11 +579,159 @@ _zip_memmem(const unsigned char *big, int biglen, const unsigned char *little, return NULL; p = big-1; while ((p=(const unsigned char *) - memchr(p+1, little[0], (size_t)(big-(p+1)+biglen-littlelen+1))) - != NULL) { + memchr(p+1, little[0], (size_t)(big-(p+1))+(size_t)(biglen-littlelen)+1)) != NULL) { if (memcmp(p+1, little+1, littlelen-1)==0) return (unsigned char *)p; } return NULL; } + + + +static struct zip_cdir * +_zip_read_eocd(const unsigned char *eocd, const unsigned char *buf, off_t buf_offset, size_t buflen, + unsigned int flags, struct zip_error *error) +{ + struct zip_cdir *cd; + const unsigned char *cdp; + zip_uint64_t i, nentry, size, offset; + + if (eocd+EOCDLEN > buf+buflen) { + _zip_error_set(error, ZIP_ER_INCONS, 0); + return NULL; + } + + cdp = eocd + 8; + + /* number of cdir-entries on this disk */ + i = _zip_read2(&cdp); + /* number of cdir-entries */ + nentry = _zip_read2(&cdp); + + if (nentry != i) { + _zip_error_set(error, ZIP_ER_NOZIP, 0); + return NULL; + } + + size = _zip_read4(&cdp); + offset = _zip_read4(&cdp); + + if (size > ZIP_OFF_MAX || offset > ZIP_OFF_MAX || offset+size > ZIP_OFF_MAX) { + _zip_error_set(error, ZIP_ER_SEEK, EFBIG); + return NULL; + } + + if (offset+size > (zip_uint64_t)(buf_offset + (eocd-buf))) { + /* cdir spans past EOCD record */ + _zip_error_set(error, ZIP_ER_INCONS, 0); + return NULL; + } + + if ((flags & ZIP_CHECKCONS) && offset+size != (zip_uint64_t)(buf_offset + (eocd-buf))) { + _zip_error_set(error, ZIP_ER_INCONS, 0); + return NULL; + } + + if ((cd=_zip_cdir_new(nentry, error)) == NULL) + return NULL; + + cd->size = (off_t)size; + cd->offset = (off_t)offset; + + return cd; +} + + + +static struct zip_cdir * +_zip_read_eocd64(FILE *f, const zip_uint8_t *eocd64loc, const zip_uint8_t *buf, + off_t buf_offset, size_t buflen, unsigned int flags, struct zip_error *error) +{ + struct zip_cdir *cd; + zip_uint64_t offset; + const zip_uint8_t *cdp; + zip_uint8_t eocd[EOCD64LEN]; + zip_uint64_t eocd_offset; + zip_uint64_t size, nentry, i; + + cdp = eocd64loc+8; + eocd_offset = _zip_read8(&cdp); + + if (eocd_offset > ZIP_OFF_MAX || eocd_offset + EOCD64LEN > ZIP_OFF_MAX) { + _zip_error_set(error, ZIP_ER_SEEK, EFBIG); + return NULL; + } + + if (eocd64loc < buf || (off_t)eocd_offset+EOCD64LEN > (buf_offset+(eocd64loc-buf))) { + _zip_error_set(error, ZIP_ER_INCONS, 0); + return NULL; + } + + if ((off_t)eocd_offset >= buf_offset && (off_t)eocd_offset+EOCD64LEN <= buf_offset+(ssize_t)buflen) + cdp = buf+((off_t)eocd_offset-buf_offset); + else { + if (fseeko(f, (off_t)eocd_offset, SEEK_SET) != 0) { + _zip_error_set(error, ZIP_ER_SEEK, errno); + return NULL; + } + + clearerr(f); + if (fread(eocd, 1, EOCD64LEN, f) < EOCD64LEN) { + _zip_error_set(error, ZIP_ER_READ, errno); + return NULL; + } + + if (ferror(f)) { + _zip_error_set(error, ZIP_ER_READ, errno); + return NULL; + } + + cdp = eocd; + } + + if (memcmp(cdp, EOCD64_MAGIC, 4) != 0) { + _zip_error_set(error, ZIP_ER_INCONS, 0); + return NULL; + } + cdp += 4; + + size = _zip_read8(&cdp); + + if ((flags & ZIP_CHECKCONS) && size+eocd_offset+12 != (zip_uint64_t)(buf_offset+(eocd64loc-buf))) { + _zip_error_set(error, ZIP_ER_INCONS, 0); + return NULL; + } + + cdp += 4; /* skip version made by/needed */ + cdp += 8; /* skip num disks */ + + nentry = _zip_read8(&cdp); + i = _zip_read8(&cdp); + + if (nentry != i) { + _zip_error_set(error, ZIP_ER_MULTIDISK, 0); + return NULL; + } + + size = _zip_read8(&cdp); + offset = _zip_read8(&cdp); + + if (size > ZIP_OFF_MAX || offset > ZIP_OFF_MAX || offset+size > ZIP_OFF_MAX) { + _zip_error_set(error, ZIP_ER_SEEK, EFBIG); + return NULL; + } + if ((flags & ZIP_CHECKCONS) && offset+size != eocd_offset) { + _zip_error_set(error, ZIP_ER_INCONS, 0); + return NULL; + } + + if ((cd=_zip_cdir_new(nentry, error)) == NULL) + return NULL; + + + cd->size = (off_t)size; + cd->offset = (off_t)offset; + + return cd; +} diff --git a/ext/zip/lib/zip_rename.c b/ext/zip/lib/zip_rename.c index 6b5a035917..8841caeca9 100644 --- a/ext/zip/lib/zip_rename.c +++ b/ext/zip/lib/zip_rename.c @@ -1,6 +1,6 @@ /* zip_rename.c -- rename file in zip archive - Copyright (C) 1999-2009 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2012 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -35,36 +35,13 @@ #include <string.h> +#define _ZIP_COMPILING_DEPRECATED #include "zipint.h" -ZIP_EXTERN(int) +ZIP_EXTERN int zip_rename(struct zip *za, zip_uint64_t idx, const char *name) { - const char *old_name; - int old_is_dir, new_is_dir; - - if (idx >= za->nentry || name[0] == '\0') { - _zip_error_set(&za->error, ZIP_ER_INVAL, 0); - return -1; - } - - if (ZIP_IS_RDONLY(za)) { - _zip_error_set(&za->error, ZIP_ER_RDONLY, 0); - return -1; - } - - if ((old_name=zip_get_name(za, idx, 0)) == NULL) - return -1; - - new_is_dir = (name[strlen(name)-1] == '/'); - old_is_dir = (old_name[strlen(old_name)-1] == '/'); - - if (new_is_dir != old_is_dir) { - _zip_error_set(&za->error, ZIP_ER_INVAL, 0); - return -1; - } - - return _zip_set_name(za, idx, name); + return zip_file_rename(za, idx, name, 0); } diff --git a/ext/zip/lib/zip_replace.c b/ext/zip/lib/zip_replace.c index 6dc3dd5ab5..de717afec7 100644 --- a/ext/zip/lib/zip_replace.c +++ b/ext/zip/lib/zip_replace.c @@ -1,6 +1,6 @@ /* zip_replace.c -- replace file via callback function - Copyright (C) 1999-2009 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2012 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -33,53 +33,13 @@ +#define _ZIP_COMPILING_DEPRECATED #include "zipint.h" -ZIP_EXTERN(int) +ZIP_EXTERN int zip_replace(struct zip *za, zip_uint64_t idx, struct zip_source *source) { - if (idx >= za->nentry || source == NULL) { - _zip_error_set(&za->error, ZIP_ER_INVAL, 0); - return -1; - } - - if (_zip_replace(za, idx, NULL, source) == -1) - return -1; - - return 0; -} - - - - -/* NOTE: Signed due to -1 on error. See zip_add.c for more details. */ - -zip_int64_t -_zip_replace(struct zip *za, zip_uint64_t idx, const char *name, - struct zip_source *source) -{ - if (ZIP_IS_RDONLY(za)) { - _zip_error_set(&za->error, ZIP_ER_RDONLY, 0); - return -1; - } - - if (idx == ZIP_UINT64_MAX) { - if (_zip_entry_new(za) == NULL) - return -1; - - idx = za->nentry - 1; - } - - _zip_unchange_data(za->entry+idx); - - if (name && _zip_set_name(za, idx, name) != 0) - return -1; - - za->entry[idx].state = ((za->cdir == NULL || idx >= za->cdir->nentry) - ? ZIP_ST_ADDED : ZIP_ST_REPLACED); - za->entry[idx].source = source; - - return idx; + return zip_file_replace(za, idx, source, 0); } diff --git a/ext/zip/lib/zip_set_archive_comment.c b/ext/zip/lib/zip_set_archive_comment.c index 3cd069c757..df1caee06b 100644 --- a/ext/zip/lib/zip_set_archive_comment.c +++ b/ext/zip/lib/zip_set_archive_comment.c @@ -1,6 +1,6 @@ /* zip_set_archive_comment.c -- set archive comment - Copyright (C) 2006-2009 Dieter Baron and Thomas Klausner + Copyright (C) 2006-2013 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -39,32 +39,46 @@ -ZIP_EXTERN(int) -zip_set_archive_comment(struct zip *za, const char *comment, int len) +ZIP_EXTERN int +zip_set_archive_comment(struct zip *za, const char *comment, zip_uint16_t len) { - char *tmpcom; + struct zip_string *cstr; - if (len < 0 || len > MAXCOMLEN - || (len > 0 && comment == NULL)) { - _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + if (ZIP_IS_RDONLY(za)) { + _zip_error_set(&za->error, ZIP_ER_RDONLY, 0); return -1; } - if (ZIP_IS_RDONLY(za)) { - _zip_error_set(&za->error, ZIP_ER_RDONLY, 0); + if (len > 0 && comment == NULL) { + _zip_error_set(&za->error, ZIP_ER_INVAL, 0); return -1; } if (len > 0) { - if ((tmpcom=(char *)_zip_memdup(comment, len, &za->error)) == NULL) + if ((cstr=_zip_string_new((const zip_uint8_t *)comment, len, ZIP_FL_ENC_GUESS, &za->error)) == NULL) return -1; + + if (_zip_guess_encoding(cstr, ZIP_ENCODING_UNKNOWN) == ZIP_ENCODING_CP437) { + _zip_string_free(cstr); + _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } } else - tmpcom = NULL; + cstr = NULL; + + _zip_string_free(za->comment_changes); + za->comment_changes = NULL; - free(za->ch_comment); - za->ch_comment = tmpcom; - za->ch_comment_len = len; + if (((za->comment_orig && _zip_string_equal(za->comment_orig, cstr)) + || (za->comment_orig == NULL && cstr == NULL))) { + _zip_string_free(cstr); + za->comment_changed = 0; + } + else { + za->comment_changes = cstr; + za->comment_changed = 1; + } return 0; } diff --git a/ext/zip/lib/zip_set_archive_flag.c b/ext/zip/lib/zip_set_archive_flag.c index 07bcfbe304..b6cdab120d 100644 --- a/ext/zip/lib/zip_set_archive_flag.c +++ b/ext/zip/lib/zip_set_archive_flag.c @@ -37,8 +37,8 @@ -ZIP_EXTERN(int) -zip_set_archive_flag(struct zip *za, int flag, int value) +ZIP_EXTERN int +zip_set_archive_flag(struct zip *za, unsigned int flag, int value) { unsigned int new_flags; diff --git a/ext/zip/lib/zip_set_default_password.c b/ext/zip/lib/zip_set_default_password.c index c274d1100b..b9aa80acff 100644 --- a/ext/zip/lib/zip_set_default_password.c +++ b/ext/zip/lib/zip_set_default_password.c @@ -40,7 +40,7 @@ -ZIP_EXTERN(int) +ZIP_EXTERN int zip_set_default_password(struct zip *za, const char *passwd) { if (za == NULL) diff --git a/ext/zip/lib/zip_set_file_comment.c b/ext/zip/lib/zip_set_file_comment.c index 5e63dc2730..7acd0eb36d 100644 --- a/ext/zip/lib/zip_set_file_comment.c +++ b/ext/zip/lib/zip_set_file_comment.c @@ -1,6 +1,6 @@ /* zip_set_file_comment.c -- set comment for file in archive - Copyright (C) 2006-2009 Dieter Baron and Thomas Klausner + Copyright (C) 2006-2012 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -35,38 +35,17 @@ #include <stdlib.h> +#define _ZIP_COMPILING_DEPRECATED #include "zipint.h" -ZIP_EXTERN(int) -zip_set_file_comment(struct zip *za, zip_uint64_t idx, - const char *comment, int len) +ZIP_EXTERN int +zip_set_file_comment(struct zip *za, zip_uint64_t idx, const char *comment, int len) { - char *tmpcom; - - if (idx >= za->nentry - || len < 0 || len > MAXCOMLEN - || (len > 0 && comment == NULL)) { - _zip_error_set(&za->error, ZIP_ER_INVAL, 0); - return -1; - } - - if (ZIP_IS_RDONLY(za)) { - _zip_error_set(&za->error, ZIP_ER_RDONLY, 0); - return -1; + if (len < 0 || len > ZIP_UINT16_MAX) { + _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; } - - if (len > 0) { - if ((tmpcom=(char *)_zip_memdup(comment, len, &za->error)) == NULL) - return -1; - } - else - tmpcom = NULL; - - free(za->entry[idx].ch_comment); - za->entry[idx].ch_comment = tmpcom; - za->entry[idx].ch_comment_len = len; - - return 0; + return zip_file_set_comment(za, idx, comment, (zip_uint16_t)len, 0); } diff --git a/ext/zip/lib/zip_set_file_compression.c b/ext/zip/lib/zip_set_file_compression.c new file mode 100644 index 0000000000..ea8517d70e --- /dev/null +++ b/ext/zip/lib/zip_set_file_compression.c @@ -0,0 +1,90 @@ +/* + zip_set_file_compression.c -- set compression for file in archive + Copyright (C) 2012 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR 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. +*/ + + + +#include "zipint.h" + + + +ZIP_EXTERN int +zip_set_file_compression(struct zip *za, zip_uint64_t idx, + zip_int32_t method, zip_uint32_t flags) +{ + struct zip_entry *e; + zip_int32_t old_method; + + if (idx >= za->nentry) { + _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + if (ZIP_IS_RDONLY(za)) { + _zip_error_set(&za->error, ZIP_ER_RDONLY, 0); + return -1; + } + + if (method != ZIP_CM_DEFAULT && method != ZIP_CM_STORE && method != ZIP_CM_DEFLATE) { + _zip_error_set(&za->error, ZIP_ER_COMPNOTSUPP, 0); + return -1; + } + + e = za->entry+idx; + + old_method = (e->orig == NULL ? ZIP_CM_DEFAULT : e->orig->comp_method); + + /* XXX: revisit this when flags are supported, since they may require a recompression */ + + if (method == old_method) { + if (e->changes) { + e->changes->changed &= ~ZIP_DIRENT_COMP_METHOD; + if (e->changes->changed == 0) { + _zip_dirent_free(e->changes); + e->changes = NULL; + } + } + } + else { + if (e->changes == NULL) { + if ((e->changes=_zip_dirent_clone(e->orig)) == NULL) { + _zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return -1; + } + } + + e->changes->comp_method = method; + e->changes->changed |= ZIP_DIRENT_COMP_METHOD; + } + + return 0; +} diff --git a/ext/zip/lib/zip_set_name.c b/ext/zip/lib/zip_set_name.c index 2a90601bfe..60c9e7d5bf 100644 --- a/ext/zip/lib/zip_set_name.c +++ b/ext/zip/lib/zip_set_name.c @@ -1,6 +1,6 @@ /* zip_set_name.c -- rename helper function - Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2012 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -41,35 +41,77 @@ int -_zip_set_name(struct zip *za, zip_uint64_t idx, const char *name) +_zip_set_name(struct zip *za, zip_uint64_t idx, const char *name, zip_flags_t flags) { - char *s; + struct zip_entry *e; + struct zip_string *str; + int changed; zip_int64_t i; - - if (idx >= za->nentry || name == NULL) { + + if (idx >= za->nentry) { _zip_error_set(&za->error, ZIP_ER_INVAL, 0); return -1; } - if ((i=_zip_name_locate(za, name, 0, NULL)) != -1 && i != idx) { + if (ZIP_IS_RDONLY(za)) { + _zip_error_set(&za->error, ZIP_ER_RDONLY, 0); + return -1; + } + + if (name && strlen(name) > 0) { + /* XXX: check for string too long */ + if ((str=_zip_string_new((const zip_uint8_t *)name, (zip_uint16_t)strlen(name), flags, &za->error)) == NULL) + return -1; + if ((flags & ZIP_FL_ENCODING_ALL) == ZIP_FL_ENC_GUESS && _zip_guess_encoding(str, ZIP_ENCODING_UNKNOWN) == ZIP_ENCODING_UTF8_GUESSED) + str->encoding = ZIP_ENCODING_UTF8_KNOWN; + } + else + str = NULL; + + /* XXX: encoding flags needed for CP437? */ + if ((i=_zip_name_locate(za, name, 0, NULL)) >= 0 && (zip_uint64_t)i != idx) { + _zip_string_free(str); _zip_error_set(&za->error, ZIP_ER_EXISTS, 0); return -1; } /* no effective name change */ - if (i == idx) + if (i>=0 && (zip_uint64_t)i == idx) { + _zip_string_free(str); return 0; - - if ((s=strdup(name)) == NULL) { - _zip_error_set(&za->error, ZIP_ER_MEMORY, 0); - return -1; } - - if (za->entry[idx].state == ZIP_ST_UNCHANGED) - za->entry[idx].state = ZIP_ST_RENAMED; - free(za->entry[idx].ch_filename); - za->entry[idx].ch_filename = s; + e = za->entry+idx; + + if (e->changes) { + _zip_string_free(e->changes->filename); + e->changes->filename = NULL; + e->changes->changed &= ~ZIP_DIRENT_FILENAME; + } + + if (e->orig) + changed = !_zip_string_equal(e->orig->filename, str); + else + changed = 1; + + if (changed) { + if (e->changes == NULL) { + if ((e->changes=_zip_dirent_clone(e->orig)) == NULL) { + _zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + _zip_string_free(str); + return -1; + } + } + e->changes->filename = str; + e->changes->changed |= ZIP_DIRENT_FILENAME; + } + else { + _zip_string_free(str); + if (e->changes && e->changes->changed == 0) { + _zip_dirent_free(e->changes); + e->changes = NULL; + } + } return 0; } diff --git a/ext/zip/lib/zip_source_buffer.c b/ext/zip/lib/zip_source_buffer.c index 8c9154ce3c..8a13e7602d 100644 --- a/ext/zip/lib/zip_source_buffer.c +++ b/ext/zip/lib/zip_source_buffer.c @@ -48,7 +48,7 @@ static zip_int64_t read_data(void *, void *, zip_uint64_t, enum zip_source_cmd); -ZIP_EXTERN(struct zip_source *) +ZIP_EXTERN struct zip_source * zip_source_buffer(struct zip *za, const void *data, zip_uint64_t len, int freep) { struct read_data *f; @@ -98,9 +98,7 @@ read_data(void *state, void *data, zip_uint64_t len, enum zip_source_cmd cmd) return 0; case ZIP_SOURCE_READ: - /* XXX: return error if (len > ZIP_INT64_MAX) */ - - n = z->end - z->buf; + n = (zip_uint64_t)(z->end - z->buf); if (n > len) n = len; @@ -109,7 +107,7 @@ read_data(void *state, void *data, zip_uint64_t len, enum zip_source_cmd cmd) z->buf += n; } - return n; + return (zip_int64_t)n; case ZIP_SOURCE_CLOSE: return 0; @@ -125,7 +123,7 @@ read_data(void *state, void *data, zip_uint64_t len, enum zip_source_cmd cmd) zip_stat_init(st); st->mtime = z->mtime; - st->size = z->end - z->data; + st->size = (zip_uint64_t)(z->end - z->data); st->comp_size = st->size; st->comp_method = ZIP_CM_STORE; st->encryption_method = ZIP_EM_NONE; diff --git a/ext/zip/lib/zip_source_close.c b/ext/zip/lib/zip_source_close.c index a3bf7e5e1d..7b89d5fc15 100644 --- a/ext/zip/lib/zip_source_close.c +++ b/ext/zip/lib/zip_source_close.c @@ -37,7 +37,7 @@ -ZIP_EXTERN(void) +void zip_source_close(struct zip_source *src) { if (!src->is_open) diff --git a/ext/zip/lib/zip_source_crc.c b/ext/zip/lib/zip_source_crc.c index 7fd78f5697..99bc965228 100644 --- a/ext/zip/lib/zip_source_crc.c +++ b/ext/zip/lib/zip_source_crc.c @@ -38,7 +38,7 @@ #include "zipint.h" -struct crc { +struct crc_context { int eof; int validate; int e[2]; @@ -51,23 +51,27 @@ static zip_int64_t crc_read(struct zip_source *, void *, void * -ZIP_EXTERN(struct zip_source *) +struct zip_source * zip_source_crc(struct zip *za, struct zip_source *src, int validate) { - struct crc *ctx; + struct crc_context *ctx; if (src == NULL) { _zip_error_set(&za->error, ZIP_ER_INVAL, 0); return NULL; } - if ((ctx=(struct crc *)malloc(sizeof(*ctx))) == NULL) { + if ((ctx=(struct crc_context *)malloc(sizeof(*ctx))) == NULL) { _zip_error_set(&za->error, ZIP_ER_MEMORY, 0); return NULL; } + ctx->eof = 0; ctx->validate = validate; - + ctx->e[0] = ctx->e[1] = 0; + ctx->size = 0; + ctx->crc = 0; + return zip_source_layered(za, src, crc_read, ctx); } @@ -77,15 +81,15 @@ static zip_int64_t crc_read(struct zip_source *src, void *_ctx, void *data, zip_uint64_t len, enum zip_source_cmd cmd) { - struct crc *ctx; + struct crc_context *ctx; zip_int64_t n; - ctx = (struct crc *)_ctx; + ctx = (struct crc_context *)_ctx; switch (cmd) { case ZIP_SOURCE_OPEN: ctx->eof = 0; - ctx->crc = crc32(0, NULL, 0); + ctx->crc = (zip_uint32_t)crc32(0, NULL, 0); ctx->size = 0; return 0; @@ -120,8 +124,8 @@ crc_read(struct zip_source *src, void *_ctx, void *data, } } else { - ctx->size += n; - ctx->crc = crc32(ctx->crc, data, n); + ctx->size += (zip_uint64_t)n; + ctx->crc = (zip_uint32_t)crc32(ctx->crc, (const Bytef *)data, (uInt)n); /* XXX: check for overflow, use multiple crc calls if needed */ } return n; @@ -139,7 +143,10 @@ crc_read(struct zip_source *src, void *_ctx, void *data, After all, this only works for uncompressed data. */ st->size = ctx->size; st->crc = ctx->crc; - st->valid |= ZIP_STAT_SIZE|ZIP_STAT_CRC; + st->comp_size = ctx->size; + st->comp_method = ZIP_CM_STORE; + st->encryption_method = ZIP_EM_NONE; + st->valid |= ZIP_STAT_SIZE|ZIP_STAT_CRC|ZIP_STAT_COMP_SIZE|ZIP_STAT_COMP_METHOD|ZIP_STAT_ENCRYPTION_METHOD;; } } return 0; diff --git a/ext/zip/lib/zip_source_deflate.c b/ext/zip/lib/zip_source_deflate.c index 5d9c5e67bb..879953144c 100644 --- a/ext/zip/lib/zip_source_deflate.c +++ b/ext/zip/lib/zip_source_deflate.c @@ -60,14 +60,14 @@ static void deflate_free(struct deflate *); -ZIP_EXTERN(struct zip_source *) +struct zip_source * zip_source_deflate(struct zip *za, struct zip_source *src, - zip_uint16_t cm, int flags) + zip_int32_t cm, int flags) { struct deflate *ctx; struct zip_source *s2; - if (src == NULL || cm != ZIP_CM_DEFLATE) { + if (src == NULL || (cm != ZIP_CM_DEFLATE && !ZIP_CM_IS_DEFAULT(cm))) { _zip_error_set(&za->error, ZIP_ER_INVAL, 0); return NULL; } @@ -113,7 +113,7 @@ compress_read(struct zip_source *src, struct deflate *ctx, return 0; ctx->zstr.next_out = (Bytef *)data; - ctx->zstr.avail_out = len; + ctx->zstr.avail_out = (uInt)len; /* XXX: check for overflow */ end = 0; while (!end) { @@ -136,8 +136,7 @@ compress_read(struct zip_source *src, struct deflate *ctx, break; } - if ((n=zip_source_read(src, ctx->buffer, - sizeof(ctx->buffer))) < 0) { + if ((n=zip_source_read(src, ctx->buffer, sizeof(ctx->buffer))) < 0) { zip_source_error(src, ctx->e, ctx->e+1); end = 1; break; @@ -149,7 +148,7 @@ compress_read(struct zip_source *src, struct deflate *ctx, } else { ctx->zstr.next_in = (Bytef *)ctx->buffer; - ctx->zstr.avail_in = n; + ctx->zstr.avail_in = (uInt)n; } continue; } @@ -167,7 +166,7 @@ compress_read(struct zip_source *src, struct deflate *ctx, } if (ctx->zstr.avail_out < len) - return len - ctx->zstr.avail_out; + return (zip_int64_t)(len - ctx->zstr.avail_out); return (ctx->e[0] == 0) ? 0 : -1; } @@ -188,7 +187,7 @@ decompress_read(struct zip_source *src, struct deflate *ctx, return 0; ctx->zstr.next_out = (Bytef *)data; - ctx->zstr.avail_out = len; + ctx->zstr.avail_out = (uInt)len; /* XXX: check for overflow */ end = 0; while (!end && ctx->zstr.avail_out) { @@ -210,8 +209,7 @@ decompress_read(struct zip_source *src, struct deflate *ctx, break; } - if ((n=zip_source_read(src, ctx->buffer, - sizeof(ctx->buffer))) < 0) { + if ((n=zip_source_read(src, ctx->buffer, sizeof(ctx->buffer))) < 0) { zip_source_error(src, ctx->e, ctx->e+1); end = 1; break; @@ -220,7 +218,7 @@ decompress_read(struct zip_source *src, struct deflate *ctx, ctx->eof = 1; else { ctx->zstr.next_in = (Bytef *)ctx->buffer; - ctx->zstr.avail_in = n; + ctx->zstr.avail_in = (uInt)n; } continue; } @@ -237,7 +235,7 @@ decompress_read(struct zip_source *src, struct deflate *ctx, } if (ctx->zstr.avail_out < len) - return len - ctx->zstr.avail_out; + return (zip_int64_t)(len - ctx->zstr.avail_out); return (ctx->e[0] == 0) ? 0 : -1; } @@ -334,7 +332,7 @@ deflate_decompress(struct zip_source *src, void *ud, void *data, ctx->zstr.zfree = Z_NULL; ctx->zstr.opaque = NULL; ctx->zstr.next_in = (Bytef *)ctx->buffer; - ctx->zstr.avail_in = n; + ctx->zstr.avail_in = (uInt)n /* XXX: check for overflow */; /* negative value to tell zlib that there is no header */ if ((ret=inflateInit2(&ctx->zstr, -MAX_WBITS)) != Z_OK) { diff --git a/ext/zip/lib/zip_source_error.c b/ext/zip/lib/zip_source_error.c index 70ec8bc5d4..a1efd551ea 100644 --- a/ext/zip/lib/zip_source_error.c +++ b/ext/zip/lib/zip_source_error.c @@ -1,6 +1,6 @@ /* zip_source_error.c -- get last error from zip_source - Copyright (C) 2009 Dieter Baron and Thomas Klausner + Copyright (C) 2009-2013 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -37,24 +37,21 @@ -ZIP_EXTERN(void) +void zip_source_error(struct zip_source *src, int *ze, int *se) { - int e[2] = { 0, 0 }; + int e[2]; if (src->src == NULL) { + if (src->cb.f(src->ud, e, sizeof(e), ZIP_SOURCE_ERROR) < 0) { + e[0] = ZIP_ER_INTERNAL; + e[1] = 0; + } } else { switch (src->error_source) { case ZIP_LES_NONE: - if (src->src == NULL) { - if (src->cb.f(src->ud, e, sizeof(e), ZIP_SOURCE_ERROR) < 0) { - e[0] = ZIP_ER_INTERNAL; - e[1] = 0; - } - } - else - e[0] = e[1] = 0; + e[0] = e[1] = 0; break; case ZIP_LES_INVAL: @@ -67,8 +64,7 @@ zip_source_error(struct zip_source *src, int *ze, int *se) return; case ZIP_LES_UPPER: - if (src->cb.l(src->src, src->ud, e, sizeof(e), - ZIP_SOURCE_ERROR) < 0) { + if (src->cb.l(src->src, src->ud, e, sizeof(e), ZIP_SOURCE_ERROR) < 0) { e[0] = ZIP_ER_INTERNAL; e[1] = 0; } @@ -77,6 +73,7 @@ zip_source_error(struct zip_source *src, int *ze, int *se) default: e[0] = ZIP_ER_INTERNAL; e[1] = 0; + break; } } diff --git a/ext/zip/lib/zip_source_file.c b/ext/zip/lib/zip_source_file.c index 681cc2f3ea..79c8ee5aca 100644 --- a/ext/zip/lib/zip_source_file.c +++ b/ext/zip/lib/zip_source_file.c @@ -40,7 +40,7 @@ -ZIP_EXTERN(struct zip_source *) +ZIP_EXTERN struct zip_source * zip_source_file(struct zip *za, const char *fname, zip_uint64_t start, zip_int64_t len) { diff --git a/ext/zip/lib/zip_source_filep.c b/ext/zip/lib/zip_source_filep.c index 4d896a4c01..0bd2d6846e 100644 --- a/ext/zip/lib/zip_source_filep.c +++ b/ext/zip/lib/zip_source_filep.c @@ -58,14 +58,14 @@ static zip_int64_t read_file(void *state, void *data, zip_uint64_t len, -ZIP_EXTERN(struct zip_source *) +ZIP_EXTERN struct zip_source * zip_source_filep(struct zip *za, FILE *file, zip_uint64_t start, zip_int64_t len) { if (za == NULL) return NULL; - if (file == NULL || start < 0 || len < -1) { + if (file == NULL || len < -1) { _zip_error_set(&za->error, ZIP_ER_INVAL, 0); return NULL; } @@ -125,7 +125,7 @@ read_file(void *state, void *data, zip_uint64_t len, enum zip_source_cmd cmd) { struct read_file *z; char *buf; - int i, n; + size_t i, n; z = (struct read_file *)state; buf = (char *)data; @@ -140,7 +140,7 @@ read_file(void *state, void *data, zip_uint64_t len, enum zip_source_cmd cmd) } } - if (z->closep) { + if (z->closep && z->off > 0) { if (fseeko(z->f, (off_t)z->off, SEEK_SET) < 0) { z->e[0] = ZIP_ER_SEEK; z->e[1] = errno; @@ -153,30 +153,31 @@ read_file(void *state, void *data, zip_uint64_t len, enum zip_source_cmd cmd) case ZIP_SOURCE_READ: /* XXX: return INVAL if len > size_t max */ if (z->remain != -1) - n = len > z->remain ? z->remain : len; + n = len > (zip_uint64_t)z->remain ? (zip_uint64_t)z->remain : len; else n = len; if (!z->closep) { /* we might share this file with others, so let's be safe */ - if (fseeko(z->f, (off_t)(z->off + z->len-z->remain), - SEEK_SET) < 0) { + if (fseeko(z->f, (off_t)(z->off + (zip_uint64_t)(z->len-z->remain)), SEEK_SET) < 0) { z->e[0] = ZIP_ER_SEEK; z->e[1] = errno; return -1; } } - if ((i=fread(buf, 1, n, z->f)) < 0) { - z->e[0] = ZIP_ER_READ; - z->e[1] = errno; - return -1; + if ((i=fread(buf, 1, n, z->f)) == 0) { + if (ferror(z->f)) { + z->e[0] = ZIP_ER_READ; + z->e[1] = errno; + return -1; + } } if (z->remain != -1) z->remain -= i; - return i; + return (zip_int64_t)i; case ZIP_SOURCE_CLOSE: if (z->fname) { @@ -214,11 +215,11 @@ read_file(void *state, void *data, zip_uint64_t len, enum zip_source_cmd cmd) st->mtime = fst.st_mtime; st->valid |= ZIP_STAT_MTIME; if (z->len != -1) { - st->size = z->len; + st->size = (zip_uint64_t)z->len; st->valid |= ZIP_STAT_SIZE; } else if ((fst.st_mode&S_IFMT) == S_IFREG) { - st->size = fst.st_size; + st->size = (zip_uint64_t)fst.st_size; st->valid |= ZIP_STAT_SIZE; } } diff --git a/ext/zip/lib/zip_source_free.c b/ext/zip/lib/zip_source_free.c index f71c71ed6c..b1e7840496 100644 --- a/ext/zip/lib/zip_source_free.c +++ b/ext/zip/lib/zip_source_free.c @@ -39,7 +39,7 @@ -ZIP_EXTERN(void) +ZIP_EXTERN void zip_source_free(struct zip_source *src) { if (src == NULL) diff --git a/ext/zip/lib/zip_source_function.c b/ext/zip/lib/zip_source_function.c index 984b107f7b..cb92e339b4 100644 --- a/ext/zip/lib/zip_source_function.c +++ b/ext/zip/lib/zip_source_function.c @@ -39,7 +39,7 @@ -ZIP_EXTERN(struct zip_source *) +ZIP_EXTERN struct zip_source * zip_source_function(struct zip *za, zip_source_callback zcb, void *ud) { struct zip_source *zs; diff --git a/ext/zip/lib/zip_source_layered.c b/ext/zip/lib/zip_source_layered.c index 86ed420407..ad2870333c 100644 --- a/ext/zip/lib/zip_source_layered.c +++ b/ext/zip/lib/zip_source_layered.c @@ -39,7 +39,7 @@ -ZIP_EXTERN(struct zip_source *) +struct zip_source * zip_source_layered(struct zip *za, struct zip_source *src, zip_source_layered_callback cb, void *ud) { diff --git a/ext/zip/lib/zip_source_open.c b/ext/zip/lib/zip_source_open.c index 2c768f7f3a..a5010393e7 100644 --- a/ext/zip/lib/zip_source_open.c +++ b/ext/zip/lib/zip_source_open.c @@ -1,6 +1,6 @@ /* zip_source_open.c -- open zip_source (prepare for reading) - Copyright (C) 2009 Dieter Baron and Thomas Klausner + Copyright (C) 2009-2013 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -37,7 +37,7 @@ -ZIP_EXTERN(int) +int zip_source_open(struct zip_source *src) { zip_int64_t ret; @@ -60,7 +60,7 @@ zip_source_open(struct zip_source *src) ret = src->cb.l(src->src, src->ud, NULL, 0, ZIP_SOURCE_OPEN); if (ret < 0) { - (void)zip_source_close(src->src); + zip_source_close(src->src); if (ret == ZIP_SOURCE_ERR_LOWER) src->error_source = ZIP_LES_LOWER; diff --git a/ext/zip/lib/zip_source_pkware.c b/ext/zip/lib/zip_source_pkware.c index 83b5cc5ad5..ec53dfeef0 100644 --- a/ext/zip/lib/zip_source_pkware.c +++ b/ext/zip/lib/zip_source_pkware.c @@ -49,10 +49,6 @@ struct trad_pkware { #define KEY1 591751049 #define KEY2 878082192 -static const uLongf *crc = NULL; - -#define CRC32(c, b) (crc[((c) ^ (b)) & 0xff] ^ ((c) >> 8)) - static void decrypt(struct trad_pkware *, zip_uint8_t *, @@ -64,7 +60,7 @@ static void pkware_free(struct trad_pkware *); -ZIP_EXTERN(struct zip_source *) +struct zip_source * zip_source_pkware(struct zip *za, struct zip_source *src, zip_uint16_t em, int flags, const char *password) { @@ -80,9 +76,6 @@ zip_source_pkware(struct zip *za, struct zip_source *src, return NULL; } - if (crc == NULL) - crc = get_crc_table(); - if ((ctx=(struct trad_pkware *)malloc(sizeof(*ctx))) == NULL) { _zip_error_set(&za->error, ZIP_ER_MEMORY, 0); return NULL; @@ -118,7 +111,7 @@ decrypt(struct trad_pkware *ctx, zip_uint8_t *out, const zip_uint8_t *in, if (!update_only) { /* decrypt next byte */ - tmp = ctx->key[2] | 2; + tmp = (zip_uint16_t)(ctx->key[2] | 2); tmp = (tmp * (tmp ^ 1)) >> 8; b ^= tmp; } @@ -128,10 +121,10 @@ decrypt(struct trad_pkware *ctx, zip_uint8_t *out, const zip_uint8_t *in, out[i] = b; /* update keys */ - ctx->key[0] = CRC32(ctx->key[0], b); + ctx->key[0] = (zip_uint32_t)crc32(ctx->key[0] ^ 0xffffffffUL, &b, 1) ^ 0xffffffffUL; ctx->key[1] = (ctx->key[1] + (ctx->key[0] & 0xff)) * 134775813 + 1; b = ctx->key[1] >> 24; - ctx->key[2] = CRC32(ctx->key[2], b); + ctx->key[2] = (zip_uint32_t)crc32(ctx->key[2] ^ 0xffffffffUL, &b, 1) ^ 0xffffffffUL; } } @@ -196,7 +189,7 @@ pkware_decrypt(struct zip_source *src, void *ud, void *data, if ((n=zip_source_read(src, data, len)) < 0) return ZIP_SOURCE_ERR_LOWER; - decrypt(ud, (zip_uint8_t *)data, (zip_uint8_t *)data, (zip_uint64_t)n, + decrypt((struct trad_pkware *)ud, (zip_uint8_t *)data, (zip_uint8_t *)data, (zip_uint64_t)n, 0); return n; diff --git a/ext/zip/lib/zip_source_pop.c b/ext/zip/lib/zip_source_pop.c index 406093869b..cd9cb529b5 100644 --- a/ext/zip/lib/zip_source_pop.c +++ b/ext/zip/lib/zip_source_pop.c @@ -39,7 +39,7 @@ -ZIP_EXTERN(struct zip_source *) +struct zip_source * zip_source_pop(struct zip_source *src) { struct zip_source *lower; diff --git a/ext/zip/lib/zip_source_read.c b/ext/zip/lib/zip_source_read.c index 7246f9ccb5..81b90ba42d 100644 --- a/ext/zip/lib/zip_source_read.c +++ b/ext/zip/lib/zip_source_read.c @@ -37,7 +37,7 @@ -ZIP_EXTERN(zip_int64_t) +zip_int64_t zip_source_read(struct zip_source *src, void *data, zip_uint64_t len) { zip_int64_t ret; diff --git a/ext/zip/lib/zip_source_stat.c b/ext/zip/lib/zip_source_stat.c index 662779eb6c..85ae6a2fd6 100644 --- a/ext/zip/lib/zip_source_stat.c +++ b/ext/zip/lib/zip_source_stat.c @@ -37,7 +37,7 @@ -ZIP_EXTERN(int) +int zip_source_stat(struct zip_source *src, struct zip_stat *st) { zip_int64_t ret; diff --git a/ext/zip/lib/zip_source_window.c b/ext/zip/lib/zip_source_window.c new file mode 100644 index 0000000000..fd202099b5 --- /dev/null +++ b/ext/zip/lib/zip_source_window.c @@ -0,0 +1,150 @@ +/* + zip_source_window.c -- return part of lower source + Copyright (C) 2012-2013 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR 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. +*/ + + + +#include <stdlib.h> +#include <string.h> + +#include "zipint.h" + +struct window { + zip_uint64_t skip; + zip_uint64_t len; + zip_uint64_t left; + int e[2]; +}; + +static zip_int64_t window_read(struct zip_source *, void *, void *, + zip_uint64_t, enum zip_source_cmd); + + + +struct zip_source * +zip_source_window(struct zip *za, struct zip_source *src, zip_uint64_t start, zip_uint64_t len) +{ + struct window *ctx; + + if (src == NULL) { + _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return NULL; + } + + if ((ctx=(struct window *)malloc(sizeof(*ctx))) == NULL) { + _zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return NULL; + } + + ctx->skip = start; + ctx->len = len; + ctx->left = len; + + return zip_source_layered(za, src, window_read, ctx); +} + + + +static zip_int64_t +window_read(struct zip_source *src, void *_ctx, void *data, + zip_uint64_t len, enum zip_source_cmd cmd) +{ + struct window *ctx; + zip_int64_t ret; + zip_uint64_t n, i; + char b[8192]; + + ctx = (struct window *)_ctx; + + switch (cmd) { + case ZIP_SOURCE_OPEN: + for (n=0; n<ctx->skip; n+=(zip_uint64_t)ret) { + i = (ctx->skip-n > sizeof(b) ? sizeof(b) : ctx->skip-n); + if ((ret=zip_source_read(src, b, i)) < 0) + return ZIP_SOURCE_ERR_LOWER; + if (ret==0) { + ctx->e[0] = ZIP_ER_EOF; + ctx->e[1] = 0; + return -1; + } + } + return 0; + + case ZIP_SOURCE_READ: + if (len > ctx->left) + len = ctx->left; + + if (len == 0) + return 0; + + if ((ret=zip_source_read(src, data, len)) < 0) + return ZIP_SOURCE_ERR_LOWER; + + ctx->left -= (zip_uint64_t)ret; + + if (ret == 0) { + if (ctx->left > 0) { + ctx->e[0] = ZIP_ER_EOF; + ctx->e[1] = 0; + return -1; + } + } + return ret; + + case ZIP_SOURCE_CLOSE: + return 0; + + case ZIP_SOURCE_STAT: + { + struct zip_stat *st; + + st = (struct zip_stat *)data; + + st->size = ctx->len; + st->valid |= ZIP_STAT_SIZE; + st->valid &= ~(ZIP_STAT_CRC|ZIP_STAT_COMP_SIZE); + } + return 0; + + case ZIP_SOURCE_ERROR: + memcpy(data, ctx->e, sizeof(ctx->e)); + return 0; + + case ZIP_SOURCE_FREE: + free(ctx); + return 0; + + default: + return -1; + } + +} diff --git a/ext/zip/lib/zip_source_zip.c b/ext/zip/lib/zip_source_zip.c index 228803c717..e4fc2229f7 100644 --- a/ext/zip/lib/zip_source_zip.c +++ b/ext/zip/lib/zip_source_zip.c @@ -38,153 +38,24 @@ #include "zipint.h" -struct read_zip { - struct zip_file *zf; - struct zip_stat st; - zip_uint64_t off; - zip_int64_t len; -}; - -static zip_int64_t read_zip(void *st, void *data, zip_uint64_t len, - enum zip_source_cmd cmd); - -ZIP_EXTERN(struct zip_source *) +ZIP_EXTERN struct zip_source * zip_source_zip(struct zip *za, struct zip *srcza, zip_uint64_t srcidx, - int flags, zip_uint64_t start, zip_int64_t len) + zip_flags_t flags, zip_uint64_t start, zip_int64_t len) { - struct zip_error error; - struct zip_source *zs; - struct read_zip *p; - - /* XXX: ZIP_FL_RECOMPRESS */ - - if (za == NULL) - return NULL; - - if (srcza == NULL || len < -1 || srcidx < 0 || srcidx >= srcza->nentry) { - _zip_error_set(&za->error, ZIP_ER_INVAL, 0); - return NULL; + if (len < -1) { + _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return NULL; } - - if ((flags & ZIP_FL_UNCHANGED) == 0 - && ZIP_ENTRY_DATA_CHANGED(srcza->entry+srcidx)) { - _zip_error_set(&za->error, ZIP_ER_CHANGED, 0); - return NULL; - } - - if (len == 0) - len = -1; - - if (start == 0 && len == -1 && (flags & ZIP_FL_RECOMPRESS) == 0) + + if (len == -1) + len = 0; + + if (start == 0 && len == 0) flags |= ZIP_FL_COMPRESSED; else flags &= ~ZIP_FL_COMPRESSED; - if ((p=(struct read_zip *)malloc(sizeof(*p))) == NULL) { - _zip_error_set(&za->error, ZIP_ER_MEMORY, 0); - return NULL; - } - - _zip_error_copy(&error, &srcza->error); - - if (zip_stat_index(srcza, srcidx, flags, &p->st) < 0 - || (p->zf=zip_fopen_index(srcza, srcidx, flags)) == NULL) { - free(p); - _zip_error_copy(&za->error, &srcza->error); - _zip_error_copy(&srcza->error, &error); - - return NULL; - } - p->off = start; - p->len = len; - - if ((flags & ZIP_FL_COMPRESSED) == 0) { - p->st.size = p->st.comp_size = len; - p->st.comp_method = ZIP_CM_STORE; - p->st.crc = 0; - } - - if ((zs=zip_source_function(za, read_zip, p)) == NULL) { - free(p); - return NULL; - } - - return zs; -} - - - -static zip_int64_t -read_zip(void *state, void *data, zip_uint64_t len, enum zip_source_cmd cmd) -{ - struct read_zip *z; - char b[8192], *buf; - int i; - zip_uint64_t n; - - z = (struct read_zip *)state; - buf = (char *)data; - - switch (cmd) { - case ZIP_SOURCE_OPEN: - for (n=0; n<z->off; n+= i) { - i = (z->off-n > sizeof(b) ? sizeof(b) : z->off-n); - if ((i=zip_fread(z->zf, b, i)) < 0) { - zip_fclose(z->zf); - z->zf = NULL; - return -1; - } - } - return 0; - - case ZIP_SOURCE_READ: - if (z->len != -1) - n = len > z->len ? z->len : len; - else - n = len; - - - if ((i=zip_fread(z->zf, buf, n)) < 0) - return -1; - - if (z->len != -1) - z->len -= i; - - return i; - - case ZIP_SOURCE_CLOSE: - return 0; - - case ZIP_SOURCE_STAT: - if (len < sizeof(z->st)) - return -1; - len = sizeof(z->st); - - memcpy(data, &z->st, len); - return len; - - case ZIP_SOURCE_ERROR: - { - int *e; - - if (len < sizeof(int)*2) - return -1; - - e = (int *)data; - zip_file_error_get(z->zf, e, e+1); - } - return sizeof(int)*2; - - case ZIP_SOURCE_FREE: - zip_fclose(z->zf); - free(z); - return 0; - - default: - ; - } - - return -1; + return _zip_source_zip_new(za, srcza, srcidx, flags, start, (zip_uint64_t)len, NULL); } diff --git a/ext/zip/lib/zip_source_zip_new.c b/ext/zip/lib/zip_source_zip_new.c new file mode 100644 index 0000000000..8e48f6f3fa --- /dev/null +++ b/ext/zip/lib/zip_source_zip_new.c @@ -0,0 +1,172 @@ +/* + zip_source_zip_new.c -- prepare data structures for zip_fopen/zip_source_zip + Copyright (C) 2012 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR 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. +*/ + + + +#include <stdlib.h> + +#include "zipint.h" + + + +struct zip_source * +_zip_source_zip_new(struct zip *za, struct zip *srcza, zip_uint64_t srcidx, zip_flags_t flags, + zip_uint64_t start, zip_uint64_t len, const char *password) +{ + zip_compression_implementation comp_impl; + zip_encryption_implementation enc_impl; + struct zip_source *src, *s2; + zip_uint64_t offset; + struct zip_stat st; + + if (za == NULL) + return NULL; + + if (srcza == NULL || srcidx >= srcza->nentry) { + _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return NULL; + } + + if ((flags & ZIP_FL_UNCHANGED) == 0 + && (ZIP_ENTRY_DATA_CHANGED(srcza->entry+srcidx) || srcza->entry[srcidx].deleted)) { + _zip_error_set(&za->error, ZIP_ER_CHANGED, 0); + return NULL; + } + + if (zip_stat_index(srcza, srcidx, flags|ZIP_FL_UNCHANGED, &st) < 0) { + _zip_error_set(&za->error, ZIP_ER_INTERNAL, 0); + return NULL; + } + + if (flags & ZIP_FL_ENCRYPTED) + flags |= ZIP_FL_COMPRESSED; + + if ((start > 0 || len > 0) && (flags & ZIP_FL_COMPRESSED)) { + _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return NULL; + } + + /* overflow or past end of file */ + if ((start > 0 || len > 0) && (start+len < start || start+len > st.size)) { + _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return NULL; + } + + enc_impl = NULL; + if (((flags & ZIP_FL_ENCRYPTED) == 0) && (st.encryption_method != ZIP_EM_NONE)) { + if (password == NULL) { + _zip_error_set(&za->error, ZIP_ER_NOPASSWD, 0); + return NULL; + } + if ((enc_impl=_zip_get_encryption_implementation(st.encryption_method)) == NULL) { + _zip_error_set(&za->error, ZIP_ER_ENCRNOTSUPP, 0); + return NULL; + } + } + + comp_impl = NULL; + if ((flags & ZIP_FL_COMPRESSED) == 0) { + if (st.comp_method != ZIP_CM_STORE) { + if ((comp_impl=_zip_get_compression_implementation(st.comp_method)) == NULL) { + _zip_error_set(&za->error, ZIP_ER_COMPNOTSUPP, 0); + return NULL; + } + } + } + + if ((offset=_zip_file_get_offset(srcza, srcidx, &za->error)) == 0) + return NULL; + + if (st.comp_size == 0) { + if ((src=zip_source_buffer(za, NULL, 0, 0)) == NULL) + return NULL; + } + else { + if (start+len > 0 && enc_impl == NULL && comp_impl == NULL) { + struct zip_stat st2; + + st2.size = len ? len : st.size-start; + st2.comp_size = st2.size; + st2.comp_method = ZIP_CM_STORE; + st2.mtime = st.mtime; + st2.valid = ZIP_STAT_SIZE|ZIP_STAT_COMP_SIZE|ZIP_STAT_COMP_METHOD|ZIP_STAT_MTIME; + + /* XXX: check for overflow of st2.size */ + if ((src=_zip_source_file_or_p(za, NULL, srcza->zp, offset+start, (zip_int64_t)st2.size, 0, &st2)) == NULL) + return NULL; + } + else { + /* XXX: check for overflow of st.comp_size */ + if ((src=_zip_source_file_or_p(za, NULL, srcza->zp, offset, (zip_int64_t)st.comp_size, 0, &st)) == NULL) + return NULL; + } + + if (enc_impl) { + if ((s2=enc_impl(za, src, st.encryption_method, 0, password)) == NULL) { + zip_source_free(src); + /* XXX: set error (how?) */ + return NULL; + } + src = s2; + } + if (comp_impl) { + if ((s2=comp_impl(za, src, st.comp_method, 0)) == NULL) { + zip_source_free(src); + /* XXX: set error (how?) */ + return NULL; + } + src = s2; + } + if (((flags & ZIP_FL_COMPRESSED) == 0 || st.comp_method == ZIP_CM_STORE) + && (len == 0 || len == st.comp_size)) { + /* when reading the whole file, check for crc errors */ + if ((s2=zip_source_crc(za, src, 1)) == NULL) { + zip_source_free(src); + /* XXX: set error (how?) */ + return NULL; + } + src = s2; + } + + if (start+len > 0 && (comp_impl || enc_impl)) { + if ((s2=zip_source_window(za, src, start, len ? len : st.size-start)) == NULL) { + zip_source_free(src); + /* XXX: set error (how?) (why?) */ + return NULL; + } + src = s2; + } + } + + return src; +} diff --git a/ext/zip/lib/zip_stat.c b/ext/zip/lib/zip_stat.c index c8a25e1d84..8254627d92 100644 --- a/ext/zip/lib/zip_stat.c +++ b/ext/zip/lib/zip_stat.c @@ -37,13 +37,13 @@ -ZIP_EXTERN(int) -zip_stat(struct zip *za, const char *fname, int flags, struct zip_stat *st) +ZIP_EXTERN int +zip_stat(struct zip *za, const char *fname, zip_flags_t flags, struct zip_stat *st) { - int idx; + zip_int64_t idx; if ((idx=zip_name_locate(za, fname, flags)) < 0) return -1; - return zip_stat_index(za, idx, flags, st); + return zip_stat_index(za, (zip_uint64_t)idx, flags, st); } diff --git a/ext/zip/lib/zip_stat_index.c b/ext/zip/lib/zip_stat_index.c index 8faa8cc394..f4ce72aaa8 100644 --- a/ext/zip/lib/zip_stat_index.c +++ b/ext/zip/lib/zip_stat_index.c @@ -37,16 +37,15 @@ -ZIP_EXTERN(int) -zip_stat_index(struct zip *za, zip_uint64_t index, int flags, +ZIP_EXTERN int +zip_stat_index(struct zip *za, zip_uint64_t index, zip_flags_t flags, struct zip_stat *st) { const char *name; - - if (index >= za->nentry) { - _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + struct zip_dirent *de; + + if ((de=_zip_get_dirent(za, index, flags, NULL)) == NULL) return -1; - } if ((name=zip_get_name(za, index, flags)) == NULL) return -1; @@ -60,20 +59,15 @@ zip_stat_index(struct zip *za, zip_uint64_t index, int flags, } } else { - if (za->cdir == NULL || index >= za->cdir->nentry) { - _zip_error_set(&za->error, ZIP_ER_INVAL, 0); - return -1; - } - zip_stat_init(st); - st->crc = za->cdir->entry[index].crc; - st->size = za->cdir->entry[index].uncomp_size; - st->mtime = za->cdir->entry[index].last_mod; - st->comp_size = za->cdir->entry[index].comp_size; - st->comp_method = za->cdir->entry[index].comp_method; - if (za->cdir->entry[index].bitflags & ZIP_GPBF_ENCRYPTED) { - if (za->cdir->entry[index].bitflags & ZIP_GPBF_STRONG_ENCRYPTION) { + st->crc = de->crc; + st->size = de->uncomp_size; + st->mtime = de->last_mod; + st->comp_size = de->comp_size; + st->comp_method = (zip_uint16_t)de->comp_method; + if (de->bitflags & ZIP_GPBF_ENCRYPTED) { + if (de->bitflags & ZIP_GPBF_STRONG_ENCRYPTION) { /* XXX */ st->encryption_method = ZIP_EM_UNKNOWN; } diff --git a/ext/zip/lib/zip_stat_init.c b/ext/zip/lib/zip_stat_init.c index 74e1ffd0b0..d17613bf5e 100644 --- a/ext/zip/lib/zip_stat_init.c +++ b/ext/zip/lib/zip_stat_init.c @@ -37,7 +37,7 @@ -ZIP_EXTERN(void) +ZIP_EXTERN void zip_stat_init(struct zip_stat *st) { st->valid = 0; diff --git a/ext/zip/lib/zip_strerror.c b/ext/zip/lib/zip_strerror.c index ad23bafed6..9ebee144f9 100644 --- a/ext/zip/lib/zip_strerror.c +++ b/ext/zip/lib/zip_strerror.c @@ -36,7 +36,8 @@ #include "zipint.h" -ZIP_EXTERN(const char *) + +ZIP_EXTERN const char * zip_strerror(struct zip *za) { return _zip_error_strerror(&za->error); diff --git a/ext/zip/lib/zip_string.c b/ext/zip/lib/zip_string.c new file mode 100644 index 0000000000..a2d5eb5d3f --- /dev/null +++ b/ext/zip/lib/zip_string.c @@ -0,0 +1,196 @@ +/* + zip_string.c -- string handling (with encoding) + Copyright (C) 2012 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR 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. +*/ + + + +#include <stdlib.h> +#include <string.h> + +#include "zipint.h" + + + +zip_uint32_t +_zip_string_crc32(const struct zip_string *s) +{ + zip_uint32_t crc; + + crc = (zip_uint32_t)crc32(0L, Z_NULL, 0); + + if (s != NULL) + crc = (zip_uint32_t)crc32(crc, s->raw, s->length); + + return crc; +} + + + +int +_zip_string_equal(const struct zip_string *a, const struct zip_string *b) +{ + if (a == NULL || b == NULL) + return a == b; + + if (a->length != b->length) + return 0; + + /* XXX: encoding */ + + return (memcmp(a->raw, b->raw, a->length) == 0); +} + + + +void +_zip_string_free(struct zip_string *s) +{ + if (s == NULL) + return; + + free(s->raw); + free(s->converted); + free(s); +} + + + +const zip_uint8_t * +_zip_string_get(struct zip_string *string, zip_uint32_t *lenp, zip_flags_t flags, struct zip_error *error) +{ + static const zip_uint8_t empty[1] = ""; + + if (string == NULL) { + if (lenp) + *lenp = 0; + return empty; + } + + if ((flags & ZIP_FL_ENC_RAW) == 0) { + /* start guessing */ + if (string->encoding == ZIP_ENCODING_UNKNOWN) + _zip_guess_encoding(string, ZIP_ENCODING_UNKNOWN); + + if (((flags & ZIP_FL_ENC_STRICT) + && string->encoding != ZIP_ENCODING_ASCII && string->encoding != ZIP_ENCODING_UTF8_KNOWN) + || (string->encoding == ZIP_ENCODING_CP437)) { + if (string->converted == NULL) { + if ((string->converted=_zip_cp437_to_utf8(string->raw, string->length, + &string->converted_length, error)) == NULL) + return NULL; + } + if (lenp) + *lenp = string->converted_length; + return string->converted; + } + } + + if (lenp) + *lenp = string->length; + return string->raw; +} + + + +zip_uint16_t +_zip_string_length(const struct zip_string *s) +{ + if (s == NULL) + return 0; + + return s->length; +} + + + +struct zip_string * +_zip_string_new(const zip_uint8_t *raw, zip_uint16_t length, zip_flags_t flags, struct zip_error *error) +{ + struct zip_string *s; + enum zip_encoding_type expected_encoding; + + if (length == 0) + return NULL; + + switch (flags & ZIP_FL_ENCODING_ALL) { + case ZIP_FL_ENC_GUESS: + expected_encoding = ZIP_ENCODING_UNKNOWN; + break; + case ZIP_FL_ENC_UTF_8: + expected_encoding = ZIP_ENCODING_UTF8_KNOWN; + break; + case ZIP_FL_ENC_CP437: + expected_encoding = ZIP_ENCODING_CP437; + break; + default: + _zip_error_set(error, ZIP_ER_INVAL, 0); + return NULL; + } + + if ((s=(struct zip_string *)malloc(sizeof(*s))) == NULL) { + _zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; + } + + if ((s->raw=(zip_uint8_t *)malloc(length+1)) == NULL) { + free(s); + return NULL; + } + + memcpy(s->raw, raw, length); + s->raw[length] = '\0'; + s->length = length; + s->encoding = ZIP_ENCODING_UNKNOWN; + s->converted = NULL; + s->converted_length = 0; + + if (expected_encoding != ZIP_ENCODING_UNKNOWN) { + if (_zip_guess_encoding(s, expected_encoding) == ZIP_ENCODING_ERROR) { + _zip_string_free(s); + _zip_error_set(error, ZIP_ER_INVAL, 0); + return NULL; + } + } + + return s; +} + + + +void +_zip_string_write(const struct zip_string *s, FILE *f) +{ + if (s == NULL) + return; + + fwrite(s->raw, s->length, 1, f); +} diff --git a/ext/zip/lib/zip_unchange.c b/ext/zip/lib/zip_unchange.c index 550e8b9903..5f0e753b78 100644 --- a/ext/zip/lib/zip_unchange.c +++ b/ext/zip/lib/zip_unchange.c @@ -39,7 +39,7 @@ -ZIP_EXTERN(int) +ZIP_EXTERN int zip_unchange(struct zip *za, zip_uint64_t idx) { return _zip_unchange(za, idx, 0); @@ -50,34 +50,23 @@ zip_unchange(struct zip *za, zip_uint64_t idx) int _zip_unchange(struct zip *za, zip_uint64_t idx, int allow_duplicates) { - int i; + zip_int64_t i; if (idx >= za->nentry) { _zip_error_set(&za->error, ZIP_ER_INVAL, 0); return -1; } - if (za->entry[idx].ch_filename) { - if (!allow_duplicates) { - i = _zip_name_locate(za, - _zip_get_name(za, idx, ZIP_FL_UNCHANGED, NULL), - 0, NULL); - if (i != -1 && i != idx) { - _zip_error_set(&za->error, ZIP_ER_EXISTS, 0); - return -1; - } + if (!allow_duplicates && za->entry[idx].changes && (za->entry[idx].changes->changed & ZIP_DIRENT_FILENAME)) { + i = _zip_name_locate(za, _zip_get_name(za, idx, ZIP_FL_UNCHANGED, NULL), 0, NULL); + if (i >= 0 && (zip_uint64_t)i != idx) { + _zip_error_set(&za->error, ZIP_ER_EXISTS, 0); + return -1; } - - free(za->entry[idx].ch_filename); - za->entry[idx].ch_filename = NULL; } - free(za->entry[idx].ch_extra); - za->entry[idx].ch_extra = NULL; - za->entry[idx].ch_extra_len = -1; - free(za->entry[idx].ch_comment); - za->entry[idx].ch_comment = NULL; - za->entry[idx].ch_comment_len = -1; + _zip_dirent_free(za->entry[idx].changes); + za->entry[idx].changes = NULL; _zip_unchange_data(za->entry+idx); diff --git a/ext/zip/lib/zip_unchange_all.c b/ext/zip/lib/zip_unchange_all.c index 01282f89db..bbc2825eb6 100644 --- a/ext/zip/lib/zip_unchange_all.c +++ b/ext/zip/lib/zip_unchange_all.c @@ -39,10 +39,11 @@ -ZIP_EXTERN(int) +ZIP_EXTERN int zip_unchange_all(struct zip *za) { - int ret, i; + int ret; + zip_uint64_t i; ret = 0; for (i=0; i<za->nentry; i++) diff --git a/ext/zip/lib/zip_unchange_archive.c b/ext/zip/lib/zip_unchange_archive.c index ca2b678544..e24ee21727 100644 --- a/ext/zip/lib/zip_unchange_archive.c +++ b/ext/zip/lib/zip_unchange_archive.c @@ -39,13 +39,15 @@ -ZIP_EXTERN(int) +ZIP_EXTERN int zip_unchange_archive(struct zip *za) { - free(za->ch_comment); - za->ch_comment = NULL; - za->ch_comment_len = -1; - + if (za->comment_changed) { + _zip_string_free(za->comment_changes); + za->comment_changes = NULL; + za->comment_changed = 0; + } + za->ch_flags = za->flags; return 0; diff --git a/ext/zip/lib/zip_unchange_data.c b/ext/zip/lib/zip_unchange_data.c index 7dd93b768a..fa25feb038 100644 --- a/ext/zip/lib/zip_unchange_data.c +++ b/ext/zip/lib/zip_unchange_data.c @@ -1,8 +1,6 @@ /* - $NiH: zip_unchange_data.c,v 1.14 2004/11/30 23:02:47 wiz Exp $ - zip_unchange_data.c -- undo helper function - Copyright (C) 1999, 2004 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2012 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -35,8 +33,6 @@ -#include <stdlib.h> - #include "zipint.h" void @@ -46,7 +42,15 @@ _zip_unchange_data(struct zip_entry *ze) zip_source_free(ze->source); ze->source = NULL; } - - ze->state = ze->ch_filename ? ZIP_ST_RENAMED : ZIP_ST_UNCHANGED; + + if (ze->changes != NULL && (ze->changes->changed & ZIP_DIRENT_COMP_METHOD) && ze->changes->comp_method == ZIP_CM_REPLACED_DEFAULT) { + ze->changes->changed &= ~ZIP_DIRENT_COMP_METHOD; + if (ze->changes->changed == 0) { + _zip_dirent_free(ze->changes); + ze->changes = NULL; + } + } + + ze->deleted = 0; } diff --git a/ext/zip/lib/zip_utf-8.c b/ext/zip/lib/zip_utf-8.c new file mode 100644 index 0000000000..c36fad13f5 --- /dev/null +++ b/ext/zip/lib/zip_utf-8.c @@ -0,0 +1,255 @@ +/* + zip_utf-8.c -- UTF-8 support functions for libzip + Copyright (C) 2011-2012 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR 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. +*/ + + + +#include "zipint.h" + +#include <stdlib.h> + + + +static const zip_uint16_t _cp437_to_unicode[256] = { + /* 0x00 - 0x0F */ + 0x2007, 0x263A, 0x263B, 0x2665, 0x2666, 0x2663, 0x2660, 0x2022, + 0x25D8, 0x25CB, 0x25D9, 0x2642, 0x2640, 0x266A, 0x266B, 0x263C, + + /* 0x10 - 0x1F */ + 0x25BA, 0x25C4, 0x2195, 0x203C, 0x00B6, 0x00A7, 0x25AC, 0x21A8, + 0x2191, 0x2193, 0x2192, 0x2190, 0x221F, 0x2194, 0x25B2, 0x25BC, + + /* 0x20 - 0x2F */ + 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, + 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F, + + /* 0x30 - 0x3F */ + 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, + 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F, + + /* 0x40 - 0x4F */ + 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, + 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, + + /* 0x50 - 0x5F */ + 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, + 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F, + + /* 0x60 - 0x6F */ + 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, + 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F, + + /* 0x70 - 0x7F */ + 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, + 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x2302, + + /* 0x80 - 0x8F */ + 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, + 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5, + + /* 0x90 - 0x9F */ + 0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, + 0x00FF, 0x00D6, 0x00DC, 0x00A2, 0x00A3, 0x00A5, 0x20A7, 0x0192, + + /* 0xA0 - 0xAF */ + 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, + 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, + + /* 0xB0 - 0xBF */ + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, + 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, + + /* 0xC0 - 0xCF */ + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, + 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, + + /* 0xD0 - 0xDF */ + 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, + 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, + + /* 0xE0 - 0xEF */ + 0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, + 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229, + + /* 0xF0 - 0xFF */ + 0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, + 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0 +}; + +#define UTF_8_LEN_2_MASK 0xe0 +#define UTF_8_LEN_2_MATCH 0xc0 +#define UTF_8_LEN_3_MASK 0xf0 +#define UTF_8_LEN_3_MATCH 0xe0 +#define UTF_8_LEN_4_MASK 0xf8 +#define UTF_8_LEN_4_MATCH 0xf0 +#define UTF_8_CONTINUE_MASK 0xc0 +#define UTF_8_CONTINUE_MATCH 0x80 + + + +enum zip_encoding_type +_zip_guess_encoding(struct zip_string *str, enum zip_encoding_type expected_encoding) +{ + enum zip_encoding_type enc; + const zip_uint8_t *name; + zip_uint32_t i, j, ulen; + + if (str == NULL) + return ZIP_ENCODING_ASCII; + + name = str->raw; + + if (str->encoding != ZIP_ENCODING_UNKNOWN) + enc = str->encoding; + else { + enc = ZIP_ENCODING_ASCII; + for (i=0; i<str->length; i++) { + if ((name[i] > 31 && name[i] < 128) || name[i] == '\r' || name[i] == '\n' || name[i] == '\t') + continue; + + enc = ZIP_ENCODING_UTF8_GUESSED; + if ((name[i] & UTF_8_LEN_2_MASK) == UTF_8_LEN_2_MATCH) + ulen = 1; + else if ((name[i] & UTF_8_LEN_3_MASK) == UTF_8_LEN_3_MATCH) + ulen = 2; + else if ((name[i] & UTF_8_LEN_4_MASK) == UTF_8_LEN_4_MATCH) + ulen = 3; + else { + enc = ZIP_ENCODING_CP437; + break; + } + + if (i + ulen >= str->length) { + enc = ZIP_ENCODING_CP437; + break; + } + + for (j=1; j<=ulen; j++) { + if ((name[i+j] & UTF_8_CONTINUE_MASK) != UTF_8_CONTINUE_MATCH) { + enc = ZIP_ENCODING_CP437; + goto done; + } + } + i += ulen; + } + } + +done: + str->encoding = enc; + + if (expected_encoding != ZIP_ENCODING_UNKNOWN) { + if (expected_encoding == ZIP_ENCODING_UTF8_KNOWN && enc == ZIP_ENCODING_UTF8_GUESSED) + str->encoding = enc = ZIP_ENCODING_UTF8_KNOWN; + + if (expected_encoding != enc && enc != ZIP_ENCODING_ASCII) + return ZIP_ENCODING_ERROR; + } + + return enc; +} + + + +static zip_uint32_t +_zip_unicode_to_utf8_len(zip_uint32_t codepoint) +{ + if (codepoint < 0x0080) + return 1; + if (codepoint < 0x0800) + return 2; + if (codepoint < 0x10000) + return 3; + return 4; +} + + + +static zip_uint32_t +_zip_unicode_to_utf8(zip_uint32_t codepoint, zip_uint8_t *buf) +{ + if (codepoint < 0x0080) { + buf[0] = codepoint & 0xff; + return 1; + } + if (codepoint < 0x0800) { + buf[0] = UTF_8_LEN_2_MATCH | ((codepoint >> 6) & 0x1f); + buf[1] = UTF_8_CONTINUE_MATCH | (codepoint & 0x3f); + return 2; + } + if (codepoint < 0x10000) { + buf[0] = UTF_8_LEN_3_MATCH | ((codepoint >> 12) & 0x0f); + buf[1] = UTF_8_CONTINUE_MATCH | ((codepoint >> 6) & 0x3f); + buf[2] = UTF_8_CONTINUE_MATCH | (codepoint & 0x3f); + return 3; + } + buf[0] = UTF_8_LEN_4_MATCH | ((codepoint >> 18) & 0x07); + buf[1] = UTF_8_CONTINUE_MATCH | ((codepoint >> 12) & 0x3f); + buf[2] = UTF_8_CONTINUE_MATCH | ((codepoint >> 6) & 0x3f); + buf[3] = UTF_8_CONTINUE_MATCH | (codepoint & 0x3f); + return 4; +} + + + +zip_uint8_t * +_zip_cp437_to_utf8(const zip_uint8_t * const _cp437buf, zip_uint32_t len, + zip_uint32_t *utf8_lenp, struct zip_error *error) +{ + zip_uint8_t *cp437buf = (zip_uint8_t *)_cp437buf; + zip_uint8_t *utf8buf; + zip_uint32_t buflen, i, offset; + + if (len == 0) { + if (utf8_lenp) + *utf8_lenp = 0; + return NULL; + } + + buflen = 1; + for (i=0; i<len; i++) + buflen += _zip_unicode_to_utf8_len(_cp437_to_unicode[cp437buf[i]]); + + if ((utf8buf=(zip_uint8_t*)malloc(buflen)) == NULL) { + _zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; + } + + offset = 0; + for (i=0; i<len; i++) + offset += _zip_unicode_to_utf8(_cp437_to_unicode[cp437buf[i]], + utf8buf+offset); + + utf8buf[buflen-1] = 0; + if (utf8_lenp) + *utf8_lenp = buflen-1; + return utf8buf; +} diff --git a/ext/zip/lib/zip_win32.h b/ext/zip/lib/zip_win32.h deleted file mode 100644 index ff28d2878c..0000000000 --- a/ext/zip/lib/zip_win32.h +++ /dev/null @@ -1,31 +0,0 @@ -#define _POSIX_ -#include <windows.h> -#include <io.h> -#include <fcntl.h> -#include <string.h> -#include <zconf.h> - -#ifndef strcasecmp -# define strcmpi _strcmpi -#endif - -#ifndef ssize_t -# define ssize_t SSIZE_T -#endif - -#ifndef mode_t -# define mode_t int -#endif - -#ifndef snprintf -# define snprintf _snprintf -#endif - -#ifndef mkstemp -# define mkstemp(t) _creat(_mktemp(t), _S_IREAD|_S_IWRITE) -#endif -/* -#ifndef fseeko -# define fseeko fseek -#endif -*/ diff --git a/ext/zip/lib/zipconf.h b/ext/zip/lib/zipconf.h index 2b4340c861..1cb5c0467a 100644 --- a/ext/zip/lib/zipconf.h +++ b/ext/zip/lib/zipconf.h @@ -1,51 +1,129 @@ -#ifndef _HAD_ZIPCONF_H -#define _HAD_ZIPCONF_H - -/* - zipconf.h -- platform specific include file - - This file was generated automatically by ./make_zipconf.sh - based on ../config.h. - */ - -#define LIBZIP_VERSION "0.10.1" -#define LIBZIP_VERSION_MAJOR 0 -#define LIBZIP_VERSION_MINOR 10 -#define LIBZIP_VERSION_MICRO 0 - -#ifdef PHP_WIN32 -#include <win32/php_stdint.h> -#else -#include <inttypes.h> -#endif - -typedef int8_t zip_int8_t; -#define ZIP_INT8_MIN INT8_MIN -#define ZIP_INT8_MAX INT8_MAX - -typedef uint8_t zip_uint8_t; -#define ZIP_UINT8_MAX UINT8_MAX - -typedef int16_t zip_int16_t; -#define ZIP_INT16_MIN INT16_MIN -#define ZIP_INT16_MAX INT16_MAX - -typedef uint16_t zip_uint16_t; -#define ZIP_UINT16_MAX UINT16_MAX - -typedef int32_t zip_int32_t; -#define ZIP_INT32_MIN INT32_MIN -#define ZIP_INT32_MAX INT32_MAX - -typedef uint32_t zip_uint32_t; -#define ZIP_UINT32_MAX UINT32_MAX - -typedef int64_t zip_int64_t; -#define ZIP_INT64_MIN INT64_MIN -#define ZIP_INT64_MAX INT64_MAX - -typedef uint64_t zip_uint64_t; -#define ZIP_UINT64_MAX UINT64_MAX - - -#endif /* zipconf.h */ +#ifndef _HAD_ZIPCONF_H
+#define _HAD_ZIPCONF_H
+
+/*
+ zipconf.h -- platform specific include file
+
+ This file was generated automatically by CMake
+ based on ../cmake-zipconf.h.in.
+ */
+#define LIBZIP_VERSION "0.11.1"
+/* #undef HAVE_INTTYPES_H_LIBZIP */
+
+#if defined(_WIN32)
+# if _MSC_VER > 1500
+# define HAVE_STDINT_H_LIBZIP
+# else
+# include "win32/php_stdint.h"
+# endif
+#else
+# include <inttypes.h>
+#endif
+#define HAVE_SYS_TYPES_H_LIBZIP
+#define HAVE___INT8_LIBZIP
+#define HAVE_INT8_T_LIBZIP
+#define HAVE_UINT8_T_LIBZIP
+#define HAVE___INT16_LIBZIP
+#define HAVE_INT16_T_LIBZIP
+#define HAVE_UINT16_T_LIBZIP
+#define HAVE___INT32_LIBZIP
+#define HAVE_INT32_T_LIBZIP
+#define HAVE_UINT32_T_LIBZIP
+#define HAVE___INT64_LIBZIP
+#define HAVE_INT64_T_LIBZIP
+#define HAVE_UINT64_T_LIBZIP
+#define SHORT_LIBZIP 2
+#define INT_LIBZIP 4
+#define LONG_LIBZIP 4
+#define LONG_LONG_LIBZIP 8
+
+#if defined(HAVE_STDINT_H_LIBZIP)
+#include <stdint.h>
+#elif defined(HAVE_INTTYPES_H_LIBZIP)
+#include <inttypes.h>
+#elif defined(HAVE_SYS_TYPES_H_LIBZIP)
+#include <sys/types.h>
+#endif
+
+#if defined(HAVE_INT8_T_LIBZIP)
+typedef int8_t zip_int8_t;
+#elif defined(HAVE___INT8_LIBZIP)
+typedef __int8 zip_int8_t;
+#else
+typedef signed char zip_int8_t;
+#endif
+#if defined(HAVE_UINT8_T_LIBZIP)
+typedef uint8_t zip_uint8_t;
+#elif defined(HAVE___INT8_LIBZIP)
+typedef unsigned __int8 zip_uint8_t;
+#else
+typedef unsigned char zip_uint8_t;
+#endif
+#if defined(HAVE_INT16_T_LIBZIP)
+typedef int16_t zip_int16_t;
+#elif defined(HAVE___INT16_LIBZIP)
+typedef __int16 zip_int16_t;
+#elif defined(SHORT_LIBZIP) && SHORT_LIBZIP == 2
+typedef signed short zip_int16_t;
+#endif
+#if defined(HAVE_UINT16_T_LIBZIP)
+typedef uint16_t zip_uint16_t;
+#elif defined(HAVE___INT16_LIBZIP)
+typedef unsigned __int16 zip_uint16_t;
+#elif defined(SHORT_LIBZIP) && SHORT_LIBZIP == 2
+typedef unsigned short zip_uint16_t;
+#endif
+#if defined(HAVE_INT32_T_LIBZIP)
+typedef int32_t zip_int32_t;
+#elif defined(HAVE___INT32_LIBZIP)
+typedef __int32 zip_int32_t;
+#elif defined(INT_LIBZIP) && INT_LIBZIP == 4
+typedef signed int zip_int32_t;
+#elif defined(LONG_LIBZIP) && LONG_LIBZIP == 4
+typedef signed long zip_int32_t;
+#endif
+#if defined(HAVE_UINT32_T_LIBZIP)
+typedef uint32_t zip_uint32_t;
+#elif defined(HAVE___INT32_LIBZIP)
+typedef unsigned __int32 zip_uint32_t;
+#elif defined(INT_LIBZIP) && INT_LIBZIP == 4
+typedef unsigned int zip_uint32_t;
+#elif defined(LONG_LIBZIP) && LONG_LIBZIP == 4
+typedef unsigned long zip_uint32_t;
+#endif
+#if defined(HAVE_INT64_T_LIBZIP)
+typedef int64_t zip_int64_t;
+#elif defined(HAVE___INT64_LIBZIP)
+typedef __int64 zip_int64_t;
+#elif defined(LONG_LIBZIP) && LONG_LIBZIP == 8
+typedef signed long zip_int64_t;
+#elif defined(LONG_LONG_LIBZIP) && LONG_LONG_LIBZIP == 8
+typedef signed long long zip_int64_t;
+#endif
+#if defined(HAVE_UINT64_T_LIBZIP)
+typedef uint64_t zip_uint64_t;
+#elif defined(HAVE___INT64_LIBZIP)
+typedef unsigned __int64 zip_uint64_t;
+#elif defined(LONG_LIBZIP) && LONG_LONG_LIBZIP == 8
+typedef unsigned long zip_uint64_t;
+#elif defined(LONG_LONG_LIBZIP) && LONG_LONG_LIBZIP == 8
+typedef unsigned long long zip_uint64_t;
+#endif
+
+#define ZIP_INT8_MIN -0x80
+#define ZIP_INT8_MAX 0x7f
+#define ZIP_UINT8_MAX 0xff
+
+#define ZIP_INT16_MIN -0x8000
+#define ZIP_INT16_MAX 0x7fff
+#define ZIP_UINT16_MAX 0xffff
+
+#define ZIP_INT32_MIN -0x80000000L
+#define ZIP_INT32_MAX 0x7fffffffL
+#define ZIP_UINT32_MAX 0xffffffffLU
+
+#define ZIP_INT64_MIN -0x8000000000000000LL
+#define ZIP_INT64_MAX 0x7fffffffffffffffLL
+#define ZIP_UINT64_MAX 0xffffffffffffffffULL
+
+#endif /* zipconf.h */
diff --git a/ext/zip/lib/zipint.h b/ext/zip/lib/zipint.h index ea21dddcd4..e8765c5b66 100644 --- a/ext/zip/lib/zipint.h +++ b/ext/zip/lib/zipint.h @@ -3,7 +3,7 @@ /* zipint.h -- internal declarations. - Copyright (C) 1999-2011 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2013 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -20,7 +20,7 @@ 3. The names of the authors may not be used to endorse or promote products derived from this software without specific prior written permission. - + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -34,69 +34,123 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include <zlib.h> +/* to have *_MAX definitions for all types when compiling with g++ */ +#define __STDC_LIMIT_MACROS -#include "zip.h" +#include <zlib.h> -#ifndef HAVE_FSEEKO -#define fseeko(s, o, w) (fseek((s), (long int)(o), (w))) +#ifdef PHP_WIN32 +/* for dup(), close(), etc. */ +#include <io.h> +#include "config.w32.h" #endif -#ifndef HAVE_FTELLO -#define ftello(s) ((long)ftell((s))) +#ifndef _ZIP_COMPILING_DEPRECATED +#define ZIP_DISABLE_DEPRECATED #endif -#ifndef PHP_WIN32 -#ifndef HAVE_MKSTEMP -int _zip_mkstemp(char *); -#define mkstemp _zip_mkstemp -#endif +#include "zip.h" +#ifdef PHP_WIN32 +# include "php_zip_config.w32.h" +#else +# include "config.h" #endif -#ifdef PHP_WIN32 +#if defined(HAVE_MOVEFILEEXA) && defined(_WIN32) #include <windows.h> -#include <wchar.h> #define _zip_rename(s, t) \ - (!MoveFileExA((s), (t), \ - MOVEFILE_COPY_ALLOWED|MOVEFILE_REPLACE_EXISTING)) + (!MoveFileExA((s), (t), MOVEFILE_COPY_ALLOWED|MOVEFILE_REPLACE_EXISTING)) +#else +#define _zip_rename rename +#endif -/* for dup(), close(), etc. */ -#include <io.h> +#ifdef _WIN32 +#undef strcasecmp +# define strcasecmp _strcmpi +#endif -#if !defined(HAVE_OPEN) +#if defined(HAVE__CLOSE) +#define close _close +#endif +#if defined(HAVE__DUP) +#define dup _dup +#endif +/* crashes reported when using fdopen instead of _fdopen on Windows/Visual Studio 10/Win64 */ +#if defined(HAVE__FDOPEN) +#define fdopen _fdopen +#endif +#if defined(HAVE__FILENO) +#define fileno _fileno +#endif +/* Windows' open() doesn't understand Unix permissions */ #if defined(HAVE__OPEN) #define open(a, b, c) _open((a), (b)) #endif +#if defined(HAVE__SNPRINTF) +#define snprintf _snprintf +#endif +#if defined(HAVE__STRDUP) && !defined(strdup) +#define strdup _strdup #endif -#else -#define _zip_rename rename +#ifndef HAVE_FSEEKO +#define fseeko(s, o, w) (fseek((s), (long int)(o), (w))) #endif -#ifndef strcasecmp -# define strcmpi strcasecmp +#ifndef HAVE_FTELLO +#define ftello(s) ((long)ftell((s))) #endif +#ifndef HAVE_MKSTEMP +int _zip_mkstemp(char *); +#define mkstemp _zip_mkstemp +#endif - +#if !defined(HAVE_STRCASECMP) +#if defined(HAVE__STRICMP) +#define strcasecmp _stricmp +#endif +#endif + +#if SIZEOF_OFF_T == 8 +#define ZIP_OFF_MAX ZIP_INT64_MAX +#elif SIZEOF_OFF_T == 4 +#define ZIP_OFF_MAX ZIP_INT32_MAX +#elif SIZEOF_OFF_T == 2 +#define ZIP_OFF_MAX ZIP_INT16_MAX +#else +#error unsupported size of off_t +#endif #define CENTRAL_MAGIC "PK\1\2" #define LOCAL_MAGIC "PK\3\4" #define EOCD_MAGIC "PK\5\6" #define DATADES_MAGIC "PK\7\8" +#define EOCD64LOC_MAGIC "PK\6\7" +#define EOCD64_MAGIC "PK\6\6" #define TORRENT_SIG "TORRENTZIPPED-" #define TORRENT_SIG_LEN 14 #define TORRENT_CRC_LEN 8 #define TORRENT_MEM_LEVEL 8 #define CDENTRYSIZE 46u #define LENTRYSIZE 30 -#undef MAXCOMLEN /* defined as 19 on BSD for max command name */ #define MAXCOMLEN 65536 #define MAXEXTLEN 65536 #define EOCDLEN 22 -#define CDBUFSIZE (MAXCOMLEN+EOCDLEN) +#define EOCD64LOCLEN 20 +#define EOCD64LEN 56 +#define CDBUFSIZE (MAXCOMLEN+EOCDLEN+EOCD64LOCLEN) #define BUFSIZE 8192 +#define ZIP_CM_REPLACED_DEFAULT (-2) + +#define ZIP_CM_IS_DEFAULT(x) ((x) == ZIP_CM_DEFAULT || (x) == ZIP_CM_REPLACED_DEFAULT) + +#define ZIP_EF_UTF_8_COMMENT 0x6375 +#define ZIP_EF_UTF_8_NAME 0x7075 +#define ZIP_EF_ZIP64 0x0001 + +#define ZIP_EF_IS_INTERNAL(id) ((id) == ZIP_EF_UTF_8_COMMENT || (id) == ZIP_EF_UTF_8_NAME || (id) == ZIP_EF_ZIP64) /* This section contains API that won't materialize like this. It's @@ -104,20 +158,22 @@ int _zip_mkstemp(char *); typedef struct zip_source *(*zip_compression_implementation)(struct zip *, struct zip_source *, - zip_uint16_t, int); + zip_int32_t, int); typedef struct zip_source *(*zip_encryption_implementation)(struct zip *, struct zip_source *, zip_uint16_t, int, const char *); -ZIP_EXTERN(zip_compression_implementation) zip_get_compression_implementation( - zip_uint16_t); -ZIP_EXTERN(zip_encryption_implementation) zip_get_encryption_implementation( - zip_uint16_t); +zip_compression_implementation _zip_get_compression_implementation(zip_int32_t); +zip_encryption_implementation _zip_get_encryption_implementation(zip_uint16_t); +/* This API is not final yet, but we need it internally, so it's private for now. */ + +const zip_uint8_t *zip_get_extra_field_by_id(struct zip *, int, int, zip_uint16_t, int, zip_uint16_t *); + /* This section contains API that is of limited use until support for user-supplied compression/encryption implementation is finished. Thus we will keep it private for now. */ @@ -126,40 +182,37 @@ typedef zip_int64_t (*zip_source_layered_callback)(struct zip_source *, void *, void *, zip_uint64_t, enum zip_source_cmd); -ZIP_EXTERN(void) zip_source_close(struct zip_source *); -ZIP_EXTERN(struct zip_source *)zip_source_crc(struct zip *, struct zip_source *, - int); -ZIP_EXTERN(struct zip_source *)zip_source_deflate(struct zip *, - struct zip_source *, - zip_uint16_t, int); -ZIP_EXTERN(void) zip_source_error(struct zip_source *, int *, int *); -ZIP_EXTERN(struct zip_source *)zip_source_layered(struct zip *, - struct zip_source *, - zip_source_layered_callback, - void *); -ZIP_EXTERN(int) zip_source_open(struct zip_source *); -ZIP_EXTERN(struct zip_source *)zip_source_pkware(struct zip *, - struct zip_source *, - zip_uint16_t, int, - const char *); -ZIP_EXTERN(zip_int64_t) zip_source_read(struct zip_source *, void *, - zip_uint64_t); -ZIP_EXTERN(int) zip_source_stat(struct zip_source *, struct zip_stat *); +void zip_source_close(struct zip_source *); +struct zip_source *zip_source_crc(struct zip *, struct zip_source *, + int); +struct zip_source *zip_source_deflate(struct zip *, + struct zip_source *, + zip_int32_t, int); +void zip_source_error(struct zip_source *, int *, int *); +struct zip_source *zip_source_layered(struct zip *, + struct zip_source *, + zip_source_layered_callback, + void *); +int zip_source_open(struct zip_source *); +struct zip_source *zip_source_pkware(struct zip *, + struct zip_source *, + zip_uint16_t, int, + const char *); +zip_int64_t zip_source_read(struct zip_source *, void *, + zip_uint64_t); +int zip_source_stat(struct zip_source *, struct zip_stat *); +struct zip_source *zip_source_window(struct zip *, struct zip_source *, + zip_uint64_t, zip_uint64_t); /* This function will probably remain private. It is not needed to implement compression/encryption routines. (We should probably rename it to _zip_source_pop.) */ -ZIP_EXTERN(struct zip_source *)zip_source_pop(struct zip_source *); +struct zip_source *zip_source_pop(struct zip_source *); -/* state of change of a file in zip archive */ - -enum zip_state { ZIP_ST_UNCHANGED, ZIP_ST_DELETED, ZIP_ST_REPLACED, - ZIP_ST_ADDED, ZIP_ST_RENAMED }; - /* error source for layered sources */ enum zip_les { ZIP_LES_NONE, ZIP_LES_UPPER, ZIP_LES_LOWER, ZIP_LES_INVAL }; @@ -169,6 +222,28 @@ enum zip_les { ZIP_LES_NONE, ZIP_LES_UPPER, ZIP_LES_LOWER, ZIP_LES_INVAL }; #define ZIP_GPBF_ENCRYPTED 0x0001 /* is encrypted */ #define ZIP_GPBF_DATA_DESCRIPTOR 0x0008 /* crc/size after file data */ #define ZIP_GPBF_STRONG_ENCRYPTION 0x0040 /* uses strong encryption */ +#define ZIP_GPBF_ENCODING_UTF_8 0x0800 /* file name encoding is UTF-8 */ + + +/* extra fields */ +#define ZIP_EF_LOCAL ZIP_FL_LOCAL /* include in local header */ +#define ZIP_EF_CENTRAL ZIP_FL_CENTRAL /* include in central directory */ +#define ZIP_EF_BOTH (ZIP_EF_LOCAL|ZIP_EF_CENTRAL) /* include in both */ + +#define ZIP_FL_FORCE_ZIP64 1024 /* force zip64 extra field (_zip_dirent_write) */ + +#define ZIP_FL_ENCODING_ALL (ZIP_FL_ENC_GUESS|ZIP_FL_ENC_CP437|ZIP_FL_ENC_UTF_8) + + +/* encoding type */ +enum zip_encoding_type { + ZIP_ENCODING_UNKNOWN, /* not yet analyzed */ + ZIP_ENCODING_ASCII, /* plain ASCII */ + ZIP_ENCODING_UTF8_KNOWN, /* is UTF-8 */ + ZIP_ENCODING_UTF8_GUESSED, /* possibly UTF-8 */ + ZIP_ENCODING_CP437, /* Code Page 437 */ + ZIP_ENCODING_ERROR /* should be UTF-8 but isn't */ +}; /* error information */ @@ -181,25 +256,29 @@ struct zip_error { /* zip archive, part of API */ struct zip { - char *zn; /* file name */ - FILE *zp; /* file */ - struct zip_error error; /* error information */ + char *zn; /* file name */ + FILE *zp; /* file */ + unsigned int open_flags; /* flags passed to zip_open */ + struct zip_error error; /* error information */ - unsigned int flags; /* archive global flags */ - unsigned int ch_flags; /* changed archive global flags */ - - char *default_password; /* password used when no other supplied */ - - struct zip_cdir *cdir; /* central directory */ - char *ch_comment; /* changed archive comment */ - int ch_comment_len; /* length of changed zip archive - * comment, -1 if unchanged */ - zip_uint64_t nentry; /* number of entries */ - zip_uint64_t nentry_alloc; /* number of entries allocated */ - struct zip_entry *entry; /* entries */ - int nfile; /* number of opened files within archive */ - int nfile_alloc; /* number of files allocated */ - struct zip_file **file; /* opened files within archive */ + unsigned int flags; /* archive global flags */ + unsigned int ch_flags; /* changed archive global flags */ + + char *default_password; /* password used when no other supplied */ + + struct zip_string *comment_orig; /* archive comment */ + struct zip_string *comment_changes; /* changed archive comment */ + int comment_changed; /* whether archive comment was changed */ + + zip_uint64_t nentry; /* number of entries */ + zip_uint64_t nentry_alloc; /* number of entries allocated */ + struct zip_entry *entry; /* entries */ + + unsigned int nfile; /* number of opened files within archive */ + unsigned int nfile_alloc; /* number of files allocated */ + struct zip_file **file; /* opened files within archive */ + + char *tempdir; /* custom temp dir (needed e.g. for OS X sandboxing) */ }; /* file in zip archive, part of API */ @@ -213,37 +292,52 @@ struct zip_file { /* zip archive directory entry (central or local) */ +#define ZIP_DIRENT_COMP_METHOD 0x0001u +#define ZIP_DIRENT_FILENAME 0x0002u +#define ZIP_DIRENT_COMMENT 0x0004u +#define ZIP_DIRENT_EXTRA_FIELD 0x0008u +#define ZIP_DIRENT_ALL 0xffffu + struct zip_dirent { - unsigned short version_madeby; /* (c) version of creator */ - unsigned short version_needed; /* (cl) version needed to extract */ - unsigned short bitflags; /* (cl) general purpose bit flag */ - unsigned short comp_method; /* (cl) compression method used */ - time_t last_mod; /* (cl) time of last modification */ - unsigned int crc; /* (cl) CRC-32 of uncompressed data */ - unsigned int comp_size; /* (cl) size of commpressed data */ - unsigned int uncomp_size; /* (cl) size of uncommpressed data */ - char *filename; /* (cl) file name (NUL-terminated) */ - unsigned short filename_len; /* (cl) length of filename (w/o NUL) */ - char *extrafield; /* (cl) extra field */ - unsigned short extrafield_len; /* (cl) length of extra field */ - char *comment; /* (c) file comment */ - unsigned short comment_len; /* (c) length of file comment */ - unsigned short disk_number; /* (c) disk number start */ - unsigned short int_attrib; /* (c) internal file attributes */ - unsigned int ext_attrib; /* (c) external file attributes */ - unsigned int offset; /* (c) offset of local header */ + zip_uint32_t changed; + int local_extra_fields_read; /* whether we already read in local header extra fields */ + int cloned; /* wether this instance is cloned, and thus shares non-changed strings */ + + zip_uint16_t version_madeby; /* (c) version of creator */ + zip_uint16_t version_needed; /* (cl) version needed to extract */ + zip_uint16_t bitflags; /* (cl) general purpose bit flag */ + zip_int32_t comp_method; /* (cl) compression method used (uint16 and ZIP_CM_DEFAULT (-1)) */ + time_t last_mod; /* (cl) time of last modification */ + zip_uint32_t crc; /* (cl) CRC-32 of uncompressed data */ + zip_uint64_t comp_size; /* (cl) size of compressed data */ + zip_uint64_t uncomp_size; /* (cl) size of uncompressed data */ + struct zip_string *filename; /* (cl) file name (NUL-terminated) */ + struct zip_extra_field *extra_fields; /* (cl) extra fields, parsed */ + struct zip_string *comment; /* (c) file comment */ + zip_uint32_t disk_number; /* (c) disk number start */ + zip_uint16_t int_attrib; /* (c) internal file attributes */ + zip_uint32_t ext_attrib; /* (c) external file attributes */ + zip_uint64_t offset; /* (c) offset of local header */ }; /* zip archive central directory */ struct zip_cdir { - struct zip_dirent *entry; /* directory entries */ - int nentry; /* number of entries */ + struct zip_entry *entry; /* directory entries */ + zip_uint64_t nentry; /* number of entries */ + zip_uint64_t nentry_alloc; /* number of entries allocated */ - unsigned int size; /* size of central direcotry */ - unsigned int offset; /* offset of central directory in file */ - char *comment; /* zip archive comment */ - unsigned short comment_len; /* length of zip archive comment */ + off_t size; /* size of central directory */ + off_t offset; /* offset of central directory in file */ + struct zip_string *comment; /* zip archive comment */ +}; + +struct zip_extra_field { + struct zip_extra_field *next; + zip_flags_t flags; /* in local/central header */ + zip_uint16_t id; /* header id */ + zip_uint16_t size; /* data size */ + zip_uint8_t *data; }; @@ -262,13 +356,31 @@ struct zip_source { /* entry in zip archive directory */ struct zip_entry { - enum zip_state state; + struct zip_dirent *orig; + struct zip_dirent *changes; struct zip_source *source; - char *ch_filename; - char *ch_extra; - int ch_extra_len; - char *ch_comment; - int ch_comment_len; + int deleted; +}; + + + +/* file or archive comment, or filename */ + +struct zip_string { + zip_uint8_t *raw; /* raw string */ + zip_uint16_t length; /* length of raw string */ + enum zip_encoding_type encoding; /* autorecognized encoding */ + zip_uint8_t *converted; /* autoconverted string */ + zip_uint32_t converted_length; /* length of converted */ +}; + + + +/* which files to write, and in which order (name is for torrentzip sorting) */ + +struct zip_filelist { + zip_uint64_t idx; + const char *name; }; @@ -279,66 +391,111 @@ extern const int _zip_err_type[]; -#define ZIP_ENTRY_DATA_CHANGED(x) \ - ((x)->state == ZIP_ST_REPLACED \ - || (x)->state == ZIP_ST_ADDED) +#define ZIP_ENTRY_CHANGED(e, f) ((e)->changes && ((e)->changes->changed & (f))) + +#define ZIP_ENTRY_DATA_CHANGED(x) ((x)->source != NULL) #define ZIP_IS_RDONLY(za) ((za)->ch_flags & ZIP_AFL_RDONLY) +zip_int64_t _zip_add_entry(struct zip *); + int _zip_cdir_compute_crc(struct zip *, uLong *); void _zip_cdir_free(struct zip_cdir *); -int _zip_cdir_grow(struct zip_cdir *, int, struct zip_error *); -struct zip_cdir *_zip_cdir_new(int, struct zip_error *); -int _zip_cdir_write(struct zip_cdir *, FILE *, struct zip_error *); +int _zip_cdir_grow(struct zip_cdir *, zip_uint64_t, struct zip_error *); +struct zip_cdir *_zip_cdir_new(zip_uint64_t, struct zip_error *); +zip_int64_t _zip_cdir_write(struct zip *, const struct zip_filelist *, zip_uint64_t, FILE *); +struct zip_dirent *_zip_dirent_clone(const struct zip_dirent *); +void _zip_dirent_free(struct zip_dirent *); void _zip_dirent_finalize(struct zip_dirent *); void _zip_dirent_init(struct zip_dirent *); -int _zip_dirent_read(struct zip_dirent *, FILE *, unsigned char **, - zip_uint32_t *, int, struct zip_error *); +int _zip_dirent_needs_zip64(const struct zip_dirent *, zip_flags_t); +struct zip_dirent *_zip_dirent_new(void); +int _zip_dirent_read(struct zip_dirent *, FILE *, const unsigned char **, + zip_uint64_t *, int, struct zip_error *); +zip_int32_t _zip_dirent_size(FILE *, zip_uint16_t, struct zip_error *); void _zip_dirent_torrent_normalize(struct zip_dirent *); -int _zip_dirent_write(struct zip_dirent *, FILE *, int, struct zip_error *); - -void _zip_entry_free(struct zip_entry *); -void _zip_entry_init(struct zip *, int); -struct zip_entry *_zip_entry_new(struct zip *); +int _zip_dirent_write(struct zip_dirent *, FILE *, zip_flags_t, struct zip_error *); + +struct zip_extra_field *_zip_ef_clone(const struct zip_extra_field *, struct zip_error *); +struct zip_extra_field *_zip_ef_delete_by_id(struct zip_extra_field *, zip_uint16_t, zip_uint16_t, zip_flags_t); +void _zip_ef_free(struct zip_extra_field *); +const zip_uint8_t *_zip_ef_get_by_id(const struct zip_extra_field *, zip_uint16_t *, zip_uint16_t, zip_uint16_t, zip_flags_t, struct zip_error *); +struct zip_extra_field *_zip_ef_merge(struct zip_extra_field *, struct zip_extra_field *); +struct zip_extra_field *_zip_ef_new(zip_uint16_t, zip_uint16_t, const zip_uint8_t *, zip_flags_t); +struct zip_extra_field *_zip_ef_parse(const zip_uint8_t *, zip_uint16_t, zip_flags_t, struct zip_error *); +struct zip_extra_field *_zip_ef_remove_internal(struct zip_extra_field *); +zip_uint16_t _zip_ef_size(const struct zip_extra_field *, zip_flags_t); +void _zip_ef_write(const struct zip_extra_field *, zip_flags_t, FILE *); + +void _zip_entry_finalize(struct zip_entry *); +void _zip_entry_init(struct zip_entry *); void _zip_error_clear(struct zip_error *); -void _zip_error_copy(struct zip_error *, struct zip_error *); +void _zip_error_copy(struct zip_error *, const struct zip_error *); void _zip_error_fini(struct zip_error *); -void _zip_error_get(struct zip_error *, int *, int *); +void _zip_error_get(const struct zip_error *, int *, int *); void _zip_error_init(struct zip_error *); void _zip_error_set(struct zip_error *, int, int); void _zip_error_set_from_source(struct zip_error *, struct zip_source *); const char *_zip_error_strerror(struct zip_error *); +const zip_uint8_t *_zip_extract_extra_field_by_id(struct zip_error *, zip_uint16_t, int, const zip_uint8_t *, zip_uint16_t, zip_uint16_t *); + +int _zip_file_extra_field_prepare_for_change(struct zip *, zip_uint64_t); int _zip_file_fillbuf(void *, size_t, struct zip_file *); -unsigned int _zip_file_get_offset(struct zip *, int); +zip_uint64_t _zip_file_get_offset(const struct zip *, zip_uint64_t, struct zip_error *); int _zip_filerange_crc(FILE *, off_t, off_t, uLong *, struct zip_error *); -struct zip *_zip_open(const char *, FILE *, int, int, int *); +struct zip_dirent *_zip_get_dirent(struct zip *, zip_uint64_t, zip_flags_t, struct zip_error *); + +enum zip_encoding_type _zip_guess_encoding(struct zip_string *, enum zip_encoding_type); +zip_uint8_t *_zip_cp437_to_utf8(const zip_uint8_t * const, zip_uint32_t, + zip_uint32_t *, struct zip_error *error); + +struct zip *_zip_open(const char *, FILE *, unsigned int, int *); + +int _zip_read_local_ef(struct zip *, zip_uint64_t); struct zip_source *_zip_source_file_or_p(struct zip *, const char *, FILE *, zip_uint64_t, zip_int64_t, int, const struct zip_stat *); struct zip_source *_zip_source_new(struct zip *); - -int _zip_changed(struct zip *, int *); -void _zip_free(struct zip *); -const char *_zip_get_name(struct zip *, zip_uint64_t, int, struct zip_error *); +struct zip_source *_zip_source_zip_new(struct zip *, struct zip *, zip_uint64_t, zip_flags_t, + zip_uint64_t, zip_uint64_t, const char *); + +int _zip_string_equal(const struct zip_string *, const struct zip_string *); +void _zip_string_free(struct zip_string *); +zip_uint32_t _zip_string_crc32(const struct zip_string *); +const zip_uint8_t *_zip_string_get(struct zip_string *, zip_uint32_t *, zip_flags_t, struct zip_error *); +zip_uint16_t _zip_string_length(const struct zip_string *); +struct zip_string *_zip_string_new(const zip_uint8_t *, zip_uint16_t, zip_flags_t, struct zip_error *); +void _zip_string_write(const struct zip_string *, FILE *); + +int _zip_changed(const struct zip *, zip_uint64_t *); +const char *_zip_get_name(struct zip *, zip_uint64_t, zip_flags_t, struct zip_error *); int _zip_local_header_read(struct zip *, int); void *_zip_memdup(const void *, size_t, struct zip_error *); -int _zip_name_locate(struct zip *, const char *, int, struct zip_error *); +zip_int64_t _zip_name_locate(struct zip *, const char *, zip_flags_t, struct zip_error *); struct zip *_zip_new(struct zip_error *); -unsigned short _zip_read2(unsigned char **); -unsigned int _zip_read4(unsigned char **); -zip_int64_t _zip_replace(struct zip *, zip_uint64_t, const char *, - struct zip_source *); -int _zip_set_name(struct zip *, zip_uint64_t, const char *); -void _zip_u2d_time(time_t, unsigned short *, unsigned short *); +zip_uint16_t _zip_read2(const zip_uint8_t **); +zip_uint32_t _zip_read4(const zip_uint8_t **); +zip_uint64_t _zip_read8(const zip_uint8_t **); +zip_uint8_t *_zip_read_data(const zip_uint8_t **, FILE *, size_t, int, struct zip_error *); +zip_int64_t _zip_file_replace(struct zip *, zip_uint64_t, const char *, struct zip_source *, zip_flags_t); +int _zip_set_name(struct zip *, zip_uint64_t, const char *, zip_flags_t); +void _zip_u2d_time(time_t, zip_uint16_t *, zip_uint16_t *); int _zip_unchange(struct zip *, zip_uint64_t, int); void _zip_unchange_data(struct zip_entry *); +void _zip_poke4(zip_uint32_t, zip_uint8_t **); +void _zip_poke8(zip_uint64_t, zip_uint8_t **); +void _zip_write2(zip_uint16_t, FILE *); +void _zip_write4(zip_uint32_t, FILE *); +void _zip_write8(zip_uint64_t, FILE *); + + #endif /* zipint.h */ diff --git a/ext/zip/php_zip.c b/ext/zip/php_zip.c index d3ec27bafe..cd1d7cd425 100644 --- a/ext/zip/php_zip.c +++ b/ext/zip/php_zip.c @@ -30,8 +30,6 @@ #include "ext/pcre/php_pcre.h" #include "ext/standard/php_filestat.h" #include "php_zip.h" -#include "lib/zip.h" -#include "lib/zipint.h" /* zip_open is a macro for renaming libzip zipopen, so we need to use PHP_NAMED_FUNCTION */ static PHP_NAMED_FUNCTION(zif_zip_open); @@ -53,6 +51,24 @@ static PHP_NAMED_FUNCTION(zif_zip_entry_close); #endif #endif +#if PHP_VERSION_ID < 50400 +#define ARG_PATH "s" +#define KEY_ARG_DC +#define KEY_ARG_CC +#else +#define ARG_PATH "p" +#define KEY_ARG_DC , const zend_literal *key +#define KEY_ARG_CC , key +#endif + +#if PHP_VERSION_ID < 50500 +#define TYPE_ARG_DC +#define TYPE_ARG_CC +#else +#define TYPE_ARG_DC , int type +#define TYPE_ARG_CC , type +#endif + /* {{{ Resource le */ static int le_zip_dir; #define le_zip_dir_name "Zip Directory" @@ -154,7 +170,7 @@ static int php_zip_extract_file(struct zip * za, char *dest, char *file, int fil size_t path_cleaned_len; cwd_state new_state; - new_state.cwd = (char*)malloc(1); + new_state.cwd = (char*)emalloc(1); new_state.cwd[0] = '\0'; new_state.cwd_length = 0; @@ -191,7 +207,7 @@ static int php_zip_extract_file(struct zip * za, char *dest, char *file, int fil if (ZIP_OPENBASEDIR_CHECKPATH(file_dirname_fullpath)) { efree(file_dirname_fullpath); efree(file_basename); - free(new_state.cwd); + efree(new_state.cwd); return 0; } } @@ -215,7 +231,7 @@ static int php_zip_extract_file(struct zip * za, char *dest, char *file, int fil efree(file_dirname_fullpath); if (!is_dir_only) { efree(file_basename); - free(new_state.cwd); + efree(new_state.cwd); } return 0; } @@ -224,7 +240,7 @@ static int php_zip_extract_file(struct zip * za, char *dest, char *file, int fil /* it is a standalone directory, job done */ if (is_dir_only) { efree(file_dirname_fullpath); - free(new_state.cwd); + efree(new_state.cwd); return 1; } @@ -232,13 +248,13 @@ static int php_zip_extract_file(struct zip * za, char *dest, char *file, int fil if (!len) { efree(file_dirname_fullpath); efree(file_basename); - free(new_state.cwd); + efree(new_state.cwd); return 0; } else if (len > MAXPATHLEN) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Full extraction path exceed MAXPATHLEN (%i)", MAXPATHLEN); efree(file_dirname_fullpath); efree(file_basename); - free(new_state.cwd); + efree(new_state.cwd); return 0; } @@ -250,7 +266,7 @@ static int php_zip_extract_file(struct zip * za, char *dest, char *file, int fil efree(fullpath); efree(file_dirname_fullpath); efree(file_basename); - free(new_state.cwd); + efree(new_state.cwd); return 0; } @@ -285,7 +301,7 @@ done: efree(fullpath); efree(file_basename); efree(file_dirname_fullpath); - free(new_state.cwd); + efree(new_state.cwd); if (n<0) { return 0; @@ -299,7 +315,6 @@ static int php_zip_add_file(struct zip *za, const char *filename, size_t filenam char *entry_name, size_t entry_name_len, long offset_start, long offset_len TSRMLS_DC) /* {{{ */ { struct zip_source *zs; - int cur_idx; char resolved_path[MAXPATHLEN]; zval exists_flag; @@ -321,25 +336,11 @@ static int php_zip_add_file(struct zip *za, const char *filename, size_t filenam if (!zs) { return -1; } - - cur_idx = zip_name_locate(za, (const char *)entry_name, 0); - /* TODO: fix _zip_replace */ - if (cur_idx<0) { - /* reset the error */ - if (za->error.str) { - _zip_error_fini(&za->error); - } - _zip_error_init(&za->error); - } else { - if (zip_delete(za, cur_idx) == -1) { - zip_source_free(zs); - return -1; - } - } - - if (zip_add(za, entry_name, zs) == -1) { + if (zip_file_add(za, entry_name, zs, ZIP_FL_OVERWRITE) < 0) { + zip_source_free(zs); return -1; } else { + zip_error_clear(za); return 1; } } @@ -417,7 +418,7 @@ static int php_zip_parse_options(zval *options, long *remove_all_path, ze_zip_object *obj = (ze_zip_object*) zend_object_store_get_object(object TSRMLS_CC); \ intern = obj->za; \ if (!intern) { \ - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid or unitialized Zip object"); \ + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid or uninitialized Zip object"); \ RETURN_FALSE; \ } \ } @@ -780,7 +781,11 @@ static const zend_function_entry zip_functions[] = { PHP_FE(zip_entry_name, arginfo_zip_entry_name) PHP_FE(zip_entry_compressedsize, arginfo_zip_entry_compressedsize) PHP_FE(zip_entry_compressionmethod, arginfo_zip_entry_compressionmethod) +#ifdef PHP_FE_END PHP_FE_END +#else + {NULL,NULL,NULL} +#endif }; /* }}} */ @@ -869,7 +874,7 @@ static int php_zip_property_reader(ze_zip_object *obj, zip_prop_handler *hnd, zv } /* }}} */ -static zval **php_zip_get_property_ptr_ptr(zval *object, zval *member, int type, const zend_literal *key TSRMLS_DC) /* {{{ */ +static zval **php_zip_get_property_ptr_ptr(zval *object, zval *member TYPE_ARG_DC KEY_ARG_DC TSRMLS_DC) /* {{{ */ { ze_zip_object *obj; zval tmp_member; @@ -884,24 +889,27 @@ static zval **php_zip_get_property_ptr_ptr(zval *object, zval *member, int type, zval_copy_ctor(&tmp_member); convert_to_string(&tmp_member); member = &tmp_member; +#if PHP_VERSION_ID >= 50400 key = NULL; +#endif } ret = FAILURE; obj = (ze_zip_object *)zend_objects_get_address(object TSRMLS_CC); if (obj->prop_handler != NULL) { +#if PHP_VERSION_ID >= 50400 if (key) { ret = zend_hash_quick_find(obj->prop_handler, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, key->hash_value, (void **) &hnd); - } else { + } else +#endif ret = zend_hash_find(obj->prop_handler, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, (void **) &hnd); - } } if (ret == FAILURE) { std_hnd = zend_get_std_object_handlers(); - retval = std_hnd->get_property_ptr_ptr(object, member, type, key TSRMLS_CC); + retval = std_hnd->get_property_ptr_ptr(object, member TYPE_ARG_CC KEY_ARG_CC TSRMLS_CC); } if (member == &tmp_member) { @@ -911,7 +919,7 @@ static zval **php_zip_get_property_ptr_ptr(zval *object, zval *member, int type, } /* }}} */ -static zval* php_zip_read_property(zval *object, zval *member, int type, const zend_literal *key TSRMLS_DC) /* {{{ */ +static zval* php_zip_read_property(zval *object, zval *member, int type KEY_ARG_DC TSRMLS_DC) /* {{{ */ { ze_zip_object *obj; zval tmp_member; @@ -925,18 +933,21 @@ static zval* php_zip_read_property(zval *object, zval *member, int type, const z zval_copy_ctor(&tmp_member); convert_to_string(&tmp_member); member = &tmp_member; +#if PHP_VERSION_ID >= 50400 key = NULL; +#endif } ret = FAILURE; obj = (ze_zip_object *)zend_objects_get_address(object TSRMLS_CC); if (obj->prop_handler != NULL) { +#if PHP_VERSION_ID >= 50400 if (key) { ret = zend_hash_quick_find(obj->prop_handler, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, key->hash_value, (void **) &hnd); - } else { + } else +#endif ret = zend_hash_find(obj->prop_handler, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, (void **) &hnd); - } } if (ret == SUCCESS) { @@ -949,7 +960,7 @@ static zval* php_zip_read_property(zval *object, zval *member, int type, const z } } else { std_hnd = zend_get_std_object_handlers(); - retval = std_hnd->read_property(object, member, type, key TSRMLS_CC); + retval = std_hnd->read_property(object, member, type KEY_ARG_CC TSRMLS_CC); } if (member == &tmp_member) { @@ -959,7 +970,7 @@ static zval* php_zip_read_property(zval *object, zval *member, int type, const z } /* }}} */ -static int php_zip_has_property(zval *object, zval *member, int type, const zend_literal *key TSRMLS_DC) /* {{{ */ +static int php_zip_has_property(zval *object, zval *member, int type KEY_ARG_DC TSRMLS_DC) /* {{{ */ { ze_zip_object *obj; zval tmp_member; @@ -972,18 +983,21 @@ static int php_zip_has_property(zval *object, zval *member, int type, const zend zval_copy_ctor(&tmp_member); convert_to_string(&tmp_member); member = &tmp_member; +#if PHP_VERSION_ID >= 50400 key = NULL; +#endif } ret = FAILURE; obj = (ze_zip_object *)zend_objects_get_address(object TSRMLS_CC); if (obj->prop_handler != NULL) { +#if PHP_VERSION_ID >= 50400 if (key) { ret = zend_hash_quick_find(obj->prop_handler, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, key->hash_value, (void **) &hnd); - } else { + } else +#endif ret = zend_hash_find(obj->prop_handler, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, (void **) &hnd); - } } if (ret == SUCCESS) { @@ -1005,7 +1019,7 @@ static int php_zip_has_property(zval *object, zval *member, int type, const zend zval_ptr_dtor(&tmp); } else { std_hnd = zend_get_std_object_handlers(); - retval = std_hnd->has_property(object, member, type, key TSRMLS_CC); + retval = std_hnd->has_property(object, member, type KEY_ARG_CC TSRMLS_CC); } if (member == &tmp_member) { @@ -1059,7 +1073,8 @@ static void php_zip_object_free_storage(void *object TSRMLS_DC) /* {{{ */ } if (intern->za) { if (zip_close(intern->za) != 0) { - _zip_free(intern->za); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot destroy the zip context"); + return; } intern->za = NULL; } @@ -1096,6 +1111,9 @@ static void php_zip_object_free_storage(void *object TSRMLS_DC) /* {{{ */ static zend_object_value php_zip_object_new(zend_class_entry *class_type TSRMLS_DC) /* {{{ */ { +#if PHP_VERSION_ID < 50400 + zval *tmp; +#endif ze_zip_object *intern; zend_object_value retval; @@ -1116,8 +1134,13 @@ static zend_object_value php_zip_object_new(zend_class_entry *class_type TSRMLS_ intern->zo.ce = class_type; #endif - object_properties_init(&intern->zo, class_type); +#if PHP_VERSION_ID < 50400 + zend_hash_copy(intern->zo.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, + (void *) &tmp, sizeof(zval *)); +#else + object_properties_init(&intern->zo, class_type); +#endif retval.handle = zend_objects_store_put(intern, NULL, (zend_objects_free_object_storage_t) php_zip_object_free_storage, @@ -1140,7 +1163,7 @@ static void php_zip_free_dir(zend_rsrc_list_entry *rsrc TSRMLS_DC) if (zip_int) { if (zip_int->za) { if (zip_close(zip_int->za) != 0) { - _zip_free(zip_int->za); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot destroy the zip context"); } zip_int->za = NULL; } @@ -1159,13 +1182,7 @@ static void php_zip_free_entry(zend_rsrc_list_entry *rsrc TSRMLS_DC) if (zr_rsrc) { if (zr_rsrc->zf) { - if (zr_rsrc->zf->za) { - zip_fclose(zr_rsrc->zf); - } else { - if (zr_rsrc->zf->src) - zip_source_free(zr_rsrc->zf->src); - free(zr_rsrc->zf); - } + zip_fclose(zr_rsrc->zf); zr_rsrc->zf = NULL; } efree(zr_rsrc); @@ -1195,7 +1212,7 @@ zend_module_entry zip_module_entry = { NULL, NULL, PHP_MINFO(zip), - PHP_ZIP_VERSION_STRING, + PHP_ZIP_VERSION, STANDARD_MODULE_PROPERTIES }; /* }}} */ @@ -1215,7 +1232,7 @@ static PHP_NAMED_FUNCTION(zif_zip_open) zip_rsrc *rsrc_int; int err = 0; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p", &filename, &filename_len) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, ARG_PATH, &filename, &filename_len) == FAILURE) { return; } @@ -1498,7 +1515,7 @@ static ZIPARCHIVE_METHOD(open) zval *this = getThis(); ze_zip_object *ze_obj = NULL; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|l", &filename, &filename_len, &flags) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, ARG_PATH "|l", &filename, &filename_len, &flags) == FAILURE) { return; } @@ -1523,7 +1540,8 @@ static ZIPARCHIVE_METHOD(open) if (ze_obj->za) { /* we already have an opened zip, free it */ if (zip_close(ze_obj->za) != 0) { - _zip_free(ze_obj->za); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Empty string as source"); + RETURN_FALSE; } ze_obj->za = NULL; } @@ -1543,6 +1561,38 @@ static ZIPARCHIVE_METHOD(open) } /* }}} */ +/* {{{ proto resource ZipArchive::setPassword(string password) +Set the password for the active archive */ +static ZIPARCHIVE_METHOD(setPassword) +{ + struct zip *intern; + zval *this = getThis(); + char *password; + int password_len; + + if (!this) { + RETURN_FALSE; + } + + ZIP_FROM_OBJECT(intern, this); + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &password, &password_len) == FAILURE) { + return; + } + + if (password_len < 1) { + RETURN_FALSE; + } else { + int res = zip_set_default_password(intern, (const char *)password); + if (res == 0) { + RETURN_TRUE; + } else { + RETURN_FALSE; + } + } +} +/* }}} */ + /* {{{ proto bool ZipArchive::close() close the zip archive */ static ZIPARCHIVE_METHOD(close) @@ -1552,7 +1602,7 @@ static ZIPARCHIVE_METHOD(close) ze_zip_object *ze_obj; if (!this) { - RETURN_FALSE; + RETURN_FALSE; } ZIP_FROM_OBJECT(intern, this); @@ -1560,7 +1610,7 @@ static ZIPARCHIVE_METHOD(close) ze_obj = (ze_zip_object*) zend_object_store_get_object(this TSRMLS_CC); if (zip_close(intern)) { - RETURN_FALSE; + zip_discard(intern); } efree(ze_obj->filename); @@ -1637,6 +1687,7 @@ static ZIPARCHIVE_METHOD(addEmptyDir) if (zip_add_dir(intern, (const char *)s) == -1) { RETVAL_FALSE; } + zip_error_clear(intern); RETVAL_TRUE; } @@ -1654,7 +1705,7 @@ static void php_zip_add_from_pattern(INTERNAL_FUNCTION_PARAMETERS, int type) /* char *path = NULL; char *remove_path = NULL; char *add_path = NULL; - int pattern_len, add_path_len = 0, remove_path_len = 0, path_len = 0; + int pattern_len, add_path_len, remove_path_len = 0, path_len = 0; long remove_all_path = 0; long flags = 0; zval *options = NULL; @@ -1667,12 +1718,12 @@ static void php_zip_add_from_pattern(INTERNAL_FUNCTION_PARAMETERS, int type) /* ZIP_FROM_OBJECT(intern, this); /* 1 == glob, 2==pcre */ if (type == 1) { - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|la", + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, ARG_PATH "|la", &pattern, &pattern_len, &flags, &options) == FAILURE) { return; } } else { - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|sa", + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, ARG_PATH "|sa", &pattern, &pattern_len, &path, &path_len, &options) == FAILURE) { return; } @@ -1703,13 +1754,12 @@ static void php_zip_add_from_pattern(INTERNAL_FUNCTION_PARAMETERS, int type) /* zval **zval_file = NULL; for (i = 0; i < found; i++) { - char *file, *file_stripped, *entry_name; + char *file_stripped, *entry_name; size_t entry_name_len, file_stripped_len; char entry_name_buf[MAXPATHLEN]; char *basename = NULL; if (zend_hash_index_find(Z_ARRVAL_P(return_value), i, (void **) &zval_file) == SUCCESS) { - file = Z_STRVAL_PP(zval_file); if (remove_all_path) { php_basename(Z_STRVAL_PP(zval_file), Z_STRLEN_PP(zval_file), NULL, 0, &basename, (size_t *)&file_stripped_len TSRMLS_CC); @@ -1786,7 +1836,7 @@ static ZIPARCHIVE_METHOD(addFile) ZIP_FROM_OBJECT(intern, this); - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|sll", + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, ARG_PATH "|sll", &filename, &filename_len, &entry_name, &entry_name_len, &offset_start, &offset_len) == FAILURE) { return; } @@ -1856,16 +1906,18 @@ static ZIPARCHIVE_METHOD(addFromString) /* TODO: fix _zip_replace */ if (cur_idx >= 0) { if (zip_delete(intern, cur_idx) == -1) { - goto fail; + zip_source_free(zs); + RETURN_FALSE; } } - if (zip_add(intern, name, zs) != -1) { + if (zip_add(intern, name, zs) == -1) { + zip_source_free(zs); + RETURN_FALSE; + } else { + zip_error_clear(intern); RETURN_TRUE; } -fail: - zip_source_free(zs); - RETURN_FALSE; } /* }}} */ @@ -1886,7 +1938,7 @@ static ZIPARCHIVE_METHOD(statName) ZIP_FROM_OBJECT(intern, this); - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|l", + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, ARG_PATH "|l", &name, &name_len, &flags) == FAILURE) { return; } @@ -1942,7 +1994,7 @@ static ZIPARCHIVE_METHOD(locateName) ZIP_FROM_OBJECT(intern, this); - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|l", + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, ARG_PATH "|l", &name, &name_len, &flags) == FAILURE) { return; } @@ -2522,7 +2574,7 @@ static void php_zip_get_from(INTERNAL_FUNCTION_PARAMETERS, int type) /* {{{ */ ZIP_FROM_OBJECT(intern, this); if (type == 1) { - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|ll", &filename, &filename_len, &len, &flags) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, ARG_PATH "|ll", &filename, &filename_len, &len, &flags) == FAILURE) { return; } PHP_ZIP_STAT_PATH(intern, filename, filename_len, flags, sb); @@ -2598,7 +2650,7 @@ static ZIPARCHIVE_METHOD(getStream) ZIP_FROM_OBJECT(intern, this); - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p", &filename, &filename_len) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, ARG_PATH, &filename, &filename_len) == FAILURE) { return; } @@ -2621,6 +2673,10 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_open, 0, 0, 1) ZEND_ARG_INFO(0, flags) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_setpassword, 0, 0, 1) + ZEND_ARG_INFO(0, password) +ZEND_END_ARG_INFO() + ZEND_BEGIN_ARG_INFO(arginfo_ziparchive__void, 0) ZEND_END_ARG_INFO() @@ -2733,6 +2789,7 @@ ZEND_END_ARG_INFO() /* {{{ ze_zip_object_class_functions */ static const zend_function_entry zip_class_functions[] = { ZIPARCHIVE_ME(open, arginfo_ziparchive_open, ZEND_ACC_PUBLIC) + ZIPARCHIVE_ME(setPassword, arginfo_ziparchive_setpassword, ZEND_ACC_PUBLIC) ZIPARCHIVE_ME(close, arginfo_ziparchive__void, ZEND_ACC_PUBLIC) ZIPARCHIVE_ME(getStatusString, arginfo_ziparchive__void, ZEND_ACC_PUBLIC) ZIPARCHIVE_ME(addEmptyDir, arginfo_ziparchive_addemptydir, ZEND_ACC_PUBLIC) @@ -2875,7 +2932,7 @@ static PHP_MINFO_FUNCTION(zip) php_info_print_table_row(2, "Zip", "enabled"); php_info_print_table_row(2, "Extension Version","$Id$"); - php_info_print_table_row(2, "Zip version", PHP_ZIP_VERSION_STRING); + php_info_print_table_row(2, "Zip version", PHP_ZIP_VERSION); php_info_print_table_row(2, "Libzip version", LIBZIP_VERSION); php_info_print_table_end(); diff --git a/ext/zip/php_zip.h b/ext/zip/php_zip.h index 7dd9ff09d0..c8da941b7a 100644 --- a/ext/zip/php_zip.h +++ b/ext/zip/php_zip.h @@ -28,9 +28,17 @@ extern zend_module_entry zip_module_entry; #include "TSRM.h" #endif +#if defined(HAVE_LIBZIP) +#include <zip.h> +#else #include "lib/zip.h" +#endif -#define PHP_ZIP_VERSION_STRING "1.11.0" +#ifndef ZIP_OVERWRITE +#define ZIP_OVERWRITE ZIP_TRUNCATE +#endif + +#define PHP_ZIP_VERSION "1.12.3" #if ((PHP_MAJOR_VERSION >= 5 && PHP_MINOR_VERSION >= 2) || PHP_MAJOR_VERSION >= 6) # define PHP_ZIP_USE_OO 1 @@ -67,8 +75,9 @@ typedef struct _ze_zip_read_rsrc { } zip_read_rsrc; #ifdef PHP_ZIP_USE_OO -#define ZIPARCHIVE_ME(name, arg_info, flags) ZEND_FENTRY(name, c_ziparchive_ ##name, arg_info, flags) -#define ZIPARCHIVE_METHOD(name) ZEND_NAMED_FUNCTION(c_ziparchive_##name) +#define ZIPARCHIVE_ME(name, arg_info, flags) {#name, c_ziparchive_ ##name, arg_info,(zend_uint) (sizeof(arg_info)/sizeof(struct _zend_arg_info)-1), flags }, +#define ZIPARCHIVE_METHOD(name) ZEND_NAMED_FUNCTION(c_ziparchive_ ##name) + /* Extends zend object */ typedef struct _ze_zip_object { @@ -81,8 +90,8 @@ typedef struct _ze_zip_object { int filename_len; } ze_zip_object; -php_stream *php_stream_zip_opener(php_stream_wrapper *wrapper, char *path, char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC); -php_stream *php_stream_zip_open(char *filename, char *path, char *mode STREAMS_DC TSRMLS_DC); +php_stream *php_stream_zip_opener(php_stream_wrapper *wrapper, const char *path, const char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC); +php_stream *php_stream_zip_open(const char *filename, const char *path, const char *mode STREAMS_DC TSRMLS_DC); extern php_stream_wrapper php_stream_zip_wrapper; #endif diff --git a/ext/zip/tests/bug38943.inc b/ext/zip/tests/bug38943.inc new file mode 100644 index 0000000000..a6f45e8294 --- /dev/null +++ b/ext/zip/tests/bug38943.inc @@ -0,0 +1,16 @@ +<?php +class myZip extends ZipArchive { + private $test = 0; + public $testp = 1; + private $testarray = array(); + + public function __construct() { + $this->testarray[] = 1; + var_dump($this->testarray); + } +} + +$z = new myZip; +$z->testp = "foobar"; +var_dump($z); + diff --git a/ext/zip/tests/bug38943_2.phpt b/ext/zip/tests/bug38943_2.phpt new file mode 100644 index 0000000000..bdbad94517 --- /dev/null +++ b/ext/zip/tests/bug38943_2.phpt @@ -0,0 +1,38 @@ +--TEST-- +#38943, properties in extended class cannot be set (5.3) +--SKIPIF-- +<?php +/* $Id: bug38943_2.phpt 271800 2008-12-24 11:28:25Z pajoye $ */ +if(!extension_loaded('zip')) die('skip'); +if (version_compare(PHP_VERSION, "5.3", "<")) die('skip test for5.3+ only'); +?> +--FILE-- +<?php +include 'bug38943.inc'; +?> +--EXPECTF-- +array(1) { + [0]=> + int(1) +} +object(myZip)#1 (%d) { + ["test":"myZip":private]=> + int(0) + ["testp"]=> + string(6) "foobar" + ["testarray":"myZip":private]=> + array(1) { + [0]=> + int(1) + } + ["status"]=> + int(0) + ["statusSys"]=> + int(0) + ["numFiles"]=> + int(0) + ["filename"]=> + string(0) "" + ["comment"]=> + string(0) "" +} diff --git a/ext/zip/tests/doubleclose.phpt b/ext/zip/tests/doubleclose.phpt new file mode 100644 index 0000000000..abc62c8434 --- /dev/null +++ b/ext/zip/tests/doubleclose.phpt @@ -0,0 +1,43 @@ +--TEST-- +close() called twice +--SKIPIF-- +<?php +if(!extension_loaded('zip')) die('skip'); +?> +--FILE-- +<?php + +echo "Procedural\n"; +$zip = zip_open(dirname(__FILE__) . '/test.zip'); +if (!is_resource($zip)) { + die("Failure"); + } +var_dump(zip_close($zip)); +var_dump(zip_close($zip)); + +echo "Object\n"; +$zip = new ZipArchive(); +if (!$zip->open(dirname(__FILE__) . '/test.zip')) { + die('Failure'); +} +if ($zip->status == ZIPARCHIVE::ER_OK) { + var_dump($zip->close()); + var_dump($zip->close()); +} else { + die("Failure"); +} + +?> +Done +--EXPECTF-- +Procedural +NULL + +Warning: zip_close(): %i is not a valid Zip Directory resource in %s +bool(false) +Object +bool(true) + +Warning: ZipArchive::close(): Invalid or uninitialized Zip object in %s +bool(false) +Done diff --git a/ext/zip/tests/zip_entry_close.phpt b/ext/zip/tests/zip_entry_close.phpt new file mode 100644 index 0000000000..82b7819054 --- /dev/null +++ b/ext/zip/tests/zip_entry_close.phpt @@ -0,0 +1,24 @@ +--TEST-- +zip_entry_close() function: simple and double call +--SKIPIF-- +<?php +/* $Id$ */ +if(!extension_loaded('zip')) die('skip'); +?> +--FILE-- +<?php +$zip = zip_open(dirname(__FILE__)."/test_procedural.zip"); +$entry = zip_read($zip); +echo "entry_open: "; var_dump(zip_entry_open($zip, $entry, "r")); +echo "entry_close: "; var_dump(zip_entry_close($entry)); +echo "entry_close: "; var_dump(zip_entry_close($entry)); +zip_close($zip); +?> +Done +--EXPECTF-- +entry_open: bool(true) +entry_close: bool(true) +entry_close: +Warning: zip_entry_close(): %d is not a valid Zip Entry resource in %s +bool(false) +Done diff --git a/ext/zip/zip_stream.c b/ext/zip/zip_stream.c index 400edd6e6c..02fbc70f85 100644 --- a/ext/zip/zip_stream.c +++ b/ext/zip/zip_stream.c @@ -1,3 +1,21 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 5 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997-2013 The PHP Group | + +----------------------------------------------------------------------+ + | 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 | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt. | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Author: Piere-Alain Joye <pierre@php.net> | + +----------------------------------------------------------------------+ +*/ + /* $Id$ */ #ifdef HAVE_CONFIG_H # include "config.h" @@ -6,8 +24,6 @@ #if HAVE_ZIP #ifdef ZEND_ENGINE_2 -#include "lib/zip.h" - #include "php_streams.h" #include "ext/standard/file.h" #include "ext/standard/php_string.h" @@ -185,7 +201,7 @@ php_stream_ops php_stream_zipio_ops = { }; /* {{{ php_stream_zip_open */ -php_stream *php_stream_zip_open(char *filename, char *path, char *mode STREAMS_DC TSRMLS_DC) +php_stream *php_stream_zip_open(const char *filename, const char *path, const char *mode STREAMS_DC TSRMLS_DC) { struct zip_file *zf = NULL; int err = 0; @@ -235,8 +251,8 @@ php_stream *php_stream_zip_open(char *filename, char *path, char *mode STREAMS_D /* {{{ php_stream_zip_opener */ php_stream *php_stream_zip_opener(php_stream_wrapper *wrapper, - char *path, - char *mode, + const char *path, + const char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC) diff --git a/ext/zlib/php_zlib.h b/ext/zlib/php_zlib.h index 6b1d0cd80c..3e4b9381e7 100644 --- a/ext/zlib/php_zlib.h +++ b/ext/zlib/php_zlib.h @@ -58,7 +58,7 @@ ZEND_BEGIN_MODULE_GLOBALS(zlib) zend_bool handler_registered; ZEND_END_MODULE_GLOBALS(zlib); -php_stream *php_stream_gzopen(php_stream_wrapper *wrapper, char *path, char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC); +php_stream *php_stream_gzopen(php_stream_wrapper *wrapper, const char *path, const char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC); extern php_stream_ops php_stream_gzio_ops; extern php_stream_wrapper php_stream_gzip_wrapper; extern php_stream_filter_factory php_zlib_filter_factory; diff --git a/ext/zlib/tests/bug65391.phpt b/ext/zlib/tests/bug65391.phpt index 3ba5350810..439473fc5d 100644 --- a/ext/zlib/tests/bug65391.phpt +++ b/ext/zlib/tests/bug65391.phpt @@ -25,4 +25,3 @@ Array [2] => Vary: Accept-Encoding ) Done - diff --git a/ext/zlib/tests/gzseek_basic2.phpt b/ext/zlib/tests/gzseek_basic2.phpt index a815b8ff41..82d305d0fb 100644 --- a/ext/zlib/tests/gzseek_basic2.phpt +++ b/ext/zlib/tests/gzseek_basic2.phpt @@ -8,7 +8,7 @@ if (!extension_loaded("zlib")) { ?> --FILE-- <?php -$f = "temp3.txt.gz"; +$f = "gzseek_basic2.gz"; $h = gzopen($f, 'w'); $str1 = "This is the first line."; $str2 = "This is the second line."; @@ -39,4 +39,4 @@ reading the output file This is the first line. string(40) "0000000000000000000000000000000000000000" This is the second line. -===DONE===
\ No newline at end of file +===DONE=== diff --git a/ext/zlib/tests/gzseek_variation1.phpt b/ext/zlib/tests/gzseek_variation1.phpt index 301b57d151..b260783f11 100644 --- a/ext/zlib/tests/gzseek_variation1.phpt +++ b/ext/zlib/tests/gzseek_variation1.phpt @@ -8,7 +8,7 @@ if (!extension_loaded("zlib")) { ?> --FILE-- <?php -$f = "temp3.txt.gz"; +$f = "gzseek_variation1.gz"; $h = gzopen($f, 'w'); $str1 = "This is the first line."; $str2 = "This is the second line."; @@ -30,4 +30,4 @@ unlink($f); This is the first line. string(40) "0000000000000000000000000000000000000000" This is the second line. -===DONE===
\ No newline at end of file +===DONE=== diff --git a/ext/zlib/tests/gzseek_variation4.phpt b/ext/zlib/tests/gzseek_variation4.phpt index fc641f6c82..3d0cf67ceb 100644 --- a/ext/zlib/tests/gzseek_variation4.phpt +++ b/ext/zlib/tests/gzseek_variation4.phpt @@ -8,7 +8,7 @@ if (!extension_loaded("zlib")) { ?> --FILE-- <?php -$f = "temp3.txt.gz"; +$f = "gzseek_variation5.gz"; $h = gzopen($f, 'w'); $str1 = "This is the first line."; $str2 = "This is the second line."; @@ -39,4 +39,4 @@ reading the output file This is the first line. string(40) "0000000000000000000000000000000000000000" This is the second line. -===DONE===
\ No newline at end of file +===DONE=== diff --git a/ext/zlib/tests/gzseek_variation5.phpt b/ext/zlib/tests/gzseek_variation5.phpt index 0167e204c2..93fb19fdbb 100644 --- a/ext/zlib/tests/gzseek_variation5.phpt +++ b/ext/zlib/tests/gzseek_variation5.phpt @@ -8,7 +8,7 @@ if (!extension_loaded("zlib")) { ?> --FILE-- <?php -$f = "temp3.txt.gz"; +$f = "gzseek_variation5.gz"; $h = gzopen($f, 'w'); $str1 = "This is the first line."; $str2 = "This is the second line."; @@ -39,4 +39,4 @@ reading the output file This is the first line. string(40) "0000000000000000000000000000000000000000" This is the second line. -===DONE===
\ No newline at end of file +===DONE=== diff --git a/ext/zlib/tests/gzseek_variation7.phpt b/ext/zlib/tests/gzseek_variation7.phpt index aab0834652..a365272ba2 100644 --- a/ext/zlib/tests/gzseek_variation7.phpt +++ b/ext/zlib/tests/gzseek_variation7.phpt @@ -8,7 +8,7 @@ if (!extension_loaded("zlib")) { ?> --FILE-- <?php -$f = "temp3.txt.gz"; +$f = "gzseek_variation7.gz"; $h = gzopen($f, 'w'); $str1 = "This is the first line."; $str2 = "This is the second line."; @@ -44,4 +44,4 @@ tell=int(47) reading the output file This is the first line.This is the second line. -===DONE===
\ No newline at end of file +===DONE=== diff --git a/ext/zlib/zlib_fopen_wrapper.c b/ext/zlib/zlib_fopen_wrapper.c index 1b00eb8713..2fd9dc7766 100644 --- a/ext/zlib/zlib_fopen_wrapper.c +++ b/ext/zlib/zlib_fopen_wrapper.c @@ -106,7 +106,7 @@ php_stream_ops php_stream_gzio_ops = { NULL /* set_option */ }; -php_stream *php_stream_gzopen(php_stream_wrapper *wrapper, char *path, char *mode, int options, +php_stream *php_stream_gzopen(php_stream_wrapper *wrapper, const char *path, const char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC) { struct php_gz_stream_data_t *self; |