diff --git a/composer.json b/composer.json index 16562b0..c2fdfdc 100644 --- a/composer.json +++ b/composer.json @@ -10,17 +10,14 @@ ], "minimum-stability": "stable", "require": { - "guzzlehttp/guzzle": "^6.2" + "guzzlehttp/guzzle": "^6.2", + "deviservi/nusoap": "^1.1" }, "require-dev": { "phpunit/phpunit": "5.3.*", "satooshi/php-coveralls": "^1.0" - }, "autoload": { - "classmap": [ - "src/Drivers/lib/nusoap.php" - ], "psr-4": { "Zarinpal\\": "src/" } diff --git a/src/Drivers/lib/changelog b/src/Drivers/lib/changelog deleted file mode 100644 index b76580e..0000000 --- a/src/Drivers/lib/changelog +++ /dev/null @@ -1,648 +0,0 @@ -2003-07-21, version 0.6.5 -- soap_transport_http: SOAPAction header is quoted again, fixes problem w/ Weblogic Server -- applied Jason Levitt patch for proper array serialization, fixes problem w/ Amazon shopping cart services -- fixed null value serialization -- applied patch from "BZC ToOn'S" - fixes wsdl serialization when no parameters -- applied John's patch, implementing compression for the server - -2003-07-22, version 0.6.5 -- soap_server: fixed bug causing charset encoding not to be passed to the parser -- soap_fault: added default encoding to the fault serialization -- soap_parser: changed the parser to pre-load the parent's result array when processing scalar values. This increases parsing speed. - -2003-07-23, version 0.6.5 -- soap_base: fix code that overwrites user-supplied attributes in serialize_val -- soap_base: use arrays-of-arrays rather than attempting multi-dimensional in serialize_val -- xmlschema: emit import statements and qualify all elements with prefix in serializeSchema (better interop with validation tools) -- soapclient: get xml character encoding from HTTP Content-Type header if provided, e.g. text/xml;charset="UTF-8" -- soapclient: use headers in call if provided (previously ignored this parameter) -- soap_server: in parse_request, if neither getallheaders nor $_SERVER are available, use $HTTP_SERVER_VARS to get SOAPAction and xml encoding - -2003-07-24, version 0.6.5 -- soap_transport_http: apply patch from Steven Brown "if the server closes connection prematurely, nusoap would spin trying to read data that isn't there" - -2003-07-25, version 0.6.5 -- wsdl: apply patch from Sven to workaround single schema limitation -- wsdl: apply a variant of the patch from Holger to handle empty values for array by serializing an array with 0 elements -- xmlschema: remove the redundant default namespace attribute on the schema element; everything in xsd is explicitly specified as being from xsd -- soap_transport_http: fix setCredentials and add TODO comments in sendHTTPS about what to change if this setCredentials stays - -2003-07-30, version 0.6.5 -- nusoap_base: change documentation of soap_defencoding to specify it is the encoding for outgoing messages -- nusoap_base: only change &, <, > to entities, not all HTML entities -- soap_transport_http: update the Content-Type header in sendRequest, since soap_defencoding could be changed after ctor is called -- soap_server: use soap_defencoding instead of charset_encoding -- soap_server: read encoding from _SERVER if available -- nusoap_base: do entity translation for string parameters with an xsd type specified (thanks David Derr) - -2003-07-31, version 0.6.5 -- soap_transport_http: add proxy authentication -- soap_transport_http: build payload the same way for http and https -- wsdl: add proxy authentication -- soapclient: add proxy authentication -- soapclient: allow proxy information in ctor, so that it can be used for wsdl - -2003-08-01, version 0.6.5 -- soap_transport_http: close a persistent connection that's at EOF -- soap_transport_http: prevent conflicts between setEncoding and usePersistentConnection -- soap_transport_http: fix use of $headers instead of $this->incoming_headers in getResponse -- soapclient: improve handling of persistent connections -- soapclient: force xml_encoding to upper case -- soap_server: let the Web server decide whether to close the connection (no Connection: close header) -- soap_server: force xml_encoding to upper case - -2003-08-04, version 0.6.5 -- soap_parser: use XML type information to pick a PHP data type; also decode base64 -- soap_server: read all HTTP headers when using _SERVER or HTTP_SERVER_VARS -- soap_server: add gzip encoding support for outgoing messages -- soap_transport_http: deflate is gzcompress/gzuncompress (cf. http://archive.develooper.com/libwww@perl.org/msg04650.html) -- soap_transport_http: clean use of persistentConnection so it's always a set boolean -- soapclient: add responseData member to access deflated/gunzipped payload - -2003-08-05, version 0.6.5 -- soap_server: look multiple places when setting debug_flag - -2003-08-07, version 0.6.5 -- nusoap_base: serialize specified type (e.g. ArrayOfString) even for simple array -- wsdl: only specify encodingStyle in the input/output soap bindings when it is not empty (thanks Guillaume) - -2003-08-15, version 0.6.5 -- soap_parser: fix parsing of elements with no XSD type specified -- soap_parser: use PHP string type for XSD long and unsignedLong types - -2003-08-16, version 0.6.5 -- soap_parser: fix code generating warning (thanks Torsten) - -2003-08-19, version 0.6.5 -- soap_parser: fix another line of code generating a warning (thanks Torsten) - -2003-08-22, version 0.6.5 -- soap_server: remove all '--' from debug_str; previous code changed '---' to '- --' -- wsdl, soapclient, soap_parser: patch submitted by Mark Spavin as described by - the following... -> Changes for the multiple/nested imports from the wsdl file. This builds an -> array of files not just the last one and also checks for relative paths to -> the parent. This will then get the imported files from the remote site -> instead of your local disk. Local wsdl files should still work (untested). -> -> Changes for multiple encoding sytles as previously posted - -2003-08-24, version 0.6.5 -- wsdl, soapclient: fix some PHP notices from previous update - -2003-08-26, version 0.6.5 -- wsdl: support multiple SOAP ports -- soapclient, soap_server: when no charset is specified, use UTF-8, even though HTTP specifies US-ASCII. -- soap_transport_http: do not prepend $host with 'ssl://' for https (is this required for older cURL versions?) - -2003-08-27, version 0.6.5 -- soap_server: support compressed request messages (thanks John Huong) -- soap_parser: deserialize Apache Vector as an array -- xmlschema: use $this->typemap in getPHPType (which is not used) -- soapclient, wsdl: check for WSDL errors after serializing parameters -- nusoap_base: add serialization of Apache Map (when not using WSDL) -- wsdl: add serialization of Apache Map (when using WSDL) -- wsdl: only change &, <, > to entities, not all HTML entities - -2003-08-28, version 0.6.5 -- soap_transport_http: disable cURL verification of peer and server (formerly the cURL default) -- soap_transport_http: mingle cURL code with straight http, so sendHTTP is no longer needed - -2003-08-29, version 0.6.6 -- soap_transport_http: add setContentType -- soapclient: call setContentType using new getHTTPContentType and getHTTPContentTypeCharset - -2003-09-05, version 0.6.6 -- wsdl: add some more code to handle null/nil values (but there's still a way to go) - -2003-10-21, version 0.6.6 -- soap_transport_http: only include port in Host header if it was specified in the URL -- soap_transport_http: add some code to use OpenSSL for PHP ssl:// scheme, but comment out since it's not ready -- soap_server: use $_SERVER['PHP_SELF'] if $GLOBALS['PHP_SELF'] is not set -- wsdl: add WSDL request and response and transport debug to debug -- wsdl: handle custom type extending xmlschema namespace (GLUE ... Thanks Matt) -- soap_parser: add param to docs -- soapclient: add getHTTPBody, getHTTPContentType, getHTTPContentTypeCharset (anticipating MIME subclass) - -2003-10-28, version 0.6.6 -- nusoap_base: add expandEntities method -- wsdl: use expandEntities -- soap_fault: use expandEntities -- soap_transport_http: Allow credentials to be included in URL, rather than requiring setCredentials -- soap_transport_http: Merge HTTP headers that span multiple lines -- soap_parser: Properly set errors in ctor -- soapclient: Pass headers to parseResponse and parse them in that method - -2003-10-30, version 0.6.6 -- xmlschema: Add some information for the related type to an element - -2003-12-09, version 0.6.6 -- nusoap_base: Add some namespace methods previously in xmlschema -- xmlschema: Improve parsing of complexType, element and simpleType -- xmlschema: Improve serialization -- xmlschema: Track imports -- xmlschema: Track elementFormDefault and form attributes -- wsdl: Support multiple (note that setting $server->wsdl->schemaTargetNamespace no longer does anything! Use configureWSDL instead.) -- wsdl: Use form attribute of element to control namespace specification -- wsdl: Support chained imports (A imports B which imports C) -- wsdl: Include port in endpoint address when serializing -- soap_server: Fix use of style (rpc|document) and use (encoded|literal) -- soap_server: Support _SERVER[CONTENT_TYPE] in addition to _SERVER[HTTP_CONTENT_TYPE] -- soap_server: Support wsdl with multiple -- soap_client: Remove a var_dump -- soap_client: Add style and use parameters to call method to support doc/lit without WSDL -- soap_transport_http: Check that $this->fp exists when doing persistent connections - -2003-12-17, version 0.6.6 -- soap_server: pass namespaces to xmlschema constructor -- wsdl: post-process after all imports -- wsdl: remove some debug, add some error handling -- xmlschema: allow enclosing namespaces to be specified in constructor -- xmlschema: improve handling of compositors and simple types - -2004-01-08, version 0.6.6 -- soap_server: when requested WSDL is in a file, return to client using passthru (thanks Ingo Fischer) -- soapclient: have proxy inherit more client state -- soapclient: allow timeout and response timeout to be specified in the constructor -- wsdl: allow timeout and response timeout to be specified in the constructor -- soap_transport_http: allow response timeout to be specified in send and sendHTTPS - -2004-01-28, version 0.6.6 -- wsdl: add namespace for array and scalar when form is qualified -- wsdl: fix a bug in which data type of complexType elements were ignored in serialization -- wsdl: enhance handling of URLs with file scheme -- wsdl: add addSimpleType -- xmlschema: add addSimpleType -- xmlschema: always set phpType elements -- soapclient: allow a wsdl instance to be specified in constructor -- soap_server: allow a wsdl instance to be specified in constructor (not tested!) -- soap_server: fix default SOAPAction created in register method -- soap_transport_http: accept chunking with LF separators in addition to CRLF. -- wsdlcache: added class -- nusoapmime: fix comments - -2004-02-23, version 0.6.6 -- soap_transport_http: don't try to unchunk cURL data, since cURL already does it -- soap_transport_http: append CVS revision to version in User-Agent -- wsdl: serialize boolean as true|false, not 1|0, to agree with XML Schema -- soap_server: always exit() after returning WSDL -- soap_server: use the WSDL URL scheme as the default endpoint URL scheme -- soap_server: append CVS revision to version in X-SOAP-Server -- nusoap_base: add (CVS) revision -- wsdlcache: synchronize using a per-WSDL lock file (Thanks Ingo) -- wsdlcache: add cache lifetime, after which cache contents are invalidated (Thanks Ingo) - -2004-03-15, version 0.6.6 -- nusoap_base: add isArraySimpleOrStruct method -- soap_server: improve WSDL URL scheme determination -- soap_server: only deflate/gzip payloads > 1024 bytes -- soap_server: fix parameter order in fault method (always used as faultcode, faultstring) -- soap_server: refactor parse_request into multiple functions (for sanity) -- soap_server: set the namespace on the Response element to the same as the request -- soap_server: name the return value element 'return' by default -- soap_server: added and documented data fields, so that service programmers can use them if desired -- soap_parser: standardize parsing error message -- soap_parser: fix document and responseHeaders so they are the correct XML text (as documented) -- soap_transport_http: fix read from persistent connection -- soapclient: clean up debugging for persistent connection -- wsdl: enforce correct naming of messages parts when an associative array is used for parameters -- wsdl: better serialization of null values -- wsdl: standardize parsing error message -- xmlschema: standardize parsing error message - -2004-03-24, version 0.6.7 -- soap_transport_http: add digest authentication (based on code by Kevin A. Miller) -- xmlschema: improve parsing of import elements -- wsdl: do schema imports even if there are no wsdl imports - -2004-04-12, version 0.6.7 -- wsdl: serialize multiple elements when maxOccurs="unbounded" and value is an array -- wsdl: serialize soapval values (used to force an XML type, e.g. when WSDL uses an abstract type) -- nusoapmime: do not require nusoap.php (it is now the programmer's responsibility) - -2004-04-21, version 0.6.7 -- soap_parser: parse repeated element name into an array (de-serializes doc/lit array into a PHP array when there is more than 1 array element) -- soap_server: do not wrap response in a response element for a document style service - -2004-04-30, version 0.6.7 -- soap_transport_http: allow digest auth params to be separated by "," as well as ", " -- soap_transport_http: re-initialize incoming headers for each response -- soap_server: add methodreturnisliteralxml property to allow service function to return XML as a string -- soapclient: improve rpc/literal support -- soapclient: allow XML string as call params in addition to array -- soapclient: support document style and literal encoding when not using WSDL - -2004-05-05, version 0.6.7 -- wsdl: serialize PHP objects for WSDL XML Schema complexTypes, in addition to associative arrays -- wsdl: fix WSDL generation when there is no encodingStyle -- soap_transport_http: suppress fsockopen warnings -- soap_transport_http: detect socket timeouts when reading (0 bytes returned) -- soap_transport_http: read chunked content "in-line" so it works on a persistent connection -- nusoap_base: serialize boolean as true|false, not 1|0, to agree with XML Schema -- nusoap_base: serialize array of struct differently than array of array - -2004-06-25, version 0.6.8 -- soap_server: prefer gzip to deflate, since IE does not like our deflate -- soap_server: move webDescription to the wsdl class -- soap_server: allow class and instance method calls for service (thanks Ingo Fischer and Roland Knall) -- wsdl: get webDescription from the soap_server class -- wsdl: allow compression from the server -- wsdl: fix serialization of soapval without a type -- wsdl: propagate debug value from query string to SOAP endpoint in programmatic WSDL generation -- nusoap_base: add anyType, anySimpleType for 2001 XML Schema -- nusoap_base: provide additional debug functions -- soap_transport_http: ignore Content-Length when chunked encoding is used -- soap_transport_http: remove ':' from username for Basic authentication (cf. RFC 2617) -- soap_transport_http: urldecode username and password taken from URL -- soap_transport_http: use raw inflate/deflate for IE/IIS compatibility, rather than having Zlib headers according to HTTP 1.1 spec -- soap_transport_http: attempt to handle the case when both the service application and Web server compress the response -- soapclient: when creating proxy methods, replace '.' in operation name with '__' in function name -- soapclient: initialize requestHeaders in proxy -- general: use new debug methods; never access debug_str directly - -2004-09-30, version 0.6.8 -- soapclient: do not allow getProxy call when WSDL is not used -- soapclient: use ISO-8859-1 as the charset if not specified in the Content-Type header -- soapclient: when an empty string is specified for the call namespace, do not put the method element in a namespace -- soapclient: let soap_transport_http check for SSL support -- soapclient: have proxy inherit soap_defencoding from the client from which it is generated -- soapclient: do not assume that 'ns1' is an unused namespace prefix; always generate namespace prefixes randomly -- soap_parser: compare any encoding in the XML declaration to the charset from the HTTP Content-Type header (thanks Ingo Fischer) -- soap_parser: improve parse repeated element name into an array (de-serializes doc/lit array into a PHP array when there is more than 1 array element) -- soap_server: use ISO-8859-1 as the charset if not specified in the Content-Type header -- soap_server: allow suppression of automatic UTF-8 decoding -- soap_server: fix a bug when call_user_func_array() is used -- soap_transport_http: correct digest authentication through a proxy -- wsdl: serialize SOAP-ENC types similarly to XSD types -- xmlschema: force unprefixed type into default namespace -- xmlschema: fix serialization of definition of simple types - -2004-10-01, version 0.6.8 -- soap_parser: handle default namespace attributes -- soap_server: add default_utf8 field -- soap_server: support literal encoding (with RPC style) -- soap_transport_http: parse HTTP status and generate error for 300, 302-307, 400, 401-417, 501-505 (thanks for the idea Ghislain) -- soap_transport_http: follow HTTP redirection (HTTP status 301 and Location header) (thanks for the idea Ghislain) -- xmlschema: allow any attributes to be specified in an element of a complexType, e.g., abstract, default, form, minOccurs, maxOccurs, nillable (thanks Jirka Pech for the original patch) - -2004-10-02, version 0.6.8 -- soapclient: read/write cookies (thanks Ingo) -- soap_server: change faultcode on non-resendable faults to Client -- soap_transport_http: read/write cookies (thanks Ingo) - -2004-10-05, version 0.6.8 -- wsdl: add addElement method -- wsdl: support the document style in the register method -- xmlschema: parse unnamed simpleTypes, rather than ignoring them -- xmlschema: include untyped elements when parsing a complexType -- xmlschema: add addElement method - -2004-10-14, version 0.6.8 -- soapclient: support client certificates -- soap_parser: deserialize attributes, prefixing names with "!" -- soap_server: notify the client with HTML when WSDL is requested but not supported by service -- soap_transport_http: support client certificates -- wsdl: support defaults for elements of a complexType -- wsdl: serialize elements from complexType extension base -- wsdl: serialize data (associative array elements) as attributes according to XML Schema -- xmlschema: record extension base if present for a complexType - -2004-12-15, version 0.6.8 -- nusoap_base: add 2000 XML Schema (rare, but used by Akamai) -- soap_parser: avoid deserializing more common attributes that are not data -- soap_parser: be lax when HTTP specifies ISO-8859-1 (the default) and XML specifies UTF-8 (the norm) -- soap_server: account for the fact that get_class_methods returns methods in all lower case (thanks Steve Haldane) -- soap_transport_http: parse digest info that includes '=' in the data (thanks Jinsuk Kim) -- wsdl: feably handle some cases for literal serialization of form="unqualified" elements -- wsdl: don't serialize the decimal portion of a PHP double when the XML type is long -- wsdl: fix serialization of attributes for complexType that is an extension -- wsdlcache: enhance diagnostics -- xmlschema: handle untyped elements -- xmlschema: handle WSDL for SOAP Array that uses the base attribute plus a sequence of element - -2005-01-22, version 0.6.8 -- wsdl: allow an element in one schema to have a type from another schema - -2005-01-24, version 0.6.8 -- xmlschema: correctly parse nested complexType definitions - -2005-02-14, version 0.6.8 -- nusoap_base: fix a bug in which attributes were sometimes not serialized with a value -- nusoap_base: improve serialization of null values (thanks Dominique Stender) -- soap_parser: parse null values by handling the nil attribute (thanks Dominique Stender) -- soap_server: set character encoding for a fault to be the same as for the server (thanks Mark Scott) -- soap_server: correctly check for null value returned from method when WSDL is used (without WSDL, cannot distinguish whether NULL or void return is desired) -- soapclient: for document style, call should always return an array rooted at the response part (all bets are off when there are multiple parts) -- xmlschema: save enumeration values parsed from WSDL - -2005-02-10, version 0.6.9 -- soapclient: only set SOAP headers when they are specified in call params (so setHeaders still works) - -2005-04-04, version 0.6.9 -- soap_server: use get_class instead of is_a (thanks Thomas Noel) -- soapclient: use get_class instead of is_a (thanks Thomas Noel) -- soapclient: add setEndpoint method -- soap_transport_http: fix client certificates (thanks Doug Anarino and Eryan Eriobowo) - -2005-04-29, version 0.6.9 -- nusoap_base: add global variable and methods for setting debug level -- nusoap_base: use xsd:anyType instead of xsd:ur-type to serialize arrays with multiple element types (thanks Ingo Fischer) -- nusoap_base: expand entities in attributes (thanks Gaetano Giunta) -- soapclient: call parent constructor -- soapval: call parent constructor -- soap_fault: call parent constructor -- soap_parser: call parent constructor -- soap_server: assume get_class_methods always returns lower case for PHP 4.x only -- soap_server: call parent constructor -- soap_transport_http: do nothing in setEncoding if gzdeflate is not present (thanks Franck Touanen for pointing this out) -- soap_transport_http: fix check for server request for digest authentication (thanks Mark Spavin) -- soap_transport_http: call parent constructor -- wsdl: fix documentation page popup of one method after another (thanks Owen) -- wsdl: call parent constructor -- wsdl: expand entities in attributes (thanks Gaetano Giunta) -- xmlschema: call parent constructor - -2005-06-03, version 0.6.9 -- nusoap_base: serialize empty arrays as having elements xsd:anyType[0] -- nusoap_base: add encodingStyle parameter to serializeEnvelope -- nusoap_base: serialize xsi:type with nil values -- nusoap_base: improve debug and comments -- soap_parser: correctly parse an empty array to an empty array, not an empty string -- soap_parser: improve debug and comments -- soap_server: specify encodingStyle for envelope when WSDL is used -- soapclient: factor out new getProxyClassCode method -- soapclient: specify encodingStyle for envelope -- soapclient: improve debug and comments -- wsdl: add namespace for Apache SOAP types if a variable of such type is serialized -- wsdl: serialize nil value for nillable elements when no value is provided -- wsdl: serialize xsi:type with nil values -- wsdl: copy attributes as well as elements to an element from its complexType -- wsdl: specify encodingStyle for operations -- wsdl: improve debug and comments -- xmlschema: improve debug and comments - -2005-06-03, version 0.7.0 -- nusoap_base: improve debug and comments -- nusoap_base: fix version, which should have been 0.7.0 since 2005-03-04 - -2005-06-06, version 0.7.1 -- nusoap_base: adjust numeric element names for serialization, instead of forcing them to 'soapVal' -- nusoapmime: add type=text/xml to multipart/related (thanks Emmanuel Cordonnier) -- soap_fault: fix serialization of detail -- soap_server: check required parameters for register method -- soap_server: when getallheaders is used, massage header names -- soap_server: use SOAPAction to determine operation when doc/lit service does not wrap parameters in an element with the method name (thanks Peter Hrastnik) -- soap_transport_http: correctly handle multiple HTTP/1.1 100 responses for https (thanks Jan Slabon) -- wsdl: fixed documentation for addComplexType (thanks Csintalan Ádám) -- wsdl: serialize array data when maxOccurs = 'unbounded' OR maxOccurs > 1 (thanks Dominique Schreckling) -- wsdl: when serializing a string == 'false' as a boolean, set the value to false -- wsdl: when serializing a complexType, require the PHP value supplied to be an array - -2005-07-01, version 0.7.1 -- nusoap_base: Allow SOAP headers to be supplied as an array like parameters -- soap_parser: de-serialize simpleContent that accompanies complexContent -- soap_server: append debug information when programmatically-defined WSDL is returned -- soap_transport_http: Add debug when an outgoing header is set -- soapclient: Allow SOAP headers to be supplied as an array like parameters -- xmlschema: serialize attributes more generally, rather than assuming they are for SOAP 1.1 Array -- wsdl: when serializing, look up types by namespace, not prefix (simple programmatic doc/lit WSDL now seems to work) -- wsdl: process namespace declarations first when parsing an element - -2005-07-27, version 0.7.1 -- nusoap_base: do not override supplied element name with class name when serializing an object in serialize_val -- nusoap_base: remove http://soapinterop.org/xsd (si) from namespaces array -- nusoapmime: add nusoapservermime class to implement MIME attachments on the server -- soap_fault: improve documentation -- soap_server: improve documentation -- soap_server: make consistent use of _SERVER and HTTP_SERVER_VARS -- soap_server: make all incoming HTTP header keys lower case -- soap_server: add hook functions to support subclassing for MIME attachments -- soap_transport_http: remove an unnecessary global statement -- soapclient: when creating a proxy, make $params within each function an associative array -- soapval: improve documentation -- wsdl: when serializing complexType elements, used typed serialization if there is either a type or a reference for the element -- wsdl: allow PHP objects to be serialized as SOAP structs in serializeType -- wsdl: for WSDL and XML Schema imports, don't forget to use the TCP port number (thanks Luca GIOPPO) -- wsdl: make consistent use of _SERVER and HTTP_SERVER_VARS -- xmlschema: improve documentation - -2005-07-31, version 0.7.2 -- nusoap_base: correctly serialize attributes in serialize_val (thanks Hidran Arias) -- soap_parser: when resolving references, do not assume that buildVal returns an array (thanks Akshell) -- soap_parser: removed decode_entities, which does not work (thanks Martin Sarsale) -- soap_server: fix a bug parsing headers from _SERVER and HTTP_SERVER_VARS (thanks Bert Catsburg) -- soap_server: parse all "headers" from HTTP_SERVER_VARS (not just HTTP_*) -- soap_server: use PHP_SELF instead of SCRIPT_NAME for WSDL endpoint -- soap_server: when generating a fault while debug_flag is true, put debug into faultdetail -- wsdl: add enumeration parameter to addSimpleType -- xmlschema: add enumeration parameter to addSimpleType - -2006-02-02, version 0.7.2 -- soapclient: initialize paramArrayStr to improve proxy generation -- soap_parser: handle PHP5 soapclient's incorrect transmission of WSDL-described SOAP encoded arrays. -- soap_server: don't assume _SERVER['HTTPS'] is set; try HTTP_SERVER_VARS['HTTPS'] if it is not -- soap_server: "flatten out" the parameter array to call_user_func_array (thanks André Mamitzsch) -- soap_server: make thrown exceptions conform to specs -- wsdl: use serialize_val to serialize an array when the XSD type is soapenc:Array (JBoss/Axis does this) -- wsdl: change formatting of serialized XML for the WSDL -- xmlschema: change formatting of namespaces when serializing XML for the schema - -2006-04-07, version 0.7.2 -- soap_server: if methodparams is not an array, call call_user_func_array with an empty array (thanks Eric Grossi) -- wsdl: distinguish parts with element specified from those with type specified by suffixing element names with ^ -- wsdl: do a case-insensitive match on schema URI when looking for type -- xmlschema: only get element (not type) when name has ^ suffix - -2006-05-16, version 0.7.2 -- soapclient: add getHeader to get parsed SOAP Header -- soap_parser: check status when receiving Header or Body element -- soap_parser: add soapheader -- soap_server: add requestHeader with parsed SOAP Header - -2006-06-15, version 0.7.2 -- wsdl: fix bug in addComplexType (thanks Maarten Meijer) -- soap_transport_http: change cURL message - -2007-03-19, version 0.7.2 -- soapclient: declare as nusoapclient, then also subclass soapclient if SOAP extension not loaded -- soapclientmime: declare as nusoapclientmime, then also subclass soapclientmime if SOAP extension not loaded - -2007-03-28, version 0.7.2 -- nusoap_base: fix serialization of a soapval when its value is a soapval -- soapval: fix serialization of a soapval when its value is a soapval -- soapval: add __toString (cf. http://article.gmane.org/gmane.comp.php.nusoap.general/2776) -- nusoapclient: use lazy retrieval of WSDL instead of always getting it in the constructor -- nusoapclient: fix getProxy that was broken in last revision -- wsdl: add ability to set authorization credentials and retrieve WSDL outside of constructor - -2007-04-05, version 0.7.2 -- nusoapclientmime: don't rely exclusively on Content-Disposition to distinguish the root part from attachment; also check Content-Type (thanks Ben Bosman) -- nusoapclientmime: obey RFC 2045 Section 5.1 (thanks Chris Butler) -- nusoapservermime: don't rely exclusively on Content-Disposition to distinguish the root part from attachment; also check Content-Type (thanks Ben Bosman) -- nusoapservermime: obey RFC 2045 Section 5.1 (thanks Chris Butler) -- nusoap_base: remove extra whitespace from some XML elements -- nusoap_base: allow SOAP headers to be specified as an associative array (thanks Unique) -- nusoap_base: implement __toString -- nusoap_base: improve doc accuracy and consistency (thanks Martin K?gler) -- iso8601_to_timestamp: avoid problem with negative hours after calculation, etc. (thanks Guntram Trebs) -- nusoapclient: support user-settable cURL options (thanks Ciprian Popovici) -- nusoapclient: call SOAP 1.2 binding operations if no SOAP 1.1 present (there is no reason to believe this will always work!) -- nusoapclient: improve doc accuracy and consistency (thanks Martin K?gler) -- soap_server: don't try to use eval to call function when any parameter is an object -- soap_server: don't print return value within debug string; returned objects would need __toString in PHP 5.2 -- soap_server: use URL scheme for WSDL access as the scheme in SOAPAction -- soap_server: strip port number from server name (some FastCGI implementations include port in server name) -- soap_transport_http: support user-settable cURL options (thanks Ciprian Popovici) -- soap_transport_http: use cURL for NTLM authentication -- soap_transport_http: make digest authentication work for GET as well as POST -- soap_transport_http: improve doc accuracy and consistency (thanks Martin K?gler) -- soapval: remove __toString -- wsdl: set operation style if necessary, but do not override one already provided (thanks Raffaele Capobianco) -- wsdl: check SOAP 1.2 binding operations if no SOAP 1.1 present -- wsdl: improve doc accuracy and consistency (thanks Martin K?gler) -- xmlschema: fix simpleType serialization -- xmlschema: improve doc accuracy and consistency (thanks Martin K?gler) - -2007-04-09, version 0.7.2 -- nusoapclient: set decode_utf8 when creating a proxy (thanks Dmitri Dmitrienko) -- nusoapclient: rename class to nusoap_client -- soap_fault: also provide a class named nusoap_fault -- soap_parser: also provide a class named nusoap_parser -- soap_server: also provide a class named nusoap_server -- soap_transport_http: skip HTTP responses 301 and 401 when using cURL -- soap_transport_http: don't force HTTP Connection header when using cURL -- soap_transport_http: don't set HTTP Host and Content-Length headers when using cURL -- soap_transport_http: support CURLOPT_SSLCERTPASSWD (thanks David Blanco) -- wsdl: support user-settable cURL options (thanks Ciprian Popovici) -- wsdl: serialize parameters for non-SOAP 1.1 binding operations (there is no reason to believe this will always work!) -- xmlschema: also provide a class named nusoap_xmlschema -- nusoapclientmime: rename class to nusoap_client_mime -- nusoapservermime: rename class to nusoap_server_mime - -2007-04-11, version 0.7.2 -- nusoap_client: enable cURL usage to be forced (thanks Giunta Gaetano) -- soap_transport_http: enable cURL proxy usage (thanks Giunta Gaetano) -- soap_transport_http: enable cURL usage to be forced (thanks Giunta Gaetano) -- soap_transport_http: use cURL's HTTP authentication options for basic, digest -- wsdl: enable cURL usage to be forced (thanks Giunta Gaetano) - -2007-04-12, version 0.7.2 -- nusoap_client: add debug -- nusoap_xmlschema: don't add elements of complexTypes to elements array (thanks Heiko Hund) -- soap_transport_http: set cURL connection timeout if supported -- soap_transport_http: add debug when setting cURL option -- soap_transport_http: fix digest authentication broken in previous revision -- wsdl: add debug -- wsdlcache: address some issues with non-existing cache-files and PHP Warnings which came in such cases (thanks Ingo Fischer) -- wsdlcache: change class name to nusoap_wsdlcache - -2007-04-13, version 0.7.2 -- wsdl: wrap parameters if unwrapped values are supplied and WSDL specifies Microsoft-style wrapping - -2007-04-16, version 0.7.2 -- nusoap_base: avoid warning in getDebugAsXMLComment -- nusoap_client: small debug change -- nusoap_client_mime: set responseData when the root part is found - -2007-04-17, version 0.7.2 -- soap_transport_http: improve detection of undefined cURL options (thanks Ingo Fischer) - -2007-05-28, version 0.7.2 -- soap_transport_http: support digest authentication opaque feature (cf. RFC 2617) (thanks Daniel Lacroix) -- soap_transport_http: check safe_mode and open_basedir before setting CURLOPT_FOLLOWLOCATION -- soap_transport_http: skip "HTTP/1.0 200 Connection established" header when cURL returns it (thanks Raimund Jacob) -- nusoap_client: improve handling when getProxy is called and WSDL is not being used -- nusoap_base: add comments about which specifications are used/implemented by NuSOAP -- nusoap_xmlschema: create names for unnamed types that are unique by scope within XML Schema - -2007-06-11, version 0.7.2 -- wsdl: wrap return value if unwrapped value is supplied and WSDL specifies Microsoft-style wrapping - -2007-06-22, version 0.7.2 -- nusoap_xmlschema: fix serialization of simpleType restriction (thanks Rizwan Tejpar) - -2007-07-30, version 0.7.2 -- nusoap_server: Per http://www.ws-i.org/Profiles/BasicProfile-1.1-2004-08-24.html R2735, rpc/literal accessor elements should not be in a namespace (thanks Kostas Kalevras) -- nusoap_client: Per http://www.ws-i.org/Profiles/BasicProfile-1.1-2004-08-24.html R2735, rpc/literal accessor elements should not be in a namespace (thanks Kostas Kalevras) - -2007-10-21, version 0.7.2 -- nusoap_server: Per http://www.ws-i.org/Profiles/BasicProfile-1.1-2004-08-24.html R2735, rpc/literal accessor elements should not be in a namespace (thanks Kostas Kalevras) -- nusoap_client: Per http://www.ws-i.org/Profiles/BasicProfile-1.1-2004-08-24.html R2735, rpc/literal accessor elements should not be in a namespace (thanks Kostas Kalevras) - -2007-10-26, version 0.7.2 -- nusoap_server: Fix munging of _SERVER variables that start with HTTP_ (thanks Thomas Wieczorek) - -2007-10-30, version 0.7.2 -- nusoap_xmlschema: Serialize values for elementFormDefault, attributeFormDefault -- wsdl: Improve consistency between doc/lit schema auto-wrapping and client's parsed schema -- nusoap_server: Correct bug that placed encodingType in Envelope for doc/lit -- nusoap_server: Specify elementFormDefault for schema within doc/lit wsdl - -2007-10-31, version 0.7.2 -- wsdl: Fix typo in parametersMatchWrapped (thanks Sam Stepanyan) -- soap_transport_http: Fix three typos in setProxy (thanks Sam Stepanyan) -- nusoap_xmlschema: Fix typo in serializeTypeDef (thanks Sam Stepanyan) - -2007-11-06, version 1.0rc1 -- wsdl: Improve handling of return values from doc/lit methods -- nusoap_server: Handle case when method is not in a namespace - -2007-11-27, version 1.0rc1 -- nusoap_server: always try to invoke service for a POST -- nusoap_server: only return Location: for WSDL at http://... -- nusoap_base: change some syntax associated with globalDebugLevel - -2008-01-08, version 1.0rc1 -- nusoap_server: fix a typo where = was used instead of == (thanks J. (Johan) Bosma) - -2008-01-10, version 1.0rc1 -- nusoap_client: handle case where request or response has no content-type header (thanks Ingo Fischer) -- nusoap_server: handle case where request or response has no content-type header (thanks Ingo Fischer) -- wsdl: change CSS for .title in webDescription (thanks Marcus Uy) - -2008-01-25, version 1.0rc1 -- nusoap_xmlschema: when an element is of a complexType that is an extension, copy extensionBase from the type -- nusoap_xmlschema: do not apply elementFormDefault to globally defined elements - -2008-02-11, version 1.0rc1 -- wsdl: internally set form of wrapped parameter elements to unqualified (so server handles correctly) - -2008-03-03, version 1.0.rc1 -- nusoap_xmlschema: fix extension when base type has no explicit prefix -- nusoap_xmlschema: support XML Schema include -- wsdl: improve support for sequence by serializing inherited attributes and elements first - -2008-03-04, version 1.0.rc1 -- wsdl: allow WSDL port name to be specified in getOperations -- nusoap_client: allow WSDL port name to be specified in ctor - -2008-03-06, version 1.0rc1 -- wsdl: fix some port name variable references -- nusoap_base: change comments regarding preferred mode of support -- wsdl2nusoap: initial revision - -2008-03-14, version 1.0rc1 -- nusoap_base: fix timezone offset in timestamp_to_iso8601 (thanks Mario Trojan) - -2008-03-27, version 1.0rc1 -- nusoap_server: fix bug setting encodingStyle in serialize_return (thanks Luca Gobbo) - -2008-05-15, version 1.0rc1 -- nusoap_parser: handle case where Header or Body tags are used within SOAP messages (thanks Sergey Zhuravlev) - -2008-08-26, version 1.0rc1 -- wsdl: serialize simpleContent for complexType -- wsdl: avoid serializing complexType elements with no value and minOccurs = 0 regardless of nillability - -2010-04-26, version 0.9.5 -- nusoap_xmlschema: replace regex function calls (ereg, eregi, split) with PCRE calls (preg_match, preg_split) (thanks Pier-Luc Duchaine) -- wsdl: replace regex function calls (ereg, eregi, split) with PCRE calls (preg_match, preg_split) (thanks Pier-Luc Duchaine) -- soap_transport_http: replace regex function calls (ereg, eregi, split) with PCRE calls (preg_match, preg_split) (thanks Pier-Luc Duchaine) -- soap_transport_http: remove call to deprecated function set_magic_quotes_runtime -- nusoap_server: replace regex function calls (ereg, eregi, split) with PCRE calls (preg_match, preg_split) (thanks Pier-Luc Duchaine) -- nusoap_server: check that value is an object before calling get_class (thanks Pier-Luc Duchaine) -- nusoap_parser: replace regex function calls (ereg, eregi, split) with PCRE calls (preg_match, preg_split) (thanks Pier-Luc Duchaine) -- nusoap_client: replace regex function calls (ereg, eregi, split) with PCRE calls (preg_match, preg_split) (thanks Pier-Luc Duchaine) -- nusoap_client: do not assign the return value of new by reference (it is deprecated) (thanks Pier-Luc Duchaine) -- nusoap_base: replace regex function calls (ereg, eregi, split) with PCRE calls (preg_match, preg_split) (thanks Pier-Luc Duchaine) -- nusoapmime: do not assign the return value of new by reference (it is deprecated) diff --git a/src/Drivers/lib/class.nusoap_base.php b/src/Drivers/lib/class.nusoap_base.php deleted file mode 100644 index 9c158e4..0000000 --- a/src/Drivers/lib/class.nusoap_base.php +++ /dev/null @@ -1,1022 +0,0 @@ - - * @author Scott Nichol - * - * @version $Id: class.nusoap_base.php,v 1.56 2010/04/26 20:15:08 snichol Exp $ - */ -class nusoap_base -{ - /* - * Identification for HTTP headers. - * - * @var string - * @access private - */ - public $title = 'NuSOAP'; - /* - * Version for HTTP headers. - * - * @var string - * @access private - */ - public $version = '0.9.5'; - /* - * CVS revision for HTTP headers. - * - * @var string - * @access private - */ - public $revision = '$Revision: 1.56 $'; - /* - * Current error string (manipulated by getError/setError) - * - * @var string - * @access private - */ - public $error_str = ''; - /* - * Current debug string (manipulated by debug/appendDebug/clearDebug/getDebug/getDebugAsXMLComment) - * - * @var string - * @access private - */ - public $debug_str = ''; - /* - * toggles automatic encoding of special characters as entities - * (should always be true, I think) - * - * @var boolean - * @access private - */ - public $charencoding = true; - /* - * the debug level for this instance - * - * @var integer - * @access private - */ - public $debugLevel; - - /* - * set schema version - * - * @var string - * @access public - */ - public $XMLSchemaVersion = 'http://www.w3.org/2001/XMLSchema'; - - /* - * charset encoding for outgoing messages - * - * @var string - * @access public - */ - public $soap_defencoding = 'ISO-8859-1'; - //var $soap_defencoding = 'UTF-8'; - - /* - * namespaces in an array of prefix => uri - * - * this is "seeded" by a set of constants, but it may be altered by code - * - * @var array - * @access public - */ - public $namespaces = [ - 'SOAP-ENV' => 'http://schemas.xmlsoap.org/soap/envelope/', - 'xsd' => 'http://www.w3.org/2001/XMLSchema', - 'xsi' => 'http://www.w3.org/2001/XMLSchema-instance', - 'SOAP-ENC' => 'http://schemas.xmlsoap.org/soap/encoding/', - ]; - - /* - * namespaces used in the current context, e.g. during serialization - * - * @var array - * @access private - */ - public $usedNamespaces = []; - - /* - * XML Schema types in an array of uri => (array of xml type => php type) - * is this legacy yet? - * no, this is used by the nusoap_xmlschema class to verify type => namespace mappings. - * @var array - * @access public - */ - public $typemap = [ - 'http://www.w3.org/2001/XMLSchema' => [ - 'string' => 'string', 'boolean' => 'boolean', 'float' => 'double', 'double' => 'double', 'decimal' => 'double', - 'duration' => '', 'dateTime' => 'string', 'time' => 'string', 'date' => 'string', 'gYearMonth' => '', - 'gYear' => '', 'gMonthDay' => '', 'gDay' => '', 'gMonth' => '', 'hexBinary' => 'string', 'base64Binary' => 'string', - // abstract "any" types - 'anyType' => 'string', 'anySimpleType' => 'string', - // derived datatypes - 'normalizedString' => 'string', 'token' => 'string', 'language' => '', 'NMTOKEN' => '', 'NMTOKENS' => '', 'Name' => '', 'NCName' => '', 'ID' => '', - 'IDREF' => '', 'IDREFS' => '', 'ENTITY' => '', 'ENTITIES' => '', 'integer' => 'integer', 'nonPositiveInteger' => 'integer', - 'negativeInteger' => 'integer', 'long' => 'integer', 'int' => 'integer', 'short' => 'integer', 'byte' => 'integer', 'nonNegativeInteger' => 'integer', - 'unsignedLong' => '', 'unsignedInt' => '', 'unsignedShort' => '', 'unsignedByte' => '', 'positiveInteger' => '', ], - 'http://www.w3.org/2000/10/XMLSchema' => [ - 'i4' => '', 'int' => 'integer', 'boolean' => 'boolean', 'string' => 'string', 'double' => 'double', - 'float' => 'double', 'dateTime' => 'string', - 'timeInstant' => 'string', 'base64Binary' => 'string', 'base64' => 'string', 'ur-type' => 'array', ], - 'http://www.w3.org/1999/XMLSchema' => [ - 'i4' => '', 'int' => 'integer', 'boolean' => 'boolean', 'string' => 'string', 'double' => 'double', - 'float' => 'double', 'dateTime' => 'string', - 'timeInstant' => 'string', 'base64Binary' => 'string', 'base64' => 'string', 'ur-type' => 'array', ], - 'http://soapinterop.org/xsd' => ['SOAPStruct' => 'struct'], - 'http://schemas.xmlsoap.org/soap/encoding/' => ['base64' => 'string', 'array' => 'array', 'Array' => 'array'], - 'http://xml.apache.org/xml-soap' => ['Map'], - ]; - - /* - * XML entities to convert - * - * @var array - * @access public - * @deprecated - * @see expandEntities - */ - public $xmlEntities = ['quot' => '"', 'amp' => '&', - 'lt' => '<', 'gt' => '>', 'apos' => "'", ]; - - /** - * constructor. - */ - public function nusoap_base() - { - $this->debugLevel = $GLOBALS['_transient']['static']['nusoap_base']['globalDebugLevel']; - } - - /** - * gets the global debug level, which applies to future instances. - * - * @return int Debug level 0-9, where 0 turns off - */ - public function getGlobalDebugLevel() - { - return $GLOBALS['_transient']['static']['nusoap_base']['globalDebugLevel']; - } - - /** - * sets the global debug level, which applies to future instances. - * - * @param int $level Debug level 0-9, where 0 turns off - */ - public function setGlobalDebugLevel($level) - { - $GLOBALS['_transient']['static']['nusoap_base']['globalDebugLevel'] = $level; - } - - /** - * gets the debug level for this instance. - * - * @return int Debug level 0-9, where 0 turns off - */ - public function getDebugLevel() - { - return $this->debugLevel; - } - - /** - * sets the debug level for this instance. - * - * @param int $level Debug level 0-9, where 0 turns off - */ - public function setDebugLevel($level) - { - $this->debugLevel = $level; - } - - /** - * adds debug data to the instance debug string with formatting. - * - * @param string $string debug data - */ - public function debug($string) - { - if ($this->debugLevel > 0) { - $this->appendDebug($this->getmicrotime().' '.get_class($this).": $string\n"); - } - } - - /** - * adds debug data to the instance debug string without formatting. - * - * @param string $string debug data - */ - public function appendDebug($string) - { - if ($this->debugLevel > 0) { - // it would be nice to use a memory stream here to use - // memory more efficiently - $this->debug_str .= $string; - } - } - - /** - * clears the current debug data for this instance. - */ - public function clearDebug() - { - // it would be nice to use a memory stream here to use - // memory more efficiently - $this->debug_str = ''; - } - - /** - * gets the current debug data for this instance. - * - * @return debug data - */ - public function &getDebug() - { - // it would be nice to use a memory stream here to use - // memory more efficiently - return $this->debug_str; - } - - /** - * gets the current debug data for this instance as an XML comment - * this may change the contents of the debug data. - * - * @return debug data as an XML comment - */ - public function &getDebugAsXMLComment() - { - // it would be nice to use a memory stream here to use - // memory more efficiently - while (strpos($this->debug_str, '--')) { - $this->debug_str = str_replace('--', '- -', $this->debug_str); - } - $ret = ""; - - return $ret; - } - - /** - * expands entities, e.g. changes '<' to '<'. - * - * @param string $val The string in which to expand entities. - */ - public function expandEntities($val) - { - if ($this->charencoding) { - $val = str_replace('&', '&', $val); - $val = str_replace("'", ''', $val); - $val = str_replace('"', '"', $val); - $val = str_replace('<', '<', $val); - $val = str_replace('>', '>', $val); - } - - return $val; - } - - /** - * returns error string if present. - * - * @return mixed error string or false - */ - public function getError() - { - if ($this->error_str != '') { - return $this->error_str; - } - - return false; - } - - /** - * sets error string. - * - * @return bool $string error string - */ - public function setError($str) - { - $this->error_str = $str; - } - - /** - * detect if array is a simple array or a struct (associative array). - * - * @param mixed $val The PHP array - * - * @return string (arraySimple|arrayStruct) - */ - public function isArraySimpleOrStruct($val) - { - $keyList = array_keys($val); - foreach ($keyList as $keyListValue) { - if (!is_int($keyListValue)) { - return 'arrayStruct'; - } - } - - return 'arraySimple'; - } - - /** - * serializes PHP values in accordance w/ section 5. Type information is - * not serialized if $use == 'literal'. - * - * @param mixed $val The value to serialize - * @param string $name The name (local part) of the XML element - * @param string $type The XML schema type (local part) for the element - * @param string $name_ns The namespace for the name of the XML element - * @param string $type_ns The namespace for the type of the element - * @param array $attributes The attributes to serialize as name=>value pairs - * @param string $use The WSDL "use" (encoded|literal) - * @param bool $soapval Whether this is called from soapval. - * - * @return string The serialized element, possibly with child elements - */ - public function serialize_val($val, $name = false, $type = false, $name_ns = false, $type_ns = false, $attributes = false, $use = 'encoded', $soapval = false) - { - $this->debug("in serialize_val: name=$name, type=$type, name_ns=$name_ns, type_ns=$type_ns, use=$use, soapval=$soapval"); - $this->appendDebug('value='.$this->varDump($val)); - $this->appendDebug('attributes='.$this->varDump($attributes)); - - if (is_object($val) && get_class($val) == 'soapval' && (!$soapval)) { - $this->debug('serialize_val: serialize soapval'); - $xml = $val->serialize($use); - $this->appendDebug($val->getDebug()); - $val->clearDebug(); - $this->debug("serialize_val of soapval returning $xml"); - - return $xml; - } - // force valid name if necessary - if (is_numeric($name)) { - $name = '__numeric_'.$name; - } elseif (!$name) { - $name = 'noname'; - } - // if name has ns, add ns prefix to name - $xmlns = ''; - if ($name_ns) { - $prefix = 'nu'.rand(1000, 9999); - $name = $prefix.':'.$name; - $xmlns .= " xmlns:$prefix=\"$name_ns\""; - } - // if type is prefixed, create type prefix - if ($type_ns != '' && $type_ns == $this->namespaces['xsd']) { - // need to fix this. shouldn't default to xsd if no ns specified - // w/o checking against typemap - $type_prefix = 'xsd'; - } elseif ($type_ns) { - $type_prefix = 'ns'.rand(1000, 9999); - $xmlns .= " xmlns:$type_prefix=\"$type_ns\""; - } - // serialize attributes if present - $atts = ''; - if ($attributes) { - foreach ($attributes as $k => $v) { - $atts .= " $k=\"".$this->expandEntities($v).'"'; - } - } - // serialize null value - if (is_null($val)) { - $this->debug('serialize_val: serialize null'); - if ($use == 'literal') { - // TODO: depends on minOccurs - $xml = "<$name$xmlns$atts/>"; - $this->debug("serialize_val returning $xml"); - - return $xml; - } else { - if (isset($type) && isset($type_prefix)) { - $type_str = " xsi:type=\"$type_prefix:$type\""; - } else { - $type_str = ''; - } - $xml = "<$name$xmlns$type_str$atts xsi:nil=\"true\"/>"; - $this->debug("serialize_val returning $xml"); - - return $xml; - } - } - // serialize if an xsd built-in primitive type - if ($type != '' && isset($this->typemap[$this->XMLSchemaVersion][$type])) { - $this->debug('serialize_val: serialize xsd built-in primitive type'); - if (is_bool($val)) { - if ($type == 'boolean') { - $val = $val ? 'true' : 'false'; - } elseif (!$val) { - $val = 0; - } - } elseif (is_string($val)) { - $val = $this->expandEntities($val); - } - if ($use == 'literal') { - $xml = "<$name$xmlns$atts>$val"; - $this->debug("serialize_val returning $xml"); - - return $xml; - } else { - $xml = "<$name$xmlns xsi:type=\"xsd:$type\"$atts>$val"; - $this->debug("serialize_val returning $xml"); - - return $xml; - } - } - // detect type and serialize - $xml = ''; - switch (true) { - case is_bool($val) || $type == 'boolean': - $this->debug('serialize_val: serialize boolean'); - if ($type == 'boolean') { - $val = $val ? 'true' : 'false'; - } elseif (!$val) { - $val = 0; - } - if ($use == 'literal') { - $xml .= "<$name$xmlns$atts>$val"; - } else { - $xml .= "<$name$xmlns xsi:type=\"xsd:boolean\"$atts>$val"; - } - break; - case is_int($val) || is_int($val) || $type == 'int': - $this->debug('serialize_val: serialize int'); - if ($use == 'literal') { - $xml .= "<$name$xmlns$atts>$val"; - } else { - $xml .= "<$name$xmlns xsi:type=\"xsd:int\"$atts>$val"; - } - break; - case is_float($val) || is_float($val) || $type == 'float': - $this->debug('serialize_val: serialize float'); - if ($use == 'literal') { - $xml .= "<$name$xmlns$atts>$val"; - } else { - $xml .= "<$name$xmlns xsi:type=\"xsd:float\"$atts>$val"; - } - break; - case is_string($val) || $type == 'string': - $this->debug('serialize_val: serialize string'); - $val = $this->expandEntities($val); - if ($use == 'literal') { - $xml .= "<$name$xmlns$atts>$val"; - } else { - $xml .= "<$name$xmlns xsi:type=\"xsd:string\"$atts>$val"; - } - break; - case is_object($val): - $this->debug('serialize_val: serialize object'); - if (get_class($val) == 'soapval') { - $this->debug('serialize_val: serialize soapval object'); - $pXml = $val->serialize($use); - $this->appendDebug($val->getDebug()); - $val->clearDebug(); - } else { - if (!$name) { - $name = get_class($val); - $this->debug("In serialize_val, used class name $name as element name"); - } else { - $this->debug("In serialize_val, do not override name $name for element name for class ".get_class($val)); - } - foreach (get_object_vars($val) as $k => $v) { - $pXml = isset($pXml) ? $pXml.$this->serialize_val($v, $k, false, false, false, false, $use) : $this->serialize_val($v, $k, false, false, false, false, $use); - } - } - if (isset($type) && isset($type_prefix)) { - $type_str = " xsi:type=\"$type_prefix:$type\""; - } else { - $type_str = ''; - } - if ($use == 'literal') { - $xml .= "<$name$xmlns$atts>$pXml"; - } else { - $xml .= "<$name$xmlns$type_str$atts>$pXml"; - } - break; - break; - case is_array($val) || $type: - // detect if struct or array - $valueType = $this->isArraySimpleOrStruct($val); - if ($valueType == 'arraySimple' || preg_match('/^ArrayOf/', $type)) { - $this->debug('serialize_val: serialize array'); - $i = 0; - if (is_array($val) && count($val) > 0) { - foreach ($val as $v) { - if (is_object($v) && get_class($v) == 'soapval') { - $tt_ns = $v->type_ns; - $tt = $v->type; - } elseif (is_array($v)) { - $tt = $this->isArraySimpleOrStruct($v); - } else { - $tt = gettype($v); - } - $array_types[$tt] = 1; - // TODO: for literal, the name should be $name - $xml .= $this->serialize_val($v, 'item', false, false, false, false, $use); - ++$i; - } - if (count($array_types) > 1) { - $array_typename = 'xsd:anyType'; - } elseif (isset($tt) && isset($this->typemap[$this->XMLSchemaVersion][$tt])) { - if ($tt == 'integer') { - $tt = 'int'; - } - $array_typename = 'xsd:'.$tt; - } elseif (isset($tt) && $tt == 'arraySimple') { - $array_typename = 'SOAP-ENC:Array'; - } elseif (isset($tt) && $tt == 'arrayStruct') { - $array_typename = 'unnamed_struct_use_soapval'; - } else { - // if type is prefixed, create type prefix - if ($tt_ns != '' && $tt_ns == $this->namespaces['xsd']) { - $array_typename = 'xsd:'.$tt; - } elseif ($tt_ns) { - $tt_prefix = 'ns'.rand(1000, 9999); - $array_typename = "$tt_prefix:$tt"; - $xmlns .= " xmlns:$tt_prefix=\"$tt_ns\""; - } else { - $array_typename = $tt; - } - } - $array_type = $i; - if ($use == 'literal') { - $type_str = ''; - } elseif (isset($type) && isset($type_prefix)) { - $type_str = " xsi:type=\"$type_prefix:$type\""; - } else { - $type_str = ' xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="'.$array_typename."[$array_type]\""; - } - // empty array - } else { - if ($use == 'literal') { - $type_str = ''; - } elseif (isset($type) && isset($type_prefix)) { - $type_str = " xsi:type=\"$type_prefix:$type\""; - } else { - $type_str = ' xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="xsd:anyType[0]"'; - } - } - // TODO: for array in literal, there is no wrapper here - $xml = "<$name$xmlns$type_str$atts>".$xml.""; - } else { - // got a struct - $this->debug('serialize_val: serialize struct'); - if (isset($type) && isset($type_prefix)) { - $type_str = " xsi:type=\"$type_prefix:$type\""; - } else { - $type_str = ''; - } - if ($use == 'literal') { - $xml .= "<$name$xmlns$atts>"; - } else { - $xml .= "<$name$xmlns$type_str$atts>"; - } - foreach ($val as $k => $v) { - // Apache Map - if ($type == 'Map' && $type_ns == 'http://xml.apache.org/xml-soap') { - $xml .= ''; - $xml .= $this->serialize_val($k, 'key', false, false, false, false, $use); - $xml .= $this->serialize_val($v, 'value', false, false, false, false, $use); - $xml .= ''; - } else { - $xml .= $this->serialize_val($v, $k, false, false, false, false, $use); - } - } - $xml .= ""; - } - break; - default: - $this->debug('serialize_val: serialize unknown'); - $xml .= 'not detected, got '.gettype($val).' for '.$val; - break; - } - $this->debug("serialize_val returning $xml"); - - return $xml; - } - - /** - * serializes a message. - * - * @param string $body the XML of the SOAP body - * @param mixed $headers optional string of XML with SOAP header content, or array of soapval objects for SOAP headers, or associative array - * @param array $namespaces optional the namespaces used in generating the body and headers - * @param string $style optional (rpc|document) - * @param string $use optional (encoded|literal) - * @param string $encodingStyle optional (usually 'http://schemas.xmlsoap.org/soap/encoding/' for encoded) - * - * @return string the message - */ - public function serializeEnvelope($body, $headers = false, $namespaces = [], $style = 'rpc', $use = 'encoded', $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/') - { - // TODO: add an option to automatically run utf8_encode on $body and $headers - // if $this->soap_defencoding is UTF-8. Not doing this automatically allows - // one to send arbitrary UTF-8 characters, not just characters that map to ISO-8859-1 - - $this->debug('In serializeEnvelope length='.strlen($body).' body (max 1000 characters)='.substr($body, 0, 1000)." style=$style use=$use encodingStyle=$encodingStyle"); - $this->debug('headers:'); - $this->appendDebug($this->varDump($headers)); - $this->debug('namespaces:'); - $this->appendDebug($this->varDump($namespaces)); - - // serialize namespaces - $ns_string = ''; - foreach (array_merge($this->namespaces, $namespaces) as $k => $v) { - $ns_string .= " xmlns:$k=\"$v\""; - } - if ($encodingStyle) { - $ns_string = " SOAP-ENV:encodingStyle=\"$encodingStyle\"$ns_string"; - } - - // serialize headers - if ($headers) { - if (is_array($headers)) { - $xml = ''; - foreach ($headers as $k => $v) { - if (is_object($v) && get_class($v) == 'soapval') { - $xml .= $this->serialize_val($v, false, false, false, false, false, $use); - } else { - $xml .= $this->serialize_val($v, $k, false, false, false, false, $use); - } - } - $headers = $xml; - $this->debug("In serializeEnvelope, serialized array of headers to $headers"); - } - $headers = ''.$headers.''; - } - // serialize envelope - return - 'soap_defencoding.'"?'.'>'. - ''. - $headers. - ''. - $body. - ''. - ''; - } - - /** - * formats a string to be inserted into an HTML stream. - * - * @param string $str The string to format - * - * @return string The formatted string - * - * @deprecated - */ - public function formatDump($str) - { - $str = htmlspecialchars($str); - - return nl2br($str); - } - - /** - * contracts (changes namespace to prefix) a qualified name. - * - * @param string $qname qname - * - * @return string contracted qname - */ - public function contractQname($qname) - { - // get element namespace - //$this->xdebug("Contract $qname"); - if (strrpos($qname, ':')) { - // get unqualified name - $name = substr($qname, strrpos($qname, ':') + 1); - // get ns - $ns = substr($qname, 0, strrpos($qname, ':')); - $p = $this->getPrefixFromNamespace($ns); - if ($p) { - return $p.':'.$name; - } - - return $qname; - } else { - return $qname; - } - } - - /** - * expands (changes prefix to namespace) a qualified name. - * - * @param string $qname qname - * - * @return string expanded qname - */ - public function expandQname($qname) - { - // get element prefix - if (strpos($qname, ':') && !preg_match('/^http:\/\//', $qname)) { - // get unqualified name - $name = substr(strstr($qname, ':'), 1); - // get ns prefix - $prefix = substr($qname, 0, strpos($qname, ':')); - if (isset($this->namespaces[$prefix])) { - return $this->namespaces[$prefix].':'.$name; - } else { - return $qname; - } - } else { - return $qname; - } - } - - /** - * returns the local part of a prefixed string - * returns the original string, if not prefixed. - * - * @param string $str The prefixed string - * - * @return string The local part - */ - public function getLocalPart($str) - { - if ($sstr = strrchr($str, ':')) { - // get unqualified name - return substr($sstr, 1); - } else { - return $str; - } - } - - /** - * returns the prefix part of a prefixed string - * returns false, if not prefixed. - * - * @param string $str The prefixed string - * - * @return mixed The prefix or false if there is no prefix - */ - public function getPrefix($str) - { - if ($pos = strrpos($str, ':')) { - // get prefix - return substr($str, 0, $pos); - } - - return false; - } - - /** - * pass it a prefix, it returns a namespace. - * - * @param string $prefix The prefix - * - * @return mixed The namespace, false if no namespace has the specified prefix - */ - public function getNamespaceFromPrefix($prefix) - { - if (isset($this->namespaces[$prefix])) { - return $this->namespaces[$prefix]; - } - //$this->setError("No namespace registered for prefix '$prefix'"); - return false; - } - - /** - * returns the prefix for a given namespace (or prefix) - * or false if no prefixes registered for the given namespace. - * - * @param string $ns The namespace - * - * @return mixed The prefix, false if the namespace has no prefixes - */ - public function getPrefixFromNamespace($ns) - { - foreach ($this->namespaces as $p => $n) { - if ($ns == $n || $ns == $p) { - $this->usedNamespaces[$p] = $n; - - return $p; - } - } - - return false; - } - - /** - * returns the time in ODBC canonical form with microseconds. - * - * @return string The time in ODBC canonical form with microseconds - */ - public function getmicrotime() - { - if (function_exists('gettimeofday')) { - $tod = gettimeofday(); - $sec = $tod['sec']; - $usec = $tod['usec']; - } else { - $sec = time(); - $usec = 0; - } - - return strftime('%Y-%m-%d %H:%M:%S', $sec).'.'.sprintf('%06d', $usec); - } - - /** - * Returns a string with the output of var_dump. - * - * @param mixed $data The variable to var_dump - * - * @return string The output of var_dump - */ - public function varDump($data) - { - ob_start(); - var_dump($data); - $ret_val = ob_get_contents(); - ob_end_clean(); - - return $ret_val; - } - - /** - * represents the object as a string. - * - * @return string - */ - public function __toString() - { - return $this->varDump($this); - } -} - -// XML Schema Datatype Helper Functions - -//xsd:dateTime helpers - -/** - * convert unix timestamp to ISO 8601 compliant date string. - * - * @param int $timestamp Unix time stamp - * @param bool $utc Whether the time stamp is UTC or local - * - * @return mixed ISO 8601 date string or false - */ -function timestamp_to_iso8601($timestamp, $utc = true) -{ - $datestr = date('Y-m-d\TH:i:sO', $timestamp); - $pos = strrpos($datestr, '+'); - if ($pos === false) { - $pos = strrpos($datestr, '-'); - } - if ($pos !== false) { - if (strlen($datestr) == $pos + 5) { - $datestr = substr($datestr, 0, $pos + 3).':'.substr($datestr, -2); - } - } - if ($utc) { - $pattern = '/'. - '([0-9]{4})-'.// centuries & years CCYY- - '([0-9]{2})-'.// months MM- - '([0-9]{2})'.// days DD - 'T'.// separator T - '([0-9]{2}):'.// hours hh: - '([0-9]{2}):'.// minutes mm: - '([0-9]{2})(\.[0-9]*)?'.// seconds ss.ss... - '(Z|[+\-][0-9]{2}:?[0-9]{2})?'.// Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's - '/'; - - if (preg_match($pattern, $datestr, $regs)) { - return sprintf('%04d-%02d-%02dT%02d:%02d:%02dZ', $regs[1], $regs[2], $regs[3], $regs[4], $regs[5], $regs[6]); - } - - return false; - } else { - return $datestr; - } -} - -/** - * convert ISO 8601 compliant date string to unix timestamp. - * - * @param string $datestr ISO 8601 compliant date string - * - * @return mixed Unix timestamp (int) or false - */ -function iso8601_to_timestamp($datestr) -{ - $pattern = '/'. - '([0-9]{4})-'.// centuries & years CCYY- - '([0-9]{2})-'.// months MM- - '([0-9]{2})'.// days DD - 'T'.// separator T - '([0-9]{2}):'.// hours hh: - '([0-9]{2}):'.// minutes mm: - '([0-9]{2})(\.[0-9]+)?'.// seconds ss.ss... - '(Z|[+\-][0-9]{2}:?[0-9]{2})?'.// Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's - '/'; - if (preg_match($pattern, $datestr, $regs)) { - // not utc - if ($regs[8] != 'Z') { - $op = substr($regs[8], 0, 1); - $h = substr($regs[8], 1, 2); - $m = substr($regs[8], strlen($regs[8]) - 2, 2); - if ($op == '-') { - $regs[4] = $regs[4] + $h; - $regs[5] = $regs[5] + $m; - } elseif ($op == '+') { - $regs[4] = $regs[4] - $h; - $regs[5] = $regs[5] - $m; - } - } - - return gmmktime($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]); -// return strtotime("$regs[1]-$regs[2]-$regs[3] $regs[4]:$regs[5]:$regs[6]Z"); - } else { - return false; - } -} - -/** - * sleeps some number of microseconds. - * - * @param string $usec the number of microseconds to sleep - * - * @deprecated - */ -function usleepWindows($usec) -{ - $start = gettimeofday(); - - do { - $stop = gettimeofday(); - $timePassed = 1000000 * ($stop['sec'] - $start['sec']) - + $stop['usec'] - $start['usec']; - } while ($timePassed < $usec); -} diff --git a/src/Drivers/lib/class.soap_fault.php b/src/Drivers/lib/class.soap_fault.php deleted file mode 100644 index b41d6c3..0000000 --- a/src/Drivers/lib/class.soap_fault.php +++ /dev/null @@ -1,90 +0,0 @@ - - * - * @version $Id: class.soap_fault.php,v 1.14 2007/04/11 15:49:47 snichol Exp $ - */ -class nusoap_fault extends nusoap_base -{ - /* - * The fault code (client|server) - * @var string - * @access private - */ - public $faultcode; - /* - * The fault actor - * @var string - * @access private - */ - public $faultactor; - /* - * The fault string, a description of the fault - * @var string - * @access private - */ - public $faultstring; - /* - * The fault detail, typically a string or array of string - * @var mixed - * @access private - */ - public $faultdetail; - - /** - * constructor. - * - * @param string $faultcode (SOAP-ENV:Client | SOAP-ENV:Server) - * @param string $faultactor only used when msg routed between multiple actors - * @param string $faultstring human readable error message - * @param mixed $faultdetail detail, typically a string or array of string - */ - public function nusoap_fault($faultcode, $faultactor = '', $faultstring = '', $faultdetail = '') - { - parent::nusoap_base(); - $this->faultcode = $faultcode; - $this->faultactor = $faultactor; - $this->faultstring = $faultstring; - $this->faultdetail = $faultdetail; - } - - /** - * serialize a fault. - * - * @return string The serialization of the fault instance. - */ - public function serialize() - { - $ns_string = ''; - foreach ($this->namespaces as $k => $v) { - $ns_string .= "\n xmlns:$k=\"$v\""; - } - $return_msg = - 'soap_defencoding.'"?>'. - '\n". - ''. - ''. - $this->serialize_val($this->faultcode, 'faultcode'). - $this->serialize_val($this->faultactor, 'faultactor'). - $this->serialize_val($this->faultstring, 'faultstring'). - $this->serialize_val($this->faultdetail, 'detail'). - ''. - ''. - ''; - - return $return_msg; - } -} - -/** - * Backward compatibility. - */ -class soap_fault extends nusoap_fault -{ -} diff --git a/src/Drivers/lib/class.soap_parser.php b/src/Drivers/lib/class.soap_parser.php deleted file mode 100644 index 6f1bd53..0000000 --- a/src/Drivers/lib/class.soap_parser.php +++ /dev/null @@ -1,648 +0,0 @@ - - * @author Scott Nichol - * - * @version $Id: class.soap_parser.php,v 1.42 2010/04/26 20:15:08 snichol Exp $ - */ -class nusoap_parser extends nusoap_base -{ - public $xml = ''; - public $xml_encoding = ''; - public $method = ''; - public $root_struct = ''; - public $root_struct_name = ''; - public $root_struct_namespace = ''; - public $root_header = ''; - public $document = ''; // incoming SOAP body (text) - // determines where in the message we are (envelope,header,body,method) - public $status = ''; - public $position = 0; - public $depth = 0; - public $default_namespace = ''; - public $namespaces = []; - public $message = []; - public $parent = ''; - public $fault = false; - public $fault_code = ''; - public $fault_str = ''; - public $fault_detail = ''; - public $depth_array = []; - public $debug_flag = true; - public $soapresponse = null; // parsed SOAP Body - public $soapheader = null; // parsed SOAP Header - public $responseHeaders = ''; // incoming SOAP headers (text) - public $body_position = 0; - // for multiref parsing: - // array of id => pos - public $ids = []; - // array of id => hrefs => pos - public $multirefs = []; - // toggle for auto-decoding element content - public $decode_utf8 = true; - - /** - * constructor that actually does the parsing. - * - * @param string $xml SOAP message - * @param string $encoding character encoding scheme of message - * @param string $method method for which XML is parsed (unused?) - * @param string $decode_utf8 whether to decode UTF-8 to ISO-8859-1 - */ - public function nusoap_parser($xml, $encoding = 'UTF-8', $method = '', $decode_utf8 = true) - { - parent::nusoap_base(); - $this->xml = $xml; - $this->xml_encoding = $encoding; - $this->method = $method; - $this->decode_utf8 = $decode_utf8; - - // Check whether content has been read. - if (!empty($xml)) { - // Check XML encoding - $pos_xml = strpos($xml, '', $pos_xml + 2) - $pos_xml + 1); - if (preg_match("/encoding=[\"']([^\"']*)[\"']/", $xml_decl, $res)) { - $xml_encoding = $res[1]; - if (strtoupper($xml_encoding) != $encoding) { - $err = "Charset from HTTP Content-Type '".$encoding."' does not match encoding from XML declaration '".$xml_encoding."'"; - $this->debug($err); - if ($encoding != 'ISO-8859-1' || strtoupper($xml_encoding) != 'UTF-8') { - $this->setError($err); - - return; - } - // when HTTP says ISO-8859-1 (the default) and XML says UTF-8 (the typical), assume the other endpoint is just sloppy and proceed - } else { - $this->debug('Charset from HTTP Content-Type matches encoding from XML declaration'); - } - } else { - $this->debug('No encoding specified in XML declaration'); - } - } else { - $this->debug('No XML declaration'); - } - $this->debug('Entering nusoap_parser(), length='.strlen($xml).', encoding='.$encoding); - // Create an XML parser - why not xml_parser_create_ns? - $this->parser = xml_parser_create($this->xml_encoding); - // Set the options for parsing the XML data. - //xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1); - xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0); - xml_parser_set_option($this->parser, XML_OPTION_TARGET_ENCODING, $this->xml_encoding); - // Set the object for the parser. - xml_set_object($this->parser, $this); - // Set the element handlers for the parser. - xml_set_element_handler($this->parser, 'start_element', 'end_element'); - xml_set_character_data_handler($this->parser, 'character_data'); - - // Parse the XML file. - if (!xml_parse($this->parser, $xml, true)) { - // Display an error message. - $err = sprintf('XML error parsing SOAP payload on line %d: %s', - xml_get_current_line_number($this->parser), - xml_error_string(xml_get_error_code($this->parser))); - $this->debug($err); - $this->debug("XML payload:\n".$xml); - $this->setError($err); - } else { - $this->debug('in nusoap_parser ctor, message:'); - $this->appendDebug($this->varDump($this->message)); - $this->debug('parsed successfully, found root struct: '.$this->root_struct.' of name '.$this->root_struct_name); - // get final value - $this->soapresponse = $this->message[$this->root_struct]['result']; - // get header value - if ($this->root_header != '' && isset($this->message[$this->root_header]['result'])) { - $this->soapheader = $this->message[$this->root_header]['result']; - } - // resolve hrefs/ids - if (count($this->multirefs) > 0) { - foreach ($this->multirefs as $id => $hrefs) { - $this->debug('resolving multirefs for id: '.$id); - $idVal = $this->buildVal($this->ids[$id]); - if (is_array($idVal) && isset($idVal['!id'])) { - unset($idVal['!id']); - } - foreach ($hrefs as $refPos => $ref) { - $this->debug('resolving href at pos '.$refPos); - $this->multirefs[$id][$refPos] = $idVal; - } - } - } - } - xml_parser_free($this->parser); - } else { - $this->debug('xml was empty, didn\'t parse!'); - $this->setError('xml was empty, didn\'t parse!'); - } - } - - /** - * start-element handler. - * - * @param resource $parser XML parser object - * @param string $name element name - * @param array $attrs associative array of attributes - */ - public function start_element($parser, $name, $attrs) - { - // position in a total number of elements, starting from 0 - // update class level pos - $pos = $this->position++; - // and set mine - $this->message[$pos] = ['pos' => $pos, 'children' => '', 'cdata' => '']; - // depth = how many levels removed from root? - // set mine as current global depth and increment global depth value - $this->message[$pos]['depth'] = $this->depth++; - - // else add self as child to whoever the current parent is - if ($pos != 0) { - $this->message[$this->parent]['children'] .= '|'.$pos; - } - // set my parent - $this->message[$pos]['parent'] = $this->parent; - // set self as current parent - $this->parent = $pos; - // set self as current value for this depth - $this->depth_array[$this->depth] = $pos; - // get element prefix - if (strpos($name, ':')) { - // get ns prefix - $prefix = substr($name, 0, strpos($name, ':')); - // get unqualified name - $name = substr(strstr($name, ':'), 1); - } - // set status - if ($name == 'Envelope' && $this->status == '') { - $this->status = 'envelope'; - } elseif ($name == 'Header' && $this->status == 'envelope') { - $this->root_header = $pos; - $this->status = 'header'; - } elseif ($name == 'Body' && $this->status == 'envelope') { - $this->status = 'body'; - $this->body_position = $pos; - // set method - } elseif ($this->status == 'body' && $pos == ($this->body_position + 1)) { - $this->status = 'method'; - $this->root_struct_name = $name; - $this->root_struct = $pos; - $this->message[$pos]['type'] = 'struct'; - $this->debug("found root struct $this->root_struct_name, pos $this->root_struct"); - } - // set my status - $this->message[$pos]['status'] = $this->status; - // set name - $this->message[$pos]['name'] = htmlspecialchars($name); - // set attrs - $this->message[$pos]['attrs'] = $attrs; - - // loop through atts, logging ns and type declarations - $attstr = ''; - foreach ($attrs as $key => $value) { - $key_prefix = $this->getPrefix($key); - $key_localpart = $this->getLocalPart($key); - // if ns declarations, add to class level array of valid namespaces - if ($key_prefix == 'xmlns') { - if (preg_match('/^http:\/\/www.w3.org\/[0-9]{4}\/XMLSchema$/', $value)) { - $this->XMLSchemaVersion = $value; - $this->namespaces['xsd'] = $this->XMLSchemaVersion; - $this->namespaces['xsi'] = $this->XMLSchemaVersion.'-instance'; - } - $this->namespaces[$key_localpart] = $value; - // set method namespace - if ($name == $this->root_struct_name) { - $this->methodNamespace = $value; - } - // if it's a type declaration, set type - } elseif ($key_localpart == 'type') { - if (isset($this->message[$pos]['type']) && $this->message[$pos]['type'] == 'array') { - // do nothing: already processed arrayType - } else { - $value_prefix = $this->getPrefix($value); - $value_localpart = $this->getLocalPart($value); - $this->message[$pos]['type'] = $value_localpart; - $this->message[$pos]['typePrefix'] = $value_prefix; - if (isset($this->namespaces[$value_prefix])) { - $this->message[$pos]['type_namespace'] = $this->namespaces[$value_prefix]; - } elseif (isset($attrs['xmlns:'.$value_prefix])) { - $this->message[$pos]['type_namespace'] = $attrs['xmlns:'.$value_prefix]; - } - // should do something here with the namespace of specified type? - } - } elseif ($key_localpart == 'arrayType') { - $this->message[$pos]['type'] = 'array'; - /* do arrayType ereg here - [1] arrayTypeValue ::= atype asize - [2] atype ::= QName rank* - [3] rank ::= '[' (',')* ']' - [4] asize ::= '[' length~ ']' - [5] length ::= nextDimension* Digit+ - [6] nextDimension ::= Digit+ ',' - */ - $expr = '/([A-Za-z0-9_]+):([A-Za-z]+[A-Za-z0-9_]+)\[([0-9]+),?([0-9]*)\]/'; - if (preg_match($expr, $value, $regs)) { - $this->message[$pos]['typePrefix'] = $regs[1]; - $this->message[$pos]['arrayTypePrefix'] = $regs[1]; - if (isset($this->namespaces[$regs[1]])) { - $this->message[$pos]['arrayTypeNamespace'] = $this->namespaces[$regs[1]]; - } elseif (isset($attrs['xmlns:'.$regs[1]])) { - $this->message[$pos]['arrayTypeNamespace'] = $attrs['xmlns:'.$regs[1]]; - } - $this->message[$pos]['arrayType'] = $regs[2]; - $this->message[$pos]['arraySize'] = $regs[3]; - $this->message[$pos]['arrayCols'] = $regs[4]; - } - // specifies nil value (or not) - } elseif ($key_localpart == 'nil') { - $this->message[$pos]['nil'] = ($value == 'true' || $value == '1'); - // some other attribute - } elseif ($key != 'href' && $key != 'xmlns' && $key_localpart != 'encodingStyle' && $key_localpart != 'root') { - $this->message[$pos]['xattrs']['!'.$key] = $value; - } - - if ($key == 'xmlns') { - $this->default_namespace = $value; - } - // log id - if ($key == 'id') { - $this->ids[$value] = $pos; - } - // root - if ($key_localpart == 'root' && $value == 1) { - $this->status = 'method'; - $this->root_struct_name = $name; - $this->root_struct = $pos; - $this->debug("found root struct $this->root_struct_name, pos $pos"); - } - // for doclit - $attstr .= " $key=\"$value\""; - } - // get namespace - must be done after namespace atts are processed - if (isset($prefix)) { - $this->message[$pos]['namespace'] = $this->namespaces[$prefix]; - $this->default_namespace = $this->namespaces[$prefix]; - } else { - $this->message[$pos]['namespace'] = $this->default_namespace; - } - if ($this->status == 'header') { - if ($this->root_header != $pos) { - $this->responseHeaders .= '<'.(isset($prefix) ? $prefix.':' : '')."$name$attstr>"; - } - } elseif ($this->root_struct_name != '') { - $this->document .= '<'.(isset($prefix) ? $prefix.':' : '')."$name$attstr>"; - } - } - - /** - * end-element handler. - * - * @param resource $parser XML parser object - * @param string $name element name - */ - public function end_element($parser, $name) - { - // position of current element is equal to the last value left in depth_array for my depth - $pos = $this->depth_array[$this->depth--]; - - // get element prefix - if (strpos($name, ':')) { - // get ns prefix - $prefix = substr($name, 0, strpos($name, ':')); - // get unqualified name - $name = substr(strstr($name, ':'), 1); - } - - // build to native type - if (isset($this->body_position) && $pos > $this->body_position) { - // deal w/ multirefs - if (isset($this->message[$pos]['attrs']['href'])) { - // get id - $id = substr($this->message[$pos]['attrs']['href'], 1); - // add placeholder to href array - $this->multirefs[$id][$pos] = 'placeholder'; - // add set a reference to it as the result value - $this->message[$pos]['result'] = &$this->multirefs[$id][$pos]; - // build complexType values - } elseif ($this->message[$pos]['children'] != '') { - // if result has already been generated (struct/array) - if (!isset($this->message[$pos]['result'])) { - $this->message[$pos]['result'] = $this->buildVal($pos); - } - // build complexType values of attributes and possibly simpleContent - } elseif (isset($this->message[$pos]['xattrs'])) { - if (isset($this->message[$pos]['nil']) && $this->message[$pos]['nil']) { - $this->message[$pos]['xattrs']['!'] = null; - } elseif (isset($this->message[$pos]['cdata']) && trim($this->message[$pos]['cdata']) != '') { - if (isset($this->message[$pos]['type'])) { - $this->message[$pos]['xattrs']['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$pos]['type'], isset($this->message[$pos]['type_namespace']) ? $this->message[$pos]['type_namespace'] : ''); - } else { - $parent = $this->message[$pos]['parent']; - if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) { - $this->message[$pos]['xattrs']['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : ''); - } else { - $this->message[$pos]['xattrs']['!'] = $this->message[$pos]['cdata']; - } - } - } - $this->message[$pos]['result'] = $this->message[$pos]['xattrs']; - // set value of simpleType (or nil complexType) - } else { - //$this->debug('adding data for scalar value '.$this->message[$pos]['name'].' of value '.$this->message[$pos]['cdata']); - if (isset($this->message[$pos]['nil']) && $this->message[$pos]['nil']) { - $this->message[$pos]['xattrs']['!'] = null; - } elseif (isset($this->message[$pos]['type'])) { - $this->message[$pos]['result'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$pos]['type'], isset($this->message[$pos]['type_namespace']) ? $this->message[$pos]['type_namespace'] : ''); - } else { - $parent = $this->message[$pos]['parent']; - if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) { - $this->message[$pos]['result'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : ''); - } else { - $this->message[$pos]['result'] = $this->message[$pos]['cdata']; - } - } - - /* add value to parent's result, if parent is struct/array - $parent = $this->message[$pos]['parent']; - if($this->message[$parent]['type'] != 'map'){ - if(strtolower($this->message[$parent]['type']) == 'array'){ - $this->message[$parent]['result'][] = $this->message[$pos]['result']; - } else { - $this->message[$parent]['result'][$this->message[$pos]['name']] = $this->message[$pos]['result']; - } - } - */ - } - } - - // for doclit - if ($this->status == 'header') { - if ($this->root_header != $pos) { - $this->responseHeaders .= '"; - } - } elseif ($pos >= $this->root_struct) { - $this->document .= '"; - } - // switch status - if ($pos == $this->root_struct) { - $this->status = 'body'; - $this->root_struct_namespace = $this->message[$pos]['namespace']; - } elseif ($pos == $this->root_header) { - $this->status = 'envelope'; - } elseif ($name == 'Body' && $this->status == 'body') { - $this->status = 'envelope'; - } elseif ($name == 'Header' && $this->status == 'header') { // will never happen - $this->status = 'envelope'; - } elseif ($name == 'Envelope' && $this->status == 'envelope') { - $this->status = ''; - } - // set parent back to my parent - $this->parent = $this->message[$pos]['parent']; - } - - /** - * element content handler. - * - * @param resource $parser XML parser object - * @param string $data element content - */ - public function character_data($parser, $data) - { - $pos = $this->depth_array[$this->depth]; - if ($this->xml_encoding == 'UTF-8') { - // TODO: add an option to disable this for folks who want - // raw UTF-8 that, e.g., might not map to iso-8859-1 - // TODO: this can also be handled with xml_parser_set_option($this->parser, XML_OPTION_TARGET_ENCODING, "ISO-8859-1"); - if ($this->decode_utf8) { - $data = utf8_decode($data); - } - } - $this->message[$pos]['cdata'] .= $data; - // for doclit - if ($this->status == 'header') { - $this->responseHeaders .= $data; - } else { - $this->document .= $data; - } - } - - /** - * get the parsed message (SOAP Body). - * - * @return mixed - * - * @deprecated use get_soapbody instead - */ - public function get_response() - { - return $this->soapresponse; - } - - /** - * get the parsed SOAP Body (NULL if there was none). - * - * @return mixed - */ - public function get_soapbody() - { - return $this->soapresponse; - } - - /** - * get the parsed SOAP Header (NULL if there was none). - * - * @return mixed - */ - public function get_soapheader() - { - return $this->soapheader; - } - - /** - * get the unparsed SOAP Header. - * - * @return string XML or empty if no Header - */ - public function getHeaders() - { - return $this->responseHeaders; - } - - /** - * decodes simple types into PHP variables. - * - * @param string $value value to decode - * @param string $type XML type to decode - * @param string $typens XML type namespace to decode - * - * @return mixed PHP value - */ - public function decodeSimple($value, $type, $typens) - { - // TODO: use the namespace! - if ((!isset($type)) || $type == 'string' || $type == 'long' || $type == 'unsignedLong') { - return (string) $value; - } - if ($type == 'int' || $type == 'integer' || $type == 'short' || $type == 'byte') { - return (int) $value; - } - if ($type == 'float' || $type == 'double' || $type == 'decimal') { - return (float) $value; - } - if ($type == 'boolean') { - if (strtolower($value) == 'false' || strtolower($value) == 'f') { - return false; - } - - return (bool) $value; - } - if ($type == 'base64' || $type == 'base64Binary') { - $this->debug('Decode base64 value'); - - return base64_decode($value); - } - // obscure numeric types - if ($type == 'nonPositiveInteger' || $type == 'negativeInteger' - || $type == 'nonNegativeInteger' || $type == 'positiveInteger' - || $type == 'unsignedInt' - || $type == 'unsignedShort' || $type == 'unsignedByte') { - return (int) $value; - } - // bogus: parser treats array with no elements as a simple type - if ($type == 'array') { - return []; - } - // everything else - return (string) $value; - } - - /** - * builds response structures for compound values (arrays/structs) - * and scalars. - * - * @param int $pos position in node tree - * - * @return mixed PHP value - */ - public function buildVal($pos) - { - if (!isset($this->message[$pos]['type'])) { - $this->message[$pos]['type'] = ''; - } - $this->debug('in buildVal() for '.$this->message[$pos]['name']."(pos $pos) of type ".$this->message[$pos]['type']); - // if there are children... - if ($this->message[$pos]['children'] != '') { - $this->debug('in buildVal, there are children'); - $children = explode('|', $this->message[$pos]['children']); - array_shift($children); // knock off empty - // md array - if (isset($this->message[$pos]['arrayCols']) && $this->message[$pos]['arrayCols'] != '') { - $r = 0; // rowcount - $c = 0; // colcount - foreach ($children as $child_pos) { - $this->debug("in buildVal, got an MD array element: $r, $c"); - $params[$r][] = $this->message[$child_pos]['result']; - $c++; - if ($c == $this->message[$pos]['arrayCols']) { - $c = 0; - $r++; - } - } - // array - } elseif ($this->message[$pos]['type'] == 'array' || $this->message[$pos]['type'] == 'Array') { - $this->debug('in buildVal, adding array '.$this->message[$pos]['name']); - foreach ($children as $child_pos) { - $params[] = &$this->message[$child_pos]['result']; - } - // apache Map type: java hashtable - } elseif ($this->message[$pos]['type'] == 'Map' && $this->message[$pos]['type_namespace'] == 'http://xml.apache.org/xml-soap') { - $this->debug('in buildVal, Java Map '.$this->message[$pos]['name']); - foreach ($children as $child_pos) { - $kv = explode('|', $this->message[$child_pos]['children']); - $params[$this->message[$kv[1]]['result']] = &$this->message[$kv[2]]['result']; - } - // generic compound type - //} elseif($this->message[$pos]['type'] == 'SOAPStruct' || $this->message[$pos]['type'] == 'struct') { - } else { - // Apache Vector type: treat as an array - $this->debug('in buildVal, adding Java Vector or generic compound type '.$this->message[$pos]['name']); - if ($this->message[$pos]['type'] == 'Vector' && $this->message[$pos]['type_namespace'] == 'http://xml.apache.org/xml-soap') { - $notstruct = 1; - } else { - $notstruct = 0; - } - // - foreach ($children as $child_pos) { - if ($notstruct) { - $params[] = &$this->message[$child_pos]['result']; - } else { - if (isset($params[$this->message[$child_pos]['name']])) { - // de-serialize repeated element name into an array - if ((!is_array($params[$this->message[$child_pos]['name']])) || (!isset($params[$this->message[$child_pos]['name']][0]))) { - $params[$this->message[$child_pos]['name']] = [$params[$this->message[$child_pos]['name']]]; - } - $params[$this->message[$child_pos]['name']][] = &$this->message[$child_pos]['result']; - } else { - $params[$this->message[$child_pos]['name']] = &$this->message[$child_pos]['result']; - } - } - } - } - if (isset($this->message[$pos]['xattrs'])) { - $this->debug('in buildVal, handling attributes'); - foreach ($this->message[$pos]['xattrs'] as $n => $v) { - $params[$n] = $v; - } - } - // handle simpleContent - if (isset($this->message[$pos]['cdata']) && trim($this->message[$pos]['cdata']) != '') { - $this->debug('in buildVal, handling simpleContent'); - if (isset($this->message[$pos]['type'])) { - $params['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$pos]['type'], isset($this->message[$pos]['type_namespace']) ? $this->message[$pos]['type_namespace'] : ''); - } else { - $parent = $this->message[$pos]['parent']; - if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) { - $params['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : ''); - } else { - $params['!'] = $this->message[$pos]['cdata']; - } - } - } - $ret = is_array($params) ? $params : []; - $this->debug('in buildVal, return:'); - $this->appendDebug($this->varDump($ret)); - - return $ret; - } else { - $this->debug('in buildVal, no children, building scalar'); - $cdata = isset($this->message[$pos]['cdata']) ? $this->message[$pos]['cdata'] : ''; - if (isset($this->message[$pos]['type'])) { - $ret = $this->decodeSimple($cdata, $this->message[$pos]['type'], isset($this->message[$pos]['type_namespace']) ? $this->message[$pos]['type_namespace'] : ''); - $this->debug("in buildVal, return: $ret"); - - return $ret; - } - $parent = $this->message[$pos]['parent']; - if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) { - $ret = $this->decodeSimple($cdata, $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : ''); - $this->debug("in buildVal, return: $ret"); - - return $ret; - } - $ret = $this->message[$pos]['cdata']; - $this->debug("in buildVal, return: $ret"); - - return $ret; - } - } -} - -/** - * Backward compatibility. - */ -class soap_parser extends nusoap_parser -{ -} diff --git a/src/Drivers/lib/class.soap_server.php b/src/Drivers/lib/class.soap_server.php deleted file mode 100644 index c259729..0000000 --- a/src/Drivers/lib/class.soap_server.php +++ /dev/null @@ -1,1137 +0,0 @@ - - * @author Scott Nichol - * - * @version $Id: class.soap_server.php,v 1.63 2010/04/26 20:15:08 snichol Exp $ - */ -class nusoap_server extends nusoap_base -{ - /* - * HTTP headers of request - * @var array - * @access private - */ - public $headers = []; - /* - * HTTP request - * @var string - * @access private - */ - public $request = ''; - /* - * SOAP headers from request (incomplete namespace resolution; special characters not escaped) (text) - * @var string - * @access public - */ - public $requestHeaders = ''; - /* - * SOAP Headers from request (parsed) - * @var mixed - * @access public - */ - public $requestHeader = null; - /* - * SOAP body request portion (incomplete namespace resolution; special characters not escaped) (text) - * @var string - * @access public - */ - public $document = ''; - /* - * SOAP payload for request (text) - * @var string - * @access public - */ - public $requestSOAP = ''; - /* - * requested method namespace URI - * @var string - * @access private - */ - public $methodURI = ''; - /* - * name of method requested - * @var string - * @access private - */ - public $methodname = ''; - /* - * method parameters from request - * @var array - * @access private - */ - public $methodparams = []; - /* - * SOAP Action from request - * @var string - * @access private - */ - public $SOAPAction = ''; - /* - * character set encoding of incoming (request) messages - * @var string - * @access public - */ - public $xml_encoding = ''; - /* - * toggles whether the parser decodes element content w/ utf8_decode() - * @var boolean - * @access public - */ - public $decode_utf8 = true; - - /* - * HTTP headers of response - * @var array - * @access public - */ - public $outgoing_headers = []; - /* - * HTTP response - * @var string - * @access private - */ - public $response = ''; - /* - * SOAP headers for response (text or array of soapval or associative array) - * @var mixed - * @access public - */ - public $responseHeaders = ''; - /* - * SOAP payload for response (text) - * @var string - * @access private - */ - public $responseSOAP = ''; - /* - * method return value to place in response - * @var mixed - * @access private - */ - public $methodreturn = false; - /* - * whether $methodreturn is a string of literal XML - * @var boolean - * @access public - */ - public $methodreturnisliteralxml = false; - /* - * SOAP fault for response (or false) - * @var mixed - * @access private - */ - public $fault = false; - /* - * text indication of result (for debugging) - * @var string - * @access private - */ - public $result = 'successful'; - - /* - * assoc array of operations => opData; operations are added by the register() - * method or by parsing an external WSDL definition - * @var array - * @access private - */ - public $operations = []; - /* - * wsdl instance (if one) - * @var mixed - * @access private - */ - public $wsdl = false; - /* - * URL for WSDL (if one) - * @var mixed - * @access private - */ - public $externalWSDLURL = false; - /* - * whether to append debug to response as XML comment - * @var boolean - * @access public - */ - public $debug_flag = false; - - /** - * constructor - * the optional parameter is a path to a WSDL file that you'd like to bind the server instance to. - * - * @param mixed $wsdl file path or URL (string), or wsdl instance (object) - */ - public function nusoap_server($wsdl = false) - { - parent::nusoap_base(); - // turn on debugging? - global $debug; - global $HTTP_SERVER_VARS; - - if (isset($_SERVER)) { - $this->debug('_SERVER is defined:'); - $this->appendDebug($this->varDump($_SERVER)); - } elseif (isset($HTTP_SERVER_VARS)) { - $this->debug('HTTP_SERVER_VARS is defined:'); - $this->appendDebug($this->varDump($HTTP_SERVER_VARS)); - } else { - $this->debug('Neither _SERVER nor HTTP_SERVER_VARS is defined.'); - } - - if (isset($debug)) { - $this->debug("In nusoap_server, set debug_flag=$debug based on global flag"); - $this->debug_flag = $debug; - } elseif (isset($_SERVER['QUERY_STRING'])) { - $qs = explode('&', $_SERVER['QUERY_STRING']); - foreach ($qs as $v) { - if (substr($v, 0, 6) == 'debug=') { - $this->debug('In nusoap_server, set debug_flag='.substr($v, 6).' based on query string #1'); - $this->debug_flag = substr($v, 6); - } - } - } elseif (isset($HTTP_SERVER_VARS['QUERY_STRING'])) { - $qs = explode('&', $HTTP_SERVER_VARS['QUERY_STRING']); - foreach ($qs as $v) { - if (substr($v, 0, 6) == 'debug=') { - $this->debug('In nusoap_server, set debug_flag='.substr($v, 6).' based on query string #2'); - $this->debug_flag = substr($v, 6); - } - } - } - - // wsdl - if ($wsdl) { - $this->debug('In nusoap_server, WSDL is specified'); - if (is_object($wsdl) && (get_class($wsdl) == 'wsdl')) { - $this->wsdl = $wsdl; - $this->externalWSDLURL = $this->wsdl->wsdl; - $this->debug('Use existing wsdl instance from '.$this->externalWSDLURL); - } else { - $this->debug('Create wsdl from '.$wsdl); - $this->wsdl = new wsdl($wsdl); - $this->externalWSDLURL = $wsdl; - } - $this->appendDebug($this->wsdl->getDebug()); - $this->wsdl->clearDebug(); - if ($err = $this->wsdl->getError()) { - die('WSDL ERROR: '.$err); - } - } - } - - /** - * processes request and returns response. - * - * @param string $data usually is the value of $HTTP_RAW_POST_DATA - */ - public function service($data) - { - global $HTTP_SERVER_VARS; - - if (isset($_SERVER['REQUEST_METHOD'])) { - $rm = $_SERVER['REQUEST_METHOD']; - } elseif (isset($HTTP_SERVER_VARS['REQUEST_METHOD'])) { - $rm = $HTTP_SERVER_VARS['REQUEST_METHOD']; - } else { - $rm = ''; - } - - if (isset($_SERVER['QUERY_STRING'])) { - $qs = $_SERVER['QUERY_STRING']; - } elseif (isset($HTTP_SERVER_VARS['QUERY_STRING'])) { - $qs = $HTTP_SERVER_VARS['QUERY_STRING']; - } else { - $qs = ''; - } - $this->debug("In service, request method=$rm query string=$qs strlen(\$data)=".strlen($data)); - - if ($rm == 'POST') { - $this->debug('In service, invoke the request'); - $this->parse_request($data); - if (!$this->fault) { - $this->invoke_method(); - } - if (!$this->fault) { - $this->serialize_return(); - } - $this->send_response(); - } elseif (preg_match('/wsdl/', $qs)) { - $this->debug('In service, this is a request for WSDL'); - if ($this->externalWSDLURL) { - if (strpos($this->externalWSDLURL, 'http://') !== false) { // assume URL - $this->debug('In service, re-direct for WSDL'); - header('Location: '.$this->externalWSDLURL); - } else { // assume file - $this->debug('In service, use file passthru for WSDL'); - header("Content-Type: text/xml\r\n"); - $pos = strpos($this->externalWSDLURL, 'file://'); - if ($pos === false) { - $filename = $this->externalWSDLURL; - } else { - $filename = substr($this->externalWSDLURL, $pos + 7); - } - $fp = fopen($this->externalWSDLURL, 'r'); - fpassthru($fp); - } - } elseif ($this->wsdl) { - $this->debug('In service, serialize WSDL'); - header("Content-Type: text/xml; charset=ISO-8859-1\r\n"); - echo $this->wsdl->serialize($this->debug_flag); - if ($this->debug_flag) { - $this->debug('wsdl:'); - $this->appendDebug($this->varDump($this->wsdl)); - echo $this->getDebugAsXMLComment(); - } - } else { - $this->debug('In service, there is no WSDL'); - header("Content-Type: text/html; charset=ISO-8859-1\r\n"); - echo 'This service does not provide WSDL'; - } - } elseif ($this->wsdl) { - $this->debug('In service, return Web description'); - echo $this->wsdl->webDescription(); - } else { - $this->debug('In service, no Web description'); - header("Content-Type: text/html; charset=ISO-8859-1\r\n"); - echo 'This service does not provide a Web description'; - } - } - - /** - * parses HTTP request headers. - * - * The following fields are set by this function (when successful) - * - * headers - * request - * xml_encoding - * SOAPAction - */ - public function parse_http_headers() - { - global $HTTP_SERVER_VARS; - - $this->request = ''; - $this->SOAPAction = ''; - if (function_exists('getallheaders')) { - $this->debug('In parse_http_headers, use getallheaders'); - $headers = getallheaders(); - foreach ($headers as $k => $v) { - $k = strtolower($k); - $this->headers[$k] = $v; - $this->request .= "$k: $v\r\n"; - $this->debug("$k: $v"); - } - // get SOAPAction header - if (isset($this->headers['soapaction'])) { - $this->SOAPAction = str_replace('"', '', $this->headers['soapaction']); - } - // get the character encoding of the incoming request - if (isset($this->headers['content-type']) && strpos($this->headers['content-type'], '=')) { - $enc = str_replace('"', '', substr(strstr($this->headers['content-type'], '='), 1)); - if (preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i', $enc)) { - $this->xml_encoding = strtoupper($enc); - } else { - $this->xml_encoding = 'US-ASCII'; - } - } else { - // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1 - $this->xml_encoding = 'ISO-8859-1'; - } - } elseif (isset($_SERVER) && is_array($_SERVER)) { - $this->debug('In parse_http_headers, use _SERVER'); - foreach ($_SERVER as $k => $v) { - if (substr($k, 0, 5) == 'HTTP_') { - $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', substr($k, 5)))); - } else { - $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', $k))); - } - if ($k == 'soapaction') { - // get SOAPAction header - $k = 'SOAPAction'; - $v = str_replace('"', '', $v); - $v = str_replace('\\', '', $v); - $this->SOAPAction = $v; - } elseif ($k == 'content-type') { - // get the character encoding of the incoming request - if (strpos($v, '=')) { - $enc = substr(strstr($v, '='), 1); - $enc = str_replace('"', '', $enc); - $enc = str_replace('\\', '', $enc); - if (preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i', $enc)) { - $this->xml_encoding = strtoupper($enc); - } else { - $this->xml_encoding = 'US-ASCII'; - } - } else { - // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1 - $this->xml_encoding = 'ISO-8859-1'; - } - } - $this->headers[$k] = $v; - $this->request .= "$k: $v\r\n"; - $this->debug("$k: $v"); - } - } elseif (is_array($HTTP_SERVER_VARS)) { - $this->debug('In parse_http_headers, use HTTP_SERVER_VARS'); - foreach ($HTTP_SERVER_VARS as $k => $v) { - if (substr($k, 0, 5) == 'HTTP_') { - $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', substr($k, 5)))); - $k = strtolower(substr($k, 5)); - } else { - $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', $k))); - $k = strtolower($k); - } - if ($k == 'soapaction') { - // get SOAPAction header - $k = 'SOAPAction'; - $v = str_replace('"', '', $v); - $v = str_replace('\\', '', $v); - $this->SOAPAction = $v; - } elseif ($k == 'content-type') { - // get the character encoding of the incoming request - if (strpos($v, '=')) { - $enc = substr(strstr($v, '='), 1); - $enc = str_replace('"', '', $enc); - $enc = str_replace('\\', '', $enc); - if (preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i', $enc)) { - $this->xml_encoding = strtoupper($enc); - } else { - $this->xml_encoding = 'US-ASCII'; - } - } else { - // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1 - $this->xml_encoding = 'ISO-8859-1'; - } - } - $this->headers[$k] = $v; - $this->request .= "$k: $v\r\n"; - $this->debug("$k: $v"); - } - } else { - $this->debug('In parse_http_headers, HTTP headers not accessible'); - $this->setError('HTTP headers not accessible'); - } - } - - /** - * parses a request. - * - * The following fields are set by this function (when successful) - * - * headers - * request - * xml_encoding - * SOAPAction - * request - * requestSOAP - * methodURI - * methodname - * methodparams - * requestHeaders - * document - * - * This sets the fault field on error - * - * @param string $data XML string - */ - public function parse_request($data = '') - { - $this->debug('entering parse_request()'); - $this->parse_http_headers(); - $this->debug('got character encoding: '.$this->xml_encoding); - // uncompress if necessary - if (isset($this->headers['content-encoding']) && $this->headers['content-encoding'] != '') { - $this->debug('got content encoding: '.$this->headers['content-encoding']); - if ($this->headers['content-encoding'] == 'deflate' || $this->headers['content-encoding'] == 'gzip') { - // if decoding works, use it. else assume data wasn't gzencoded - if (function_exists('gzuncompress')) { - if ($this->headers['content-encoding'] == 'deflate' && $degzdata = @gzuncompress($data)) { - $data = $degzdata; - } elseif ($this->headers['content-encoding'] == 'gzip' && $degzdata = gzinflate(substr($data, 10))) { - $data = $degzdata; - } else { - $this->fault('SOAP-ENV:Client', 'Errors occurred when trying to decode the data'); - - return; - } - } else { - $this->fault('SOAP-ENV:Client', 'This Server does not support compressed data'); - - return; - } - } - } - $this->request .= "\r\n".$data; - $data = $this->parseRequest($this->headers, $data); - $this->requestSOAP = $data; - $this->debug('leaving parse_request'); - } - - /** - * invokes a PHP function for the requested SOAP method. - * - * The following fields are set by this function (when successful) - * - * methodreturn - * - * Note that the PHP function that is called may also set the following - * fields to affect the response sent to the client - * - * responseHeaders - * outgoing_headers - * - * This sets the fault field on error - */ - public function invoke_method() - { - $this->debug('in invoke_method, methodname='.$this->methodname.' methodURI='.$this->methodURI.' SOAPAction='.$this->SOAPAction); - - // - // if you are debugging in this area of the code, your service uses a class to implement methods, - // you use SOAP RPC, and the client is .NET, please be aware of the following... - // when the .NET wsdl.exe utility generates a proxy, it will remove the '.' or '..' from the - // method name. that is fine for naming the .NET methods. it is not fine for properly constructing - // the XML request and reading the XML response. you need to add the RequestElementName and - // ResponseElementName to the System.Web.Services.Protocols.SoapRpcMethodAttribute that wsdl.exe - // generates for the method. these parameters are used to specify the correct XML element names - // for .NET to use, i.e. the names with the '.' in them. - // - $orig_methodname = $this->methodname; - if ($this->wsdl) { - if ($this->opData = $this->wsdl->getOperationData($this->methodname)) { - $this->debug('in invoke_method, found WSDL operation='.$this->methodname); - $this->appendDebug('opData='.$this->varDump($this->opData)); - } elseif ($this->opData = $this->wsdl->getOperationDataForSoapAction($this->SOAPAction)) { - // Note: hopefully this case will only be used for doc/lit, since rpc services should have wrapper element - $this->debug('in invoke_method, found WSDL soapAction='.$this->SOAPAction.' for operation='.$this->opData['name']); - $this->appendDebug('opData='.$this->varDump($this->opData)); - $this->methodname = $this->opData['name']; - } else { - $this->debug('in invoke_method, no WSDL for operation='.$this->methodname); - $this->fault('SOAP-ENV:Client', "Operation '".$this->methodname."' is not defined in the WSDL for this service"); - - return; - } - } else { - $this->debug('in invoke_method, no WSDL to validate method'); - } - - // if a . is present in $this->methodname, we see if there is a class in scope, - // which could be referred to. We will also distinguish between two deliminators, - // to allow methods to be called a the class or an instance - if (strpos($this->methodname, '..') > 0) { - $delim = '..'; - } elseif (strpos($this->methodname, '.') > 0) { - $delim = '.'; - } else { - $delim = ''; - } - $this->debug("in invoke_method, delim=$delim"); - - $class = ''; - $method = ''; - if (strlen($delim) > 0 && substr_count($this->methodname, $delim) == 1) { - $try_class = substr($this->methodname, 0, strpos($this->methodname, $delim)); - if (class_exists($try_class)) { - // get the class and method name - $class = $try_class; - $method = substr($this->methodname, strpos($this->methodname, $delim) + strlen($delim)); - $this->debug("in invoke_method, class=$class method=$method delim=$delim"); - } else { - $this->debug("in invoke_method, class=$try_class not found"); - } - } else { - $try_class = ''; - $this->debug('in invoke_method, no class to try'); - } - - // does method exist? - if ($class == '') { - if (!function_exists($this->methodname)) { - $this->debug("in invoke_method, function '$this->methodname' not found!"); - $this->result = 'fault: method not found'; - $this->fault('SOAP-ENV:Client', "method '$this->methodname'('$orig_methodname') not defined in service('$try_class' '$delim')"); - - return; - } - } else { - $method_to_compare = (substr(phpversion(), 0, 2) == '4.') ? strtolower($method) : $method; - if (!in_array($method_to_compare, get_class_methods($class))) { - $this->debug("in invoke_method, method '$this->methodname' not found in class '$class'!"); - $this->result = 'fault: method not found'; - $this->fault('SOAP-ENV:Client', "method '$this->methodname'/'$method_to_compare'('$orig_methodname') not defined in service/'$class'('$try_class' '$delim')"); - - return; - } - } - - // evaluate message, getting back parameters - // verify that request parameters match the method's signature - if (!$this->verify_method($this->methodname, $this->methodparams)) { - // debug - $this->debug('ERROR: request not verified against method signature'); - $this->result = 'fault: request failed validation against method signature'; - // return fault - $this->fault('SOAP-ENV:Client', "Operation '$this->methodname' not defined in service."); - - return; - } - - // if there are parameters to pass - $this->debug('in invoke_method, params:'); - $this->appendDebug($this->varDump($this->methodparams)); - $this->debug("in invoke_method, calling '$this->methodname'"); - if (!function_exists('call_user_func_array')) { - if ($class == '') { - $this->debug('in invoke_method, calling function using eval()'); - $funcCall = "\$this->methodreturn = $this->methodname("; - } else { - if ($delim == '..') { - $this->debug('in invoke_method, calling class method using eval()'); - $funcCall = '$this->methodreturn = '.$class.'::'.$method.'('; - } else { - $this->debug('in invoke_method, calling instance method using eval()'); - // generate unique instance name - $instname = '$inst_'.time(); - $funcCall = $instname.' = new '.$class.'(); '; - $funcCall .= '$this->methodreturn = '.$instname.'->'.$method.'('; - } - } - if ($this->methodparams) { - foreach ($this->methodparams as $param) { - if (is_array($param) || is_object($param)) { - $this->fault('SOAP-ENV:Client', 'NuSOAP does not handle complexType parameters correctly when using eval; call_user_func_array must be available'); - - return; - } - $funcCall .= "\"$param\","; - } - $funcCall = substr($funcCall, 0, -1); - } - $funcCall .= ');'; - $this->debug('in invoke_method, function call: '.$funcCall); - @eval($funcCall); - } else { - if ($class == '') { - $this->debug('in invoke_method, calling function using call_user_func_array()'); - $call_arg = "$this->methodname"; // straight assignment changes $this->methodname to lower case after call_user_func_array() - } elseif ($delim == '..') { - $this->debug('in invoke_method, calling class method using call_user_func_array()'); - $call_arg = [$class, $method]; - } else { - $this->debug('in invoke_method, calling instance method using call_user_func_array()'); - $instance = new $class (); - $call_arg = [&$instance, $method]; - } - if (is_array($this->methodparams)) { - $this->methodreturn = call_user_func_array($call_arg, array_values($this->methodparams)); - } else { - $this->methodreturn = call_user_func_array($call_arg, []); - } - } - $this->debug('in invoke_method, methodreturn:'); - $this->appendDebug($this->varDump($this->methodreturn)); - $this->debug("in invoke_method, called method $this->methodname, received data of type ".gettype($this->methodreturn)); - } - - /** - * serializes the return value from a PHP function into a full SOAP Envelope. - * - * The following fields are set by this function (when successful) - * - * responseSOAP - * - * This sets the fault field on error - */ - public function serialize_return() - { - $this->debug('Entering serialize_return methodname: '.$this->methodname.' methodURI: '.$this->methodURI); - // if fault - if (isset($this->methodreturn) && is_object($this->methodreturn) && ((get_class($this->methodreturn) == 'soap_fault') || (get_class($this->methodreturn) == 'nusoap_fault'))) { - $this->debug('got a fault object from method'); - $this->fault = $this->methodreturn; - - return; - } elseif ($this->methodreturnisliteralxml) { - $return_val = $this->methodreturn; - // returned value(s) - } else { - $this->debug('got a(n) '.gettype($this->methodreturn).' from method'); - $this->debug('serializing return value'); - if ($this->wsdl) { - if (count($this->opData['output']['parts']) > 1) { - $this->debug('more than one output part, so use the method return unchanged'); - $opParams = $this->methodreturn; - } elseif (count($this->opData['output']['parts']) == 1) { - $this->debug('exactly one output part, so wrap the method return in a simple array'); - // TODO: verify that it is not already wrapped! - //foreach ($this->opData['output']['parts'] as $name => $type) { - // $this->debug('wrap in element named ' . $name); - //} - $opParams = [$this->methodreturn]; - } - $return_val = $this->wsdl->serializeRPCParameters($this->methodname, 'output', $opParams); - $this->appendDebug($this->wsdl->getDebug()); - $this->wsdl->clearDebug(); - if ($errstr = $this->wsdl->getError()) { - $this->debug('got wsdl error: '.$errstr); - $this->fault('SOAP-ENV:Server', 'unable to serialize result'); - - return; - } - } else { - if (isset($this->methodreturn)) { - $return_val = $this->serialize_val($this->methodreturn, 'return'); - } else { - $return_val = ''; - $this->debug('in absence of WSDL, assume void return for backward compatibility'); - } - } - } - $this->debug('return value:'); - $this->appendDebug($this->varDump($return_val)); - - $this->debug('serializing response'); - if ($this->wsdl) { - $this->debug('have WSDL for serialization: style is '.$this->opData['style']); - if ($this->opData['style'] == 'rpc') { - $this->debug('style is rpc for serialization: use is '.$this->opData['output']['use']); - if ($this->opData['output']['use'] == 'literal') { - // http://www.ws-i.org/Profiles/BasicProfile-1.1-2004-08-24.html R2735 says rpc/literal accessor elements should not be in a namespace - if ($this->methodURI) { - $payload = 'methodname.'Response xmlns:ns1="'.$this->methodURI.'">'.$return_val.'methodname.'Response>'; - } else { - $payload = '<'.$this->methodname.'Response>'.$return_val.'methodname.'Response>'; - } - } else { - if ($this->methodURI) { - $payload = 'methodname.'Response xmlns:ns1="'.$this->methodURI.'">'.$return_val.'methodname.'Response>'; - } else { - $payload = '<'.$this->methodname.'Response>'.$return_val.'methodname.'Response>'; - } - } - } else { - $this->debug('style is not rpc for serialization: assume document'); - $payload = $return_val; - } - } else { - $this->debug('do not have WSDL for serialization: assume rpc/encoded'); - $payload = 'methodname.'Response xmlns:ns1="'.$this->methodURI.'">'.$return_val.'methodname.'Response>'; - } - $this->result = 'successful'; - if ($this->wsdl) { - //if($this->debug_flag){ - $this->appendDebug($this->wsdl->getDebug()); - // } - if (isset($this->opData['output']['encodingStyle'])) { - $encodingStyle = $this->opData['output']['encodingStyle']; - } else { - $encodingStyle = ''; - } - // Added: In case we use a WSDL, return a serialized env. WITH the usedNamespaces. - $this->responseSOAP = $this->serializeEnvelope($payload, $this->responseHeaders, $this->wsdl->usedNamespaces, $this->opData['style'], $this->opData['output']['use'], $encodingStyle); - } else { - $this->responseSOAP = $this->serializeEnvelope($payload, $this->responseHeaders); - } - $this->debug('Leaving serialize_return'); - } - - /** - * sends an HTTP response. - * - * The following fields are set by this function (when successful) - * - * outgoing_headers - * response - */ - public function send_response() - { - $this->debug('Enter send_response'); - if ($this->fault) { - $payload = $this->fault->serialize(); - $this->outgoing_headers[] = 'HTTP/1.0 500 Internal Server Error'; - $this->outgoing_headers[] = 'Status: 500 Internal Server Error'; - } else { - $payload = $this->responseSOAP; - // Some combinations of PHP+Web server allow the Status - // to come through as a header. Since OK is the default - // just do nothing. - // $this->outgoing_headers[] = "HTTP/1.0 200 OK"; - // $this->outgoing_headers[] = "Status: 200 OK"; - } - // add debug data if in debug mode - if (isset($this->debug_flag) && $this->debug_flag) { - $payload .= $this->getDebugAsXMLComment(); - } - $this->outgoing_headers[] = "Server: $this->title Server v$this->version"; - preg_match('/\$Revisio'.'n: ([^ ]+)/', $this->revision, $rev); - $this->outgoing_headers[] = "X-SOAP-Server: $this->title/$this->version (".$rev[1].')'; - // Let the Web server decide about this - //$this->outgoing_headers[] = "Connection: Close\r\n"; - $payload = $this->getHTTPBody($payload); - $type = $this->getHTTPContentType(); - $charset = $this->getHTTPContentTypeCharset(); - $this->outgoing_headers[] = "Content-Type: $type".($charset ? '; charset='.$charset : ''); - //begin code to compress payload - by John - // NOTE: there is no way to know whether the Web server will also compress - // this data. - if (strlen($payload) > 1024 && isset($this->headers) && isset($this->headers['accept-encoding'])) { - if (strstr($this->headers['accept-encoding'], 'gzip')) { - if (function_exists('gzencode')) { - if (isset($this->debug_flag) && $this->debug_flag) { - $payload .= ''; - } - $this->outgoing_headers[] = 'Content-Encoding: gzip'; - $payload = gzencode($payload); - } else { - if (isset($this->debug_flag) && $this->debug_flag) { - $payload .= ''; - } - } - } elseif (strstr($this->headers['accept-encoding'], 'deflate')) { - // Note: MSIE requires gzdeflate output (no Zlib header and checksum), - // instead of gzcompress output, - // which conflicts with HTTP 1.1 spec (http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.5) - if (function_exists('gzdeflate')) { - if (isset($this->debug_flag) && $this->debug_flag) { - $payload .= ''; - } - $this->outgoing_headers[] = 'Content-Encoding: deflate'; - $payload = gzdeflate($payload); - } else { - if (isset($this->debug_flag) && $this->debug_flag) { - $payload .= ''; - } - } - } - } - //end code - $this->outgoing_headers[] = 'Content-Length: '.strlen($payload); - reset($this->outgoing_headers); - foreach ($this->outgoing_headers as $hdr) { - header($hdr, false); - } - echo $payload; - $this->response = implode("\r\n", $this->outgoing_headers)."\r\n\r\n".$payload; - } - - /** - * takes the value that was created by parsing the request - * and compares to the method's signature, if available. - * - * @param string $operation The operation to be invoked - * @param array $request The array of parameter values - * - * @return bool Whether the operation was found - */ - public function verify_method($operation, $request) - { - if (isset($this->wsdl) && is_object($this->wsdl)) { - if ($this->wsdl->getOperationData($operation)) { - return true; - } - } elseif (isset($this->operations[$operation])) { - return true; - } - - return false; - } - - /** - * processes SOAP message received from client. - * - * @param array $headers The HTTP headers - * @param string $data unprocessed request data from client - * - * @return mixed value of the message, decoded into a PHP type - */ - public function parseRequest($headers, $data) - { - $this->debug('Entering parseRequest() for data of length '.strlen($data).' headers:'); - $this->appendDebug($this->varDump($headers)); - if (!isset($headers['content-type'])) { - $this->setError('Request not of type text/xml (no content-type header)'); - - return false; - } - if (!strstr($headers['content-type'], 'text/xml')) { - $this->setError('Request not of type text/xml'); - - return false; - } - if (strpos($headers['content-type'], '=')) { - $enc = str_replace('"', '', substr(strstr($headers['content-type'], '='), 1)); - $this->debug('Got response encoding: '.$enc); - if (preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i', $enc)) { - $this->xml_encoding = strtoupper($enc); - } else { - $this->xml_encoding = 'US-ASCII'; - } - } else { - // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1 - $this->xml_encoding = 'ISO-8859-1'; - } - $this->debug('Use encoding: '.$this->xml_encoding.' when creating nusoap_parser'); - // parse response, get soap parser obj - $parser = new nusoap_parser($data, $this->xml_encoding, '', $this->decode_utf8); - // parser debug - $this->debug("parser debug: \n".$parser->getDebug()); - // if fault occurred during message parsing - if ($err = $parser->getError()) { - $this->result = 'fault: error in msg parsing: '.$err; - $this->fault('SOAP-ENV:Client', "error in msg parsing:\n".$err); - // else successfully parsed request into soapval object - } else { - // get/set methodname - $this->methodURI = $parser->root_struct_namespace; - $this->methodname = $parser->root_struct_name; - $this->debug('methodname: '.$this->methodname.' methodURI: '.$this->methodURI); - $this->debug('calling parser->get_soapbody()'); - $this->methodparams = $parser->get_soapbody(); - // get SOAP headers - $this->requestHeaders = $parser->getHeaders(); - // get SOAP Header - $this->requestHeader = $parser->get_soapheader(); - // add document for doclit support - $this->document = $parser->document; - } - } - - /** - * gets the HTTP body for the current response. - * - * @param string $soapmsg The SOAP payload - * - * @return string The HTTP body, which includes the SOAP payload - */ - public function getHTTPBody($soapmsg) - { - return $soapmsg; - } - - /** - * gets the HTTP content type for the current response. - * - * Note: getHTTPBody must be called before this. - * - * @return string the HTTP content type for the current response. - */ - public function getHTTPContentType() - { - return 'text/xml'; - } - - /** - * gets the HTTP content type charset for the current response. - * returns false for non-text content types. - * - * Note: getHTTPBody must be called before this. - * - * @return string the HTTP content type charset for the current response. - */ - public function getHTTPContentTypeCharset() - { - return $this->soap_defencoding; - } - - /** - * add a method to the dispatch map (this has been replaced by the register method). - * - * @param string $methodname - * @param string $in array of input values - * @param string $out array of output values - * - * @deprecated - */ - public function add_to_map($methodname, $in, $out) - { - $this->operations[$methodname] = ['name' => $methodname, 'in' => $in, 'out' => $out]; - } - - /** - * register a service function with the server. - * - * @param string $name the name of the PHP function, class.method or class..method - * @param array $in assoc array of input values: key = param name, value = param type - * @param array $out assoc array of output values: key = param name, value = param type - * @param mixed $namespace the element namespace for the method or false - * @param mixed $soapaction the soapaction for the method or false - * @param mixed $style optional (rpc|document) or false Note: when 'document' is specified, parameter and return wrappers are created for you automatically - * @param mixed $use optional (encoded|literal) or false - * @param string $documentation optional Description to include in WSDL - * @param string $encodingStyle optional (usually 'http://schemas.xmlsoap.org/soap/encoding/' for encoded) - */ - public function register($name, $in = [], $out = [], $namespace = false, $soapaction = false, $style = false, $use = false, $documentation = '', $encodingStyle = '') - { - global $HTTP_SERVER_VARS; - - if ($this->externalWSDLURL) { - die('You cannot bind to an external WSDL file, and register methods outside of it! Please choose either WSDL or no WSDL.'); - } - if (!$name) { - die('You must specify a name when you register an operation'); - } - if (!is_array($in)) { - die('You must provide an array for operation inputs'); - } - if (!is_array($out)) { - die('You must provide an array for operation outputs'); - } - if (false == $namespace) { - } - if (false == $soapaction) { - if (isset($_SERVER)) { - $SERVER_NAME = $_SERVER['SERVER_NAME']; - $SCRIPT_NAME = isset($_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : $_SERVER['SCRIPT_NAME']; - $HTTPS = isset($_SERVER['HTTPS']) ? $_SERVER['HTTPS'] : (isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off'); - } elseif (isset($HTTP_SERVER_VARS)) { - $SERVER_NAME = $HTTP_SERVER_VARS['SERVER_NAME']; - $SCRIPT_NAME = isset($HTTP_SERVER_VARS['PHP_SELF']) ? $HTTP_SERVER_VARS['PHP_SELF'] : $HTTP_SERVER_VARS['SCRIPT_NAME']; - $HTTPS = isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off'; - } else { - $this->setError('Neither _SERVER nor HTTP_SERVER_VARS is available'); - } - if ($HTTPS == '1' || $HTTPS == 'on') { - $SCHEME = 'https'; - } else { - $SCHEME = 'http'; - } - $soapaction = "$SCHEME://$SERVER_NAME$SCRIPT_NAME/$name"; - } - if (false == $style) { - $style = 'rpc'; - } - if (false == $use) { - $use = 'encoded'; - } - if ($use == 'encoded' && $encodingStyle == '') { - $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/'; - } - - $this->operations[$name] = [ - 'name' => $name, - 'in' => $in, - 'out' => $out, - 'namespace' => $namespace, - 'soapaction' => $soapaction, - 'style' => $style, ]; - if ($this->wsdl) { - $this->wsdl->addOperation($name, $in, $out, $namespace, $soapaction, $style, $use, $documentation, $encodingStyle); - } - - return true; - } - - /** - * Specify a fault to be returned to the client. - * This also acts as a flag to the server that a fault has occured. - * - * @param string $faultcode - * @param string $faultstring - * @param string $faultactor - * @param string $faultdetail - */ - public function fault($faultcode, $faultstring, $faultactor = '', $faultdetail = '') - { - if ($faultdetail == '' && $this->debug_flag) { - $faultdetail = $this->getDebug(); - } - $this->fault = new nusoap_fault($faultcode, $faultactor, $faultstring, $faultdetail); - $this->fault->soap_defencoding = $this->soap_defencoding; - } - - /** - * Sets up wsdl object. - * Acts as a flag to enable internal WSDL generation. - * - * @param string $serviceName, name of the service - * @param mixed $namespace optional 'tns' service namespace or false - * @param mixed $endpoint optional URL of service endpoint or false - * @param string $style optional (rpc|document) WSDL style (also specified by operation) - * @param string $transport optional SOAP transport - * @param mixed $schemaTargetNamespace optional 'types' targetNamespace for service schema or false - */ - public function configureWSDL($serviceName, $namespace = false, $endpoint = false, $style = 'rpc', $transport = 'http://schemas.xmlsoap.org/soap/http', $schemaTargetNamespace = false) - { - global $HTTP_SERVER_VARS; - - if (isset($_SERVER)) { - $SERVER_NAME = $_SERVER['SERVER_NAME']; - $SERVER_PORT = $_SERVER['SERVER_PORT']; - $SCRIPT_NAME = isset($_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : $_SERVER['SCRIPT_NAME']; - $HTTPS = isset($_SERVER['HTTPS']) ? $_SERVER['HTTPS'] : (isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off'); - } elseif (isset($HTTP_SERVER_VARS)) { - $SERVER_NAME = $HTTP_SERVER_VARS['SERVER_NAME']; - $SERVER_PORT = $HTTP_SERVER_VARS['SERVER_PORT']; - $SCRIPT_NAME = isset($HTTP_SERVER_VARS['PHP_SELF']) ? $HTTP_SERVER_VARS['PHP_SELF'] : $HTTP_SERVER_VARS['SCRIPT_NAME']; - $HTTPS = isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off'; - } else { - $this->setError('Neither _SERVER nor HTTP_SERVER_VARS is available'); - } - // If server name has port number attached then strip it (else port number gets duplicated in WSDL output) (occurred using lighttpd and FastCGI) - $colon = strpos($SERVER_NAME, ':'); - if ($colon) { - $SERVER_NAME = substr($SERVER_NAME, 0, $colon); - } - if ($SERVER_PORT == 80) { - $SERVER_PORT = ''; - } else { - $SERVER_PORT = ':'.$SERVER_PORT; - } - if (false == $namespace) { - $namespace = "http://$SERVER_NAME/soap/$serviceName"; - } - - if (false == $endpoint) { - if ($HTTPS == '1' || $HTTPS == 'on') { - $SCHEME = 'https'; - } else { - $SCHEME = 'http'; - } - $endpoint = "$SCHEME://$SERVER_NAME$SERVER_PORT$SCRIPT_NAME"; - } - - if (false == $schemaTargetNamespace) { - $schemaTargetNamespace = $namespace; - } - - $this->wsdl = new wsdl(); - $this->wsdl->serviceName = $serviceName; - $this->wsdl->endpoint = $endpoint; - $this->wsdl->namespaces['tns'] = $namespace; - $this->wsdl->namespaces['soap'] = 'http://schemas.xmlsoap.org/wsdl/soap/'; - $this->wsdl->namespaces['wsdl'] = 'http://schemas.xmlsoap.org/wsdl/'; - if ($schemaTargetNamespace != $namespace) { - $this->wsdl->namespaces['types'] = $schemaTargetNamespace; - } - $this->wsdl->schemas[$schemaTargetNamespace][0] = new nusoap_xmlschema('', '', $this->wsdl->namespaces); - if ($style == 'document') { - $this->wsdl->schemas[$schemaTargetNamespace][0]->schemaInfo['elementFormDefault'] = 'qualified'; - } - $this->wsdl->schemas[$schemaTargetNamespace][0]->schemaTargetNamespace = $schemaTargetNamespace; - $this->wsdl->schemas[$schemaTargetNamespace][0]->imports['http://schemas.xmlsoap.org/soap/encoding/'][0] = ['location' => '', 'loaded' => true]; - $this->wsdl->schemas[$schemaTargetNamespace][0]->imports['http://schemas.xmlsoap.org/wsdl/'][0] = ['location' => '', 'loaded' => true]; - $this->wsdl->bindings[$serviceName.'Binding'] = [ - 'name' => $serviceName.'Binding', - 'style' => $style, - 'transport' => $transport, - 'portType' => $serviceName.'PortType', ]; - $this->wsdl->ports[$serviceName.'Port'] = [ - 'binding' => $serviceName.'Binding', - 'location' => $endpoint, - 'bindingType' => 'http://schemas.xmlsoap.org/wsdl/soap/', ]; - } -} - -/** - * Backward compatibility. - */ -class soap_server extends nusoap_server -{ -} diff --git a/src/Drivers/lib/class.soap_transport_http.php b/src/Drivers/lib/class.soap_transport_http.php deleted file mode 100644 index 461f8d6..0000000 --- a/src/Drivers/lib/class.soap_transport_http.php +++ /dev/null @@ -1,1347 +0,0 @@ - - * @author Scott Nichol - * - * @version $Id: class.soap_transport_http.php,v 1.68 2010/04/26 20:15:08 snichol Exp $ - */ -class soap_transport_http extends nusoap_base -{ - public $url = ''; - public $uri = ''; - public $digest_uri = ''; - public $scheme = ''; - public $host = ''; - public $port = ''; - public $path = ''; - public $request_method = 'POST'; - public $protocol_version = '1.0'; - public $encoding = ''; - public $outgoing_headers = []; - public $incoming_headers = []; - public $incoming_cookies = []; - public $outgoing_payload = ''; - public $incoming_payload = ''; - public $response_status_line; // HTTP response status line - public $useSOAPAction = true; - public $persistentConnection = false; - public $ch = false; // cURL handle - public $ch_options = []; // cURL custom options - public $use_curl = false; // force cURL use - public $proxy = null; // proxy information (associative array) - public $username = ''; - public $password = ''; - public $authtype = ''; - public $digestRequest = []; - public $certRequest = []; // keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, certpassword (optional), verifypeer (optional), verifyhost (optional) - // cainfofile: certificate authority file, e.g. '$pathToPemFiles/rootca.pem' - // sslcertfile: SSL certificate file, e.g. '$pathToPemFiles/mycert.pem' - // sslkeyfile: SSL key file, e.g. '$pathToPemFiles/mykey.pem' - // passphrase: SSL key password/passphrase - // certpassword: SSL certificate password - // verifypeer: default is 1 - // verifyhost: default is 1 - - /** - * constructor. - * - * @param string $url The URL to which to connect - * @param array $curl_options User-specified cURL options - * @param bool $use_curl Whether to try to force cURL use - */ - public function soap_transport_http($url, $curl_options = null, $use_curl = false) - { - parent::nusoap_base(); - $this->debug("ctor url=$url use_curl=$use_curl curl_options:"); - $this->appendDebug($this->varDump($curl_options)); - $this->setURL($url); - if (is_array($curl_options)) { - $this->ch_options = $curl_options; - } - $this->use_curl = $use_curl; - preg_match('/\$Revisio'.'n: ([^ ]+)/', $this->revision, $rev); - $this->setHeader('User-Agent', $this->title.'/'.$this->version.' ('.$rev[1].')'); - } - - /** - * sets a cURL option. - * - * @param mixed $option The cURL option (always integer?) - * @param mixed $value The cURL option value - */ - public function setCurlOption($option, $value) - { - $this->debug("setCurlOption option=$option, value="); - $this->appendDebug($this->varDump($value)); - curl_setopt($this->ch, $option, $value); - } - - /** - * sets an HTTP header. - * - * @param string $name The name of the header - * @param string $value The value of the header - */ - public function setHeader($name, $value) - { - $this->outgoing_headers[$name] = $value; - $this->debug("set header $name: $value"); - } - - /** - * unsets an HTTP header. - * - * @param string $name The name of the header - */ - public function unsetHeader($name) - { - if (isset($this->outgoing_headers[$name])) { - $this->debug("unset header $name"); - unset($this->outgoing_headers[$name]); - } - } - - /** - * sets the URL to which to connect. - * - * @param string $url The URL to which to connect - */ - public function setURL($url) - { - $this->url = $url; - - $u = parse_url($url); - foreach ($u as $k => $v) { - $this->debug("parsed URL $k = $v"); - $this->$k = $v; - } - - // add any GET params to path - if (isset($u['query']) && $u['query'] != '') { - $this->path .= '?'.$u['query']; - } - - // set default port - if (!isset($u['port'])) { - if ($u['scheme'] == 'https') { - $this->port = 443; - } else { - $this->port = 80; - } - } - - $this->uri = $this->path; - $this->digest_uri = $this->uri; - - // build headers - if (!isset($u['port'])) { - $this->setHeader('Host', $this->host); - } else { - $this->setHeader('Host', $this->host.':'.$this->port); - } - - if (isset($u['user']) && $u['user'] != '') { - $this->setCredentials(urldecode($u['user']), isset($u['pass']) ? urldecode($u['pass']) : ''); - } - } - - /** - * gets the I/O method to use. - * - * @return string I/O method to use (socket|curl|unknown) - */ - public function io_method() - { - if ($this->use_curl || ($this->scheme == 'https') || ($this->scheme == 'http' && $this->authtype == 'ntlm') || ($this->scheme == 'http' && is_array($this->proxy) && $this->proxy['authtype'] == 'ntlm')) { - return 'curl'; - } - if (($this->scheme == 'http' || $this->scheme == 'ssl') && $this->authtype != 'ntlm' && (!is_array($this->proxy) || $this->proxy['authtype'] != 'ntlm')) { - return 'socket'; - } - - return 'unknown'; - } - - /** - * establish an HTTP connection. - * - * @param int $timeout set connection timeout in seconds - * @param int $response_timeout set response timeout in seconds - * - * @return bool true if connected, false if not - */ - public function connect($connection_timeout = 0, $response_timeout = 30) - { - // For PHP 4.3 with OpenSSL, change https scheme to ssl, then treat like - // "regular" socket. - // TODO: disabled for now because OpenSSL must be *compiled* in (not just - // loaded), and until PHP5 stream_get_wrappers is not available. -// if ($this->scheme == 'https') { -// if (version_compare(phpversion(), '4.3.0') >= 0) { -// if (extension_loaded('openssl')) { -// $this->scheme = 'ssl'; -// $this->debug('Using SSL over OpenSSL'); -// } -// } -// } - $this->debug("connect connection_timeout $connection_timeout, response_timeout $response_timeout, scheme $this->scheme, host $this->host, port $this->port"); - if ($this->io_method() == 'socket') { - if (!is_array($this->proxy)) { - $host = $this->host; - $port = $this->port; - } else { - $host = $this->proxy['host']; - $port = $this->proxy['port']; - } - - // use persistent connection - if ($this->persistentConnection && isset($this->fp) && is_resource($this->fp)) { - if (!feof($this->fp)) { - $this->debug('Re-use persistent connection'); - - return true; - } - fclose($this->fp); - $this->debug('Closed persistent connection at EOF'); - } - - // munge host if using OpenSSL - if ($this->scheme == 'ssl') { - $host = 'ssl://'.$host; - } - $this->debug('calling fsockopen with host '.$host.' connection_timeout '.$connection_timeout); - - // open socket - if ($connection_timeout > 0) { - $this->fp = @fsockopen($host, $this->port, $this->errno, $this->error_str, $connection_timeout); - } else { - $this->fp = @fsockopen($host, $this->port, $this->errno, $this->error_str); - } - - // test pointer - if (!$this->fp) { - $msg = 'Couldn\'t open socket connection to server '.$this->url; - if ($this->errno) { - $msg .= ', Error ('.$this->errno.'): '.$this->error_str; - } else { - $msg .= ' prior to connect(). This is often a problem looking up the host name.'; - } - $this->debug($msg); - $this->setError($msg); - - return false; - } - - // set response timeout - $this->debug('set response timeout to '.$response_timeout); - socket_set_timeout($this->fp, $response_timeout); - - $this->debug('socket connected'); - - return true; - } elseif ($this->io_method() == 'curl') { - if (!extension_loaded('curl')) { - // $this->setError('cURL Extension, or OpenSSL extension w/ PHP version >= 4.3 is required for HTTPS'); - $this->setError('The PHP cURL Extension is required for HTTPS or NLTM. You will need to re-build or update your PHP to include cURL or change php.ini to load the PHP cURL extension.'); - - return false; - } - // Avoid warnings when PHP does not have these options - if (defined('CURLOPT_CONNECTIONTIMEOUT')) { - $CURLOPT_CONNECTIONTIMEOUT = CURLOPT_CONNECTIONTIMEOUT; - } else { - $CURLOPT_CONNECTIONTIMEOUT = 78; - } - if (defined('CURLOPT_HTTPAUTH')) { - $CURLOPT_HTTPAUTH = CURLOPT_HTTPAUTH; - } else { - $CURLOPT_HTTPAUTH = 107; - } - if (defined('CURLOPT_PROXYAUTH')) { - $CURLOPT_PROXYAUTH = CURLOPT_PROXYAUTH; - } else { - $CURLOPT_PROXYAUTH = 111; - } - if (defined('CURLAUTH_BASIC')) { - $CURLAUTH_BASIC = CURLAUTH_BASIC; - } else { - $CURLAUTH_BASIC = 1; - } - if (defined('CURLAUTH_DIGEST')) { - $CURLAUTH_DIGEST = CURLAUTH_DIGEST; - } else { - $CURLAUTH_DIGEST = 2; - } - if (defined('CURLAUTH_NTLM')) { - $CURLAUTH_NTLM = CURLAUTH_NTLM; - } else { - $CURLAUTH_NTLM = 8; - } - - $this->debug('connect using cURL'); - // init CURL - $this->ch = curl_init(); - // set url - $hostURL = ($this->port != '') ? "$this->scheme://$this->host:$this->port" : "$this->scheme://$this->host"; - // add path - $hostURL .= $this->path; - $this->setCurlOption(CURLOPT_URL, $hostURL); - // follow location headers (re-directs) - if (ini_get('safe_mode') || ini_get('open_basedir')) { - $this->debug('safe_mode or open_basedir set, so do not set CURLOPT_FOLLOWLOCATION'); - $this->debug('safe_mode = '); - $this->appendDebug($this->varDump(ini_get('safe_mode'))); - $this->debug('open_basedir = '); - $this->appendDebug($this->varDump(ini_get('open_basedir'))); - } else { - $this->setCurlOption(CURLOPT_FOLLOWLOCATION, 1); - } - // ask for headers in the response output - $this->setCurlOption(CURLOPT_HEADER, 1); - // ask for the response output as the return value - $this->setCurlOption(CURLOPT_RETURNTRANSFER, 1); - // encode - // We manage this ourselves through headers and encoding -// if(function_exists('gzuncompress')){ -// $this->setCurlOption(CURLOPT_ENCODING, 'deflate'); -// } - // persistent connection - if ($this->persistentConnection) { - // I believe the following comment is now bogus, having applied to - // the code when it used CURLOPT_CUSTOMREQUEST to send the request. - // The way we send data, we cannot use persistent connections, since - // there will be some "junk" at the end of our request. - //$this->setCurlOption(CURL_HTTP_VERSION_1_1, true); - $this->persistentConnection = false; - $this->setHeader('Connection', 'close'); - } - // set timeouts - if ($connection_timeout != 0) { - $this->setCurlOption($CURLOPT_CONNECTIONTIMEOUT, $connection_timeout); - } - if ($response_timeout != 0) { - $this->setCurlOption(CURLOPT_TIMEOUT, $response_timeout); - } - - if ($this->scheme == 'https') { - $this->debug('set cURL SSL verify options'); - // recent versions of cURL turn on peer/host checking by default, - // while PHP binaries are not compiled with a default location for the - // CA cert bundle, so disable peer/host checking. - //$this->setCurlOption(CURLOPT_CAINFO, 'f:\php-4.3.2-win32\extensions\curl-ca-bundle.crt'); - $this->setCurlOption(CURLOPT_SSL_VERIFYPEER, 0); - $this->setCurlOption(CURLOPT_SSL_VERIFYHOST, 0); - - // support client certificates (thanks Tobias Boes, Doug Anarino, Eryan Ariobowo) - if ($this->authtype == 'certificate') { - $this->debug('set cURL certificate options'); - if (isset($this->certRequest['cainfofile'])) { - $this->setCurlOption(CURLOPT_CAINFO, $this->certRequest['cainfofile']); - } - if (isset($this->certRequest['verifypeer'])) { - $this->setCurlOption(CURLOPT_SSL_VERIFYPEER, $this->certRequest['verifypeer']); - } else { - $this->setCurlOption(CURLOPT_SSL_VERIFYPEER, 1); - } - if (isset($this->certRequest['verifyhost'])) { - $this->setCurlOption(CURLOPT_SSL_VERIFYHOST, $this->certRequest['verifyhost']); - } else { - $this->setCurlOption(CURLOPT_SSL_VERIFYHOST, 1); - } - if (isset($this->certRequest['sslcertfile'])) { - $this->setCurlOption(CURLOPT_SSLCERT, $this->certRequest['sslcertfile']); - } - if (isset($this->certRequest['sslkeyfile'])) { - $this->setCurlOption(CURLOPT_SSLKEY, $this->certRequest['sslkeyfile']); - } - if (isset($this->certRequest['passphrase'])) { - $this->setCurlOption(CURLOPT_SSLKEYPASSWD, $this->certRequest['passphrase']); - } - if (isset($this->certRequest['certpassword'])) { - $this->setCurlOption(CURLOPT_SSLCERTPASSWD, $this->certRequest['certpassword']); - } - } - } - if ($this->authtype && ($this->authtype != 'certificate')) { - if ($this->username) { - $this->debug('set cURL username/password'); - $this->setCurlOption(CURLOPT_USERPWD, "$this->username:$this->password"); - } - if ($this->authtype == 'basic') { - $this->debug('set cURL for Basic authentication'); - $this->setCurlOption($CURLOPT_HTTPAUTH, $CURLAUTH_BASIC); - } - if ($this->authtype == 'digest') { - $this->debug('set cURL for digest authentication'); - $this->setCurlOption($CURLOPT_HTTPAUTH, $CURLAUTH_DIGEST); - } - if ($this->authtype == 'ntlm') { - $this->debug('set cURL for NTLM authentication'); - $this->setCurlOption($CURLOPT_HTTPAUTH, $CURLAUTH_NTLM); - } - } - if (is_array($this->proxy)) { - $this->debug('set cURL proxy options'); - if ($this->proxy['port'] != '') { - $this->setCurlOption(CURLOPT_PROXY, $this->proxy['host'].':'.$this->proxy['port']); - } else { - $this->setCurlOption(CURLOPT_PROXY, $this->proxy['host']); - } - if ($this->proxy['username'] || $this->proxy['password']) { - $this->debug('set cURL proxy authentication options'); - $this->setCurlOption(CURLOPT_PROXYUSERPWD, $this->proxy['username'].':'.$this->proxy['password']); - if ($this->proxy['authtype'] == 'basic') { - $this->setCurlOption($CURLOPT_PROXYAUTH, $CURLAUTH_BASIC); - } - if ($this->proxy['authtype'] == 'ntlm') { - $this->setCurlOption($CURLOPT_PROXYAUTH, $CURLAUTH_NTLM); - } - } - } - $this->debug('cURL connection set up'); - - return true; - } else { - $this->setError('Unknown scheme '.$this->scheme); - $this->debug('Unknown scheme '.$this->scheme); - - return false; - } - } - - /** - * sends the SOAP request and gets the SOAP response via HTTP[S]. - * - * @param string $data message data - * @param int $timeout set connection timeout in seconds - * @param int $response_timeout set response timeout in seconds - * @param array $cookies cookies to send - * - * @return string data - */ - public function send($data, $timeout = 0, $response_timeout = 30, $cookies = null) - { - $this->debug('entered send() with data of length: '.strlen($data)); - - $this->tryagain = true; - $tries = 0; - while ($this->tryagain) { - $this->tryagain = false; - if ($tries++ < 2) { - // make connnection - if (!$this->connect($timeout, $response_timeout)) { - return false; - } - - // send request - if (!$this->sendRequest($data, $cookies)) { - return false; - } - - // get response - $respdata = $this->getResponse(); - } else { - $this->setError("Too many tries to get an OK response ($this->response_status_line)"); - } - } - $this->debug('end of send()'); - - return $respdata; - } - - /** - * sends the SOAP request and gets the SOAP response via HTTPS using CURL. - * - * @param string $data message data - * @param int $timeout set connection timeout in seconds - * @param int $response_timeout set response timeout in seconds - * @param array $cookies cookies to send - * - * @return string data - * - * @deprecated - */ - public function sendHTTPS($data, $timeout, $response_timeout, $cookies) - { - return $this->send($data, $timeout, $response_timeout, $cookies); - } - - /** - * if authenticating, set user credentials here. - * - * @param string $username - * @param string $password - * @param string $authtype (basic|digest|certificate|ntlm) - * @param array $digestRequest (keys must be nonce, nc, realm, qop) - * @param array $certRequest (keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, certpassword (optional), verifypeer (optional), verifyhost (optional): see corresponding options in cURL docs) - */ - public function setCredentials($username, $password, $authtype = 'basic', $digestRequest = [], $certRequest = []) - { - $this->debug("setCredentials username=$username authtype=$authtype digestRequest="); - $this->appendDebug($this->varDump($digestRequest)); - $this->debug('certRequest='); - $this->appendDebug($this->varDump($certRequest)); - // cf. RFC 2617 - if ($authtype == 'basic') { - $this->setHeader('Authorization', 'Basic '.base64_encode(str_replace(':', '', $username).':'.$password)); - } elseif ($authtype == 'digest') { - if (isset($digestRequest['nonce'])) { - $digestRequest['nc'] = isset($digestRequest['nc']) ? $digestRequest['nc']++ : 1; - - // calculate the Digest hashes (calculate code based on digest implementation found at: http://www.rassoc.com/gregr/weblog/stories/2002/07/09/webServicesSecurityHttpDigestAuthenticationWithoutActiveDirectory.html) - - // A1 = unq(username-value) ":" unq(realm-value) ":" passwd - $A1 = $username.':'.(isset($digestRequest['realm']) ? $digestRequest['realm'] : '').':'.$password; - - // H(A1) = MD5(A1) - $HA1 = md5($A1); - - // A2 = Method ":" digest-uri-value - $A2 = $this->request_method.':'.$this->digest_uri; - - // H(A2) - $HA2 = md5($A2); - - // KD(secret, data) = H(concat(secret, ":", data)) - // if qop == auth: - // request-digest = <"> < KD ( H(A1), unq(nonce-value) - // ":" nc-value - // ":" unq(cnonce-value) - // ":" unq(qop-value) - // ":" H(A2) - // ) <"> - // if qop is missing, - // request-digest = <"> < KD ( H(A1), unq(nonce-value) ":" H(A2) ) > <"> - - $unhashedDigest = ''; - $nonce = isset($digestRequest['nonce']) ? $digestRequest['nonce'] : ''; - $cnonce = $nonce; - if ($digestRequest['qop'] != '') { - $unhashedDigest = $HA1.':'.$nonce.':'.sprintf('%08d', $digestRequest['nc']).':'.$cnonce.':'.$digestRequest['qop'].':'.$HA2; - } else { - $unhashedDigest = $HA1.':'.$nonce.':'.$HA2; - } - - $hashedDigest = md5($unhashedDigest); - - $opaque = ''; - if (isset($digestRequest['opaque'])) { - $opaque = ', opaque="'.$digestRequest['opaque'].'"'; - } - - $this->setHeader('Authorization', 'Digest username="'.$username.'", realm="'.$digestRequest['realm'].'", nonce="'.$nonce.'", uri="'.$this->digest_uri.$opaque.'", cnonce="'.$cnonce.'", nc='.sprintf('%08x', $digestRequest['nc']).', qop="'.$digestRequest['qop'].'", response="'.$hashedDigest.'"'); - } - } elseif ($authtype == 'certificate') { - $this->certRequest = $certRequest; - $this->debug('Authorization header not set for certificate'); - } elseif ($authtype == 'ntlm') { - // do nothing - $this->debug('Authorization header not set for ntlm'); - } - $this->username = $username; - $this->password = $password; - $this->authtype = $authtype; - $this->digestRequest = $digestRequest; - } - - /** - * set the soapaction value. - * - * @param string $soapaction - */ - public function setSOAPAction($soapaction) - { - $this->setHeader('SOAPAction', '"'.$soapaction.'"'); - } - - /** - * use http encoding. - * - * @param string $enc encoding style. supported values: gzip, deflate, or both - */ - public function setEncoding($enc = 'gzip, deflate') - { - if (function_exists('gzdeflate')) { - $this->protocol_version = '1.1'; - $this->setHeader('Accept-Encoding', $enc); - if (!isset($this->outgoing_headers['Connection'])) { - $this->setHeader('Connection', 'close'); - $this->persistentConnection = false; - } - // deprecated as of PHP 5.3.0 - //set_magic_quotes_runtime(0); - $this->encoding = $enc; - } - } - - /** - * set proxy info here. - * - * @param string $proxyhost use an empty string to remove proxy - * @param string $proxyport - * @param string $proxyusername - * @param string $proxypassword - * @param string $proxyauthtype (basic|ntlm) - */ - public function setProxy($proxyhost, $proxyport, $proxyusername = '', $proxypassword = '', $proxyauthtype = 'basic') - { - if ($proxyhost) { - $this->proxy = [ - 'host' => $proxyhost, - 'port' => $proxyport, - 'username' => $proxyusername, - 'password' => $proxypassword, - 'authtype' => $proxyauthtype, - ]; - if ($proxyusername != '' && $proxypassword != '' && $proxyauthtype = 'basic') { - $this->setHeader('Proxy-Authorization', ' Basic '.base64_encode($proxyusername.':'.$proxypassword)); - } - } else { - $this->debug('remove proxy'); - $proxy = null; - unsetHeader('Proxy-Authorization'); - } - } - - /** - * Test if the given string starts with a header that is to be skipped. - * Skippable headers result from chunked transfer and proxy requests. - * - * @param string $data The string to check. - * @returns boolean Whether a skippable header was found. - */ - public function isSkippableCurlHeader(&$data) - { - $skipHeaders = ['HTTP/1.1 100', - 'HTTP/1.0 301', - 'HTTP/1.1 301', - 'HTTP/1.0 302', - 'HTTP/1.1 302', - 'HTTP/1.0 401', - 'HTTP/1.1 401', - 'HTTP/1.0 200 Connection established', ]; - foreach ($skipHeaders as $hd) { - $prefix = substr($data, 0, strlen($hd)); - if ($prefix == $hd) { - return true; - } - } - - return false; - } - - /** - * decode a string that is encoded w/ "chunked' transfer encoding - * as defined in RFC2068 19.4.6. - * - * @param string $buffer - * @param string $lb - * @returns string - * - * @deprecated - */ - public function decodeChunked($buffer, $lb) - { - // length := 0 - $length = 0; - $new = ''; - - // read chunk-size, chunk-extension (if any) and CRLF - // get the position of the linebreak - $chunkend = strpos($buffer, $lb); - if ($chunkend == false) { - $this->debug('no linebreak found in decodeChunked'); - - return $new; - } - $temp = substr($buffer, 0, $chunkend); - $chunk_size = hexdec(trim($temp)); - $chunkstart = $chunkend + strlen($lb); - // while (chunk-size > 0) { - while ($chunk_size > 0) { - $this->debug("chunkstart: $chunkstart chunk_size: $chunk_size"); - $chunkend = strpos($buffer, $lb, $chunkstart + $chunk_size); - - // Just in case we got a broken connection - if ($chunkend == false) { - $chunk = substr($buffer, $chunkstart); - // append chunk-data to entity-body - $new .= $chunk; - $length += strlen($chunk); - break; - } - - // read chunk-data and CRLF - $chunk = substr($buffer, $chunkstart, $chunkend - $chunkstart); - // append chunk-data to entity-body - $new .= $chunk; - // length := length + chunk-size - $length += strlen($chunk); - // read chunk-size and CRLF - $chunkstart = $chunkend + strlen($lb); - - $chunkend = strpos($buffer, $lb, $chunkstart) + strlen($lb); - if ($chunkend == false) { - break; //Just in case we got a broken connection - } - $temp = substr($buffer, $chunkstart, $chunkend - $chunkstart); - $chunk_size = hexdec(trim($temp)); - $chunkstart = $chunkend; - } - - return $new; - } - - /** - * Writes the payload, including HTTP headers, to $this->outgoing_payload. - * - * @param string $data HTTP body - * @param string $cookie_str data for HTTP Cookie header - * - * @return void - */ - public function buildPayload($data, $cookie_str = '') - { - // Note: for cURL connections, $this->outgoing_payload is ignored, - // as is the Content-Length header, but these are still created as - // debugging guides. - - // add content-length header - if ($this->request_method != 'GET') { - $this->setHeader('Content-Length', strlen($data)); - } - - // start building outgoing payload: - if ($this->proxy) { - $uri = $this->url; - } else { - $uri = $this->uri; - } - $req = "$this->request_method $uri HTTP/$this->protocol_version"; - $this->debug("HTTP request: $req"); - $this->outgoing_payload = "$req\r\n"; - - // loop thru headers, serializing - foreach ($this->outgoing_headers as $k => $v) { - $hdr = $k.': '.$v; - $this->debug("HTTP header: $hdr"); - $this->outgoing_payload .= "$hdr\r\n"; - } - - // add any cookies - if ($cookie_str != '') { - $hdr = 'Cookie: '.$cookie_str; - $this->debug("HTTP header: $hdr"); - $this->outgoing_payload .= "$hdr\r\n"; - } - - // header/body separator - $this->outgoing_payload .= "\r\n"; - - // add data - $this->outgoing_payload .= $data; - } - - /** - * sends the SOAP request via HTTP[S]. - * - * @param string $data message data - * @param array $cookies cookies to send - * - * @return bool true if OK, false if problem - */ - public function sendRequest($data, $cookies = null) - { - // build cookie string - $cookie_str = $this->getCookiesForRequest($cookies, (($this->scheme == 'ssl') || ($this->scheme == 'https'))); - - // build payload - $this->buildPayload($data, $cookie_str); - - if ($this->io_method() == 'socket') { - // send payload - if (!fwrite($this->fp, $this->outgoing_payload, strlen($this->outgoing_payload))) { - $this->setError('couldn\'t write message data to socket'); - $this->debug('couldn\'t write message data to socket'); - - return false; - } - $this->debug('wrote data to socket, length = '.strlen($this->outgoing_payload)); - - return true; - } elseif ($this->io_method() == 'curl') { - // set payload - // cURL does say this should only be the verb, and in fact it - // turns out that the URI and HTTP version are appended to this, which - // some servers refuse to work with (so we no longer use this method!) - //$this->setCurlOption(CURLOPT_CUSTOMREQUEST, $this->outgoing_payload); - $curl_headers = []; - foreach ($this->outgoing_headers as $k => $v) { - if ($k == 'Connection' || $k == 'Content-Length' || $k == 'Host' || $k == 'Authorization' || $k == 'Proxy-Authorization') { - $this->debug("Skip cURL header $k: $v"); - } else { - $curl_headers[] = "$k: $v"; - } - } - if ($cookie_str != '') { - $curl_headers[] = 'Cookie: '.$cookie_str; - } - $this->setCurlOption(CURLOPT_HTTPHEADER, $curl_headers); - $this->debug('set cURL HTTP headers'); - if ($this->request_method == 'POST') { - $this->setCurlOption(CURLOPT_POST, 1); - $this->setCurlOption(CURLOPT_POSTFIELDS, $data); - $this->debug('set cURL POST data'); - } else { - } - // insert custom user-set cURL options - foreach ($this->ch_options as $key => $val) { - $this->setCurlOption($key, $val); - } - - $this->debug('set cURL payload'); - - return true; - } - } - - /** - * gets the SOAP response via HTTP[S]. - * - * @return string the response (also sets member variables like incoming_payload) - */ - public function getResponse() - { - $this->incoming_payload = ''; - - if ($this->io_method() == 'socket') { - // loop until headers have been retrieved - $data = ''; - while (!isset($lb)) { - - // We might EOF during header read. - if (feof($this->fp)) { - $this->incoming_payload = $data; - $this->debug('found no headers before EOF after length '.strlen($data)); - $this->debug("received before EOF:\n".$data); - $this->setError('server failed to send headers'); - - return false; - } - - $tmp = fgets($this->fp, 256); - $tmplen = strlen($tmp); - $this->debug("read line of $tmplen bytes: ".trim($tmp)); - - if ($tmplen == 0) { - $this->incoming_payload = $data; - $this->debug('socket read of headers timed out after length '.strlen($data)); - $this->debug('read before timeout: '.$data); - $this->setError('socket read of headers timed out'); - - return false; - } - - $data .= $tmp; - $pos = strpos($data, "\r\n\r\n"); - if ($pos > 1) { - $lb = "\r\n"; - } else { - $pos = strpos($data, "\n\n"); - if ($pos > 1) { - $lb = "\n"; - } - } - // remove 100 headers - if (isset($lb) && preg_match('/^HTTP\/1.1 100/', $data)) { - unset($lb); - $data = ''; - }// - } - // store header data - $this->incoming_payload .= $data; - $this->debug('found end of headers after length '.strlen($data)); - // process headers - $header_data = trim(substr($data, 0, $pos)); - $header_array = explode($lb, $header_data); - $this->incoming_headers = []; - $this->incoming_cookies = []; - foreach ($header_array as $header_line) { - $arr = explode(':', $header_line, 2); - if (count($arr) > 1) { - $header_name = strtolower(trim($arr[0])); - $this->incoming_headers[$header_name] = trim($arr[1]); - if ($header_name == 'set-cookie') { - // TODO: allow multiple cookies from parseCookie - $cookie = $this->parseCookie(trim($arr[1])); - if ($cookie) { - $this->incoming_cookies[] = $cookie; - $this->debug('found cookie: '.$cookie['name'].' = '.$cookie['value']); - } else { - $this->debug('did not find cookie in '.trim($arr[1])); - } - } - } elseif (isset($header_name)) { - // append continuation line to previous header - $this->incoming_headers[$header_name] .= $lb.' '.$header_line; - } - } - - // loop until msg has been received - if (isset($this->incoming_headers['transfer-encoding']) && strtolower($this->incoming_headers['transfer-encoding']) == 'chunked') { - $content_length = 2147483647; // ignore any content-length header - $chunked = true; - $this->debug('want to read chunked content'); - } elseif (isset($this->incoming_headers['content-length'])) { - $content_length = $this->incoming_headers['content-length']; - $chunked = false; - $this->debug("want to read content of length $content_length"); - } else { - $content_length = 2147483647; - $chunked = false; - $this->debug('want to read content to EOF'); - } - $data = ''; - do { - if ($chunked) { - $tmp = fgets($this->fp, 256); - $tmplen = strlen($tmp); - $this->debug("read chunk line of $tmplen bytes"); - if ($tmplen == 0) { - $this->incoming_payload = $data; - $this->debug('socket read of chunk length timed out after length '.strlen($data)); - $this->debug("read before timeout:\n".$data); - $this->setError('socket read of chunk length timed out'); - - return false; - } - $content_length = hexdec(trim($tmp)); - $this->debug("chunk length $content_length"); - } - $strlen = 0; - while (($strlen < $content_length) && (!feof($this->fp))) { - $readlen = min(8192, $content_length - $strlen); - $tmp = fread($this->fp, $readlen); - $tmplen = strlen($tmp); - $this->debug("read buffer of $tmplen bytes"); - if (($tmplen == 0) && (!feof($this->fp))) { - $this->incoming_payload = $data; - $this->debug('socket read of body timed out after length '.strlen($data)); - $this->debug("read before timeout:\n".$data); - $this->setError('socket read of body timed out'); - - return false; - } - $strlen += $tmplen; - $data .= $tmp; - } - if ($chunked && ($content_length > 0)) { - $tmp = fgets($this->fp, 256); - $tmplen = strlen($tmp); - $this->debug("read chunk terminator of $tmplen bytes"); - if ($tmplen == 0) { - $this->incoming_payload = $data; - $this->debug('socket read of chunk terminator timed out after length '.strlen($data)); - $this->debug("read before timeout:\n".$data); - $this->setError('socket read of chunk terminator timed out'); - - return false; - } - } - } while ($chunked && ($content_length > 0) && (!feof($this->fp))); - if (feof($this->fp)) { - $this->debug('read to EOF'); - } - $this->debug('read body of length '.strlen($data)); - $this->incoming_payload .= $data; - $this->debug('received a total of '.strlen($this->incoming_payload).' bytes of data from server'); - - // close filepointer - if ( - (isset($this->incoming_headers['connection']) && strtolower($this->incoming_headers['connection']) == 'close') || - (!$this->persistentConnection) || feof($this->fp)) { - fclose($this->fp); - $this->fp = false; - $this->debug('closed socket'); - } - - // connection was closed unexpectedly - if ($this->incoming_payload == '') { - $this->setError('no response from server'); - - return false; - } - - // decode transfer-encoding -// if(isset($this->incoming_headers['transfer-encoding']) && strtolower($this->incoming_headers['transfer-encoding']) == 'chunked'){ -// if(!$data = $this->decodeChunked($data, $lb)){ -// $this->setError('Decoding of chunked data failed'); -// return false; -// } - //print "
\nde-chunked:\n---------------\n$data\n\n---------------\n
"; - // set decoded payload -// $this->incoming_payload = $header_data.$lb.$lb.$data; -// } - } elseif ($this->io_method() == 'curl') { - // send and receive - $this->debug('send and receive with cURL'); - $this->incoming_payload = curl_exec($this->ch); - $data = $this->incoming_payload; - - $cErr = curl_error($this->ch); - if ($cErr != '') { - $err = 'cURL ERROR: '.curl_errno($this->ch).': '.$cErr.'
'; - // TODO: there is a PHP bug that can cause this to SEGV for CURLINFO_CONTENT_TYPE - foreach (curl_getinfo($this->ch) as $k => $v) { - $err .= "$k: $v
"; - } - $this->debug($err); - $this->setError($err); - curl_close($this->ch); - - return false; - } else { - //echo '
';
-            //var_dump(curl_getinfo($this->ch));
-            //echo '
'; - } - // close curl - $this->debug('No cURL error, closing cURL'); - curl_close($this->ch); - - // try removing skippable headers - $savedata = $data; - while ($this->isSkippableCurlHeader($data)) { - $this->debug('Found HTTP header to skip'); - if ($pos = strpos($data, "\r\n\r\n")) { - $data = ltrim(substr($data, $pos)); - } elseif ($pos = strpos($data, "\n\n")) { - $data = ltrim(substr($data, $pos)); - } - } - - if ($data == '') { - // have nothing left; just remove 100 header(s) - $data = $savedata; - while (preg_match('/^HTTP\/1.1 100/', $data)) { - if ($pos = strpos($data, "\r\n\r\n")) { - $data = ltrim(substr($data, $pos)); - } elseif ($pos = strpos($data, "\n\n")) { - $data = ltrim(substr($data, $pos)); - } - } - } - - // separate content from HTTP headers - if ($pos = strpos($data, "\r\n\r\n")) { - $lb = "\r\n"; - } elseif ($pos = strpos($data, "\n\n")) { - $lb = "\n"; - } else { - $this->debug('no proper separation of headers and document'); - $this->setError('no proper separation of headers and document'); - - return false; - } - $header_data = trim(substr($data, 0, $pos)); - $header_array = explode($lb, $header_data); - $data = ltrim(substr($data, $pos)); - $this->debug('found proper separation of headers and document'); - $this->debug('cleaned data, stringlen: '.strlen($data)); - // clean headers - foreach ($header_array as $header_line) { - $arr = explode(':', $header_line, 2); - if (count($arr) > 1) { - $header_name = strtolower(trim($arr[0])); - $this->incoming_headers[$header_name] = trim($arr[1]); - if ($header_name == 'set-cookie') { - // TODO: allow multiple cookies from parseCookie - $cookie = $this->parseCookie(trim($arr[1])); - if ($cookie) { - $this->incoming_cookies[] = $cookie; - $this->debug('found cookie: '.$cookie['name'].' = '.$cookie['value']); - } else { - $this->debug('did not find cookie in '.trim($arr[1])); - } - } - } elseif (isset($header_name)) { - // append continuation line to previous header - $this->incoming_headers[$header_name] .= $lb.' '.$header_line; - } - } - } - - $this->response_status_line = $header_array[0]; - $arr = explode(' ', $this->response_status_line, 3); - $http_version = $arr[0]; - $http_status = intval($arr[1]); - $http_reason = count($arr) > 2 ? $arr[2] : ''; - - // see if we need to resend the request with http digest authentication - if (isset($this->incoming_headers['location']) && ($http_status == 301 || $http_status == 302)) { - $this->debug("Got $http_status $http_reason with Location: ".$this->incoming_headers['location']); - $this->setURL($this->incoming_headers['location']); - $this->tryagain = true; - - return false; - } - - // see if we need to resend the request with http digest authentication - if (isset($this->incoming_headers['www-authenticate']) && $http_status == 401) { - $this->debug("Got 401 $http_reason with WWW-Authenticate: ".$this->incoming_headers['www-authenticate']); - if (strstr($this->incoming_headers['www-authenticate'], 'Digest ')) { - $this->debug('Server wants digest authentication'); - // remove "Digest " from our elements - $digestString = str_replace('Digest ', '', $this->incoming_headers['www-authenticate']); - - // parse elements into array - $digestElements = explode(',', $digestString); - foreach ($digestElements as $val) { - $tempElement = explode('=', trim($val), 2); - $digestRequest[$tempElement[0]] = str_replace('"', '', $tempElement[1]); - } - - // should have (at least) qop, realm, nonce - if (isset($digestRequest['nonce'])) { - $this->setCredentials($this->username, $this->password, 'digest', $digestRequest); - $this->tryagain = true; - - return false; - } - } - $this->debug('HTTP authentication failed'); - $this->setError('HTTP authentication failed'); - - return false; - } - - if ( - ($http_status >= 300 && $http_status <= 307) || - ($http_status >= 400 && $http_status <= 417) || - ($http_status >= 501 && $http_status <= 505) - ) { - $this->setError("Unsupported HTTP response status $http_status $http_reason (soapclient->response has contents of the response)"); - - return false; - } - - // decode content-encoding - if (isset($this->incoming_headers['content-encoding']) && $this->incoming_headers['content-encoding'] != '') { - if (strtolower($this->incoming_headers['content-encoding']) == 'deflate' || strtolower($this->incoming_headers['content-encoding']) == 'gzip') { - // if decoding works, use it. else assume data wasn't gzencoded - if (function_exists('gzinflate')) { - //$timer->setMarker('starting decoding of gzip/deflated content'); - // IIS 5 requires gzinflate instead of gzuncompress (similar to IE 5 and gzdeflate v. gzcompress) - // this means there are no Zlib headers, although there should be - $this->debug('The gzinflate function exists'); - $datalen = strlen($data); - if ($this->incoming_headers['content-encoding'] == 'deflate') { - if ($degzdata = @gzinflate($data)) { - $data = $degzdata; - $this->debug('The payload has been inflated to '.strlen($data).' bytes'); - if (strlen($data) < $datalen) { - // test for the case that the payload has been compressed twice - $this->debug('The inflated payload is smaller than the gzipped one; try again'); - if ($degzdata = @gzinflate($data)) { - $data = $degzdata; - $this->debug('The payload has been inflated again to '.strlen($data).' bytes'); - } - } - } else { - $this->debug('Error using gzinflate to inflate the payload'); - $this->setError('Error using gzinflate to inflate the payload'); - } - } elseif ($this->incoming_headers['content-encoding'] == 'gzip') { - if ($degzdata = @gzinflate(substr($data, 10))) { // do our best - $data = $degzdata; - $this->debug('The payload has been un-gzipped to '.strlen($data).' bytes'); - if (strlen($data) < $datalen) { - // test for the case that the payload has been compressed twice - $this->debug('The un-gzipped payload is smaller than the gzipped one; try again'); - if ($degzdata = @gzinflate(substr($data, 10))) { - $data = $degzdata; - $this->debug('The payload has been un-gzipped again to '.strlen($data).' bytes'); - } - } - } else { - $this->debug('Error using gzinflate to un-gzip the payload'); - $this->setError('Error using gzinflate to un-gzip the payload'); - } - } - //$timer->setMarker('finished decoding of gzip/deflated content'); - //print "\nde-inflated:\n---------------\n$data\n-------------\n"; - // set decoded payload - $this->incoming_payload = $header_data.$lb.$lb.$data; - } else { - $this->debug('The server sent compressed data. Your php install must have the Zlib extension compiled in to support this.'); - $this->setError('The server sent compressed data. Your php install must have the Zlib extension compiled in to support this.'); - } - } else { - $this->debug('Unsupported Content-Encoding '.$this->incoming_headers['content-encoding']); - $this->setError('Unsupported Content-Encoding '.$this->incoming_headers['content-encoding']); - } - } else { - $this->debug('No Content-Encoding header'); - } - - if (strlen($data) == 0) { - $this->debug('no data after headers!'); - $this->setError('no data present after HTTP headers'); - - return false; - } - - return $data; - } - - /** - * sets the content-type for the SOAP message to be sent. - * - * @param string $type the content type, MIME style - * @param mixed $charset character set used for encoding (or false) - */ - public function setContentType($type, $charset = false) - { - $this->setHeader('Content-Type', $type.($charset ? '; charset='.$charset : '')); - } - - /** - * specifies that an HTTP persistent connection should be used. - * - * @return bool whether the request was honored by this method. - */ - public function usePersistentConnection() - { - if (isset($this->outgoing_headers['Accept-Encoding'])) { - return false; - } - $this->protocol_version = '1.1'; - $this->persistentConnection = true; - $this->setHeader('Connection', 'Keep-Alive'); - - return true; - } - - /** - * parse an incoming Cookie into it's parts. - * - * @param string $cookie_str content of cookie - * - * @return array with data of that cookie - */ - /* - * TODO: allow a Set-Cookie string to be parsed into multiple cookies - */ - public function parseCookie($cookie_str) - { - $cookie_str = str_replace('; ', ';', $cookie_str).';'; - $data = preg_split('/;/', $cookie_str); - $value_str = $data[0]; - - $cookie_param = 'domain='; - $start = strpos($cookie_str, $cookie_param); - if ($start > 0) { - $domain = substr($cookie_str, $start + strlen($cookie_param)); - $domain = substr($domain, 0, strpos($domain, ';')); - } else { - $domain = ''; - } - - $cookie_param = 'expires='; - $start = strpos($cookie_str, $cookie_param); - if ($start > 0) { - $expires = substr($cookie_str, $start + strlen($cookie_param)); - $expires = substr($expires, 0, strpos($expires, ';')); - } else { - $expires = ''; - } - - $cookie_param = 'path='; - $start = strpos($cookie_str, $cookie_param); - if ($start > 0) { - $path = substr($cookie_str, $start + strlen($cookie_param)); - $path = substr($path, 0, strpos($path, ';')); - } else { - $path = '/'; - } - - $cookie_param = ';secure;'; - if (strpos($cookie_str, $cookie_param) !== false) { - $secure = true; - } else { - $secure = false; - } - - $sep_pos = strpos($value_str, '='); - - if ($sep_pos) { - $name = substr($value_str, 0, $sep_pos); - $value = substr($value_str, $sep_pos + 1); - $cookie = ['name' => $name, - 'value' => $value, - 'domain' => $domain, - 'path' => $path, - 'expires' => $expires, - 'secure' => $secure, - ]; - - return $cookie; - } - - return false; - } - - /** - * sort out cookies for the current request. - * - * @param array $cookies array with all cookies - * @param bool $secure is the send-content secure or not? - * - * @return string for Cookie-HTTP-Header - */ - public function getCookiesForRequest($cookies, $secure = false) - { - $cookie_str = ''; - if ((!is_null($cookies)) && (is_array($cookies))) { - foreach ($cookies as $cookie) { - if (!is_array($cookie)) { - continue; - } - $this->debug('check cookie for validity: '.$cookie['name'].'='.$cookie['value']); - if ((isset($cookie['expires'])) && (!empty($cookie['expires']))) { - if (strtotime($cookie['expires']) <= time()) { - $this->debug('cookie has expired'); - continue; - } - } - if ((isset($cookie['domain'])) && (!empty($cookie['domain']))) { - $domain = preg_quote($cookie['domain']); - if (!preg_match("'.*$domain$'i", $this->host)) { - $this->debug('cookie has different domain'); - continue; - } - } - if ((isset($cookie['path'])) && (!empty($cookie['path']))) { - $path = preg_quote($cookie['path']); - if (!preg_match("'^$path.*'i", $this->path)) { - $this->debug('cookie is for a different path'); - continue; - } - } - if ((!$secure) && (isset($cookie['secure'])) && ($cookie['secure'])) { - $this->debug('cookie is secure, transport is not'); - continue; - } - $cookie_str .= $cookie['name'].'='.$cookie['value'].'; '; - $this->debug('add cookie to Cookie-String: '.$cookie['name'].'='.$cookie['value']); - } - } - - return $cookie_str; - } -} diff --git a/src/Drivers/lib/class.soap_val.php b/src/Drivers/lib/class.soap_val.php deleted file mode 100644 index 41c0908..0000000 --- a/src/Drivers/lib/class.soap_val.php +++ /dev/null @@ -1,102 +0,0 @@ - - * - * @version $Id: class.soap_val.php,v 1.11 2007/04/06 13:56:32 snichol Exp $ - */ -class soapval extends nusoap_base -{ - /* - * The XML element name - * - * @var string - * @access private - */ - public $name; - /* - * The XML type name (string or false) - * - * @var mixed - * @access private - */ - public $type; - /* - * The PHP value - * - * @var mixed - * @access private - */ - public $value; - /* - * The XML element namespace (string or false) - * - * @var mixed - * @access private - */ - public $element_ns; - /* - * The XML type namespace (string or false) - * - * @var mixed - * @access private - */ - public $type_ns; - /* - * The XML element attributes (array or false) - * - * @var mixed - * @access private - */ - public $attributes; - - /** - * constructor. - * - * @param string $name optional name - * @param mixed $type optional type name - * @param mixed $value optional value - * @param mixed $element_ns optional namespace of value - * @param mixed $type_ns optional namespace of type - * @param mixed $attributes associative array of attributes to add to element serialization - */ - public function soapval($name = 'soapval', $type = false, $value = -1, $element_ns = false, $type_ns = false, $attributes = false) - { - parent::nusoap_base(); - $this->name = $name; - $this->type = $type; - $this->value = $value; - $this->element_ns = $element_ns; - $this->type_ns = $type_ns; - $this->attributes = $attributes; - } - - /** - * return serialized value. - * - * @param string $use The WSDL use value (encoded|literal) - * - * @return string XML data - */ - public function serialize($use = 'encoded') - { - return $this->serialize_val($this->value, $this->name, $this->type, $this->element_ns, $this->type_ns, $this->attributes, $use, true); - } - - /** - * decodes a soapval object into a PHP native type. - * - * @return mixed - */ - public function decode() - { - return $this->value; - } -} diff --git a/src/Drivers/lib/class.soapclient.php b/src/Drivers/lib/class.soapclient.php deleted file mode 100644 index 5c6b651..0000000 --- a/src/Drivers/lib/class.soapclient.php +++ /dev/null @@ -1,1020 +0,0 @@ -call( string methodname [ ,array parameters] ); - * - * // bye bye client - * unset($soapclient); - * - * @author Dietrich Ayala - * @author Scott Nichol - * - * @version $Id: class.soapclient.php,v 1.69 2010/04/26 20:15:08 snichol Exp $ - */ -class nusoap_client extends nusoap_base -{ - public $username = ''; // Username for HTTP authentication - public $password = ''; // Password for HTTP authentication - public $authtype = ''; // Type of HTTP authentication - public $certRequest = []; // Certificate for HTTP SSL authentication - public $requestHeaders = false; // SOAP headers in request (text) - public $responseHeaders = ''; // SOAP headers from response (incomplete namespace resolution) (text) - public $responseHeader = null; // SOAP Header from response (parsed) - public $document = ''; // SOAP body response portion (incomplete namespace resolution) (text) - public $endpoint; - public $forceEndpoint = ''; // overrides WSDL endpoint - public $proxyhost = ''; - public $proxyport = ''; - public $proxyusername = ''; - public $proxypassword = ''; - public $portName = ''; // port name to use in WSDL - public $xml_encoding = ''; // character set encoding of incoming (response) messages - public $http_encoding = false; - public $timeout = 0; // HTTP connection timeout - public $response_timeout = 30; // HTTP response timeout - public $endpointType = ''; // soap|wsdl, empty for WSDL initialization error - public $persistentConnection = false; - public $defaultRpcParams = false; // This is no longer used - public $request = ''; // HTTP request - public $response = ''; // HTTP response - public $responseData = ''; // SOAP payload of response - public $cookies = []; // Cookies from response or for request - public $decode_utf8 = true; // toggles whether the parser decodes element content w/ utf8_decode() - public $operations = []; // WSDL operations, empty for WSDL initialization error - public $curl_options = []; // User-specified cURL options - public $bindingType = ''; // WSDL operation binding type - public $use_curl = false; // whether to always try to use cURL - - /* - * fault related variables - */ - /* - * @var fault - * @access public - */ - public $fault; - /* - * @var faultcode - * @access public - */ - public $faultcode; - /* - * @var faultstring - * @access public - */ - public $faultstring; - /* - * @var faultdetail - * @access public - */ - public $faultdetail; - - /** - * constructor. - * - * @param mixed $endpoint SOAP server or WSDL URL (string), or wsdl instance (object) - * @param mixed $wsdl optional, set to 'wsdl' or true if using WSDL - * @param string $proxyhost optional - * @param string $proxyport optional - * @param string $proxyusername optional - * @param string $proxypassword optional - * @param int $timeout set the connection timeout - * @param int $response_timeout set the response timeout - * @param string $portName optional portName in WSDL document - */ - public function nusoap_client($endpoint, $wsdl = false, $proxyhost = false, $proxyport = false, $proxyusername = false, $proxypassword = false, $timeout = 0, $response_timeout = 30, $portName = '') - { - parent::nusoap_base(); - $this->endpoint = $endpoint; - $this->proxyhost = $proxyhost; - $this->proxyport = $proxyport; - $this->proxyusername = $proxyusername; - $this->proxypassword = $proxypassword; - $this->timeout = $timeout; - $this->response_timeout = $response_timeout; - $this->portName = $portName; - - $this->debug("ctor wsdl=$wsdl timeout=$timeout response_timeout=$response_timeout"); - $this->appendDebug('endpoint='.$this->varDump($endpoint)); - - // make values - if ($wsdl) { - if (is_object($endpoint) && (get_class($endpoint) == 'wsdl')) { - $this->wsdl = $endpoint; - $this->endpoint = $this->wsdl->wsdl; - $this->wsdlFile = $this->endpoint; - $this->debug('existing wsdl instance created from '.$this->endpoint); - $this->checkWSDL(); - } else { - $this->wsdlFile = $this->endpoint; - $this->wsdl = null; - $this->debug('will use lazy evaluation of wsdl from '.$this->endpoint); - } - $this->endpointType = 'wsdl'; - } else { - $this->debug("instantiate SOAP with endpoint at $endpoint"); - $this->endpointType = 'soap'; - } - } - - /** - * calls method, returns PHP native type. - * - * @param string $operation SOAP server URL or path - * @param mixed $params An array, associative or simple, of the parameters - * for the method call, or a string that is the XML - * for the call. For rpc style, this call will - * wrap the XML in a tag named after the method, as - * well as the SOAP Envelope and Body. For document - * style, this will only wrap with the Envelope and Body. - * IMPORTANT: when using an array with document style, - * in which case there - * is really one parameter, the root of the fragment - * used in the call, which encloses what programmers - * normally think of parameters. A parameter array - * *must* include the wrapper. - * @param string $namespace optional method namespace (WSDL can override) - * @param string $soapAction optional SOAPAction value (WSDL can override) - * @param mixed $headers optional string of XML with SOAP header content, or array of soapval objects for SOAP headers, or associative array - * @param bool $rpcParams optional (no longer used) - * @param string $style optional (rpc|document) the style to use when serializing parameters (WSDL can override) - * @param string $use optional (encoded|literal) the use when serializing parameters (WSDL can override) - * - * @return mixed response from SOAP call, normally an associative array mirroring the structure of the XML response, false for certain fatal errors - */ - public function call($operation, $params = [], $namespace = 'http://tempuri.org', $soapAction = '', $headers = false, $rpcParams = null, $style = 'rpc', $use = 'encoded') - { - $this->operation = $operation; - $this->fault = false; - $this->setError(''); - $this->request = ''; - $this->response = ''; - $this->responseData = ''; - $this->faultstring = ''; - $this->faultcode = ''; - $this->opData = []; - - $this->debug("call: operation=$operation, namespace=$namespace, soapAction=$soapAction, rpcParams=$rpcParams, style=$style, use=$use, endpointType=$this->endpointType"); - $this->appendDebug('params='.$this->varDump($params)); - $this->appendDebug('headers='.$this->varDump($headers)); - if ($headers) { - $this->requestHeaders = $headers; - } - if ($this->endpointType == 'wsdl' && is_null($this->wsdl)) { - $this->loadWSDL(); - if ($this->getError()) { - return false; - } - } - // serialize parameters - if ($this->endpointType == 'wsdl' && $opData = $this->getOperationData($operation)) { - // use WSDL for operation - $this->opData = $opData; - $this->debug('found operation'); - $this->appendDebug('opData='.$this->varDump($opData)); - if (isset($opData['soapAction'])) { - $soapAction = $opData['soapAction']; - } - if (!$this->forceEndpoint) { - $this->endpoint = $opData['endpoint']; - } else { - $this->endpoint = $this->forceEndpoint; - } - $namespace = isset($opData['input']['namespace']) ? $opData['input']['namespace'] : $namespace; - $style = $opData['style']; - $use = $opData['input']['use']; - // add ns to ns array - if ($namespace != '' && !isset($this->wsdl->namespaces[$namespace])) { - $nsPrefix = 'ns'.rand(1000, 9999); - $this->wsdl->namespaces[$nsPrefix] = $namespace; - } - $nsPrefix = $this->wsdl->getPrefixFromNamespace($namespace); - // serialize payload - if (is_string($params)) { - $this->debug("serializing param string for WSDL operation $operation"); - $payload = $params; - } elseif (is_array($params)) { - $this->debug("serializing param array for WSDL operation $operation"); - $payload = $this->wsdl->serializeRPCParameters($operation, 'input', $params, $this->bindingType); - } else { - $this->debug('params must be array or string'); - $this->setError('params must be array or string'); - - return false; - } - $usedNamespaces = $this->wsdl->usedNamespaces; - if (isset($opData['input']['encodingStyle'])) { - $encodingStyle = $opData['input']['encodingStyle']; - } else { - $encodingStyle = ''; - } - $this->appendDebug($this->wsdl->getDebug()); - $this->wsdl->clearDebug(); - if ($errstr = $this->wsdl->getError()) { - $this->debug('got wsdl error: '.$errstr); - $this->setError('wsdl error: '.$errstr); - - return false; - } - } elseif ($this->endpointType == 'wsdl') { - // operation not in WSDL - $this->appendDebug($this->wsdl->getDebug()); - $this->wsdl->clearDebug(); - $this->setError('operation '.$operation.' not present in WSDL.'); - $this->debug("operation '$operation' not present in WSDL."); - - return false; - } else { - // no WSDL - //$this->namespaces['ns1'] = $namespace; - $nsPrefix = 'ns'.rand(1000, 9999); - // serialize - $payload = ''; - if (is_string($params)) { - $this->debug("serializing param string for operation $operation"); - $payload = $params; - } elseif (is_array($params)) { - $this->debug("serializing param array for operation $operation"); - foreach ($params as $k => $v) { - $payload .= $this->serialize_val($v, $k, false, false, false, false, $use); - } - } else { - $this->debug('params must be array or string'); - $this->setError('params must be array or string'); - - return false; - } - $usedNamespaces = []; - if ($use == 'encoded') { - $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/'; - } else { - $encodingStyle = ''; - } - } - // wrap RPC calls with method element - if ($style == 'rpc') { - if ($use == 'literal') { - $this->debug('wrapping RPC request with literal method element'); - if ($namespace) { - // http://www.ws-i.org/Profiles/BasicProfile-1.1-2004-08-24.html R2735 says rpc/literal accessor elements should not be in a namespace - $payload = "<$nsPrefix:$operation xmlns:$nsPrefix=\"$namespace\">". - $payload. - ""; - } else { - $payload = "<$operation>".$payload.""; - } - } else { - $this->debug('wrapping RPC request with encoded method element'); - if ($namespace) { - $payload = "<$nsPrefix:$operation xmlns:$nsPrefix=\"$namespace\">". - $payload. - ""; - } else { - $payload = "<$operation>". - $payload. - ""; - } - } - } - // serialize envelope - $soapmsg = $this->serializeEnvelope($payload, $this->requestHeaders, $usedNamespaces, $style, $use, $encodingStyle); - $this->debug("endpoint=$this->endpoint, soapAction=$soapAction, namespace=$namespace, style=$style, use=$use, encodingStyle=$encodingStyle"); - $this->debug('SOAP message length='.strlen($soapmsg).' contents (max 1000 bytes)='.substr($soapmsg, 0, 1000)); - // send - $return = $this->send($this->getHTTPBody($soapmsg), $soapAction, $this->timeout, $this->response_timeout); - if ($errstr = $this->getError()) { - $this->debug('Error: '.$errstr); - - return false; - } else { - $this->return = $return; - $this->debug('sent message successfully and got a(n) '.gettype($return)); - $this->appendDebug('return='.$this->varDump($return)); - - // fault? - if (is_array($return) && isset($return['faultcode'])) { - $this->debug('got fault'); - $this->setError($return['faultcode'].': '.$return['faultstring']); - $this->fault = true; - foreach ($return as $k => $v) { - $this->$k = $v; - $this->debug("$k = $v
"); - } - - return $return; - } elseif ($style == 'document') { - // NOTE: if the response is defined to have multiple parts (i.e. unwrapped), - // we are only going to return the first part here...sorry about that - return $return; - } else { - // array of return values - if (is_array($return)) { - // multiple 'out' parameters, which we return wrapped up - // in the array - if (count($return) > 1) { - return $return; - } - // single 'out' parameter (normally the return value) - $return = array_shift($return); - $this->debug('return shifted value: '); - $this->appendDebug($this->varDump($return)); - - return $return; - // nothing returned (ie, echoVoid) - } else { - return ''; - } - } - } - } - - /** - * check WSDL passed as an instance or pulled from an endpoint. - */ - public function checkWSDL() - { - $this->appendDebug($this->wsdl->getDebug()); - $this->wsdl->clearDebug(); - $this->debug('checkWSDL'); - // catch errors - if ($errstr = $this->wsdl->getError()) { - $this->appendDebug($this->wsdl->getDebug()); - $this->wsdl->clearDebug(); - $this->debug('got wsdl error: '.$errstr); - $this->setError('wsdl error: '.$errstr); - } elseif ($this->operations = $this->wsdl->getOperations($this->portName, 'soap')) { - $this->appendDebug($this->wsdl->getDebug()); - $this->wsdl->clearDebug(); - $this->bindingType = 'soap'; - $this->debug('got '.count($this->operations).' operations from wsdl '.$this->wsdlFile.' for binding type '.$this->bindingType); - } elseif ($this->operations = $this->wsdl->getOperations($this->portName, 'soap12')) { - $this->appendDebug($this->wsdl->getDebug()); - $this->wsdl->clearDebug(); - $this->bindingType = 'soap12'; - $this->debug('got '.count($this->operations).' operations from wsdl '.$this->wsdlFile.' for binding type '.$this->bindingType); - $this->debug('**************** WARNING: SOAP 1.2 BINDING *****************'); - } else { - $this->appendDebug($this->wsdl->getDebug()); - $this->wsdl->clearDebug(); - $this->debug('getOperations returned false'); - $this->setError('no operations defined in the WSDL document!'); - } - } - - /** - * instantiate wsdl object and parse wsdl file. - */ - public function loadWSDL() - { - $this->debug('instantiating wsdl class with doc: '.$this->wsdlFile); - $this->wsdl = new wsdl('', $this->proxyhost, $this->proxyport, $this->proxyusername, $this->proxypassword, $this->timeout, $this->response_timeout, $this->curl_options, $this->use_curl); - $this->wsdl->setCredentials($this->username, $this->password, $this->authtype, $this->certRequest); - $this->wsdl->fetchWSDL($this->wsdlFile); - $this->checkWSDL(); - } - - /** - * get available data pertaining to an operation. - * - * @param string $operation operation name - * - * @return array array of data pertaining to the operation - */ - public function getOperationData($operation) - { - if ($this->endpointType == 'wsdl' && is_null($this->wsdl)) { - $this->loadWSDL(); - if ($this->getError()) { - return false; - } - } - if (isset($this->operations[$operation])) { - return $this->operations[$operation]; - } - $this->debug("No data for operation: $operation"); - } - - /** - * send the SOAP message. - * - * Note: if the operation has multiple return values - * the return value of this method will be an array - * of those values. - * - * @param string $msg a SOAPx4 soapmsg object - * @param string $soapaction SOAPAction value - * @param int $timeout set connection timeout in seconds - * @param int $response_timeout set response timeout in seconds - * - * @return mixed native PHP types. - */ - public function send($msg, $soapaction = '', $timeout = 0, $response_timeout = 30) - { - $this->checkCookies(); - // detect transport - switch (true) { - // http(s) - case preg_match('/^http/', $this->endpoint): - $this->debug('transporting via HTTP'); - if ($this->persistentConnection == true && is_object($this->persistentConnection)) { - $http = &$this->persistentConnection; - } else { - $http = new soap_transport_http($this->endpoint, $this->curl_options, $this->use_curl); - if ($this->persistentConnection) { - $http->usePersistentConnection(); - } - } - $http->setContentType($this->getHTTPContentType(), $this->getHTTPContentTypeCharset()); - $http->setSOAPAction($soapaction); - if ($this->proxyhost && $this->proxyport) { - $http->setProxy($this->proxyhost, $this->proxyport, $this->proxyusername, $this->proxypassword); - } - if ($this->authtype != '') { - $http->setCredentials($this->username, $this->password, $this->authtype, [], $this->certRequest); - } - if ($this->http_encoding != '') { - $http->setEncoding($this->http_encoding); - } - $this->debug('sending message, length='.strlen($msg)); - if (preg_match('/^http:/', $this->endpoint)) { - //if(strpos($this->endpoint,'http:')){ - $this->responseData = $http->send($msg, $timeout, $response_timeout, $this->cookies); - } elseif (preg_match('/^https/', $this->endpoint)) { - //} elseif(strpos($this->endpoint,'https:')){ - //if(phpversion() == '4.3.0-dev'){ - //$response = $http->send($msg,$timeout,$response_timeout); - //$this->request = $http->outgoing_payload; - //$this->response = $http->incoming_payload; - //} else - $this->responseData = $http->sendHTTPS($msg, $timeout, $response_timeout, $this->cookies); - } else { - $this->setError('no http/s in endpoint url'); - } - $this->request = $http->outgoing_payload; - $this->response = $http->incoming_payload; - $this->appendDebug($http->getDebug()); - $this->UpdateCookies($http->incoming_cookies); - - // save transport object if using persistent connections - if ($this->persistentConnection) { - $http->clearDebug(); - if (!is_object($this->persistentConnection)) { - $this->persistentConnection = $http; - } - } - - if ($err = $http->getError()) { - $this->setError('HTTP Error: '.$err); - - return false; - } elseif ($this->getError()) { - return false; - } else { - $this->debug('got response, length='.strlen($this->responseData).' type='.$http->incoming_headers['content-type']); - - return $this->parseResponse($http->incoming_headers, $this->responseData); - } - break; - default: - $this->setError('no transport found, or selected transport is not yet supported!'); - - return false; - break; - } - } - - /** - * processes SOAP message returned from server. - * - * @param array $headers The HTTP headers - * @param string $data unprocessed response data from server - * - * @return mixed value of the message, decoded into a PHP type - */ - public function parseResponse($headers, $data) - { - $this->debug('Entering parseResponse() for data of length '.strlen($data).' headers:'); - $this->appendDebug($this->varDump($headers)); - if (!isset($headers['content-type'])) { - $this->setError('Response not of type text/xml (no content-type header)'); - - return false; - } - if (!strstr($headers['content-type'], 'text/xml')) { - $this->setError('Response not of type text/xml: '.$headers['content-type']); - - return false; - } - if (strpos($headers['content-type'], '=')) { - $enc = str_replace('"', '', substr(strstr($headers['content-type'], '='), 1)); - $this->debug('Got response encoding: '.$enc); - if (preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i', $enc)) { - $this->xml_encoding = strtoupper($enc); - } else { - $this->xml_encoding = 'US-ASCII'; - } - } else { - // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1 - $this->xml_encoding = 'ISO-8859-1'; - } - $this->debug('Use encoding: '.$this->xml_encoding.' when creating nusoap_parser'); - $parser = new nusoap_parser($data, $this->xml_encoding, $this->operation, $this->decode_utf8); - // add parser debug data to our debug - $this->appendDebug($parser->getDebug()); - // if parse errors - if ($errstr = $parser->getError()) { - $this->setError($errstr); - // destroy the parser object - unset($parser); - - return false; - } else { - // get SOAP headers - $this->responseHeaders = $parser->getHeaders(); - // get SOAP headers - $this->responseHeader = $parser->get_soapheader(); - // get decoded message - $return = $parser->get_soapbody(); - // add document for doclit support - $this->document = $parser->document; - // destroy the parser object - unset($parser); - // return decode message - return $return; - } - } - - /** - * sets user-specified cURL options. - * - * @param mixed $option The cURL option (always integer?) - * @param mixed $value The cURL option value - */ - public function setCurlOption($option, $value) - { - $this->debug("setCurlOption option=$option, value="); - $this->appendDebug($this->varDump($value)); - $this->curl_options[$option] = $value; - } - - /** - * sets the SOAP endpoint, which can override WSDL. - * - * @param string $endpoint The endpoint URL to use, or empty string or false to prevent override - */ - public function setEndpoint($endpoint) - { - $this->debug("setEndpoint(\"$endpoint\")"); - $this->forceEndpoint = $endpoint; - } - - /** - * set the SOAP headers. - * - * @param mixed $headers String of XML with SOAP header content, or array of soapval objects for SOAP headers - */ - public function setHeaders($headers) - { - $this->debug('setHeaders headers='); - $this->appendDebug($this->varDump($headers)); - $this->requestHeaders = $headers; - } - - /** - * get the SOAP response headers (namespace resolution incomplete). - * - * @return string - */ - public function getHeaders() - { - return $this->responseHeaders; - } - - /** - * get the SOAP response Header (parsed). - * - * @return mixed - */ - public function getHeader() - { - return $this->responseHeader; - } - - /** - * set proxy info here. - * - * @param string $proxyhost - * @param string $proxyport - * @param string $proxyusername - * @param string $proxypassword - */ - public function setHTTPProxy($proxyhost, $proxyport, $proxyusername = '', $proxypassword = '') - { - $this->proxyhost = $proxyhost; - $this->proxyport = $proxyport; - $this->proxyusername = $proxyusername; - $this->proxypassword = $proxypassword; - } - - /** - * if authenticating, set user credentials here. - * - * @param string $username - * @param string $password - * @param string $authtype (basic|digest|certificate|ntlm) - * @param array $certRequest (keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, verifypeer (optional), verifyhost (optional): see corresponding options in cURL docs) - */ - public function setCredentials($username, $password, $authtype = 'basic', $certRequest = []) - { - $this->debug("setCredentials username=$username authtype=$authtype certRequest="); - $this->appendDebug($this->varDump($certRequest)); - $this->username = $username; - $this->password = $password; - $this->authtype = $authtype; - $this->certRequest = $certRequest; - } - - /** - * use HTTP encoding. - * - * @param string $enc HTTP encoding - */ - public function setHTTPEncoding($enc = 'gzip, deflate') - { - $this->debug("setHTTPEncoding(\"$enc\")"); - $this->http_encoding = $enc; - } - - /** - * Set whether to try to use cURL connections if possible. - * - * @param bool $use Whether to try to use cURL - */ - public function setUseCURL($use) - { - $this->debug("setUseCURL($use)"); - $this->use_curl = $use; - } - - /** - * use HTTP persistent connections if possible. - */ - public function useHTTPPersistentConnection() - { - $this->debug('useHTTPPersistentConnection'); - $this->persistentConnection = true; - } - - /** - * gets the default RPC parameter setting. - * If true, default is that call params are like RPC even for document style. - * Each call() can override this value. - * - * This is no longer used. - * - * @return bool - * - * @deprecated - */ - public function getDefaultRpcParams() - { - return $this->defaultRpcParams; - } - - /** - * sets the default RPC parameter setting. - * If true, default is that call params are like RPC even for document style - * Each call() can override this value. - * - * This is no longer used. - * - * @param bool $rpcParams - * - * @deprecated - */ - public function setDefaultRpcParams($rpcParams) - { - $this->defaultRpcParams = $rpcParams; - } - - /** - * dynamically creates an instance of a proxy class, - * allowing user to directly call methods from wsdl. - * - * @return object soap_proxy object - */ - public function getProxy() - { - $r = rand(); - $evalStr = $this->_getProxyClassCode($r); - //$this->debug("proxy class: $evalStr"); - if ($this->getError()) { - $this->debug('Error from _getProxyClassCode, so return NULL'); - - return; - } - // eval the class - eval($evalStr); - // instantiate proxy object - eval("\$proxy = new nusoap_proxy_$r('');"); - // transfer current wsdl data to the proxy thereby avoiding parsing the wsdl twice - $proxy->endpointType = 'wsdl'; - $proxy->wsdlFile = $this->wsdlFile; - $proxy->wsdl = $this->wsdl; - $proxy->operations = $this->operations; - $proxy->defaultRpcParams = $this->defaultRpcParams; - // transfer other state - $proxy->soap_defencoding = $this->soap_defencoding; - $proxy->username = $this->username; - $proxy->password = $this->password; - $proxy->authtype = $this->authtype; - $proxy->certRequest = $this->certRequest; - $proxy->requestHeaders = $this->requestHeaders; - $proxy->endpoint = $this->endpoint; - $proxy->forceEndpoint = $this->forceEndpoint; - $proxy->proxyhost = $this->proxyhost; - $proxy->proxyport = $this->proxyport; - $proxy->proxyusername = $this->proxyusername; - $proxy->proxypassword = $this->proxypassword; - $proxy->http_encoding = $this->http_encoding; - $proxy->timeout = $this->timeout; - $proxy->response_timeout = $this->response_timeout; - $proxy->persistentConnection = &$this->persistentConnection; - $proxy->decode_utf8 = $this->decode_utf8; - $proxy->curl_options = $this->curl_options; - $proxy->bindingType = $this->bindingType; - $proxy->use_curl = $this->use_curl; - - return $proxy; - } - - /** - * dynamically creates proxy class code. - * - * @return string PHP/NuSOAP code for the proxy class - */ - public function _getProxyClassCode($r) - { - $this->debug("in getProxy endpointType=$this->endpointType"); - $this->appendDebug('wsdl='.$this->varDump($this->wsdl)); - if ($this->endpointType != 'wsdl') { - $evalStr = 'A proxy can only be created for a WSDL client'; - $this->setError($evalStr); - $evalStr = "echo \"$evalStr\";"; - - return $evalStr; - } - if ($this->endpointType == 'wsdl' && is_null($this->wsdl)) { - $this->loadWSDL(); - if ($this->getError()) { - return 'echo "'.$this->getError().'";'; - } - } - $evalStr = ''; - foreach ($this->operations as $operation => $opData) { - if ($operation != '') { - // create param string and param comment string - if (count($opData['input']['parts']) > 0) { - $paramStr = ''; - $paramArrayStr = ''; - $paramCommentStr = ''; - foreach ($opData['input']['parts'] as $name => $type) { - $paramStr .= "\$$name, "; - $paramArrayStr .= "'$name' => \$$name, "; - $paramCommentStr .= "$type \$$name, "; - } - $paramStr = substr($paramStr, 0, strlen($paramStr) - 2); - $paramArrayStr = substr($paramArrayStr, 0, strlen($paramArrayStr) - 2); - $paramCommentStr = substr($paramCommentStr, 0, strlen($paramCommentStr) - 2); - } else { - $paramStr = ''; - $paramArrayStr = ''; - $paramCommentStr = 'void'; - } - $opData['namespace'] = !isset($opData['namespace']) ? 'http://testuri.com' : $opData['namespace']; - $evalStr .= "// $paramCommentStr - function ".str_replace('.', '__', $operation)."($paramStr) { - \$params = array($paramArrayStr); - return \$this->call('$operation', \$params, '".$opData['namespace']."', '".(isset($opData['soapAction']) ? $opData['soapAction'] : '')."'); - } - "; - unset($paramStr); - unset($paramCommentStr); - } - } - $evalStr = 'class nusoap_proxy_'.$r.' extends nusoap_client { - '.$evalStr.' -}'; - - return $evalStr; - } - - /** - * dynamically creates proxy class code. - * - * @return string PHP/NuSOAP code for the proxy class - */ - public function getProxyClassCode() - { - $r = rand(); - - return $this->_getProxyClassCode($r); - } - - /** - * gets the HTTP body for the current request. - * - * @param string $soapmsg The SOAP payload - * - * @return string The HTTP body, which includes the SOAP payload - */ - public function getHTTPBody($soapmsg) - { - return $soapmsg; - } - - /** - * gets the HTTP content type for the current request. - * - * Note: getHTTPBody must be called before this. - * - * @return string the HTTP content type for the current request. - */ - public function getHTTPContentType() - { - return 'text/xml'; - } - - /** - * gets the HTTP content type charset for the current request. - * returns false for non-text content types. - * - * Note: getHTTPBody must be called before this. - * - * @return string the HTTP content type charset for the current request. - */ - public function getHTTPContentTypeCharset() - { - return $this->soap_defencoding; - } - - /* - * whether or not parser should decode utf8 element content - * - * @return always returns true - * @access public - */ - public function decodeUTF8($bool) - { - $this->decode_utf8 = $bool; - - return true; - } - - /** - * adds a new Cookie into $this->cookies array. - * - * @param string $name Cookie Name - * @param string $value Cookie Value - * - * @return bool if cookie-set was successful returns true, else false - */ - public function setCookie($name, $value) - { - if (strlen($name) == 0) { - return false; - } - $this->cookies[] = ['name' => $name, 'value' => $value]; - - return true; - } - - /** - * gets all Cookies. - * - * @return array with all internal cookies - */ - public function getCookies() - { - return $this->cookies; - } - - /** - * checks all Cookies and delete those which are expired. - * - * @return bool always return true - */ - public function checkCookies() - { - if (count($this->cookies) == 0) { - return true; - } - $this->debug('checkCookie: check '.count($this->cookies).' cookies'); - $curr_cookies = $this->cookies; - $this->cookies = []; - foreach ($curr_cookies as $cookie) { - if (!is_array($cookie)) { - $this->debug('Remove cookie that is not an array'); - continue; - } - if ((isset($cookie['expires'])) && (!empty($cookie['expires']))) { - if (strtotime($cookie['expires']) > time()) { - $this->cookies[] = $cookie; - } else { - $this->debug('Remove expired cookie '.$cookie['name']); - } - } else { - $this->cookies[] = $cookie; - } - } - $this->debug('checkCookie: '.count($this->cookies).' cookies left in array'); - - return true; - } - - /** - * updates the current cookies with a new set. - * - * @param array $cookies new cookies with which to update current ones - * - * @return bool always return true - */ - public function UpdateCookies($cookies) - { - if (count($this->cookies) == 0) { - // no existing cookies: take whatever is new - if (count($cookies) > 0) { - $this->debug('Setting new cookie(s)'); - $this->cookies = $cookies; - } - - return true; - } - if (count($cookies) == 0) { - // no new cookies: keep what we've got - return true; - } - // merge - foreach ($cookies as $newCookie) { - if (!is_array($newCookie)) { - continue; - } - if ((!isset($newCookie['name'])) || (!isset($newCookie['value']))) { - continue; - } - $newName = $newCookie['name']; - - $found = false; - for ($i = 0; $i < count($this->cookies); $i++) { - $cookie = $this->cookies[$i]; - if (!is_array($cookie)) { - continue; - } - if (!isset($cookie['name'])) { - continue; - } - if ($newName != $cookie['name']) { - continue; - } - $newDomain = isset($newCookie['domain']) ? $newCookie['domain'] : 'NODOMAIN'; - $domain = isset($cookie['domain']) ? $cookie['domain'] : 'NODOMAIN'; - if ($newDomain != $domain) { - continue; - } - $newPath = isset($newCookie['path']) ? $newCookie['path'] : 'NOPATH'; - $path = isset($cookie['path']) ? $cookie['path'] : 'NOPATH'; - if ($newPath != $path) { - continue; - } - $this->cookies[$i] = $newCookie; - $found = true; - $this->debug('Update cookie '.$newName.'='.$newCookie['value']); - break; - } - if (!$found) { - $this->debug('Add cookie '.$newName.'='.$newCookie['value']); - $this->cookies[] = $newCookie; - } - } - - return true; - } -} - -if (!extension_loaded('soap')) { - /** - * For backwards compatiblity, define soapclient unless the PHP SOAP extension is loaded. - */ - class soapclient extends nusoap_client - { - } -} diff --git a/src/Drivers/lib/class.wsdl.php b/src/Drivers/lib/class.wsdl.php deleted file mode 100644 index 3825ce9..0000000 --- a/src/Drivers/lib/class.wsdl.php +++ /dev/null @@ -1,1971 +0,0 @@ - - * @author Scott Nichol - * - * @version $Id: class.wsdl.php,v 1.76 2010/04/26 20:15:08 snichol Exp $ - */ -class wsdl extends nusoap_base -{ - // URL or filename of the root of this WSDL - public $wsdl; - // define internal arrays of bindings, ports, operations, messages, etc. - public $schemas = []; - public $currentSchema; - public $message = []; - public $complexTypes = []; - public $messages = []; - public $currentMessage; - public $currentOperation; - public $portTypes = []; - public $currentPortType; - public $bindings = []; - public $currentBinding; - public $ports = []; - public $currentPort; - public $opData = []; - public $status = ''; - public $documentation = false; - public $endpoint = ''; - // array of wsdl docs to import - public $import = []; - // parser vars - public $parser; - public $position = 0; - public $depth = 0; - public $depth_array = []; - // for getting wsdl - public $proxyhost = ''; - public $proxyport = ''; - public $proxyusername = ''; - public $proxypassword = ''; - public $timeout = 0; - public $response_timeout = 30; - public $curl_options = []; // User-specified cURL options - public $use_curl = false; // whether to always try to use cURL - // for HTTP authentication - public $username = ''; // Username for HTTP authentication - public $password = ''; // Password for HTTP authentication - public $authtype = ''; // Type of HTTP authentication - public $certRequest = []; // Certificate for HTTP SSL authentication - - /** - * constructor. - * - * @param string $wsdl WSDL document URL - * @param string $proxyhost - * @param string $proxyport - * @param string $proxyusername - * @param string $proxypassword - * @param int $timeout set the connection timeout - * @param int $response_timeout set the response timeout - * @param array $curl_options user-specified cURL options - * @param bool $use_curl try to use cURL - */ - public function wsdl($wsdl = '', $proxyhost = false, $proxyport = false, $proxyusername = false, $proxypassword = false, $timeout = 0, $response_timeout = 30, $curl_options = null, $use_curl = false) - { - parent::nusoap_base(); - $this->debug("ctor wsdl=$wsdl timeout=$timeout response_timeout=$response_timeout"); - $this->proxyhost = $proxyhost; - $this->proxyport = $proxyport; - $this->proxyusername = $proxyusername; - $this->proxypassword = $proxypassword; - $this->timeout = $timeout; - $this->response_timeout = $response_timeout; - if (is_array($curl_options)) { - $this->curl_options = $curl_options; - } - $this->use_curl = $use_curl; - $this->fetchWSDL($wsdl); - } - - /** - * fetches the WSDL document and parses it. - */ - public function fetchWSDL($wsdl) - { - $this->debug("parse and process WSDL path=$wsdl"); - $this->wsdl = $wsdl; - // parse wsdl file - if ($this->wsdl != '') { - $this->parseWSDL($this->wsdl); - } - // imports - // TODO: handle imports more properly, grabbing them in-line and nesting them - $imported_urls = []; - $imported = 1; - while ($imported > 0) { - $imported = 0; - // Schema imports - foreach ($this->schemas as $ns => $list) { - foreach ($list as $xs) { - $wsdlparts = parse_url($this->wsdl); // this is bogusly simple! - foreach ($xs->imports as $ns2 => $list2) { - for ($ii = 0; $ii < count($list2); $ii++) { - if (!$list2[$ii]['loaded']) { - $this->schemas[$ns]->imports[$ns2][$ii]['loaded'] = true; - $url = $list2[$ii]['location']; - if ($url != '') { - $urlparts = parse_url($url); - if (!isset($urlparts['host'])) { - $url = $wsdlparts['scheme'].'://'.$wsdlparts['host'].(isset($wsdlparts['port']) ? ':'.$wsdlparts['port'] : ''). - substr($wsdlparts['path'], 0, strrpos($wsdlparts['path'], '/') + 1).$urlparts['path']; - } - if (!in_array($url, $imported_urls)) { - $this->parseWSDL($url); - $imported++; - $imported_urls[] = $url; - } - } else { - $this->debug('Unexpected scenario: empty URL for unloaded import'); - } - } - } - } - } - } - // WSDL imports - $wsdlparts = parse_url($this->wsdl); // this is bogusly simple! - foreach ($this->import as $ns => $list) { - for ($ii = 0; $ii < count($list); $ii++) { - if (!$list[$ii]['loaded']) { - $this->import[$ns][$ii]['loaded'] = true; - $url = $list[$ii]['location']; - if ($url != '') { - $urlparts = parse_url($url); - if (!isset($urlparts['host'])) { - $url = $wsdlparts['scheme'].'://'.$wsdlparts['host'].(isset($wsdlparts['port']) ? ':'.$wsdlparts['port'] : ''). - substr($wsdlparts['path'], 0, strrpos($wsdlparts['path'], '/') + 1).$urlparts['path']; - } - if (!in_array($url, $imported_urls)) { - $this->parseWSDL($url); - $imported++; - $imported_urls[] = $url; - } - } else { - $this->debug('Unexpected scenario: empty URL for unloaded import'); - } - } - } - } - } - // add new data to operation data - foreach ($this->bindings as $binding => $bindingData) { - if (isset($bindingData['operations']) && is_array($bindingData['operations'])) { - foreach ($bindingData['operations'] as $operation => $data) { - $this->debug('post-parse data gathering for '.$operation); - $this->bindings[$binding]['operations'][$operation]['input'] = - isset($this->bindings[$binding]['operations'][$operation]['input']) ? - array_merge($this->bindings[$binding]['operations'][$operation]['input'], $this->portTypes[$bindingData['portType']][$operation]['input']) : - $this->portTypes[$bindingData['portType']][$operation]['input']; - $this->bindings[$binding]['operations'][$operation]['output'] = - isset($this->bindings[$binding]['operations'][$operation]['output']) ? - array_merge($this->bindings[$binding]['operations'][$operation]['output'], $this->portTypes[$bindingData['portType']][$operation]['output']) : - $this->portTypes[$bindingData['portType']][$operation]['output']; - if (isset($this->messages[$this->bindings[$binding]['operations'][$operation]['input']['message']])) { - $this->bindings[$binding]['operations'][$operation]['input']['parts'] = $this->messages[$this->bindings[$binding]['operations'][$operation]['input']['message']]; - } - if (isset($this->messages[$this->bindings[$binding]['operations'][$operation]['output']['message']])) { - $this->bindings[$binding]['operations'][$operation]['output']['parts'] = $this->messages[$this->bindings[$binding]['operations'][$operation]['output']['message']]; - } - // Set operation style if necessary, but do not override one already provided - if (isset($bindingData['style']) && !isset($this->bindings[$binding]['operations'][$operation]['style'])) { - $this->bindings[$binding]['operations'][$operation]['style'] = $bindingData['style']; - } - $this->bindings[$binding]['operations'][$operation]['transport'] = isset($bindingData['transport']) ? $bindingData['transport'] : ''; - $this->bindings[$binding]['operations'][$operation]['documentation'] = isset($this->portTypes[$bindingData['portType']][$operation]['documentation']) ? $this->portTypes[$bindingData['portType']][$operation]['documentation'] : ''; - $this->bindings[$binding]['operations'][$operation]['endpoint'] = isset($bindingData['endpoint']) ? $bindingData['endpoint'] : ''; - } - } - } - } - - /** - * parses the wsdl document. - * - * @param string $wsdl path or URL - */ - public function parseWSDL($wsdl = '') - { - $this->debug("parse WSDL at path=$wsdl"); - - if ($wsdl == '') { - $this->debug('no wsdl passed to parseWSDL()!!'); - $this->setError('no wsdl passed to parseWSDL()!!'); - - return false; - } - - // parse $wsdl for url format - $wsdl_props = parse_url($wsdl); - - if (isset($wsdl_props['scheme']) && ($wsdl_props['scheme'] == 'http' || $wsdl_props['scheme'] == 'https')) { - $this->debug('getting WSDL http(s) URL '.$wsdl); - // get wsdl - $tr = new soap_transport_http($wsdl, $this->curl_options, $this->use_curl); - $tr->request_method = 'GET'; - $tr->useSOAPAction = false; - if ($this->proxyhost && $this->proxyport) { - $tr->setProxy($this->proxyhost, $this->proxyport, $this->proxyusername, $this->proxypassword); - } - if ($this->authtype != '') { - $tr->setCredentials($this->username, $this->password, $this->authtype, [], $this->certRequest); - } - $tr->setEncoding('gzip, deflate'); - $wsdl_string = $tr->send('', $this->timeout, $this->response_timeout); - //$this->debug("WSDL request\n" . $tr->outgoing_payload); - //$this->debug("WSDL response\n" . $tr->incoming_payload); - $this->appendDebug($tr->getDebug()); - // catch errors - if ($err = $tr->getError()) { - $errstr = 'Getting '.$wsdl.' - HTTP ERROR: '.$err; - $this->debug($errstr); - $this->setError($errstr); - unset($tr); - - return false; - } - unset($tr); - $this->debug('got WSDL URL'); - } else { - // $wsdl is not http(s), so treat it as a file URL or plain file path - if (isset($wsdl_props['scheme']) && ($wsdl_props['scheme'] == 'file') && isset($wsdl_props['path'])) { - $path = isset($wsdl_props['host']) ? ($wsdl_props['host'].':'.$wsdl_props['path']) : $wsdl_props['path']; - } else { - $path = $wsdl; - } - $this->debug('getting WSDL file '.$path); - if ($fp = @fopen($path, 'r')) { - $wsdl_string = ''; - while ($data = fread($fp, 32768)) { - $wsdl_string .= $data; - } - fclose($fp); - } else { - $errstr = "Bad path to WSDL file $path"; - $this->debug($errstr); - $this->setError($errstr); - - return false; - } - } - $this->debug('Parse WSDL'); - // end new code added - // Create an XML parser. - $this->parser = xml_parser_create(); - // Set the options for parsing the XML data. - // xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1); - xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0); - // Set the object for the parser. - xml_set_object($this->parser, $this); - // Set the element handlers for the parser. - xml_set_element_handler($this->parser, 'start_element', 'end_element'); - xml_set_character_data_handler($this->parser, 'character_data'); - // Parse the XML file. - if (!xml_parse($this->parser, $wsdl_string, true)) { - // Display an error message. - $errstr = sprintf( - 'XML error parsing WSDL from %s on line %d: %s', - $wsdl, - xml_get_current_line_number($this->parser), - xml_error_string(xml_get_error_code($this->parser)) - ); - $this->debug($errstr); - $this->debug("XML payload:\n".$wsdl_string); - $this->setError($errstr); - - return false; - } - // free the parser - xml_parser_free($this->parser); - $this->debug('Parsing WSDL done'); - // catch wsdl parse errors - if ($this->getError()) { - return false; - } - - return true; - } - - /** - * start-element handler. - * - * @param string $parser XML parser object - * @param string $name element name - * @param string $attrs associative array of attributes - */ - public function start_element($parser, $name, $attrs) - { - if ($this->status == 'schema') { - $this->currentSchema->schemaStartElement($parser, $name, $attrs); - $this->appendDebug($this->currentSchema->getDebug()); - $this->currentSchema->clearDebug(); - } elseif (preg_match('/schema$/', $name)) { - $this->debug('Parsing WSDL schema'); - // $this->debug("startElement for $name ($attrs[name]). status = $this->status (".$this->getLocalPart($name).")"); - $this->status = 'schema'; - $this->currentSchema = new nusoap_xmlschema('', '', $this->namespaces); - $this->currentSchema->schemaStartElement($parser, $name, $attrs); - $this->appendDebug($this->currentSchema->getDebug()); - $this->currentSchema->clearDebug(); - } else { - // position in the total number of elements, starting from 0 - $pos = $this->position++; - $depth = $this->depth++; - // set self as current value for this depth - $this->depth_array[$depth] = $pos; - $this->message[$pos] = ['cdata' => '']; - // process attributes - if (count($attrs) > 0) { - // register namespace declarations - foreach ($attrs as $k => $v) { - if (preg_match('/^xmlns/', $k)) { - if ($ns_prefix = substr(strrchr($k, ':'), 1)) { - $this->namespaces[$ns_prefix] = $v; - } else { - $this->namespaces['ns'.(count($this->namespaces) + 1)] = $v; - } - if ($v == 'http://www.w3.org/2001/XMLSchema' || $v == 'http://www.w3.org/1999/XMLSchema' || $v == 'http://www.w3.org/2000/10/XMLSchema') { - $this->XMLSchemaVersion = $v; - $this->namespaces['xsi'] = $v.'-instance'; - } - } - } - // expand each attribute prefix to its namespace - foreach ($attrs as $k => $v) { - $k = strpos($k, ':') ? $this->expandQname($k) : $k; - if ($k != 'location' && $k != 'soapAction' && $k != 'namespace') { - $v = strpos($v, ':') ? $this->expandQname($v) : $v; - } - $eAttrs[$k] = $v; - } - $attrs = $eAttrs; - } else { - $attrs = []; - } - // get element prefix, namespace and name - if (preg_match('/:/', $name)) { - // get ns prefix - $prefix = substr($name, 0, strpos($name, ':')); - // get ns - $namespace = isset($this->namespaces[$prefix]) ? $this->namespaces[$prefix] : ''; - // get unqualified name - $name = substr(strstr($name, ':'), 1); - } - // process attributes, expanding any prefixes to namespaces - // find status, register data - switch ($this->status) { - case 'message': - if ($name == 'part') { - if (isset($attrs['type'])) { - $this->debug('msg '.$this->currentMessage.": found part (with type) $attrs[name]: ".implode(',', $attrs)); - $this->messages[$this->currentMessage][$attrs['name']] = $attrs['type']; - } - if (isset($attrs['element'])) { - $this->debug('msg '.$this->currentMessage.": found part (with element) $attrs[name]: ".implode(',', $attrs)); - $this->messages[$this->currentMessage][$attrs['name']] = $attrs['element'].'^'; - } - } - break; - case 'portType': - switch ($name) { - case 'operation': - $this->currentPortOperation = $attrs['name']; - $this->debug("portType $this->currentPortType operation: $this->currentPortOperation"); - if (isset($attrs['parameterOrder'])) { - $this->portTypes[$this->currentPortType][$attrs['name']]['parameterOrder'] = $attrs['parameterOrder']; - } - break; - case 'documentation': - $this->documentation = true; - break; - // merge input/output data - default: - $m = isset($attrs['message']) ? $this->getLocalPart($attrs['message']) : ''; - $this->portTypes[$this->currentPortType][$this->currentPortOperation][$name]['message'] = $m; - break; - } - break; - case 'binding': - switch ($name) { - case 'binding': - // get ns prefix - if (isset($attrs['style'])) { - $this->bindings[$this->currentBinding]['prefix'] = $prefix; - } - $this->bindings[$this->currentBinding] = array_merge($this->bindings[$this->currentBinding], $attrs); - break; - case 'header': - $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus]['headers'][] = $attrs; - break; - case 'operation': - if (isset($attrs['soapAction'])) { - $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['soapAction'] = $attrs['soapAction']; - } - if (isset($attrs['style'])) { - $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['style'] = $attrs['style']; - } - if (isset($attrs['name'])) { - $this->currentOperation = $attrs['name']; - $this->debug("current binding operation: $this->currentOperation"); - $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['name'] = $attrs['name']; - $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['binding'] = $this->currentBinding; - $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['endpoint'] = isset($this->bindings[$this->currentBinding]['endpoint']) ? $this->bindings[$this->currentBinding]['endpoint'] : ''; - } - break; - case 'input': - $this->opStatus = 'input'; - break; - case 'output': - $this->opStatus = 'output'; - break; - case 'body': - if (isset($this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus])) { - $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus] = array_merge($this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus], $attrs); - } else { - $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus] = $attrs; - } - break; - } - break; - case 'service': - switch ($name) { - case 'port': - $this->currentPort = $attrs['name']; - $this->debug('current port: '.$this->currentPort); - $this->ports[$this->currentPort]['binding'] = $this->getLocalPart($attrs['binding']); - - break; - case 'address': - $this->ports[$this->currentPort]['location'] = $attrs['location']; - $this->ports[$this->currentPort]['bindingType'] = $namespace; - $this->bindings[$this->ports[$this->currentPort]['binding']]['bindingType'] = $namespace; - $this->bindings[$this->ports[$this->currentPort]['binding']]['endpoint'] = $attrs['location']; - break; - } - break; - } - // set status - switch ($name) { - case 'import': - if (isset($attrs['location'])) { - $this->import[$attrs['namespace']][] = ['location' => $attrs['location'], 'loaded' => false]; - $this->debug('parsing import '.$attrs['namespace'].' - '.$attrs['location'].' ('.count($this->import[$attrs['namespace']]).')'); - } else { - $this->import[$attrs['namespace']][] = ['location' => '', 'loaded' => true]; - if (!$this->getPrefixFromNamespace($attrs['namespace'])) { - $this->namespaces['ns'.(count($this->namespaces) + 1)] = $attrs['namespace']; - } - $this->debug('parsing import '.$attrs['namespace'].' - [no location] ('.count($this->import[$attrs['namespace']]).')'); - } - break; - //wait for schema - //case 'types': - // $this->status = 'schema'; - // break; - case 'message': - $this->status = 'message'; - $this->messages[$attrs['name']] = []; - $this->currentMessage = $attrs['name']; - break; - case 'portType': - $this->status = 'portType'; - $this->portTypes[$attrs['name']] = []; - $this->currentPortType = $attrs['name']; - break; - case 'binding': - if (isset($attrs['name'])) { - // get binding name - if (strpos($attrs['name'], ':')) { - $this->currentBinding = $this->getLocalPart($attrs['name']); - } else { - $this->currentBinding = $attrs['name']; - } - $this->status = 'binding'; - $this->bindings[$this->currentBinding]['portType'] = $this->getLocalPart($attrs['type']); - $this->debug("current binding: $this->currentBinding of portType: ".$attrs['type']); - } - break; - case 'service': - $this->serviceName = $attrs['name']; - $this->status = 'service'; - $this->debug('current service: '.$this->serviceName); - break; - case 'definitions': - foreach ($attrs as $name => $value) { - $this->wsdl_info[$name] = $value; - } - break; - } - } - } - - /** - * end-element handler. - * - * @param string $parser XML parser object - * @param string $name element name - */ - public function end_element($parser, $name) - { - // unset schema status - if (/*preg_match('/types$/', $name) ||*/ preg_match('/schema$/', $name)) { - $this->status = ''; - $this->appendDebug($this->currentSchema->getDebug()); - $this->currentSchema->clearDebug(); - $this->schemas[$this->currentSchema->schemaTargetNamespace][] = $this->currentSchema; - $this->debug('Parsing WSDL schema done'); - } - if ($this->status == 'schema') { - $this->currentSchema->schemaEndElement($parser, $name); - } else { - // bring depth down a notch - $this->depth--; - } - // end documentation - if ($this->documentation) { - //TODO: track the node to which documentation should be assigned; it can be a part, message, etc. - //$this->portTypes[$this->currentPortType][$this->currentPortOperation]['documentation'] = $this->documentation; - $this->documentation = false; - } - } - - /** - * element content handler. - * - * @param string $parser XML parser object - * @param string $data element content - */ - public function character_data($parser, $data) - { - $pos = isset($this->depth_array[$this->depth]) ? $this->depth_array[$this->depth] : 0; - if (isset($this->message[$pos]['cdata'])) { - $this->message[$pos]['cdata'] .= $data; - } - if ($this->documentation) { - $this->documentation .= $data; - } - } - - /** - * if authenticating, set user credentials here. - * - * @param string $username - * @param string $password - * @param string $authtype (basic|digest|certificate|ntlm) - * @param array $certRequest (keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, certpassword (optional), verifypeer (optional), verifyhost (optional): see corresponding options in cURL docs) - */ - public function setCredentials($username, $password, $authtype = 'basic', $certRequest = []) - { - $this->debug("setCredentials username=$username authtype=$authtype certRequest="); - $this->appendDebug($this->varDump($certRequest)); - $this->username = $username; - $this->password = $password; - $this->authtype = $authtype; - $this->certRequest = $certRequest; - } - - public function getBindingData($binding) - { - if (is_array($this->bindings[$binding])) { - return $this->bindings[$binding]; - } - } - - /** - * returns an assoc array of operation names => operation data. - * - * @param string $portName WSDL port name - * @param string $bindingType eg: soap, smtp, dime (only soap and soap12 are currently supported) - * - * @return array - */ - public function getOperations($portName = '', $bindingType = 'soap') - { - $ops = []; - if ($bindingType == 'soap') { - $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/'; - } elseif ($bindingType == 'soap12') { - $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/'; - } else { - $this->debug("getOperations bindingType $bindingType may not be supported"); - } - $this->debug("getOperations for port '$portName' bindingType $bindingType"); - // loop thru ports - foreach ($this->ports as $port => $portData) { - $this->debug("getOperations checking port $port bindingType ".$portData['bindingType']); - if ($portName == '' || $port == $portName) { - // binding type of port matches parameter - if ($portData['bindingType'] == $bindingType) { - $this->debug("getOperations found port $port bindingType $bindingType"); - //$this->debug("port data: " . $this->varDump($portData)); - //$this->debug("bindings: " . $this->varDump($this->bindings[ $portData['binding'] ])); - // merge bindings - if (isset($this->bindings[$portData['binding']]['operations'])) { - $ops = array_merge($ops, $this->bindings[$portData['binding']]['operations']); - } - } - } - } - if (count($ops) == 0) { - $this->debug("getOperations found no operations for port '$portName' bindingType $bindingType"); - } - - return $ops; - } - - /** - * returns an associative array of data necessary for calling an operation. - * - * @param string $operation name of operation - * @param string $bindingType type of binding eg: soap, soap12 - * - * @return array - */ - public function getOperationData($operation, $bindingType = 'soap') - { - if ($bindingType == 'soap') { - $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/'; - } elseif ($bindingType == 'soap12') { - $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/'; - } - // loop thru ports - foreach ($this->ports as $port => $portData) { - // binding type of port matches parameter - if ($portData['bindingType'] == $bindingType) { - // get binding - //foreach($this->bindings[ $portData['binding'] ]['operations'] as $bOperation => $opData) { - foreach (array_keys($this->bindings[$portData['binding']]['operations']) as $bOperation) { - // note that we could/should also check the namespace here - if ($operation == $bOperation) { - $opData = $this->bindings[$portData['binding']]['operations'][$operation]; - - return $opData; - } - } - } - } - } - - /** - * returns an associative array of data necessary for calling an operation. - * - * @param string $soapAction soapAction for operation - * @param string $bindingType type of binding eg: soap, soap12 - * - * @return array - */ - public function getOperationDataForSoapAction($soapAction, $bindingType = 'soap') - { - if ($bindingType == 'soap') { - $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/'; - } elseif ($bindingType == 'soap12') { - $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/'; - } - // loop thru ports - foreach ($this->ports as $port => $portData) { - // binding type of port matches parameter - if ($portData['bindingType'] == $bindingType) { - // loop through operations for the binding - foreach ($this->bindings[$portData['binding']]['operations'] as $bOperation => $opData) { - if ($opData['soapAction'] == $soapAction) { - return $opData; - } - } - } - } - } - - /** - * returns an array of information about a given type - * returns false if no type exists by the given name. - * - * typeDef = array( - * 'elements' => array(), // refs to elements array - * 'restrictionBase' => '', - * 'phpType' => '', - * 'order' => '(sequence|all)', - * 'attrs' => array() // refs to attributes array - * ) - * - * @param string $type the type - * @param string $ns namespace (not prefix) of the type - * - * @return mixed - * - * @see nusoap_xmlschema - */ - public function getTypeDef($type, $ns) - { - $this->debug("in getTypeDef: type=$type, ns=$ns"); - if ((!$ns) && isset($this->namespaces['tns'])) { - $ns = $this->namespaces['tns']; - $this->debug("in getTypeDef: type namespace forced to $ns"); - } - if (!isset($this->schemas[$ns])) { - foreach ($this->schemas as $ns0 => $schema0) { - if (strcasecmp($ns, $ns0) == 0) { - $this->debug("in getTypeDef: replacing schema namespace $ns with $ns0"); - $ns = $ns0; - break; - } - } - } - if (isset($this->schemas[$ns])) { - $this->debug("in getTypeDef: have schema for namespace $ns"); - for ($i = 0; $i < count($this->schemas[$ns]); $i++) { - $xs = &$this->schemas[$ns][$i]; - $t = $xs->getTypeDef($type); - $this->appendDebug($xs->getDebug()); - $xs->clearDebug(); - if ($t) { - $this->debug("in getTypeDef: found type $type"); - if (!isset($t['phpType'])) { - // get info for type to tack onto the element - $uqType = substr($t['type'], strrpos($t['type'], ':') + 1); - $ns = substr($t['type'], 0, strrpos($t['type'], ':')); - $etype = $this->getTypeDef($uqType, $ns); - if ($etype) { - $this->debug("found type for [element] $type:"); - $this->debug($this->varDump($etype)); - if (isset($etype['phpType'])) { - $t['phpType'] = $etype['phpType']; - } - if (isset($etype['elements'])) { - $t['elements'] = $etype['elements']; - } - if (isset($etype['attrs'])) { - $t['attrs'] = $etype['attrs']; - } - } else { - $this->debug("did not find type for [element] $type"); - } - } - - return $t; - } - } - $this->debug("in getTypeDef: did not find type $type"); - } else { - $this->debug("in getTypeDef: do not have schema for namespace $ns"); - } - - return false; - } - - /** - * prints html description of services. - */ - public function webDescription() - { - global $HTTP_SERVER_VARS; - - if (isset($_SERVER)) { - $PHP_SELF = $_SERVER['PHP_SELF']; - } elseif (isset($HTTP_SERVER_VARS)) { - $PHP_SELF = $HTTP_SERVER_VARS['PHP_SELF']; - } else { - $this->setError('Neither _SERVER nor HTTP_SERVER_VARS is available'); - } - - $b = ' - NuSOAP: '.$this->serviceName.' - - - - -
-

-
'.$this->serviceName.'
- -
'; - - return $b; - } - - /** - * serialize the parsed wsdl. - * - * @param mixed $debug whether to put debug=1 in endpoint URL - * - * @return string serialization of WSDL - */ - public function serialize($debug = 0) - { - $xml = ''; - $xml .= "\nnamespaces as $k => $v) { - $xml .= " xmlns:$k=\"$v\""; - } - // 10.9.02 - add poulter fix for wsdl and tns declarations - if (isset($this->namespaces['wsdl'])) { - $xml .= ' xmlns="'.$this->namespaces['wsdl'].'"'; - } - if (isset($this->namespaces['tns'])) { - $xml .= ' targetNamespace="'.$this->namespaces['tns'].'"'; - } - $xml .= '>'; - // imports - if (count($this->import) > 0) { - foreach ($this->import as $ns => $list) { - foreach ($list as $ii) { - if ($ii['location'] != '') { - $xml .= ''; - } else { - $xml .= ''; - } - } - } - } - // types - if (count($this->schemas) >= 1) { - $xml .= "\n\n"; - foreach ($this->schemas as $ns => $list) { - foreach ($list as $xs) { - $xml .= $xs->serializeSchema(); - } - } - $xml .= ''; - } - // messages - if (count($this->messages) >= 1) { - foreach ($this->messages as $msgName => $msgParts) { - $xml .= "\n'; - if (is_array($msgParts)) { - foreach ($msgParts as $partName => $partType) { - // print 'serializing '.$partType.', sv: '.$this->XMLSchemaVersion.'
'; - if (strpos($partType, ':')) { - $typePrefix = $this->getPrefixFromNamespace($this->getPrefix($partType)); - } elseif (isset($this->typemap[$this->namespaces['xsd']][$partType])) { - // print 'checking typemap: '.$this->XMLSchemaVersion.'
'; - $typePrefix = 'xsd'; - } else { - foreach ($this->typemap as $ns => $types) { - if (isset($types[$partType])) { - $typePrefix = $this->getPrefixFromNamespace($ns); - } - } - if (!isset($typePrefix)) { - die("$partType has no namespace!"); - } - } - $ns = $this->getNamespaceFromPrefix($typePrefix); - $localPart = $this->getLocalPart($partType); - $typeDef = $this->getTypeDef($localPart, $ns); - if ($typeDef['typeClass'] == 'element') { - $elementortype = 'element'; - if (substr($localPart, -1) == '^') { - $localPart = substr($localPart, 0, -1); - } - } else { - $elementortype = 'type'; - } - $xml .= "\n".' '; - } - } - $xml .= '
'; - } - } - // bindings & porttypes - if (count($this->bindings) >= 1) { - $binding_xml = ''; - $portType_xml = ''; - foreach ($this->bindings as $bindingName => $attrs) { - $binding_xml .= "\n'; - $binding_xml .= "\n".' '; - $portType_xml .= "\n'; - foreach ($attrs['operations'] as $opName => $opParts) { - $binding_xml .= "\n".' '; - $binding_xml .= "\n".' '; - if (isset($opParts['input']['encodingStyle']) && $opParts['input']['encodingStyle'] != '') { - $enc_style = ' encodingStyle="'.$opParts['input']['encodingStyle'].'"'; - } else { - $enc_style = ''; - } - $binding_xml .= "\n".' '; - if (isset($opParts['output']['encodingStyle']) && $opParts['output']['encodingStyle'] != '') { - $enc_style = ' encodingStyle="'.$opParts['output']['encodingStyle'].'"'; - } else { - $enc_style = ''; - } - $binding_xml .= "\n".' '; - $binding_xml .= "\n".' '; - $portType_xml .= "\n".' '.htmlspecialchars($opParts['documentation']).''; - } - $portType_xml .= "\n".' '; - $portType_xml .= "\n".' '; - $portType_xml .= "\n".' '; - } - $portType_xml .= "\n".''; - $binding_xml .= "\n".''; - } - $xml .= $portType_xml.$binding_xml; - } - // services - $xml .= "\nserviceName.'">'; - if (count($this->ports) >= 1) { - foreach ($this->ports as $pName => $attrs) { - $xml .= "\n".' '; - $xml .= "\n".' '; - $xml .= "\n".' '; - } - } - $xml .= "\n".''; - - return $xml."\n"; - } - - /** - * determine whether a set of parameters are unwrapped - * when they are expect to be wrapped, Microsoft-style. - * - * @param string $type the type (element name) of the wrapper - * @param array $parameters the parameter values for the SOAP call - * - * @return bool whether they parameters are unwrapped (and should be wrapped) - */ - public function parametersMatchWrapped($type, &$parameters) - { - $this->debug("in parametersMatchWrapped type=$type, parameters="); - $this->appendDebug($this->varDump($parameters)); - - // split type into namespace:unqualified-type - if (strpos($type, ':')) { - $uqType = substr($type, strrpos($type, ':') + 1); - $ns = substr($type, 0, strrpos($type, ':')); - $this->debug("in parametersMatchWrapped: got a prefixed type: $uqType, $ns"); - if ($this->getNamespaceFromPrefix($ns)) { - $ns = $this->getNamespaceFromPrefix($ns); - $this->debug("in parametersMatchWrapped: expanded prefixed type: $uqType, $ns"); - } - } else { - // TODO: should the type be compared to types in XSD, and the namespace - // set to XSD if the type matches? - $this->debug("in parametersMatchWrapped: No namespace for type $type"); - $ns = ''; - $uqType = $type; - } - - // get the type information - if (!$typeDef = $this->getTypeDef($uqType, $ns)) { - $this->debug("in parametersMatchWrapped: $type ($uqType) is not a supported type."); - - return false; - } - $this->debug('in parametersMatchWrapped: found typeDef='); - $this->appendDebug($this->varDump($typeDef)); - if (substr($uqType, -1) == '^') { - $uqType = substr($uqType, 0, -1); - } - $phpType = $typeDef['phpType']; - $arrayType = (isset($typeDef['arrayType']) ? $typeDef['arrayType'] : ''); - $this->debug("in parametersMatchWrapped: uqType: $uqType, ns: $ns, phptype: $phpType, arrayType: $arrayType"); - - // we expect a complexType or element of complexType - if ($phpType != 'struct') { - $this->debug('in parametersMatchWrapped: not a struct'); - - return false; - } - - // see whether the parameter names match the elements - if (isset($typeDef['elements']) && is_array($typeDef['elements'])) { - $elements = 0; - $matches = 0; - foreach ($typeDef['elements'] as $name => $attrs) { - if (isset($parameters[$name])) { - $this->debug("in parametersMatchWrapped: have parameter named $name"); - $matches++; - } else { - $this->debug("in parametersMatchWrapped: do not have parameter named $name"); - } - $elements++; - } - - $this->debug("in parametersMatchWrapped: $matches parameter names match $elements wrapped parameter names"); - if ($matches == 0) { - return false; - } - - return true; - } - - // since there are no elements for the type, if the user passed no - // parameters, the parameters match wrapped. - $this->debug("in parametersMatchWrapped: no elements type $ns:$uqType"); - - return count($parameters) == 0; - } - - /** - * serialize PHP values according to a WSDL message definition - * contrary to the method name, this is not limited to RPC. - * - * TODO - * - multi-ref serialization - * - validate PHP values against type definitions, return errors if invalid - * - * @param string $operation operation name - * @param string $direction (input|output) - * @param mixed $parameters parameter value(s) - * @param string $bindingType (soap|soap12) - * - * @return mixed parameters serialized as XML or false on error (e.g. operation not found) - */ - public function serializeRPCParameters($operation, $direction, $parameters, $bindingType = 'soap') - { - $this->debug("in serializeRPCParameters: operation=$operation, direction=$direction, XMLSchemaVersion=$this->XMLSchemaVersion, bindingType=$bindingType"); - $this->appendDebug('parameters='.$this->varDump($parameters)); - - if ($direction != 'input' && $direction != 'output') { - $this->debug('The value of the \$direction argument needs to be either "input" or "output"'); - $this->setError('The value of the \$direction argument needs to be either "input" or "output"'); - - return false; - } - if (!$opData = $this->getOperationData($operation, $bindingType)) { - $this->debug('Unable to retrieve WSDL data for operation: '.$operation.' bindingType: '.$bindingType); - $this->setError('Unable to retrieve WSDL data for operation: '.$operation.' bindingType: '.$bindingType); - - return false; - } - $this->debug('in serializeRPCParameters: opData:'); - $this->appendDebug($this->varDump($opData)); - - // Get encoding style for output and set to current - $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/'; - if (($direction == 'input') && isset($opData['output']['encodingStyle']) && ($opData['output']['encodingStyle'] != $encodingStyle)) { - $encodingStyle = $opData['output']['encodingStyle']; - $enc_style = $encodingStyle; - } - - // set input params - $xml = ''; - if (isset($opData[$direction]['parts']) && count($opData[$direction]['parts']) > 0) { - $parts = &$opData[$direction]['parts']; - $part_count = count($parts); - $style = $opData['style']; - $use = $opData[$direction]['use']; - $this->debug("have $part_count part(s) to serialize using $style/$use"); - if (is_array($parameters)) { - $parametersArrayType = $this->isArraySimpleOrStruct($parameters); - $parameter_count = count($parameters); - $this->debug("have $parameter_count parameter(s) provided as $parametersArrayType to serialize"); - // check for Microsoft-style wrapped parameters - if ($style == 'document' && $use == 'literal' && $part_count == 1 && isset($parts['parameters'])) { - $this->debug('check whether the caller has wrapped the parameters'); - if ($direction == 'output' && $parametersArrayType == 'arraySimple' && $parameter_count == 1) { - // TODO: consider checking here for double-wrapping, when - // service function wraps, then NuSOAP wraps again - $this->debug("change simple array to associative with 'parameters' element"); - $parameters['parameters'] = $parameters[0]; - unset($parameters[0]); - } - if (($parametersArrayType == 'arrayStruct' || $parameter_count == 0) && !isset($parameters['parameters'])) { - $this->debug('check whether caller\'s parameters match the wrapped ones'); - if ($this->parametersMatchWrapped($parts['parameters'], $parameters)) { - $this->debug('wrap the parameters for the caller'); - $parameters = ['parameters' => $parameters]; - $parameter_count = 1; - } - } - } - foreach ($parts as $name => $type) { - $this->debug("serializing part $name of type $type"); - // Track encoding style - if (isset($opData[$direction]['encodingStyle']) && $encodingStyle != $opData[$direction]['encodingStyle']) { - $encodingStyle = $opData[$direction]['encodingStyle']; - $enc_style = $encodingStyle; - } else { - $enc_style = false; - } - // NOTE: add error handling here - // if serializeType returns false, then catch global error and fault - if ($parametersArrayType == 'arraySimple') { - $p = array_shift($parameters); - $this->debug('calling serializeType w/indexed param'); - $xml .= $this->serializeType($name, $type, $p, $use, $enc_style); - } elseif (isset($parameters[$name])) { - $this->debug('calling serializeType w/named param'); - $xml .= $this->serializeType($name, $type, $parameters[$name], $use, $enc_style); - } else { - // TODO: only send nillable - $this->debug('calling serializeType w/null param'); - $xml .= $this->serializeType($name, $type, null, $use, $enc_style); - } - } - } else { - $this->debug('no parameters passed.'); - } - } - $this->debug("serializeRPCParameters returning: $xml"); - - return $xml; - } - - /** - * serialize a PHP value according to a WSDL message definition. - * - * TODO - * - multi-ref serialization - * - validate PHP values against type definitions, return errors if invalid - * - * @param string $operation operation name - * @param string $direction (input|output) - * @param mixed $parameters parameter value(s) - * - * @return mixed parameters serialized as XML or false on error (e.g. operation not found) - * - * @deprecated - */ - public function serializeParameters($operation, $direction, $parameters) - { - $this->debug("in serializeParameters: operation=$operation, direction=$direction, XMLSchemaVersion=$this->XMLSchemaVersion"); - $this->appendDebug('parameters='.$this->varDump($parameters)); - - if ($direction != 'input' && $direction != 'output') { - $this->debug('The value of the \$direction argument needs to be either "input" or "output"'); - $this->setError('The value of the \$direction argument needs to be either "input" or "output"'); - - return false; - } - if (!$opData = $this->getOperationData($operation)) { - $this->debug('Unable to retrieve WSDL data for operation: '.$operation); - $this->setError('Unable to retrieve WSDL data for operation: '.$operation); - - return false; - } - $this->debug('opData:'); - $this->appendDebug($this->varDump($opData)); - - // Get encoding style for output and set to current - $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/'; - if (($direction == 'input') && isset($opData['output']['encodingStyle']) && ($opData['output']['encodingStyle'] != $encodingStyle)) { - $encodingStyle = $opData['output']['encodingStyle']; - $enc_style = $encodingStyle; - } - - // set input params - $xml = ''; - if (isset($opData[$direction]['parts']) && count($opData[$direction]['parts']) > 0) { - $use = $opData[$direction]['use']; - $this->debug("use=$use"); - $this->debug('got '.count($opData[$direction]['parts']).' part(s)'); - if (is_array($parameters)) { - $parametersArrayType = $this->isArraySimpleOrStruct($parameters); - $this->debug('have '.$parametersArrayType.' parameters'); - foreach ($opData[$direction]['parts'] as $name => $type) { - $this->debug('serializing part "'.$name.'" of type "'.$type.'"'); - // Track encoding style - if (isset($opData[$direction]['encodingStyle']) && $encodingStyle != $opData[$direction]['encodingStyle']) { - $encodingStyle = $opData[$direction]['encodingStyle']; - $enc_style = $encodingStyle; - } else { - $enc_style = false; - } - // NOTE: add error handling here - // if serializeType returns false, then catch global error and fault - if ($parametersArrayType == 'arraySimple') { - $p = array_shift($parameters); - $this->debug('calling serializeType w/indexed param'); - $xml .= $this->serializeType($name, $type, $p, $use, $enc_style); - } elseif (isset($parameters[$name])) { - $this->debug('calling serializeType w/named param'); - $xml .= $this->serializeType($name, $type, $parameters[$name], $use, $enc_style); - } else { - // TODO: only send nillable - $this->debug('calling serializeType w/null param'); - $xml .= $this->serializeType($name, $type, null, $use, $enc_style); - } - } - } else { - $this->debug('no parameters passed.'); - } - } - $this->debug("serializeParameters returning: $xml"); - - return $xml; - } - - /** - * serializes a PHP value according a given type definition. - * - * @param string $name name of value (part or element) - * @param string $type XML schema type of value (type or element) - * @param mixed $value a native PHP value (parameter value) - * @param string $use use for part (encoded|literal) - * @param string $encodingStyle SOAP encoding style for the value (if different than the enclosing style) - * @param bool $unqualified a kludge for what should be XML namespace form handling - * - * @return string value serialized as an XML string - */ - public function serializeType($name, $type, $value, $use = 'encoded', $encodingStyle = false, $unqualified = false) - { - $this->debug("in serializeType: name=$name, type=$type, use=$use, encodingStyle=$encodingStyle, unqualified=".($unqualified ? 'unqualified' : 'qualified')); - $this->appendDebug('value='.$this->varDump($value)); - if ($use == 'encoded' && $encodingStyle) { - $encodingStyle = ' SOAP-ENV:encodingStyle="'.$encodingStyle.'"'; - } - - // if a soapval has been supplied, let its type override the WSDL - if (is_object($value) && get_class($value) == 'soapval') { - if ($value->type_ns) { - $type = $value->type_ns.':'.$value->type; - $forceType = true; - $this->debug("in serializeType: soapval overrides type to $type"); - } elseif ($value->type) { - $type = $value->type; - $forceType = true; - $this->debug("in serializeType: soapval overrides type to $type"); - } else { - $forceType = false; - $this->debug('in serializeType: soapval does not override type'); - } - $attrs = $value->attributes; - $value = $value->value; - $this->debug("in serializeType: soapval overrides value to $value"); - if ($attrs) { - if (!is_array($value)) { - $value['!'] = $value; - } - foreach ($attrs as $n => $v) { - $value['!'.$n] = $v; - } - $this->debug('in serializeType: soapval provides attributes'); - } - } else { - $forceType = false; - } - - $xml = ''; - if (strpos($type, ':')) { - $uqType = substr($type, strrpos($type, ':') + 1); - $ns = substr($type, 0, strrpos($type, ':')); - $this->debug("in serializeType: got a prefixed type: $uqType, $ns"); - if ($this->getNamespaceFromPrefix($ns)) { - $ns = $this->getNamespaceFromPrefix($ns); - $this->debug("in serializeType: expanded prefixed type: $uqType, $ns"); - } - - if ($ns == $this->XMLSchemaVersion || $ns == 'http://schemas.xmlsoap.org/soap/encoding/') { - $this->debug('in serializeType: type namespace indicates XML Schema or SOAP Encoding type'); - if ($unqualified && $use == 'literal') { - $elementNS = ' xmlns=""'; - } else { - $elementNS = ''; - } - if (is_null($value)) { - if ($use == 'literal') { - // TODO: depends on minOccurs - $xml = "<$name$elementNS/>"; - } else { - // TODO: depends on nillable, which should be checked before calling this method - $xml = "<$name$elementNS xsi:nil=\"true\" xsi:type=\"".$this->getPrefixFromNamespace($ns).":$uqType\"/>"; - } - $this->debug("in serializeType: returning: $xml"); - - return $xml; - } - if ($uqType == 'Array') { - // JBoss/Axis does this sometimes - return $this->serialize_val($value, $name, false, false, false, false, $use); - } - if ($uqType == 'boolean') { - if ((is_string($value) && $value == 'false') || (!$value)) { - $value = 'false'; - } else { - $value = 'true'; - } - } - if ($uqType == 'string' && gettype($value) == 'string') { - $value = $this->expandEntities($value); - } - if (($uqType == 'long' || $uqType == 'unsignedLong') && gettype($value) == 'double') { - $value = sprintf('%.0lf', $value); - } - // it's a scalar - // TODO: what about null/nil values? - // check type isn't a custom type extending xmlschema namespace - if (!$this->getTypeDef($uqType, $ns)) { - if ($use == 'literal') { - if ($forceType) { - $xml = "<$name$elementNS xsi:type=\"".$this->getPrefixFromNamespace($ns).":$uqType\">$value"; - } else { - $xml = "<$name$elementNS>$value"; - } - } else { - $xml = "<$name$elementNS xsi:type=\"".$this->getPrefixFromNamespace($ns).":$uqType\"$encodingStyle>$value"; - } - $this->debug("in serializeType: returning: $xml"); - - return $xml; - } - $this->debug('custom type extends XML Schema or SOAP Encoding namespace (yuck)'); - } elseif ($ns == 'http://xml.apache.org/xml-soap') { - $this->debug('in serializeType: appears to be Apache SOAP type'); - if ($uqType == 'Map') { - $tt_prefix = $this->getPrefixFromNamespace('http://xml.apache.org/xml-soap'); - if (!$tt_prefix) { - $this->debug('in serializeType: Add namespace for Apache SOAP type'); - $tt_prefix = 'ns'.rand(1000, 9999); - $this->namespaces[$tt_prefix] = 'http://xml.apache.org/xml-soap'; - // force this to be added to usedNamespaces - $tt_prefix = $this->getPrefixFromNamespace('http://xml.apache.org/xml-soap'); - } - $contents = ''; - foreach ($value as $k => $v) { - $this->debug("serializing map element: key $k, value $v"); - $contents .= ''; - $contents .= $this->serialize_val($k, 'key', false, false, false, false, $use); - $contents .= $this->serialize_val($v, 'value', false, false, false, false, $use); - $contents .= ''; - } - if ($use == 'literal') { - if ($forceType) { - $xml = "<$name xsi:type=\"".$tt_prefix.":$uqType\">$contents"; - } else { - $xml = "<$name>$contents"; - } - } else { - $xml = "<$name xsi:type=\"".$tt_prefix.":$uqType\"$encodingStyle>$contents"; - } - $this->debug("in serializeType: returning: $xml"); - - return $xml; - } - $this->debug('in serializeType: Apache SOAP type, but only support Map'); - } - } else { - // TODO: should the type be compared to types in XSD, and the namespace - // set to XSD if the type matches? - $this->debug("in serializeType: No namespace for type $type"); - $ns = ''; - $uqType = $type; - } - if (!$typeDef = $this->getTypeDef($uqType, $ns)) { - $this->setError("$type ($uqType) is not a supported type."); - $this->debug("in serializeType: $type ($uqType) is not a supported type."); - - return false; - } else { - $this->debug('in serializeType: found typeDef'); - $this->appendDebug('typeDef='.$this->varDump($typeDef)); - if (substr($uqType, -1) == '^') { - $uqType = substr($uqType, 0, -1); - } - } - if (!isset($typeDef['phpType'])) { - $this->setError("$type ($uqType) has no phpType."); - $this->debug("in serializeType: $type ($uqType) has no phpType."); - - return false; - } - $phpType = $typeDef['phpType']; - $this->debug("in serializeType: uqType: $uqType, ns: $ns, phptype: $phpType, arrayType: ".(isset($typeDef['arrayType']) ? $typeDef['arrayType'] : '')); - // if php type == struct, map value to the element names - if ($phpType == 'struct') { - if (isset($typeDef['typeClass']) && $typeDef['typeClass'] == 'element') { - $elementName = $uqType; - if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) { - $elementNS = " xmlns=\"$ns\""; - } else { - $elementNS = ' xmlns=""'; - } - } else { - $elementName = $name; - if ($unqualified) { - $elementNS = ' xmlns=""'; - } else { - $elementNS = ''; - } - } - if (is_null($value)) { - if ($use == 'literal') { - // TODO: depends on minOccurs and nillable - $xml = "<$elementName$elementNS/>"; - } else { - $xml = "<$elementName$elementNS xsi:nil=\"true\" xsi:type=\"".$this->getPrefixFromNamespace($ns).":$uqType\"/>"; - } - $this->debug("in serializeType: returning: $xml"); - - return $xml; - } - if (is_object($value)) { - $value = get_object_vars($value); - } - if (is_array($value)) { - $elementAttrs = $this->serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType); - if ($use == 'literal') { - if ($forceType) { - $xml = "<$elementName$elementNS$elementAttrs xsi:type=\"".$this->getPrefixFromNamespace($ns).":$uqType\">"; - } else { - $xml = "<$elementName$elementNS$elementAttrs>"; - } - } else { - $xml = "<$elementName$elementNS$elementAttrs xsi:type=\"".$this->getPrefixFromNamespace($ns).":$uqType\"$encodingStyle>"; - } - - if (isset($typeDef['simpleContent']) && $typeDef['simpleContent'] == 'true') { - if (isset($value['!'])) { - $xml .= $value['!']; - $this->debug("in serializeType: serialized simpleContent for type $type"); - } else { - $this->debug("in serializeType: no simpleContent to serialize for type $type"); - } - } else { - // complexContent - $xml .= $this->serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use, $encodingStyle); - } - $xml .= ""; - } else { - $this->debug('in serializeType: phpType is struct, but value is not an array'); - $this->setError('phpType is struct, but value is not an array: see debug output for details'); - $xml = ''; - } - } elseif ($phpType == 'array') { - if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) { - $elementNS = " xmlns=\"$ns\""; - } else { - if ($unqualified) { - $elementNS = ' xmlns=""'; - } else { - $elementNS = ''; - } - } - if (is_null($value)) { - if ($use == 'literal') { - // TODO: depends on minOccurs - $xml = "<$name$elementNS/>"; - } else { - $xml = "<$name$elementNS xsi:nil=\"true\" xsi:type=\"". - $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/'). - ':Array" '. - $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/'). - ':arrayType="'. - $this->getPrefixFromNamespace($this->getPrefix($typeDef['arrayType'])). - ':'. - $this->getLocalPart($typeDef['arrayType']).'[0]"/>'; - } - $this->debug("in serializeType: returning: $xml"); - - return $xml; - } - if (isset($typeDef['multidimensional'])) { - $nv = []; - foreach ($value as $v) { - $cols = ','.count($v); - $nv = array_merge($nv, $v); - } - $value = $nv; - } else { - $cols = ''; - } - if (is_array($value) && count($value) >= 1) { - $rows = count($value); - $contents = ''; - foreach ($value as $k => $v) { - $this->debug("serializing array element: $k, $v of type: $typeDef[arrayType]"); - //if (strpos($typeDef['arrayType'], ':') ) { - if (!in_array($typeDef['arrayType'], $this->typemap['http://www.w3.org/2001/XMLSchema'])) { - $contents .= $this->serializeType('item', $typeDef['arrayType'], $v, $use); - } else { - $contents .= $this->serialize_val($v, 'item', $typeDef['arrayType'], null, $this->XMLSchemaVersion, false, $use); - } - } - } else { - $rows = 0; - $contents = null; - } - // TODO: for now, an empty value will be serialized as a zero element - // array. Revisit this when coding the handling of null/nil values. - if ($use == 'literal') { - $xml = "<$name$elementNS>" - .$contents - .""; - } else { - $xml = "<$name$elementNS xsi:type=\"".$this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/').':Array" '. - $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/') - .':arrayType="' - .$this->getPrefixFromNamespace($this->getPrefix($typeDef['arrayType'])) - .':'.$this->getLocalPart($typeDef['arrayType'])."[$rows$cols]\">" - .$contents - .""; - } - } elseif ($phpType == 'scalar') { - if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) { - $elementNS = " xmlns=\"$ns\""; - } else { - if ($unqualified) { - $elementNS = ' xmlns=""'; - } else { - $elementNS = ''; - } - } - if ($use == 'literal') { - if ($forceType) { - $xml = "<$name$elementNS xsi:type=\"".$this->getPrefixFromNamespace($ns).":$uqType\">$value"; - } else { - $xml = "<$name$elementNS>$value"; - } - } else { - $xml = "<$name$elementNS xsi:type=\"".$this->getPrefixFromNamespace($ns).":$uqType\"$encodingStyle>$value"; - } - } - $this->debug("in serializeType: returning: $xml"); - - return $xml; - } - - /** - * serializes the attributes for a complexType. - * - * @param array $typeDef our internal representation of an XML schema type (or element) - * @param mixed $value a native PHP value (parameter value) - * @param string $ns the namespace of the type - * @param string $uqType the local part of the type - * - * @return string value serialized as an XML string - */ - public function serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType) - { - $this->debug("serializeComplexTypeAttributes for XML Schema type $ns:$uqType"); - $xml = ''; - if (isset($typeDef['extensionBase'])) { - $nsx = $this->getPrefix($typeDef['extensionBase']); - $uqTypex = $this->getLocalPart($typeDef['extensionBase']); - if ($this->getNamespaceFromPrefix($nsx)) { - $nsx = $this->getNamespaceFromPrefix($nsx); - } - if ($typeDefx = $this->getTypeDef($uqTypex, $nsx)) { - $this->debug("serialize attributes for extension base $nsx:$uqTypex"); - $xml .= $this->serializeComplexTypeAttributes($typeDefx, $value, $nsx, $uqTypex); - } else { - $this->debug("extension base $nsx:$uqTypex is not a supported type"); - } - } - if (isset($typeDef['attrs']) && is_array($typeDef['attrs'])) { - $this->debug("serialize attributes for XML Schema type $ns:$uqType"); - if (is_array($value)) { - $xvalue = $value; - } elseif (is_object($value)) { - $xvalue = get_object_vars($value); - } else { - $this->debug("value is neither an array nor an object for XML Schema type $ns:$uqType"); - $xvalue = []; - } - foreach ($typeDef['attrs'] as $aName => $attrs) { - if (isset($xvalue['!'.$aName])) { - $xname = '!'.$aName; - $this->debug("value provided for attribute $aName with key $xname"); - } elseif (isset($xvalue[$aName])) { - $xname = $aName; - $this->debug("value provided for attribute $aName with key $xname"); - } elseif (isset($attrs['default'])) { - $xname = '!'.$aName; - $xvalue[$xname] = $attrs['default']; - $this->debug('use default value of '.$xvalue[$aName].' for attribute '.$aName); - } else { - $xname = ''; - $this->debug("no value provided for attribute $aName"); - } - if ($xname) { - $xml .= " $aName=\"".$this->expandEntities($xvalue[$xname]).'"'; - } - } - } else { - $this->debug("no attributes to serialize for XML Schema type $ns:$uqType"); - } - - return $xml; - } - - /** - * serializes the elements for a complexType. - * - * @param array $typeDef our internal representation of an XML schema type (or element) - * @param mixed $value a native PHP value (parameter value) - * @param string $ns the namespace of the type - * @param string $uqType the local part of the type - * @param string $use use for part (encoded|literal) - * @param string $encodingStyle SOAP encoding style for the value (if different than the enclosing style) - * - * @return string value serialized as an XML string - */ - public function serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use = 'encoded', $encodingStyle = false) - { - $this->debug("in serializeComplexTypeElements for XML Schema type $ns:$uqType"); - $xml = ''; - if (isset($typeDef['extensionBase'])) { - $nsx = $this->getPrefix($typeDef['extensionBase']); - $uqTypex = $this->getLocalPart($typeDef['extensionBase']); - if ($this->getNamespaceFromPrefix($nsx)) { - $nsx = $this->getNamespaceFromPrefix($nsx); - } - if ($typeDefx = $this->getTypeDef($uqTypex, $nsx)) { - $this->debug("serialize elements for extension base $nsx:$uqTypex"); - $xml .= $this->serializeComplexTypeElements($typeDefx, $value, $nsx, $uqTypex, $use, $encodingStyle); - } else { - $this->debug("extension base $nsx:$uqTypex is not a supported type"); - } - } - if (isset($typeDef['elements']) && is_array($typeDef['elements'])) { - $this->debug("in serializeComplexTypeElements, serialize elements for XML Schema type $ns:$uqType"); - if (is_array($value)) { - $xvalue = $value; - } elseif (is_object($value)) { - $xvalue = get_object_vars($value); - } else { - $this->debug("value is neither an array nor an object for XML Schema type $ns:$uqType"); - $xvalue = []; - } - // toggle whether all elements are present - ideally should validate against schema - if (count($typeDef['elements']) != count($xvalue)) { - $optionals = true; - } - foreach ($typeDef['elements'] as $eName => $attrs) { - if (!isset($xvalue[$eName])) { - if (isset($attrs['default'])) { - $xvalue[$eName] = $attrs['default']; - $this->debug('use default value of '.$xvalue[$eName].' for element '.$eName); - } - } - // if user took advantage of a minOccurs=0, then only serialize named parameters - if (isset($optionals) - && (!isset($xvalue[$eName])) - && ((!isset($attrs['nillable'])) || $attrs['nillable'] != 'true') - ) { - if (isset($attrs['minOccurs']) && $attrs['minOccurs'] != '0') { - $this->debug("apparent error: no value provided for element $eName with minOccurs=".$attrs['minOccurs']); - } - // do nothing - $this->debug("no value provided for complexType element $eName and element is not nillable, so serialize nothing"); - } else { - // get value - if (isset($xvalue[$eName])) { - $v = $xvalue[$eName]; - } else { - $v = null; - } - if (isset($attrs['form'])) { - $unqualified = ($attrs['form'] == 'unqualified'); - } else { - $unqualified = false; - } - if (isset($attrs['maxOccurs']) && ($attrs['maxOccurs'] == 'unbounded' || $attrs['maxOccurs'] > 1) && isset($v) && is_array($v) && $this->isArraySimpleOrStruct($v) == 'arraySimple') { - $vv = $v; - foreach ($vv as $k => $v) { - if (isset($attrs['type']) || isset($attrs['ref'])) { - // serialize schema-defined type - $xml .= $this->serializeType($eName, isset($attrs['type']) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified); - } else { - // serialize generic type (can this ever really happen?) - $this->debug("calling serialize_val() for $v, $eName, false, false, false, false, $use"); - $xml .= $this->serialize_val($v, $eName, false, false, false, false, $use); - } - } - } else { - if (is_null($v) && isset($attrs['minOccurs']) && $attrs['minOccurs'] == '0') { - // do nothing - } elseif (is_null($v) && isset($attrs['nillable']) && $attrs['nillable'] == 'true') { - // TODO: serialize a nil correctly, but for now serialize schema-defined type - $xml .= $this->serializeType($eName, isset($attrs['type']) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified); - } elseif (isset($attrs['type']) || isset($attrs['ref'])) { - // serialize schema-defined type - $xml .= $this->serializeType($eName, isset($attrs['type']) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified); - } else { - // serialize generic type (can this ever really happen?) - $this->debug("calling serialize_val() for $v, $eName, false, false, false, false, $use"); - $xml .= $this->serialize_val($v, $eName, false, false, false, false, $use); - } - } - } - } - } else { - $this->debug("no elements to serialize for XML Schema type $ns:$uqType"); - } - - return $xml; - } - - /** - * adds an XML Schema complex type to the WSDL types. - * - * @param string $name - * @param string $typeClass (complexType|simpleType|attribute) - * @param string $phpType currently supported are array and struct (php assoc array) - * @param string $compositor (all|sequence|choice) - * @param string $restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array) - * @param array $elements e.g. array ( name => array(name=>'',type=>'') ) - * @param array $attrs e.g. array(array('ref'=>'SOAP-ENC:arrayType','wsdl:arrayType'=>'xsd:string[]')) - * @param string $arrayType as namespace:name (xsd:string) - * - * @see nusoap_xmlschema - */ - public function addComplexType($name, $typeClass = 'complexType', $phpType = 'array', $compositor = '', $restrictionBase = '', $elements = [], $attrs = [], $arrayType = '') - { - if (count($elements) > 0) { - $eElements = []; - foreach ($elements as $n => $e) { - // expand each element - $ee = []; - foreach ($e as $k => $v) { - $k = strpos($k, ':') ? $this->expandQname($k) : $k; - $v = strpos($v, ':') ? $this->expandQname($v) : $v; - $ee[$k] = $v; - } - $eElements[$n] = $ee; - } - $elements = $eElements; - } - - if (count($attrs) > 0) { - foreach ($attrs as $n => $a) { - // expand each attribute - foreach ($a as $k => $v) { - $k = strpos($k, ':') ? $this->expandQname($k) : $k; - $v = strpos($v, ':') ? $this->expandQname($v) : $v; - $aa[$k] = $v; - } - $eAttrs[$n] = $aa; - } - $attrs = $eAttrs; - } - - $restrictionBase = strpos($restrictionBase, ':') ? $this->expandQname($restrictionBase) : $restrictionBase; - $arrayType = strpos($arrayType, ':') ? $this->expandQname($arrayType) : $arrayType; - - $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns']; - $this->schemas[$typens][0]->addComplexType($name, $typeClass, $phpType, $compositor, $restrictionBase, $elements, $attrs, $arrayType); - } - - /** - * adds an XML Schema simple type to the WSDL types. - * - * @param string $name - * @param string $restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array) - * @param string $typeClass (should always be simpleType) - * @param string $phpType (should always be scalar) - * @param array $enumeration array of values - * - * @see nusoap_xmlschema - */ - public function addSimpleType($name, $restrictionBase = '', $typeClass = 'simpleType', $phpType = 'scalar', $enumeration = []) - { - $restrictionBase = strpos($restrictionBase, ':') ? $this->expandQname($restrictionBase) : $restrictionBase; - - $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns']; - $this->schemas[$typens][0]->addSimpleType($name, $restrictionBase, $typeClass, $phpType, $enumeration); - } - - /** - * adds an element to the WSDL types. - * - * @param array $attrs attributes that must include name and type - * - * @see nusoap_xmlschema - */ - public function addElement($attrs) - { - $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns']; - $this->schemas[$typens][0]->addElement($attrs); - } - - /** - * register an operation with the server. - * - * @param string $name operation (method) name - * @param array $in assoc array of input values: key = param name, value = param type - * @param array $out assoc array of output values: key = param name, value = param type - * @param string $namespace optional The namespace for the operation - * @param string $soapaction optional The soapaction for the operation - * @param string $style (rpc|document) optional The style for the operation Note: when 'document' is specified, parameter and return wrappers are created for you automatically - * @param string $use (encoded|literal) optional The use for the parameters (cannot mix right now) - * @param string $documentation optional The description to include in the WSDL - * @param string $encodingStyle optional (usually 'http://schemas.xmlsoap.org/soap/encoding/' for encoded) - */ - public function addOperation($name, $in = false, $out = false, $namespace = false, $soapaction = false, $style = 'rpc', $use = 'encoded', $documentation = '', $encodingStyle = '') - { - if ($use == 'encoded' && $encodingStyle == '') { - $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/'; - } - - if ($style == 'document') { - $elements = []; - foreach ($in as $n => $t) { - $elements[$n] = ['name' => $n, 'type' => $t, 'form' => 'unqualified']; - } - $this->addComplexType($name.'RequestType', 'complexType', 'struct', 'all', '', $elements); - $this->addElement(['name' => $name, 'type' => $name.'RequestType']); - $in = ['parameters' => 'tns:'.$name.'^']; - - $elements = []; - foreach ($out as $n => $t) { - $elements[$n] = ['name' => $n, 'type' => $t, 'form' => 'unqualified']; - } - $this->addComplexType($name.'ResponseType', 'complexType', 'struct', 'all', '', $elements); - $this->addElement(['name' => $name.'Response', 'type' => $name.'ResponseType', 'form' => 'qualified']); - $out = ['parameters' => 'tns:'.$name.'Response'.'^']; - } - - // get binding - $this->bindings[$this->serviceName.'Binding']['operations'][$name] = - [ - 'name' => $name, - 'binding' => $this->serviceName.'Binding', - 'endpoint' => $this->endpoint, - 'soapAction' => $soapaction, - 'style' => $style, - 'input' => [ - 'use' => $use, - 'namespace' => $namespace, - 'encodingStyle' => $encodingStyle, - 'message' => $name.'Request', - 'parts' => $in, ], - 'output' => [ - 'use' => $use, - 'namespace' => $namespace, - 'encodingStyle' => $encodingStyle, - 'message' => $name.'Response', - 'parts' => $out, ], - 'namespace' => $namespace, - 'transport' => 'http://schemas.xmlsoap.org/soap/http', - 'documentation' => $documentation, ]; - // add portTypes - // add messages - if ($in) { - foreach ($in as $pName => $pType) { - if (strpos($pType, ':')) { - $pType = $this->getNamespaceFromPrefix($this->getPrefix($pType)).':'.$this->getLocalPart($pType); - } - $this->messages[$name.'Request'][$pName] = $pType; - } - } else { - $this->messages[$name.'Request'] = '0'; - } - if ($out) { - foreach ($out as $pName => $pType) { - if (strpos($pType, ':')) { - $pType = $this->getNamespaceFromPrefix($this->getPrefix($pType)).':'.$this->getLocalPart($pType); - } - $this->messages[$name.'Response'][$pName] = $pType; - } - } else { - $this->messages[$name.'Response'] = '0'; - } - - return true; - } -} diff --git a/src/Drivers/lib/class.wsdlcache.php b/src/Drivers/lib/class.wsdlcache.php deleted file mode 100644 index 179e443..0000000 --- a/src/Drivers/lib/class.wsdlcache.php +++ /dev/null @@ -1,225 +0,0 @@ - - * @author Ingo Fischer - * - * @version $Id: class.wsdlcache.php,v 1.7 2007/04/17 16:34:03 snichol Exp $ - */ -class nusoap_wsdlcache -{ - /* - * @var resource - * @access private - */ - public $fplock; - /* - * @var integer - * @access private - */ - public $cache_lifetime; - /* - * @var string - * @access private - */ - public $cache_dir; - /* - * @var string - * @access public - */ - public $debug_str = ''; - - /** - * constructor. - * - * @param string $cache_dir directory for cache-files - * @param int $cache_lifetime lifetime for caching-files in seconds or 0 for unlimited - */ - public function nusoap_wsdlcache($cache_dir = '.', $cache_lifetime = 0) - { - $this->fplock = []; - $this->cache_dir = $cache_dir != '' ? $cache_dir : '.'; - $this->cache_lifetime = $cache_lifetime; - } - - /** - * creates the filename used to cache a wsdl instance. - * - * @param string $wsdl The URL of the wsdl instance - * - * @return string The filename used to cache the instance - */ - public function createFilename($wsdl) - { - return $this->cache_dir.'/wsdlcache-'.md5($wsdl); - } - - /** - * adds debug data to the class level debug string. - * - * @param string $string debug data - */ - public function debug($string) - { - $this->debug_str .= get_class($this).": $string\n"; - } - - /** - * gets a wsdl instance from the cache. - * - * @param string $wsdl The URL of the wsdl instance - * - * @return object wsdl The cached wsdl instance, null if the instance is not in the cache - */ - public function get($wsdl) - { - $filename = $this->createFilename($wsdl); - if ($this->obtainMutex($filename, 'r')) { - // check for expired WSDL that must be removed from the cache - if ($this->cache_lifetime > 0) { - if (file_exists($filename) && (time() - filemtime($filename) > $this->cache_lifetime)) { - unlink($filename); - $this->debug("Expired $wsdl ($filename) from cache"); - $this->releaseMutex($filename); - - return; - } - } - // see what there is to return - if (!file_exists($filename)) { - $this->debug("$wsdl ($filename) not in cache (1)"); - $this->releaseMutex($filename); - - return; - } - $fp = @fopen($filename, 'r'); - if ($fp) { - $s = implode('', @file($filename)); - fclose($fp); - $this->debug("Got $wsdl ($filename) from cache"); - } else { - $s = null; - $this->debug("$wsdl ($filename) not in cache (2)"); - } - $this->releaseMutex($filename); - - return (!is_null($s)) ? unserialize($s) : null; - } else { - $this->debug("Unable to obtain mutex for $filename in get"); - } - } - - /** - * obtains the local mutex. - * - * @param string $filename The Filename of the Cache to lock - * @param string $mode The open-mode ("r" or "w") or the file - affects lock-mode - * - * @return bool Lock successfully obtained ?! - */ - public function obtainMutex($filename, $mode) - { - if (isset($this->fplock[md5($filename)])) { - $this->debug("Lock for $filename already exists"); - - return false; - } - $this->fplock[md5($filename)] = fopen($filename.'.lock', 'w'); - if ($mode == 'r') { - return flock($this->fplock[md5($filename)], LOCK_SH); - } else { - return flock($this->fplock[md5($filename)], LOCK_EX); - } - } - - /** - * adds a wsdl instance to the cache. - * - * @param object wsdl $wsdl_instance The wsdl instance to add - * - * @return bool WSDL successfully cached - */ - public function put($wsdl_instance) - { - $filename = $this->createFilename($wsdl_instance->wsdl); - $s = serialize($wsdl_instance); - if ($this->obtainMutex($filename, 'w')) { - $fp = fopen($filename, 'w'); - if (!$fp) { - $this->debug("Cannot write $wsdl_instance->wsdl ($filename) in cache"); - $this->releaseMutex($filename); - - return false; - } - fwrite($fp, $s); - fclose($fp); - $this->debug("Put $wsdl_instance->wsdl ($filename) in cache"); - $this->releaseMutex($filename); - - return true; - } else { - $this->debug("Unable to obtain mutex for $filename in put"); - } - - return false; - } - - /** - * releases the local mutex. - * - * @param string $filename The Filename of the Cache to lock - * - * @return bool Lock successfully released - */ - public function releaseMutex($filename) - { - $ret = flock($this->fplock[md5($filename)], LOCK_UN); - fclose($this->fplock[md5($filename)]); - unset($this->fplock[md5($filename)]); - if (!$ret) { - $this->debug("Not able to release lock for $filename"); - } - - return $ret; - } - - /** - * removes a wsdl instance from the cache. - * - * @param string $wsdl The URL of the wsdl instance - * - * @return bool Whether there was an instance to remove - */ - public function remove($wsdl) - { - $filename = $this->createFilename($wsdl); - if (!file_exists($filename)) { - $this->debug("$wsdl ($filename) not in cache to be removed"); - - return false; - } - // ignore errors obtaining mutex - $this->obtainMutex($filename, 'w'); - $ret = unlink($filename); - $this->debug("Removed ($ret) $wsdl ($filename) from cache"); - $this->releaseMutex($filename); - - return $ret; - } -} - -/** - * For backward compatibility. - */ -class wsdlcache extends nusoap_wsdlcache -{ -} diff --git a/src/Drivers/lib/class.xmlschema.php b/src/Drivers/lib/class.xmlschema.php deleted file mode 100644 index 60e3ef4..0000000 --- a/src/Drivers/lib/class.xmlschema.php +++ /dev/null @@ -1,994 +0,0 @@ - - * @author Scott Nichol - * - * @version $Id: class.xmlschema.php,v 1.53 2010/04/26 20:15:08 snichol Exp $ - */ -class nusoap_xmlschema extends nusoap_base -{ - // files - public $schema = ''; - public $xml = ''; - // namespaces - public $enclosingNamespaces; - // schema info - public $schemaInfo = []; - public $schemaTargetNamespace = ''; - // types, elements, attributes defined by the schema - public $attributes = []; - public $complexTypes = []; - public $complexTypeStack = []; - public $currentComplexType = null; - public $elements = []; - public $elementStack = []; - public $currentElement = null; - public $simpleTypes = []; - public $simpleTypeStack = []; - public $currentSimpleType = null; - // imports - public $imports = []; - // parser vars - public $parser; - public $position = 0; - public $depth = 0; - public $depth_array = []; - public $message = []; - public $defaultNamespace = []; - - /** - * constructor. - * - * @param string $schema schema document URI - * @param string $xml xml document URI - * @param string $namespaces namespaces defined in enclosing XML - */ - public function nusoap_xmlschema($schema = '', $xml = '', $namespaces = []) - { - parent::nusoap_base(); - $this->debug('nusoap_xmlschema class instantiated, inside constructor'); - // files - $this->schema = $schema; - $this->xml = $xml; - - // namespaces - $this->enclosingNamespaces = $namespaces; - $this->namespaces = array_merge($this->namespaces, $namespaces); - - // parse schema file - if ($schema != '') { - $this->debug('initial schema file: '.$schema); - $this->parseFile($schema, 'schema'); - } - - // parse xml file - if ($xml != '') { - $this->debug('initial xml file: '.$xml); - $this->parseFile($xml, 'xml'); - } - } - - /** - * parse an XML file. - * - * @param string $xml path/URL to XML file - * @param string $type (schema | xml) - * - * @return bool - */ - public function parseFile($xml, $type) - { - // parse xml file - if ($xml != '') { - $xmlStr = @implode('', @file($xml)); - if ($xmlStr == '') { - $msg = 'Error reading XML from '.$xml; - $this->setError($msg); - $this->debug($msg); - - return false; - } else { - $this->debug("parsing $xml"); - $this->parseString($xmlStr, $type); - $this->debug("done parsing $xml"); - - return true; - } - } - - return false; - } - - /** - * parse an XML string. - * - * @param string $xml path or URL - * @param string $type (schema|xml) - */ - public function parseString($xml, $type) - { - // parse xml string - if ($xml != '') { - - // Create an XML parser. - $this->parser = xml_parser_create(); - // Set the options for parsing the XML data. - xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0); - - // Set the object for the parser. - xml_set_object($this->parser, $this); - - // Set the element handlers for the parser. - if ($type == 'schema') { - xml_set_element_handler($this->parser, 'schemaStartElement', 'schemaEndElement'); - xml_set_character_data_handler($this->parser, 'schemaCharacterData'); - } elseif ($type == 'xml') { - xml_set_element_handler($this->parser, 'xmlStartElement', 'xmlEndElement'); - xml_set_character_data_handler($this->parser, 'xmlCharacterData'); - } - - // Parse the XML file. - if (!xml_parse($this->parser, $xml, true)) { - // Display an error message. - $errstr = sprintf('XML error parsing XML schema on line %d: %s', - xml_get_current_line_number($this->parser), - xml_error_string(xml_get_error_code($this->parser)) - ); - $this->debug($errstr); - $this->debug("XML payload:\n".$xml); - $this->setError($errstr); - } - - xml_parser_free($this->parser); - } else { - $this->debug('no xml passed to parseString()!!'); - $this->setError('no xml passed to parseString()!!'); - } - } - - /** - * gets a type name for an unnamed type. - * - * @param string Element name - * - * @return string A type name for an unnamed type - */ - public function CreateTypeName($ename) - { - $scope = ''; - for ($i = 0; $i < count($this->complexTypeStack); $i++) { - $scope .= $this->complexTypeStack[$i].'_'; - } - - return $scope.$ename.'_ContainedType'; - } - - /** - * start-element handler. - * - * @param string $parser XML parser object - * @param string $name element name - * @param string $attrs associative array of attributes - */ - public function schemaStartElement($parser, $name, $attrs) - { - - // position in the total number of elements, starting from 0 - $pos = $this->position++; - $depth = $this->depth++; - // set self as current value for this depth - $this->depth_array[$depth] = $pos; - $this->message[$pos] = ['cdata' => '']; - if ($depth > 0) { - $this->defaultNamespace[$pos] = $this->defaultNamespace[$this->depth_array[$depth - 1]]; - } else { - $this->defaultNamespace[$pos] = false; - } - - // get element prefix - if ($prefix = $this->getPrefix($name)) { - // get unqualified name - $name = $this->getLocalPart($name); - } else { - $prefix = ''; - } - - // loop thru attributes, expanding, and registering namespace declarations - if (count($attrs) > 0) { - foreach ($attrs as $k => $v) { - // if ns declarations, add to class level array of valid namespaces - if (preg_match('/^xmlns/', $k)) { - //$this->xdebug("$k: $v"); - //$this->xdebug('ns_prefix: '.$this->getPrefix($k)); - if ($ns_prefix = substr(strrchr($k, ':'), 1)) { - //$this->xdebug("Add namespace[$ns_prefix] = $v"); - $this->namespaces[$ns_prefix] = $v; - } else { - $this->defaultNamespace[$pos] = $v; - if (!$this->getPrefixFromNamespace($v)) { - $this->namespaces['ns'.(count($this->namespaces) + 1)] = $v; - } - } - if ($v == 'http://www.w3.org/2001/XMLSchema' || $v == 'http://www.w3.org/1999/XMLSchema' || $v == 'http://www.w3.org/2000/10/XMLSchema') { - $this->XMLSchemaVersion = $v; - $this->namespaces['xsi'] = $v.'-instance'; - } - } - } - foreach ($attrs as $k => $v) { - // expand each attribute - $k = strpos($k, ':') ? $this->expandQname($k) : $k; - $v = strpos($v, ':') ? $this->expandQname($v) : $v; - $eAttrs[$k] = $v; - } - $attrs = $eAttrs; - } else { - $attrs = []; - } - // find status, register data - switch ($name) { - case 'all': // (optional) compositor content for a complexType - case 'choice': - case 'group': - case 'sequence': - //$this->xdebug("compositor $name for currentComplexType: $this->currentComplexType and currentElement: $this->currentElement"); - $this->complexTypes[$this->currentComplexType]['compositor'] = $name; - //if($name == 'all' || $name == 'sequence'){ - // $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct'; - //} - break; - case 'attribute': // complexType attribute - //$this->xdebug("parsing attribute $attrs[name] $attrs[ref] of value: ".$attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']); - $this->xdebug('parsing attribute:'); - $this->appendDebug($this->varDump($attrs)); - if (!isset($attrs['form'])) { - // TODO: handle globals - $attrs['form'] = $this->schemaInfo['attributeFormDefault']; - } - if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])) { - $v = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']; - if (!strpos($v, ':')) { - // no namespace in arrayType attribute value... - if ($this->defaultNamespace[$pos]) { - // ...so use the default - $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'] = $this->defaultNamespace[$pos].':'.$attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']; - } - } - } - if (isset($attrs['name'])) { - $this->attributes[$attrs['name']] = $attrs; - $aname = $attrs['name']; - } elseif (isset($attrs['ref']) && $attrs['ref'] == 'http://schemas.xmlsoap.org/soap/encoding/:arrayType') { - if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])) { - $aname = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']; - } else { - $aname = ''; - } - } elseif (isset($attrs['ref'])) { - $aname = $attrs['ref']; - $this->attributes[$attrs['ref']] = $attrs; - } - - if ($this->currentComplexType) { // This should *always* be - $this->complexTypes[$this->currentComplexType]['attrs'][$aname] = $attrs; - } - // arrayType attribute - if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']) || $this->getLocalPart($aname) == 'arrayType') { - $this->complexTypes[$this->currentComplexType]['phpType'] = 'array'; - $prefix = $this->getPrefix($aname); - if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])) { - $v = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']; - } else { - $v = ''; - } - if (strpos($v, '[,]')) { - $this->complexTypes[$this->currentComplexType]['multidimensional'] = true; - } - $v = substr($v, 0, strpos($v, '[')); // clip the [] - if (!strpos($v, ':') && isset($this->typemap[$this->XMLSchemaVersion][$v])) { - $v = $this->XMLSchemaVersion.':'.$v; - } - $this->complexTypes[$this->currentComplexType]['arrayType'] = $v; - } - break; - case 'complexContent': // (optional) content for a complexType - $this->xdebug("do nothing for element $name"); - break; - case 'complexType': - array_push($this->complexTypeStack, $this->currentComplexType); - if (isset($attrs['name'])) { - // TODO: what is the scope of named complexTypes that appear - // nested within other c complexTypes? - $this->xdebug('processing named complexType '.$attrs['name']); - //$this->currentElement = false; - $this->currentComplexType = $attrs['name']; - $this->complexTypes[$this->currentComplexType] = $attrs; - $this->complexTypes[$this->currentComplexType]['typeClass'] = 'complexType'; - // This is for constructs like - // - // - // - // - // - if (isset($attrs['base']) && preg_match('/:Array$/', $attrs['base'])) { - $this->xdebug('complexType is unusual array'); - $this->complexTypes[$this->currentComplexType]['phpType'] = 'array'; - } else { - $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct'; - } - } else { - $name = $this->CreateTypeName($this->currentElement); - $this->xdebug('processing unnamed complexType for element '.$this->currentElement.' named '.$name); - $this->currentComplexType = $name; - //$this->currentElement = false; - $this->complexTypes[$this->currentComplexType] = $attrs; - $this->complexTypes[$this->currentComplexType]['typeClass'] = 'complexType'; - // This is for constructs like - // - // - // - // - // - if (isset($attrs['base']) && preg_match('/:Array$/', $attrs['base'])) { - $this->xdebug('complexType is unusual array'); - $this->complexTypes[$this->currentComplexType]['phpType'] = 'array'; - } else { - $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct'; - } - } - $this->complexTypes[$this->currentComplexType]['simpleContent'] = 'false'; - break; - case 'element': - array_push($this->elementStack, $this->currentElement); - if (!isset($attrs['form'])) { - if ($this->currentComplexType) { - $attrs['form'] = $this->schemaInfo['elementFormDefault']; - } else { - // global - $attrs['form'] = 'qualified'; - } - } - if (isset($attrs['type'])) { - $this->xdebug('processing typed element '.$attrs['name'].' of type '.$attrs['type']); - if (!$this->getPrefix($attrs['type'])) { - if ($this->defaultNamespace[$pos]) { - $attrs['type'] = $this->defaultNamespace[$pos].':'.$attrs['type']; - $this->xdebug('used default namespace to make type '.$attrs['type']); - } - } - // This is for constructs like - // - // - // - // - // - if ($this->currentComplexType && $this->complexTypes[$this->currentComplexType]['phpType'] == 'array') { - $this->xdebug('arrayType for unusual array is '.$attrs['type']); - $this->complexTypes[$this->currentComplexType]['arrayType'] = $attrs['type']; - } - $this->currentElement = $attrs['name']; - $ename = $attrs['name']; - } elseif (isset($attrs['ref'])) { - $this->xdebug('processing element as ref to '.$attrs['ref']); - $this->currentElement = 'ref to '.$attrs['ref']; - $ename = $this->getLocalPart($attrs['ref']); - } else { - $type = $this->CreateTypeName($this->currentComplexType.'_'.$attrs['name']); - $this->xdebug('processing untyped element '.$attrs['name'].' type '.$type); - $this->currentElement = $attrs['name']; - $attrs['type'] = $this->schemaTargetNamespace.':'.$type; - $ename = $attrs['name']; - } - if (isset($ename) && $this->currentComplexType) { - $this->xdebug("add element $ename to complexType $this->currentComplexType"); - $this->complexTypes[$this->currentComplexType]['elements'][$ename] = $attrs; - } elseif (!isset($attrs['ref'])) { - $this->xdebug("add element $ename to elements array"); - $this->elements[$attrs['name']] = $attrs; - $this->elements[$attrs['name']]['typeClass'] = 'element'; - } - break; - case 'enumeration': // restriction value list member - $this->xdebug('enumeration '.$attrs['value']); - if ($this->currentSimpleType) { - $this->simpleTypes[$this->currentSimpleType]['enumeration'][] = $attrs['value']; - } elseif ($this->currentComplexType) { - $this->complexTypes[$this->currentComplexType]['enumeration'][] = $attrs['value']; - } - break; - case 'extension': // simpleContent or complexContent type extension - $this->xdebug('extension '.$attrs['base']); - if ($this->currentComplexType) { - $ns = $this->getPrefix($attrs['base']); - if ($ns == '') { - $this->complexTypes[$this->currentComplexType]['extensionBase'] = $this->schemaTargetNamespace.':'.$attrs['base']; - } else { - $this->complexTypes[$this->currentComplexType]['extensionBase'] = $attrs['base']; - } - } else { - $this->xdebug('no current complexType to set extensionBase'); - } - break; - case 'import': - if (isset($attrs['schemaLocation'])) { - $this->xdebug('import namespace '.$attrs['namespace'].' from '.$attrs['schemaLocation']); - $this->imports[$attrs['namespace']][] = ['location' => $attrs['schemaLocation'], 'loaded' => false]; - } else { - $this->xdebug('import namespace '.$attrs['namespace']); - $this->imports[$attrs['namespace']][] = ['location' => '', 'loaded' => true]; - if (!$this->getPrefixFromNamespace($attrs['namespace'])) { - $this->namespaces['ns'.(count($this->namespaces) + 1)] = $attrs['namespace']; - } - } - break; - case 'include': - if (isset($attrs['schemaLocation'])) { - $this->xdebug('include into namespace '.$this->schemaTargetNamespace.' from '.$attrs['schemaLocation']); - $this->imports[$this->schemaTargetNamespace][] = ['location' => $attrs['schemaLocation'], 'loaded' => false]; - } else { - $this->xdebug('ignoring invalid XML Schema construct: include without schemaLocation attribute'); - } - break; - case 'list': // simpleType value list - $this->xdebug("do nothing for element $name"); - break; - case 'restriction': // simpleType, simpleContent or complexContent value restriction - $this->xdebug('restriction '.$attrs['base']); - if ($this->currentSimpleType) { - $this->simpleTypes[$this->currentSimpleType]['type'] = $attrs['base']; - } elseif ($this->currentComplexType) { - $this->complexTypes[$this->currentComplexType]['restrictionBase'] = $attrs['base']; - if (strstr($attrs['base'], ':') == ':Array') { - $this->complexTypes[$this->currentComplexType]['phpType'] = 'array'; - } - } - break; - case 'schema': - $this->schemaInfo = $attrs; - $this->schemaInfo['schemaVersion'] = $this->getNamespaceFromPrefix($prefix); - if (isset($attrs['targetNamespace'])) { - $this->schemaTargetNamespace = $attrs['targetNamespace']; - } - if (!isset($attrs['elementFormDefault'])) { - $this->schemaInfo['elementFormDefault'] = 'unqualified'; - } - if (!isset($attrs['attributeFormDefault'])) { - $this->schemaInfo['attributeFormDefault'] = 'unqualified'; - } - break; - case 'simpleContent': // (optional) content for a complexType - if ($this->currentComplexType) { // This should *always* be - $this->complexTypes[$this->currentComplexType]['simpleContent'] = 'true'; - } else { - $this->xdebug("do nothing for element $name because there is no current complexType"); - } - break; - case 'simpleType': - array_push($this->simpleTypeStack, $this->currentSimpleType); - if (isset($attrs['name'])) { - $this->xdebug('processing simpleType for name '.$attrs['name']); - $this->currentSimpleType = $attrs['name']; - $this->simpleTypes[$attrs['name']] = $attrs; - $this->simpleTypes[$attrs['name']]['typeClass'] = 'simpleType'; - $this->simpleTypes[$attrs['name']]['phpType'] = 'scalar'; - } else { - $name = $this->CreateTypeName($this->currentComplexType.'_'.$this->currentElement); - $this->xdebug('processing unnamed simpleType for element '.$this->currentElement.' named '.$name); - $this->currentSimpleType = $name; - //$this->currentElement = false; - $this->simpleTypes[$this->currentSimpleType] = $attrs; - $this->simpleTypes[$this->currentSimpleType]['phpType'] = 'scalar'; - } - break; - case 'union': // simpleType type list - $this->xdebug("do nothing for element $name"); - break; - default: - $this->xdebug("do not have any logic to process element $name"); - } - } - - /** - * end-element handler. - * - * @param string $parser XML parser object - * @param string $name element name - */ - public function schemaEndElement($parser, $name) - { - // bring depth down a notch - $this->depth--; - // position of current element is equal to the last value left in depth_array for my depth - if (isset($this->depth_array[$this->depth])) { - $pos = $this->depth_array[$this->depth]; - } - // get element prefix - if ($prefix = $this->getPrefix($name)) { - // get unqualified name - $name = $this->getLocalPart($name); - } else { - $prefix = ''; - } - // move on... - if ($name == 'complexType') { - $this->xdebug('done processing complexType '.($this->currentComplexType ? $this->currentComplexType : '(unknown)')); - $this->xdebug($this->varDump($this->complexTypes[$this->currentComplexType])); - $this->currentComplexType = array_pop($this->complexTypeStack); - //$this->currentElement = false; - } - if ($name == 'element') { - $this->xdebug('done processing element '.($this->currentElement ? $this->currentElement : '(unknown)')); - $this->currentElement = array_pop($this->elementStack); - } - if ($name == 'simpleType') { - $this->xdebug('done processing simpleType '.($this->currentSimpleType ? $this->currentSimpleType : '(unknown)')); - $this->xdebug($this->varDump($this->simpleTypes[$this->currentSimpleType])); - $this->currentSimpleType = array_pop($this->simpleTypeStack); - } - } - - /** - * element content handler. - * - * @param string $parser XML parser object - * @param string $data element content - */ - public function schemaCharacterData($parser, $data) - { - $pos = $this->depth_array[$this->depth - 1]; - $this->message[$pos]['cdata'] .= $data; - } - - /** - * serialize the schema. - */ - public function serializeSchema() - { - $schemaPrefix = $this->getPrefixFromNamespace($this->XMLSchemaVersion); - $xml = ''; - // imports - if (count($this->imports) > 0) { - foreach ($this->imports as $ns => $list) { - foreach ($list as $ii) { - if ($ii['location'] != '') { - $xml .= " <$schemaPrefix:import location=\"".$ii['location'].'" namespace="'.$ns."\" />\n"; - } else { - $xml .= " <$schemaPrefix:import namespace=\"".$ns."\" />\n"; - } - } - } - } - // complex types - foreach ($this->complexTypes as $typeName => $attrs) { - $contentStr = ''; - // serialize child elements - if (isset($attrs['elements']) && (count($attrs['elements']) > 0)) { - foreach ($attrs['elements'] as $element => $eParts) { - if (isset($eParts['ref'])) { - $contentStr .= " <$schemaPrefix:element ref=\"$element\"/>\n"; - } else { - $contentStr .= " <$schemaPrefix:element name=\"$element\" type=\"".$this->contractQName($eParts['type']).'"'; - foreach ($eParts as $aName => $aValue) { - // handle, e.g., abstract, default, form, minOccurs, maxOccurs, nillable - if ($aName != 'name' && $aName != 'type') { - $contentStr .= " $aName=\"$aValue\""; - } - } - $contentStr .= "/>\n"; - } - } - // compositor wraps elements - if (isset($attrs['compositor']) && ($attrs['compositor'] != '')) { - $contentStr = " <$schemaPrefix:$attrs[compositor]>\n".$contentStr." \n"; - } - } - // attributes - if (isset($attrs['attrs']) && (count($attrs['attrs']) >= 1)) { - foreach ($attrs['attrs'] as $attr => $aParts) { - $contentStr .= " <$schemaPrefix:attribute"; - foreach ($aParts as $a => $v) { - if ($a == 'ref' || $a == 'type') { - $contentStr .= " $a=\"".$this->contractQName($v).'"'; - } elseif ($a == 'http://schemas.xmlsoap.org/wsdl/:arrayType') { - $this->usedNamespaces['wsdl'] = $this->namespaces['wsdl']; - $contentStr .= ' wsdl:arrayType="'.$this->contractQName($v).'"'; - } else { - $contentStr .= " $a=\"$v\""; - } - } - $contentStr .= "/>\n"; - } - } - // if restriction - if (isset($attrs['restrictionBase']) && $attrs['restrictionBase'] != '') { - $contentStr = " <$schemaPrefix:restriction base=\"".$this->contractQName($attrs['restrictionBase'])."\">\n".$contentStr." \n"; - // complex or simple content - if ((isset($attrs['elements']) && count($attrs['elements']) > 0) || (isset($attrs['attrs']) && count($attrs['attrs']) > 0)) { - $contentStr = " <$schemaPrefix:complexContent>\n".$contentStr." \n"; - } - } - // finalize complex type - if ($contentStr != '') { - $contentStr = " <$schemaPrefix:complexType name=\"$typeName\">\n".$contentStr." \n"; - } else { - $contentStr = " <$schemaPrefix:complexType name=\"$typeName\"/>\n"; - } - $xml .= $contentStr; - } - // simple types - if (isset($this->simpleTypes) && count($this->simpleTypes) > 0) { - foreach ($this->simpleTypes as $typeName => $eParts) { - $xml .= " <$schemaPrefix:simpleType name=\"$typeName\">\n <$schemaPrefix:restriction base=\"".$this->contractQName($eParts['type'])."\">\n"; - if (isset($eParts['enumeration'])) { - foreach ($eParts['enumeration'] as $e) { - $xml .= " <$schemaPrefix:enumeration value=\"$e\"/>\n"; - } - } - $xml .= " \n "; - } - } - // elements - if (isset($this->elements) && count($this->elements) > 0) { - foreach ($this->elements as $element => $eParts) { - $xml .= " <$schemaPrefix:element name=\"$element\" type=\"".$this->contractQName($eParts['type'])."\"/>\n"; - } - } - // attributes - if (isset($this->attributes) && count($this->attributes) > 0) { - foreach ($this->attributes as $attr => $aParts) { - $xml .= " <$schemaPrefix:attribute name=\"$attr\" type=\"".$this->contractQName($aParts['type'])."\"\n/>"; - } - } - // finish 'er up - $attr = ''; - foreach ($this->schemaInfo as $k => $v) { - if ($k == 'elementFormDefault' || $k == 'attributeFormDefault') { - $attr .= " $k=\"$v\""; - } - } - $el = "<$schemaPrefix:schema$attr targetNamespace=\"$this->schemaTargetNamespace\"\n"; - foreach (array_diff($this->usedNamespaces, $this->enclosingNamespaces) as $nsp => $ns) { - $el .= " xmlns:$nsp=\"$ns\""; - } - $xml = $el.">\n".$xml."\n"; - - return $xml; - } - - /** - * adds debug data to the clas level debug string. - * - * @param string $string debug data - */ - public function xdebug($string) - { - $this->debug('<'.$this->schemaTargetNamespace.'> '.$string); - } - - /** - * get the PHP type of a user defined type in the schema - * PHP type is kind of a misnomer since it actually returns 'struct' for assoc. arrays - * returns false if no type exists, or not w/ the given namespace - * else returns a string that is either a native php type, or 'struct'. - * - * @param string $type name of defined type - * @param string $ns namespace of type - * - * @return mixed - * - * @deprecated - */ - public function getPHPType($type, $ns) - { - if (isset($this->typemap[$ns][$type])) { - //print "found type '$type' and ns $ns in typemap
"; - return $this->typemap[$ns][$type]; - } elseif (isset($this->complexTypes[$type])) { - //print "getting type '$type' and ns $ns from complexTypes array
"; - return $this->complexTypes[$type]['phpType']; - } - - return false; - } - - /** - * returns an associative array of information about a given type - * returns false if no type exists by the given name. - * - * For a complexType typeDef = array( - * 'restrictionBase' => '', - * 'phpType' => '', - * 'compositor' => '(sequence|all)', - * 'elements' => array(), // refs to elements array - * 'attrs' => array() // refs to attributes array - * ... and so on (see addComplexType) - * ) - * - * For simpleType or element, the array has different keys. - * - * @param string $type - * - * @return mixed - * - * @see addComplexType - * @see addSimpleType - * @see addElement - */ - public function getTypeDef($type) - { - //$this->debug("in getTypeDef for type $type"); - if (substr($type, -1) == '^') { - $is_element = 1; - $type = substr($type, 0, -1); - } else { - $is_element = 0; - } - - if ((!$is_element) && isset($this->complexTypes[$type])) { - $this->xdebug("in getTypeDef, found complexType $type"); - - return $this->complexTypes[$type]; - } elseif ((!$is_element) && isset($this->simpleTypes[$type])) { - $this->xdebug("in getTypeDef, found simpleType $type"); - if (!isset($this->simpleTypes[$type]['phpType'])) { - // get info for type to tack onto the simple type - // TODO: can this ever really apply (i.e. what is a simpleType really?) - $uqType = substr($this->simpleTypes[$type]['type'], strrpos($this->simpleTypes[$type]['type'], ':') + 1); - $ns = substr($this->simpleTypes[$type]['type'], 0, strrpos($this->simpleTypes[$type]['type'], ':')); - $etype = $this->getTypeDef($uqType); - if ($etype) { - $this->xdebug("in getTypeDef, found type for simpleType $type:"); - $this->xdebug($this->varDump($etype)); - if (isset($etype['phpType'])) { - $this->simpleTypes[$type]['phpType'] = $etype['phpType']; - } - if (isset($etype['elements'])) { - $this->simpleTypes[$type]['elements'] = $etype['elements']; - } - } - } - - return $this->simpleTypes[$type]; - } elseif (isset($this->elements[$type])) { - $this->xdebug("in getTypeDef, found element $type"); - if (!isset($this->elements[$type]['phpType'])) { - // get info for type to tack onto the element - $uqType = substr($this->elements[$type]['type'], strrpos($this->elements[$type]['type'], ':') + 1); - $ns = substr($this->elements[$type]['type'], 0, strrpos($this->elements[$type]['type'], ':')); - $etype = $this->getTypeDef($uqType); - if ($etype) { - $this->xdebug("in getTypeDef, found type for element $type:"); - $this->xdebug($this->varDump($etype)); - if (isset($etype['phpType'])) { - $this->elements[$type]['phpType'] = $etype['phpType']; - } - if (isset($etype['elements'])) { - $this->elements[$type]['elements'] = $etype['elements']; - } - if (isset($etype['extensionBase'])) { - $this->elements[$type]['extensionBase'] = $etype['extensionBase']; - } - } elseif ($ns == 'http://www.w3.org/2001/XMLSchema') { - $this->xdebug("in getTypeDef, element $type is an XSD type"); - $this->elements[$type]['phpType'] = 'scalar'; - } - } - - return $this->elements[$type]; - } elseif (isset($this->attributes[$type])) { - $this->xdebug("in getTypeDef, found attribute $type"); - - return $this->attributes[$type]; - } elseif (preg_match('/_ContainedType$/', $type)) { - $this->xdebug("in getTypeDef, have an untyped element $type"); - $typeDef['typeClass'] = 'simpleType'; - $typeDef['phpType'] = 'scalar'; - $typeDef['type'] = 'http://www.w3.org/2001/XMLSchema:string'; - - return $typeDef; - } - $this->xdebug("in getTypeDef, did not find $type"); - - return false; - } - - /** - * returns a sample serialization of a given type, or false if no type by the given name. - * - * @param string $type name of type - * - * @return mixed - * - * @deprecated - */ - public function serializeTypeDef($type) - { - //print "in sTD() for type $type
"; - if ($typeDef = $this->getTypeDef($type)) { - $str .= '<'.$type; - if (is_array($typeDef['attrs'])) { - foreach ($typeDef['attrs'] as $attName => $data) { - $str .= " $attName=\"{type = ".$data['type'].'}"'; - } - } - $str .= ' xmlns="'.$this->schema['targetNamespace'].'"'; - if (count($typeDef['elements']) > 0) { - $str .= '>'; - foreach ($typeDef['elements'] as $element => $eData) { - $str .= $this->serializeTypeDef($element); - } - $str .= ""; - } elseif ($typeDef['typeClass'] == 'element') { - $str .= ">"; - } else { - $str .= '/>'; - } - - return $str; - } - - return false; - } - - /** - * returns HTML form elements that allow a user - * to enter values for creating an instance of the given type. - * - * @param string $name name for type instance - * @param string $type name of type - * - * @return string - * - * @deprecated - */ - public function typeToForm($name, $type) - { - // get typedef - if ($typeDef = $this->getTypeDef($type)) { - // if struct - if ($typeDef['phpType'] == 'struct') { - $buffer .= ''; - foreach ($typeDef['elements'] as $child => $childDef) { - $buffer .= " - - "; - } - $buffer .= '
$childDef[name] (type: ".$this->getLocalPart($childDef['type'])."):
'; - // if array - } elseif ($typeDef['phpType'] == 'array') { - $buffer .= ''; - for ($i = 0; $i < 3; $i++) { - $buffer .= " - - "; - } - $buffer .= '
array item (type: $typeDef[arrayType]):
'; - // if scalar - } else { - $buffer .= ""; - } - } else { - $buffer .= ""; - } - - return $buffer; - } - - /** - * adds a complex type to the schema. - * - * example: array - * - * addType( - * 'ArrayOfstring', - * 'complexType', - * 'array', - * '', - * 'SOAP-ENC:Array', - * array('ref'=>'SOAP-ENC:arrayType','wsdl:arrayType'=>'string[]'), - * 'xsd:string' - * ); - * - * example: PHP associative array ( SOAP Struct ) - * - * addType( - * 'SOAPStruct', - * 'complexType', - * 'struct', - * 'all', - * array('myVar'=> array('name'=>'myVar','type'=>'string') - * ); - * - * @param name - * @param typeClass (complexType|simpleType|attribute) - * @param phpType: currently supported are array and struct (php assoc array) - * @param compositor (all|sequence|choice) - * @param restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array) - * @param elements = array ( name = array(name=>'',type=>'') ) - * @param attrs = array( - * array( - * 'ref' => "http://schemas.xmlsoap.org/soap/encoding/:arrayType", - * "http://schemas.xmlsoap.org/wsdl/:arrayType" => "string[]" - * ) - * ) - * @param arrayType: namespace:name (http://www.w3.org/2001/XMLSchema:string) - * - * @see getTypeDef - */ - public function addComplexType($name, $typeClass = 'complexType', $phpType = 'array', $compositor = '', $restrictionBase = '', $elements = [], $attrs = [], $arrayType = '') - { - $this->complexTypes[$name] = [ - 'name' => $name, - 'typeClass' => $typeClass, - 'phpType' => $phpType, - 'compositor' => $compositor, - 'restrictionBase' => $restrictionBase, - 'elements' => $elements, - 'attrs' => $attrs, - 'arrayType' => $arrayType, - ]; - - $this->xdebug("addComplexType $name:"); - $this->appendDebug($this->varDump($this->complexTypes[$name])); - } - - /** - * adds a simple type to the schema. - * - * @param string $name - * @param string $restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array) - * @param string $typeClass (should always be simpleType) - * @param string $phpType (should always be scalar) - * @param array $enumeration array of values - * - * @see nusoap_xmlschema - * @see getTypeDef - */ - public function addSimpleType($name, $restrictionBase = '', $typeClass = 'simpleType', $phpType = 'scalar', $enumeration = []) - { - $this->simpleTypes[$name] = [ - 'name' => $name, - 'typeClass' => $typeClass, - 'phpType' => $phpType, - 'type' => $restrictionBase, - 'enumeration' => $enumeration, - ]; - - $this->xdebug("addSimpleType $name:"); - $this->appendDebug($this->varDump($this->simpleTypes[$name])); - } - - /** - * adds an element to the schema. - * - * @param array $attrs attributes that must include name and type - * - * @see nusoap_xmlschema - */ - public function addElement($attrs) - { - if (!$this->getPrefix($attrs['type'])) { - $attrs['type'] = $this->schemaTargetNamespace.':'.$attrs['type']; - } - $this->elements[$attrs['name']] = $attrs; - $this->elements[$attrs['name']]['typeClass'] = 'element'; - - $this->xdebug('addElement '.$attrs['name']); - $this->appendDebug($this->varDump($this->elements[$attrs['name']])); - } -} - -/** - * Backward compatibility. - */ -class XMLSchema extends nusoap_xmlschema -{ -} diff --git a/src/Drivers/lib/nusoap.php b/src/Drivers/lib/nusoap.php deleted file mode 100644 index 70b3b51..0000000 --- a/src/Drivers/lib/nusoap.php +++ /dev/null @@ -1,8148 +0,0 @@ - -* @author Scott Nichol -* @version $Id: nusoap.php,v 1.123 2010/04/26 20:15:08 snichol Exp $ -* @access public -*/ -class nusoap_base { - /** - * Identification for HTTP headers. - * - * @var string - * @access private - */ - var $title = 'NuSOAP'; - /** - * Version for HTTP headers. - * - * @var string - * @access private - */ - var $version = '0.9.5'; - /** - * CVS revision for HTTP headers. - * - * @var string - * @access private - */ - var $revision = '$Revision: 1.123 $'; - /** - * Current error string (manipulated by getError/setError) - * - * @var string - * @access private - */ - var $error_str = ''; - /** - * Current debug string (manipulated by debug/appendDebug/clearDebug/getDebug/getDebugAsXMLComment) - * - * @var string - * @access private - */ - var $debug_str = ''; - /** - * toggles automatic encoding of special characters as entities - * (should always be true, I think) - * - * @var boolean - * @access private - */ - var $charencoding = true; - /** - * the debug level for this instance - * - * @var integer - * @access private - */ - var $debugLevel; - - /** - * set schema version - * - * @var string - * @access public - */ - var $XMLSchemaVersion = 'http://www.w3.org/2001/XMLSchema'; - - /** - * charset encoding for outgoing messages - * - * @var string - * @access public - */ - // var $soap_defencoding = 'ISO-8859-1'; - var $soap_defencoding = 'UTF-8'; - - /** - * namespaces in an array of prefix => uri - * - * this is "seeded" by a set of constants, but it may be altered by code - * - * @var array - * @access public - */ - var $namespaces = array( - 'SOAP-ENV' => 'http://schemas.xmlsoap.org/soap/envelope/', - 'xsd' => 'http://www.w3.org/2001/XMLSchema', - 'xsi' => 'http://www.w3.org/2001/XMLSchema-instance', - 'SOAP-ENC' => 'http://schemas.xmlsoap.org/soap/encoding/' - ); - - /** - * namespaces used in the current context, e.g. during serialization - * - * @var array - * @access private - */ - var $usedNamespaces = array(); - - /** - * XML Schema types in an array of uri => (array of xml type => php type) - * is this legacy yet? - * no, this is used by the nusoap_xmlschema class to verify type => namespace mappings. - * @var array - * @access public - */ - var $typemap = array( - 'http://www.w3.org/2001/XMLSchema' => array( - 'string'=>'string','boolean'=>'boolean','float'=>'double','double'=>'double','decimal'=>'double', - 'duration'=>'','dateTime'=>'string','time'=>'string','date'=>'string','gYearMonth'=>'', - 'gYear'=>'','gMonthDay'=>'','gDay'=>'','gMonth'=>'','hexBinary'=>'string','base64Binary'=>'string', - // abstract "any" types - 'anyType'=>'string','anySimpleType'=>'string', - // derived datatypes - 'normalizedString'=>'string','token'=>'string','language'=>'','NMTOKEN'=>'','NMTOKENS'=>'','Name'=>'','NCName'=>'','ID'=>'', - 'IDREF'=>'','IDREFS'=>'','ENTITY'=>'','ENTITIES'=>'','integer'=>'integer','nonPositiveInteger'=>'integer', - 'negativeInteger'=>'integer','long'=>'integer','int'=>'integer','short'=>'integer','byte'=>'integer','nonNegativeInteger'=>'integer', - 'unsignedLong'=>'','unsignedInt'=>'','unsignedShort'=>'','unsignedByte'=>'','positiveInteger'=>''), - 'http://www.w3.org/2000/10/XMLSchema' => array( - 'i4'=>'','int'=>'integer','boolean'=>'boolean','string'=>'string','double'=>'double', - 'float'=>'double','dateTime'=>'string', - 'timeInstant'=>'string','base64Binary'=>'string','base64'=>'string','ur-type'=>'array'), - 'http://www.w3.org/1999/XMLSchema' => array( - 'i4'=>'','int'=>'integer','boolean'=>'boolean','string'=>'string','double'=>'double', - 'float'=>'double','dateTime'=>'string', - 'timeInstant'=>'string','base64Binary'=>'string','base64'=>'string','ur-type'=>'array'), - 'http://soapinterop.org/xsd' => array('SOAPStruct'=>'struct'), - 'http://schemas.xmlsoap.org/soap/encoding/' => array('base64'=>'string','array'=>'array','Array'=>'array'), - 'http://xml.apache.org/xml-soap' => array('Map') - ); - - /** - * XML entities to convert - * - * @var array - * @access public - * @deprecated - * @see expandEntities - */ - var $xmlEntities = array('quot' => '"','amp' => '&', - 'lt' => '<','gt' => '>','apos' => "'"); - - /** - * constructor - * - * @access public - */ - function nusoap_base() { - $this->debugLevel = $GLOBALS['_transient']['static']['nusoap_base']['globalDebugLevel']; - } - - /** - * gets the global debug level, which applies to future instances - * - * @return integer Debug level 0-9, where 0 turns off - * @access public - */ - function getGlobalDebugLevel() { - return $GLOBALS['_transient']['static']['nusoap_base']['globalDebugLevel']; - } - - /** - * sets the global debug level, which applies to future instances - * - * @param int $level Debug level 0-9, where 0 turns off - * @access public - */ - function setGlobalDebugLevel($level) { - $GLOBALS['_transient']['static']['nusoap_base']['globalDebugLevel'] = $level; - } - - /** - * gets the debug level for this instance - * - * @return int Debug level 0-9, where 0 turns off - * @access public - */ - function getDebugLevel() { - return $this->debugLevel; - } - - /** - * sets the debug level for this instance - * - * @param int $level Debug level 0-9, where 0 turns off - * @access public - */ - function setDebugLevel($level) { - $this->debugLevel = $level; - } - - /** - * adds debug data to the instance debug string with formatting - * - * @param string $string debug data - * @access private - */ - function debug($string){ - if ($this->debugLevel > 0) { - $this->appendDebug($this->getmicrotime().' '.get_class($this).": $string\n"); - } - } - - /** - * adds debug data to the instance debug string without formatting - * - * @param string $string debug data - * @access public - */ - function appendDebug($string){ - if ($this->debugLevel > 0) { - // it would be nice to use a memory stream here to use - // memory more efficiently - $this->debug_str .= $string; - } - } - - /** - * clears the current debug data for this instance - * - * @access public - */ - function clearDebug() { - // it would be nice to use a memory stream here to use - // memory more efficiently - $this->debug_str = ''; - } - - /** - * gets the current debug data for this instance - * - * @return debug data - * @access public - */ - function &getDebug() { - // it would be nice to use a memory stream here to use - // memory more efficiently - return $this->debug_str; - } - - /** - * gets the current debug data for this instance as an XML comment - * this may change the contents of the debug data - * - * @return debug data as an XML comment - * @access public - */ - function &getDebugAsXMLComment() { - // it would be nice to use a memory stream here to use - // memory more efficiently - while (strpos($this->debug_str, '--')) { - $this->debug_str = str_replace('--', '- -', $this->debug_str); - } - $ret = ""; - return $ret; - } - - /** - * expands entities, e.g. changes '<' to '<'. - * - * @param string $val The string in which to expand entities. - * @access private - */ - function expandEntities($val) { - if ($this->charencoding) { - $val = str_replace('&', '&', $val); - $val = str_replace("'", ''', $val); - $val = str_replace('"', '"', $val); - $val = str_replace('<', '<', $val); - $val = str_replace('>', '>', $val); - } - return $val; - } - - /** - * returns error string if present - * - * @return mixed error string or false - * @access public - */ - function getError(){ - if($this->error_str != ''){ - return $this->error_str; - } - return false; - } - - /** - * sets error string - * - * @return boolean $string error string - * @access private - */ - function setError($str){ - $this->error_str = $str; - } - - /** - * detect if array is a simple array or a struct (associative array) - * - * @param mixed $val The PHP array - * @return string (arraySimple|arrayStruct) - * @access private - */ - function isArraySimpleOrStruct($val) { - $keyList = array_keys($val); - foreach ($keyList as $keyListValue) { - if (!is_int($keyListValue)) { - return 'arrayStruct'; - } - } - return 'arraySimple'; - } - - /** - * serializes PHP values in accordance w/ section 5. Type information is - * not serialized if $use == 'literal'. - * - * @param mixed $val The value to serialize - * @param string $name The name (local part) of the XML element - * @param string $type The XML schema type (local part) for the element - * @param string $name_ns The namespace for the name of the XML element - * @param string $type_ns The namespace for the type of the element - * @param array $attributes The attributes to serialize as name=>value pairs - * @param string $use The WSDL "use" (encoded|literal) - * @param boolean $soapval Whether this is called from soapval. - * @return string The serialized element, possibly with child elements - * @access public - */ - function serialize_val($val,$name=false,$type=false,$name_ns=false,$type_ns=false,$attributes=false,$use='encoded',$soapval=false) { - $this->debug("in serialize_val: name=$name, type=$type, name_ns=$name_ns, type_ns=$type_ns, use=$use, soapval=$soapval"); - $this->appendDebug('value=' . $this->varDump($val)); - $this->appendDebug('attributes=' . $this->varDump($attributes)); - - if (is_object($val) && get_class($val) == 'soapval' && (! $soapval)) { - $this->debug("serialize_val: serialize soapval"); - $xml = $val->serialize($use); - $this->appendDebug($val->getDebug()); - $val->clearDebug(); - $this->debug("serialize_val of soapval returning $xml"); - return $xml; - } - // force valid name if necessary - if (is_numeric($name)) { - $name = '__numeric_' . $name; - } elseif (! $name) { - $name = 'noname'; - } - // if name has ns, add ns prefix to name - $xmlns = ''; - if($name_ns){ - $prefix = 'nu'.rand(1000,9999); - $name = $prefix.':'.$name; - $xmlns .= " xmlns:$prefix=\"$name_ns\""; - } - // if type is prefixed, create type prefix - if($type_ns != '' && $type_ns == $this->namespaces['xsd']){ - // need to fix this. shouldn't default to xsd if no ns specified - // w/o checking against typemap - $type_prefix = 'xsd'; - } elseif($type_ns){ - $type_prefix = 'ns'.rand(1000,9999); - $xmlns .= " xmlns:$type_prefix=\"$type_ns\""; - } - // serialize attributes if present - $atts = ''; - if($attributes){ - foreach($attributes as $k => $v){ - $atts .= " $k=\"".$this->expandEntities($v).'"'; - } - } - // serialize null value - if (is_null($val)) { - $this->debug("serialize_val: serialize null"); - if ($use == 'literal') { - // TODO: depends on minOccurs - $xml = "<$name$xmlns$atts/>"; - $this->debug("serialize_val returning $xml"); - return $xml; - } else { - if (isset($type) && isset($type_prefix)) { - $type_str = " xsi:type=\"$type_prefix:$type\""; - } else { - $type_str = ''; - } - $xml = "<$name$xmlns$type_str$atts xsi:nil=\"true\"/>"; - $this->debug("serialize_val returning $xml"); - return $xml; - } - } - // serialize if an xsd built-in primitive type - if($type != '' && isset($this->typemap[$this->XMLSchemaVersion][$type])){ - $this->debug("serialize_val: serialize xsd built-in primitive type"); - if (is_bool($val)) { - if ($type == 'boolean') { - $val = $val ? 'true' : 'false'; - } elseif (! $val) { - $val = 0; - } - } else if (is_string($val)) { - $val = $this->expandEntities($val); - } - if ($use == 'literal') { - $xml = "<$name$xmlns$atts>$val"; - $this->debug("serialize_val returning $xml"); - return $xml; - } else { - $xml = "<$name$xmlns xsi:type=\"xsd:$type\"$atts>$val"; - $this->debug("serialize_val returning $xml"); - return $xml; - } - } - // detect type and serialize - $xml = ''; - switch(true) { - case (is_bool($val) || $type == 'boolean'): - $this->debug("serialize_val: serialize boolean"); - if ($type == 'boolean') { - $val = $val ? 'true' : 'false'; - } elseif (! $val) { - $val = 0; - } - if ($use == 'literal') { - $xml .= "<$name$xmlns$atts>$val"; - } else { - $xml .= "<$name$xmlns xsi:type=\"xsd:boolean\"$atts>$val"; - } - break; - case (is_int($val) || is_long($val) || $type == 'int'): - $this->debug("serialize_val: serialize int"); - if ($use == 'literal') { - $xml .= "<$name$xmlns$atts>$val"; - } else { - $xml .= "<$name$xmlns xsi:type=\"xsd:int\"$atts>$val"; - } - break; - case (is_float($val)|| is_double($val) || $type == 'float'): - $this->debug("serialize_val: serialize float"); - if ($use == 'literal') { - $xml .= "<$name$xmlns$atts>$val"; - } else { - $xml .= "<$name$xmlns xsi:type=\"xsd:float\"$atts>$val"; - } - break; - case (is_string($val) || $type == 'string'): - $this->debug("serialize_val: serialize string"); - $val = $this->expandEntities($val); - if ($use == 'literal') { - $xml .= "<$name$xmlns$atts>$val"; - } else { - $xml .= "<$name$xmlns xsi:type=\"xsd:string\"$atts>$val"; - } - break; - case is_object($val): - $this->debug("serialize_val: serialize object"); - if (get_class($val) == 'soapval') { - $this->debug("serialize_val: serialize soapval object"); - $pXml = $val->serialize($use); - $this->appendDebug($val->getDebug()); - $val->clearDebug(); - } else { - if (! $name) { - $name = get_class($val); - $this->debug("In serialize_val, used class name $name as element name"); - } else { - $this->debug("In serialize_val, do not override name $name for element name for class " . get_class($val)); - } - foreach(get_object_vars($val) as $k => $v){ - $pXml = isset($pXml) ? $pXml.$this->serialize_val($v,$k,false,false,false,false,$use) : $this->serialize_val($v,$k,false,false,false,false,$use); - } - } - if(isset($type) && isset($type_prefix)){ - $type_str = " xsi:type=\"$type_prefix:$type\""; - } else { - $type_str = ''; - } - if ($use == 'literal') { - $xml .= "<$name$xmlns$atts>$pXml"; - } else { - $xml .= "<$name$xmlns$type_str$atts>$pXml"; - } - break; - break; - case (is_array($val) || $type): - // detect if struct or array - $valueType = $this->isArraySimpleOrStruct($val); - if($valueType=='arraySimple' || preg_match('/^ArrayOf/',$type)){ - $this->debug("serialize_val: serialize array"); - $i = 0; - if(is_array($val) && count($val)> 0){ - foreach($val as $v){ - if(is_object($v) && get_class($v) == 'soapval'){ - $tt_ns = $v->type_ns; - $tt = $v->type; - } elseif (is_array($v)) { - $tt = $this->isArraySimpleOrStruct($v); - } else { - $tt = gettype($v); - } - $array_types[$tt] = 1; - // TODO: for literal, the name should be $name - $xml .= $this->serialize_val($v,'item',false,false,false,false,$use); - ++$i; - } - if(count($array_types) > 1){ - $array_typename = 'xsd:anyType'; - } elseif(isset($tt) && isset($this->typemap[$this->XMLSchemaVersion][$tt])) { - if ($tt == 'integer') { - $tt = 'int'; - } - $array_typename = 'xsd:'.$tt; - } elseif(isset($tt) && $tt == 'arraySimple'){ - $array_typename = 'SOAP-ENC:Array'; - } elseif(isset($tt) && $tt == 'arrayStruct'){ - $array_typename = 'unnamed_struct_use_soapval'; - } else { - // if type is prefixed, create type prefix - if ($tt_ns != '' && $tt_ns == $this->namespaces['xsd']){ - $array_typename = 'xsd:' . $tt; - } elseif ($tt_ns) { - $tt_prefix = 'ns' . rand(1000, 9999); - $array_typename = "$tt_prefix:$tt"; - $xmlns .= " xmlns:$tt_prefix=\"$tt_ns\""; - } else { - $array_typename = $tt; - } - } - $array_type = $i; - if ($use == 'literal') { - $type_str = ''; - } else if (isset($type) && isset($type_prefix)) { - $type_str = " xsi:type=\"$type_prefix:$type\""; - } else { - $type_str = " xsi:type=\"SOAP-ENC:Array\" SOAP-ENC:arrayType=\"".$array_typename."[$array_type]\""; - } - // empty array - } else { - if ($use == 'literal') { - $type_str = ''; - } else if (isset($type) && isset($type_prefix)) { - $type_str = " xsi:type=\"$type_prefix:$type\""; - } else { - $type_str = " xsi:type=\"SOAP-ENC:Array\" SOAP-ENC:arrayType=\"xsd:anyType[0]\""; - } - } - // TODO: for array in literal, there is no wrapper here - $xml = "<$name$xmlns$type_str$atts>".$xml.""; - } else { - // got a struct - $this->debug("serialize_val: serialize struct"); - if(isset($type) && isset($type_prefix)){ - $type_str = " xsi:type=\"$type_prefix:$type\""; - } else { - $type_str = ''; - } - if ($use == 'literal') { - $xml .= "<$name$xmlns$atts>"; - } else { - $xml .= "<$name$xmlns$type_str$atts>"; - } - foreach($val as $k => $v){ - // Apache Map - if ($type == 'Map' && $type_ns == 'http://xml.apache.org/xml-soap') { - $xml .= ''; - $xml .= $this->serialize_val($k,'key',false,false,false,false,$use); - $xml .= $this->serialize_val($v,'value',false,false,false,false,$use); - $xml .= ''; - } else { - $xml .= $this->serialize_val($v,$k,false,false,false,false,$use); - } - } - $xml .= ""; - } - break; - default: - $this->debug("serialize_val: serialize unknown"); - $xml .= 'not detected, got '.gettype($val).' for '.$val; - break; - } - $this->debug("serialize_val returning $xml"); - return $xml; - } - - /** - * serializes a message - * - * @param string $body the XML of the SOAP body - * @param mixed $headers optional string of XML with SOAP header content, or array of soapval objects for SOAP headers, or associative array - * @param array $namespaces optional the namespaces used in generating the body and headers - * @param string $style optional (rpc|document) - * @param string $use optional (encoded|literal) - * @param string $encodingStyle optional (usually 'http://schemas.xmlsoap.org/soap/encoding/' for encoded) - * @return string the message - * @access public - */ - function serializeEnvelope($body,$headers=false,$namespaces=array(),$style='rpc',$use='encoded',$encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'){ - // TODO: add an option to automatically run utf8_encode on $body and $headers - // if $this->soap_defencoding is UTF-8. Not doing this automatically allows - // one to send arbitrary UTF-8 characters, not just characters that map to ISO-8859-1 - - $this->debug("In serializeEnvelope length=" . strlen($body) . " body (max 1000 characters)=" . substr($body, 0, 1000) . " style=$style use=$use encodingStyle=$encodingStyle"); - $this->debug("headers:"); - $this->appendDebug($this->varDump($headers)); - $this->debug("namespaces:"); - $this->appendDebug($this->varDump($namespaces)); - - // serialize namespaces - $ns_string = ''; - foreach(array_merge($this->namespaces,$namespaces) as $k => $v){ - $ns_string .= " xmlns:$k=\"$v\""; - } - if($encodingStyle) { - $ns_string = " SOAP-ENV:encodingStyle=\"$encodingStyle\"$ns_string"; - } - - // serialize headers - if($headers){ - if (is_array($headers)) { - $xml = ''; - foreach ($headers as $k => $v) { - if (is_object($v) && get_class($v) == 'soapval') { - $xml .= $this->serialize_val($v, false, false, false, false, false, $use); - } else { - $xml .= $this->serialize_val($v, $k, false, false, false, false, $use); - } - } - $headers = $xml; - $this->debug("In serializeEnvelope, serialized array of headers to $headers"); - } - $headers = "".$headers.""; - } - // serialize envelope - return - 'soap_defencoding .'"?'.">". - '". - $headers. - "". - $body. - "". - ""; - } - - /** - * formats a string to be inserted into an HTML stream - * - * @param string $str The string to format - * @return string The formatted string - * @access public - * @deprecated - */ - function formatDump($str){ - $str = htmlspecialchars($str); - return nl2br($str); - } - - /** - * contracts (changes namespace to prefix) a qualified name - * - * @param string $qname qname - * @return string contracted qname - * @access private - */ - function contractQname($qname){ - // get element namespace - //$this->xdebug("Contract $qname"); - if (strrpos($qname, ':')) { - // get unqualified name - $name = substr($qname, strrpos($qname, ':') + 1); - // get ns - $ns = substr($qname, 0, strrpos($qname, ':')); - $p = $this->getPrefixFromNamespace($ns); - if ($p) { - return $p . ':' . $name; - } - return $qname; - } else { - return $qname; - } - } - - /** - * expands (changes prefix to namespace) a qualified name - * - * @param string $qname qname - * @return string expanded qname - * @access private - */ - function expandQname($qname){ - // get element prefix - if(strpos($qname,':') && !preg_match('/^http:\/\//',$qname)){ - // get unqualified name - $name = substr(strstr($qname,':'),1); - // get ns prefix - $prefix = substr($qname,0,strpos($qname,':')); - if(isset($this->namespaces[$prefix])){ - return $this->namespaces[$prefix].':'.$name; - } else { - return $qname; - } - } else { - return $qname; - } - } - - /** - * returns the local part of a prefixed string - * returns the original string, if not prefixed - * - * @param string $str The prefixed string - * @return string The local part - * @access public - */ - function getLocalPart($str){ - if($sstr = strrchr($str,':')){ - // get unqualified name - return substr( $sstr, 1 ); - } else { - return $str; - } - } - - /** - * returns the prefix part of a prefixed string - * returns false, if not prefixed - * - * @param string $str The prefixed string - * @return mixed The prefix or false if there is no prefix - * @access public - */ - function getPrefix($str){ - if($pos = strrpos($str,':')){ - // get prefix - return substr($str,0,$pos); - } - return false; - } - - /** - * pass it a prefix, it returns a namespace - * - * @param string $prefix The prefix - * @return mixed The namespace, false if no namespace has the specified prefix - * @access public - */ - function getNamespaceFromPrefix($prefix){ - if (isset($this->namespaces[$prefix])) { - return $this->namespaces[$prefix]; - } - //$this->setError("No namespace registered for prefix '$prefix'"); - return false; - } - - /** - * returns the prefix for a given namespace (or prefix) - * or false if no prefixes registered for the given namespace - * - * @param string $ns The namespace - * @return mixed The prefix, false if the namespace has no prefixes - * @access public - */ - function getPrefixFromNamespace($ns) { - foreach ($this->namespaces as $p => $n) { - if ($ns == $n || $ns == $p) { - $this->usedNamespaces[$p] = $n; - return $p; - } - } - return false; - } - - /** - * returns the time in ODBC canonical form with microseconds - * - * @return string The time in ODBC canonical form with microseconds - * @access public - */ - function getmicrotime() { - if (function_exists('gettimeofday')) { - $tod = gettimeofday(); - $sec = $tod['sec']; - $usec = $tod['usec']; - } else { - $sec = time(); - $usec = 0; - } - return strftime('%Y-%m-%d %H:%M:%S', $sec) . '.' . sprintf('%06d', $usec); - } - - /** - * Returns a string with the output of var_dump - * - * @param mixed $data The variable to var_dump - * @return string The output of var_dump - * @access public - */ - function varDump($data) { - ob_start(); - var_dump($data); - $ret_val = ob_get_contents(); - ob_end_clean(); - return $ret_val; - } - - /** - * represents the object as a string - * - * @return string - * @access public - */ - function __toString() { - return $this->varDump($this); - } -} - -// XML Schema Datatype Helper Functions - -//xsd:dateTime helpers - -/** -* convert unix timestamp to ISO 8601 compliant date string -* -* @param int $timestamp Unix time stamp -* @param boolean $utc Whether the time stamp is UTC or local -* @return mixed ISO 8601 date string or false -* @access public -*/ -function timestamp_to_iso8601($timestamp,$utc=true){ - $datestr = date('Y-m-d\TH:i:sO',$timestamp); - $pos = strrpos($datestr, "+"); - if ($pos === FALSE) { - $pos = strrpos($datestr, "-"); - } - if ($pos !== FALSE) { - if (strlen($datestr) == $pos + 5) { - $datestr = substr($datestr, 0, $pos + 3) . ':' . substr($datestr, -2); - } - } - if($utc){ - $pattern = '/'. - '([0-9]{4})-'. // centuries & years CCYY- - '([0-9]{2})-'. // months MM- - '([0-9]{2})'. // days DD - 'T'. // separator T - '([0-9]{2}):'. // hours hh: - '([0-9]{2}):'. // minutes mm: - '([0-9]{2})(\.[0-9]*)?'. // seconds ss.ss... - '(Z|[+\-][0-9]{2}:?[0-9]{2})?'. // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's - '/'; - - if(preg_match($pattern,$datestr,$regs)){ - return sprintf('%04d-%02d-%02dT%02d:%02d:%02dZ',$regs[1],$regs[2],$regs[3],$regs[4],$regs[5],$regs[6]); - } - return false; - } else { - return $datestr; - } -} - -/** -* convert ISO 8601 compliant date string to unix timestamp -* -* @param string $datestr ISO 8601 compliant date string -* @return mixed Unix timestamp (int) or false -* @access public -*/ -function iso8601_to_timestamp($datestr){ - $pattern = '/'. - '([0-9]{4})-'. // centuries & years CCYY- - '([0-9]{2})-'. // months MM- - '([0-9]{2})'. // days DD - 'T'. // separator T - '([0-9]{2}):'. // hours hh: - '([0-9]{2}):'. // minutes mm: - '([0-9]{2})(\.[0-9]+)?'. // seconds ss.ss... - '(Z|[+\-][0-9]{2}:?[0-9]{2})?'. // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's - '/'; - if(preg_match($pattern,$datestr,$regs)){ - // not utc - if($regs[8] != 'Z'){ - $op = substr($regs[8],0,1); - $h = substr($regs[8],1,2); - $m = substr($regs[8],strlen($regs[8])-2,2); - if($op == '-'){ - $regs[4] = $regs[4] + $h; - $regs[5] = $regs[5] + $m; - } elseif($op == '+'){ - $regs[4] = $regs[4] - $h; - $regs[5] = $regs[5] - $m; - } - } - return gmmktime($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]); -// return strtotime("$regs[1]-$regs[2]-$regs[3] $regs[4]:$regs[5]:$regs[6]Z"); - } else { - return false; - } -} - -/** -* sleeps some number of microseconds -* -* @param string $usec the number of microseconds to sleep -* @access public -* @deprecated -*/ -function usleepWindows($usec) -{ - $start = gettimeofday(); - - do - { - $stop = gettimeofday(); - $timePassed = 1000000 * ($stop['sec'] - $start['sec']) - + $stop['usec'] - $start['usec']; - } - while ($timePassed < $usec); -} - -?> -* @version $Id: nusoap.php,v 1.123 2010/04/26 20:15:08 snichol Exp $ -* @access public -*/ -class nusoap_fault extends nusoap_base { - /** - * The fault code (client|server) - * @var string - * @access private - */ - var $faultcode; - /** - * The fault actor - * @var string - * @access private - */ - var $faultactor; - /** - * The fault string, a description of the fault - * @var string - * @access private - */ - var $faultstring; - /** - * The fault detail, typically a string or array of string - * @var mixed - * @access private - */ - var $faultdetail; - - /** - * constructor - * - * @param string $faultcode (SOAP-ENV:Client | SOAP-ENV:Server) - * @param string $faultactor only used when msg routed between multiple actors - * @param string $faultstring human readable error message - * @param mixed $faultdetail detail, typically a string or array of string - */ - function nusoap_fault($faultcode,$faultactor='',$faultstring='',$faultdetail=''){ - parent::nusoap_base(); - $this->faultcode = $faultcode; - $this->faultactor = $faultactor; - $this->faultstring = $faultstring; - $this->faultdetail = $faultdetail; - } - - /** - * serialize a fault - * - * @return string The serialization of the fault instance. - * @access public - */ - function serialize(){ - $ns_string = ''; - foreach($this->namespaces as $k => $v){ - $ns_string .= "\n xmlns:$k=\"$v\""; - } - $return_msg = - 'soap_defencoding.'"?>'. - '\n". - ''. - ''. - $this->serialize_val($this->faultcode, 'faultcode'). - $this->serialize_val($this->faultactor, 'faultactor'). - $this->serialize_val($this->faultstring, 'faultstring'). - $this->serialize_val($this->faultdetail, 'detail'). - ''. - ''. - ''; - return $return_msg; - } -} - -/** - * Backward compatibility - */ -class soap_fault extends nusoap_fault { -} - -?> -* @author Scott Nichol -* @version $Id: nusoap.php,v 1.123 2010/04/26 20:15:08 snichol Exp $ -* @access public -*/ -class nusoap_xmlschema extends nusoap_base { - - // files - var $schema = ''; - var $xml = ''; - // namespaces - var $enclosingNamespaces; - // schema info - var $schemaInfo = array(); - var $schemaTargetNamespace = ''; - // types, elements, attributes defined by the schema - var $attributes = array(); - var $complexTypes = array(); - var $complexTypeStack = array(); - var $currentComplexType = null; - var $elements = array(); - var $elementStack = array(); - var $currentElement = null; - var $simpleTypes = array(); - var $simpleTypeStack = array(); - var $currentSimpleType = null; - // imports - var $imports = array(); - // parser vars - var $parser; - var $position = 0; - var $depth = 0; - var $depth_array = array(); - var $message = array(); - var $defaultNamespace = array(); - - /** - * constructor - * - * @param string $schema schema document URI - * @param string $xml xml document URI - * @param string $namespaces namespaces defined in enclosing XML - * @access public - */ - function nusoap_xmlschema($schema='',$xml='',$namespaces=array()){ - parent::nusoap_base(); - $this->debug('nusoap_xmlschema class instantiated, inside constructor'); - // files - $this->schema = $schema; - $this->xml = $xml; - - // namespaces - $this->enclosingNamespaces = $namespaces; - $this->namespaces = array_merge($this->namespaces, $namespaces); - - // parse schema file - if($schema != ''){ - $this->debug('initial schema file: '.$schema); - $this->parseFile($schema, 'schema'); - } - - // parse xml file - if($xml != ''){ - $this->debug('initial xml file: '.$xml); - $this->parseFile($xml, 'xml'); - } - - } - - /** - * parse an XML file - * - * @param string $xml path/URL to XML file - * @param string $type (schema | xml) - * @return boolean - * @access public - */ - function parseFile($xml,$type){ - // parse xml file - if($xml != ""){ - $xmlStr = @join("",@file($xml)); - if($xmlStr == ""){ - $msg = 'Error reading XML from '.$xml; - $this->setError($msg); - $this->debug($msg); - return false; - } else { - $this->debug("parsing $xml"); - $this->parseString($xmlStr,$type); - $this->debug("done parsing $xml"); - return true; - } - } - return false; - } - - /** - * parse an XML string - * - * @param string $xml path or URL - * @param string $type (schema|xml) - * @access private - */ - function parseString($xml,$type){ - // parse xml string - if($xml != ""){ - - // Create an XML parser. - $this->parser = xml_parser_create(); - // Set the options for parsing the XML data. - xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0); - - // Set the object for the parser. - xml_set_object($this->parser, $this); - - // Set the element handlers for the parser. - if($type == "schema"){ - xml_set_element_handler($this->parser, 'schemaStartElement','schemaEndElement'); - xml_set_character_data_handler($this->parser,'schemaCharacterData'); - } elseif($type == "xml"){ - xml_set_element_handler($this->parser, 'xmlStartElement','xmlEndElement'); - xml_set_character_data_handler($this->parser,'xmlCharacterData'); - } - - // Parse the XML file. - if(!xml_parse($this->parser,$xml,true)){ - // Display an error message. - $errstr = sprintf('XML error parsing XML schema on line %d: %s', - xml_get_current_line_number($this->parser), - xml_error_string(xml_get_error_code($this->parser)) - ); - $this->debug($errstr); - $this->debug("XML payload:\n" . $xml); - $this->setError($errstr); - } - - xml_parser_free($this->parser); - } else{ - $this->debug('no xml passed to parseString()!!'); - $this->setError('no xml passed to parseString()!!'); - } - } - - /** - * gets a type name for an unnamed type - * - * @param string Element name - * @return string A type name for an unnamed type - * @access private - */ - function CreateTypeName($ename) { - $scope = ''; - for ($i = 0; $i < count($this->complexTypeStack); $i++) { - $scope .= $this->complexTypeStack[$i] . '_'; - } - return $scope . $ename . '_ContainedType'; - } - - /** - * start-element handler - * - * @param string $parser XML parser object - * @param string $name element name - * @param string $attrs associative array of attributes - * @access private - */ - function schemaStartElement($parser, $name, $attrs) { - - // position in the total number of elements, starting from 0 - $pos = $this->position++; - $depth = $this->depth++; - // set self as current value for this depth - $this->depth_array[$depth] = $pos; - $this->message[$pos] = array('cdata' => ''); - if ($depth > 0) { - $this->defaultNamespace[$pos] = $this->defaultNamespace[$this->depth_array[$depth - 1]]; - } else { - $this->defaultNamespace[$pos] = false; - } - - // get element prefix - if($prefix = $this->getPrefix($name)){ - // get unqualified name - $name = $this->getLocalPart($name); - } else { - $prefix = ''; - } - - // loop thru attributes, expanding, and registering namespace declarations - if(count($attrs) > 0){ - foreach($attrs as $k => $v){ - // if ns declarations, add to class level array of valid namespaces - if(preg_match('/^xmlns/',$k)){ - //$this->xdebug("$k: $v"); - //$this->xdebug('ns_prefix: '.$this->getPrefix($k)); - if($ns_prefix = substr(strrchr($k,':'),1)){ - //$this->xdebug("Add namespace[$ns_prefix] = $v"); - $this->namespaces[$ns_prefix] = $v; - } else { - $this->defaultNamespace[$pos] = $v; - if (! $this->getPrefixFromNamespace($v)) { - $this->namespaces['ns'.(count($this->namespaces)+1)] = $v; - } - } - if($v == 'http://www.w3.org/2001/XMLSchema' || $v == 'http://www.w3.org/1999/XMLSchema' || $v == 'http://www.w3.org/2000/10/XMLSchema'){ - $this->XMLSchemaVersion = $v; - $this->namespaces['xsi'] = $v.'-instance'; - } - } - } - foreach($attrs as $k => $v){ - // expand each attribute - $k = strpos($k,':') ? $this->expandQname($k) : $k; - $v = strpos($v,':') ? $this->expandQname($v) : $v; - $eAttrs[$k] = $v; - } - $attrs = $eAttrs; - } else { - $attrs = array(); - } - // find status, register data - switch($name){ - case 'all': // (optional) compositor content for a complexType - case 'choice': - case 'group': - case 'sequence': - //$this->xdebug("compositor $name for currentComplexType: $this->currentComplexType and currentElement: $this->currentElement"); - $this->complexTypes[$this->currentComplexType]['compositor'] = $name; - //if($name == 'all' || $name == 'sequence'){ - // $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct'; - //} - break; - case 'attribute': // complexType attribute - //$this->xdebug("parsing attribute $attrs[name] $attrs[ref] of value: ".$attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']); - $this->xdebug("parsing attribute:"); - $this->appendDebug($this->varDump($attrs)); - if (!isset($attrs['form'])) { - // TODO: handle globals - $attrs['form'] = $this->schemaInfo['attributeFormDefault']; - } - if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])) { - $v = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']; - if (!strpos($v, ':')) { - // no namespace in arrayType attribute value... - if ($this->defaultNamespace[$pos]) { - // ...so use the default - $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'] = $this->defaultNamespace[$pos] . ':' . $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']; - } - } - } - if(isset($attrs['name'])){ - $this->attributes[$attrs['name']] = $attrs; - $aname = $attrs['name']; - } elseif(isset($attrs['ref']) && $attrs['ref'] == 'http://schemas.xmlsoap.org/soap/encoding/:arrayType'){ - if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])) { - $aname = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']; - } else { - $aname = ''; - } - } elseif(isset($attrs['ref'])){ - $aname = $attrs['ref']; - $this->attributes[$attrs['ref']] = $attrs; - } - - if($this->currentComplexType){ // This should *always* be - $this->complexTypes[$this->currentComplexType]['attrs'][$aname] = $attrs; - } - // arrayType attribute - if(isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']) || $this->getLocalPart($aname) == 'arrayType'){ - $this->complexTypes[$this->currentComplexType]['phpType'] = 'array'; - $prefix = $this->getPrefix($aname); - if(isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])){ - $v = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']; - } else { - $v = ''; - } - if(strpos($v,'[,]')){ - $this->complexTypes[$this->currentComplexType]['multidimensional'] = true; - } - $v = substr($v,0,strpos($v,'[')); // clip the [] - if(!strpos($v,':') && isset($this->typemap[$this->XMLSchemaVersion][$v])){ - $v = $this->XMLSchemaVersion.':'.$v; - } - $this->complexTypes[$this->currentComplexType]['arrayType'] = $v; - } - break; - case 'complexContent': // (optional) content for a complexType - $this->xdebug("do nothing for element $name"); - break; - case 'complexType': - array_push($this->complexTypeStack, $this->currentComplexType); - if(isset($attrs['name'])){ - // TODO: what is the scope of named complexTypes that appear - // nested within other c complexTypes? - $this->xdebug('processing named complexType '.$attrs['name']); - //$this->currentElement = false; - $this->currentComplexType = $attrs['name']; - $this->complexTypes[$this->currentComplexType] = $attrs; - $this->complexTypes[$this->currentComplexType]['typeClass'] = 'complexType'; - // This is for constructs like - // - // - // - // - // - if(isset($attrs['base']) && preg_match('/:Array$/',$attrs['base'])){ - $this->xdebug('complexType is unusual array'); - $this->complexTypes[$this->currentComplexType]['phpType'] = 'array'; - } else { - $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct'; - } - } else { - $name = $this->CreateTypeName($this->currentElement); - $this->xdebug('processing unnamed complexType for element ' . $this->currentElement . ' named ' . $name); - $this->currentComplexType = $name; - //$this->currentElement = false; - $this->complexTypes[$this->currentComplexType] = $attrs; - $this->complexTypes[$this->currentComplexType]['typeClass'] = 'complexType'; - // This is for constructs like - // - // - // - // - // - if(isset($attrs['base']) && preg_match('/:Array$/',$attrs['base'])){ - $this->xdebug('complexType is unusual array'); - $this->complexTypes[$this->currentComplexType]['phpType'] = 'array'; - } else { - $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct'; - } - } - $this->complexTypes[$this->currentComplexType]['simpleContent'] = 'false'; - break; - case 'element': - array_push($this->elementStack, $this->currentElement); - if (!isset($attrs['form'])) { - if ($this->currentComplexType) { - $attrs['form'] = $this->schemaInfo['elementFormDefault']; - } else { - // global - $attrs['form'] = 'qualified'; - } - } - if(isset($attrs['type'])){ - $this->xdebug("processing typed element ".$attrs['name']." of type ".$attrs['type']); - if (! $this->getPrefix($attrs['type'])) { - if ($this->defaultNamespace[$pos]) { - $attrs['type'] = $this->defaultNamespace[$pos] . ':' . $attrs['type']; - $this->xdebug('used default namespace to make type ' . $attrs['type']); - } - } - // This is for constructs like - // - // - // - // - // - if ($this->currentComplexType && $this->complexTypes[$this->currentComplexType]['phpType'] == 'array') { - $this->xdebug('arrayType for unusual array is ' . $attrs['type']); - $this->complexTypes[$this->currentComplexType]['arrayType'] = $attrs['type']; - } - $this->currentElement = $attrs['name']; - $ename = $attrs['name']; - } elseif(isset($attrs['ref'])){ - $this->xdebug("processing element as ref to ".$attrs['ref']); - $this->currentElement = "ref to ".$attrs['ref']; - $ename = $this->getLocalPart($attrs['ref']); - } else { - $type = $this->CreateTypeName($this->currentComplexType . '_' . $attrs['name']); - $this->xdebug("processing untyped element " . $attrs['name'] . ' type ' . $type); - $this->currentElement = $attrs['name']; - $attrs['type'] = $this->schemaTargetNamespace . ':' . $type; - $ename = $attrs['name']; - } - if (isset($ename) && $this->currentComplexType) { - $this->xdebug("add element $ename to complexType $this->currentComplexType"); - $this->complexTypes[$this->currentComplexType]['elements'][$ename] = $attrs; - } elseif (!isset($attrs['ref'])) { - $this->xdebug("add element $ename to elements array"); - $this->elements[ $attrs['name'] ] = $attrs; - $this->elements[ $attrs['name'] ]['typeClass'] = 'element'; - } - break; - case 'enumeration': // restriction value list member - $this->xdebug('enumeration ' . $attrs['value']); - if ($this->currentSimpleType) { - $this->simpleTypes[$this->currentSimpleType]['enumeration'][] = $attrs['value']; - } elseif ($this->currentComplexType) { - $this->complexTypes[$this->currentComplexType]['enumeration'][] = $attrs['value']; - } - break; - case 'extension': // simpleContent or complexContent type extension - $this->xdebug('extension ' . $attrs['base']); - if ($this->currentComplexType) { - $ns = $this->getPrefix($attrs['base']); - if ($ns == '') { - $this->complexTypes[$this->currentComplexType]['extensionBase'] = $this->schemaTargetNamespace . ':' . $attrs['base']; - } else { - $this->complexTypes[$this->currentComplexType]['extensionBase'] = $attrs['base']; - } - } else { - $this->xdebug('no current complexType to set extensionBase'); - } - break; - case 'import': - if (isset($attrs['schemaLocation'])) { - $this->xdebug('import namespace ' . $attrs['namespace'] . ' from ' . $attrs['schemaLocation']); - $this->imports[$attrs['namespace']][] = array('location' => $attrs['schemaLocation'], 'loaded' => false); - } else { - $this->xdebug('import namespace ' . $attrs['namespace']); - $this->imports[$attrs['namespace']][] = array('location' => '', 'loaded' => true); - if (! $this->getPrefixFromNamespace($attrs['namespace'])) { - $this->namespaces['ns'.(count($this->namespaces)+1)] = $attrs['namespace']; - } - } - break; - case 'include': - if (isset($attrs['schemaLocation'])) { - $this->xdebug('include into namespace ' . $this->schemaTargetNamespace . ' from ' . $attrs['schemaLocation']); - $this->imports[$this->schemaTargetNamespace][] = array('location' => $attrs['schemaLocation'], 'loaded' => false); - } else { - $this->xdebug('ignoring invalid XML Schema construct: include without schemaLocation attribute'); - } - break; - case 'list': // simpleType value list - $this->xdebug("do nothing for element $name"); - break; - case 'restriction': // simpleType, simpleContent or complexContent value restriction - $this->xdebug('restriction ' . $attrs['base']); - if($this->currentSimpleType){ - $this->simpleTypes[$this->currentSimpleType]['type'] = $attrs['base']; - } elseif($this->currentComplexType){ - $this->complexTypes[$this->currentComplexType]['restrictionBase'] = $attrs['base']; - if(strstr($attrs['base'],':') == ':Array'){ - $this->complexTypes[$this->currentComplexType]['phpType'] = 'array'; - } - } - break; - case 'schema': - $this->schemaInfo = $attrs; - $this->schemaInfo['schemaVersion'] = $this->getNamespaceFromPrefix($prefix); - if (isset($attrs['targetNamespace'])) { - $this->schemaTargetNamespace = $attrs['targetNamespace']; - } - if (!isset($attrs['elementFormDefault'])) { - $this->schemaInfo['elementFormDefault'] = 'unqualified'; - } - if (!isset($attrs['attributeFormDefault'])) { - $this->schemaInfo['attributeFormDefault'] = 'unqualified'; - } - break; - case 'simpleContent': // (optional) content for a complexType - if ($this->currentComplexType) { // This should *always* be - $this->complexTypes[$this->currentComplexType]['simpleContent'] = 'true'; - } else { - $this->xdebug("do nothing for element $name because there is no current complexType"); - } - break; - case 'simpleType': - array_push($this->simpleTypeStack, $this->currentSimpleType); - if(isset($attrs['name'])){ - $this->xdebug("processing simpleType for name " . $attrs['name']); - $this->currentSimpleType = $attrs['name']; - $this->simpleTypes[ $attrs['name'] ] = $attrs; - $this->simpleTypes[ $attrs['name'] ]['typeClass'] = 'simpleType'; - $this->simpleTypes[ $attrs['name'] ]['phpType'] = 'scalar'; - } else { - $name = $this->CreateTypeName($this->currentComplexType . '_' . $this->currentElement); - $this->xdebug('processing unnamed simpleType for element ' . $this->currentElement . ' named ' . $name); - $this->currentSimpleType = $name; - //$this->currentElement = false; - $this->simpleTypes[$this->currentSimpleType] = $attrs; - $this->simpleTypes[$this->currentSimpleType]['phpType'] = 'scalar'; - } - break; - case 'union': // simpleType type list - $this->xdebug("do nothing for element $name"); - break; - default: - $this->xdebug("do not have any logic to process element $name"); - } - } - - /** - * end-element handler - * - * @param string $parser XML parser object - * @param string $name element name - * @access private - */ - function schemaEndElement($parser, $name) { - // bring depth down a notch - $this->depth--; - // position of current element is equal to the last value left in depth_array for my depth - if(isset($this->depth_array[$this->depth])){ - $pos = $this->depth_array[$this->depth]; - } - // get element prefix - if ($prefix = $this->getPrefix($name)){ - // get unqualified name - $name = $this->getLocalPart($name); - } else { - $prefix = ''; - } - // move on... - if($name == 'complexType'){ - $this->xdebug('done processing complexType ' . ($this->currentComplexType ? $this->currentComplexType : '(unknown)')); - $this->xdebug($this->varDump($this->complexTypes[$this->currentComplexType])); - $this->currentComplexType = array_pop($this->complexTypeStack); - //$this->currentElement = false; - } - if($name == 'element'){ - $this->xdebug('done processing element ' . ($this->currentElement ? $this->currentElement : '(unknown)')); - $this->currentElement = array_pop($this->elementStack); - } - if($name == 'simpleType'){ - $this->xdebug('done processing simpleType ' . ($this->currentSimpleType ? $this->currentSimpleType : '(unknown)')); - $this->xdebug($this->varDump($this->simpleTypes[$this->currentSimpleType])); - $this->currentSimpleType = array_pop($this->simpleTypeStack); - } - } - - /** - * element content handler - * - * @param string $parser XML parser object - * @param string $data element content - * @access private - */ - function schemaCharacterData($parser, $data){ - $pos = $this->depth_array[$this->depth - 1]; - $this->message[$pos]['cdata'] .= $data; - } - - /** - * serialize the schema - * - * @access public - */ - function serializeSchema(){ - - $schemaPrefix = $this->getPrefixFromNamespace($this->XMLSchemaVersion); - $xml = ''; - // imports - if (sizeof($this->imports) > 0) { - foreach($this->imports as $ns => $list) { - foreach ($list as $ii) { - if ($ii['location'] != '') { - $xml .= " <$schemaPrefix:import location=\"" . $ii['location'] . '" namespace="' . $ns . "\" />\n"; - } else { - $xml .= " <$schemaPrefix:import namespace=\"" . $ns . "\" />\n"; - } - } - } - } - // complex types - foreach($this->complexTypes as $typeName => $attrs){ - $contentStr = ''; - // serialize child elements - if(isset($attrs['elements']) && (count($attrs['elements']) > 0)){ - foreach($attrs['elements'] as $element => $eParts){ - if(isset($eParts['ref'])){ - $contentStr .= " <$schemaPrefix:element ref=\"$element\"/>\n"; - } else { - $contentStr .= " <$schemaPrefix:element name=\"$element\" type=\"" . $this->contractQName($eParts['type']) . "\""; - foreach ($eParts as $aName => $aValue) { - // handle, e.g., abstract, default, form, minOccurs, maxOccurs, nillable - if ($aName != 'name' && $aName != 'type') { - $contentStr .= " $aName=\"$aValue\""; - } - } - $contentStr .= "/>\n"; - } - } - // compositor wraps elements - if (isset($attrs['compositor']) && ($attrs['compositor'] != '')) { - $contentStr = " <$schemaPrefix:$attrs[compositor]>\n".$contentStr." \n"; - } - } - // attributes - if(isset($attrs['attrs']) && (count($attrs['attrs']) >= 1)){ - foreach($attrs['attrs'] as $attr => $aParts){ - $contentStr .= " <$schemaPrefix:attribute"; - foreach ($aParts as $a => $v) { - if ($a == 'ref' || $a == 'type') { - $contentStr .= " $a=\"".$this->contractQName($v).'"'; - } elseif ($a == 'http://schemas.xmlsoap.org/wsdl/:arrayType') { - $this->usedNamespaces['wsdl'] = $this->namespaces['wsdl']; - $contentStr .= ' wsdl:arrayType="'.$this->contractQName($v).'"'; - } else { - $contentStr .= " $a=\"$v\""; - } - } - $contentStr .= "/>\n"; - } - } - // if restriction - if (isset($attrs['restrictionBase']) && $attrs['restrictionBase'] != ''){ - $contentStr = " <$schemaPrefix:restriction base=\"".$this->contractQName($attrs['restrictionBase'])."\">\n".$contentStr." \n"; - // complex or simple content - if ((isset($attrs['elements']) && count($attrs['elements']) > 0) || (isset($attrs['attrs']) && count($attrs['attrs']) > 0)){ - $contentStr = " <$schemaPrefix:complexContent>\n".$contentStr." \n"; - } - } - // finalize complex type - if($contentStr != ''){ - $contentStr = " <$schemaPrefix:complexType name=\"$typeName\">\n".$contentStr." \n"; - } else { - $contentStr = " <$schemaPrefix:complexType name=\"$typeName\"/>\n"; - } - $xml .= $contentStr; - } - // simple types - if(isset($this->simpleTypes) && count($this->simpleTypes) > 0){ - foreach($this->simpleTypes as $typeName => $eParts){ - $xml .= " <$schemaPrefix:simpleType name=\"$typeName\">\n <$schemaPrefix:restriction base=\"".$this->contractQName($eParts['type'])."\">\n"; - if (isset($eParts['enumeration'])) { - foreach ($eParts['enumeration'] as $e) { - $xml .= " <$schemaPrefix:enumeration value=\"$e\"/>\n"; - } - } - $xml .= " \n "; - } - } - // elements - if(isset($this->elements) && count($this->elements) > 0){ - foreach($this->elements as $element => $eParts){ - $xml .= " <$schemaPrefix:element name=\"$element\" type=\"".$this->contractQName($eParts['type'])."\"/>\n"; - } - } - // attributes - if(isset($this->attributes) && count($this->attributes) > 0){ - foreach($this->attributes as $attr => $aParts){ - $xml .= " <$schemaPrefix:attribute name=\"$attr\" type=\"".$this->contractQName($aParts['type'])."\"\n/>"; - } - } - // finish 'er up - $attr = ''; - foreach ($this->schemaInfo as $k => $v) { - if ($k == 'elementFormDefault' || $k == 'attributeFormDefault') { - $attr .= " $k=\"$v\""; - } - } - $el = "<$schemaPrefix:schema$attr targetNamespace=\"$this->schemaTargetNamespace\"\n"; - foreach (array_diff($this->usedNamespaces, $this->enclosingNamespaces) as $nsp => $ns) { - $el .= " xmlns:$nsp=\"$ns\""; - } - $xml = $el . ">\n".$xml."\n"; - return $xml; - } - - /** - * adds debug data to the clas level debug string - * - * @param string $string debug data - * @access private - */ - function xdebug($string){ - $this->debug('<' . $this->schemaTargetNamespace . '> '.$string); - } - - /** - * get the PHP type of a user defined type in the schema - * PHP type is kind of a misnomer since it actually returns 'struct' for assoc. arrays - * returns false if no type exists, or not w/ the given namespace - * else returns a string that is either a native php type, or 'struct' - * - * @param string $type name of defined type - * @param string $ns namespace of type - * @return mixed - * @access public - * @deprecated - */ - function getPHPType($type,$ns){ - if(isset($this->typemap[$ns][$type])){ - //print "found type '$type' and ns $ns in typemap
"; - return $this->typemap[$ns][$type]; - } elseif(isset($this->complexTypes[$type])){ - //print "getting type '$type' and ns $ns from complexTypes array
"; - return $this->complexTypes[$type]['phpType']; - } - return false; - } - - /** - * returns an associative array of information about a given type - * returns false if no type exists by the given name - * - * For a complexType typeDef = array( - * 'restrictionBase' => '', - * 'phpType' => '', - * 'compositor' => '(sequence|all)', - * 'elements' => array(), // refs to elements array - * 'attrs' => array() // refs to attributes array - * ... and so on (see addComplexType) - * ) - * - * For simpleType or element, the array has different keys. - * - * @param string $type - * @return mixed - * @access public - * @see addComplexType - * @see addSimpleType - * @see addElement - */ - function getTypeDef($type){ - //$this->debug("in getTypeDef for type $type"); - if (substr($type, -1) == '^') { - $is_element = 1; - $type = substr($type, 0, -1); - } else { - $is_element = 0; - } - - if((! $is_element) && isset($this->complexTypes[$type])){ - $this->xdebug("in getTypeDef, found complexType $type"); - return $this->complexTypes[$type]; - } elseif((! $is_element) && isset($this->simpleTypes[$type])){ - $this->xdebug("in getTypeDef, found simpleType $type"); - if (!isset($this->simpleTypes[$type]['phpType'])) { - // get info for type to tack onto the simple type - // TODO: can this ever really apply (i.e. what is a simpleType really?) - $uqType = substr($this->simpleTypes[$type]['type'], strrpos($this->simpleTypes[$type]['type'], ':') + 1); - $ns = substr($this->simpleTypes[$type]['type'], 0, strrpos($this->simpleTypes[$type]['type'], ':')); - $etype = $this->getTypeDef($uqType); - if ($etype) { - $this->xdebug("in getTypeDef, found type for simpleType $type:"); - $this->xdebug($this->varDump($etype)); - if (isset($etype['phpType'])) { - $this->simpleTypes[$type]['phpType'] = $etype['phpType']; - } - if (isset($etype['elements'])) { - $this->simpleTypes[$type]['elements'] = $etype['elements']; - } - } - } - return $this->simpleTypes[$type]; - } elseif(isset($this->elements[$type])){ - $this->xdebug("in getTypeDef, found element $type"); - if (!isset($this->elements[$type]['phpType'])) { - // get info for type to tack onto the element - $uqType = substr($this->elements[$type]['type'], strrpos($this->elements[$type]['type'], ':') + 1); - $ns = substr($this->elements[$type]['type'], 0, strrpos($this->elements[$type]['type'], ':')); - $etype = $this->getTypeDef($uqType); - if ($etype) { - $this->xdebug("in getTypeDef, found type for element $type:"); - $this->xdebug($this->varDump($etype)); - if (isset($etype['phpType'])) { - $this->elements[$type]['phpType'] = $etype['phpType']; - } - if (isset($etype['elements'])) { - $this->elements[$type]['elements'] = $etype['elements']; - } - if (isset($etype['extensionBase'])) { - $this->elements[$type]['extensionBase'] = $etype['extensionBase']; - } - } elseif ($ns == 'http://www.w3.org/2001/XMLSchema') { - $this->xdebug("in getTypeDef, element $type is an XSD type"); - $this->elements[$type]['phpType'] = 'scalar'; - } - } - return $this->elements[$type]; - } elseif(isset($this->attributes[$type])){ - $this->xdebug("in getTypeDef, found attribute $type"); - return $this->attributes[$type]; - } elseif (preg_match('/_ContainedType$/', $type)) { - $this->xdebug("in getTypeDef, have an untyped element $type"); - $typeDef['typeClass'] = 'simpleType'; - $typeDef['phpType'] = 'scalar'; - $typeDef['type'] = 'http://www.w3.org/2001/XMLSchema:string'; - return $typeDef; - } - $this->xdebug("in getTypeDef, did not find $type"); - return false; - } - - /** - * returns a sample serialization of a given type, or false if no type by the given name - * - * @param string $type name of type - * @return mixed - * @access public - * @deprecated - */ - function serializeTypeDef($type){ - //print "in sTD() for type $type
"; - if($typeDef = $this->getTypeDef($type)){ - $str .= '<'.$type; - if(is_array($typeDef['attrs'])){ - foreach($typeDef['attrs'] as $attName => $data){ - $str .= " $attName=\"{type = ".$data['type']."}\""; - } - } - $str .= " xmlns=\"".$this->schema['targetNamespace']."\""; - if(count($typeDef['elements']) > 0){ - $str .= ">"; - foreach($typeDef['elements'] as $element => $eData){ - $str .= $this->serializeTypeDef($element); - } - $str .= ""; - } elseif($typeDef['typeClass'] == 'element') { - $str .= ">"; - } else { - $str .= "/>"; - } - return $str; - } - return false; - } - - /** - * returns HTML form elements that allow a user - * to enter values for creating an instance of the given type. - * - * @param string $name name for type instance - * @param string $type name of type - * @return string - * @access public - * @deprecated - */ - function typeToForm($name,$type){ - // get typedef - if($typeDef = $this->getTypeDef($type)){ - // if struct - if($typeDef['phpType'] == 'struct'){ - $buffer .= ''; - foreach($typeDef['elements'] as $child => $childDef){ - $buffer .= " - - "; - } - $buffer .= '
$childDef[name] (type: ".$this->getLocalPart($childDef['type'])."):
'; - // if array - } elseif($typeDef['phpType'] == 'array'){ - $buffer .= ''; - for($i=0;$i < 3; $i++){ - $buffer .= " - - "; - } - $buffer .= '
array item (type: $typeDef[arrayType]):
'; - // if scalar - } else { - $buffer .= ""; - } - } else { - $buffer .= ""; - } - return $buffer; - } - - /** - * adds a complex type to the schema - * - * example: array - * - * addType( - * 'ArrayOfstring', - * 'complexType', - * 'array', - * '', - * 'SOAP-ENC:Array', - * array('ref'=>'SOAP-ENC:arrayType','wsdl:arrayType'=>'string[]'), - * 'xsd:string' - * ); - * - * example: PHP associative array ( SOAP Struct ) - * - * addType( - * 'SOAPStruct', - * 'complexType', - * 'struct', - * 'all', - * array('myVar'=> array('name'=>'myVar','type'=>'string') - * ); - * - * @param name - * @param typeClass (complexType|simpleType|attribute) - * @param phpType: currently supported are array and struct (php assoc array) - * @param compositor (all|sequence|choice) - * @param restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array) - * @param elements = array ( name = array(name=>'',type=>'') ) - * @param attrs = array( - * array( - * 'ref' => "http://schemas.xmlsoap.org/soap/encoding/:arrayType", - * "http://schemas.xmlsoap.org/wsdl/:arrayType" => "string[]" - * ) - * ) - * @param arrayType: namespace:name (http://www.w3.org/2001/XMLSchema:string) - * @access public - * @see getTypeDef - */ - function addComplexType($name,$typeClass='complexType',$phpType='array',$compositor='',$restrictionBase='',$elements=array(),$attrs=array(),$arrayType=''){ - $this->complexTypes[$name] = array( - 'name' => $name, - 'typeClass' => $typeClass, - 'phpType' => $phpType, - 'compositor'=> $compositor, - 'restrictionBase' => $restrictionBase, - 'elements' => $elements, - 'attrs' => $attrs, - 'arrayType' => $arrayType - ); - - $this->xdebug("addComplexType $name:"); - $this->appendDebug($this->varDump($this->complexTypes[$name])); - } - - /** - * adds a simple type to the schema - * - * @param string $name - * @param string $restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array) - * @param string $typeClass (should always be simpleType) - * @param string $phpType (should always be scalar) - * @param array $enumeration array of values - * @access public - * @see nusoap_xmlschema - * @see getTypeDef - */ - function addSimpleType($name, $restrictionBase='', $typeClass='simpleType', $phpType='scalar', $enumeration=array()) { - $this->simpleTypes[$name] = array( - 'name' => $name, - 'typeClass' => $typeClass, - 'phpType' => $phpType, - 'type' => $restrictionBase, - 'enumeration' => $enumeration - ); - - $this->xdebug("addSimpleType $name:"); - $this->appendDebug($this->varDump($this->simpleTypes[$name])); - } - - /** - * adds an element to the schema - * - * @param array $attrs attributes that must include name and type - * @see nusoap_xmlschema - * @access public - */ - function addElement($attrs) { - if (! $this->getPrefix($attrs['type'])) { - $attrs['type'] = $this->schemaTargetNamespace . ':' . $attrs['type']; - } - $this->elements[ $attrs['name'] ] = $attrs; - $this->elements[ $attrs['name'] ]['typeClass'] = 'element'; - - $this->xdebug("addElement " . $attrs['name']); - $this->appendDebug($this->varDump($this->elements[ $attrs['name'] ])); - } -} - -/** - * Backward compatibility - */ -class XMLSchema extends nusoap_xmlschema { -} - -?> -* @version $Id: nusoap.php,v 1.123 2010/04/26 20:15:08 snichol Exp $ -* @access public -*/ -class soapval extends nusoap_base { - /** - * The XML element name - * - * @var string - * @access private - */ - var $name; - /** - * The XML type name (string or false) - * - * @var mixed - * @access private - */ - var $type; - /** - * The PHP value - * - * @var mixed - * @access private - */ - var $value; - /** - * The XML element namespace (string or false) - * - * @var mixed - * @access private - */ - var $element_ns; - /** - * The XML type namespace (string or false) - * - * @var mixed - * @access private - */ - var $type_ns; - /** - * The XML element attributes (array or false) - * - * @var mixed - * @access private - */ - var $attributes; - - /** - * constructor - * - * @param string $name optional name - * @param mixed $type optional type name - * @param mixed $value optional value - * @param mixed $element_ns optional namespace of value - * @param mixed $type_ns optional namespace of type - * @param mixed $attributes associative array of attributes to add to element serialization - * @access public - */ - function soapval($name='soapval',$type=false,$value=-1,$element_ns=false,$type_ns=false,$attributes=false) { - parent::nusoap_base(); - $this->name = $name; - $this->type = $type; - $this->value = $value; - $this->element_ns = $element_ns; - $this->type_ns = $type_ns; - $this->attributes = $attributes; - } - - /** - * return serialized value - * - * @param string $use The WSDL use value (encoded|literal) - * @return string XML data - * @access public - */ - function serialize($use='encoded') { - return $this->serialize_val($this->value, $this->name, $this->type, $this->element_ns, $this->type_ns, $this->attributes, $use, true); - } - - /** - * decodes a soapval object into a PHP native type - * - * @return mixed - * @access public - */ - function decode(){ - return $this->value; - } -} - - - -?> -* @author Scott Nichol -* @version $Id: nusoap.php,v 1.123 2010/04/26 20:15:08 snichol Exp $ -* @access public -*/ -class soap_transport_http extends nusoap_base { - - var $url = ''; - var $uri = ''; - var $digest_uri = ''; - var $scheme = ''; - var $host = ''; - var $port = ''; - var $path = ''; - var $request_method = 'POST'; - var $protocol_version = '1.0'; - var $encoding = ''; - var $outgoing_headers = array(); - var $incoming_headers = array(); - var $incoming_cookies = array(); - var $outgoing_payload = ''; - var $incoming_payload = ''; - var $response_status_line; // HTTP response status line - var $useSOAPAction = true; - var $persistentConnection = false; - var $ch = false; // cURL handle - var $ch_options = array(); // cURL custom options - var $use_curl = false; // force cURL use - var $proxy = null; // proxy information (associative array) - var $username = ''; - var $password = ''; - var $authtype = ''; - var $digestRequest = array(); - var $certRequest = array(); // keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, certpassword (optional), verifypeer (optional), verifyhost (optional) - // cainfofile: certificate authority file, e.g. '$pathToPemFiles/rootca.pem' - // sslcertfile: SSL certificate file, e.g. '$pathToPemFiles/mycert.pem' - // sslkeyfile: SSL key file, e.g. '$pathToPemFiles/mykey.pem' - // passphrase: SSL key password/passphrase - // certpassword: SSL certificate password - // verifypeer: default is 1 - // verifyhost: default is 1 - - /** - * constructor - * - * @param string $url The URL to which to connect - * @param array $curl_options User-specified cURL options - * @param boolean $use_curl Whether to try to force cURL use - * @access public - */ - function soap_transport_http($url, $curl_options = NULL, $use_curl = false){ - parent::nusoap_base(); - $this->debug("ctor url=$url use_curl=$use_curl curl_options:"); - $this->appendDebug($this->varDump($curl_options)); - $this->setURL($url); - if (is_array($curl_options)) { - $this->ch_options = $curl_options; - } - $this->use_curl = $use_curl; - preg_match('/\$Revisio' . 'n: ([^ ]+)/', $this->revision, $rev); - $this->setHeader('User-Agent', $this->title.'/'.$this->version.' ('.$rev[1].')'); - } - - /** - * sets a cURL option - * - * @param mixed $option The cURL option (always integer?) - * @param mixed $value The cURL option value - * @access private - */ - function setCurlOption($option, $value) { - $this->debug("setCurlOption option=$option, value="); - $this->appendDebug($this->varDump($value)); - curl_setopt($this->ch, $option, $value); - } - - /** - * sets an HTTP header - * - * @param string $name The name of the header - * @param string $value The value of the header - * @access private - */ - function setHeader($name, $value) { - $this->outgoing_headers[$name] = $value; - $this->debug("set header $name: $value"); - } - - /** - * unsets an HTTP header - * - * @param string $name The name of the header - * @access private - */ - function unsetHeader($name) { - if (isset($this->outgoing_headers[$name])) { - $this->debug("unset header $name"); - unset($this->outgoing_headers[$name]); - } - } - - /** - * sets the URL to which to connect - * - * @param string $url The URL to which to connect - * @access private - */ - function setURL($url) { - $this->url = $url; - - $u = parse_url($url); - foreach($u as $k => $v){ - $this->debug("parsed URL $k = $v"); - $this->$k = $v; - } - - // add any GET params to path - if(isset($u['query']) && $u['query'] != ''){ - $this->path .= '?' . $u['query']; - } - - // set default port - if(!isset($u['port'])){ - if($u['scheme'] == 'https'){ - $this->port = 443; - } else { - $this->port = 80; - } - } - - $this->uri = $this->path; - $this->digest_uri = $this->uri; - - // build headers - if (!isset($u['port'])) { - $this->setHeader('Host', $this->host); - } else { - $this->setHeader('Host', $this->host.':'.$this->port); - } - - if (isset($u['user']) && $u['user'] != '') { - $this->setCredentials(urldecode($u['user']), isset($u['pass']) ? urldecode($u['pass']) : ''); - } - } - - /** - * gets the I/O method to use - * - * @return string I/O method to use (socket|curl|unknown) - * @access private - */ - function io_method() { - if ($this->use_curl || ($this->scheme == 'https') || ($this->scheme == 'http' && $this->authtype == 'ntlm') || ($this->scheme == 'http' && is_array($this->proxy) && $this->proxy['authtype'] == 'ntlm')) - return 'curl'; - if (($this->scheme == 'http' || $this->scheme == 'ssl') && $this->authtype != 'ntlm' && (!is_array($this->proxy) || $this->proxy['authtype'] != 'ntlm')) - return 'socket'; - return 'unknown'; - } - - /** - * establish an HTTP connection - * - * @param integer $timeout set connection timeout in seconds - * @param integer $response_timeout set response timeout in seconds - * @return boolean true if connected, false if not - * @access private - */ - function connect($connection_timeout=0,$response_timeout=30){ - // For PHP 4.3 with OpenSSL, change https scheme to ssl, then treat like - // "regular" socket. - // TODO: disabled for now because OpenSSL must be *compiled* in (not just - // loaded), and until PHP5 stream_get_wrappers is not available. -// if ($this->scheme == 'https') { -// if (version_compare(phpversion(), '4.3.0') >= 0) { -// if (extension_loaded('openssl')) { -// $this->scheme = 'ssl'; -// $this->debug('Using SSL over OpenSSL'); -// } -// } -// } - $this->debug("connect connection_timeout $connection_timeout, response_timeout $response_timeout, scheme $this->scheme, host $this->host, port $this->port"); - if ($this->io_method() == 'socket') { - if (!is_array($this->proxy)) { - $host = $this->host; - $port = $this->port; - } else { - $host = $this->proxy['host']; - $port = $this->proxy['port']; - } - - // use persistent connection - if($this->persistentConnection && isset($this->fp) && is_resource($this->fp)){ - if (!feof($this->fp)) { - $this->debug('Re-use persistent connection'); - return true; - } - fclose($this->fp); - $this->debug('Closed persistent connection at EOF'); - } - - // munge host if using OpenSSL - if ($this->scheme == 'ssl') { - $host = 'ssl://' . $host; - } - $this->debug('calling fsockopen with host ' . $host . ' connection_timeout ' . $connection_timeout); - - // open socket - if($connection_timeout > 0){ - $this->fp = @fsockopen( $host, $this->port, $this->errno, $this->error_str, $connection_timeout); - } else { - $this->fp = @fsockopen( $host, $this->port, $this->errno, $this->error_str); - } - - // test pointer - if(!$this->fp) { - $msg = 'Couldn\'t open socket connection to server ' . $this->url; - if ($this->errno) { - $msg .= ', Error ('.$this->errno.'): '.$this->error_str; - } else { - $msg .= ' prior to connect(). This is often a problem looking up the host name.'; - } - $this->debug($msg); - $this->setError($msg); - return false; - } - - // set response timeout - $this->debug('set response timeout to ' . $response_timeout); - socket_set_timeout( $this->fp, $response_timeout); - - $this->debug('socket connected'); - return true; - } else if ($this->io_method() == 'curl') { - if (!extension_loaded('curl')) { -// $this->setError('cURL Extension, or OpenSSL extension w/ PHP version >= 4.3 is required for HTTPS'); - $this->setError('The PHP cURL Extension is required for HTTPS or NLTM. You will need to re-build or update your PHP to include cURL or change php.ini to load the PHP cURL extension.'); - return false; - } - // Avoid warnings when PHP does not have these options - if (defined('CURLOPT_CONNECTIONTIMEOUT')) - $CURLOPT_CONNECTIONTIMEOUT = CURLOPT_CONNECTIONTIMEOUT; - else - $CURLOPT_CONNECTIONTIMEOUT = 78; - if (defined('CURLOPT_HTTPAUTH')) - $CURLOPT_HTTPAUTH = CURLOPT_HTTPAUTH; - else - $CURLOPT_HTTPAUTH = 107; - if (defined('CURLOPT_PROXYAUTH')) - $CURLOPT_PROXYAUTH = CURLOPT_PROXYAUTH; - else - $CURLOPT_PROXYAUTH = 111; - if (defined('CURLAUTH_BASIC')) - $CURLAUTH_BASIC = CURLAUTH_BASIC; - else - $CURLAUTH_BASIC = 1; - if (defined('CURLAUTH_DIGEST')) - $CURLAUTH_DIGEST = CURLAUTH_DIGEST; - else - $CURLAUTH_DIGEST = 2; - if (defined('CURLAUTH_NTLM')) - $CURLAUTH_NTLM = CURLAUTH_NTLM; - else - $CURLAUTH_NTLM = 8; - - $this->debug('connect using cURL'); - // init CURL - $this->ch = curl_init(); - // set url - $hostURL = ($this->port != '') ? "$this->scheme://$this->host:$this->port" : "$this->scheme://$this->host"; - // add path - $hostURL .= $this->path; - $this->setCurlOption(CURLOPT_URL, $hostURL); - // follow location headers (re-directs) - if (ini_get('safe_mode') || ini_get('open_basedir')) { - $this->debug('safe_mode or open_basedir set, so do not set CURLOPT_FOLLOWLOCATION'); - $this->debug('safe_mode = '); - $this->appendDebug($this->varDump(ini_get('safe_mode'))); - $this->debug('open_basedir = '); - $this->appendDebug($this->varDump(ini_get('open_basedir'))); - } else { - $this->setCurlOption(CURLOPT_FOLLOWLOCATION, 1); - } - // ask for headers in the response output - $this->setCurlOption(CURLOPT_HEADER, 1); - // ask for the response output as the return value - $this->setCurlOption(CURLOPT_RETURNTRANSFER, 1); - // encode - // We manage this ourselves through headers and encoding -// if(function_exists('gzuncompress')){ -// $this->setCurlOption(CURLOPT_ENCODING, 'deflate'); -// } - // persistent connection - if ($this->persistentConnection) { - // I believe the following comment is now bogus, having applied to - // the code when it used CURLOPT_CUSTOMREQUEST to send the request. - // The way we send data, we cannot use persistent connections, since - // there will be some "junk" at the end of our request. - //$this->setCurlOption(CURL_HTTP_VERSION_1_1, true); - $this->persistentConnection = false; - $this->setHeader('Connection', 'close'); - } - // set timeouts - if ($connection_timeout != 0) { - $this->setCurlOption($CURLOPT_CONNECTIONTIMEOUT, $connection_timeout); - } - if ($response_timeout != 0) { - $this->setCurlOption(CURLOPT_TIMEOUT, $response_timeout); - } - - if ($this->scheme == 'https') { - $this->debug('set cURL SSL verify options'); - // recent versions of cURL turn on peer/host checking by default, - // while PHP binaries are not compiled with a default location for the - // CA cert bundle, so disable peer/host checking. - //$this->setCurlOption(CURLOPT_CAINFO, 'f:\php-4.3.2-win32\extensions\curl-ca-bundle.crt'); - $this->setCurlOption(CURLOPT_SSL_VERIFYPEER, 0); - $this->setCurlOption(CURLOPT_SSL_VERIFYHOST, 0); - - // support client certificates (thanks Tobias Boes, Doug Anarino, Eryan Ariobowo) - if ($this->authtype == 'certificate') { - $this->debug('set cURL certificate options'); - if (isset($this->certRequest['cainfofile'])) { - $this->setCurlOption(CURLOPT_CAINFO, $this->certRequest['cainfofile']); - } - if (isset($this->certRequest['verifypeer'])) { - $this->setCurlOption(CURLOPT_SSL_VERIFYPEER, $this->certRequest['verifypeer']); - } else { - $this->setCurlOption(CURLOPT_SSL_VERIFYPEER, 1); - } - if (isset($this->certRequest['verifyhost'])) { - $this->setCurlOption(CURLOPT_SSL_VERIFYHOST, $this->certRequest['verifyhost']); - } else { - $this->setCurlOption(CURLOPT_SSL_VERIFYHOST, 1); - } - if (isset($this->certRequest['sslcertfile'])) { - $this->setCurlOption(CURLOPT_SSLCERT, $this->certRequest['sslcertfile']); - } - if (isset($this->certRequest['sslkeyfile'])) { - $this->setCurlOption(CURLOPT_SSLKEY, $this->certRequest['sslkeyfile']); - } - if (isset($this->certRequest['passphrase'])) { - $this->setCurlOption(CURLOPT_SSLKEYPASSWD, $this->certRequest['passphrase']); - } - if (isset($this->certRequest['certpassword'])) { - $this->setCurlOption(CURLOPT_SSLCERTPASSWD, $this->certRequest['certpassword']); - } - } - } - if ($this->authtype && ($this->authtype != 'certificate')) { - if ($this->username) { - $this->debug('set cURL username/password'); - $this->setCurlOption(CURLOPT_USERPWD, "$this->username:$this->password"); - } - if ($this->authtype == 'basic') { - $this->debug('set cURL for Basic authentication'); - $this->setCurlOption($CURLOPT_HTTPAUTH, $CURLAUTH_BASIC); - } - if ($this->authtype == 'digest') { - $this->debug('set cURL for digest authentication'); - $this->setCurlOption($CURLOPT_HTTPAUTH, $CURLAUTH_DIGEST); - } - if ($this->authtype == 'ntlm') { - $this->debug('set cURL for NTLM authentication'); - $this->setCurlOption($CURLOPT_HTTPAUTH, $CURLAUTH_NTLM); - } - } - if (is_array($this->proxy)) { - $this->debug('set cURL proxy options'); - if ($this->proxy['port'] != '') { - $this->setCurlOption(CURLOPT_PROXY, $this->proxy['host'].':'.$this->proxy['port']); - } else { - $this->setCurlOption(CURLOPT_PROXY, $this->proxy['host']); - } - if ($this->proxy['username'] || $this->proxy['password']) { - $this->debug('set cURL proxy authentication options'); - $this->setCurlOption(CURLOPT_PROXYUSERPWD, $this->proxy['username'].':'.$this->proxy['password']); - if ($this->proxy['authtype'] == 'basic') { - $this->setCurlOption($CURLOPT_PROXYAUTH, $CURLAUTH_BASIC); - } - if ($this->proxy['authtype'] == 'ntlm') { - $this->setCurlOption($CURLOPT_PROXYAUTH, $CURLAUTH_NTLM); - } - } - } - $this->debug('cURL connection set up'); - return true; - } else { - $this->setError('Unknown scheme ' . $this->scheme); - $this->debug('Unknown scheme ' . $this->scheme); - return false; - } - } - - /** - * sends the SOAP request and gets the SOAP response via HTTP[S] - * - * @param string $data message data - * @param integer $timeout set connection timeout in seconds - * @param integer $response_timeout set response timeout in seconds - * @param array $cookies cookies to send - * @return string data - * @access public - */ - function send($data, $timeout=0, $response_timeout=30, $cookies=NULL) { - - $this->debug('entered send() with data of length: '.strlen($data)); - - $this->tryagain = true; - $tries = 0; - while ($this->tryagain) { - $this->tryagain = false; - if ($tries++ < 2) { - // make connnection - if (!$this->connect($timeout, $response_timeout)){ - return false; - } - - // send request - if (!$this->sendRequest($data, $cookies)){ - return false; - } - - // get response - $respdata = $this->getResponse(); - } else { - $this->setError("Too many tries to get an OK response ($this->response_status_line)"); - } - } - $this->debug('end of send()'); - return $respdata; - } - - - /** - * sends the SOAP request and gets the SOAP response via HTTPS using CURL - * - * @param string $data message data - * @param integer $timeout set connection timeout in seconds - * @param integer $response_timeout set response timeout in seconds - * @param array $cookies cookies to send - * @return string data - * @access public - * @deprecated - */ - function sendHTTPS($data, $timeout=0, $response_timeout=30, $cookies) { - return $this->send($data, $timeout, $response_timeout, $cookies); - } - - /** - * if authenticating, set user credentials here - * - * @param string $username - * @param string $password - * @param string $authtype (basic|digest|certificate|ntlm) - * @param array $digestRequest (keys must be nonce, nc, realm, qop) - * @param array $certRequest (keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, certpassword (optional), verifypeer (optional), verifyhost (optional): see corresponding options in cURL docs) - * @access public - */ - function setCredentials($username, $password, $authtype = 'basic', $digestRequest = array(), $certRequest = array()) { - $this->debug("setCredentials username=$username authtype=$authtype digestRequest="); - $this->appendDebug($this->varDump($digestRequest)); - $this->debug("certRequest="); - $this->appendDebug($this->varDump($certRequest)); - // cf. RFC 2617 - if ($authtype == 'basic') { - $this->setHeader('Authorization', 'Basic '.base64_encode(str_replace(':','',$username).':'.$password)); - } elseif ($authtype == 'digest') { - if (isset($digestRequest['nonce'])) { - $digestRequest['nc'] = isset($digestRequest['nc']) ? $digestRequest['nc']++ : 1; - - // calculate the Digest hashes (calculate code based on digest implementation found at: http://www.rassoc.com/gregr/weblog/stories/2002/07/09/webServicesSecurityHttpDigestAuthenticationWithoutActiveDirectory.html) - - // A1 = unq(username-value) ":" unq(realm-value) ":" passwd - $A1 = $username. ':' . (isset($digestRequest['realm']) ? $digestRequest['realm'] : '') . ':' . $password; - - // H(A1) = MD5(A1) - $HA1 = md5($A1); - - // A2 = Method ":" digest-uri-value - $A2 = $this->request_method . ':' . $this->digest_uri; - - // H(A2) - $HA2 = md5($A2); - - // KD(secret, data) = H(concat(secret, ":", data)) - // if qop == auth: - // request-digest = <"> < KD ( H(A1), unq(nonce-value) - // ":" nc-value - // ":" unq(cnonce-value) - // ":" unq(qop-value) - // ":" H(A2) - // ) <"> - // if qop is missing, - // request-digest = <"> < KD ( H(A1), unq(nonce-value) ":" H(A2) ) > <"> - - $unhashedDigest = ''; - $nonce = isset($digestRequest['nonce']) ? $digestRequest['nonce'] : ''; - $cnonce = $nonce; - if ($digestRequest['qop'] != '') { - $unhashedDigest = $HA1 . ':' . $nonce . ':' . sprintf("%08d", $digestRequest['nc']) . ':' . $cnonce . ':' . $digestRequest['qop'] . ':' . $HA2; - } else { - $unhashedDigest = $HA1 . ':' . $nonce . ':' . $HA2; - } - - $hashedDigest = md5($unhashedDigest); - - $opaque = ''; - if (isset($digestRequest['opaque'])) { - $opaque = ', opaque="' . $digestRequest['opaque'] . '"'; - } - - $this->setHeader('Authorization', 'Digest username="' . $username . '", realm="' . $digestRequest['realm'] . '", nonce="' . $nonce . '", uri="' . $this->digest_uri . $opaque . '", cnonce="' . $cnonce . '", nc=' . sprintf("%08x", $digestRequest['nc']) . ', qop="' . $digestRequest['qop'] . '", response="' . $hashedDigest . '"'); - } - } elseif ($authtype == 'certificate') { - $this->certRequest = $certRequest; - $this->debug('Authorization header not set for certificate'); - } elseif ($authtype == 'ntlm') { - // do nothing - $this->debug('Authorization header not set for ntlm'); - } - $this->username = $username; - $this->password = $password; - $this->authtype = $authtype; - $this->digestRequest = $digestRequest; - } - - /** - * set the soapaction value - * - * @param string $soapaction - * @access public - */ - function setSOAPAction($soapaction) { - $this->setHeader('SOAPAction', '"' . $soapaction . '"'); - } - - /** - * use http encoding - * - * @param string $enc encoding style. supported values: gzip, deflate, or both - * @access public - */ - function setEncoding($enc='gzip, deflate') { - if (function_exists('gzdeflate')) { - $this->protocol_version = '1.1'; - $this->setHeader('Accept-Encoding', $enc); - if (!isset($this->outgoing_headers['Connection'])) { - $this->setHeader('Connection', 'close'); - $this->persistentConnection = false; - } - // deprecated as of PHP 5.3.0 - //set_magic_quotes_runtime(0); - $this->encoding = $enc; - } - } - - /** - * set proxy info here - * - * @param string $proxyhost use an empty string to remove proxy - * @param string $proxyport - * @param string $proxyusername - * @param string $proxypassword - * @param string $proxyauthtype (basic|ntlm) - * @access public - */ - function setProxy($proxyhost, $proxyport, $proxyusername = '', $proxypassword = '', $proxyauthtype = 'basic') { - if ($proxyhost) { - $this->proxy = array( - 'host' => $proxyhost, - 'port' => $proxyport, - 'username' => $proxyusername, - 'password' => $proxypassword, - 'authtype' => $proxyauthtype - ); - if ($proxyusername != '' && $proxypassword != '' && $proxyauthtype = 'basic') { - $this->setHeader('Proxy-Authorization', ' Basic '.base64_encode($proxyusername.':'.$proxypassword)); - } - } else { - $this->debug('remove proxy'); - $proxy = null; - unsetHeader('Proxy-Authorization'); - } - } - - - /** - * Test if the given string starts with a header that is to be skipped. - * Skippable headers result from chunked transfer and proxy requests. - * - * @param string $data The string to check. - * @returns boolean Whether a skippable header was found. - * @access private - */ - function isSkippableCurlHeader(&$data) { - $skipHeaders = array( 'HTTP/1.1 100', - 'HTTP/1.0 301', - 'HTTP/1.1 301', - 'HTTP/1.0 302', - 'HTTP/1.1 302', - 'HTTP/1.0 401', - 'HTTP/1.1 401', - 'HTTP/1.0 200 Connection established'); - foreach ($skipHeaders as $hd) { - $prefix = substr($data, 0, strlen($hd)); - if ($prefix == $hd) return true; - } - - return false; - } - - /** - * decode a string that is encoded w/ "chunked' transfer encoding - * as defined in RFC2068 19.4.6 - * - * @param string $buffer - * @param string $lb - * @returns string - * @access public - * @deprecated - */ - function decodeChunked($buffer, $lb){ - // length := 0 - $length = 0; - $new = ''; - - // read chunk-size, chunk-extension (if any) and CRLF - // get the position of the linebreak - $chunkend = strpos($buffer, $lb); - if ($chunkend == FALSE) { - $this->debug('no linebreak found in decodeChunked'); - return $new; - } - $temp = substr($buffer,0,$chunkend); - $chunk_size = hexdec( trim($temp) ); - $chunkstart = $chunkend + strlen($lb); - // while (chunk-size > 0) { - while ($chunk_size > 0) { - $this->debug("chunkstart: $chunkstart chunk_size: $chunk_size"); - $chunkend = strpos( $buffer, $lb, $chunkstart + $chunk_size); - - // Just in case we got a broken connection - if ($chunkend == FALSE) { - $chunk = substr($buffer,$chunkstart); - // append chunk-data to entity-body - $new .= $chunk; - $length += strlen($chunk); - break; - } - - // read chunk-data and CRLF - $chunk = substr($buffer,$chunkstart,$chunkend-$chunkstart); - // append chunk-data to entity-body - $new .= $chunk; - // length := length + chunk-size - $length += strlen($chunk); - // read chunk-size and CRLF - $chunkstart = $chunkend + strlen($lb); - - $chunkend = strpos($buffer, $lb, $chunkstart) + strlen($lb); - if ($chunkend == FALSE) { - break; //Just in case we got a broken connection - } - $temp = substr($buffer,$chunkstart,$chunkend-$chunkstart); - $chunk_size = hexdec( trim($temp) ); - $chunkstart = $chunkend; - } - return $new; - } - - /** - * Writes the payload, including HTTP headers, to $this->outgoing_payload. - * - * @param string $data HTTP body - * @param string $cookie_str data for HTTP Cookie header - * @return void - * @access private - */ - function buildPayload($data, $cookie_str = '') { - // Note: for cURL connections, $this->outgoing_payload is ignored, - // as is the Content-Length header, but these are still created as - // debugging guides. - - // add content-length header - if ($this->request_method != 'GET') { - $this->setHeader('Content-Length', strlen($data)); - } - - // start building outgoing payload: - if ($this->proxy) { - $uri = $this->url; - } else { - $uri = $this->uri; - } - $req = "$this->request_method $uri HTTP/$this->protocol_version"; - $this->debug("HTTP request: $req"); - $this->outgoing_payload = "$req\r\n"; - - // loop thru headers, serializing - foreach($this->outgoing_headers as $k => $v){ - $hdr = $k.': '.$v; - $this->debug("HTTP header: $hdr"); - $this->outgoing_payload .= "$hdr\r\n"; - } - - // add any cookies - if ($cookie_str != '') { - $hdr = 'Cookie: '.$cookie_str; - $this->debug("HTTP header: $hdr"); - $this->outgoing_payload .= "$hdr\r\n"; - } - - // header/body separator - $this->outgoing_payload .= "\r\n"; - - // add data - $this->outgoing_payload .= $data; - } - - /** - * sends the SOAP request via HTTP[S] - * - * @param string $data message data - * @param array $cookies cookies to send - * @return boolean true if OK, false if problem - * @access private - */ - function sendRequest($data, $cookies = NULL) { - // build cookie string - $cookie_str = $this->getCookiesForRequest($cookies, (($this->scheme == 'ssl') || ($this->scheme == 'https'))); - - // build payload - $this->buildPayload($data, $cookie_str); - - if ($this->io_method() == 'socket') { - // send payload - if(!fputs($this->fp, $this->outgoing_payload, strlen($this->outgoing_payload))) { - $this->setError('couldn\'t write message data to socket'); - $this->debug('couldn\'t write message data to socket'); - return false; - } - $this->debug('wrote data to socket, length = ' . strlen($this->outgoing_payload)); - return true; - } else if ($this->io_method() == 'curl') { - // set payload - // cURL does say this should only be the verb, and in fact it - // turns out that the URI and HTTP version are appended to this, which - // some servers refuse to work with (so we no longer use this method!) - //$this->setCurlOption(CURLOPT_CUSTOMREQUEST, $this->outgoing_payload); - $curl_headers = array(); - foreach($this->outgoing_headers as $k => $v){ - if ($k == 'Connection' || $k == 'Content-Length' || $k == 'Host' || $k == 'Authorization' || $k == 'Proxy-Authorization') { - $this->debug("Skip cURL header $k: $v"); - } else { - $curl_headers[] = "$k: $v"; - } - } - if ($cookie_str != '') { - $curl_headers[] = 'Cookie: ' . $cookie_str; - } - $this->setCurlOption(CURLOPT_HTTPHEADER, $curl_headers); - $this->debug('set cURL HTTP headers'); - if ($this->request_method == "POST") { - $this->setCurlOption(CURLOPT_POST, 1); - $this->setCurlOption(CURLOPT_POSTFIELDS, $data); - $this->debug('set cURL POST data'); - } else { - } - // insert custom user-set cURL options - foreach ($this->ch_options as $key => $val) { - $this->setCurlOption($key, $val); - } - - $this->debug('set cURL payload'); - return true; - } - } - - /** - * gets the SOAP response via HTTP[S] - * - * @return string the response (also sets member variables like incoming_payload) - * @access private - */ - function getResponse(){ - $this->incoming_payload = ''; - - if ($this->io_method() == 'socket') { - // loop until headers have been retrieved - $data = ''; - while (!isset($lb)){ - - // We might EOF during header read. - if(feof($this->fp)) { - $this->incoming_payload = $data; - $this->debug('found no headers before EOF after length ' . strlen($data)); - $this->debug("received before EOF:\n" . $data); - $this->setError('server failed to send headers'); - return false; - } - - $tmp = fgets($this->fp, 256); - $tmplen = strlen($tmp); - $this->debug("read line of $tmplen bytes: " . trim($tmp)); - - if ($tmplen == 0) { - $this->incoming_payload = $data; - $this->debug('socket read of headers timed out after length ' . strlen($data)); - $this->debug("read before timeout: " . $data); - $this->setError('socket read of headers timed out'); - return false; - } - - $data .= $tmp; - $pos = strpos($data,"\r\n\r\n"); - if($pos > 1){ - $lb = "\r\n"; - } else { - $pos = strpos($data,"\n\n"); - if($pos > 1){ - $lb = "\n"; - } - } - // remove 100 headers - if (isset($lb) && preg_match('/^HTTP\/1.1 100/',$data)) { - unset($lb); - $data = ''; - }// - } - // store header data - $this->incoming_payload .= $data; - $this->debug('found end of headers after length ' . strlen($data)); - // process headers - $header_data = trim(substr($data,0,$pos)); - $header_array = explode($lb,$header_data); - $this->incoming_headers = array(); - $this->incoming_cookies = array(); - foreach($header_array as $header_line){ - $arr = explode(':',$header_line, 2); - if(count($arr) > 1){ - $header_name = strtolower(trim($arr[0])); - $this->incoming_headers[$header_name] = trim($arr[1]); - if ($header_name == 'set-cookie') { - // TODO: allow multiple cookies from parseCookie - $cookie = $this->parseCookie(trim($arr[1])); - if ($cookie) { - $this->incoming_cookies[] = $cookie; - $this->debug('found cookie: ' . $cookie['name'] . ' = ' . $cookie['value']); - } else { - $this->debug('did not find cookie in ' . trim($arr[1])); - } - } - } else if (isset($header_name)) { - // append continuation line to previous header - $this->incoming_headers[$header_name] .= $lb . ' ' . $header_line; - } - } - - // loop until msg has been received - if (isset($this->incoming_headers['transfer-encoding']) && strtolower($this->incoming_headers['transfer-encoding']) == 'chunked') { - $content_length = 2147483647; // ignore any content-length header - $chunked = true; - $this->debug("want to read chunked content"); - } elseif (isset($this->incoming_headers['content-length'])) { - $content_length = $this->incoming_headers['content-length']; - $chunked = false; - $this->debug("want to read content of length $content_length"); - } else { - $content_length = 2147483647; - $chunked = false; - $this->debug("want to read content to EOF"); - } - $data = ''; - do { - if ($chunked) { - $tmp = fgets($this->fp, 256); - $tmplen = strlen($tmp); - $this->debug("read chunk line of $tmplen bytes"); - if ($tmplen == 0) { - $this->incoming_payload = $data; - $this->debug('socket read of chunk length timed out after length ' . strlen($data)); - $this->debug("read before timeout:\n" . $data); - $this->setError('socket read of chunk length timed out'); - return false; - } - $content_length = hexdec(trim($tmp)); - $this->debug("chunk length $content_length"); - } - $strlen = 0; - while (($strlen < $content_length) && (!feof($this->fp))) { - $readlen = min(8192, $content_length - $strlen); - $tmp = fread($this->fp, $readlen); - $tmplen = strlen($tmp); - $this->debug("read buffer of $tmplen bytes"); - if (($tmplen == 0) && (!feof($this->fp))) { - $this->incoming_payload = $data; - $this->debug('socket read of body timed out after length ' . strlen($data)); - $this->debug("read before timeout:\n" . $data); - $this->setError('socket read of body timed out'); - return false; - } - $strlen += $tmplen; - $data .= $tmp; - } - if ($chunked && ($content_length > 0)) { - $tmp = fgets($this->fp, 256); - $tmplen = strlen($tmp); - $this->debug("read chunk terminator of $tmplen bytes"); - if ($tmplen == 0) { - $this->incoming_payload = $data; - $this->debug('socket read of chunk terminator timed out after length ' . strlen($data)); - $this->debug("read before timeout:\n" . $data); - $this->setError('socket read of chunk terminator timed out'); - return false; - } - } - } while ($chunked && ($content_length > 0) && (!feof($this->fp))); - if (feof($this->fp)) { - $this->debug('read to EOF'); - } - $this->debug('read body of length ' . strlen($data)); - $this->incoming_payload .= $data; - $this->debug('received a total of '.strlen($this->incoming_payload).' bytes of data from server'); - - // close filepointer - if( - (isset($this->incoming_headers['connection']) && strtolower($this->incoming_headers['connection']) == 'close') || - (! $this->persistentConnection) || feof($this->fp)){ - fclose($this->fp); - $this->fp = false; - $this->debug('closed socket'); - } - - // connection was closed unexpectedly - if($this->incoming_payload == ''){ - $this->setError('no response from server'); - return false; - } - - // decode transfer-encoding -// if(isset($this->incoming_headers['transfer-encoding']) && strtolower($this->incoming_headers['transfer-encoding']) == 'chunked'){ -// if(!$data = $this->decodeChunked($data, $lb)){ -// $this->setError('Decoding of chunked data failed'); -// return false; -// } - //print "
\nde-chunked:\n---------------\n$data\n\n---------------\n
"; - // set decoded payload -// $this->incoming_payload = $header_data.$lb.$lb.$data; -// } - - } else if ($this->io_method() == 'curl') { - // send and receive - $this->debug('send and receive with cURL'); - $this->incoming_payload = curl_exec($this->ch); - $data = $this->incoming_payload; - - $cErr = curl_error($this->ch); - if ($cErr != '') { - $err = 'cURL ERROR: '.curl_errno($this->ch).': '.$cErr.'
'; - // TODO: there is a PHP bug that can cause this to SEGV for CURLINFO_CONTENT_TYPE - foreach(curl_getinfo($this->ch) as $k => $v){ - $err .= "$k: $v
"; - } - $this->debug($err); - $this->setError($err); - curl_close($this->ch); - return false; - } else { - //echo '
';
-			//var_dump(curl_getinfo($this->ch));
-			//echo '
'; - } - // close curl - $this->debug('No cURL error, closing cURL'); - curl_close($this->ch); - - // try removing skippable headers - $savedata = $data; - while ($this->isSkippableCurlHeader($data)) { - $this->debug("Found HTTP header to skip"); - if ($pos = strpos($data,"\r\n\r\n")) { - $data = ltrim(substr($data,$pos)); - } elseif($pos = strpos($data,"\n\n") ) { - $data = ltrim(substr($data,$pos)); - } - } - - if ($data == '') { - // have nothing left; just remove 100 header(s) - $data = $savedata; - while (preg_match('/^HTTP\/1.1 100/',$data)) { - if ($pos = strpos($data,"\r\n\r\n")) { - $data = ltrim(substr($data,$pos)); - } elseif($pos = strpos($data,"\n\n") ) { - $data = ltrim(substr($data,$pos)); - } - } - } - - // separate content from HTTP headers - if ($pos = strpos($data,"\r\n\r\n")) { - $lb = "\r\n"; - } elseif( $pos = strpos($data,"\n\n")) { - $lb = "\n"; - } else { - $this->debug('no proper separation of headers and document'); - $this->setError('no proper separation of headers and document'); - return false; - } - $header_data = trim(substr($data,0,$pos)); - $header_array = explode($lb,$header_data); - $data = ltrim(substr($data,$pos)); - $this->debug('found proper separation of headers and document'); - $this->debug('cleaned data, stringlen: '.strlen($data)); - // clean headers - foreach ($header_array as $header_line) { - $arr = explode(':',$header_line,2); - if(count($arr) > 1){ - $header_name = strtolower(trim($arr[0])); - $this->incoming_headers[$header_name] = trim($arr[1]); - if ($header_name == 'set-cookie') { - // TODO: allow multiple cookies from parseCookie - $cookie = $this->parseCookie(trim($arr[1])); - if ($cookie) { - $this->incoming_cookies[] = $cookie; - $this->debug('found cookie: ' . $cookie['name'] . ' = ' . $cookie['value']); - } else { - $this->debug('did not find cookie in ' . trim($arr[1])); - } - } - } else if (isset($header_name)) { - // append continuation line to previous header - $this->incoming_headers[$header_name] .= $lb . ' ' . $header_line; - } - } - } - - $this->response_status_line = $header_array[0]; - $arr = explode(' ', $this->response_status_line, 3); - $http_version = $arr[0]; - $http_status = intval($arr[1]); - $http_reason = count($arr) > 2 ? $arr[2] : ''; - - // see if we need to resend the request with http digest authentication - if (isset($this->incoming_headers['location']) && ($http_status == 301 || $http_status == 302)) { - $this->debug("Got $http_status $http_reason with Location: " . $this->incoming_headers['location']); - $this->setURL($this->incoming_headers['location']); - $this->tryagain = true; - return false; - } - - // see if we need to resend the request with http digest authentication - if (isset($this->incoming_headers['www-authenticate']) && $http_status == 401) { - $this->debug("Got 401 $http_reason with WWW-Authenticate: " . $this->incoming_headers['www-authenticate']); - if (strstr($this->incoming_headers['www-authenticate'], "Digest ")) { - $this->debug('Server wants digest authentication'); - // remove "Digest " from our elements - $digestString = str_replace('Digest ', '', $this->incoming_headers['www-authenticate']); - - // parse elements into array - $digestElements = explode(',', $digestString); - foreach ($digestElements as $val) { - $tempElement = explode('=', trim($val), 2); - $digestRequest[$tempElement[0]] = str_replace("\"", '', $tempElement[1]); - } - - // should have (at least) qop, realm, nonce - if (isset($digestRequest['nonce'])) { - $this->setCredentials($this->username, $this->password, 'digest', $digestRequest); - $this->tryagain = true; - return false; - } - } - $this->debug('HTTP authentication failed'); - $this->setError('HTTP authentication failed'); - return false; - } - - if ( - ($http_status >= 300 && $http_status <= 307) || - ($http_status >= 400 && $http_status <= 417) || - ($http_status >= 501 && $http_status <= 505) - ) { - $this->setError("Unsupported HTTP response status $http_status $http_reason (soapclient->response has contents of the response)"); - return false; - } - - // decode content-encoding - if(isset($this->incoming_headers['content-encoding']) && $this->incoming_headers['content-encoding'] != ''){ - if(strtolower($this->incoming_headers['content-encoding']) == 'deflate' || strtolower($this->incoming_headers['content-encoding']) == 'gzip'){ - // if decoding works, use it. else assume data wasn't gzencoded - if(function_exists('gzinflate')){ - //$timer->setMarker('starting decoding of gzip/deflated content'); - // IIS 5 requires gzinflate instead of gzuncompress (similar to IE 5 and gzdeflate v. gzcompress) - // this means there are no Zlib headers, although there should be - $this->debug('The gzinflate function exists'); - $datalen = strlen($data); - if ($this->incoming_headers['content-encoding'] == 'deflate') { - if ($degzdata = @gzinflate($data)) { - $data = $degzdata; - $this->debug('The payload has been inflated to ' . strlen($data) . ' bytes'); - if (strlen($data) < $datalen) { - // test for the case that the payload has been compressed twice - $this->debug('The inflated payload is smaller than the gzipped one; try again'); - if ($degzdata = @gzinflate($data)) { - $data = $degzdata; - $this->debug('The payload has been inflated again to ' . strlen($data) . ' bytes'); - } - } - } else { - $this->debug('Error using gzinflate to inflate the payload'); - $this->setError('Error using gzinflate to inflate the payload'); - } - } elseif ($this->incoming_headers['content-encoding'] == 'gzip') { - if ($degzdata = @gzinflate(substr($data, 10))) { // do our best - $data = $degzdata; - $this->debug('The payload has been un-gzipped to ' . strlen($data) . ' bytes'); - if (strlen($data) < $datalen) { - // test for the case that the payload has been compressed twice - $this->debug('The un-gzipped payload is smaller than the gzipped one; try again'); - if ($degzdata = @gzinflate(substr($data, 10))) { - $data = $degzdata; - $this->debug('The payload has been un-gzipped again to ' . strlen($data) . ' bytes'); - } - } - } else { - $this->debug('Error using gzinflate to un-gzip the payload'); - $this->setError('Error using gzinflate to un-gzip the payload'); - } - } - //$timer->setMarker('finished decoding of gzip/deflated content'); - //print "\nde-inflated:\n---------------\n$data\n-------------\n"; - // set decoded payload - $this->incoming_payload = $header_data.$lb.$lb.$data; - } else { - $this->debug('The server sent compressed data. Your php install must have the Zlib extension compiled in to support this.'); - $this->setError('The server sent compressed data. Your php install must have the Zlib extension compiled in to support this.'); - } - } else { - $this->debug('Unsupported Content-Encoding ' . $this->incoming_headers['content-encoding']); - $this->setError('Unsupported Content-Encoding ' . $this->incoming_headers['content-encoding']); - } - } else { - $this->debug('No Content-Encoding header'); - } - - if(strlen($data) == 0){ - $this->debug('no data after headers!'); - $this->setError('no data present after HTTP headers'); - return false; - } - - return $data; - } - - /** - * sets the content-type for the SOAP message to be sent - * - * @param string $type the content type, MIME style - * @param mixed $charset character set used for encoding (or false) - * @access public - */ - function setContentType($type, $charset = false) { - $this->setHeader('Content-Type', $type . ($charset ? '; charset=' . $charset : '')); - } - - /** - * specifies that an HTTP persistent connection should be used - * - * @return boolean whether the request was honored by this method. - * @access public - */ - function usePersistentConnection(){ - if (isset($this->outgoing_headers['Accept-Encoding'])) { - return false; - } - $this->protocol_version = '1.1'; - $this->persistentConnection = true; - $this->setHeader('Connection', 'Keep-Alive'); - return true; - } - - /** - * parse an incoming Cookie into it's parts - * - * @param string $cookie_str content of cookie - * @return array with data of that cookie - * @access private - */ - /* - * TODO: allow a Set-Cookie string to be parsed into multiple cookies - */ - function parseCookie($cookie_str) { - $cookie_str = str_replace('; ', ';', $cookie_str) . ';'; - $data = preg_split('/;/', $cookie_str); - $value_str = $data[0]; - - $cookie_param = 'domain='; - $start = strpos($cookie_str, $cookie_param); - if ($start > 0) { - $domain = substr($cookie_str, $start + strlen($cookie_param)); - $domain = substr($domain, 0, strpos($domain, ';')); - } else { - $domain = ''; - } - - $cookie_param = 'expires='; - $start = strpos($cookie_str, $cookie_param); - if ($start > 0) { - $expires = substr($cookie_str, $start + strlen($cookie_param)); - $expires = substr($expires, 0, strpos($expires, ';')); - } else { - $expires = ''; - } - - $cookie_param = 'path='; - $start = strpos($cookie_str, $cookie_param); - if ( $start > 0 ) { - $path = substr($cookie_str, $start + strlen($cookie_param)); - $path = substr($path, 0, strpos($path, ';')); - } else { - $path = '/'; - } - - $cookie_param = ';secure;'; - if (strpos($cookie_str, $cookie_param) !== FALSE) { - $secure = true; - } else { - $secure = false; - } - - $sep_pos = strpos($value_str, '='); - - if ($sep_pos) { - $name = substr($value_str, 0, $sep_pos); - $value = substr($value_str, $sep_pos + 1); - $cookie= array( 'name' => $name, - 'value' => $value, - 'domain' => $domain, - 'path' => $path, - 'expires' => $expires, - 'secure' => $secure - ); - return $cookie; - } - return false; - } - - /** - * sort out cookies for the current request - * - * @param array $cookies array with all cookies - * @param boolean $secure is the send-content secure or not? - * @return string for Cookie-HTTP-Header - * @access private - */ - function getCookiesForRequest($cookies, $secure=false) { - $cookie_str = ''; - if ((! is_null($cookies)) && (is_array($cookies))) { - foreach ($cookies as $cookie) { - if (! is_array($cookie)) { - continue; - } - $this->debug("check cookie for validity: ".$cookie['name'].'='.$cookie['value']); - if ((isset($cookie['expires'])) && (! empty($cookie['expires']))) { - if (strtotime($cookie['expires']) <= time()) { - $this->debug('cookie has expired'); - continue; - } - } - if ((isset($cookie['domain'])) && (! empty($cookie['domain']))) { - $domain = preg_quote($cookie['domain']); - if (! preg_match("'.*$domain$'i", $this->host)) { - $this->debug('cookie has different domain'); - continue; - } - } - if ((isset($cookie['path'])) && (! empty($cookie['path']))) { - $path = preg_quote($cookie['path']); - if (! preg_match("'^$path.*'i", $this->path)) { - $this->debug('cookie is for a different path'); - continue; - } - } - if ((! $secure) && (isset($cookie['secure'])) && ($cookie['secure'])) { - $this->debug('cookie is secure, transport is not'); - continue; - } - $cookie_str .= $cookie['name'] . '=' . $cookie['value'] . '; '; - $this->debug('add cookie to Cookie-String: ' . $cookie['name'] . '=' . $cookie['value']); - } - } - return $cookie_str; - } -} - -?> -* @author Scott Nichol -* @version $Id: nusoap.php,v 1.123 2010/04/26 20:15:08 snichol Exp $ -* @access public -*/ -class nusoap_server extends nusoap_base { - /** - * HTTP headers of request - * @var array - * @access private - */ - var $headers = array(); - /** - * HTTP request - * @var string - * @access private - */ - var $request = ''; - /** - * SOAP headers from request (incomplete namespace resolution; special characters not escaped) (text) - * @var string - * @access public - */ - var $requestHeaders = ''; - /** - * SOAP Headers from request (parsed) - * @var mixed - * @access public - */ - var $requestHeader = NULL; - /** - * SOAP body request portion (incomplete namespace resolution; special characters not escaped) (text) - * @var string - * @access public - */ - var $document = ''; - /** - * SOAP payload for request (text) - * @var string - * @access public - */ - var $requestSOAP = ''; - /** - * requested method namespace URI - * @var string - * @access private - */ - var $methodURI = ''; - /** - * name of method requested - * @var string - * @access private - */ - var $methodname = ''; - /** - * method parameters from request - * @var array - * @access private - */ - var $methodparams = array(); - /** - * SOAP Action from request - * @var string - * @access private - */ - var $SOAPAction = ''; - /** - * character set encoding of incoming (request) messages - * @var string - * @access public - */ - var $xml_encoding = ''; - /** - * toggles whether the parser decodes element content w/ utf8_decode() - * @var boolean - * @access public - */ - var $decode_utf8 = true; - - /** - * HTTP headers of response - * @var array - * @access public - */ - var $outgoing_headers = array(); - /** - * HTTP response - * @var string - * @access private - */ - var $response = ''; - /** - * SOAP headers for response (text or array of soapval or associative array) - * @var mixed - * @access public - */ - var $responseHeaders = ''; - /** - * SOAP payload for response (text) - * @var string - * @access private - */ - var $responseSOAP = ''; - /** - * method return value to place in response - * @var mixed - * @access private - */ - var $methodreturn = false; - /** - * whether $methodreturn is a string of literal XML - * @var boolean - * @access public - */ - var $methodreturnisliteralxml = false; - /** - * SOAP fault for response (or false) - * @var mixed - * @access private - */ - var $fault = false; - /** - * text indication of result (for debugging) - * @var string - * @access private - */ - var $result = 'successful'; - - /** - * assoc array of operations => opData; operations are added by the register() - * method or by parsing an external WSDL definition - * @var array - * @access private - */ - var $operations = array(); - /** - * wsdl instance (if one) - * @var mixed - * @access private - */ - var $wsdl = false; - /** - * URL for WSDL (if one) - * @var mixed - * @access private - */ - var $externalWSDLURL = false; - /** - * whether to append debug to response as XML comment - * @var boolean - * @access public - */ - var $debug_flag = false; - - - /** - * constructor - * the optional parameter is a path to a WSDL file that you'd like to bind the server instance to. - * - * @param mixed $wsdl file path or URL (string), or wsdl instance (object) - * @access public - */ - function nusoap_server($wsdl=false){ - parent::nusoap_base(); - // turn on debugging? - global $debug; - global $HTTP_SERVER_VARS; - - if (isset($_SERVER)) { - $this->debug("_SERVER is defined:"); - $this->appendDebug($this->varDump($_SERVER)); - } elseif (isset($HTTP_SERVER_VARS)) { - $this->debug("HTTP_SERVER_VARS is defined:"); - $this->appendDebug($this->varDump($HTTP_SERVER_VARS)); - } else { - $this->debug("Neither _SERVER nor HTTP_SERVER_VARS is defined."); - } - - if (isset($debug)) { - $this->debug("In nusoap_server, set debug_flag=$debug based on global flag"); - $this->debug_flag = $debug; - } elseif (isset($_SERVER['QUERY_STRING'])) { - $qs = explode('&', $_SERVER['QUERY_STRING']); - foreach ($qs as $v) { - if (substr($v, 0, 6) == 'debug=') { - $this->debug("In nusoap_server, set debug_flag=" . substr($v, 6) . " based on query string #1"); - $this->debug_flag = substr($v, 6); - } - } - } elseif (isset($HTTP_SERVER_VARS['QUERY_STRING'])) { - $qs = explode('&', $HTTP_SERVER_VARS['QUERY_STRING']); - foreach ($qs as $v) { - if (substr($v, 0, 6) == 'debug=') { - $this->debug("In nusoap_server, set debug_flag=" . substr($v, 6) . " based on query string #2"); - $this->debug_flag = substr($v, 6); - } - } - } - - // wsdl - if($wsdl){ - $this->debug("In nusoap_server, WSDL is specified"); - if (is_object($wsdl) && (get_class($wsdl) == 'wsdl')) { - $this->wsdl = $wsdl; - $this->externalWSDLURL = $this->wsdl->wsdl; - $this->debug('Use existing wsdl instance from ' . $this->externalWSDLURL); - } else { - $this->debug('Create wsdl from ' . $wsdl); - $this->wsdl = new wsdl($wsdl); - $this->externalWSDLURL = $wsdl; - } - $this->appendDebug($this->wsdl->getDebug()); - $this->wsdl->clearDebug(); - if($err = $this->wsdl->getError()){ - die('WSDL ERROR: '.$err); - } - } - } - - /** - * processes request and returns response - * - * @param string $data usually is the value of $HTTP_RAW_POST_DATA - * @access public - */ - function service($data){ - global $HTTP_SERVER_VARS; - - if (isset($_SERVER['REQUEST_METHOD'])) { - $rm = $_SERVER['REQUEST_METHOD']; - } elseif (isset($HTTP_SERVER_VARS['REQUEST_METHOD'])) { - $rm = $HTTP_SERVER_VARS['REQUEST_METHOD']; - } else { - $rm = ''; - } - - if (isset($_SERVER['QUERY_STRING'])) { - $qs = $_SERVER['QUERY_STRING']; - } elseif (isset($HTTP_SERVER_VARS['QUERY_STRING'])) { - $qs = $HTTP_SERVER_VARS['QUERY_STRING']; - } else { - $qs = ''; - } - $this->debug("In service, request method=$rm query string=$qs strlen(\$data)=" . strlen($data)); - - if ($rm == 'POST') { - $this->debug("In service, invoke the request"); - $this->parse_request($data); - if (! $this->fault) { - $this->invoke_method(); - } - if (! $this->fault) { - $this->serialize_return(); - } - $this->send_response(); - } elseif (preg_match('/wsdl/', $qs) ){ - $this->debug("In service, this is a request for WSDL"); - if ($this->externalWSDLURL){ - if (strpos($this->externalWSDLURL, "http://") !== false) { // assume URL - $this->debug("In service, re-direct for WSDL"); - header('Location: '.$this->externalWSDLURL); - } else { // assume file - $this->debug("In service, use file passthru for WSDL"); - header("Content-Type: text/xml\r\n"); - $pos = strpos($this->externalWSDLURL, "file://"); - if ($pos === false) { - $filename = $this->externalWSDLURL; - } else { - $filename = substr($this->externalWSDLURL, $pos + 7); - } - $fp = fopen($this->externalWSDLURL, 'r'); - fpassthru($fp); - } - } elseif ($this->wsdl) { - $this->debug("In service, serialize WSDL"); - header("Content-Type: text/xml; charset=ISO-8859-1\r\n"); - print $this->wsdl->serialize($this->debug_flag); - if ($this->debug_flag) { - $this->debug('wsdl:'); - $this->appendDebug($this->varDump($this->wsdl)); - print $this->getDebugAsXMLComment(); - } - } else { - $this->debug("In service, there is no WSDL"); - header("Content-Type: text/html; charset=ISO-8859-1\r\n"); - print "This service does not provide WSDL"; - } - } elseif ($this->wsdl) { - $this->debug("In service, return Web description"); - print $this->wsdl->webDescription(); - } else { - $this->debug("In service, no Web description"); - header("Content-Type: text/html; charset=ISO-8859-1\r\n"); - print "This service does not provide a Web description"; - } - } - - /** - * parses HTTP request headers. - * - * The following fields are set by this function (when successful) - * - * headers - * request - * xml_encoding - * SOAPAction - * - * @access private - */ - function parse_http_headers() { - global $HTTP_SERVER_VARS; - - $this->request = ''; - $this->SOAPAction = ''; - if(function_exists('getallheaders')){ - $this->debug("In parse_http_headers, use getallheaders"); - $headers = getallheaders(); - foreach($headers as $k=>$v){ - $k = strtolower($k); - $this->headers[$k] = $v; - $this->request .= "$k: $v\r\n"; - $this->debug("$k: $v"); - } - // get SOAPAction header - if(isset($this->headers['soapaction'])){ - $this->SOAPAction = str_replace('"','',$this->headers['soapaction']); - } - // get the character encoding of the incoming request - if(isset($this->headers['content-type']) && strpos($this->headers['content-type'],'=')){ - $enc = str_replace('"','',substr(strstr($this->headers["content-type"],'='),1)); - if(preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i',$enc)){ - $this->xml_encoding = strtoupper($enc); - } else { - $this->xml_encoding = 'US-ASCII'; - } - } else { - // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1 - $this->xml_encoding = 'ISO-8859-1'; - } - } elseif(isset($_SERVER) && is_array($_SERVER)){ - $this->debug("In parse_http_headers, use _SERVER"); - foreach ($_SERVER as $k => $v) { - if (substr($k, 0, 5) == 'HTTP_') { - $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', substr($k, 5)))); - } else { - $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', $k))); - } - if ($k == 'soapaction') { - // get SOAPAction header - $k = 'SOAPAction'; - $v = str_replace('"', '', $v); - $v = str_replace('\\', '', $v); - $this->SOAPAction = $v; - } else if ($k == 'content-type') { - // get the character encoding of the incoming request - if (strpos($v, '=')) { - $enc = substr(strstr($v, '='), 1); - $enc = str_replace('"', '', $enc); - $enc = str_replace('\\', '', $enc); - if (preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i',$enc)) { - $this->xml_encoding = strtoupper($enc); - } else { - $this->xml_encoding = 'US-ASCII'; - } - } else { - // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1 - $this->xml_encoding = 'ISO-8859-1'; - } - } - $this->headers[$k] = $v; - $this->request .= "$k: $v\r\n"; - $this->debug("$k: $v"); - } - } elseif (is_array($HTTP_SERVER_VARS)) { - $this->debug("In parse_http_headers, use HTTP_SERVER_VARS"); - foreach ($HTTP_SERVER_VARS as $k => $v) { - if (substr($k, 0, 5) == 'HTTP_') { - $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', substr($k, 5)))); $k = strtolower(substr($k, 5)); - } else { - $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', $k))); $k = strtolower($k); - } - if ($k == 'soapaction') { - // get SOAPAction header - $k = 'SOAPAction'; - $v = str_replace('"', '', $v); - $v = str_replace('\\', '', $v); - $this->SOAPAction = $v; - } else if ($k == 'content-type') { - // get the character encoding of the incoming request - if (strpos($v, '=')) { - $enc = substr(strstr($v, '='), 1); - $enc = str_replace('"', '', $enc); - $enc = str_replace('\\', '', $enc); - if (preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i',$enc)) { - $this->xml_encoding = strtoupper($enc); - } else { - $this->xml_encoding = 'US-ASCII'; - } - } else { - // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1 - $this->xml_encoding = 'ISO-8859-1'; - } - } - $this->headers[$k] = $v; - $this->request .= "$k: $v\r\n"; - $this->debug("$k: $v"); - } - } else { - $this->debug("In parse_http_headers, HTTP headers not accessible"); - $this->setError("HTTP headers not accessible"); - } - } - - /** - * parses a request - * - * The following fields are set by this function (when successful) - * - * headers - * request - * xml_encoding - * SOAPAction - * request - * requestSOAP - * methodURI - * methodname - * methodparams - * requestHeaders - * document - * - * This sets the fault field on error - * - * @param string $data XML string - * @access private - */ - function parse_request($data='') { - $this->debug('entering parse_request()'); - $this->parse_http_headers(); - $this->debug('got character encoding: '.$this->xml_encoding); - // uncompress if necessary - if (isset($this->headers['content-encoding']) && $this->headers['content-encoding'] != '') { - $this->debug('got content encoding: ' . $this->headers['content-encoding']); - if ($this->headers['content-encoding'] == 'deflate' || $this->headers['content-encoding'] == 'gzip') { - // if decoding works, use it. else assume data wasn't gzencoded - if (function_exists('gzuncompress')) { - if ($this->headers['content-encoding'] == 'deflate' && $degzdata = @gzuncompress($data)) { - $data = $degzdata; - } elseif ($this->headers['content-encoding'] == 'gzip' && $degzdata = gzinflate(substr($data, 10))) { - $data = $degzdata; - } else { - $this->fault('SOAP-ENV:Client', 'Errors occurred when trying to decode the data'); - return; - } - } else { - $this->fault('SOAP-ENV:Client', 'This Server does not support compressed data'); - return; - } - } - } - $this->request .= "\r\n".$data; - $data = $this->parseRequest($this->headers, $data); - $this->requestSOAP = $data; - $this->debug('leaving parse_request'); - } - - /** - * invokes a PHP function for the requested SOAP method - * - * The following fields are set by this function (when successful) - * - * methodreturn - * - * Note that the PHP function that is called may also set the following - * fields to affect the response sent to the client - * - * responseHeaders - * outgoing_headers - * - * This sets the fault field on error - * - * @access private - */ - function invoke_method() { - $this->debug('in invoke_method, methodname=' . $this->methodname . ' methodURI=' . $this->methodURI . ' SOAPAction=' . $this->SOAPAction); - - // - // if you are debugging in this area of the code, your service uses a class to implement methods, - // you use SOAP RPC, and the client is .NET, please be aware of the following... - // when the .NET wsdl.exe utility generates a proxy, it will remove the '.' or '..' from the - // method name. that is fine for naming the .NET methods. it is not fine for properly constructing - // the XML request and reading the XML response. you need to add the RequestElementName and - // ResponseElementName to the System.Web.Services.Protocols.SoapRpcMethodAttribute that wsdl.exe - // generates for the method. these parameters are used to specify the correct XML element names - // for .NET to use, i.e. the names with the '.' in them. - // - $orig_methodname = $this->methodname; - if ($this->wsdl) { - if ($this->opData = $this->wsdl->getOperationData($this->methodname)) { - $this->debug('in invoke_method, found WSDL operation=' . $this->methodname); - $this->appendDebug('opData=' . $this->varDump($this->opData)); - } elseif ($this->opData = $this->wsdl->getOperationDataForSoapAction($this->SOAPAction)) { - // Note: hopefully this case will only be used for doc/lit, since rpc services should have wrapper element - $this->debug('in invoke_method, found WSDL soapAction=' . $this->SOAPAction . ' for operation=' . $this->opData['name']); - $this->appendDebug('opData=' . $this->varDump($this->opData)); - $this->methodname = $this->opData['name']; - } else { - $this->debug('in invoke_method, no WSDL for operation=' . $this->methodname); - $this->fault('SOAP-ENV:Client', "Operation '" . $this->methodname . "' is not defined in the WSDL for this service"); - return; - } - } else { - $this->debug('in invoke_method, no WSDL to validate method'); - } - - // if a . is present in $this->methodname, we see if there is a class in scope, - // which could be referred to. We will also distinguish between two deliminators, - // to allow methods to be called a the class or an instance - if (strpos($this->methodname, '..') > 0) { - $delim = '..'; - } else if (strpos($this->methodname, '.') > 0) { - $delim = '.'; - } else { - $delim = ''; - } - $this->debug("in invoke_method, delim=$delim"); - - $class = ''; - $method = ''; - if (strlen($delim) > 0 && substr_count($this->methodname, $delim) == 1) { - $try_class = substr($this->methodname, 0, strpos($this->methodname, $delim)); - if (class_exists($try_class)) { - // get the class and method name - $class = $try_class; - $method = substr($this->methodname, strpos($this->methodname, $delim) + strlen($delim)); - $this->debug("in invoke_method, class=$class method=$method delim=$delim"); - } else { - $this->debug("in invoke_method, class=$try_class not found"); - } - } else { - $try_class = ''; - $this->debug("in invoke_method, no class to try"); - } - - // does method exist? - if ($class == '') { - if (!function_exists($this->methodname)) { - $this->debug("in invoke_method, function '$this->methodname' not found!"); - $this->result = 'fault: method not found'; - $this->fault('SOAP-ENV:Client',"method '$this->methodname'('$orig_methodname') not defined in service('$try_class' '$delim')"); - return; - } - } else { - $method_to_compare = (substr(phpversion(), 0, 2) == '4.') ? strtolower($method) : $method; - if (!in_array($method_to_compare, get_class_methods($class))) { - $this->debug("in invoke_method, method '$this->methodname' not found in class '$class'!"); - $this->result = 'fault: method not found'; - $this->fault('SOAP-ENV:Client',"method '$this->methodname'/'$method_to_compare'('$orig_methodname') not defined in service/'$class'('$try_class' '$delim')"); - return; - } - } - - // evaluate message, getting back parameters - // verify that request parameters match the method's signature - if(! $this->verify_method($this->methodname,$this->methodparams)){ - // debug - $this->debug('ERROR: request not verified against method signature'); - $this->result = 'fault: request failed validation against method signature'; - // return fault - $this->fault('SOAP-ENV:Client',"Operation '$this->methodname' not defined in service."); - return; - } - - // if there are parameters to pass - $this->debug('in invoke_method, params:'); - $this->appendDebug($this->varDump($this->methodparams)); - $this->debug("in invoke_method, calling '$this->methodname'"); - if (!function_exists('call_user_func_array')) { - if ($class == '') { - $this->debug('in invoke_method, calling function using eval()'); - $funcCall = "\$this->methodreturn = $this->methodname("; - } else { - if ($delim == '..') { - $this->debug('in invoke_method, calling class method using eval()'); - $funcCall = "\$this->methodreturn = ".$class."::".$method."("; - } else { - $this->debug('in invoke_method, calling instance method using eval()'); - // generate unique instance name - $instname = "\$inst_".time(); - $funcCall = $instname." = new ".$class."(); "; - $funcCall .= "\$this->methodreturn = ".$instname."->".$method."("; - } - } - if ($this->methodparams) { - foreach ($this->methodparams as $param) { - if (is_array($param) || is_object($param)) { - $this->fault('SOAP-ENV:Client', 'NuSOAP does not handle complexType parameters correctly when using eval; call_user_func_array must be available'); - return; - } - $funcCall .= "\"$param\","; - } - $funcCall = substr($funcCall, 0, -1); - } - $funcCall .= ');'; - $this->debug('in invoke_method, function call: '.$funcCall); - @eval($funcCall); - } else { - if ($class == '') { - $this->debug('in invoke_method, calling function using call_user_func_array()'); - $call_arg = "$this->methodname"; // straight assignment changes $this->methodname to lower case after call_user_func_array() - } elseif ($delim == '..') { - $this->debug('in invoke_method, calling class method using call_user_func_array()'); - $call_arg = array ($class, $method); - } else { - $this->debug('in invoke_method, calling instance method using call_user_func_array()'); - $instance = new $class (); - $call_arg = array(&$instance, $method); - } - if (is_array($this->methodparams)) { - $this->methodreturn = call_user_func_array($call_arg, array_values($this->methodparams)); - } else { - $this->methodreturn = call_user_func_array($call_arg, array()); - } - } - $this->debug('in invoke_method, methodreturn:'); - $this->appendDebug($this->varDump($this->methodreturn)); - $this->debug("in invoke_method, called method $this->methodname, received data of type ".gettype($this->methodreturn)); - } - - /** - * serializes the return value from a PHP function into a full SOAP Envelope - * - * The following fields are set by this function (when successful) - * - * responseSOAP - * - * This sets the fault field on error - * - * @access private - */ - function serialize_return() { - $this->debug('Entering serialize_return methodname: ' . $this->methodname . ' methodURI: ' . $this->methodURI); - // if fault - if (isset($this->methodreturn) && is_object($this->methodreturn) && ((get_class($this->methodreturn) == 'soap_fault') || (get_class($this->methodreturn) == 'nusoap_fault'))) { - $this->debug('got a fault object from method'); - $this->fault = $this->methodreturn; - return; - } elseif ($this->methodreturnisliteralxml) { - $return_val = $this->methodreturn; - // returned value(s) - } else { - $this->debug('got a(n) '.gettype($this->methodreturn).' from method'); - $this->debug('serializing return value'); - if($this->wsdl){ - if (sizeof($this->opData['output']['parts']) > 1) { - $this->debug('more than one output part, so use the method return unchanged'); - $opParams = $this->methodreturn; - } elseif (sizeof($this->opData['output']['parts']) == 1) { - $this->debug('exactly one output part, so wrap the method return in a simple array'); - // TODO: verify that it is not already wrapped! - //foreach ($this->opData['output']['parts'] as $name => $type) { - // $this->debug('wrap in element named ' . $name); - //} - $opParams = array($this->methodreturn); - } - $return_val = $this->wsdl->serializeRPCParameters($this->methodname,'output',$opParams); - $this->appendDebug($this->wsdl->getDebug()); - $this->wsdl->clearDebug(); - if($errstr = $this->wsdl->getError()){ - $this->debug('got wsdl error: '.$errstr); - $this->fault('SOAP-ENV:Server', 'unable to serialize result'); - return; - } - } else { - if (isset($this->methodreturn)) { - $return_val = $this->serialize_val($this->methodreturn, 'return'); - } else { - $return_val = ''; - $this->debug('in absence of WSDL, assume void return for backward compatibility'); - } - } - } - $this->debug('return value:'); - $this->appendDebug($this->varDump($return_val)); - - $this->debug('serializing response'); - if ($this->wsdl) { - $this->debug('have WSDL for serialization: style is ' . $this->opData['style']); - if ($this->opData['style'] == 'rpc') { - $this->debug('style is rpc for serialization: use is ' . $this->opData['output']['use']); - if ($this->opData['output']['use'] == 'literal') { - // http://www.ws-i.org/Profiles/BasicProfile-1.1-2004-08-24.html R2735 says rpc/literal accessor elements should not be in a namespace - if ($this->methodURI) { - $payload = 'methodname.'Response xmlns:ns1="'.$this->methodURI.'">'.$return_val.'methodname."Response>"; - } else { - $payload = '<'.$this->methodname.'Response>'.$return_val.'methodname.'Response>'; - } - } else { - if ($this->methodURI) { - $payload = 'methodname.'Response xmlns:ns1="'.$this->methodURI.'">'.$return_val.'methodname."Response>"; - } else { - $payload = '<'.$this->methodname.'Response>'.$return_val.'methodname.'Response>'; - } - } - } else { - $this->debug('style is not rpc for serialization: assume document'); - $payload = $return_val; - } - } else { - $this->debug('do not have WSDL for serialization: assume rpc/encoded'); - $payload = 'methodname.'Response xmlns:ns1="'.$this->methodURI.'">'.$return_val.'methodname."Response>"; - } - $this->result = 'successful'; - if($this->wsdl){ - //if($this->debug_flag){ - $this->appendDebug($this->wsdl->getDebug()); - // } - if (isset($this->opData['output']['encodingStyle'])) { - $encodingStyle = $this->opData['output']['encodingStyle']; - } else { - $encodingStyle = ''; - } - // Added: In case we use a WSDL, return a serialized env. WITH the usedNamespaces. - $this->responseSOAP = $this->serializeEnvelope($payload,$this->responseHeaders,$this->wsdl->usedNamespaces,$this->opData['style'],$this->opData['output']['use'],$encodingStyle); - } else { - $this->responseSOAP = $this->serializeEnvelope($payload,$this->responseHeaders); - } - $this->debug("Leaving serialize_return"); - } - - /** - * sends an HTTP response - * - * The following fields are set by this function (when successful) - * - * outgoing_headers - * response - * - * @access private - */ - function send_response() { - $this->debug('Enter send_response'); - if ($this->fault) { - $payload = $this->fault->serialize(); - $this->outgoing_headers[] = "HTTP/1.0 500 Internal Server Error"; - $this->outgoing_headers[] = "Status: 500 Internal Server Error"; - } else { - $payload = $this->responseSOAP; - // Some combinations of PHP+Web server allow the Status - // to come through as a header. Since OK is the default - // just do nothing. - // $this->outgoing_headers[] = "HTTP/1.0 200 OK"; - // $this->outgoing_headers[] = "Status: 200 OK"; - } - // add debug data if in debug mode - if(isset($this->debug_flag) && $this->debug_flag){ - $payload .= $this->getDebugAsXMLComment(); - } - $this->outgoing_headers[] = "Server: $this->title Server v$this->version"; - preg_match('/\$Revisio' . 'n: ([^ ]+)/', $this->revision, $rev); - $this->outgoing_headers[] = "X-SOAP-Server: $this->title/$this->version (".$rev[1].")"; - // Let the Web server decide about this - //$this->outgoing_headers[] = "Connection: Close\r\n"; - $payload = $this->getHTTPBody($payload); - $type = $this->getHTTPContentType(); - $charset = $this->getHTTPContentTypeCharset(); - $this->outgoing_headers[] = "Content-Type: $type" . ($charset ? '; charset=' . $charset : ''); - //begin code to compress payload - by John - // NOTE: there is no way to know whether the Web server will also compress - // this data. - if (strlen($payload) > 1024 && isset($this->headers) && isset($this->headers['accept-encoding'])) { - if (strstr($this->headers['accept-encoding'], 'gzip')) { - if (function_exists('gzencode')) { - if (isset($this->debug_flag) && $this->debug_flag) { - $payload .= ""; - } - $this->outgoing_headers[] = "Content-Encoding: gzip"; - $payload = gzencode($payload); - } else { - if (isset($this->debug_flag) && $this->debug_flag) { - $payload .= ""; - } - } - } elseif (strstr($this->headers['accept-encoding'], 'deflate')) { - // Note: MSIE requires gzdeflate output (no Zlib header and checksum), - // instead of gzcompress output, - // which conflicts with HTTP 1.1 spec (http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.5) - if (function_exists('gzdeflate')) { - if (isset($this->debug_flag) && $this->debug_flag) { - $payload .= ""; - } - $this->outgoing_headers[] = "Content-Encoding: deflate"; - $payload = gzdeflate($payload); - } else { - if (isset($this->debug_flag) && $this->debug_flag) { - $payload .= ""; - } - } - } - } - //end code - $this->outgoing_headers[] = "Content-Length: ".strlen($payload); - reset($this->outgoing_headers); - foreach($this->outgoing_headers as $hdr){ - header($hdr, false); - } - print $payload; - $this->response = join("\r\n",$this->outgoing_headers)."\r\n\r\n".$payload; - } - - /** - * takes the value that was created by parsing the request - * and compares to the method's signature, if available. - * - * @param string $operation The operation to be invoked - * @param array $request The array of parameter values - * @return boolean Whether the operation was found - * @access private - */ - function verify_method($operation,$request){ - if(isset($this->wsdl) && is_object($this->wsdl)){ - if($this->wsdl->getOperationData($operation)){ - return true; - } - } elseif(isset($this->operations[$operation])){ - return true; - } - return false; - } - - /** - * processes SOAP message received from client - * - * @param array $headers The HTTP headers - * @param string $data unprocessed request data from client - * @return mixed value of the message, decoded into a PHP type - * @access private - */ - function parseRequest($headers, $data) { - $this->debug('Entering parseRequest() for data of length ' . strlen($data) . ' headers:'); - $this->appendDebug($this->varDump($headers)); - if (!isset($headers['content-type'])) { - $this->setError('Request not of type text/xml (no content-type header)'); - return false; - } - if (!strstr($headers['content-type'], 'text/xml')) { - $this->setError('Request not of type text/xml'); - return false; - } - if (strpos($headers['content-type'], '=')) { - $enc = str_replace('"', '', substr(strstr($headers["content-type"], '='), 1)); - $this->debug('Got response encoding: ' . $enc); - if(preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i',$enc)){ - $this->xml_encoding = strtoupper($enc); - } else { - $this->xml_encoding = 'US-ASCII'; - } - } else { - // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1 - $this->xml_encoding = 'ISO-8859-1'; - } - $this->debug('Use encoding: ' . $this->xml_encoding . ' when creating nusoap_parser'); - // parse response, get soap parser obj - $parser = new nusoap_parser($data,$this->xml_encoding,'',$this->decode_utf8); - // parser debug - $this->debug("parser debug: \n".$parser->getDebug()); - // if fault occurred during message parsing - if($err = $parser->getError()){ - $this->result = 'fault: error in msg parsing: '.$err; - $this->fault('SOAP-ENV:Client',"error in msg parsing:\n".$err); - // else successfully parsed request into soapval object - } else { - // get/set methodname - $this->methodURI = $parser->root_struct_namespace; - $this->methodname = $parser->root_struct_name; - $this->debug('methodname: '.$this->methodname.' methodURI: '.$this->methodURI); - $this->debug('calling parser->get_soapbody()'); - $this->methodparams = $parser->get_soapbody(); - // get SOAP headers - $this->requestHeaders = $parser->getHeaders(); - // get SOAP Header - $this->requestHeader = $parser->get_soapheader(); - // add document for doclit support - $this->document = $parser->document; - } - } - - /** - * gets the HTTP body for the current response. - * - * @param string $soapmsg The SOAP payload - * @return string The HTTP body, which includes the SOAP payload - * @access private - */ - function getHTTPBody($soapmsg) { - return $soapmsg; - } - - /** - * gets the HTTP content type for the current response. - * - * Note: getHTTPBody must be called before this. - * - * @return string the HTTP content type for the current response. - * @access private - */ - function getHTTPContentType() { - return 'text/xml'; - } - - /** - * gets the HTTP content type charset for the current response. - * returns false for non-text content types. - * - * Note: getHTTPBody must be called before this. - * - * @return string the HTTP content type charset for the current response. - * @access private - */ - function getHTTPContentTypeCharset() { - return $this->soap_defencoding; - } - - /** - * add a method to the dispatch map (this has been replaced by the register method) - * - * @param string $methodname - * @param string $in array of input values - * @param string $out array of output values - * @access public - * @deprecated - */ - function add_to_map($methodname,$in,$out){ - $this->operations[$methodname] = array('name' => $methodname,'in' => $in,'out' => $out); - } - - /** - * register a service function with the server - * - * @param string $name the name of the PHP function, class.method or class..method - * @param array $in assoc array of input values: key = param name, value = param type - * @param array $out assoc array of output values: key = param name, value = param type - * @param mixed $namespace the element namespace for the method or false - * @param mixed $soapaction the soapaction for the method or false - * @param mixed $style optional (rpc|document) or false Note: when 'document' is specified, parameter and return wrappers are created for you automatically - * @param mixed $use optional (encoded|literal) or false - * @param string $documentation optional Description to include in WSDL - * @param string $encodingStyle optional (usually 'http://schemas.xmlsoap.org/soap/encoding/' for encoded) - * @access public - */ - function register($name,$in=array(),$out=array(),$namespace=false,$soapaction=false,$style=false,$use=false,$documentation='',$encodingStyle=''){ - global $HTTP_SERVER_VARS; - - if($this->externalWSDLURL){ - die('You cannot bind to an external WSDL file, and register methods outside of it! Please choose either WSDL or no WSDL.'); - } - if (! $name) { - die('You must specify a name when you register an operation'); - } - if (!is_array($in)) { - die('You must provide an array for operation inputs'); - } - if (!is_array($out)) { - die('You must provide an array for operation outputs'); - } - if(false == $namespace) { - } - if(false == $soapaction) { - if (isset($_SERVER)) { - $SERVER_NAME = $_SERVER['SERVER_NAME']; - $SCRIPT_NAME = isset($_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : $_SERVER['SCRIPT_NAME']; - $HTTPS = isset($_SERVER['HTTPS']) ? $_SERVER['HTTPS'] : (isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off'); - } elseif (isset($HTTP_SERVER_VARS)) { - $SERVER_NAME = $HTTP_SERVER_VARS['SERVER_NAME']; - $SCRIPT_NAME = isset($HTTP_SERVER_VARS['PHP_SELF']) ? $HTTP_SERVER_VARS['PHP_SELF'] : $HTTP_SERVER_VARS['SCRIPT_NAME']; - $HTTPS = isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off'; - } else { - $this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available"); - } - if ($HTTPS == '1' || $HTTPS == 'on') { - $SCHEME = 'https'; - } else { - $SCHEME = 'http'; - } - $soapaction = "$SCHEME://$SERVER_NAME$SCRIPT_NAME/$name"; - } - if(false == $style) { - $style = "rpc"; - } - if(false == $use) { - $use = "encoded"; - } - if ($use == 'encoded' && $encodingStyle == '') { - $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/'; - } - - $this->operations[$name] = array( - 'name' => $name, - 'in' => $in, - 'out' => $out, - 'namespace' => $namespace, - 'soapaction' => $soapaction, - 'style' => $style); - if($this->wsdl){ - $this->wsdl->addOperation($name,$in,$out,$namespace,$soapaction,$style,$use,$documentation,$encodingStyle); - } - return true; - } - - /** - * Specify a fault to be returned to the client. - * This also acts as a flag to the server that a fault has occured. - * - * @param string $faultcode - * @param string $faultstring - * @param string $faultactor - * @param string $faultdetail - * @access public - */ - function fault($faultcode,$faultstring,$faultactor='',$faultdetail=''){ - if ($faultdetail == '' && $this->debug_flag) { - $faultdetail = $this->getDebug(); - } - $this->fault = new nusoap_fault($faultcode,$faultactor,$faultstring,$faultdetail); - $this->fault->soap_defencoding = $this->soap_defencoding; - } - - /** - * Sets up wsdl object. - * Acts as a flag to enable internal WSDL generation - * - * @param string $serviceName, name of the service - * @param mixed $namespace optional 'tns' service namespace or false - * @param mixed $endpoint optional URL of service endpoint or false - * @param string $style optional (rpc|document) WSDL style (also specified by operation) - * @param string $transport optional SOAP transport - * @param mixed $schemaTargetNamespace optional 'types' targetNamespace for service schema or false - */ - function configureWSDL($serviceName,$namespace = false,$endpoint = false,$style='rpc', $transport = 'http://schemas.xmlsoap.org/soap/http', $schemaTargetNamespace = false) - { - global $HTTP_SERVER_VARS; - - if (isset($_SERVER)) { - $SERVER_NAME = $_SERVER['SERVER_NAME']; - $SERVER_PORT = $_SERVER['SERVER_PORT']; - $SCRIPT_NAME = isset($_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : $_SERVER['SCRIPT_NAME']; - $HTTPS = isset($_SERVER['HTTPS']) ? $_SERVER['HTTPS'] : (isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off'); - } elseif (isset($HTTP_SERVER_VARS)) { - $SERVER_NAME = $HTTP_SERVER_VARS['SERVER_NAME']; - $SERVER_PORT = $HTTP_SERVER_VARS['SERVER_PORT']; - $SCRIPT_NAME = isset($HTTP_SERVER_VARS['PHP_SELF']) ? $HTTP_SERVER_VARS['PHP_SELF'] : $HTTP_SERVER_VARS['SCRIPT_NAME']; - $HTTPS = isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off'; - } else { - $this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available"); - } - // If server name has port number attached then strip it (else port number gets duplicated in WSDL output) (occurred using lighttpd and FastCGI) - $colon = strpos($SERVER_NAME,":"); - if ($colon) { - $SERVER_NAME = substr($SERVER_NAME, 0, $colon); - } - if ($SERVER_PORT == 80) { - $SERVER_PORT = ''; - } else { - $SERVER_PORT = ':' . $SERVER_PORT; - } - if(false == $namespace) { - $namespace = "http://$SERVER_NAME/soap/$serviceName"; - } - - if(false == $endpoint) { - if ($HTTPS == '1' || $HTTPS == 'on') { - $SCHEME = 'https'; - } else { - $SCHEME = 'http'; - } - $endpoint = "$SCHEME://$SERVER_NAME$SERVER_PORT$SCRIPT_NAME"; - } - - if(false == $schemaTargetNamespace) { - $schemaTargetNamespace = $namespace; - } - - $this->wsdl = new wsdl; - $this->wsdl->serviceName = $serviceName; - $this->wsdl->endpoint = $endpoint; - $this->wsdl->namespaces['tns'] = $namespace; - $this->wsdl->namespaces['soap'] = 'http://schemas.xmlsoap.org/wsdl/soap/'; - $this->wsdl->namespaces['wsdl'] = 'http://schemas.xmlsoap.org/wsdl/'; - if ($schemaTargetNamespace != $namespace) { - $this->wsdl->namespaces['types'] = $schemaTargetNamespace; - } - $this->wsdl->schemas[$schemaTargetNamespace][0] = new nusoap_xmlschema('', '', $this->wsdl->namespaces); - if ($style == 'document') { - $this->wsdl->schemas[$schemaTargetNamespace][0]->schemaInfo['elementFormDefault'] = 'qualified'; - } - $this->wsdl->schemas[$schemaTargetNamespace][0]->schemaTargetNamespace = $schemaTargetNamespace; - $this->wsdl->schemas[$schemaTargetNamespace][0]->imports['http://schemas.xmlsoap.org/soap/encoding/'][0] = array('location' => '', 'loaded' => true); - $this->wsdl->schemas[$schemaTargetNamespace][0]->imports['http://schemas.xmlsoap.org/wsdl/'][0] = array('location' => '', 'loaded' => true); - $this->wsdl->bindings[$serviceName.'Binding'] = array( - 'name'=>$serviceName.'Binding', - 'style'=>$style, - 'transport'=>$transport, - 'portType'=>$serviceName.'PortType'); - $this->wsdl->ports[$serviceName.'Port'] = array( - 'binding'=>$serviceName.'Binding', - 'location'=>$endpoint, - 'bindingType'=>'http://schemas.xmlsoap.org/wsdl/soap/'); - } -} - -/** - * Backward compatibility - */ -class soap_server extends nusoap_server { -} - -?> -* @author Scott Nichol -* @version $Id: nusoap.php,v 1.123 2010/04/26 20:15:08 snichol Exp $ -* @access public -*/ -class wsdl extends nusoap_base { - // URL or filename of the root of this WSDL - var $wsdl; - // define internal arrays of bindings, ports, operations, messages, etc. - var $schemas = array(); - var $currentSchema; - var $message = array(); - var $complexTypes = array(); - var $messages = array(); - var $currentMessage; - var $currentOperation; - var $portTypes = array(); - var $currentPortType; - var $bindings = array(); - var $currentBinding; - var $ports = array(); - var $currentPort; - var $opData = array(); - var $status = ''; - var $documentation = false; - var $endpoint = ''; - // array of wsdl docs to import - var $import = array(); - // parser vars - var $parser; - var $position = 0; - var $depth = 0; - var $depth_array = array(); - // for getting wsdl - var $proxyhost = ''; - var $proxyport = ''; - var $proxyusername = ''; - var $proxypassword = ''; - var $timeout = 0; - var $response_timeout = 30; - var $curl_options = array(); // User-specified cURL options - var $use_curl = false; // whether to always try to use cURL - // for HTTP authentication - var $username = ''; // Username for HTTP authentication - var $password = ''; // Password for HTTP authentication - var $authtype = ''; // Type of HTTP authentication - var $certRequest = array(); // Certificate for HTTP SSL authentication - - /** - * constructor - * - * @param string $wsdl WSDL document URL - * @param string $proxyhost - * @param string $proxyport - * @param string $proxyusername - * @param string $proxypassword - * @param integer $timeout set the connection timeout - * @param integer $response_timeout set the response timeout - * @param array $curl_options user-specified cURL options - * @param boolean $use_curl try to use cURL - * @access public - */ - function wsdl($wsdl = '',$proxyhost=false,$proxyport=false,$proxyusername=false,$proxypassword=false,$timeout=0,$response_timeout=30,$curl_options=null,$use_curl=false){ - parent::nusoap_base(); - $this->debug("ctor wsdl=$wsdl timeout=$timeout response_timeout=$response_timeout"); - $this->proxyhost = $proxyhost; - $this->proxyport = $proxyport; - $this->proxyusername = $proxyusername; - $this->proxypassword = $proxypassword; - $this->timeout = $timeout; - $this->response_timeout = $response_timeout; - if (is_array($curl_options)) - $this->curl_options = $curl_options; - $this->use_curl = $use_curl; - $this->fetchWSDL($wsdl); - } - - /** - * fetches the WSDL document and parses it - * - * @access public - */ - function fetchWSDL($wsdl) { - $this->debug("parse and process WSDL path=$wsdl"); - $this->wsdl = $wsdl; - // parse wsdl file - if ($this->wsdl != "") { - $this->parseWSDL($this->wsdl); - } - // imports - // TODO: handle imports more properly, grabbing them in-line and nesting them - $imported_urls = array(); - $imported = 1; - while ($imported > 0) { - $imported = 0; - // Schema imports - foreach ($this->schemas as $ns => $list) { - foreach ($list as $xs) { - $wsdlparts = parse_url($this->wsdl); // this is bogusly simple! - foreach ($xs->imports as $ns2 => $list2) { - for ($ii = 0; $ii < count($list2); $ii++) { - if (! $list2[$ii]['loaded']) { - $this->schemas[$ns]->imports[$ns2][$ii]['loaded'] = true; - $url = $list2[$ii]['location']; - if ($url != '') { - $urlparts = parse_url($url); - if (!isset($urlparts['host'])) { - $url = $wsdlparts['scheme'] . '://' . $wsdlparts['host'] . (isset($wsdlparts['port']) ? ':' .$wsdlparts['port'] : '') . - substr($wsdlparts['path'],0,strrpos($wsdlparts['path'],'/') + 1) .$urlparts['path']; - } - if (! in_array($url, $imported_urls)) { - $this->parseWSDL($url); - $imported++; - $imported_urls[] = $url; - } - } else { - $this->debug("Unexpected scenario: empty URL for unloaded import"); - } - } - } - } - } - } - // WSDL imports - $wsdlparts = parse_url($this->wsdl); // this is bogusly simple! - foreach ($this->import as $ns => $list) { - for ($ii = 0; $ii < count($list); $ii++) { - if (! $list[$ii]['loaded']) { - $this->import[$ns][$ii]['loaded'] = true; - $url = $list[$ii]['location']; - if ($url != '') { - $urlparts = parse_url($url); - if (!isset($urlparts['host'])) { - $url = $wsdlparts['scheme'] . '://' . $wsdlparts['host'] . (isset($wsdlparts['port']) ? ':' . $wsdlparts['port'] : '') . - substr($wsdlparts['path'],0,strrpos($wsdlparts['path'],'/') + 1) .$urlparts['path']; - } - if (! in_array($url, $imported_urls)) { - $this->parseWSDL($url); - $imported++; - $imported_urls[] = $url; - } - } else { - $this->debug("Unexpected scenario: empty URL for unloaded import"); - } - } - } - } - } - // add new data to operation data - foreach($this->bindings as $binding => $bindingData) { - if (isset($bindingData['operations']) && is_array($bindingData['operations'])) { - foreach($bindingData['operations'] as $operation => $data) { - $this->debug('post-parse data gathering for ' . $operation); - $this->bindings[$binding]['operations'][$operation]['input'] = - isset($this->bindings[$binding]['operations'][$operation]['input']) ? - array_merge($this->bindings[$binding]['operations'][$operation]['input'], $this->portTypes[ $bindingData['portType'] ][$operation]['input']) : - $this->portTypes[ $bindingData['portType'] ][$operation]['input']; - $this->bindings[$binding]['operations'][$operation]['output'] = - isset($this->bindings[$binding]['operations'][$operation]['output']) ? - array_merge($this->bindings[$binding]['operations'][$operation]['output'], $this->portTypes[ $bindingData['portType'] ][$operation]['output']) : - $this->portTypes[ $bindingData['portType'] ][$operation]['output']; - if(isset($this->messages[ $this->bindings[$binding]['operations'][$operation]['input']['message'] ])){ - $this->bindings[$binding]['operations'][$operation]['input']['parts'] = $this->messages[ $this->bindings[$binding]['operations'][$operation]['input']['message'] ]; - } - if(isset($this->messages[ $this->bindings[$binding]['operations'][$operation]['output']['message'] ])){ - $this->bindings[$binding]['operations'][$operation]['output']['parts'] = $this->messages[ $this->bindings[$binding]['operations'][$operation]['output']['message'] ]; - } - // Set operation style if necessary, but do not override one already provided - if (isset($bindingData['style']) && !isset($this->bindings[$binding]['operations'][$operation]['style'])) { - $this->bindings[$binding]['operations'][$operation]['style'] = $bindingData['style']; - } - $this->bindings[$binding]['operations'][$operation]['transport'] = isset($bindingData['transport']) ? $bindingData['transport'] : ''; - $this->bindings[$binding]['operations'][$operation]['documentation'] = isset($this->portTypes[ $bindingData['portType'] ][$operation]['documentation']) ? $this->portTypes[ $bindingData['portType'] ][$operation]['documentation'] : ''; - $this->bindings[$binding]['operations'][$operation]['endpoint'] = isset($bindingData['endpoint']) ? $bindingData['endpoint'] : ''; - } - } - } - } - - /** - * parses the wsdl document - * - * @param string $wsdl path or URL - * @access private - */ - function parseWSDL($wsdl = '') { - $this->debug("parse WSDL at path=$wsdl"); - - if ($wsdl == '') { - $this->debug('no wsdl passed to parseWSDL()!!'); - $this->setError('no wsdl passed to parseWSDL()!!'); - return false; - } - - // parse $wsdl for url format - $wsdl_props = parse_url($wsdl); - - if (isset($wsdl_props['scheme']) && ($wsdl_props['scheme'] == 'http' || $wsdl_props['scheme'] == 'https')) { - $this->debug('getting WSDL http(s) URL ' . $wsdl); - // get wsdl - $tr = new soap_transport_http($wsdl, $this->curl_options, $this->use_curl); - $tr->request_method = 'GET'; - $tr->useSOAPAction = false; - if($this->proxyhost && $this->proxyport){ - $tr->setProxy($this->proxyhost,$this->proxyport,$this->proxyusername,$this->proxypassword); - } - if ($this->authtype != '') { - $tr->setCredentials($this->username, $this->password, $this->authtype, array(), $this->certRequest); - } - $tr->setEncoding('gzip, deflate'); - $wsdl_string = $tr->send('', $this->timeout, $this->response_timeout); - //$this->debug("WSDL request\n" . $tr->outgoing_payload); - //$this->debug("WSDL response\n" . $tr->incoming_payload); - $this->appendDebug($tr->getDebug()); - // catch errors - if($err = $tr->getError() ){ - $errstr = 'Getting ' . $wsdl . ' - HTTP ERROR: '.$err; - $this->debug($errstr); - $this->setError($errstr); - unset($tr); - return false; - } - unset($tr); - $this->debug("got WSDL URL"); - } else { - // $wsdl is not http(s), so treat it as a file URL or plain file path - if (isset($wsdl_props['scheme']) && ($wsdl_props['scheme'] == 'file') && isset($wsdl_props['path'])) { - $path = isset($wsdl_props['host']) ? ($wsdl_props['host'] . ':' . $wsdl_props['path']) : $wsdl_props['path']; - } else { - $path = $wsdl; - } - $this->debug('getting WSDL file ' . $path); - if ($fp = @fopen($path, 'r')) { - $wsdl_string = ''; - while ($data = fread($fp, 32768)) { - $wsdl_string .= $data; - } - fclose($fp); - } else { - $errstr = "Bad path to WSDL file $path"; - $this->debug($errstr); - $this->setError($errstr); - return false; - } - } - $this->debug('Parse WSDL'); - // end new code added - // Create an XML parser. - $this->parser = xml_parser_create(); - // Set the options for parsing the XML data. - // xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1); - xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0); - // Set the object for the parser. - xml_set_object($this->parser, $this); - // Set the element handlers for the parser. - xml_set_element_handler($this->parser, 'start_element', 'end_element'); - xml_set_character_data_handler($this->parser, 'character_data'); - // Parse the XML file. - if (!xml_parse($this->parser, $wsdl_string, true)) { - // Display an error message. - $errstr = sprintf( - 'XML error parsing WSDL from %s on line %d: %s', - $wsdl, - xml_get_current_line_number($this->parser), - xml_error_string(xml_get_error_code($this->parser)) - ); - $this->debug($errstr); - $this->debug("XML payload:\n" . $wsdl_string); - $this->setError($errstr); - return false; - } - // free the parser - xml_parser_free($this->parser); - $this->debug('Parsing WSDL done'); - // catch wsdl parse errors - if($this->getError()){ - return false; - } - return true; - } - - /** - * start-element handler - * - * @param string $parser XML parser object - * @param string $name element name - * @param string $attrs associative array of attributes - * @access private - */ - function start_element($parser, $name, $attrs) - { - if ($this->status == 'schema') { - $this->currentSchema->schemaStartElement($parser, $name, $attrs); - $this->appendDebug($this->currentSchema->getDebug()); - $this->currentSchema->clearDebug(); - } elseif (preg_match('/schema$/', $name)) { - $this->debug('Parsing WSDL schema'); - // $this->debug("startElement for $name ($attrs[name]). status = $this->status (".$this->getLocalPart($name).")"); - $this->status = 'schema'; - $this->currentSchema = new nusoap_xmlschema('', '', $this->namespaces); - $this->currentSchema->schemaStartElement($parser, $name, $attrs); - $this->appendDebug($this->currentSchema->getDebug()); - $this->currentSchema->clearDebug(); - } else { - // position in the total number of elements, starting from 0 - $pos = $this->position++; - $depth = $this->depth++; - // set self as current value for this depth - $this->depth_array[$depth] = $pos; - $this->message[$pos] = array('cdata' => ''); - // process attributes - if (count($attrs) > 0) { - // register namespace declarations - foreach($attrs as $k => $v) { - if (preg_match('/^xmlns/',$k)) { - if ($ns_prefix = substr(strrchr($k, ':'), 1)) { - $this->namespaces[$ns_prefix] = $v; - } else { - $this->namespaces['ns' . (count($this->namespaces) + 1)] = $v; - } - if ($v == 'http://www.w3.org/2001/XMLSchema' || $v == 'http://www.w3.org/1999/XMLSchema' || $v == 'http://www.w3.org/2000/10/XMLSchema') { - $this->XMLSchemaVersion = $v; - $this->namespaces['xsi'] = $v . '-instance'; - } - } - } - // expand each attribute prefix to its namespace - foreach($attrs as $k => $v) { - $k = strpos($k, ':') ? $this->expandQname($k) : $k; - if ($k != 'location' && $k != 'soapAction' && $k != 'namespace') { - $v = strpos($v, ':') ? $this->expandQname($v) : $v; - } - $eAttrs[$k] = $v; - } - $attrs = $eAttrs; - } else { - $attrs = array(); - } - // get element prefix, namespace and name - if (preg_match('/:/', $name)) { - // get ns prefix - $prefix = substr($name, 0, strpos($name, ':')); - // get ns - $namespace = isset($this->namespaces[$prefix]) ? $this->namespaces[$prefix] : ''; - // get unqualified name - $name = substr(strstr($name, ':'), 1); - } - // process attributes, expanding any prefixes to namespaces - // find status, register data - switch ($this->status) { - case 'message': - if ($name == 'part') { - if (isset($attrs['type'])) { - $this->debug("msg " . $this->currentMessage . ": found part (with type) $attrs[name]: " . implode(',', $attrs)); - $this->messages[$this->currentMessage][$attrs['name']] = $attrs['type']; - } - if (isset($attrs['element'])) { - $this->debug("msg " . $this->currentMessage . ": found part (with element) $attrs[name]: " . implode(',', $attrs)); - $this->messages[$this->currentMessage][$attrs['name']] = $attrs['element'] . '^'; - } - } - break; - case 'portType': - switch ($name) { - case 'operation': - $this->currentPortOperation = $attrs['name']; - $this->debug("portType $this->currentPortType operation: $this->currentPortOperation"); - if (isset($attrs['parameterOrder'])) { - $this->portTypes[$this->currentPortType][$attrs['name']]['parameterOrder'] = $attrs['parameterOrder']; - } - break; - case 'documentation': - $this->documentation = true; - break; - // merge input/output data - default: - $m = isset($attrs['message']) ? $this->getLocalPart($attrs['message']) : ''; - $this->portTypes[$this->currentPortType][$this->currentPortOperation][$name]['message'] = $m; - break; - } - break; - case 'binding': - switch ($name) { - case 'binding': - // get ns prefix - if (isset($attrs['style'])) { - $this->bindings[$this->currentBinding]['prefix'] = $prefix; - } - $this->bindings[$this->currentBinding] = array_merge($this->bindings[$this->currentBinding], $attrs); - break; - case 'header': - $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus]['headers'][] = $attrs; - break; - case 'operation': - if (isset($attrs['soapAction'])) { - $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['soapAction'] = $attrs['soapAction']; - } - if (isset($attrs['style'])) { - $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['style'] = $attrs['style']; - } - if (isset($attrs['name'])) { - $this->currentOperation = $attrs['name']; - $this->debug("current binding operation: $this->currentOperation"); - $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['name'] = $attrs['name']; - $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['binding'] = $this->currentBinding; - $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['endpoint'] = isset($this->bindings[$this->currentBinding]['endpoint']) ? $this->bindings[$this->currentBinding]['endpoint'] : ''; - } - break; - case 'input': - $this->opStatus = 'input'; - break; - case 'output': - $this->opStatus = 'output'; - break; - case 'body': - if (isset($this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus])) { - $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus] = array_merge($this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus], $attrs); - } else { - $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus] = $attrs; - } - break; - } - break; - case 'service': - switch ($name) { - case 'port': - $this->currentPort = $attrs['name']; - $this->debug('current port: ' . $this->currentPort); - $this->ports[$this->currentPort]['binding'] = $this->getLocalPart($attrs['binding']); - - break; - case 'address': - $this->ports[$this->currentPort]['location'] = $attrs['location']; - $this->ports[$this->currentPort]['bindingType'] = $namespace; - $this->bindings[ $this->ports[$this->currentPort]['binding'] ]['bindingType'] = $namespace; - $this->bindings[ $this->ports[$this->currentPort]['binding'] ]['endpoint'] = $attrs['location']; - break; - } - break; - } - // set status - switch ($name) { - case 'import': - if (isset($attrs['location'])) { - $this->import[$attrs['namespace']][] = array('location' => $attrs['location'], 'loaded' => false); - $this->debug('parsing import ' . $attrs['namespace']. ' - ' . $attrs['location'] . ' (' . count($this->import[$attrs['namespace']]).')'); - } else { - $this->import[$attrs['namespace']][] = array('location' => '', 'loaded' => true); - if (! $this->getPrefixFromNamespace($attrs['namespace'])) { - $this->namespaces['ns'.(count($this->namespaces)+1)] = $attrs['namespace']; - } - $this->debug('parsing import ' . $attrs['namespace']. ' - [no location] (' . count($this->import[$attrs['namespace']]).')'); - } - break; - //wait for schema - //case 'types': - // $this->status = 'schema'; - // break; - case 'message': - $this->status = 'message'; - $this->messages[$attrs['name']] = array(); - $this->currentMessage = $attrs['name']; - break; - case 'portType': - $this->status = 'portType'; - $this->portTypes[$attrs['name']] = array(); - $this->currentPortType = $attrs['name']; - break; - case "binding": - if (isset($attrs['name'])) { - // get binding name - if (strpos($attrs['name'], ':')) { - $this->currentBinding = $this->getLocalPart($attrs['name']); - } else { - $this->currentBinding = $attrs['name']; - } - $this->status = 'binding'; - $this->bindings[$this->currentBinding]['portType'] = $this->getLocalPart($attrs['type']); - $this->debug("current binding: $this->currentBinding of portType: " . $attrs['type']); - } - break; - case 'service': - $this->serviceName = $attrs['name']; - $this->status = 'service'; - $this->debug('current service: ' . $this->serviceName); - break; - case 'definitions': - foreach ($attrs as $name => $value) { - $this->wsdl_info[$name] = $value; - } - break; - } - } - } - - /** - * end-element handler - * - * @param string $parser XML parser object - * @param string $name element name - * @access private - */ - function end_element($parser, $name){ - // unset schema status - if (/*preg_match('/types$/', $name) ||*/ preg_match('/schema$/', $name)) { - $this->status = ""; - $this->appendDebug($this->currentSchema->getDebug()); - $this->currentSchema->clearDebug(); - $this->schemas[$this->currentSchema->schemaTargetNamespace][] = $this->currentSchema; - $this->debug('Parsing WSDL schema done'); - } - if ($this->status == 'schema') { - $this->currentSchema->schemaEndElement($parser, $name); - } else { - // bring depth down a notch - $this->depth--; - } - // end documentation - if ($this->documentation) { - //TODO: track the node to which documentation should be assigned; it can be a part, message, etc. - //$this->portTypes[$this->currentPortType][$this->currentPortOperation]['documentation'] = $this->documentation; - $this->documentation = false; - } - } - - /** - * element content handler - * - * @param string $parser XML parser object - * @param string $data element content - * @access private - */ - function character_data($parser, $data) - { - $pos = isset($this->depth_array[$this->depth]) ? $this->depth_array[$this->depth] : 0; - if (isset($this->message[$pos]['cdata'])) { - $this->message[$pos]['cdata'] .= $data; - } - if ($this->documentation) { - $this->documentation .= $data; - } - } - - /** - * if authenticating, set user credentials here - * - * @param string $username - * @param string $password - * @param string $authtype (basic|digest|certificate|ntlm) - * @param array $certRequest (keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, certpassword (optional), verifypeer (optional), verifyhost (optional): see corresponding options in cURL docs) - * @access public - */ - function setCredentials($username, $password, $authtype = 'basic', $certRequest = array()) { - $this->debug("setCredentials username=$username authtype=$authtype certRequest="); - $this->appendDebug($this->varDump($certRequest)); - $this->username = $username; - $this->password = $password; - $this->authtype = $authtype; - $this->certRequest = $certRequest; - } - - function getBindingData($binding) - { - if (is_array($this->bindings[$binding])) { - return $this->bindings[$binding]; - } - } - - /** - * returns an assoc array of operation names => operation data - * - * @param string $portName WSDL port name - * @param string $bindingType eg: soap, smtp, dime (only soap and soap12 are currently supported) - * @return array - * @access public - */ - function getOperations($portName = '', $bindingType = 'soap') { - $ops = array(); - if ($bindingType == 'soap') { - $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/'; - } elseif ($bindingType == 'soap12') { - $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/'; - } else { - $this->debug("getOperations bindingType $bindingType may not be supported"); - } - $this->debug("getOperations for port '$portName' bindingType $bindingType"); - // loop thru ports - foreach($this->ports as $port => $portData) { - $this->debug("getOperations checking port $port bindingType " . $portData['bindingType']); - if ($portName == '' || $port == $portName) { - // binding type of port matches parameter - if ($portData['bindingType'] == $bindingType) { - $this->debug("getOperations found port $port bindingType $bindingType"); - //$this->debug("port data: " . $this->varDump($portData)); - //$this->debug("bindings: " . $this->varDump($this->bindings[ $portData['binding'] ])); - // merge bindings - if (isset($this->bindings[ $portData['binding'] ]['operations'])) { - $ops = array_merge ($ops, $this->bindings[ $portData['binding'] ]['operations']); - } - } - } - } - if (count($ops) == 0) { - $this->debug("getOperations found no operations for port '$portName' bindingType $bindingType"); - } - return $ops; - } - - /** - * returns an associative array of data necessary for calling an operation - * - * @param string $operation name of operation - * @param string $bindingType type of binding eg: soap, soap12 - * @return array - * @access public - */ - function getOperationData($operation, $bindingType = 'soap') - { - if ($bindingType == 'soap') { - $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/'; - } elseif ($bindingType == 'soap12') { - $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/'; - } - // loop thru ports - foreach($this->ports as $port => $portData) { - // binding type of port matches parameter - if ($portData['bindingType'] == $bindingType) { - // get binding - //foreach($this->bindings[ $portData['binding'] ]['operations'] as $bOperation => $opData) { - foreach(array_keys($this->bindings[ $portData['binding'] ]['operations']) as $bOperation) { - // note that we could/should also check the namespace here - if ($operation == $bOperation) { - $opData = $this->bindings[ $portData['binding'] ]['operations'][$operation]; - return $opData; - } - } - } - } - } - - /** - * returns an associative array of data necessary for calling an operation - * - * @param string $soapAction soapAction for operation - * @param string $bindingType type of binding eg: soap, soap12 - * @return array - * @access public - */ - function getOperationDataForSoapAction($soapAction, $bindingType = 'soap') { - if ($bindingType == 'soap') { - $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/'; - } elseif ($bindingType == 'soap12') { - $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/'; - } - // loop thru ports - foreach($this->ports as $port => $portData) { - // binding type of port matches parameter - if ($portData['bindingType'] == $bindingType) { - // loop through operations for the binding - foreach ($this->bindings[ $portData['binding'] ]['operations'] as $bOperation => $opData) { - if ($opData['soapAction'] == $soapAction) { - return $opData; - } - } - } - } - } - - /** - * returns an array of information about a given type - * returns false if no type exists by the given name - * - * typeDef = array( - * 'elements' => array(), // refs to elements array - * 'restrictionBase' => '', - * 'phpType' => '', - * 'order' => '(sequence|all)', - * 'attrs' => array() // refs to attributes array - * ) - * - * @param string $type the type - * @param string $ns namespace (not prefix) of the type - * @return mixed - * @access public - * @see nusoap_xmlschema - */ - function getTypeDef($type, $ns) { - $this->debug("in getTypeDef: type=$type, ns=$ns"); - if ((! $ns) && isset($this->namespaces['tns'])) { - $ns = $this->namespaces['tns']; - $this->debug("in getTypeDef: type namespace forced to $ns"); - } - if (!isset($this->schemas[$ns])) { - foreach ($this->schemas as $ns0 => $schema0) { - if (strcasecmp($ns, $ns0) == 0) { - $this->debug("in getTypeDef: replacing schema namespace $ns with $ns0"); - $ns = $ns0; - break; - } - } - } - if (isset($this->schemas[$ns])) { - $this->debug("in getTypeDef: have schema for namespace $ns"); - for ($i = 0; $i < count($this->schemas[$ns]); $i++) { - $xs = &$this->schemas[$ns][$i]; - $t = $xs->getTypeDef($type); - $this->appendDebug($xs->getDebug()); - $xs->clearDebug(); - if ($t) { - $this->debug("in getTypeDef: found type $type"); - if (!isset($t['phpType'])) { - // get info for type to tack onto the element - $uqType = substr($t['type'], strrpos($t['type'], ':') + 1); - $ns = substr($t['type'], 0, strrpos($t['type'], ':')); - $etype = $this->getTypeDef($uqType, $ns); - if ($etype) { - $this->debug("found type for [element] $type:"); - $this->debug($this->varDump($etype)); - if (isset($etype['phpType'])) { - $t['phpType'] = $etype['phpType']; - } - if (isset($etype['elements'])) { - $t['elements'] = $etype['elements']; - } - if (isset($etype['attrs'])) { - $t['attrs'] = $etype['attrs']; - } - } else { - $this->debug("did not find type for [element] $type"); - } - } - return $t; - } - } - $this->debug("in getTypeDef: did not find type $type"); - } else { - $this->debug("in getTypeDef: do not have schema for namespace $ns"); - } - return false; - } - - /** - * prints html description of services - * - * @access private - */ - function webDescription(){ - global $HTTP_SERVER_VARS; - - if (isset($_SERVER)) { - $PHP_SELF = $_SERVER['PHP_SELF']; - } elseif (isset($HTTP_SERVER_VARS)) { - $PHP_SELF = $HTTP_SERVER_VARS['PHP_SELF']; - } else { - $this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available"); - } - - $b = ' - NuSOAP: '.$this->serviceName.' - - - - -
-

-
'.$this->serviceName.'
- -
'; - return $b; - } - - /** - * serialize the parsed wsdl - * - * @param mixed $debug whether to put debug=1 in endpoint URL - * @return string serialization of WSDL - * @access public - */ - function serialize($debug = 0) - { - $xml = ''; - $xml .= "\nnamespaces as $k => $v) { - $xml .= " xmlns:$k=\"$v\""; - } - // 10.9.02 - add poulter fix for wsdl and tns declarations - if (isset($this->namespaces['wsdl'])) { - $xml .= " xmlns=\"" . $this->namespaces['wsdl'] . "\""; - } - if (isset($this->namespaces['tns'])) { - $xml .= " targetNamespace=\"" . $this->namespaces['tns'] . "\""; - } - $xml .= '>'; - // imports - if (sizeof($this->import) > 0) { - foreach($this->import as $ns => $list) { - foreach ($list as $ii) { - if ($ii['location'] != '') { - $xml .= ''; - } else { - $xml .= ''; - } - } - } - } - // types - if (count($this->schemas)>=1) { - $xml .= "\n\n"; - foreach ($this->schemas as $ns => $list) { - foreach ($list as $xs) { - $xml .= $xs->serializeSchema(); - } - } - $xml .= ''; - } - // messages - if (count($this->messages) >= 1) { - foreach($this->messages as $msgName => $msgParts) { - $xml .= "\n'; - if(is_array($msgParts)){ - foreach($msgParts as $partName => $partType) { - // print 'serializing '.$partType.', sv: '.$this->XMLSchemaVersion.'
'; - if (strpos($partType, ':')) { - $typePrefix = $this->getPrefixFromNamespace($this->getPrefix($partType)); - } elseif (isset($this->typemap[$this->namespaces['xsd']][$partType])) { - // print 'checking typemap: '.$this->XMLSchemaVersion.'
'; - $typePrefix = 'xsd'; - } else { - foreach($this->typemap as $ns => $types) { - if (isset($types[$partType])) { - $typePrefix = $this->getPrefixFromNamespace($ns); - } - } - if (!isset($typePrefix)) { - die("$partType has no namespace!"); - } - } - $ns = $this->getNamespaceFromPrefix($typePrefix); - $localPart = $this->getLocalPart($partType); - $typeDef = $this->getTypeDef($localPart, $ns); - if ($typeDef['typeClass'] == 'element') { - $elementortype = 'element'; - if (substr($localPart, -1) == '^') { - $localPart = substr($localPart, 0, -1); - } - } else { - $elementortype = 'type'; - } - $xml .= "\n" . ' '; - } - } - $xml .= '
'; - } - } - // bindings & porttypes - if (count($this->bindings) >= 1) { - $binding_xml = ''; - $portType_xml = ''; - foreach($this->bindings as $bindingName => $attrs) { - $binding_xml .= "\n'; - $binding_xml .= "\n" . ' '; - $portType_xml .= "\n'; - foreach($attrs['operations'] as $opName => $opParts) { - $binding_xml .= "\n" . ' '; - $binding_xml .= "\n" . ' '; - if (isset($opParts['input']['encodingStyle']) && $opParts['input']['encodingStyle'] != '') { - $enc_style = ' encodingStyle="' . $opParts['input']['encodingStyle'] . '"'; - } else { - $enc_style = ''; - } - $binding_xml .= "\n" . ' '; - if (isset($opParts['output']['encodingStyle']) && $opParts['output']['encodingStyle'] != '') { - $enc_style = ' encodingStyle="' . $opParts['output']['encodingStyle'] . '"'; - } else { - $enc_style = ''; - } - $binding_xml .= "\n" . ' '; - $binding_xml .= "\n" . ' '; - $portType_xml .= "\n" . ' ' . htmlspecialchars($opParts['documentation']) . ''; - } - $portType_xml .= "\n" . ' '; - $portType_xml .= "\n" . ' '; - $portType_xml .= "\n" . ' '; - } - $portType_xml .= "\n" . ''; - $binding_xml .= "\n" . ''; - } - $xml .= $portType_xml . $binding_xml; - } - // services - $xml .= "\nserviceName . '">'; - if (count($this->ports) >= 1) { - foreach($this->ports as $pName => $attrs) { - $xml .= "\n" . ' '; - $xml .= "\n" . ' '; - $xml .= "\n" . ' '; - } - } - $xml .= "\n" . ''; - return $xml . "\n"; - } - - /** - * determine whether a set of parameters are unwrapped - * when they are expect to be wrapped, Microsoft-style. - * - * @param string $type the type (element name) of the wrapper - * @param array $parameters the parameter values for the SOAP call - * @return boolean whether they parameters are unwrapped (and should be wrapped) - * @access private - */ - function parametersMatchWrapped($type, &$parameters) { - $this->debug("in parametersMatchWrapped type=$type, parameters="); - $this->appendDebug($this->varDump($parameters)); - - // split type into namespace:unqualified-type - if (strpos($type, ':')) { - $uqType = substr($type, strrpos($type, ':') + 1); - $ns = substr($type, 0, strrpos($type, ':')); - $this->debug("in parametersMatchWrapped: got a prefixed type: $uqType, $ns"); - if ($this->getNamespaceFromPrefix($ns)) { - $ns = $this->getNamespaceFromPrefix($ns); - $this->debug("in parametersMatchWrapped: expanded prefixed type: $uqType, $ns"); - } - } else { - // TODO: should the type be compared to types in XSD, and the namespace - // set to XSD if the type matches? - $this->debug("in parametersMatchWrapped: No namespace for type $type"); - $ns = ''; - $uqType = $type; - } - - // get the type information - if (!$typeDef = $this->getTypeDef($uqType, $ns)) { - $this->debug("in parametersMatchWrapped: $type ($uqType) is not a supported type."); - return false; - } - $this->debug("in parametersMatchWrapped: found typeDef="); - $this->appendDebug($this->varDump($typeDef)); - if (substr($uqType, -1) == '^') { - $uqType = substr($uqType, 0, -1); - } - $phpType = $typeDef['phpType']; - $arrayType = (isset($typeDef['arrayType']) ? $typeDef['arrayType'] : ''); - $this->debug("in parametersMatchWrapped: uqType: $uqType, ns: $ns, phptype: $phpType, arrayType: $arrayType"); - - // we expect a complexType or element of complexType - if ($phpType != 'struct') { - $this->debug("in parametersMatchWrapped: not a struct"); - return false; - } - - // see whether the parameter names match the elements - if (isset($typeDef['elements']) && is_array($typeDef['elements'])) { - $elements = 0; - $matches = 0; - foreach ($typeDef['elements'] as $name => $attrs) { - if (isset($parameters[$name])) { - $this->debug("in parametersMatchWrapped: have parameter named $name"); - $matches++; - } else { - $this->debug("in parametersMatchWrapped: do not have parameter named $name"); - } - $elements++; - } - - $this->debug("in parametersMatchWrapped: $matches parameter names match $elements wrapped parameter names"); - if ($matches == 0) { - return false; - } - return true; - } - - // since there are no elements for the type, if the user passed no - // parameters, the parameters match wrapped. - $this->debug("in parametersMatchWrapped: no elements type $ns:$uqType"); - return count($parameters) == 0; - } - - /** - * serialize PHP values according to a WSDL message definition - * contrary to the method name, this is not limited to RPC - * - * TODO - * - multi-ref serialization - * - validate PHP values against type definitions, return errors if invalid - * - * @param string $operation operation name - * @param string $direction (input|output) - * @param mixed $parameters parameter value(s) - * @param string $bindingType (soap|soap12) - * @return mixed parameters serialized as XML or false on error (e.g. operation not found) - * @access public - */ - function serializeRPCParameters($operation, $direction, $parameters, $bindingType = 'soap') { - $this->debug("in serializeRPCParameters: operation=$operation, direction=$direction, XMLSchemaVersion=$this->XMLSchemaVersion, bindingType=$bindingType"); - $this->appendDebug('parameters=' . $this->varDump($parameters)); - - if ($direction != 'input' && $direction != 'output') { - $this->debug('The value of the \$direction argument needs to be either "input" or "output"'); - $this->setError('The value of the \$direction argument needs to be either "input" or "output"'); - return false; - } - if (!$opData = $this->getOperationData($operation, $bindingType)) { - $this->debug('Unable to retrieve WSDL data for operation: ' . $operation . ' bindingType: ' . $bindingType); - $this->setError('Unable to retrieve WSDL data for operation: ' . $operation . ' bindingType: ' . $bindingType); - return false; - } - $this->debug('in serializeRPCParameters: opData:'); - $this->appendDebug($this->varDump($opData)); - - // Get encoding style for output and set to current - $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/'; - if(($direction == 'input') && isset($opData['output']['encodingStyle']) && ($opData['output']['encodingStyle'] != $encodingStyle)) { - $encodingStyle = $opData['output']['encodingStyle']; - $enc_style = $encodingStyle; - } - - // set input params - $xml = ''; - if (isset($opData[$direction]['parts']) && sizeof($opData[$direction]['parts']) > 0) { - $parts = &$opData[$direction]['parts']; - $part_count = sizeof($parts); - $style = $opData['style']; - $use = $opData[$direction]['use']; - $this->debug("have $part_count part(s) to serialize using $style/$use"); - if (is_array($parameters)) { - $parametersArrayType = $this->isArraySimpleOrStruct($parameters); - $parameter_count = count($parameters); - $this->debug("have $parameter_count parameter(s) provided as $parametersArrayType to serialize"); - // check for Microsoft-style wrapped parameters - if ($style == 'document' && $use == 'literal' && $part_count == 1 && isset($parts['parameters'])) { - $this->debug('check whether the caller has wrapped the parameters'); - if ($direction == 'output' && $parametersArrayType == 'arraySimple' && $parameter_count == 1) { - // TODO: consider checking here for double-wrapping, when - // service function wraps, then NuSOAP wraps again - $this->debug("change simple array to associative with 'parameters' element"); - $parameters['parameters'] = $parameters[0]; - unset($parameters[0]); - } - if (($parametersArrayType == 'arrayStruct' || $parameter_count == 0) && !isset($parameters['parameters'])) { - $this->debug('check whether caller\'s parameters match the wrapped ones'); - if ($this->parametersMatchWrapped($parts['parameters'], $parameters)) { - $this->debug('wrap the parameters for the caller'); - $parameters = array('parameters' => $parameters); - $parameter_count = 1; - } - } - } - foreach ($parts as $name => $type) { - $this->debug("serializing part $name of type $type"); - // Track encoding style - if (isset($opData[$direction]['encodingStyle']) && $encodingStyle != $opData[$direction]['encodingStyle']) { - $encodingStyle = $opData[$direction]['encodingStyle']; - $enc_style = $encodingStyle; - } else { - $enc_style = false; - } - // NOTE: add error handling here - // if serializeType returns false, then catch global error and fault - if ($parametersArrayType == 'arraySimple') { - $p = array_shift($parameters); - $this->debug('calling serializeType w/indexed param'); - $xml .= $this->serializeType($name, $type, $p, $use, $enc_style); - } elseif (isset($parameters[$name])) { - $this->debug('calling serializeType w/named param'); - $xml .= $this->serializeType($name, $type, $parameters[$name], $use, $enc_style); - } else { - // TODO: only send nillable - $this->debug('calling serializeType w/null param'); - $xml .= $this->serializeType($name, $type, null, $use, $enc_style); - } - } - } else { - $this->debug('no parameters passed.'); - } - } - $this->debug("serializeRPCParameters returning: $xml"); - return $xml; - } - - /** - * serialize a PHP value according to a WSDL message definition - * - * TODO - * - multi-ref serialization - * - validate PHP values against type definitions, return errors if invalid - * - * @param string $operation operation name - * @param string $direction (input|output) - * @param mixed $parameters parameter value(s) - * @return mixed parameters serialized as XML or false on error (e.g. operation not found) - * @access public - * @deprecated - */ - function serializeParameters($operation, $direction, $parameters) - { - $this->debug("in serializeParameters: operation=$operation, direction=$direction, XMLSchemaVersion=$this->XMLSchemaVersion"); - $this->appendDebug('parameters=' . $this->varDump($parameters)); - - if ($direction != 'input' && $direction != 'output') { - $this->debug('The value of the \$direction argument needs to be either "input" or "output"'); - $this->setError('The value of the \$direction argument needs to be either "input" or "output"'); - return false; - } - if (!$opData = $this->getOperationData($operation)) { - $this->debug('Unable to retrieve WSDL data for operation: ' . $operation); - $this->setError('Unable to retrieve WSDL data for operation: ' . $operation); - return false; - } - $this->debug('opData:'); - $this->appendDebug($this->varDump($opData)); - - // Get encoding style for output and set to current - $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/'; - if(($direction == 'input') && isset($opData['output']['encodingStyle']) && ($opData['output']['encodingStyle'] != $encodingStyle)) { - $encodingStyle = $opData['output']['encodingStyle']; - $enc_style = $encodingStyle; - } - - // set input params - $xml = ''; - if (isset($opData[$direction]['parts']) && sizeof($opData[$direction]['parts']) > 0) { - - $use = $opData[$direction]['use']; - $this->debug("use=$use"); - $this->debug('got ' . count($opData[$direction]['parts']) . ' part(s)'); - if (is_array($parameters)) { - $parametersArrayType = $this->isArraySimpleOrStruct($parameters); - $this->debug('have ' . $parametersArrayType . ' parameters'); - foreach($opData[$direction]['parts'] as $name => $type) { - $this->debug('serializing part "'.$name.'" of type "'.$type.'"'); - // Track encoding style - if(isset($opData[$direction]['encodingStyle']) && $encodingStyle != $opData[$direction]['encodingStyle']) { - $encodingStyle = $opData[$direction]['encodingStyle']; - $enc_style = $encodingStyle; - } else { - $enc_style = false; - } - // NOTE: add error handling here - // if serializeType returns false, then catch global error and fault - if ($parametersArrayType == 'arraySimple') { - $p = array_shift($parameters); - $this->debug('calling serializeType w/indexed param'); - $xml .= $this->serializeType($name, $type, $p, $use, $enc_style); - } elseif (isset($parameters[$name])) { - $this->debug('calling serializeType w/named param'); - $xml .= $this->serializeType($name, $type, $parameters[$name], $use, $enc_style); - } else { - // TODO: only send nillable - $this->debug('calling serializeType w/null param'); - $xml .= $this->serializeType($name, $type, null, $use, $enc_style); - } - } - } else { - $this->debug('no parameters passed.'); - } - } - $this->debug("serializeParameters returning: $xml"); - return $xml; - } - - /** - * serializes a PHP value according a given type definition - * - * @param string $name name of value (part or element) - * @param string $type XML schema type of value (type or element) - * @param mixed $value a native PHP value (parameter value) - * @param string $use use for part (encoded|literal) - * @param string $encodingStyle SOAP encoding style for the value (if different than the enclosing style) - * @param boolean $unqualified a kludge for what should be XML namespace form handling - * @return string value serialized as an XML string - * @access private - */ - function serializeType($name, $type, $value, $use='encoded', $encodingStyle=false, $unqualified=false) - { - $this->debug("in serializeType: name=$name, type=$type, use=$use, encodingStyle=$encodingStyle, unqualified=" . ($unqualified ? "unqualified" : "qualified")); - $this->appendDebug("value=" . $this->varDump($value)); - if($use == 'encoded' && $encodingStyle) { - $encodingStyle = ' SOAP-ENV:encodingStyle="' . $encodingStyle . '"'; - } - - // if a soapval has been supplied, let its type override the WSDL - if (is_object($value) && get_class($value) == 'soapval') { - if ($value->type_ns) { - $type = $value->type_ns . ':' . $value->type; - $forceType = true; - $this->debug("in serializeType: soapval overrides type to $type"); - } elseif ($value->type) { - $type = $value->type; - $forceType = true; - $this->debug("in serializeType: soapval overrides type to $type"); - } else { - $forceType = false; - $this->debug("in serializeType: soapval does not override type"); - } - $attrs = $value->attributes; - $value = $value->value; - $this->debug("in serializeType: soapval overrides value to $value"); - if ($attrs) { - if (!is_array($value)) { - $value['!'] = $value; - } - foreach ($attrs as $n => $v) { - $value['!' . $n] = $v; - } - $this->debug("in serializeType: soapval provides attributes"); - } - } else { - $forceType = false; - } - - $xml = ''; - if (strpos($type, ':')) { - $uqType = substr($type, strrpos($type, ':') + 1); - $ns = substr($type, 0, strrpos($type, ':')); - $this->debug("in serializeType: got a prefixed type: $uqType, $ns"); - if ($this->getNamespaceFromPrefix($ns)) { - $ns = $this->getNamespaceFromPrefix($ns); - $this->debug("in serializeType: expanded prefixed type: $uqType, $ns"); - } - - if($ns == $this->XMLSchemaVersion || $ns == 'http://schemas.xmlsoap.org/soap/encoding/'){ - $this->debug('in serializeType: type namespace indicates XML Schema or SOAP Encoding type'); - if ($unqualified && $use == 'literal') { - $elementNS = " xmlns=\"\""; - } else { - $elementNS = ''; - } - if (is_null($value)) { - if ($use == 'literal') { - // TODO: depends on minOccurs - $xml = "<$name$elementNS/>"; - } else { - // TODO: depends on nillable, which should be checked before calling this method - $xml = "<$name$elementNS xsi:nil=\"true\" xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"/>"; - } - $this->debug("in serializeType: returning: $xml"); - return $xml; - } - if ($uqType == 'Array') { - // JBoss/Axis does this sometimes - return $this->serialize_val($value, $name, false, false, false, false, $use); - } - if ($uqType == 'boolean') { - if ((is_string($value) && $value == 'false') || (! $value)) { - $value = 'false'; - } else { - $value = 'true'; - } - } - if ($uqType == 'string' && gettype($value) == 'string') { - $value = $this->expandEntities($value); - } - if (($uqType == 'long' || $uqType == 'unsignedLong') && gettype($value) == 'double') { - $value = sprintf("%.0lf", $value); - } - // it's a scalar - // TODO: what about null/nil values? - // check type isn't a custom type extending xmlschema namespace - if (!$this->getTypeDef($uqType, $ns)) { - if ($use == 'literal') { - if ($forceType) { - $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">$value"; - } else { - $xml = "<$name$elementNS>$value"; - } - } else { - $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>$value"; - } - $this->debug("in serializeType: returning: $xml"); - return $xml; - } - $this->debug('custom type extends XML Schema or SOAP Encoding namespace (yuck)'); - } else if ($ns == 'http://xml.apache.org/xml-soap') { - $this->debug('in serializeType: appears to be Apache SOAP type'); - if ($uqType == 'Map') { - $tt_prefix = $this->getPrefixFromNamespace('http://xml.apache.org/xml-soap'); - if (! $tt_prefix) { - $this->debug('in serializeType: Add namespace for Apache SOAP type'); - $tt_prefix = 'ns' . rand(1000, 9999); - $this->namespaces[$tt_prefix] = 'http://xml.apache.org/xml-soap'; - // force this to be added to usedNamespaces - $tt_prefix = $this->getPrefixFromNamespace('http://xml.apache.org/xml-soap'); - } - $contents = ''; - foreach($value as $k => $v) { - $this->debug("serializing map element: key $k, value $v"); - $contents .= ''; - $contents .= $this->serialize_val($k,'key',false,false,false,false,$use); - $contents .= $this->serialize_val($v,'value',false,false,false,false,$use); - $contents .= ''; - } - if ($use == 'literal') { - if ($forceType) { - $xml = "<$name xsi:type=\"" . $tt_prefix . ":$uqType\">$contents"; - } else { - $xml = "<$name>$contents"; - } - } else { - $xml = "<$name xsi:type=\"" . $tt_prefix . ":$uqType\"$encodingStyle>$contents"; - } - $this->debug("in serializeType: returning: $xml"); - return $xml; - } - $this->debug('in serializeType: Apache SOAP type, but only support Map'); - } - } else { - // TODO: should the type be compared to types in XSD, and the namespace - // set to XSD if the type matches? - $this->debug("in serializeType: No namespace for type $type"); - $ns = ''; - $uqType = $type; - } - if(!$typeDef = $this->getTypeDef($uqType, $ns)){ - $this->setError("$type ($uqType) is not a supported type."); - $this->debug("in serializeType: $type ($uqType) is not a supported type."); - return false; - } else { - $this->debug("in serializeType: found typeDef"); - $this->appendDebug('typeDef=' . $this->varDump($typeDef)); - if (substr($uqType, -1) == '^') { - $uqType = substr($uqType, 0, -1); - } - } - if (!isset($typeDef['phpType'])) { - $this->setError("$type ($uqType) has no phpType."); - $this->debug("in serializeType: $type ($uqType) has no phpType."); - return false; - } - $phpType = $typeDef['phpType']; - $this->debug("in serializeType: uqType: $uqType, ns: $ns, phptype: $phpType, arrayType: " . (isset($typeDef['arrayType']) ? $typeDef['arrayType'] : '') ); - // if php type == struct, map value to the element names - if ($phpType == 'struct') { - if (isset($typeDef['typeClass']) && $typeDef['typeClass'] == 'element') { - $elementName = $uqType; - if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) { - $elementNS = " xmlns=\"$ns\""; - } else { - $elementNS = " xmlns=\"\""; - } - } else { - $elementName = $name; - if ($unqualified) { - $elementNS = " xmlns=\"\""; - } else { - $elementNS = ''; - } - } - if (is_null($value)) { - if ($use == 'literal') { - // TODO: depends on minOccurs and nillable - $xml = "<$elementName$elementNS/>"; - } else { - $xml = "<$elementName$elementNS xsi:nil=\"true\" xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"/>"; - } - $this->debug("in serializeType: returning: $xml"); - return $xml; - } - if (is_object($value)) { - $value = get_object_vars($value); - } - if (is_array($value)) { - $elementAttrs = $this->serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType); - if ($use == 'literal') { - if ($forceType) { - $xml = "<$elementName$elementNS$elementAttrs xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">"; - } else { - $xml = "<$elementName$elementNS$elementAttrs>"; - } - } else { - $xml = "<$elementName$elementNS$elementAttrs xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>"; - } - - if (isset($typeDef['simpleContent']) && $typeDef['simpleContent'] == 'true') { - if (isset($value['!'])) { - $xml .= $value['!']; - $this->debug("in serializeType: serialized simpleContent for type $type"); - } else { - $this->debug("in serializeType: no simpleContent to serialize for type $type"); - } - } else { - // complexContent - $xml .= $this->serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use, $encodingStyle); - } - $xml .= ""; - } else { - $this->debug("in serializeType: phpType is struct, but value is not an array"); - $this->setError("phpType is struct, but value is not an array: see debug output for details"); - $xml = ''; - } - } elseif ($phpType == 'array') { - if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) { - $elementNS = " xmlns=\"$ns\""; - } else { - if ($unqualified) { - $elementNS = " xmlns=\"\""; - } else { - $elementNS = ''; - } - } - if (is_null($value)) { - if ($use == 'literal') { - // TODO: depends on minOccurs - $xml = "<$name$elementNS/>"; - } else { - $xml = "<$name$elementNS xsi:nil=\"true\" xsi:type=\"" . - $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/') . - ":Array\" " . - $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/') . - ':arrayType="' . - $this->getPrefixFromNamespace($this->getPrefix($typeDef['arrayType'])) . - ':' . - $this->getLocalPart($typeDef['arrayType'])."[0]\"/>"; - } - $this->debug("in serializeType: returning: $xml"); - return $xml; - } - if (isset($typeDef['multidimensional'])) { - $nv = array(); - foreach($value as $v) { - $cols = ',' . sizeof($v); - $nv = array_merge($nv, $v); - } - $value = $nv; - } else { - $cols = ''; - } - if (is_array($value) && sizeof($value) >= 1) { - $rows = sizeof($value); - $contents = ''; - foreach($value as $k => $v) { - $this->debug("serializing array element: $k, $v of type: $typeDef[arrayType]"); - //if (strpos($typeDef['arrayType'], ':') ) { - if (!in_array($typeDef['arrayType'],$this->typemap['http://www.w3.org/2001/XMLSchema'])) { - $contents .= $this->serializeType('item', $typeDef['arrayType'], $v, $use); - } else { - $contents .= $this->serialize_val($v, 'item', $typeDef['arrayType'], null, $this->XMLSchemaVersion, false, $use); - } - } - } else { - $rows = 0; - $contents = null; - } - // TODO: for now, an empty value will be serialized as a zero element - // array. Revisit this when coding the handling of null/nil values. - if ($use == 'literal') { - $xml = "<$name$elementNS>" - .$contents - .""; - } else { - $xml = "<$name$elementNS xsi:type=\"".$this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/').':Array" '. - $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/') - .':arrayType="' - .$this->getPrefixFromNamespace($this->getPrefix($typeDef['arrayType'])) - .":".$this->getLocalPart($typeDef['arrayType'])."[$rows$cols]\">" - .$contents - .""; - } - } elseif ($phpType == 'scalar') { - if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) { - $elementNS = " xmlns=\"$ns\""; - } else { - if ($unqualified) { - $elementNS = " xmlns=\"\""; - } else { - $elementNS = ''; - } - } - if ($use == 'literal') { - if ($forceType) { - $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">$value"; - } else { - $xml = "<$name$elementNS>$value"; - } - } else { - $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>$value"; - } - } - $this->debug("in serializeType: returning: $xml"); - return $xml; - } - - /** - * serializes the attributes for a complexType - * - * @param array $typeDef our internal representation of an XML schema type (or element) - * @param mixed $value a native PHP value (parameter value) - * @param string $ns the namespace of the type - * @param string $uqType the local part of the type - * @return string value serialized as an XML string - * @access private - */ - function serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType) { - $this->debug("serializeComplexTypeAttributes for XML Schema type $ns:$uqType"); - $xml = ''; - if (isset($typeDef['extensionBase'])) { - $nsx = $this->getPrefix($typeDef['extensionBase']); - $uqTypex = $this->getLocalPart($typeDef['extensionBase']); - if ($this->getNamespaceFromPrefix($nsx)) { - $nsx = $this->getNamespaceFromPrefix($nsx); - } - if ($typeDefx = $this->getTypeDef($uqTypex, $nsx)) { - $this->debug("serialize attributes for extension base $nsx:$uqTypex"); - $xml .= $this->serializeComplexTypeAttributes($typeDefx, $value, $nsx, $uqTypex); - } else { - $this->debug("extension base $nsx:$uqTypex is not a supported type"); - } - } - if (isset($typeDef['attrs']) && is_array($typeDef['attrs'])) { - $this->debug("serialize attributes for XML Schema type $ns:$uqType"); - if (is_array($value)) { - $xvalue = $value; - } elseif (is_object($value)) { - $xvalue = get_object_vars($value); - } else { - $this->debug("value is neither an array nor an object for XML Schema type $ns:$uqType"); - $xvalue = array(); - } - foreach ($typeDef['attrs'] as $aName => $attrs) { - if (isset($xvalue['!' . $aName])) { - $xname = '!' . $aName; - $this->debug("value provided for attribute $aName with key $xname"); - } elseif (isset($xvalue[$aName])) { - $xname = $aName; - $this->debug("value provided for attribute $aName with key $xname"); - } elseif (isset($attrs['default'])) { - $xname = '!' . $aName; - $xvalue[$xname] = $attrs['default']; - $this->debug('use default value of ' . $xvalue[$aName] . ' for attribute ' . $aName); - } else { - $xname = ''; - $this->debug("no value provided for attribute $aName"); - } - if ($xname) { - $xml .= " $aName=\"" . $this->expandEntities($xvalue[$xname]) . "\""; - } - } - } else { - $this->debug("no attributes to serialize for XML Schema type $ns:$uqType"); - } - return $xml; - } - - /** - * serializes the elements for a complexType - * - * @param array $typeDef our internal representation of an XML schema type (or element) - * @param mixed $value a native PHP value (parameter value) - * @param string $ns the namespace of the type - * @param string $uqType the local part of the type - * @param string $use use for part (encoded|literal) - * @param string $encodingStyle SOAP encoding style for the value (if different than the enclosing style) - * @return string value serialized as an XML string - * @access private - */ - function serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use='encoded', $encodingStyle=false) { - $this->debug("in serializeComplexTypeElements for XML Schema type $ns:$uqType"); - $xml = ''; - if (isset($typeDef['extensionBase'])) { - $nsx = $this->getPrefix($typeDef['extensionBase']); - $uqTypex = $this->getLocalPart($typeDef['extensionBase']); - if ($this->getNamespaceFromPrefix($nsx)) { - $nsx = $this->getNamespaceFromPrefix($nsx); - } - if ($typeDefx = $this->getTypeDef($uqTypex, $nsx)) { - $this->debug("serialize elements for extension base $nsx:$uqTypex"); - $xml .= $this->serializeComplexTypeElements($typeDefx, $value, $nsx, $uqTypex, $use, $encodingStyle); - } else { - $this->debug("extension base $nsx:$uqTypex is not a supported type"); - } - } - if (isset($typeDef['elements']) && is_array($typeDef['elements'])) { - $this->debug("in serializeComplexTypeElements, serialize elements for XML Schema type $ns:$uqType"); - if (is_array($value)) { - $xvalue = $value; - } elseif (is_object($value)) { - $xvalue = get_object_vars($value); - } else { - $this->debug("value is neither an array nor an object for XML Schema type $ns:$uqType"); - $xvalue = array(); - } - // toggle whether all elements are present - ideally should validate against schema - if (count($typeDef['elements']) != count($xvalue)){ - $optionals = true; - } - foreach ($typeDef['elements'] as $eName => $attrs) { - if (!isset($xvalue[$eName])) { - if (isset($attrs['default'])) { - $xvalue[$eName] = $attrs['default']; - $this->debug('use default value of ' . $xvalue[$eName] . ' for element ' . $eName); - } - } - // if user took advantage of a minOccurs=0, then only serialize named parameters - if (isset($optionals) - && (!isset($xvalue[$eName])) - && ( (!isset($attrs['nillable'])) || $attrs['nillable'] != 'true') - ){ - if (isset($attrs['minOccurs']) && $attrs['minOccurs'] <> '0') { - $this->debug("apparent error: no value provided for element $eName with minOccurs=" . $attrs['minOccurs']); - } - // do nothing - $this->debug("no value provided for complexType element $eName and element is not nillable, so serialize nothing"); - } else { - // get value - if (isset($xvalue[$eName])) { - $v = $xvalue[$eName]; - } else { - $v = null; - } - if (isset($attrs['form'])) { - $unqualified = ($attrs['form'] == 'unqualified'); - } else { - $unqualified = false; - } - if (isset($attrs['maxOccurs']) && ($attrs['maxOccurs'] == 'unbounded' || $attrs['maxOccurs'] > 1) && isset($v) && is_array($v) && $this->isArraySimpleOrStruct($v) == 'arraySimple') { - $vv = $v; - foreach ($vv as $k => $v) { - if (isset($attrs['type']) || isset($attrs['ref'])) { - // serialize schema-defined type - $xml .= $this->serializeType($eName, isset($attrs['type']) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified); - } else { - // serialize generic type (can this ever really happen?) - $this->debug("calling serialize_val() for $v, $eName, false, false, false, false, $use"); - $xml .= $this->serialize_val($v, $eName, false, false, false, false, $use); - } - } - } else { - if (is_null($v) && isset($attrs['minOccurs']) && $attrs['minOccurs'] == '0') { - // do nothing - } elseif (is_null($v) && isset($attrs['nillable']) && $attrs['nillable'] == 'true') { - // TODO: serialize a nil correctly, but for now serialize schema-defined type - $xml .= $this->serializeType($eName, isset($attrs['type']) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified); - } elseif (isset($attrs['type']) || isset($attrs['ref'])) { - // serialize schema-defined type - $xml .= $this->serializeType($eName, isset($attrs['type']) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified); - } else { - // serialize generic type (can this ever really happen?) - $this->debug("calling serialize_val() for $v, $eName, false, false, false, false, $use"); - $xml .= $this->serialize_val($v, $eName, false, false, false, false, $use); - } - } - } - } - } else { - $this->debug("no elements to serialize for XML Schema type $ns:$uqType"); - } - return $xml; - } - - /** - * adds an XML Schema complex type to the WSDL types - * - * @param string $name - * @param string $typeClass (complexType|simpleType|attribute) - * @param string $phpType currently supported are array and struct (php assoc array) - * @param string $compositor (all|sequence|choice) - * @param string $restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array) - * @param array $elements e.g. array ( name => array(name=>'',type=>'') ) - * @param array $attrs e.g. array(array('ref'=>'SOAP-ENC:arrayType','wsdl:arrayType'=>'xsd:string[]')) - * @param string $arrayType as namespace:name (xsd:string) - * @see nusoap_xmlschema - * @access public - */ - function addComplexType($name,$typeClass='complexType',$phpType='array',$compositor='',$restrictionBase='',$elements=array(),$attrs=array(),$arrayType='') { - if (count($elements) > 0) { - $eElements = array(); - foreach($elements as $n => $e){ - // expand each element - $ee = array(); - foreach ($e as $k => $v) { - $k = strpos($k,':') ? $this->expandQname($k) : $k; - $v = strpos($v,':') ? $this->expandQname($v) : $v; - $ee[$k] = $v; - } - $eElements[$n] = $ee; - } - $elements = $eElements; - } - - if (count($attrs) > 0) { - foreach($attrs as $n => $a){ - // expand each attribute - foreach ($a as $k => $v) { - $k = strpos($k,':') ? $this->expandQname($k) : $k; - $v = strpos($v,':') ? $this->expandQname($v) : $v; - $aa[$k] = $v; - } - $eAttrs[$n] = $aa; - } - $attrs = $eAttrs; - } - - $restrictionBase = strpos($restrictionBase,':') ? $this->expandQname($restrictionBase) : $restrictionBase; - $arrayType = strpos($arrayType,':') ? $this->expandQname($arrayType) : $arrayType; - - $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns']; - $this->schemas[$typens][0]->addComplexType($name,$typeClass,$phpType,$compositor,$restrictionBase,$elements,$attrs,$arrayType); - } - - /** - * adds an XML Schema simple type to the WSDL types - * - * @param string $name - * @param string $restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array) - * @param string $typeClass (should always be simpleType) - * @param string $phpType (should always be scalar) - * @param array $enumeration array of values - * @see nusoap_xmlschema - * @access public - */ - function addSimpleType($name, $restrictionBase='', $typeClass='simpleType', $phpType='scalar', $enumeration=array()) { - $restrictionBase = strpos($restrictionBase,':') ? $this->expandQname($restrictionBase) : $restrictionBase; - - $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns']; - $this->schemas[$typens][0]->addSimpleType($name, $restrictionBase, $typeClass, $phpType, $enumeration); - } - - /** - * adds an element to the WSDL types - * - * @param array $attrs attributes that must include name and type - * @see nusoap_xmlschema - * @access public - */ - function addElement($attrs) { - $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns']; - $this->schemas[$typens][0]->addElement($attrs); - } - - /** - * register an operation with the server - * - * @param string $name operation (method) name - * @param array $in assoc array of input values: key = param name, value = param type - * @param array $out assoc array of output values: key = param name, value = param type - * @param string $namespace optional The namespace for the operation - * @param string $soapaction optional The soapaction for the operation - * @param string $style (rpc|document) optional The style for the operation Note: when 'document' is specified, parameter and return wrappers are created for you automatically - * @param string $use (encoded|literal) optional The use for the parameters (cannot mix right now) - * @param string $documentation optional The description to include in the WSDL - * @param string $encodingStyle optional (usually 'http://schemas.xmlsoap.org/soap/encoding/' for encoded) - * @access public - */ - function addOperation($name, $in = false, $out = false, $namespace = false, $soapaction = false, $style = 'rpc', $use = 'encoded', $documentation = '', $encodingStyle = ''){ - if ($use == 'encoded' && $encodingStyle == '') { - $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/'; - } - - if ($style == 'document') { - $elements = array(); - foreach ($in as $n => $t) { - $elements[$n] = array('name' => $n, 'type' => $t, 'form' => 'unqualified'); - } - $this->addComplexType($name . 'RequestType', 'complexType', 'struct', 'all', '', $elements); - $this->addElement(array('name' => $name, 'type' => $name . 'RequestType')); - $in = array('parameters' => 'tns:' . $name . '^'); - - $elements = array(); - foreach ($out as $n => $t) { - $elements[$n] = array('name' => $n, 'type' => $t, 'form' => 'unqualified'); - } - $this->addComplexType($name . 'ResponseType', 'complexType', 'struct', 'all', '', $elements); - $this->addElement(array('name' => $name . 'Response', 'type' => $name . 'ResponseType', 'form' => 'qualified')); - $out = array('parameters' => 'tns:' . $name . 'Response' . '^'); - } - - // get binding - $this->bindings[ $this->serviceName . 'Binding' ]['operations'][$name] = - array( - 'name' => $name, - 'binding' => $this->serviceName . 'Binding', - 'endpoint' => $this->endpoint, - 'soapAction' => $soapaction, - 'style' => $style, - 'input' => array( - 'use' => $use, - 'namespace' => $namespace, - 'encodingStyle' => $encodingStyle, - 'message' => $name . 'Request', - 'parts' => $in), - 'output' => array( - 'use' => $use, - 'namespace' => $namespace, - 'encodingStyle' => $encodingStyle, - 'message' => $name . 'Response', - 'parts' => $out), - 'namespace' => $namespace, - 'transport' => 'http://schemas.xmlsoap.org/soap/http', - 'documentation' => $documentation); - // add portTypes - // add messages - if($in) - { - foreach($in as $pName => $pType) - { - if(strpos($pType,':')) { - $pType = $this->getNamespaceFromPrefix($this->getPrefix($pType)).":".$this->getLocalPart($pType); - } - $this->messages[$name.'Request'][$pName] = $pType; - } - } else { - $this->messages[$name.'Request']= '0'; - } - if($out) - { - foreach($out as $pName => $pType) - { - if(strpos($pType,':')) { - $pType = $this->getNamespaceFromPrefix($this->getPrefix($pType)).":".$this->getLocalPart($pType); - } - $this->messages[$name.'Response'][$pName] = $pType; - } - } else { - $this->messages[$name.'Response']= '0'; - } - return true; - } -} -?> -* @author Scott Nichol -* @version $Id: nusoap.php,v 1.123 2010/04/26 20:15:08 snichol Exp $ -* @access public -*/ -class nusoap_parser extends nusoap_base { - - var $xml = ''; - var $xml_encoding = ''; - var $method = ''; - var $root_struct = ''; - var $root_struct_name = ''; - var $root_struct_namespace = ''; - var $root_header = ''; - var $document = ''; // incoming SOAP body (text) - // determines where in the message we are (envelope,header,body,method) - var $status = ''; - var $position = 0; - var $depth = 0; - var $default_namespace = ''; - var $namespaces = array(); - var $message = array(); - var $parent = ''; - var $fault = false; - var $fault_code = ''; - var $fault_str = ''; - var $fault_detail = ''; - var $depth_array = array(); - var $debug_flag = true; - var $soapresponse = NULL; // parsed SOAP Body - var $soapheader = NULL; // parsed SOAP Header - var $responseHeaders = ''; // incoming SOAP headers (text) - var $body_position = 0; - // for multiref parsing: - // array of id => pos - var $ids = array(); - // array of id => hrefs => pos - var $multirefs = array(); - // toggle for auto-decoding element content - var $decode_utf8 = true; - - /** - * constructor that actually does the parsing - * - * @param string $xml SOAP message - * @param string $encoding character encoding scheme of message - * @param string $method method for which XML is parsed (unused?) - * @param string $decode_utf8 whether to decode UTF-8 to ISO-8859-1 - * @access public - */ - function nusoap_parser($xml,$encoding='UTF-8',$method='',$decode_utf8=true){ - parent::nusoap_base(); - $this->xml = $xml; - $this->xml_encoding = $encoding; - $this->method = $method; - $this->decode_utf8 = $decode_utf8; - - // Check whether content has been read. - if(!empty($xml)){ - // Check XML encoding - $pos_xml = strpos($xml, '', $pos_xml + 2) - $pos_xml + 1); - if (preg_match("/encoding=[\"']([^\"']*)[\"']/", $xml_decl, $res)) { - $xml_encoding = $res[1]; - if (strtoupper($xml_encoding) != $encoding) { - $err = "Charset from HTTP Content-Type '" . $encoding . "' does not match encoding from XML declaration '" . $xml_encoding . "'"; - $this->debug($err); - if ($encoding != 'ISO-8859-1' || strtoupper($xml_encoding) != 'UTF-8') { - $this->setError($err); - return; - } - // when HTTP says ISO-8859-1 (the default) and XML says UTF-8 (the typical), assume the other endpoint is just sloppy and proceed - } else { - $this->debug('Charset from HTTP Content-Type matches encoding from XML declaration'); - } - } else { - $this->debug('No encoding specified in XML declaration'); - } - } else { - $this->debug('No XML declaration'); - } - $this->debug('Entering nusoap_parser(), length='.strlen($xml).', encoding='.$encoding); - // Create an XML parser - why not xml_parser_create_ns? - $this->parser = xml_parser_create($this->xml_encoding); - // Set the options for parsing the XML data. - //xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1); - xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0); - xml_parser_set_option($this->parser, XML_OPTION_TARGET_ENCODING, $this->xml_encoding); - // Set the object for the parser. - xml_set_object($this->parser, $this); - // Set the element handlers for the parser. - xml_set_element_handler($this->parser, 'start_element','end_element'); - xml_set_character_data_handler($this->parser,'character_data'); - - // Parse the XML file. - if(!xml_parse($this->parser,$xml,true)){ - // Display an error message. - $err = sprintf('XML error parsing SOAP payload on line %d: %s', - xml_get_current_line_number($this->parser), - xml_error_string(xml_get_error_code($this->parser))); - $this->debug($err); - $this->debug("XML payload:\n" . $xml); - $this->setError($err); - } else { - $this->debug('in nusoap_parser ctor, message:'); - $this->appendDebug($this->varDump($this->message)); - $this->debug('parsed successfully, found root struct: '.$this->root_struct.' of name '.$this->root_struct_name); - // get final value - $this->soapresponse = $this->message[$this->root_struct]['result']; - // get header value - if($this->root_header != '' && isset($this->message[$this->root_header]['result'])){ - $this->soapheader = $this->message[$this->root_header]['result']; - } - // resolve hrefs/ids - if(sizeof($this->multirefs) > 0){ - foreach($this->multirefs as $id => $hrefs){ - $this->debug('resolving multirefs for id: '.$id); - $idVal = $this->buildVal($this->ids[$id]); - if (is_array($idVal) && isset($idVal['!id'])) { - unset($idVal['!id']); - } - foreach($hrefs as $refPos => $ref){ - $this->debug('resolving href at pos '.$refPos); - $this->multirefs[$id][$refPos] = $idVal; - } - } - } - } - xml_parser_free($this->parser); - } else { - $this->debug('xml was empty, didn\'t parse!'); - $this->setError('xml was empty, didn\'t parse!'); - } - } - - /** - * start-element handler - * - * @param resource $parser XML parser object - * @param string $name element name - * @param array $attrs associative array of attributes - * @access private - */ - function start_element($parser, $name, $attrs) { - // position in a total number of elements, starting from 0 - // update class level pos - $pos = $this->position++; - // and set mine - $this->message[$pos] = array('pos' => $pos,'children'=>'','cdata'=>''); - // depth = how many levels removed from root? - // set mine as current global depth and increment global depth value - $this->message[$pos]['depth'] = $this->depth++; - - // else add self as child to whoever the current parent is - if($pos != 0){ - $this->message[$this->parent]['children'] .= '|'.$pos; - } - // set my parent - $this->message[$pos]['parent'] = $this->parent; - // set self as current parent - $this->parent = $pos; - // set self as current value for this depth - $this->depth_array[$this->depth] = $pos; - // get element prefix - if(strpos($name,':')){ - // get ns prefix - $prefix = substr($name,0,strpos($name,':')); - // get unqualified name - $name = substr(strstr($name,':'),1); - } - // set status - if ($name == 'Envelope' && $this->status == '') { - $this->status = 'envelope'; - } elseif ($name == 'Header' && $this->status == 'envelope') { - $this->root_header = $pos; - $this->status = 'header'; - } elseif ($name == 'Body' && $this->status == 'envelope'){ - $this->status = 'body'; - $this->body_position = $pos; - // set method - } elseif($this->status == 'body' && $pos == ($this->body_position+1)) { - $this->status = 'method'; - $this->root_struct_name = $name; - $this->root_struct = $pos; - $this->message[$pos]['type'] = 'struct'; - $this->debug("found root struct $this->root_struct_name, pos $this->root_struct"); - } - // set my status - $this->message[$pos]['status'] = $this->status; - // set name - $this->message[$pos]['name'] = htmlspecialchars($name); - // set attrs - $this->message[$pos]['attrs'] = $attrs; - - // loop through atts, logging ns and type declarations - $attstr = ''; - foreach($attrs as $key => $value){ - $key_prefix = $this->getPrefix($key); - $key_localpart = $this->getLocalPart($key); - // if ns declarations, add to class level array of valid namespaces - if($key_prefix == 'xmlns'){ - if(preg_match('/^http:\/\/www.w3.org\/[0-9]{4}\/XMLSchema$/',$value)){ - $this->XMLSchemaVersion = $value; - $this->namespaces['xsd'] = $this->XMLSchemaVersion; - $this->namespaces['xsi'] = $this->XMLSchemaVersion.'-instance'; - } - $this->namespaces[$key_localpart] = $value; - // set method namespace - if($name == $this->root_struct_name){ - $this->methodNamespace = $value; - } - // if it's a type declaration, set type - } elseif($key_localpart == 'type'){ - if (isset($this->message[$pos]['type']) && $this->message[$pos]['type'] == 'array') { - // do nothing: already processed arrayType - } else { - $value_prefix = $this->getPrefix($value); - $value_localpart = $this->getLocalPart($value); - $this->message[$pos]['type'] = $value_localpart; - $this->message[$pos]['typePrefix'] = $value_prefix; - if(isset($this->namespaces[$value_prefix])){ - $this->message[$pos]['type_namespace'] = $this->namespaces[$value_prefix]; - } else if(isset($attrs['xmlns:'.$value_prefix])) { - $this->message[$pos]['type_namespace'] = $attrs['xmlns:'.$value_prefix]; - } - // should do something here with the namespace of specified type? - } - } elseif($key_localpart == 'arrayType'){ - $this->message[$pos]['type'] = 'array'; - /* do arrayType ereg here - [1] arrayTypeValue ::= atype asize - [2] atype ::= QName rank* - [3] rank ::= '[' (',')* ']' - [4] asize ::= '[' length~ ']' - [5] length ::= nextDimension* Digit+ - [6] nextDimension ::= Digit+ ',' - */ - $expr = '/([A-Za-z0-9_]+):([A-Za-z]+[A-Za-z0-9_]+)\[([0-9]+),?([0-9]*)\]/'; - if(preg_match($expr,$value,$regs)){ - $this->message[$pos]['typePrefix'] = $regs[1]; - $this->message[$pos]['arrayTypePrefix'] = $regs[1]; - if (isset($this->namespaces[$regs[1]])) { - $this->message[$pos]['arrayTypeNamespace'] = $this->namespaces[$regs[1]]; - } else if (isset($attrs['xmlns:'.$regs[1]])) { - $this->message[$pos]['arrayTypeNamespace'] = $attrs['xmlns:'.$regs[1]]; - } - $this->message[$pos]['arrayType'] = $regs[2]; - $this->message[$pos]['arraySize'] = $regs[3]; - $this->message[$pos]['arrayCols'] = $regs[4]; - } - // specifies nil value (or not) - } elseif ($key_localpart == 'nil'){ - $this->message[$pos]['nil'] = ($value == 'true' || $value == '1'); - // some other attribute - } elseif ($key != 'href' && $key != 'xmlns' && $key_localpart != 'encodingStyle' && $key_localpart != 'root') { - $this->message[$pos]['xattrs']['!' . $key] = $value; - } - - if ($key == 'xmlns') { - $this->default_namespace = $value; - } - // log id - if($key == 'id'){ - $this->ids[$value] = $pos; - } - // root - if($key_localpart == 'root' && $value == 1){ - $this->status = 'method'; - $this->root_struct_name = $name; - $this->root_struct = $pos; - $this->debug("found root struct $this->root_struct_name, pos $pos"); - } - // for doclit - $attstr .= " $key=\"$value\""; - } - // get namespace - must be done after namespace atts are processed - if(isset($prefix)){ - $this->message[$pos]['namespace'] = $this->namespaces[$prefix]; - $this->default_namespace = $this->namespaces[$prefix]; - } else { - $this->message[$pos]['namespace'] = $this->default_namespace; - } - if($this->status == 'header'){ - if ($this->root_header != $pos) { - $this->responseHeaders .= "<" . (isset($prefix) ? $prefix . ':' : '') . "$name$attstr>"; - } - } elseif($this->root_struct_name != ''){ - $this->document .= "<" . (isset($prefix) ? $prefix . ':' : '') . "$name$attstr>"; - } - } - - /** - * end-element handler - * - * @param resource $parser XML parser object - * @param string $name element name - * @access private - */ - function end_element($parser, $name) { - // position of current element is equal to the last value left in depth_array for my depth - $pos = $this->depth_array[$this->depth--]; - - // get element prefix - if(strpos($name,':')){ - // get ns prefix - $prefix = substr($name,0,strpos($name,':')); - // get unqualified name - $name = substr(strstr($name,':'),1); - } - - // build to native type - if(isset($this->body_position) && $pos > $this->body_position){ - // deal w/ multirefs - if(isset($this->message[$pos]['attrs']['href'])){ - // get id - $id = substr($this->message[$pos]['attrs']['href'],1); - // add placeholder to href array - $this->multirefs[$id][$pos] = 'placeholder'; - // add set a reference to it as the result value - $this->message[$pos]['result'] =& $this->multirefs[$id][$pos]; - // build complexType values - } elseif($this->message[$pos]['children'] != ''){ - // if result has already been generated (struct/array) - if(!isset($this->message[$pos]['result'])){ - $this->message[$pos]['result'] = $this->buildVal($pos); - } - // build complexType values of attributes and possibly simpleContent - } elseif (isset($this->message[$pos]['xattrs'])) { - if (isset($this->message[$pos]['nil']) && $this->message[$pos]['nil']) { - $this->message[$pos]['xattrs']['!'] = null; - } elseif (isset($this->message[$pos]['cdata']) && trim($this->message[$pos]['cdata']) != '') { - if (isset($this->message[$pos]['type'])) { - $this->message[$pos]['xattrs']['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$pos]['type'], isset($this->message[$pos]['type_namespace']) ? $this->message[$pos]['type_namespace'] : ''); - } else { - $parent = $this->message[$pos]['parent']; - if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) { - $this->message[$pos]['xattrs']['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : ''); - } else { - $this->message[$pos]['xattrs']['!'] = $this->message[$pos]['cdata']; - } - } - } - $this->message[$pos]['result'] = $this->message[$pos]['xattrs']; - // set value of simpleType (or nil complexType) - } else { - //$this->debug('adding data for scalar value '.$this->message[$pos]['name'].' of value '.$this->message[$pos]['cdata']); - if (isset($this->message[$pos]['nil']) && $this->message[$pos]['nil']) { - $this->message[$pos]['xattrs']['!'] = null; - } elseif (isset($this->message[$pos]['type'])) { - $this->message[$pos]['result'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$pos]['type'], isset($this->message[$pos]['type_namespace']) ? $this->message[$pos]['type_namespace'] : ''); - } else { - $parent = $this->message[$pos]['parent']; - if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) { - $this->message[$pos]['result'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : ''); - } else { - $this->message[$pos]['result'] = $this->message[$pos]['cdata']; - } - } - - /* add value to parent's result, if parent is struct/array - $parent = $this->message[$pos]['parent']; - if($this->message[$parent]['type'] != 'map'){ - if(strtolower($this->message[$parent]['type']) == 'array'){ - $this->message[$parent]['result'][] = $this->message[$pos]['result']; - } else { - $this->message[$parent]['result'][$this->message[$pos]['name']] = $this->message[$pos]['result']; - } - } - */ - } - } - - // for doclit - if($this->status == 'header'){ - if ($this->root_header != $pos) { - $this->responseHeaders .= ""; - } - } elseif($pos >= $this->root_struct){ - $this->document .= ""; - } - // switch status - if ($pos == $this->root_struct){ - $this->status = 'body'; - $this->root_struct_namespace = $this->message[$pos]['namespace']; - } elseif ($pos == $this->root_header) { - $this->status = 'envelope'; - } elseif ($name == 'Body' && $this->status == 'body') { - $this->status = 'envelope'; - } elseif ($name == 'Header' && $this->status == 'header') { // will never happen - $this->status = 'envelope'; - } elseif ($name == 'Envelope' && $this->status == 'envelope') { - $this->status = ''; - } - // set parent back to my parent - $this->parent = $this->message[$pos]['parent']; - } - - /** - * element content handler - * - * @param resource $parser XML parser object - * @param string $data element content - * @access private - */ - function character_data($parser, $data){ - $pos = $this->depth_array[$this->depth]; - if ($this->xml_encoding=='UTF-8'){ - // TODO: add an option to disable this for folks who want - // raw UTF-8 that, e.g., might not map to iso-8859-1 - // TODO: this can also be handled with xml_parser_set_option($this->parser, XML_OPTION_TARGET_ENCODING, "ISO-8859-1"); - if($this->decode_utf8){ - $data = utf8_decode($data); - } - } - $this->message[$pos]['cdata'] .= $data; - // for doclit - if($this->status == 'header'){ - $this->responseHeaders .= $data; - } else { - $this->document .= $data; - } - } - - /** - * get the parsed message (SOAP Body) - * - * @return mixed - * @access public - * @deprecated use get_soapbody instead - */ - function get_response(){ - return $this->soapresponse; - } - - /** - * get the parsed SOAP Body (NULL if there was none) - * - * @return mixed - * @access public - */ - function get_soapbody(){ - return $this->soapresponse; - } - - /** - * get the parsed SOAP Header (NULL if there was none) - * - * @return mixed - * @access public - */ - function get_soapheader(){ - return $this->soapheader; - } - - /** - * get the unparsed SOAP Header - * - * @return string XML or empty if no Header - * @access public - */ - function getHeaders(){ - return $this->responseHeaders; - } - - /** - * decodes simple types into PHP variables - * - * @param string $value value to decode - * @param string $type XML type to decode - * @param string $typens XML type namespace to decode - * @return mixed PHP value - * @access private - */ - function decodeSimple($value, $type, $typens) { - // TODO: use the namespace! - if ((!isset($type)) || $type == 'string' || $type == 'long' || $type == 'unsignedLong') { - return (string) $value; - } - if ($type == 'int' || $type == 'integer' || $type == 'short' || $type == 'byte') { - return (int) $value; - } - if ($type == 'float' || $type == 'double' || $type == 'decimal') { - return (double) $value; - } - if ($type == 'boolean') { - if (strtolower($value) == 'false' || strtolower($value) == 'f') { - return false; - } - return (boolean) $value; - } - if ($type == 'base64' || $type == 'base64Binary') { - $this->debug('Decode base64 value'); - return base64_decode($value); - } - // obscure numeric types - if ($type == 'nonPositiveInteger' || $type == 'negativeInteger' - || $type == 'nonNegativeInteger' || $type == 'positiveInteger' - || $type == 'unsignedInt' - || $type == 'unsignedShort' || $type == 'unsignedByte') { - return (int) $value; - } - // bogus: parser treats array with no elements as a simple type - if ($type == 'array') { - return array(); - } - // everything else - return (string) $value; - } - - /** - * builds response structures for compound values (arrays/structs) - * and scalars - * - * @param integer $pos position in node tree - * @return mixed PHP value - * @access private - */ - function buildVal($pos){ - if(!isset($this->message[$pos]['type'])){ - $this->message[$pos]['type'] = ''; - } - $this->debug('in buildVal() for '.$this->message[$pos]['name']."(pos $pos) of type ".$this->message[$pos]['type']); - // if there are children... - if($this->message[$pos]['children'] != ''){ - $this->debug('in buildVal, there are children'); - $children = explode('|',$this->message[$pos]['children']); - array_shift($children); // knock off empty - // md array - if(isset($this->message[$pos]['arrayCols']) && $this->message[$pos]['arrayCols'] != ''){ - $r=0; // rowcount - $c=0; // colcount - foreach($children as $child_pos){ - $this->debug("in buildVal, got an MD array element: $r, $c"); - $params[$r][] = $this->message[$child_pos]['result']; - $c++; - if($c == $this->message[$pos]['arrayCols']){ - $c = 0; - $r++; - } - } - // array - } elseif($this->message[$pos]['type'] == 'array' || $this->message[$pos]['type'] == 'Array'){ - $this->debug('in buildVal, adding array '.$this->message[$pos]['name']); - foreach($children as $child_pos){ - $params[] = &$this->message[$child_pos]['result']; - } - // apache Map type: java hashtable - } elseif($this->message[$pos]['type'] == 'Map' && $this->message[$pos]['type_namespace'] == 'http://xml.apache.org/xml-soap'){ - $this->debug('in buildVal, Java Map '.$this->message[$pos]['name']); - foreach($children as $child_pos){ - $kv = explode("|",$this->message[$child_pos]['children']); - $params[$this->message[$kv[1]]['result']] = &$this->message[$kv[2]]['result']; - } - // generic compound type - //} elseif($this->message[$pos]['type'] == 'SOAPStruct' || $this->message[$pos]['type'] == 'struct') { - } else { - // Apache Vector type: treat as an array - $this->debug('in buildVal, adding Java Vector or generic compound type '.$this->message[$pos]['name']); - if ($this->message[$pos]['type'] == 'Vector' && $this->message[$pos]['type_namespace'] == 'http://xml.apache.org/xml-soap') { - $notstruct = 1; - } else { - $notstruct = 0; - } - // - foreach($children as $child_pos){ - if($notstruct){ - $params[] = &$this->message[$child_pos]['result']; - } else { - if (isset($params[$this->message[$child_pos]['name']])) { - // de-serialize repeated element name into an array - if ((!is_array($params[$this->message[$child_pos]['name']])) || (!isset($params[$this->message[$child_pos]['name']][0]))) { - $params[$this->message[$child_pos]['name']] = array($params[$this->message[$child_pos]['name']]); - } - $params[$this->message[$child_pos]['name']][] = &$this->message[$child_pos]['result']; - } else { - $params[$this->message[$child_pos]['name']] = &$this->message[$child_pos]['result']; - } - } - } - } - if (isset($this->message[$pos]['xattrs'])) { - $this->debug('in buildVal, handling attributes'); - foreach ($this->message[$pos]['xattrs'] as $n => $v) { - $params[$n] = $v; - } - } - // handle simpleContent - if (isset($this->message[$pos]['cdata']) && trim($this->message[$pos]['cdata']) != '') { - $this->debug('in buildVal, handling simpleContent'); - if (isset($this->message[$pos]['type'])) { - $params['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$pos]['type'], isset($this->message[$pos]['type_namespace']) ? $this->message[$pos]['type_namespace'] : ''); - } else { - $parent = $this->message[$pos]['parent']; - if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) { - $params['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : ''); - } else { - $params['!'] = $this->message[$pos]['cdata']; - } - } - } - $ret = is_array($params) ? $params : array(); - $this->debug('in buildVal, return:'); - $this->appendDebug($this->varDump($ret)); - return $ret; - } else { - $this->debug('in buildVal, no children, building scalar'); - $cdata = isset($this->message[$pos]['cdata']) ? $this->message[$pos]['cdata'] : ''; - if (isset($this->message[$pos]['type'])) { - $ret = $this->decodeSimple($cdata, $this->message[$pos]['type'], isset($this->message[$pos]['type_namespace']) ? $this->message[$pos]['type_namespace'] : ''); - $this->debug("in buildVal, return: $ret"); - return $ret; - } - $parent = $this->message[$pos]['parent']; - if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) { - $ret = $this->decodeSimple($cdata, $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : ''); - $this->debug("in buildVal, return: $ret"); - return $ret; - } - $ret = $this->message[$pos]['cdata']; - $this->debug("in buildVal, return: $ret"); - return $ret; - } - } -} - -/** - * Backward compatibility - */ -class soap_parser extends nusoap_parser { -} - -?>call( string methodname [ ,array parameters] ); -* -* // bye bye client -* unset($soapclient); -* -* @author Dietrich Ayala -* @author Scott Nichol -* @version $Id: nusoap.php,v 1.123 2010/04/26 20:15:08 snichol Exp $ -* @access public -*/ -class nusoap_client extends nusoap_base { - - var $username = ''; // Username for HTTP authentication - var $password = ''; // Password for HTTP authentication - var $authtype = ''; // Type of HTTP authentication - var $certRequest = array(); // Certificate for HTTP SSL authentication - var $requestHeaders = false; // SOAP headers in request (text) - var $responseHeaders = ''; // SOAP headers from response (incomplete namespace resolution) (text) - var $responseHeader = NULL; // SOAP Header from response (parsed) - var $document = ''; // SOAP body response portion (incomplete namespace resolution) (text) - var $endpoint; - var $forceEndpoint = ''; // overrides WSDL endpoint - var $proxyhost = ''; - var $proxyport = ''; - var $proxyusername = ''; - var $proxypassword = ''; - var $portName = ''; // port name to use in WSDL - var $xml_encoding = ''; // character set encoding of incoming (response) messages - var $http_encoding = false; - var $timeout = 0; // HTTP connection timeout - var $response_timeout = 30; // HTTP response timeout - var $endpointType = ''; // soap|wsdl, empty for WSDL initialization error - var $persistentConnection = false; - var $defaultRpcParams = false; // This is no longer used - var $request = ''; // HTTP request - var $response = ''; // HTTP response - var $responseData = ''; // SOAP payload of response - var $cookies = array(); // Cookies from response or for request - var $decode_utf8 = true; // toggles whether the parser decodes element content w/ utf8_decode() - var $operations = array(); // WSDL operations, empty for WSDL initialization error - var $curl_options = array(); // User-specified cURL options - var $bindingType = ''; // WSDL operation binding type - var $use_curl = false; // whether to always try to use cURL - - /* - * fault related variables - */ - /** - * @var fault - * @access public - */ - var $fault; - /** - * @var faultcode - * @access public - */ - var $faultcode; - /** - * @var faultstring - * @access public - */ - var $faultstring; - /** - * @var faultdetail - * @access public - */ - var $faultdetail; - - /** - * constructor - * - * @param mixed $endpoint SOAP server or WSDL URL (string), or wsdl instance (object) - * @param mixed $wsdl optional, set to 'wsdl' or true if using WSDL - * @param string $proxyhost optional - * @param string $proxyport optional - * @param string $proxyusername optional - * @param string $proxypassword optional - * @param integer $timeout set the connection timeout - * @param integer $response_timeout set the response timeout - * @param string $portName optional portName in WSDL document - * @access public - */ - function nusoap_client($endpoint,$wsdl = false,$proxyhost = false,$proxyport = false,$proxyusername = false, $proxypassword = false, $timeout = 0, $response_timeout = 30, $portName = ''){ - parent::nusoap_base(); - $this->endpoint = $endpoint; - $this->proxyhost = $proxyhost; - $this->proxyport = $proxyport; - $this->proxyusername = $proxyusername; - $this->proxypassword = $proxypassword; - $this->timeout = $timeout; - $this->response_timeout = $response_timeout; - $this->portName = $portName; - - $this->debug("ctor wsdl=$wsdl timeout=$timeout response_timeout=$response_timeout"); - $this->appendDebug('endpoint=' . $this->varDump($endpoint)); - - // make values - if($wsdl){ - if (is_object($endpoint) && (get_class($endpoint) == 'wsdl')) { - $this->wsdl = $endpoint; - $this->endpoint = $this->wsdl->wsdl; - $this->wsdlFile = $this->endpoint; - $this->debug('existing wsdl instance created from ' . $this->endpoint); - $this->checkWSDL(); - } else { - $this->wsdlFile = $this->endpoint; - $this->wsdl = null; - $this->debug('will use lazy evaluation of wsdl from ' . $this->endpoint); - } - $this->endpointType = 'wsdl'; - } else { - $this->debug("instantiate SOAP with endpoint at $endpoint"); - $this->endpointType = 'soap'; - } - } - - /** - * calls method, returns PHP native type - * - * @param string $operation SOAP server URL or path - * @param mixed $params An array, associative or simple, of the parameters - * for the method call, or a string that is the XML - * for the call. For rpc style, this call will - * wrap the XML in a tag named after the method, as - * well as the SOAP Envelope and Body. For document - * style, this will only wrap with the Envelope and Body. - * IMPORTANT: when using an array with document style, - * in which case there - * is really one parameter, the root of the fragment - * used in the call, which encloses what programmers - * normally think of parameters. A parameter array - * *must* include the wrapper. - * @param string $namespace optional method namespace (WSDL can override) - * @param string $soapAction optional SOAPAction value (WSDL can override) - * @param mixed $headers optional string of XML with SOAP header content, or array of soapval objects for SOAP headers, or associative array - * @param boolean $rpcParams optional (no longer used) - * @param string $style optional (rpc|document) the style to use when serializing parameters (WSDL can override) - * @param string $use optional (encoded|literal) the use when serializing parameters (WSDL can override) - * @return mixed response from SOAP call, normally an associative array mirroring the structure of the XML response, false for certain fatal errors - * @access public - */ - function call($operation,$params=array(),$namespace='http://tempuri.org',$soapAction='',$headers=false,$rpcParams=null,$style='rpc',$use='encoded'){ - $this->operation = $operation; - $this->fault = false; - $this->setError(''); - $this->request = ''; - $this->response = ''; - $this->responseData = ''; - $this->faultstring = ''; - $this->faultcode = ''; - $this->opData = array(); - - $this->debug("call: operation=$operation, namespace=$namespace, soapAction=$soapAction, rpcParams=$rpcParams, style=$style, use=$use, endpointType=$this->endpointType"); - $this->appendDebug('params=' . $this->varDump($params)); - $this->appendDebug('headers=' . $this->varDump($headers)); - if ($headers) { - $this->requestHeaders = $headers; - } - if ($this->endpointType == 'wsdl' && is_null($this->wsdl)) { - $this->loadWSDL(); - if ($this->getError()) - return false; - } - // serialize parameters - if($this->endpointType == 'wsdl' && $opData = $this->getOperationData($operation)){ - // use WSDL for operation - $this->opData = $opData; - $this->debug("found operation"); - $this->appendDebug('opData=' . $this->varDump($opData)); - if (isset($opData['soapAction'])) { - $soapAction = $opData['soapAction']; - } - if (! $this->forceEndpoint) { - $this->endpoint = $opData['endpoint']; - } else { - $this->endpoint = $this->forceEndpoint; - } - $namespace = isset($opData['input']['namespace']) ? $opData['input']['namespace'] : $namespace; - $style = $opData['style']; - $use = $opData['input']['use']; - // add ns to ns array - if($namespace != '' && !isset($this->wsdl->namespaces[$namespace])){ - $nsPrefix = 'ns' . rand(1000, 9999); - $this->wsdl->namespaces[$nsPrefix] = $namespace; - } - $nsPrefix = $this->wsdl->getPrefixFromNamespace($namespace); - // serialize payload - if (is_string($params)) { - $this->debug("serializing param string for WSDL operation $operation"); - $payload = $params; - } elseif (is_array($params)) { - $this->debug("serializing param array for WSDL operation $operation"); - $payload = $this->wsdl->serializeRPCParameters($operation,'input',$params,$this->bindingType); - } else { - $this->debug('params must be array or string'); - $this->setError('params must be array or string'); - return false; - } - $usedNamespaces = $this->wsdl->usedNamespaces; - if (isset($opData['input']['encodingStyle'])) { - $encodingStyle = $opData['input']['encodingStyle']; - } else { - $encodingStyle = ''; - } - $this->appendDebug($this->wsdl->getDebug()); - $this->wsdl->clearDebug(); - if ($errstr = $this->wsdl->getError()) { - $this->debug('got wsdl error: '.$errstr); - $this->setError('wsdl error: '.$errstr); - return false; - } - } elseif($this->endpointType == 'wsdl') { - // operation not in WSDL - $this->appendDebug($this->wsdl->getDebug()); - $this->wsdl->clearDebug(); - $this->setError('operation '.$operation.' not present in WSDL.'); - $this->debug("operation '$operation' not present in WSDL."); - return false; - } else { - // no WSDL - //$this->namespaces['ns1'] = $namespace; - $nsPrefix = 'ns' . rand(1000, 9999); - // serialize - $payload = ''; - if (is_string($params)) { - $this->debug("serializing param string for operation $operation"); - $payload = $params; - } elseif (is_array($params)) { - $this->debug("serializing param array for operation $operation"); - foreach($params as $k => $v){ - $payload .= $this->serialize_val($v,$k,false,false,false,false,$use); - } - } else { - $this->debug('params must be array or string'); - $this->setError('params must be array or string'); - return false; - } - $usedNamespaces = array(); - if ($use == 'encoded') { - $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/'; - } else { - $encodingStyle = ''; - } - } - // wrap RPC calls with method element - if ($style == 'rpc') { - if ($use == 'literal') { - $this->debug("wrapping RPC request with literal method element"); - if ($namespace) { - // http://www.ws-i.org/Profiles/BasicProfile-1.1-2004-08-24.html R2735 says rpc/literal accessor elements should not be in a namespace - $payload = "<$nsPrefix:$operation xmlns:$nsPrefix=\"$namespace\">" . - $payload . - ""; - } else { - $payload = "<$operation>" . $payload . ""; - } - } else { - $this->debug("wrapping RPC request with encoded method element"); - if ($namespace) { - $payload = "<$nsPrefix:$operation xmlns:$nsPrefix=\"$namespace\">" . - $payload . - ""; - } else { - $payload = "<$operation>" . - $payload . - ""; - } - } - } - // serialize envelope - $soapmsg = $this->serializeEnvelope($payload,$this->requestHeaders,$usedNamespaces,$style,$use,$encodingStyle); - $this->debug("endpoint=$this->endpoint, soapAction=$soapAction, namespace=$namespace, style=$style, use=$use, encodingStyle=$encodingStyle"); - $this->debug('SOAP message length=' . strlen($soapmsg) . ' contents (max 1000 bytes)=' . substr($soapmsg, 0, 1000)); - // send - $return = $this->send($this->getHTTPBody($soapmsg),$soapAction,$this->timeout,$this->response_timeout); - if($errstr = $this->getError()){ - $this->debug('Error: '.$errstr); - return false; - } else { - $this->return = $return; - $this->debug('sent message successfully and got a(n) '.gettype($return)); - $this->appendDebug('return=' . $this->varDump($return)); - - // fault? - if(is_array($return) && isset($return['faultcode'])){ - $this->debug('got fault'); - $this->setError($return['faultcode'].': '.$return['faultstring']); - $this->fault = true; - foreach($return as $k => $v){ - $this->$k = $v; - $this->debug("$k = $v
"); - } - return $return; - } elseif ($style == 'document') { - // NOTE: if the response is defined to have multiple parts (i.e. unwrapped), - // we are only going to return the first part here...sorry about that - return $return; - } else { - // array of return values - if(is_array($return)){ - // multiple 'out' parameters, which we return wrapped up - // in the array - if(sizeof($return) > 1){ - return $return; - } - // single 'out' parameter (normally the return value) - $return = array_shift($return); - $this->debug('return shifted value: '); - $this->appendDebug($this->varDump($return)); - return $return; - // nothing returned (ie, echoVoid) - } else { - return ""; - } - } - } - } - - /** - * check WSDL passed as an instance or pulled from an endpoint - * - * @access private - */ - function checkWSDL() { - $this->appendDebug($this->wsdl->getDebug()); - $this->wsdl->clearDebug(); - $this->debug('checkWSDL'); - // catch errors - if ($errstr = $this->wsdl->getError()) { - $this->appendDebug($this->wsdl->getDebug()); - $this->wsdl->clearDebug(); - $this->debug('got wsdl error: '.$errstr); - $this->setError('wsdl error: '.$errstr); - } elseif ($this->operations = $this->wsdl->getOperations($this->portName, 'soap')) { - $this->appendDebug($this->wsdl->getDebug()); - $this->wsdl->clearDebug(); - $this->bindingType = 'soap'; - $this->debug('got '.count($this->operations).' operations from wsdl '.$this->wsdlFile.' for binding type '.$this->bindingType); - } elseif ($this->operations = $this->wsdl->getOperations($this->portName, 'soap12')) { - $this->appendDebug($this->wsdl->getDebug()); - $this->wsdl->clearDebug(); - $this->bindingType = 'soap12'; - $this->debug('got '.count($this->operations).' operations from wsdl '.$this->wsdlFile.' for binding type '.$this->bindingType); - $this->debug('**************** WARNING: SOAP 1.2 BINDING *****************'); - } else { - $this->appendDebug($this->wsdl->getDebug()); - $this->wsdl->clearDebug(); - $this->debug('getOperations returned false'); - $this->setError('no operations defined in the WSDL document!'); - } - } - - /** - * instantiate wsdl object and parse wsdl file - * - * @access public - */ - function loadWSDL() { - $this->debug('instantiating wsdl class with doc: '.$this->wsdlFile); - $this->wsdl = new wsdl('',$this->proxyhost,$this->proxyport,$this->proxyusername,$this->proxypassword,$this->timeout,$this->response_timeout,$this->curl_options,$this->use_curl); - $this->wsdl->setCredentials($this->username, $this->password, $this->authtype, $this->certRequest); - $this->wsdl->fetchWSDL($this->wsdlFile); - $this->checkWSDL(); - } - - /** - * get available data pertaining to an operation - * - * @param string $operation operation name - * @return array array of data pertaining to the operation - * @access public - */ - function getOperationData($operation){ - if ($this->endpointType == 'wsdl' && is_null($this->wsdl)) { - $this->loadWSDL(); - if ($this->getError()) - return false; - } - if(isset($this->operations[$operation])){ - return $this->operations[$operation]; - } - $this->debug("No data for operation: $operation"); - } - - /** - * send the SOAP message - * - * Note: if the operation has multiple return values - * the return value of this method will be an array - * of those values. - * - * @param string $msg a SOAPx4 soapmsg object - * @param string $soapaction SOAPAction value - * @param integer $timeout set connection timeout in seconds - * @param integer $response_timeout set response timeout in seconds - * @return mixed native PHP types. - * @access private - */ - function send($msg, $soapaction = '', $timeout=0, $response_timeout=30) { - $this->checkCookies(); - // detect transport - switch(true){ - // http(s) - case preg_match('/^http/',$this->endpoint): - $this->debug('transporting via HTTP'); - if($this->persistentConnection == true && is_object($this->persistentConnection)){ - $http =& $this->persistentConnection; - } else { - $http = new soap_transport_http($this->endpoint, $this->curl_options, $this->use_curl); - if ($this->persistentConnection) { - $http->usePersistentConnection(); - } - } - $http->setContentType($this->getHTTPContentType(), $this->getHTTPContentTypeCharset()); - $http->setSOAPAction($soapaction); - if($this->proxyhost && $this->proxyport){ - $http->setProxy($this->proxyhost,$this->proxyport,$this->proxyusername,$this->proxypassword); - } - if($this->authtype != '') { - $http->setCredentials($this->username, $this->password, $this->authtype, array(), $this->certRequest); - } - if($this->http_encoding != ''){ - $http->setEncoding($this->http_encoding); - } - $this->debug('sending message, length='.strlen($msg)); - if(preg_match('/^http:/',$this->endpoint)){ - //if(strpos($this->endpoint,'http:')){ - $this->responseData = $http->send($msg,$timeout,$response_timeout,$this->cookies); - } elseif(preg_match('/^https/',$this->endpoint)){ - //} elseif(strpos($this->endpoint,'https:')){ - //if(phpversion() == '4.3.0-dev'){ - //$response = $http->send($msg,$timeout,$response_timeout); - //$this->request = $http->outgoing_payload; - //$this->response = $http->incoming_payload; - //} else - $this->responseData = $http->sendHTTPS($msg,$timeout,$response_timeout,$this->cookies); - } else { - $this->setError('no http/s in endpoint url'); - } - $this->request = $http->outgoing_payload; - $this->response = $http->incoming_payload; - $this->appendDebug($http->getDebug()); - $this->UpdateCookies($http->incoming_cookies); - - // save transport object if using persistent connections - if ($this->persistentConnection) { - $http->clearDebug(); - if (!is_object($this->persistentConnection)) { - $this->persistentConnection = $http; - } - } - - if($err = $http->getError()){ - $this->setError('HTTP Error: '.$err); - return false; - } elseif($this->getError()){ - return false; - } else { - $this->debug('got response, length='. strlen($this->responseData).' type='.$http->incoming_headers['content-type']); - return $this->parseResponse($http->incoming_headers, $this->responseData); - } - break; - default: - $this->setError('no transport found, or selected transport is not yet supported!'); - return false; - break; - } - } - - /** - * processes SOAP message returned from server - * - * @param array $headers The HTTP headers - * @param string $data unprocessed response data from server - * @return mixed value of the message, decoded into a PHP type - * @access private - */ - function parseResponse($headers, $data) { - $this->debug('Entering parseResponse() for data of length ' . strlen($data) . ' headers:'); - $this->appendDebug($this->varDump($headers)); - if (!isset($headers['content-type'])) { - $this->setError('Response not of type text/xml (no content-type header)'); - return false; - } - if (!strstr($headers['content-type'], 'text/xml')) { - $this->setError('Response not of type text/xml: ' . $headers['content-type']); - return false; - } - if (strpos($headers['content-type'], '=')) { - $enc = str_replace('"', '', substr(strstr($headers["content-type"], '='), 1)); - $this->debug('Got response encoding: ' . $enc); - if(preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i',$enc)){ - $this->xml_encoding = strtoupper($enc); - } else { - $this->xml_encoding = 'US-ASCII'; - } - } else { - // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1 - $this->xml_encoding = 'ISO-8859-1'; - } - $this->debug('Use encoding: ' . $this->xml_encoding . ' when creating nusoap_parser'); - $parser = new nusoap_parser($data,$this->xml_encoding,$this->operation,$this->decode_utf8); - // add parser debug data to our debug - $this->appendDebug($parser->getDebug()); - // if parse errors - if($errstr = $parser->getError()){ - $this->setError( $errstr); - // destroy the parser object - unset($parser); - return false; - } else { - // get SOAP headers - $this->responseHeaders = $parser->getHeaders(); - // get SOAP headers - $this->responseHeader = $parser->get_soapheader(); - // get decoded message - $return = $parser->get_soapbody(); - // add document for doclit support - $this->document = $parser->document; - // destroy the parser object - unset($parser); - // return decode message - return $return; - } - } - - /** - * sets user-specified cURL options - * - * @param mixed $option The cURL option (always integer?) - * @param mixed $value The cURL option value - * @access public - */ - function setCurlOption($option, $value) { - $this->debug("setCurlOption option=$option, value="); - $this->appendDebug($this->varDump($value)); - $this->curl_options[$option] = $value; - } - - /** - * sets the SOAP endpoint, which can override WSDL - * - * @param string $endpoint The endpoint URL to use, or empty string or false to prevent override - * @access public - */ - function setEndpoint($endpoint) { - $this->debug("setEndpoint(\"$endpoint\")"); - $this->forceEndpoint = $endpoint; - } - - /** - * set the SOAP headers - * - * @param mixed $headers String of XML with SOAP header content, or array of soapval objects for SOAP headers - * @access public - */ - function setHeaders($headers){ - $this->debug("setHeaders headers="); - $this->appendDebug($this->varDump($headers)); - $this->requestHeaders = $headers; - } - - /** - * get the SOAP response headers (namespace resolution incomplete) - * - * @return string - * @access public - */ - function getHeaders(){ - return $this->responseHeaders; - } - - /** - * get the SOAP response Header (parsed) - * - * @return mixed - * @access public - */ - function getHeader(){ - return $this->responseHeader; - } - - /** - * set proxy info here - * - * @param string $proxyhost - * @param string $proxyport - * @param string $proxyusername - * @param string $proxypassword - * @access public - */ - function setHTTPProxy($proxyhost, $proxyport, $proxyusername = '', $proxypassword = '') { - $this->proxyhost = $proxyhost; - $this->proxyport = $proxyport; - $this->proxyusername = $proxyusername; - $this->proxypassword = $proxypassword; - } - - /** - * if authenticating, set user credentials here - * - * @param string $username - * @param string $password - * @param string $authtype (basic|digest|certificate|ntlm) - * @param array $certRequest (keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, verifypeer (optional), verifyhost (optional): see corresponding options in cURL docs) - * @access public - */ - function setCredentials($username, $password, $authtype = 'basic', $certRequest = array()) { - $this->debug("setCredentials username=$username authtype=$authtype certRequest="); - $this->appendDebug($this->varDump($certRequest)); - $this->username = $username; - $this->password = $password; - $this->authtype = $authtype; - $this->certRequest = $certRequest; - } - - /** - * use HTTP encoding - * - * @param string $enc HTTP encoding - * @access public - */ - function setHTTPEncoding($enc='gzip, deflate'){ - $this->debug("setHTTPEncoding(\"$enc\")"); - $this->http_encoding = $enc; - } - - /** - * Set whether to try to use cURL connections if possible - * - * @param boolean $use Whether to try to use cURL - * @access public - */ - function setUseCURL($use) { - $this->debug("setUseCURL($use)"); - $this->use_curl = $use; - } - - /** - * use HTTP persistent connections if possible - * - * @access public - */ - function useHTTPPersistentConnection(){ - $this->debug("useHTTPPersistentConnection"); - $this->persistentConnection = true; - } - - /** - * gets the default RPC parameter setting. - * If true, default is that call params are like RPC even for document style. - * Each call() can override this value. - * - * This is no longer used. - * - * @return boolean - * @access public - * @deprecated - */ - function getDefaultRpcParams() { - return $this->defaultRpcParams; - } - - /** - * sets the default RPC parameter setting. - * If true, default is that call params are like RPC even for document style - * Each call() can override this value. - * - * This is no longer used. - * - * @param boolean $rpcParams - * @access public - * @deprecated - */ - function setDefaultRpcParams($rpcParams) { - $this->defaultRpcParams = $rpcParams; - } - - /** - * dynamically creates an instance of a proxy class, - * allowing user to directly call methods from wsdl - * - * @return object soap_proxy object - * @access public - */ - function getProxy() { - $r = rand(); - $evalStr = $this->_getProxyClassCode($r); - //$this->debug("proxy class: $evalStr"); - if ($this->getError()) { - $this->debug("Error from _getProxyClassCode, so return NULL"); - return null; - } - // eval the class - eval($evalStr); - // instantiate proxy object - eval("\$proxy = new nusoap_proxy_$r('');"); - // transfer current wsdl data to the proxy thereby avoiding parsing the wsdl twice - $proxy->endpointType = 'wsdl'; - $proxy->wsdlFile = $this->wsdlFile; - $proxy->wsdl = $this->wsdl; - $proxy->operations = $this->operations; - $proxy->defaultRpcParams = $this->defaultRpcParams; - // transfer other state - $proxy->soap_defencoding = $this->soap_defencoding; - $proxy->username = $this->username; - $proxy->password = $this->password; - $proxy->authtype = $this->authtype; - $proxy->certRequest = $this->certRequest; - $proxy->requestHeaders = $this->requestHeaders; - $proxy->endpoint = $this->endpoint; - $proxy->forceEndpoint = $this->forceEndpoint; - $proxy->proxyhost = $this->proxyhost; - $proxy->proxyport = $this->proxyport; - $proxy->proxyusername = $this->proxyusername; - $proxy->proxypassword = $this->proxypassword; - $proxy->http_encoding = $this->http_encoding; - $proxy->timeout = $this->timeout; - $proxy->response_timeout = $this->response_timeout; - $proxy->persistentConnection = &$this->persistentConnection; - $proxy->decode_utf8 = $this->decode_utf8; - $proxy->curl_options = $this->curl_options; - $proxy->bindingType = $this->bindingType; - $proxy->use_curl = $this->use_curl; - return $proxy; - } - - /** - * dynamically creates proxy class code - * - * @return string PHP/NuSOAP code for the proxy class - * @access private - */ - function _getProxyClassCode($r) { - $this->debug("in getProxy endpointType=$this->endpointType"); - $this->appendDebug("wsdl=" . $this->varDump($this->wsdl)); - if ($this->endpointType != 'wsdl') { - $evalStr = 'A proxy can only be created for a WSDL client'; - $this->setError($evalStr); - $evalStr = "echo \"$evalStr\";"; - return $evalStr; - } - if ($this->endpointType == 'wsdl' && is_null($this->wsdl)) { - $this->loadWSDL(); - if ($this->getError()) { - return "echo \"" . $this->getError() . "\";"; - } - } - $evalStr = ''; - foreach ($this->operations as $operation => $opData) { - if ($operation != '') { - // create param string and param comment string - if (sizeof($opData['input']['parts']) > 0) { - $paramStr = ''; - $paramArrayStr = ''; - $paramCommentStr = ''; - foreach ($opData['input']['parts'] as $name => $type) { - $paramStr .= "\$$name, "; - $paramArrayStr .= "'$name' => \$$name, "; - $paramCommentStr .= "$type \$$name, "; - } - $paramStr = substr($paramStr, 0, strlen($paramStr)-2); - $paramArrayStr = substr($paramArrayStr, 0, strlen($paramArrayStr)-2); - $paramCommentStr = substr($paramCommentStr, 0, strlen($paramCommentStr)-2); - } else { - $paramStr = ''; - $paramArrayStr = ''; - $paramCommentStr = 'void'; - } - $opData['namespace'] = !isset($opData['namespace']) ? 'http://testuri.com' : $opData['namespace']; - $evalStr .= "// $paramCommentStr - function " . str_replace('.', '__', $operation) . "($paramStr) { - \$params = array($paramArrayStr); - return \$this->call('$operation', \$params, '".$opData['namespace']."', '".(isset($opData['soapAction']) ? $opData['soapAction'] : '')."'); - } - "; - unset($paramStr); - unset($paramCommentStr); - } - } - $evalStr = 'class nusoap_proxy_'.$r.' extends nusoap_client { - '.$evalStr.' -}'; - return $evalStr; - } - - /** - * dynamically creates proxy class code - * - * @return string PHP/NuSOAP code for the proxy class - * @access public - */ - function getProxyClassCode() { - $r = rand(); - return $this->_getProxyClassCode($r); - } - - /** - * gets the HTTP body for the current request. - * - * @param string $soapmsg The SOAP payload - * @return string The HTTP body, which includes the SOAP payload - * @access private - */ - function getHTTPBody($soapmsg) { - return $soapmsg; - } - - /** - * gets the HTTP content type for the current request. - * - * Note: getHTTPBody must be called before this. - * - * @return string the HTTP content type for the current request. - * @access private - */ - function getHTTPContentType() { - return 'text/xml'; - } - - /** - * gets the HTTP content type charset for the current request. - * returns false for non-text content types. - * - * Note: getHTTPBody must be called before this. - * - * @return string the HTTP content type charset for the current request. - * @access private - */ - function getHTTPContentTypeCharset() { - return $this->soap_defencoding; - } - - /* - * whether or not parser should decode utf8 element content - * - * @return always returns true - * @access public - */ - function decodeUTF8($bool){ - $this->decode_utf8 = $bool; - return true; - } - - /** - * adds a new Cookie into $this->cookies array - * - * @param string $name Cookie Name - * @param string $value Cookie Value - * @return boolean if cookie-set was successful returns true, else false - * @access public - */ - function setCookie($name, $value) { - if (strlen($name) == 0) { - return false; - } - $this->cookies[] = array('name' => $name, 'value' => $value); - return true; - } - - /** - * gets all Cookies - * - * @return array with all internal cookies - * @access public - */ - function getCookies() { - return $this->cookies; - } - - /** - * checks all Cookies and delete those which are expired - * - * @return boolean always return true - * @access private - */ - function checkCookies() { - if (sizeof($this->cookies) == 0) { - return true; - } - $this->debug('checkCookie: check ' . sizeof($this->cookies) . ' cookies'); - $curr_cookies = $this->cookies; - $this->cookies = array(); - foreach ($curr_cookies as $cookie) { - if (! is_array($cookie)) { - $this->debug('Remove cookie that is not an array'); - continue; - } - if ((isset($cookie['expires'])) && (! empty($cookie['expires']))) { - if (strtotime($cookie['expires']) > time()) { - $this->cookies[] = $cookie; - } else { - $this->debug('Remove expired cookie ' . $cookie['name']); - } - } else { - $this->cookies[] = $cookie; - } - } - $this->debug('checkCookie: '.sizeof($this->cookies).' cookies left in array'); - return true; - } - - /** - * updates the current cookies with a new set - * - * @param array $cookies new cookies with which to update current ones - * @return boolean always return true - * @access private - */ - function UpdateCookies($cookies) { - if (sizeof($this->cookies) == 0) { - // no existing cookies: take whatever is new - if (sizeof($cookies) > 0) { - $this->debug('Setting new cookie(s)'); - $this->cookies = $cookies; - } - return true; - } - if (sizeof($cookies) == 0) { - // no new cookies: keep what we've got - return true; - } - // merge - foreach ($cookies as $newCookie) { - if (!is_array($newCookie)) { - continue; - } - if ((!isset($newCookie['name'])) || (!isset($newCookie['value']))) { - continue; - } - $newName = $newCookie['name']; - - $found = false; - for ($i = 0; $i < count($this->cookies); $i++) { - $cookie = $this->cookies[$i]; - if (!is_array($cookie)) { - continue; - } - if (!isset($cookie['name'])) { - continue; - } - if ($newName != $cookie['name']) { - continue; - } - $newDomain = isset($newCookie['domain']) ? $newCookie['domain'] : 'NODOMAIN'; - $domain = isset($cookie['domain']) ? $cookie['domain'] : 'NODOMAIN'; - if ($newDomain != $domain) { - continue; - } - $newPath = isset($newCookie['path']) ? $newCookie['path'] : 'NOPATH'; - $path = isset($cookie['path']) ? $cookie['path'] : 'NOPATH'; - if ($newPath != $path) { - continue; - } - $this->cookies[$i] = $newCookie; - $found = true; - $this->debug('Update cookie ' . $newName . '=' . $newCookie['value']); - break; - } - if (! $found) { - $this->debug('Add cookie ' . $newName . '=' . $newCookie['value']); - $this->cookies[] = $newCookie; - } - } - return true; - } -} - -if (!extension_loaded('soap')) { - /** - * For backwards compatiblity, define soapclient unless the PHP SOAP extension is loaded. - */ - class soapclient extends nusoap_client { - } -} -?> diff --git a/src/Drivers/lib/nusoapmime.php b/src/Drivers/lib/nusoapmime.php deleted file mode 100644 index 03794e4..0000000 --- a/src/Drivers/lib/nusoapmime.php +++ /dev/null @@ -1,516 +0,0 @@ - - * @author Thanks to Guillaume and Henning Reich for posting great attachment code to the mail list - * - * @version $Id: nusoapmime.php,v 1.13 2010/04/26 20:15:08 snichol Exp $ - */ -class nusoap_client_mime extends nusoap_client -{ - /* - * @var array Each array element in the return is an associative array with keys - * data, filename, contenttype, cid - * @access private - */ - public $requestAttachments = []; - /* - * @var array Each array element in the return is an associative array with keys - * data, filename, contenttype, cid - * @access private - */ - public $responseAttachments; - /* - * @var string - * @access private - */ - public $mimeContentType; - - /** - * adds a MIME attachment to the current request. - * - * If the $data parameter contains an empty string, this method will read - * the contents of the file named by the $filename parameter. - * - * If the $cid parameter is false, this method will generate the cid. - * - * @param string $data The data of the attachment - * @param string $filename The filename of the attachment (default is empty string) - * @param string $contenttype The MIME Content-Type of the attachment (default is application/octet-stream) - * @param string $cid The content-id (cid) of the attachment (default is false) - * - * @return string The content-id (cid) of the attachment - */ - public function addAttachment($data, $filename = '', $contenttype = 'application/octet-stream', $cid = false) - { - if (!$cid) { - $cid = md5(uniqid(time())); - } - - $info['data'] = $data; - $info['filename'] = $filename; - $info['contenttype'] = $contenttype; - $info['cid'] = $cid; - - $this->requestAttachments[] = $info; - - return $cid; - } - - /** - * clears the MIME attachments for the current request. - */ - public function clearAttachments() - { - $this->requestAttachments = []; - } - - /** - * gets the MIME attachments from the current response. - * - * Each array element in the return is an associative array with keys - * data, filename, contenttype, cid. These keys correspond to the parameters - * for addAttachment. - * - * @return array The attachments. - */ - public function getAttachments() - { - return $this->responseAttachments; - } - - /** - * gets the HTTP body for the current request. - * - * @param string $soapmsg The SOAP payload - * - * @return string The HTTP body, which includes the SOAP payload - */ - public function getHTTPBody($soapmsg) - { - if (count($this->requestAttachments) > 0) { - $params['content_type'] = 'multipart/related; type="text/xml"'; - $mimeMessage = new Mail_mimePart('', $params); - unset($params); - - $params['content_type'] = 'text/xml'; - $params['encoding'] = '8bit'; - $params['charset'] = $this->soap_defencoding; - $mimeMessage->addSubpart($soapmsg, $params); - - foreach ($this->requestAttachments as $att) { - unset($params); - - $params['content_type'] = $att['contenttype']; - $params['encoding'] = 'base64'; - $params['disposition'] = 'attachment'; - $params['dfilename'] = $att['filename']; - $params['cid'] = $att['cid']; - - if ($att['data'] == '' && $att['filename'] != '') { - if ($fd = fopen($att['filename'], 'rb')) { - $data = fread($fd, filesize($att['filename'])); - fclose($fd); - } else { - $data = ''; - } - $mimeMessage->addSubpart($data, $params); - } else { - $mimeMessage->addSubpart($att['data'], $params); - } - } - - $output = $mimeMessage->encode(); - $mimeHeaders = $output['headers']; - - foreach ($mimeHeaders as $k => $v) { - $this->debug("MIME header $k: $v"); - if (strtolower($k) == 'content-type') { - // PHP header() seems to strip leading whitespace starting - // the second line, so force everything to one line - $this->mimeContentType = str_replace("\r\n", ' ', $v); - } - } - - return $output['body']; - } - - return parent::getHTTPBody($soapmsg); - } - - /** - * gets the HTTP content type for the current request. - * - * Note: getHTTPBody must be called before this. - * - * @return string the HTTP content type for the current request. - */ - public function getHTTPContentType() - { - if (count($this->requestAttachments) > 0) { - return $this->mimeContentType; - } - - return parent::getHTTPContentType(); - } - - /** - * gets the HTTP content type charset for the current request. - * returns false for non-text content types. - * - * Note: getHTTPBody must be called before this. - * - * @return string the HTTP content type charset for the current request. - */ - public function getHTTPContentTypeCharset() - { - if (count($this->requestAttachments) > 0) { - return false; - } - - return parent::getHTTPContentTypeCharset(); - } - - /** - * processes SOAP message returned from server. - * - * @param array $headers The HTTP headers - * @param string $data unprocessed response data from server - * - * @return mixed value of the message, decoded into a PHP type - */ - public function parseResponse($headers, $data) - { - $this->debug('Entering parseResponse() for payload of length '.strlen($data).' and type of '.$headers['content-type']); - $this->responseAttachments = []; - if (strstr($headers['content-type'], 'multipart/related')) { - $this->debug('Decode multipart/related'); - $input = ''; - foreach ($headers as $k => $v) { - $input .= "$k: $v\r\n"; - } - $params['input'] = $input."\r\n".$data; - $params['include_bodies'] = true; - $params['decode_bodies'] = true; - $params['decode_headers'] = true; - - $structure = Mail_mimeDecode::decode($params); - - foreach ($structure->parts as $part) { - if (!isset($part->disposition) && (strstr($part->headers['content-type'], 'text/xml'))) { - $this->debug('Have root part of type '.$part->headers['content-type']); - $root = $part->body; - $return = parent::parseResponse($part->headers, $part->body); - } else { - $this->debug('Have an attachment of type '.$part->headers['content-type']); - $info['data'] = $part->body; - $info['filename'] = isset($part->d_parameters['filename']) ? $part->d_parameters['filename'] : ''; - $info['contenttype'] = $part->headers['content-type']; - $info['cid'] = $part->headers['content-id']; - $this->responseAttachments[] = $info; - } - } - - if (isset($return)) { - $this->responseData = $root; - - return $return; - } - - $this->setError('No root part found in multipart/related content'); - - return ''; - } - $this->debug('Not multipart/related'); - - return parent::parseResponse($headers, $data); - } -} - -/* - * For backwards compatiblity, define soapclientmime unless the PHP SOAP extension is loaded. - */ -if (!extension_loaded('soap')) { - class soapclientmime extends nusoap_client_mime - { - } -} - -/** - * nusoap_server_mime server supporting MIME attachments defined at - * http://www.w3.org/TR/SOAP-attachments. It depends on the PEAR Mail_MIME library. - * - * @author Scott Nichol - * @author Thanks to Guillaume and Henning Reich for posting great attachment code to the mail list - * - * @version $Id: nusoapmime.php,v 1.13 2010/04/26 20:15:08 snichol Exp $ - */ -class nusoap_server_mime extends nusoap_server -{ - /* - * @var array Each array element in the return is an associative array with keys - * data, filename, contenttype, cid - * @access private - */ - public $requestAttachments = []; - /* - * @var array Each array element in the return is an associative array with keys - * data, filename, contenttype, cid - * @access private - */ - public $responseAttachments; - /* - * @var string - * @access private - */ - public $mimeContentType; - - /** - * adds a MIME attachment to the current response. - * - * If the $data parameter contains an empty string, this method will read - * the contents of the file named by the $filename parameter. - * - * If the $cid parameter is false, this method will generate the cid. - * - * @param string $data The data of the attachment - * @param string $filename The filename of the attachment (default is empty string) - * @param string $contenttype The MIME Content-Type of the attachment (default is application/octet-stream) - * @param string $cid The content-id (cid) of the attachment (default is false) - * - * @return string The content-id (cid) of the attachment - */ - public function addAttachment($data, $filename = '', $contenttype = 'application/octet-stream', $cid = false) - { - if (!$cid) { - $cid = md5(uniqid(time())); - } - - $info['data'] = $data; - $info['filename'] = $filename; - $info['contenttype'] = $contenttype; - $info['cid'] = $cid; - - $this->responseAttachments[] = $info; - - return $cid; - } - - /** - * clears the MIME attachments for the current response. - */ - public function clearAttachments() - { - $this->responseAttachments = []; - } - - /** - * gets the MIME attachments from the current request. - * - * Each array element in the return is an associative array with keys - * data, filename, contenttype, cid. These keys correspond to the parameters - * for addAttachment. - * - * @return array The attachments. - */ - public function getAttachments() - { - return $this->requestAttachments; - } - - /** - * gets the HTTP body for the current response. - * - * @param string $soapmsg The SOAP payload - * - * @return string The HTTP body, which includes the SOAP payload - */ - public function getHTTPBody($soapmsg) - { - if (count($this->responseAttachments) > 0) { - $params['content_type'] = 'multipart/related; type="text/xml"'; - $mimeMessage = new Mail_mimePart('', $params); - unset($params); - - $params['content_type'] = 'text/xml'; - $params['encoding'] = '8bit'; - $params['charset'] = $this->soap_defencoding; - $mimeMessage->addSubpart($soapmsg, $params); - - foreach ($this->responseAttachments as $att) { - unset($params); - - $params['content_type'] = $att['contenttype']; - $params['encoding'] = 'base64'; - $params['disposition'] = 'attachment'; - $params['dfilename'] = $att['filename']; - $params['cid'] = $att['cid']; - - if ($att['data'] == '' && $att['filename'] != '') { - if ($fd = fopen($att['filename'], 'rb')) { - $data = fread($fd, filesize($att['filename'])); - fclose($fd); - } else { - $data = ''; - } - $mimeMessage->addSubpart($data, $params); - } else { - $mimeMessage->addSubpart($att['data'], $params); - } - } - - $output = $mimeMessage->encode(); - $mimeHeaders = $output['headers']; - - foreach ($mimeHeaders as $k => $v) { - $this->debug("MIME header $k: $v"); - if (strtolower($k) == 'content-type') { - // PHP header() seems to strip leading whitespace starting - // the second line, so force everything to one line - $this->mimeContentType = str_replace("\r\n", ' ', $v); - } - } - - return $output['body']; - } - - return parent::getHTTPBody($soapmsg); - } - - /** - * gets the HTTP content type for the current response. - * - * Note: getHTTPBody must be called before this. - * - * @return string the HTTP content type for the current response. - */ - public function getHTTPContentType() - { - if (count($this->responseAttachments) > 0) { - return $this->mimeContentType; - } - - return parent::getHTTPContentType(); - } - - /** - * gets the HTTP content type charset for the current response. - * returns false for non-text content types. - * - * Note: getHTTPBody must be called before this. - * - * @return string the HTTP content type charset for the current response. - */ - public function getHTTPContentTypeCharset() - { - if (count($this->responseAttachments) > 0) { - return false; - } - - return parent::getHTTPContentTypeCharset(); - } - - /** - * processes SOAP message received from client. - * - * @param array $headers The HTTP headers - * @param string $data unprocessed request data from client - * - * @return mixed value of the message, decoded into a PHP type - */ - public function parseRequest($headers, $data) - { - $this->debug('Entering parseRequest() for payload of length '.strlen($data).' and type of '.$headers['content-type']); - $this->requestAttachments = []; - if (strstr($headers['content-type'], 'multipart/related')) { - $this->debug('Decode multipart/related'); - $input = ''; - foreach ($headers as $k => $v) { - $input .= "$k: $v\r\n"; - } - $params['input'] = $input."\r\n".$data; - $params['include_bodies'] = true; - $params['decode_bodies'] = true; - $params['decode_headers'] = true; - - $structure = Mail_mimeDecode::decode($params); - - foreach ($structure->parts as $part) { - if (!isset($part->disposition) && (strstr($part->headers['content-type'], 'text/xml'))) { - $this->debug('Have root part of type '.$part->headers['content-type']); - $return = parent::parseRequest($part->headers, $part->body); - } else { - $this->debug('Have an attachment of type '.$part->headers['content-type']); - $info['data'] = $part->body; - $info['filename'] = isset($part->d_parameters['filename']) ? $part->d_parameters['filename'] : ''; - $info['contenttype'] = $part->headers['content-type']; - $info['cid'] = $part->headers['content-id']; - $this->requestAttachments[] = $info; - } - } - - if (isset($return)) { - return $return; - } - - $this->setError('No root part found in multipart/related content'); - - return; - } - $this->debug('Not multipart/related'); - - return parent::parseRequest($headers, $data); - } -} - -/* - * For backwards compatiblity - */ -class nusoapservermime extends nusoap_server_mime -{ -}