diff options
Diffstat (limited to 'php/src/php5')
-rw-r--r-- | php/src/php5/.depend.mak | 1233 | ||||
-rw-r--r-- | php/src/php5/Communicator.cpp | 2177 | ||||
-rw-r--r-- | php/src/php5/Communicator.h | 60 | ||||
-rw-r--r-- | php/src/php5/Config.h | 129 | ||||
-rw-r--r-- | php/src/php5/Connection.cpp | 764 | ||||
-rw-r--r-- | php/src/php5/Connection.h | 27 | ||||
-rw-r--r-- | php/src/php5/Endpoint.cpp | 545 | ||||
-rw-r--r-- | php/src/php5/Endpoint.h | 27 | ||||
-rw-r--r-- | php/src/php5/IcePHP.rc | 38 | ||||
-rw-r--r-- | php/src/php5/Init.cpp | 287 | ||||
-rw-r--r-- | php/src/php5/Logger.cpp | 325 | ||||
-rw-r--r-- | php/src/php5/Logger.h | 30 | ||||
-rw-r--r-- | php/src/php5/Makefile | 39 | ||||
-rw-r--r-- | php/src/php5/Makefile.mak | 67 | ||||
-rw-r--r-- | php/src/php5/Operation.cpp | 908 | ||||
-rw-r--r-- | php/src/php5/Operation.h | 37 | ||||
-rw-r--r-- | php/src/php5/Properties.cpp | 697 | ||||
-rw-r--r-- | php/src/php5/Properties.h | 38 | ||||
-rw-r--r-- | php/src/php5/Proxy.cpp | 1762 | ||||
-rw-r--r-- | php/src/php5/Proxy.h | 34 | ||||
-rw-r--r-- | php/src/php5/Types.cpp | 4046 | ||||
-rw-r--r-- | php/src/php5/Types.h | 650 | ||||
-rw-r--r-- | php/src/php5/Util.cpp | 1034 | ||||
-rw-r--r-- | php/src/php5/Util.h | 167 |
24 files changed, 15121 insertions, 0 deletions
diff --git a/php/src/php5/.depend.mak b/php/src/php5/.depend.mak new file mode 100644 index 00000000000..811a3c85864 --- /dev/null +++ b/php/src/php5/.depend.mak @@ -0,0 +1,1233 @@ + +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\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\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\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\Service.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\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\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\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\Service.h" \ + "Endpoint.h" \ + "Types.h" \ + "Communicator.h" \ + "Operation.h" \ + "$(ice_cpp_dir)\include\IceUtil\OutputUtil.h" \ + "Util.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\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\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\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\Service.h" \ + "Util.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\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\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\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\Service.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\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\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\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\Service.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\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\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\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\Service.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\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\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\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\Service.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\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\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\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\Service.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\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\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\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\Service.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\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\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\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\Service.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/php5/Communicator.cpp b/php/src/php5/Communicator.cpp new file mode 100644 index 00000000000..8b03d75a694 --- /dev/null +++ b/php/src/php5/Communicator.cpp @@ -0,0 +1,2177 @@ +// ********************************************************************** +// +// 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/DisableWarnings.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; +zend_class_entry* valueFactoryManagerClassEntry = 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; + +class FactoryWrapper; +typedef IceUtil::Handle<FactoryWrapper> FactoryWrapperPtr; + +class DefaultValueFactory; +typedef IceUtil::Handle<DefaultValueFactory> DefaultValueFactoryPtr; + +// +// CommunicatorInfoI encapsulates communicator-related information that +// is specific to a PHP "request". In other words, multiple PHP requests +// might share the same communicator instance but still need separate +// workspaces. For example, we don't want the value factories installed +// by one request to influence the behavior of another request. +// +class CommunicatorInfoI : public CommunicatorInfo +{ +public: + + CommunicatorInfoI(const ActiveCommunicatorPtr&, zval*); + + virtual void getZval(zval* TSRMLS_DC); + virtual void addRef(TSRMLS_D); + virtual void decRef(TSRMLS_D); + + virtual Ice::CommunicatorPtr getCommunicator() const; + + bool addFactory(zval*, const string&, bool TSRMLS_DC); + FactoryWrapperPtr findFactory(const string&) const; + Ice::ValueFactoryPtr defaultFactory() const { return _defaultFactory; } + void destroyFactories(TSRMLS_D); + + const ActiveCommunicatorPtr ac; + const zval zv; + +private: + + typedef map<string, FactoryWrapperPtr> FactoryMap; + + FactoryMap _factories; + DefaultValueFactoryPtr _defaultFactory; +}; +typedef IceUtil::Handle<CommunicatorInfoI> CommunicatorInfoIPtr; + +// +// Wraps a PHP object/value factory. +// +class FactoryWrapper : public Ice::ValueFactory +{ +public: + + FactoryWrapper(zval*, bool, const CommunicatorInfoIPtr&); + + virtual Ice::ValuePtr create(const string&); + + void getZval(zval* TSRMLS_DC); + + bool isObjectFactory() const; + + void destroy(TSRMLS_D); + +protected: + + zval* _factory; + bool _isObjectFactory; + CommunicatorInfoIPtr _info; +}; + +// +// Implements the default value factory behavior. +// +class DefaultValueFactory : public Ice::ValueFactory +{ +public: + + DefaultValueFactory(const CommunicatorInfoIPtr&); + + virtual Ice::ValuePtr create(const string&); + + void setDelegate(const FactoryWrapperPtr& d) { _delegate = d; } + FactoryWrapperPtr getDelegate() const { return _delegate; } + + void destroy(TSRMLS_D); + +private: + + FactoryWrapperPtr _delegate; + CommunicatorInfoIPtr _info; +}; + +// +// Each PHP request has its own set of value factories. More precisely, there is +// a value factory map for each communicator that is created by a PHP request. +// (see CommunicatorInfoI). +// +// We define a custom value factory manager implementation that delegates to +// to PHP objects supplied by the application. +// +// An instance of this class is installed as the communicator's value factory +// manager, and the class holds a reference to its communicator. When find() is +// invoked, the class resolves the appropriate factory as follows: +// +// * Using its communicator reference as the key, look up the corresponding +// CommunicatorInfoI object in the request-specific communicator map. +// +// * If the type-id is empty, return the default factory. This factory will +// either delegate to an application-supplied default factory (if present) or +// default-construct an instance of a concrete Slice class type. +// +// * For non-empty type-ids, return a wrapper around the application-supplied +// factory, if any. +// +class ValueFactoryManager : public Ice::ValueFactoryManager +{ +public: + + virtual void add(const Ice::ValueFactoryPtr&, const string&); + virtual Ice::ValueFactoryPtr find(const string&) const; + + void setCommunicator(const Ice::CommunicatorPtr& c) { _communicator = c; } + Ice::CommunicatorPtr getCommunicator() const { return _communicator; } + + void getZval(zval* TSRMLS_DC); + + void destroy(); + +private: + + Ice::CommunicatorPtr _communicator; +}; +typedef IceUtil::Handle<ValueFactoryManager> ValueFactoryManagerPtr; + +class ReaperTask : public IceUtil::TimerTask +{ +public: + + virtual void runTimerTask(); +}; + +} + +namespace +{ +// +// Communicator support. +// +zend_object_handlers _handlers; + +// +// ValueFactoryManager support. +// +zend_object_handlers _vfmHandlers; + +// +// 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_value handleAlloc(zend_class_entry* TSRMLS_DC); +static void handleFreeStorage(void* TSRMLS_DC); +static zend_object_value handleClone(zval* TSRMLS_DC); + +static zend_object_value handleVfmAlloc(zend_class_entry* TSRMLS_DC); +static void handleVfmFreeStorage(void* TSRMLS_DC); +static zend_object_value handleVfmClone(zval* TSRMLS_DC); +} + +ZEND_METHOD(Ice_Communicator, __construct) +{ + runtimeError("communicators cannot be instantiated directly" TSRMLS_CC); +} + +ZEND_METHOD(Ice_Communicator, destroy) +{ + CommunicatorInfoIPtr _this = Wrapper<CommunicatorInfoIPtr>::value(getThis() TSRMLS_CC); + 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|value factories installed by this request. + // + _this->destroyFactories(TSRMLS_C); + + 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); + + ValueFactoryManagerPtr vfm = ValueFactoryManagerPtr::dynamicCast(c->getValueFactoryManager()); + assert(vfm); + vfm->destroy(); + + try + { + c->destroy(); + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_Communicator, stringToProxy) +{ + CommunicatorInfoIPtr _this = Wrapper<CommunicatorInfoIPtr>::value(getThis() TSRMLS_CC); + assert(_this); + + char* str; + int strLen; + if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, 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 TSRMLS_CC)) + { + RETURN_NULL(); + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_Communicator, proxyToString) +{ + CommunicatorInfoIPtr _this = Wrapper<CommunicatorInfoIPtr>::value(getThis() TSRMLS_CC); + assert(_this); + + zval* zv; + if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("O!"), &zv, proxyClassEntry) != SUCCESS) + { + RETURN_NULL(); + } + + try + { + string str; + if(zv) + { + Ice::ObjectPrx prx; + ClassInfoPtr info; + if(!fetchProxy(zv, prx, info TSRMLS_CC)) + { + RETURN_NULL(); + } + assert(prx); + str = prx->ice_toString(); + } + RETURN_STRINGL(STRCAST(str.c_str()), static_cast<int>(str.length()), 1); + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_Communicator, propertyToProxy) +{ + CommunicatorInfoIPtr _this = Wrapper<CommunicatorInfoIPtr>::value(getThis() TSRMLS_CC); + assert(_this); + + char* str; + int strLen; + if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, 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 TSRMLS_CC)) + { + RETURN_NULL(); + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_Communicator, proxyToProperty) +{ + CommunicatorInfoIPtr _this = Wrapper<CommunicatorInfoIPtr>::value(getThis() TSRMLS_CC); + assert(_this); + + zval* zv; + char* str; + int strLen; + if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, 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 TSRMLS_CC)) + { + RETURN_NULL(); + } + assert(prx); + + Ice::PropertyDict val = _this->getCommunicator()->proxyToProperty(prx, prefix); + if(!createStringMap(return_value, val TSRMLS_CC)) + { + RETURN_NULL(); + } + } + else + { + array_init(return_value); + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_Communicator, stringToIdentity) +{ + CommunicatorInfoIPtr _this = Wrapper<CommunicatorInfoIPtr>::value(getThis() TSRMLS_CC); + assert(_this); + + char* str; + int strLen; + if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, 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 TSRMLS_CC)) + { + RETURN_NULL(); + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_Communicator, identityToString) +{ + CommunicatorInfoIPtr _this = Wrapper<CommunicatorInfoIPtr>::value(getThis() TSRMLS_CC); + assert(_this); + + zend_class_entry* identityClass = idToClass("::Ice::Identity" TSRMLS_CC); + assert(identityClass); + + zval* zv; + if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("O"), &zv, identityClass) != SUCCESS) + { + RETURN_NULL(); + } + Ice::Identity id; + if(!extractIdentity(zv, id TSRMLS_CC)) + { + RETURN_NULL(); + } + + try + { + string str = _this->getCommunicator()->identityToString(id); + RETURN_STRINGL(STRCAST(str.c_str()), static_cast<int>(str.length()), 1); + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_Communicator, addObjectFactory) +{ + CommunicatorInfoIPtr _this = Wrapper<CommunicatorInfoIPtr>::value(getThis() TSRMLS_CC); + assert(_this); + + zend_class_entry* factoryClass = idToClass("Ice::ObjectFactory" TSRMLS_CC); + assert(factoryClass); + + zval* factory; + char* id; + int idLen; + if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("Os!"), &factory, factoryClass, &id, + &idLen TSRMLS_CC) != SUCCESS) + { + RETURN_NULL(); + } + + string type; + if(id) + { + type = string(id, idLen); + } + + if(!_this->addFactory(factory, type, true TSRMLS_CC)) + { + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_Communicator, findObjectFactory) +{ + CommunicatorInfoIPtr _this = Wrapper<CommunicatorInfoIPtr>::value(getThis() TSRMLS_CC); + assert(_this); + + char* id; + int idLen; + if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("s!"), &id, &idLen TSRMLS_CC) != SUCCESS) + { + RETURN_NULL(); + } + + string type; + if(id) + { + type = string(id, idLen); + } + + FactoryWrapperPtr w = _this->findFactory(type); + if(w && w->isObjectFactory()) + { + w->getZval(return_value TSRMLS_CC); + } + else + { + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_Communicator, getValueFactoryManager) +{ + if(ZEND_NUM_ARGS() > 0) + { + WRONG_PARAM_COUNT; + } + + CommunicatorInfoIPtr _this = Wrapper<CommunicatorInfoIPtr>::value(getThis() TSRMLS_CC); + assert(_this); + + try + { + ValueFactoryManagerPtr vfm = + ValueFactoryManagerPtr::dynamicCast(_this->getCommunicator()->getValueFactoryManager()); + assert(vfm); + if(object_init_ex(return_value, valueFactoryManagerClassEntry) != SUCCESS) + { + runtimeError("unable to initialize properties object" TSRMLS_CC); + RETURN_NULL(); + } + + Wrapper<ValueFactoryManagerPtr>* obj = Wrapper<ValueFactoryManagerPtr>::extract(return_value TSRMLS_CC); + assert(!obj->ptr); + obj->ptr = new ValueFactoryManagerPtr(vfm); + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_Communicator, getImplicitContext) +{ + runtimeError("not implemented" TSRMLS_CC); +} + +ZEND_METHOD(Ice_Communicator, getProperties) +{ + if(ZEND_NUM_ARGS() > 0) + { + WRONG_PARAM_COUNT; + } + + CommunicatorInfoIPtr _this = Wrapper<CommunicatorInfoIPtr>::value(getThis() TSRMLS_CC); + assert(_this); + + try + { + Ice::PropertiesPtr props = _this->getCommunicator()->getProperties(); + if(!createProperties(return_value, props TSRMLS_CC)) + { + RETURN_NULL(); + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_Communicator, getLogger) +{ + if(ZEND_NUM_ARGS() > 0) + { + WRONG_PARAM_COUNT; + } + + CommunicatorInfoIPtr _this = Wrapper<CommunicatorInfoIPtr>::value(getThis() TSRMLS_CC); + assert(_this); + + try + { + Ice::LoggerPtr logger = _this->getCommunicator()->getLogger(); + if(!createLogger(return_value, logger TSRMLS_CC)) + { + RETURN_NULL(); + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_Communicator, getDefaultRouter) +{ + if(ZEND_NUM_ARGS() > 0) + { + WRONG_PARAM_COUNT; + } + + CommunicatorInfoIPtr _this = Wrapper<CommunicatorInfoIPtr>::value(getThis() TSRMLS_CC); + assert(_this); + + try + { + Ice::RouterPrx router = _this->getCommunicator()->getDefaultRouter(); + if(router) + { + ClassInfoPtr info = getClassInfoById("::Ice::Router" TSRMLS_CC); + if(!info) + { + runtimeError("no definition for Ice::Router" TSRMLS_CC); + RETURN_NULL(); + } + if(!createProxy(return_value, router, info, _this TSRMLS_CC)) + { + RETURN_NULL(); + } + } + else + { + RETURN_NULL(); + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_Communicator, setDefaultRouter) +{ + CommunicatorInfoIPtr _this = Wrapper<CommunicatorInfoIPtr>::value(getThis() TSRMLS_CC); + assert(_this); + + zval* zv; + if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("O!"), &zv, proxyClassEntry TSRMLS_CC) != + SUCCESS) + { + RETURN_NULL(); + } + + Ice::ObjectPrx proxy; + ClassInfoPtr info; + if(zv && !fetchProxy(zv, proxy, info TSRMLS_CC)) + { + RETURN_NULL(); + } + + try + { + Ice::RouterPrx router; + if(proxy) + { + if(!info || !info->isA("::Ice::Router")) + { + invalidArgument("setDefaultRouter requires a proxy narrowed to Ice::Router" TSRMLS_CC); + RETURN_NULL(); + } + router = Ice::RouterPrx::uncheckedCast(proxy); + } + _this->getCommunicator()->setDefaultRouter(router); + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_Communicator, getDefaultLocator) +{ + if(ZEND_NUM_ARGS() > 0) + { + WRONG_PARAM_COUNT; + } + + CommunicatorInfoIPtr _this = Wrapper<CommunicatorInfoIPtr>::value(getThis() TSRMLS_CC); + assert(_this); + + try + { + Ice::LocatorPrx locator = _this->getCommunicator()->getDefaultLocator(); + if(locator) + { + ClassInfoPtr info = getClassInfoById("::Ice::Locator" TSRMLS_CC); + if(!info) + { + runtimeError("no definition for Ice::Locator" TSRMLS_CC); + RETURN_NULL(); + } + if(!createProxy(return_value, locator, info, _this TSRMLS_CC)) + { + RETURN_NULL(); + } + } + else + { + RETURN_NULL(); + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_Communicator, setDefaultLocator) +{ + CommunicatorInfoIPtr _this = Wrapper<CommunicatorInfoIPtr>::value(getThis() TSRMLS_CC); + assert(_this); + + zval* zv; + if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("O!"), &zv, proxyClassEntry TSRMLS_CC) != + SUCCESS) + { + RETURN_NULL(); + } + + Ice::ObjectPrx proxy; + ClassInfoPtr info; + if(zv && !fetchProxy(zv, proxy, info TSRMLS_CC)) + { + RETURN_NULL(); + } + + try + { + Ice::LocatorPrx locator; + if(proxy) + { + if(!info || !info->isA("::Ice::Locator")) + { + invalidArgument("setDefaultLocator requires a proxy narrowed to Ice::Locator" TSRMLS_CC); + RETURN_NULL(); + } + locator = Ice::LocatorPrx::uncheckedCast(proxy); + } + _this->getCommunicator()->setDefaultLocator(locator); + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_Communicator, flushBatchRequests) +{ + CommunicatorInfoIPtr _this = Wrapper<CommunicatorInfoIPtr>::value(getThis() TSRMLS_CC); + assert(_this); + + if(ZEND_NUM_ARGS() != 8) + { + WRONG_PARAM_COUNT; + } + + try + { + _this->getCommunicator()->flushBatchRequests(); + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_ValueFactoryManager, __construct) +{ + runtimeError("value factory managers cannot be instantiated directly" TSRMLS_CC); +} + +ZEND_METHOD(Ice_ValueFactoryManager, add) +{ + ValueFactoryManagerPtr _this = Wrapper<ValueFactoryManagerPtr>::value(getThis() TSRMLS_CC); + assert(_this); + + zend_class_entry* factoryClass = idToClass("Ice::ValueFactory" TSRMLS_CC); + assert(factoryClass); + + zval* factory; + char* id; + int idLen; + if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("Os!"), &factory, factoryClass, &id, + &idLen TSRMLS_CC) != SUCCESS) + { + RETURN_NULL(); + } + + string type; + if(id) + { + type = string(id, idLen); + } + + CommunicatorMap* m = static_cast<CommunicatorMap*>(ICE_G(communicatorMap)); + assert(m); + CommunicatorMap::iterator p = m->find(_this->getCommunicator()); + assert(p != m->end()); + + CommunicatorInfoIPtr info = p->second; + + if(!info->addFactory(factory, type, false TSRMLS_CC)) + { + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_ValueFactoryManager, find) +{ + ValueFactoryManagerPtr _this = Wrapper<ValueFactoryManagerPtr>::value(getThis() TSRMLS_CC); + assert(_this); + + char* id; + int idLen; + if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("s!"), &id, &idLen TSRMLS_CC) != SUCCESS) + { + RETURN_NULL(); + } + + string type; + if(id) + { + type = string(id, idLen); + } + + CommunicatorMap* m = static_cast<CommunicatorMap*>(ICE_G(communicatorMap)); + assert(m); + CommunicatorMap::iterator p = m->find(_this->getCommunicator()); + assert(p != m->end()); + + CommunicatorInfoIPtr info = p->second; + + FactoryWrapperPtr w = info->findFactory(type); + if(w) + { + w->getZval(return_value TSRMLS_CC); + } + else + { + RETURN_NULL(); + } +} + +#ifdef _WIN32 +extern "C" +#endif +static zend_object_value +handleAlloc(zend_class_entry* ce TSRMLS_DC) +{ + zend_object_value result; + + Wrapper<CommunicatorInfoIPtr>* obj = Wrapper<CommunicatorInfoIPtr>::create(ce TSRMLS_CC); + assert(obj); + + result.handle = zend_objects_store_put(obj, 0, (zend_objects_free_object_storage_t)handleFreeStorage, 0 TSRMLS_CC); + result.handlers = &_handlers; + + return result; +} + +#ifdef _WIN32 +extern "C" +#endif +static void +handleFreeStorage(void* p TSRMLS_DC) +{ + Wrapper<CommunicatorInfoIPtr>* obj = static_cast<Wrapper<CommunicatorInfoIPtr>*>(p); + delete obj->ptr; + zend_object_std_dtor(static_cast<zend_object*>(p) TSRMLS_CC); + efree(p); +} + +#ifdef _WIN32 +extern "C" +#endif +static zend_object_value +handleClone(zval* zv TSRMLS_DC) +{ + php_error_docref(0 TSRMLS_CC, E_ERROR, "communicators cannot be cloned"); + return zend_object_value(); +} + +#ifdef _WIN32 +extern "C" +#endif +static zend_object_value +handleVfmAlloc(zend_class_entry* ce TSRMLS_DC) +{ + zend_object_value result; + + Wrapper<ValueFactoryManagerPtr>* obj = Wrapper<ValueFactoryManagerPtr>::create(ce TSRMLS_CC); + assert(obj); + + result.handle = + zend_objects_store_put(obj, 0, (zend_objects_free_object_storage_t)handleVfmFreeStorage, 0 TSRMLS_CC); + result.handlers = &_vfmHandlers; + + return result; +} + +#ifdef _WIN32 +extern "C" +#endif +static void +handleVfmFreeStorage(void* p TSRMLS_DC) +{ + Wrapper<ValueFactoryManagerPtr>* obj = static_cast<Wrapper<ValueFactoryManagerPtr>*>(p); + delete obj->ptr; + zend_object_std_dtor(static_cast<zend_object*>(p) TSRMLS_CC); + efree(p); +} + +#ifdef _WIN32 +extern "C" +#endif +static zend_object_value +handleVfmClone(zval* zv TSRMLS_DC) +{ + php_error_docref(0 TSRMLS_CC, E_ERROR, "value factory managers cannot be cloned"); + return zend_object_value(); +} + +static CommunicatorInfoIPtr +createCommunicator(zval* zv, const ActiveCommunicatorPtr& ac TSRMLS_DC) +{ + try + { + if(object_init_ex(zv, communicatorClassEntry) != SUCCESS) + { + runtimeError("unable to initialize communicator object" TSRMLS_CC); + return 0; + } + + Wrapper<CommunicatorInfoIPtr>* obj = Wrapper<CommunicatorInfoIPtr>::extract(zv TSRMLS_CC); + 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 TSRMLS_CC); + return 0; + } +} + +static CommunicatorInfoIPtr +initializeCommunicator(zval* zv, Ice::StringSeq& args, bool hasArgs, const Ice::InitializationData& initData TSRMLS_DC) +{ + try + { + Ice::CommunicatorPtr c; + if(hasArgs) + { + c = Ice::initialize(args, initData); + } + else + { + c = Ice::initialize(initData); + } + + ActiveCommunicatorPtr ac = new ActiveCommunicator(c); + + ValueFactoryManagerPtr vfm = ValueFactoryManagerPtr::dynamicCast(c->getValueFactoryManager()); + assert(vfm); + vfm->setCommunicator(c); + + CommunicatorInfoIPtr info = createCommunicator(zv, ac TSRMLS_CC); + if(!info) + { + try + { + c->destroy(); + } + catch(...) + { + } + + vfm->destroy(); + } + + return info; + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + return 0; + } +} + +ZEND_FUNCTION(Ice_initialize) +{ + if(ZEND_NUM_ARGS() > 2) + { + runtimeError("too many arguments" TSRMLS_CC); + RETURN_NULL(); + } + + zend_class_entry* initClass = idToClass("::Ice::InitializationData" TSRMLS_CC); + 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" TSRMLS_CC); + 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_PP(args[0]) == IS_ARRAY) + { + if(!extractStringArray(*args[0], seq TSRMLS_CC)) + { + RETURN_NULL(); + } + zvargs = *args[0]; + hasArgs = true; + if(ZEND_NUM_ARGS() > 1) + { + if(Z_TYPE_PP(args[1]) != IS_OBJECT || Z_OBJCE_PP(args[1]) != initClass) + { + string s = zendTypeToString(Z_TYPE_PP(args[1])); + invalidArgument("expected InitializationData object but received %s" TSRMLS_CC, s.c_str()); + RETURN_NULL(); + } + zvinit = *args[1]; + } + } + else if(Z_TYPE_PP(args[0]) == IS_OBJECT && Z_OBJCE_PP(args[0]) == initClass) + { + if(ZEND_NUM_ARGS() > 1) + { + runtimeError("too many arguments" TSRMLS_CC); + RETURN_NULL(); + } + zvinit = *args[0]; + } + else + { + string s = zendTypeToString(Z_TYPE_PP(args[0])); + invalidArgument("unexpected argument type %s" TSRMLS_CC, s.c_str()); + RETURN_NULL(); + } + } + + if(zvinit) + { + void* data; + string member; + + member = "properties"; + if(zend_hash_find(Z_OBJPROP_P(zvinit), STRCAST(member.c_str()), static_cast<uint>(member.size() + 1), &data) + == SUCCESS) + { + zval** val = reinterpret_cast<zval**>(data); + if(!fetchProperties(*val, initData.properties TSRMLS_CC)) + { + RETURN_NULL(); + } + } + + member = "logger"; + if(zend_hash_find(Z_OBJPROP_P(zvinit), STRCAST(member.c_str()), static_cast<uint>(member.size() + 1), &data) + == SUCCESS) + { + zval** val = reinterpret_cast<zval**>(data); + if(!fetchLogger(*val, initData.logger TSRMLS_CC)) + { + RETURN_NULL(); + } + } + } + + initData.compactIdResolver = new IdResolver(TSRMLS_C); + initData.valueFactoryManager = new ValueFactoryManager; + + CommunicatorInfoIPtr info = initializeCommunicator(return_value, seq, hasArgs, initData TSRMLS_CC); + if(!info) + { + RETURN_NULL(); + } + + if(zvargs && PZVAL_IS_REF(zvargs)) + { + zval_dtor(zvargs); + if(!createStringArray(zvargs, seq TSRMLS_CC)) + { + RETURN_NULL(); + } + } +} + +ZEND_FUNCTION(Ice_register) +{ + zval* comm; + char* s; + int sLen; + long expires = 0; + if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("Os|l"), &comm, communicatorClassEntry, &s, + &sLen, &expires TSRMLS_CC) != SUCCESS) + { + RETURN_NULL(); + } + + string id(s, sLen); + if(id.empty()) + { + invalidArgument("communicator id cannot be empty" TSRMLS_CC); + RETURN_NULL(); + } + + CommunicatorInfoIPtr info = Wrapper<CommunicatorInfoIPtr>::value(comm TSRMLS_CC); + 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; + int sLen; + if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("s"), &s, &sLen TSRMLS_CC) != 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; + int sLen; + if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("s"), &s, &sLen TSRMLS_CC) != 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 TSRMLS_CC); + return; + } + } + + if(!createCommunicator(return_value, p->second TSRMLS_CC)) + { + RETURN_NULL(); + } +} + +ZEND_FUNCTION(Ice_getProperties) +{ + char* s = 0; + int sLen; + if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("|s"), &s, &sLen TSRMLS_CC) != 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 TSRMLS_CC)) + { + RETURN_NULL(); + } +} + +ZEND_FUNCTION(Ice_identityToString) +{ + zend_class_entry* identityClass = idToClass("::Ice::Identity" TSRMLS_CC); + assert(identityClass); + + zval* zv; + if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("O"), &zv, identityClass) != SUCCESS) + { + RETURN_NULL(); + } + Ice::Identity id; + if(!extractIdentity(zv, id TSRMLS_CC)) + { + RETURN_NULL(); + } + + try + { + string str = Ice::identityToString(id); + RETURN_STRINGL(STRCAST(str.c_str()), static_cast<int>(str.length()), 1); + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + RETURN_NULL(); + } +} + +ZEND_FUNCTION(Ice_stringToIdentity) +{ + char* str; + int strLen; + if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, 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 TSRMLS_CC)) + { + RETURN_NULL(); + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + 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, getValueFactoryManager, 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} +}; + +// +// Predefined methods for ValueFactoryManager. +// +static zend_function_entry _vfmInterfaceMethods[] = +{ + {0, 0, 0} +}; +static zend_function_entry _vfmClassMethods[] = +{ + ZEND_ME(Ice_ValueFactoryManager, __construct, NULL, ZEND_ACC_PRIVATE|ZEND_ACC_CTOR) + ZEND_ME(Ice_ValueFactoryManager, add, NULL, ZEND_ACC_PUBLIC) + ZEND_ME(Ice_ValueFactoryManager, find, NULL, ZEND_ACC_PUBLIC) + {0, 0, 0} +}; + +static bool +createProfile(const string& name, const string& config, const string& options TSRMLS_DC) +{ + ProfileMap::iterator p = _profiles.find(name); + if(p != _profiles.end()) + { + php_error_docref(0 TSRMLS_CC, 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 TSRMLS_CC, 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 TSRMLS_CC, 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 TSRMLS_DC) +{ + // + // 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 TSRMLS_CC, 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 TSRMLS_CC, E_WARNING, "invalid profile section in file %s:\n%s\n", file.c_str(), + line); + return false; + } + + if(!name.empty()) + { + createProfile(name, config, options TSRMLS_CC); + 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 TSRMLS_CC, 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 TSRMLS_CC, E_WARNING, "unknown profile entry in file %s:\n%s\n", file.c_str(), line); + } + + if(name.empty()) + { + php_error_docref(0 TSRMLS_CC, 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 TSRMLS_CC)) + { + return false; + } + } + + return true; +} + +bool +IcePHP::communicatorInit(TSRMLS_D) +{ + // + // 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 TSRMLS_CC); + memcpy(&_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); + _handlers.clone_obj = handleClone; + zend_class_implements(communicatorClassEntry TSRMLS_CC, 1, interface); + + // + // Register the ValueFactoryManager interface. + // +#ifdef ICEPHP_USE_NAMESPACES + INIT_NS_CLASS_ENTRY(ce, "Ice", "ValueFactoryManager", _vfmInterfaceMethods); +#else + INIT_CLASS_ENTRY(ce, "Ice_ValueFactoryManager", _vfmInterfaceMethods); +#endif + zend_class_entry* vfmInterface = zend_register_internal_interface(&ce TSRMLS_CC); + + // + // Register the ValueFactoryManager class. + // + INIT_CLASS_ENTRY(ce, "IcePHP_ValueFactoryManager", _vfmClassMethods); + ce.create_object = handleVfmAlloc; + valueFactoryManagerClassEntry = zend_register_internal_class(&ce TSRMLS_CC); + memcpy(&_vfmHandlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); + _vfmHandlers.clone_obj = handleVfmClone; + zend_class_implements(valueFactoryManagerClassEntry TSRMLS_CC, 1, vfmInterface); + + // + // 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 TSRMLS_CC)) + { + 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 TSRMLS_CC)) + { + 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(TSRMLS_D) +{ + _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(TSRMLS_D) +{ + ICE_G(communicatorMap) = 0; + + return true; +} + +bool +IcePHP::communicatorRequestShutdown(TSRMLS_D) +{ + 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|value factories installed during this request. + // + info->destroyFactories(TSRMLS_C); + } + + // + // 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::FactoryWrapper::FactoryWrapper(zval* factory, bool isObjectFactory, const CommunicatorInfoIPtr& info) : + _factory(factory), + _isObjectFactory(isObjectFactory), + _info(info) +{ + Z_ADDREF_P(_factory); +} + +Ice::ValuePtr +IcePHP::FactoryWrapper::create(const string& id) +{ + // + // Get the TSRM id for the current request. + // + TSRMLS_FETCH(); + + // + // 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" TSRMLS_CC); + } + else + { + cls = getClassInfoById(id TSRMLS_CC); + } + + if(!cls) + { + return 0; + } + + zval* arg; + MAKE_STD_ZVAL(arg); + ZVAL_STRINGL(arg, STRCAST(id.c_str()), static_cast<int>(id.length()), 1); + + zval* obj = 0; + + zend_try + { + const char* func = "create"; + zend_call_method(&_factory, 0, 0, const_cast<char*>(func), static_cast<int>(strlen(func)), &obj, 1, arg, + 0 TSRMLS_CC); + } + zend_catch + { + obj = 0; + } + zend_end_try(); + + zval_ptr_dtor(&arg); + + // + // Bail out if an exception has already been thrown. + // + if(!obj || EG(exception)) + { + throw AbortMarshaling(); + } + + AutoDestroy destroy(obj); + + if(Z_TYPE_P(obj) == IS_NULL) + { + return 0; + } + + return new ObjectReader(obj, cls, _info TSRMLS_CC); +} + +void +IcePHP::FactoryWrapper::getZval(zval* factory TSRMLS_DC) +{ + *factory = *_factory; // This is legal - it simply copies the object's handle. + INIT_PZVAL(factory); + zval_copy_ctor(factory); +} + +bool +IcePHP::FactoryWrapper::isObjectFactory() const +{ + return _isObjectFactory; +} + +void +IcePHP::FactoryWrapper::destroy(TSRMLS_D) +{ + if(_isObjectFactory) + { + // + // Invoke the destroy method on the PHP factory. + // + invokeMethod(_factory, "destroy" TSRMLS_CC); + zend_clear_exception(TSRMLS_C); + } + zval_ptr_dtor(&_factory); + _info = 0; +} + +IcePHP::DefaultValueFactory::DefaultValueFactory(const CommunicatorInfoIPtr& info) : + _info(info) +{ +} + +Ice::ValuePtr +IcePHP::DefaultValueFactory::create(const string& id) +{ + // + // Get the TSRM id for the current request. + // + TSRMLS_FETCH(); + + if(_delegate) + { + Ice::ValuePtr v = _delegate->create(id); + if(v) + { + return v; + } + } + + // + // 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" TSRMLS_CC); + } + else + { + cls = getClassInfoById(id TSRMLS_CC); + } + + if(!cls) + { + return 0; + } + + // + // If the requested type is an abstract class, then we give up. + // + if(cls->isAbstract) + { + return 0; + } + + // + // Instantiate the object. + // + zval* obj; + MAKE_STD_ZVAL(obj); + AutoDestroy destroy(obj); + + if(object_init_ex(obj, const_cast<zend_class_entry*>(cls->zce)) != SUCCESS) + { + throw AbortMarshaling(); + } + + if(!invokeMethod(obj, ZEND_CONSTRUCTOR_FUNC_NAME TSRMLS_CC)) + { + throw AbortMarshaling(); + } + + return new ObjectReader(obj, cls, _info TSRMLS_CC); +} + +void +IcePHP::DefaultValueFactory::destroy(TSRMLS_D) +{ + if(_delegate) + { + _delegate->destroy(); + _delegate = 0; + } + _info = 0; +} + +IcePHP::CommunicatorInfoI::CommunicatorInfoI(const ActiveCommunicatorPtr& c, zval* z) : + ac(c), + zv(*z), // This is legal - it simply copies the object's handle. + _defaultFactory(new DefaultValueFactory(this)) +{ +} + +void +IcePHP::CommunicatorInfoI::getZval(zval* z TSRMLS_DC) +{ + Z_TYPE_P(z) = IS_OBJECT; + z->value.obj = zv.value.obj; + addRef(TSRMLS_C); +} + +void +IcePHP::CommunicatorInfoI::addRef(TSRMLS_D) +{ + zval* p = const_cast<zval*>(&zv); + Z_OBJ_HT_P(p)->add_ref(p TSRMLS_CC); +} + +void +IcePHP::CommunicatorInfoI::decRef(TSRMLS_D) +{ + zval* p = const_cast<zval*>(&zv); + Z_OBJ_HT(zv)->del_ref(p TSRMLS_CC); +} + +Ice::CommunicatorPtr +IcePHP::CommunicatorInfoI::getCommunicator() const +{ + return ac->communicator; +} + +bool +IcePHP::CommunicatorInfoI::addFactory(zval* factory, const string& id, bool isObjectFactory TSRMLS_DC) +{ + if(id.empty()) + { + if(_defaultFactory->getDelegate()) + { + Ice::AlreadyRegisteredException ex(__FILE__, __LINE__); + ex.kindOfObject = "value factory"; + ex.id = id; + throwException(ex TSRMLS_CC); + return false; + } + + _defaultFactory->setDelegate(new FactoryWrapper(factory, isObjectFactory, this)); + } + else + { + FactoryMap::iterator p = _factories.find(id); + if(p != _factories.end()) + { + Ice::AlreadyRegisteredException ex(__FILE__, __LINE__); + ex.kindOfObject = "value factory"; + ex.id = id; + throwException(ex TSRMLS_CC); + return false; + } + + _factories.insert(FactoryMap::value_type(id, new FactoryWrapper(factory, isObjectFactory, this))); + } + + return true; +} + +FactoryWrapperPtr +IcePHP::CommunicatorInfoI::findFactory(const string& id) const +{ + if(id.empty()) + { + return _defaultFactory->getDelegate(); + } + else + { + FactoryMap::const_iterator p = _factories.find(id); + if(p != _factories.end()) + { + return p->second; + } + } + + return 0; +} + +void +IcePHP::CommunicatorInfoI::destroyFactories(TSRMLS_D) +{ + for(FactoryMap::iterator p = _factories.begin(); p != _factories.end(); ++p) + { + p->second->destroy(TSRMLS_C); + } + _factories.clear(); + _defaultFactory->destroy(TSRMLS_C); +} + +void +IcePHP::ValueFactoryManager::add(const Ice::ValueFactoryPtr&, const string&) +{ + // + // We don't support factories registered in C++. + // + throw Ice::FeatureNotSupportedException(__FILE__, __LINE__, "C++ value factory"); +} + +Ice::ValueFactoryPtr +IcePHP::ValueFactoryManager::find(const string& id) const +{ + // + // Get the TSRM id for the current request. + // + TSRMLS_FETCH(); + + CommunicatorMap* m = static_cast<CommunicatorMap*>(ICE_G(communicatorMap)); + assert(m); + CommunicatorMap::iterator p = m->find(_communicator); + assert(p != m->end()); + + CommunicatorInfoIPtr info = p->second; + + if(id.empty()) + { + return info->defaultFactory(); + } + else + { + return info->findFactory(id); + } +} + +void +IcePHP::ValueFactoryManager::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/php5/Communicator.h b/php/src/php5/Communicator.h new file mode 100644 index 00000000000..30f07d273e1 --- /dev/null +++ b/php/src/php5/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/php5/Config.h b/php/src/php5/Config.h new file mode 100644 index 00000000000..0c18832f642 --- /dev/null +++ b/php/src/php5/Config.h @@ -0,0 +1,129 @@ +// ********************************************************************** +// +// 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 + +// +// The PHP header files define a macro named "inline". +// +#ifdef inline +# undef inline +#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 diff --git a/php/src/php5/Connection.cpp b/php/src/php5/Connection.cpp new file mode 100644 index 00000000000..c4bab84d404 --- /dev/null +++ b/php/src/php5/Connection.cpp @@ -0,0 +1,764 @@ +// ********************************************************************** +// +// 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_value handleConnectionAlloc(zend_class_entry* TSRMLS_DC); +static void handleConnectionFreeStorage(void* TSRMLS_DC); +static int handleConnectionCompare(zval*, zval* TSRMLS_DC); + +static zend_object_value handleConnectionInfoAlloc(zend_class_entry* TSRMLS_DC); +static void handleConnectionInfoFreeStorage(void* TSRMLS_DC); +} + +ZEND_METHOD(Ice_Connection, __construct) +{ + runtimeError("Connection cannot be instantiated" TSRMLS_CC); +} + +ZEND_METHOD(Ice_Connection, __toString) +{ + if(ZEND_NUM_ARGS() > 0) + { + WRONG_PARAM_COUNT; + } + + Ice::ConnectionPtr _this = Wrapper<Ice::ConnectionPtr>::value(getThis() TSRMLS_CC); + assert(_this); + + try + { + string str = _this->toString(); + RETURN_STRINGL(STRCAST(str.c_str()), static_cast<int>(str.length()), 1); + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_Connection, close) +{ + Ice::ConnectionPtr _this = Wrapper<Ice::ConnectionPtr>::value(getThis() TSRMLS_CC); + assert(_this); + + zend_bool b; + if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("b"), &b TSRMLS_CC) != SUCCESS) + { + RETURN_NULL(); + } + + try + { + _this->close(b ? true : false); + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_Connection, getEndpoint) +{ + if(ZEND_NUM_ARGS() > 0) + { + WRONG_PARAM_COUNT; + } + + Ice::ConnectionPtr _this = Wrapper<Ice::ConnectionPtr>::value(getThis() TSRMLS_CC); + assert(_this); + + try + { + if(!createEndpoint(return_value, _this->getEndpoint() TSRMLS_CC)) + { + RETURN_NULL(); + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_Connection, flushBatchRequests) +{ + if(ZEND_NUM_ARGS() > 0) + { + WRONG_PARAM_COUNT; + } + + Ice::ConnectionPtr _this = Wrapper<Ice::ConnectionPtr>::value(getThis() TSRMLS_CC); + assert(_this); + + try + { + _this->flushBatchRequests(); + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_Connection, setACM) +{ + Ice::ConnectionPtr _this = Wrapper<Ice::ConnectionPtr>::value(getThis() TSRMLS_CC); + assert(_this); + + zval* t; + zval* c; + zval* h; + if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("zzz"), &t, &c, &h TSRMLS_CC) != SUCCESS) + { + RETURN_NULL(); + } + + IceUtil::Optional<Ice::Int> timeout; + IceUtil::Optional<Ice::ACMClose> close; + IceUtil::Optional<Ice::ACMHeartbeat> heartbeat; + + if(!isUnset(t TSRMLS_CC)) + { + if(Z_TYPE_P(t) != IS_LONG) + { + invalidArgument("value for 'timeout' argument must be Unset or an integer" TSRMLS_CC); + RETURN_NULL(); + } + timeout = static_cast<Ice::Int>(Z_LVAL_P(t)); + } + + if(!isUnset(c TSRMLS_CC)) + { + if(Z_TYPE_P(c) != IS_LONG) + { + invalidArgument("value for 'close' argument must be Unset or an enumerator of ACMClose" TSRMLS_CC); + RETURN_NULL(); + } + close = static_cast<Ice::ACMClose>(Z_LVAL_P(c)); + } + + if(!isUnset(h TSRMLS_CC)) + { + if(Z_TYPE_P(h) != IS_LONG) + { + invalidArgument("value for 'heartbeat' argument must be Unset or an enumerator of ACMHeartbeat" TSRMLS_CC); + RETURN_NULL(); + } + heartbeat = static_cast<Ice::ACMHeartbeat>(Z_LVAL_P(h)); + } + + try + { + _this->setACM(timeout, close, heartbeat); + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_Connection, getACM) +{ + if(ZEND_NUM_ARGS() > 0) + { + WRONG_PARAM_COUNT; + } + + Ice::ConnectionPtr _this = Wrapper<Ice::ConnectionPtr>::value(getThis() TSRMLS_CC); + assert(_this); + + try + { + Ice::ACM acm = _this->getACM(); + + zend_class_entry* acmClass = idToClass("::Ice::ACM" TSRMLS_CC); + + if(object_init_ex(return_value, const_cast<zend_class_entry*>(acmClass)) != SUCCESS) + { + runtimeError("unable to initialize object of type %s" TSRMLS_CC, 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 TSRMLS_CC); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_Connection, type) +{ + if(ZEND_NUM_ARGS() > 0) + { + WRONG_PARAM_COUNT; + } + + Ice::ConnectionPtr _this = Wrapper<Ice::ConnectionPtr>::value(getThis() TSRMLS_CC); + assert(_this); + + try + { + string str = _this->type(); + RETURN_STRINGL(STRCAST(str.c_str()), str.length(), 1); + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_Connection, timeout) +{ + if(ZEND_NUM_ARGS() != 0) + { + WRONG_PARAM_COUNT; + } + + Ice::ConnectionPtr _this = Wrapper<Ice::ConnectionPtr>::value(getThis() TSRMLS_CC); + assert(_this); + + try + { + Ice::Int timeout = _this->timeout(); + ZVAL_LONG(return_value, static_cast<long>(timeout)); + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + 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() TSRMLS_CC); + assert(_this); + + try + { + Ice::ConnectionInfoPtr info = _this->getInfo(); + if(!createConnectionInfo(return_value, _this->getInfo() TSRMLS_CC)) + { + RETURN_NULL(); + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_Connection, setBufferSize) +{ + Ice::ConnectionPtr _this = Wrapper<Ice::ConnectionPtr>::value(getThis() TSRMLS_CC); + assert(_this); + + zval* r; + zval* s; + if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("zz"), &r, &s TSRMLS_CC) != 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 TSRMLS_CC); + RETURN_NULL(); + } +} + +#ifdef _WIN32 +extern "C" +#endif +static zend_object_value +handleConnectionAlloc(zend_class_entry* ce TSRMLS_DC) +{ + zend_object_value result; + + Wrapper<Ice::ConnectionPtr>* obj = Wrapper<Ice::ConnectionPtr>::create(ce TSRMLS_CC); + assert(obj); + + result.handle = zend_objects_store_put(obj, 0, (zend_objects_free_object_storage_t)handleConnectionFreeStorage, + 0 TSRMLS_CC); + result.handlers = &_connectionHandlers; + + return result; +} + +#ifdef _WIN32 +extern "C" +#endif +static void +handleConnectionFreeStorage(void* p TSRMLS_DC) +{ + Wrapper<Ice::ConnectionPtr>* obj = static_cast<Wrapper<Ice::ConnectionPtr>*>(p); + delete obj->ptr; + zend_object_std_dtor(static_cast<zend_object*>(p) TSRMLS_CC); + efree(p); +} + +#ifdef _WIN32 +extern "C" +#endif +static int +handleConnectionCompare(zval* zobj1, zval* zobj2 TSRMLS_DC) +{ + // + // PHP guarantees that the objects have the same class. + // + + Ice::ConnectionPtr con1 = Wrapper<Ice::ConnectionPtr>::value(zobj1 TSRMLS_CC); + assert(con1); + Ice::ConnectionPtr con2 = Wrapper<Ice::ConnectionPtr>::value(zobj2 TSRMLS_CC); + 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" TSRMLS_CC); +} + +// +// 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_value +handleConnectionInfoAlloc(zend_class_entry* ce TSRMLS_DC) +{ + zend_object_value result; + + Wrapper<Ice::ConnectionInfoPtr>* obj = Wrapper<Ice::ConnectionInfoPtr>::create(ce TSRMLS_CC); + assert(obj); + + result.handle = zend_objects_store_put(obj, 0, (zend_objects_free_object_storage_t)handleConnectionInfoFreeStorage, + 0 TSRMLS_CC); + result.handlers = &_connectionInfoHandlers; + + return result; +} + +#ifdef _WIN32 +extern "C" +#endif +static void +handleConnectionInfoFreeStorage(void* p TSRMLS_DC) +{ + Wrapper<Ice::ConnectionInfoPtr>* obj = static_cast<Wrapper<Ice::ConnectionInfoPtr>*>(p); + delete obj->ptr; + zend_object_std_dtor(static_cast<zend_object*>(p) TSRMLS_CC); + efree(p); +} + +bool +IcePHP::connectionInit(TSRMLS_D) +{ + // + // 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 TSRMLS_CC); + + // + // Register the Connection class. + // + INIT_CLASS_ENTRY(ce, "IcePHP_Connection", _connectionClassMethods); + ce.create_object = handleConnectionAlloc; + connectionClassEntry = zend_register_internal_class(&ce TSRMLS_CC); + memcpy(&_connectionHandlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); + _connectionHandlers.compare_objects = handleConnectionCompare; + zend_class_implements(connectionClassEntry TSRMLS_CC, 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 TSRMLS_CC); + memcpy(&_connectionInfoHandlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); + zend_declare_property_bool(connectionInfoClassEntry, STRCAST("incoming"), sizeof("incoming") - 1, 0, + ZEND_ACC_PUBLIC TSRMLS_CC); + zend_declare_property_string(connectionInfoClassEntry, STRCAST("adapterName"), sizeof("adapterName") - 1, + STRCAST(""), ZEND_ACC_PUBLIC TSRMLS_CC); + + // + // 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, NULL TSRMLS_CC); + zend_declare_property_string(ipConnectionInfoClassEntry, STRCAST("localAddress"), sizeof("localAddress") - 1, + STRCAST(""), ZEND_ACC_PUBLIC TSRMLS_CC); + zend_declare_property_long(ipConnectionInfoClassEntry, STRCAST("localPort"), sizeof("localPort") - 1, 0, + ZEND_ACC_PUBLIC TSRMLS_CC); + zend_declare_property_string(ipConnectionInfoClassEntry, STRCAST("remoteAddress"), sizeof("remoteAddress") - 1, + STRCAST(""), ZEND_ACC_PUBLIC TSRMLS_CC); + zend_declare_property_long(ipConnectionInfoClassEntry, STRCAST("remotePort"), sizeof("remotePort") - 1, 0, + ZEND_ACC_PUBLIC TSRMLS_CC); + + // + // 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, NULL TSRMLS_CC); + + // + // 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, NULL TSRMLS_CC); + zend_declare_property_string(udpConnectionInfoClassEntry, STRCAST("mcastAddress"), sizeof("mcastAddress") - 1, + STRCAST(""), ZEND_ACC_PUBLIC TSRMLS_CC); + zend_declare_property_long(udpConnectionInfoClassEntry, STRCAST("mcastPort"), sizeof("mcastPort") - 1, 0, + ZEND_ACC_PUBLIC TSRMLS_CC); + + // + // 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, NULL TSRMLS_CC); + zend_declare_property_string(wsConnectionInfoClassEntry, STRCAST("headers"), sizeof("headers") - 1, + STRCAST(""), ZEND_ACC_PUBLIC TSRMLS_CC); + + // + // 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, NULL TSRMLS_CC); + zend_declare_property_string(sslConnectionInfoClassEntry, STRCAST("cipher"), sizeof("cipher") - 1, + STRCAST(""), ZEND_ACC_PUBLIC TSRMLS_CC); + zend_declare_property_string(sslConnectionInfoClassEntry, STRCAST("certs"), sizeof("certs") - 1, + STRCAST(""), ZEND_ACC_PUBLIC TSRMLS_CC); + zend_declare_property_bool(sslConnectionInfoClassEntry, STRCAST("verified"), sizeof("verified") - 1, 0, + ZEND_ACC_PUBLIC TSRMLS_CC); + + // + // 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, NULL TSRMLS_CC); + zend_declare_property_string(wssConnectionInfoClassEntry, STRCAST("headers"), sizeof("headers") - 1, + STRCAST(""), ZEND_ACC_PUBLIC TSRMLS_CC); + + + return true; +} + +bool +IcePHP::createConnection(zval* zv, const Ice::ConnectionPtr& p TSRMLS_DC) +{ + if(object_init_ex(zv, connectionClassEntry) != SUCCESS) + { + runtimeError("unable to initialize connection" TSRMLS_CC); + return false; + } + + Wrapper<Ice::ConnectionPtr>* obj = Wrapper<Ice::ConnectionPtr>::extract(zv TSRMLS_CC); + assert(obj); + assert(!obj->ptr); + obj->ptr = new Ice::ConnectionPtr(p); + + return true; +} + +bool +IcePHP::fetchConnection(zval* zv, Ice::ConnectionPtr& connection TSRMLS_DC) +{ + 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" TSRMLS_CC); + return false; + } + Wrapper<Ice::ConnectionPtr>* obj = Wrapper<Ice::ConnectionPtr>::extract(zv TSRMLS_CC); + if(!obj) + { + return false; + } + connection = *obj->ptr; + } + return true; +} + +bool +IcePHP::createConnectionInfo(zval* zv, const Ice::ConnectionInfoPtr& p TSRMLS_DC) +{ + int status; + if(Ice::WSConnectionInfoPtr::dynamicCast(p)) + { + Ice::WSConnectionInfoPtr info = Ice::WSConnectionInfoPtr::dynamicCast(p); + if((status = object_init_ex(zv, wsConnectionInfoClassEntry)) == SUCCESS) + { + zval* zmap; + MAKE_STD_ZVAL(zmap); + AutoDestroy mapDestroyer(zmap); + if(createStringMap(zmap, info->headers TSRMLS_CC)) + { + 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()), 1); + 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; + MAKE_STD_ZVAL(zmap); + AutoDestroy mapDestroyer(zmap); + if(createStringMap(zmap, info->headers TSRMLS_CC)) + { + 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" TSRMLS_CC); + 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()), 1); + add_property_bool(zv, STRCAST("verified"), info->verified ? 1 : 0); + + zval* zarr; + MAKE_STD_ZVAL(zarr); + AutoDestroy listDestroyer(zarr); + if(createStringArray(zarr, info->certs TSRMLS_CC)) + { + 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()), 1); + add_property_long(zv, STRCAST("localPort"), static_cast<long>(info->localPort)); + add_property_string(zv, STRCAST("remoteAddress"), const_cast<char*>(info->remoteAddress.c_str()), 1); + 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()), 1); + 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 TSRMLS_CC); + assert(obj); + assert(!obj->ptr); + obj->ptr = new Ice::ConnectionInfoPtr(p); + + return true; +} diff --git a/php/src/php5/Connection.h b/php/src/php5/Connection.h new file mode 100644 index 00000000000..cfdaef321ae --- /dev/null +++ b/php/src/php5/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(TSRMLS_D); + +bool createConnection(zval*, const Ice::ConnectionPtr& TSRMLS_DC); +bool fetchConnection(zval*, Ice::ConnectionPtr& TSRMLS_DC); + +bool createConnectionInfo(zval*, const Ice::ConnectionInfoPtr& TSRMLS_DC); + +} // End of namespace IcePHP + +#endif diff --git a/php/src/php5/Endpoint.cpp b/php/src/php5/Endpoint.cpp new file mode 100644 index 00000000000..f9f0ca00c26 --- /dev/null +++ b/php/src/php5/Endpoint.cpp @@ -0,0 +1,545 @@ +// ********************************************************************** +// +// 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_value handleEndpointAlloc(zend_class_entry* TSRMLS_DC); +static void handleEndpointFreeStorage(void* TSRMLS_DC); + +static zend_object_value handleEndpointInfoAlloc(zend_class_entry* TSRMLS_DC); +static void handleEndpointInfoFreeStorage(void* TSRMLS_DC); +} + +ZEND_METHOD(Ice_Endpoint, __construct) +{ + runtimeError("Endpoint cannot be instantiated" TSRMLS_CC); +} + +ZEND_METHOD(Ice_Endpoint, __toString) +{ + if(ZEND_NUM_ARGS() > 0) + { + WRONG_PARAM_COUNT; + } + + Ice::EndpointPtr _this = Wrapper<Ice::EndpointPtr>::value(getThis() TSRMLS_CC); + assert(_this); + + try + { + string str = _this->toString(); + RETURN_STRINGL(STRCAST(str.c_str()), static_cast<int>(str.length()), 1); + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + 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() TSRMLS_CC); + assert(_this); + + if(!createEndpointInfo(return_value, _this->getInfo() TSRMLS_CC)) + { + RETURN_NULL(); + } +} + +#ifdef _WIN32 +extern "C" +#endif +static zend_object_value +handleEndpointAlloc(zend_class_entry* ce TSRMLS_DC) +{ + zend_object_value result; + + Wrapper<Ice::EndpointPtr>* obj = Wrapper<Ice::EndpointPtr>::create(ce TSRMLS_CC); + assert(obj); + + result.handle = zend_objects_store_put(obj, 0, (zend_objects_free_object_storage_t)handleEndpointFreeStorage, + 0 TSRMLS_CC); + result.handlers = &_endpointHandlers; + + return result; +} + +#ifdef _WIN32 +extern "C" +#endif +static void +handleEndpointFreeStorage(void* p TSRMLS_DC) +{ + Wrapper<Ice::EndpointPtr>* obj = static_cast<Wrapper<Ice::EndpointPtr>*>(p); + delete obj->ptr; + zend_object_std_dtor(static_cast<zend_object*>(p) TSRMLS_CC); + efree(p); +} + +ZEND_METHOD(Ice_EndpointInfo, __construct) +{ + runtimeError("EndpointInfo cannot be instantiated" TSRMLS_CC); +} + +ZEND_METHOD(Ice_EndpointInfo, type) +{ + if(ZEND_NUM_ARGS() > 0) + { + WRONG_PARAM_COUNT; + } + + Ice::EndpointInfoPtr _this = Wrapper<Ice::EndpointInfoPtr>::value(getThis() TSRMLS_CC); + assert(_this); + + try + { + short type = static_cast<short>(_this->type()); + RETURN_LONG(type); + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_EndpointInfo, datagram) +{ + if(ZEND_NUM_ARGS() > 0) + { + WRONG_PARAM_COUNT; + } + + Ice::EndpointInfoPtr _this = Wrapper<Ice::EndpointInfoPtr>::value(getThis() TSRMLS_CC); + assert(_this); + + try + { + RETURN_BOOL(_this->datagram() ? 1 : 0); + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_EndpointInfo, secure) +{ + if(ZEND_NUM_ARGS() > 0) + { + WRONG_PARAM_COUNT; + } + + Ice::EndpointInfoPtr _this = Wrapper<Ice::EndpointInfoPtr>::value(getThis() TSRMLS_CC); + assert(_this); + + try + { + RETURN_BOOL(_this->secure() ? 1 : 0); + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + RETURN_NULL(); + } +} + +#ifdef _WIN32 +extern "C" +#endif +static zend_object_value +handleEndpointInfoAlloc(zend_class_entry* ce TSRMLS_DC) +{ + zend_object_value result; + + Wrapper<Ice::EndpointInfoPtr>* obj = Wrapper<Ice::EndpointInfoPtr>::create(ce TSRMLS_CC); + assert(obj); + + result.handle = zend_objects_store_put(obj, 0, (zend_objects_free_object_storage_t)handleEndpointInfoFreeStorage, + 0 TSRMLS_CC); + result.handlers = &_endpointInfoHandlers; + + return result; +} + +#ifdef _WIN32 +extern "C" +#endif +static void +handleEndpointInfoFreeStorage(void* p TSRMLS_DC) +{ + Wrapper<Ice::EndpointInfoPtr>* obj = static_cast<Wrapper<Ice::EndpointInfoPtr>*>(p); + delete obj->ptr; + zend_object_std_dtor(static_cast<zend_object*>(p) TSRMLS_CC); + efree(p); +} + +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(TSRMLS_D) +{ + // + // 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 TSRMLS_CC); + + // + // Define a concrete Endpoint implementation class. + // + INIT_CLASS_ENTRY(ce, "IcePHP_Endpoint", _endpointMethods); + ce.create_object = handleEndpointAlloc; + endpointClassEntry = zend_register_internal_class(&ce TSRMLS_CC); + memcpy(&_endpointHandlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); + zend_class_implements(endpointClassEntry TSRMLS_CC, 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 TSRMLS_CC); + memcpy(&_endpointInfoHandlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); + zend_declare_property_long(endpointInfoClassEntry, STRCAST("timeout"), sizeof("timeout") - 1, 0, + ZEND_ACC_PUBLIC TSRMLS_CC); + zend_declare_property_bool(endpointInfoClassEntry, STRCAST("compress"), sizeof("compress") - 1, 0, + ZEND_ACC_PUBLIC TSRMLS_CC); + + // + // 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, NULL TSRMLS_CC); + zend_declare_property_string(ipEndpointInfoClassEntry, STRCAST("host"), sizeof("host") - 1, STRCAST(""), + ZEND_ACC_PUBLIC TSRMLS_CC); + zend_declare_property_long(ipEndpointInfoClassEntry, STRCAST("port"), sizeof("port") - 1, 0, + ZEND_ACC_PUBLIC TSRMLS_CC); + zend_declare_property_string(ipEndpointInfoClassEntry, STRCAST("sourceAddress"), sizeof("sourceAddress") - 1, + STRCAST(""), ZEND_ACC_PUBLIC TSRMLS_CC); + + // + // 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, NULL TSRMLS_CC); + + // + // 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, NULL TSRMLS_CC); + zend_declare_property_string(udpEndpointInfoClassEntry, STRCAST("mcastInterface"), sizeof("mcastInterface") - 1, + STRCAST(""), ZEND_ACC_PUBLIC TSRMLS_CC); + zend_declare_property_long(udpEndpointInfoClassEntry, STRCAST("mcastTtl"), sizeof("mcastTtl") - 1, 0, + ZEND_ACC_PUBLIC TSRMLS_CC); + + // + // 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, NULL TSRMLS_CC); + zend_declare_property_string(wsEndpointInfoClassEntry, STRCAST("resource"), sizeof("resource") - 1, + STRCAST(""), ZEND_ACC_PUBLIC TSRMLS_CC); + + // + // 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, NULL TSRMLS_CC); + zend_declare_property_null(opaqueEndpointInfoClassEntry, STRCAST("rawEncoding"), sizeof("rawEncoding") - 1, + ZEND_ACC_PUBLIC TSRMLS_CC); + zend_declare_property_null(opaqueEndpointInfoClassEntry, STRCAST("rawBytes"), sizeof("rawBytes") - 1, + ZEND_ACC_PUBLIC TSRMLS_CC); + + // + // 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, NULL TSRMLS_CC); + + // + // 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, NULL TSRMLS_CC); + zend_declare_property_string(wssEndpointInfoClassEntry, STRCAST("resource"), sizeof("resource") - 1, + STRCAST(""), ZEND_ACC_PUBLIC TSRMLS_CC); + + return true; +} + +bool +IcePHP::createEndpoint(zval* zv, const Ice::EndpointPtr& p TSRMLS_DC) +{ + if(object_init_ex(zv, endpointClassEntry) != SUCCESS) + { + runtimeError("unable to initialize endpoint" TSRMLS_CC); + return false; + } + + Wrapper<Ice::EndpointPtr>* obj = Wrapper<Ice::EndpointPtr>::extract(zv TSRMLS_CC); + assert(obj); + assert(!obj->ptr); + obj->ptr = new Ice::EndpointPtr(p); + + return true; +} + +bool +IcePHP::fetchEndpoint(zval* zv, Ice::EndpointPtr& endpoint TSRMLS_DC) +{ + 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" TSRMLS_CC); + return false; + } + Wrapper<Ice::EndpointPtr>* obj = Wrapper<Ice::EndpointPtr>::extract(zv TSRMLS_CC); + if(!obj) + { + return false; + } + endpoint = *obj->ptr; + } + return true; +} + +bool +IcePHP::createEndpointInfo(zval* zv, const Ice::EndpointInfoPtr& p TSRMLS_DC) +{ + 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()), 1); + } + } + 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()), 1); + 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; + MAKE_STD_ZVAL(rawEncoding); + createEncodingVersion(rawEncoding, info->rawEncoding TSRMLS_CC); + add_property_zval(zv, STRCAST("rawEncoding"), rawEncoding); + zval_ptr_dtor(&rawEncoding); // add_property_zval increased the refcount of rawEncoding + + zval* rawBytes; + MAKE_STD_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()), 1); + } + } + 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" TSRMLS_CC); + 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()), 1); + add_property_long(zv, STRCAST("port"), static_cast<long>(info->port)); + add_property_string(zv, STRCAST("sourceAddress"), const_cast<char*>(info->sourceAddress.c_str()), 1); + } + + 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 TSRMLS_CC); + assert(obj); + assert(!obj->ptr); + obj->ptr = new Ice::EndpointInfoPtr(p); + + return true; +} diff --git a/php/src/php5/Endpoint.h b/php/src/php5/Endpoint.h new file mode 100644 index 00000000000..1559c0a89f6 --- /dev/null +++ b/php/src/php5/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(TSRMLS_D); + +bool createEndpoint(zval*, const Ice::EndpointPtr& TSRMLS_DC); +bool fetchEndpoint(zval*, Ice::EndpointPtr& TSRMLS_DC); + +bool createEndpointInfo(zval*, const Ice::EndpointInfoPtr& TSRMLS_DC); + +} // End of namespace IcePHP + +#endif diff --git a/php/src/php5/IcePHP.rc b/php/src/php5/IcePHP.rc new file mode 100644 index 00000000000..c46127e6330 --- /dev/null +++ b/php/src/php5/IcePHP.rc @@ -0,0 +1,38 @@ +#include "winver.h" + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 3,7,0,0 + PRODUCTVERSION 3,7,0,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.7.0\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.7.0\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1252 + END +END diff --git a/php/src/php5/Init.cpp b/php/src/php5/Init.cpp new file mode 100644 index 00000000000..fbb397724d8 --- /dev/null +++ b/php/src/php5/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_uint>(-1)) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(Ice_createProperties_arginfo, 1, ZEND_RETURN_VALUE, static_cast<zend_uint>(-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(TSRMLS_C)) + { + return FAILURE; + } + + if(!propertiesInit(TSRMLS_C)) + { + return FAILURE; + } + + if(!proxyInit(TSRMLS_C)) + { + return FAILURE; + } + + if(!typesInit(INIT_FUNC_ARGS_PASSTHRU)) + { + return FAILURE; + } + + if(!loggerInit(TSRMLS_C)) + { + return FAILURE; + } + + if(!endpointInit(TSRMLS_C)) + { + return FAILURE; + } + + if(!connectionInit(TSRMLS_C)) + { + return FAILURE; + } + + return SUCCESS; +} + +ZEND_MSHUTDOWN_FUNCTION(ice) +{ + UNREGISTER_INI_ENTRIES(); + + int status = SUCCESS; + + if(!communicatorShutdown(TSRMLS_C)) + { + status = FAILURE; + } + + return status; +} + +ZEND_RINIT_FUNCTION(ice) +{ + ICE_G(communicatorMap) = 0; + + if(!communicatorRequestInit(TSRMLS_C)) + { + return FAILURE; + } + + if(!typesRequestInit(TSRMLS_C)) + { + return FAILURE; + } + + return SUCCESS; +} + +ZEND_RSHUTDOWN_FUNCTION(ice) +{ + if(!communicatorRequestShutdown(TSRMLS_C)) + { + return FAILURE; + } + + if(!typesRequestShutdown(TSRMLS_C)) + { + 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/php5/Logger.cpp b/php/src/php5/Logger.cpp new file mode 100644 index 00000000000..eb911c71de7 --- /dev/null +++ b/php/src/php5/Logger.cpp @@ -0,0 +1,325 @@ +// ********************************************************************** +// +// 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_value handleAlloc(zend_class_entry* TSRMLS_DC); +static void handleFreeStorage(void* TSRMLS_DC); +static zend_object_value handleClone(zval* TSRMLS_DC); +} + +ZEND_METHOD(Ice_Logger, __construct) +{ + runtimeError("logger objects cannot be instantiated" TSRMLS_CC); +} + +ZEND_METHOD(Ice_Logger, __toString) +{ + if(ZEND_NUM_ARGS() > 0) + { + WRONG_PARAM_COUNT; + } + + RETURN_NULL(); +} + +ZEND_METHOD(Ice_Logger, print) +{ + char* m; + int mLen; + + if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("s"), &m, &mLen) == FAILURE) + { + RETURN_NULL(); + } + + Ice::LoggerPtr _this = Wrapper<Ice::LoggerPtr>::value(getThis() TSRMLS_CC); + assert(_this); + + string msg(m, mLen); + try + { + _this->print(msg); + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_Logger, trace) +{ + char* c; + int cLen; + char* m; + int mLen; + + if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("ss"), &c, &cLen, &m, &mLen) == FAILURE) + { + RETURN_NULL(); + } + + Ice::LoggerPtr _this = Wrapper<Ice::LoggerPtr>::value(getThis() TSRMLS_CC); + assert(_this); + + string category(c, cLen); + string msg(m, mLen); + try + { + _this->trace(category, msg); + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_Logger, warning) +{ + char* m; + int mLen; + + if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("s"), &m, &mLen) == FAILURE) + { + RETURN_NULL(); + } + + Ice::LoggerPtr _this = Wrapper<Ice::LoggerPtr>::value(getThis() TSRMLS_CC); + assert(_this); + + string msg(m, mLen); + try + { + _this->warning(msg); + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_Logger, error) +{ + char* m; + int mLen; + + if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("s"), &m, &mLen) == FAILURE) + { + RETURN_NULL(); + } + + Ice::LoggerPtr _this = Wrapper<Ice::LoggerPtr>::value(getThis() TSRMLS_CC); + assert(_this); + + string msg(m, mLen); + try + { + _this->error(msg); + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_Logger, cloneWithPrefix) +{ + char* p; + int pLen; + + if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("s"), &p, &pLen) == FAILURE) + { + RETURN_NULL(); + } + + Ice::LoggerPtr _this = Wrapper<Ice::LoggerPtr>::value(getThis() TSRMLS_CC); + assert(_this); + + Ice::LoggerPtr clone; + + string prefix(p, pLen); + try + { + clone = _this->cloneWithPrefix(prefix); + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + RETURN_NULL(); + } + + if(!createLogger(return_value, clone TSRMLS_CC)) + { + RETURN_NULL(); + } +} + +#ifdef _WIN32 +extern "C" +#endif +static zend_object_value +handleAlloc(zend_class_entry* ce TSRMLS_DC) +{ + zend_object_value result; + + Wrapper<Ice::LoggerPtr>* obj = Wrapper<Ice::LoggerPtr>::create(ce TSRMLS_CC); + assert(obj); + + result.handle = zend_objects_store_put(obj, 0, (zend_objects_free_object_storage_t)handleFreeStorage, 0 TSRMLS_CC); + result.handlers = &_loggerHandlers; + + return result; +} + +#ifdef _WIN32 +extern "C" +#endif +static void +handleFreeStorage(void* p TSRMLS_DC) +{ + Wrapper<Ice::LoggerPtr>* obj = static_cast<Wrapper<Ice::LoggerPtr>*>(p); + delete obj->ptr; + zend_object_std_dtor(static_cast<zend_object*>(p) TSRMLS_CC); + efree(p); +} + +#ifdef _WIN32 +extern "C" +#endif +static zend_object_value +handleClone(zval* zv TSRMLS_DC) +{ + php_error_docref(0 TSRMLS_CC, E_ERROR, "loggers cannot be cloned"); + return zend_object_value(); +} + +// +// 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(TSRMLS_D) +{ + // + // 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 TSRMLS_CC); + + // + // Register the Logger class. + // + INIT_CLASS_ENTRY(ce, "IcePHP_Logger", _classMethods); + ce.create_object = handleAlloc; + loggerClassEntry = zend_register_internal_class(&ce TSRMLS_CC); + memcpy(&_loggerHandlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); + _loggerHandlers.clone_obj = handleClone; + zend_class_implements(loggerClassEntry TSRMLS_CC, 1, interface); + + return true; +} + +bool +IcePHP::createLogger(zval* zv, const Ice::LoggerPtr& p TSRMLS_DC) +{ + if(object_init_ex(zv, loggerClassEntry) != SUCCESS) + { + runtimeError("unable to initialize logger object" TSRMLS_CC); + return false; + } + + Wrapper<Ice::LoggerPtr>* obj = Wrapper<Ice::LoggerPtr>::extract(zv TSRMLS_CC); + assert(!obj->ptr); + obj->ptr = new Ice::LoggerPtr(p); + + return true; +} + +bool +IcePHP::fetchLogger(zval* zv, Ice::LoggerPtr& p TSRMLS_DC) +{ + if(!ZVAL_IS_NULL(zv)) + { + if(Z_TYPE_P(zv) != IS_OBJECT || Z_OBJCE_P(zv) != loggerClassEntry) + { + invalidArgument("value is not a logger object" TSRMLS_CC); + return false; + } + p = Wrapper<Ice::LoggerPtr>::value(zv TSRMLS_CC); + if(!p) + { + runtimeError("unable to retrieve logger object from object store" TSRMLS_CC); + return false; + } + } + return true; +} diff --git a/php/src/php5/Logger.h b/php/src/php5/Logger.h new file mode 100644 index 00000000000..c3ab3c531c0 --- /dev/null +++ b/php/src/php5/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(TSRMLS_D); + +bool createLogger(zval*, const Ice::LoggerPtr& TSRMLS_DC); +bool fetchLogger(zval*, Ice::LoggerPtr& TSRMLS_DC); + +// +// Class entry. +// +extern zend_class_entry* loggerClassEntry; + +} // End of namespace IcePHP + +#endif diff --git a/php/src/php5/Makefile b/php/src/php5/Makefile new file mode 100644 index 00000000000..8f1f7fe3bae --- /dev/null +++ b/php/src/php5/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/php5/Makefile.mak b/php/src/php5/Makefile.mak new file mode 100644 index 00000000000..c7259854422 --- /dev/null +++ b/php/src/php5/Makefile.mak @@ -0,0 +1,67 @@ +# ********************************************************************** +# +# 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 + + +# +# 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" +CPPFLAGS = $(CPPFLAGS) -D_USE_32BIT_TIME_T +!endif + +!if "$(OPTIMIZE)" != "yes" +PDBFLAGS = /pdb:$(LIBNAME:.lib=.pdb) +!endif + +LINKWITH = $(ICE_LIBS) $(PHP_LIBS) $(CXXLIBS) + +$(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/php5/Operation.cpp b/php/src/php5/Operation.cpp new file mode 100644 index 00000000000..f7f44b493f6 --- /dev/null +++ b/php/src/php5/Operation.cpp @@ -0,0 +1,908 @@ +// ********************************************************************** +// +// 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* TSRMLS_DC); + + void unset(TSRMLS_D); + + 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* + TSRMLS_DC); + ~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& TSRMLS_DC); + static ParamInfoPtr convertParam(zval*, int TSRMLS_DC); + static void getArgInfo(zend_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& TSRMLS_DC); + + virtual void invoke(INTERNAL_FUNCTION_PARAMETERS) = 0; + +protected: + + Ice::ObjectPrx _prx; + CommunicatorInfoPtr _communicator; +#ifdef ZTS + TSRMLS_D; +#endif +}; +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& TSRMLS_DC); + +protected: + + OperationIPtr _op; + + bool prepareRequest(int, zval**, Ice::OutputStream*, pair<const Ice::Byte*, const Ice::Byte*>& TSRMLS_DC); + void unmarshalResults(int, zval**, zval*, const pair<const Ice::Byte*, const Ice::Byte*>& TSRMLS_DC); + zval* unmarshalException(const pair<const Ice::Byte*, const Ice::Byte*>& TSRMLS_DC); + bool validateException(const ExceptionInfoPtr& TSRMLS_DC) 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& TSRMLS_DC); + + virtual void invoke(INTERNAL_FUNCTION_PARAMETERS); +}; + +class UserExceptionFactory : public Ice::UserExceptionFactory +{ +public: + + UserExceptionFactory(const CommunicatorInfoPtr& communicator TSRMLS_DC) : + _communicator(communicator) + { +#ifdef ZTS + this->TSRMLS_C = TSRMLS_C; +#endif + } + + virtual void createAndThrow(const string& id) + { + ExceptionInfoPtr info = getExceptionInfo(id TSRMLS_CC); + if(info) + { + throw ExceptionReader(_communicator, info TSRMLS_CC); + } + } + +private: + + const CommunicatorInfoPtr _communicator; +#if ZTS + TSRMLS_D; +#endif +}; + +} + +// +// ResultCallback implementation. +// +IcePHP::ResultCallback::ResultCallback() : + zv(0) +{ +} + +IcePHP::ResultCallback::~ResultCallback() +{ + if(zv) + { + zval_ptr_dtor(&zv); + } +} + +void +IcePHP::ResultCallback::unmarshaled(zval* val, zval*, void* TSRMLS_DC) +{ + // + // Keep a reference to the unmarshaled value. + // + zv = val; + Z_ADDREF_P(zv); +} + +void +IcePHP::ResultCallback::unset(TSRMLS_D) +{ + MAKE_STD_ZVAL(zv); + assignUnset(zv TSRMLS_CC); +} + +// +// 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 TSRMLS_DC) : + name(n), mode(m), sendMode(sm), format(f), _zendFunction(0) +{ + // + // inParams + // + sendsClasses = false; + if(in) + { + convertParams(in, inParams, sendsClasses TSRMLS_CC); + } + + // + // outParams + // + returnsClasses = false; + if(out) + { + convertParams(out, outParams, returnsClasses TSRMLS_CC); + } + + // + // returnType + // + if(ret) + { + returnType = convertParam(ret, 0 TSRMLS_CC); + 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); + HashPosition pos; + zend_hash_internal_pointer_reset_ex(arr, &pos); + void* data; + while(zend_hash_get_current_data_ex(arr, &data, &pos) != FAILURE) + { + zval** val = reinterpret_cast<zval**>(data); + ExceptionInfoPtr i = Wrapper<ExceptionInfoPtr>::value(*val TSRMLS_CC); + exceptions.push_back(i); + zend_hash_move_forward_ex(arr, &pos); + } + } +} + +IcePHP::OperationI::~OperationI() +{ + if(_zendFunction) + { + delete []_zendFunction->arg_info; + efree(const_cast<char*>(_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_arg_info* argInfo = new zend_arg_info[numParams]; + + int i = 0; + ParamInfoList::const_iterator p; + for(p = inParams.begin(); p != inParams.end(); ++p, ++i) + { + getArgInfo(argInfo[i], *p, false); +#if PHP_VERSION_ID < 50400 + argInfo[i].required_num_args = static_cast<zend_uint>(numParams); +#endif + } + for(p = outParams.begin(); p != outParams.end(); ++p, ++i) + { + getArgInfo(argInfo[i], *p, true); +#if PHP_VERSION_ID < 50400 + argInfo[i].required_num_args = static_cast<zend_uint>(numParams); +#endif + } + + string fixed = fixIdent(name); + _zendFunction = static_cast<zend_internal_function*>(emalloc(sizeof(zend_internal_function))); + _zendFunction->type = ZEND_INTERNAL_FUNCTION; + _zendFunction->function_name = estrndup(STRCAST(fixed.c_str()), static_cast<zend_uint>(fixed.length())); + _zendFunction->scope = proxyClassEntry; + _zendFunction->fn_flags = ZEND_ACC_PUBLIC; + _zendFunction->prototype = 0; + _zendFunction->num_args = static_cast<zend_uint>(numParams); + _zendFunction->arg_info = argInfo; + _zendFunction->required_num_args = _zendFunction->num_args; +#if PHP_VERSION_ID < 50400 + _zendFunction->pass_rest_by_reference = 0; + _zendFunction->return_reference = 0; +#endif + _zendFunction->handler = ZEND_FN(IcePHP_Operation_call); + } + + return reinterpret_cast<zend_function*>(_zendFunction); +} + +void +IcePHP::OperationI::convertParams(zval* p, ParamInfoList& params, bool& usesClasses TSRMLS_DC) +{ + assert(Z_TYPE_P(p) == IS_ARRAY); + HashTable* arr = Z_ARRVAL_P(p); + HashPosition pos; + zend_hash_internal_pointer_reset_ex(arr, &pos); + void* data; + int i = 0; + while(zend_hash_get_current_data_ex(arr, &data, &pos) != FAILURE) + { + zval** val = reinterpret_cast<zval**>(data); + ParamInfoPtr param = convertParam(*val, i TSRMLS_CC); + params.push_back(param); + if(!param->optional && !usesClasses) + { + usesClasses = param->type->usesClasses(); + } + zend_hash_move_forward_ex(arr, &pos); + ++i; + } +} + +ParamInfoPtr +IcePHP::OperationI::convertParam(zval* p, int pos TSRMLS_DC) +{ + assert(Z_TYPE_P(p) == IS_ARRAY); + HashTable* arr = Z_ARRVAL_P(p); + assert(zend_hash_num_elements(arr) == 3); + + ParamInfoPtr param = new ParamInfo; + zval** m; + + zend_hash_index_find(arr, 0, reinterpret_cast<void**>(&m)); + param->type = Wrapper<TypeInfoPtr>::value(*m TSRMLS_CC); + zend_hash_index_find(arr, 1, reinterpret_cast<void**>(&m)); + assert(Z_TYPE_PP(m) == IS_BOOL); + param->optional = Z_BVAL_PP(m) ? true : false; + zend_hash_index_find(arr, 2, reinterpret_cast<void**>(&m)); + assert(Z_TYPE_PP(m) == IS_LONG); + param->tag = Z_LVAL_PP(m); + param->pos = pos; + + return param; +} + +void +IcePHP::OperationI::getArgInfo(zend_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); + +#if PHP_VERSION_ID < 50400 + arg.array_type_hint = isArray ? 1 : 0; + arg.return_reference = 0; +#else + arg.type_hint = isArray ? IS_ARRAY : 0; +#endif + } + else + { +#if PHP_VERSION_ID < 50400 + arg.array_type_hint = 0; + arg.return_reference = 0; +#else + arg.type_hint = 0; +#endif + } + + arg.pass_by_reference = out ? 1 : 0; +} + +// +// Invocation +// +IcePHP::Invocation::Invocation(const Ice::ObjectPrx& prx, const CommunicatorInfoPtr& communicator TSRMLS_DC) : + _prx(prx), _communicator(communicator) +{ +#ifdef ZTS + this->TSRMLS_C = TSRMLS_C; +#endif +} + +// +// TypedInvocation +// +IcePHP::TypedInvocation::TypedInvocation(const Ice::ObjectPrx& prx, const CommunicatorInfoPtr& communicator, + const OperationIPtr& op TSRMLS_DC) : + Invocation(prx, communicator TSRMLS_CC), _op(op) +{ +} + +bool +IcePHP::TypedInvocation::prepareRequest(int argc, zval** args, Ice::OutputStream* os, + pair<const Ice::Byte*, const Ice::Byte*>& params TSRMLS_DC) +{ + // + // 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)" TSRMLS_CC, 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(PZVAL_IS_REF(args[i])); + } + + if(!_op->inParams.empty()) + { + try + { + // + // Marshal the in parameters. + // + 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]; + if((!info->optional || !isUnset(arg TSRMLS_CC)) && !info->type->validate(arg TSRMLS_CC)) + { + invalidArgument("invalid value for argument %d in operation `%s'" TSRMLS_CC, 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]; + info->type->marshal(arg, os, &objectMap, false TSRMLS_CC); + } + } + + // + // Marshal the optional parameters. + // + for(p = _op->optionalInParams.begin(); p != _op->optionalInParams.end(); ++p) + { + ParamInfoPtr info = *p; + zval* arg = args[info->pos]; + if(!isUnset(arg TSRMLS_CC) && os->writeOptional(info->tag, info->type->optionalFormat())) + { + info->type->marshal(arg, os, &objectMap, true TSRMLS_CC); + } + } + + if(_op->sendsClasses) + { + os->writePendingObjects(); + } + + os->endEncapsulation(); + params = os->finished(); + } + catch(const AbortMarshaling&) + { + return false; + } + catch(const Ice::Exception& ex) + { + throwException(ex TSRMLS_CC); + return false; + } + } + + return true; +} + +void +IcePHP::TypedInvocation::unmarshalResults(int argc, zval** args, zval* ret, + const pair<const Ice::Byte*, const Ice::Byte*>& bytes TSRMLS_DC) +{ + Ice::InputStream is(_communicator->getCommunicator(), bytes); + + // + // Store a pointer to a local StreamUtil object as the stream's closure. + // This is necessary to support object unmarshaling (see ObjectReader). + // + StreamUtil util; + assert(!is.getClosure()); + is.setClosure(&util); + + is.startEncapsulation(); + + ParamInfoList::iterator p; + + // + // These callbacks collect references 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 TSRMLS_CC); + } + } + + // + // 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 TSRMLS_CC); + } + + // + // 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 TSRMLS_CC); + } + else + { + cb->unset(TSRMLS_C); + } + } + + if(_op->returnsClasses) + { + is.readPendingObjects(); + } + + is.endEncapsulation(); + + util.updateSlicedData(TSRMLS_C); + + int i = static_cast<int>(_op->inParams.size()); + for(ResultCallbackList::iterator q = outParamCallbacks.begin(); q != outParamCallbacks.end(); ++q, ++i) + { + // + // We must explicitly destroy the existing contents of all zvals passed + // as out parameters, otherwise leaks occur. + // + zval* val = (*q)->zv; + zval_dtor(args[i]); + args[i]->value = val->value; + Z_TYPE_P(args[i]) = Z_TYPE_P(val); + zval_copy_ctor(args[i]); + } + + if(_op->returnType) + { + ret->value = retCallback->zv->value; + Z_TYPE_P(ret) = Z_TYPE_P(retCallback->zv); + zval_copy_ctor(ret); + } +} + +zval* +IcePHP::TypedInvocation::unmarshalException(const pair<const Ice::Byte*, const Ice::Byte*>& bytes TSRMLS_DC) +{ + Ice::InputStream is(_communicator->getCommunicator(), bytes); + + // + // Store a pointer to a local StreamUtil object as the stream's closure. + // This is necessary to support object unmarshaling (see ObjectReader). + // + StreamUtil util; + assert(!is.getClosure()); + is.setClosure(&util); + + is.startEncapsulation(); + + try + { + Ice::UserExceptionFactoryPtr factory = new UserExceptionFactory(_communicator TSRMLS_CC); + is.throwException(factory); + } + catch(const ExceptionReader& r) + { + is.endEncapsulation(); + + zval* ex = r.getException(); + ExceptionInfoPtr info = r.getInfo(); + + if(validateException(info TSRMLS_CC)) + { + util.updateSlicedData(TSRMLS_C); + + Ice::SlicedDataPtr slicedData = r.getSlicedData(); + if(slicedData) + { + StreamUtil::setSlicedDataMember(ex, slicedData TSRMLS_CC); + } + + return ex; + } + else + { + zval_ptr_dtor(&ex); + Ice::UnknownUserException uue(__FILE__, __LINE__, + "operation raised undeclared exception `" + info->id + "'"); + return convertException(uue TSRMLS_CC); + } + } + + // + // 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"); + return convertException(uue TSRMLS_CC); +} + +bool +IcePHP::TypedInvocation::validateException(const ExceptionInfoPtr& info TSRMLS_DC) 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 TSRMLS_DC) : + Invocation(prx, communicator TSRMLS_CC), TypedInvocation(prx, communicator, op TSRMLS_CC) +{ +} + +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" TSRMLS_CC); + return; + } + + Ice::OutputStream os(_prx->ice_getCommunicator()); + pair<const Ice::Byte*, const Ice::Byte*> params; + if(!prepareRequest(ZEND_NUM_ARGS(), *args, &os, params TSRMLS_CC)) + { + return; + } + + bool hasCtx = false; + Ice::Context ctx; + if(ZEND_NUM_ARGS() == _op->numParams + 1) + { + if(!extractStringMap(*args[ZEND_NUM_ARGS() - 1], ctx TSRMLS_CC)) + { + 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(rb TSRMLS_CC); + if(ex) + { + zend_throw_exception_object(ex TSRMLS_CC); + } + } + 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 TSRMLS_CC); + } + } + } + catch(const AbortMarshaling&) + { + } + catch(const Ice::Exception& ex) + { + throwException(ex TSRMLS_CC); + } +} + +ZEND_FUNCTION(IcePHP_defineOperation) +{ + zval* cls; + char* name; + int nameLen; + long mode; + long sendMode; + long format; + zval* inParams; + zval* outParams; + zval* returnType; + zval* exceptions; + + if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, 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 TSRMLS_CC); + 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 TSRMLS_CC); + + 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 TSRMLS_CC); + assert(b); + assert(proxy); + assert(cls); + + OperationPtr op = cls->getOperation(get_active_function_name(TSRMLS_C)); + 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 TSRMLS_CC); + inv->invoke(INTERNAL_FUNCTION_PARAM_PASSTHRU); +} diff --git a/php/src/php5/Operation.h b/php/src/php5/Operation.h new file mode 100644 index 00000000000..91230201bc4 --- /dev/null +++ b/php/src/php5/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/php5/Properties.cpp b/php/src/php5/Properties.cpp new file mode 100644 index 00000000000..5fad58e39a8 --- /dev/null +++ b/php/src/php5/Properties.cpp @@ -0,0 +1,697 @@ +// ********************************************************************** +// +// 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_value handleAlloc(zend_class_entry* TSRMLS_DC); +static void handleFreeStorage(void* TSRMLS_DC); +static zend_object_value handleClone(zval* TSRMLS_DC); +} + +ZEND_METHOD(Ice_Properties, __construct) +{ + runtimeError("properties objects cannot be instantiated, use createProperties()" TSRMLS_CC); +} + +ZEND_METHOD(Ice_Properties, __toString) +{ + if(ZEND_NUM_ARGS() > 0) + { + WRONG_PARAM_COUNT; + } + + Ice::PropertiesPtr _this = Wrapper<Ice::PropertiesPtr>::value(getThis() TSRMLS_CC); + 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()), 1); + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_Properties, getProperty) +{ + char* name; + int nameLen; + + if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("s"), &name, &nameLen) == FAILURE) + { + RETURN_NULL(); + } + + Ice::PropertiesPtr _this = Wrapper<Ice::PropertiesPtr>::value(getThis() TSRMLS_CC); + assert(_this); + + string propName(name, nameLen); + try + { + string val = _this->getProperty(propName); + RETURN_STRINGL(STRCAST(val.c_str()), static_cast<int>(val.length()), 1); + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_Properties, getPropertyWithDefault) +{ + char* name; + int nameLen; + char* def; + int defLen; + + if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("ss!"), &name, &nameLen, &def, &defLen) == + FAILURE) + { + RETURN_NULL(); + } + + Ice::PropertiesPtr _this = Wrapper<Ice::PropertiesPtr>::value(getThis() TSRMLS_CC); + 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()), 1); + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_Properties, getPropertyAsInt) +{ + char* name; + int nameLen; + + if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("s"), &name, &nameLen) == FAILURE) + { + RETURN_NULL(); + } + + Ice::PropertiesPtr _this = Wrapper<Ice::PropertiesPtr>::value(getThis() TSRMLS_CC); + 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 TSRMLS_CC); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_Properties, getPropertyAsIntWithDefault) +{ + char* name; + int nameLen; + long def; + + if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("sl"), &name, &nameLen, &def) == FAILURE) + { + RETURN_NULL(); + } + + Ice::PropertiesPtr _this = Wrapper<Ice::PropertiesPtr>::value(getThis() TSRMLS_CC); + 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 TSRMLS_CC); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_Properties, getPropertyAsList) +{ + char* name; + int nameLen; + + if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("s"), &name, &nameLen) == FAILURE) + { + RETURN_NULL(); + } + + Ice::PropertiesPtr _this = Wrapper<Ice::PropertiesPtr>::value(getThis() TSRMLS_CC); + assert(_this); + + string propName(name, nameLen); + try + { + Ice::StringSeq val = _this->getPropertyAsList(propName); + if(!createStringArray(return_value, val TSRMLS_CC)) + { + RETURN_NULL(); + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_Properties, getPropertyAsListWithDefault) +{ + char* name; + int nameLen; + zval* def; + + if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("sa!"), &name, &nameLen, &def) == FAILURE) + { + RETURN_NULL(); + } + + Ice::PropertiesPtr _this = Wrapper<Ice::PropertiesPtr>::value(getThis() TSRMLS_CC); + assert(_this); + + string propName(name, nameLen); + Ice::StringSeq defaultValue; + if(def && !extractStringArray(def, defaultValue TSRMLS_CC)) + { + RETURN_NULL(); + } + + try + { + Ice::StringSeq val = _this->getPropertyAsListWithDefault(propName, defaultValue); + if(!createStringArray(return_value, val TSRMLS_CC)) + { + RETURN_NULL(); + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_Properties, getPropertiesForPrefix) +{ + char* p; + int pLen; + + if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("s!"), &p, &pLen) == FAILURE) + { + RETURN_NULL(); + } + + Ice::PropertiesPtr _this = Wrapper<Ice::PropertiesPtr>::value(getThis() TSRMLS_CC); + assert(_this); + + string prefix; + if(p) + { + prefix = string(p, pLen); + } + + try + { + Ice::PropertyDict val = _this->getPropertiesForPrefix(prefix); + if(!createStringMap(return_value, val TSRMLS_CC)) + { + RETURN_NULL(); + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_Properties, setProperty) +{ + char* name; + int nameLen; + char* val; + int valLen; + + if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("ss!"), &name, &nameLen, &val, &valLen) == + FAILURE) + { + RETURN_NULL(); + } + + Ice::PropertiesPtr _this = Wrapper<Ice::PropertiesPtr>::value(getThis() TSRMLS_CC); + 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 TSRMLS_CC); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_Properties, getCommandLineOptions) +{ + if(ZEND_NUM_ARGS() != 0) + { + WRONG_PARAM_COUNT; + } + + Ice::PropertiesPtr _this = Wrapper<Ice::PropertiesPtr>::value(getThis() TSRMLS_CC); + assert(_this); + + try + { + Ice::StringSeq val = _this->getCommandLineOptions(); + if(!createStringArray(return_value, val TSRMLS_CC)) + { + RETURN_NULL(); + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_Properties, parseCommandLineOptions) +{ + char* p; + int pLen; + zval* opts; + + if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("s!a!"), &p, &pLen, &opts) == FAILURE) + { + RETURN_NULL(); + } + + Ice::PropertiesPtr _this = Wrapper<Ice::PropertiesPtr>::value(getThis() TSRMLS_CC); + assert(_this); + + string prefix; + if(p) + { + prefix = string(p, pLen); + } + Ice::StringSeq options; + if(opts && !extractStringArray(opts, options TSRMLS_CC)) + { + RETURN_NULL(); + } + + try + { + Ice::StringSeq val = _this->parseCommandLineOptions(prefix, options); + if(!createStringArray(return_value, val TSRMLS_CC)) + { + RETURN_NULL(); + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_Properties, parseIceCommandLineOptions) +{ + zval* opts; + + if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("a!"), &opts) == FAILURE) + { + RETURN_NULL(); + } + + Ice::PropertiesPtr _this = Wrapper<Ice::PropertiesPtr>::value(getThis() TSRMLS_CC); + assert(_this); + + Ice::StringSeq options; + if(opts && !extractStringArray(opts, options TSRMLS_CC)) + { + RETURN_NULL(); + } + + try + { + Ice::StringSeq val = _this->parseIceCommandLineOptions(options); + if(!createStringArray(return_value, val TSRMLS_CC)) + { + RETURN_NULL(); + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_Properties, load) +{ + char* f; + int fLen; + + if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("s"), &f, &fLen) == FAILURE) + { + RETURN_NULL(); + } + + Ice::PropertiesPtr _this = Wrapper<Ice::PropertiesPtr>::value(getThis() TSRMLS_CC); + assert(_this); + + string file(f, fLen); + + try + { + _this->load(file); + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_Properties, clone) +{ + if(ZEND_NUM_ARGS() > 0) + { + WRONG_PARAM_COUNT; + } + + Ice::PropertiesPtr _this = Wrapper<Ice::PropertiesPtr>::value(getThis() TSRMLS_CC); + assert(_this); + + try + { + Ice::PropertiesPtr pclone = _this->clone(); + + if(!createProperties(return_value, pclone TSRMLS_CC)) + { + RETURN_NULL(); + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + RETURN_NULL(); + } +} + +#ifdef _WIN32 +extern "C" +#endif +static zend_object_value +handleAlloc(zend_class_entry* ce TSRMLS_DC) +{ + zend_object_value result; + + Wrapper<Ice::PropertiesPtr>* obj = Wrapper<Ice::PropertiesPtr>::create(ce TSRMLS_CC); + assert(obj); + + result.handle = zend_objects_store_put(obj, 0, (zend_objects_free_object_storage_t)handleFreeStorage, 0 TSRMLS_CC); + result.handlers = &_handlers; + + return result; +} + +#ifdef _WIN32 +extern "C" +#endif +static void +handleFreeStorage(void* p TSRMLS_DC) +{ + Wrapper<Ice::PropertiesPtr>* obj = static_cast<Wrapper<Ice::PropertiesPtr>*>(p); + delete obj->ptr; + zend_object_std_dtor(static_cast<zend_object*>(p) TSRMLS_CC); + efree(p); +} + +#ifdef _WIN32 +extern "C" +#endif +static zend_object_value +handleClone(zval* zv TSRMLS_DC) +{ + zend_object_value result; + memset(&result, 0, sizeof(zend_object_value)); + + Ice::PropertiesPtr p = Wrapper<Ice::PropertiesPtr>::value(zv TSRMLS_CC); + assert(p); + + Ice::PropertiesPtr pclone = p->clone(); + + zval* clone; + MAKE_STD_ZVAL(clone); + if(!createProperties(clone, pclone TSRMLS_CC)) + { + return result; + } + + // + // We only need to return the new object's handle, so we must destroy the zval containing + // a reference to the new object. We increment the object's reference count to ensure it + // does not get destroyed. + // + result = clone->value.obj; + Z_OBJ_HT_P(clone)->add_ref(clone TSRMLS_CC); + zval_dtor(clone); + efree(clone); + + return result; +} + +ZEND_FUNCTION(Ice_createProperties) +{ + zval* arglist = 0; + zval* defaultsObj = 0; + + if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("|a!O!"), &arglist, &defaultsObj, + propertiesClassEntry) == FAILURE) + { + RETURN_NULL(); + } + + Ice::StringSeq seq; + if(arglist && !extractStringArray(arglist, seq TSRMLS_CC)) + { + RETURN_NULL(); + } + + Ice::PropertiesPtr defaults; + if(defaultsObj && !fetchProperties(defaultsObj, defaults TSRMLS_CC)) + { + RETURN_NULL(); + } + + try + { + Ice::PropertiesPtr props; + if(arglist || defaults) + { + props = Ice::createProperties(seq, defaults); + } + else + { + props = Ice::createProperties(); + } + + if(!createProperties(return_value, props TSRMLS_CC)) + { + RETURN_NULL(); + } + + if(arglist && PZVAL_IS_REF(arglist)) + { + zval_dtor(arglist); + if(!createStringArray(arglist, seq TSRMLS_CC)) + { + RETURN_NULL(); + } + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + 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(TSRMLS_D) +{ + // + // 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 TSRMLS_CC); + + // + // Register the Properties class. + // + INIT_CLASS_ENTRY(ce, "IcePHP_Properties", _classMethods); + ce.create_object = handleAlloc; + propertiesClassEntry = zend_register_internal_class(&ce TSRMLS_CC); + memcpy(&_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); + _handlers.clone_obj = handleClone; + zend_class_implements(propertiesClassEntry TSRMLS_CC, 1, interface); + + return true; +} + +bool +IcePHP::createProperties(zval* zv, const Ice::PropertiesPtr& p TSRMLS_DC) +{ + if(object_init_ex(zv, propertiesClassEntry) != SUCCESS) + { + runtimeError("unable to initialize properties object" TSRMLS_CC); + return false; + } + + Wrapper<Ice::PropertiesPtr>* obj = Wrapper<Ice::PropertiesPtr>::extract(zv TSRMLS_CC); + assert(!obj->ptr); + obj->ptr = new Ice::PropertiesPtr(p); + + return true; +} + +bool +IcePHP::fetchProperties(zval* zv, Ice::PropertiesPtr& p TSRMLS_DC) +{ + if(!ZVAL_IS_NULL(zv)) + { + if(Z_TYPE_P(zv) != IS_OBJECT || Z_OBJCE_P(zv) != propertiesClassEntry) + { + invalidArgument("value is not a properties object" TSRMLS_CC); + return false; + } + p = Wrapper<Ice::PropertiesPtr>::value(zv TSRMLS_CC); + if(!p) + { + runtimeError("unable to retrieve properties object from object store" TSRMLS_CC); + return false; + } + } + return true; +} diff --git a/php/src/php5/Properties.h b/php/src/php5/Properties.h new file mode 100644 index 00000000000..c4fa8b24e9d --- /dev/null +++ b/php/src/php5/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(TSRMLS_D); + +bool createProperties(zval*, const Ice::PropertiesPtr& TSRMLS_DC); +bool fetchProperties(zval*, Ice::PropertiesPtr& TSRMLS_DC); + +// +// Class entry. +// +extern zend_class_entry* propertiesClassEntry; + +} // End of namespace IcePHP + +#endif diff --git a/php/src/php5/Proxy.cpp b/php/src/php5/Proxy.cpp new file mode 100644 index 00000000000..b86c15314c9 --- /dev/null +++ b/php/src/php5/Proxy.cpp @@ -0,0 +1,1762 @@ +// ********************************************************************** +// +// 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_value handleAlloc(zend_class_entry* TSRMLS_DC); +static void handleFreeStorage(void* TSRMLS_DC); +static zend_object_value handleClone(zval* TSRMLS_DC); +#if PHP_VERSION_ID < 50400 +static union _zend_function* handleGetMethod(zval**, char*, int TSRMLS_DC); +#else +static union _zend_function* handleGetMethod(zval**, char*, int, const _zend_literal* TSRMLS_DC); +#endif +static int handleCompare(zval*, zval* TSRMLS_DC); +} + +static ClassInfoPtr lookupClass(const string& TSRMLS_DC); + +namespace IcePHP +{ + +// +// Encapsulates proxy and type information. +// +class Proxy : public IceUtil::Shared +{ +public: + + Proxy(const Ice::ObjectPrx&, const ClassInfoPtr&, const CommunicatorInfoPtr& TSRMLS_DC); + ~Proxy(); + + bool clone(zval*, const Ice::ObjectPrx& TSRMLS_DC); + bool cloneUntyped(zval*, const Ice::ObjectPrx& TSRMLS_DC); + static bool create(zval*, const Ice::ObjectPrx&, const ClassInfoPtr&, const CommunicatorInfoPtr& TSRMLS_DC); + + Ice::ObjectPrx proxy; + ClassInfoPtr info; + CommunicatorInfoPtr communicator; + zval* connection; + zval* cachedConnection; +#if ZTS + TSRMLS_D; +#endif +}; +typedef IceUtil::Handle<Proxy> ProxyPtr; + +} // End of namespace IcePHP + +ZEND_METHOD(Ice_ObjectPrx, __construct) +{ + runtimeError("proxies cannot be instantiated, use stringToProxy()" TSRMLS_CC); +} + +ZEND_METHOD(Ice_ObjectPrx, __toString) +{ + if(ZEND_NUM_ARGS() > 0) + { + WRONG_PARAM_COUNT; + } + + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC); + assert(_this); + + try + { + string str = _this->proxy->ice_toString(); + RETURN_STRINGL(STRCAST(str.c_str()), static_cast<int>(str.length()), 1); + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_ObjectPrx, ice_getCommunicator) +{ + if(ZEND_NUM_ARGS() > 0) + { + WRONG_PARAM_COUNT; + } + + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC); + assert(_this); + + _this->communicator->getZval(return_value TSRMLS_CC); +} + +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() TSRMLS_CC); + assert(_this); + + createIdentity(return_value, _this->proxy->ice_getIdentity() TSRMLS_CC); +} + +ZEND_METHOD(Ice_ObjectPrx, ice_identity) +{ + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC); + assert(_this); + + zend_class_entry* cls = idToClass("::Ice::Identity" TSRMLS_CC); + assert(cls); + + zval *zid; + + if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("O"), &zid, cls) == FAILURE) + { + RETURN_NULL(); + } + + Ice::Identity id; + if(extractIdentity(zid, id TSRMLS_CC)) + { + try + { + if(!_this->cloneUntyped(return_value, _this->proxy->ice_identity(id) TSRMLS_CC)) + { + RETURN_NULL(); + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + RETURN_NULL(); + } + } +} + +ZEND_METHOD(Ice_ObjectPrx, ice_getContext) +{ + if(ZEND_NUM_ARGS() != 0) + { + WRONG_PARAM_COUNT; + } + + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC); + assert(_this); + + if(!createStringMap(return_value, _this->proxy->ice_getContext() TSRMLS_CC)) + { + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_ObjectPrx, ice_context) +{ + zval* arr = 0; + + if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("a"), &arr) == FAILURE) + { + RETURN_NULL(); + } + + // + // Populate the context. + // + Ice::Context ctx; + if(arr && !extractStringMap(arr, ctx TSRMLS_CC)) + { + RETURN_NULL(); + } + + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC); + assert(_this); + + try + { + if(!_this->clone(return_value, _this->proxy->ice_context(ctx) TSRMLS_CC)) + { + RETURN_NULL(); + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_ObjectPrx, ice_getFacet) +{ + if(ZEND_NUM_ARGS() != 0) + { + WRONG_PARAM_COUNT; + } + + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC); + assert(_this); + + try + { + string facet = _this->proxy->ice_getFacet(); + ZVAL_STRINGL(return_value, STRCAST(facet.c_str()), static_cast<int>(facet.length()), 1); + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_ObjectPrx, ice_facet) +{ + char* name; + int len; + + if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("s"), &name, &len) == FAILURE) + { + RETURN_NULL(); + } + + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC); + assert(_this); + + try + { + if(!_this->cloneUntyped(return_value, _this->proxy->ice_facet(name) TSRMLS_CC)) + { + RETURN_NULL(); + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_ObjectPrx, ice_getAdapterId) +{ + if(ZEND_NUM_ARGS() != 0) + { + WRONG_PARAM_COUNT; + } + + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC); + assert(_this); + + try + { + string id = _this->proxy->ice_getAdapterId(); + ZVAL_STRINGL(return_value, STRCAST(id.c_str()), static_cast<int>(id.length()), 1); + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_ObjectPrx, ice_adapterId) +{ + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC); + assert(_this); + + char* id; + int len; + + if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("s"), &id, &len) == FAILURE) + { + RETURN_NULL(); + } + + try + { + if(!_this->clone(return_value, _this->proxy->ice_adapterId(id) TSRMLS_CC)) + { + RETURN_NULL(); + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_ObjectPrx, ice_getEndpoints) +{ + if(ZEND_NUM_ARGS() != 0) + { + WRONG_PARAM_COUNT; + } + + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC); + 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; + MAKE_STD_ZVAL(elem); + if(!createEndpoint(elem, *p TSRMLS_CC)) + { + zval_ptr_dtor(&elem); + RETURN_NULL(); + } + add_index_zval(return_value, idx, elem); + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_ObjectPrx, ice_endpoints) +{ + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC); + assert(_this); + + zval* zv; + + if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("a"), &zv) == FAILURE) + { + RETURN_NULL(); + } + + Ice::EndpointSeq seq; + + HashTable* arr = Z_ARRVAL_P(zv); + HashPosition pos; + void* data; + + zend_hash_internal_pointer_reset_ex(arr, &pos); + while(zend_hash_get_current_data_ex(arr, &data, &pos) != FAILURE) + { + zval** val = reinterpret_cast<zval**>(data); + + if(Z_TYPE_PP(val) != IS_OBJECT) + { + runtimeError("expected an element of type Ice::Endpoint" TSRMLS_CC); + RETURN_NULL(); + } + + Ice::EndpointPtr endpoint; + if(!fetchEndpoint(*val, endpoint TSRMLS_CC)) + { + RETURN_NULL(); + } + + seq.push_back(endpoint); + + zend_hash_move_forward_ex(arr, &pos); + } + + try + { + if(!_this->clone(return_value, _this->proxy->ice_endpoints(seq) TSRMLS_CC)) + { + RETURN_NULL(); + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_ObjectPrx, ice_getLocatorCacheTimeout) +{ + if(ZEND_NUM_ARGS() != 0) + { + WRONG_PARAM_COUNT; + } + + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC); + 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 TSRMLS_CC); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_ObjectPrx, ice_getConnectionId) +{ + if(ZEND_NUM_ARGS() != 0) + { + WRONG_PARAM_COUNT; + } + + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC); + assert(_this); + + try + { + string connectionId = _this->proxy->ice_getConnectionId(); + ZVAL_STRINGL(return_value, STRCAST(connectionId.c_str()), static_cast<int>(connectionId.length()), 1); + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_ObjectPrx, ice_locatorCacheTimeout) +{ + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC); + assert(_this); + + long l; + if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("l"), &l) != SUCCESS) + { + RETURN_NULL(); + } + + try + { + if(!_this->clone(return_value, _this->proxy->ice_locatorCacheTimeout(l) TSRMLS_CC)) + { + RETURN_NULL(); + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_ObjectPrx, ice_isConnectionCached) +{ + if(ZEND_NUM_ARGS() != 0) + { + WRONG_PARAM_COUNT; + } + + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC); + assert(_this); + + try + { + bool b = _this->proxy->ice_isConnectionCached(); + ZVAL_BOOL(return_value, b ? 1 : 0); + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_ObjectPrx, ice_connectionCached) +{ + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC); + assert(_this); + + zend_bool b; + if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("b"), &b) != SUCCESS) + { + RETURN_NULL(); + } + + try + { + if(!_this->clone(return_value, _this->proxy->ice_connectionCached(b ? true : false) TSRMLS_CC)) + { + RETURN_NULL(); + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_ObjectPrx, ice_getEndpointSelection) +{ + if(ZEND_NUM_ARGS() != 0) + { + WRONG_PARAM_COUNT; + } + + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC); + 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 TSRMLS_CC); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_ObjectPrx, ice_endpointSelection) +{ + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC); + assert(_this); + + long l; + if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("l"), &l) != SUCCESS) + { + RETURN_NULL(); + } + + if(l < 0 || l > 1) + { + runtimeError("expecting Random or Ordered" TSRMLS_CC); + RETURN_NULL(); + } + + try + { + Ice::EndpointSelectionType type = l == 0 ? Ice::Random : Ice::Ordered; + if(!_this->clone(return_value, _this->proxy->ice_endpointSelection(type) TSRMLS_CC)) + { + RETURN_NULL(); + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_ObjectPrx, ice_isSecure) +{ + if(ZEND_NUM_ARGS() != 0) + { + WRONG_PARAM_COUNT; + } + + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC); + assert(_this); + + try + { + bool b = _this->proxy->ice_isSecure(); + RETURN_BOOL(b ? 1 : 0); + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + RETURN_FALSE; + } +} + +ZEND_METHOD(Ice_ObjectPrx, ice_secure) +{ + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC); + assert(_this); + + zend_bool b; + if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("b"), &b TSRMLS_CC) != SUCCESS) + { + RETURN_NULL(); + } + + try + { + if(!_this->clone(return_value, _this->proxy->ice_secure(b ? true : false) TSRMLS_CC)) + { + RETURN_NULL(); + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_ObjectPrx, ice_getEncodingVersion) +{ + if(ZEND_NUM_ARGS() != 0) + { + WRONG_PARAM_COUNT; + } + + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC); + assert(_this); + + try + { + if(!createEncodingVersion(return_value, _this->proxy->ice_getEncodingVersion() TSRMLS_CC)) + { + RETURN_NULL(); + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_ObjectPrx, ice_encodingVersion) +{ + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC); + assert(_this); + + zend_class_entry* cls = idToClass("::Ice::EncodingVersion" TSRMLS_CC); + assert(cls); + + zval *zv; + if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("O"), &zv, cls) == FAILURE) + { + RETURN_NULL(); + } + + Ice::EncodingVersion v; + if(extractEncodingVersion(zv, v TSRMLS_CC)) + { + try + { + if(!_this->clone(return_value, _this->proxy->ice_encodingVersion(v) TSRMLS_CC)) + { + RETURN_NULL(); + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + RETURN_NULL(); + } + } +} + +ZEND_METHOD(Ice_ObjectPrx, ice_isPreferSecure) +{ + if(ZEND_NUM_ARGS() != 0) + { + WRONG_PARAM_COUNT; + } + + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC); + assert(_this); + + try + { + bool b = _this->proxy->ice_isPreferSecure(); + RETURN_BOOL(b ? 1 : 0); + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + RETURN_FALSE; + } +} + +ZEND_METHOD(Ice_ObjectPrx, ice_preferSecure) +{ + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC); + assert(_this); + + zend_bool b; + if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("b"), &b TSRMLS_CC) != SUCCESS) + { + RETURN_NULL(); + } + + try + { + if(!_this->clone(return_value, _this->proxy->ice_preferSecure(b ? true : false) TSRMLS_CC)) + { + RETURN_NULL(); + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_ObjectPrx, ice_getRouter) +{ + if(ZEND_NUM_ARGS() != 0) + { + WRONG_PARAM_COUNT; + } + + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC); + assert(_this); + + try + { + Ice::RouterPrx router = _this->proxy->ice_getRouter(); + if(router) + { + ClassInfoPtr info = lookupClass("::Ice::Router" TSRMLS_CC); + if(!info) + { + RETURN_NULL(); + } + + assert(info); + + if(!createProxy(return_value, router, info, _this->communicator TSRMLS_CC)) + { + RETURN_NULL(); + } + } + else + { + RETURN_NULL(); + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + RETURN_FALSE; + } +} + +ZEND_METHOD(Ice_ObjectPrx, ice_router) +{ + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC); + assert(_this); + + zval* zprx; + if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("O!"), &zprx, proxyClassEntry TSRMLS_CC) != + SUCCESS) + { + RETURN_NULL(); + } + + Ice::ObjectPrx proxy; + ClassInfoPtr def; + if(zprx && !fetchProxy(zprx, proxy, def TSRMLS_CC)) + { + RETURN_NULL(); + } + + Ice::RouterPrx router; + if(proxy) + { + if(!def || !def->isA("::Ice::Router")) + { + runtimeError("ice_router requires a proxy narrowed to Ice::Router" TSRMLS_CC); + RETURN_NULL(); + } + router = Ice::RouterPrx::uncheckedCast(proxy); + } + + try + { + if(!_this->clone(return_value, _this->proxy->ice_router(router) TSRMLS_CC)) + { + RETURN_NULL(); + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_ObjectPrx, ice_getLocator) +{ + if(ZEND_NUM_ARGS() != 0) + { + WRONG_PARAM_COUNT; + } + + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC); + assert(_this); + + try + { + Ice::LocatorPrx locator = _this->proxy->ice_getLocator(); + if(locator) + { + ClassInfoPtr info = lookupClass("::Ice::Locator" TSRMLS_CC); + if(!info) + { + RETURN_NULL(); + } + + if(!createProxy(return_value, locator, info, _this->communicator TSRMLS_CC)) + { + RETURN_NULL(); + } + } + else + { + RETURN_NULL(); + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + RETURN_FALSE; + } +} + +ZEND_METHOD(Ice_ObjectPrx, ice_locator) +{ + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC); + assert(_this); + + zval* zprx; + if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("O!"), &zprx, proxyClassEntry TSRMLS_CC) != + SUCCESS) + { + RETURN_NULL(); + } + + Ice::ObjectPrx proxy; + ClassInfoPtr def; + if(zprx && !fetchProxy(zprx, proxy, def TSRMLS_CC)) + { + RETURN_NULL(); + } + + Ice::LocatorPrx locator; + if(proxy) + { + if(!def || !def->isA("::Ice::Locator")) + { + runtimeError("ice_locator requires a proxy narrowed to Ice::Locator" TSRMLS_CC); + RETURN_NULL(); + } + locator = Ice::LocatorPrx::uncheckedCast(proxy); + } + + try + { + if(!_this->clone(return_value, _this->proxy->ice_locator(locator) TSRMLS_CC)) + { + RETURN_NULL(); + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_ObjectPrx, ice_twoway) +{ + if(ZEND_NUM_ARGS() != 0) + { + WRONG_PARAM_COUNT; + } + + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC); + assert(_this); + + try + { + if(!_this->clone(return_value, _this->proxy->ice_twoway() TSRMLS_CC)) + { + RETURN_NULL(); + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_ObjectPrx, ice_isTwoway) +{ + if(ZEND_NUM_ARGS() != 0) + { + WRONG_PARAM_COUNT; + } + + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC); + assert(_this); + + try + { + bool b = _this->proxy->ice_isTwoway(); + RETURN_BOOL(b ? 1 : 0); + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + RETURN_FALSE; + } +} + +ZEND_METHOD(Ice_ObjectPrx, ice_oneway) +{ + if(ZEND_NUM_ARGS() != 0) + { + WRONG_PARAM_COUNT; + } + + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC); + assert(_this); + + try + { + if(!_this->clone(return_value, _this->proxy->ice_oneway() TSRMLS_CC)) + { + RETURN_NULL(); + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_ObjectPrx, ice_isOneway) +{ + if(ZEND_NUM_ARGS() != 0) + { + WRONG_PARAM_COUNT; + } + + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC); + assert(_this); + + try + { + bool b = _this->proxy->ice_isOneway(); + RETURN_BOOL(b ? 1 : 0); + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + RETURN_FALSE; + } +} + +ZEND_METHOD(Ice_ObjectPrx, ice_batchOneway) +{ + if(ZEND_NUM_ARGS() != 0) + { + WRONG_PARAM_COUNT; + } + + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC); + assert(_this); + + try + { + if(!_this->clone(return_value, _this->proxy->ice_batchOneway() TSRMLS_CC)) + { + RETURN_NULL(); + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_ObjectPrx, ice_isBatchOneway) +{ + if(ZEND_NUM_ARGS() != 0) + { + WRONG_PARAM_COUNT; + } + + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC); + assert(_this); + + try + { + bool b = _this->proxy->ice_isBatchOneway(); + RETURN_BOOL(b ? 1 : 0); + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + RETURN_FALSE; + } +} + +ZEND_METHOD(Ice_ObjectPrx, ice_datagram) +{ + if(ZEND_NUM_ARGS() != 0) + { + WRONG_PARAM_COUNT; + } + + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC); + assert(_this); + + try + { + if(!_this->clone(return_value, _this->proxy->ice_datagram() TSRMLS_CC)) + { + RETURN_NULL(); + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_ObjectPrx, ice_isDatagram) +{ + if(ZEND_NUM_ARGS() != 0) + { + WRONG_PARAM_COUNT; + } + + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC); + assert(_this); + + try + { + bool b = _this->proxy->ice_isDatagram(); + RETURN_BOOL(b ? 1 : 0); + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + RETURN_FALSE; + } +} + +ZEND_METHOD(Ice_ObjectPrx, ice_batchDatagram) +{ + if(ZEND_NUM_ARGS() != 0) + { + WRONG_PARAM_COUNT; + } + + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC); + assert(_this); + + try + { + if(!_this->clone(return_value, _this->proxy->ice_batchDatagram() TSRMLS_CC)) + { + RETURN_NULL(); + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_ObjectPrx, ice_isBatchDatagram) +{ + if(ZEND_NUM_ARGS() != 0) + { + WRONG_PARAM_COUNT; + } + + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC); + assert(_this); + + try + { + bool b = _this->proxy->ice_isBatchDatagram(); + RETURN_BOOL(b ? 1 : 0); + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + RETURN_FALSE; + } +} + +ZEND_METHOD(Ice_ObjectPrx, ice_compress) +{ + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC); + assert(_this); + + zend_bool b; + if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("b"), &b) != SUCCESS) + { + RETURN_NULL(); + } + + try + { + if(!_this->clone(return_value, _this->proxy->ice_compress(b ? true : false) TSRMLS_CC)) + { + RETURN_NULL(); + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_ObjectPrx, ice_timeout) +{ + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC); + assert(_this); + + try + { + long l; + if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("l"), &l) != SUCCESS) + { + RETURN_NULL(); + } + // TODO: range check? + if(!_this->clone(return_value, _this->proxy->ice_timeout(l) TSRMLS_CC)) + { + RETURN_NULL(); + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_ObjectPrx, ice_connectionId) +{ + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC); + assert(_this); + + try + { + char* id; + int idLen; + if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("s"), &id, &idLen) != SUCCESS) + { + RETURN_NULL(); + } + if(!_this->clone(return_value, _this->proxy->ice_connectionId(id) TSRMLS_CC)) + { + RETURN_NULL(); + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_ObjectPrx, ice_getConnection) +{ + if(ZEND_NUM_ARGS() != 0) + { + WRONG_PARAM_COUNT; + } + + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC); + assert(_this); + + try + { + Ice::ConnectionPtr con = _this->proxy->ice_getConnection(); + if(!createConnection(return_value, con TSRMLS_CC)) + { + RETURN_NULL(); + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_ObjectPrx, ice_getCachedConnection) +{ + if(ZEND_NUM_ARGS() != 0) + { + WRONG_PARAM_COUNT; + } + + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC); + assert(_this); + + try + { + Ice::ConnectionPtr con = _this->proxy->ice_getCachedConnection(); + if(!con || !createConnection(return_value, con TSRMLS_CC)) + { + RETURN_NULL(); + } + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + RETURN_NULL(); + } +} + +ZEND_METHOD(Ice_ObjectPrx, ice_flushBatchRequests) +{ + if(ZEND_NUM_ARGS() != 0) + { + WRONG_PARAM_COUNT; + } + + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC); + assert(_this); + + try + { + _this->proxy->ice_flushBatchRequests(); + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + RETURN_NULL(); + } +} + +static ClassInfoPtr +lookupClass(const string& id TSRMLS_DC) +{ + ClassInfoPtr info = getClassInfoById(id TSRMLS_CC); + if(!info) + { + if(!id.empty() && id[id.size() - 1] == '*') + { + info = getClassInfoById(id.substr(0, id.size() - 1) TSRMLS_CC); + } + } + + if(info && !info->defined) + { + runtimeError("%s is declared but not defined" TSRMLS_CC, id.c_str()); + } + else if(!info) + { + runtimeError("no definition found for class or interface %s" TSRMLS_CC, 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; + int idLen; + char* facet = 0; + int facetLen; + zval* arr = 0; + + if(zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, 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() TSRMLS_CC, 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(TSRMLS_C)); + return; + } + } + + ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC); + assert(_this); + + // + // Populate the context. + // + Ice::Context ctx; + if(arr && !extractStringMap(arr, ctx TSRMLS_CC)) + { + RETURN_NULL(); + } + + try + { + ClassInfoPtr info = lookupClass(id TSRMLS_CC); + 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 TSRMLS_CC)) + { + RETURN_NULL(); + } + } + catch(const Ice::FacetNotExistException&) + { + // Ignore. + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + 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 TSRMLS_DC) : + proxy(p), info(i), communicator(comm), connection(0), cachedConnection(0) +{ +#ifdef ZTS + this->TSRMLS_C = TSRMLS_C; +#endif + + // + // We want to ensure that the PHP object corresponding to the communicator is + // not destroyed until after this proxy is destroyed. + // + communicator->addRef(TSRMLS_C); +} + +IcePHP::Proxy::~Proxy() +{ + communicator->decRef(TSRMLS_C); + if(connection) + { + zval_ptr_dtor(&connection); + } + if(cachedConnection) + { + zval_ptr_dtor(&cachedConnection); + } +} + +bool +IcePHP::Proxy::clone(zval* zv, const Ice::ObjectPrx& p TSRMLS_DC) +{ + return create(zv, p, info, communicator TSRMLS_CC); +} + +bool +IcePHP::Proxy::cloneUntyped(zval* zv, const Ice::ObjectPrx& p TSRMLS_DC) +{ + return create(zv, p, 0, communicator TSRMLS_CC); +} + +bool +IcePHP::Proxy::create(zval* zv, const Ice::ObjectPrx& p, const ClassInfoPtr& info, const CommunicatorInfoPtr& comm + TSRMLS_DC) +{ + ClassInfoPtr cls = info; + if(!cls) + { + cls = getClassInfoById("::Ice::Object" TSRMLS_CC); + assert(cls); + } + + if(object_init_ex(zv, proxyClassEntry) != SUCCESS) + { + runtimeError("unable to initialize proxy" TSRMLS_CC); + return false; + } + + Wrapper<ProxyPtr>* obj = Wrapper<ProxyPtr>::extract(zv TSRMLS_CC); + ProxyPtr proxy = new Proxy(p, cls, comm TSRMLS_CC); + assert(!obj->ptr); + obj->ptr = new ProxyPtr(proxy); + + return true; +} + +#ifdef _WIN32 +extern "C" +#endif +static zend_object_value +handleAlloc(zend_class_entry* ce TSRMLS_DC) +{ + zend_object_value result; + + Wrapper<ProxyPtr>* obj = Wrapper<ProxyPtr>::create(ce TSRMLS_CC); + assert(obj); + + result.handle = zend_objects_store_put(obj, 0, (zend_objects_free_object_storage_t)handleFreeStorage, + 0 TSRMLS_CC); + result.handlers = &_handlers; + + return result; +} + +#ifdef _WIN32 +extern "C" +#endif +static void +handleFreeStorage(void* p TSRMLS_DC) +{ + Wrapper<ProxyPtr>* obj = static_cast<Wrapper<ProxyPtr>*>(p); + delete obj->ptr; + zend_object_std_dtor(static_cast<zend_object*>(p) TSRMLS_CC); + efree(p); +} + +#ifdef _WIN32 +extern "C" +#endif +static zend_object_value +handleClone(zval* zv TSRMLS_DC) +{ + // + // Create a new object that shares a C++ proxy instance with this object. + // + + zend_object_value result; + memset(&result, 0, sizeof(zend_object_value)); + + ProxyPtr obj = Wrapper<ProxyPtr>::value(zv TSRMLS_CC); + assert(obj); + + zval* clone; + MAKE_STD_ZVAL(clone); + if(!obj->clone(clone, obj->proxy TSRMLS_CC)) + { + return result; + } + + // + // We only need to return the new object's handle, so we must destroy the zval containing + // a reference to the new object. We increment the object's reference count to ensure it + // does not get destroyed. + // + result = clone->value.obj; + Z_OBJ_HT_P(clone)->add_ref(clone TSRMLS_CC); + zval_dtor(clone); + efree(clone); + + return result; +} + +#ifdef _WIN32 +extern "C" +#endif +static union _zend_function* +#if PHP_VERSION_ID < 50400 +handleGetMethod(zval** zv, char* method, int len TSRMLS_DC) +#else +handleGetMethod(zval** zv, char* method, int len, const _zend_literal* key TSRMLS_DC) +#endif +{ + 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. + // +#if PHP_VERSION_ID < 50400 + result = zend_get_std_object_handlers()->get_method(zv, method, len TSRMLS_CC); +#else + result = zend_get_std_object_handlers()->get_method(zv, method, len, key TSRMLS_CC); +#endif + if(!result) + { + Wrapper<ProxyPtr>* obj = Wrapper<ProxyPtr>::extract(*zv TSRMLS_CC); + assert(obj->ptr); + ProxyPtr _this = *obj->ptr; + + ClassInfoPtr info = _this->info; + assert(info); + + OperationPtr op = info->getOperation(method); + 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 TSRMLS_DC) +{ + // + // PHP guarantees that the objects have the same class. + // + + Wrapper<ProxyPtr>* obj1 = Wrapper<ProxyPtr>::extract(zobj1 TSRMLS_CC); + assert(obj1->ptr); + ProxyPtr _this1 = *obj1->ptr; + Ice::ObjectPrx prx1 = _this1->proxy; + + Wrapper<ProxyPtr>* obj2 = Wrapper<ProxyPtr>::extract(zobj2 TSRMLS_CC); + 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(TSRMLS_D) +{ + // + // 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 TSRMLS_CC); + //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; + + return true; +} + +bool +IcePHP::createProxy(zval* zv, const Ice::ObjectPrx& p, const CommunicatorInfoPtr& comm TSRMLS_DC) +{ + return Proxy::create(zv, p, 0, comm TSRMLS_CC); +} + +bool +IcePHP::createProxy(zval* zv, const Ice::ObjectPrx& p, const ClassInfoPtr& info, const CommunicatorInfoPtr& comm + TSRMLS_DC) +{ + return Proxy::create(zv, p, info, comm TSRMLS_CC); +} + +bool +IcePHP::fetchProxy(zval* zv, Ice::ObjectPrx& prx, ClassInfoPtr& cls TSRMLS_DC) +{ + CommunicatorInfoPtr comm; + return fetchProxy(zv, prx, cls, comm TSRMLS_CC); +} + +bool +IcePHP::fetchProxy(zval* zv, Ice::ObjectPrx& prx, ClassInfoPtr& cls, CommunicatorInfoPtr& comm TSRMLS_DC) +{ + if(!ZVAL_IS_NULL(zv)) + { + if(Z_TYPE_P(zv) != IS_OBJECT || Z_OBJCE_P(zv) != proxyClassEntry) + { + invalidArgument("value is not a proxy" TSRMLS_CC); + return false; + } + Wrapper<ProxyPtr>* obj = Wrapper<ProxyPtr>::extract(zv TSRMLS_CC); + if(!obj) + { + runtimeError("unable to retrieve proxy object from object store" TSRMLS_CC); + return false; + } + assert(obj->ptr); + prx = (*obj->ptr)->proxy; + cls = (*obj->ptr)->info; + comm = (*obj->ptr)->communicator; + } + return true; +} diff --git a/php/src/php5/Proxy.h b/php/src/php5/Proxy.h new file mode 100644 index 00000000000..235a427c2f5 --- /dev/null +++ b/php/src/php5/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(TSRMLS_D); + +bool createProxy(zval*, const Ice::ObjectPrx&, const CommunicatorInfoPtr& TSRMLS_DC); +bool createProxy(zval*, const Ice::ObjectPrx&, const ClassInfoPtr&, const CommunicatorInfoPtr& TSRMLS_DC); +bool fetchProxy(zval*, Ice::ObjectPrx&, ClassInfoPtr& TSRMLS_DC); +bool fetchProxy(zval*, Ice::ObjectPrx&, ClassInfoPtr&, CommunicatorInfoPtr& TSRMLS_DC); + +// +// Class entry. +// +extern zend_class_entry* proxyClassEntry; + +} // End of namespace IcePHP + +#endif diff --git a/php/src/php5/Types.cpp b/php/src/php5/Types.cpp new file mode 100644 index 00000000000..970646b987c --- /dev/null +++ b/php/src/php5/Types.cpp @@ -0,0 +1,4046 @@ +// ********************************************************************** +// +// 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_value handleTypeInfoAlloc(zend_class_entry* TSRMLS_DC); +static void handleTypeInfoFreeStorage(void* TSRMLS_DC); + +static zend_object_value handleExceptionInfoAlloc(zend_class_entry* TSRMLS_DC); +static void handleExceptionInfoFreeStorage(void* TSRMLS_DC); +} + +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 TSRMLS_DC) +{ + 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 TSRMLS_DC) +{ + 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; +} + +// +// addClassInfoById() +// +static void +addClassInfoById(const ClassInfoPtr& p TSRMLS_DC) +{ + assert(!getClassInfoById(p->id TSRMLS_CC)); + + 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 TSRMLS_DC) +{ + assert(!getClassInfoByName(p->name TSRMLS_CC)); +#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 TSRMLS_DC) +{ + // + // See if there's a match in our class name => ClassInfo map. + // + ClassInfoPtr info = getClassInfoByName(cls->name TSRMLS_CC); + + // + // 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 TSRMLS_CC); + } + + // + // Check interfaces. + // + if(!info) + { + for(zend_uint i = 0; i < cls->num_interfaces && !info; ++i) + { + if(!formal || checkClass(cls->interfaces[i], formal)) + { + info = getClassInfoByClass(cls->interfaces[i], formal TSRMLS_CC); + } + } + } + + return info; +} + +// +// getClassInfoById() +// +IcePHP::ClassInfoPtr +IcePHP::getClassInfoById(const string& id TSRMLS_DC) +{ + 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 TSRMLS_DC) +{ + 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 TSRMLS_DC) +{ + 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; +} + +// +// StreamUtil implementation +// +zend_class_entry* IcePHP::StreamUtil::_slicedDataType = 0; +zend_class_entry* IcePHP::StreamUtil::_sliceInfoType = 0; + +IcePHP::StreamUtil::~StreamUtil() +{ + // + // 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::StreamUtil::add(const ReadObjectCallbackPtr& callback) +{ + _callbacks.push_back(callback); +} + +void +IcePHP::StreamUtil::add(const ObjectReaderPtr& reader) +{ + assert(reader->getSlicedData()); + _readers.insert(reader); +} + +void +IcePHP::StreamUtil::updateSlicedData(TSRMLS_D) +{ + for(set<ObjectReaderPtr>::iterator p = _readers.begin(); p != _readers.end(); ++p) + { + setSlicedDataMember((*p)->getObject(), (*p)->getSlicedData() TSRMLS_CC); + } +} + +void +IcePHP::StreamUtil::setSlicedDataMember(zval* obj, const Ice::SlicedDataPtr& slicedData TSRMLS_DC) +{ + // + // Create a PHP equivalent of the SlicedData object. + // + + assert(slicedData); + + if(!_slicedDataType) + { + _slicedDataType = idToClass("::Ice::SlicedData" TSRMLS_CC); + assert(_slicedDataType); + } + if(!_sliceInfoType) + { + _sliceInfoType = idToClass("::Ice::SliceInfo" TSRMLS_CC); + assert(_sliceInfoType); + } + + zval* sd; + MAKE_STD_ZVAL(sd); + AutoDestroy sdDestroyer(sd); + + if(object_init_ex(sd, _slicedDataType) != SUCCESS) + { + throw AbortMarshaling(); + } + + zval* slices; + MAKE_STD_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; + MAKE_STD_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; + MAKE_STD_ZVAL(typeId); + AutoDestroy typeIdDestroyer(typeId); + ZVAL_STRINGL(typeId, STRCAST((*p)->typeId.c_str()), static_cast<int>((*p)->typeId.size()), 1); + if(add_property_zval(slice, STRCAST("typeId"), typeId) != SUCCESS) + { + throw AbortMarshaling(); + } + + // + // compactId + // + zval* compactId; + MAKE_STD_ZVAL(compactId); + AutoDestroy compactIdDestroyer(compactId); + ZVAL_LONG(compactId, (*p)->compactId); + if(add_property_zval(slice, STRCAST("compactId"), compactId) != SUCCESS) + { + throw AbortMarshaling(); + } + + // + // bytes + // + zval* bytes; + MAKE_STD_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; + MAKE_STD_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; + MAKE_STD_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; + MAKE_STD_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::StreamUtil::getSlicedDataMember(zval* obj, ObjectMap* objectMap TSRMLS_DC) +{ + Ice::SlicedDataPtr slicedData; + + string name = "_ice_slicedData"; + void* data; + if(zend_hash_find(Z_OBJPROP_P(obj), STRCAST(name.c_str()), name.size() + 1, &data) == SUCCESS) + { + zval* sd = *(reinterpret_cast<zval**>(data)); + + if(Z_TYPE_P(sd) != IS_NULL) + { +#ifndef NDEBUG + int status; +#endif + + // + // The "slices" member is an array of Ice_SliceInfo objects. + // +#ifndef NDEBUG + status = +#endif + zend_hash_find(Z_OBJPROP_P(sd), STRCAST("slices"), sizeof("slices"), &data); + assert(status == SUCCESS); + zval* sl = *(reinterpret_cast<zval**>(data)); + assert(Z_TYPE_P(sl) == IS_ARRAY); + + Ice::SliceInfoSeq slices; + + HashTable* arr = Z_ARRVAL_P(sl); + assert(arr); + HashPosition pos; + zend_hash_internal_pointer_reset_ex(arr, &pos); + + while(zend_hash_get_current_data_ex(arr, &data, &pos) != FAILURE) + { + zval* s = *(reinterpret_cast<zval**>(data)); + assert(Z_OBJCE_P(s) == _sliceInfoType); + + Ice::SliceInfoPtr info = new Ice::SliceInfo; + +#ifndef NDEBUG + status = +#endif + zend_hash_find(Z_OBJPROP_P(s), STRCAST("typeId"), sizeof("typeId"), &data); + assert(status == SUCCESS); + zval* typeId = *(reinterpret_cast<zval**>(data)); + assert(Z_TYPE_P(typeId) == IS_STRING); + info->typeId = string(Z_STRVAL_P(typeId), Z_STRLEN_P(typeId)); + +#ifndef NDEBUG + status = +#endif + zend_hash_find(Z_OBJPROP_P(s), STRCAST("compactId"), sizeof("compactId"), &data); + assert(status == SUCCESS); + zval* compactId = *(reinterpret_cast<zval**>(data)); + assert(Z_TYPE_P(compactId) == IS_LONG); + info->compactId = Z_LVAL_P(compactId); + +#ifndef NDEBUG + status = +#endif + zend_hash_find(Z_OBJPROP_P(s), STRCAST("bytes"), sizeof("bytes"), &data); + assert(status == SUCCESS); + zval* bytes = *(reinterpret_cast<zval**>(data)); + assert(Z_TYPE_P(bytes) == IS_ARRAY); + HashTable* barr = Z_ARRVAL_P(bytes); + HashPosition bpos; + zend_hash_internal_pointer_reset_ex(barr, &bpos); + info->bytes.resize(zend_hash_num_elements(barr)); + + vector<Ice::Byte>::size_type i = 0; + while(zend_hash_get_current_data_ex(barr, &data, &bpos) != FAILURE) + { + zval* e = *(reinterpret_cast<zval**>(data)); + long l = Z_LVAL_P(e); + assert(l >= 0 && l <= 255); + info->bytes[i++] = static_cast<Ice::Byte>(l); + zend_hash_move_forward_ex(barr, &bpos); + } + +#ifndef NDEBUG + status = +#endif + zend_hash_find(Z_OBJPROP_P(s), STRCAST("objects"), sizeof("objects"), &data); + assert(status == SUCCESS); + zval* objects = *(reinterpret_cast<zval**>(data)); + assert(Z_TYPE_P(objects) == IS_ARRAY); + HashTable* oarr = Z_ARRVAL_P(objects); + HashPosition opos; + zend_hash_internal_pointer_reset_ex(oarr, &opos); + + while(zend_hash_get_current_data_ex(oarr, &data, &opos) != FAILURE) + { + zval* o = *(reinterpret_cast<zval**>(data)); + 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 TSRMLS_CC); + objectMap->insert(ObjectMap::value_type(Z_OBJ_HANDLE_P(o), writer)); + } + else + { + writer = i->second; + } + + info->objects.push_back(writer); + zend_hash_move_forward_ex(oarr, &opos); + } + +#ifndef NDEBUG + status = +#endif + zend_hash_find(Z_OBJPROP_P(s), STRCAST("hasOptionalMembers"), sizeof("hasOptionalMembers"), &data); + assert(status == SUCCESS); + zval* hasOptionalMembers = *(reinterpret_cast<zval**>(data)); + assert(Z_TYPE_P(hasOptionalMembers) == IS_BOOL); + info->hasOptionalMembers = Z_BVAL_P(hasOptionalMembers) ? true : false; + +#ifndef NDEBUG + status = +#endif + zend_hash_find(Z_OBJPROP_P(s), STRCAST("isLastSlice"), sizeof("isLastSlice"), &data); + assert(status == SUCCESS); + zval* isLastSlice = *(reinterpret_cast<zval**>(data)); + assert(Z_TYPE_P(isLastSlice) == IS_BOOL); + info->isLastSlice = Z_BVAL_P(isLastSlice) ? true : false; + + slices.push_back(info); + zend_hash_move_forward_ex(arr, &pos); + } + + 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* TSRMLS_DC) +{ + 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 TSRMLS_DC) +{ + switch(kind) + { + case PrimitiveInfo::KindBool: + { + 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()); + return false; + } + break; + } + case PrimitiveInfo::KindByte: + { + 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()); + 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); + return false; + } + break; + } + case PrimitiveInfo::KindShort: + { + 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()); + 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); + return false; + } + break; + } + case PrimitiveInfo::KindInt: + { + 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()); + 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); + 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)); + invalidArgument("expected long value but received %s" TSRMLS_CC, s.c_str()); + return false; + } + Ice::Long val; + if(Z_TYPE_P(zv) == IS_LONG) + { + val = Z_LVAL_P(zv); + } + else + { + 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)); + 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)); + 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()) || !isfinite(val); + } + break; + } + case PrimitiveInfo::KindDouble: + { + 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()); + 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)); + invalidArgument("expected string value but received %s" TSRMLS_CC, 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, Ice::OutputStream* os, ObjectMap*, bool TSRMLS_DC) +{ + switch(kind) + { + case PrimitiveInfo::KindBool: + { + assert(Z_TYPE_P(zv) == IS_BOOL); + os->write(Z_BVAL_P(zv) ? true : false); + break; + } + case PrimitiveInfo::KindByte: + { + assert(Z_TYPE_P(zv) == IS_LONG); + long val = 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 = 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 = 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 = 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(Ice::InputStream* is, const UnmarshalCallbackPtr& cb, + const CommunicatorInfoPtr&, zval* target, void* closure, bool TSRMLS_DC) +{ + zval* zv; + MAKE_STD_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()), 1); + } + 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()), 1); + break; + } + } + + cb->unmarshaled(zv, target, closure TSRMLS_CC); +} + +void +IcePHP::PrimitiveInfo::print(zval* zv, IceUtilInternal::Output& out, PrintObjectHistory* TSRMLS_DC) +{ + if(!validate(zv TSRMLS_CC)) + { + out << "<invalid value - expected " << getId() << ">"; + return; + } + zval tmp = *zv; + zval_copy_ctor(&tmp); + INIT_PZVAL(&tmp); + convert_to_string(&tmp); + out << Z_STRVAL(tmp); + zval_dtor(&tmp); +} + +// +// EnumInfo implementation. +// +IcePHP::EnumInfo::EnumInfo(const string& ident, zval* en TSRMLS_DC) : + id(ident), + maxValue(0) +{ + HashTable* arr = Z_ARRVAL_P(en); + void* data; + HashPosition pos; + zend_hash_internal_pointer_reset_ex(arr, &pos); + while(zend_hash_get_current_data_ex(arr, &data, &pos) != FAILURE) + { + zval** val; + + val = reinterpret_cast<zval**>(data); + assert(Z_TYPE_PP(val) == IS_STRING); + string name = Z_STRVAL_PP(val); + zend_hash_move_forward_ex(arr, &pos); + + zend_hash_get_current_data_ex(arr, &data, &pos); + val = reinterpret_cast<zval**>(data); + assert(Z_TYPE_PP(val) == IS_LONG); + Ice::Int value = static_cast<Ice::Int>(Z_LVAL_PP(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 TSRMLS_DC) +{ + 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, Ice::OutputStream* os, ObjectMap*, bool TSRMLS_DC) +{ + 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(Ice::InputStream* is, const UnmarshalCallbackPtr& cb, + const CommunicatorInfoPtr&, zval* target, void* closure, bool TSRMLS_DC) +{ + zval* zv; + ALLOC_INIT_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" TSRMLS_CC, val, id.c_str()); + throw AbortMarshaling(); + } + + ZVAL_LONG(zv, val); + cb->unmarshaled(zv, target, closure TSRMLS_CC); +} + +void +IcePHP::EnumInfo::print(zval* zv, IceUtilInternal::Output& out, PrintObjectHistory* TSRMLS_DC) +{ + if(!validate(zv TSRMLS_CC)) + { + 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* TSRMLS_DC) +{ + setMember(target, zv TSRMLS_CC); +} + +void +IcePHP::DataMember::setMember(zval* target, zval* zv TSRMLS_DC) +{ + 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'" TSRMLS_CC, name.c_str()); + throw AbortMarshaling(); + } +} + +static void +convertDataMembers(zval* zv, DataMemberList& reqMembers, DataMemberList& optMembers, bool allowOptional TSRMLS_DC) +{ + list<DataMemberPtr> optList; + + assert(Z_TYPE_P(zv) == IS_ARRAY); + HashTable* membersArray = Z_ARRVAL_P(zv); + void* data; + HashPosition pos; + zend_hash_internal_pointer_reset_ex(membersArray, &pos); + while(zend_hash_get_current_data_ex(membersArray, &data, &pos) != FAILURE) + { + zval** arr = reinterpret_cast<zval**>(data); + + DataMemberPtr m = new DataMember(); + zval** elem; + + assert(Z_TYPE_PP(arr) == IS_ARRAY); + HashTable* member = Z_ARRVAL_PP(arr); + assert(zend_hash_num_elements(member) == allowOptional ? 4 : 2); + zend_hash_index_find(member, 0, reinterpret_cast<void**>(&elem)); + assert(Z_TYPE_PP(elem) == IS_STRING); + m->name = Z_STRVAL_PP(elem); + zend_hash_index_find(member, 1, reinterpret_cast<void**>(&elem)); + assert(Z_TYPE_PP(elem) == IS_OBJECT); + m->type = Wrapper<TypeInfoPtr>::value(*elem TSRMLS_CC); + + if(allowOptional) + { + zend_hash_index_find(member, 2, reinterpret_cast<void**>(&elem)); + assert(Z_TYPE_PP(elem) == IS_BOOL); + m->optional = Z_BVAL_PP(elem) ? true : false; + zend_hash_index_find(member, 3, reinterpret_cast<void**>(&elem)); + assert(Z_TYPE_PP(elem) == IS_LONG); + m->tag = static_cast<int>(Z_LVAL_PP(elem)); + } + else + { + m->optional = false; + m->tag = 0; + } + + if(m->optional) + { + optList.push_back(m); + } + else + { + reqMembers.push_back(m); + } + + zend_hash_move_forward_ex(membersArray, &pos); + } + + 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 TSRMLS_DC) : + id(ident), name(n), _nullMarshalValue(0) +{ + DataMemberList opt; + convertDataMembers(m, const_cast<DataMemberList&>(members), opt, false TSRMLS_CC); + assert(opt.empty()); + const_cast<zend_class_entry*&>(zce) = nameToClass(name TSRMLS_CC); + 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 TSRMLS_DC) +{ + if(Z_TYPE_P(zv) == IS_NULL) + { + return true; + } + 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()); + 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" TSRMLS_CC, zce->name, ce->name); + 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, Ice::OutputStream* os, ObjectMap* objectMap, bool optional TSRMLS_DC) +{ + 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(_nullMarshalValue == 0) + { + MAKE_STD_ZVAL(_nullMarshalValue); + if(object_init_ex(_nullMarshalValue, const_cast<zend_class_entry*>(zce)) != SUCCESS) + { + runtimeError("unable to initialize object of type %s" TSRMLS_CC, zce->name); + throw AbortMarshaling(); + } + + if(!invokeMethod(_nullMarshalValue, ZEND_CONSTRUCTOR_FUNC_NAME TSRMLS_CC)) + { + assert(false); + } + } + 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; + + void* data; + if(zend_hash_find(Z_OBJPROP_P(zv), STRCAST(member->name.c_str()), member->name.size() + 1, &data) == FAILURE) + { + runtimeError("member `%s' of %s is not defined" TSRMLS_CC, member->name.c_str(), id.c_str()); + throw AbortMarshaling(); + } + + zval** val = reinterpret_cast<zval**>(data); + if(!member->type->validate(*val TSRMLS_CC)) + { + invalidArgument("invalid value for %s member `%s'" TSRMLS_CC, id.c_str(), member->name.c_str()); + throw AbortMarshaling(); + } + + member->type->marshal(*val, os, objectMap, false TSRMLS_CC); + } + + if(optional && _variableLength) + { + os->endSize(sizePos); + } +} + +void +IcePHP::StructInfo::unmarshal(Ice::InputStream* is, const UnmarshalCallbackPtr& cb, + const CommunicatorInfoPtr& comm, zval* target, void* closure, bool optional TSRMLS_DC) +{ + zval* zv; + MAKE_STD_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" TSRMLS_CC, zce->name); + 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 TSRMLS_CC); + } + + cb->unmarshaled(zv, target, closure TSRMLS_CC); +} + +void +IcePHP::StructInfo::print(zval* zv, IceUtilInternal::Output& out, PrintObjectHistory* history TSRMLS_DC) +{ + if(!validate(zv TSRMLS_CC)) + { + 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 << " = "; + void* data; + if(zend_hash_find(Z_OBJPROP_P(zv), STRCAST(member->name.c_str()), member->name.size() + 1, &data) == + SUCCESS) + { + zval** val = reinterpret_cast<zval**>(data); + member->type->print(*val, out, history TSRMLS_CC); + } + 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(_nullMarshalValue != 0) + { + zval_ptr_dtor(&_nullMarshalValue); + _nullMarshalValue = 0; + } +} + +// +// SequenceInfo implementation. +// +IcePHP::SequenceInfo::SequenceInfo(const string& ident, zval* e TSRMLS_DC) : + id(ident) +{ + const_cast<TypeInfoPtr&>(elementType) = Wrapper<TypeInfoPtr>::value(e TSRMLS_CC); +} + +string +IcePHP::SequenceInfo::getId() const +{ + return id; +} + +bool +IcePHP::SequenceInfo::validate(zval* zv TSRMLS_DC) +{ + 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, Ice::OutputStream* os, ObjectMap* objectMap, bool optional TSRMLS_DC) +{ + 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 TSRMLS_CC); + return; + } + + HashPosition pos; + zend_hash_internal_pointer_reset_ex(arr, &pos); + + os->writeSize(sz); + + void* data; + while(zend_hash_get_current_data_ex(arr, &data, &pos) != FAILURE) + { + zval** val = reinterpret_cast<zval**>(data); + if(!elementType->validate(*val TSRMLS_CC)) + { + invalidArgument("invalid value for sequence element `%s'" TSRMLS_CC, id.c_str()); + throw AbortMarshaling(); + } + elementType->marshal(*val, os, objectMap, false TSRMLS_CC); + zend_hash_move_forward_ex(arr, &pos); + } + } + + if(optional && elementType->variableLength()) + { + os->endSize(sizePos); + } +} + +void +IcePHP::SequenceInfo::unmarshal(Ice::InputStream* is, const UnmarshalCallbackPtr& cb, + const CommunicatorInfoPtr& comm, zval* target, void* closure, bool optional TSRMLS_DC) +{ + 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 TSRMLS_CC); + return; + } + + zval* zv; + MAKE_STD_ZVAL(zv); + array_init(zv); + AutoDestroy destroy(zv); + + Ice::Int sz = is->readSize(); + for(Ice::Int i = 0; i < sz; ++i) + { + void* cl = reinterpret_cast<void*>(i); + elementType->unmarshal(is, this, comm, zv, cl, false TSRMLS_CC); + } + + cb->unmarshaled(zv, target, closure TSRMLS_CC); +} + +void +IcePHP::SequenceInfo::print(zval* zv, IceUtilInternal::Output& out, PrintObjectHistory* history TSRMLS_DC) +{ + if(!validate(zv TSRMLS_CC)) + { + 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); + + HashPosition pos; + zend_hash_internal_pointer_reset_ex(arr, &pos); + + out.sb(); + + int i = 0; + void* data; + while(zend_hash_get_current_data_ex(arr, &data, &pos) != FAILURE) + { + zval** val = reinterpret_cast<zval**>(data); + out << nl << '[' << i << "] = "; + elementType->print(*val, out, history TSRMLS_CC); + zend_hash_move_forward_ex(arr, &pos); + ++i; + } + + out.eb(); + } +} + +void +IcePHP::SequenceInfo::unmarshaled(zval* zv, zval* target, void* closure TSRMLS_DC) +{ + assert(Z_TYPE_P(target) == IS_ARRAY); + long i = reinterpret_cast<long>(closure); + add_index_zval(target, i, 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, Ice::OutputStream* os TSRMLS_DC) +{ + HashTable* arr = Z_ARRVAL_P(zv); + + HashPosition pos; + zend_hash_internal_pointer_reset_ex(arr, &pos); + + 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; + void* data; + while(zend_hash_get_current_data_ex(arr, &data, &pos) != FAILURE) + { + zval** val = reinterpret_cast<zval**>(data); + if(!pi->validate(*val TSRMLS_CC)) + { + throw AbortMarshaling(); + } + seq[i++] = Z_BVAL_P(*val) ? true : false; + zend_hash_move_forward_ex(arr, &pos); + } +#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; + void* data; + while(zend_hash_get_current_data_ex(arr, &data, &pos) != FAILURE) + { + zval** val = reinterpret_cast<zval**>(data); + if(!pi->validate(*val TSRMLS_CC)) + { + throw AbortMarshaling(); + } + long l = Z_LVAL_P(*val); + assert(l >= 0 && l <= 255); + seq[i++] = static_cast<Ice::Byte>(l); + zend_hash_move_forward_ex(arr, &pos); + } + os->write(&seq[0], &seq[0] + seq.size()); + break; + } + case PrimitiveInfo::KindShort: + { + Ice::ShortSeq seq(sz); + Ice::Int i = 0; + void* data; + while(zend_hash_get_current_data_ex(arr, &data, &pos) != FAILURE) + { + zval** val = reinterpret_cast<zval**>(data); + if(!pi->validate(*val TSRMLS_CC)) + { + throw AbortMarshaling(); + } + long l = Z_LVAL_P(*val); + assert(l >= SHRT_MIN && l <= SHRT_MAX); + seq[i++] = static_cast<Ice::Short>(l); + zend_hash_move_forward_ex(arr, &pos); + } + os->write(&seq[0], &seq[0] + seq.size()); + break; + } + case PrimitiveInfo::KindInt: + { + Ice::IntSeq seq(sz); + Ice::Int i = 0; + void* data; + while(zend_hash_get_current_data_ex(arr, &data, &pos) != FAILURE) + { + zval** val = reinterpret_cast<zval**>(data); + if(!pi->validate(*val TSRMLS_CC)) + { + throw AbortMarshaling(); + } + long l = Z_LVAL_P(*val); + assert(l >= INT_MIN && l <= INT_MAX); + seq[i++] = static_cast<Ice::Int>(l); + zend_hash_move_forward_ex(arr, &pos); + } + os->write(&seq[0], &seq[0] + seq.size()); + break; + } + case PrimitiveInfo::KindLong: + { + Ice::LongSeq seq(sz); + Ice::Int i = 0; + void* data; + while(zend_hash_get_current_data_ex(arr, &data, &pos) != FAILURE) + { + zval** val = reinterpret_cast<zval**>(data); + if(!pi->validate(*val TSRMLS_CC)) + { + 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 = Z_LVAL_P(*val); + } + else + { + string sval(Z_STRVAL_P(*val), Z_STRLEN_P(*val)); + IceUtilInternal::stringToInt64(sval, l); + } + seq[i++] = l; + zend_hash_move_forward_ex(arr, &pos); + } + os->write(&seq[0], &seq[0] + seq.size()); + break; + } + case PrimitiveInfo::KindFloat: + { + Ice::FloatSeq seq(sz); + Ice::Int i = 0; + void* data; + while(zend_hash_get_current_data_ex(arr, &data, &pos) != FAILURE) + { + zval** val = reinterpret_cast<zval**>(data); + if(!pi->validate(*val TSRMLS_CC)) + { + 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_move_forward_ex(arr, &pos); + } + os->write(&seq[0], &seq[0] + seq.size()); + break; + } + case PrimitiveInfo::KindDouble: + { + Ice::DoubleSeq seq(sz); + Ice::Int i = 0; + void* data; + while(zend_hash_get_current_data_ex(arr, &data, &pos) != FAILURE) + { + zval** val = reinterpret_cast<zval**>(data); + if(!pi->validate(*val TSRMLS_CC)) + { + 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_move_forward_ex(arr, &pos); + } + os->write(&seq[0], &seq[0] + seq.size()); + break; + } + case PrimitiveInfo::KindString: + { + Ice::StringSeq seq(sz); + Ice::Int i = 0; + void* data; + while(zend_hash_get_current_data_ex(arr, &data, &pos) != FAILURE) + { + zval** val = reinterpret_cast<zval**>(data); + if(!pi->validate(*val TSRMLS_CC)) + { + 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_move_forward_ex(arr, &pos); + } + os->write(seq); + break; + } + } +} + +void +IcePHP::SequenceInfo::unmarshalPrimitiveSequence(const PrimitiveInfoPtr& pi, Ice::InputStream* is, + const UnmarshalCallbackPtr& cb, zval* target, void* closure TSRMLS_DC) +{ + zval* zv; + MAKE_STD_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; + MAKE_STD_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()), 1); + } + 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; + MAKE_STD_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; + MAKE_STD_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; + MAKE_STD_ZVAL(val); + ZVAL_STRINGL(val, STRCAST(p->c_str()), static_cast<int>(p->length()), 1); + add_index_zval(zv, i, val); + } + break; + } + } + + cb->unmarshaled(zv, target, closure TSRMLS_CC); +} + +// +// DictionaryInfo implementation. +// +IcePHP::DictionaryInfo::DictionaryInfo(const string& ident, zval* k, zval* v TSRMLS_DC) : + id(ident) +{ + const_cast<TypeInfoPtr&>(keyType) = Wrapper<TypeInfoPtr>::value(k TSRMLS_CC); + const_cast<TypeInfoPtr&>(valueType) = Wrapper<TypeInfoPtr>::value(v TSRMLS_CC); + + _variableLength = keyType->variableLength() || valueType->variableLength(); + _wireSize = keyType->wireSize() + valueType->wireSize(); +} + +string +IcePHP::DictionaryInfo::getId() const +{ + return id; +} + +bool +IcePHP::DictionaryInfo::validate(zval* zv TSRMLS_DC) +{ + 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, Ice::OutputStream* os, ObjectMap* objectMap, bool optional TSRMLS_DC) +{ + 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" TSRMLS_CC, id.c_str()); + throw AbortMarshaling(); + } + + os->writeSize(sz); + + if(sz > 0) + { + HashPosition pos; + void* data; + + zend_hash_internal_pointer_reset_ex(arr, &pos); + while(zend_hash_get_current_data_ex(arr, &data, &pos) != FAILURE) + { + zval** val = reinterpret_cast<zval**>(data); + + // + // Get the key (which can be a long or a string). + // + char* keyStr; + uint keyLen; + ulong keyNum; + int hashKeyType = zend_hash_get_current_key_ex(arr, &keyStr, &keyLen, &keyNum, 0, &pos); + + // + // Store the key in a zval so that we can reuse the marshaling logic. + // + zval* zkey; + MAKE_STD_ZVAL(zkey); + AutoDestroy destroy(zkey); + + if(hashKeyType == HASH_KEY_IS_LONG) + { + ZVAL_LONG(zkey, keyNum); + } + else + { + ZVAL_STRINGL(zkey, keyStr, keyLen - 1, 1); + } + + // + // 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(hashKeyType == HASH_KEY_IS_STRING) + { + convert_to_long(zkey); + } + break; + } + + case PrimitiveInfo::KindString: + { + if(hashKeyType == HASH_KEY_IS_LONG) + { + convert_to_string(zkey); + } + break; + } + + case PrimitiveInfo::KindFloat: + case PrimitiveInfo::KindDouble: + assert(false); + } + } + else + { + if(hashKeyType == HASH_KEY_IS_STRING) + { + convert_to_long(zkey); + } + } + + // + // Marshal the key. + // + if(!keyType->validate(zkey TSRMLS_CC)) + { + invalidArgument("invalid key in `%s' element" TSRMLS_CC, id.c_str()); + throw AbortMarshaling(); + } + keyType->marshal(zkey, os, objectMap, false TSRMLS_CC); + + // + // Marshal the value. + // + if(!valueType->validate(*val TSRMLS_CC)) + { + invalidArgument("invalid value in `%s' element" TSRMLS_CC, id.c_str()); + throw AbortMarshaling(); + } + valueType->marshal(*val, os, objectMap, false TSRMLS_CC); + + zend_hash_move_forward_ex(arr, &pos); + } + } + + if(optional && _variableLength) + { + os->endSize(sizePos); + } +} + +void +IcePHP::DictionaryInfo::unmarshal(Ice::InputStream* is, const UnmarshalCallbackPtr& cb, + const CommunicatorInfoPtr& comm, zval* target, void* closure, bool optional TSRMLS_DC) +{ + 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" TSRMLS_CC, id.c_str()); + throw AbortMarshaling(); + } + + zval* zv; + MAKE_STD_ZVAL(zv); + array_init(zv); + AutoDestroy destroy(zv); + + KeyCallbackPtr keyCB = new KeyCallback; + + 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. + // + keyType->unmarshal(is, keyCB, comm, 0, 0, false TSRMLS_CC); + assert(keyCB->key); + + // + // Allocate a callback that holds a reference to the key. + // + ValueCallbackPtr valueCB = new ValueCallback(keyCB->key TSRMLS_CC); + + // + // Pass the key to the callback. + // + valueType->unmarshal(is, valueCB, comm, zv, 0, false TSRMLS_CC); + } + + cb->unmarshaled(zv, target, closure TSRMLS_CC); +} + +void +IcePHP::DictionaryInfo::print(zval* zv, IceUtilInternal::Output& out, PrintObjectHistory* history TSRMLS_DC) +{ + if(!validate(zv TSRMLS_CC)) + { + out << "<invalid value - expected " << id << ">"; + return; + } + + if(Z_TYPE_P(zv) == IS_NULL) + { + out << "{}"; + } + else + { + HashTable* arr = Z_ARRVAL_P(zv); + HashPosition pos; + void* data; + bool first = true; + + out.sb(); + + zend_hash_internal_pointer_reset_ex(arr, &pos); + while(zend_hash_get_current_data_ex(arr, &data, &pos) != FAILURE) + { + zval** val = reinterpret_cast<zval**>(data); + + // + // Get the key (which can be a long or a string). + // + char* keyStr; + uint keyLen; + ulong keyNum; + int hashKeyType = zend_hash_get_current_key_ex(arr, &keyStr, &keyLen, &keyNum, 0, &pos); + + if(first) + { + first = false; + } + else + { + out << nl; + } + out << nl << "key = "; + if(hashKeyType == HASH_KEY_IS_LONG) + { + out << keyNum; + } + else + { + out << keyStr; + } + out << nl << "value = "; + valueType->print(*val, out, history TSRMLS_CC); + + zend_hash_move_forward_ex(arr, &pos); + } + + out.eb(); + } +} + +IcePHP::DictionaryInfo::KeyCallback::KeyCallback() : + key(0) +{ +} + +IcePHP::DictionaryInfo::KeyCallback::~KeyCallback() +{ + if(key) + { + zval_ptr_dtor(&key); + } +} + +void +IcePHP::DictionaryInfo::KeyCallback::unmarshaled(zval* zv, zval*, void* TSRMLS_DC) +{ + if(key) + { + zval_ptr_dtor(&key); + } + + key = zv; + Z_ADDREF_P(key); +} + +IcePHP::DictionaryInfo::ValueCallback::ValueCallback(zval* k TSRMLS_DC) : + key(k) +{ + Z_ADDREF_P(key); +} + +IcePHP::DictionaryInfo::ValueCallback::~ValueCallback() +{ + zval_ptr_dtor(&key); +} + +void +IcePHP::DictionaryInfo::ValueCallback::unmarshaled(zval* zv, zval* target, void* TSRMLS_DC) +{ + assert(Z_TYPE_P(target) == IS_ARRAY); + + switch(Z_TYPE_P(key)) + { + case IS_LONG: + add_index_zval(target, Z_LVAL_P(key), zv); + break; + case IS_BOOL: + add_index_zval(target, Z_BVAL_P(key) ? 1 : 0, zv); + break; + case IS_STRING: + add_assoc_zval_ex(target, Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, zv); + break; + default: + assert(false); + return; + } + Z_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 TSRMLS_DC) : + 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 TSRMLS_DC) +{ + 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 TSRMLS_CC); + const_cast<ClassInfoPtr&>(base) = ClassInfoPtr::dynamicCast(p); + assert(base); + } + + if(i) + { + HashTable* interfacesArray = Z_ARRVAL_P(i); + void* data; + HashPosition pos; + zend_hash_internal_pointer_reset_ex(interfacesArray, &pos); + while(zend_hash_get_current_data_ex(interfacesArray, &data, &pos) != FAILURE) + { + zval** interfaceType = reinterpret_cast<zval**>(data); + TypeInfoPtr t = Wrapper<TypeInfoPtr>::value(*interfaceType TSRMLS_CC); + ClassInfoPtr c = ClassInfoPtr::dynamicCast(t); + assert(c); + const_cast<ClassInfoList&>(interfaces).push_back(c); + zend_hash_move_forward_ex(interfacesArray, &pos); + } + } + + if(m) + { + convertDataMembers(m, const_cast<DataMemberList&>(members), const_cast<DataMemberList&>(optionalMembers), + true TSRMLS_CC); + } + + const_cast<bool&>(defined) = true; + const_cast<zend_class_entry*&>(zce) = nameToClass(name TSRMLS_CC); + 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 TSRMLS_DC) +{ + 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, Ice::OutputStream* os, ObjectMap* objectMap, bool TSRMLS_DC) +{ + if(!defined) + { + runtimeError("class or interface %s is declared but not defined" TSRMLS_CC, id.c_str()); + throw AbortMarshaling(); + } + + if(Z_TYPE_P(zv) == IS_NULL) + { + Ice::ObjectPtr nil; + os->write(nil); + return; + } + + assert(Z_TYPE_P(zv) == IS_OBJECT); // validate() should have caught this. + assert(checkClass(Z_OBJCE_P(zv), 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 TSRMLS_CC); + 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->write(writer); +} + +namespace +{ + +void +patchObject(void* addr, const Ice::ObjectPtr& v) +{ + ReadObjectCallback* cb = static_cast<ReadObjectCallback*>(addr); + assert(cb); + cb->invoke(v); +} + +} + +void +IcePHP::ClassInfo::unmarshal(Ice::InputStream* is, const UnmarshalCallbackPtr& cb, + const CommunicatorInfoPtr& comm, zval* target, void* closure, bool TSRMLS_DC) +{ + if(!defined) + { + runtimeError("class or interface %s is declared but not defined" TSRMLS_CC, id.c_str()); + throw AbortMarshaling(); + } + + // + // This callback is notified when the Slice value is actually read. The StreamUtil object + // attached to the stream keeps a reference to the callback object to ensure it lives + // long enough. + // + ReadObjectCallbackPtr rocb = new ReadObjectCallback(this, cb, target, closure TSRMLS_CC); + StreamUtil* util = reinterpret_cast<StreamUtil*>(is->getClosure()); + assert(util); + util->add(rocb); + is->read(patchObject, rocb.get()); +} + +void +IcePHP::ClassInfo::print(zval* zv, IceUtilInternal::Output& out, PrintObjectHistory* history TSRMLS_DC) +{ + if(!validate(zv TSRMLS_CC)) + { + 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 TSRMLS_CC); + 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 TSRMLS_DC) +{ + if(base) + { + base->printMembers(zv, out, history TSRMLS_CC); + } + + DataMemberList::const_iterator q; + + for(q = members.begin(); q != members.end(); ++q) + { + DataMemberPtr member = *q; + + out << nl << member->name << " = "; + void* data; + if(zend_hash_find(Z_OBJPROP_P(zv), STRCAST(member->name.c_str()), member->name.size() + 1, &data) == SUCCESS) + { + zval** val = reinterpret_cast<zval**>(data); + member->type->print(*val, out, history TSRMLS_CC); + } + else + { + out << "<not defined>"; + } + } + + for(q = optionalMembers.begin(); q != optionalMembers.end(); ++q) + { + DataMemberPtr member = *q; + + out << nl << member->name << " = "; + void* data; + if(zend_hash_find(Z_OBJPROP_P(zv), STRCAST(member->name.c_str()), member->name.size() + 1, &data) == SUCCESS) + { + zval** val = reinterpret_cast<zval**>(data); + if(isUnset(*val TSRMLS_CC)) + { + out << "<unset>"; + } + else + { + member->type->print(*val, out, history TSRMLS_CC); + } + } + 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 TSRMLS_DC) : + id(ident), defined(false) +{ +} + +void +IcePHP::ProxyInfo::define(const ClassInfoPtr& c TSRMLS_DC) +{ + const_cast<ClassInfoPtr&>(cls) = c; + const_cast<bool&>(defined) = true; +} + +string +IcePHP::ProxyInfo::getId() const +{ + return id; +} + +bool +IcePHP::ProxyInfo::validate(zval* zv 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()); + 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, Ice::OutputStream* os, ObjectMap*, bool optional TSRMLS_DC) +{ + 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 TSRMLS_CC)) + { + throw AbortMarshaling(); + } + if(!info->isA(id)) + { + invalidArgument("proxy is not narrowed to %s" TSRMLS_CC, id.c_str()); + throw AbortMarshaling(); + } + os->write(proxy); + } + + if(optional) + { + os->endSize(sizePos); + } +} + +void +IcePHP::ProxyInfo::unmarshal(Ice::InputStream* is, const UnmarshalCallbackPtr& cb, + const CommunicatorInfoPtr& comm, zval* target, void* closure, bool optional TSRMLS_DC) +{ + zval* zv; + MAKE_STD_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 TSRMLS_CC); + return; + } + + if(!cls->defined) + { + runtimeError("class or interface %s is declared but not defined" TSRMLS_CC, id.c_str()); + throw AbortMarshaling(); + } + + if(!createProxy(zv, proxy, cls, comm TSRMLS_CC)) + { + throw AbortMarshaling(); + } + cb->unmarshaled(zv, target, closure TSRMLS_CC); +} + +void +IcePHP::ProxyInfo::print(zval* zv, IceUtilInternal::Output& out, PrintObjectHistory* TSRMLS_DC) +{ + if(!validate(zv TSRMLS_CC)) + { + 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 TSRMLS_CC)) + { + 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 TSRMLS_DC) : + _object(object), _map(objectMap) +{ +#ifdef ZTS + this->TSRMLS_C = TSRMLS_C; +#endif + + Z_ADDREF_P(_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 TSRMLS_CC); + assert(_info); +} + +IcePHP::ObjectWriter::~ObjectWriter() +{ + zval_ptr_dtor(&_object); +} + +void +IcePHP::ObjectWriter::ice_preMarshal() +{ + string name = "ice_premarshal"; // Must be lowercase. + if(zend_hash_exists(&Z_OBJCE_P(_object)->function_table, STRCAST(name.c_str()), static_cast<uint>(name.size() + 1))) + { + if(!invokeMethod(_object, name TSRMLS_CC)) + { + throw AbortMarshaling(); + } + } +} + +void +IcePHP::ObjectWriter::__write(Ice::OutputStream* os) const +{ + Ice::SlicedDataPtr slicedData; + + if(_info->preserve) + { + // + // Retrieve the SlicedData object that we stored as a hidden member of the PHP object. + // + slicedData = StreamUtil::getSlicedDataMember(_object, const_cast<ObjectMap*>(_map) TSRMLS_CC); + } + + 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::__read(Ice::InputStream*) +{ + assert(false); +} + +void +IcePHP::ObjectWriter::writeMembers(Ice::OutputStream* os, const DataMemberList& members) const +{ + for(DataMemberList::const_iterator q = members.begin(); q != members.end(); ++q) + { + DataMemberPtr member = *q; + + void* data; + if(zend_hash_find(Z_OBJPROP_P(_object), + STRCAST(member->name.c_str()), static_cast<int>(member->name.size() + 1), &data) == FAILURE) + { + runtimeError("member `%s' of %s is not defined" TSRMLS_CC, member->name.c_str(), _info->id.c_str()); + throw AbortMarshaling(); + } + + zval** val = reinterpret_cast<zval**>(data); + + if(member->optional && (isUnset(*val TSRMLS_CC) || + !os->writeOptional(member->tag, member->type->optionalFormat()))) + { + continue; + } + + if(!member->type->validate(*val TSRMLS_CC)) + { + invalidArgument("invalid value for %s member `%s'" TSRMLS_CC, _info->id.c_str(), + member->name.c_str()); + throw AbortMarshaling(); + } + + member->type->marshal(*val, os, _map, member->optional TSRMLS_CC); + } +} + +// +// ObjectReader implementation. +// +IcePHP::ObjectReader::ObjectReader(zval* object, const ClassInfoPtr& info, const CommunicatorInfoPtr& comm TSRMLS_DC) : + _object(object), _info(info), _communicator(comm) +{ +#ifdef ZTS + this->TSRMLS_C = TSRMLS_C; +#endif + + Z_ADDREF_P(_object); +} + +IcePHP::ObjectReader::~ObjectReader() +{ + zval_ptr_dtor(&_object); +} + +void +IcePHP::ObjectReader::ice_postUnmarshal() +{ + string name = "ice_postunmarshal"; // Must be lowercase. + if(zend_hash_exists(&Z_OBJCE_P(_object)->function_table, STRCAST(name.c_str()), static_cast<int>(name.size() + 1))) + { + if(!invokeMethod(_object, name TSRMLS_CC)) + { + throw AbortMarshaling(); + } + } +} + +void +IcePHP::ObjectReader::__write(Ice::OutputStream*) const +{ + assert(false); +} + +void +IcePHP::ObjectReader::__read(Ice::InputStream* 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 TSRMLS_CC); + } + + // + // 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 TSRMLS_CC); + } + else + { + zval* zv; + MAKE_STD_ZVAL(zv); + AutoDestroy destroy(zv); + assignUnset(zv TSRMLS_CC); + member->setMember(_object, zv TSRMLS_CC); + } + } + + is->endSlice(); + + info = info->base; + } + } + + _slicedData = is->endObject(_info->preserve); + + if(_slicedData) + { + StreamUtil* util = reinterpret_cast<StreamUtil*>(is->getClosure()); + 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; + MAKE_STD_ZVAL(zv); + AutoDestroy typeIdDestroyer(zv); + ZVAL_STRINGL(zv, STRCAST(typeId.c_str()), static_cast<int>(typeId.size()), 1); + add_property_zval(_object, STRCAST("unknownTypeId"), zv); + } + } +} + +ClassInfoPtr +IcePHP::ObjectReader::getInfo() const +{ + return _info; +} + +zval* +IcePHP::ObjectReader::getObject() const +{ + return _object; +} + +Ice::SlicedDataPtr +IcePHP::ObjectReader::getSlicedData() const +{ + return _slicedData; +} + +// +// ReadObjectCallback implementation. +// +IcePHP::ReadObjectCallback::ReadObjectCallback(const ClassInfoPtr& info, const UnmarshalCallbackPtr& cb, + zval* target, void* closure TSRMLS_DC) : + _info(info), _cb(cb), _target(target), _closure(closure) +{ +#ifdef ZTS + this->TSRMLS_C = TSRMLS_C; +#endif + + // + // Keep a reference to the target to prevent it from being deallocated until the + // Ice object is actually read. + // + if(_target) + { + Z_ADDREF_P(_target); + } +} + +IcePHP::ReadObjectCallback::~ReadObjectCallback() +{ + if(_target) + { + 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 TSRMLS_CC); + } + else + { + zval* zv; + MAKE_STD_ZVAL(zv); + AutoDestroy destroy(zv); + ZVAL_NULL(zv); + _cb->unmarshaled(zv, _target, _closure TSRMLS_CC); + } +} + +// +// ExceptionInfo implementation. +// +zval* +IcePHP::ExceptionInfo::unmarshal(Ice::InputStream* is, const CommunicatorInfoPtr& comm TSRMLS_DC) +{ + zval* zv; + MAKE_STD_ZVAL(zv); + AutoDestroy destroy(zv); + + if(object_init_ex(zv, zce) != SUCCESS) + { + runtimeError("unable to initialize object of type %s" TSRMLS_CC, zce->name); + 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 TSRMLS_CC); + } + + // + // 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 TSRMLS_CC); + } + else + { + zval* un; + MAKE_STD_ZVAL(un); + AutoDestroy destroy(un); + assignUnset(un TSRMLS_CC); + member->setMember(zv, un TSRMLS_CC); + } + } + + is->endSlice(); + + info = info->base; + } + + return destroy.release(); +} + +void +IcePHP::ExceptionInfo::print(zval* zv, IceUtilInternal::Output& out TSRMLS_DC) +{ + 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()); + return; + } + + // + // Compare class entries. + // + 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); + return; + } + + PrintObjectHistory history; + history.index = 0; + + out << "exception " << id; + out.sb(); + printMembers(zv, out, &history TSRMLS_CC); + out.eb(); +} + +void +IcePHP::ExceptionInfo::printMembers(zval* zv, IceUtilInternal::Output& out, PrintObjectHistory* history TSRMLS_DC) +{ + if(base) + { + base->printMembers(zv, out, history TSRMLS_CC); + } + + DataMemberList::iterator q; + + for(q = members.begin(); q != members.end(); ++q) + { + DataMemberPtr member = *q; + + out << nl << member->name << " = "; + void* data; + if(zend_hash_find(Z_OBJPROP_P(zv), STRCAST(member->name.c_str()), static_cast<int>(member->name.size() + 1), + &data) == SUCCESS) + { + zval** val = reinterpret_cast<zval**>(data); + member->type->print(*val, out, history TSRMLS_CC); + } + else + { + out << "<not defined>"; + } + } + + for(q = optionalMembers.begin(); q != optionalMembers.end(); ++q) + { + DataMemberPtr member = *q; + + out << nl << member->name << " = "; + void* data; + if(zend_hash_find(Z_OBJPROP_P(zv), STRCAST(member->name.c_str()), static_cast<int>(member->name.size() + 1), + &data) == SUCCESS) + { + zval** val = reinterpret_cast<zval**>(data); + if(isUnset(*val TSRMLS_CC)) + { + out << "<unset>"; + } + else + { + member->type->print(*val, out, history TSRMLS_CC); + } + } + 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 + TSRMLS_DC) : + _communicatorInfo(communicatorInfo), _info(info) +{ +#ifdef ZTS + this->TSRMLS_C = TSRMLS_C; +#endif +} + +IcePHP::ExceptionReader::~ExceptionReader() + throw() +{ +} + +string +IcePHP::ExceptionReader::ice_id() const +{ + return _info->id; +} + +IcePHP::ExceptionReader* +IcePHP::ExceptionReader::ice_clone() const +{ + assert(false); + return 0; +} + +void +IcePHP::ExceptionReader::ice_throw() const +{ + throw *this; +} + +void +IcePHP::ExceptionReader::__write(Ice::OutputStream*) const +{ + assert(false); +} + +void +IcePHP::ExceptionReader::__read(Ice::InputStream* is) +{ + 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; +} + +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(TSRMLS_D) +{ +#ifdef ZTS + this->TSRMLS_C = TSRMLS_C; +#endif +} + +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_value +handleTypeInfoAlloc(zend_class_entry* ce TSRMLS_DC) +{ + zend_object_value result; + + Wrapper<TypeInfoPtr>* obj = Wrapper<TypeInfoPtr>::create(ce TSRMLS_CC); + assert(obj); + + result.handle = + zend_objects_store_put(obj, 0, reinterpret_cast<zend_objects_free_object_storage_t>(handleTypeInfoFreeStorage), + 0 TSRMLS_CC); + result.handlers = &_typeInfoHandlers; + + return result; +} + +#ifdef _WIN32 +extern "C" +#endif +static void +handleTypeInfoFreeStorage(void* p TSRMLS_DC) +{ + Wrapper<TypeInfoPtr>* obj = static_cast<Wrapper<TypeInfoPtr>*>(p); + delete obj->ptr; + zend_object_std_dtor(static_cast<zend_object*>(p) TSRMLS_CC); + efree(p); +} + +static bool +createTypeInfo(zval* zv, const TypeInfoPtr& p TSRMLS_DC) +{ + if(object_init_ex(zv, typeInfoClassEntry) != SUCCESS) + { + runtimeError("unable to initialize type" TSRMLS_CC); + return false; + } + + Wrapper<TypeInfoPtr>* ze = static_cast<Wrapper<TypeInfoPtr>*>(zend_object_store_get_object(zv TSRMLS_CC)); + assert(!ze->ptr); + ze->ptr = new TypeInfoPtr(p); + + return true; +} + +ZEND_FUNCTION(IcePHP_defineEnum) +{ + char* id; + int idLen; + zval* enumerators; + + if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("sa"), &id, &idLen, &enumerators) == FAILURE) + { + return; + } + + EnumInfoPtr type = new EnumInfo(id, enumerators TSRMLS_CC); + + if(!createTypeInfo(return_value, type TSRMLS_CC)) + { + RETURN_NULL(); + } +} + +ZEND_FUNCTION(IcePHP_defineStruct) +{ + char* id; + int idLen; + char* name; + int nameLen; + zval* members; + + if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("ssa"), &id, &idLen, &name, &nameLen, + &members) == FAILURE) + { + return; + } + + StructInfoPtr type = new StructInfo(id, name, members TSRMLS_CC); + + if(!createTypeInfo(return_value, type TSRMLS_CC)) + { + RETURN_NULL(); + } +} + +ZEND_FUNCTION(IcePHP_defineSequence) +{ + char* id; + int idLen; + zval* element; + + if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("so"), &id, &idLen, &element) == FAILURE) + { + return; + } + + SequenceInfoPtr type = new SequenceInfo(id, element TSRMLS_CC); + + if(!createTypeInfo(return_value, type TSRMLS_CC)) + { + RETURN_NULL(); + } +} + +ZEND_FUNCTION(IcePHP_defineDictionary) +{ + char* id; + int idLen; + zval* key; + zval* value; + + if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("soo"), &id, &idLen, &key, &value) == FAILURE) + { + return; + } + + DictionaryInfoPtr type = new DictionaryInfo(id, key, value TSRMLS_CC); + + if(!createTypeInfo(return_value, type TSRMLS_CC)) + { + RETURN_NULL(); + } +} + +ZEND_FUNCTION(IcePHP_declareProxy) +{ + char* id; + int idLen; + + if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("s"), &id, &idLen) == FAILURE) + { + return; + } + + ProxyInfoPtr type = getProxyInfo(id TSRMLS_CC); + if(!type) + { + type = new ProxyInfo(id TSRMLS_CC); + addProxyInfo(type TSRMLS_CC); + } + + if(!createTypeInfo(return_value, type TSRMLS_CC)) + { + RETURN_NULL(); + } +} + +ZEND_FUNCTION(IcePHP_defineProxy) +{ + zval* cls; + + if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("o"), &cls) == FAILURE) + { + return; + } + + TypeInfoPtr p = Wrapper<TypeInfoPtr>::value(cls TSRMLS_CC); + ClassInfoPtr c = ClassInfoPtr::dynamicCast(p); + assert(c); + + ProxyInfoPtr type = getProxyInfo(c->id TSRMLS_CC); + if(!type) + { + type = new ProxyInfo(c->id TSRMLS_CC); + addProxyInfo(type TSRMLS_CC); + } + + type->define(c TSRMLS_CC); + + if(!createTypeInfo(return_value, type TSRMLS_CC)) + { + RETURN_NULL(); + } +} + +ZEND_FUNCTION(IcePHP_declareClass) +{ + char* id; + int idLen; + + if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("s"), &id, &idLen) == FAILURE) + { + return; + } + + ClassInfoPtr type = getClassInfoById(id TSRMLS_CC); + if(!type) + { + type = new ClassInfo(id TSRMLS_CC); + addClassInfoById(type TSRMLS_CC); + } + + if(!createTypeInfo(return_value, type TSRMLS_CC)) + { + RETURN_NULL(); + } +} + +ZEND_FUNCTION(IcePHP_defineClass) +{ + char* id; + int idLen; + char* name; + int nameLen; + long compactId; + zend_bool isAbstract; + zend_bool preserve; + zval* base; + zval* interfaces; + zval* members; + + if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("sslbbo!a!a!"), &id, &idLen, &name, &nameLen, + &compactId, &isAbstract, &preserve, &base, &interfaces, &members) == FAILURE) + { + return; + } + + ClassInfoPtr type = getClassInfoById(id TSRMLS_CC); + if(!type) + { + type = new ClassInfo(id TSRMLS_CC); + addClassInfoById(type TSRMLS_CC); + } + + type->define(name, static_cast<Ice::Int>(compactId), isAbstract ? true : false, preserve ? true : false, base, + interfaces, members TSRMLS_CC); + addClassInfoByName(type TSRMLS_CC); + + 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 TSRMLS_CC)) + { + RETURN_NULL(); + } +} + +#ifdef _WIN32 +extern "C" +#endif +static zend_object_value +handleExceptionInfoAlloc(zend_class_entry* ce TSRMLS_DC) +{ + zend_object_value result; + + Wrapper<ExceptionInfoPtr>* obj = Wrapper<ExceptionInfoPtr>::create(ce TSRMLS_CC); + assert(obj); + + result.handle = + zend_objects_store_put(obj, 0, + reinterpret_cast<zend_objects_free_object_storage_t>(handleExceptionInfoFreeStorage), 0 TSRMLS_CC); + result.handlers = &_exceptionInfoHandlers; + + return result; +} + +#ifdef _WIN32 +extern "C" +#endif +static void +handleExceptionInfoFreeStorage(void* p TSRMLS_DC) +{ + Wrapper<ExceptionInfoPtr>* obj = static_cast<Wrapper<ExceptionInfoPtr>*>(p); + delete obj->ptr; + zend_object_std_dtor(static_cast<zend_object*>(p) TSRMLS_CC); + efree(p); +} + + +static bool +createExceptionInfo(zval* zv, const ExceptionInfoPtr& p TSRMLS_DC) +{ + if(object_init_ex(zv, exceptionInfoClassEntry) != SUCCESS) + { + runtimeError("unable to initialize exception info" TSRMLS_CC); + return false; + } + + Wrapper<ExceptionInfoPtr>* ze = static_cast<Wrapper<ExceptionInfoPtr>*>(zend_object_store_get_object(zv TSRMLS_CC)); + assert(!ze->ptr); + ze->ptr = new ExceptionInfoPtr(p); + + return true; +} + +ZEND_FUNCTION(IcePHP_defineException) +{ + char* id; + int idLen; + char* name; + int nameLen; + zend_bool preserve; + zval* base; + zval* members; + + if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, 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 TSRMLS_CC); + } + if(members) + { + convertDataMembers(members, ex->members, ex->optionalMembers, true TSRMLS_CC); + } + + 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 TSRMLS_CC); + + assert(!getExceptionInfo(ex->id TSRMLS_CC)); + + 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 TSRMLS_CC)) + { + 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() TSRMLS_CC, const_cast<char*>("zz"), &v, &t) == FAILURE) + { + return; + } + + TypeInfoPtr type = Wrapper<TypeInfoPtr>::value(t TSRMLS_CC); + assert(type); + + ostringstream ostr; + IceUtilInternal::Output out(ostr); + PrintObjectHistory history; + history.index = 0; + type->print(v, out, &history TSRMLS_CC); + + string str = ostr.str(); + RETURN_STRINGL(STRCAST(str.c_str()), static_cast<int>(str.length()), 1); +} + +ZEND_FUNCTION(IcePHP_stringifyException) +{ + if(ZEND_NUM_ARGS() != 2) + { + WRONG_PARAM_COUNT; + } + + zval* v; + zval* t; + + if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("oo"), &v, &t) == FAILURE) + { + return; + } + + ExceptionInfoPtr ex = Wrapper<ExceptionInfoPtr>::value(t TSRMLS_CC); + assert(ex); + + ostringstream ostr; + IceUtilInternal::Output out(ostr); + ex->print(v, out TSRMLS_CC); + + string str = ostr.str(); + RETURN_STRINGL(STRCAST(str.c_str()), static_cast<int>(str.length()), 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 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 TSRMLS_DC) +{ + 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 TSRMLS_DC) +{ + *zv = *ICE_G(unset); + zval_copy_ctor(zv); +} + +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 TSRMLS_CC); + memcpy(&_typeInfoHandlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); + + // + // Register the IcePHP_ExceptionInfo class. + // + INIT_CLASS_ENTRY(ce, "IcePHP_ExceptionInfo", _exceptionInfoMethods); + ce.create_object = handleExceptionInfoAlloc; + exceptionInfoClassEntry = zend_register_internal_class(&ce TSRMLS_CC); + memcpy(&_exceptionInfoHandlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); + + 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(TSRMLS_D) +{ + // + // 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; + MAKE_STD_ZVAL(zv); + if(!createTypeInfo(zv, type TSRMLS_CC)) + { + zval_ptr_dtor(&zv); + return false; + } + string name = "IcePHP__t_" + type->getId(); + ZEND_SET_SYMBOL(&EG(symbol_table), const_cast<char*>(name.c_str()), zv); + } + + ICE_G(idToClassInfoMap) = 0; + ICE_G(nameToClassInfoMap) = 0; + ICE_G(proxyInfoMap) = 0; + ICE_G(exceptionInfoMap) = 0; + + zval* unset; + MAKE_STD_ZVAL(unset); + ZVAL_STRINGL(unset, STRCAST(_unsetGUID.c_str()), static_cast<int>(_unsetGUID.length()), 1); + ICE_G(unset) = unset; + + return true; +} + +bool +IcePHP::typesRequestShutdown(TSRMLS_D) +{ + 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_ptr_dtor(&ICE_G(unset)); + + return true; +} diff --git a/php/src/php5/Types.h b/php/src/php5/Types.h new file mode 100644 index 00000000000..7cc535e8b94 --- /dev/null +++ b/php/src/php5/Types.h @@ -0,0 +1,650 @@ +// ********************************************************************** +// +// 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 <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 +{ +}; + +class ClassInfo; +typedef IceUtil::Handle<ClassInfo> ClassInfoPtr; +typedef std::vector<ClassInfoPtr> ClassInfoList; + +typedef std::map<unsigned int, Ice::ObjectPtr> ObjectMap; + +class ObjectReader; +typedef IceUtil::Handle<ObjectReader> ObjectReaderPtr; + +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* TSRMLS_DC) = 0; +}; +typedef IceUtil::Handle<UnmarshalCallback> UnmarshalCallbackPtr; + +// +// ReadObjectCallback retains all of the information necessary to store an unmarshaled +// Slice value as a PHP object. +// +class ReadObjectCallback : public IceUtil::Shared +{ +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; +#if ZTS + TSRMLS_D; +#endif +}; +typedef IceUtil::Handle<ReadObjectCallback> ReadObjectCallbackPtr; + +// +// This class keeps track of PHP objects (instances of Slice classes +// and exceptions) that have preserved slices. +// +class StreamUtil +{ +public: + + ~StreamUtil(); + + // + // Keep a reference to a ReadObjectCallback for patching purposes. + // + void add(const ReadObjectCallbackPtr&); + + // + // Keep track of object instances that have preserved slices. + // + void add(const ObjectReaderPtr&); + + void updateSlicedData(TSRMLS_D); + + static void setSlicedDataMember(zval*, const Ice::SlicedDataPtr& TSRMLS_DC); + static Ice::SlicedDataPtr getSlicedDataMember(zval*, ObjectMap* TSRMLS_DC); + +private: + + std::vector<ReadObjectCallbackPtr> _callbacks; + std::set<ObjectReaderPtr> _readers; + static zend_class_entry* _slicedDataType; + static zend_class_entry* _sliceInfoType; +}; + +// +// Base class for type information. +// +class TypeInfo : public UnmarshalCallback +{ +public: + + virtual std::string getId() const = 0; + + virtual bool validate(zval* TSRMLS_DC) = 0; + + 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* TSRMLS_DC); // 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*, Ice::OutputStream*, ObjectMap*, bool TSRMLS_DC) = 0; + virtual void unmarshal(Ice::InputStream*, const UnmarshalCallbackPtr&, const CommunicatorInfoPtr&, + zval*, void*, bool TSRMLS_DC) = 0; + + virtual void print(zval*, IceUtilInternal::Output&, PrintObjectHistory* TSRMLS_DC) = 0; +}; +typedef IceUtil::Handle<TypeInfo> TypeInfoPtr; + +// +// Primitive type information. +// +class PrimitiveInfo : public TypeInfo +{ +public: + + virtual std::string getId() const; + + virtual bool validate(zval* TSRMLS_DC); + + virtual bool variableLength() const; + virtual int wireSize() const; + virtual Ice::OptionalFormat optionalFormat() const; + + virtual void marshal(zval*, Ice::OutputStream*, ObjectMap*, bool TSRMLS_DC); + virtual void unmarshal(Ice::InputStream*, const UnmarshalCallbackPtr&, const CommunicatorInfoPtr&, + zval*, void*, bool TSRMLS_DC); + + virtual void print(zval*, IceUtilInternal::Output&, PrintObjectHistory* TSRMLS_DC); + + 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* TSRMLS_DC); + + virtual std::string getId() const; + + virtual bool validate(zval* TSRMLS_DC); + + virtual bool variableLength() const; + virtual int wireSize() const; + virtual Ice::OptionalFormat optionalFormat() const; + + virtual void marshal(zval*, Ice::OutputStream*, ObjectMap*, bool TSRMLS_DC); + virtual void unmarshal(Ice::InputStream*, const UnmarshalCallbackPtr&, const CommunicatorInfoPtr&, + zval*, void*, bool TSRMLS_DC); + + virtual void print(zval*, IceUtilInternal::Output&, PrintObjectHistory* TSRMLS_DC); + + 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* TSRMLS_DC); + + void setMember(zval*, zval* TSRMLS_DC); + + 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* TSRMLS_DC); + + virtual std::string getId() const; + + virtual bool validate(zval* TSRMLS_DC); + + virtual bool variableLength() const; + virtual int wireSize() const; + virtual Ice::OptionalFormat optionalFormat() const; + + virtual bool usesClasses() const; + + virtual void marshal(zval*, Ice::OutputStream*, ObjectMap*, bool TSRMLS_DC); + virtual void unmarshal(Ice::InputStream*, const UnmarshalCallbackPtr&, const CommunicatorInfoPtr&, + zval*, void*, bool TSRMLS_DC); + + virtual void print(zval*, IceUtilInternal::Output&, PrintObjectHistory* TSRMLS_DC); + + 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* TSRMLS_DC); + + virtual std::string getId() const; + + virtual bool validate(zval* TSRMLS_DC); + + virtual bool variableLength() const; + virtual int wireSize() const; + virtual Ice::OptionalFormat optionalFormat() const; + + virtual bool usesClasses() const; + + virtual void marshal(zval*, Ice::OutputStream*, ObjectMap*, bool TSRMLS_DC); + virtual void unmarshal(Ice::InputStream*, const UnmarshalCallbackPtr&, const CommunicatorInfoPtr&, + zval*, void*, bool TSRMLS_DC); + + virtual void print(zval*, IceUtilInternal::Output&, PrintObjectHistory* TSRMLS_DC); + + virtual void unmarshaled(zval*, zval*, void* TSRMLS_DC); + + virtual void destroy(); + + const std::string id; + const TypeInfoPtr elementType; + +private: + + void marshalPrimitiveSequence(const PrimitiveInfoPtr&, zval*, Ice::OutputStream* TSRMLS_DC); + void unmarshalPrimitiveSequence(const PrimitiveInfoPtr&, Ice::InputStream*, const UnmarshalCallbackPtr&, + zval*, void* TSRMLS_DC); +}; +typedef IceUtil::Handle<SequenceInfo> SequenceInfoPtr; + +// +// Dictionary information. +// +class DictionaryInfo : public TypeInfo +{ +public: + + DictionaryInfo(const std::string&, zval*, zval* TSRMLS_DC); + + virtual std::string getId() const; + + virtual bool validate(zval* TSRMLS_DC); + + virtual bool variableLength() const; + virtual int wireSize() const; + virtual Ice::OptionalFormat optionalFormat() const; + + virtual bool usesClasses() const; + + virtual void marshal(zval*, Ice::OutputStream*, ObjectMap*, bool TSRMLS_DC); + virtual void unmarshal(Ice::InputStream*, const UnmarshalCallbackPtr&, const CommunicatorInfoPtr&, + zval*, void*, bool TSRMLS_DC); + + virtual void print(zval*, IceUtilInternal::Output&, PrintObjectHistory* TSRMLS_DC); + + virtual void destroy(); + + class KeyCallback : public UnmarshalCallback + { + public: + + KeyCallback(); + ~KeyCallback(); + + virtual void unmarshaled(zval*, zval*, void* TSRMLS_DC); + + zval* key; + }; + typedef IceUtil::Handle<KeyCallback> KeyCallbackPtr; + + class ValueCallback : public UnmarshalCallback + { + public: + + ValueCallback(zval* TSRMLS_DC); + ~ValueCallback(); + + virtual void unmarshaled(zval*, zval*, void* TSRMLS_DC); + + 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; + +typedef std::vector<TypeInfoPtr> TypeInfoList; + +class ClassInfo : public TypeInfo +{ +public: + + ClassInfo(const std::string& TSRMLS_DC); + + void define(const std::string&, Ice::Int, bool, bool, zval*, zval*, zval* TSRMLS_DC); + + virtual std::string getId() const; + + virtual bool validate(zval* TSRMLS_DC); + + virtual bool variableLength() const; + virtual int wireSize() const; + virtual Ice::OptionalFormat optionalFormat() const; + + virtual bool usesClasses() const; + + virtual void marshal(zval*, Ice::OutputStream*, ObjectMap*, bool TSRMLS_DC); + virtual void unmarshal(Ice::InputStream*, const UnmarshalCallbackPtr&, const CommunicatorInfoPtr&, + zval*, void*, bool TSRMLS_DC); + + virtual void print(zval*, IceUtilInternal::Output&, PrintObjectHistory* TSRMLS_DC); + + virtual void destroy(); + + void printMembers(zval*, IceUtilInternal::Output&, PrintObjectHistory* TSRMLS_DC); + + 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& TSRMLS_DC); + + void define(const ClassInfoPtr& TSRMLS_DC); + + virtual std::string getId() const; + + virtual bool validate(zval* TSRMLS_DC); + + virtual bool variableLength() const; + virtual int wireSize() const; + virtual Ice::OptionalFormat optionalFormat() const; + + virtual void marshal(zval*, Ice::OutputStream*, ObjectMap*, bool TSRMLS_DC); + virtual void unmarshal(Ice::InputStream*, const UnmarshalCallbackPtr&, const CommunicatorInfoPtr&, + zval*, void*, bool TSRMLS_DC); + + virtual void print(zval*, IceUtilInternal::Output&, PrintObjectHistory* TSRMLS_DC); + + 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(Ice::InputStream*, const CommunicatorInfoPtr& TSRMLS_DC); + + void print(zval*, IceUtilInternal::Output& TSRMLS_DC); + void printMembers(zval*, IceUtilInternal::Output&, PrintObjectHistory* TSRMLS_DC); + + 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& TSRMLS_DC); +ClassInfoPtr getClassInfoByName(const std::string& TSRMLS_DC); +ExceptionInfoPtr getExceptionInfo(const std::string& TSRMLS_DC); + +bool isUnset(zval* TSRMLS_DC); +void assignUnset(zval* TSRMLS_DC); + +bool typesInit(INIT_FUNC_ARGS); +bool typesRequestInit(TSRMLS_D); +bool typesRequestShutdown(TSRMLS_D); + +// +// ObjectWriter wraps a PHP object for marshaling. +// +class ObjectWriter : public Ice::Object +{ +public: + + ObjectWriter(zval*, ObjectMap*, const ClassInfoPtr& TSRMLS_DC); + ~ObjectWriter(); + + virtual void ice_preMarshal(); + + virtual void __write(Ice::OutputStream*) const; + virtual void __read(Ice::InputStream*); + +private: + + void writeMembers(Ice::OutputStream*, const DataMemberList&) const; + + zval* _object; + ObjectMap* _map; + ClassInfoPtr _info; +#if ZTS + TSRMLS_D; +#endif +}; + +// +// ObjectReader unmarshals the state of an Ice object. +// +class ObjectReader : public Ice::Object +{ +public: + + ObjectReader(zval*, const ClassInfoPtr&, const CommunicatorInfoPtr& TSRMLS_DC); + ~ObjectReader(); + + virtual void ice_postUnmarshal(); + + virtual void __write(Ice::OutputStream*) const; + virtual void __read(Ice::InputStream*); + + virtual ClassInfoPtr getInfo() const; + + zval* getObject() const; + + Ice::SlicedDataPtr getSlicedData() const; + +private: + + zval* _object; + ClassInfoPtr _info; + CommunicatorInfoPtr _communicator; + Ice::SlicedDataPtr _slicedData; +#if ZTS + TSRMLS_D; +#endif +}; + +// +// ExceptionReader creates a PHP user exception and unmarshals it. +// +class ExceptionReader : public Ice::UserException +{ +public: + + ExceptionReader(const CommunicatorInfoPtr&, const ExceptionInfoPtr& TSRMLS_DC); + ~ExceptionReader() throw(); + + virtual std::string ice_id() const; + virtual ExceptionReader* ice_clone() const; + virtual void ice_throw() const; + + virtual void __write(Ice::OutputStream*) const; + virtual void __read(Ice::InputStream*); + virtual bool __usesClasses() const; + + ExceptionInfoPtr getInfo() const; + + zval* getException() const; + + Ice::SlicedDataPtr getSlicedData() const; + + using Ice::UserException::__read; + using Ice::UserException::__write; + +protected: + + virtual void __writeImpl(Ice::OutputStream*) const {} + virtual void __readImpl(Ice::InputStream*) {} + +private: + + CommunicatorInfoPtr _communicatorInfo; + ExceptionInfoPtr _info; + zval* _ex; + Ice::SlicedDataPtr _slicedData; +#if ZTS + TSRMLS_D; +#endif +}; + +class IdResolver : public Ice::CompactIdResolver +{ +public: + + IdResolver(TSRMLS_D); + + virtual std::string resolve(Ice::Int) const; + +private: + +#if ZTS + TSRMLS_D; +#endif +}; + +} // End of namespace IcePHP + +#endif diff --git a/php/src/php5/Util.cpp b/php/src/php5/Util.cpp new file mode 100644 index 00000000000..0413faa4eb4 --- /dev/null +++ b/php/src/php5/Util.cpp @@ -0,0 +1,1034 @@ +// ********************************************************************** +// +// 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 TSRMLS_DC) +{ + *member = 0; + + void* data = 0; + if(zend_hash_find(Z_OBJPROP_P(zv), STRCAST(name.c_str()), name.size() + 1, &data) == FAILURE) + { + if(required) + { + invalidArgument("object does not contain member `%s'" TSRMLS_CC, name.c_str()); + return false; + } + } + + if(data) + { + zval** val = reinterpret_cast<zval**>(data); + + if(Z_TYPE_PP(val) != type) + { + string expected = zendTypeToString(type); + string actual = zendTypeToString(Z_TYPE_PP(val)); + invalidArgument("expected value of type %s for member `%s' but received %s" TSRMLS_CC, expected.c_str(), + name.c_str(), actual.c_str()); + return false; + } + + *member = *val; + } + + return true; +} + +void +setStringMember(zval* obj, const string& name, const string& val TSRMLS_DC) +{ + 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()) TSRMLS_CC); +} + +template<typename T> +bool +getVersion(zval* zv, T& v, const char* type TSRMLS_DC) +{ + if(Z_TYPE_P(zv) != IS_OBJECT) + { + invalidArgument("value does not contain an object" TSRMLS_CC); + return false; + } + + zend_class_entry* cls = idToClass(type TSRMLS_CC); + assert(cls); + + zend_class_entry* ce = Z_OBJCE_P(zv); + if(ce != cls) + { + invalidArgument("expected an instance of %s" TSRMLS_CC, ce->name); + return false; + } + + zval* majorVal; + if(!getMember(zv, "major", &majorVal, IS_LONG, true TSRMLS_CC)) + { + return false; + } + + zval* minorVal; + if(!getMember(zv, "minor", &minorVal, IS_LONG, true TSRMLS_CC)) + { + return false; + } + + long m; + m = Z_LVAL_P(majorVal); + if(m < 0 || m > 255) + { + invalidArgument("version major must be a value between 0 and 255" TSRMLS_CC); + return false; + } + v.major = static_cast<Ice::Byte>(m); + + m = Z_LVAL_P(minorVal); + if(m < 0 || m > 255) + { + invalidArgument("version minor must be a value between 0 and 255" TSRMLS_CC); + return false; + } + v.minor = static_cast<Ice::Byte>(m); + + return true; +} + +template<typename T> +bool +createVersion(zval* zv, const T& version, const char* type TSRMLS_DC) +{ + zend_class_entry* cls = idToClass(type TSRMLS_CC); + assert(cls); + + if(object_init_ex(zv, cls) != SUCCESS) + { + runtimeError("unable to initialize %s" TSRMLS_CC, cls->name); + return false; + } + + zend_update_property_long(cls, zv, const_cast<char*>("major"), sizeof("major") - 1, version.major TSRMLS_CC); + zend_update_property_long(cls, zv, const_cast<char*>("minor"), sizeof("minor") - 1, version.minor TSRMLS_CC); + + return true; +} + +template<typename T> +bool +versionToString(zval* zv, zval* s, const char* type TSRMLS_DC) +{ + T v; + if(!getVersion<T>(zv, v, type TSRMLS_CC)) + { + return false; + } + + try + { + string str = IceInternal::versionToString<T>(v); + ZVAL_STRINGL(s, STRCAST(str.c_str()), static_cast<int>(str.length()), 1); + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + return false; + } + + return true; +} + +template<typename T> +bool +stringToVersion(const string& s, zval* zv, const char* type TSRMLS_DC) +{ + try + { + T v = IceInternal::stringToVersion<T>(s); + return createVersion<T>(zv, v, type TSRMLS_CC); + } + catch(const IceUtil::Exception& ex) + { + throwException(ex TSRMLS_CC); + } + + return false; +} + +char Ice_ProtocolVersion[] = "::Ice::ProtocolVersion"; +char Ice_EncodingVersion[] = "::Ice::EncodingVersion"; + +} + +#if PHP_VERSION_ID < 50400 +#ifdef _WIN32 +extern "C" +#endif +static void +dtor_wrapper(void* p) +{ + zval_ptr_dtor(static_cast<zval**>(p)); +} +#endif + +void* +IcePHP::createWrapper(zend_class_entry* ce, size_t sz TSRMLS_DC) +{ + zend_object* obj; + + obj = static_cast<zend_object*>(emalloc(sz)); + + zend_object_std_init(obj, ce TSRMLS_CC); + +#if PHP_VERSION_ID < 50400 + zval* tmp; + obj->properties = static_cast<HashTable*>(emalloc(sizeof(HashTable))); + zend_hash_init(obj->properties, 0, 0, dtor_wrapper, 0); + zend_hash_copy(obj->properties, &ce->default_properties, (copy_ctor_func_t)zval_add_ref, &tmp, sizeof(zval*)); +#else + object_properties_init(obj, ce); +#endif + + return obj; +} + +void* +IcePHP::extractWrapper(zval* zv TSRMLS_DC) +{ + if(!zv) + { + runtimeError("method %s() must be invoked on an object" TSRMLS_CC, get_active_function_name(TSRMLS_C)); + return 0; + } + + zend_object* obj = static_cast<zend_object*>(zend_object_store_get_object(zv TSRMLS_CC)); + if(!obj) + { + runtimeError("no object found in %s()" TSRMLS_CC, get_active_function_name(TSRMLS_C)); + return 0; + } + + return obj; +} + +zend_class_entry* +IcePHP::idToClass(const string& id TSRMLS_DC) +{ +#ifdef ICEPHP_USE_NAMESPACES + string cls = scopedToName(id, true); +#else + string cls = scopedToName(id, false); +#endif + + return nameToClass(cls TSRMLS_CC); +} + +zend_class_entry* +IcePHP::nameToClass(const string& name TSRMLS_DC) +{ + zend_class_entry** result; + if(zend_lookup_class(STRCAST(name.c_str()), static_cast<int>(name.length()), &result TSRMLS_CC) == FAILURE) + { + return 0; + } + return *result; +} + +bool +IcePHP::createIdentity(zval* zv, const Ice::Identity& id TSRMLS_DC) +{ + zend_class_entry* cls = idToClass("::Ice::Identity" TSRMLS_CC); + assert(cls); + + if(object_init_ex(zv, cls) != SUCCESS) + { + runtimeError("unable to initialize Ice::Identity" TSRMLS_CC); + return false; + } + + setStringMember(zv, "name", id.name TSRMLS_CC); + setStringMember(zv, "category", id.category TSRMLS_CC); + + return true; +} + +bool +IcePHP::extractIdentity(zval* zv, Ice::Identity& id TSRMLS_DC) +{ + if(Z_TYPE_P(zv) != IS_OBJECT) + { + invalidArgument("value does not contain an object" TSRMLS_CC); + return false; + } + + zend_class_entry* cls = idToClass("::Ice::Identity" TSRMLS_CC); + assert(cls); + + zend_class_entry* ce = Z_OBJCE_P(zv); + if(ce != cls) + { + invalidArgument("expected an identity but received %s" TSRMLS_CC, ce->name); + return false; + } + + // + // Category is optional, but name is required. + // + zval* categoryVal; + zval* nameVal; + + if(!getMember(zv, "category", &categoryVal, IS_STRING, false TSRMLS_CC) || + !getMember(zv, "name", &nameVal, IS_STRING, true TSRMLS_CC)) + { + return false; + } + + id.name = Z_STRVAL_P(nameVal); + if(categoryVal) + { + id.category = Z_STRVAL_P(categoryVal); + } + else + { + id.category = ""; + } + + return true; +} + +bool +IcePHP::createStringMap(zval* zv, const map<string, string>& ctx TSRMLS_DC) +{ + 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()), p->first.length() + 1, + const_cast<char*>(p->second.c_str()), + static_cast<uint>(p->second.length()), 1) == FAILURE) + { + return false; + } + } + + return true; +} + +bool +IcePHP::extractStringMap(zval* zv, map<string, string>& ctx TSRMLS_DC) +{ + if(Z_TYPE_P(zv) != IS_ARRAY) + { + string s = zendTypeToString(Z_TYPE_P(zv)); + invalidArgument("expected an associative array but received %s" TSRMLS_CC, s.c_str()); + return false; + } + + HashTable* arr = Z_ARRVAL_P(zv); + void* data; + HashPosition pos; + + zend_hash_internal_pointer_reset_ex(arr, &pos); + while(zend_hash_get_current_data_ex(arr, &data, &pos) != FAILURE) + { + zval** val = reinterpret_cast<zval**>(data); + + // + // Get the key (which can be a long or a string). + // + char* keyStr; + uint keyLen; + ulong keyNum; + int keyType = zend_hash_get_current_key_ex(arr, &keyStr, &keyLen, &keyNum, 0, &pos); + + // + // Store the key in a zval, so that we can reuse the PrimitiveMarshaler logic. + // + if(keyType != HASH_KEY_IS_STRING) + { + invalidArgument("array key must be a string" TSRMLS_CC); + return false; + } + + if(Z_TYPE_PP(val) != IS_STRING) + { + invalidArgument("array value must be a string" TSRMLS_CC); + return false; + } + + ctx[keyStr] = Z_STRVAL_PP(val); + + zend_hash_move_forward_ex(arr, &pos); + } + + return true; +} + +bool +IcePHP::createStringArray(zval* zv, const Ice::StringSeq& seq TSRMLS_DC) +{ + 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()), 1) == FAILURE) + { + return false; + } + } + + return true; +} + +bool +IcePHP::extractStringArray(zval* zv, Ice::StringSeq& seq TSRMLS_DC) +{ + if(Z_TYPE_P(zv) != IS_ARRAY) + { + string s = zendTypeToString(Z_TYPE_P(zv)); + invalidArgument("expected an array of strings but received %s" TSRMLS_CC, s.c_str()); + return false; + } + + HashTable* arr = Z_ARRVAL_P(zv); + void* data; + HashPosition pos; + + zend_hash_internal_pointer_reset_ex(arr, &pos); + while(zend_hash_get_current_data_ex(arr, &data, &pos) != FAILURE) + { + zval** val = reinterpret_cast<zval**>(data); + + if(Z_TYPE_PP(val) != IS_STRING) + { + invalidArgument("array element must be a string" TSRMLS_CC); + return false; + } + + string s(Z_STRVAL_PP(val), Z_STRLEN_PP(val)); + seq.push_back(s); + + zend_hash_move_forward_ex(arr, &pos); + } + + return true; +} + +bool +IcePHP::createProtocolVersion(zval* zv, const Ice::ProtocolVersion& v TSRMLS_DC) +{ + return createVersion<Ice::ProtocolVersion>(zv, v, Ice_ProtocolVersion TSRMLS_CC); +} + +bool +IcePHP::createEncodingVersion(zval* zv, const Ice::EncodingVersion& v TSRMLS_DC) +{ + return createVersion<Ice::EncodingVersion>(zv, v, Ice_EncodingVersion TSRMLS_CC); +} + +bool +IcePHP::extractEncodingVersion(zval* zv, Ice::EncodingVersion& v TSRMLS_DC) +{ + return getVersion<Ice::EncodingVersion>(zv, v, Ice_EncodingVersion TSRMLS_CC); +} + +static bool +convertLocalException(const Ice::LocalException& ex, zval* zex TSRMLS_DC) +{ + 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 TSRMLS_CC); + } + catch(const Ice::PluginInitializationException& e) + { + setStringMember(zex, "reason", e.reason TSRMLS_CC); + } + catch(const Ice::AlreadyRegisteredException& e) + { + setStringMember(zex, "kindOfObject", e.kindOfObject TSRMLS_CC); + setStringMember(zex, "id", e.id TSRMLS_CC); + } + catch(const Ice::NotRegisteredException& e) + { + setStringMember(zex, "kindOfObject", e.kindOfObject TSRMLS_CC); + setStringMember(zex, "id", e.id TSRMLS_CC); + } + catch(const Ice::TwowayOnlyException& e) + { + setStringMember(zex, "operation", e.operation TSRMLS_CC); + } + catch(const Ice::UnknownException& e) + { + setStringMember(zex, "unknown", e.unknown TSRMLS_CC); + } + catch(const Ice::ObjectAdapterDeactivatedException& e) + { + setStringMember(zex, "name", e.name TSRMLS_CC); + } + catch(const Ice::ObjectAdapterIdInUseException& e) + { + setStringMember(zex, "id", e.id TSRMLS_CC); + } + catch(const Ice::NoEndpointException& e) + { + setStringMember(zex, "proxy", e.proxy TSRMLS_CC); + } + catch(const Ice::EndpointParseException& e) + { + setStringMember(zex, "str", e.str TSRMLS_CC); + } + catch(const Ice::IdentityParseException& e) + { + setStringMember(zex, "str", e.str TSRMLS_CC); + } + catch(const Ice::ProxyParseException& e) + { + setStringMember(zex, "str", e.str TSRMLS_CC); + } + catch(const Ice::IllegalIdentityException& e) + { + zval* id; + MAKE_STD_ZVAL(id); + if(!createIdentity(id, e.id TSRMLS_CC)) + { + zval_ptr_dtor(&id); + return false; + } + zend_update_property(cls, zex, const_cast<char*>("id"), sizeof("id") - 1, id TSRMLS_CC); + zval_ptr_dtor(&id); + } + catch(const Ice::RequestFailedException& e) + { + zval* id; + MAKE_STD_ZVAL(id); + if(!createIdentity(id, e.id TSRMLS_CC)) + { + zval_ptr_dtor(&id); + return false; + } + zend_update_property(cls, zex, const_cast<char*>("id"), sizeof("id") - 1, id TSRMLS_CC); + zval_ptr_dtor(&id); + setStringMember(zex, "facet", e.facet TSRMLS_CC); + setStringMember(zex, "operation", e.operation TSRMLS_CC); + } + catch(const Ice::FileException& e) + { + zend_update_property_long(cls, zex, const_cast<char*>("error"), sizeof("error") - 1, e.error TSRMLS_CC); + setStringMember(zex, "path", e.path TSRMLS_CC); + } + 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 TSRMLS_CC); + } + catch(const Ice::DNSException& e) + { + zend_update_property_long(cls, zex, const_cast<char*>("error"), sizeof("error") - 1, e.error TSRMLS_CC); + setStringMember(zex, "host", e.host TSRMLS_CC); + } + catch(const Ice::UnsupportedProtocolException& e) + { + zval* v; + MAKE_STD_ZVAL(v); + if(!createProtocolVersion(v, e.bad TSRMLS_CC)) + { + zval_ptr_dtor(&v); + return false; + } + zend_update_property(cls, zex, const_cast<char*>("bad"), sizeof("bad") - 1, v TSRMLS_CC); + zval_ptr_dtor(&v); + + MAKE_STD_ZVAL(v); + if(!createProtocolVersion(v, e.supported TSRMLS_CC)) + { + zval_ptr_dtor(&v); + return false; + } + zend_update_property(cls, zex, const_cast<char*>("supported"), sizeof("supported") - 1, v TSRMLS_CC); + zval_ptr_dtor(&v); + } + catch(const Ice::UnsupportedEncodingException& e) + { + zval* v; + MAKE_STD_ZVAL(v); + if(!createEncodingVersion(v, e.bad TSRMLS_CC)) + { + zval_ptr_dtor(&v); + return false; + } + zend_update_property(cls, zex, const_cast<char*>("bad"), sizeof("bad") - 1, v TSRMLS_CC); + zval_ptr_dtor(&v); + + MAKE_STD_ZVAL(v); + if(!createEncodingVersion(v, e.supported TSRMLS_CC)) + { + zval_ptr_dtor(&v); + return false; + } + zend_update_property(cls, zex, const_cast<char*>("supported"), sizeof("supported") - 1, v TSRMLS_CC); + zval_ptr_dtor(&v); + } + catch(const Ice::NoValueFactoryException& e) + { + setStringMember(zex, "reason", e.reason TSRMLS_CC); + setStringMember(zex, "type", e.type TSRMLS_CC); + } + catch(const Ice::UnexpectedObjectException& e) + { + setStringMember(zex, "reason", e.reason TSRMLS_CC); + setStringMember(zex, "type", e.type TSRMLS_CC); + setStringMember(zex, "expectedType", e.expectedType TSRMLS_CC); + } + catch(const Ice::ProtocolException& e) // This must appear after all subclasses of ProtocolException. + { + setStringMember(zex, "reason", e.reason TSRMLS_CC); + } + catch(const Ice::FeatureNotSupportedException& e) + { + setStringMember(zex, "unsupportedFeature", e.unsupportedFeature TSRMLS_CC); + } + catch(const Ice::SecurityException& e) + { + setStringMember(zex, "reason", e.reason TSRMLS_CC); + } + catch(const Ice::LocalException&) + { + // + // Nothing to do. + // + } + + return true; +} + +zval* +IcePHP::convertException(const Ice::Exception& ex TSRMLS_DC) +{ + zval* zex; + MAKE_STD_ZVAL(zex); + AutoDestroy destroy(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_id() TSRMLS_CC); + if(cls) + { + if(object_init_ex(zex, cls) != SUCCESS) + { + runtimeError("unable to create exception %s" TSRMLS_CC, cls->name); + return 0; + } + if(!convertLocalException(e, zex TSRMLS_CC)) + { + return 0; + } + } + else + { + cls = idToClass("Ice::UnknownLocalException" TSRMLS_CC); + assert(cls); + if(object_init_ex(zex, cls) != SUCCESS) + { + runtimeError("unable to create exception %s" TSRMLS_CC, cls->name); + return 0; + } + setStringMember(zex, "unknown", str TSRMLS_CC); + } + } + catch(const Ice::UserException&) + { + zend_class_entry* cls = idToClass("Ice::UnknownUserException" TSRMLS_CC); + assert(cls); + if(object_init_ex(zex, cls) != SUCCESS) + { + runtimeError("unable to create exception %s" TSRMLS_CC, cls->name); + return 0; + } + setStringMember(zex, "unknown", str TSRMLS_CC); + } + catch(const Ice::Exception&) + { + zend_class_entry* cls = idToClass("Ice::UnknownException" TSRMLS_CC); + assert(cls); + if(object_init_ex(zex, cls) != SUCCESS) + { + runtimeError("unable to create exception %s" TSRMLS_CC, cls->name); + return 0; + } + setStringMember(zex, "unknown", str TSRMLS_CC); + } + + return destroy.release(); +} + +void +IcePHP::throwException(const Ice::Exception& ex TSRMLS_DC) +{ + zval* zex = convertException(ex TSRMLS_CC); + if(zex) + { + zend_throw_exception_object(zex TSRMLS_CC); + } +} + +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_BOOL: + result = "bool"; + break; + + default: + result = "unknown"; + break; + } + + return result; +} + +static void +throwError(const string& name, const string& msg TSRMLS_DC) +{ + zval* ex; + MAKE_STD_ZVAL(ex); + AutoDestroy destroy(ex); + + zend_class_entry* cls; + { + zend_class_entry** p; + if(zend_lookup_class(STRCAST(name.c_str()), static_cast<int>(name.size()), &p TSRMLS_CC) == FAILURE) + { + assert(false); + } + cls = *p; + } + if(object_init_ex(ex, cls) == FAILURE) + { + assert(false); + } + + // + // Invoke constructor. + // + if(!invokeMethod(ex, ZEND_CONSTRUCTOR_FUNC_NAME, msg TSRMLS_CC)) + { + assert(false); + } + + zend_throw_exception_object(ex TSRMLS_CC); + destroy.release(); +} + +void +IcePHP::runtimeError(const char* fmt TSRMLS_DC, ...) +{ + va_list args; + char msg[1024]; + +#if ZTS + va_start(args, TSRMLS_C); +#else + va_start(args, fmt); +#endif + +#if defined(_MSC_VER) + vsprintf_s(msg, fmt, args); +#else + vsprintf(msg, fmt, args); +#endif + + va_end(args); + + throwError("RuntimeException", msg TSRMLS_CC); +} + +void +IcePHP::invalidArgument(const char* fmt TSRMLS_DC, ...) +{ + va_list args; + char msg[1024]; + +#if ZTS + va_start(args, TSRMLS_C); +#else + va_start(args, fmt); +#endif + +#if defined(_MSC_VER) + vsprintf_s(msg, fmt, args); +#else + vsprintf(msg, fmt, args); +#endif + + va_end(args); + + throwError("InvalidArgumentException", msg TSRMLS_CC); +} + +static bool +invokeMethodHelper(zval* obj, const string& name, zval* param TSRMLS_DC) +{ + assert(zend_hash_exists(&Z_OBJCE_P(obj)->function_table, STRCAST(name.c_str()), name.size() + 1)); + zval ret, method; + INIT_ZVAL(ret); + INIT_ZVAL(method); + ZVAL_STRING(&method, STRCAST(name.c_str()), 1); + zend_uint numParams = param ? 1 : 0; + zval** params = param ? ¶m : 0; + int status = 0; + zend_try + { + status = call_user_function(0, &obj, &method, &ret, numParams, params TSRMLS_CC); + } + 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 TSRMLS_DC) +{ + return invokeMethodHelper(obj, name, 0 TSRMLS_CC); +} + +bool +IcePHP::invokeMethod(zval* obj, const string& name, const string& arg TSRMLS_DC) +{ + zval* param; + MAKE_STD_ZVAL(param); + ZVAL_STRINGL(param, STRCAST(arg.c_str()), static_cast<int>(arg.size()), 1); + AutoDestroy destroy(param); + return invokeMethodHelper(obj, name, param TSRMLS_CC); +} + +bool +IcePHP::checkClass(zend_class_entry* ce, zend_class_entry* base) +{ + while(ce) + { + if(ce == base) + { + return true; + } + + for(zend_uint 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)), 1); +} + +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()), 1); +} + +ZEND_FUNCTION(Ice_currentProtocol) +{ + if(ZEND_NUM_ARGS() > 0) + { + WRONG_PARAM_COUNT; + } + + if(!createProtocolVersion(return_value, Ice::currentProtocol TSRMLS_CC)) + { + RETURN_NULL(); + } +} + +ZEND_FUNCTION(Ice_currentProtocolEncoding) +{ + if(ZEND_NUM_ARGS() > 0) + { + WRONG_PARAM_COUNT; + } + + if(!createEncodingVersion(return_value, Ice::currentProtocolEncoding TSRMLS_CC)) + { + RETURN_NULL(); + } +} + +ZEND_FUNCTION(Ice_currentEncoding) +{ + if(ZEND_NUM_ARGS() > 0) + { + WRONG_PARAM_COUNT; + } + + if(!createEncodingVersion(return_value, Ice::currentEncoding TSRMLS_CC)) + { + RETURN_NULL(); + } +} + +ZEND_FUNCTION(Ice_protocolVersionToString) +{ + zend_class_entry* versionClass = idToClass(Ice_ProtocolVersion TSRMLS_CC); + assert(versionClass); + + zval* zv; + if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("O"), &zv, versionClass) != SUCCESS) + { + RETURN_NULL(); + } + + if(!versionToString<Ice::ProtocolVersion>(zv, return_value, Ice_ProtocolVersion TSRMLS_CC)) + { + RETURN_NULL(); + } +} + +ZEND_FUNCTION(Ice_stringToProtocolVersion) +{ + char* str; + int strLen; + if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("s"), &str, &strLen) != SUCCESS) + { + RETURN_NULL(); + } + string s(str, strLen); + + if(!stringToVersion<Ice::ProtocolVersion>(s, return_value, Ice_ProtocolVersion TSRMLS_CC)) + { + RETURN_NULL(); + } +} + +ZEND_FUNCTION(Ice_encodingVersionToString) +{ + zend_class_entry* versionClass = idToClass(Ice_EncodingVersion TSRMLS_CC); + assert(versionClass); + + zval* zv; + if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("O"), &zv, versionClass) != SUCCESS) + { + RETURN_NULL(); + } + + if(!versionToString<Ice::EncodingVersion>(zv, return_value, Ice_EncodingVersion TSRMLS_CC)) + { + RETURN_NULL(); + } +} + +ZEND_FUNCTION(Ice_stringToEncodingVersion) +{ + char* str; + int strLen; + if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("s"), &str, &strLen) != SUCCESS) + { + RETURN_NULL(); + } + string s(str, strLen); + + if(!stringToVersion<Ice::EncodingVersion>(s, return_value, Ice_EncodingVersion TSRMLS_CC)) + { + RETURN_NULL(); + } +} diff --git a/php/src/php5/Util.h b/php/src/php5/Util.h new file mode 100644 index 00000000000..35b2b025c22 --- /dev/null +++ b/php/src/php5/Util.h @@ -0,0 +1,167 @@ +// ********************************************************************** +// +// 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 TSRMLS_DC); +void* extractWrapper(zval* TSRMLS_DC); + +// +// Wraps a C++ pointer inside a PHP object. +// +template<typename T> +struct Wrapper +{ + zend_object zobj; + T* ptr; + + static Wrapper<T>* create(zend_class_entry* ce TSRMLS_DC) + { + Wrapper<T>* w = static_cast<Wrapper<T>*>(createWrapper(ce, sizeof(Wrapper<T>) TSRMLS_CC)); + w->ptr = 0; + return w; + } + + static Wrapper<T>* extract(zval* zv TSRMLS_DC) + { + return static_cast<Wrapper<T>*>(extractWrapper(zv TSRMLS_CC)); + } + + static T value(zval* zv TSRMLS_DC) + { + Wrapper<T>* w = extract(zv TSRMLS_CC); + if(w) + { + return *w->ptr; + } + return 0; + } +}; + +zend_class_entry* idToClass(const std::string& TSRMLS_DC); +zend_class_entry* nameToClass(const std::string& TSRMLS_DC); + +bool createIdentity(zval*, const Ice::Identity& TSRMLS_DC); +bool extractIdentity(zval*, Ice::Identity& TSRMLS_DC); + +bool createStringMap(zval*, const std::map<std::string, std::string>& TSRMLS_DC); +bool extractStringMap(zval*, std::map<std::string, std::string>& TSRMLS_DC); + +bool createStringArray(zval*, const Ice::StringSeq& TSRMLS_DC); +bool extractStringArray(zval*, Ice::StringSeq& TSRMLS_DC); + +// +// Create a PHP instance of Ice_ProtocolVersion. +// +bool createProtocolVersion(zval*, const Ice::ProtocolVersion& TSRMLS_DC); + +// +// Create a PHP instance of Ice_EncodingVersion. +// +bool createEncodingVersion(zval*, const Ice::EncodingVersion& TSRMLS_DC); + +// +// Extracts the members of an encoding version. +// +bool extractEncodingVersion(zval*, Ice::EncodingVersion& TSRMLS_DC); + +// +// Convert the given exception into its PHP equivalent. +// +zval* convertException(const Ice::Exception& TSRMLS_DC); + +// +// Convert the exception and "throw" it. +// +void throwException(const Ice::Exception& TSRMLS_DC); + +// +// 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* TSRMLS_DC, ...); + +// +// Raise InvalidArgumentException with the given message. +// +void invalidArgument(const char* TSRMLS_DC, ...); + +// +// Invoke a method on a PHP object. The method must not take any arguments. +// +bool invokeMethod(zval*, const std::string& TSRMLS_DC); + +// +// Invoke a method on a PHP object. The method must take one string argument. +// +bool invokeMethod(zval*, const std::string&, const std::string& TSRMLS_DC); + +// +// 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; +}; + +} // End of namespace IcePHP + +#endif |