diff options
author | Jose <jose@zeroc.com> | 2016-06-15 18:06:00 +0200 |
---|---|---|
committer | Jose <jose@zeroc.com> | 2016-06-15 18:06:00 +0200 |
commit | 99855eefd7419c24e9b204fb851ec95adc581b4e (patch) | |
tree | 0d79a68449d770c3c550b43121c0d6d43f602d14 /php | |
parent | Allow java libraries to override pom scm data (diff) | |
parent | Stack trace test expec files for Linux (diff) | |
download | ice-99855eefd7419c24e9b204fb851ec95adc581b4e.tar.bz2 ice-99855eefd7419c24e9b204fb851ec95adc581b4e.tar.xz ice-99855eefd7419c24e9b204fb851ec95adc581b4e.zip |
Merge branch '3.6-stretch' into 3.6
Diffstat (limited to 'php')
-rw-r--r-- | php/BuildInstructionsWindows.md | 32 | ||||
-rw-r--r-- | php/Makefile | 4 | ||||
-rw-r--r-- | php/config/Make.rules.mak.php | 18 | ||||
-rw-r--r-- | php/config/Make.rules.php | 14 | ||||
-rw-r--r-- | php/src/Makefile | 7 | ||||
-rw-r--r-- | php/src/Makefile.mak | 2 | ||||
-rw-r--r-- | php/src/php5/.depend.mak (renamed from php/src/IcePHP/.depend.mak) | 0 | ||||
-rw-r--r-- | php/src/php5/Communicator.cpp (renamed from php/src/IcePHP/Communicator.cpp) | 0 | ||||
-rw-r--r-- | php/src/php5/Communicator.h (renamed from php/src/IcePHP/Communicator.h) | 0 | ||||
-rw-r--r-- | php/src/php5/Config.h (renamed from php/src/IcePHP/Config.h) | 0 | ||||
-rw-r--r-- | php/src/php5/Connection.cpp (renamed from php/src/IcePHP/Connection.cpp) | 0 | ||||
-rw-r--r-- | php/src/php5/Connection.h (renamed from php/src/IcePHP/Connection.h) | 0 | ||||
-rw-r--r-- | php/src/php5/Endpoint.cpp (renamed from php/src/IcePHP/Endpoint.cpp) | 0 | ||||
-rw-r--r-- | php/src/php5/Endpoint.h (renamed from php/src/IcePHP/Endpoint.h) | 0 | ||||
-rw-r--r-- | php/src/php5/IcePHP.rc (renamed from php/src/IcePHP/IcePHP.rc) | 0 | ||||
-rw-r--r-- | php/src/php5/Init.cpp (renamed from php/src/IcePHP/Init.cpp) | 0 | ||||
-rw-r--r-- | php/src/php5/Logger.cpp (renamed from php/src/IcePHP/Logger.cpp) | 0 | ||||
-rw-r--r-- | php/src/php5/Logger.h (renamed from php/src/IcePHP/Logger.h) | 0 | ||||
-rw-r--r-- | php/src/php5/Makefile (renamed from php/src/IcePHP/Makefile) | 2 | ||||
-rw-r--r-- | php/src/php5/Makefile.mak (renamed from php/src/IcePHP/Makefile.mak) | 16 | ||||
-rw-r--r-- | php/src/php5/Operation.cpp (renamed from php/src/IcePHP/Operation.cpp) | 6 | ||||
-rw-r--r-- | php/src/php5/Operation.h (renamed from php/src/IcePHP/Operation.h) | 0 | ||||
-rw-r--r-- | php/src/php5/Properties.cpp (renamed from php/src/IcePHP/Properties.cpp) | 0 | ||||
-rw-r--r-- | php/src/php5/Properties.h (renamed from php/src/IcePHP/Properties.h) | 0 | ||||
-rw-r--r-- | php/src/php5/Proxy.cpp (renamed from php/src/IcePHP/Proxy.cpp) | 0 | ||||
-rw-r--r-- | php/src/php5/Proxy.h (renamed from php/src/IcePHP/Proxy.h) | 0 | ||||
-rw-r--r-- | php/src/php5/Types.cpp (renamed from php/src/IcePHP/Types.cpp) | 148 | ||||
-rw-r--r-- | php/src/php5/Types.h (renamed from php/src/IcePHP/Types.h) | 16 | ||||
-rw-r--r-- | php/src/php5/Util.cpp (renamed from php/src/IcePHP/Util.cpp) | 0 | ||||
-rw-r--r-- | php/src/php5/Util.h (renamed from php/src/IcePHP/Util.h) | 0 | ||||
-rw-r--r-- | php/src/php7/.depend.mak | 1299 | ||||
-rw-r--r-- | php/src/php7/Communicator.cpp | 1772 | ||||
-rw-r--r-- | php/src/php7/Communicator.h | 60 | ||||
-rw-r--r-- | php/src/php7/Config.h | 122 | ||||
-rw-r--r-- | php/src/php7/Connection.cpp | 755 | ||||
-rw-r--r-- | php/src/php7/Connection.h | 27 | ||||
-rw-r--r-- | php/src/php7/Endpoint.cpp | 537 | ||||
-rw-r--r-- | php/src/php7/Endpoint.h | 27 | ||||
-rw-r--r-- | php/src/php7/IcePHP.rc | 38 | ||||
-rw-r--r-- | php/src/php7/Init.cpp | 287 | ||||
-rw-r--r-- | php/src/php7/Logger.cpp | 323 | ||||
-rw-r--r-- | php/src/php7/Logger.h | 30 | ||||
-rw-r--r-- | php/src/php7/Makefile | 39 | ||||
-rw-r--r-- | php/src/php7/Makefile.mak | 53 | ||||
-rw-r--r-- | php/src/php7/Operation.cpp | 875 | ||||
-rw-r--r-- | php/src/php7/Operation.h | 37 | ||||
-rw-r--r-- | php/src/php7/Properties.cpp | 681 | ||||
-rw-r--r-- | php/src/php7/Properties.h | 38 | ||||
-rw-r--r-- | php/src/php7/Proxy.cpp | 1718 | ||||
-rw-r--r-- | php/src/php7/Proxy.h | 34 | ||||
-rw-r--r-- | php/src/php7/Types.cpp | 3973 | ||||
-rw-r--r-- | php/src/php7/Types.h | 590 | ||||
-rw-r--r-- | php/src/php7/Util.cpp | 972 | ||||
-rw-r--r-- | php/src/php7/Util.h | 188 |
54 files changed, 14628 insertions, 112 deletions
diff --git a/php/BuildInstructionsWindows.md b/php/BuildInstructionsWindows.md index 0399249f283..080138e9a73 100644 --- a/php/BuildInstructionsWindows.md +++ b/php/BuildInstructionsWindows.md @@ -18,38 +18,22 @@ distribution or compile from source yourself. ## Building the PHP Extension -The Ice installer for Windows includes a pre-compiled extension for PHP 5.6 -built with Visual Studio 2012 (Visual C++ 11) and compatible with the "Thread- -safe VC11" distribution of PHP available on [php.net](). We encourage you to use -this extension if possible, together with a compatible Web server. - -> *The Apache binaries provided by the Apache Software Foundation are compiled -with Visual C++ 6 and therefore are not compatible with the Ice for PHP -extension included in our Windows installer. A VC11 build of Apache is available -from alternate sources.* - The most common motivation for compiling the Ice extension yourself is to create -an extension that is compatible with your existing environment, such as when -your Web server or PHP interpreter is built with a different compiler. +an extension that is compatible with your existing environment, such as when your +Web server or PHP interpreter is built with a different compiler. -To build the Ice extension, first download the PHP5 binary archive or Windows +To build the Ice extension, first download the PHP binary archive or Windows installer and install the distribution. -You will also need to download and extract the PHP5 sources (Ice for PHP -requires the PHP header files). Change to the PHP5 source directory and run the +You will also need to download and extract the PHP sources (Ice for PHP requires +the PHP header files). Change to the PHP source directory and run the following commands: > buildconf > configure -You do not need to actually build PHP from source, but these two steps are -necessary to generate header files that are required by the Ice extension. - -If you have not built Ice for C++ from the `cpp` subdirectory then you need to -set the `ICE_HOME` environment variable to the location of your Ice for C++ -installation. For example: - - > set ICE_HOME=C:\Ice +You must built Ice for C++ from the cpp subdirectory, if you have not done so +review cpp\BuildInstructionsWindows.md first. Change to the Ice for PHP source directory: @@ -81,7 +65,7 @@ directive by running the command-line version of PHP with the `-i` option: Review the output for a line like this: - extension_dir => C:\php5 => C:\php5 + extension_dir => C:\php => C:\php The directive may also be set to a relative path, such as: diff --git a/php/Makefile b/php/Makefile index 35344832dd5..38f40e98378 100644 --- a/php/Makefile +++ b/php/Makefile @@ -17,6 +17,10 @@ ifneq ($(MAKECMDGOALS),install) SUBDIRS := $(SUBDIRS) test endif +ifeq ($(NOTEST),yes) + SUBDIRS := $(filter-out test, $(SUBDIRS)) +endif + INSTALL_SUBDIRS = $(install_phpdir) $(install_libdir) install:: install-common diff --git a/php/config/Make.rules.mak.php b/php/config/Make.rules.mak.php index b7c3d023144..1a91375aed6 100644 --- a/php/config/Make.rules.mak.php +++ b/php/config/Make.rules.mak.php @@ -26,10 +26,10 @@ prefix = $(PREFIX) OPTIMIZE = yes # -# Specify your C++ compiler. The only value currently supported to -# build IcePHP is VC110. Leave unset for auto-detection. +# Specify your C++ compiler. The only values currently supported to +# build IcePHP are VC110 (PHP 5) and VC140 (PHP 7). # -#CPP_COMPILER = VCxxx +CPP_COMPILER = auto # # Determines whether the extension uses PHP namespaces (requires @@ -105,6 +105,14 @@ install_libdir = $(prefix)\php !include $(top_srcdir)\config\Make.rules.msvc !endif +!if "$(CPP_COMPILER)" == "VC110" +php_version = php5 +!else if "$(CPP_COMPILER)" == "VC140" +php_version = php7 +!else +!error Invalid CPP_COMPILER setting: $(CPP_COMPILER). Must be set to VC110 or VC140. +!endif + libsuff = $(x64suffix) !if "$(OPTIMIZE)" != "yes" @@ -132,9 +140,9 @@ ICE_LDFLAGS = /LIBPATH:"$(ice_dir)\lib$(libsuff)" slicedir = $(ice_dir)\slice !if "$(PHP_ZTS)" == "yes" -PHP_LIB_PREFIX = php5ts +PHP_LIB_PREFIX = $(php_version)ts !else -PHP_LIB_PREFIX = php5 +PHP_LIB_PREFIX = $(php_version) !endif !if "$(OPTIMIZE)" != "yes" diff --git a/php/config/Make.rules.php b/php/config/Make.rules.php index 277be398661..8287ed3067f 100644 --- a/php/config/Make.rules.php +++ b/php/config/Make.rules.php @@ -52,6 +52,11 @@ embedded_runpath ?= yes # #USE_NAMESPACES ?= yes +# +# Use specific PHP version +# +PHP_CONFIG ?= php-config + # ---------------------------------------------------------------------- # Don't change anything below this line! # ---------------------------------------------------------------------- @@ -63,8 +68,8 @@ ice_language = php ice_require_cpp = yes slice_translator = slice2php -ifeq ($(shell php-config --libs /dev/null && echo 0),0) - $(error php-config not found review your PHP installation and ensure php-config is in your PATH) +ifeq ($(shell $(PHP_CONFIG) --libs /dev/null && echo 0),0) + $(error $(PHP_CONFIG) not found review your PHP installation and ensure $(PHP_CONFIG) is in your PATH) endif ifeq ($(shell test -f $(top_srcdir)/config/Make.common.rules && echo 0),0) @@ -80,7 +85,7 @@ ifndef usr_dir_install install_libdir = $(prefix)/php else install_phpdir = $(prefix)/share/php - install_libdir = $(shell php -r "echo(ini_get('extension_dir'));") + install_libdir = $(shell $(PHP_CONFIG) --extension-dir) endif ifdef ice_src_dist @@ -114,10 +119,9 @@ ifneq ($(embedded_runpath_prefix),) runpath_libdir := $(embedded_runpath_prefix)/lib$(lp64suffix) endif -CPPFLAGS = ICECPPFLAGS = -I$(slicedir) SLICE2PHPFLAGS := $(SLICE2PHPFLAGS) $(ICECPPFLAGS) -LDFLAGS = $(LDPLATFORMFLAGS) $(CXXFLAGS) -L$(libdir) +LDFLAGS := $(LDFLAGS) $(LDPLATFORMFLAGS) $(CXXFLAGS) -L$(libdir) ifeq ("$(USE_NAMESPACES)","yes") CPPFLAGS := $(CPPFLAGS) -DICEPHP_USE_NAMESPACES diff --git a/php/src/Makefile b/php/src/Makefile index 7a3c951beec..855f56740d2 100644 --- a/php/src/Makefile +++ b/php/src/Makefile @@ -11,7 +11,12 @@ top_srcdir = .. include $(top_srcdir)/config/Make.rules.php -SUBDIRS = IcePHP + +ifeq ($(shell [ $$($(PHP_CONFIG) --vernum) -lt 70000 ] && echo true),true) +SUBDIRS = php5 +else +SUBDIRS = php7 +endif $(EVERYTHING):: @for subdir in $(SUBDIRS); \ diff --git a/php/src/Makefile.mak b/php/src/Makefile.mak index 4643700e3f6..521843edb0e 100644 --- a/php/src/Makefile.mak +++ b/php/src/Makefile.mak @@ -11,7 +11,7 @@ top_srcdir = .. !include $(top_srcdir)\config\Make.rules.mak.php -SUBDIRS = IcePHP +SUBDIRS = $(php_version) $(EVERYTHING):: @for %i in ( $(SUBDIRS) ) do \ diff --git a/php/src/IcePHP/.depend.mak b/php/src/php5/.depend.mak index 811a3c85864..811a3c85864 100644 --- a/php/src/IcePHP/.depend.mak +++ b/php/src/php5/.depend.mak diff --git a/php/src/IcePHP/Communicator.cpp b/php/src/php5/Communicator.cpp index 2e0e83793a7..2e0e83793a7 100644 --- a/php/src/IcePHP/Communicator.cpp +++ b/php/src/php5/Communicator.cpp diff --git a/php/src/IcePHP/Communicator.h b/php/src/php5/Communicator.h index 30f07d273e1..30f07d273e1 100644 --- a/php/src/IcePHP/Communicator.h +++ b/php/src/php5/Communicator.h diff --git a/php/src/IcePHP/Config.h b/php/src/php5/Config.h index 0c18832f642..0c18832f642 100644 --- a/php/src/IcePHP/Config.h +++ b/php/src/php5/Config.h diff --git a/php/src/IcePHP/Connection.cpp b/php/src/php5/Connection.cpp index c4bab84d404..c4bab84d404 100644 --- a/php/src/IcePHP/Connection.cpp +++ b/php/src/php5/Connection.cpp diff --git a/php/src/IcePHP/Connection.h b/php/src/php5/Connection.h index cfdaef321ae..cfdaef321ae 100644 --- a/php/src/IcePHP/Connection.h +++ b/php/src/php5/Connection.h diff --git a/php/src/IcePHP/Endpoint.cpp b/php/src/php5/Endpoint.cpp index f9f0ca00c26..f9f0ca00c26 100644 --- a/php/src/IcePHP/Endpoint.cpp +++ b/php/src/php5/Endpoint.cpp diff --git a/php/src/IcePHP/Endpoint.h b/php/src/php5/Endpoint.h index 1559c0a89f6..1559c0a89f6 100644 --- a/php/src/IcePHP/Endpoint.h +++ b/php/src/php5/Endpoint.h diff --git a/php/src/IcePHP/IcePHP.rc b/php/src/php5/IcePHP.rc index de4c575714f..de4c575714f 100644 --- a/php/src/IcePHP/IcePHP.rc +++ b/php/src/php5/IcePHP.rc diff --git a/php/src/IcePHP/Init.cpp b/php/src/php5/Init.cpp index fbb397724d8..fbb397724d8 100644 --- a/php/src/IcePHP/Init.cpp +++ b/php/src/php5/Init.cpp diff --git a/php/src/IcePHP/Logger.cpp b/php/src/php5/Logger.cpp index eb911c71de7..eb911c71de7 100644 --- a/php/src/IcePHP/Logger.cpp +++ b/php/src/php5/Logger.cpp diff --git a/php/src/IcePHP/Logger.h b/php/src/php5/Logger.h index c3ab3c531c0..c3ab3c531c0 100644 --- a/php/src/IcePHP/Logger.h +++ b/php/src/php5/Logger.h diff --git a/php/src/IcePHP/Makefile b/php/src/php5/Makefile index 8f1f7fe3bae..e240186ed0f 100644 --- a/php/src/IcePHP/Makefile +++ b/php/src/php5/Makefile @@ -27,7 +27,7 @@ OBJS = Communicator.o \ include $(top_srcdir)/config/Make.rules.php -CPPFLAGS := -I. $(CPPFLAGS) $(ICE_FLAGS) $(shell php-config --includes) +CPPFLAGS := -I. $(CPPFLAGS) $(ICE_FLAGS) $(shell $(PHP_CONFIG) --includes) LINKWITH := $(ICE_LIBS) $(CXXLIBS) diff --git a/php/src/IcePHP/Makefile.mak b/php/src/php5/Makefile.mak index 2362a1d4b31..1698a2b901c 100644 --- a/php/src/IcePHP/Makefile.mak +++ b/php/src/php5/Makefile.mak @@ -10,7 +10,7 @@ top_srcdir = ..\.. LIBNAME = php_ice$(LIBSUFFIX).lib -DLLNAME = $(libdir)\php_ice$(LIBSUFFIX).dll +DLLNAME = $(libdir)\php_ice$(LIBSUFFIX).dll TARGETS = $(LIBNAME) $(DLLNAME) @@ -25,22 +25,8 @@ OBJS = .\Communicator.obj \ .\Types.obj \ .\Util.obj - -# -# Get Make.common.rules.mak to figure out CPP_COMPILER by setting it -# to "auto" -# -CPP_COMPILER=auto - !include $(top_srcdir)\config\Make.rules.mak.php -# -# Ensure we're using VC110 -# -!if "$(CPP_COMPILER)" != "VC110" -!error Invalid CPP_COMPILER setting: $(CPP_COMPILER). Must be set to VC110. -!endif - CPPFLAGS = -I. -I.. $(CPPFLAGS) $(ICE_CPPFLAGS) $(PHP_CPPFLAGS) !if "$(ARCH)" == "x86" diff --git a/php/src/IcePHP/Operation.cpp b/php/src/php5/Operation.cpp index 164f6003011..6257494386c 100644 --- a/php/src/IcePHP/Operation.cpp +++ b/php/src/php5/Operation.cpp @@ -460,7 +460,7 @@ IcePHP::TypedInvocation::TypedInvocation(const Ice::ObjectPrx& prx, const Commun } bool -IcePHP::TypedInvocation::prepareRequest(int argc, zval** args, Ice::OutputStreamPtr& os, +IcePHP::TypedInvocation::prepareRequest(int argc, zval** args, Ice::OutputStreamPtr& os, pair<const Ice::Byte*, const Ice::Byte*>& params TSRMLS_DC) { // @@ -501,7 +501,7 @@ IcePHP::TypedInvocation::prepareRequest(int argc, zval** args, Ice::OutputStream { ParamInfoPtr info = *p; zval* arg = args[info->pos]; - if((!info->optional || !isUnset(arg TSRMLS_CC)) && !info->type->validate(arg TSRMLS_CC)) + if((!info->optional || !isUnset(arg TSRMLS_CC)) && !info->type->validate(arg, false TSRMLS_CC)) { invalidArgument("invalid value for argument %d in operation `%s'" TSRMLS_CC, info->pos + 1, _op->name.c_str()); @@ -770,7 +770,7 @@ IcePHP::SyncTypedInvocation::invoke(INTERNAL_FUNCTION_PARAMETERS) runtimeError("unable to get arguments" TSRMLS_CC); return; } - + Ice::OutputStreamPtr os; pair<const Ice::Byte*, const Ice::Byte*> params; if(!prepareRequest(ZEND_NUM_ARGS(), *args, os, params TSRMLS_CC)) diff --git a/php/src/IcePHP/Operation.h b/php/src/php5/Operation.h index 91230201bc4..91230201bc4 100644 --- a/php/src/IcePHP/Operation.h +++ b/php/src/php5/Operation.h diff --git a/php/src/IcePHP/Properties.cpp b/php/src/php5/Properties.cpp index 5fad58e39a8..5fad58e39a8 100644 --- a/php/src/IcePHP/Properties.cpp +++ b/php/src/php5/Properties.cpp diff --git a/php/src/IcePHP/Properties.h b/php/src/php5/Properties.h index c4fa8b24e9d..c4fa8b24e9d 100644 --- a/php/src/IcePHP/Properties.h +++ b/php/src/php5/Properties.h diff --git a/php/src/IcePHP/Proxy.cpp b/php/src/php5/Proxy.cpp index b86c15314c9..b86c15314c9 100644 --- a/php/src/IcePHP/Proxy.cpp +++ b/php/src/php5/Proxy.cpp diff --git a/php/src/IcePHP/Proxy.h b/php/src/php5/Proxy.h index 235a427c2f5..235a427c2f5 100644 --- a/php/src/IcePHP/Proxy.h +++ b/php/src/php5/Proxy.h diff --git a/php/src/IcePHP/Types.cpp b/php/src/php5/Types.cpp index 94b7cfd4e2a..563aabba5fb 100644 --- a/php/src/IcePHP/Types.cpp +++ b/php/src/php5/Types.cpp @@ -658,7 +658,7 @@ IcePHP::PrimitiveInfo::getId() const } bool -IcePHP::PrimitiveInfo::validate(zval* zv TSRMLS_DC) +IcePHP::PrimitiveInfo::validate(zval* zv, bool throwException TSRMLS_DC) { switch(kind) { @@ -666,8 +666,11 @@ IcePHP::PrimitiveInfo::validate(zval* zv TSRMLS_DC) { if(Z_TYPE_P(zv) != IS_BOOL) { - string s = zendTypeToString(Z_TYPE_P(zv)); - invalidArgument("expected boolean value but received %s" TSRMLS_CC, s.c_str()); + if(throwException) + { + string s = zendTypeToString(Z_TYPE_P(zv)); + invalidArgument("expected boolean value but received %s" TSRMLS_CC, s.c_str()); + } return false; } break; @@ -677,13 +680,19 @@ IcePHP::PrimitiveInfo::validate(zval* zv TSRMLS_DC) if(Z_TYPE_P(zv) != IS_LONG) { string s = zendTypeToString(Z_TYPE_P(zv)); - invalidArgument("expected byte value but received %s" TSRMLS_CC, s.c_str()); + if(throwException) + { + invalidArgument("expected byte value but received %s" TSRMLS_CC, s.c_str()); + } return false; } long val = Z_LVAL_P(zv); if(val < 0 || val > 255) { - invalidArgument("value %ld is out of range for a byte" TSRMLS_CC, val); + if(throwException) + { + invalidArgument("value %ld is out of range for a byte" TSRMLS_CC, val); + } return false; } break; @@ -693,13 +702,19 @@ IcePHP::PrimitiveInfo::validate(zval* zv TSRMLS_DC) if(Z_TYPE_P(zv) != IS_LONG) { string s = zendTypeToString(Z_TYPE_P(zv)); - invalidArgument("expected short value but received %s" TSRMLS_CC, s.c_str()); + if(throwException) + { + invalidArgument("expected short value but received %s" TSRMLS_CC, s.c_str()); + } return false; } long val = Z_LVAL_P(zv); if(val < SHRT_MIN || val > SHRT_MAX) { - invalidArgument("value %ld is out of range for a short" TSRMLS_CC, val); + if(throwException) + { + invalidArgument("value %ld is out of range for a short" TSRMLS_CC, val); + } return false; } break; @@ -709,13 +724,19 @@ IcePHP::PrimitiveInfo::validate(zval* zv TSRMLS_DC) if(Z_TYPE_P(zv) != IS_LONG) { string s = zendTypeToString(Z_TYPE_P(zv)); - invalidArgument("expected int value but received %s" TSRMLS_CC, s.c_str()); + if(throwException) + { + invalidArgument("expected int value but received %s" TSRMLS_CC, s.c_str()); + } return false; } long val = Z_LVAL_P(zv); if(val < INT_MIN || val > INT_MAX) { - invalidArgument("value %ld is out of range for an int" TSRMLS_CC, val); + if(throwException) + { + invalidArgument("value %ld is out of range for an int" TSRMLS_CC, val); + } return false; } break; @@ -729,7 +750,10 @@ IcePHP::PrimitiveInfo::validate(zval* zv TSRMLS_DC) if(Z_TYPE_P(zv) != IS_LONG && Z_TYPE_P(zv) != IS_STRING) { string s = zendTypeToString(Z_TYPE_P(zv)); - invalidArgument("expected long value but received %s" TSRMLS_CC, s.c_str()); + if(throwException) + { + invalidArgument("expected long value but received %s" TSRMLS_CC, s.c_str()); + } return false; } Ice::Long val; @@ -742,7 +766,10 @@ IcePHP::PrimitiveInfo::validate(zval* zv TSRMLS_DC) string sval(Z_STRVAL_P(zv), Z_STRLEN_P(zv)); if(!IceUtilInternal::stringToInt64(sval, val)) { - invalidArgument("invalid long value `%s'" TSRMLS_CC, Z_STRVAL_P(zv)); + if(throwException) + { + invalidArgument("invalid long value `%s'" TSRMLS_CC, Z_STRVAL_P(zv)); + } return false; } } @@ -753,13 +780,16 @@ IcePHP::PrimitiveInfo::validate(zval* zv TSRMLS_DC) if(Z_TYPE_P(zv) != IS_DOUBLE && Z_TYPE_P(zv) != IS_LONG) { string s = zendTypeToString(Z_TYPE_P(zv)); - invalidArgument("expected float value but received %s" TSRMLS_CC, s.c_str()); + if(throwException) + { + invalidArgument("expected float value but received %s" TSRMLS_CC, s.c_str()); + } return false; } if(Z_TYPE_P(zv) == IS_DOUBLE) { double val = Z_DVAL_P(zv); - return (val <= numeric_limits<float>::max() && val >= -numeric_limits<float>::max()) || + return (val <= numeric_limits<float>::max() && val >= -numeric_limits<float>::max()) || #if defined(_MSC_VER) && (_MSC_VER <= 1700) !_finite(val); #else @@ -773,7 +803,10 @@ IcePHP::PrimitiveInfo::validate(zval* zv TSRMLS_DC) if(Z_TYPE_P(zv) != IS_DOUBLE && Z_TYPE_P(zv) != IS_LONG) { string s = zendTypeToString(Z_TYPE_P(zv)); - invalidArgument("expected double value but received %s" TSRMLS_CC, s.c_str()); + if(throwException) + { + invalidArgument("expected double value but received %s" TSRMLS_CC, s.c_str()); + } return false; } break; @@ -783,7 +816,10 @@ IcePHP::PrimitiveInfo::validate(zval* zv TSRMLS_DC) if(Z_TYPE_P(zv) != IS_STRING && Z_TYPE_P(zv) != IS_NULL) { string s = zendTypeToString(Z_TYPE_P(zv)); - invalidArgument("expected string value but received %s" TSRMLS_CC, s.c_str()); + if(throwException) + { + invalidArgument("expected string value but received %s" TSRMLS_CC, s.c_str()); + } return false; } break; @@ -1045,7 +1081,7 @@ IcePHP::PrimitiveInfo::unmarshal(const Ice::InputStreamPtr& is, const UnmarshalC void IcePHP::PrimitiveInfo::print(zval* zv, IceUtilInternal::Output& out, PrintObjectHistory* TSRMLS_DC) { - if(!validate(zv TSRMLS_CC)) + if(!validate(zv, false TSRMLS_CC)) { out << "<invalid value - expected " << getId() << ">"; return; @@ -1100,7 +1136,7 @@ IcePHP::EnumInfo::getId() const } bool -IcePHP::EnumInfo::validate(zval* zv TSRMLS_DC) +IcePHP::EnumInfo::validate(zval* zv, bool TSRMLS_DC) { if(Z_TYPE_P(zv) == IS_LONG) { @@ -1161,7 +1197,7 @@ IcePHP::EnumInfo::unmarshal(const Ice::InputStreamPtr& is, const UnmarshalCallba void IcePHP::EnumInfo::print(zval* zv, IceUtilInternal::Output& out, PrintObjectHistory* TSRMLS_DC) { - if(!validate(zv TSRMLS_CC)) + if(!validate(zv, false TSRMLS_CC)) { out << "<invalid value - expected " << id << ">"; return; @@ -1309,7 +1345,7 @@ IcePHP::StructInfo::getId() const } bool -IcePHP::StructInfo::validate(zval* zv TSRMLS_DC) +IcePHP::StructInfo::validate(zval* zv, bool throwException TSRMLS_DC) { if(Z_TYPE_P(zv) == IS_NULL) { @@ -1317,8 +1353,11 @@ IcePHP::StructInfo::validate(zval* zv TSRMLS_DC) } else if(Z_TYPE_P(zv) != IS_OBJECT) { - string s = zendTypeToString(Z_TYPE_P(zv)); - invalidArgument("expected struct value of type %s but received %s" TSRMLS_CC, zce->name, s.c_str()); + if(throwException) + { + string s = zendTypeToString(Z_TYPE_P(zv)); + invalidArgument("expected struct value of type %s but received %s" TSRMLS_CC, zce->name, s.c_str()); + } return false; } @@ -1328,7 +1367,10 @@ IcePHP::StructInfo::validate(zval* zv TSRMLS_DC) zend_class_entry* ce = Z_OBJCE_P(zv); if(ce != zce) { - invalidArgument("expected struct value of type %s but received %s" TSRMLS_CC, zce->name, ce->name); + if(throwException) + { + invalidArgument("expected struct value of type %s but received %s" TSRMLS_CC, zce->name, ce->name); + } return false; } @@ -1416,7 +1458,7 @@ IcePHP::StructInfo::marshal(zval* zv, const Ice::OutputStreamPtr& os, ObjectMap* } zval** val = reinterpret_cast<zval**>(data); - if(!member->type->validate(*val TSRMLS_CC)) + if(!member->type->validate(*val, false TSRMLS_CC)) { invalidArgument("invalid value for %s member `%s'" TSRMLS_CC, id.c_str(), member->name.c_str()); throw AbortMarshaling(); @@ -1469,7 +1511,7 @@ IcePHP::StructInfo::unmarshal(const Ice::InputStreamPtr& is, const UnmarshalCall void IcePHP::StructInfo::print(zval* zv, IceUtilInternal::Output& out, PrintObjectHistory* history TSRMLS_DC) { - if(!validate(zv TSRMLS_CC)) + if(!validate(zv, false TSRMLS_CC)) { out << "<invalid value - expected " << id << ">"; return; @@ -1534,7 +1576,7 @@ IcePHP::SequenceInfo::getId() const } bool -IcePHP::SequenceInfo::validate(zval* zv TSRMLS_DC) +IcePHP::SequenceInfo::validate(zval* zv, bool TSRMLS_DC) { return Z_TYPE_P(zv) == IS_NULL || Z_TYPE_P(zv) == IS_ARRAY; } @@ -1611,7 +1653,7 @@ IcePHP::SequenceInfo::marshal(zval* zv, const Ice::OutputStreamPtr& os, ObjectMa while(zend_hash_get_current_data_ex(arr, &data, &pos) != FAILURE) { zval** val = reinterpret_cast<zval**>(data); - if(!elementType->validate(*val TSRMLS_CC)) + if(!elementType->validate(*val, false TSRMLS_CC)) { invalidArgument("invalid value for sequence element `%s'" TSRMLS_CC, id.c_str()); throw AbortMarshaling(); @@ -1668,7 +1710,7 @@ IcePHP::SequenceInfo::unmarshal(const Ice::InputStreamPtr& is, const UnmarshalCa void IcePHP::SequenceInfo::print(zval* zv, IceUtilInternal::Output& out, PrintObjectHistory* history TSRMLS_DC) { - if(!validate(zv TSRMLS_CC)) + if(!validate(zv, false TSRMLS_CC)) { out << "<invalid value - expected " << id << ">"; return; @@ -1745,7 +1787,7 @@ IcePHP::SequenceInfo::marshalPrimitiveSequence(const PrimitiveInfoPtr& pi, zval* while(zend_hash_get_current_data_ex(arr, &data, &pos) != FAILURE) { zval** val = reinterpret_cast<zval**>(data); - if(!pi->validate(*val TSRMLS_CC)) + if(!pi->validate(*val, true TSRMLS_CC)) { throw AbortMarshaling(); } @@ -1767,7 +1809,7 @@ IcePHP::SequenceInfo::marshalPrimitiveSequence(const PrimitiveInfoPtr& pi, zval* while(zend_hash_get_current_data_ex(arr, &data, &pos) != FAILURE) { zval** val = reinterpret_cast<zval**>(data); - if(!pi->validate(*val TSRMLS_CC)) + if(!pi->validate(*val, true TSRMLS_CC)) { throw AbortMarshaling(); } @@ -1787,7 +1829,7 @@ IcePHP::SequenceInfo::marshalPrimitiveSequence(const PrimitiveInfoPtr& pi, zval* while(zend_hash_get_current_data_ex(arr, &data, &pos) != FAILURE) { zval** val = reinterpret_cast<zval**>(data); - if(!pi->validate(*val TSRMLS_CC)) + if(!pi->validate(*val, true TSRMLS_CC)) { throw AbortMarshaling(); } @@ -1807,7 +1849,7 @@ IcePHP::SequenceInfo::marshalPrimitiveSequence(const PrimitiveInfoPtr& pi, zval* while(zend_hash_get_current_data_ex(arr, &data, &pos) != FAILURE) { zval** val = reinterpret_cast<zval**>(data); - if(!pi->validate(*val TSRMLS_CC)) + if(!pi->validate(*val, true TSRMLS_CC)) { throw AbortMarshaling(); } @@ -1827,7 +1869,7 @@ IcePHP::SequenceInfo::marshalPrimitiveSequence(const PrimitiveInfoPtr& pi, zval* while(zend_hash_get_current_data_ex(arr, &data, &pos) != FAILURE) { zval** val = reinterpret_cast<zval**>(data); - if(!pi->validate(*val TSRMLS_CC)) + if(!pi->validate(*val, true TSRMLS_CC)) { throw AbortMarshaling(); } @@ -1860,7 +1902,7 @@ IcePHP::SequenceInfo::marshalPrimitiveSequence(const PrimitiveInfoPtr& pi, zval* while(zend_hash_get_current_data_ex(arr, &data, &pos) != FAILURE) { zval** val = reinterpret_cast<zval**>(data); - if(!pi->validate(*val TSRMLS_CC)) + if(!pi->validate(*val, true TSRMLS_CC)) { throw AbortMarshaling(); } @@ -1891,7 +1933,7 @@ IcePHP::SequenceInfo::marshalPrimitiveSequence(const PrimitiveInfoPtr& pi, zval* while(zend_hash_get_current_data_ex(arr, &data, &pos) != FAILURE) { zval** val = reinterpret_cast<zval**>(data); - if(!pi->validate(*val TSRMLS_CC)) + if(!pi->validate(*val, true TSRMLS_CC)) { throw AbortMarshaling(); } @@ -1922,7 +1964,7 @@ IcePHP::SequenceInfo::marshalPrimitiveSequence(const PrimitiveInfoPtr& pi, zval* while(zend_hash_get_current_data_ex(arr, &data, &pos) != FAILURE) { zval** val = reinterpret_cast<zval**>(data); - if(!pi->validate(*val TSRMLS_CC)) + if(!pi->validate(*val, true TSRMLS_CC)) { throw AbortMarshaling(); } @@ -2094,7 +2136,7 @@ IcePHP::DictionaryInfo::getId() const } bool -IcePHP::DictionaryInfo::validate(zval* zv TSRMLS_DC) +IcePHP::DictionaryInfo::validate(zval* zv, bool TSRMLS_DC) { return Z_TYPE_P(zv) == IS_NULL || Z_TYPE_P(zv) == IS_ARRAY; } @@ -2243,7 +2285,7 @@ IcePHP::DictionaryInfo::marshal(zval* zv, const Ice::OutputStreamPtr& os, Object // // Marshal the key. // - if(!keyType->validate(zkey TSRMLS_CC)) + if(!keyType->validate(zkey, false TSRMLS_CC)) { invalidArgument("invalid key in `%s' element" TSRMLS_CC, id.c_str()); throw AbortMarshaling(); @@ -2253,7 +2295,7 @@ IcePHP::DictionaryInfo::marshal(zval* zv, const Ice::OutputStreamPtr& os, Object // // Marshal the value. // - if(!valueType->validate(*val TSRMLS_CC)) + if(!valueType->validate(*val, false TSRMLS_CC)) { invalidArgument("invalid value in `%s' element" TSRMLS_CC, id.c_str()); throw AbortMarshaling(); @@ -2328,7 +2370,7 @@ IcePHP::DictionaryInfo::unmarshal(const Ice::InputStreamPtr& is, const Unmarshal void IcePHP::DictionaryInfo::print(zval* zv, IceUtilInternal::Output& out, PrintObjectHistory* history TSRMLS_DC) { - if(!validate(zv TSRMLS_CC)) + if(!validate(zv, false TSRMLS_CC)) { out << "<invalid value - expected " << id << ">"; return; @@ -2519,7 +2561,7 @@ IcePHP::ClassInfo::getId() const } bool -IcePHP::ClassInfo::validate(zval* val TSRMLS_DC) +IcePHP::ClassInfo::validate(zval* val, bool TSRMLS_DC) { if(Z_TYPE_P(val) == IS_OBJECT) { @@ -2568,7 +2610,7 @@ IcePHP::ClassInfo::marshal(zval* zv, const Ice::OutputStreamPtr& os, ObjectMap* } assert(Z_TYPE_P(zv) == IS_OBJECT); // validate() should have caught this. - assert(checkClass(Z_OBJCE_P(zv), zce)); // validate() should have caught this. + assert(checkClass(Z_OBJCE_P(zv), const_cast<zend_class_entry*>(zce))); // validate() should have caught this. // // Ice::ObjectWriter is a subclass of Ice::Object that wraps a PHP object for marshaling. @@ -2611,7 +2653,7 @@ IcePHP::ClassInfo::unmarshal(const Ice::InputStreamPtr& is, const UnmarshalCallb void IcePHP::ClassInfo::print(zval* zv, IceUtilInternal::Output& out, PrintObjectHistory* history TSRMLS_DC) { - if(!validate(zv TSRMLS_CC)) + if(!validate(zv, false TSRMLS_CC)) { out << "<invalid value - expected " << id << ">"; return; @@ -2783,14 +2825,17 @@ IcePHP::ProxyInfo::getId() const } bool -IcePHP::ProxyInfo::validate(zval* zv TSRMLS_DC) +IcePHP::ProxyInfo::validate(zval* zv, bool throwException TSRMLS_DC) { if(Z_TYPE_P(zv) != IS_NULL) { if(Z_TYPE_P(zv) != IS_OBJECT || (Z_TYPE_P(zv) == IS_OBJECT && Z_OBJCE_P(zv) != proxyClassEntry)) { - string s = zendTypeToString(Z_TYPE_P(zv)); - invalidArgument("expected proxy value or null but received %s" TSRMLS_CC, s.c_str()); + if(throwException) + { + string s = zendTypeToString(Z_TYPE_P(zv)); + invalidArgument("expected proxy value or null but received %s" TSRMLS_CC, s.c_str()); + } return false; } } @@ -2891,7 +2936,7 @@ IcePHP::ProxyInfo::unmarshal(const Ice::InputStreamPtr& is, const UnmarshalCallb void IcePHP::ProxyInfo::print(zval* zv, IceUtilInternal::Output& out, PrintObjectHistory* TSRMLS_DC) { - if(!validate(zv TSRMLS_CC)) + if(!validate(zv, false TSRMLS_CC)) { out << "<invalid value - expected " << id << ">"; return; @@ -3019,7 +3064,7 @@ IcePHP::ObjectWriter::writeMembers(const Ice::OutputStreamPtr& os, const DataMem continue; } - if(!member->type->validate(*val TSRMLS_CC)) + if(!member->type->validate(*val, false TSRMLS_CC)) { invalidArgument("invalid value for %s member `%s'" TSRMLS_CC, _info->id.c_str(), member->name.c_str()); @@ -3280,10 +3325,14 @@ IcePHP::ExceptionInfo::unmarshal(const Ice::InputStreamPtr& is, const Communicat void IcePHP::ExceptionInfo::print(zval* zv, IceUtilInternal::Output& out TSRMLS_DC) { + out << "exception " << id; + out.sb(); + if(Z_TYPE_P(zv) != IS_OBJECT) { string s = zendTypeToString(Z_TYPE_P(zv)); - invalidArgument("expected exception value of type %s but received %s" TSRMLS_CC, zce->name, s.c_str()); + out << nl << "expected exception value of type " << zce->name << " but received " << s; + out.eb(); return; } @@ -3293,7 +3342,8 @@ IcePHP::ExceptionInfo::print(zval* zv, IceUtilInternal::Output& out TSRMLS_DC) zend_class_entry* ce = Z_OBJCE_P(zv); if(ce != zce) { - invalidArgument("expected exception value of type %s but received %s" TSRMLS_CC, zce->name, ce->name); + out << nl << "expected exception value of type " << zce->name << " but received " << ce->name; + out.eb(); return; } diff --git a/php/src/IcePHP/Types.h b/php/src/php5/Types.h index e540d49ae01..4968b26a160 100644 --- a/php/src/IcePHP/Types.h +++ b/php/src/php5/Types.h @@ -111,7 +111,7 @@ public: virtual std::string getId() const = 0; - virtual bool validate(zval* TSRMLS_DC) = 0; + virtual bool validate(zval*, bool TSRMLS_DC) = 0; virtual bool variableLength() const = 0; virtual int wireSize() const = 0; @@ -150,7 +150,7 @@ public: virtual std::string getId() const; - virtual bool validate(zval* TSRMLS_DC); + virtual bool validate(zval*, bool TSRMLS_DC); virtual bool variableLength() const; virtual int wireSize() const; @@ -189,7 +189,7 @@ public: virtual std::string getId() const; - virtual bool validate(zval* TSRMLS_DC); + virtual bool validate(zval*, bool TSRMLS_DC); virtual bool variableLength() const; virtual int wireSize() const; @@ -235,7 +235,7 @@ public: virtual std::string getId() const; - virtual bool validate(zval* TSRMLS_DC); + virtual bool validate(zval*, bool TSRMLS_DC); virtual bool variableLength() const; virtual int wireSize() const; @@ -275,7 +275,7 @@ public: virtual std::string getId() const; - virtual bool validate(zval* TSRMLS_DC); + virtual bool validate(zval*, bool TSRMLS_DC); virtual bool variableLength() const; virtual int wireSize() const; @@ -315,7 +315,7 @@ public: virtual std::string getId() const; - virtual bool validate(zval* TSRMLS_DC); + virtual bool validate(zval*, bool TSRMLS_DC); virtual bool variableLength() const; virtual int wireSize() const; @@ -388,7 +388,7 @@ public: virtual std::string getId() const; - virtual bool validate(zval* TSRMLS_DC); + virtual bool validate(zval*, bool TSRMLS_DC); virtual bool variableLength() const; virtual int wireSize() const; @@ -440,7 +440,7 @@ public: virtual std::string getId() const; - virtual bool validate(zval* TSRMLS_DC); + virtual bool validate(zval*, bool TSRMLS_DC); virtual bool variableLength() const; virtual int wireSize() const; diff --git a/php/src/IcePHP/Util.cpp b/php/src/php5/Util.cpp index 2d81667eb60..2d81667eb60 100644 --- a/php/src/IcePHP/Util.cpp +++ b/php/src/php5/Util.cpp diff --git a/php/src/IcePHP/Util.h b/php/src/php5/Util.h index 35b2b025c22..35b2b025c22 100644 --- a/php/src/IcePHP/Util.h +++ b/php/src/php5/Util.h diff --git a/php/src/php7/.depend.mak b/php/src/php7/.depend.mak new file mode 100644 index 00000000000..c75a632088d --- /dev/null +++ b/php/src/php7/.depend.mak @@ -0,0 +1,1299 @@ + +Communicator.obj: \ + Communicator.cpp \ + "Communicator.h" \ + "Config.h" \ + "$(ice_cpp_dir)\include\Ice\Ice.h" \ + "$(ice_cpp_dir)\include\IceUtil\PushDisableWarnings.h" \ + "$(ice_cpp_dir)\include\Ice\Config.h" \ + "$(ice_cpp_dir)\include\IceUtil\Config.h" \ + "$(ice_cpp_dir)\include\Ice\DeprecatedStringConverter.h" \ + "$(ice_cpp_dir)\include\Ice\CommunicatorF.h" \ + "$(ice_cpp_dir)\include\Ice\ProxyF.h" \ + "$(ice_cpp_dir)\include\IceUtil\Shared.h" \ + "$(ice_cpp_dir)\include\IceUtil\Atomic.h" \ + "$(ice_cpp_dir)\include\Ice\ProxyHandle.h" \ + "$(ice_cpp_dir)\include\IceUtil\Handle.h" \ + "$(ice_cpp_dir)\include\IceUtil\Exception.h" \ + "$(ice_cpp_dir)\include\Ice\ObjectF.h" \ + "$(ice_cpp_dir)\include\Ice\Handle.h" \ + "$(ice_cpp_dir)\include\Ice\Exception.h" \ + "$(ice_cpp_dir)\include\Ice\Format.h" \ + "$(ice_cpp_dir)\include\Ice\StreamF.h" \ + "$(ice_cpp_dir)\include\Ice\LocalObject.h" \ + "$(ice_cpp_dir)\include\Ice\LocalObjectF.h" \ + "$(ice_cpp_dir)\include\Ice\StreamHelpers.h" \ + "$(ice_cpp_dir)\include\IceUtil\ScopedArray.h" \ + "$(ice_cpp_dir)\include\IceUtil\Iterator.h" \ + "$(ice_cpp_dir)\include\IceUtil\Optional.h" \ + "$(ice_cpp_dir)\include\IceUtil\UndefSysMacros.h" \ + "$(ice_cpp_dir)\include\IceUtil\PopDisableWarnings.h" \ + "$(ice_cpp_dir)\include\IceUtil\StringConverter.h" \ + "$(ice_cpp_dir)\include\Ice\Plugin.h" \ + "$(ice_cpp_dir)\include\Ice\LoggerF.h" \ + "$(ice_cpp_dir)\include\Ice\BuiltinSequences.h" \ + "$(ice_cpp_dir)\include\Ice\Initialize.h" \ + "$(ice_cpp_dir)\include\IceUtil\Timer.h" \ + "$(ice_cpp_dir)\include\IceUtil\Thread.h" \ + "$(ice_cpp_dir)\include\IceUtil\Mutex.h" \ + "$(ice_cpp_dir)\include\IceUtil\Lock.h" \ + "$(ice_cpp_dir)\include\IceUtil\ThreadException.h" \ + "$(ice_cpp_dir)\include\IceUtil\Time.h" \ + "$(ice_cpp_dir)\include\IceUtil\MutexProtocol.h" \ + "$(ice_cpp_dir)\include\IceUtil\Monitor.h" \ + "$(ice_cpp_dir)\include\IceUtil\Cond.h" \ + "$(ice_cpp_dir)\include\Ice\PropertiesF.h" \ + "$(ice_cpp_dir)\include\Ice\Proxy.h" \ + "$(ice_cpp_dir)\include\Ice\ProxyFactoryF.h" \ + "$(ice_cpp_dir)\include\Ice\ConnectionIF.h" \ + "$(ice_cpp_dir)\include\Ice\RequestHandlerF.h" \ + "$(ice_cpp_dir)\include\Ice\EndpointF.h" \ + "$(ice_cpp_dir)\include\Ice\EndpointTypes.h" \ + "$(ice_cpp_dir)\include\Ice\ObjectAdapterF.h" \ + "$(ice_cpp_dir)\include\Ice\ReferenceF.h" \ + "$(ice_cpp_dir)\include\Ice\BatchRequestQueueF.h" \ + "$(ice_cpp_dir)\include\Ice\AsyncResult.h" \ + "$(ice_cpp_dir)\include\IceUtil\UniquePtr.h" \ + "$(ice_cpp_dir)\include\Ice\ConnectionF.h" \ + "$(ice_cpp_dir)\include\Ice\InstanceF.h" \ + "$(ice_cpp_dir)\include\Ice\AsyncResultF.h" \ + "$(ice_cpp_dir)\include\Ice\ObserverHelper.h" \ + "$(ice_cpp_dir)\include\Ice\Instrumentation.h" \ + "$(ice_cpp_dir)\include\Ice\Current.h" \ + "$(ice_cpp_dir)\include\Ice\Identity.h" \ + "$(ice_cpp_dir)\include\Ice\Version.h" \ + "$(ice_cpp_dir)\include\Ice\BasicStream.h" \ + "$(ice_cpp_dir)\include\Ice\Object.h" \ + "$(ice_cpp_dir)\include\Ice\IncomingAsyncF.h" \ + "$(ice_cpp_dir)\include\Ice\ObjectFactoryF.h" \ + "$(ice_cpp_dir)\include\Ice\ObjectFactoryManagerF.h" \ + "$(ice_cpp_dir)\include\Ice\Buffer.h" \ + "$(ice_cpp_dir)\include\Ice\Protocol.h" \ + "$(ice_cpp_dir)\include\Ice\SlicedDataF.h" \ + "$(ice_cpp_dir)\include\Ice\UserExceptionFactory.h" \ + "$(ice_cpp_dir)\include\Ice\FactoryTable.h" \ + "$(ice_cpp_dir)\include\Ice\InstrumentationF.h" \ + "$(ice_cpp_dir)\include\Ice\Dispatcher.h" \ + "$(ice_cpp_dir)\include\Ice\BatchRequestInterceptor.h" \ + "$(ice_cpp_dir)\include\Ice\LocalException.h" \ + "$(ice_cpp_dir)\include\Ice\PropertiesAdmin.h" \ + "$(ice_cpp_dir)\include\Ice\GCObject.h" \ + "$(ice_cpp_dir)\include\IceUtil\MutexPtrLock.h" \ + "$(ice_cpp_dir)\include\Ice\Incoming.h" \ + "$(ice_cpp_dir)\include\Ice\ServantLocatorF.h" \ + "$(ice_cpp_dir)\include\Ice\ServantManagerF.h" \ + "$(ice_cpp_dir)\include\Ice\ResponseHandlerF.h" \ + "$(ice_cpp_dir)\include\Ice\IncomingAsync.h" \ + "$(ice_cpp_dir)\include\Ice\Properties.h" \ + "$(ice_cpp_dir)\include\Ice\Logger.h" \ + "$(ice_cpp_dir)\include\Ice\LoggerUtil.h" \ + "$(ice_cpp_dir)\include\Ice\RemoteLogger.h" \ + "$(ice_cpp_dir)\include\Ice\FactoryTableInit.h" \ + "$(ice_cpp_dir)\include\Ice\DefaultObjectFactory.h" \ + "$(ice_cpp_dir)\include\Ice\ObjectFactory.h" \ + "$(ice_cpp_dir)\include\Ice\Communicator.h" \ + "$(ice_cpp_dir)\include\Ice\RouterF.h" \ + "$(ice_cpp_dir)\include\Ice\LocatorF.h" \ + "$(ice_cpp_dir)\include\Ice\PluginF.h" \ + "$(ice_cpp_dir)\include\Ice\ImplicitContextF.h" \ + "$(ice_cpp_dir)\include\Ice\FacetMap.h" \ + "$(ice_cpp_dir)\include\Ice\CommunicatorAsync.h" \ + "$(ice_cpp_dir)\include\Ice\ObjectAdapter.h" \ + "$(ice_cpp_dir)\include\Ice\Endpoint.h" \ + "$(ice_cpp_dir)\include\Ice\ServantLocator.h" \ + "$(ice_cpp_dir)\include\Ice\SlicedData.h" \ + "$(ice_cpp_dir)\include\Ice\OutgoingAsync.h" \ + "$(ice_cpp_dir)\include\Ice\OutgoingAsyncF.h" \ + "$(ice_cpp_dir)\include\Ice\Process.h" \ + "$(ice_cpp_dir)\include\Ice\Application.h" \ + "$(ice_cpp_dir)\include\Ice\Connection.h" \ + "$(ice_cpp_dir)\include\Ice\ConnectionAsync.h" \ + "$(ice_cpp_dir)\include\Ice\Functional.h" \ + "$(ice_cpp_dir)\include\IceUtil\Functional.h" \ + "$(ice_cpp_dir)\include\Ice\Stream.h" \ + "$(ice_cpp_dir)\include\Ice\ImplicitContext.h" \ + "$(ice_cpp_dir)\include\Ice\Locator.h" \ + "$(ice_cpp_dir)\include\Ice\ProcessF.h" \ + "$(ice_cpp_dir)\include\Ice\Router.h" \ + "$(ice_cpp_dir)\include\Ice\DispatchInterceptor.h" \ + "$(ice_cpp_dir)\include\Ice\NativePropertiesAdmin.h" \ + "$(ice_cpp_dir)\include\Ice\Metrics.h" \ + "$(ice_cpp_dir)\include\Ice\SliceChecksums.h" \ + "$(ice_cpp_dir)\include\Ice\SliceChecksumDict.h" \ + "$(ice_cpp_dir)\include\Ice\Service.h" \ + "$(ice_cpp_dir)\include\Ice\RegisterPlugins.h" \ + "Logger.h" \ + "Properties.h" \ + "Proxy.h" \ + "Types.h" \ + "Operation.h" \ + "$(ice_cpp_dir)\include\IceUtil\OutputUtil.h" \ + "Util.h" \ + "$(ice_cpp_dir)\include\IceUtil\Options.h" \ + "$(ice_cpp_dir)\include\IceUtil\RecMutex.h" \ + "$(ice_cpp_dir)\include\IceUtil\StringUtil.h" \ + +Connection.obj: \ + Connection.cpp \ + "Connection.h" \ + "Config.h" \ + "$(ice_cpp_dir)\include\Ice\Ice.h" \ + "$(ice_cpp_dir)\include\IceUtil\PushDisableWarnings.h" \ + "$(ice_cpp_dir)\include\Ice\Config.h" \ + "$(ice_cpp_dir)\include\IceUtil\Config.h" \ + "$(ice_cpp_dir)\include\Ice\DeprecatedStringConverter.h" \ + "$(ice_cpp_dir)\include\Ice\CommunicatorF.h" \ + "$(ice_cpp_dir)\include\Ice\ProxyF.h" \ + "$(ice_cpp_dir)\include\IceUtil\Shared.h" \ + "$(ice_cpp_dir)\include\IceUtil\Atomic.h" \ + "$(ice_cpp_dir)\include\Ice\ProxyHandle.h" \ + "$(ice_cpp_dir)\include\IceUtil\Handle.h" \ + "$(ice_cpp_dir)\include\IceUtil\Exception.h" \ + "$(ice_cpp_dir)\include\Ice\ObjectF.h" \ + "$(ice_cpp_dir)\include\Ice\Handle.h" \ + "$(ice_cpp_dir)\include\Ice\Exception.h" \ + "$(ice_cpp_dir)\include\Ice\Format.h" \ + "$(ice_cpp_dir)\include\Ice\StreamF.h" \ + "$(ice_cpp_dir)\include\Ice\LocalObject.h" \ + "$(ice_cpp_dir)\include\Ice\LocalObjectF.h" \ + "$(ice_cpp_dir)\include\Ice\StreamHelpers.h" \ + "$(ice_cpp_dir)\include\IceUtil\ScopedArray.h" \ + "$(ice_cpp_dir)\include\IceUtil\Iterator.h" \ + "$(ice_cpp_dir)\include\IceUtil\Optional.h" \ + "$(ice_cpp_dir)\include\IceUtil\UndefSysMacros.h" \ + "$(ice_cpp_dir)\include\IceUtil\PopDisableWarnings.h" \ + "$(ice_cpp_dir)\include\IceUtil\StringConverter.h" \ + "$(ice_cpp_dir)\include\Ice\Plugin.h" \ + "$(ice_cpp_dir)\include\Ice\LoggerF.h" \ + "$(ice_cpp_dir)\include\Ice\BuiltinSequences.h" \ + "$(ice_cpp_dir)\include\Ice\Initialize.h" \ + "$(ice_cpp_dir)\include\IceUtil\Timer.h" \ + "$(ice_cpp_dir)\include\IceUtil\Thread.h" \ + "$(ice_cpp_dir)\include\IceUtil\Mutex.h" \ + "$(ice_cpp_dir)\include\IceUtil\Lock.h" \ + "$(ice_cpp_dir)\include\IceUtil\ThreadException.h" \ + "$(ice_cpp_dir)\include\IceUtil\Time.h" \ + "$(ice_cpp_dir)\include\IceUtil\MutexProtocol.h" \ + "$(ice_cpp_dir)\include\IceUtil\Monitor.h" \ + "$(ice_cpp_dir)\include\IceUtil\Cond.h" \ + "$(ice_cpp_dir)\include\Ice\PropertiesF.h" \ + "$(ice_cpp_dir)\include\Ice\Proxy.h" \ + "$(ice_cpp_dir)\include\Ice\ProxyFactoryF.h" \ + "$(ice_cpp_dir)\include\Ice\ConnectionIF.h" \ + "$(ice_cpp_dir)\include\Ice\RequestHandlerF.h" \ + "$(ice_cpp_dir)\include\Ice\EndpointF.h" \ + "$(ice_cpp_dir)\include\Ice\EndpointTypes.h" \ + "$(ice_cpp_dir)\include\Ice\ObjectAdapterF.h" \ + "$(ice_cpp_dir)\include\Ice\ReferenceF.h" \ + "$(ice_cpp_dir)\include\Ice\BatchRequestQueueF.h" \ + "$(ice_cpp_dir)\include\Ice\AsyncResult.h" \ + "$(ice_cpp_dir)\include\IceUtil\UniquePtr.h" \ + "$(ice_cpp_dir)\include\Ice\ConnectionF.h" \ + "$(ice_cpp_dir)\include\Ice\InstanceF.h" \ + "$(ice_cpp_dir)\include\Ice\AsyncResultF.h" \ + "$(ice_cpp_dir)\include\Ice\ObserverHelper.h" \ + "$(ice_cpp_dir)\include\Ice\Instrumentation.h" \ + "$(ice_cpp_dir)\include\Ice\Current.h" \ + "$(ice_cpp_dir)\include\Ice\Identity.h" \ + "$(ice_cpp_dir)\include\Ice\Version.h" \ + "$(ice_cpp_dir)\include\Ice\BasicStream.h" \ + "$(ice_cpp_dir)\include\Ice\Object.h" \ + "$(ice_cpp_dir)\include\Ice\IncomingAsyncF.h" \ + "$(ice_cpp_dir)\include\Ice\ObjectFactoryF.h" \ + "$(ice_cpp_dir)\include\Ice\ObjectFactoryManagerF.h" \ + "$(ice_cpp_dir)\include\Ice\Buffer.h" \ + "$(ice_cpp_dir)\include\Ice\Protocol.h" \ + "$(ice_cpp_dir)\include\Ice\SlicedDataF.h" \ + "$(ice_cpp_dir)\include\Ice\UserExceptionFactory.h" \ + "$(ice_cpp_dir)\include\Ice\FactoryTable.h" \ + "$(ice_cpp_dir)\include\Ice\InstrumentationF.h" \ + "$(ice_cpp_dir)\include\Ice\Dispatcher.h" \ + "$(ice_cpp_dir)\include\Ice\BatchRequestInterceptor.h" \ + "$(ice_cpp_dir)\include\Ice\LocalException.h" \ + "$(ice_cpp_dir)\include\Ice\PropertiesAdmin.h" \ + "$(ice_cpp_dir)\include\Ice\GCObject.h" \ + "$(ice_cpp_dir)\include\IceUtil\MutexPtrLock.h" \ + "$(ice_cpp_dir)\include\Ice\Incoming.h" \ + "$(ice_cpp_dir)\include\Ice\ServantLocatorF.h" \ + "$(ice_cpp_dir)\include\Ice\ServantManagerF.h" \ + "$(ice_cpp_dir)\include\Ice\ResponseHandlerF.h" \ + "$(ice_cpp_dir)\include\Ice\IncomingAsync.h" \ + "$(ice_cpp_dir)\include\Ice\Properties.h" \ + "$(ice_cpp_dir)\include\Ice\Logger.h" \ + "$(ice_cpp_dir)\include\Ice\LoggerUtil.h" \ + "$(ice_cpp_dir)\include\Ice\RemoteLogger.h" \ + "$(ice_cpp_dir)\include\Ice\FactoryTableInit.h" \ + "$(ice_cpp_dir)\include\Ice\DefaultObjectFactory.h" \ + "$(ice_cpp_dir)\include\Ice\ObjectFactory.h" \ + "$(ice_cpp_dir)\include\Ice\Communicator.h" \ + "$(ice_cpp_dir)\include\Ice\RouterF.h" \ + "$(ice_cpp_dir)\include\Ice\LocatorF.h" \ + "$(ice_cpp_dir)\include\Ice\PluginF.h" \ + "$(ice_cpp_dir)\include\Ice\ImplicitContextF.h" \ + "$(ice_cpp_dir)\include\Ice\FacetMap.h" \ + "$(ice_cpp_dir)\include\Ice\CommunicatorAsync.h" \ + "$(ice_cpp_dir)\include\Ice\ObjectAdapter.h" \ + "$(ice_cpp_dir)\include\Ice\Endpoint.h" \ + "$(ice_cpp_dir)\include\Ice\ServantLocator.h" \ + "$(ice_cpp_dir)\include\Ice\SlicedData.h" \ + "$(ice_cpp_dir)\include\Ice\OutgoingAsync.h" \ + "$(ice_cpp_dir)\include\Ice\OutgoingAsyncF.h" \ + "$(ice_cpp_dir)\include\Ice\Process.h" \ + "$(ice_cpp_dir)\include\Ice\Application.h" \ + "$(ice_cpp_dir)\include\Ice\Connection.h" \ + "$(ice_cpp_dir)\include\Ice\ConnectionAsync.h" \ + "$(ice_cpp_dir)\include\Ice\Functional.h" \ + "$(ice_cpp_dir)\include\IceUtil\Functional.h" \ + "$(ice_cpp_dir)\include\Ice\Stream.h" \ + "$(ice_cpp_dir)\include\Ice\ImplicitContext.h" \ + "$(ice_cpp_dir)\include\Ice\Locator.h" \ + "$(ice_cpp_dir)\include\Ice\ProcessF.h" \ + "$(ice_cpp_dir)\include\Ice\Router.h" \ + "$(ice_cpp_dir)\include\Ice\DispatchInterceptor.h" \ + "$(ice_cpp_dir)\include\Ice\NativePropertiesAdmin.h" \ + "$(ice_cpp_dir)\include\Ice\Metrics.h" \ + "$(ice_cpp_dir)\include\Ice\SliceChecksums.h" \ + "$(ice_cpp_dir)\include\Ice\SliceChecksumDict.h" \ + "$(ice_cpp_dir)\include\Ice\Service.h" \ + "$(ice_cpp_dir)\include\Ice\RegisterPlugins.h" \ + "Endpoint.h" \ + "Types.h" \ + "Communicator.h" \ + "Operation.h" \ + "$(ice_cpp_dir)\include\IceUtil\OutputUtil.h" \ + "Util.h" \ + "$(ice_cpp_dir)\include\IceSSL\IceSSL.h" \ + "$(ice_cpp_dir)\include\IceSSL\Plugin.h" \ + "$(ice_cpp_dir)\include\IceSSL\Config.h" \ + "$(ice_cpp_dir)\include\IceSSL\ConnectionInfo.h" \ + "$(ice_cpp_dir)\include\IceSSL\EndpointInfo.h" \ + +Endpoint.obj: \ + Endpoint.cpp \ + "Endpoint.h" \ + "Config.h" \ + "$(ice_cpp_dir)\include\Ice\Ice.h" \ + "$(ice_cpp_dir)\include\IceUtil\PushDisableWarnings.h" \ + "$(ice_cpp_dir)\include\Ice\Config.h" \ + "$(ice_cpp_dir)\include\IceUtil\Config.h" \ + "$(ice_cpp_dir)\include\Ice\DeprecatedStringConverter.h" \ + "$(ice_cpp_dir)\include\Ice\CommunicatorF.h" \ + "$(ice_cpp_dir)\include\Ice\ProxyF.h" \ + "$(ice_cpp_dir)\include\IceUtil\Shared.h" \ + "$(ice_cpp_dir)\include\IceUtil\Atomic.h" \ + "$(ice_cpp_dir)\include\Ice\ProxyHandle.h" \ + "$(ice_cpp_dir)\include\IceUtil\Handle.h" \ + "$(ice_cpp_dir)\include\IceUtil\Exception.h" \ + "$(ice_cpp_dir)\include\Ice\ObjectF.h" \ + "$(ice_cpp_dir)\include\Ice\Handle.h" \ + "$(ice_cpp_dir)\include\Ice\Exception.h" \ + "$(ice_cpp_dir)\include\Ice\Format.h" \ + "$(ice_cpp_dir)\include\Ice\StreamF.h" \ + "$(ice_cpp_dir)\include\Ice\LocalObject.h" \ + "$(ice_cpp_dir)\include\Ice\LocalObjectF.h" \ + "$(ice_cpp_dir)\include\Ice\StreamHelpers.h" \ + "$(ice_cpp_dir)\include\IceUtil\ScopedArray.h" \ + "$(ice_cpp_dir)\include\IceUtil\Iterator.h" \ + "$(ice_cpp_dir)\include\IceUtil\Optional.h" \ + "$(ice_cpp_dir)\include\IceUtil\UndefSysMacros.h" \ + "$(ice_cpp_dir)\include\IceUtil\PopDisableWarnings.h" \ + "$(ice_cpp_dir)\include\IceUtil\StringConverter.h" \ + "$(ice_cpp_dir)\include\Ice\Plugin.h" \ + "$(ice_cpp_dir)\include\Ice\LoggerF.h" \ + "$(ice_cpp_dir)\include\Ice\BuiltinSequences.h" \ + "$(ice_cpp_dir)\include\Ice\Initialize.h" \ + "$(ice_cpp_dir)\include\IceUtil\Timer.h" \ + "$(ice_cpp_dir)\include\IceUtil\Thread.h" \ + "$(ice_cpp_dir)\include\IceUtil\Mutex.h" \ + "$(ice_cpp_dir)\include\IceUtil\Lock.h" \ + "$(ice_cpp_dir)\include\IceUtil\ThreadException.h" \ + "$(ice_cpp_dir)\include\IceUtil\Time.h" \ + "$(ice_cpp_dir)\include\IceUtil\MutexProtocol.h" \ + "$(ice_cpp_dir)\include\IceUtil\Monitor.h" \ + "$(ice_cpp_dir)\include\IceUtil\Cond.h" \ + "$(ice_cpp_dir)\include\Ice\PropertiesF.h" \ + "$(ice_cpp_dir)\include\Ice\Proxy.h" \ + "$(ice_cpp_dir)\include\Ice\ProxyFactoryF.h" \ + "$(ice_cpp_dir)\include\Ice\ConnectionIF.h" \ + "$(ice_cpp_dir)\include\Ice\RequestHandlerF.h" \ + "$(ice_cpp_dir)\include\Ice\EndpointF.h" \ + "$(ice_cpp_dir)\include\Ice\EndpointTypes.h" \ + "$(ice_cpp_dir)\include\Ice\ObjectAdapterF.h" \ + "$(ice_cpp_dir)\include\Ice\ReferenceF.h" \ + "$(ice_cpp_dir)\include\Ice\BatchRequestQueueF.h" \ + "$(ice_cpp_dir)\include\Ice\AsyncResult.h" \ + "$(ice_cpp_dir)\include\IceUtil\UniquePtr.h" \ + "$(ice_cpp_dir)\include\Ice\ConnectionF.h" \ + "$(ice_cpp_dir)\include\Ice\InstanceF.h" \ + "$(ice_cpp_dir)\include\Ice\AsyncResultF.h" \ + "$(ice_cpp_dir)\include\Ice\ObserverHelper.h" \ + "$(ice_cpp_dir)\include\Ice\Instrumentation.h" \ + "$(ice_cpp_dir)\include\Ice\Current.h" \ + "$(ice_cpp_dir)\include\Ice\Identity.h" \ + "$(ice_cpp_dir)\include\Ice\Version.h" \ + "$(ice_cpp_dir)\include\Ice\BasicStream.h" \ + "$(ice_cpp_dir)\include\Ice\Object.h" \ + "$(ice_cpp_dir)\include\Ice\IncomingAsyncF.h" \ + "$(ice_cpp_dir)\include\Ice\ObjectFactoryF.h" \ + "$(ice_cpp_dir)\include\Ice\ObjectFactoryManagerF.h" \ + "$(ice_cpp_dir)\include\Ice\Buffer.h" \ + "$(ice_cpp_dir)\include\Ice\Protocol.h" \ + "$(ice_cpp_dir)\include\Ice\SlicedDataF.h" \ + "$(ice_cpp_dir)\include\Ice\UserExceptionFactory.h" \ + "$(ice_cpp_dir)\include\Ice\FactoryTable.h" \ + "$(ice_cpp_dir)\include\Ice\InstrumentationF.h" \ + "$(ice_cpp_dir)\include\Ice\Dispatcher.h" \ + "$(ice_cpp_dir)\include\Ice\BatchRequestInterceptor.h" \ + "$(ice_cpp_dir)\include\Ice\LocalException.h" \ + "$(ice_cpp_dir)\include\Ice\PropertiesAdmin.h" \ + "$(ice_cpp_dir)\include\Ice\GCObject.h" \ + "$(ice_cpp_dir)\include\IceUtil\MutexPtrLock.h" \ + "$(ice_cpp_dir)\include\Ice\Incoming.h" \ + "$(ice_cpp_dir)\include\Ice\ServantLocatorF.h" \ + "$(ice_cpp_dir)\include\Ice\ServantManagerF.h" \ + "$(ice_cpp_dir)\include\Ice\ResponseHandlerF.h" \ + "$(ice_cpp_dir)\include\Ice\IncomingAsync.h" \ + "$(ice_cpp_dir)\include\Ice\Properties.h" \ + "$(ice_cpp_dir)\include\Ice\Logger.h" \ + "$(ice_cpp_dir)\include\Ice\LoggerUtil.h" \ + "$(ice_cpp_dir)\include\Ice\RemoteLogger.h" \ + "$(ice_cpp_dir)\include\Ice\FactoryTableInit.h" \ + "$(ice_cpp_dir)\include\Ice\DefaultObjectFactory.h" \ + "$(ice_cpp_dir)\include\Ice\ObjectFactory.h" \ + "$(ice_cpp_dir)\include\Ice\Communicator.h" \ + "$(ice_cpp_dir)\include\Ice\RouterF.h" \ + "$(ice_cpp_dir)\include\Ice\LocatorF.h" \ + "$(ice_cpp_dir)\include\Ice\PluginF.h" \ + "$(ice_cpp_dir)\include\Ice\ImplicitContextF.h" \ + "$(ice_cpp_dir)\include\Ice\FacetMap.h" \ + "$(ice_cpp_dir)\include\Ice\CommunicatorAsync.h" \ + "$(ice_cpp_dir)\include\Ice\ObjectAdapter.h" \ + "$(ice_cpp_dir)\include\Ice\Endpoint.h" \ + "$(ice_cpp_dir)\include\Ice\ServantLocator.h" \ + "$(ice_cpp_dir)\include\Ice\SlicedData.h" \ + "$(ice_cpp_dir)\include\Ice\OutgoingAsync.h" \ + "$(ice_cpp_dir)\include\Ice\OutgoingAsyncF.h" \ + "$(ice_cpp_dir)\include\Ice\Process.h" \ + "$(ice_cpp_dir)\include\Ice\Application.h" \ + "$(ice_cpp_dir)\include\Ice\Connection.h" \ + "$(ice_cpp_dir)\include\Ice\ConnectionAsync.h" \ + "$(ice_cpp_dir)\include\Ice\Functional.h" \ + "$(ice_cpp_dir)\include\IceUtil\Functional.h" \ + "$(ice_cpp_dir)\include\Ice\Stream.h" \ + "$(ice_cpp_dir)\include\Ice\ImplicitContext.h" \ + "$(ice_cpp_dir)\include\Ice\Locator.h" \ + "$(ice_cpp_dir)\include\Ice\ProcessF.h" \ + "$(ice_cpp_dir)\include\Ice\Router.h" \ + "$(ice_cpp_dir)\include\Ice\DispatchInterceptor.h" \ + "$(ice_cpp_dir)\include\Ice\NativePropertiesAdmin.h" \ + "$(ice_cpp_dir)\include\Ice\Metrics.h" \ + "$(ice_cpp_dir)\include\Ice\SliceChecksums.h" \ + "$(ice_cpp_dir)\include\Ice\SliceChecksumDict.h" \ + "$(ice_cpp_dir)\include\Ice\Service.h" \ + "$(ice_cpp_dir)\include\Ice\RegisterPlugins.h" \ + "Util.h" \ + "$(ice_cpp_dir)\include\IceSSL\EndpointInfo.h" \ + +Init.obj: \ + Init.cpp \ + "Communicator.h" \ + "Config.h" \ + "$(ice_cpp_dir)\include\Ice\Ice.h" \ + "$(ice_cpp_dir)\include\IceUtil\PushDisableWarnings.h" \ + "$(ice_cpp_dir)\include\Ice\Config.h" \ + "$(ice_cpp_dir)\include\IceUtil\Config.h" \ + "$(ice_cpp_dir)\include\Ice\DeprecatedStringConverter.h" \ + "$(ice_cpp_dir)\include\Ice\CommunicatorF.h" \ + "$(ice_cpp_dir)\include\Ice\ProxyF.h" \ + "$(ice_cpp_dir)\include\IceUtil\Shared.h" \ + "$(ice_cpp_dir)\include\IceUtil\Atomic.h" \ + "$(ice_cpp_dir)\include\Ice\ProxyHandle.h" \ + "$(ice_cpp_dir)\include\IceUtil\Handle.h" \ + "$(ice_cpp_dir)\include\IceUtil\Exception.h" \ + "$(ice_cpp_dir)\include\Ice\ObjectF.h" \ + "$(ice_cpp_dir)\include\Ice\Handle.h" \ + "$(ice_cpp_dir)\include\Ice\Exception.h" \ + "$(ice_cpp_dir)\include\Ice\Format.h" \ + "$(ice_cpp_dir)\include\Ice\StreamF.h" \ + "$(ice_cpp_dir)\include\Ice\LocalObject.h" \ + "$(ice_cpp_dir)\include\Ice\LocalObjectF.h" \ + "$(ice_cpp_dir)\include\Ice\StreamHelpers.h" \ + "$(ice_cpp_dir)\include\IceUtil\ScopedArray.h" \ + "$(ice_cpp_dir)\include\IceUtil\Iterator.h" \ + "$(ice_cpp_dir)\include\IceUtil\Optional.h" \ + "$(ice_cpp_dir)\include\IceUtil\UndefSysMacros.h" \ + "$(ice_cpp_dir)\include\IceUtil\PopDisableWarnings.h" \ + "$(ice_cpp_dir)\include\IceUtil\StringConverter.h" \ + "$(ice_cpp_dir)\include\Ice\Plugin.h" \ + "$(ice_cpp_dir)\include\Ice\LoggerF.h" \ + "$(ice_cpp_dir)\include\Ice\BuiltinSequences.h" \ + "$(ice_cpp_dir)\include\Ice\Initialize.h" \ + "$(ice_cpp_dir)\include\IceUtil\Timer.h" \ + "$(ice_cpp_dir)\include\IceUtil\Thread.h" \ + "$(ice_cpp_dir)\include\IceUtil\Mutex.h" \ + "$(ice_cpp_dir)\include\IceUtil\Lock.h" \ + "$(ice_cpp_dir)\include\IceUtil\ThreadException.h" \ + "$(ice_cpp_dir)\include\IceUtil\Time.h" \ + "$(ice_cpp_dir)\include\IceUtil\MutexProtocol.h" \ + "$(ice_cpp_dir)\include\IceUtil\Monitor.h" \ + "$(ice_cpp_dir)\include\IceUtil\Cond.h" \ + "$(ice_cpp_dir)\include\Ice\PropertiesF.h" \ + "$(ice_cpp_dir)\include\Ice\Proxy.h" \ + "$(ice_cpp_dir)\include\Ice\ProxyFactoryF.h" \ + "$(ice_cpp_dir)\include\Ice\ConnectionIF.h" \ + "$(ice_cpp_dir)\include\Ice\RequestHandlerF.h" \ + "$(ice_cpp_dir)\include\Ice\EndpointF.h" \ + "$(ice_cpp_dir)\include\Ice\EndpointTypes.h" \ + "$(ice_cpp_dir)\include\Ice\ObjectAdapterF.h" \ + "$(ice_cpp_dir)\include\Ice\ReferenceF.h" \ + "$(ice_cpp_dir)\include\Ice\BatchRequestQueueF.h" \ + "$(ice_cpp_dir)\include\Ice\AsyncResult.h" \ + "$(ice_cpp_dir)\include\IceUtil\UniquePtr.h" \ + "$(ice_cpp_dir)\include\Ice\ConnectionF.h" \ + "$(ice_cpp_dir)\include\Ice\InstanceF.h" \ + "$(ice_cpp_dir)\include\Ice\AsyncResultF.h" \ + "$(ice_cpp_dir)\include\Ice\ObserverHelper.h" \ + "$(ice_cpp_dir)\include\Ice\Instrumentation.h" \ + "$(ice_cpp_dir)\include\Ice\Current.h" \ + "$(ice_cpp_dir)\include\Ice\Identity.h" \ + "$(ice_cpp_dir)\include\Ice\Version.h" \ + "$(ice_cpp_dir)\include\Ice\BasicStream.h" \ + "$(ice_cpp_dir)\include\Ice\Object.h" \ + "$(ice_cpp_dir)\include\Ice\IncomingAsyncF.h" \ + "$(ice_cpp_dir)\include\Ice\ObjectFactoryF.h" \ + "$(ice_cpp_dir)\include\Ice\ObjectFactoryManagerF.h" \ + "$(ice_cpp_dir)\include\Ice\Buffer.h" \ + "$(ice_cpp_dir)\include\Ice\Protocol.h" \ + "$(ice_cpp_dir)\include\Ice\SlicedDataF.h" \ + "$(ice_cpp_dir)\include\Ice\UserExceptionFactory.h" \ + "$(ice_cpp_dir)\include\Ice\FactoryTable.h" \ + "$(ice_cpp_dir)\include\Ice\InstrumentationF.h" \ + "$(ice_cpp_dir)\include\Ice\Dispatcher.h" \ + "$(ice_cpp_dir)\include\Ice\BatchRequestInterceptor.h" \ + "$(ice_cpp_dir)\include\Ice\LocalException.h" \ + "$(ice_cpp_dir)\include\Ice\PropertiesAdmin.h" \ + "$(ice_cpp_dir)\include\Ice\GCObject.h" \ + "$(ice_cpp_dir)\include\IceUtil\MutexPtrLock.h" \ + "$(ice_cpp_dir)\include\Ice\Incoming.h" \ + "$(ice_cpp_dir)\include\Ice\ServantLocatorF.h" \ + "$(ice_cpp_dir)\include\Ice\ServantManagerF.h" \ + "$(ice_cpp_dir)\include\Ice\ResponseHandlerF.h" \ + "$(ice_cpp_dir)\include\Ice\IncomingAsync.h" \ + "$(ice_cpp_dir)\include\Ice\Properties.h" \ + "$(ice_cpp_dir)\include\Ice\Logger.h" \ + "$(ice_cpp_dir)\include\Ice\LoggerUtil.h" \ + "$(ice_cpp_dir)\include\Ice\RemoteLogger.h" \ + "$(ice_cpp_dir)\include\Ice\FactoryTableInit.h" \ + "$(ice_cpp_dir)\include\Ice\DefaultObjectFactory.h" \ + "$(ice_cpp_dir)\include\Ice\ObjectFactory.h" \ + "$(ice_cpp_dir)\include\Ice\Communicator.h" \ + "$(ice_cpp_dir)\include\Ice\RouterF.h" \ + "$(ice_cpp_dir)\include\Ice\LocatorF.h" \ + "$(ice_cpp_dir)\include\Ice\PluginF.h" \ + "$(ice_cpp_dir)\include\Ice\ImplicitContextF.h" \ + "$(ice_cpp_dir)\include\Ice\FacetMap.h" \ + "$(ice_cpp_dir)\include\Ice\CommunicatorAsync.h" \ + "$(ice_cpp_dir)\include\Ice\ObjectAdapter.h" \ + "$(ice_cpp_dir)\include\Ice\Endpoint.h" \ + "$(ice_cpp_dir)\include\Ice\ServantLocator.h" \ + "$(ice_cpp_dir)\include\Ice\SlicedData.h" \ + "$(ice_cpp_dir)\include\Ice\OutgoingAsync.h" \ + "$(ice_cpp_dir)\include\Ice\OutgoingAsyncF.h" \ + "$(ice_cpp_dir)\include\Ice\Process.h" \ + "$(ice_cpp_dir)\include\Ice\Application.h" \ + "$(ice_cpp_dir)\include\Ice\Connection.h" \ + "$(ice_cpp_dir)\include\Ice\ConnectionAsync.h" \ + "$(ice_cpp_dir)\include\Ice\Functional.h" \ + "$(ice_cpp_dir)\include\IceUtil\Functional.h" \ + "$(ice_cpp_dir)\include\Ice\Stream.h" \ + "$(ice_cpp_dir)\include\Ice\ImplicitContext.h" \ + "$(ice_cpp_dir)\include\Ice\Locator.h" \ + "$(ice_cpp_dir)\include\Ice\ProcessF.h" \ + "$(ice_cpp_dir)\include\Ice\Router.h" \ + "$(ice_cpp_dir)\include\Ice\DispatchInterceptor.h" \ + "$(ice_cpp_dir)\include\Ice\NativePropertiesAdmin.h" \ + "$(ice_cpp_dir)\include\Ice\Metrics.h" \ + "$(ice_cpp_dir)\include\Ice\SliceChecksums.h" \ + "$(ice_cpp_dir)\include\Ice\SliceChecksumDict.h" \ + "$(ice_cpp_dir)\include\Ice\Service.h" \ + "$(ice_cpp_dir)\include\Ice\RegisterPlugins.h" \ + "Connection.h" \ + "Endpoint.h" \ + "Logger.h" \ + "Operation.h" \ + "Properties.h" \ + "Proxy.h" \ + "Types.h" \ + "$(ice_cpp_dir)\include\IceUtil\OutputUtil.h" \ + "Util.h" \ + +Logger.obj: \ + Logger.cpp \ + "Logger.h" \ + "Config.h" \ + "$(ice_cpp_dir)\include\Ice\Ice.h" \ + "$(ice_cpp_dir)\include\IceUtil\PushDisableWarnings.h" \ + "$(ice_cpp_dir)\include\Ice\Config.h" \ + "$(ice_cpp_dir)\include\IceUtil\Config.h" \ + "$(ice_cpp_dir)\include\Ice\DeprecatedStringConverter.h" \ + "$(ice_cpp_dir)\include\Ice\CommunicatorF.h" \ + "$(ice_cpp_dir)\include\Ice\ProxyF.h" \ + "$(ice_cpp_dir)\include\IceUtil\Shared.h" \ + "$(ice_cpp_dir)\include\IceUtil\Atomic.h" \ + "$(ice_cpp_dir)\include\Ice\ProxyHandle.h" \ + "$(ice_cpp_dir)\include\IceUtil\Handle.h" \ + "$(ice_cpp_dir)\include\IceUtil\Exception.h" \ + "$(ice_cpp_dir)\include\Ice\ObjectF.h" \ + "$(ice_cpp_dir)\include\Ice\Handle.h" \ + "$(ice_cpp_dir)\include\Ice\Exception.h" \ + "$(ice_cpp_dir)\include\Ice\Format.h" \ + "$(ice_cpp_dir)\include\Ice\StreamF.h" \ + "$(ice_cpp_dir)\include\Ice\LocalObject.h" \ + "$(ice_cpp_dir)\include\Ice\LocalObjectF.h" \ + "$(ice_cpp_dir)\include\Ice\StreamHelpers.h" \ + "$(ice_cpp_dir)\include\IceUtil\ScopedArray.h" \ + "$(ice_cpp_dir)\include\IceUtil\Iterator.h" \ + "$(ice_cpp_dir)\include\IceUtil\Optional.h" \ + "$(ice_cpp_dir)\include\IceUtil\UndefSysMacros.h" \ + "$(ice_cpp_dir)\include\IceUtil\PopDisableWarnings.h" \ + "$(ice_cpp_dir)\include\IceUtil\StringConverter.h" \ + "$(ice_cpp_dir)\include\Ice\Plugin.h" \ + "$(ice_cpp_dir)\include\Ice\LoggerF.h" \ + "$(ice_cpp_dir)\include\Ice\BuiltinSequences.h" \ + "$(ice_cpp_dir)\include\Ice\Initialize.h" \ + "$(ice_cpp_dir)\include\IceUtil\Timer.h" \ + "$(ice_cpp_dir)\include\IceUtil\Thread.h" \ + "$(ice_cpp_dir)\include\IceUtil\Mutex.h" \ + "$(ice_cpp_dir)\include\IceUtil\Lock.h" \ + "$(ice_cpp_dir)\include\IceUtil\ThreadException.h" \ + "$(ice_cpp_dir)\include\IceUtil\Time.h" \ + "$(ice_cpp_dir)\include\IceUtil\MutexProtocol.h" \ + "$(ice_cpp_dir)\include\IceUtil\Monitor.h" \ + "$(ice_cpp_dir)\include\IceUtil\Cond.h" \ + "$(ice_cpp_dir)\include\Ice\PropertiesF.h" \ + "$(ice_cpp_dir)\include\Ice\Proxy.h" \ + "$(ice_cpp_dir)\include\Ice\ProxyFactoryF.h" \ + "$(ice_cpp_dir)\include\Ice\ConnectionIF.h" \ + "$(ice_cpp_dir)\include\Ice\RequestHandlerF.h" \ + "$(ice_cpp_dir)\include\Ice\EndpointF.h" \ + "$(ice_cpp_dir)\include\Ice\EndpointTypes.h" \ + "$(ice_cpp_dir)\include\Ice\ObjectAdapterF.h" \ + "$(ice_cpp_dir)\include\Ice\ReferenceF.h" \ + "$(ice_cpp_dir)\include\Ice\BatchRequestQueueF.h" \ + "$(ice_cpp_dir)\include\Ice\AsyncResult.h" \ + "$(ice_cpp_dir)\include\IceUtil\UniquePtr.h" \ + "$(ice_cpp_dir)\include\Ice\ConnectionF.h" \ + "$(ice_cpp_dir)\include\Ice\InstanceF.h" \ + "$(ice_cpp_dir)\include\Ice\AsyncResultF.h" \ + "$(ice_cpp_dir)\include\Ice\ObserverHelper.h" \ + "$(ice_cpp_dir)\include\Ice\Instrumentation.h" \ + "$(ice_cpp_dir)\include\Ice\Current.h" \ + "$(ice_cpp_dir)\include\Ice\Identity.h" \ + "$(ice_cpp_dir)\include\Ice\Version.h" \ + "$(ice_cpp_dir)\include\Ice\BasicStream.h" \ + "$(ice_cpp_dir)\include\Ice\Object.h" \ + "$(ice_cpp_dir)\include\Ice\IncomingAsyncF.h" \ + "$(ice_cpp_dir)\include\Ice\ObjectFactoryF.h" \ + "$(ice_cpp_dir)\include\Ice\ObjectFactoryManagerF.h" \ + "$(ice_cpp_dir)\include\Ice\Buffer.h" \ + "$(ice_cpp_dir)\include\Ice\Protocol.h" \ + "$(ice_cpp_dir)\include\Ice\SlicedDataF.h" \ + "$(ice_cpp_dir)\include\Ice\UserExceptionFactory.h" \ + "$(ice_cpp_dir)\include\Ice\FactoryTable.h" \ + "$(ice_cpp_dir)\include\Ice\InstrumentationF.h" \ + "$(ice_cpp_dir)\include\Ice\Dispatcher.h" \ + "$(ice_cpp_dir)\include\Ice\BatchRequestInterceptor.h" \ + "$(ice_cpp_dir)\include\Ice\LocalException.h" \ + "$(ice_cpp_dir)\include\Ice\PropertiesAdmin.h" \ + "$(ice_cpp_dir)\include\Ice\GCObject.h" \ + "$(ice_cpp_dir)\include\IceUtil\MutexPtrLock.h" \ + "$(ice_cpp_dir)\include\Ice\Incoming.h" \ + "$(ice_cpp_dir)\include\Ice\ServantLocatorF.h" \ + "$(ice_cpp_dir)\include\Ice\ServantManagerF.h" \ + "$(ice_cpp_dir)\include\Ice\ResponseHandlerF.h" \ + "$(ice_cpp_dir)\include\Ice\IncomingAsync.h" \ + "$(ice_cpp_dir)\include\Ice\Properties.h" \ + "$(ice_cpp_dir)\include\Ice\Logger.h" \ + "$(ice_cpp_dir)\include\Ice\LoggerUtil.h" \ + "$(ice_cpp_dir)\include\Ice\RemoteLogger.h" \ + "$(ice_cpp_dir)\include\Ice\FactoryTableInit.h" \ + "$(ice_cpp_dir)\include\Ice\DefaultObjectFactory.h" \ + "$(ice_cpp_dir)\include\Ice\ObjectFactory.h" \ + "$(ice_cpp_dir)\include\Ice\Communicator.h" \ + "$(ice_cpp_dir)\include\Ice\RouterF.h" \ + "$(ice_cpp_dir)\include\Ice\LocatorF.h" \ + "$(ice_cpp_dir)\include\Ice\PluginF.h" \ + "$(ice_cpp_dir)\include\Ice\ImplicitContextF.h" \ + "$(ice_cpp_dir)\include\Ice\FacetMap.h" \ + "$(ice_cpp_dir)\include\Ice\CommunicatorAsync.h" \ + "$(ice_cpp_dir)\include\Ice\ObjectAdapter.h" \ + "$(ice_cpp_dir)\include\Ice\Endpoint.h" \ + "$(ice_cpp_dir)\include\Ice\ServantLocator.h" \ + "$(ice_cpp_dir)\include\Ice\SlicedData.h" \ + "$(ice_cpp_dir)\include\Ice\OutgoingAsync.h" \ + "$(ice_cpp_dir)\include\Ice\OutgoingAsyncF.h" \ + "$(ice_cpp_dir)\include\Ice\Process.h" \ + "$(ice_cpp_dir)\include\Ice\Application.h" \ + "$(ice_cpp_dir)\include\Ice\Connection.h" \ + "$(ice_cpp_dir)\include\Ice\ConnectionAsync.h" \ + "$(ice_cpp_dir)\include\Ice\Functional.h" \ + "$(ice_cpp_dir)\include\IceUtil\Functional.h" \ + "$(ice_cpp_dir)\include\Ice\Stream.h" \ + "$(ice_cpp_dir)\include\Ice\ImplicitContext.h" \ + "$(ice_cpp_dir)\include\Ice\Locator.h" \ + "$(ice_cpp_dir)\include\Ice\ProcessF.h" \ + "$(ice_cpp_dir)\include\Ice\Router.h" \ + "$(ice_cpp_dir)\include\Ice\DispatchInterceptor.h" \ + "$(ice_cpp_dir)\include\Ice\NativePropertiesAdmin.h" \ + "$(ice_cpp_dir)\include\Ice\Metrics.h" \ + "$(ice_cpp_dir)\include\Ice\SliceChecksums.h" \ + "$(ice_cpp_dir)\include\Ice\SliceChecksumDict.h" \ + "$(ice_cpp_dir)\include\Ice\Service.h" \ + "$(ice_cpp_dir)\include\Ice\RegisterPlugins.h" \ + "Util.h" \ + +Operation.obj: \ + Operation.cpp \ + "Operation.h" \ + "Config.h" \ + "$(ice_cpp_dir)\include\Ice\Ice.h" \ + "$(ice_cpp_dir)\include\IceUtil\PushDisableWarnings.h" \ + "$(ice_cpp_dir)\include\Ice\Config.h" \ + "$(ice_cpp_dir)\include\IceUtil\Config.h" \ + "$(ice_cpp_dir)\include\Ice\DeprecatedStringConverter.h" \ + "$(ice_cpp_dir)\include\Ice\CommunicatorF.h" \ + "$(ice_cpp_dir)\include\Ice\ProxyF.h" \ + "$(ice_cpp_dir)\include\IceUtil\Shared.h" \ + "$(ice_cpp_dir)\include\IceUtil\Atomic.h" \ + "$(ice_cpp_dir)\include\Ice\ProxyHandle.h" \ + "$(ice_cpp_dir)\include\IceUtil\Handle.h" \ + "$(ice_cpp_dir)\include\IceUtil\Exception.h" \ + "$(ice_cpp_dir)\include\Ice\ObjectF.h" \ + "$(ice_cpp_dir)\include\Ice\Handle.h" \ + "$(ice_cpp_dir)\include\Ice\Exception.h" \ + "$(ice_cpp_dir)\include\Ice\Format.h" \ + "$(ice_cpp_dir)\include\Ice\StreamF.h" \ + "$(ice_cpp_dir)\include\Ice\LocalObject.h" \ + "$(ice_cpp_dir)\include\Ice\LocalObjectF.h" \ + "$(ice_cpp_dir)\include\Ice\StreamHelpers.h" \ + "$(ice_cpp_dir)\include\IceUtil\ScopedArray.h" \ + "$(ice_cpp_dir)\include\IceUtil\Iterator.h" \ + "$(ice_cpp_dir)\include\IceUtil\Optional.h" \ + "$(ice_cpp_dir)\include\IceUtil\UndefSysMacros.h" \ + "$(ice_cpp_dir)\include\IceUtil\PopDisableWarnings.h" \ + "$(ice_cpp_dir)\include\IceUtil\StringConverter.h" \ + "$(ice_cpp_dir)\include\Ice\Plugin.h" \ + "$(ice_cpp_dir)\include\Ice\LoggerF.h" \ + "$(ice_cpp_dir)\include\Ice\BuiltinSequences.h" \ + "$(ice_cpp_dir)\include\Ice\Initialize.h" \ + "$(ice_cpp_dir)\include\IceUtil\Timer.h" \ + "$(ice_cpp_dir)\include\IceUtil\Thread.h" \ + "$(ice_cpp_dir)\include\IceUtil\Mutex.h" \ + "$(ice_cpp_dir)\include\IceUtil\Lock.h" \ + "$(ice_cpp_dir)\include\IceUtil\ThreadException.h" \ + "$(ice_cpp_dir)\include\IceUtil\Time.h" \ + "$(ice_cpp_dir)\include\IceUtil\MutexProtocol.h" \ + "$(ice_cpp_dir)\include\IceUtil\Monitor.h" \ + "$(ice_cpp_dir)\include\IceUtil\Cond.h" \ + "$(ice_cpp_dir)\include\Ice\PropertiesF.h" \ + "$(ice_cpp_dir)\include\Ice\Proxy.h" \ + "$(ice_cpp_dir)\include\Ice\ProxyFactoryF.h" \ + "$(ice_cpp_dir)\include\Ice\ConnectionIF.h" \ + "$(ice_cpp_dir)\include\Ice\RequestHandlerF.h" \ + "$(ice_cpp_dir)\include\Ice\EndpointF.h" \ + "$(ice_cpp_dir)\include\Ice\EndpointTypes.h" \ + "$(ice_cpp_dir)\include\Ice\ObjectAdapterF.h" \ + "$(ice_cpp_dir)\include\Ice\ReferenceF.h" \ + "$(ice_cpp_dir)\include\Ice\BatchRequestQueueF.h" \ + "$(ice_cpp_dir)\include\Ice\AsyncResult.h" \ + "$(ice_cpp_dir)\include\IceUtil\UniquePtr.h" \ + "$(ice_cpp_dir)\include\Ice\ConnectionF.h" \ + "$(ice_cpp_dir)\include\Ice\InstanceF.h" \ + "$(ice_cpp_dir)\include\Ice\AsyncResultF.h" \ + "$(ice_cpp_dir)\include\Ice\ObserverHelper.h" \ + "$(ice_cpp_dir)\include\Ice\Instrumentation.h" \ + "$(ice_cpp_dir)\include\Ice\Current.h" \ + "$(ice_cpp_dir)\include\Ice\Identity.h" \ + "$(ice_cpp_dir)\include\Ice\Version.h" \ + "$(ice_cpp_dir)\include\Ice\BasicStream.h" \ + "$(ice_cpp_dir)\include\Ice\Object.h" \ + "$(ice_cpp_dir)\include\Ice\IncomingAsyncF.h" \ + "$(ice_cpp_dir)\include\Ice\ObjectFactoryF.h" \ + "$(ice_cpp_dir)\include\Ice\ObjectFactoryManagerF.h" \ + "$(ice_cpp_dir)\include\Ice\Buffer.h" \ + "$(ice_cpp_dir)\include\Ice\Protocol.h" \ + "$(ice_cpp_dir)\include\Ice\SlicedDataF.h" \ + "$(ice_cpp_dir)\include\Ice\UserExceptionFactory.h" \ + "$(ice_cpp_dir)\include\Ice\FactoryTable.h" \ + "$(ice_cpp_dir)\include\Ice\InstrumentationF.h" \ + "$(ice_cpp_dir)\include\Ice\Dispatcher.h" \ + "$(ice_cpp_dir)\include\Ice\BatchRequestInterceptor.h" \ + "$(ice_cpp_dir)\include\Ice\LocalException.h" \ + "$(ice_cpp_dir)\include\Ice\PropertiesAdmin.h" \ + "$(ice_cpp_dir)\include\Ice\GCObject.h" \ + "$(ice_cpp_dir)\include\IceUtil\MutexPtrLock.h" \ + "$(ice_cpp_dir)\include\Ice\Incoming.h" \ + "$(ice_cpp_dir)\include\Ice\ServantLocatorF.h" \ + "$(ice_cpp_dir)\include\Ice\ServantManagerF.h" \ + "$(ice_cpp_dir)\include\Ice\ResponseHandlerF.h" \ + "$(ice_cpp_dir)\include\Ice\IncomingAsync.h" \ + "$(ice_cpp_dir)\include\Ice\Properties.h" \ + "$(ice_cpp_dir)\include\Ice\Logger.h" \ + "$(ice_cpp_dir)\include\Ice\LoggerUtil.h" \ + "$(ice_cpp_dir)\include\Ice\RemoteLogger.h" \ + "$(ice_cpp_dir)\include\Ice\FactoryTableInit.h" \ + "$(ice_cpp_dir)\include\Ice\DefaultObjectFactory.h" \ + "$(ice_cpp_dir)\include\Ice\ObjectFactory.h" \ + "$(ice_cpp_dir)\include\Ice\Communicator.h" \ + "$(ice_cpp_dir)\include\Ice\RouterF.h" \ + "$(ice_cpp_dir)\include\Ice\LocatorF.h" \ + "$(ice_cpp_dir)\include\Ice\PluginF.h" \ + "$(ice_cpp_dir)\include\Ice\ImplicitContextF.h" \ + "$(ice_cpp_dir)\include\Ice\FacetMap.h" \ + "$(ice_cpp_dir)\include\Ice\CommunicatorAsync.h" \ + "$(ice_cpp_dir)\include\Ice\ObjectAdapter.h" \ + "$(ice_cpp_dir)\include\Ice\Endpoint.h" \ + "$(ice_cpp_dir)\include\Ice\ServantLocator.h" \ + "$(ice_cpp_dir)\include\Ice\SlicedData.h" \ + "$(ice_cpp_dir)\include\Ice\OutgoingAsync.h" \ + "$(ice_cpp_dir)\include\Ice\OutgoingAsyncF.h" \ + "$(ice_cpp_dir)\include\Ice\Process.h" \ + "$(ice_cpp_dir)\include\Ice\Application.h" \ + "$(ice_cpp_dir)\include\Ice\Connection.h" \ + "$(ice_cpp_dir)\include\Ice\ConnectionAsync.h" \ + "$(ice_cpp_dir)\include\Ice\Functional.h" \ + "$(ice_cpp_dir)\include\IceUtil\Functional.h" \ + "$(ice_cpp_dir)\include\Ice\Stream.h" \ + "$(ice_cpp_dir)\include\Ice\ImplicitContext.h" \ + "$(ice_cpp_dir)\include\Ice\Locator.h" \ + "$(ice_cpp_dir)\include\Ice\ProcessF.h" \ + "$(ice_cpp_dir)\include\Ice\Router.h" \ + "$(ice_cpp_dir)\include\Ice\DispatchInterceptor.h" \ + "$(ice_cpp_dir)\include\Ice\NativePropertiesAdmin.h" \ + "$(ice_cpp_dir)\include\Ice\Metrics.h" \ + "$(ice_cpp_dir)\include\Ice\SliceChecksums.h" \ + "$(ice_cpp_dir)\include\Ice\SliceChecksumDict.h" \ + "$(ice_cpp_dir)\include\Ice\Service.h" \ + "$(ice_cpp_dir)\include\Ice\RegisterPlugins.h" \ + "Communicator.h" \ + "Proxy.h" \ + "Types.h" \ + "$(ice_cpp_dir)\include\IceUtil\OutputUtil.h" \ + "Util.h" \ + "$(ice_cpp_dir)\include\Slice\PHPUtil.h" \ + "$(ice_cpp_dir)\include\Slice\Parser.h" \ + +Properties.obj: \ + Properties.cpp \ + "Properties.h" \ + "Config.h" \ + "$(ice_cpp_dir)\include\Ice\Ice.h" \ + "$(ice_cpp_dir)\include\IceUtil\PushDisableWarnings.h" \ + "$(ice_cpp_dir)\include\Ice\Config.h" \ + "$(ice_cpp_dir)\include\IceUtil\Config.h" \ + "$(ice_cpp_dir)\include\Ice\DeprecatedStringConverter.h" \ + "$(ice_cpp_dir)\include\Ice\CommunicatorF.h" \ + "$(ice_cpp_dir)\include\Ice\ProxyF.h" \ + "$(ice_cpp_dir)\include\IceUtil\Shared.h" \ + "$(ice_cpp_dir)\include\IceUtil\Atomic.h" \ + "$(ice_cpp_dir)\include\Ice\ProxyHandle.h" \ + "$(ice_cpp_dir)\include\IceUtil\Handle.h" \ + "$(ice_cpp_dir)\include\IceUtil\Exception.h" \ + "$(ice_cpp_dir)\include\Ice\ObjectF.h" \ + "$(ice_cpp_dir)\include\Ice\Handle.h" \ + "$(ice_cpp_dir)\include\Ice\Exception.h" \ + "$(ice_cpp_dir)\include\Ice\Format.h" \ + "$(ice_cpp_dir)\include\Ice\StreamF.h" \ + "$(ice_cpp_dir)\include\Ice\LocalObject.h" \ + "$(ice_cpp_dir)\include\Ice\LocalObjectF.h" \ + "$(ice_cpp_dir)\include\Ice\StreamHelpers.h" \ + "$(ice_cpp_dir)\include\IceUtil\ScopedArray.h" \ + "$(ice_cpp_dir)\include\IceUtil\Iterator.h" \ + "$(ice_cpp_dir)\include\IceUtil\Optional.h" \ + "$(ice_cpp_dir)\include\IceUtil\UndefSysMacros.h" \ + "$(ice_cpp_dir)\include\IceUtil\PopDisableWarnings.h" \ + "$(ice_cpp_dir)\include\IceUtil\StringConverter.h" \ + "$(ice_cpp_dir)\include\Ice\Plugin.h" \ + "$(ice_cpp_dir)\include\Ice\LoggerF.h" \ + "$(ice_cpp_dir)\include\Ice\BuiltinSequences.h" \ + "$(ice_cpp_dir)\include\Ice\Initialize.h" \ + "$(ice_cpp_dir)\include\IceUtil\Timer.h" \ + "$(ice_cpp_dir)\include\IceUtil\Thread.h" \ + "$(ice_cpp_dir)\include\IceUtil\Mutex.h" \ + "$(ice_cpp_dir)\include\IceUtil\Lock.h" \ + "$(ice_cpp_dir)\include\IceUtil\ThreadException.h" \ + "$(ice_cpp_dir)\include\IceUtil\Time.h" \ + "$(ice_cpp_dir)\include\IceUtil\MutexProtocol.h" \ + "$(ice_cpp_dir)\include\IceUtil\Monitor.h" \ + "$(ice_cpp_dir)\include\IceUtil\Cond.h" \ + "$(ice_cpp_dir)\include\Ice\PropertiesF.h" \ + "$(ice_cpp_dir)\include\Ice\Proxy.h" \ + "$(ice_cpp_dir)\include\Ice\ProxyFactoryF.h" \ + "$(ice_cpp_dir)\include\Ice\ConnectionIF.h" \ + "$(ice_cpp_dir)\include\Ice\RequestHandlerF.h" \ + "$(ice_cpp_dir)\include\Ice\EndpointF.h" \ + "$(ice_cpp_dir)\include\Ice\EndpointTypes.h" \ + "$(ice_cpp_dir)\include\Ice\ObjectAdapterF.h" \ + "$(ice_cpp_dir)\include\Ice\ReferenceF.h" \ + "$(ice_cpp_dir)\include\Ice\BatchRequestQueueF.h" \ + "$(ice_cpp_dir)\include\Ice\AsyncResult.h" \ + "$(ice_cpp_dir)\include\IceUtil\UniquePtr.h" \ + "$(ice_cpp_dir)\include\Ice\ConnectionF.h" \ + "$(ice_cpp_dir)\include\Ice\InstanceF.h" \ + "$(ice_cpp_dir)\include\Ice\AsyncResultF.h" \ + "$(ice_cpp_dir)\include\Ice\ObserverHelper.h" \ + "$(ice_cpp_dir)\include\Ice\Instrumentation.h" \ + "$(ice_cpp_dir)\include\Ice\Current.h" \ + "$(ice_cpp_dir)\include\Ice\Identity.h" \ + "$(ice_cpp_dir)\include\Ice\Version.h" \ + "$(ice_cpp_dir)\include\Ice\BasicStream.h" \ + "$(ice_cpp_dir)\include\Ice\Object.h" \ + "$(ice_cpp_dir)\include\Ice\IncomingAsyncF.h" \ + "$(ice_cpp_dir)\include\Ice\ObjectFactoryF.h" \ + "$(ice_cpp_dir)\include\Ice\ObjectFactoryManagerF.h" \ + "$(ice_cpp_dir)\include\Ice\Buffer.h" \ + "$(ice_cpp_dir)\include\Ice\Protocol.h" \ + "$(ice_cpp_dir)\include\Ice\SlicedDataF.h" \ + "$(ice_cpp_dir)\include\Ice\UserExceptionFactory.h" \ + "$(ice_cpp_dir)\include\Ice\FactoryTable.h" \ + "$(ice_cpp_dir)\include\Ice\InstrumentationF.h" \ + "$(ice_cpp_dir)\include\Ice\Dispatcher.h" \ + "$(ice_cpp_dir)\include\Ice\BatchRequestInterceptor.h" \ + "$(ice_cpp_dir)\include\Ice\LocalException.h" \ + "$(ice_cpp_dir)\include\Ice\PropertiesAdmin.h" \ + "$(ice_cpp_dir)\include\Ice\GCObject.h" \ + "$(ice_cpp_dir)\include\IceUtil\MutexPtrLock.h" \ + "$(ice_cpp_dir)\include\Ice\Incoming.h" \ + "$(ice_cpp_dir)\include\Ice\ServantLocatorF.h" \ + "$(ice_cpp_dir)\include\Ice\ServantManagerF.h" \ + "$(ice_cpp_dir)\include\Ice\ResponseHandlerF.h" \ + "$(ice_cpp_dir)\include\Ice\IncomingAsync.h" \ + "$(ice_cpp_dir)\include\Ice\Properties.h" \ + "$(ice_cpp_dir)\include\Ice\Logger.h" \ + "$(ice_cpp_dir)\include\Ice\LoggerUtil.h" \ + "$(ice_cpp_dir)\include\Ice\RemoteLogger.h" \ + "$(ice_cpp_dir)\include\Ice\FactoryTableInit.h" \ + "$(ice_cpp_dir)\include\Ice\DefaultObjectFactory.h" \ + "$(ice_cpp_dir)\include\Ice\ObjectFactory.h" \ + "$(ice_cpp_dir)\include\Ice\Communicator.h" \ + "$(ice_cpp_dir)\include\Ice\RouterF.h" \ + "$(ice_cpp_dir)\include\Ice\LocatorF.h" \ + "$(ice_cpp_dir)\include\Ice\PluginF.h" \ + "$(ice_cpp_dir)\include\Ice\ImplicitContextF.h" \ + "$(ice_cpp_dir)\include\Ice\FacetMap.h" \ + "$(ice_cpp_dir)\include\Ice\CommunicatorAsync.h" \ + "$(ice_cpp_dir)\include\Ice\ObjectAdapter.h" \ + "$(ice_cpp_dir)\include\Ice\Endpoint.h" \ + "$(ice_cpp_dir)\include\Ice\ServantLocator.h" \ + "$(ice_cpp_dir)\include\Ice\SlicedData.h" \ + "$(ice_cpp_dir)\include\Ice\OutgoingAsync.h" \ + "$(ice_cpp_dir)\include\Ice\OutgoingAsyncF.h" \ + "$(ice_cpp_dir)\include\Ice\Process.h" \ + "$(ice_cpp_dir)\include\Ice\Application.h" \ + "$(ice_cpp_dir)\include\Ice\Connection.h" \ + "$(ice_cpp_dir)\include\Ice\ConnectionAsync.h" \ + "$(ice_cpp_dir)\include\Ice\Functional.h" \ + "$(ice_cpp_dir)\include\IceUtil\Functional.h" \ + "$(ice_cpp_dir)\include\Ice\Stream.h" \ + "$(ice_cpp_dir)\include\Ice\ImplicitContext.h" \ + "$(ice_cpp_dir)\include\Ice\Locator.h" \ + "$(ice_cpp_dir)\include\Ice\ProcessF.h" \ + "$(ice_cpp_dir)\include\Ice\Router.h" \ + "$(ice_cpp_dir)\include\Ice\DispatchInterceptor.h" \ + "$(ice_cpp_dir)\include\Ice\NativePropertiesAdmin.h" \ + "$(ice_cpp_dir)\include\Ice\Metrics.h" \ + "$(ice_cpp_dir)\include\Ice\SliceChecksums.h" \ + "$(ice_cpp_dir)\include\Ice\SliceChecksumDict.h" \ + "$(ice_cpp_dir)\include\Ice\Service.h" \ + "$(ice_cpp_dir)\include\Ice\RegisterPlugins.h" \ + "Util.h" \ + +Proxy.obj: \ + Proxy.cpp \ + "Proxy.h" \ + "Config.h" \ + "$(ice_cpp_dir)\include\Ice\Ice.h" \ + "$(ice_cpp_dir)\include\IceUtil\PushDisableWarnings.h" \ + "$(ice_cpp_dir)\include\Ice\Config.h" \ + "$(ice_cpp_dir)\include\IceUtil\Config.h" \ + "$(ice_cpp_dir)\include\Ice\DeprecatedStringConverter.h" \ + "$(ice_cpp_dir)\include\Ice\CommunicatorF.h" \ + "$(ice_cpp_dir)\include\Ice\ProxyF.h" \ + "$(ice_cpp_dir)\include\IceUtil\Shared.h" \ + "$(ice_cpp_dir)\include\IceUtil\Atomic.h" \ + "$(ice_cpp_dir)\include\Ice\ProxyHandle.h" \ + "$(ice_cpp_dir)\include\IceUtil\Handle.h" \ + "$(ice_cpp_dir)\include\IceUtil\Exception.h" \ + "$(ice_cpp_dir)\include\Ice\ObjectF.h" \ + "$(ice_cpp_dir)\include\Ice\Handle.h" \ + "$(ice_cpp_dir)\include\Ice\Exception.h" \ + "$(ice_cpp_dir)\include\Ice\Format.h" \ + "$(ice_cpp_dir)\include\Ice\StreamF.h" \ + "$(ice_cpp_dir)\include\Ice\LocalObject.h" \ + "$(ice_cpp_dir)\include\Ice\LocalObjectF.h" \ + "$(ice_cpp_dir)\include\Ice\StreamHelpers.h" \ + "$(ice_cpp_dir)\include\IceUtil\ScopedArray.h" \ + "$(ice_cpp_dir)\include\IceUtil\Iterator.h" \ + "$(ice_cpp_dir)\include\IceUtil\Optional.h" \ + "$(ice_cpp_dir)\include\IceUtil\UndefSysMacros.h" \ + "$(ice_cpp_dir)\include\IceUtil\PopDisableWarnings.h" \ + "$(ice_cpp_dir)\include\IceUtil\StringConverter.h" \ + "$(ice_cpp_dir)\include\Ice\Plugin.h" \ + "$(ice_cpp_dir)\include\Ice\LoggerF.h" \ + "$(ice_cpp_dir)\include\Ice\BuiltinSequences.h" \ + "$(ice_cpp_dir)\include\Ice\Initialize.h" \ + "$(ice_cpp_dir)\include\IceUtil\Timer.h" \ + "$(ice_cpp_dir)\include\IceUtil\Thread.h" \ + "$(ice_cpp_dir)\include\IceUtil\Mutex.h" \ + "$(ice_cpp_dir)\include\IceUtil\Lock.h" \ + "$(ice_cpp_dir)\include\IceUtil\ThreadException.h" \ + "$(ice_cpp_dir)\include\IceUtil\Time.h" \ + "$(ice_cpp_dir)\include\IceUtil\MutexProtocol.h" \ + "$(ice_cpp_dir)\include\IceUtil\Monitor.h" \ + "$(ice_cpp_dir)\include\IceUtil\Cond.h" \ + "$(ice_cpp_dir)\include\Ice\PropertiesF.h" \ + "$(ice_cpp_dir)\include\Ice\Proxy.h" \ + "$(ice_cpp_dir)\include\Ice\ProxyFactoryF.h" \ + "$(ice_cpp_dir)\include\Ice\ConnectionIF.h" \ + "$(ice_cpp_dir)\include\Ice\RequestHandlerF.h" \ + "$(ice_cpp_dir)\include\Ice\EndpointF.h" \ + "$(ice_cpp_dir)\include\Ice\EndpointTypes.h" \ + "$(ice_cpp_dir)\include\Ice\ObjectAdapterF.h" \ + "$(ice_cpp_dir)\include\Ice\ReferenceF.h" \ + "$(ice_cpp_dir)\include\Ice\BatchRequestQueueF.h" \ + "$(ice_cpp_dir)\include\Ice\AsyncResult.h" \ + "$(ice_cpp_dir)\include\IceUtil\UniquePtr.h" \ + "$(ice_cpp_dir)\include\Ice\ConnectionF.h" \ + "$(ice_cpp_dir)\include\Ice\InstanceF.h" \ + "$(ice_cpp_dir)\include\Ice\AsyncResultF.h" \ + "$(ice_cpp_dir)\include\Ice\ObserverHelper.h" \ + "$(ice_cpp_dir)\include\Ice\Instrumentation.h" \ + "$(ice_cpp_dir)\include\Ice\Current.h" \ + "$(ice_cpp_dir)\include\Ice\Identity.h" \ + "$(ice_cpp_dir)\include\Ice\Version.h" \ + "$(ice_cpp_dir)\include\Ice\BasicStream.h" \ + "$(ice_cpp_dir)\include\Ice\Object.h" \ + "$(ice_cpp_dir)\include\Ice\IncomingAsyncF.h" \ + "$(ice_cpp_dir)\include\Ice\ObjectFactoryF.h" \ + "$(ice_cpp_dir)\include\Ice\ObjectFactoryManagerF.h" \ + "$(ice_cpp_dir)\include\Ice\Buffer.h" \ + "$(ice_cpp_dir)\include\Ice\Protocol.h" \ + "$(ice_cpp_dir)\include\Ice\SlicedDataF.h" \ + "$(ice_cpp_dir)\include\Ice\UserExceptionFactory.h" \ + "$(ice_cpp_dir)\include\Ice\FactoryTable.h" \ + "$(ice_cpp_dir)\include\Ice\InstrumentationF.h" \ + "$(ice_cpp_dir)\include\Ice\Dispatcher.h" \ + "$(ice_cpp_dir)\include\Ice\BatchRequestInterceptor.h" \ + "$(ice_cpp_dir)\include\Ice\LocalException.h" \ + "$(ice_cpp_dir)\include\Ice\PropertiesAdmin.h" \ + "$(ice_cpp_dir)\include\Ice\GCObject.h" \ + "$(ice_cpp_dir)\include\IceUtil\MutexPtrLock.h" \ + "$(ice_cpp_dir)\include\Ice\Incoming.h" \ + "$(ice_cpp_dir)\include\Ice\ServantLocatorF.h" \ + "$(ice_cpp_dir)\include\Ice\ServantManagerF.h" \ + "$(ice_cpp_dir)\include\Ice\ResponseHandlerF.h" \ + "$(ice_cpp_dir)\include\Ice\IncomingAsync.h" \ + "$(ice_cpp_dir)\include\Ice\Properties.h" \ + "$(ice_cpp_dir)\include\Ice\Logger.h" \ + "$(ice_cpp_dir)\include\Ice\LoggerUtil.h" \ + "$(ice_cpp_dir)\include\Ice\RemoteLogger.h" \ + "$(ice_cpp_dir)\include\Ice\FactoryTableInit.h" \ + "$(ice_cpp_dir)\include\Ice\DefaultObjectFactory.h" \ + "$(ice_cpp_dir)\include\Ice\ObjectFactory.h" \ + "$(ice_cpp_dir)\include\Ice\Communicator.h" \ + "$(ice_cpp_dir)\include\Ice\RouterF.h" \ + "$(ice_cpp_dir)\include\Ice\LocatorF.h" \ + "$(ice_cpp_dir)\include\Ice\PluginF.h" \ + "$(ice_cpp_dir)\include\Ice\ImplicitContextF.h" \ + "$(ice_cpp_dir)\include\Ice\FacetMap.h" \ + "$(ice_cpp_dir)\include\Ice\CommunicatorAsync.h" \ + "$(ice_cpp_dir)\include\Ice\ObjectAdapter.h" \ + "$(ice_cpp_dir)\include\Ice\Endpoint.h" \ + "$(ice_cpp_dir)\include\Ice\ServantLocator.h" \ + "$(ice_cpp_dir)\include\Ice\SlicedData.h" \ + "$(ice_cpp_dir)\include\Ice\OutgoingAsync.h" \ + "$(ice_cpp_dir)\include\Ice\OutgoingAsyncF.h" \ + "$(ice_cpp_dir)\include\Ice\Process.h" \ + "$(ice_cpp_dir)\include\Ice\Application.h" \ + "$(ice_cpp_dir)\include\Ice\Connection.h" \ + "$(ice_cpp_dir)\include\Ice\ConnectionAsync.h" \ + "$(ice_cpp_dir)\include\Ice\Functional.h" \ + "$(ice_cpp_dir)\include\IceUtil\Functional.h" \ + "$(ice_cpp_dir)\include\Ice\Stream.h" \ + "$(ice_cpp_dir)\include\Ice\ImplicitContext.h" \ + "$(ice_cpp_dir)\include\Ice\Locator.h" \ + "$(ice_cpp_dir)\include\Ice\ProcessF.h" \ + "$(ice_cpp_dir)\include\Ice\Router.h" \ + "$(ice_cpp_dir)\include\Ice\DispatchInterceptor.h" \ + "$(ice_cpp_dir)\include\Ice\NativePropertiesAdmin.h" \ + "$(ice_cpp_dir)\include\Ice\Metrics.h" \ + "$(ice_cpp_dir)\include\Ice\SliceChecksums.h" \ + "$(ice_cpp_dir)\include\Ice\SliceChecksumDict.h" \ + "$(ice_cpp_dir)\include\Ice\Service.h" \ + "$(ice_cpp_dir)\include\Ice\RegisterPlugins.h" \ + "Communicator.h" \ + "Types.h" \ + "Operation.h" \ + "$(ice_cpp_dir)\include\IceUtil\OutputUtil.h" \ + "Connection.h" \ + "Endpoint.h" \ + "Util.h" \ + +Types.obj: \ + Types.cpp \ + "Types.h" \ + "Config.h" \ + "$(ice_cpp_dir)\include\Ice\Ice.h" \ + "$(ice_cpp_dir)\include\IceUtil\PushDisableWarnings.h" \ + "$(ice_cpp_dir)\include\Ice\Config.h" \ + "$(ice_cpp_dir)\include\IceUtil\Config.h" \ + "$(ice_cpp_dir)\include\Ice\DeprecatedStringConverter.h" \ + "$(ice_cpp_dir)\include\Ice\CommunicatorF.h" \ + "$(ice_cpp_dir)\include\Ice\ProxyF.h" \ + "$(ice_cpp_dir)\include\IceUtil\Shared.h" \ + "$(ice_cpp_dir)\include\IceUtil\Atomic.h" \ + "$(ice_cpp_dir)\include\Ice\ProxyHandle.h" \ + "$(ice_cpp_dir)\include\IceUtil\Handle.h" \ + "$(ice_cpp_dir)\include\IceUtil\Exception.h" \ + "$(ice_cpp_dir)\include\Ice\ObjectF.h" \ + "$(ice_cpp_dir)\include\Ice\Handle.h" \ + "$(ice_cpp_dir)\include\Ice\Exception.h" \ + "$(ice_cpp_dir)\include\Ice\Format.h" \ + "$(ice_cpp_dir)\include\Ice\StreamF.h" \ + "$(ice_cpp_dir)\include\Ice\LocalObject.h" \ + "$(ice_cpp_dir)\include\Ice\LocalObjectF.h" \ + "$(ice_cpp_dir)\include\Ice\StreamHelpers.h" \ + "$(ice_cpp_dir)\include\IceUtil\ScopedArray.h" \ + "$(ice_cpp_dir)\include\IceUtil\Iterator.h" \ + "$(ice_cpp_dir)\include\IceUtil\Optional.h" \ + "$(ice_cpp_dir)\include\IceUtil\UndefSysMacros.h" \ + "$(ice_cpp_dir)\include\IceUtil\PopDisableWarnings.h" \ + "$(ice_cpp_dir)\include\IceUtil\StringConverter.h" \ + "$(ice_cpp_dir)\include\Ice\Plugin.h" \ + "$(ice_cpp_dir)\include\Ice\LoggerF.h" \ + "$(ice_cpp_dir)\include\Ice\BuiltinSequences.h" \ + "$(ice_cpp_dir)\include\Ice\Initialize.h" \ + "$(ice_cpp_dir)\include\IceUtil\Timer.h" \ + "$(ice_cpp_dir)\include\IceUtil\Thread.h" \ + "$(ice_cpp_dir)\include\IceUtil\Mutex.h" \ + "$(ice_cpp_dir)\include\IceUtil\Lock.h" \ + "$(ice_cpp_dir)\include\IceUtil\ThreadException.h" \ + "$(ice_cpp_dir)\include\IceUtil\Time.h" \ + "$(ice_cpp_dir)\include\IceUtil\MutexProtocol.h" \ + "$(ice_cpp_dir)\include\IceUtil\Monitor.h" \ + "$(ice_cpp_dir)\include\IceUtil\Cond.h" \ + "$(ice_cpp_dir)\include\Ice\PropertiesF.h" \ + "$(ice_cpp_dir)\include\Ice\Proxy.h" \ + "$(ice_cpp_dir)\include\Ice\ProxyFactoryF.h" \ + "$(ice_cpp_dir)\include\Ice\ConnectionIF.h" \ + "$(ice_cpp_dir)\include\Ice\RequestHandlerF.h" \ + "$(ice_cpp_dir)\include\Ice\EndpointF.h" \ + "$(ice_cpp_dir)\include\Ice\EndpointTypes.h" \ + "$(ice_cpp_dir)\include\Ice\ObjectAdapterF.h" \ + "$(ice_cpp_dir)\include\Ice\ReferenceF.h" \ + "$(ice_cpp_dir)\include\Ice\BatchRequestQueueF.h" \ + "$(ice_cpp_dir)\include\Ice\AsyncResult.h" \ + "$(ice_cpp_dir)\include\IceUtil\UniquePtr.h" \ + "$(ice_cpp_dir)\include\Ice\ConnectionF.h" \ + "$(ice_cpp_dir)\include\Ice\InstanceF.h" \ + "$(ice_cpp_dir)\include\Ice\AsyncResultF.h" \ + "$(ice_cpp_dir)\include\Ice\ObserverHelper.h" \ + "$(ice_cpp_dir)\include\Ice\Instrumentation.h" \ + "$(ice_cpp_dir)\include\Ice\Current.h" \ + "$(ice_cpp_dir)\include\Ice\Identity.h" \ + "$(ice_cpp_dir)\include\Ice\Version.h" \ + "$(ice_cpp_dir)\include\Ice\BasicStream.h" \ + "$(ice_cpp_dir)\include\Ice\Object.h" \ + "$(ice_cpp_dir)\include\Ice\IncomingAsyncF.h" \ + "$(ice_cpp_dir)\include\Ice\ObjectFactoryF.h" \ + "$(ice_cpp_dir)\include\Ice\ObjectFactoryManagerF.h" \ + "$(ice_cpp_dir)\include\Ice\Buffer.h" \ + "$(ice_cpp_dir)\include\Ice\Protocol.h" \ + "$(ice_cpp_dir)\include\Ice\SlicedDataF.h" \ + "$(ice_cpp_dir)\include\Ice\UserExceptionFactory.h" \ + "$(ice_cpp_dir)\include\Ice\FactoryTable.h" \ + "$(ice_cpp_dir)\include\Ice\InstrumentationF.h" \ + "$(ice_cpp_dir)\include\Ice\Dispatcher.h" \ + "$(ice_cpp_dir)\include\Ice\BatchRequestInterceptor.h" \ + "$(ice_cpp_dir)\include\Ice\LocalException.h" \ + "$(ice_cpp_dir)\include\Ice\PropertiesAdmin.h" \ + "$(ice_cpp_dir)\include\Ice\GCObject.h" \ + "$(ice_cpp_dir)\include\IceUtil\MutexPtrLock.h" \ + "$(ice_cpp_dir)\include\Ice\Incoming.h" \ + "$(ice_cpp_dir)\include\Ice\ServantLocatorF.h" \ + "$(ice_cpp_dir)\include\Ice\ServantManagerF.h" \ + "$(ice_cpp_dir)\include\Ice\ResponseHandlerF.h" \ + "$(ice_cpp_dir)\include\Ice\IncomingAsync.h" \ + "$(ice_cpp_dir)\include\Ice\Properties.h" \ + "$(ice_cpp_dir)\include\Ice\Logger.h" \ + "$(ice_cpp_dir)\include\Ice\LoggerUtil.h" \ + "$(ice_cpp_dir)\include\Ice\RemoteLogger.h" \ + "$(ice_cpp_dir)\include\Ice\FactoryTableInit.h" \ + "$(ice_cpp_dir)\include\Ice\DefaultObjectFactory.h" \ + "$(ice_cpp_dir)\include\Ice\ObjectFactory.h" \ + "$(ice_cpp_dir)\include\Ice\Communicator.h" \ + "$(ice_cpp_dir)\include\Ice\RouterF.h" \ + "$(ice_cpp_dir)\include\Ice\LocatorF.h" \ + "$(ice_cpp_dir)\include\Ice\PluginF.h" \ + "$(ice_cpp_dir)\include\Ice\ImplicitContextF.h" \ + "$(ice_cpp_dir)\include\Ice\FacetMap.h" \ + "$(ice_cpp_dir)\include\Ice\CommunicatorAsync.h" \ + "$(ice_cpp_dir)\include\Ice\ObjectAdapter.h" \ + "$(ice_cpp_dir)\include\Ice\Endpoint.h" \ + "$(ice_cpp_dir)\include\Ice\ServantLocator.h" \ + "$(ice_cpp_dir)\include\Ice\SlicedData.h" \ + "$(ice_cpp_dir)\include\Ice\OutgoingAsync.h" \ + "$(ice_cpp_dir)\include\Ice\OutgoingAsyncF.h" \ + "$(ice_cpp_dir)\include\Ice\Process.h" \ + "$(ice_cpp_dir)\include\Ice\Application.h" \ + "$(ice_cpp_dir)\include\Ice\Connection.h" \ + "$(ice_cpp_dir)\include\Ice\ConnectionAsync.h" \ + "$(ice_cpp_dir)\include\Ice\Functional.h" \ + "$(ice_cpp_dir)\include\IceUtil\Functional.h" \ + "$(ice_cpp_dir)\include\Ice\Stream.h" \ + "$(ice_cpp_dir)\include\Ice\ImplicitContext.h" \ + "$(ice_cpp_dir)\include\Ice\Locator.h" \ + "$(ice_cpp_dir)\include\Ice\ProcessF.h" \ + "$(ice_cpp_dir)\include\Ice\Router.h" \ + "$(ice_cpp_dir)\include\Ice\DispatchInterceptor.h" \ + "$(ice_cpp_dir)\include\Ice\NativePropertiesAdmin.h" \ + "$(ice_cpp_dir)\include\Ice\Metrics.h" \ + "$(ice_cpp_dir)\include\Ice\SliceChecksums.h" \ + "$(ice_cpp_dir)\include\Ice\SliceChecksumDict.h" \ + "$(ice_cpp_dir)\include\Ice\Service.h" \ + "$(ice_cpp_dir)\include\Ice\RegisterPlugins.h" \ + "Communicator.h" \ + "Operation.h" \ + "$(ice_cpp_dir)\include\IceUtil\OutputUtil.h" \ + "Proxy.h" \ + "Util.h" \ + "$(ice_cpp_dir)\include\IceUtil\InputUtil.h" \ + "$(ice_cpp_dir)\include\Slice\PHPUtil.h" \ + "$(ice_cpp_dir)\include\Slice\Parser.h" \ + +Util.obj: \ + Util.cpp \ + "Util.h" \ + "Config.h" \ + "$(ice_cpp_dir)\include\Ice\Ice.h" \ + "$(ice_cpp_dir)\include\IceUtil\PushDisableWarnings.h" \ + "$(ice_cpp_dir)\include\Ice\Config.h" \ + "$(ice_cpp_dir)\include\IceUtil\Config.h" \ + "$(ice_cpp_dir)\include\Ice\DeprecatedStringConverter.h" \ + "$(ice_cpp_dir)\include\Ice\CommunicatorF.h" \ + "$(ice_cpp_dir)\include\Ice\ProxyF.h" \ + "$(ice_cpp_dir)\include\IceUtil\Shared.h" \ + "$(ice_cpp_dir)\include\IceUtil\Atomic.h" \ + "$(ice_cpp_dir)\include\Ice\ProxyHandle.h" \ + "$(ice_cpp_dir)\include\IceUtil\Handle.h" \ + "$(ice_cpp_dir)\include\IceUtil\Exception.h" \ + "$(ice_cpp_dir)\include\Ice\ObjectF.h" \ + "$(ice_cpp_dir)\include\Ice\Handle.h" \ + "$(ice_cpp_dir)\include\Ice\Exception.h" \ + "$(ice_cpp_dir)\include\Ice\Format.h" \ + "$(ice_cpp_dir)\include\Ice\StreamF.h" \ + "$(ice_cpp_dir)\include\Ice\LocalObject.h" \ + "$(ice_cpp_dir)\include\Ice\LocalObjectF.h" \ + "$(ice_cpp_dir)\include\Ice\StreamHelpers.h" \ + "$(ice_cpp_dir)\include\IceUtil\ScopedArray.h" \ + "$(ice_cpp_dir)\include\IceUtil\Iterator.h" \ + "$(ice_cpp_dir)\include\IceUtil\Optional.h" \ + "$(ice_cpp_dir)\include\IceUtil\UndefSysMacros.h" \ + "$(ice_cpp_dir)\include\IceUtil\PopDisableWarnings.h" \ + "$(ice_cpp_dir)\include\IceUtil\StringConverter.h" \ + "$(ice_cpp_dir)\include\Ice\Plugin.h" \ + "$(ice_cpp_dir)\include\Ice\LoggerF.h" \ + "$(ice_cpp_dir)\include\Ice\BuiltinSequences.h" \ + "$(ice_cpp_dir)\include\Ice\Initialize.h" \ + "$(ice_cpp_dir)\include\IceUtil\Timer.h" \ + "$(ice_cpp_dir)\include\IceUtil\Thread.h" \ + "$(ice_cpp_dir)\include\IceUtil\Mutex.h" \ + "$(ice_cpp_dir)\include\IceUtil\Lock.h" \ + "$(ice_cpp_dir)\include\IceUtil\ThreadException.h" \ + "$(ice_cpp_dir)\include\IceUtil\Time.h" \ + "$(ice_cpp_dir)\include\IceUtil\MutexProtocol.h" \ + "$(ice_cpp_dir)\include\IceUtil\Monitor.h" \ + "$(ice_cpp_dir)\include\IceUtil\Cond.h" \ + "$(ice_cpp_dir)\include\Ice\PropertiesF.h" \ + "$(ice_cpp_dir)\include\Ice\Proxy.h" \ + "$(ice_cpp_dir)\include\Ice\ProxyFactoryF.h" \ + "$(ice_cpp_dir)\include\Ice\ConnectionIF.h" \ + "$(ice_cpp_dir)\include\Ice\RequestHandlerF.h" \ + "$(ice_cpp_dir)\include\Ice\EndpointF.h" \ + "$(ice_cpp_dir)\include\Ice\EndpointTypes.h" \ + "$(ice_cpp_dir)\include\Ice\ObjectAdapterF.h" \ + "$(ice_cpp_dir)\include\Ice\ReferenceF.h" \ + "$(ice_cpp_dir)\include\Ice\BatchRequestQueueF.h" \ + "$(ice_cpp_dir)\include\Ice\AsyncResult.h" \ + "$(ice_cpp_dir)\include\IceUtil\UniquePtr.h" \ + "$(ice_cpp_dir)\include\Ice\ConnectionF.h" \ + "$(ice_cpp_dir)\include\Ice\InstanceF.h" \ + "$(ice_cpp_dir)\include\Ice\AsyncResultF.h" \ + "$(ice_cpp_dir)\include\Ice\ObserverHelper.h" \ + "$(ice_cpp_dir)\include\Ice\Instrumentation.h" \ + "$(ice_cpp_dir)\include\Ice\Current.h" \ + "$(ice_cpp_dir)\include\Ice\Identity.h" \ + "$(ice_cpp_dir)\include\Ice\Version.h" \ + "$(ice_cpp_dir)\include\Ice\BasicStream.h" \ + "$(ice_cpp_dir)\include\Ice\Object.h" \ + "$(ice_cpp_dir)\include\Ice\IncomingAsyncF.h" \ + "$(ice_cpp_dir)\include\Ice\ObjectFactoryF.h" \ + "$(ice_cpp_dir)\include\Ice\ObjectFactoryManagerF.h" \ + "$(ice_cpp_dir)\include\Ice\Buffer.h" \ + "$(ice_cpp_dir)\include\Ice\Protocol.h" \ + "$(ice_cpp_dir)\include\Ice\SlicedDataF.h" \ + "$(ice_cpp_dir)\include\Ice\UserExceptionFactory.h" \ + "$(ice_cpp_dir)\include\Ice\FactoryTable.h" \ + "$(ice_cpp_dir)\include\Ice\InstrumentationF.h" \ + "$(ice_cpp_dir)\include\Ice\Dispatcher.h" \ + "$(ice_cpp_dir)\include\Ice\BatchRequestInterceptor.h" \ + "$(ice_cpp_dir)\include\Ice\LocalException.h" \ + "$(ice_cpp_dir)\include\Ice\PropertiesAdmin.h" \ + "$(ice_cpp_dir)\include\Ice\GCObject.h" \ + "$(ice_cpp_dir)\include\IceUtil\MutexPtrLock.h" \ + "$(ice_cpp_dir)\include\Ice\Incoming.h" \ + "$(ice_cpp_dir)\include\Ice\ServantLocatorF.h" \ + "$(ice_cpp_dir)\include\Ice\ServantManagerF.h" \ + "$(ice_cpp_dir)\include\Ice\ResponseHandlerF.h" \ + "$(ice_cpp_dir)\include\Ice\IncomingAsync.h" \ + "$(ice_cpp_dir)\include\Ice\Properties.h" \ + "$(ice_cpp_dir)\include\Ice\Logger.h" \ + "$(ice_cpp_dir)\include\Ice\LoggerUtil.h" \ + "$(ice_cpp_dir)\include\Ice\RemoteLogger.h" \ + "$(ice_cpp_dir)\include\Ice\FactoryTableInit.h" \ + "$(ice_cpp_dir)\include\Ice\DefaultObjectFactory.h" \ + "$(ice_cpp_dir)\include\Ice\ObjectFactory.h" \ + "$(ice_cpp_dir)\include\Ice\Communicator.h" \ + "$(ice_cpp_dir)\include\Ice\RouterF.h" \ + "$(ice_cpp_dir)\include\Ice\LocatorF.h" \ + "$(ice_cpp_dir)\include\Ice\PluginF.h" \ + "$(ice_cpp_dir)\include\Ice\ImplicitContextF.h" \ + "$(ice_cpp_dir)\include\Ice\FacetMap.h" \ + "$(ice_cpp_dir)\include\Ice\CommunicatorAsync.h" \ + "$(ice_cpp_dir)\include\Ice\ObjectAdapter.h" \ + "$(ice_cpp_dir)\include\Ice\Endpoint.h" \ + "$(ice_cpp_dir)\include\Ice\ServantLocator.h" \ + "$(ice_cpp_dir)\include\Ice\SlicedData.h" \ + "$(ice_cpp_dir)\include\Ice\OutgoingAsync.h" \ + "$(ice_cpp_dir)\include\Ice\OutgoingAsyncF.h" \ + "$(ice_cpp_dir)\include\Ice\Process.h" \ + "$(ice_cpp_dir)\include\Ice\Application.h" \ + "$(ice_cpp_dir)\include\Ice\Connection.h" \ + "$(ice_cpp_dir)\include\Ice\ConnectionAsync.h" \ + "$(ice_cpp_dir)\include\Ice\Functional.h" \ + "$(ice_cpp_dir)\include\IceUtil\Functional.h" \ + "$(ice_cpp_dir)\include\Ice\Stream.h" \ + "$(ice_cpp_dir)\include\Ice\ImplicitContext.h" \ + "$(ice_cpp_dir)\include\Ice\Locator.h" \ + "$(ice_cpp_dir)\include\Ice\ProcessF.h" \ + "$(ice_cpp_dir)\include\Ice\Router.h" \ + "$(ice_cpp_dir)\include\Ice\DispatchInterceptor.h" \ + "$(ice_cpp_dir)\include\Ice\NativePropertiesAdmin.h" \ + "$(ice_cpp_dir)\include\Ice\Metrics.h" \ + "$(ice_cpp_dir)\include\Ice\SliceChecksums.h" \ + "$(ice_cpp_dir)\include\Ice\SliceChecksumDict.h" \ + "$(ice_cpp_dir)\include\Ice\Service.h" \ + "$(ice_cpp_dir)\include\Ice\RegisterPlugins.h" \ + "$(ice_cpp_dir)\include\IceUtil\UUID.h" \ + "$(ice_cpp_dir)\include\Slice\PHPUtil.h" \ + "$(ice_cpp_dir)\include\Slice\Parser.h" \ diff --git a/php/src/php7/Communicator.cpp b/php/src/php7/Communicator.cpp new file mode 100644 index 00000000000..ea0e614edf3 --- /dev/null +++ b/php/src/php7/Communicator.cpp @@ -0,0 +1,1772 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +#include <Communicator.h> +#include <Logger.h> +#include <Properties.h> +#include <Proxy.h> +#include <Types.h> +#include <Util.h> +#include <IceUtil/Options.h> +#include <IceUtil/MutexPtrLock.h> +#include <IceUtil/StringUtil.h> +#include <IceUtil/Timer.h> + +using namespace std; +using namespace IcePHP; + +ZEND_EXTERN_MODULE_GLOBALS(ice) + +// +// Class entries represent the PHP class implementations we have registered. +// +namespace IcePHP +{ + +zend_class_entry* communicatorClassEntry = 0; + +// +// An active communicator is in use by at least one request and may have +// registered so that it remains active after a request completes. The +// communicator is destroyed when there are no more references to this +// object. +// +class ActiveCommunicator : public IceUtil::Shared +{ +public: + + ActiveCommunicator(const Ice::CommunicatorPtr& c); + ~ActiveCommunicator(); + + const Ice::CommunicatorPtr communicator; + vector<string> ids; + int expires; + IceUtil::Time lastAccess; +}; +typedef IceUtil::Handle<ActiveCommunicator> ActiveCommunicatorPtr; + +typedef std::map<std::string, zval> ObjectFactoryMap; + +class CommunicatorInfoI : public CommunicatorInfo +{ +public: + + CommunicatorInfoI(const ActiveCommunicatorPtr&, zval*); + + virtual void getZval(zval*); + virtual void addRef(void); + virtual void decRef(void); + + virtual Ice::CommunicatorPtr getCommunicator() const; + + bool addObjectFactory(const std::string&, zval*); + bool findObjectFactory(const std::string&, zval*); + void destroyObjectFactories(void); + + const ActiveCommunicatorPtr ac; + zval zv; + ObjectFactoryMap objectFactories; +}; +typedef IceUtil::Handle<CommunicatorInfoI> CommunicatorInfoIPtr; + +// +// Each PHP request has its own set of object factories. More precisely, there is +// an object factory map for each communicator that is created by a PHP request. +// The factory class defined below delegates the create/destroy methods to PHP +// objects supplied by the application. An instance of this class is installed +// as the communicator's default object factory, and the class holds a reference +// to its communicator. When create is invoked, the class resolves the appropriate +// PHP object as follows: +// +// * Using its communicator reference as the key, look up the corresponding +// CommunicatorInfoI object in the request-specific communicator map. +// +// * In the object factory map held by the CommunicatorInfoI object, look for a +// PHP factory object using the same algorithm as the Ice core. +// +class ObjectFactoryI : public Ice::ObjectFactory +{ +public: + + ObjectFactoryI(const Ice::CommunicatorPtr&); + + virtual Ice::ObjectPtr create(const std::string&); + virtual void destroy(); + +private: + + Ice::CommunicatorPtr _communicator; +}; + +class ReaperTask : public IceUtil::TimerTask +{ +public: + + virtual void runTimerTask(); +}; + +} + +namespace +{ +// +// Communicator support. +// +zend_object_handlers _handlers; + +// +// The profile map holds Properties objects corresponding to the "default" profile +// (defined via the ice.config & ice.options settings in php.ini) as well as named +// profiles defined in an external file. +// +typedef map<string, Ice::PropertiesPtr> ProfileMap; +ProfileMap _profiles; +const string _defaultProfileName = ""; + +// +// This map represents communicators that have been registered so that they can be used +// by multiple PHP requests. +// +typedef map<string, ActiveCommunicatorPtr> RegisteredCommunicatorMap; +RegisteredCommunicatorMap _registeredCommunicators; +IceUtil::Mutex* _registeredCommunicatorsMutex = 0; + +IceUtil::TimerPtr _timer; + +// +// This map is stored in the "global" variables for each PHP request and holds +// the communicators that have been created (or registered communicators that have +// been used) by the request. +// +typedef map<Ice::CommunicatorPtr, CommunicatorInfoIPtr> CommunicatorMap; + +class Init +{ +public: + + Init() + { + _registeredCommunicatorsMutex = new IceUtil::Mutex(); + } + + ~Init() + { + delete _registeredCommunicatorsMutex; + _registeredCommunicatorsMutex = 0; + } +}; + +Init init; +} + +extern "C" +{ +static zend_object* handleAlloc(zend_class_entry*); +static void handleFreeStorage(zend_object*); +static zend_object* handleClone(zval*); +} + +ZEND_METHOD(Ice_Communicator, __construct) +{ + runtimeError("communicators cannot be instantiated directly"); +} + +ZEND_METHOD(Ice_Communicator, destroy) +{ + CommunicatorInfoIPtr _this = Wrapper<CommunicatorInfoIPtr>::value(getThis()); + assert(_this); + + // + // Remove all registrations. + // + { + IceUtilInternal::MutexPtrLock<IceUtil::Mutex> lock(_registeredCommunicatorsMutex); + for(vector<string>::iterator p = _this->ac->ids.begin(); p != _this->ac->ids.end(); ++p) + { + _registeredCommunicators.erase(*p); + } + _this->ac->ids.clear(); + } + + // + // We need to destroy any object factories installed by this request. + // + _this->destroyObjectFactories(); + + Ice::CommunicatorPtr c = _this->getCommunicator(); + assert(c); + CommunicatorMap* m = reinterpret_cast<CommunicatorMap*>(ICE_G(communicatorMap)); + assert(m); + assert(m->find(c) != m->end()); + m->erase(c); + + try + { + c->destroy(); + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_Communicator, stringToProxy) +{ + CommunicatorInfoIPtr _this = Wrapper<CommunicatorInfoIPtr>::value(getThis()); + assert(_this); + + char* str; + size_t strLen; + if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("s"), &str, &strLen) != SUCCESS) + { + RETURN_NULL(); + } + string s(str, strLen); + + try + { + Ice::ObjectPrx prx = _this->getCommunicator()->stringToProxy(s); + if(!createProxy(return_value, prx, _this)) + { + RETURN_NULL(); + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_Communicator, proxyToString) +{ + CommunicatorInfoIPtr _this = Wrapper<CommunicatorInfoIPtr>::value(getThis()); + assert(_this); + + zval* zv; + if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("O!"), &zv, proxyClassEntry) != SUCCESS) + { + RETURN_NULL(); + } + + try + { + string str; + if(zv) + { + Ice::ObjectPrx prx; + ClassInfoPtr info; + if(!fetchProxy(zv, prx, info)) + { + RETURN_NULL(); + } + assert(prx); + str = prx->ice_toString(); + } + RETURN_STRINGL(STRCAST(str.c_str()), static_cast<int>(str.length())); + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_Communicator, propertyToProxy) +{ + CommunicatorInfoIPtr _this = Wrapper<CommunicatorInfoIPtr>::value(getThis()); + assert(_this); + + char* str; + size_t strLen; + if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("s"), &str, &strLen) != SUCCESS) + { + RETURN_NULL(); + } + string s(str, strLen); + + try + { + Ice::ObjectPrx prx = _this->getCommunicator()->propertyToProxy(s); + if(!createProxy(return_value, prx, _this)) + { + RETURN_NULL(); + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_Communicator, proxyToProperty) +{ + CommunicatorInfoIPtr _this = Wrapper<CommunicatorInfoIPtr>::value(getThis()); + assert(_this); + + zval* zv; + char* str; + size_t strLen; + if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("O!s"), &zv, proxyClassEntry, &str, &strLen) + != SUCCESS) + { + RETURN_NULL(); + } + + string prefix(str, strLen); + + try + { + if(zv) + { + Ice::ObjectPrx prx; + ClassInfoPtr info; + if(!fetchProxy(zv, prx, info)) + { + RETURN_NULL(); + } + assert(prx); + + Ice::PropertyDict val = _this->getCommunicator()->proxyToProperty(prx, prefix); + if(!createStringMap(return_value, val)) + { + RETURN_NULL(); + } + } + else + { + array_init(return_value); + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_Communicator, stringToIdentity) +{ + CommunicatorInfoIPtr _this = Wrapper<CommunicatorInfoIPtr>::value(getThis()); + assert(_this); + + char* str; + size_t strLen; + if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("s"), &str, &strLen) != SUCCESS) + { + RETURN_NULL(); + } + string s(str, strLen); + + try + { + Ice::Identity id = _this->getCommunicator()->stringToIdentity(s); + if(!createIdentity(return_value, id)) + { + RETURN_NULL(); + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_Communicator, identityToString) +{ + CommunicatorInfoIPtr _this = Wrapper<CommunicatorInfoIPtr>::value(getThis()); + assert(_this); + + zend_class_entry* identityClass = idToClass("::Ice::Identity"); + assert(identityClass); + + zval* zv; + if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("O"), &zv, identityClass) != SUCCESS) + { + RETURN_NULL(); + } + Ice::Identity id; + if(!extractIdentity(zv, id)) + { + RETURN_NULL(); + } + + try + { + string str = _this->getCommunicator()->identityToString(id); + RETURN_STRINGL(STRCAST(str.c_str()), static_cast<int>(str.length())); + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_Communicator, addObjectFactory) +{ + CommunicatorInfoIPtr _this = Wrapper<CommunicatorInfoIPtr>::value(getThis()); + assert(_this); + + zend_class_entry* factoryClass = idToClass("Ice::ObjectFactory"); + assert(factoryClass); + + zval* factory; + char* id; + size_t idLen; + if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("Os!"), &factory, factoryClass, &id, + &idLen) != SUCCESS) + { + RETURN_NULL(); + } + + string type; + if(id) + { + type = string(id, idLen); + } + + if(!_this->addObjectFactory(type, factory)) + { + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_Communicator, findObjectFactory) +{ + CommunicatorInfoIPtr _this = Wrapper<CommunicatorInfoIPtr>::value(getThis()); + assert(_this); + + char* id; + size_t idLen; + if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("s!"), &id, &idLen) != SUCCESS) + { + RETURN_NULL(); + } + + string type; + if(id) + { + type = string(id, idLen); + } + + if(!_this->findObjectFactory(type, return_value)) + { + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_Communicator, getImplicitContext) +{ + runtimeError("not implemented"); +} + +ZEND_METHOD(Ice_Communicator, getProperties) +{ + if(ZEND_NUM_ARGS() > 0) + { + WRONG_PARAM_COUNT; + } + + CommunicatorInfoIPtr _this = Wrapper<CommunicatorInfoIPtr>::value(getThis()); + assert(_this); + + try + { + Ice::PropertiesPtr props = _this->getCommunicator()->getProperties(); + if(!createProperties(return_value, props)) + { + RETURN_NULL(); + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_Communicator, getLogger) +{ + if(ZEND_NUM_ARGS() > 0) + { + WRONG_PARAM_COUNT; + } + + CommunicatorInfoIPtr _this = Wrapper<CommunicatorInfoIPtr>::value(getThis()); + assert(_this); + + try + { + Ice::LoggerPtr logger = _this->getCommunicator()->getLogger(); + if(!createLogger(return_value, logger)) + { + RETURN_NULL(); + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + RETURN_NULL(); + } +} + + +ZEND_METHOD(Ice_Communicator, getDefaultRouter) +{ + if(ZEND_NUM_ARGS() > 0) + { + WRONG_PARAM_COUNT; + } + + CommunicatorInfoIPtr _this = Wrapper<CommunicatorInfoIPtr>::value(getThis()); + assert(_this); + + try + { + Ice::RouterPrx router = _this->getCommunicator()->getDefaultRouter(); + if(router) + { + ClassInfoPtr info = getClassInfoById("::Ice::Router"); + if(!info) + { + runtimeError("no definition for Ice::Router"); + RETURN_NULL(); + } + if(!createProxy(return_value, router, info, _this)) + { + RETURN_NULL(); + } + } + else + { + RETURN_NULL(); + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_Communicator, setDefaultRouter) +{ + CommunicatorInfoIPtr _this = Wrapper<CommunicatorInfoIPtr>::value(getThis()); + assert(_this); + + zval* zv; + if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("O!"), &zv, proxyClassEntry) != + SUCCESS) + { + RETURN_NULL(); + } + + Ice::ObjectPrx proxy; + ClassInfoPtr info; + if(zv && !fetchProxy(zv, proxy, info)) + { + RETURN_NULL(); + } + + try + { + Ice::RouterPrx router; + if(proxy) + { + if(!info || !info->isA("::Ice::Router")) + { + invalidArgument("setDefaultRouter requires a proxy narrowed to Ice::Router"); + RETURN_NULL(); + } + router = Ice::RouterPrx::uncheckedCast(proxy); + } + _this->getCommunicator()->setDefaultRouter(router); + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_Communicator, getDefaultLocator) +{ + if(ZEND_NUM_ARGS() > 0) + { + WRONG_PARAM_COUNT; + } + + CommunicatorInfoIPtr _this = Wrapper<CommunicatorInfoIPtr>::value(getThis()); + assert(_this); + + try + { + Ice::LocatorPrx locator = _this->getCommunicator()->getDefaultLocator(); + if(locator) + { + ClassInfoPtr info = getClassInfoById("::Ice::Locator"); + if(!info) + { + runtimeError("no definition for Ice::Locator"); + RETURN_NULL(); + } + if(!createProxy(return_value, locator, info, _this)) + { + RETURN_NULL(); + } + } + else + { + RETURN_NULL(); + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_Communicator, setDefaultLocator) +{ + CommunicatorInfoIPtr _this = Wrapper<CommunicatorInfoIPtr>::value(getThis()); + assert(_this); + + zval* zv; + if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("O!"), &zv, proxyClassEntry) != + SUCCESS) + { + RETURN_NULL(); + } + + Ice::ObjectPrx proxy; + ClassInfoPtr info; + if(zv && !fetchProxy(zv, proxy, info)) + { + RETURN_NULL(); + } + + try + { + Ice::LocatorPrx locator; + if(proxy) + { + if(!info || !info->isA("::Ice::Locator")) + { + invalidArgument("setDefaultLocator requires a proxy narrowed to Ice::Locator"); + RETURN_NULL(); + } + locator = Ice::LocatorPrx::uncheckedCast(proxy); + } + _this->getCommunicator()->setDefaultLocator(locator); + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_Communicator, flushBatchRequests) +{ + CommunicatorInfoIPtr _this = Wrapper<CommunicatorInfoIPtr>::value(getThis()); + assert(_this); + + if(ZEND_NUM_ARGS() != 8) + { + WRONG_PARAM_COUNT; + } + + try + { + _this->getCommunicator()->flushBatchRequests(); + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + RETURN_NULL(); + } +} + +#ifdef _WIN32 +extern "C" +#endif +static zend_object* +handleAlloc(zend_class_entry* ce) +{ + Wrapper<CommunicatorInfoIPtr>* obj = Wrapper<CommunicatorInfoIPtr>::create(ce); + assert(obj); + + obj->zobj.handlers = &_handlers; + + return &obj->zobj; +} + +#ifdef _WIN32 +extern "C" +#endif +static void +handleFreeStorage(zend_object* object) +{ + Wrapper<CommunicatorInfoIPtr>* obj = Wrapper<CommunicatorInfoIPtr>::fetch(object); + assert(obj); + + delete obj->ptr; + zend_object_std_dtor(object); +} + +#ifdef _WIN32 +extern "C" +#endif +static zend_object* +handleClone(zval* zv) +{ + php_error_docref(0, E_ERROR, "communicators cannot be cloned"); + return 0; +} + +static CommunicatorInfoIPtr +createCommunicator(zval* zv, const ActiveCommunicatorPtr& ac) +{ + try + { + if(object_init_ex(zv, communicatorClassEntry) != SUCCESS) + { + runtimeError("unable to initialize communicator object"); + return 0; + } + + Wrapper<CommunicatorInfoIPtr>* obj = Wrapper<CommunicatorInfoIPtr>::extract(zv); + assert(!obj->ptr); + + CommunicatorInfoIPtr info = new CommunicatorInfoI(ac, zv); + obj->ptr = new CommunicatorInfoIPtr(info); + + CommunicatorMap* m; + if(ICE_G(communicatorMap)) + { + m = reinterpret_cast<CommunicatorMap*>(ICE_G(communicatorMap)); + } + else + { + m = new CommunicatorMap; + ICE_G(communicatorMap) = m; + } + m->insert(CommunicatorMap::value_type(ac->communicator, info)); + + return info; + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + return 0; + } +} + +static CommunicatorInfoIPtr +initializeCommunicator(zval* zv, Ice::StringSeq& args, bool hasArgs, const Ice::InitializationData& initData) +{ + try + { + Ice::CommunicatorPtr c; + if(hasArgs) + { + c = Ice::initialize(args, initData); + } + else + { + c = Ice::initialize(initData); + } + + ActiveCommunicatorPtr ac = new ActiveCommunicator(c); + + // + // Install a default object factory that delegates to PHP factories. + // + c->addObjectFactory(new ObjectFactoryI(c), ""); + + CommunicatorInfoIPtr info = createCommunicator(zv, ac); + if(!info) + { + try + { + c->destroy(); + } + catch(...) + { + } + } + + return info; + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + return 0; + } +} + +ZEND_FUNCTION(Ice_initialize) +{ + if(ZEND_NUM_ARGS() > 2) + { + runtimeError("too many arguments"); + RETURN_NULL(); + } + + zend_class_entry* initClass = idToClass("::Ice::InitializationData"); + assert(initClass); + + // + // Retrieve the arguments. + // + zval* args = static_cast<zval*>(emalloc(ZEND_NUM_ARGS() * sizeof(zval))); + AutoEfree autoArgs(args); // Call efree on return + if(zend_get_parameters_array_ex(ZEND_NUM_ARGS(), args) == FAILURE) + { + runtimeError("unable to get arguments"); + RETURN_NULL(); + } + + Ice::StringSeq seq; + Ice::InitializationData initData; + zval* zvargs = 0; + zval* zvinit = 0; + + // + // Accept the following invocations: + // + // initialize(array, InitializationData) + // initialize(array) + // initialize(InitializationData) + // initialize() + // + bool hasArgs = false; + if(ZEND_NUM_ARGS()) + { + if(Z_TYPE(args[0]) == IS_ARRAY) + { + if(!extractStringArray(&args[0], seq)) + { + RETURN_NULL(); + } + zvargs = &args[0]; + hasArgs = true; + if(ZEND_NUM_ARGS() > 1) + { + if(Z_TYPE(args[1]) != IS_OBJECT || Z_OBJCE(args[1]) != initClass) + { + string s = zendTypeToString(Z_TYPE(args[1])); + invalidArgument("expected InitializationData object but received %s", s.c_str()); + RETURN_NULL(); + } + zvinit = &args[1]; + } + } + else if(Z_TYPE(args[0]) == IS_OBJECT && Z_OBJCE(args[0]) == initClass) + { + if(ZEND_NUM_ARGS() > 1) + { + runtimeError("too many arguments"); + RETURN_NULL(); + } + zvinit = &args[0]; + } + else + { + string s = zendTypeToString(Z_TYPE(args[0])); + invalidArgument("unexpected argument type %s", s.c_str()); + RETURN_NULL(); + } + } + + if(zvinit) + { + zval* data; + string member; + + member = "properties"; + { + if((data = zend_hash_str_find(Z_OBJPROP_P(zvinit), STRCAST(member.c_str()), member.size()))) + { + assert(Z_TYPE_P(data) == IS_INDIRECT); + if(!fetchProperties(Z_INDIRECT_P(data), initData.properties)) + { + RETURN_NULL(); + } + } + } + + member = "logger"; + { + if((data = zend_hash_str_find(Z_OBJPROP_P(zvinit), STRCAST(member.c_str()), member.size()))) + { + assert(Z_TYPE_P(data) == IS_INDIRECT); + if(!fetchLogger(Z_INDIRECT_P(data), initData.logger)) + { + RETURN_NULL(); + } + } + } + } + + initData.compactIdResolver = new IdResolver(); + + CommunicatorInfoIPtr info = initializeCommunicator(return_value, seq, hasArgs, initData); + if(!info) + { + RETURN_NULL(); + } + + if(zvargs && Z_ISREF_P(zvargs)) + { + zval_dtor(zvargs); + if(!createStringArray(zvargs, seq)) + { + RETURN_NULL(); + } + } +} + +ZEND_FUNCTION(Ice_register) +{ + zval* comm; + char* s; + size_t sLen; + long expires = 0; + if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("Os|l"), &comm, communicatorClassEntry, &s, + &sLen, &expires) != SUCCESS) + { + RETURN_NULL(); + } + + string id(s, sLen); + if(id.empty()) + { + invalidArgument("communicator id cannot be empty"); + RETURN_NULL(); + } + + CommunicatorInfoIPtr info = Wrapper<CommunicatorInfoIPtr>::value(comm); + assert(info); + + IceUtilInternal::MutexPtrLock<IceUtil::Mutex> lock(_registeredCommunicatorsMutex); + + RegisteredCommunicatorMap::iterator p = _registeredCommunicators.find(id); + if(p != _registeredCommunicators.end()) + { + if(p->second->communicator != info->getCommunicator()) + { + // + // A different communicator is already registered with that ID. + // + RETURN_FALSE; + } + } + else + { + info->ac->ids.push_back(id); + _registeredCommunicators[id] = info->ac; + } + + if(expires > 0) + { + // + // Update the expiration time. If a communicator is registered with multiple IDs, we + // always use the most recent expiration setting. + // + info->ac->expires = static_cast<int>(expires); + info->ac->lastAccess = IceUtil::Time::now(); + + // + // Start the timer if necessary. Reap expired communicators every five minutes. + // + if(!_timer) + { + _timer = new IceUtil::Timer; + _timer->scheduleRepeated(new ReaperTask, IceUtil::Time::seconds(5 * 60)); + } + } + + RETURN_TRUE; +} + +ZEND_FUNCTION(Ice_unregister) +{ + char* s; + size_t sLen; + if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("s"), &s, &sLen) != SUCCESS) + { + RETURN_NULL(); + } + + string id(s, sLen); + + IceUtilInternal::MutexPtrLock<IceUtil::Mutex> lock(_registeredCommunicatorsMutex); + + RegisteredCommunicatorMap::iterator p = _registeredCommunicators.find(id); + if(p == _registeredCommunicators.end()) + { + // + // No communicator registered with that ID. + // + RETURN_FALSE; + } + + // + // Remove the ID from the ActiveCommunicator's list of registered IDs. + // + ActiveCommunicatorPtr ac = p->second; + vector<string>::iterator q = find(ac->ids.begin(), ac->ids.end(), id); + assert(q != ac->ids.end()); + ac->ids.erase(q); + + _registeredCommunicators.erase(p); + + RETURN_TRUE; +} + +ZEND_FUNCTION(Ice_find) +{ + char* s; + size_t sLen; + if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("s"), &s, &sLen) != SUCCESS) + { + RETURN_NULL(); + } + + string id(s, sLen); + + IceUtilInternal::MutexPtrLock<IceUtil::Mutex> lock(_registeredCommunicatorsMutex); + + RegisteredCommunicatorMap::iterator p = _registeredCommunicators.find(id); + if(p == _registeredCommunicators.end()) + { + // + // No communicator registered with that ID. + // + RETURN_NULL(); + } + + if(p->second->expires > 0) + { + p->second->lastAccess = IceUtil::Time::now(); + } + + // + // Check if this communicator has already been obtained by the current request. + // If so, we can return the existing PHP object that corresponds to the communicator. + // + CommunicatorMap* m = reinterpret_cast<CommunicatorMap*>(ICE_G(communicatorMap)); + if(m) + { + CommunicatorMap::iterator q = m->find(p->second->communicator); + if(q != m->end()) + { + q->second->getZval(return_value); + return; + } + } + + if(!createCommunicator(return_value, p->second)) + { + RETURN_NULL(); + } +} + +ZEND_FUNCTION(Ice_getProperties) +{ + char* s = 0; + size_t sLen; + if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("|s"), &s, &sLen) != SUCCESS) + { + RETURN_NULL(); + } + + string name; + if(s) + { + name = string(s, sLen); + } + + ProfileMap::iterator p = _profiles.find(name); + if(p == _profiles.end()) + { + RETURN_NULL(); + } + + Ice::PropertiesPtr clone = p->second->clone(); + if(!createProperties(return_value, clone)) + { + RETURN_NULL(); + } +} + +ZEND_FUNCTION(Ice_identityToString) +{ + zend_class_entry* identityClass = idToClass("::Ice::Identity"); + assert(identityClass); + + zval* zv; + if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("O"), &zv, identityClass) != SUCCESS) + { + RETURN_NULL(); + } + Ice::Identity id; + if(!extractIdentity(zv, id)) + { + RETURN_NULL(); + } + + try + { + string str = Ice::identityToString(id); + RETURN_STRINGL(STRCAST(str.c_str()), static_cast<int>(str.length())); + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + RETURN_NULL(); + } +} + +ZEND_FUNCTION(Ice_stringToIdentity) +{ + char* str; + size_t strLen; + if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("s"), &str, &strLen) != SUCCESS) + { + RETURN_NULL(); + } + string s(str, strLen); + + try + { + Ice::Identity id = Ice::stringToIdentity(s); + if(!createIdentity(return_value, id)) + { + RETURN_NULL(); + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + RETURN_NULL(); + } +} + +// +// Necessary to suppress warnings from zend_function_entry in php-5.2 +// and INI_STR macro. +// +#ifdef __GNUC__ +# pragma GCC diagnostic ignored "-Wwrite-strings" +#endif + +// +// Predefined methods for Communicator. +// +static zend_function_entry _interfaceMethods[] = +{ + {0, 0, 0} +}; +static zend_function_entry _classMethods[] = +{ + ZEND_ME(Ice_Communicator, __construct, NULL, ZEND_ACC_PRIVATE|ZEND_ACC_CTOR) + ZEND_ME(Ice_Communicator, destroy, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_Communicator, stringToProxy, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_Communicator, proxyToString, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_Communicator, propertyToProxy, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_Communicator, proxyToProperty, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_Communicator, stringToIdentity, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_Communicator, identityToString, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_Communicator, addObjectFactory, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_Communicator, findObjectFactory, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_Communicator, getImplicitContext, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_Communicator, getProperties, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_Communicator, getLogger, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_Communicator, getDefaultRouter, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_Communicator, setDefaultRouter, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_Communicator, getDefaultLocator, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_Communicator, setDefaultLocator, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_Communicator, flushBatchRequests, NULL, ZEND_ACC_PUBLIC) + {0, 0, 0} +}; + +static bool +createProfile(const string& name, const string& config, const string& options) +{ + ProfileMap::iterator p = _profiles.find(name); + if(p != _profiles.end()) + { + php_error_docref(0, E_WARNING, "duplicate Ice profile `%s'", name.c_str()); + return false; + } + + Ice::PropertiesPtr properties = Ice::createProperties(); + + if(!config.empty()) + { + try + { + properties->load(config); + } + catch(const IceUtil::Exception& ex) + { + ostringstream ostr; + ex.ice_print(ostr); + php_error_docref(0, E_WARNING, "unable to load Ice configuration file %s:\n%s", config.c_str(), + ostr.str().c_str()); + return false; + } + } + + if(!options.empty()) + { + vector<string> args; + try + { + args = IceUtilInternal::Options::split(options); + } + catch(const IceUtil::Exception& ex) + { + ostringstream ostr; + ex.ice_print(ostr); + string msg = ostr.str(); + php_error_docref(0, E_WARNING, "error occurred while parsing the options `%s':\n%s", + options.c_str(), msg.c_str()); + return false; + } + + properties->parseCommandLineOptions("", args); + } + + _profiles[name] = properties; + return true; +} + +static bool +parseProfiles(const string& file) +{ + // + // The Zend engine doesn't export a function for loading an INI file, so we + // have to do it ourselves. The format is: + // + // [profile-name] + // ice.config = config-file + // ice.options = args + // + ifstream in(file.c_str()); + if(!in) + { + php_error_docref(0, E_WARNING, "unable to open Ice profiles in %s", file.c_str()); + return false; + } + + string name, config, options; + char line[1024]; + while(in.getline(line, 1024)) + { + const string delim = " \t\r\n"; + string s = line; + + string::size_type idx = s.find(';'); + if(idx != string::npos) + { + s.erase(idx); + } + + idx = s.find_last_not_of(delim); + if(idx != string::npos && idx + 1 < s.length()) + { + s.erase(idx + 1); + } + + string::size_type beg = s.find_first_not_of(delim); + if(beg == string::npos) + { + continue; + } + + if(s[beg] == '[') + { + beg++; + string::size_type end = s.find_first_of(" \t]", beg); + if(end == string::npos || s[s.length() - 1] != ']') + { + php_error_docref(0, E_WARNING, "invalid profile section in file %s:\n%s\n", file.c_str(), + line); + return false; + } + + if(!name.empty()) + { + createProfile(name, config, options); + config.clear(); + options.clear(); + } + + name = s.substr(beg, end - beg); + } + else + { + string::size_type end = s.find_first_of(delim + "=", beg); + assert(end != string::npos); + + string key = s.substr(beg, end - beg); + + end = s.find('=', end); + if(end == string::npos) + { + php_error_docref(0, E_WARNING, "invalid profile entry in file %s:\n%s\n", file.c_str(), line); + return false; + } + ++end; + + string value; + beg = s.find_first_not_of(delim, end); + if(beg != string::npos) + { + end = s.length(); + value = s.substr(beg, end - beg); + + // + // Check for quotes and remove them if present + // + string::size_type qpos = IceUtilInternal::checkQuote(value); + if(qpos != string::npos) + { + value = value.substr(1, qpos - 1); + } + } + + if(key == "config" || key == "ice.config") + { + config = value; + } + else if(key == "options" || key == "ice.options") + { + options = value; + } + else + { + php_error_docref(0, E_WARNING, "unknown profile entry in file %s:\n%s\n", file.c_str(), line); + } + + if(name.empty()) + { + php_error_docref(0, E_WARNING, "no section for profile entry in file %s:\n%s\n", file.c_str(), + line); + return false; + } + } + } + + if(!name.empty()) + { + if(!createProfile(name, config, options)) + { + return false; + } + } + + return true; +} + +bool +IcePHP::communicatorInit(void) +{ + // + // We register an interface and a class that implements the interface. This allows + // applications to safely include the Slice-generated code for the type. + // + + // + // Register the Communicator interface. + // + zend_class_entry ce; +#ifdef ICEPHP_USE_NAMESPACES + INIT_NS_CLASS_ENTRY(ce, "Ice", "Communicator", _interfaceMethods); +#else + INIT_CLASS_ENTRY(ce, "Ice_Communicator", _interfaceMethods); +#endif + zend_class_entry* interface = zend_register_internal_interface(&ce TSRMLS_CC); + + // + // Register the Communicator class. + // + INIT_CLASS_ENTRY(ce, "IcePHP_Communicator", _classMethods); + ce.create_object = handleAlloc; + communicatorClassEntry = zend_register_internal_class(&ce); + memcpy(&_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); + _handlers.clone_obj = handleClone; + _handlers.free_obj = handleFreeStorage; + _handlers.offset = XtOffsetOf(Wrapper<CommunicatorInfoIPtr>, zobj); + zend_class_implements(communicatorClassEntry, 1, interface); + + // + // Create the profiles from configuration settings. + // + const char* empty = ""; + const char* config = INI_STR("ice.config"); // Needs to be a string literal! + if(!config) + { + config = empty; + } + const char* options = INI_STR("ice.options"); // Needs to be a string literal! + if(!options) + { + options = empty; + } + if(!createProfile(_defaultProfileName, config, options)) + { + return false; + } + + const char* profiles = INI_STR("ice.profiles"); // Needs to be a string literal! + if(!profiles) + { + profiles = empty; + } + if(strlen(profiles) > 0) + { + if(!parseProfiles(profiles)) + { + return false; + } + + if(INI_BOOL(const_cast<char*>("ice.hide_profiles"))) + { + memset(const_cast<char*>(profiles), '*', strlen(profiles)); + // + // For some reason the code below does not work as expected. It causes a call + // to ini_get_all() to segfault. + // + /* + if(zend_alter_ini_entry("ice.profiles", sizeof("ice.profiles"), "<hidden>", sizeof("<hidden>") - 1, + PHP_INI_ALL, PHP_INI_STAGE_STARTUP) == FAILURE) + { + return false; + } + */ + } + } + + return true; +} + +bool +IcePHP::communicatorShutdown(void) +{ + _profiles.clear(); + + IceUtilInternal::MutexPtrLock<IceUtil::Mutex> lock(_registeredCommunicatorsMutex); + + if(_timer) + { + _timer->destroy(); + _timer = 0; + } + + // + // Clearing the map releases the last remaining reference counts of the ActiveCommunicator + // objects. The ActiveCommunicator destructor destroys its communicator. + // + _registeredCommunicators.clear(); + + return true; +} + +bool +IcePHP::communicatorRequestInit(void) +{ + ICE_G(communicatorMap) = 0; + + return true; +} + +bool +IcePHP::communicatorRequestShutdown(void) +{ + if(ICE_G(communicatorMap)) + { + CommunicatorMap* m = static_cast<CommunicatorMap*>(ICE_G(communicatorMap)); + for(CommunicatorMap::iterator p = m->begin(); p != m->end(); ++p) + { + CommunicatorInfoIPtr info = p->second; + + // + // We need to destroy any object factories installed during this request. + // + info->destroyObjectFactories(); + } + + // + // Deleting the map decrements the reference count of its ActiveCommunicator + // values. If there are no other references to an ActiveCommunicator, its + // destructor destroys the communicator. + // + delete m; + } + + return true; +} + +IcePHP::ActiveCommunicator::ActiveCommunicator(const Ice::CommunicatorPtr& c) : + communicator(c), expires(0) +{ +} + +IcePHP::ActiveCommunicator::~ActiveCommunicator() +{ + // + // There are no more references to this communicator, so we can safely destroy it now. + // + try + { + communicator->destroy(); + } + catch(...) + { + } +} + +IcePHP::CommunicatorInfoI::CommunicatorInfoI(const ActiveCommunicatorPtr& c, zval* z) : + ac(c) +{ + ZVAL_COPY_VALUE(&zv, z); +} + +void +IcePHP::CommunicatorInfoI::getZval(zval* z) +{ + ZVAL_COPY_VALUE(z, &zv); + addRef(); +} + +void +IcePHP::CommunicatorInfoI::addRef(void) +{ + Z_ADDREF_P(&zv); +} + +void +IcePHP::CommunicatorInfoI::decRef(void) +{ + Z_DELREF_P(&zv); +} + +Ice::CommunicatorPtr +IcePHP::CommunicatorInfoI::getCommunicator() const +{ + return ac->communicator; +} + +bool +IcePHP::CommunicatorInfoI::addObjectFactory(const string& id, zval* factory) +{ + ObjectFactoryMap::iterator p = objectFactories.find(id); + if(p != objectFactories.end()) + { + Ice::AlreadyRegisteredException ex(__FILE__, __LINE__); + ex.kindOfObject = "object factory"; + ex.id = id; + throwException(ex TSRMLS_CC); + return false; + } + + zval zv; + ZVAL_COPY_VALUE(&zv, factory); + objectFactories.insert(ObjectFactoryMap::value_type(id, zv)); + + return true; +} + +bool +IcePHP::CommunicatorInfoI::findObjectFactory(const string& id, zval* zv) +{ + ObjectFactoryMap::iterator p = objectFactories.find(id); + if(p != objectFactories.end()) + { + ZVAL_COPY(zv, &p->second); + return true; + } + + return false; +} + +void +IcePHP::CommunicatorInfoI::destroyObjectFactories() +{ + for(ObjectFactoryMap::iterator p = objectFactories.begin(); p != objectFactories.end(); ++p) + { + // + // Invoke the destroy method on each registered PHP factory. + // + invokeMethod(&p->second, "destroy"); + zend_clear_exception(); + zval_ptr_dtor(&p->second); + } +} + +IcePHP::ObjectFactoryI::ObjectFactoryI(const Ice::CommunicatorPtr& communicator) : + _communicator(communicator) +{ +} + +Ice::ObjectPtr +IcePHP::ObjectFactoryI::create(const string& id) +{ + CommunicatorMap* m = static_cast<CommunicatorMap*>(ICE_G(communicatorMap)); + assert(m); + CommunicatorMap::iterator p = m->find(_communicator); + assert(p != m->end()); + + CommunicatorInfoIPtr info = p->second; + + zval factory; + ZVAL_UNDEF(&factory); + + // + // Check if the application has registered a factory for this id. + // + ObjectFactoryMap::iterator q = info->objectFactories.find(id); + if(q == info->objectFactories.end()) + { + q = info->objectFactories.find(""); // Look for a default factory. + } + if(q != info->objectFactories.end()) + { + ZVAL_COPY(&factory, &q->second); + } + + // + // Get the type information. + // + ClassInfoPtr cls; + if(id == Ice::Object::ice_staticId()) + { + // + // When the ID is that of Ice::Object, it indicates that the stream has not + // found a factory and is providing us an opportunity to preserve the object. + // + cls = getClassInfoById("::Ice::UnknownSlicedObject"); + } + else + { + cls = getClassInfoById(id); + } + + if(!cls) + { + return 0; + } + + if(!Z_ISUNDEF(factory)) + { + zval arg; + ZVAL_STRINGL(&arg, STRCAST(id.c_str()), static_cast<int>(id.length())); + + zval obj; + ZVAL_UNDEF(&obj); + + zend_try + { + zend_call_method(&factory, 0, 0, const_cast<char*>("create"), sizeof("create") - 1, &obj, 1, &arg, 0); + + } + zend_catch + { + } + zend_end_try(); + + zval_ptr_dtor(&arg); + + // + // Bail out if an exception has already been thrown. + // + if(Z_ISUNDEF(obj) || EG(exception)) + { + throw AbortMarshaling(); + } + + AutoDestroy destroy(&obj); + + if(Z_TYPE(obj) == IS_NULL) + { + return 0; + } + + return new ObjectReader(&obj, cls, info); + } + + // + // If the requested type is an abstract class, then we give up. + // + if(cls->isAbstract) + { + return 0; + } + + // + // Instantiate the object. + // + zval obj; + ZVAL_UNDEF(&obj); + + if(object_init_ex(&obj, const_cast<zend_class_entry*>(cls->zce)) != SUCCESS) + { + throw AbortMarshaling(); + } + + if(!invokeMethod(&obj, ZEND_CONSTRUCTOR_FUNC_NAME)) + { + throw AbortMarshaling(); + } + + + return new ObjectReader(&obj, cls, info); +} + +void +IcePHP::ObjectFactoryI::destroy() +{ + _communicator = 0; +} + +void +IcePHP::ReaperTask::runTimerTask() +{ + IceUtilInternal::MutexPtrLock<IceUtil::Mutex> lock(_registeredCommunicatorsMutex); + + IceUtil::Time now = IceUtil::Time::now(); + RegisteredCommunicatorMap::iterator p = _registeredCommunicators.begin(); + while(p != _registeredCommunicators.end()) + { + if(p->second->lastAccess + IceUtil::Time::seconds(p->second->expires * 60) <= now) + { + try + { + p->second->communicator->destroy(); + } + catch(...) + { + } + _registeredCommunicators.erase(p++); + } + else + { + ++p; + } + } +} diff --git a/php/src/php7/Communicator.h b/php/src/php7/Communicator.h new file mode 100644 index 00000000000..30f07d273e1 --- /dev/null +++ b/php/src/php7/Communicator.h @@ -0,0 +1,60 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +#ifndef ICEPHP_COMMUNICATOR_H +#define ICEPHP_COMMUNICATOR_H + +#include <Config.h> +#include <Ice/CommunicatorF.h> + +// +// Global functions. +// +extern "C" +{ +ZEND_FUNCTION(Ice_initialize); +ZEND_FUNCTION(Ice_register); +ZEND_FUNCTION(Ice_unregister); +ZEND_FUNCTION(Ice_find); +ZEND_FUNCTION(Ice_getProperties); +ZEND_FUNCTION(Ice_identityToString); +ZEND_FUNCTION(Ice_stringToIdentity); +} + +namespace IcePHP +{ + +bool communicatorInit(TSRMLS_D); +bool communicatorShutdown(TSRMLS_D); +bool communicatorRequestInit(TSRMLS_D); +bool communicatorRequestShutdown(TSRMLS_D); + +// +// Class entry. +// +extern zend_class_entry* communicatorClassEntry; + +// +// The CommunicatorInfo class represents a communicator that is in use by a PHP request. +// +class CommunicatorInfo : public IceUtil::Shared +{ +public: + + virtual void getZval(zval* TSRMLS_DC) = 0; + virtual void addRef(TSRMLS_D) = 0; + virtual void decRef(TSRMLS_D) = 0; + + virtual Ice::CommunicatorPtr getCommunicator() const = 0; +}; +typedef IceUtil::Handle<CommunicatorInfo> CommunicatorInfoPtr; + +} // End of namespace IcePHP + +#endif diff --git a/php/src/php7/Config.h b/php/src/php7/Config.h new file mode 100644 index 00000000000..10fb6a77fe3 --- /dev/null +++ b/php/src/php7/Config.h @@ -0,0 +1,122 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +#ifndef ICE_PHP_CONFIG_H +#define ICE_PHP_CONFIG_H + +// +// We need to define WIN32_LEAN_AND_MEAN to avoid redefinition errors in +// winsock2.h. However, we can't define the macro in the Makefile because +// a PHP header defines it without a surrounding #ifndef, so we have to +// undefine it before including the PHP header files. +// +#ifdef _WIN32 +# define WIN32_LEAN_AND_MEAN +#endif + +#include <Ice/Ice.h> + +#ifdef _WIN32 +# undef WIN32_LEAN_AND_MEAN +#endif + +#ifdef _WIN32 +#include <crtdbg.h> +#include <math.h> +#endif + +#ifdef _WIN32 +extern "C" +{ +#endif + +#ifdef _WIN32 +# pragma warning( disable : 4018) // suppress signed/unsigned mismatch in zend_execute.h (PHP 5.3.x) +#elif defined(__GNUC__) +# pragma GCC diagnostic warning "-Wsign-compare" +#endif + +#ifdef _WIN64 +# pragma warning( disable : 4267) // suppress size_t/uint conversion warnings in zend macros for Windows x64 builds +#endif + +#if defined(__GNUC__) && ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) +# pragma GCC diagnostic warning "-Wnarrowing" +#endif + +#include "php.h" + +#ifdef _WIN32 +# pragma warning( default : 4018) +#endif + +#include "php_ini.h" +#include "ext/standard/info.h" +#include "zend_interfaces.h" +#include "zend_exceptions.h" + +#ifdef _WIN32 +} +#endif + +extern zend_module_entry ice_module_entry; +#define phpext_ice_ptr &ice_module_entry + +#ifdef PHP_WIN32 +#define PHP_ICE_API __declspec(dllexport) +#else +#define PHP_ICE_API +#endif + +#ifdef ZTS +#include "TSRM.h" +#endif + +ZEND_MINIT_FUNCTION(ice); +ZEND_MSHUTDOWN_FUNCTION(ice); +ZEND_RINIT_FUNCTION(ice); +ZEND_RSHUTDOWN_FUNCTION(ice); +ZEND_MINFO_FUNCTION(ice); + +ZEND_BEGIN_MODULE_GLOBALS(ice) + void* communicatorMap; + void* idToClassInfoMap; + void* compactIdToClassInfoMap; + void* nameToClassInfoMap; + void* proxyInfoMap; + void* exceptionInfoMap; + zval* unset; +ZEND_END_MODULE_GLOBALS(ice) + +#ifdef ZTS +# define ICE_G(v) TSRMG(ice_globals_id, zend_ice_globals*, v) +#else +# define ICE_G(v) (ice_globals.v) +#endif + +#ifndef Z_ADDREF_P +# ifndef ZVAL_ADDREF +# error "Unknown PHP version" +# endif +# define Z_ADDREF_P(zv) ZVAL_ADDREF(zv) +#endif + +#ifndef ZEND_MN +# define ZEND_MN(name) ZEND_FN(name) +#endif + +// +// Older versions of PHP use char* instead of const char* in many APIs. +// +#ifdef STRCAST +# error "STRCAST already defined!" +#endif +#define STRCAST(s) const_cast<char*>(s) + +#endif
\ No newline at end of file diff --git a/php/src/php7/Connection.cpp b/php/src/php7/Connection.cpp new file mode 100644 index 00000000000..b1942d133c0 --- /dev/null +++ b/php/src/php7/Connection.cpp @@ -0,0 +1,755 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +#include <Connection.h> +#include <Endpoint.h> +#include <Types.h> +#include <Util.h> +#include <IceSSL/IceSSL.h> + +using namespace std; +using namespace IcePHP; + +ZEND_EXTERN_MODULE_GLOBALS(ice) + +// +// Class entries represent the PHP class implementations we have registered. +// +static zend_class_entry* connectionClassEntry = 0; + +static zend_class_entry* connectionInfoClassEntry = 0; +static zend_class_entry* ipConnectionInfoClassEntry = 0; +static zend_class_entry* tcpConnectionInfoClassEntry = 0; +static zend_class_entry* udpConnectionInfoClassEntry = 0; +static zend_class_entry* wsConnectionInfoClassEntry = 0; +static zend_class_entry* sslConnectionInfoClassEntry = 0; +static zend_class_entry* wssConnectionInfoClassEntry = 0; + +// +// Ice::Connection support. +// +static zend_object_handlers _connectionHandlers; +static zend_object_handlers _connectionInfoHandlers; + +extern "C" +{ +static zend_object* handleConnectionAlloc(zend_class_entry*); +static void handleConnectionFreeStorage(zend_object*); +static int handleConnectionCompare(zval*, zval*); + +static zend_object* handleConnectionInfoAlloc(zend_class_entry*); +static void handleConnectionInfoFreeStorage(zend_object*); +} + +ZEND_METHOD(Ice_Connection, __construct) +{ + runtimeError("Connection cannot be instantiated"); +} + +ZEND_METHOD(Ice_Connection, __toString) +{ + if(ZEND_NUM_ARGS() > 0) + { + WRONG_PARAM_COUNT; + } + + Ice::ConnectionPtr _this = Wrapper<Ice::ConnectionPtr>::value(getThis()); + assert(_this); + + try + { + string str = _this->toString(); + RETURN_STRINGL(STRCAST(str.c_str()), static_cast<int>(str.length())); + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_Connection, close) +{ + Ice::ConnectionPtr _this = Wrapper<Ice::ConnectionPtr>::value(getThis()); + assert(_this); + + zend_bool b; + if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("b"), &b) != SUCCESS) + { + RETURN_NULL(); + } + + try + { + _this->close(b ? true : false); + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_Connection, getEndpoint) +{ + if(ZEND_NUM_ARGS() > 0) + { + WRONG_PARAM_COUNT; + } + + Ice::ConnectionPtr _this = Wrapper<Ice::ConnectionPtr>::value(getThis()); + assert(_this); + + try + { + if(!createEndpoint(return_value, _this->getEndpoint())) + { + RETURN_NULL(); + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_Connection, flushBatchRequests) +{ + if(ZEND_NUM_ARGS() > 0) + { + WRONG_PARAM_COUNT; + } + + Ice::ConnectionPtr _this = Wrapper<Ice::ConnectionPtr>::value(getThis()); + assert(_this); + + try + { + _this->flushBatchRequests(); + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_Connection, setACM) +{ + Ice::ConnectionPtr _this = Wrapper<Ice::ConnectionPtr>::value(getThis()); + assert(_this); + + zval* t; + zval* c; + zval* h; + if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("zzz"), &t, &c, &h) != SUCCESS) + { + RETURN_NULL(); + } + + IceUtil::Optional<Ice::Int> timeout; + IceUtil::Optional<Ice::ACMClose> close; + IceUtil::Optional<Ice::ACMHeartbeat> heartbeat; + + if(!isUnset(t)) + { + if(Z_TYPE_P(t) != IS_LONG) + { + invalidArgument("value for 'timeout' argument must be Unset or an integer"); + RETURN_NULL(); + } + timeout = static_cast<Ice::Int>(Z_LVAL_P(t)); + } + + if(!isUnset(c)) + { + if(Z_TYPE_P(c) != IS_LONG) + { + invalidArgument("value for 'close' argument must be Unset or an enumerator of ACMClose"); + RETURN_NULL(); + } + close = static_cast<Ice::ACMClose>(Z_LVAL_P(c)); + } + + if(!isUnset(h)) + { + if(Z_TYPE_P(h) != IS_LONG) + { + invalidArgument("value for 'heartbeat' argument must be Unset or an enumerator of ACMHeartbeat"); + RETURN_NULL(); + } + heartbeat = static_cast<Ice::ACMHeartbeat>(Z_LVAL_P(h)); + } + + try + { + _this->setACM(timeout, close, heartbeat); + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_Connection, getACM) +{ + if(ZEND_NUM_ARGS() > 0) + { + WRONG_PARAM_COUNT; + } + + Ice::ConnectionPtr _this = Wrapper<Ice::ConnectionPtr>::value(getThis()); + assert(_this); + + try + { + Ice::ACM acm = _this->getACM(); + + zend_class_entry* acmClass = idToClass("::Ice::ACM"); + + if(object_init_ex(return_value, const_cast<zend_class_entry*>(acmClass)) != SUCCESS) + { + runtimeError("unable to initialize object of type %s", acmClass->name); + RETURN_NULL(); + } + + add_property_long(return_value, STRCAST("timeout"), static_cast<long>(acm.timeout)); + add_property_long(return_value, STRCAST("close"), static_cast<long>(acm.close)); + add_property_long(return_value, STRCAST("heartbeat"), static_cast<long>(acm.heartbeat)); + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_Connection, type) +{ + if(ZEND_NUM_ARGS() > 0) + { + WRONG_PARAM_COUNT; + } + + Ice::ConnectionPtr _this = Wrapper<Ice::ConnectionPtr>::value(getThis()); + assert(_this); + + try + { + string str = _this->type(); + RETURN_STRINGL(STRCAST(str.c_str()), str.length()); + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_Connection, timeout) +{ + if(ZEND_NUM_ARGS() != 0) + { + WRONG_PARAM_COUNT; + } + + Ice::ConnectionPtr _this = Wrapper<Ice::ConnectionPtr>::value(getThis()); + assert(_this); + + try + { + Ice::Int timeout = _this->timeout(); + ZVAL_LONG(return_value, static_cast<long>(timeout)); + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_Connection, toString) +{ + ZEND_MN(Ice_Connection___toString)(INTERNAL_FUNCTION_PARAM_PASSTHRU); +} + +ZEND_METHOD(Ice_Connection, getInfo) +{ + if(ZEND_NUM_ARGS() != 0) + { + WRONG_PARAM_COUNT; + } + + Ice::ConnectionPtr _this = Wrapper<Ice::ConnectionPtr>::value(getThis()); + assert(_this); + + try + { + Ice::ConnectionInfoPtr info = _this->getInfo(); + if(!createConnectionInfo(return_value, _this->getInfo())) + { + RETURN_NULL(); + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_Connection, setBufferSize) +{ + Ice::ConnectionPtr _this = Wrapper<Ice::ConnectionPtr>::value(getThis()); + assert(_this); + + zval* r; + zval* s; + if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("zz"), &r, &s) != SUCCESS) + { + RETURN_NULL(); + } + + int rcvSize = static_cast<int>(Z_LVAL_P(r)); + int sndSize = static_cast<int>(Z_LVAL_P(s)); + + try + { + _this->setBufferSize(rcvSize, sndSize); + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + RETURN_NULL(); + } +} + +#ifdef _WIN32 +extern "C" +#endif +static zend_object* +handleConnectionAlloc(zend_class_entry* ce) +{ + Wrapper<Ice::ConnectionPtr>* obj = Wrapper<Ice::ConnectionPtr>::create(ce); + assert(obj); + + obj->zobj.handlers = &_connectionHandlers; + + return &obj->zobj; +} + +#ifdef _WIN32 +extern "C" +#endif +static void +handleConnectionFreeStorage(zend_object* object) +{ + Wrapper<Ice::ConnectionPtr>* obj = Wrapper<Ice::ConnectionPtr>::fetch(object); + delete obj->ptr; + zend_object_std_dtor(object); +} + +#ifdef _WIN32 +extern "C" +#endif +static int +handleConnectionCompare(zval* zobj1, zval* zobj2) +{ + // + // PHP guarantees that the objects have the same class. + // + + Ice::ConnectionPtr con1 = Wrapper<Ice::ConnectionPtr>::value(zobj1); + assert(con1); + Ice::ConnectionPtr con2 = Wrapper<Ice::ConnectionPtr>::value(zobj2); + assert(con2); + + if(con1 == con2) + { + return 0; + } + else if(con1 < con2) + { + return -1; + } + else + { + return 1; + } +} + +// +// Necessary to suppress warnings from zend_function_entry in php-5.2. +// +#if defined(__GNUC__) +# pragma GCC diagnostic ignored "-Wwrite-strings" +#endif + +// +// Predefined methods for Connection. +// +static zend_function_entry _interfaceMethods[] = +{ + {0, 0, 0} +}; +static zend_function_entry _connectionClassMethods[] = +{ + ZEND_ME(Ice_Connection, __construct, NULL, ZEND_ACC_PRIVATE|ZEND_ACC_CTOR) + ZEND_ME(Ice_Connection, __toString, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_Connection, close, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_Connection, getEndpoint, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_Connection, flushBatchRequests, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_Connection, setACM, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_Connection, getACM, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_Connection, type, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_Connection, timeout, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_Connection, toString, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_Connection, getInfo, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_Connection, setBufferSize, NULL, ZEND_ACC_PUBLIC) + {0, 0, 0} +}; + +ZEND_METHOD(Ice_ConnectionInfo, __construct) +{ + runtimeError("ConnectionInfo cannot be instantiated"); +} + +// +// Predefined methods for ConnectionInfo. +// +static zend_function_entry _connectionInfoClassMethods[] = +{ + ZEND_ME(Ice_ConnectionInfo, __construct, NULL, ZEND_ACC_PRIVATE|ZEND_ACC_CTOR) + {0, 0, 0} +}; +// +// enable warning again +// +#if defined(__GNUC__) +# pragma GCC diagnostic error "-Wwrite-strings" +#endif + +#ifdef _WIN32 +extern "C" +#endif +static zend_object* +handleConnectionInfoAlloc(zend_class_entry* ce) +{ + Wrapper<Ice::ConnectionInfoPtr>* obj = Wrapper<Ice::ConnectionInfoPtr>::create(ce); + assert(obj); + + obj->zobj.handlers = &_connectionInfoHandlers; + + return &obj->zobj; +} + +#ifdef _WIN32 +extern "C" +#endif +static void +handleConnectionInfoFreeStorage(zend_object* object) +{ + Wrapper<Ice::ConnectionInfoPtr>* obj = Wrapper<Ice::ConnectionInfoPtr>::fetch(object); + delete obj->ptr; + zend_object_std_dtor(object); +} + +bool +IcePHP::connectionInit(void) +{ + // + // We register an interface and a class that implements the interface. This allows + // applications to safely include the Slice-generated code for the type. + // + + // + // Register the Connection interface. + // + zend_class_entry ce; +#ifdef ICEPHP_USE_NAMESPACES + INIT_NS_CLASS_ENTRY(ce, "Ice", "Connection", _interfaceMethods); +#else + INIT_CLASS_ENTRY(ce, "Ice_Connection", _interfaceMethods); +#endif + zend_class_entry* interface = zend_register_internal_interface(&ce); + + // + // Register the Connection class. + // + INIT_CLASS_ENTRY(ce, "IcePHP_Connection", _connectionClassMethods); + ce.create_object = handleConnectionAlloc; + connectionClassEntry = zend_register_internal_class(&ce); + memcpy(&_connectionHandlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); + _connectionHandlers.compare_objects = handleConnectionCompare; + _connectionHandlers.free_obj = handleConnectionFreeStorage; + _connectionHandlers.offset = XtOffsetOf(Wrapper<Ice::ConnectionPtr>, zobj); + zend_class_implements(connectionClassEntry, 1, interface); + + // + // Register the ConnectionInfo class. + // +#ifdef ICEPHP_USE_NAMESPACES + INIT_NS_CLASS_ENTRY(ce, "Ice", "ConnectionInfo", _connectionInfoClassMethods); +#else + INIT_CLASS_ENTRY(ce, "Ice_ConnectionInfo", _connectionInfoClassMethods); +#endif + ce.create_object = handleConnectionInfoAlloc; + connectionInfoClassEntry = zend_register_internal_class(&ce); + memcpy(&_connectionInfoHandlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); + _connectionInfoHandlers.free_obj = handleConnectionInfoFreeStorage; + _connectionInfoHandlers.offset = XtOffsetOf(Wrapper<Ice::ConnectionInfoPtr>, zobj); + zend_declare_property_bool(connectionInfoClassEntry, STRCAST("incoming"), sizeof("incoming") - 1, 0, + ZEND_ACC_PUBLIC); + zend_declare_property_string(connectionInfoClassEntry, STRCAST("adapterName"), sizeof("adapterName") - 1, + STRCAST(""), ZEND_ACC_PUBLIC); + + // + // Register the IPConnectionInfo class. + // +#ifdef ICEPHP_USE_NAMESPACES + INIT_NS_CLASS_ENTRY(ce, "Ice", "IPConnectionInfo", NULL); +#else + INIT_CLASS_ENTRY(ce, "Ice_IPConnectionInfo", NULL); +#endif + ce.create_object = handleConnectionInfoAlloc; + ipConnectionInfoClassEntry = zend_register_internal_class_ex(&ce, connectionInfoClassEntry); + zend_declare_property_string(ipConnectionInfoClassEntry, STRCAST("localAddress"), sizeof("localAddress") - 1, + STRCAST(""), ZEND_ACC_PUBLIC); + zend_declare_property_long(ipConnectionInfoClassEntry, STRCAST("localPort"), sizeof("localPort") - 1, 0, + ZEND_ACC_PUBLIC); + zend_declare_property_string(ipConnectionInfoClassEntry, STRCAST("remoteAddress"), sizeof("remoteAddress") - 1, + STRCAST(""), ZEND_ACC_PUBLIC); + zend_declare_property_long(ipConnectionInfoClassEntry, STRCAST("remotePort"), sizeof("remotePort") - 1, 0, + ZEND_ACC_PUBLIC); + + // + // Register the TCPConnectionInfo class. + // +#ifdef ICEPHP_USE_NAMESPACES + INIT_NS_CLASS_ENTRY(ce, "Ice", "TCPConnectionInfo", NULL); +#else + INIT_CLASS_ENTRY(ce, "Ice_TCPConnectionInfo", NULL); +#endif + ce.create_object = handleConnectionInfoAlloc; + tcpConnectionInfoClassEntry = zend_register_internal_class_ex(&ce, ipConnectionInfoClassEntry); + + // + // Register the UDPConnectionInfo class. + // +#ifdef ICEPHP_USE_NAMESPACES + INIT_NS_CLASS_ENTRY(ce, "Ice", "UDPConnectionInfo", NULL); +#else + INIT_CLASS_ENTRY(ce, "Ice_UDPConnectionInfo", NULL); +#endif + ce.create_object = handleConnectionInfoAlloc; + udpConnectionInfoClassEntry = zend_register_internal_class_ex(&ce, ipConnectionInfoClassEntry); + zend_declare_property_string(udpConnectionInfoClassEntry, STRCAST("mcastAddress"), sizeof("mcastAddress") - 1, + STRCAST(""), ZEND_ACC_PUBLIC); + zend_declare_property_long(udpConnectionInfoClassEntry, STRCAST("mcastPort"), sizeof("mcastPort") - 1, 0, + ZEND_ACC_PUBLIC); + + // + // Register the WSConnectionInfo class. + // +#ifdef ICEPHP_USE_NAMESPACES + INIT_NS_CLASS_ENTRY(ce, "Ice", "WSConnectionInfo", NULL); +#else + INIT_CLASS_ENTRY(ce, "Ice_WSConnectionInfo", NULL); +#endif + ce.create_object = handleConnectionInfoAlloc; + wsConnectionInfoClassEntry = zend_register_internal_class_ex(&ce, ipConnectionInfoClassEntry); + zend_declare_property_string(wsConnectionInfoClassEntry, STRCAST("headers"), sizeof("headers") - 1, + STRCAST(""), ZEND_ACC_PUBLIC); + + // + // Register the SSLConnectionInfo class. + // +#ifdef ICEPHP_USE_NAMESPACES + INIT_NS_CLASS_ENTRY(ce, "Ice", "SSLConnectionInfo", NULL); +#else + INIT_CLASS_ENTRY(ce, "Ice_SSLConnectionInfo", NULL); +#endif + ce.create_object = handleConnectionInfoAlloc; + sslConnectionInfoClassEntry = zend_register_internal_class_ex(&ce, ipConnectionInfoClassEntry); + zend_declare_property_string(sslConnectionInfoClassEntry, STRCAST("cipher"), sizeof("cipher") - 1, + STRCAST(""), ZEND_ACC_PUBLIC); + zend_declare_property_string(sslConnectionInfoClassEntry, STRCAST("certs"), sizeof("certs") - 1, + STRCAST(""), ZEND_ACC_PUBLIC); + zend_declare_property_bool(sslConnectionInfoClassEntry, STRCAST("verified"), sizeof("verified") - 1, 0, + ZEND_ACC_PUBLIC); + + // + // Register the WSConnectionInfo class. + // +#ifdef ICEPHP_USE_NAMESPACES + INIT_NS_CLASS_ENTRY(ce, "Ice", "WSSConnectionInfo", NULL); +#else + INIT_CLASS_ENTRY(ce, "Ice_WSSConnectionInfo", NULL); +#endif + ce.create_object = handleConnectionInfoAlloc; + wssConnectionInfoClassEntry = zend_register_internal_class_ex(&ce, sslConnectionInfoClassEntry); + zend_declare_property_string(wssConnectionInfoClassEntry, STRCAST("headers"), sizeof("headers") - 1, + STRCAST(""), ZEND_ACC_PUBLIC); + + + return true; +} + +bool +IcePHP::createConnection(zval* zv, const Ice::ConnectionPtr& p) +{ + if(object_init_ex(zv, connectionClassEntry) != SUCCESS) + { + runtimeError("unable to initialize connection"); + return false; + } + + Wrapper<Ice::ConnectionPtr>* obj = Wrapper<Ice::ConnectionPtr>::extract(zv); + assert(obj); + assert(!obj->ptr); + obj->ptr = new Ice::ConnectionPtr(p); + + return true; +} + +bool +IcePHP::fetchConnection(zval* zv, Ice::ConnectionPtr& connection) +{ + if(ZVAL_IS_NULL(zv)) + { + connection = 0; + } + else + { + if(Z_TYPE_P(zv) != IS_OBJECT || Z_OBJCE_P(zv) != connectionClassEntry) + { + invalidArgument("value is not a connection"); + return false; + } + Wrapper<Ice::ConnectionPtr>* obj = Wrapper<Ice::ConnectionPtr>::extract(zv); + if(!obj) + { + return false; + } + connection = *obj->ptr; + } + return true; +} + +bool +IcePHP::createConnectionInfo(zval* zv, const Ice::ConnectionInfoPtr& p) +{ + int status; + if(Ice::WSConnectionInfoPtr::dynamicCast(p)) + { + Ice::WSConnectionInfoPtr info = Ice::WSConnectionInfoPtr::dynamicCast(p); + if((status = object_init_ex(zv, wsConnectionInfoClassEntry)) == SUCCESS) + { + zval zmap; + AutoDestroy mapDestroyer(&zmap); + if(createStringMap(&zmap, info->headers)) + { + add_property_zval(zv, STRCAST("headers"), &zmap); + } + else + { + return false; + } + } + } + else if(Ice::TCPConnectionInfoPtr::dynamicCast(p)) + { + status = object_init_ex(zv, tcpConnectionInfoClassEntry); + } + else if(Ice::UDPConnectionInfoPtr::dynamicCast(p)) + { + Ice::UDPConnectionInfoPtr info = Ice::UDPConnectionInfoPtr::dynamicCast(p); + if((status = object_init_ex(zv, udpConnectionInfoClassEntry)) == SUCCESS) + { + add_property_string(zv, STRCAST("mcastAddress"), const_cast<char*>(info->mcastAddress.c_str())); + add_property_long(zv, STRCAST("mcastPort"), static_cast<long>(info->mcastPort)); + } + } + else if(IceSSL::WSSConnectionInfoPtr::dynamicCast(p)) + { + IceSSL::WSSConnectionInfoPtr info = IceSSL::WSSConnectionInfoPtr::dynamicCast(p); + if((status = object_init_ex(zv, wssConnectionInfoClassEntry)) == SUCCESS) + { + zval zmap; + AutoDestroy mapDestroyer(&zmap); + if(createStringMap(&zmap, info->headers)) + { + add_property_zval(zv, STRCAST("headers"), &zmap); + } + else + { + return false; + } + } + } + else if(IceSSL::ConnectionInfoPtr::dynamicCast(p)) + { + status = object_init_ex(zv, sslConnectionInfoClassEntry); + } + else if(Ice::IPConnectionInfoPtr::dynamicCast(p)) + { + status = object_init_ex(zv, ipConnectionInfoClassEntry); + } + else + { + status = object_init_ex(zv, connectionInfoClassEntry); + } + + if(status != SUCCESS) + { + runtimeError("unable to initialize connection info"); + return false; + } + + if(IceSSL::ConnectionInfoPtr::dynamicCast(p)) + { + IceSSL::ConnectionInfoPtr info = IceSSL::ConnectionInfoPtr::dynamicCast(p); + add_property_string(zv, STRCAST("cipher"), const_cast<char*>(info->cipher.c_str())); + add_property_bool(zv, STRCAST("verified"), info->verified ? 1 : 0); + + zval zarr; + AutoDestroy listDestroyer(&zarr); + if(createStringArray(&zarr, info->certs)) + { + add_property_zval(zv, STRCAST("certs"), &zarr); + } + else + { + return false; + } + } + + if(Ice::IPConnectionInfoPtr::dynamicCast(p)) + { + Ice::IPConnectionInfoPtr info = Ice::IPConnectionInfoPtr::dynamicCast(p); + add_property_string(zv, STRCAST("localAddress"), const_cast<char*>(info->localAddress.c_str())); + add_property_long(zv, STRCAST("localPort"), static_cast<long>(info->localPort)); + add_property_string(zv, STRCAST("remoteAddress"), const_cast<char*>(info->remoteAddress.c_str())); + add_property_long(zv, STRCAST("remotePort"), static_cast<long>(info->remotePort)); + } + + add_property_bool(zv, STRCAST("incoming"), p->incoming ? 1 : 0); + add_property_string(zv, STRCAST("adapterName"), const_cast<char*>(p->adapterName.c_str())); + add_property_long(zv, STRCAST("rcvSize"), static_cast<long>(p->rcvSize)); + add_property_long(zv, STRCAST("sndSize"), static_cast<long>(p->sndSize)); + + Wrapper<Ice::ConnectionInfoPtr>* obj = Wrapper<Ice::ConnectionInfoPtr>::extract(zv); + assert(obj); + assert(!obj->ptr); + obj->ptr = new Ice::ConnectionInfoPtr(p); + + return true; +} diff --git a/php/src/php7/Connection.h b/php/src/php7/Connection.h new file mode 100644 index 00000000000..38ae32a56fa --- /dev/null +++ b/php/src/php7/Connection.h @@ -0,0 +1,27 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +#ifndef ICEPHP_CONNECTION_H +#define ICEPHP_CONNECTION_H + +#include <Config.h> + +namespace IcePHP +{ + +bool connectionInit(void); + +bool createConnection(zval*, const Ice::ConnectionPtr&); +bool fetchConnection(zval*, Ice::ConnectionPtr&); + +bool createConnectionInfo(zval*, const Ice::ConnectionInfoPtr&); + +} // End of namespace IcePHP + +#endif diff --git a/php/src/php7/Endpoint.cpp b/php/src/php7/Endpoint.cpp new file mode 100644 index 00000000000..31747200dc7 --- /dev/null +++ b/php/src/php7/Endpoint.cpp @@ -0,0 +1,537 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +#include <Endpoint.h> +#include <Util.h> +#include <IceSSL/EndpointInfo.h> + +using namespace std; +using namespace IcePHP; + +ZEND_EXTERN_MODULE_GLOBALS(ice) + +// +// Class entries representing the PHP class implementations we have registered. +// +static zend_class_entry* endpointClassEntry = 0; + +static zend_class_entry* endpointInfoClassEntry = 0; +static zend_class_entry* ipEndpointInfoClassEntry = 0; +static zend_class_entry* tcpEndpointInfoClassEntry = 0; +static zend_class_entry* udpEndpointInfoClassEntry = 0; +static zend_class_entry* wsEndpointInfoClassEntry = 0; +static zend_class_entry* opaqueEndpointInfoClassEntry = 0; +static zend_class_entry* sslEndpointInfoClassEntry = 0; +static zend_class_entry* wssEndpointInfoClassEntry = 0; + +// +// Ice::Endpoint support. +// +static zend_object_handlers _endpointHandlers; +static zend_object_handlers _endpointInfoHandlers; + +extern "C" +{ +static zend_object* handleEndpointAlloc(zend_class_entry*); +static void handleEndpointFreeStorage(zend_object*); + +static zend_object* handleEndpointInfoAlloc(zend_class_entry*); +static void handleEndpointInfoFreeStorage(zend_object*); +} + +ZEND_METHOD(Ice_Endpoint, __construct) +{ + runtimeError("Endpoint cannot be instantiated"); +} + +ZEND_METHOD(Ice_Endpoint, __toString) +{ + if(ZEND_NUM_ARGS() > 0) + { + WRONG_PARAM_COUNT; + } + + Ice::EndpointPtr _this = Wrapper<Ice::EndpointPtr>::value(getThis()); + assert(_this); + + try + { + string str = _this->toString(); + RETURN_STRINGL(STRCAST(str.c_str()), static_cast<int>(str.length())); + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_Endpoint, toString) +{ + ZEND_MN(Ice_Endpoint___toString)(INTERNAL_FUNCTION_PARAM_PASSTHRU); +} + +ZEND_METHOD(Ice_Endpoint, getInfo) +{ + if(ZEND_NUM_ARGS() > 0) + { + WRONG_PARAM_COUNT; + } + + Ice::EndpointPtr _this = Wrapper<Ice::EndpointPtr>::value(getThis()); + assert(_this); + + if(!createEndpointInfo(return_value, _this->getInfo())) + { + RETURN_NULL(); + } +} + +#ifdef _WIN32 +extern "C" +#endif +static zend_object* +handleEndpointAlloc(zend_class_entry* ce) +{ + Wrapper<Ice::EndpointPtr>* obj = Wrapper<Ice::EndpointPtr>::create(ce); + assert(obj); + + obj->zobj.handlers = &_endpointHandlers; + + return &obj->zobj; +} + +#ifdef _WIN32 +extern "C" +#endif +static void +handleEndpointFreeStorage(zend_object* object) +{ + Wrapper<Ice::EndpointPtr>* obj = Wrapper<Ice::EndpointPtr>::fetch(object); + delete obj->ptr; + zend_object_std_dtor(object); +} + +ZEND_METHOD(Ice_EndpointInfo, __construct) +{ + runtimeError("EndpointInfo cannot be instantiated"); +} + +ZEND_METHOD(Ice_EndpointInfo, type) +{ + if(ZEND_NUM_ARGS() > 0) + { + WRONG_PARAM_COUNT; + } + + Ice::EndpointInfoPtr _this = Wrapper<Ice::EndpointInfoPtr>::value(getThis()); + assert(_this); + + try + { + short type = static_cast<short>(_this->type()); + RETURN_LONG(type); + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_EndpointInfo, datagram) +{ + if(ZEND_NUM_ARGS() > 0) + { + WRONG_PARAM_COUNT; + } + + Ice::EndpointInfoPtr _this = Wrapper<Ice::EndpointInfoPtr>::value(getThis()); + assert(_this); + + try + { + RETURN_BOOL(_this->datagram() ? 1 : 0); + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_EndpointInfo, secure) +{ + if(ZEND_NUM_ARGS() > 0) + { + WRONG_PARAM_COUNT; + } + + Ice::EndpointInfoPtr _this = Wrapper<Ice::EndpointInfoPtr>::value(getThis()); + assert(_this); + + try + { + RETURN_BOOL(_this->secure() ? 1 : 0); + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + RETURN_NULL(); + } +} + +#ifdef _WIN32 +extern "C" +#endif +static zend_object* +handleEndpointInfoAlloc(zend_class_entry* ce) +{ + Wrapper<Ice::EndpointInfoPtr>* obj = Wrapper<Ice::EndpointInfoPtr>::create(ce); + assert(obj); + + obj->zobj.handlers = &_endpointInfoHandlers; + + return &obj->zobj; +} + +#ifdef _WIN32 +extern "C" +#endif +static void +handleEndpointInfoFreeStorage(zend_object* object) +{ + Wrapper<Ice::EndpointInfoPtr>* obj = Wrapper<Ice::EndpointInfoPtr>::fetch(object); + delete obj->ptr; + zend_object_std_dtor(object); +} + +static zend_function_entry _interfaceMethods[] = +{ + {0, 0, 0} +}; + +// +// Necessary to suppress warnings from zend_function_entry in php-5.2. +// +#if defined(__GNUC__) +# pragma GCC diagnostic ignored "-Wwrite-strings" +#endif + +// +// Predefined methods for Endpoint. +// +static zend_function_entry _endpointMethods[] = +{ + ZEND_ME(Ice_Endpoint, __construct, NULL, ZEND_ACC_PRIVATE|ZEND_ACC_CTOR) + ZEND_ME(Ice_Endpoint, __toString, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_Endpoint, toString, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_Endpoint, getInfo, NULL, ZEND_ACC_PUBLIC) + {0, 0, 0} +}; + +// +// Predefined methods for EndpointInfo. +// +static zend_function_entry _endpointInfoMethods[] = +{ + ZEND_ME(Ice_EndpointInfo, __construct, NULL, ZEND_ACC_PRIVATE|ZEND_ACC_CTOR) + ZEND_ME(Ice_EndpointInfo, type, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_EndpointInfo, datagram, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_EndpointInfo, secure, NULL, ZEND_ACC_PUBLIC) + {0, 0, 0} +}; + +// +// enable warning again +// +#if defined(__GNUC__) +# pragma GCC diagnostic error "-Wwrite-strings" +#endif + +bool +IcePHP::endpointInit(void) +{ + // + // Although the Endpoint and EndpointInfo types are defined in Slice, we need to + // define implementations at the time the PHP extension is loaded; we can't wait + // to do this until after the generated code has been loaded. Consequently, we + // define our own placeholder versions of the Slice types so that we can subclass + // them. This essentially means that the generated code for these types is ignored. + // + + // + // Define the Endpoint interface. + // + zend_class_entry ce; +#ifdef ICEPHP_USE_NAMESPACES + INIT_NS_CLASS_ENTRY(ce, "Ice", "Endpoint", _interfaceMethods); +#else + INIT_CLASS_ENTRY(ce, "Ice_Endpoint", _interfaceMethods); +#endif + zend_class_entry* endpointInterface = zend_register_internal_interface(&ce); + + // + // Define a concrete Endpoint implementation class. + // + INIT_CLASS_ENTRY(ce, "IcePHP_Endpoint", _endpointMethods); + ce.create_object = handleEndpointAlloc; + endpointClassEntry = zend_register_internal_class(&ce); + memcpy(&_endpointHandlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); + _endpointHandlers.free_obj = handleEndpointFreeStorage; + _endpointHandlers.offset = XtOffsetOf(Wrapper<Ice::EndpointPtr>, zobj); + zend_class_implements(endpointClassEntry, 1, endpointInterface); + + // + // Define the EndpointInfo class. + // +#ifdef ICEPHP_USE_NAMESPACES + INIT_NS_CLASS_ENTRY(ce, "Ice", "EndpointInfo", _endpointInfoMethods); +#else + INIT_CLASS_ENTRY(ce, "Ice_EndpointInfo", _endpointInfoMethods); +#endif + ce.create_object = handleEndpointInfoAlloc; + endpointInfoClassEntry = zend_register_internal_class(&ce); + memcpy(&_endpointInfoHandlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); + _endpointInfoHandlers.free_obj = handleEndpointInfoFreeStorage; + _endpointInfoHandlers.offset = XtOffsetOf(Wrapper<Ice::EndpointInfoPtr>, zobj); + zend_declare_property_long(endpointInfoClassEntry, STRCAST("timeout"), sizeof("timeout") - 1, 0, + ZEND_ACC_PUBLIC); + zend_declare_property_bool(endpointInfoClassEntry, STRCAST("compress"), sizeof("compress") - 1, 0, + ZEND_ACC_PUBLIC); + + // + // Define the IPEndpointInfo class. + // +#ifdef ICEPHP_USE_NAMESPACES + INIT_NS_CLASS_ENTRY(ce, "Ice", "IPEndpointInfo", NULL); +#else + INIT_CLASS_ENTRY(ce, "Ice_IPEndpointInfo", NULL); +#endif + ce.create_object = handleEndpointInfoAlloc; + ipEndpointInfoClassEntry = zend_register_internal_class_ex(&ce, endpointInfoClassEntry); + zend_declare_property_string(ipEndpointInfoClassEntry, STRCAST("host"), sizeof("host") - 1, STRCAST(""), + ZEND_ACC_PUBLIC); + zend_declare_property_long(ipEndpointInfoClassEntry, STRCAST("port"), sizeof("port") - 1, 0, + ZEND_ACC_PUBLIC); + zend_declare_property_string(ipEndpointInfoClassEntry, STRCAST("sourceAddress"), sizeof("sourceAddress") - 1, + STRCAST(""), ZEND_ACC_PUBLIC); + + // + // Define the TCPEndpointInfo class. + // +#ifdef ICEPHP_USE_NAMESPACES + INIT_NS_CLASS_ENTRY(ce, "Ice", "TCPEndpointInfo", NULL); +#else + INIT_CLASS_ENTRY(ce, "Ice_TCPEndpointInfo", NULL); +#endif + ce.create_object = handleEndpointInfoAlloc; + tcpEndpointInfoClassEntry = zend_register_internal_class_ex(&ce, ipEndpointInfoClassEntry); + + // + // Define the UDPEndpointInfo class. + // +#ifdef ICEPHP_USE_NAMESPACES + INIT_NS_CLASS_ENTRY(ce, "Ice", "UDPEndpointInfo", NULL); +#else + INIT_CLASS_ENTRY(ce, "Ice_UDPEndpointInfo", NULL); +#endif + ce.create_object = handleEndpointInfoAlloc; + udpEndpointInfoClassEntry = zend_register_internal_class_ex(&ce, ipEndpointInfoClassEntry); + zend_declare_property_string(udpEndpointInfoClassEntry, STRCAST("mcastInterface"), sizeof("mcastInterface") - 1, + STRCAST(""), ZEND_ACC_PUBLIC); + zend_declare_property_long(udpEndpointInfoClassEntry, STRCAST("mcastTtl"), sizeof("mcastTtl") - 1, 0, + ZEND_ACC_PUBLIC); + + // + // Define the WSEndpointInfo class. + // +#ifdef ICEPHP_USE_NAMESPACES + INIT_NS_CLASS_ENTRY(ce, "Ice", "WSEndpointInfo", NULL); +#else + INIT_CLASS_ENTRY(ce, "Ice_WSEndpointInfo", NULL); +#endif + ce.create_object = handleEndpointInfoAlloc; + wsEndpointInfoClassEntry = zend_register_internal_class_ex(&ce, ipEndpointInfoClassEntry); + zend_declare_property_string(wsEndpointInfoClassEntry, STRCAST("resource"), sizeof("resource") - 1, + STRCAST(""), ZEND_ACC_PUBLIC); + + // + // Define the OpaqueEndpointInfo class. + // +#ifdef ICEPHP_USE_NAMESPACES + INIT_NS_CLASS_ENTRY(ce, "Ice", "OpaqueEndpointInfo", NULL); +#else + INIT_CLASS_ENTRY(ce, "Ice_OpaqueEndpointInfo", NULL); +#endif + ce.create_object = handleEndpointInfoAlloc; + opaqueEndpointInfoClassEntry = zend_register_internal_class_ex(&ce, endpointInfoClassEntry); + zend_declare_property_null(opaqueEndpointInfoClassEntry, STRCAST("rawEncoding"), sizeof("rawEncoding") - 1, + ZEND_ACC_PUBLIC); + zend_declare_property_null(opaqueEndpointInfoClassEntry, STRCAST("rawBytes"), sizeof("rawBytes") - 1, + ZEND_ACC_PUBLIC); + + // + // Define the SSLEndpointInfo class. + // +#ifdef ICEPHP_USE_NAMESPACES + INIT_NS_CLASS_ENTRY(ce, "Ice", "SSLEndpointInfo", NULL); +#else + INIT_CLASS_ENTRY(ce, "Ice_SSLEndpointInfo", NULL); +#endif + ce.create_object = handleEndpointInfoAlloc; + sslEndpointInfoClassEntry = zend_register_internal_class_ex(&ce, ipEndpointInfoClassEntry); + + // + // Define the WSSEndpointInfo class. + // +#ifdef ICEPHP_USE_NAMESPACES + INIT_NS_CLASS_ENTRY(ce, "Ice", "WSSEndpointInfo", NULL); +#else + INIT_CLASS_ENTRY(ce, "Ice_WSSEndpointInfo", NULL); +#endif + ce.create_object = handleEndpointInfoAlloc; + wssEndpointInfoClassEntry = zend_register_internal_class_ex(&ce, sslEndpointInfoClassEntry); + zend_declare_property_string(wssEndpointInfoClassEntry, STRCAST("resource"), sizeof("resource") - 1, + STRCAST(""), ZEND_ACC_PUBLIC); + + return true; +} + +bool +IcePHP::createEndpoint(zval* zv, const Ice::EndpointPtr& p) +{ + if(object_init_ex(zv, endpointClassEntry) != SUCCESS) + { + runtimeError("unable to initialize endpoint"); + return false; + } + + Wrapper<Ice::EndpointPtr>* obj = Wrapper<Ice::EndpointPtr>::extract(zv); + assert(obj); + assert(!obj->ptr); + obj->ptr = new Ice::EndpointPtr(p); + + return true; +} + +bool +IcePHP::fetchEndpoint(zval* zv, Ice::EndpointPtr& endpoint) +{ + if(ZVAL_IS_NULL(zv)) + { + endpoint = 0; + } + else + { + if(Z_TYPE_P(zv) != IS_OBJECT || !checkClass(Z_OBJCE_P(zv), endpointClassEntry)) + { + invalidArgument("value is not an endpoint"); + return false; + } + Wrapper<Ice::EndpointPtr>* obj = Wrapper<Ice::EndpointPtr>::extract(zv); + if(!obj) + { + return false; + } + endpoint = *obj->ptr; + } + return true; +} + +bool +IcePHP::createEndpointInfo(zval* zv, const Ice::EndpointInfoPtr& p) +{ + int status; + if(Ice::WSEndpointInfoPtr::dynamicCast(p)) + { + Ice::WSEndpointInfoPtr info = Ice::WSEndpointInfoPtr::dynamicCast(p); + if((status = object_init_ex(zv, wsEndpointInfoClassEntry)) == SUCCESS) + { + add_property_string(zv, STRCAST("resource"), const_cast<char*>(info->resource.c_str())); + } + } + else if(Ice::TCPEndpointInfoPtr::dynamicCast(p)) + { + status = object_init_ex(zv, tcpEndpointInfoClassEntry); + } + else if(Ice::UDPEndpointInfoPtr::dynamicCast(p)) + { + Ice::UDPEndpointInfoPtr info = Ice::UDPEndpointInfoPtr::dynamicCast(p); + if((status = object_init_ex(zv, udpEndpointInfoClassEntry)) == SUCCESS) + { + add_property_string(zv, STRCAST("mcastInterface"), const_cast<char*>(info->mcastInterface.c_str())); + add_property_long(zv, STRCAST("mcastTtl"), static_cast<long>(info->mcastTtl)); + } + } + else if(Ice::OpaqueEndpointInfoPtr::dynamicCast(p)) + { + Ice::OpaqueEndpointInfoPtr info = Ice::OpaqueEndpointInfoPtr::dynamicCast(p); + if((status = object_init_ex(zv, opaqueEndpointInfoClassEntry)) == SUCCESS) + { + zval rawEncoding; + createEncodingVersion(&rawEncoding, info->rawEncoding); + add_property_zval(zv, STRCAST("rawEncoding"), &rawEncoding); + zval_ptr_dtor(&rawEncoding); // add_property_zval increased the refcount of rawEncoding + + zval rawBytes; + array_init(&rawBytes); + for(Ice::ByteSeq::iterator i = info->rawBytes.begin(); i != info->rawBytes.end(); ++i) + { + add_next_index_long(&rawBytes, *i & 0xff); + } + add_property_zval(zv, STRCAST("rawBytes"), &rawBytes); + zval_ptr_dtor(&rawBytes); // add_property_zval increased the refcount of rawBytes + } + } + else if(IceSSL::WSSEndpointInfoPtr::dynamicCast(p)) + { + IceSSL::WSSEndpointInfoPtr info = IceSSL::WSSEndpointInfoPtr::dynamicCast(p); + if((status = object_init_ex(zv, wssEndpointInfoClassEntry)) == SUCCESS) + { + add_property_string(zv, STRCAST("resource"), const_cast<char*>(info->resource.c_str())); + } + } + else if(IceSSL::EndpointInfoPtr::dynamicCast(p)) + { + status = object_init_ex(zv, sslEndpointInfoClassEntry); + } + else if(Ice::IPEndpointInfoPtr::dynamicCast(p)) + { + status = object_init_ex(zv, ipEndpointInfoClassEntry); + } + else + { + status = object_init_ex(zv, endpointInfoClassEntry); + } + + if(status != SUCCESS) + { + runtimeError("unable to initialize endpoint info"); + return false; + } + + if(Ice::IPEndpointInfoPtr::dynamicCast(p)) + { + Ice::IPEndpointInfoPtr info = Ice::IPEndpointInfoPtr::dynamicCast(p); + add_property_string(zv, STRCAST("host"), const_cast<char*>(info->host.c_str())); + add_property_long(zv, STRCAST("port"), static_cast<long>(info->port)); + add_property_string(zv, STRCAST("sourceAddress"), const_cast<char*>(info->sourceAddress.c_str())); + } + + add_property_long(zv, STRCAST("timeout"), static_cast<long>(p->timeout)); + add_property_bool(zv, STRCAST("compress"), static_cast<long>(p->compress)); + + Wrapper<Ice::EndpointInfoPtr>* obj = Wrapper<Ice::EndpointInfoPtr>::extract(zv); + assert(obj); + assert(!obj->ptr); + obj->ptr = new Ice::EndpointInfoPtr(p); + + return true; +} diff --git a/php/src/php7/Endpoint.h b/php/src/php7/Endpoint.h new file mode 100644 index 00000000000..b26a388f631 --- /dev/null +++ b/php/src/php7/Endpoint.h @@ -0,0 +1,27 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +#ifndef ICEPHP_ENDPOINT_H +#define ICEPHP_ENDPOINT_H + +#include <Config.h> + +namespace IcePHP +{ + +bool endpointInit(void); + +bool createEndpoint(zval*, const Ice::EndpointPtr&); +bool fetchEndpoint(zval*, Ice::EndpointPtr&); + +bool createEndpointInfo(zval*, const Ice::EndpointInfoPtr&); + +} // End of namespace IcePHP + +#endif diff --git a/php/src/php7/IcePHP.rc b/php/src/php7/IcePHP.rc new file mode 100644 index 00000000000..ee77391769a --- /dev/null +++ b/php/src/php7/IcePHP.rc @@ -0,0 +1,38 @@ +#include "winver.h" + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 3,6,2,0 + PRODUCTVERSION 3,6,2,0 + FILEFLAGSMASK VS_FFI_FILEFLAGSMASK +#ifdef _DEBUG + FILEFLAGS VS_FF_DEBUG + #define INTERNALNAME "php_iced\0" + #define ORIGINALFILENAME "php_iced.dll\0" +#else + FILEFLAGS 0x0L + #define INTERNALNAME "php_ice\0" + #define ORIGINALFILENAME "php_ice.dll\0" +#endif + FILEOS 0x4L + FILETYPE VFT_DLL + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904e4" + BEGIN + VALUE "CompanyName", "ZeroC, Inc.\0" + VALUE "FileDescription", "Ice for PHP Extension\0" + VALUE "FileVersion", "3.6.2\0" + VALUE "InternalName", INTERNALNAME + VALUE "LegalCopyright", "Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.\0" + VALUE "OriginalFilename", ORIGINALFILENAME + VALUE "ProductName", "Ice\0" + VALUE "ProductVersion", "3.6.2\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1252 + END +END diff --git a/php/src/php7/Init.cpp b/php/src/php7/Init.cpp new file mode 100644 index 00000000000..1679703f80a --- /dev/null +++ b/php/src/php7/Init.cpp @@ -0,0 +1,287 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +#include <Communicator.h> +#include <Connection.h> +#include <Endpoint.h> +#include <Logger.h> +#include <Operation.h> +#include <Properties.h> +#include <Proxy.h> +#include <Types.h> +#include <Util.h> + +using namespace std; +using namespace IcePHP; + +ZEND_DECLARE_MODULE_GLOBALS(ice) + +ZEND_BEGIN_ARG_INFO_EX(Ice_initialize_arginfo, 1, ZEND_RETURN_VALUE, static_cast<zend_ulong>(-1)) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(Ice_createProperties_arginfo, 1, ZEND_RETURN_VALUE, static_cast<zend_ulong>(-1)) +ZEND_END_ARG_INFO() + +#define ICEPHP_COMMUNICATOR_FUNCTIONS \ + ZEND_FE(Ice_initialize, Ice_initialize_arginfo) \ + ZEND_FE(Ice_register, NULL) \ + ZEND_FE(Ice_unregister, NULL) \ + ZEND_FE(Ice_find, NULL) \ + ZEND_FE(Ice_getProperties, NULL) \ + ZEND_FE(Ice_identityToString, NULL) \ + ZEND_FE(Ice_stringToIdentity, NULL) + +#ifdef ICEPHP_USE_NAMESPACES +# define ICEPHP_COMMUNICATOR_NS_FUNCTIONS \ + ZEND_NS_FALIAS("Ice", initialize, Ice_initialize, Ice_initialize_arginfo) \ + ZEND_NS_FALIAS("Ice", register, Ice_register, NULL) \ + ZEND_NS_FALIAS("Ice", unregister, Ice_unregister, NULL) \ + ZEND_NS_FALIAS("Ice", find, Ice_find, NULL) \ + ZEND_NS_FALIAS("Ice", getProperties, Ice_getProperties, NULL) \ + ZEND_NS_FALIAS("Ice", identityToString, Ice_identityToString, NULL) \ + ZEND_NS_FALIAS("Ice", stringToIdentity, Ice_stringToIdentity, NULL) +#else +# define ICEPHP_COMMUNICATOR_NS_FUNCTIONS +#endif + +#define ICEPHP_OPERATION_FUNCTIONS \ + ZEND_FE(IcePHP_defineOperation, NULL) + +#define ICEPHP_PROPERTIES_FUNCTIONS \ + ZEND_FE(Ice_createProperties, Ice_createProperties_arginfo) + +#ifdef ICEPHP_USE_NAMESPACES +# define ICEPHP_PROPERTIES_NS_FUNCTIONS \ + ZEND_NS_FALIAS("Ice", createProperties, Ice_createProperties, Ice_createProperties_arginfo) +#else +# define ICEPHP_PROPERTIES_NS_FUNCTIONS +#endif + +#define ICEPHP_TYPE_FUNCTIONS \ + ZEND_FE(IcePHP_defineEnum, NULL) \ + ZEND_FE(IcePHP_defineStruct, NULL) \ + ZEND_FE(IcePHP_defineSequence, NULL) \ + ZEND_FE(IcePHP_defineDictionary, NULL) \ + ZEND_FE(IcePHP_declareProxy, NULL) \ + ZEND_FE(IcePHP_defineProxy, NULL) \ + ZEND_FE(IcePHP_declareClass, NULL) \ + ZEND_FE(IcePHP_defineClass, NULL) \ + ZEND_FE(IcePHP_defineException, NULL) \ + ZEND_FE(IcePHP_stringify, NULL) \ + ZEND_FE(IcePHP_stringifyException, NULL) + +#define ICEPHP_UTIL_FUNCTIONS \ + ZEND_FE(Ice_stringVersion, NULL) \ + ZEND_FE(Ice_intVersion, NULL) \ + ZEND_FE(Ice_generateUUID, NULL) \ + ZEND_FE(Ice_currentProtocol, NULL) \ + ZEND_FE(Ice_currentProtocolEncoding, NULL) \ + ZEND_FE(Ice_currentEncoding, NULL) \ + ZEND_FE(Ice_protocolVersionToString, NULL) \ + ZEND_FE(Ice_stringToProtocolVersion, NULL) \ + ZEND_FE(Ice_encodingVersionToString, NULL) \ + ZEND_FE(Ice_stringToEncodingVersion, NULL) + +#ifdef ICEPHP_USE_NAMESPACES +# define ICEPHP_UTIL_NS_FUNCTIONS \ + ZEND_NS_FALIAS("Ice", stringVersion, Ice_stringVersion, NULL) \ + ZEND_NS_FALIAS("Ice", intVersion, Ice_intVersion, NULL) \ + ZEND_NS_FALIAS("Ice", generateUUID, Ice_generateUUID, NULL) \ + ZEND_NS_FALIAS("Ice", currentProtocol, Ice_currentProtocol, NULL) \ + ZEND_NS_FALIAS("Ice", currentProtocolEncoding, Ice_currentProtocolEncoding, NULL) \ + ZEND_NS_FALIAS("Ice", currentEncoding, Ice_currentEncoding, NULL) \ + ZEND_NS_FALIAS("Ice", protocolVersionToString, Ice_protocolVersionToString, NULL) \ + ZEND_NS_FALIAS("Ice", stringToProtocolVersion, Ice_stringToProtocolVersion, NULL) \ + ZEND_NS_FALIAS("Ice", encodingVersionToString, Ice_encodingVersionToString, NULL) \ + ZEND_NS_FALIAS("Ice", stringToEncodingVersion, Ice_stringToEncodingVersion, NULL) +#else +# define ICEPHP_UTIL_NS_FUNCTIONS +#endif + +// +// Necessary to suppress warnings from zend_function_entry in php-5.2. +// +#if defined(__GNUC__) +# pragma GCC diagnostic ignored "-Wwrite-strings" +#endif + +// +// Entries for all global functions. +// +zend_function_entry ice_functions[] = +{ + ICEPHP_COMMUNICATOR_FUNCTIONS + ICEPHP_COMMUNICATOR_NS_FUNCTIONS + ICEPHP_OPERATION_FUNCTIONS + ICEPHP_PROPERTIES_FUNCTIONS + ICEPHP_PROPERTIES_NS_FUNCTIONS + ICEPHP_TYPE_FUNCTIONS + ICEPHP_UTIL_FUNCTIONS + ICEPHP_UTIL_NS_FUNCTIONS + {0, 0, 0} +}; +// +// enable warning again +// +#if defined(__GNUC__) +# pragma GCC diagnostic error "-Wwrite-strings" +#endif + +// +// The ice_module_entry declaration below generates lots of warnings: +// +// deprecated conversion from string constant to ‘char*’ +// +// We disable them with a pragma. +// +#if defined(__GNUC__) +# pragma GCC diagnostic ignored "-Wwrite-strings" +#endif + +zend_module_entry ice_module_entry = +{ + STANDARD_MODULE_HEADER, + "ice", + ice_functions, + ZEND_MINIT(ice), + ZEND_MSHUTDOWN(ice), + ZEND_RINIT(ice), + ZEND_RSHUTDOWN(ice), + ZEND_MINFO(ice), + NO_VERSION_YET, + STANDARD_MODULE_PROPERTIES +}; + +ZEND_GET_MODULE(ice) + +// +// Declare initialization file entries. +// +PHP_INI_BEGIN() + PHP_INI_ENTRY("ice.config", "", PHP_INI_SYSTEM, 0) + PHP_INI_ENTRY("ice.options", "", PHP_INI_SYSTEM, 0) + PHP_INI_ENTRY("ice.profiles", "", PHP_INI_SYSTEM, 0) + PHP_INI_ENTRY("ice.hide_profiles", "1", PHP_INI_SYSTEM, 0) +PHP_INI_END() + +extern "C" +int initIceGlobals(zend_ice_globals* g) +{ + g->communicatorMap = 0; + g->idToClassInfoMap = 0; + g->compactIdToClassInfoMap = 0; + g->nameToClassInfoMap = 0; + g->proxyInfoMap = 0; + g->exceptionInfoMap = 0; + g->unset = 0; + return SUCCESS; +} + +ZEND_MINIT_FUNCTION(ice) +{ + Ice::registerIceSSL(false); + Ice::registerIceDiscovery(false); + Ice::registerIceLocatorDiscovery(false); + + REGISTER_INI_ENTRIES(); + ZEND_INIT_MODULE_GLOBALS(ice, initIceGlobals, 0); + + if(!communicatorInit()) + { + return FAILURE; + } + + if(!propertiesInit()) + { + return FAILURE; + } + + if(!proxyInit()) + { + return FAILURE; + } + + if(!typesInit(INIT_FUNC_ARGS_PASSTHRU)) + { + return FAILURE; + } + + if(!loggerInit()) + { + return FAILURE; + } + + if(!endpointInit()) + { + return FAILURE; + } + + if(!connectionInit()) + { + return FAILURE; + } + + return SUCCESS; +} + +ZEND_MSHUTDOWN_FUNCTION(ice) +{ + UNREGISTER_INI_ENTRIES(); + + int status = SUCCESS; + + if(!communicatorShutdown()) + { + status = FAILURE; + } + + return status; +} + +ZEND_RINIT_FUNCTION(ice) +{ + ICE_G(communicatorMap) = 0; + + if(!communicatorRequestInit()) + { + return FAILURE; + } + + if(!typesRequestInit()) + { + return FAILURE; + } + + return SUCCESS; +} + +ZEND_RSHUTDOWN_FUNCTION(ice) +{ + if(!communicatorRequestShutdown()) + { + return FAILURE; + } + + if(!typesRequestShutdown()) + { + return FAILURE; + } + + return SUCCESS; +} + +ZEND_MINFO_FUNCTION(ice) +{ + php_info_print_table_start(); + php_info_print_table_header(2, "Ice support", "enabled"); + php_info_print_table_row(2, "Ice version", ICE_STRING_VERSION); + php_info_print_table_end(); + + DISPLAY_INI_ENTRIES(); +} diff --git a/php/src/php7/Logger.cpp b/php/src/php7/Logger.cpp new file mode 100644 index 00000000000..b5c9e962007 --- /dev/null +++ b/php/src/php7/Logger.cpp @@ -0,0 +1,323 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +#include <Logger.h> +#include <Util.h> + +using namespace std; +using namespace IcePHP; + +ZEND_EXTERN_MODULE_GLOBALS(ice) + +// +// Class entries represent the PHP class implementations we have registered. +// +namespace IcePHP +{ +zend_class_entry* loggerClassEntry = 0; +} + +// +// Logger support. +// +static zend_object_handlers _loggerHandlers; + +extern "C" +{ +static zend_object* handleAlloc(zend_class_entry*); +static void handleFreeStorage(zend_object*); +static zend_object* handleClone(zval*); +} + +ZEND_METHOD(Ice_Logger, __construct) +{ + runtimeError("logger objects cannot be instantiated"); +} + +ZEND_METHOD(Ice_Logger, __toString) +{ + if(ZEND_NUM_ARGS() > 0) + { + WRONG_PARAM_COUNT; + } + + RETURN_NULL(); +} + +ZEND_METHOD(Ice_Logger, print) +{ + char* m; + size_t mLen; + + if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("s"), &m, &mLen) == FAILURE) + { + RETURN_NULL(); + } + + Ice::LoggerPtr _this = Wrapper<Ice::LoggerPtr>::value(getThis()); + assert(_this); + + string msg(m, mLen); + try + { + _this->print(msg); + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_Logger, trace) +{ + char* c; + size_t cLen; + char* m; + size_t mLen; + + if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("ss"), &c, &cLen, &m, &mLen) == FAILURE) + { + RETURN_NULL(); + } + + Ice::LoggerPtr _this = Wrapper<Ice::LoggerPtr>::value(getThis()); + assert(_this); + + string category(c, cLen); + string msg(m, mLen); + try + { + _this->trace(category, msg); + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_Logger, warning) +{ + char* m; + size_t mLen; + + if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("s"), &m, &mLen) == FAILURE) + { + RETURN_NULL(); + } + + Ice::LoggerPtr _this = Wrapper<Ice::LoggerPtr>::value(getThis()); + assert(_this); + + string msg(m, mLen); + try + { + _this->warning(msg); + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_Logger, error) +{ + char* m; + size_t mLen; + + if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("s"), &m, &mLen) == FAILURE) + { + RETURN_NULL(); + } + + Ice::LoggerPtr _this = Wrapper<Ice::LoggerPtr>::value(getThis()); + assert(_this); + + string msg(m, mLen); + try + { + _this->error(msg); + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_Logger, cloneWithPrefix) +{ + char* p; + size_t pLen; + + if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("s"), &p, &pLen) == FAILURE) + { + RETURN_NULL(); + } + + Ice::LoggerPtr _this = Wrapper<Ice::LoggerPtr>::value(getThis()); + assert(_this); + + Ice::LoggerPtr clone; + + string prefix(p, pLen); + try + { + clone = _this->cloneWithPrefix(prefix); + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + RETURN_NULL(); + } + + if(!createLogger(return_value, clone)) + { + RETURN_NULL(); + } +} + +#ifdef _WIN32 +extern "C" +#endif +static zend_object* +handleAlloc(zend_class_entry* ce) +{ + Wrapper<Ice::LoggerPtr>* obj = Wrapper<Ice::LoggerPtr>::create(ce); + assert(obj); + + obj->zobj.handlers = &_loggerHandlers; + + return &obj->zobj; +} + +#ifdef _WIN32 +extern "C" +#endif +static void +handleFreeStorage(zend_object* object) +{ + Wrapper<Ice::LoggerPtr>* obj = Wrapper<Ice::LoggerPtr>::fetch(object); + delete obj->ptr; + zend_object_std_dtor(object); +} + +#ifdef _WIN32 +extern "C" +#endif +static zend_object* +handleClone(zval* zv) +{ + php_error_docref(0, E_ERROR, "loggers cannot be cloned"); + return 0; +} + +// +// Necessary to suppress warnings from zend_function_entry in php-5.2. +// +#if defined(__GNUC__) +# pragma GCC diagnostic ignored "-Wwrite-strings" +#endif + +// +// Predefined methods for Logger. +// +static zend_function_entry _interfaceMethods[] = +{ + {0, 0, 0} +}; +static zend_function_entry _classMethods[] = +{ + ZEND_ME(Ice_Logger, __construct, NULL, ZEND_ACC_PRIVATE|ZEND_ACC_CTOR) + ZEND_ME(Ice_Logger, __toString, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_Logger, print, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_Logger, trace, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_Logger, warning, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_Logger, error, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_Logger, cloneWithPrefix, NULL, ZEND_ACC_PUBLIC) + {0, 0, 0} +}; +// +// enable warning again +// +#if defined(__GNUC__) +# pragma GCC diagnostic error "-Wwrite-strings" +#endif + +bool +IcePHP::loggerInit(void) +{ + // + // We register an interface and a class that implements the interface. This allows + // applications to safely include the Slice-generated code for the type. + // + + // + // Register the Logger interface. + // + zend_class_entry ce; +#ifdef ICEPHP_USE_NAMESPACES + INIT_NS_CLASS_ENTRY(ce, "Ice", "Logger", _interfaceMethods); +#else + INIT_CLASS_ENTRY(ce, "Ice_Logger", _interfaceMethods); +#endif + zend_class_entry* interface = zend_register_internal_interface(&ce); + + // + // Register the Logger class. + // + INIT_CLASS_ENTRY(ce, "IcePHP_Logger", _classMethods); + ce.create_object = handleAlloc; + loggerClassEntry = zend_register_internal_class(&ce); + memcpy(&_loggerHandlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); + _loggerHandlers.clone_obj = handleClone; + _loggerHandlers.free_obj = handleFreeStorage; + _loggerHandlers.offset = XtOffsetOf(Wrapper<Ice::LoggerPtr>, zobj); + zend_class_implements(loggerClassEntry, 1, interface); + + return true; +} + +bool +IcePHP::createLogger(zval* zv, const Ice::LoggerPtr& p) +{ + if(object_init_ex(zv, loggerClassEntry) != SUCCESS) + { + runtimeError("unable to initialize logger object"); + return false; + } + + Wrapper<Ice::LoggerPtr>* obj = Wrapper<Ice::LoggerPtr>::extract(zv); + assert(!obj->ptr); + obj->ptr = new Ice::LoggerPtr(p); + + return true; +} + +bool +IcePHP::fetchLogger(zval* zv, Ice::LoggerPtr& p) +{ + if(!ZVAL_IS_NULL(zv)) + { + if(Z_TYPE_P(zv) != IS_OBJECT || Z_OBJCE_P(zv) != loggerClassEntry) + { + invalidArgument("value is not a logger object"); + return false; + } + p = Wrapper<Ice::LoggerPtr>::value(zv); + if(!p) + { + runtimeError("unable to retrieve logger object from object store"); + return false; + } + } + return true; +} diff --git a/php/src/php7/Logger.h b/php/src/php7/Logger.h new file mode 100644 index 00000000000..7ab38b6c42c --- /dev/null +++ b/php/src/php7/Logger.h @@ -0,0 +1,30 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +#ifndef ICEPHP_LOGGER_H +#define ICEPHP_LOGGER_H + +#include <Config.h> + +namespace IcePHP +{ + +bool loggerInit(void); + +bool createLogger(zval*, const Ice::LoggerPtr&); +bool fetchLogger(zval*, Ice::LoggerPtr&); + +// +// Class entry. +// +extern zend_class_entry* loggerClassEntry; + +} // End of namespace IcePHP + +#endif diff --git a/php/src/php7/Makefile b/php/src/php7/Makefile new file mode 100644 index 00000000000..e240186ed0f --- /dev/null +++ b/php/src/php7/Makefile @@ -0,0 +1,39 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved. +# +# This copy of Ice is licensed to you under the terms described in the +# ICE_LICENSE file included in this distribution. +# +# ********************************************************************** + +top_srcdir = ../.. + +LIBNAME = $(call mkphplibname,IcePHP) +SONAME = $(LIBNAME) + +TARGETS = $(libdir)/$(LIBNAME) + +OBJS = Communicator.o \ + Connection.o \ + Endpoint.o \ + Init.o \ + Logger.o \ + Operation.o \ + Properties.o \ + Proxy.o \ + Types.o \ + Util.o + +include $(top_srcdir)/config/Make.rules.php + +CPPFLAGS := -I. $(CPPFLAGS) $(ICE_FLAGS) $(shell $(PHP_CONFIG) --includes) + +LINKWITH := $(ICE_LIBS) $(CXXLIBS) + +$(libdir)/$(LIBNAME): $(OBJS) + rm -f $@ + $(call mkshlib,$@,$(SONAME),$(OBJS),$(LINKWITH)) + +install:: all + $(call installphplib,$(libdir)/$(LIBNAME),$(DESTDIR)$(install_libdir)) diff --git a/php/src/php7/Makefile.mak b/php/src/php7/Makefile.mak new file mode 100644 index 00000000000..c71d7560feb --- /dev/null +++ b/php/src/php7/Makefile.mak @@ -0,0 +1,53 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved. +# +# This copy of Ice is licensed to you under the terms described in the +# ICE_LICENSE file included in this distribution. +# +# ********************************************************************** + +top_srcdir = ..\.. + +LIBNAME = php_ice$(LIBSUFFIX).lib +DLLNAME = $(libdir)\php_ice$(LIBSUFFIX).dll + +TARGETS = $(LIBNAME) $(DLLNAME) + +OBJS = .\Communicator.obj \ + .\Connection.obj \ + .\Endpoint.obj \ + .\Init.obj \ + .\Logger.obj \ + .\Operation.obj \ + .\Properties.obj \ + .\Proxy.obj \ + .\Types.obj \ + .\Util.obj + +!include $(top_srcdir)\config\Make.rules.mak.php + +CPPFLAGS = -I. -I.. $(CPPFLAGS) $(ICE_CPPFLAGS) $(PHP_CPPFLAGS) -DZEND_WIN32_KEEP_INLINE + +!if "$(ARCH)" == "x86" +CPPFLAGS = $(CPPFLAGS) -D_USE_32BIT_TIME_T +!endif + +!if "$(OPTIMIZE)" != "yes" +PDBFLAGS = /pdb:$(LIBNAME:.lib=.pdb) +!endif + +LINKWITH = $(ICE_LIBS) $(PHP_LIBS) $(CXXLIBS) icediscovery$(LIBSUFFIX).lib icelocatordiscovery$(LIBSUFFIX).lib + +$(LIBNAME): $(DLLNAME) + +$(DLLNAME): $(OBJS) IcePHP.res + $(LINK) $(ICE_LDFLAGS) $(PHP_LDFLAGS) $(LD_DLLFLAGS) $(PDBFLAGS) $(OBJS) \ + $(PREOUT)$(DLLNAME) $(PRELIBS)$(LINKWITH) IcePHP.res + move $(DLLNAME:.dll=.lib) $(LIBNAME) + +clean:: + -del /q IcePHP.res + +install:: all + copy $(DLLNAME) "$(install_libdir)" diff --git a/php/src/php7/Operation.cpp b/php/src/php7/Operation.cpp new file mode 100644 index 00000000000..73ee697c470 --- /dev/null +++ b/php/src/php7/Operation.cpp @@ -0,0 +1,875 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +#include <Operation.h> +#include <Communicator.h> +#include <Proxy.h> +#include <Types.h> +#include <Util.h> +#include <Slice/PHPUtil.h> + +using namespace std; +using namespace IcePHP; +using namespace Slice::PHP; + +extern "C" +{ +ZEND_FUNCTION(IcePHP_Operation_call); +} + +namespace IcePHP +{ + +class ParamInfo : public IceUtil::Shared +{ +public: + + TypeInfoPtr type; + bool optional; + int tag; + int pos; +}; +typedef IceUtil::Handle<ParamInfo> ParamInfoPtr; +typedef list<ParamInfoPtr> ParamInfoList; + +// +// Receives an out parameter or return value. +// +class ResultCallback : public UnmarshalCallback +{ +public: + + ResultCallback(); + ~ResultCallback(); + + virtual void unmarshaled(zval*, zval*, void*); + + void unset(void); + + zval zv; +}; +typedef IceUtil::Handle<ResultCallback> ResultCallbackPtr; +typedef vector<ResultCallbackPtr> ResultCallbackList; + +// +// Encapsulates attributes of an operation. +// +class OperationI : public Operation +{ +public: + + OperationI(const char*, Ice::OperationMode, Ice::OperationMode, Ice::FormatType, zval*, zval*, zval*, zval* + ); + ~OperationI(); + + virtual zend_function* function(); + + string name; // On-the-wire name. + Ice::OperationMode mode; + Ice::OperationMode sendMode; + Ice::FormatType format; + ParamInfoList inParams; + ParamInfoList optionalInParams; + ParamInfoList outParams; + ParamInfoList optionalOutParams; + ParamInfoPtr returnType; + ExceptionInfoList exceptions; + bool sendsClasses; + bool returnsClasses; + int numParams; + +private: + + zend_internal_function* _zendFunction; + + static void convertParams(zval*, ParamInfoList&, bool&); + static ParamInfoPtr convertParam(zval*, int); + static void getArgInfo(zend_internal_arg_info&, const ParamInfoPtr&, bool); +}; +typedef IceUtil::Handle<OperationI> OperationIPtr; + +// +// The base class for client-side invocations. +// +class Invocation : virtual public IceUtil::Shared +{ +public: + + Invocation(const Ice::ObjectPrx&, const CommunicatorInfoPtr&); + + virtual void invoke(INTERNAL_FUNCTION_PARAMETERS) = 0; + +protected: + + Ice::ObjectPrx _prx; + CommunicatorInfoPtr _communicator; +}; +typedef IceUtil::Handle<Invocation> InvocationPtr; + +// +// TypedInvocation uses the information in the given operation to validate, marshal, and unmarshal +// parameters and exceptions. +// +class TypedInvocation : virtual public Invocation +{ +public: + + TypedInvocation(const Ice::ObjectPrx&, const CommunicatorInfoPtr&, const OperationIPtr&); + +protected: + + OperationIPtr _op; + + bool prepareRequest(int, zval*, Ice::OutputStreamPtr&, pair<const Ice::Byte*, const Ice::Byte*>&); + void unmarshalResults(int, zval*, zval*, const pair<const Ice::Byte*, const Ice::Byte*>&); + void unmarshalException(zval*, const pair<const Ice::Byte*, const Ice::Byte*>&); + bool validateException(const ExceptionInfoPtr&) const; + void checkTwowayOnly(const Ice::ObjectPrx&) const; +}; + +// +// A synchronous typed invocation. +// +class SyncTypedInvocation : virtual public TypedInvocation +{ +public: + + SyncTypedInvocation(const Ice::ObjectPrx&, const CommunicatorInfoPtr&, const OperationIPtr&); + + virtual void invoke(INTERNAL_FUNCTION_PARAMETERS); +}; + +class UserExceptionReaderFactoryI : public Ice::UserExceptionReaderFactory +{ +public: + + UserExceptionReaderFactoryI(const CommunicatorInfoPtr& communicator) : + _communicator(communicator) + { + } + + virtual void createAndThrow(const string& id) const + { + ExceptionInfoPtr info = getExceptionInfo(id); + if(info) + { + throw ExceptionReader(_communicator, info); + } + } + +private: + + const CommunicatorInfoPtr _communicator; +}; + +} + +// +// ResultCallback implementation. +// +IcePHP::ResultCallback::ResultCallback() +{ + ZVAL_UNDEF(&zv); +} + +IcePHP::ResultCallback::~ResultCallback() +{ + zval_ptr_dtor(&zv); +} + +void +IcePHP::ResultCallback::unmarshaled(zval* val, zval*, void*) +{ + // + // Copy the unmarshaled value into this result callback + // This increases the refcount for refcounted values and + // coppies non-refcound values + // + ZVAL_COPY(&zv, val); +} + +void +IcePHP::ResultCallback::unset(void) +{ + assignUnset(&zv); +} + +// +// OperationI implementation. +// +IcePHP::OperationI::OperationI(const char* n, Ice::OperationMode m, Ice::OperationMode sm, Ice::FormatType f, zval* in, + zval* out, zval* ret, zval* ex) : + name(n), mode(m), sendMode(sm), format(f), _zendFunction(0) +{ + // + // inParams + // + sendsClasses = false; + if(in) + { + convertParams(in, inParams, sendsClasses); + } + + // + // outParams + // + returnsClasses = false; + if(out) + { + convertParams(out, outParams, returnsClasses); + } + + // + // returnType + // + if(ret) + { + returnType = convertParam(ret, 0); + if(!returnsClasses) + { + returnsClasses = returnType->type->usesClasses(); + } + } + + numParams = static_cast<int>(inParams.size() + outParams.size()); + + class SortFn + { + public: + static bool compare(const ParamInfoPtr& lhs, const ParamInfoPtr& rhs) + { + return lhs->tag < rhs->tag; + } + + static bool isRequired(const ParamInfoPtr& i) + { + return !i->optional; + } + }; + + // + // The inParams list represents the parameters in the order of declaration. + // We also need a sorted list of optional parameters. + // + ParamInfoList l = inParams; + copy(l.begin(), remove_if(l.begin(), l.end(), SortFn::isRequired), back_inserter(optionalInParams)); + optionalInParams.sort(SortFn::compare); + + // + // The outParams list represents the parameters in the order of declaration. + // We also need a sorted list of optional parameters. If the return value is + // optional, we must include it in this list. + // + l = outParams; + copy(l.begin(), remove_if(l.begin(), l.end(), SortFn::isRequired), back_inserter(optionalOutParams)); + if(returnType && returnType->optional) + { + optionalOutParams.push_back(returnType); + } + optionalOutParams.sort(SortFn::compare); + + // + // exceptions + // + if(ex) + { + HashTable* arr = Z_ARRVAL_P(ex); + zval* val; + + ZEND_HASH_FOREACH_VAL(arr, val) + { + ExceptionInfoPtr i = Wrapper<ExceptionInfoPtr>::value(val); + exceptions.push_back(i); + } + ZEND_HASH_FOREACH_END(); + } +} + +IcePHP::OperationI::~OperationI() +{ + if(_zendFunction) + { + delete []_zendFunction->arg_info; + zend_string_release(_zendFunction->function_name); + efree(_zendFunction); + } +} + +zend_function* +IcePHP::OperationI::function() +{ + if(!_zendFunction) + { + // + // Create an array that indicates how arguments are passed to the operation. + // + zend_internal_arg_info* argInfo = new zend_internal_arg_info[numParams]; + + int i = 0; + ParamInfoList::const_iterator p; + for(p = inParams.begin(); p != inParams.end(); ++p, ++i) + { + getArgInfo(argInfo[i], *p, false); + } + for(p = outParams.begin(); p != outParams.end(); ++p, ++i) + { + getArgInfo(argInfo[i], *p, true); + } + + string fixed = fixIdent(name); + + _zendFunction = static_cast<zend_internal_function*>(emalloc(sizeof(zend_internal_function))); + _zendFunction->type = ZEND_INTERNAL_FUNCTION; + _zendFunction->function_name = zend_string_init(STRCAST(fixed.c_str()), static_cast<uint32_t>(fixed.length()), 0); + _zendFunction->scope = proxyClassEntry; + _zendFunction->fn_flags = ZEND_ACC_PUBLIC; + _zendFunction->prototype = 0; + _zendFunction->num_args = static_cast<uint32_t>(numParams); + _zendFunction->arg_info = argInfo; + _zendFunction->required_num_args = _zendFunction->num_args; + _zendFunction->handler = ZEND_FN(IcePHP_Operation_call); + zend_set_function_arg_flags(reinterpret_cast<zend_function*>(_zendFunction)); + } + + return reinterpret_cast<zend_function*>(_zendFunction); +} + +void +IcePHP::OperationI::convertParams(zval* p, ParamInfoList& params, bool& usesClasses) +{ + assert(Z_TYPE_P(p) == IS_ARRAY); + HashTable* arr = Z_ARRVAL_P(p); + zval* val; + Ice::Int i = 0; + ZEND_HASH_FOREACH_VAL(arr, val) + { + ParamInfoPtr param = convertParam(val, i++); + params.push_back(param); + if(!param->optional && !usesClasses) + { + usesClasses = param->type->usesClasses(); + } + } + ZEND_HASH_FOREACH_END(); +} + +ParamInfoPtr +IcePHP::OperationI::convertParam(zval* p, int pos) +{ + assert(Z_TYPE_P(p) == IS_ARRAY); + HashTable* arr = Z_ARRVAL_P(p); + assert(zend_hash_num_elements(arr) == 3); + + ParamInfoPtr param = new ParamInfo; + + param->type = Wrapper<TypeInfoPtr>::value(zend_hash_index_find(arr, 0)); + + assert(Z_TYPE_P(zend_hash_index_find(arr, 1)) == IS_TRUE || Z_TYPE_P(zend_hash_index_find(arr, 1)) == IS_FALSE); + param->optional = Z_TYPE_P(zend_hash_index_find(arr, 1)) == IS_TRUE; + + assert(Z_TYPE_P(zend_hash_index_find(arr, 2)) == IS_LONG); + param->tag = static_cast<int>(Z_LVAL_P(zend_hash_index_find(arr, 2))); + + param->pos = pos; + + return param; +} + +void +IcePHP::OperationI::getArgInfo(zend_internal_arg_info& arg, const ParamInfoPtr& info, bool out) +{ + arg.name = 0; + arg.class_name = 0; + arg.allow_null = 1; + + if(!info->optional) + { + const bool isArray = SequenceInfoPtr::dynamicCast(info->type) || DictionaryInfoPtr::dynamicCast(info->type); + arg.type_hint = isArray ? IS_ARRAY : 0; + + } + else + { + arg.type_hint = 0; + } + + arg.pass_by_reference = out ? 1 : 0; +} + +// +// Invocation +// +IcePHP::Invocation::Invocation(const Ice::ObjectPrx& prx, const CommunicatorInfoPtr& communicator) : + _prx(prx), _communicator(communicator) +{ +} + +// +// TypedInvocation +// +IcePHP::TypedInvocation::TypedInvocation(const Ice::ObjectPrx& prx, const CommunicatorInfoPtr& communicator, + const OperationIPtr& op) : + Invocation(prx, communicator), _op(op) +{ +} + +bool +IcePHP::TypedInvocation::prepareRequest(int argc, zval* args, Ice::OutputStreamPtr& os, + pair<const Ice::Byte*, const Ice::Byte*>& params) +{ + // + // Verify that the expected number of arguments are supplied. The context argument is optional. + // + if(argc != _op->numParams && argc != _op->numParams + 1) + { + runtimeError("incorrect number of parameters (%d)", argc); + return false; + } + + // + // The operation's configuration (zend_function) forces out parameters + // to be passed by reference. + // + for(int i = static_cast<int>(_op->inParams.size()); i < _op->numParams; ++i) + { + assert(Z_ISREF(args[i])); + } + + if(!_op->inParams.empty()) + { + try + { + // + // Marshal the in parameters. + // + os = Ice::createOutputStream(_communicator->getCommunicator()); + os->startEncapsulation(_prx->ice_getEncodingVersion(), _op->format); + + ObjectMap objectMap; + ParamInfoList::iterator p; + + // + // Validate the supplied arguments. + // + for(p = _op->inParams.begin(); p != _op->inParams.end(); ++p) + { + ParamInfoPtr info = *p; + zval* arg = &args[info->pos]; + assert(!Z_ISREF_P(arg)); + + if((!info->optional || !isUnset(arg)) && !info->type->validate(arg, false)) + { + invalidArgument("invalid value for argument %d in operation `%s'", info->pos + 1, + _op->name.c_str()); + return false; + } + } + + // + // Marshal the required parameters. + // + for(p = _op->inParams.begin(); p != _op->inParams.end(); ++p) + { + ParamInfoPtr info = *p; + if(!info->optional) + { + zval* arg = &args[info->pos]; + assert(!Z_ISREF_P(arg)); + + info->type->marshal(arg, os, &objectMap, false); + } + } + + // + // Marshal the optional parameters. + // + for(p = _op->optionalInParams.begin(); p != _op->optionalInParams.end(); ++p) + { + ParamInfoPtr info = *p; + zval* arg = &args[info->pos]; + assert(!Z_ISREF_P(arg)); + + if(!isUnset(arg) && os->writeOptional(info->tag, info->type->optionalFormat())) + { + info->type->marshal(arg, os, &objectMap, true); + } + } + + if(_op->sendsClasses) + { + os->writePendingObjects(); + } + + os->endEncapsulation(); + params = os->finished(); + } + catch(const AbortMarshaling&) + { + return false; + } + catch(const Ice::Exception& ex) + { + throwException(ex); + return false; + } + } + + return true; +} + +void +IcePHP::TypedInvocation::unmarshalResults(int argc, zval* args, zval* ret, + const pair<const Ice::Byte*, const Ice::Byte*>& bytes) +{ + Ice::InputStreamPtr is = Ice::wrapInputStream(_communicator->getCommunicator(), bytes); + + // + // Store a pointer to a local SlicedDataUtil object as the stream's closure. + // This is necessary to support object unmarshaling (see ObjectReader). + // + SlicedDataUtil util; + assert(!is->closure()); + is->closure(&util); + + is->startEncapsulation(); + + ParamInfoList::iterator p; + + // + // These callbacks collect references (copies for unreferenced types) to the unmarshaled values. + // We copy them into the argument list *after* any pending objects have been unmarshaled. + // + ResultCallbackList outParamCallbacks; + ResultCallbackPtr retCallback; + + outParamCallbacks.resize(_op->outParams.size()); + + // + // Unmarshal the required out parameters. + // + for(p = _op->outParams.begin(); p != _op->outParams.end(); ++p) + { + ParamInfoPtr info = *p; + if(!info->optional) + { + ResultCallbackPtr cb = new ResultCallback; + outParamCallbacks[info->pos] = cb; + info->type->unmarshal(is, cb, _communicator, 0, 0, false); + } + } + + // + // Unmarshal the required return value, if any. + // + if(_op->returnType && !_op->returnType->optional) + { + retCallback = new ResultCallback; + _op->returnType->type->unmarshal(is, retCallback, _communicator, 0, 0, false); + } + + // + // Unmarshal the optional results. This includes an optional return value. + // + for(p = _op->optionalOutParams.begin(); p != _op->optionalOutParams.end(); ++p) + { + ParamInfoPtr info = *p; + + ResultCallbackPtr cb = new ResultCallback; + if(_op->returnType && info->tag == _op->returnType->tag) + { + retCallback = cb; + } + else + { + outParamCallbacks[info->pos] = cb; + } + + if(is->readOptional(info->tag, info->type->optionalFormat())) + { + info->type->unmarshal(is, cb, _communicator, 0, 0, true); + } + else + { + cb->unset(); + } + } + + if(_op->returnsClasses) + { + is->readPendingObjects(); + } + + is->endEncapsulation(); + + util.update(); + + int i = static_cast<int>(_op->inParams.size()); + for(ResultCallbackList::iterator q = outParamCallbacks.begin(); q != outParamCallbacks.end(); ++q, ++i) + { + assert(Z_ISREF(args[i])); + + // + // We must explicitly destroy the existing contents of all zvals passed + // as out parameters, otherwise leaks occur. + // + zval* arg = Z_REFVAL_P(&args[i]); + zval_ptr_dtor(arg); + ZVAL_DUP(arg, &(*q)->zv); + } + + if(_op->returnType) + { + ZVAL_DUP(ret, &retCallback->zv); + } +} + +void +IcePHP::TypedInvocation::unmarshalException(zval* zex, const pair<const Ice::Byte*, const Ice::Byte*>& bytes) +{ + Ice::InputStreamPtr is = Ice::wrapInputStream(_communicator->getCommunicator(), bytes); + + // + // Store a pointer to a local SlicedDataUtil object as the stream's closure. + // This is necessary to support object unmarshaling (see ObjectReader). + // + SlicedDataUtil util; + assert(!is->closure()); + is->closure(&util); + + is->startEncapsulation(); + + try + { + Ice::UserExceptionReaderFactoryPtr factory = new UserExceptionReaderFactoryI(_communicator); + is->throwException(factory); + } + catch(const ExceptionReader& r) + { + is->endEncapsulation(); + + zval* ex = r.getException(); + ExceptionInfoPtr info = r.getInfo(); + + if(validateException(info)) + { + util.update(); + + Ice::SlicedDataPtr slicedData = r.getSlicedData(); + if(slicedData) + { + SlicedDataUtil::setMember(ex, slicedData); + } + ZVAL_DUP(zex, ex); + return; + } + else + { + zval_ptr_dtor(ex); + Ice::UnknownUserException uue(__FILE__, __LINE__, + "operation raised undeclared exception `" + info->id + "'"); + convertException(zex, uue); + return; + } + } + + // + // Getting here should be impossible: we can get here only if the + // sender has marshaled a sequence of type IDs, none of which we + // have a factory for. This means that sender and receiver disagree + // about the Slice definitions they use. + // + Ice::UnknownUserException uue(__FILE__, __LINE__, "unknown exception"); + convertException(zex, uue); +} + +bool +IcePHP::TypedInvocation::validateException(const ExceptionInfoPtr& info) const +{ + for(ExceptionInfoList::const_iterator p = _op->exceptions.begin(); p != _op->exceptions.end(); ++p) + { + if(info->isA((*p)->id)) + { + return true; + } + } + + return false; +} + +void +IcePHP::TypedInvocation::checkTwowayOnly(const Ice::ObjectPrx& proxy) const +{ + if((_op->returnType || !_op->outParams.empty()) && !proxy->ice_isTwoway()) + { + Ice::TwowayOnlyException ex(__FILE__, __LINE__); + ex.operation = _op->name; + throw ex; + } +} + +// +// SyncTypedInvocation +// +IcePHP::SyncTypedInvocation::SyncTypedInvocation(const Ice::ObjectPrx& prx, const CommunicatorInfoPtr& communicator, + const OperationIPtr& op) : + Invocation(prx, communicator), TypedInvocation(prx, communicator, op) +{ +} + +void +IcePHP::SyncTypedInvocation::invoke(INTERNAL_FUNCTION_PARAMETERS) +{ + // + // Retrieve the arguments. + // + zval* args = static_cast<zval*>(emalloc(ZEND_NUM_ARGS() * sizeof(zval))); + AutoEfree autoArgs(args); // Call efree on return + if(zend_get_parameters_array_ex(ZEND_NUM_ARGS(), args) == FAILURE) + { + runtimeError("unable to get arguments"); + return; + } + + Ice::OutputStreamPtr os; + pair<const Ice::Byte*, const Ice::Byte*> params; + if(!prepareRequest(ZEND_NUM_ARGS(), args, os, params)) + { + return; + } + + bool hasCtx = false; + Ice::Context ctx; + if(ZEND_NUM_ARGS() == static_cast<uint32_t>(_op->numParams) + 1) + { + if(!extractStringMap(&args[ZEND_NUM_ARGS() - 1], ctx)) + { + return; + } + hasCtx = true; + } + + try + { + checkTwowayOnly(_prx); + + // + // Invoke the operation. + // + vector<Ice::Byte> result; + bool status; + { + if(hasCtx) + { + status = _prx->ice_invoke(_op->name, _op->sendMode, params, result, ctx); + } + else + { + status = _prx->ice_invoke(_op->name, _op->sendMode, params, result); + } + } + + // + // Process the reply. + // + if(_prx->ice_isTwoway()) + { + if(!status) + { + // + // Unmarshal a user exception. + // + pair<const Ice::Byte*, const Ice::Byte*> rb(0, 0); + if(!result.empty()) + { + rb.first = &result[0]; + rb.second = &result[0] + result.size(); + } + + zval ex; + unmarshalException(&ex, rb); + if(!Z_ISUNDEF(ex)) + { + zend_throw_exception_object(&ex); + } + } + else if(!_op->outParams.empty() || _op->returnType) + { + // + // Unmarshal the results. + // + pair<const Ice::Byte*, const Ice::Byte*> rb(0, 0); + if(!result.empty()) + { + rb.first = &result[0]; + rb.second = &result[0] + result.size(); + } + unmarshalResults(ZEND_NUM_ARGS(), args, return_value, rb); + } + } + } + catch(const AbortMarshaling&) + { + } + catch(const Ice::Exception& ex) + { + throwException(ex); + } +} + +ZEND_FUNCTION(IcePHP_defineOperation) +{ + zval* cls; + char* name; + size_t nameLen; + zend_long mode; + zend_long sendMode; + zend_long format; + zval* inParams; + zval* outParams; + zval* returnType; + zval* exceptions; + + if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("osllla!a!a!a!"), &cls, &name, &nameLen, + &mode, &sendMode, &format, &inParams, &outParams, &returnType, &exceptions) == FAILURE) + { + return; + } + + TypeInfoPtr type = Wrapper<TypeInfoPtr>::value(cls); + ClassInfoPtr c = ClassInfoPtr::dynamicCast(type); + assert(c); + + OperationIPtr op = new OperationI(name, static_cast<Ice::OperationMode>(mode), + static_cast<Ice::OperationMode>(sendMode), static_cast<Ice::FormatType>(format), + inParams, outParams, returnType, exceptions); + + c->addOperation(name, op); +} + +ZEND_FUNCTION(IcePHP_Operation_call) +{ + Ice::ObjectPrx proxy; + ClassInfoPtr cls; + CommunicatorInfoPtr comm; +#ifndef NDEBUG + bool b = +#endif + fetchProxy(getThis(), proxy, cls, comm); + assert(b); + assert(proxy); + assert(cls); + + OperationPtr op = cls->getOperation(get_active_function_name()); + assert(op); // handleGetMethod should have already verified the operation's existence. + OperationIPtr opi = OperationIPtr::dynamicCast(op); + assert(opi); + + InvocationPtr inv = new SyncTypedInvocation(proxy, comm, opi); + inv->invoke(INTERNAL_FUNCTION_PARAM_PASSTHRU); +} diff --git a/php/src/php7/Operation.h b/php/src/php7/Operation.h new file mode 100644 index 00000000000..91230201bc4 --- /dev/null +++ b/php/src/php7/Operation.h @@ -0,0 +1,37 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +#ifndef ICEPHP_OPERATION_H +#define ICEPHP_OPERATION_H + +#include <Config.h> + +// +// Global functions. +// +extern "C" +{ +ZEND_FUNCTION(IcePHP_defineOperation); +} + +namespace IcePHP +{ + +class Operation : public IceUtil::Shared +{ +public: + + virtual zend_function* function() = 0; + +}; +typedef IceUtil::Handle<Operation> OperationPtr; + +} + +#endif diff --git a/php/src/php7/Properties.cpp b/php/src/php7/Properties.cpp new file mode 100644 index 00000000000..cfdb779e881 --- /dev/null +++ b/php/src/php7/Properties.cpp @@ -0,0 +1,681 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +#include <Properties.h> +#include <Util.h> + +using namespace std; +using namespace IcePHP; + +ZEND_EXTERN_MODULE_GLOBALS(ice) + +// +// Class entries represent the PHP class implementations we have registered. +// +namespace IcePHP +{ +zend_class_entry* propertiesClassEntry = 0; +} + +// +// Properties support. +// +static zend_object_handlers _handlers; + +extern "C" +{ +static zend_object* handleAlloc(zend_class_entry*); +static void handleFreeStorage(zend_object*); +static zend_object* handleClone(zval*); +} + +ZEND_METHOD(Ice_Properties, __construct) +{ + runtimeError("properties objects cannot be instantiated, use createProperties()"); +} + +ZEND_METHOD(Ice_Properties, __toString) +{ + if(ZEND_NUM_ARGS() > 0) + { + WRONG_PARAM_COUNT; + } + + Ice::PropertiesPtr _this = Wrapper<Ice::PropertiesPtr>::value(getThis()); + assert(_this); + + try + { + Ice::PropertyDict val = _this->getPropertiesForPrefix(""); + string str; + for(Ice::PropertyDict::const_iterator p = val.begin(); p != val.end(); ++p) + { + if(p != val.begin()) + { + str.append("\n"); + } + str.append(p->first + "=" + p->second); + } + RETURN_STRINGL(STRCAST(str.c_str()), static_cast<int>(str.length())); + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_Properties, getProperty) +{ + char* name; + size_t nameLen; + + if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("s"), &name, &nameLen) == FAILURE) + { + RETURN_NULL(); + } + + Ice::PropertiesPtr _this = Wrapper<Ice::PropertiesPtr>::value(getThis()); + assert(_this); + + string propName(name, nameLen); + try + { + string val = _this->getProperty(propName); + RETURN_STRINGL(STRCAST(val.c_str()), static_cast<int>(val.length())); + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_Properties, getPropertyWithDefault) +{ + char* name; + size_t nameLen; + char* def; + size_t defLen; + + if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("ss!"), &name, &nameLen, &def, &defLen) == + FAILURE) + { + RETURN_NULL(); + } + + Ice::PropertiesPtr _this = Wrapper<Ice::PropertiesPtr>::value(getThis()); + assert(_this); + + string propName(name, nameLen); + string defaultValue; + if(def) + { + defaultValue = string(def, defLen); + } + + try + { + string val = _this->getPropertyWithDefault(propName, defaultValue); + RETURN_STRINGL(STRCAST(val.c_str()), static_cast<int>(val.length())); + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_Properties, getPropertyAsInt) +{ + char* name; + size_t nameLen; + + if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("s"), &name, &nameLen) == FAILURE) + { + RETURN_NULL(); + } + + Ice::PropertiesPtr _this = Wrapper<Ice::PropertiesPtr>::value(getThis()); + assert(_this); + + string propName(name, nameLen); + try + { + Ice::Int val = _this->getPropertyAsInt(propName); + RETURN_LONG(static_cast<long>(val)); + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_Properties, getPropertyAsIntWithDefault) +{ + char* name; + size_t nameLen; + long def; + + if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("sl"), &name, &nameLen, &def) == FAILURE) + { + RETURN_NULL(); + } + + Ice::PropertiesPtr _this = Wrapper<Ice::PropertiesPtr>::value(getThis()); + assert(_this); + + string propName(name, nameLen); + try + { + Ice::Int val = _this->getPropertyAsIntWithDefault(propName, def); + RETURN_LONG(static_cast<long>(val)); + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_Properties, getPropertyAsList) +{ + char* name; + size_t nameLen; + + if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("s"), &name, &nameLen) == FAILURE) + { + RETURN_NULL(); + } + + Ice::PropertiesPtr _this = Wrapper<Ice::PropertiesPtr>::value(getThis()); + assert(_this); + + string propName(name, nameLen); + try + { + Ice::StringSeq val = _this->getPropertyAsList(propName); + if(!createStringArray(return_value, val)) + { + RETURN_NULL(); + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_Properties, getPropertyAsListWithDefault) +{ + char* name; + size_t nameLen; + zval* def; + + if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("sa!"), &name, &nameLen, &def) == FAILURE) + { + RETURN_NULL(); + } + + Ice::PropertiesPtr _this = Wrapper<Ice::PropertiesPtr>::value(getThis()); + assert(_this); + + string propName(name, nameLen); + Ice::StringSeq defaultValue; + if(def && !extractStringArray(def, defaultValue)) + { + RETURN_NULL(); + } + + try + { + Ice::StringSeq val = _this->getPropertyAsListWithDefault(propName, defaultValue); + if(!createStringArray(return_value, val)) + { + RETURN_NULL(); + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_Properties, getPropertiesForPrefix) +{ + char* p; + size_t pLen; + + if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("s!"), &p, &pLen) == FAILURE) + { + RETURN_NULL(); + } + + Ice::PropertiesPtr _this = Wrapper<Ice::PropertiesPtr>::value(getThis()); + assert(_this); + + string prefix; + if(p) + { + prefix = string(p, pLen); + } + + try + { + Ice::PropertyDict val = _this->getPropertiesForPrefix(prefix); + if(!createStringMap(return_value, val)) + { + RETURN_NULL(); + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_Properties, setProperty) +{ + char* name; + size_t nameLen; + char* val; + size_t valLen; + + if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("ss!"), &name, &nameLen, &val, &valLen) == + FAILURE) + { + RETURN_NULL(); + } + + Ice::PropertiesPtr _this = Wrapper<Ice::PropertiesPtr>::value(getThis()); + assert(_this); + + string propName(name, nameLen); + string propValue; + if(val) + { + propValue = string(val, valLen); + } + + try + { + _this->setProperty(propName, propValue); + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_Properties, getCommandLineOptions) +{ + if(ZEND_NUM_ARGS() != 0) + { + WRONG_PARAM_COUNT; + } + + Ice::PropertiesPtr _this = Wrapper<Ice::PropertiesPtr>::value(getThis()); + assert(_this); + + try + { + Ice::StringSeq val = _this->getCommandLineOptions(); + if(!createStringArray(return_value, val)) + { + RETURN_NULL(); + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_Properties, parseCommandLineOptions) +{ + char* p; + size_t pLen; + zval* opts; + + if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("s!a!"), &p, &pLen, &opts) == FAILURE) + { + RETURN_NULL(); + } + + Ice::PropertiesPtr _this = Wrapper<Ice::PropertiesPtr>::value(getThis()); + assert(_this); + + string prefix; + if(p) + { + prefix = string(p, pLen); + } + Ice::StringSeq options; + if(opts && !extractStringArray(opts, options)) + { + RETURN_NULL(); + } + + try + { + Ice::StringSeq val = _this->parseCommandLineOptions(prefix, options); + if(!createStringArray(return_value, val)) + { + RETURN_NULL(); + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_Properties, parseIceCommandLineOptions) +{ + zval* opts; + + if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("a!"), &opts) == FAILURE) + { + RETURN_NULL(); + } + + Ice::PropertiesPtr _this = Wrapper<Ice::PropertiesPtr>::value(getThis()); + assert(_this); + + Ice::StringSeq options; + if(opts && !extractStringArray(opts, options)) + { + RETURN_NULL(); + } + + try + { + Ice::StringSeq val = _this->parseIceCommandLineOptions(options); + if(!createStringArray(return_value, val)) + { + RETURN_NULL(); + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_Properties, load) +{ + char* f; + size_t fLen; + + if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("s"), &f, &fLen) == FAILURE) + { + RETURN_NULL(); + } + + Ice::PropertiesPtr _this = Wrapper<Ice::PropertiesPtr>::value(getThis()); + assert(_this); + + string file(f, fLen); + + try + { + _this->load(file); + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_Properties, clone) +{ + if(ZEND_NUM_ARGS() > 0) + { + WRONG_PARAM_COUNT; + } + + Ice::PropertiesPtr _this = Wrapper<Ice::PropertiesPtr>::value(getThis()); + assert(_this); + + try + { + Ice::PropertiesPtr pclone = _this->clone(); + + if(!createProperties(return_value, pclone)) + { + RETURN_NULL(); + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + RETURN_NULL(); + } +} + +#ifdef _WIN32 +extern "C" +#endif +static zend_object* +handleAlloc(zend_class_entry* ce) +{ + Wrapper<Ice::PropertiesPtr>* obj = Wrapper<Ice::PropertiesPtr>::create(ce); + assert(obj); + + obj->zobj.handlers = &_handlers; + + return &obj->zobj; +} + +#ifdef _WIN32 +extern "C" +#endif +static void +handleFreeStorage(zend_object* object) +{ + Wrapper<Ice::PropertiesPtr>* obj = Wrapper<Ice::PropertiesPtr>::fetch(object); + delete obj->ptr; + zend_object_std_dtor(object); +} + +#ifdef _WIN32 +extern "C" +#endif +static zend_object* +handleClone(zval* zv) +{ + Ice::PropertiesPtr p = Wrapper<Ice::PropertiesPtr>::value(zv); + assert(p); + + Ice::PropertiesPtr pclone = p->clone(); + + zval clone; + if(!createProperties(&clone, pclone)) + { + return 0; + } + + return Z_OBJ(clone); +} + +ZEND_FUNCTION(Ice_createProperties) +{ + zval* arglist = 0; + zval* defaultsObj = 0; + + if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("|a!O!"), &arglist, &defaultsObj, + propertiesClassEntry) == FAILURE) + { + RETURN_NULL(); + } + + Ice::StringSeq seq; + if(arglist && !extractStringArray(arglist, seq)) + { + RETURN_NULL(); + } + + Ice::PropertiesPtr defaults; + if(defaultsObj && !fetchProperties(defaultsObj, defaults)) + { + RETURN_NULL(); + } + + try + { + Ice::PropertiesPtr props; + if(arglist || defaults) + { + props = Ice::createProperties(seq, defaults); + } + else + { + props = Ice::createProperties(); + } + + if(!createProperties(return_value, props)) + { + RETURN_NULL(); + } + + if(arglist && Z_ISREF_P(arglist)) + { + zval_dtor(arglist); + if(!createStringArray(arglist, seq)) + { + RETURN_NULL(); + } + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + RETURN_NULL(); + } +} + +// +// Necessary to suppress warnings from zend_function_entry in php-5.2. +// +#if defined(__GNUC__) +# pragma GCC diagnostic ignored "-Wwrite-strings" +#endif + +// +// Predefined methods for Properties. +// +static zend_function_entry _interfaceMethods[] = +{ + {0, 0, 0} +}; +static zend_function_entry _classMethods[] = +{ + ZEND_ME(Ice_Properties, __construct, NULL, ZEND_ACC_PRIVATE|ZEND_ACC_CTOR) + ZEND_ME(Ice_Properties, __toString, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_Properties, getProperty, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_Properties, getPropertyWithDefault, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_Properties, getPropertyAsInt, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_Properties, getPropertyAsIntWithDefault, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_Properties, getPropertyAsList, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_Properties, getPropertyAsListWithDefault, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_Properties, getPropertiesForPrefix, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_Properties, setProperty, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_Properties, getCommandLineOptions, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_Properties, parseCommandLineOptions, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_Properties, parseIceCommandLineOptions, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_Properties, load, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_Properties, clone, NULL, ZEND_ACC_PUBLIC) + {0, 0, 0} +}; + +// +// enable warning again +// +#if defined(__GNUC__) +# pragma GCC diagnostic error "-Wwrite-strings" +#endif + +bool +IcePHP::propertiesInit(void) +{ + // + // We register an interface and a class that implements the interface. This allows + // applications to safely include the Slice-generated code for the type. + // + + // + // Register the Properties interface. + // + zend_class_entry ce; +#ifdef ICEPHP_USE_NAMESPACES + INIT_NS_CLASS_ENTRY(ce, "Ice", "Properties", _interfaceMethods); +#else + INIT_CLASS_ENTRY(ce, "Ice_Properties", _interfaceMethods); +#endif + zend_class_entry* interface = zend_register_internal_interface(&ce); + + // + // Register the Properties class. + // + INIT_CLASS_ENTRY(ce, "IcePHP_Properties", _classMethods); + ce.create_object = handleAlloc; + propertiesClassEntry = zend_register_internal_class(&ce); + memcpy(&_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); + _handlers.clone_obj = handleClone; + _handlers.free_obj = handleFreeStorage; + _handlers.offset = XtOffsetOf(Wrapper<Ice::PropertiesPtr>, zobj); + zend_class_implements(propertiesClassEntry, 1, interface); + + return true; +} + +bool +IcePHP::createProperties(zval* zv, const Ice::PropertiesPtr& p) +{ + if(object_init_ex(zv, propertiesClassEntry) != SUCCESS) + { + runtimeError("unable to initialize properties object"); + return false; + } + + Wrapper<Ice::PropertiesPtr>* obj = Wrapper<Ice::PropertiesPtr>::extract(zv); + assert(!obj->ptr); + obj->ptr = new Ice::PropertiesPtr(p); + + return true; +} + +bool +IcePHP::fetchProperties(zval* zv, Ice::PropertiesPtr& p) +{ + if(!ZVAL_IS_NULL(zv)) + { + if(Z_TYPE_P(zv) != IS_OBJECT || Z_OBJCE_P(zv) != propertiesClassEntry) + { + invalidArgument("value is not a properties object"); + return false; + } + p = Wrapper<Ice::PropertiesPtr>::value(zv); + if(!p) + { + runtimeError("unable to retrieve properties object from object store"); + return false; + } + } + return true; +} diff --git a/php/src/php7/Properties.h b/php/src/php7/Properties.h new file mode 100644 index 00000000000..44584abccfd --- /dev/null +++ b/php/src/php7/Properties.h @@ -0,0 +1,38 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +#ifndef ICEPHP_PROPERTIES_H +#define ICEPHP_PROPERTIES_H + +#include <Config.h> + +// +// Global functions. +// +extern "C" +{ +ZEND_FUNCTION(Ice_createProperties); +} + +namespace IcePHP +{ + +bool propertiesInit(void); + +bool createProperties(zval*, const Ice::PropertiesPtr&); +bool fetchProperties(zval*, Ice::PropertiesPtr&); + +// +// Class entry. +// +extern zend_class_entry* propertiesClassEntry; + +} // End of namespace IcePHP + +#endif diff --git a/php/src/php7/Proxy.cpp b/php/src/php7/Proxy.cpp new file mode 100644 index 00000000000..d9bb45ca0ee --- /dev/null +++ b/php/src/php7/Proxy.cpp @@ -0,0 +1,1718 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +#include <Proxy.h> +#include <Connection.h> +#include <Endpoint.h> +#include <Util.h> + +using namespace std; +using namespace IcePHP; + +ZEND_EXTERN_MODULE_GLOBALS(ice) + +// +// Here's a brief description of how proxies are handled by this extension. +// +// A single PHP class, ObjectPrx, is registered. This is an "internal" class, +// i.e., implemented by this extension, and it is used to represent all proxies +// regardless of interface type. +// +// Like in C++, a proxy is only capable of invoking the Ice::ObjectPrx operations +// until it is narrowed with a checked or unchecked cast. Unlike C++, no PHP classes +// are created for proxies, because all marshaling activity is driven by the type +// definitions, not by statically-generated code. +// +// In order to perform a checked or unchecked cast, the generated code invokes +// ice_checkedCast or ice_uncheckedCast on the proxy to be narrowed, supplying a scoped +// name for the desired type. Internally, the proxy validates the scoped name and returns +// a new proxy containing the class or interface definition. This proxy is considered +// to be narrowed to that interface and therefore supports user-defined operations. +// +// Naturally, there are many predefined proxy methods (e.g., ice_getIdentity, etc.), but +// the proxy also needs to support user-defined operations (if it has type information). +// We use a Zend API hook that allows us to intercept the invocation of unknown methods +// on the proxy object. +// + +// +// Class entries represent the PHP class implementations we have registered. +// +namespace IcePHP +{ +zend_class_entry* proxyClassEntry = 0; +} + +// +// Ice::ObjectPrx support. +// +static zend_object_handlers _handlers; + +extern "C" +{ +static zend_object* handleAlloc(zend_class_entry*); +static void handleFreeStorage(zend_object*); +static zend_object* handleClone(zval*); +static union _zend_function* handleGetMethod(zend_object**, zend_string*, const zval*); +static int handleCompare(zval*, zval*); +} + +static ClassInfoPtr lookupClass(const string&); + +namespace IcePHP +{ + +// +// Encapsulates proxy and type information. +// +class Proxy : public IceUtil::Shared +{ +public: + + Proxy(const Ice::ObjectPrx&, const ClassInfoPtr&, const CommunicatorInfoPtr&); + ~Proxy(); + + bool clone(zval*, const Ice::ObjectPrx&); + bool cloneUntyped(zval*, const Ice::ObjectPrx&); + static bool create(zval*, const Ice::ObjectPrx&, const ClassInfoPtr&, const CommunicatorInfoPtr&); + + Ice::ObjectPrx proxy; + ClassInfoPtr info; + CommunicatorInfoPtr communicator; + zval* connection; + zval* cachedConnection; +}; +typedef IceUtil::Handle<Proxy> ProxyPtr; + +} // End of namespace IcePHP + +ZEND_METHOD(Ice_ObjectPrx, __construct) +{ + runtimeError("proxies cannot be instantiated, use stringToProxy()"); +} + +ZEND_METHOD(Ice_ObjectPrx, __toString) +{ + if(ZEND_NUM_ARGS() > 0) + { + WRONG_PARAM_COUNT; + } + + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis()); + assert(_this); + + try + { + string str = _this->proxy->ice_toString(); + RETURN_STRINGL(STRCAST(str.c_str()), static_cast<int>(str.length())); + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_ObjectPrx, ice_getCommunicator) +{ + if(ZEND_NUM_ARGS() > 0) + { + WRONG_PARAM_COUNT; + } + + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis()); + assert(_this); + + _this->communicator->getZval(return_value); +} + +ZEND_METHOD(Ice_ObjectPrx, ice_toString) +{ + ZEND_MN(Ice_ObjectPrx___toString)(INTERNAL_FUNCTION_PARAM_PASSTHRU); +} + +ZEND_METHOD(Ice_ObjectPrx, ice_getIdentity) +{ + if(ZEND_NUM_ARGS() != 0) + { + WRONG_PARAM_COUNT; + } + + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis()); + assert(_this); + assert(_this->proxy); + + createIdentity(return_value, _this->proxy->ice_getIdentity()); +} + +ZEND_METHOD(Ice_ObjectPrx, ice_identity) +{ + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis()); + assert(_this); + + zend_class_entry* cls = idToClass("::Ice::Identity"); + assert(cls); + + zval *zid; + + if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("O"), &zid, cls) == FAILURE) + { + RETURN_NULL(); + } + + Ice::Identity id; + if(extractIdentity(zid, id)) + { + try + { + if(!_this->cloneUntyped(return_value, _this->proxy->ice_identity(id))) + { + RETURN_NULL(); + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + RETURN_NULL(); + } + } +} + +ZEND_METHOD(Ice_ObjectPrx, ice_getContext) +{ + if(ZEND_NUM_ARGS() != 0) + { + WRONG_PARAM_COUNT; + } + + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis()); + assert(_this); + + if(!createStringMap(return_value, _this->proxy->ice_getContext())) + { + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_ObjectPrx, ice_context) +{ + zval* arr = 0; + + if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("a"), &arr) == FAILURE) + { + RETURN_NULL(); + } + + // + // Populate the context. + // + Ice::Context ctx; + if(arr && !extractStringMap(arr, ctx)) + { + RETURN_NULL(); + } + + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis()); + assert(_this); + + try + { + if(!_this->clone(return_value, _this->proxy->ice_context(ctx))) + { + RETURN_NULL(); + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_ObjectPrx, ice_getFacet) +{ + if(ZEND_NUM_ARGS() != 0) + { + WRONG_PARAM_COUNT; + } + + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis()); + assert(_this); + + try + { + string facet = _this->proxy->ice_getFacet(); + ZVAL_STRINGL(return_value, STRCAST(facet.c_str()), static_cast<int>(facet.length())); + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_ObjectPrx, ice_facet) +{ + char* name; + size_t len; + + if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("s"), &name, &len) == FAILURE) + { + RETURN_NULL(); + } + + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis()); + assert(_this); + + try + { + if(!_this->cloneUntyped(return_value, _this->proxy->ice_facet(name))) + { + RETURN_NULL(); + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_ObjectPrx, ice_getAdapterId) +{ + if(ZEND_NUM_ARGS() != 0) + { + WRONG_PARAM_COUNT; + } + + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis()); + assert(_this); + + try + { + string id = _this->proxy->ice_getAdapterId(); + ZVAL_STRINGL(return_value, STRCAST(id.c_str()), static_cast<int>(id.length())); + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_ObjectPrx, ice_adapterId) +{ + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis()); + assert(_this); + + char* id; + size_t len; + + if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("s"), &id, &len) == FAILURE) + { + RETURN_NULL(); + } + + try + { + if(!_this->clone(return_value, _this->proxy->ice_adapterId(id))) + { + RETURN_NULL(); + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_ObjectPrx, ice_getEndpoints) +{ + if(ZEND_NUM_ARGS() != 0) + { + WRONG_PARAM_COUNT; + } + + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis()); + assert(_this); + + try + { + Ice::EndpointSeq endpoints = _this->proxy->ice_getEndpoints(); + + array_init(return_value); + uint idx = 0; + for(Ice::EndpointSeq::const_iterator p = endpoints.begin(); p != endpoints.end(); ++p, ++idx) + { + zval elem; + if(!createEndpoint(&elem, *p)) + { + zval_ptr_dtor(&elem); + RETURN_NULL(); + } + add_index_zval(return_value, idx, &elem); + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_ObjectPrx, ice_endpoints) +{ + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis()); + assert(_this); + + zval* zv; + + if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("a"), &zv) == FAILURE) + { + RETURN_NULL(); + } + + Ice::EndpointSeq seq; + + HashTable* arr = Z_ARRVAL_P(zv); + zval* val; + ZEND_HASH_FOREACH_VAL(arr, val) + { + if(Z_TYPE_P(val) != IS_OBJECT) + { + runtimeError("expected an element of type Ice::Endpoint"); + RETURN_NULL(); + } + + Ice::EndpointPtr endpoint; + if(!fetchEndpoint(val, endpoint)) + { + RETURN_NULL(); + } + + seq.push_back(endpoint); + } + ZEND_HASH_FOREACH_END(); + + try + { + if(!_this->clone(return_value, _this->proxy->ice_endpoints(seq))) + { + RETURN_NULL(); + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_ObjectPrx, ice_getLocatorCacheTimeout) +{ + if(ZEND_NUM_ARGS() != 0) + { + WRONG_PARAM_COUNT; + } + + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis()); + assert(_this); + + try + { + Ice::Int timeout = _this->proxy->ice_getLocatorCacheTimeout(); + ZVAL_LONG(return_value, static_cast<long>(timeout)); + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_ObjectPrx, ice_getConnectionId) +{ + if(ZEND_NUM_ARGS() != 0) + { + WRONG_PARAM_COUNT; + } + + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis()); + assert(_this); + + try + { + string connectionId = _this->proxy->ice_getConnectionId(); + ZVAL_STRINGL(return_value, STRCAST(connectionId.c_str()), static_cast<int>(connectionId.length())); + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_ObjectPrx, ice_locatorCacheTimeout) +{ + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis()); + assert(_this); + + long l; + if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("l"), &l) != SUCCESS) + { + RETURN_NULL(); + } + + try + { + if(!_this->clone(return_value, _this->proxy->ice_locatorCacheTimeout(l))) + { + RETURN_NULL(); + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_ObjectPrx, ice_isConnectionCached) +{ + if(ZEND_NUM_ARGS() != 0) + { + WRONG_PARAM_COUNT; + } + + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis()); + assert(_this); + + try + { + bool b = _this->proxy->ice_isConnectionCached(); + ZVAL_BOOL(return_value, b ? 1 : 0); + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_ObjectPrx, ice_connectionCached) +{ + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis()); + assert(_this); + + zend_bool b; + if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("b"), &b) != SUCCESS) + { + RETURN_NULL(); + } + + try + { + if(!_this->clone(return_value, _this->proxy->ice_connectionCached(b ? true : false))) + { + RETURN_NULL(); + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_ObjectPrx, ice_getEndpointSelection) +{ + if(ZEND_NUM_ARGS() != 0) + { + WRONG_PARAM_COUNT; + } + + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis()); + assert(_this); + + try + { + Ice::EndpointSelectionType type = _this->proxy->ice_getEndpointSelection(); + ZVAL_LONG(return_value, type == Ice::Random ? 0 : 1); + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_ObjectPrx, ice_endpointSelection) +{ + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis()); + assert(_this); + + long l; + if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("l"), &l) != SUCCESS) + { + RETURN_NULL(); + } + + if(l < 0 || l > 1) + { + runtimeError("expecting Random or Ordered"); + RETURN_NULL(); + } + + try + { + Ice::EndpointSelectionType type = l == 0 ? Ice::Random : Ice::Ordered; + if(!_this->clone(return_value, _this->proxy->ice_endpointSelection(type))) + { + RETURN_NULL(); + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_ObjectPrx, ice_isSecure) +{ + if(ZEND_NUM_ARGS() != 0) + { + WRONG_PARAM_COUNT; + } + + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis()); + assert(_this); + + try + { + bool b = _this->proxy->ice_isSecure(); + RETURN_BOOL(b ? 1 : 0); + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + RETURN_FALSE; + } +} + +ZEND_METHOD(Ice_ObjectPrx, ice_secure) +{ + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis()); + assert(_this); + + zend_bool b; + if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("b"), &b) != SUCCESS) + { + RETURN_NULL(); + } + + try + { + if(!_this->clone(return_value, _this->proxy->ice_secure(b ? true : false))) + { + RETURN_NULL(); + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_ObjectPrx, ice_getEncodingVersion) +{ + if(ZEND_NUM_ARGS() != 0) + { + WRONG_PARAM_COUNT; + } + + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis()); + assert(_this); + + try + { + if(!createEncodingVersion(return_value, _this->proxy->ice_getEncodingVersion())) + { + RETURN_NULL(); + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_ObjectPrx, ice_encodingVersion) +{ + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis()); + assert(_this); + + zend_class_entry* cls = idToClass("::Ice::EncodingVersion"); + assert(cls); + + zval *zv; + if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("O"), &zv, cls) == FAILURE) + { + RETURN_NULL(); + } + + Ice::EncodingVersion v; + if(extractEncodingVersion(zv, v)) + { + try + { + if(!_this->clone(return_value, _this->proxy->ice_encodingVersion(v))) + { + RETURN_NULL(); + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + RETURN_NULL(); + } + } +} + +ZEND_METHOD(Ice_ObjectPrx, ice_isPreferSecure) +{ + if(ZEND_NUM_ARGS() != 0) + { + WRONG_PARAM_COUNT; + } + + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis()); + assert(_this); + + try + { + bool b = _this->proxy->ice_isPreferSecure(); + RETURN_BOOL(b ? 1 : 0); + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + RETURN_FALSE; + } +} + +ZEND_METHOD(Ice_ObjectPrx, ice_preferSecure) +{ + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis()); + assert(_this); + + zend_bool b; + if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("b"), &b) != SUCCESS) + { + RETURN_NULL(); + } + + try + { + if(!_this->clone(return_value, _this->proxy->ice_preferSecure(b ? true : false))) + { + RETURN_NULL(); + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_ObjectPrx, ice_getRouter) +{ + if(ZEND_NUM_ARGS() != 0) + { + WRONG_PARAM_COUNT; + } + + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis()); + assert(_this); + + try + { + Ice::RouterPrx router = _this->proxy->ice_getRouter(); + if(router) + { + ClassInfoPtr info = lookupClass("::Ice::Router"); + if(!info) + { + RETURN_NULL(); + } + + assert(info); + + if(!createProxy(return_value, router, info, _this->communicator)) + { + RETURN_NULL(); + } + } + else + { + RETURN_NULL(); + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + RETURN_FALSE; + } +} + +ZEND_METHOD(Ice_ObjectPrx, ice_router) +{ + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis()); + assert(_this); + + zval* zprx; + if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("O!"), &zprx, proxyClassEntry) != + SUCCESS) + { + RETURN_NULL(); + } + + Ice::ObjectPrx proxy; + ClassInfoPtr def; + if(zprx && !fetchProxy(zprx, proxy, def)) + { + RETURN_NULL(); + } + + Ice::RouterPrx router; + if(proxy) + { + if(!def || !def->isA("::Ice::Router")) + { + runtimeError("ice_router requires a proxy narrowed to Ice::Router"); + RETURN_NULL(); + } + router = Ice::RouterPrx::uncheckedCast(proxy); + } + + try + { + if(!_this->clone(return_value, _this->proxy->ice_router(router))) + { + RETURN_NULL(); + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_ObjectPrx, ice_getLocator) +{ + if(ZEND_NUM_ARGS() != 0) + { + WRONG_PARAM_COUNT; + } + + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis()); + assert(_this); + + try + { + Ice::LocatorPrx locator = _this->proxy->ice_getLocator(); + if(locator) + { + ClassInfoPtr info = lookupClass("::Ice::Locator"); + if(!info) + { + RETURN_NULL(); + } + + if(!createProxy(return_value, locator, info, _this->communicator)) + { + RETURN_NULL(); + } + } + else + { + RETURN_NULL(); + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + RETURN_FALSE; + } +} + +ZEND_METHOD(Ice_ObjectPrx, ice_locator) +{ + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis()); + assert(_this); + + zval* zprx; + if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("O!"), &zprx, proxyClassEntry) != + SUCCESS) + { + RETURN_NULL(); + } + + Ice::ObjectPrx proxy; + ClassInfoPtr def; + if(zprx && !fetchProxy(zprx, proxy, def)) + { + RETURN_NULL(); + } + + Ice::LocatorPrx locator; + if(proxy) + { + if(!def || !def->isA("::Ice::Locator")) + { + runtimeError("ice_locator requires a proxy narrowed to Ice::Locator"); + RETURN_NULL(); + } + locator = Ice::LocatorPrx::uncheckedCast(proxy); + } + + try + { + if(!_this->clone(return_value, _this->proxy->ice_locator(locator))) + { + RETURN_NULL(); + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_ObjectPrx, ice_twoway) +{ + if(ZEND_NUM_ARGS() != 0) + { + WRONG_PARAM_COUNT; + } + + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis()); + assert(_this); + + try + { + if(!_this->clone(return_value, _this->proxy->ice_twoway())) + { + RETURN_NULL(); + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_ObjectPrx, ice_isTwoway) +{ + if(ZEND_NUM_ARGS() != 0) + { + WRONG_PARAM_COUNT; + } + + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis()); + assert(_this); + + try + { + bool b = _this->proxy->ice_isTwoway(); + RETURN_BOOL(b ? 1 : 0); + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + RETURN_FALSE; + } +} + +ZEND_METHOD(Ice_ObjectPrx, ice_oneway) +{ + if(ZEND_NUM_ARGS() != 0) + { + WRONG_PARAM_COUNT; + } + + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis()); + assert(_this); + + try + { + if(!_this->clone(return_value, _this->proxy->ice_oneway())) + { + RETURN_NULL(); + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_ObjectPrx, ice_isOneway) +{ + if(ZEND_NUM_ARGS() != 0) + { + WRONG_PARAM_COUNT; + } + + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis()); + assert(_this); + + try + { + bool b = _this->proxy->ice_isOneway(); + RETURN_BOOL(b ? 1 : 0); + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + RETURN_FALSE; + } +} + +ZEND_METHOD(Ice_ObjectPrx, ice_batchOneway) +{ + if(ZEND_NUM_ARGS() != 0) + { + WRONG_PARAM_COUNT; + } + + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis()); + assert(_this); + + try + { + if(!_this->clone(return_value, _this->proxy->ice_batchOneway())) + { + RETURN_NULL(); + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_ObjectPrx, ice_isBatchOneway) +{ + if(ZEND_NUM_ARGS() != 0) + { + WRONG_PARAM_COUNT; + } + + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis()); + assert(_this); + + try + { + bool b = _this->proxy->ice_isBatchOneway(); + RETURN_BOOL(b ? 1 : 0); + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + RETURN_FALSE; + } +} + +ZEND_METHOD(Ice_ObjectPrx, ice_datagram) +{ + if(ZEND_NUM_ARGS() != 0) + { + WRONG_PARAM_COUNT; + } + + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis()); + assert(_this); + + try + { + if(!_this->clone(return_value, _this->proxy->ice_datagram())) + { + RETURN_NULL(); + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_ObjectPrx, ice_isDatagram) +{ + if(ZEND_NUM_ARGS() != 0) + { + WRONG_PARAM_COUNT; + } + + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis()); + assert(_this); + + try + { + bool b = _this->proxy->ice_isDatagram(); + RETURN_BOOL(b ? 1 : 0); + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + RETURN_FALSE; + } +} + +ZEND_METHOD(Ice_ObjectPrx, ice_batchDatagram) +{ + if(ZEND_NUM_ARGS() != 0) + { + WRONG_PARAM_COUNT; + } + + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis()); + assert(_this); + + try + { + if(!_this->clone(return_value, _this->proxy->ice_batchDatagram())) + { + RETURN_NULL(); + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_ObjectPrx, ice_isBatchDatagram) +{ + if(ZEND_NUM_ARGS() != 0) + { + WRONG_PARAM_COUNT; + } + + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis()); + assert(_this); + + try + { + bool b = _this->proxy->ice_isBatchDatagram(); + RETURN_BOOL(b ? 1 : 0); + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + RETURN_FALSE; + } +} + +ZEND_METHOD(Ice_ObjectPrx, ice_compress) +{ + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis()); + assert(_this); + + zend_bool b; + if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("b"), &b) != SUCCESS) + { + RETURN_NULL(); + } + + try + { + if(!_this->clone(return_value, _this->proxy->ice_compress(b ? true : false))) + { + RETURN_NULL(); + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_ObjectPrx, ice_timeout) +{ + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis()); + assert(_this); + + try + { + long l; + if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("l"), &l) != SUCCESS) + { + RETURN_NULL(); + } + // TODO: range check? + if(!_this->clone(return_value, _this->proxy->ice_timeout(l))) + { + RETURN_NULL(); + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_ObjectPrx, ice_connectionId) +{ + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis()); + assert(_this); + + try + { + char* id; + size_t idLen; + if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("s"), &id, &idLen) != SUCCESS) + { + RETURN_NULL(); + } + if(!_this->clone(return_value, _this->proxy->ice_connectionId(id))) + { + RETURN_NULL(); + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_ObjectPrx, ice_getConnection) +{ + if(ZEND_NUM_ARGS() != 0) + { + WRONG_PARAM_COUNT; + } + + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis()); + assert(_this); + + try + { + Ice::ConnectionPtr con = _this->proxy->ice_getConnection(); + if(!createConnection(return_value, con)) + { + RETURN_NULL(); + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_ObjectPrx, ice_getCachedConnection) +{ + if(ZEND_NUM_ARGS() != 0) + { + WRONG_PARAM_COUNT; + } + + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis()); + assert(_this); + + try + { + Ice::ConnectionPtr con = _this->proxy->ice_getCachedConnection(); + if(!con || !createConnection(return_value, con)) + { + RETURN_NULL(); + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_ObjectPrx, ice_flushBatchRequests) +{ + if(ZEND_NUM_ARGS() != 0) + { + WRONG_PARAM_COUNT; + } + + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis()); + assert(_this); + + try + { + _this->proxy->ice_flushBatchRequests(); + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + RETURN_NULL(); + } +} + +static ClassInfoPtr +lookupClass(const string& id) +{ + ClassInfoPtr info = getClassInfoById(id); + if(!info) + { + if(!id.empty() && id[id.size() - 1] == '*') + { + info = getClassInfoById(id.substr(0, id.size() - 1)); + } + } + + if(info && !info->defined) + { + runtimeError("%s is declared but not defined", id.c_str()); + } + else if(!info) + { + runtimeError("no definition found for class or interface %s", id.c_str()); + } + + return info; +} + +static void +do_cast(INTERNAL_FUNCTION_PARAMETERS, bool check) +{ + // + // First argument is required and should be a scoped name. The second and third arguments + // are optional and represent a facet name, a context, or a facet name followed by a context. + // + if(ZEND_NUM_ARGS() < 1 || ZEND_NUM_ARGS() > 3) + { + WRONG_PARAM_COUNT; + } + + char* id; + size_t idLen; + char* facet = 0; + size_t facetLen; + zval* arr = 0; + + if(zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), const_cast<char*>("s|s!a!"), &id, + &idLen, &facet, &facetLen, &arr) == FAILURE) + { + facet = 0; + if(zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), const_cast<char*>("s|a!"), &id, + &idLen, &arr) == FAILURE) + { + php_error(E_ERROR, "%s() requires a type id followed by an optional facet and/or context", + get_active_function_name()); + return; + } + } + + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis()); + assert(_this); + + // + // Populate the context. + // + Ice::Context ctx; + if(arr && !extractStringMap(arr, ctx)) + { + RETURN_NULL(); + } + + try + { + ClassInfoPtr info = lookupClass(id); + if(!info) + { + RETURN_NULL(); + } + + Ice::ObjectPrx prx = _this->proxy; + if(facet) + { + prx = prx->ice_facet(facet); + } + + if(arr) + { + prx = prx->ice_context(ctx); + } + + if(check) + { + // + // Verify that the object supports the requested type. + // + if(!prx->ice_isA(info->id)) + { + RETURN_NULL(); + } + } + + if(!createProxy(return_value, prx, info, _this->communicator)) + { + RETURN_NULL(); + } + } + catch(const Ice::FacetNotExistException&) + { + // Ignore. + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + RETVAL_FALSE; + } +} + +ZEND_METHOD(Ice_ObjectPrx, ice_uncheckedCast) +{ + do_cast(INTERNAL_FUNCTION_PARAM_PASSTHRU, false); +} + +ZEND_METHOD(Ice_ObjectPrx, ice_checkedCast) +{ + do_cast(INTERNAL_FUNCTION_PARAM_PASSTHRU, true); +} + +IcePHP::Proxy::Proxy(const Ice::ObjectPrx& p, const ClassInfoPtr& i, const CommunicatorInfoPtr& comm) : + proxy(p), info(i), communicator(comm), connection(0), cachedConnection(0) +{ + // + // We want to ensure that the PHP object corresponding to the communicator is + // not destroyed until after this proxy is destroyed. + // + communicator->addRef(); +} + +IcePHP::Proxy::~Proxy() +{ + communicator->decRef(); + if(connection) + { + zval_ptr_dtor(connection); + } + if(cachedConnection) + { + zval_ptr_dtor(cachedConnection); + } +} + +bool +IcePHP::Proxy::clone(zval* zv, const Ice::ObjectPrx& p) +{ + return create(zv, p, info, communicator); +} + +bool +IcePHP::Proxy::cloneUntyped(zval* zv, const Ice::ObjectPrx& p) +{ + return create(zv, p, 0, communicator); +} + +bool +IcePHP::Proxy::create(zval* zv, const Ice::ObjectPrx& p, const ClassInfoPtr& info, const CommunicatorInfoPtr& comm + ) +{ + ClassInfoPtr cls = info; + if(!cls) + { + cls = getClassInfoById("::Ice::Object"); + assert(cls); + } + + if(object_init_ex(zv, proxyClassEntry) != SUCCESS) + { + runtimeError("unable to initialize proxy"); + return false; + } + + Wrapper<ProxyPtr>* obj = Wrapper<ProxyPtr>::extract(zv); + ProxyPtr proxy = new Proxy(p, cls, comm); + assert(!obj->ptr); + obj->ptr = new ProxyPtr(proxy); + return true; +} + +#ifdef _WIN32 +extern "C" +#endif +static zend_object* +handleAlloc(zend_class_entry* ce) +{ + Wrapper<ProxyPtr>* obj = Wrapper<ProxyPtr>::create(ce); + assert(obj); + + obj->zobj.handlers = &_handlers; + + return &obj->zobj; +} + +#ifdef _WIN32 +extern "C" +#endif +static void +handleFreeStorage(zend_object* object) +{ + Wrapper<ProxyPtr>* obj = Wrapper<ProxyPtr>::fetch(object); + delete obj->ptr; + zend_object_std_dtor(object); +} + +#ifdef _WIN32 +extern "C" +#endif +static zend_object* +handleClone(zval* zv) +{ + // + // Create a new object that shares a C++ proxy instance with this object. + // + + ProxyPtr obj = Wrapper<ProxyPtr>::value(zv); + assert(obj); + + zval clone; + if(!obj->clone(&clone, obj->proxy)) + { + return 0; + } + + return Z_OBJ(clone); +} + +#ifdef _WIN32 +extern "C" +#endif +static union _zend_function* +handleGetMethod(zend_object **object, zend_string *name, const zval *key ) +{ + zend_function* result; + // + // First delegate to the standard implementation of get_method. This will find + // any of our predefined proxy methods. If it returns 0, then we return a + // function that will check the class definition. + // + result = zend_get_std_object_handlers()->get_method(object, name, key); + if(!result) + { + Wrapper<ProxyPtr>* obj = Wrapper<ProxyPtr>::fetch(*object); + assert(obj->ptr); + ProxyPtr _this = *obj->ptr; + + ClassInfoPtr info = _this->info; + assert(info); + + OperationPtr op = info->getOperation(name->val); + if(!op) + { + // + // Returning 0 causes PHP to report an "undefined method" error. + // + return 0; + } + + result = op->function(); + } + + return result; +} + +#ifdef _WIN32 +extern "C" +#endif +static int +handleCompare(zval* zobj1, zval* zobj2) +{ + // + // PHP guarantees that the objects have the same class. + // + + Wrapper<ProxyPtr>* obj1 = Wrapper<ProxyPtr>::extract(zobj1); + assert(obj1->ptr); + ProxyPtr _this1 = *obj1->ptr; + Ice::ObjectPrx prx1 = _this1->proxy; + + Wrapper<ProxyPtr>* obj2 = Wrapper<ProxyPtr>::extract(zobj2); + assert(obj2->ptr); + ProxyPtr _this2 = *obj2->ptr; + Ice::ObjectPrx prx2 = _this2->proxy; + + if(prx1 == prx2) + { + return 0; + } + else if(prx1 < prx2) + { + return -1; + } + else + { + return 1; + } +} + +// +// Necessary to suppress warnings from zend_function_entry in php-5.2. +// +#if defined(__GNUC__) +# pragma GCC diagnostic ignored "-Wwrite-strings" +#endif + +// +// Predefined methods for ObjectPrx. +// +static zend_function_entry _proxyMethods[] = +{ + ZEND_ME(Ice_ObjectPrx, __construct, NULL, ZEND_ACC_PRIVATE|ZEND_ACC_CTOR) + ZEND_ME(Ice_ObjectPrx, __toString, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_ObjectPrx, ice_getCommunicator, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_ObjectPrx, ice_toString, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_ObjectPrx, ice_getIdentity, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_ObjectPrx, ice_identity, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_ObjectPrx, ice_getContext, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_ObjectPrx, ice_context, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_ObjectPrx, ice_getFacet, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_ObjectPrx, ice_facet, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_ObjectPrx, ice_getAdapterId, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_ObjectPrx, ice_adapterId, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_ObjectPrx, ice_getEndpoints, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_ObjectPrx, ice_endpoints, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_ObjectPrx, ice_getLocatorCacheTimeout, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_ObjectPrx, ice_getConnectionId, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_ObjectPrx, ice_locatorCacheTimeout, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_ObjectPrx, ice_isConnectionCached, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_ObjectPrx, ice_connectionCached, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_ObjectPrx, ice_getEndpointSelection, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_ObjectPrx, ice_endpointSelection, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_ObjectPrx, ice_isSecure, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_ObjectPrx, ice_secure, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_ObjectPrx, ice_getEncodingVersion, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_ObjectPrx, ice_encodingVersion, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_ObjectPrx, ice_isPreferSecure, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_ObjectPrx, ice_preferSecure, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_ObjectPrx, ice_getRouter, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_ObjectPrx, ice_router, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_ObjectPrx, ice_getLocator, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_ObjectPrx, ice_locator, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_ObjectPrx, ice_twoway, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_ObjectPrx, ice_isTwoway, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_ObjectPrx, ice_oneway, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_ObjectPrx, ice_isOneway, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_ObjectPrx, ice_batchOneway, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_ObjectPrx, ice_isBatchOneway, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_ObjectPrx, ice_datagram, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_ObjectPrx, ice_isDatagram, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_ObjectPrx, ice_batchDatagram, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_ObjectPrx, ice_isBatchDatagram, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_ObjectPrx, ice_compress, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_ObjectPrx, ice_timeout, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_ObjectPrx, ice_connectionId, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_ObjectPrx, ice_getConnection, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_ObjectPrx, ice_getCachedConnection, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_ObjectPrx, ice_flushBatchRequests, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_ObjectPrx, ice_uncheckedCast, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_ObjectPrx, ice_checkedCast, NULL, ZEND_ACC_PUBLIC) + {0, 0, 0} +}; + +// +// enable warning again +// +#if defined(__GNUC__) +# pragma GCC diagnostic error "-Wwrite-strings" +#endif + +bool +IcePHP::proxyInit(void) +{ + // + // Register the ObjectPrx class. + // + zend_class_entry ce; +#ifdef ICEPHP_USE_NAMESPACES + INIT_NS_CLASS_ENTRY(ce, "Ice", "ObjectPrx", _proxyMethods); +#else + INIT_CLASS_ENTRY(ce, "Ice_ObjectPrx", _proxyMethods); +#endif + ce.create_object = handleAlloc; + proxyClassEntry = zend_register_internal_class(&ce); + //proxyClassEntry->ce_flags |= ZEND_ACC_EXPLICIT_ABSTRACT_CLASS; + memcpy(&_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); + _handlers.clone_obj = handleClone; + _handlers.get_method = handleGetMethod; + _handlers.compare_objects = handleCompare; + _handlers.free_obj = handleFreeStorage; + _handlers.offset = XtOffsetOf(Wrapper<ProxyPtr>, zobj); + + return true; +} + +bool +IcePHP::createProxy(zval* zv, const Ice::ObjectPrx& p, const CommunicatorInfoPtr& comm) +{ + return Proxy::create(zv, p, 0, comm); +} + +bool +IcePHP::createProxy(zval* zv, const Ice::ObjectPrx& p, const ClassInfoPtr& info, const CommunicatorInfoPtr& comm + ) +{ + return Proxy::create(zv, p, info, comm); +} + +bool +IcePHP::fetchProxy(zval* zv, Ice::ObjectPrx& prx, ClassInfoPtr& cls) +{ + CommunicatorInfoPtr comm; + return fetchProxy(zv, prx, cls, comm); +} + +bool +IcePHP::fetchProxy(zval* zv, Ice::ObjectPrx& prx, ClassInfoPtr& cls, CommunicatorInfoPtr& comm) +{ + if(!ZVAL_IS_NULL(zv)) + { + if(Z_TYPE_P(zv) != IS_OBJECT || Z_OBJCE_P(zv) != proxyClassEntry) + { + invalidArgument("value is not a proxy"); + return false; + } + Wrapper<ProxyPtr>* obj = Wrapper<ProxyPtr>::extract(zv); + if(!obj) + { + runtimeError("unable to retrieve proxy object from object store"); + return false; + } + assert(obj->ptr); + prx = (*obj->ptr)->proxy; + cls = (*obj->ptr)->info; + comm = (*obj->ptr)->communicator; + } + return true; +} diff --git a/php/src/php7/Proxy.h b/php/src/php7/Proxy.h new file mode 100644 index 00000000000..771e999ea88 --- /dev/null +++ b/php/src/php7/Proxy.h @@ -0,0 +1,34 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +#ifndef ICEPHP_PROXY_H +#define ICEPHP_PROXY_H + +#include <Config.h> +#include <Communicator.h> +#include <Types.h> + +namespace IcePHP +{ + +bool proxyInit(void); + +bool createProxy(zval*, const Ice::ObjectPrx&, const CommunicatorInfoPtr&); +bool createProxy(zval*, const Ice::ObjectPrx&, const ClassInfoPtr&, const CommunicatorInfoPtr&); +bool fetchProxy(zval*, Ice::ObjectPrx&, ClassInfoPtr&); +bool fetchProxy(zval*, Ice::ObjectPrx&, ClassInfoPtr&, CommunicatorInfoPtr&); + +// +// Class entry. +// +extern zend_class_entry* proxyClassEntry; + +} // End of namespace IcePHP + +#endif diff --git a/php/src/php7/Types.cpp b/php/src/php7/Types.cpp new file mode 100644 index 00000000000..a29dade9b50 --- /dev/null +++ b/php/src/php7/Types.cpp @@ -0,0 +1,3973 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +#include <Types.h> +#include <Proxy.h> +#include <Util.h> +#include <IceUtil/InputUtil.h> +#include <IceUtil/OutputUtil.h> +#include <IceUtil/ScopedArray.h> +#include <Slice/PHPUtil.h> +#include <Ice/SlicedData.h> + +#include <limits> + +using namespace std; +using namespace IcePHP; +using namespace IceUtil; +using namespace IceUtilInternal; + +ZEND_EXTERN_MODULE_GLOBALS(ice) + +// +// Class entries represent the PHP class implementations we have registered. +// +namespace IcePHP +{ +zend_class_entry* typeInfoClassEntry = 0; +zend_class_entry* exceptionInfoClassEntry = 0; +} + +static zend_object_handlers _typeInfoHandlers; +static zend_object_handlers _exceptionInfoHandlers; + +static string _unsetGUID = "710A52F2-A014-4CB2-AF40-348D48DBCDDD"; + +extern "C" +{ +static zend_object* handleTypeInfoAlloc(zend_class_entry*); +static void handleTypeInfoFreeStorage(zend_object*); + +static zend_object* handleExceptionInfoAlloc(zend_class_entry*); +static void handleExceptionInfoFreeStorage(zend_object*); +} + +typedef map<string, ProxyInfoPtr> ProxyInfoMap; +typedef map<string, ClassInfoPtr> ClassInfoMap; +typedef map<Ice::Int, ClassInfoPtr> CompactIdMap; +typedef map<string, ExceptionInfoPtr> ExceptionInfoMap; + +// +// addProxyInfo() +// +static void +addProxyInfo(const ProxyInfoPtr& p) +{ + ProxyInfoMap* m; + if(ICE_G(proxyInfoMap)) + { + m = reinterpret_cast<ProxyInfoMap*>(ICE_G(proxyInfoMap)); + } + else + { + m = new ProxyInfoMap; + ICE_G(proxyInfoMap) = m; + } + m->insert(ProxyInfoMap::value_type(p->id, p)); +} + +// +// getProxyInfo() +// +static IcePHP::ProxyInfoPtr +getProxyInfo(const string& id) +{ + if(ICE_G(proxyInfoMap)) + { + ProxyInfoMap* m = reinterpret_cast<ProxyInfoMap*>(ICE_G(proxyInfoMap)); + ProxyInfoMap::iterator p = m->find(id); + if(p != m->end()) + { + return p->second; + } + } + return 0; +} + +namespace IcePHP +{ + +class ReadObjectCallback : public Ice::ReadObjectCallback +{ +public: + + ReadObjectCallback(const ClassInfoPtr&, const UnmarshalCallbackPtr&, zval*, void* TSRMLS_DC); + ~ReadObjectCallback(); + + virtual void invoke(const ::Ice::ObjectPtr&); + +private: + + ClassInfoPtr _info; + UnmarshalCallbackPtr _cb; + zval _target; + void* _closure; +}; + +} + +// +// addClassInfoById() +// +static void +addClassInfoById(const ClassInfoPtr& p) +{ + assert(!getClassInfoById(p->id)); + + ClassInfoMap* m = reinterpret_cast<ClassInfoMap*>(ICE_G(idToClassInfoMap)); + if(!m) + { + m = new ClassInfoMap; + ICE_G(idToClassInfoMap) = m; + } + m->insert(ClassInfoMap::value_type(p->id, p)); +} + +// +// addClassInfoByName() +// +static void +addClassInfoByName(const ClassInfoPtr& p) +{ + assert(!getClassInfoByName(p->name)); +#ifdef ICEPHP_USE_NAMESPACES + assert(name[0] == '\\'); +#endif + + ClassInfoMap* m = reinterpret_cast<ClassInfoMap*>(ICE_G(nameToClassInfoMap)); + if(!m) + { + m = new ClassInfoMap; + ICE_G(nameToClassInfoMap) = m; + } + m->insert(ClassInfoMap::value_type(p->name, p)); +} + +static ClassInfoPtr +getClassInfoByClass(zend_class_entry* cls, zend_class_entry* formal) +{ + // + // See if there's a match in our class name => ClassInfo map. + // + ClassInfoPtr info = getClassInfoByName(cls->name->val); + + // + // Check the base class, assuming it's compatible with our formal type (if any). + // + if(!info && cls->parent && (!formal || checkClass(cls->parent, formal))) + { + info = getClassInfoByClass(cls->parent, formal); + } + + // + // Check interfaces. + // + if(!info) + { + for(zend_ulong i = 0; i < cls->num_interfaces && !info; ++i) + { + if(!formal || checkClass(cls->interfaces[i], formal)) + { + info = getClassInfoByClass(cls->interfaces[i], formal); + } + } + } + + return info; +} + +// +// getClassInfoById() +// +IcePHP::ClassInfoPtr +IcePHP::getClassInfoById(const string& id) +{ + if(ICE_G(idToClassInfoMap)) + { + ClassInfoMap* m = reinterpret_cast<ClassInfoMap*>(ICE_G(idToClassInfoMap)); + ClassInfoMap::iterator p = m->find(id); + if(p != m->end()) + { + return p->second; + } + } + return 0; +} + +// +// getClassInfoByName() +// +IcePHP::ClassInfoPtr +IcePHP::getClassInfoByName(const string& name) +{ + if(ICE_G(nameToClassInfoMap)) + { + string s = name; + +#ifdef ICEPHP_USE_NAMESPACES + // + // PHP's class definition (zend_class_entry) does not use a leading backslash + // in the class name. + // + if(s[0] != '\\') + { + s.insert(0, "\\"); + } +#endif + + ClassInfoMap* m = reinterpret_cast<ClassInfoMap*>(ICE_G(nameToClassInfoMap)); + ClassInfoMap::iterator p = m->find(s); + if(p != m->end()) + { + return p->second; + } + } + return 0; +} + +// +// getExceptionInfo() +// +IcePHP::ExceptionInfoPtr +IcePHP::getExceptionInfo(const string& id) +{ + if(ICE_G(exceptionInfoMap)) + { + ExceptionInfoMap* m = reinterpret_cast<ExceptionInfoMap*>(ICE_G(exceptionInfoMap)); + ExceptionInfoMap::iterator p = m->find(id); + if(p != m->end()) + { + return p->second; + } + } + return 0; +} + +// +// SlicedDataUtil implementation +// +zend_class_entry* IcePHP::SlicedDataUtil::_slicedDataType = 0; +zend_class_entry* IcePHP::SlicedDataUtil::_sliceInfoType = 0; + +IcePHP::SlicedDataUtil::~SlicedDataUtil() +{ + // + // Make sure we break any cycles among the ObjectReaders in preserved slices. + // + for(set<ObjectReaderPtr>::iterator p = _readers.begin(); p != _readers.end(); ++p) + { + Ice::SlicedDataPtr slicedData = (*p)->getSlicedData(); + for(Ice::SliceInfoSeq::const_iterator q = slicedData->slices.begin(); q != slicedData->slices.end(); ++q) + { + // + // Don't just call (*q)->objects.clear(), as releasing references + // to the objects could have unexpected side effects. We exchange + // the vector into a temporary and then let the temporary fall out + // of scope. + // + vector<Ice::ObjectPtr> tmp; + tmp.swap((*q)->objects); + } + } +} + +void +IcePHP::SlicedDataUtil::add(const ObjectReaderPtr& reader) +{ + assert(reader->getSlicedData()); + _readers.insert(reader); +} + +void +IcePHP::SlicedDataUtil::update(void) +{ + for(set<ObjectReaderPtr>::iterator p = _readers.begin(); p != _readers.end(); ++p) + { + setMember((*p)->getObject(), (*p)->getSlicedData()); + } +} + +void +IcePHP::SlicedDataUtil::setMember(zval* obj, const Ice::SlicedDataPtr& slicedData) +{ + // + // Create a PHP equivalent of the SlicedData object. + // + + assert(slicedData); + + if(!_slicedDataType) + { + _slicedDataType = idToClass("::Ice::SlicedData"); + assert(_slicedDataType); + } + if(!_sliceInfoType) + { + _sliceInfoType = idToClass("::Ice::SliceInfo"); + assert(_sliceInfoType); + } + + zval sd; + AutoDestroy sdDestroyer(&sd); + + if(object_init_ex(&sd, _slicedDataType) != SUCCESS) + { + throw AbortMarshaling(); + } + + zval slices; + array_init(&slices); + AutoDestroy slicesDestroyer(&slices); + + if(add_property_zval(&sd, STRCAST("slices"), &slices) != SUCCESS) + { + throw AbortMarshaling(); + } + + // + // Translate each SliceInfo object into its PHP equivalent. + // + for(vector<Ice::SliceInfoPtr>::const_iterator p = slicedData->slices.begin(); p != slicedData->slices.end(); ++p) + { + zval slice; + AutoDestroy sliceDestroyer(&slice); + + if(object_init_ex(&slice, _sliceInfoType) != SUCCESS) + { + throw AbortMarshaling(); + } + + add_next_index_zval(&slices, &slice); // Steals a reference. + Z_ADDREF_P(&slice); + + // + // typeId + // + zval typeId; + AutoDestroy typeIdDestroyer(&typeId); + ZVAL_STRINGL(&typeId, STRCAST((*p)->typeId.c_str()), static_cast<int>((*p)->typeId.size())); + if(add_property_zval(&slice, STRCAST("typeId"), &typeId) != SUCCESS) + { + throw AbortMarshaling(); + } + + // + // compactId + // + zval compactId; + AutoDestroy compactIdDestroyer(&compactId); + ZVAL_LONG(&compactId, (*p)->compactId); + if(add_property_zval(&slice, STRCAST("compactId"), &compactId) != SUCCESS) + { + throw AbortMarshaling(); + } + + // + // bytes + // + zval bytes; + array_init(&bytes); + AutoDestroy bytesDestroyer(&bytes); + for(vector<Ice::Byte>::const_iterator q = (*p)->bytes.begin(); q != (*p)->bytes.end(); ++q) + { + add_next_index_long(&bytes, *q & 0xff); + } + if(add_property_zval(&slice, STRCAST("bytes"), &bytes) != SUCCESS) + { + throw AbortMarshaling(); + } + + // + // objects + // + zval objects; + array_init(&objects); + AutoDestroy objectsDestroyer(&objects); + if(add_property_zval(&slice, STRCAST("objects"), &objects) != SUCCESS) + { + throw AbortMarshaling(); + } + + for(vector<Ice::ObjectPtr>::const_iterator q = (*p)->objects.begin(); q != (*p)->objects.end(); ++q) + { + // + // Each element in the objects list is an instance of ObjectReader that wraps a PHP object. + // + assert(*q); + ObjectReaderPtr r = ObjectReaderPtr::dynamicCast(*q); + assert(r); + zval* o = r->getObject(); + assert(Z_TYPE_P(o) == IS_OBJECT); // Should be non-nil. + add_next_index_zval(&objects, o); // Steals a reference. + Z_ADDREF_P(o); + } + + // + // hasOptionalMembers + // + zval hasOptionalMembers; + AutoDestroy hasOptionalMembersDestroyer(&hasOptionalMembers); + ZVAL_BOOL(&hasOptionalMembers, (*p)->hasOptionalMembers ? 1 : 0); + if(add_property_zval(&slice, STRCAST("hasOptionalMembers"), &hasOptionalMembers) != SUCCESS) + { + throw AbortMarshaling(); + } + + // + // isLastSlice + // + zval isLastSlice; + AutoDestroy isLastSliceDestroyer(&isLastSlice); + ZVAL_BOOL(&isLastSlice, (*p)->isLastSlice ? 1 : 0); + if(add_property_zval(&slice, STRCAST("isLastSlice"), &isLastSlice) != SUCCESS) + { + throw AbortMarshaling(); + } + } + + if(add_property_zval(obj, STRCAST("_ice_slicedData"), &sd) != SUCCESS) + { + throw AbortMarshaling(); + } +} + +// +// Instances of preserved class and exception types may have a data member +// named _ice_slicedData which is an instance of the PHP class Ice_SlicedData. +// +Ice::SlicedDataPtr +IcePHP::SlicedDataUtil::getMember(zval* obj, ObjectMap* objectMap) +{ + Ice::SlicedDataPtr slicedData; + + string name = "_ice_slicedData"; + zval* sd = zend_hash_str_find(Z_OBJPROP_P(obj), STRCAST(name.c_str()), name.size()); + if(sd) + { + if(Z_TYPE_P(sd) != IS_NULL) + { + // + // The "slices" member is an array of Ice_SliceInfo objects. + // + + zval* sl = zend_hash_str_find(Z_OBJPROP_P(sd), STRCAST("slices"), sizeof("slices") - 1); + assert(sl); + assert(Z_TYPE_P(sl) == IS_INDIRECT); + sl = Z_INDIRECT_P(sl); + assert(Z_TYPE_P(sl) == IS_ARRAY); + + Ice::SliceInfoSeq slices; + + HashTable* arr = Z_ARRVAL_P(sl); + assert(arr); + + zval* s; + + ZEND_HASH_FOREACH_VAL(arr, s) + { + assert(Z_OBJCE_P(s) == _sliceInfoType); + + Ice::SliceInfoPtr info = new Ice::SliceInfo; + + zval* typeId = zend_hash_str_find(Z_OBJPROP_P(s), STRCAST("typeId"), sizeof("typeId") - 1); + assert(Z_TYPE_P(typeId) == IS_INDIRECT); + typeId = Z_INDIRECT_P(typeId); + assert(typeId && Z_TYPE_P(typeId) == IS_STRING); + info->typeId = string(Z_STRVAL_P(typeId), Z_STRLEN_P(typeId)); + + zval* compactId = zend_hash_str_find(Z_OBJPROP_P(s), STRCAST("compactId"), sizeof("compactId") - 1); + assert(compactId && Z_TYPE_P(compactId) == IS_LONG); + info->compactId = static_cast<long>(Z_LVAL_P(compactId)); + + zval* bytes = zend_hash_str_find(Z_OBJPROP_P(s), STRCAST("bytes"), sizeof("bytes") - 1); + assert(Z_TYPE_P(bytes) == IS_INDIRECT); + bytes = Z_INDIRECT_P(bytes); + assert(bytes && Z_TYPE_P(bytes) == IS_ARRAY); + HashTable* barr = Z_ARRVAL_P(bytes); + zval* e; + info->bytes.resize(zend_hash_num_elements(barr)); + + vector<Ice::Byte>::size_type i = 0; + ZEND_HASH_FOREACH_VAL(barr, e) + { + long l = static_cast<long>(Z_LVAL_P(e)); + assert(l >= 0 && l <= 255); + info->bytes[i++] = static_cast<Ice::Byte>(l); + } + ZEND_HASH_FOREACH_END(); + + zval* objects = zend_hash_str_find(Z_OBJPROP_P(s), STRCAST("objects"), sizeof("objects") - 1); + assert(Z_TYPE_P(objects) == IS_INDIRECT); + objects = Z_INDIRECT_P(objects); + assert(objects && Z_TYPE_P(objects) == IS_ARRAY); + HashTable* oarr = Z_ARRVAL_P(objects); + zval* o; + + ZEND_HASH_FOREACH_VAL(oarr, o) + { + assert(Z_TYPE_P(o) == IS_OBJECT); + + Ice::ObjectPtr writer; + + ObjectMap::iterator i = objectMap->find(Z_OBJ_HANDLE_P(o)); + if(i == objectMap->end()) + { + writer = new ObjectWriter(o, objectMap, 0); + objectMap->insert(ObjectMap::value_type(Z_OBJ_HANDLE_P(o), writer)); + } + else + { + writer = i->second; + } + + info->objects.push_back(writer); + } + ZEND_HASH_FOREACH_END(); + + zval* hasOptionalMembers = zend_hash_str_find(Z_OBJPROP_P(s), + STRCAST("hasOptionalMembers"), + sizeof("hasOptionalMembers") - 1); + + assert(hasOptionalMembers && + (Z_TYPE_P(hasOptionalMembers) == IS_TRUE || Z_TYPE_P(hasOptionalMembers) == IS_FALSE)); + info->hasOptionalMembers = Z_TYPE_P(hasOptionalMembers) == IS_TRUE; + + zval* isLastSlice = zend_hash_str_find(Z_OBJPROP_P(s), STRCAST("isLastSlice"), sizeof("isLastSlice") - 1); + assert(isLastSlice && (Z_TYPE_P(isLastSlice) == IS_TRUE || Z_TYPE_P(isLastSlice) == IS_FALSE)); + info->isLastSlice = Z_TYPE_P(isLastSlice) == IS_TRUE; + + slices.push_back(info); + } + ZEND_HASH_FOREACH_END(); + + slicedData = new Ice::SlicedData(slices); + } + } + + return slicedData; +} + +// +// UnmarshalCallback implementation. +// +IcePHP::UnmarshalCallback::~UnmarshalCallback() +{ +} + +// +// TypeInfo implementation. +// +IcePHP::TypeInfo::TypeInfo() +{ +} + +bool +IcePHP::TypeInfo::usesClasses() const +{ + return false; +} + +void +IcePHP::TypeInfo::unmarshaled(zval*, zval*, void*) +{ + assert(false); +} + +void +IcePHP::TypeInfo::destroy() +{ +} + +// +// PrimitiveInfo implementation. +// +string +IcePHP::PrimitiveInfo::getId() const +{ + switch(kind) + { + case KindBool: + return "bool"; + case KindByte: + return "byte"; + case KindShort: + return "short"; + case KindInt: + return "int"; + case KindLong: + return "long"; + case KindFloat: + return "float"; + case KindDouble: + return "double"; + case KindString: + return "string"; + } + assert(false); + return string(); +} + +bool +IcePHP::PrimitiveInfo::validate(zval* zv, bool throwException) +{ + switch(kind) + { + case PrimitiveInfo::KindBool: + { + if(!(Z_TYPE_P(zv) == IS_TRUE || Z_TYPE_P(zv) == IS_FALSE)) + { + string s = zendTypeToString(Z_TYPE_P(zv)); + if(throwException) + { + invalidArgument("expected boolean value but received %s", s.c_str()); + } + return false; + } + break; + } + case PrimitiveInfo::KindByte: + { + if(Z_TYPE_P(zv) != IS_LONG) + { + string s = zendTypeToString(Z_TYPE_P(zv)); + if(throwException) + { + invalidArgument("expected byte value but received %s", s.c_str()); + } + return false; + } + long val = static_cast<long>(Z_LVAL_P(zv)); + if(val < 0 || val > 255) + { + if(throwException) + { + invalidArgument("value %ld is out of range for a byte", val); + } + return false; + } + break; + } + case PrimitiveInfo::KindShort: + { + if(Z_TYPE_P(zv) != IS_LONG) + { + string s = zendTypeToString(Z_TYPE_P(zv)); + if(throwException) + { + invalidArgument("expected short value but received %s", s.c_str()); + } + return false; + } + zend_long val = Z_LVAL_P(zv); + if(val < SHRT_MIN || val > SHRT_MAX) + { + if(throwException) + { + invalidArgument("value %ld is out of range for a short", val); + } + return false; + } + break; + } + case PrimitiveInfo::KindInt: + { + if(Z_TYPE_P(zv) != IS_LONG) + { + string s = zendTypeToString(Z_TYPE_P(zv)); + if(throwException) + { + invalidArgument("expected int value but received %s", s.c_str()); + } + return false; + } + zend_long val = Z_LVAL_P(zv); + if(val < INT_MIN || val > INT_MAX) + { + if(throwException) + { + invalidArgument("value %ld is out of range for an int", val); + } + return false; + } + break; + } + case PrimitiveInfo::KindLong: + { + // + // The platform's 'long' type may not be 64 bits, so we also accept + // a string argument for this type. + // + if(Z_TYPE_P(zv) != IS_LONG && Z_TYPE_P(zv) != IS_STRING) + { + string s = zendTypeToString(Z_TYPE_P(zv)); + if(throwException) + { + invalidArgument("expected long value but received %s", s.c_str()); + } + return false; + } + + if(Z_TYPE_P(zv) != IS_LONG) + { + Ice::Long val; + string sval(Z_STRVAL_P(zv), Z_STRLEN_P(zv)); + if(!IceUtilInternal::stringToInt64(sval, val)) + { + if(throwException) + { + invalidArgument("invalid long value `%s'", Z_STRVAL_P(zv)); + } + return false; + } + } + break; + } + case PrimitiveInfo::KindFloat: + { + if(Z_TYPE_P(zv) != IS_DOUBLE && Z_TYPE_P(zv) != IS_LONG) + { + string s = zendTypeToString(Z_TYPE_P(zv)); + if(throwException) + { + invalidArgument("expected float value but received %s", s.c_str()); + } + return false; + } + if(Z_TYPE_P(zv) == IS_DOUBLE) + { + double val = Z_DVAL_P(zv); + return (val <= numeric_limits<float>::max() && val >= -numeric_limits<float>::max()) || +#if defined(_MSC_VER) && (_MSC_VER <= 1700) + !_finite(val); +#else + !isfinite(val); +#endif + } + break; + } + case PrimitiveInfo::KindDouble: + { + if(Z_TYPE_P(zv) != IS_DOUBLE && Z_TYPE_P(zv) != IS_LONG) + { + string s = zendTypeToString(Z_TYPE_P(zv)); + if(throwException) + { + invalidArgument("expected double value but received %s", s.c_str()); + } + return false; + } + break; + } + case PrimitiveInfo::KindString: + { + if(Z_TYPE_P(zv) != IS_STRING && Z_TYPE_P(zv) != IS_NULL) + { + string s = zendTypeToString(Z_TYPE_P(zv)); + if(throwException) + { + invalidArgument("expected string value but received %s", s.c_str()); + } + return false; + } + break; + } + } + + return true; +} + +bool +IcePHP::PrimitiveInfo::variableLength() const +{ + return kind == KindString; +} + +int +IcePHP::PrimitiveInfo::wireSize() const +{ + switch(kind) + { + case KindBool: + case KindByte: + return 1; + case KindShort: + return 2; + case KindInt: + return 4; + case KindLong: + return 8; + case KindFloat: + return 4; + case KindDouble: + return 8; + case KindString: + return 1; + } + assert(false); + return 0; +} + +Ice::OptionalFormat +IcePHP::PrimitiveInfo::optionalFormat() const +{ + switch(kind) + { + case KindBool: + case KindByte: + return Ice::OptionalFormatF1; + case KindShort: + return Ice::OptionalFormatF2; + case KindInt: + return Ice::OptionalFormatF4; + case KindLong: + return Ice::OptionalFormatF8; + case KindFloat: + return Ice::OptionalFormatF4; + case KindDouble: + return Ice::OptionalFormatF8; + case KindString: + return Ice::OptionalFormatVSize; + } + + assert(false); + return Ice::OptionalFormatF1; +} + +void +IcePHP::PrimitiveInfo::marshal(zval* zv, const Ice::OutputStreamPtr& os, ObjectMap*, bool) +{ + switch(kind) + { + case PrimitiveInfo::KindBool: + { + assert(Z_TYPE_P(zv) == IS_TRUE || Z_TYPE_P(zv) == IS_FALSE); + os->write(Z_TYPE_P(zv) == IS_TRUE); + break; + } + case PrimitiveInfo::KindByte: + { + assert(Z_TYPE_P(zv) == IS_LONG); + long val = static_cast<long>(Z_LVAL_P(zv)); + assert(val >= 0 && val <= 255); // validate() should have caught this. + os->write(static_cast<Ice::Byte>(val)); + break; + } + case PrimitiveInfo::KindShort: + { + assert(Z_TYPE_P(zv) == IS_LONG); + long val = static_cast<long>(Z_LVAL_P(zv)); + assert(val >= SHRT_MIN && val <= SHRT_MAX); // validate() should have caught this. + os->write(static_cast<Ice::Short>(val)); + break; + } + case PrimitiveInfo::KindInt: + { + assert(Z_TYPE_P(zv) == IS_LONG); + long val = static_cast<long>(Z_LVAL_P(zv)); + assert(val >= INT_MIN && val <= INT_MAX); // validate() should have caught this. + os->write(static_cast<Ice::Int>(val)); + break; + } + case PrimitiveInfo::KindLong: + { + // + // The platform's 'long' type may not be 64 bits, so we also accept + // a string argument for this type. + // + assert(Z_TYPE_P(zv) == IS_LONG || Z_TYPE_P(zv) == IS_STRING); // validate() should have caught this. + Ice::Long val; + if(Z_TYPE_P(zv) == IS_LONG) + { + val = static_cast<long>(Z_LVAL_P(zv)); + } + else + { + string sval(Z_STRVAL_P(zv), Z_STRLEN_P(zv)); + IceUtilInternal::stringToInt64(sval, val); + } + os->write(val); + break; + } + case PrimitiveInfo::KindFloat: + { + Ice::Double val = 0; + if(Z_TYPE_P(zv) == IS_DOUBLE) + { + val = Z_DVAL_P(zv); + } + else if(Z_TYPE_P(zv) == IS_LONG) + { + val = static_cast<double>(Z_LVAL_P(zv)); + } + else + { + assert(false); // validate() should have caught this. + } + os->write(static_cast<Ice::Float>(val)); + break; + } + case PrimitiveInfo::KindDouble: + { + Ice::Double val = 0; + if(Z_TYPE_P(zv) == IS_DOUBLE) + { + val = Z_DVAL_P(zv); + } + else if(Z_TYPE_P(zv) == IS_LONG) + { + val = static_cast<double>(Z_LVAL_P(zv)); + } + else + { + assert(false); // validate() should have caught this. + } + os->write(val); + break; + } + case PrimitiveInfo::KindString: + { + assert(Z_TYPE_P(zv) == IS_STRING || Z_TYPE_P(zv) == IS_NULL); // validate() should have caught this. + if(Z_TYPE_P(zv) == IS_STRING) + { + string val(Z_STRVAL_P(zv), Z_STRLEN_P(zv)); + os->write(val); + } + else + { + os->write(string()); + } + break; + } + } +} + +void +IcePHP::PrimitiveInfo::unmarshal(const Ice::InputStreamPtr& is, const UnmarshalCallbackPtr& cb, + const CommunicatorInfoPtr&, zval* target, void* closure, bool) +{ + zval zv; + AutoDestroy destroy(&zv); + + switch(kind) + { + case PrimitiveInfo::KindBool: + { + bool val; + is->read(val); + ZVAL_BOOL(&zv, val ? 1 : 0); + break; + } + case PrimitiveInfo::KindByte: + { + Ice::Byte val; + is->read(val); + ZVAL_LONG(&zv, val & 0xff); + break; + } + case PrimitiveInfo::KindShort: + { + Ice::Short val; + is->read(val); + ZVAL_LONG(&zv, val); + break; + } + case PrimitiveInfo::KindInt: + { + Ice::Int val; + is->read(val); + ZVAL_LONG(&zv, val); + break; + } + case PrimitiveInfo::KindLong: + { + Ice::Long val; + is->read(val); + + // + // The platform's 'long' type may not be 64 bits, so we store 64-bit + // values as a string. + // + if(sizeof(Ice::Long) > sizeof(long) && (val < LONG_MIN || val > LONG_MAX)) + { + string str = IceUtilInternal::int64ToString(val); + ZVAL_STRINGL(&zv, STRCAST(str.c_str()), static_cast<int>(str.length())); + } + else + { + ZVAL_LONG(&zv, static_cast<long>(val)); + } + break; + } + case PrimitiveInfo::KindFloat: + { + Ice::Float val; + is->read(val); + ZVAL_DOUBLE(&zv, val); + break; + } + case PrimitiveInfo::KindDouble: + { + Ice::Double val; + is->read(val); + ZVAL_DOUBLE(&zv, val); + break; + } + case PrimitiveInfo::KindString: + { + string val; + is->read(val); + ZVAL_STRINGL(&zv, STRCAST(val.c_str()), static_cast<int>(val.length())); + break; + } + } + cb->unmarshaled(&zv, target, closure); +} + +void +IcePHP::PrimitiveInfo::print(zval* zv, IceUtilInternal::Output& out, PrintObjectHistory*) +{ + if(!validate(zv, false)) + { + out << "<invalid value - expected " << getId() << ">"; + return; + } + zval tmp; + ZVAL_STR(&tmp, zval_get_string(zv)); + out << Z_STRVAL(tmp); +} + +// +// EnumInfo implementation. +// +IcePHP::EnumInfo::EnumInfo(const string& ident, zval* en) : + id(ident), + maxValue(0) +{ + HashTable* arr = Z_ARRVAL_P(en); + HashPosition pos; + zval* val; + + zend_hash_internal_pointer_reset_ex(arr, &pos); + while((val = zend_hash_get_current_data_ex(arr, &pos))) + { + assert(Z_TYPE_P(val) == IS_STRING); + string name = Z_STRVAL_P(val); + zend_hash_move_forward_ex(arr, &pos); + + val = zend_hash_get_current_data_ex(arr, &pos); + assert(Z_TYPE_P(val) == IS_LONG); + Ice::Int value = static_cast<Ice::Int>(Z_LVAL_P(val)); + zend_hash_move_forward_ex(arr, &pos); + + if(value > maxValue) + { + const_cast<int&>(maxValue) = value; + } + + const_cast<map<Ice::Int, string>&>(enumerators)[value] = name; + } +} + +string +IcePHP::EnumInfo::getId() const +{ + return id; +} + +bool +IcePHP::EnumInfo::validate(zval* zv, bool) +{ + if(Z_TYPE_P(zv) == IS_LONG) + { + const Ice::Int l = static_cast<Ice::Int>(Z_LVAL_P(zv)); + return l >= 0 && enumerators.find(l) != enumerators.end(); + } + return false; +} + +bool +IcePHP::EnumInfo::variableLength() const +{ + return true; +} + +int +IcePHP::EnumInfo::wireSize() const +{ + return 1; +} + +Ice::OptionalFormat +IcePHP::EnumInfo::optionalFormat() const +{ + return Ice::OptionalFormatSize; +} + +void +IcePHP::EnumInfo::marshal(zval* zv, const Ice::OutputStreamPtr& os, ObjectMap*, bool) +{ + assert(Z_TYPE_P(zv) == IS_LONG); // validate() should have caught this. + const Ice::Int val = static_cast<Ice::Int>(Z_LVAL_P(zv)); + assert(val >= 0 && enumerators.find(val) != enumerators.end()); // validate() should have caught this. + + os->writeEnum(val, maxValue); +} + +void +IcePHP::EnumInfo::unmarshal(const Ice::InputStreamPtr& is, const UnmarshalCallbackPtr& cb, + const CommunicatorInfoPtr&, zval* target, void* closure, bool) +{ + zval zv; + AutoDestroy destroy(&zv); + + const Ice::Int val = is->readEnum(maxValue); + + if(enumerators.find(val) == enumerators.end()) + { + invalidArgument("enumerator %d is out of range for enum %s", val, id.c_str()); + throw AbortMarshaling(); + } + + ZVAL_LONG(&zv, val); + cb->unmarshaled(&zv, target, closure); +} + +void +IcePHP::EnumInfo::print(zval* zv, IceUtilInternal::Output& out, PrintObjectHistory*) +{ + if(!validate(zv, false)) + { + out << "<invalid value - expected " << id << ">"; + return; + } + const Ice::Int val = static_cast<Ice::Int>(Z_LVAL_P(zv)); + map<Ice::Int, string>::const_iterator p = enumerators.find(val); + assert(p != enumerators.end()); + out << p->second; +} + +// +// DataMember implementation. +// +void +IcePHP::DataMember::unmarshaled(zval* zv, zval* target, void*) +{ + setMember(target, zv); +} + +void +IcePHP::DataMember::setMember(zval* target, zval* zv) +{ + assert(Z_TYPE_P(target) == IS_OBJECT); + + // + // The add_property_zval function fails if the data member has protected visibility. + // As a workaround, before calling the function we change the current scope to be that + // of the object. + // + zend_class_entry *oldScope = EG(scope); + EG(scope) = Z_OBJCE_P(target); + + // + // add_property_zval increments the refcount of zv. + // + int status = add_property_zval(target, STRCAST(name.c_str()), zv); + + EG(scope) = oldScope; // Restore the previous scope. + + if(status == FAILURE) + { + runtimeError("unable to set member `%s'", name.c_str()); + throw AbortMarshaling(); + } +} + +static void +convertDataMembers(zval* zv, DataMemberList& reqMembers, DataMemberList& optMembers, bool allowOptional) +{ + list<DataMemberPtr> optList; + + assert(Z_TYPE_P(zv) == IS_ARRAY); + HashTable* membersArray = Z_ARRVAL_P(zv); + zval* arr; + + ZEND_HASH_FOREACH_VAL(membersArray, arr) + { + DataMemberPtr m = new DataMember(); + zval* elem; + + assert(Z_TYPE_P(arr) == IS_ARRAY); + HashTable* member = Z_ARRVAL_P(arr); + assert(allowOptional ? zend_hash_num_elements(member) == 4 : zend_hash_num_elements(member) == 2); + + elem = zend_hash_index_find(member, 0); + assert(Z_TYPE_P(elem) == IS_STRING); + m->name = Z_STRVAL_P(elem); + + elem = zend_hash_index_find(member, 1); + assert(Z_TYPE_P(elem) == IS_OBJECT); + m->type = Wrapper<TypeInfoPtr>::value(elem); + + if(allowOptional) + { + elem = zend_hash_index_find(member, 2); + assert(Z_TYPE_P(elem) == IS_TRUE || Z_TYPE_P(elem) == IS_FALSE); + m->optional = Z_TYPE_P(elem) == IS_TRUE; + + elem = zend_hash_index_find(member, 3); + assert(Z_TYPE_P(elem) == IS_LONG); + m->tag = static_cast<int>(Z_LVAL_P(elem)); + } + else + { + m->optional = false; + m->tag = 0; + } + + if(m->optional) + { + optList.push_back(m); + } + else + { + reqMembers.push_back(m); + } + } + ZEND_HASH_FOREACH_END(); + + if(allowOptional) + { + class SortFn + { + public: + static bool compare(const DataMemberPtr& lhs, const DataMemberPtr& rhs) + { + return lhs->tag < rhs->tag; + } + }; + + optList.sort(SortFn::compare); + copy(optList.begin(), optList.end(), back_inserter(optMembers)); + } +} + +// +// StructInfo implementation. +// +IcePHP::StructInfo::StructInfo(const string& ident, const string& n, zval* m) : + id(ident), name(n) +{ + // Set to undefined + ZVAL_UNDEF(&_nullMarshalValue); + + DataMemberList opt; + convertDataMembers(m, const_cast<DataMemberList&>(members), opt, false); + assert(opt.empty()); + const_cast<zend_class_entry*&>(zce) = nameToClass(name); + assert(zce); + + _variableLength = false; + _wireSize = 0; + for(DataMemberList::const_iterator p = members.begin(); p != members.end(); ++p) + { + if(!_variableLength && (*p)->type->variableLength()) + { + _variableLength = true; + } + _wireSize += (*p)->type->wireSize(); + } +} + +string +IcePHP::StructInfo::getId() const +{ + return id; +} + +bool +IcePHP::StructInfo::validate(zval* zv, bool throwException) +{ + if(Z_TYPE_P(zv) == IS_NULL) + { + return true; + } + else if(Z_TYPE_P(zv) != IS_OBJECT) + { + if(throwException) + { + string s = zendTypeToString(Z_TYPE_P(zv)); + invalidArgument("expected struct value of type %s but received %s", zce->name->val, s.c_str()); + } + return false; + } + + // + // Compare class entries. + // + zend_class_entry* ce = Z_OBJCE_P(zv); + if(ce != zce) + { + invalidArgument("expected struct value of type %s but received %s", zce->name->val, ce->name->val); + return false; + } + + return true; +} + +bool +IcePHP::StructInfo::variableLength() const +{ + return _variableLength; +} + +int +IcePHP::StructInfo::wireSize() const +{ + return _wireSize; +} + +Ice::OptionalFormat +IcePHP::StructInfo::optionalFormat() const +{ + return _variableLength ? Ice::OptionalFormatFSize : Ice::OptionalFormatVSize; +} + +bool +IcePHP::StructInfo::usesClasses() const +{ + for(DataMemberList::const_iterator p = members.begin(); p != members.end(); ++p) + { + if((*p)->type->usesClasses()) + { + return true; + } + } + + return false; +} + +void +IcePHP::StructInfo::marshal(zval* zv, const Ice::OutputStreamPtr& os, ObjectMap* objectMap, bool optional) +{ + assert(Z_TYPE_P(zv) == IS_NULL || (Z_TYPE_P(zv) == IS_OBJECT && Z_OBJCE_P(zv) == zce)); + + if(Z_TYPE_P(zv) == IS_NULL) + { + if(Z_ISUNDEF(_nullMarshalValue)) + { + if(object_init_ex(&_nullMarshalValue, const_cast<zend_class_entry*>(zce)) != SUCCESS) + { + runtimeError("unable to initialize object of type %s", zce->name->val); + throw AbortMarshaling(); + } + + if(!invokeMethod(&_nullMarshalValue, ZEND_CONSTRUCTOR_FUNC_NAME)) + { + assert(false); + } + } + assert(!Z_ISUNDEF(_nullMarshalValue)); + ZVAL_COPY_VALUE(zv, &_nullMarshalValue); + } + + Ice::OutputStream::size_type sizePos = 0; + if(optional) + { + if(_variableLength) + { + sizePos = os->startSize(); + } + else + { + os->writeSize(_wireSize); + } + } + + for(DataMemberList::const_iterator q = members.begin(); q != members.end(); ++q) + { + DataMemberPtr member = *q; + + zval* val = zend_hash_str_find(Z_OBJPROP_P(zv), STRCAST(member->name.c_str()), member->name.size()); + if(!val) + { + runtimeError("member `%s' of %s is not defined", member->name.c_str(), id.c_str()); + throw AbortMarshaling(); + } + + if(Z_TYPE_P(val) == IS_INDIRECT) + { + val = Z_INDIRECT_P(val); + } + + if(!member->type->validate(val, false)) + { + invalidArgument("invalid value for %s member `%s'", id.c_str(), member->name.c_str()); + throw AbortMarshaling(); + } + + member->type->marshal(val, os, objectMap, false); + } + + if(optional && _variableLength) + { + os->endSize(sizePos); + } +} + +void +IcePHP::StructInfo::unmarshal(const Ice::InputStreamPtr& is, const UnmarshalCallbackPtr& cb, + const CommunicatorInfoPtr& comm, zval* target, void* closure, bool optional) +{ + zval zv; + AutoDestroy destroy(&zv); + if(object_init_ex(&zv, const_cast<zend_class_entry*>(zce)) != SUCCESS) + { + runtimeError("unable to initialize object of type %s", zce->name->val); + throw AbortMarshaling(); + } + + if(optional) + { + if(_variableLength) + { + is->skip(4); + } + else + { + is->skipSize(); + } + } + + for(DataMemberList::const_iterator q = members.begin(); q != members.end(); ++q) + { + DataMemberPtr member = *q; + member->type->unmarshal(is, member, comm, &zv, 0, false); + } + + cb->unmarshaled(&zv, target, closure); +} + +void +IcePHP::StructInfo::print(zval* zv, IceUtilInternal::Output& out, PrintObjectHistory* history) +{ + if(!validate(zv, false)) + { + out << "<invalid value - expected " << id << ">"; + return; + } + + if(Z_TYPE_P(zv) == IS_NULL) + { + out << "<nil>"; + } + else + { + out.sb(); + for(DataMemberList::const_iterator q = members.begin(); q != members.end(); ++q) + { + DataMemberPtr member = *q; + + out << nl << member->name << " = "; + zval* val = zend_hash_str_find(Z_OBJPROP_P(zv), STRCAST(member->name.c_str()), member->name.size()); + assert(Z_TYPE_P(val) == IS_INDIRECT); + val = Z_INDIRECT_P(val); + if(val) + { + member->type->print(val, out, history); + } + else + { + out << "<not defined>"; + } + } + out.eb(); + } +} + +void +IcePHP::StructInfo::destroy() +{ + for(DataMemberList::const_iterator p = members.begin(); p != members.end(); ++p) + { + (*p)->type->destroy(); + } + const_cast<DataMemberList&>(members).clear(); + if(!Z_ISUNDEF(_nullMarshalValue)) + { + zval_ptr_dtor(&_nullMarshalValue); + } +} + +// +// SequenceInfo implementation. +// +IcePHP::SequenceInfo::SequenceInfo(const string& ident, zval* e) : + id(ident) +{ + const_cast<TypeInfoPtr&>(elementType) = Wrapper<TypeInfoPtr>::value(e); +} + +string +IcePHP::SequenceInfo::getId() const +{ + return id; +} + +bool +IcePHP::SequenceInfo::validate(zval* zv, bool) +{ + return Z_TYPE_P(zv) == IS_NULL || Z_TYPE_P(zv) == IS_ARRAY; +} + +bool +IcePHP::SequenceInfo::variableLength() const +{ + return true; +} + +int +IcePHP::SequenceInfo::wireSize() const +{ + return 1; +} + +Ice::OptionalFormat +IcePHP::SequenceInfo::optionalFormat() const +{ + return elementType->variableLength() ? Ice::OptionalFormatFSize : Ice::OptionalFormatVSize; +} + +bool +IcePHP::SequenceInfo::usesClasses() const +{ + return elementType->usesClasses(); +} + +void +IcePHP::SequenceInfo::marshal(zval* zv, const Ice::OutputStreamPtr& os, ObjectMap* objectMap, bool optional) +{ + Ice::Int sz = 0; + HashTable* arr = 0; + + if(Z_TYPE_P(zv) != IS_NULL) + { + assert(Z_TYPE_P(zv) == IS_ARRAY); // validate() should have caught this. + arr = Z_ARRVAL_P(zv); + sz = static_cast<Ice::Int>(zend_hash_num_elements(arr)); + } + + Ice::OutputStream::size_type sizePos = 0; + if(optional) + { + if(elementType->variableLength()) + { + sizePos = os->startSize(); + } + else if(elementType->wireSize() > 1) + { + os->writeSize(sz == 0 ? 1 : sz * elementType->wireSize() + (sz > 254 ? 5 : 1)); + } + } + + if(sz == 0) + { + os->writeSize(0); + } + else + { + PrimitiveInfoPtr pi = PrimitiveInfoPtr::dynamicCast(elementType); + if(pi) + { + marshalPrimitiveSequence(pi, zv, os); + return; + } + + os->writeSize(sz); + + zval* val; + ZEND_HASH_FOREACH_VAL(arr, val) + { + if(!elementType->validate(val, false)) + { + invalidArgument("invalid value for sequence element `%s'", id.c_str()); + throw AbortMarshaling(); + } + elementType->marshal(val, os, objectMap, false); + } + ZEND_HASH_FOREACH_END(); + } + + if(optional && elementType->variableLength()) + { + os->endSize(sizePos); + } +} + +void +IcePHP::SequenceInfo::unmarshal(const Ice::InputStreamPtr& is, const UnmarshalCallbackPtr& cb, + const CommunicatorInfoPtr& comm, zval* target, void* closure, bool optional) +{ + if(optional) + { + if(elementType->variableLength()) + { + is->skip(4); + } + else if(elementType->wireSize() > 1) + { + is->skipSize(); + } + } + + PrimitiveInfoPtr pi = PrimitiveInfoPtr::dynamicCast(elementType); + if(pi) + { + unmarshalPrimitiveSequence(pi, is, cb, target, closure); + return; + } + + zval zv; + array_init(&zv); + AutoDestroy destroy(&zv); + + Ice::Int sz = is->readSize(); + for(Ice::Int i = 0; i < sz; ++i) + { +#ifdef _MSC_VER +# pragma warning(disable:4311) +# pragma warning(disable:4312) +#endif + void* cl = reinterpret_cast<void*>(i); +#ifdef _MSC_VER +# pragma warning(default:4311) +# pragma warning(default:4312) +#endif + + elementType->unmarshal(is, this, comm, &zv, cl, false); + } + + cb->unmarshaled(&zv, target, closure); +} + +void +IcePHP::SequenceInfo::print(zval* zv, IceUtilInternal::Output& out, PrintObjectHistory* history) +{ + if(!validate(zv, false)) + { + out << "<invalid value - expected " << id << ">"; + return; + } + + if(Z_TYPE_P(zv) == IS_NULL) + { + out << "{}"; + } + else + { + assert(Z_TYPE_P(zv) == IS_ARRAY); + + HashTable* arr = Z_ARRVAL_P(zv); + + out.sb(); + + int i = 0; + zval* val; + ZEND_HASH_FOREACH_VAL(arr, val) + { + out << nl << '[' << i << "] = "; + elementType->print(val, out, history); + ++i; + } + ZEND_HASH_FOREACH_END(); + + out.eb(); + } +} + +void +IcePHP::SequenceInfo::unmarshaled(zval* zv, zval* target, void* closure) +{ + assert(Z_TYPE_P(target) != IS_REFERENCE); + assert(Z_TYPE_P(target) == IS_ARRAY); + +#ifdef _MSC_VER +# pragma warning(disable:4302) +# pragma warning(disable:4311) +#endif + long i = reinterpret_cast<long>(closure); +#ifdef _MSC_VER +# pragma warning(default:4302) +# pragma warning(disable:4311) +#endif + add_index_zval(target, i, zv); + if(Z_REFCOUNTED_P(zv)) + { + Z_ADDREF_P(zv); + } + +} + +void +IcePHP::SequenceInfo::destroy() +{ + if(elementType) + { + elementType->destroy(); + const_cast<TypeInfoPtr&>(elementType) = 0; + } +} + +void +IcePHP::SequenceInfo::marshalPrimitiveSequence(const PrimitiveInfoPtr& pi, zval* zv, const Ice::OutputStreamPtr& os) +{ + HashTable* arr = Z_ARRVAL_P(zv); + + Ice::Int sz = static_cast<Ice::Int>(zend_hash_num_elements(arr)); + assert(sz > 0); + + switch(pi->kind) + { + case PrimitiveInfo::KindBool: + { + Ice::BoolSeq seq(sz); + Ice::Int i = 0; + zval* val; + ZEND_HASH_FOREACH_VAL(arr, val) + { + if(!pi->validate(val, true)) + { + throw AbortMarshaling(); + } + seq[i++] = Z_TYPE_P(val) == IS_TRUE; + } + ZEND_HASH_FOREACH_END(); + +#if defined(_MSC_VER) && (_MSC_VER < 1300) + os->writeBoolSeq(seq); +#else + os->write(seq); +#endif + break; + } + case PrimitiveInfo::KindByte: + { + Ice::ByteSeq seq(sz); + Ice::Int i = 0; + zval* val; + ZEND_HASH_FOREACH_VAL(arr, val) + { + if(!pi->validate(val, true)) + { + throw AbortMarshaling(); + } + long l = static_cast<long>(Z_LVAL_P(val)); + assert(l >= 0 && l <= 255); + seq[i++] = static_cast<Ice::Byte>(l); + } + ZEND_HASH_FOREACH_END(); + + os->write(&seq[0], &seq[0] + seq.size()); + break; + } + case PrimitiveInfo::KindShort: + { + Ice::ShortSeq seq(sz); + Ice::Int i = 0; + zval* val; + ZEND_HASH_FOREACH_VAL(arr, val) + { + if(!pi->validate(val, true)) + { + throw AbortMarshaling(); + } + long l = static_cast<long>(Z_LVAL_P(val)); + assert(l >= SHRT_MIN && l <= SHRT_MAX); + seq[i++] = static_cast<Ice::Short>(l); + } + ZEND_HASH_FOREACH_END(); + + os->write(&seq[0], &seq[0] + seq.size()); + break; + } + case PrimitiveInfo::KindInt: + { + Ice::IntSeq seq(sz); + Ice::Int i = 0; + zval* val; + ZEND_HASH_FOREACH_VAL(arr, val) + { + if(!pi->validate(val, true)) + { + throw AbortMarshaling(); + } + long l = static_cast<long>(Z_LVAL_P(val)); + assert(l >= INT_MIN && l <= INT_MAX); + seq[i++] = static_cast<Ice::Int>(l); + } + ZEND_HASH_FOREACH_END(); + + os->write(&seq[0], &seq[0] + seq.size()); + break; + } + case PrimitiveInfo::KindLong: + { + Ice::LongSeq seq(sz); + Ice::Int i = 0; + zval* val; + ZEND_HASH_FOREACH_VAL(arr, val) + { + if(!pi->validate(val, true)) + { + throw AbortMarshaling(); + } + // + // The platform's 'long' type may not be 64 bits, so we also accept + // a string argument for this type. + // + assert(Z_TYPE_P(val) == IS_LONG || Z_TYPE_P(val) == IS_STRING); + Ice::Long l; + if(Z_TYPE_P(val) == IS_LONG) + { + l = static_cast<long>(Z_LVAL_P(val)); + } + else + { + string sval(Z_STRVAL_P(val), Z_STRLEN_P(val)); + IceUtilInternal::stringToInt64(sval, l); + } + seq[i++] = l; + } + ZEND_HASH_FOREACH_END(); + + os->write(&seq[0], &seq[0] + seq.size()); + break; + } + case PrimitiveInfo::KindFloat: + { + Ice::FloatSeq seq(sz); + Ice::Int i = 0; + zval* val; + ZEND_HASH_FOREACH_VAL(arr, val) + { + if(!pi->validate(val, true)) + { + throw AbortMarshaling(); + } + double d = 0; + if(Z_TYPE_P(val) == IS_DOUBLE) + { + d = Z_DVAL_P(val); + } + else if(Z_TYPE_P(val) == IS_LONG) + { + d = static_cast<double>(Z_LVAL_P(val)); + } + else + { + assert(false); // validate() should have caught this. + } + seq[i++] = static_cast<Ice::Float>(d); + } + ZEND_HASH_FOREACH_END(); + + os->write(&seq[0], &seq[0] + seq.size()); + break; + } + case PrimitiveInfo::KindDouble: + { + Ice::DoubleSeq seq(sz); + Ice::Int i = 0; + zval* val; + ZEND_HASH_FOREACH_VAL(arr, val) + { + if(!pi->validate(val, true)) + { + throw AbortMarshaling(); + } + double d = 0; + if(Z_TYPE_P(val) == IS_DOUBLE) + { + d = Z_DVAL_P(val); + } + else if(Z_TYPE_P(val) == IS_LONG) + { + d = static_cast<double>(Z_LVAL_P(val)); + } + else + { + assert(false); // validate() should have caught this. + } + seq[i++] = d; + } + ZEND_HASH_FOREACH_END(); + + os->write(&seq[0], &seq[0] + seq.size()); + break; + } + case PrimitiveInfo::KindString: + { + Ice::StringSeq seq(sz); + Ice::Int i = 0; + zval* val; + ZEND_HASH_FOREACH_VAL(arr, val) + { + if(!pi->validate(val, true)) + { + throw AbortMarshaling(); + } + string s; + if(Z_TYPE_P(val) == IS_STRING) + { + s = string(Z_STRVAL_P(val), Z_STRLEN_P(val)); + } + else + { + assert(Z_TYPE_P(val) == IS_NULL); + } + seq[i++] = s; + } + ZEND_HASH_FOREACH_END(); + + os->write(seq); + break; + } + } +} + +void +IcePHP::SequenceInfo::unmarshalPrimitiveSequence(const PrimitiveInfoPtr& pi, const Ice::InputStreamPtr& is, + const UnmarshalCallbackPtr& cb, zval* target, void* closure) +{ + zval zv; + array_init(&zv); + AutoDestroy destroy(&zv); + + switch(pi->kind) + { + case PrimitiveInfo::KindBool: + { + pair<const bool*, const bool*> pr; + IceUtil::ScopedArray<bool> arr; + is->read(pr, arr); + for(const bool* p = pr.first; p != pr.second; ++p) + { + add_next_index_bool(&zv, *p ? 1 : 0); + } + break; + } + case PrimitiveInfo::KindByte: + { + pair<const Ice::Byte*, const Ice::Byte*> pr; + is->read(pr); + for(const Ice::Byte* p = pr.first; p != pr.second; ++p) + { + add_next_index_long(&zv, *p & 0xff); + } + break; + } + case PrimitiveInfo::KindShort: + { + pair<const Ice::Short*, const Ice::Short*> pr; + IceUtil::ScopedArray<Ice::Short> arr; + is->read(pr, arr); + for(const Ice::Short* p = pr.first; p != pr.second; ++p) + { + add_next_index_long(&zv, *p); + } + break; + } + case PrimitiveInfo::KindInt: + { + pair<const Ice::Int*, const Ice::Int*> pr; + IceUtil::ScopedArray<Ice::Int> arr; + is->read(pr, arr); + for(const Ice::Int* p = pr.first; p != pr.second; ++p) + { + add_next_index_long(&zv, *p); + } + break; + } + case PrimitiveInfo::KindLong: + { + pair<const Ice::Long*, const Ice::Long*> pr; + IceUtil::ScopedArray<Ice::Long> arr; + is->read(pr, arr); + Ice::Int i = 0; + for(const Ice::Long* p = pr.first; p != pr.second; ++p, ++i) + { + zval val; + // + // The platform's 'long' type may not be 64 bits, so we store 64-bit + // values as a string. + // + if(sizeof(Ice::Long) > sizeof(long) && (*p < LONG_MIN || *p > LONG_MAX)) + { + string str = IceUtilInternal::int64ToString(*p); + ZVAL_STRINGL(&val, STRCAST(str.c_str()), static_cast<int>(str.length())); + } + else + { + ZVAL_LONG(&val, static_cast<long>(*p)); + } + add_index_zval(&zv, i, &val); + } + break; + } + case PrimitiveInfo::KindFloat: + { + pair<const Ice::Float*, const Ice::Float*> pr; + IceUtil::ScopedArray<Ice::Float> arr; + is->read(pr, arr); + Ice::Int i = 0; + for(const Ice::Float* p = pr.first; p != pr.second; ++p, ++i) + { + zval val; + ZVAL_DOUBLE(&val, *p); + add_index_zval(&zv, i, &val); + } + break; + } + case PrimitiveInfo::KindDouble: + { + pair<const Ice::Double*, const Ice::Double*> pr; + IceUtil::ScopedArray<Ice::Double> arr; + is->read(pr, arr); + Ice::Int i = 0; + for(const Ice::Double* p = pr.first; p != pr.second; ++p, ++i) + { + zval val; + ZVAL_DOUBLE(&val, *p); + add_index_zval(&zv, i, &val); + } + break; + } + case PrimitiveInfo::KindString: + { + Ice::StringSeq seq; + is->read(seq, true); + Ice::Int i = 0; + for(Ice::StringSeq::iterator p = seq.begin(); p != seq.end(); ++p, ++i) + { + zval val; + ZVAL_STRINGL(&val, STRCAST(p->c_str()), static_cast<int>(p->length())); + add_index_zval(&zv, i, &val); + } + break; + } + } + + cb->unmarshaled(&zv, target, closure); +} + +// +// DictionaryInfo implementation. +// +IcePHP::DictionaryInfo::DictionaryInfo(const string& ident, zval* k, zval* v) : + id(ident) +{ + const_cast<TypeInfoPtr&>(keyType) = Wrapper<TypeInfoPtr>::value(k); + const_cast<TypeInfoPtr&>(valueType) = Wrapper<TypeInfoPtr>::value(v); + + _variableLength = keyType->variableLength() || valueType->variableLength(); + _wireSize = keyType->wireSize() + valueType->wireSize(); +} + +string +IcePHP::DictionaryInfo::getId() const +{ + return id; +} + +bool +IcePHP::DictionaryInfo::validate(zval* zv, bool) +{ + return Z_TYPE_P(zv) == IS_NULL || Z_TYPE_P(zv) == IS_ARRAY; +} + +bool +IcePHP::DictionaryInfo::variableLength() const +{ + return true; +} + +int +IcePHP::DictionaryInfo::wireSize() const +{ + return 1; +} + +Ice::OptionalFormat +IcePHP::DictionaryInfo::optionalFormat() const +{ + return _variableLength ? Ice::OptionalFormatFSize : Ice::OptionalFormatVSize; +} + +bool +IcePHP::DictionaryInfo::usesClasses() const +{ + return valueType->usesClasses(); +} + +void +IcePHP::DictionaryInfo::marshal(zval* zv, const Ice::OutputStreamPtr& os, ObjectMap* objectMap, bool optional) +{ + Ice::Int sz = 0; + HashTable* arr = 0; + + if(Z_TYPE_P(zv) != IS_NULL) + { + assert(Z_TYPE_P(zv) == IS_ARRAY); // validate() should have caught this. + arr = Z_ARRVAL_P(zv); + sz = static_cast<Ice::Int>(zend_hash_num_elements(arr)); + } + + Ice::OutputStream::size_type sizePos = 0; + if(optional) + { + if(_variableLength) + { + sizePos = os->startSize(); + } + else + { + os->writeSize(sz == 0 ? 1 : sz * _wireSize + (sz > 254 ? 5 : 1)); + } + } + + PrimitiveInfoPtr piKey = PrimitiveInfoPtr::dynamicCast(keyType); + EnumInfoPtr enKey = EnumInfoPtr::dynamicCast(keyType); + if(!enKey && (!piKey || piKey->kind == PrimitiveInfo::KindFloat || piKey->kind == PrimitiveInfo::KindDouble)) + { + invalidArgument("dictionary type `%s' cannot be marshaled", id.c_str()); + throw AbortMarshaling(); + } + + os->writeSize(sz); + + if(sz > 0) + { + zend_long num_key; + zend_string* key; + zval* val; + + ZEND_HASH_FOREACH_KEY_VAL(arr, num_key, key, val) + { + // + // Store the key (which can be a long or a string) in a zval so that we can reuse the marshaling logic. + // + zval zkey; + AutoDestroy destroy(&zkey); + + if(key) + { + ZVAL_STRINGL(&zkey, key->val, key->len); + } + else + { + ZVAL_LONG(&zkey, num_key); + } + + // + // Convert the zval to the required type, if necessary. + // + if(piKey) + { + switch(piKey->kind) + { + case PrimitiveInfo::KindBool: + { + convert_to_boolean(&zkey); + break; + } + + case PrimitiveInfo::KindByte: + case PrimitiveInfo::KindShort: + case PrimitiveInfo::KindInt: + case PrimitiveInfo::KindLong: + { + if(key) // HASH_KEY_IS_STRING + { + convert_to_long(&zkey); + } + break; + } + + case PrimitiveInfo::KindString: + { + if(!key) // HASH_KEY_IS_LONG + { + convert_to_string(&zkey); + } + break; + } + + case PrimitiveInfo::KindFloat: + case PrimitiveInfo::KindDouble: + assert(false); + } + } + else + { + if(key) // HASH_KEY_IS_STRING + { + convert_to_long(&zkey); + } + } + + // + // Marshal the key. + // + if(!keyType->validate(&zkey, false)) + { + invalidArgument("invalid key in `%s' element", id.c_str()); + throw AbortMarshaling(); + } + keyType->marshal(&zkey, os, objectMap, false); + + // + // Marshal the value. + // + if(!valueType->validate(val, false)) + { + invalidArgument("invalid value in `%s' element", id.c_str()); + throw AbortMarshaling(); + } + valueType->marshal(val, os, objectMap, false); + } + ZEND_HASH_FOREACH_END(); + } + + if(optional && _variableLength) + { + os->endSize(sizePos); + } +} + +void +IcePHP::DictionaryInfo::unmarshal(const Ice::InputStreamPtr& is, const UnmarshalCallbackPtr& cb, + const CommunicatorInfoPtr& comm, zval* target, void* closure, bool optional) +{ + if(optional) + { + if(_variableLength) + { + is->skip(4); + } + else + { + is->skipSize(); + } + } + + PrimitiveInfoPtr piKey = PrimitiveInfoPtr::dynamicCast(keyType); + EnumInfoPtr enKey = EnumInfoPtr::dynamicCast(keyType); + if(!enKey && (!piKey || piKey->kind == PrimitiveInfo::KindFloat || piKey->kind == PrimitiveInfo::KindDouble)) + { + invalidArgument("dictionary type `%s' cannot be unmarshaled", id.c_str()); + throw AbortMarshaling(); + } + + zval zv; + array_init(&zv); + AutoDestroy destroy(&zv); + + Ice::Int sz = is->readSize(); + for(Ice::Int i = 0; i < sz; ++i) + { + // + // A dictionary key cannot be a class (or contain one), so the key must be + // available immediately. + // + KeyCallbackPtr keyCB = new KeyCallback; + keyType->unmarshal(is, keyCB, comm, 0, 0, false); + assert(Z_TYPE(keyCB->key) != IS_UNDEF); + + // + // Allocate a callback that holds a reference to the key. + // + ValueCallbackPtr valueCB = new ValueCallback(&keyCB->key); + + // + // Pass the key to the callback. + // + valueType->unmarshal(is, valueCB, comm, &zv, 0, false); + } + + cb->unmarshaled(&zv, target, closure); +} + +void +IcePHP::DictionaryInfo::print(zval* zv, IceUtilInternal::Output& out, PrintObjectHistory* history) +{ + if(!validate(zv, false)) + { + out << "<invalid value - expected " << id << ">"; + return; + } + + if(Z_TYPE_P(zv) == IS_NULL) + { + out << "{}"; + } + else + { + HashTable* arr = Z_ARRVAL_P(zv); + zval* val; + zend_long num_key; + zend_string* key; + bool first = true; + + out.sb(); + + ZEND_HASH_FOREACH_KEY_VAL(arr, num_key, key, val) + { + if(first) + { + first = false; + } + else + { + out << nl; + } + out << nl << "key = "; + + if(key) // HASH_KEY_IS_STRING + { + out << key->val; + } + else // HASH_KEY_IS_LONG + { + out << num_key; + } + out << nl << "value = "; + valueType->print(val, out, history); + } + ZEND_HASH_FOREACH_END(); + + out.eb(); + } +} + +IcePHP::DictionaryInfo::KeyCallback::KeyCallback() +{ + ZVAL_UNDEF(&key); +} + +IcePHP::DictionaryInfo::KeyCallback::~KeyCallback() +{ + zval_ptr_dtor(&key); +} + +void +IcePHP::DictionaryInfo::KeyCallback::unmarshaled(zval* zv, zval*, void*) +{ + zval_ptr_dtor(&key); + ZVAL_COPY(&key, zv); +} + +IcePHP::DictionaryInfo::ValueCallback::ValueCallback(zval* k) +{ + ZVAL_COPY_VALUE(&key, k); +} + +IcePHP::DictionaryInfo::ValueCallback::~ValueCallback() +{ +} + +void +IcePHP::DictionaryInfo::ValueCallback::unmarshaled(zval* zv, zval* target, void*) +{ + assert(Z_TYPE_P(target) == IS_ARRAY); + + switch(Z_TYPE(key)) + { + case IS_LONG: + add_index_zval(target, Z_LVAL(key), zv); + break; + case IS_TRUE: + add_index_zval(target, 1, zv); + break; + case IS_FALSE: + add_index_zval(target, 0, zv); + break; + case IS_STRING: + add_assoc_zval_ex(target, Z_STRVAL(key), Z_STRLEN(key), zv); + break; + default: + assert(false); + return; + } + + Z_TRY_ADDREF_P(zv); +} + +void +IcePHP::DictionaryInfo::destroy() +{ + if(keyType) + { + keyType->destroy(); + keyType = 0; + } + if(valueType) + { + valueType->destroy(); + valueType = 0; + } +} + +// +// ClassInfo implementation. +// +IcePHP::ClassInfo::ClassInfo(const string& ident) : + id(ident), compactId(-1), isAbstract(false), preserve(false), zce(0), defined(false) +{ +} + +void +IcePHP::ClassInfo::define(const string& n, Ice::Int compact, bool isAbs, bool pres, zval* b, zval* i, zval* m) +{ + const_cast<string&>(name) = n; + const_cast<Ice::Int&>(compactId) = static_cast<Ice::Int>(compact); + const_cast<bool&>(isAbstract) = isAbs; + const_cast<bool&>(preserve) = pres; + + if(b) + { + TypeInfoPtr p = Wrapper<TypeInfoPtr>::value(b); + const_cast<ClassInfoPtr&>(base) = ClassInfoPtr::dynamicCast(p); + assert(base); + } + + if(i) + { + HashTable* interfacesArray = Z_ARRVAL_P(i); + zval* interfaceType; + + ZEND_HASH_FOREACH_VAL(interfacesArray, interfaceType) + { + TypeInfoPtr t = Wrapper<TypeInfoPtr>::value(interfaceType); + ClassInfoPtr c = ClassInfoPtr::dynamicCast(t); + assert(c); + const_cast<ClassInfoList&>(interfaces).push_back(c); + } + ZEND_HASH_FOREACH_END(); + } + + if(m) + { + convertDataMembers(m, const_cast<DataMemberList&>(members), const_cast<DataMemberList&>(optionalMembers), + true); + } + + const_cast<bool&>(defined) = true; + const_cast<zend_class_entry*&>(zce) = nameToClass(name); + assert(zce || id == "::Ice::LocalObject"); // LocalObject does not have a native PHP equivalent. +} + +string +IcePHP::ClassInfo::getId() const +{ + return id; +} + +bool +IcePHP::ClassInfo::validate(zval* val, bool) +{ + if(Z_TYPE_P(val) == IS_OBJECT) + { + return checkClass(Z_OBJCE_P(val), const_cast<zend_class_entry*>(zce)); + } + return Z_TYPE_P(val) == IS_NULL; +} + +bool +IcePHP::ClassInfo::variableLength() const +{ + return true; +} + +int +IcePHP::ClassInfo::wireSize() const +{ + return 1; +} + +Ice::OptionalFormat +IcePHP::ClassInfo::optionalFormat() const +{ + return Ice::OptionalFormatClass; +} + +bool +IcePHP::ClassInfo::usesClasses() const +{ + return true; +} + +void +IcePHP::ClassInfo::marshal(zval* zv, const Ice::OutputStreamPtr& os, ObjectMap* objectMap, bool) +{ + if(!defined) + { + runtimeError("class or interface %s is declared but not defined", id.c_str()); + throw AbortMarshaling(); + } + + if(Z_TYPE_P(zv) == IS_NULL) + { + os->writeObject(0); + return; + } + + assert(Z_TYPE_P(zv) == IS_OBJECT); // validate() should have caught this. + assert(checkClass(Z_OBJCE_P(zv), const_cast<zend_class_entry*>(zce))); // validate() should have caught this. + + // + // Ice::ObjectWriter is a subclass of Ice::Object that wraps a PHP object for marshaling. + // It is possible that this PHP object has already been marshaled, therefore we first must + // check the object map to see if this object is present. If so, we use the existing ObjectWriter, + // otherwise we create a new one. The key of the map is the object's handle. + // + Ice::ObjectPtr writer; + assert(objectMap); + ObjectMap::iterator q = objectMap->find(Z_OBJ_HANDLE_P(zv)); + if(q == objectMap->end()) + { + writer = new ObjectWriter(zv, objectMap, this); + objectMap->insert(ObjectMap::value_type(Z_OBJ_HANDLE_P(zv), writer)); + } + else + { + writer = q->second; + } + + // + // Give the writer to the stream. The stream will eventually call write() on it. + // + os->writeObject(writer); +} + +void +IcePHP::ClassInfo::unmarshal(const Ice::InputStreamPtr& is, const UnmarshalCallbackPtr& cb, + const CommunicatorInfoPtr& comm, zval* target, void* closure, bool) +{ + if(!defined) + { + runtimeError("class or interface %s is declared but not defined", id.c_str()); + throw AbortMarshaling(); + } + + is->readObject(new ReadObjectCallback(this, cb, target, closure)); +} + +void +IcePHP::ClassInfo::print(zval* zv, IceUtilInternal::Output& out, PrintObjectHistory* history) +{ + if(!validate(zv, false)) + { + out << "<invalid value - expected " << id << ">"; + return; + } + + if(Z_TYPE_P(zv) == IS_NULL) + { + out << "<nil>"; + } + else + { + map<unsigned int, int>::iterator q = history->objects.find(Z_OBJ_HANDLE_P(zv)); + if(q != history->objects.end()) + { + out << "<object #" << q->second << ">"; + } + else + { + out << "object #" << history->index << " (" << id << ')'; + history->objects.insert(map<unsigned int, int>::value_type(Z_OBJ_HANDLE_P(zv), history->index)); + ++history->index; + out.sb(); + printMembers(zv, out, history); + out.eb(); + } + } +} + +void +IcePHP::ClassInfo::destroy() +{ + const_cast<ClassInfoPtr&>(base) = 0; + const_cast<ClassInfoList&>(interfaces).clear(); + if(!members.empty()) + { + DataMemberList ml = members; + const_cast<DataMemberList&>(members).clear(); + for(DataMemberList::iterator p = ml.begin(); p != ml.end(); ++p) + { + (*p)->type->destroy(); + } + } +} + +void +IcePHP::ClassInfo::printMembers(zval* zv, IceUtilInternal::Output& out, PrintObjectHistory* history) +{ + if(base) + { + base->printMembers(zv, out, history); + } + + DataMemberList::const_iterator q; + + for(q = members.begin(); q != members.end(); ++q) + { + DataMemberPtr member = *q; + + out << nl << member->name << " = "; + zval* val = zend_hash_str_find(Z_OBJPROP_P(zv), STRCAST(member->name.c_str()), member->name.size()); + assert(Z_TYPE_P(val) == IS_INDIRECT); + val = Z_INDIRECT_P(val); + if(val) + { + member->type->print(val, out, history); + } + else + { + out << "<not defined>"; + } + } + + for(q = optionalMembers.begin(); q != optionalMembers.end(); ++q) + { + DataMemberPtr member = *q; + + out << nl << member->name << " = "; + zval* val = zend_hash_str_find(Z_OBJPROP_P(zv), STRCAST(member->name.c_str()), member->name.size()); + assert(Z_TYPE_P(val) == IS_INDIRECT); + val = Z_INDIRECT_P(val); + if(val) + { + if(isUnset(val)) + { + out << "<unset>"; + } + else + { + member->type->print(val, out, history); + } + } + else + { + out << "<not defined>"; + } + } +} + +bool +IcePHP::ClassInfo::isA(const string& typeId) const +{ + if(id == typeId) + { + return true; + } + + if(base && base->isA(typeId)) + { + return true; + } + + for(ClassInfoList::const_iterator p = interfaces.begin(); p != interfaces.end(); ++p) + { + if((*p)->isA(typeId)) + { + return true; + } + } + + return false; +} + +void +IcePHP::ClassInfo::addOperation(const string& name, const OperationPtr& op) +{ + operations.insert(OperationMap::value_type(Slice::PHP::fixIdent(name), op)); +} + +IcePHP::OperationPtr +IcePHP::ClassInfo::getOperation(const string& name) const +{ + OperationPtr op; + OperationMap::const_iterator p = operations.find(name); + if(p != operations.end()) + { + op = p->second; + } + if(!op && base) + { + op = base->getOperation(name); + } + if(!op && !interfaces.empty()) + { + for(ClassInfoList::const_iterator q = interfaces.begin(); q != interfaces.end() && !op; ++q) + { + op = (*q)->getOperation(name); + } + } + return op; +} + +// +// ProxyInfo implementation. +// +IcePHP::ProxyInfo::ProxyInfo(const string& ident) : + id(ident), defined(false) +{ +} + +void +IcePHP::ProxyInfo::define(const ClassInfoPtr& c) +{ + const_cast<ClassInfoPtr&>(cls) = c; + const_cast<bool&>(defined) = true; +} + +string +IcePHP::ProxyInfo::getId() const +{ + return id; +} + +bool +IcePHP::ProxyInfo::validate(zval* zv, bool throwException) +{ + if(Z_TYPE_P(zv) != IS_NULL) + { + if(Z_TYPE_P(zv) != IS_OBJECT || (Z_TYPE_P(zv) == IS_OBJECT && Z_OBJCE_P(zv) != proxyClassEntry)) + { + if(throwException) + { + string s = zendTypeToString(Z_TYPE_P(zv)); + invalidArgument("expected proxy value or null but received %s", s.c_str()); + } + return false; + } + } + + return true; +} + +bool +IcePHP::ProxyInfo::variableLength() const +{ + return true; +} + +int +IcePHP::ProxyInfo::wireSize() const +{ + return 1; +} + +Ice::OptionalFormat +IcePHP::ProxyInfo::optionalFormat() const +{ + return Ice::OptionalFormatFSize; +} + +void +IcePHP::ProxyInfo::marshal(zval* zv, const Ice::OutputStreamPtr& os, ObjectMap*, bool optional) +{ + Ice::OutputStream::size_type sizePos = 0; + if(optional) + { + sizePos = os->startSize(); + } + + if(Z_TYPE_P(zv) == IS_NULL) + { + os->write(Ice::ObjectPrx()); + } + else + { + assert(Z_TYPE_P(zv) == IS_OBJECT && Z_OBJCE_P(zv) == proxyClassEntry); // validate() should have caught this. + Ice::ObjectPrx proxy; + ClassInfoPtr info; + if(!fetchProxy(zv, proxy, info)) + { + throw AbortMarshaling(); + } + if(!info->isA(id)) + { + invalidArgument("proxy is not narrowed to %s", id.c_str()); + throw AbortMarshaling(); + } + os->write(proxy); + } + + if(optional) + { + os->endSize(sizePos); + } +} + +void +IcePHP::ProxyInfo::unmarshal(const Ice::InputStreamPtr& is, const UnmarshalCallbackPtr& cb, + const CommunicatorInfoPtr& comm, zval* target, void* closure, bool optional) +{ + zval zv; + AutoDestroy destroy(&zv); + + if(optional) + { + is->skip(4); + } + + Ice::ObjectPrx proxy; + is->read(proxy); + + if(!proxy) + { + ZVAL_NULL(&zv); + cb->unmarshaled(&zv, target, closure); + return; + } + + if(!cls->defined) + { + runtimeError("class or interface %s is declared but not defined", id.c_str()); + throw AbortMarshaling(); + } + + if(!createProxy(&zv, proxy, cls, comm)) + { + throw AbortMarshaling(); + } + cb->unmarshaled(&zv, target, closure); +} + +void +IcePHP::ProxyInfo::print(zval* zv, IceUtilInternal::Output& out, PrintObjectHistory*) +{ + if(!validate(zv, false)) + { + out << "<invalid value - expected " << id << ">"; + return; + } + + if(Z_TYPE_P(zv) == IS_NULL) + { + out << "<nil>"; + } + else + { + Ice::ObjectPrx proxy; + ClassInfoPtr cls; + if(!fetchProxy(zv, proxy, cls)) + { + return; + } + out << proxy->ice_toString(); + } +} + +void +IcePHP::ProxyInfo::destroy() +{ + const_cast<ClassInfoPtr&>(cls) = 0; +} + +// +// ObjectWriter implementation. +// +IcePHP::ObjectWriter::ObjectWriter(zval* object, ObjectMap* objectMap, const ClassInfoPtr& formal) : + _map(objectMap) +{ + // Copy zval and increase ref count + ZVAL_COPY(&_object, object); + + // + // We need to determine the most-derived Slice type supported by this object. + // This is typically a Slice class, but it can also be an interface. + // + // The caller may have provided a ClassInfo representing the formal type, in + // which case we ensure that the actual type is compatible with the formal type. + // + _info = getClassInfoByClass(Z_OBJCE_P(object), formal ? const_cast<zend_class_entry*>(formal->zce) : 0); + assert(_info); +} + +IcePHP::ObjectWriter::~ObjectWriter() +{ + zval_ptr_dtor(&_object); +} + +void +IcePHP::ObjectWriter::ice_preMarshal() +{ + string name = "ice_premarshal"; // Must be lowercase. + if(zend_hash_str_exists(&Z_OBJCE_P(&_object)->function_table, STRCAST(name.c_str()), static_cast<uint>(name.size()))) + { + if(!invokeMethod(&_object, name)) + { + throw AbortMarshaling(); + } + } +} + +void +IcePHP::ObjectWriter::write(const Ice::OutputStreamPtr& os) const +{ + Ice::SlicedDataPtr slicedData; + + if(_info->preserve) + { + // + // Retrieve the SlicedData object that we stored as a hidden member of the PHP object. + // + slicedData = SlicedDataUtil::getMember(const_cast<zval*>(&_object), const_cast<ObjectMap*>(_map)); + } + + os->startObject(slicedData); + + if(_info->id != "::Ice::UnknownSlicedObject") + { + ClassInfoPtr info = _info; + while(info && info->id != Ice::Object::ice_staticId()) + { + assert(info->base); // All classes have the Ice::Object base type. + const bool lastSlice = info->base->id == Ice::Object::ice_staticId(); + os->startSlice(info->id, info->compactId, lastSlice); + + writeMembers(os, info->members); + writeMembers(os, info->optionalMembers); // The optional members have already been sorted by tag. + + os->endSlice(); + + info = info->base; + } + } + + os->endObject(); +} + +void +IcePHP::ObjectWriter::writeMembers(const Ice::OutputStreamPtr& os, const DataMemberList& members) const +{ + for(DataMemberList::const_iterator q = members.begin(); q != members.end(); ++q) + { + DataMemberPtr member = *q; + zval* val = zend_hash_str_find(Z_OBJPROP_P(const_cast<zval*>(&_object)), + STRCAST(member->name.c_str()), static_cast<int>(member->name.size())); + + if(!val) + { + runtimeError("member `%s' of %s is not defined", member->name.c_str(), _info->id.c_str()); + throw AbortMarshaling(); + } + + assert(Z_TYPE_P(val) == IS_INDIRECT); + val = Z_INDIRECT_P(val); + + if(Z_TYPE_P(val) == IS_REFERENCE) + { + val = Z_REFVAL_P(val); + } + + if(member->optional && (isUnset(val) || !os->writeOptional(member->tag, member->type->optionalFormat()))) + { + continue; + } + + if(!member->type->validate(val, false)) + { + invalidArgument("invalid value for %s member `%s'", _info->id.c_str(), member->name.c_str()); + throw AbortMarshaling(); + } + + member->type->marshal(val, os, _map, member->optional); + } +} + +// +// ObjectReader implementation. +// +IcePHP::ObjectReader::ObjectReader(zval* object, const ClassInfoPtr& info, const CommunicatorInfoPtr& comm) : + _info(info), _communicator(comm) +{ + assert(Z_TYPE_P(object) == IS_OBJECT); + ZVAL_DUP(&_object, object); +} + +IcePHP::ObjectReader::~ObjectReader() +{ + zval_ptr_dtor(&_object); +} + +void +IcePHP::ObjectReader::ice_postUnmarshal() +{ + string name = "ice_postunmarshal"; // Must be lowercase. + if(zend_hash_str_exists(&Z_OBJCE(_object)->function_table, + STRCAST(name.c_str()), static_cast<int>(name.size()))) + { + if(!invokeMethod(&_object, name)) + { + throw AbortMarshaling(); + } + } +} + +void +IcePHP::ObjectReader::read(const Ice::InputStreamPtr& is) +{ + is->startObject(); + + const bool unknown = _info->id == "::Ice::UnknownSlicedObject"; + + // + // Unmarshal the slices of a user-defined class. + // + if(!unknown) + { + ClassInfoPtr info = _info; + + while(info && info->id != Ice::Object::ice_staticId()) + { + is->startSlice(); + + DataMemberList::const_iterator p; + + for(p = info->members.begin(); p != info->members.end(); ++p) + { + DataMemberPtr member = *p; + member->type->unmarshal(is, member, _communicator, &_object, 0, false); + } + + // + // The optional members have already been sorted by tag. + // + for(p = info->optionalMembers.begin(); p != info->optionalMembers.end(); ++p) + { + DataMemberPtr member = *p; + if(is->readOptional(member->tag, member->type->optionalFormat())) + { + member->type->unmarshal(is, member, _communicator, &_object, 0, true); + } + else + { + zval zv; + AutoDestroy destroy(&zv); + assignUnset(&zv); + member->setMember(&_object, &zv); + } + } + + is->endSlice(); + + info = info->base; + } + } + + _slicedData = is->endObject(_info->preserve); + + if(_slicedData) + { + SlicedDataUtil* util = reinterpret_cast<SlicedDataUtil*>(is->closure()); + assert(util); + util->add(this); + + // + // Define the "unknownTypeId" member for an instance of UnknownSlicedObject. + // + if(unknown) + { + assert(!_slicedData->slices.empty()); + + const string typeId = _slicedData->slices[0]->typeId; + zval zv; + AutoDestroy typeIdDestroyer(&zv); + ZVAL_STRINGL(&zv, STRCAST(typeId.c_str()), static_cast<int>(typeId.size())); + add_property_zval(&_object, STRCAST("unknownTypeId"), &zv); + } + } +} + +ClassInfoPtr +IcePHP::ObjectReader::getInfo() const +{ + return _info; +} + +zval* +IcePHP::ObjectReader::getObject() const +{ + return const_cast<zval*>(&_object); +} + +Ice::SlicedDataPtr +IcePHP::ObjectReader::getSlicedData() const +{ + return _slicedData; +} + +// +// ReadObjectCallback implementation. +// +IcePHP::ReadObjectCallback::ReadObjectCallback(const ClassInfoPtr& info, const UnmarshalCallbackPtr& cb, + zval* target, void* closure) : + _info(info), _cb(cb), _closure(closure) +{ + ZVAL_NULL(&_target); + + if(target) + { + assert(Z_REFCOUNTED_P(target)); + ZVAL_COPY(&_target, target); + } +} + +IcePHP::ReadObjectCallback::~ReadObjectCallback() +{ + zval_ptr_dtor(&_target); +} + +void +IcePHP::ReadObjectCallback::invoke(const Ice::ObjectPtr& p) +{ + if(p) + { + ObjectReaderPtr reader = ObjectReaderPtr::dynamicCast(p); + assert(reader); + + // + // Verify that the unmarshaled object is compatible with the formal type. + // + zval* obj = reader->getObject(); + if(!reader->getInfo()->isA(_info->id)) + { + Ice::UnexpectedObjectException ex(__FILE__, __LINE__); + ex.reason = "unmarshaled object is not an instance of " + _info->id; + ex.type = reader->getInfo()->id; + ex.expectedType = _info->id; + throw ex; + } + _cb->unmarshaled(obj, &_target, _closure); + } + else + { + zval zv; + AutoDestroy destroy(&zv); + ZVAL_NULL(&zv); + _cb->unmarshaled(&zv, &_target, _closure); + } +} + +// +// ExceptionInfo implementation. +// +zval* +IcePHP::ExceptionInfo::unmarshal(const Ice::InputStreamPtr& is, const CommunicatorInfoPtr& comm) +{ + zval* zv = static_cast<zval*>(emalloc(sizeof(zval))); + + if(object_init_ex(zv, zce) != SUCCESS) + { + runtimeError("unable to initialize object of type %s", zce->name->val); + throw AbortMarshaling(); + } + + // + // NOTE: The type id for the first slice has already been read. + // + ExceptionInfoPtr info = this; + while(info) + { + is->startSlice(); + + DataMemberList::iterator q; + + for(q = info->members.begin(); q != info->members.end(); ++q) + { + DataMemberPtr member = *q; + member->type->unmarshal(is, member, comm, zv, 0, false); + } + + // + // The optional members have already been sorted by tag. + // + for(q = info->optionalMembers.begin(); q != info->optionalMembers.end(); ++q) + { + DataMemberPtr member = *q; + if(is->readOptional(member->tag, member->type->optionalFormat())) + { + member->type->unmarshal(is, member, comm, zv, 0, true); + } + else + { + zval un; + AutoDestroy destroy(&un); + assignUnset(&un); + member->setMember(zv, &un); + } + } + + is->endSlice(); + + info = info->base; + } + + return zv; +} + +void +IcePHP::ExceptionInfo::print(zval* zv, IceUtilInternal::Output& out) +{ + out << "exception " << id; + out.sb(); + + if(Z_TYPE_P(zv) != IS_OBJECT) + { + string s = zendTypeToString(Z_TYPE_P(zv)); + out << nl << "expected exception value of type " << zce->name->val << " but received " << s; + out.eb(); + return; + } + + // + // Compare class entries. + // + zend_class_entry* ce = Z_OBJCE_P(zv); + if(ce != zce) + { + out << nl << "expected exception value of type " << zce->name->val << " but received " << ce->name->val; + out.eb(); + return; + } + + PrintObjectHistory history; + history.index = 0; + + printMembers(zv, out, &history); + out.eb(); +} + +void +IcePHP::ExceptionInfo::printMembers(zval* zv, IceUtilInternal::Output& out, PrintObjectHistory* history) +{ + if(base) + { + base->printMembers(zv, out, history); + } + + DataMemberList::iterator q; + + for(q = members.begin(); q != members.end(); ++q) + { + DataMemberPtr member = *q; + + out << nl << member->name << " = "; + zval* val = zend_hash_str_find(Z_OBJPROP_P(zv), + STRCAST(member->name.c_str()), + static_cast<int>(member->name.size())); + + assert(Z_TYPE_P(val) == IS_INDIRECT); + val = Z_INDIRECT_P(val); + + if(val) + { + member->type->print(val, out, history); + } + else + { + out << "<not defined>"; + } + } + + for(q = optionalMembers.begin(); q != optionalMembers.end(); ++q) + { + DataMemberPtr member = *q; + + out << nl << member->name << " = "; + zval* val = zend_hash_str_find(Z_OBJPROP_P(zv), + STRCAST(member->name.c_str()), + static_cast<int>(member->name.size())); + + assert(Z_TYPE_P(val) == IS_INDIRECT); + val = Z_INDIRECT_P(val); + + if(val) + { + if(isUnset(val)) + { + out << "<unset>"; + } + else + { + member->type->print(val, out, history); + } + } + else + { + out << "<not defined>"; + } + } +} + +bool +IcePHP::ExceptionInfo::isA(const string& typeId) const +{ + if(id == typeId) + { + return true; + } + + if(base && base->isA(typeId)) + { + return true; + } + + return false; +} + +// +// ExceptionReader implementation. +// +IcePHP::ExceptionReader::ExceptionReader(const CommunicatorInfoPtr& communicatorInfo, const ExceptionInfoPtr& info + ) : + Ice::UserExceptionReader(communicatorInfo->getCommunicator()), _communicatorInfo(communicatorInfo), _info(info) +{ +} + +IcePHP::ExceptionReader::~ExceptionReader() + throw() +{ +} + +void +IcePHP::ExceptionReader::read(const Ice::InputStreamPtr& is) const +{ + is->startException(); + const_cast<zval*&>(_ex) = _info->unmarshal(is, _communicatorInfo TSRMLS_CC); + + const_cast<Ice::SlicedDataPtr&>(_slicedData) = is->endException(_info->preserve); +} + +bool +IcePHP::ExceptionReader::usesClasses() const +{ + return _info->usesClasses; +} + +string +IcePHP::ExceptionReader::ice_name() const +{ + return _info->id; +} + +IcePHP::ExceptionReader* +IcePHP::ExceptionReader::ice_clone() const +{ + assert(false); + return 0; +} + +void +IcePHP::ExceptionReader::ice_throw() const +{ + throw *this; +} + +ExceptionInfoPtr +IcePHP::ExceptionReader::getInfo() const +{ + return _info; +} + +zval* +IcePHP::ExceptionReader::getException() const +{ + return _ex; +} + +Ice::SlicedDataPtr +IcePHP::ExceptionReader::getSlicedData() const +{ + return _slicedData; +} + +// +// IdResolver +// +IcePHP::IdResolver::IdResolver(void) +{ +} + +string +IcePHP::IdResolver::resolve(Ice::Int id) const +{ + CompactIdMap* m = reinterpret_cast<CompactIdMap*>(ICE_G(compactIdToClassInfoMap)); + if(m) + { + CompactIdMap::iterator p = m->find(id); + if(p != m->end()) + { + return p->second->id; + } + } + return string(); +} + +#ifdef _WIN32 +extern "C" +#endif +static zend_object* +handleTypeInfoAlloc(zend_class_entry* ce) +{ + Wrapper<TypeInfoPtr>* obj = Wrapper<TypeInfoPtr>::create(ce); + assert(obj); + + obj->zobj.handlers = &_typeInfoHandlers; + + return &obj->zobj; +} + +#ifdef _WIN32 +extern "C" +#endif +static void +handleTypeInfoFreeStorage(zend_object* object) +{ + Wrapper<TypeInfoPtr>* obj = Wrapper<TypeInfoPtr>::fetch(object); + delete obj->ptr; + zend_object_std_dtor(object); +} + +static bool +createTypeInfo(zval* zv, const TypeInfoPtr& p) +{ + assert(typeInfoClassEntry); + if(object_init_ex(zv, typeInfoClassEntry) != SUCCESS) + { + runtimeError("unable to initialize type"); + return false; + } + + Wrapper<TypeInfoPtr>* ze = Wrapper<TypeInfoPtr>::extract(zv); + assert(!ze->ptr); + ze->ptr = new TypeInfoPtr(p); + + return true; +} + +ZEND_FUNCTION(IcePHP_defineEnum) +{ + char* id; + size_t idLen; + zval* enumerators; + + if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("sa"), &id, &idLen, &enumerators) == FAILURE) + { + return; + } + + EnumInfoPtr type = new EnumInfo(id, enumerators); + + if(!createTypeInfo(return_value, type)) + { + RETURN_NULL(); + } +} + +ZEND_FUNCTION(IcePHP_defineStruct) +{ + char* id; + size_t idLen; + char* name; + size_t nameLen; + zval* members; + + if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("ssa"), &id, &idLen, &name, &nameLen, + &members) == FAILURE) + { + return; + } + + StructInfoPtr type = new StructInfo(id, name, members); + + if(!createTypeInfo(return_value, type)) + { + RETURN_NULL(); + } +} + +ZEND_FUNCTION(IcePHP_defineSequence) +{ + char* id; + size_t idLen; + zval* element; + + if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("so"), &id, &idLen, &element) == FAILURE) + { + assert(false); + return; + } + + SequenceInfoPtr type = new SequenceInfo(id, element); + + if(!createTypeInfo(return_value, type)) + { + RETURN_NULL(); + } +} + +ZEND_FUNCTION(IcePHP_defineDictionary) +{ + char* id; + size_t idLen; + zval* key; + zval* value; + + if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("soo"), &id, &idLen, &key, &value) == FAILURE) + { + return; + } + + DictionaryInfoPtr type = new DictionaryInfo(id, key, value); + + if(!createTypeInfo(return_value, type)) + { + RETURN_NULL(); + } +} + +ZEND_FUNCTION(IcePHP_declareProxy) +{ + char* id; + size_t idLen; + + if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("s"), &id, &idLen) == FAILURE) + { + return; + } + + ProxyInfoPtr type = getProxyInfo(id); + if(!type) + { + type = new ProxyInfo(id); + addProxyInfo(type); + } + + if(!createTypeInfo(return_value, type)) + { + RETURN_NULL(); + } +} + +ZEND_FUNCTION(IcePHP_defineProxy) +{ + zval* cls; + + if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("o"), &cls) == FAILURE) + { + return; + } + + TypeInfoPtr p = Wrapper<TypeInfoPtr>::value(cls); + ClassInfoPtr c = ClassInfoPtr::dynamicCast(p); + assert(c); + + ProxyInfoPtr type = getProxyInfo(c->id); + if(!type) + { + type = new ProxyInfo(c->id); + addProxyInfo(type); + } + + type->define(c); + + if(!createTypeInfo(return_value, type)) + { + RETURN_NULL(); + } +} + +ZEND_FUNCTION(IcePHP_declareClass) +{ + char* id; + size_t idLen; + + if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("s"), &id, &idLen) == FAILURE) + { + return; + } + + ClassInfoPtr type = getClassInfoById(id); + if(!type) + { + type = new ClassInfo(id); + addClassInfoById(type); + } + + if(!createTypeInfo(return_value, type)) + { + RETURN_NULL(); + } +} + +ZEND_FUNCTION(IcePHP_defineClass) +{ + char* id; + size_t idLen; + char* name; + size_t nameLen; + long compactId; + zend_bool isAbstract; + zend_bool preserve; + zval* base; + zval* interfaces; + zval* members; + + if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("sslbbo!a!a!"), &id, &idLen, &name, &nameLen, + &compactId, &isAbstract, &preserve, &base, &interfaces, &members) == FAILURE) + { + return; + } + + ClassInfoPtr type = getClassInfoById(id); + if(!type) + { + type = new ClassInfo(id); + addClassInfoById(type); + } + + type->define(name, static_cast<Ice::Int>(compactId), isAbstract ? true : false, preserve ? true : false, base, + interfaces, members); + addClassInfoByName(type); + + CompactIdMap* m = reinterpret_cast<CompactIdMap*>(ICE_G(compactIdToClassInfoMap)); + if(!m) + { + m = new CompactIdMap; + ICE_G(compactIdToClassInfoMap) = m; + } + m->insert(CompactIdMap::value_type(type->compactId, type)); + + if(!createTypeInfo(return_value, type)) + { + RETURN_NULL(); + } +} + +#ifdef _WIN32 +extern "C" +#endif +static zend_object* +handleExceptionInfoAlloc(zend_class_entry* ce) +{ + Wrapper<ExceptionInfoPtr>* obj = Wrapper<ExceptionInfoPtr>::create(ce); + assert(obj); + + obj->zobj.handlers = &_exceptionInfoHandlers; + + return &obj->zobj; +} + +#ifdef _WIN32 +extern "C" +#endif +static void +handleExceptionInfoFreeStorage(zend_object* object) +{ + Wrapper<ExceptionInfoPtr>* obj = Wrapper<ExceptionInfoPtr>::fetch(object); + delete obj->ptr; + zend_object_std_dtor(object); +} + + +static bool +createExceptionInfo(zval* zv, const ExceptionInfoPtr& p) +{ + if(object_init_ex(zv, exceptionInfoClassEntry) != SUCCESS) + { + runtimeError("unable to initialize exception info"); + return false; + } + + Wrapper<ExceptionInfoPtr>* ze = Wrapper<ExceptionInfoPtr>::extract(zv); + assert(!ze->ptr); + ze->ptr = new ExceptionInfoPtr(p); + + return true; +} + +ZEND_FUNCTION(IcePHP_defineException) +{ + char* id; + size_t idLen; + char* name; + size_t nameLen; + zend_bool preserve; + zval* base; + zval* members; + + if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("ssbo!a!"), &id, &idLen, &name, &nameLen, + &preserve, &base, &members) == FAILURE) + { + return; + } + + ExceptionInfoPtr ex = new ExceptionInfo(); + ex->id = id; + ex->name = name; + ex->preserve = preserve ? true : false; + if(base) + { + ex->base = Wrapper<ExceptionInfoPtr>::value(base); + } + if(members) + { + convertDataMembers(members, ex->members, ex->optionalMembers, true); + } + + ex->usesClasses = false; + + // + // Only examine the required members to see if any use classes. + // + for(DataMemberList::iterator p = ex->members.begin(); p != ex->members.end(); ++p) + { + if(!ex->usesClasses) + { + ex->usesClasses = (*p)->type->usesClasses(); + } + } + + ex->zce = nameToClass(ex->name); + + assert(!getExceptionInfo(ex->id)); + + ExceptionInfoMap* m; + if(ICE_G(exceptionInfoMap)) + { + m = reinterpret_cast<ExceptionInfoMap*>(ICE_G(exceptionInfoMap)); + } + else + { + m = new ExceptionInfoMap; + ICE_G(exceptionInfoMap) = m; + } + m->insert(ExceptionInfoMap::value_type(ex->id, ex)); + + if(!createExceptionInfo(return_value, ex)) + { + RETURN_NULL(); + } +} + +ZEND_FUNCTION(IcePHP_stringify) +{ + if(ZEND_NUM_ARGS() != 2) + { + WRONG_PARAM_COUNT; + } + + zval* v; + zval* t; + + if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("zz"), &v, &t) == FAILURE) + { + return; + } + + TypeInfoPtr type = Wrapper<TypeInfoPtr>::value(t); + assert(type); + + ostringstream ostr; + IceUtilInternal::Output out(ostr); + PrintObjectHistory history; + history.index = 0; + type->print(v, out, &history); + + string str = ostr.str(); + RETURN_STRINGL(STRCAST(str.c_str()), static_cast<int>(str.length())); +} + +ZEND_FUNCTION(IcePHP_stringifyException) +{ + if(ZEND_NUM_ARGS() != 2) + { + WRONG_PARAM_COUNT; + } + + zval* v; + zval* t; + + if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("oo"), &v, &t) == FAILURE) + { + return; + } + + ExceptionInfoPtr ex = Wrapper<ExceptionInfoPtr>::value(t); + assert(ex); + + ostringstream ostr; + IceUtilInternal::Output out(ostr); + ex->print(v, out); + + string str = ostr.str(); + RETURN_STRINGL(STRCAST(str.c_str()), static_cast<int>(str.length())); +} + +// +// Necessary to suppress warnings from zend_function_entry in php-5.2. +// +#if defined(__GNUC__) +# pragma GCC diagnostic ignored "-Wwrite-strings" +#endif + +// +// Predefined methods for IcePHP_TypeInfo. +// +static zend_function_entry _typeInfoMethods[] = +{ + {0, 0, 0} +}; + +// +// Predefined methods for IcePHP_ExceptionInfo. +// +static zend_function_entry _exceptionInfoMethods[] = +{ + {0, 0, 0} +}; + +bool +IcePHP::isUnset(zval* zv) +{ + if(Z_TYPE_P(zv) == IS_STRING) + { + return _unsetGUID == string(Z_STRVAL_P(zv), Z_STRLEN_P(zv)); + } + return false; +} + +void +IcePHP::assignUnset(zval* zv) +{ + ZVAL_DUP(zv, ICE_G(unset)); +} + +bool +IcePHP::typesInit(INIT_FUNC_ARGS) +{ + zend_class_entry ce; + + // + // Register the IcePHP_TypeInfo class. + // + INIT_CLASS_ENTRY(ce, "IcePHP_TypeInfo", _typeInfoMethods); + ce.create_object = handleTypeInfoAlloc; + typeInfoClassEntry = zend_register_internal_class(&ce); + memcpy(&_typeInfoHandlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); + _typeInfoHandlers.free_obj = handleTypeInfoFreeStorage; + _typeInfoHandlers.offset = XtOffsetOf(Wrapper<TypeInfoPtr>, zobj); + + // + // Register the IcePHP_ExceptionInfo class. + // + INIT_CLASS_ENTRY(ce, "IcePHP_ExceptionInfo", _exceptionInfoMethods); + ce.create_object = handleExceptionInfoAlloc; + exceptionInfoClassEntry = zend_register_internal_class(&ce); + memcpy(&_exceptionInfoHandlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); + _exceptionInfoHandlers.free_obj = handleExceptionInfoFreeStorage; + _exceptionInfoHandlers.offset = XtOffsetOf(Wrapper<ExceptionInfoPtr>, zobj); + + REGISTER_STRING_CONSTANT("Ice_Unset", const_cast<char*>(_unsetGUID.c_str()), CONST_CS|CONST_PERSISTENT); +#ifdef ICEPHP_USE_NAMESPACES + REGISTER_NS_STRING_CONSTANT("Ice", "Unset", const_cast<char*>(_unsetGUID.c_str()), CONST_CS|CONST_PERSISTENT); +#endif + + return true; +} + +// +// enable warning again +// +#if defined(__GNUC__) +# pragma GCC diagnostic error "-Wwrite-strings" +#endif + +bool +IcePHP::typesRequestInit(void) +{ + // + // Create the global variables for the primitive types. + // + for(int i = static_cast<int>(PrimitiveInfo::KindBool); i <= static_cast<int>(PrimitiveInfo::KindString); ++i) + { + PrimitiveInfoPtr type = new PrimitiveInfo(); + type->kind = static_cast<PrimitiveInfo::Kind>(i); + + zval zv; + if(!createTypeInfo(&zv, type)) + { + zval_ptr_dtor(&zv); + return false; + } + string name = "IcePHP__t_" + type->getId(); + zend_hash_str_update(&EG(symbol_table), const_cast<char*>(name.c_str()), name.size(), &zv); + } + + ICE_G(idToClassInfoMap) = 0; + ICE_G(nameToClassInfoMap) = 0; + ICE_G(proxyInfoMap) = 0; + ICE_G(exceptionInfoMap) = 0; + + zval* unset = static_cast<zval*>(emalloc(sizeof(zval))); + ZVAL_STRINGL(unset, STRCAST(_unsetGUID.c_str()), static_cast<int>(_unsetGUID.length())); + ICE_G(unset) = unset; + + return true; +} + +bool +IcePHP::typesRequestShutdown(void) +{ + if(ICE_G(proxyInfoMap)) + { + ProxyInfoMap* m = static_cast<ProxyInfoMap*>(ICE_G(proxyInfoMap)); + for(ProxyInfoMap::iterator p = m->begin(); p != m->end(); ++p) + { + p->second->destroy(); + } + delete m; + } + + if(ICE_G(idToClassInfoMap)) + { + ClassInfoMap* m = static_cast<ClassInfoMap*>(ICE_G(idToClassInfoMap)); + for(ClassInfoMap::iterator p = m->begin(); p != m->end(); ++p) + { + p->second->destroy(); + } + delete m; + } + + if(ICE_G(nameToClassInfoMap)) + { + ClassInfoMap* m = static_cast<ClassInfoMap*>(ICE_G(nameToClassInfoMap)); + delete m; + } + + delete static_cast<ExceptionInfoMap*>(ICE_G(exceptionInfoMap)); + + zval_dtor(ICE_G(unset)); + efree(ICE_G(unset)); + return true; +} diff --git a/php/src/php7/Types.h b/php/src/php7/Types.h new file mode 100644 index 00000000000..ee3aa294945 --- /dev/null +++ b/php/src/php7/Types.h @@ -0,0 +1,590 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +#ifndef ICEPHP_TYPES_H +#define ICEPHP_TYPES_H + +#include <Config.h> +#include <Communicator.h> +#include <Operation.h> +#include <Ice/Stream.h> +#include <IceUtil/OutputUtil.h> + +// +// Global functions. +// +extern "C" +{ +ZEND_FUNCTION(IcePHP_defineEnum); +ZEND_FUNCTION(IcePHP_defineStruct); +ZEND_FUNCTION(IcePHP_defineSequence); +ZEND_FUNCTION(IcePHP_defineDictionary); +ZEND_FUNCTION(IcePHP_declareProxy); +ZEND_FUNCTION(IcePHP_defineProxy); +ZEND_FUNCTION(IcePHP_declareClass); +ZEND_FUNCTION(IcePHP_defineClass); +ZEND_FUNCTION(IcePHP_defineException); +ZEND_FUNCTION(IcePHP_stringify); +ZEND_FUNCTION(IcePHP_stringifyException); +} + +namespace IcePHP +{ + +// +// This class is raised as an exception when object marshaling needs to be aborted. +// +class AbortMarshaling +{ +}; + +typedef std::map<unsigned int, Ice::ObjectPtr> ObjectMap; + +class ObjectReader; +typedef IceUtil::Handle<ObjectReader> ObjectReaderPtr; + +// +// This class keeps track of PHP objects (instances of Slice classes +// and exceptions) that have preserved slices. +// +class SlicedDataUtil +{ +public: + + ~SlicedDataUtil(); + + void add(const ObjectReaderPtr&); + + void update(TSRMLS_D); + + static void setMember(zval*, const Ice::SlicedDataPtr& TSRMLS_DC); + static Ice::SlicedDataPtr getMember(zval*, ObjectMap* TSRMLS_DC); + +private: + + std::set<ObjectReaderPtr> _readers; + static zend_class_entry* _slicedDataType; + static zend_class_entry* _sliceInfoType; +}; + +struct PrintObjectHistory +{ + int index; + std::map<unsigned int, int> objects; +}; + +// +// The delayed nature of class unmarshaling in the Ice protocol requires us to +// handle unmarshaling using a callback strategy. An instance of UnmarshalCallback +// is supplied to each type's unmarshal() member function. For all types except +// classes, the callback is invoked with the unmarshaled value before unmarshal() +// returns. For class instances, however, the callback may not be invoked until +// the stream's finished() function is called. +// +class UnmarshalCallback : public IceUtil::Shared +{ +public: + + virtual ~UnmarshalCallback(); + + // + // The unmarshaled() member function receives the unmarshaled value. The + // last two arguments are the values passed to unmarshal() for use by + // UnmarshalCallback implementations. + // + virtual void unmarshaled(zval*, zval*, void*) = 0; +}; +typedef IceUtil::Handle<UnmarshalCallback> UnmarshalCallbackPtr; + +// +// Base class for type information. +// +class TypeInfo : public UnmarshalCallback +{ +public: + + virtual std::string getId() const = 0; + + virtual bool validate(zval*, bool) = 0; // Validate type data. Bool enables excpetion throwing. + + virtual bool variableLength() const = 0; + virtual int wireSize() const = 0; + virtual Ice::OptionalFormat optionalFormat() const = 0; + + virtual bool usesClasses() const; // Default implementation returns false. + + virtual void unmarshaled(zval*, zval*, void*); // Default implementation is assert(false). + + virtual void destroy(); + +protected: + + TypeInfo(); + +public: + + // + // The marshal and unmarshal functions can raise Ice exceptions, and may raise + // AbortMarshaling if an error occurs. + // + virtual void marshal(zval*, const Ice::OutputStreamPtr&, ObjectMap*, bool) = 0; + virtual void unmarshal(const Ice::InputStreamPtr&, const UnmarshalCallbackPtr&, const CommunicatorInfoPtr&, + zval*, void*, bool) = 0; + + virtual void print(zval*, IceUtilInternal::Output&, PrintObjectHistory*) = 0; +}; +typedef IceUtil::Handle<TypeInfo> TypeInfoPtr; + +// +// Primitive type information. +// +class PrimitiveInfo : public TypeInfo +{ +public: + + virtual std::string getId() const; + + virtual bool validate(zval*, bool); + + virtual bool variableLength() const; + virtual int wireSize() const; + virtual Ice::OptionalFormat optionalFormat() const; + + virtual void marshal(zval*, const Ice::OutputStreamPtr&, ObjectMap*, bool); + virtual void unmarshal(const Ice::InputStreamPtr&, const UnmarshalCallbackPtr&, const CommunicatorInfoPtr&, + zval*, void*, bool); + + virtual void print(zval*, IceUtilInternal::Output&, PrintObjectHistory*); + + enum Kind + { + KindBool, + KindByte, + KindShort, + KindInt, + KindLong, + KindFloat, + KindDouble, + KindString + }; + + Kind kind; +}; +typedef IceUtil::Handle<PrimitiveInfo> PrimitiveInfoPtr; + +// +// Enum information. +// +class EnumInfo : public TypeInfo +{ +public: + + EnumInfo(const std::string&, zval*); + + virtual std::string getId() const; + + virtual bool validate(zval*, bool); + + virtual bool variableLength() const; + virtual int wireSize() const; + virtual Ice::OptionalFormat optionalFormat() const; + + virtual void marshal(zval*, const Ice::OutputStreamPtr&, ObjectMap*, bool); + virtual void unmarshal(const Ice::InputStreamPtr&, const UnmarshalCallbackPtr&, const CommunicatorInfoPtr&, + zval*, void*, bool); + + virtual void print(zval*, IceUtilInternal::Output&, PrintObjectHistory*); + + const std::string id; + const std::map<Ice::Int, std::string> enumerators; + const Ice::Int maxValue; + +}; +typedef IceUtil::Handle<EnumInfo> EnumInfoPtr; + +class DataMember : public UnmarshalCallback +{ +public: + + virtual void unmarshaled(zval*, zval*, void*); + + void setMember(zval*, zval*); + + std::string name; + TypeInfoPtr type; + bool optional; + int tag; +}; +typedef IceUtil::Handle<DataMember> DataMemberPtr; +typedef std::vector<DataMemberPtr> DataMemberList; + +// +// Struct information. +// +class StructInfo : public TypeInfo +{ +public: + + StructInfo(const std::string&, const std::string&, zval*); + + virtual std::string getId() const; + + virtual bool validate(zval*, bool); + + virtual bool variableLength() const; + virtual int wireSize() const; + virtual Ice::OptionalFormat optionalFormat() const; + + virtual bool usesClasses() const; + + virtual void marshal(zval*, const Ice::OutputStreamPtr&, ObjectMap*, bool); + virtual void unmarshal(const Ice::InputStreamPtr&, const UnmarshalCallbackPtr&, const CommunicatorInfoPtr&, + zval*, void*, bool); + + virtual void print(zval*, IceUtilInternal::Output&, PrintObjectHistory*); + + virtual void destroy(); + + const std::string id; + const std::string name; // PHP class name + const DataMemberList members; + const zend_class_entry* zce; + +private: + + bool _variableLength; + int _wireSize; + zval _nullMarshalValue; +}; +typedef IceUtil::Handle<StructInfo> StructInfoPtr; + +// +// Sequence information. +// +class SequenceInfo : public TypeInfo +{ +public: + + SequenceInfo(const std::string&, zval*); + + virtual std::string getId() const; + + virtual bool validate(zval*, bool); + + virtual bool variableLength() const; + virtual int wireSize() const; + virtual Ice::OptionalFormat optionalFormat() const; + + virtual bool usesClasses() const; + + virtual void marshal(zval*, const Ice::OutputStreamPtr&, ObjectMap*, bool); + virtual void unmarshal(const Ice::InputStreamPtr&, const UnmarshalCallbackPtr&, const CommunicatorInfoPtr&, + zval*, void*, bool); + + virtual void print(zval*, IceUtilInternal::Output&, PrintObjectHistory*); + + virtual void unmarshaled(zval*, zval*, void*); + + virtual void destroy(); + + const std::string id; + const TypeInfoPtr elementType; + +private: + + void marshalPrimitiveSequence(const PrimitiveInfoPtr&, zval*, const Ice::OutputStreamPtr&); + void unmarshalPrimitiveSequence(const PrimitiveInfoPtr&, const Ice::InputStreamPtr&, const UnmarshalCallbackPtr&, + zval*, void*); +}; +typedef IceUtil::Handle<SequenceInfo> SequenceInfoPtr; + +// +// Dictionary information. +// +class DictionaryInfo : public TypeInfo +{ +public: + + DictionaryInfo(const std::string&, zval*, zval*); + + virtual std::string getId() const; + + virtual bool validate(zval*, bool); + + virtual bool variableLength() const; + virtual int wireSize() const; + virtual Ice::OptionalFormat optionalFormat() const; + + virtual bool usesClasses() const; + + virtual void marshal(zval*, const Ice::OutputStreamPtr&, ObjectMap*, bool); + virtual void unmarshal(const Ice::InputStreamPtr&, const UnmarshalCallbackPtr&, const CommunicatorInfoPtr&, + zval*, void*, bool); + + virtual void print(zval*, IceUtilInternal::Output&, PrintObjectHistory*); + + virtual void destroy(); + + class KeyCallback : public UnmarshalCallback + { + public: + + KeyCallback(); + ~KeyCallback(); + + virtual void unmarshaled(zval*, zval*, void*); + + zval key; + }; + typedef IceUtil::Handle<KeyCallback> KeyCallbackPtr; + + class ValueCallback : public UnmarshalCallback + { + public: + + ValueCallback(zval*); + ~ValueCallback(); + + virtual void unmarshaled(zval*, zval*, void*); + + zval key; + }; + typedef IceUtil::Handle<ValueCallback> ValueCallbackPtr; + + std::string id; + TypeInfoPtr keyType; + TypeInfoPtr valueType; + +private: + + bool _variableLength; + int _wireSize; +}; +typedef IceUtil::Handle<DictionaryInfo> DictionaryInfoPtr; + +class ExceptionInfo; +typedef IceUtil::Handle<ExceptionInfo> ExceptionInfoPtr; +typedef std::vector<ExceptionInfoPtr> ExceptionInfoList; + +class ClassInfo; +typedef IceUtil::Handle<ClassInfo> ClassInfoPtr; +typedef std::vector<ClassInfoPtr> ClassInfoList; + +typedef std::vector<TypeInfoPtr> TypeInfoList; + +class ClassInfo : public TypeInfo +{ +public: + + ClassInfo(const std::string&); + + void define(const std::string&, Ice::Int, bool, bool, zval*, zval*, zval*); + + virtual std::string getId() const; + + virtual bool validate(zval*, bool); + + virtual bool variableLength() const; + virtual int wireSize() const; + virtual Ice::OptionalFormat optionalFormat() const; + + virtual bool usesClasses() const; + + virtual void marshal(zval*, const Ice::OutputStreamPtr&, ObjectMap*, bool); + virtual void unmarshal(const Ice::InputStreamPtr&, const UnmarshalCallbackPtr&, const CommunicatorInfoPtr&, + zval*, void*, bool); + + virtual void print(zval*, IceUtilInternal::Output&, PrintObjectHistory*); + + virtual void destroy(); + + void printMembers(zval*, IceUtilInternal::Output&, PrintObjectHistory*); + + bool isA(const std::string&) const; + + void addOperation(const std::string&, const OperationPtr&); + OperationPtr getOperation(const std::string&) const; + + const std::string id; + const std::string name; // PHP class name + const Ice::Int compactId; + const bool isAbstract; + const bool preserve; + const ClassInfoPtr base; + const ClassInfoList interfaces; + const DataMemberList members; + const DataMemberList optionalMembers; + const zend_class_entry* zce; + bool defined; + + typedef std::map<std::string, OperationPtr> OperationMap; + OperationMap operations; +}; + +// +// Proxy information. +// +class ProxyInfo : public TypeInfo +{ +public: + + ProxyInfo(const std::string&); + + void define(const ClassInfoPtr&); + + virtual std::string getId() const; + + virtual bool validate(zval*, bool); + + virtual bool variableLength() const; + virtual int wireSize() const; + virtual Ice::OptionalFormat optionalFormat() const; + + virtual void marshal(zval*, const Ice::OutputStreamPtr&, ObjectMap*, bool); + virtual void unmarshal(const Ice::InputStreamPtr&, const UnmarshalCallbackPtr&, const CommunicatorInfoPtr&, + zval*, void*, bool); + + virtual void print(zval*, IceUtilInternal::Output&, PrintObjectHistory*); + + virtual void destroy(); + + const std::string id; + const ClassInfoPtr cls; + bool defined; +}; +typedef IceUtil::Handle<ProxyInfo> ProxyInfoPtr; + +// +// Exception information. +// +class ExceptionInfo : public IceUtil::Shared +{ +public: + + zval* unmarshal(const Ice::InputStreamPtr&, const CommunicatorInfoPtr&); + + void print(zval*, IceUtilInternal::Output&); + void printMembers(zval*, IceUtilInternal::Output&, PrintObjectHistory*); + + bool isA(const std::string&) const; + + std::string id; + std::string name; // PHP class name + bool preserve; + ExceptionInfoPtr base; + DataMemberList members; + DataMemberList optionalMembers; + bool usesClasses; + zend_class_entry* zce; +}; + +ClassInfoPtr getClassInfoById(const std::string&); +ClassInfoPtr getClassInfoByName(const std::string&); +ExceptionInfoPtr getExceptionInfo(const std::string&); + +bool isUnset(zval*); +void assignUnset(zval*); + +bool typesInit(INIT_FUNC_ARGS); +bool typesRequestInit(void); +bool typesRequestShutdown(void); + +// +// ObjectWriter wraps a PHP object for marshaling. +// +class ObjectWriter : public Ice::ObjectWriter +{ +public: + + ObjectWriter(zval*, ObjectMap*, const ClassInfoPtr&); + ~ObjectWriter(); + + virtual void ice_preMarshal(); + + virtual void write(const Ice::OutputStreamPtr&) const; + +private: + + void writeMembers(const Ice::OutputStreamPtr&, const DataMemberList&) const; + + zval _object; + ObjectMap* _map; + ClassInfoPtr _info; +}; + +// +// ObjectReader unmarshals the state of an Ice object. +// +class ObjectReader : public Ice::ObjectReader +{ +public: + + ObjectReader(zval*, const ClassInfoPtr&, const CommunicatorInfoPtr&); + ~ObjectReader(); + + virtual void ice_postUnmarshal(); + + virtual void read(const Ice::InputStreamPtr&); + + virtual ClassInfoPtr getInfo() const; + + zval* getObject() const; + + Ice::SlicedDataPtr getSlicedData() const; + +private: + + zval _object; + ClassInfoPtr _info; + CommunicatorInfoPtr _communicator; + Ice::SlicedDataPtr _slicedData; +}; + +// +// ExceptionReader creates a PHP user exception and unmarshals it. +// +class ExceptionReader : public Ice::UserExceptionReader +{ +public: + + ExceptionReader(const CommunicatorInfoPtr&, const ExceptionInfoPtr&); + ~ExceptionReader() throw(); + + virtual void read(const Ice::InputStreamPtr&) const; + virtual bool usesClasses() const; + + virtual std::string ice_name() const; + virtual ExceptionReader* ice_clone() const; + virtual void ice_throw() const; + + ExceptionInfoPtr getInfo() const; + + zval* getException() const; + + Ice::SlicedDataPtr getSlicedData() const; + +private: + + CommunicatorInfoPtr _communicatorInfo; + ExceptionInfoPtr _info; + zval* _ex; + Ice::SlicedDataPtr _slicedData; +}; + +class IdResolver : public Ice::CompactIdResolver +{ +public: + + IdResolver(void); + virtual std::string resolve(Ice::Int) const; +}; + +} // End of namespace IcePHP + +#endif diff --git a/php/src/php7/Util.cpp b/php/src/php7/Util.cpp new file mode 100644 index 00000000000..fa16d188475 --- /dev/null +++ b/php/src/php7/Util.cpp @@ -0,0 +1,972 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +#include <Util.h> +#include <IceUtil/UUID.h> +#include <Slice/PHPUtil.h> +#include <algorithm> +#include <ctype.h> + +using namespace std; +using namespace IcePHP; +using namespace Slice::PHP; + +namespace +{ + +bool +getMember(zval* zv, const string& name, zval* member, int type, bool required) +{ + zval* val = zend_hash_str_find(Z_OBJPROP_P(zv), STRCAST(name.c_str()), name.size()); + if(!val) + { + if(required) + { + invalidArgument("object does not contain member `%s'", name.c_str()); + return false; + } + } + + if(val) + { + assert(Z_TYPE_P(val) == IS_INDIRECT); + val = Z_INDIRECT_P(val); + if(Z_TYPE_P(val) != type) + { + string expected = zendTypeToString(type); + string actual = zendTypeToString(Z_TYPE_P(val)); + invalidArgument("expected value of type %s for member `%s' but received %s", expected.c_str(), + name.c_str(), actual.c_str()); + return false; + } + ZVAL_COPY_VALUE(member, val); + } + return true; +} + +void +setStringMember(zval* obj, const string& name, const string& val) +{ + zend_class_entry* cls = Z_OBJCE_P(obj); + assert(cls); + zend_update_property_stringl(cls, + obj, + const_cast<char*>(name.c_str()), + static_cast<int>(name.size()), + const_cast<char*>(val.c_str()), + static_cast<int>(val.size()) + ); +} + +template<typename T> +bool +getVersion(zval* zv, T& v, const char* type) +{ + if(Z_TYPE_P(zv) != IS_OBJECT) + { + invalidArgument("value does not contain an object"); + return false; + } + + zend_class_entry* cls = idToClass(type); + assert(cls); + + zend_class_entry* ce = Z_OBJCE_P(zv); + if(ce != cls) + { + invalidArgument("expected an instance of %s", ce->name->val); + return false; + } + + zval majorVal; + if(!getMember(zv, "major", &majorVal, IS_LONG, true)) + { + return false; + } + + zval minorVal; + if(!getMember(zv, "minor", &minorVal, IS_LONG, true)) + { + return false; + } + + long m; + m = static_cast<long>(Z_LVAL_P(&majorVal)); + if(m < 0 || m > 255) + { + invalidArgument("version major must be a value between 0 and 255"); + return false; + } + v.major = static_cast<Ice::Byte>(m); + + m = static_cast<long>(Z_LVAL_P(&minorVal)); + if(m < 0 || m > 255) + { + invalidArgument("version minor must be a value between 0 and 255"); + return false; + } + v.minor = static_cast<Ice::Byte>(m); + + return true; +} + +template<typename T> +bool +createVersion(zval* zv, const T& version, const char* type) +{ + zend_class_entry* cls = idToClass(type); + assert(cls); + + if(object_init_ex(zv, cls) != SUCCESS) + { + runtimeError("unable to initialize %s", cls->name->val); + return false; + } + + zend_update_property_long(cls, zv, const_cast<char*>("major"), sizeof("major") - 1, version.major); + zend_update_property_long(cls, zv, const_cast<char*>("minor"), sizeof("minor") - 1, version.minor); + + return true; +} + +template<typename T> +bool +versionToString(zval* zv, zval* s, const char* type) +{ + T v; + if(!getVersion<T>(zv, v, type)) + { + return false; + } + + try + { + string str = IceInternal::versionToString<T>(v); + ZVAL_STRINGL(s, STRCAST(str.c_str()), static_cast<int>(str.length())); + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + return false; + } + + return true; +} + +template<typename T> +bool +stringToVersion(const string& s, zval* zv, const char* type) +{ + try + { + T v = IceInternal::stringToVersion<T>(s); + return createVersion<T>(zv, v, type); + } + catch(const IceUtil::Exception& ex) + { + throwException(ex); + } + + return false; +} + +char Ice_ProtocolVersion[] = "::Ice::ProtocolVersion"; +char Ice_EncodingVersion[] = "::Ice::EncodingVersion"; + +} + +void* +IcePHP::extractWrapper(zval* zv) +{ + if(!zv) + { + runtimeError("method %s() must be invoked on an object", get_active_function_name()); + return 0; + } + + zend_object* obj = Z_OBJ_P(zv); + if(!obj) + { + runtimeError("no object found in %s()", get_active_function_name()); + return 0; + } + + return obj; +} + +zend_class_entry* +IcePHP::idToClass(const string& id) +{ +#ifdef ICEPHP_USE_NAMESPACES + string cls = scopedToName(id, true); +#else + string cls = scopedToName(id, false); +#endif + + return nameToClass(cls); +} + +zend_class_entry* +IcePHP::nameToClass(const string& name) +{ + zend_class_entry* result; + zend_string* s = zend_string_init(STRCAST(name.c_str()), static_cast<int>(name.length()), 0); + result = zend_lookup_class(s); + zend_string_release(s); + return result; +} + +bool +IcePHP::createIdentity(zval* zv, const Ice::Identity& id) +{ + zend_class_entry* cls = idToClass("::Ice::Identity"); + assert(cls); + + if(object_init_ex(zv, cls) != SUCCESS) + { + runtimeError("unable to initialize Ice::Identity"); + return false; + } + + setStringMember(zv, "name", id.name); + setStringMember(zv, "category", id.category); + + return true; +} + +bool +IcePHP::extractIdentity(zval* zv, Ice::Identity& id) +{ + if(Z_TYPE_P(zv) != IS_OBJECT) + { + invalidArgument("value does not contain an object"); + return false; + } + + zend_class_entry* cls = idToClass("::Ice::Identity"); + assert(cls); + + zend_class_entry* ce = Z_OBJCE_P(zv); + if(ce != cls) + { + invalidArgument("expected an identity but received %s", ce->name->val); + return false; + } + + // + // Category is optional, but name is required. + // + zval categoryVal; + ZVAL_UNDEF(&categoryVal); + zval nameVal; + + if(!getMember(zv, "category", &categoryVal, IS_STRING, false) || + !getMember(zv, "name", &nameVal, IS_STRING, true)) + { + return false; + } + + id.name = Z_STRVAL_P(&nameVal); + + if(!Z_ISUNDEF(categoryVal)) + { + id.category = Z_STRVAL_P(&categoryVal); + } + else + { + id.category = ""; + } + + return true; +} + +bool +IcePHP::createStringMap(zval* zv, const map<string, string>& ctx) +{ + array_init(zv); + + for(map<string, string>::const_iterator p = ctx.begin(); p != ctx.end(); ++p) + { + if(add_assoc_stringl_ex(zv, + const_cast<char*>(p->first.c_str()), + static_cast<uint>(p->first.length()), + const_cast<char*>(p->second.c_str()), + static_cast<uint>(p->second.length())) == FAILURE) + { + return false; + } + } + + return true; +} + +bool +IcePHP::extractStringMap(zval* zv, map<string, string>& ctx) +{ + if(Z_TYPE_P(zv) != IS_ARRAY) + { + string s = zendTypeToString(Z_TYPE_P(zv)); + invalidArgument("expected an associative array but received %s", s.c_str()); + return false; + } + + HashTable* arr = Z_ARRVAL_P(zv); + zend_ulong num_key; + zend_string* key; + zval* val; + ZEND_HASH_FOREACH_KEY_VAL(arr, num_key, key, val) + { + if(!key) + { + invalidArgument("array key must be a string"); + return false; + } + + if(Z_TYPE_P(val) != IS_STRING) + { + invalidArgument("array value must be a string"); + return false; + } + + ctx[key->val] = Z_STRVAL_P(val); + (void)num_key; // Avoids error from older versions of GCC about unused variable num_key. + } + ZEND_HASH_FOREACH_END(); + + return true; +} + +bool +IcePHP::createStringArray(zval* zv, const Ice::StringSeq& seq) +{ + array_init(zv); + for(Ice::StringSeq::const_iterator p = seq.begin(); p != seq.end(); ++p) + { + if(add_next_index_stringl(zv, STRCAST(p->c_str()), static_cast<uint>(p->length())) == FAILURE) + { + return false; + } + } + + return true; +} + +bool +IcePHP::extractStringArray(zval* zv, Ice::StringSeq& seq) +{ + if(Z_TYPE_P(zv) != IS_ARRAY) + { + string s = zendTypeToString(Z_TYPE_P(zv)); + invalidArgument("expected an array of strings but received %s", s.c_str()); + return false; + } + + HashTable* arr = Z_ARRVAL_P(zv); + zval* val; + ZEND_HASH_FOREACH_VAL(arr, val) + { + if(Z_TYPE_P(val) != IS_STRING) + { + invalidArgument("array element must be a string"); + return false; + } + + string s(Z_STRVAL_P(val), Z_STRLEN_P(val)); + seq.push_back(s); + } + ZEND_HASH_FOREACH_END(); + + return true; +} + +bool +IcePHP::createProtocolVersion(zval* zv, const Ice::ProtocolVersion& v) +{ + return createVersion<Ice::ProtocolVersion>(zv, v, Ice_ProtocolVersion); +} + +bool +IcePHP::createEncodingVersion(zval* zv, const Ice::EncodingVersion& v) +{ + return createVersion<Ice::EncodingVersion>(zv, v, Ice_EncodingVersion); +} + +bool +IcePHP::extractEncodingVersion(zval* zv, Ice::EncodingVersion& v) +{ + return getVersion<Ice::EncodingVersion>(zv, v, Ice_EncodingVersion); +} + +static bool +convertLocalException(const Ice::LocalException& ex, zval* zex) +{ + zend_class_entry* cls = Z_OBJCE_P(zex); + assert(cls); + + // + // Transfer data members from Ice exception to PHP object. + // + try + { + ex.ice_throw(); + } + catch(const Ice::InitializationException& e) + { + setStringMember(zex, "reason", e.reason); + } + catch(const Ice::PluginInitializationException& e) + { + setStringMember(zex, "reason", e.reason); + } + catch(const Ice::AlreadyRegisteredException& e) + { + setStringMember(zex, "kindOfObject", e.kindOfObject); + setStringMember(zex, "id", e.id); + } + catch(const Ice::NotRegisteredException& e) + { + setStringMember(zex, "kindOfObject", e.kindOfObject); + setStringMember(zex, "id", e.id); + } + catch(const Ice::TwowayOnlyException& e) + { + setStringMember(zex, "operation", e.operation); + } + catch(const Ice::UnknownException& e) + { + setStringMember(zex, "unknown", e.unknown); + } + catch(const Ice::ObjectAdapterDeactivatedException& e) + { + setStringMember(zex, "name", e.name); + } + catch(const Ice::ObjectAdapterIdInUseException& e) + { + setStringMember(zex, "id", e.id); + } + catch(const Ice::NoEndpointException& e) + { + setStringMember(zex, "proxy", e.proxy); + } + catch(const Ice::EndpointParseException& e) + { + setStringMember(zex, "str", e.str); + } + catch(const Ice::IdentityParseException& e) + { + setStringMember(zex, "str", e.str); + } + catch(const Ice::ProxyParseException& e) + { + setStringMember(zex, "str", e.str); + } + catch(const Ice::IllegalIdentityException& e) + { + zval id; + if(!createIdentity(&id, e.id)) + { + zval_ptr_dtor(&id); + return false; + } + zend_update_property(cls, zex, const_cast<char*>("id"), sizeof("id") - 1, &id); + zval_ptr_dtor(&id); + } + catch(const Ice::RequestFailedException& e) + { + zval id; + if(!createIdentity(&id, e.id)) + { + zval_ptr_dtor(&id); + return false; + } + zend_update_property(cls, zex, const_cast<char*>("id"), sizeof("id") - 1, &id); + zval_ptr_dtor(&id); + setStringMember(zex, "facet", e.facet); + setStringMember(zex, "operation", e.operation); + } + catch(const Ice::FileException& e) + { + zend_update_property_long(cls, zex, const_cast<char*>("error"), sizeof("error") - 1, e.error); + setStringMember(zex, "path", e.path); + } + catch(const Ice::SyscallException& e) // This must appear after all subclasses of SyscallException. + { + zend_update_property_long(cls, zex, const_cast<char*>("error"), sizeof("error") - 1, e.error); + } + catch(const Ice::DNSException& e) + { + zend_update_property_long(cls, zex, const_cast<char*>("error"), sizeof("error") - 1, e.error); + setStringMember(zex, "host", e.host); + } + catch(const Ice::UnsupportedProtocolException& e) + { + zval v; + if(!createProtocolVersion(&v, e.bad)) + { + zval_ptr_dtor(&v); + return false; + } + zend_update_property(cls, zex, const_cast<char*>("bad"), sizeof("bad") - 1, &v); + zval_ptr_dtor(&v); + + if(!createProtocolVersion(&v, e.supported)) + { + zval_ptr_dtor(&v); + return false; + } + zend_update_property(cls, zex, const_cast<char*>("supported"), sizeof("supported") - 1, &v); + zval_ptr_dtor(&v); + } + catch(const Ice::UnsupportedEncodingException& e) + { + zval v; + if(!createEncodingVersion(&v, e.bad)) + { + zval_ptr_dtor(&v); + return false; + } + zend_update_property(cls, zex, const_cast<char*>("bad"), sizeof("bad") - 1, &v); + zval_ptr_dtor(&v); + + if(!createEncodingVersion(&v, e.supported)) + { + zval_ptr_dtor(&v); + return false; + } + zend_update_property(cls, zex, const_cast<char*>("supported"), sizeof("supported") - 1, &v); + zval_ptr_dtor(&v); + } + catch(const Ice::NoObjectFactoryException& e) + { + setStringMember(zex, "reason", e.reason); + setStringMember(zex, "type", e.type); + } + catch(const Ice::UnexpectedObjectException& e) + { + setStringMember(zex, "reason", e.reason); + setStringMember(zex, "type", e.type); + setStringMember(zex, "expectedType", e.expectedType); + } + catch(const Ice::ProtocolException& e) // This must appear after all subclasses of ProtocolException. + { + setStringMember(zex, "reason", e.reason); + } + catch(const Ice::FeatureNotSupportedException& e) + { + setStringMember(zex, "unsupportedFeature", e.unsupportedFeature); + } + catch(const Ice::SecurityException& e) + { + setStringMember(zex, "reason", e.reason); + } + catch(const Ice::LocalException&) + { + // + // Nothing to do. + // + } + + return true; +} + +void +IcePHP::convertException(zval* zex, const Ice::Exception& ex) +{ + ZVAL_UNDEF(zex); + + ostringstream ostr; + ostr << ex; + string str = ostr.str(); + + try + { + ex.ice_throw(); + } + catch(const Ice::LocalException& e) + { + zend_class_entry* cls = idToClass(e.ice_name()); + if(cls) + { + if(object_init_ex(zex, cls) != SUCCESS) + { + runtimeError("unable to create exception %s", cls->name->val); + return; + } + if(!convertLocalException(e, zex)) + { + return; + } + } + else + { + cls = idToClass("Ice::UnknownLocalException"); + assert(cls); + if(object_init_ex(zex, cls) != SUCCESS) + { + runtimeError("unable to create exception %s", cls->name->val); + return; + } + setStringMember(zex, "unknown", str); + } + } + catch(const Ice::UserException&) + { + zend_class_entry* cls = idToClass("Ice::UnknownUserException"); + assert(cls); + if(object_init_ex(zex, cls) != SUCCESS) + { + runtimeError("unable to create exception %s", cls->name->val); + return; + } + setStringMember(zex, "unknown", str); + } + catch(const Ice::Exception&) + { + zend_class_entry* cls = idToClass("Ice::UnknownException"); + assert(cls); + if(object_init_ex(zex, cls) != SUCCESS) + { + runtimeError("unable to create exception %s", cls->name->val); + return; + } + setStringMember(zex, "unknown", str); + } + + return; +} + +void +IcePHP::throwException(const Ice::Exception& ex) +{ + zval zex; + convertException(&zex, ex); + if(!Z_ISUNDEF(zex)) + { + zend_throw_exception_object(&zex); + } +} + +std::string +IcePHP::zendTypeToString(int type) +{ + string result; + + switch(type) + { + case IS_NULL: + result = "null"; + break; + + case IS_LONG: + result = "long"; + break; + + case IS_DOUBLE: + result = "double"; + break; + + case IS_STRING: + result = "string"; + break; + + case IS_ARRAY: + result = "array"; + break; + + case IS_OBJECT: + result = "object"; + break; + + case IS_TRUE: + case IS_FALSE: + result = "bool"; + break; + + default: + result = "unknown"; + break; + } + + return result; +} + +static void +throwError(const string& name, const string& msg) +{ + if(EG(exception)) + { + return; + } + zval ex; + // AutoDestroy destroy(&ex); + + zend_class_entry* cls; + { + zend_class_entry* p; + zend_string* s = zend_string_init(STRCAST(name.c_str()), static_cast<int>(name.size()), 0); + p = zend_lookup_class(s); + zend_string_release(s); + assert(p); + cls = p; + } + if(object_init_ex(&ex, cls) == FAILURE) + { + assert(false); + } + + // + // Invoke constructor. + // + if(!invokeMethod(&ex, ZEND_CONSTRUCTOR_FUNC_NAME, msg)) + { + assert(false); + } + + zend_throw_exception_object(&ex); + // destroy.release(); +} + +void +IcePHP::runtimeError(const char* fmt, ...) +{ + va_list args; + char msg[1024]; + + va_start(args, fmt); + +#if defined(_MSC_VER) + vsprintf_s(msg, fmt, args); +#else + vsprintf(msg, fmt, args); +#endif + + va_end(args); + + throwError("RuntimeException", msg); +} + +void +IcePHP::invalidArgument(const char* fmt, ...) +{ + va_list args; + char msg[1024]; + + va_start(args, fmt); + +#if defined(_MSC_VER) + vsprintf_s(msg, fmt, args); +#else + vsprintf(msg, fmt, args); +#endif + + va_end(args); + + throwError("InvalidArgumentException", msg); +} + +static bool +invokeMethodHelper(zval* obj, const string& name, zval* param) +{ + assert(zend_hash_str_exists(&Z_OBJCE_P(obj)->function_table, STRCAST(name.c_str()), name.size())); + zval ret, method; + ZVAL_STRING(&method, STRCAST(name.c_str())); + uint32_t numParams = param ? 1 : 0; + // zval** params = param ? ¶m : 0; + int status = 0; + zend_try + { + status = call_user_function(0, obj, &method, &ret, numParams, param); + } + zend_catch + { + status = FAILURE; + } + zend_end_try(); + zval_dtor(&method); + zval_dtor(&ret); + if(status == FAILURE || EG(exception)) + { + return false; + } + return true; +} + +bool +IcePHP::invokeMethod(zval* obj, const string& name) +{ + return invokeMethodHelper(obj, name, 0); +} + +bool +IcePHP::invokeMethod(zval* obj, const string& name, const string& arg) +{ + zval param; + ZVAL_STRINGL(¶m, STRCAST(arg.c_str()), static_cast<int>(arg.size())); + return invokeMethodHelper(obj, name, ¶m); +} + +bool +IcePHP::checkClass(zend_class_entry* ce, zend_class_entry* base) +{ + while(ce) + { + if(ce == base) + { + return true; + } + + for(zend_ulong i = 0; i < ce->num_interfaces; ++i) + { + if(checkClass(ce->interfaces[i], base)) + { + return true; + } + } + + ce = ce->parent; + } + + return false; +} + +ZEND_FUNCTION(Ice_stringVersion) +{ + if(ZEND_NUM_ARGS() > 0) + { + WRONG_PARAM_COUNT; + } + + RETURN_STRINGL(STRCAST(ICE_STRING_VERSION), static_cast<int>(strlen(ICE_STRING_VERSION))); +} + +ZEND_FUNCTION(Ice_intVersion) +{ + if(ZEND_NUM_ARGS() > 0) + { + WRONG_PARAM_COUNT; + } + + RETURN_LONG(ICE_INT_VERSION); +} + +ZEND_FUNCTION(Ice_generateUUID) +{ + if(ZEND_NUM_ARGS() > 0) + { + WRONG_PARAM_COUNT; + } + + string uuid = IceUtil::generateUUID(); + RETURN_STRINGL(STRCAST(uuid.c_str()), static_cast<int>(uuid.size())); +} + +ZEND_FUNCTION(Ice_currentProtocol) +{ + if(ZEND_NUM_ARGS() > 0) + { + WRONG_PARAM_COUNT; + } + + if(!createProtocolVersion(return_value, Ice::currentProtocol)) + { + RETURN_NULL(); + } +} + +ZEND_FUNCTION(Ice_currentProtocolEncoding) +{ + if(ZEND_NUM_ARGS() > 0) + { + WRONG_PARAM_COUNT; + } + + if(!createEncodingVersion(return_value, Ice::currentProtocolEncoding)) + { + RETURN_NULL(); + } +} + +ZEND_FUNCTION(Ice_currentEncoding) +{ + if(ZEND_NUM_ARGS() > 0) + { + WRONG_PARAM_COUNT; + } + + if(!createEncodingVersion(return_value, Ice::currentEncoding)) + { + RETURN_NULL(); + } +} + +ZEND_FUNCTION(Ice_protocolVersionToString) +{ + zend_class_entry* versionClass = idToClass(Ice_ProtocolVersion); + assert(versionClass); + + zval zv; + if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("O"), &zv, versionClass) != SUCCESS) + { + RETURN_NULL(); + } + + if(!versionToString<Ice::ProtocolVersion>(&zv, return_value, Ice_ProtocolVersion)) + { + RETURN_NULL(); + } +} + +ZEND_FUNCTION(Ice_stringToProtocolVersion) +{ + char* str; + size_t strLen; + if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("s"), &str, &strLen) != SUCCESS) + { + RETURN_NULL(); + } + string s(str, strLen); + + if(!stringToVersion<Ice::ProtocolVersion>(s, return_value, Ice_ProtocolVersion)) + { + RETURN_NULL(); + } +} + +ZEND_FUNCTION(Ice_encodingVersionToString) +{ + zend_class_entry* versionClass = idToClass(Ice_EncodingVersion); + assert(versionClass); + + zval* zv; + if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("O"), &zv, versionClass) != SUCCESS) + { + RETURN_NULL(); + } + + if(!versionToString<Ice::EncodingVersion>(zv, return_value, Ice_EncodingVersion)) + { + RETURN_NULL(); + } +} + +ZEND_FUNCTION(Ice_stringToEncodingVersion) +{ + char* str; + size_t strLen; + if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("s"), &str, &strLen) != SUCCESS) + { + RETURN_NULL(); + } + string s(str, strLen); + + if(!stringToVersion<Ice::EncodingVersion>(s, return_value, Ice_EncodingVersion)) + { + RETURN_NULL(); + } +} diff --git a/php/src/php7/Util.h b/php/src/php7/Util.h new file mode 100644 index 00000000000..63384679a86 --- /dev/null +++ b/php/src/php7/Util.h @@ -0,0 +1,188 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +#ifndef ICEPHP_UTIL_H +#define ICEPHP_UTIL_H + +#include <Config.h> + +// +// Global functions. +// +extern "C" +{ +ZEND_FUNCTION(Ice_stringVersion); +ZEND_FUNCTION(Ice_intVersion); +ZEND_FUNCTION(Ice_generateUUID); +ZEND_FUNCTION(Ice_currentProtocol); +ZEND_FUNCTION(Ice_currentProtocolEncoding); +ZEND_FUNCTION(Ice_currentEncoding); +ZEND_FUNCTION(Ice_protocolVersionToString); +ZEND_FUNCTION(Ice_stringToProtocolVersion); +ZEND_FUNCTION(Ice_encodingVersionToString); +ZEND_FUNCTION(Ice_stringToEncodingVersion); +} + +namespace IcePHP +{ + +void* createWrapper(zend_class_entry*, size_t); +void* extractWrapper(zval*); + +// +// Wraps a C++ pointer inside a PHP object. +// +template<typename T> +struct Wrapper +{ + T* ptr; + + static Wrapper<T>* create(zend_class_entry* ce) + { + Wrapper<T>* w = static_cast<Wrapper<T>*>(ecalloc(1, sizeof(Wrapper<T>) + zend_object_properties_size(ce))); + + zend_object_std_init(&w->zobj, ce); + object_properties_init(&w->zobj, ce); + + w->ptr = 0; + return w; + } + + static Wrapper<T>* extract(zval* zv) + { + return reinterpret_cast<Wrapper<T>*>(reinterpret_cast<char *>(extractWrapper(zv)) - XtOffsetOf(Wrapper<T>, zobj)); + } + + static Wrapper<T>* fetch(zend_object* object) + { + return reinterpret_cast<Wrapper<T>*>(reinterpret_cast<char *>(object) - XtOffsetOf(Wrapper<T>, zobj)); + } + + static T value(zval* zv) + { + Wrapper<T>* w = extract(zv); + if(w) + { + return *w->ptr; + } + return 0; + } + + // This must be last element in the struct + zend_object zobj; +}; + +zend_class_entry* idToClass(const std::string&); +zend_class_entry* nameToClass(const std::string&); + +bool createIdentity(zval*, const Ice::Identity&); +bool extractIdentity(zval*, Ice::Identity&); + +bool createStringMap(zval*, const std::map<std::string, std::string>&); +bool extractStringMap(zval*, std::map<std::string, std::string>&); + +bool createStringArray(zval*, const Ice::StringSeq&); +bool extractStringArray(zval*, Ice::StringSeq&); + +// +// Create a PHP instance of Ice_ProtocolVersion. +// +bool createProtocolVersion(zval*, const Ice::ProtocolVersion&); + +// +// Create a PHP instance of Ice_EncodingVersion. +// +bool createEncodingVersion(zval*, const Ice::EncodingVersion&); + +// +// Extracts the members of an encoding version. +// +bool extractEncodingVersion(zval*, Ice::EncodingVersion&); + +// +// Convert the given exception into its PHP equivalent. +// +void convertException(zval*, const Ice::Exception&); + +// +// Convert the exception and "throw" it. +// +void throwException(const Ice::Exception&); + +// +// Convert a Zend type (e.g., IS_BOOL, etc.) to a string for use in error messages. +// +std::string zendTypeToString(int); + +// +// Raise RuntimeException with the given message. +// +void runtimeError(const char*, ...); + +// +// Raise InvalidArgumentException with the given message. +// +void invalidArgument(const char*, ...); + +// +// Invoke a method on a PHP object. The method must not take any arguments. +// +bool invokeMethod(zval*, const std::string&); + +// +// Invoke a method on a PHP object. The method must take one string argument. +// +bool invokeMethod(zval*, const std::string&, const std::string&); + +// +// Check inheritance. +// +bool checkClass(zend_class_entry*, zend_class_entry*); + +// +// Exception-safe efree. +// +class AutoEfree +{ +public: + AutoEfree(void* p) : _p(p) {} + ~AutoEfree() { efree(_p); } + +private: + void* _p; +}; + +// +// Exception-safe zval destroy. +// +class AutoDestroy +{ +public: + AutoDestroy(zval* zv) : _zv(zv) {} + ~AutoDestroy() { if(_zv) zval_ptr_dtor(_zv); } + + zval* release() { zval* z = _zv; _zv = 0; return z; } + +private: + zval* _zv; +}; + +class AutoReleaseString +{ +public: + AutoReleaseString(zend_string* s) : _s(s) {} + ~AutoReleaseString() { if(_s) zend_string_release(_s); } + +private: + zend_string* _s; +}; + +} // End of namespace IcePHP + +#endif |