5 Modification information for LGPL compliance
7 r58622 - 2010-10-22 18:18:59 -0700 (Fri, 22 Oct 2010) - engsvnbuild - Author: lam <lam@198.18.142.201>
10 r58361 - 2010-09-29 16:59:02 -0700 (Wed, 29 Sep 2010) - kjing - Author: Jenny Gonsalves <jenny@sugarcrm.com>
11 Merging with maint_6_0_1 (svn merge -r 58250:58342)
13 r57813 - 2010-08-19 10:34:44 -0700 (Thu, 19 Aug 2010) - kjing - Author: John Mertic <jmertic@sugarcrm.com>
14 Bug 39085 - When loading the opposite search panel via ajax on the ListViews, call the index action instead of the ListView action to avoid touching pre-MVC code by accident.
16 r57707 - 2010-08-10 12:26:13 -0700 (Tue, 10 Aug 2010) - kjing - Author: Stanislav Malyshev <smalyshev@gmail.com>
17 fix SOAP calls with no parameters
19 r56990 - 2010-06-16 13:05:36 -0700 (Wed, 16 Jun 2010) - kjing - snapshot "Mango" svn branch to a new one for GitHub sync
21 r56989 - 2010-06-16 13:01:33 -0700 (Wed, 16 Jun 2010) - kjing - defunt "Mango" svn dev branch before github cutover
23 r55980 - 2010-04-19 13:31:28 -0700 (Mon, 19 Apr 2010) - kjing - create Mango (6.1) based on windex
25 r51719 - 2009-10-22 10:18:00 -0700 (Thu, 22 Oct 2009) - mitani - Converted to Build 3 tags and updated the build system
27 r51634 - 2009-10-19 13:32:22 -0700 (Mon, 19 Oct 2009) - mitani - Windex is the branch for Sugar Sales 1.0 development
29 r51508 - 2009-10-14 07:40:23 -0700 (Wed, 14 Oct 2009) - jmertic - More fallout fixes from the PHP 5.3 ereg to preg changes.
31 r51455 - 2009-10-13 07:56:48 -0700 (Tue, 13 Oct 2009) - jmertic - Bug 33202 - Enable install of SugarCRM on PHP 5.3.0, asserting that the minimum supported version is PHP 5.2.x.
33 r51443 - 2009-10-12 13:34:36 -0700 (Mon, 12 Oct 2009) - jmertic - Bug 33332 - Made application PHP 5.3 compliant with E_DEPRECATED warnings on by:
34 - Changing all ereg function to either preg or simple string based ones
35 - No more references to magic quotes.
36 - Change all the session_unregister() functions to just unset() the correct session variable instead.
38 r50375 - 2009-08-24 18:07:43 -0700 (Mon, 24 Aug 2009) - dwong - branch kobe2 from tokyo r50372
40 r45763 - 2009-04-01 12:16:18 -0700 (Wed, 01 Apr 2009) - majed - Removed half of the require_once and include_onces in the product that were redundant or could be handled easily by the auto loader
42 r45680 - 2009-03-30 14:34:35 -0700 (Mon, 30 Mar 2009) - Samir Gandhi - modifeid serializeSchema to generate WS-I compliant WSDL
44 r42807 - 2008-12-29 11:16:59 -0800 (Mon, 29 Dec 2008) - dwong - Branch from trunk/sugarcrm r42806 to branches/tokyo/sugarcrm
46 r42645 - 2008-12-18 13:41:08 -0800 (Thu, 18 Dec 2008) - awu - merging maint_5_2_0 rev41336:HEAD to trunk
48 r41647 - 2008-11-11 17:44:30 -0800 (Tue, 11 Nov 2008) - majed - Fixes a few bugs
50 r41596 - 2008-11-10 19:20:04 -0800 (Mon, 10 Nov 2008) - Samir Gandhi - modified to set $method in the code
52 r41558 - 2008-11-10 14:35:34 -0800 (Mon, 10 Nov 2008) - majed - changes nusoap to allow for registering classes
54 r39619 - 2008-09-09 13:41:34 -0700 (Tue, 09 Sep 2008) - jmertic - Bug 24827 - Remove all instances where we return a new object and assign it by reference, since this is deprecated in PHP 5 and emits E_DEPRECATED errors in PHP 5.3.
57 - include/domit/php_http_client_generic.php
58 - include/domit/php_http_connector.php
59 - include/domit/testing_domit.php
60 - include/domit/xml_domit_getelementsbypath.php
61 - include/domit/xml_domit_lite_parser.php
62 - include/domit/xml_domit_nodemaps.php
63 - include/domit/xml_domit_parser.php
64 - include/domit/xml_domit_shared.php
65 - include/generic/SugarWidgets/SugarWidgetField.php
66 - include/generic/SugarWidgets/SugarWidgetReportField.php
67 - include/ListView/ProcessView.php
68 - include/nusoap/class.soapclient.php
69 - include/nusoap/nusoap.php
70 - include/nusoap/nusoapmime.php
71 - include/Pear/HTML_Safe/Safe.php
72 - include/Pear/XML_HTMLSax3/HTMLSax3.php
73 - modules/Administration/RebuildWorkFlow.php
74 - modules/Expressions/RelateSelector.php
75 - modules/Reports/templates/templates_reports.php
76 - modules/WorkFlow/Delete.php
77 - modules/WorkFlow/Save.php
78 - modules/WorkFlow/SaveSequence.php
79 - modules/WorkFlow/WorkFlow.php
80 - modules/WorkFlowActionShells/CreateStep1.php
81 - modules/WorkFlowActionShells/CreateStep2.php
82 - modules/WorkFlowActionShells/Save.php
83 - modules/WorkFlowActionShells/WorkFlowActionShell.php
84 - modules/WorkFlowAlerts/Save.php
85 - modules/WorkFlowAlerts/WorkFlowAlert.php
86 - modules/WorkFlowAlertShells/DetailView.php
87 - modules/WorkFlowAlertShells/WorkFlowAlertShell.php
88 - modules/WorkFlowTriggerShells/CreateStep1.php
89 - modules/WorkFlowTriggerShells/CreateStepFilter.php
90 - modules/WorkFlowTriggerShells/SaveFilter.php
91 - modules/WorkFlowTriggerShells/WorkFlowTriggerShell.php
92 - soap/SoapHelperFunctions.php
93 - test/modules/DynamicFields/DynamicFields_Bug24095_test.php
94 - test/simpletest/browser.php
95 - test/simpletest/default_reporter.php
96 - test/simpletest/detached.php
97 - test/simpletest/eclipse.php
98 - test/simpletest/expectation.php
99 - test/simpletest/extensions/pear_test_case.php
100 - test/simpletest/form.php
101 - test/simpletest/http.php
102 - test/simpletest/mock_objects.php
103 - test/simpletest/page.php
104 - test/simpletest/parser.php
105 - test/simpletest/remote.php
106 - test/simpletest/shell_tester.php
107 - test/simpletest/simple_test.php
108 - test/simpletest/simpletest.php
109 - test/simpletest/test/acceptance_test.php
110 - test/simpletest/test/adapter_test.php
111 - test/simpletest/test/authentication_test.php
112 - test/simpletest/test/browser_test.php
113 - test/simpletest/test/collector_test.php
114 - test/simpletest/test/compatibility_test.php
115 - test/simpletest/test/detached_test.php
116 - test/simpletest/test/eclipse_test.php
117 - test/simpletest/test/encoding_test.php
118 - test/simpletest/test/errors_test.php
119 - test/simpletest/test/expectation_test.php
120 - test/simpletest/test/form_test.php
121 - test/simpletest/test/frames_test.php
122 - test/simpletest/test/http_test.php
123 - test/simpletest/test/live_test.php
124 - test/simpletest/test/mock_objects_test.php
125 - test/simpletest/test/page_test.php
126 - test/simpletest/test/parse_error_test.php
127 - test/simpletest/test/parser_test.php
128 - test/simpletest/test/remote_test.php
129 - test/simpletest/test/shell_test.php
130 - test/simpletest/test/shell_tester_test.php
131 - test/simpletest/test/simpletest_test.php
132 - test/simpletest/test/site/page_request.php
133 - test/simpletest/test/tag_test.php
134 - test/simpletest/test/unit_tester_test.php
135 - test/simpletest/test/user_agent_test.php
136 - test/simpletest/test/visual_test.php
137 - test/simpletest/test/xml_test.php
138 - test/simpletest/test_case.php
139 - test/simpletest/ui/array_reporter/test.php
140 - test/simpletest/ui/recorder/test.php
141 - test/simpletest/unit_tester.php
142 - test/simpletest/url.php
143 - test/simpletest/user_agent.php
144 - test/simpletest/web_tester.php
145 - test/spikephpcoverage/src/PEAR.php
146 - test/spikephpcoverage/src/util/Utility.php
147 - test/spikephpcoverage/src/XML/Parser.php
148 - test/spikephpcoverage/src/XML/Parser/Simple.php
149 - test/test_utilities/SugarTest_SimpleBrowser.php
151 r38362 - 2008-07-28 14:06:59 -0700 (Mon, 28 Jul 2008) - roger - bug: 23897. Using print_r when using the debug statement in nusoap will print out the statements to the screen if the call is coming from the UI.
153 r38300 - 2008-07-25 13:33:43 -0700 (Fri, 25 Jul 2008) - Samir Gandhi - put the debug in parseresponse function
155 r38293 - 2008-07-25 12:32:34 -0700 (Fri, 25 Jul 2008) - Samir Gandhi - to put all the debug statements return value in the call function
157 r36824 - 2008-06-18 09:26:11 -0700 (Wed, 18 Jun 2008) - roger - bug: 21832
159 r26422 - 2007-09-05 17:29:12 -0700 (Wed, 05 Sep 2007) - majed - migrate from beta 1 to trunk
161 r15787 - 2006-08-10 10:14:41 -0700 (Thu, 10 Aug 2006) - roger - RRS: bug 7961
163 r14701 - 2006-07-17 13:37:26 -0700 (Mon, 17 Jul 2006) - roger - RRS: bug 5801
165 r13782 - 2006-06-06 10:58:55 -0700 (Tue, 06 Jun 2006) - majed - changes entry point code
167 r11466 - 2006-02-01 15:49:47 -0800 (Wed, 01 Feb 2006) - jacob - Adding extra !empty check to get around a PHP warning.
169 r11115 - 2006-01-17 14:54:45 -0800 (Tue, 17 Jan 2006) - majed - add entry point validation
171 r10585 - 2005-12-13 14:42:26 -0800 (Tue, 13 Dec 2005) - majed - adds new license mechanisim
173 r10170 - 2005-12-05 18:37:46 -0800 (Mon, 05 Dec 2005) - majed - fixes various issues
175 r8999 - 2005-11-04 05:26:49 -0800 (Fri, 04 Nov 2005) - roger - When nusoap was upgraded we had an issue with the user's default language not being populated during a soap request. I determined the reason this was happening and have checked in the corresponding change to nusoap.
177 r8991 - 2005-11-03 19:07:25 -0800 (Thu, 03 Nov 2005) - majed - fixes nusoap issue
179 r8846 - 2005-10-31 11:01:12 -0800 (Mon, 31 Oct 2005) - majed - new version of nusoap
181 r7905 - 2005-09-21 19:12:57 -0700 (Wed, 21 Sep 2005) - majed - restores old nusoap pre & with a few fixes
183 r7861 - 2005-09-20 15:40:25 -0700 (Tue, 20 Sep 2005) - majed - & fix for 3.5.1
185 r7452 - 2005-08-17 11:32:34 -0700 (Wed, 17 Aug 2005) - majed - changes soap to nusoap
187 r5820 - 2005-06-21 14:22:24 -0700 (Tue, 21 Jun 2005) - majed - fixes issues with nusoap and with custom fields
189 r5462 - 2005-05-25 13:50:11 -0700 (Wed, 25 May 2005) - majed - upgraded nusoap to .6.9
191 r5104 - 2005-05-04 15:33:41 -0700 (Wed, 04 May 2005) - majed - gets rid of HTTP_GET_VARS and what not which has been deprecated
193 r573 - 2004-09-04 13:03:32 -0700 (Sat, 04 Sep 2004) - sugarclint - undoing copyrights added in inadvertantly. --clint
195 r546 - 2004-09-03 11:49:38 -0700 (Fri, 03 Sep 2004) - sugarmsi - removed echo count
197 r354 - 2004-08-02 23:00:37 -0700 (Mon, 02 Aug 2004) - sugarjacob - Adding Soap
203 if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
206 $Id: nusoap.php 58622 2010-10-23 01:18:59Z engsvnbuild $
208 NuSOAP - Web Services Toolkit for PHP
210 Copyright (c) 2002 NuSphere Corporation
212 This library is free software; you can redistribute it and/or
213 modify it under the terms of the GNU Lesser General Public
214 License as published by the Free Software Foundation; either
215 version 2.1 of the License, or (at your option) any later version.
217 This library is distributed in the hope that it will be useful,
218 but WITHOUT ANY WARRANTY; without even the implied warranty of
219 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
220 Lesser General Public License for more details.
222 You should have received a copy of the GNU Lesser General Public
223 License along with this library; if not, write to the Free Software
224 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
226 The NuSOAP project home is:
227 http://sourceforge.net/projects/nusoap/
229 The primary support for NuSOAP is the Help forum on the project home page.
231 If you have any questions or comments, please email:
235 http://dietrich.ganx4.com/nusoap
238 http://www.nusphere.com
243 * Some of the standards implmented in whole or part by NuSOAP:
245 * SOAP 1.1 (http://www.w3.org/TR/2000/NOTE-SOAP-20000508/)
246 * WSDL 1.1 (http://www.w3.org/TR/2001/NOTE-wsdl-20010315)
247 * SOAP Messages With Attachments (http://www.w3.org/TR/SOAP-attachments)
248 * XML 1.0 (http://www.w3.org/TR/2006/REC-xml-20060816/)
249 * Namespaces in XML 1.0 (http://www.w3.org/TR/2006/REC-xml-names-20060816/)
250 * XML Schema 1.0 (http://www.w3.org/TR/xmlschema-0/)
251 * RFC 2045 Multipurpose Internet Mail Extensions (MIME) Part One: Format of Internet Message Bodies
252 * RFC 2068 Hypertext Transfer Protocol -- HTTP/1.1
253 * RFC 2617 HTTP Authentication: Basic and Digest Access Authentication
259 require_once('class.soapclient.php');
260 require_once('class.soap_val.php');
261 require_once('class.soap_parser.php');
262 require_once('class.soap_fault.php');
265 require_once('class.soap_transport_http.php');
267 // optional add-on classes
268 require_once('class.xmlschema.php');
269 require_once('class.wsdl.php');
272 require_once('class.soap_server.php');*/
274 // class variable emulation
275 // cf. http://www.webkreator.com/php/techniques/php-static-class-variables.html
276 $GLOBALS['_transient']['static']['nusoap_base']['globalDebugLevel'] = 0;
282 * @author Dietrich Ayala <dietrich@ganx4.com>
283 * @author Scott Nichol <snichol@users.sourceforge.net>
289 * Identification for HTTP headers.
294 var $title = 'NuSOAP';
296 * Version for HTTP headers.
301 var $version = '0.9.5';
303 * CVS revision for HTTP headers.
308 var $revision = '$Revision: 58622 $';
310 * Current error string (manipulated by getError/setError)
317 * Current debug string (manipulated by debug/appendDebug/clearDebug/getDebug/getDebugAsXMLComment)
324 * toggles automatic encoding of special characters as entities
325 * (should always be true, I think)
330 var $charencoding = true;
332 * the debug level for this instance
345 var $XMLSchemaVersion = 'http://www.w3.org/2001/XMLSchema';
348 * charset encoding for outgoing messages
353 //var $soap_defencoding = 'ISO-8859-1';
354 var $soap_defencoding = 'UTF-8';
357 * namespaces in an array of prefix => uri
359 * this is "seeded" by a set of constants, but it may be altered by code
364 var $namespaces = array(
365 'SOAP-ENV' => 'http://schemas.xmlsoap.org/soap/envelope/',
366 'xsd' => 'http://www.w3.org/2001/XMLSchema',
367 'xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
368 'SOAP-ENC' => 'http://schemas.xmlsoap.org/soap/encoding/'
372 * namespaces used in the current context, e.g. during serialization
377 var $usedNamespaces = array();
380 * XML Schema types in an array of uri => (array of xml type => php type)
381 * is this legacy yet?
382 * no, this is used by the nusoap_xmlschema class to verify type => namespace mappings.
386 var $typemap = array(
387 'http://www.w3.org/2001/XMLSchema' => array(
388 'string'=>'string','boolean'=>'boolean','float'=>'double','double'=>'double','decimal'=>'double',
389 'duration'=>'','dateTime'=>'string','time'=>'string','date'=>'string','gYearMonth'=>'',
390 'gYear'=>'','gMonthDay'=>'','gDay'=>'','gMonth'=>'','hexBinary'=>'string','base64Binary'=>'string',
391 // abstract "any" types
392 'anyType'=>'string','anySimpleType'=>'string',
394 'normalizedString'=>'string','token'=>'string','language'=>'','NMTOKEN'=>'','NMTOKENS'=>'','Name'=>'','NCName'=>'','ID'=>'',
395 'IDREF'=>'','IDREFS'=>'','ENTITY'=>'','ENTITIES'=>'','integer'=>'integer','nonPositiveInteger'=>'integer',
396 'negativeInteger'=>'integer','long'=>'integer','int'=>'integer','short'=>'integer','byte'=>'integer','nonNegativeInteger'=>'integer',
397 'unsignedLong'=>'','unsignedInt'=>'','unsignedShort'=>'','unsignedByte'=>'','positiveInteger'=>''),
398 'http://www.w3.org/2000/10/XMLSchema' => array(
399 'i4'=>'','int'=>'integer','boolean'=>'boolean','string'=>'string','double'=>'double',
400 'float'=>'double','dateTime'=>'string',
401 'timeInstant'=>'string','base64Binary'=>'string','base64'=>'string','ur-type'=>'array'),
402 'http://www.w3.org/1999/XMLSchema' => array(
403 'i4'=>'','int'=>'integer','boolean'=>'boolean','string'=>'string','double'=>'double',
404 'float'=>'double','dateTime'=>'string',
405 'timeInstant'=>'string','base64Binary'=>'string','base64'=>'string','ur-type'=>'array'),
406 'http://soapinterop.org/xsd' => array('SOAPStruct'=>'struct'),
407 'http://schemas.xmlsoap.org/soap/encoding/' => array('base64'=>'string','array'=>'array','Array'=>'array'),
408 'http://xml.apache.org/xml-soap' => array('Map')
412 * XML entities to convert
417 * @see expandEntities
419 var $xmlEntities = array('quot' => '"','amp' => '&',
420 'lt' => '<','gt' => '>','apos' => "'");
424 * This is to allows us to override the payload to resolve issues where we need to take
425 * control of the xml content
430 var $payloadOverride;
437 function nusoap_base() {
438 $this->debugLevel = $GLOBALS['_transient']['static']['nusoap_base']['globalDebugLevel'];
442 * gets the global debug level, which applies to future instances
444 * @return integer Debug level 0-9, where 0 turns off
447 function getGlobalDebugLevel() {
448 return $GLOBALS['_transient']['static']['nusoap_base']['globalDebugLevel'];
452 * sets the global debug level, which applies to future instances
454 * @param int $level Debug level 0-9, where 0 turns off
457 function setGlobalDebugLevel($level) {
458 $GLOBALS['_transient']['static']['nusoap_base']['globalDebugLevel'] = $level;
462 * gets the debug level for this instance
464 * @return int Debug level 0-9, where 0 turns off
467 function getDebugLevel() {
468 return $this->debugLevel;
472 * sets the debug level for this instance
474 * @param int $level Debug level 0-9, where 0 turns off
477 function setDebugLevel($level) {
478 $this->debugLevel = $level;
482 * adds debug data to the instance debug string with formatting
484 * @param string $string debug data
487 function debug($string){
488 if ($this->debugLevel > 0) {
489 $this->appendDebug($this->getmicrotime().' '.get_class($this).": $string\n");
494 * adds debug data to the instance debug string without formatting
496 * @param string $string debug data
499 function appendDebug($string){
500 if ($this->debugLevel > 0) {
501 // it would be nice to use a memory stream here to use
502 // memory more efficiently
503 $this->debug_str .= $string;
508 * clears the current debug data for this instance
512 function clearDebug() {
513 // it would be nice to use a memory stream here to use
514 // memory more efficiently
515 $this->debug_str = '';
519 * gets the current debug data for this instance
524 function &getDebug() {
525 // it would be nice to use a memory stream here to use
526 // memory more efficiently
527 return $this->debug_str;
531 * gets the current debug data for this instance as an XML comment
532 * this may change the contents of the debug data
534 * @return debug data as an XML comment
537 function &getDebugAsXMLComment() {
538 // it would be nice to use a memory stream here to use
539 // memory more efficiently
540 while (strpos($this->debug_str, '--')) {
541 $this->debug_str = str_replace('--', '- -', $this->debug_str);
543 $ret = "<!--\n" . $this->debug_str . "\n-->";
548 * expands entities, e.g. changes '<' to '<'.
550 * @param string $val The string in which to expand entities.
553 function expandEntities($val) {
554 if ($this->charencoding) {
555 $val = str_replace('&', '&', $val);
556 $val = str_replace("'", ''', $val);
557 $val = str_replace('"', '"', $val);
558 $val = str_replace('<', '<', $val);
559 $val = str_replace('>', '>', $val);
565 * returns error string if present
567 * @return mixed error string or false
571 if($this->error_str != ''){
572 return $this->error_str;
580 * @return boolean $string error string
583 function setError($str){
584 $this->error_str = $str;
588 * detect if array is a simple array or a struct (associative array)
590 * @param mixed $val The PHP array
591 * @return string (arraySimple|arrayStruct)
594 function isArraySimpleOrStruct($val) {
595 $keyList = array_keys($val);
596 foreach ($keyList as $keyListValue) {
597 if (!is_int($keyListValue)) {
598 return 'arrayStruct';
601 return 'arraySimple';
605 * serializes PHP values in accordance w/ section 5. Type information is
606 * not serialized if $use == 'literal'.
608 * @param mixed $val The value to serialize
609 * @param string $name The name (local part) of the XML element
610 * @param string $type The XML schema type (local part) for the element
611 * @param string $name_ns The namespace for the name of the XML element
612 * @param string $type_ns The namespace for the type of the element
613 * @param array $attributes The attributes to serialize as name=>value pairs
614 * @param string $use The WSDL "use" (encoded|literal)
615 * @param boolean $soapval Whether this is called from soapval.
616 * @return string The serialized element, possibly with child elements
619 function serialize_val($val,$name=false,$type=false,$name_ns=false,$type_ns=false,$attributes=false,$use='encoded',$soapval=false) {
620 $this->debug("in serialize_val: name=$name, type=$type, name_ns=$name_ns, type_ns=$type_ns, use=$use, soapval=$soapval");
621 $this->appendDebug('value=' . $this->varDump($val));
622 $this->appendDebug('attributes=' . $this->varDump($attributes));
624 if (is_object($val) && get_class($val) == 'soapval' && (! $soapval)) {
625 $this->debug("serialize_val: serialize soapval");
626 $xml = $val->serialize($use);
627 $this->appendDebug($val->getDebug());
629 $this->debug("serialize_val of soapval returning $xml");
632 // force valid name if necessary
633 if (is_numeric($name)) {
634 $name = '__numeric_' . $name;
638 // if name has ns, add ns prefix to name
641 $prefix = 'nu'.rand(1000,9999);
642 $name = $prefix.':'.$name;
643 $xmlns .= " xmlns:$prefix=\"$name_ns\"";
645 // if type is prefixed, create type prefix
646 if($type_ns != '' && $type_ns == $this->namespaces['xsd']){
647 // need to fix this. shouldn't default to xsd if no ns specified
648 // w/o checking against typemap
649 $type_prefix = 'xsd';
651 $type_prefix = 'ns'.rand(1000,9999);
652 $xmlns .= " xmlns:$type_prefix=\"$type_ns\"";
654 // serialize attributes if present
657 foreach($attributes as $k => $v){
658 $atts .= " $k=\"".$this->expandEntities($v).'"';
661 // serialize null value
663 $this->debug("serialize_val: serialize null");
664 if ($use == 'literal') {
665 // TODO: depends on minOccurs
666 $xml = "<$name$xmlns$atts/>";
667 $this->debug("serialize_val returning $xml");
670 if (isset($type) && isset($type_prefix)) {
671 $type_str = " xsi:type=\"$type_prefix:$type\"";
675 $xml = "<$name$xmlns$type_str$atts xsi:nil=\"true\"/>";
676 $this->debug("serialize_val returning $xml");
680 // serialize if an xsd built-in primitive type
681 if($type != '' && isset($this->typemap[$this->XMLSchemaVersion][$type])){
682 $this->debug("serialize_val: serialize xsd built-in primitive type");
684 if ($type == 'boolean') {
685 $val = $val ? 'true' : 'false';
689 } else if (is_string($val)) {
690 $val = $this->expandEntities($val);
692 if ($use == 'literal') {
693 $xml = "<$name$xmlns$atts>$val</$name>";
694 $this->debug("serialize_val returning $xml");
697 $xml = "<$name$xmlns xsi:type=\"xsd:$type\"$atts>$val</$name>";
698 $this->debug("serialize_val returning $xml");
702 // detect type and serialize
705 case (is_bool($val) || $type == 'boolean'):
706 $this->debug("serialize_val: serialize boolean");
707 if ($type == 'boolean') {
708 $val = $val ? 'true' : 'false';
712 if ($use == 'literal') {
713 $xml .= "<$name$xmlns$atts>$val</$name>";
715 $xml .= "<$name$xmlns xsi:type=\"xsd:boolean\"$atts>$val</$name>";
718 case (is_int($val) || is_long($val) || $type == 'int'):
719 $this->debug("serialize_val: serialize int");
720 if ($use == 'literal') {
721 $xml .= "<$name$xmlns$atts>$val</$name>";
723 $xml .= "<$name$xmlns xsi:type=\"xsd:int\"$atts>$val</$name>";
726 case (is_float($val)|| is_double($val) || $type == 'float'):
727 $this->debug("serialize_val: serialize float");
728 if ($use == 'literal') {
729 $xml .= "<$name$xmlns$atts>$val</$name>";
731 $xml .= "<$name$xmlns xsi:type=\"xsd:float\"$atts>$val</$name>";
734 case (is_string($val) || $type == 'string'):
735 $this->debug("serialize_val: serialize string");
736 $val = $this->expandEntities($val);
737 if ($use == 'literal') {
738 $xml .= "<$name$xmlns$atts>$val</$name>";
740 $xml .= "<$name$xmlns xsi:type=\"xsd:string\"$atts>$val</$name>";
743 case is_object($val):
744 $this->debug("serialize_val: serialize object");
745 if (get_class($val) == 'soapval') {
746 $this->debug("serialize_val: serialize soapval object");
747 $pXml = $val->serialize($use);
748 $this->appendDebug($val->getDebug());
752 $name = get_class($val);
753 $this->debug("In serialize_val, used class name $name as element name");
755 $this->debug("In serialize_val, do not override name $name for element name for class " . get_class($val));
757 foreach(get_object_vars($val) as $k => $v){
758 $pXml = isset($pXml) ? $pXml.$this->serialize_val($v,$k,false,false,false,false,$use) : $this->serialize_val($v,$k,false,false,false,false,$use);
761 if(isset($type) && isset($type_prefix)){
762 $type_str = " xsi:type=\"$type_prefix:$type\"";
766 if ($use == 'literal') {
767 $xml .= "<$name$xmlns$atts>$pXml</$name>";
769 $xml .= "<$name$xmlns$type_str$atts>$pXml</$name>";
773 case (is_array($val) || $type):
774 // detect if struct or array
775 $valueType = $this->isArraySimpleOrStruct($val);
776 if($valueType=='arraySimple' || preg_match('/^ArrayOf/',$type)){
777 $this->debug("serialize_val: serialize array");
779 if(is_array($val) && count($val)> 0){
781 if(is_object($v) && get_class($v) == 'soapval'){
782 $tt_ns = $v->type_ns;
784 } elseif (is_array($v)) {
785 $tt = $this->isArraySimpleOrStruct($v);
789 $array_types[$tt] = 1;
790 // TODO: for literal, the name should be $name
791 $xml .= $this->serialize_val($v,'item',false,false,false,false,$use);
794 if(count($array_types) > 1){
795 $array_typename = 'xsd:anyType';
796 } elseif(isset($tt) && isset($this->typemap[$this->XMLSchemaVersion][$tt])) {
797 if ($tt == 'integer') {
800 $array_typename = 'xsd:'.$tt;
801 } elseif(isset($tt) && $tt == 'arraySimple'){
802 $array_typename = 'SOAP-ENC:Array';
803 } elseif(isset($tt) && $tt == 'arrayStruct'){
804 $array_typename = 'unnamed_struct_use_soapval';
806 // if type is prefixed, create type prefix
807 if ($tt_ns != '' && $tt_ns == $this->namespaces['xsd']){
808 $array_typename = 'xsd:' . $tt;
810 $tt_prefix = 'ns' . rand(1000, 9999);
811 $array_typename = "$tt_prefix:$tt";
812 $xmlns .= " xmlns:$tt_prefix=\"$tt_ns\"";
814 $array_typename = $tt;
818 if ($use == 'literal') {
820 } else if (isset($type) && isset($type_prefix)) {
821 $type_str = " xsi:type=\"$type_prefix:$type\"";
823 $type_str = " xsi:type=\"SOAP-ENC:Array\" SOAP-ENC:arrayType=\"".$array_typename."[$array_type]\"";
827 if ($use == 'literal') {
829 } else if (isset($type) && isset($type_prefix)) {
830 $type_str = " xsi:type=\"$type_prefix:$type\"";
832 $type_str = " xsi:type=\"SOAP-ENC:Array\" SOAP-ENC:arrayType=\"xsd:anyType[0]\"";
835 // TODO: for array in literal, there is no wrapper here
836 $xml = "<$name$xmlns$type_str$atts>".$xml."</$name>";
839 $this->debug("serialize_val: serialize struct");
840 if(isset($type) && isset($type_prefix)){
841 $type_str = " xsi:type=\"$type_prefix:$type\"";
845 if ($use == 'literal') {
846 $xml .= "<$name$xmlns$atts>";
848 $xml .= "<$name$xmlns$type_str$atts>";
850 foreach($val as $k => $v){
852 if ($type == 'Map' && $type_ns == 'http://xml.apache.org/xml-soap') {
854 $xml .= $this->serialize_val($k,'key',false,false,false,false,$use);
855 $xml .= $this->serialize_val($v,'value',false,false,false,false,$use);
858 $xml .= $this->serialize_val($v,$k,false,false,false,false,$use);
865 $this->debug("serialize_val: serialize unknown");
866 $xml .= 'not detected, got '.gettype($val).' for '.$val;
869 $this->debug("serialize_val returning $xml");
874 * serializes a message
876 * @param string $body the XML of the SOAP body
877 * @param mixed $headers optional string of XML with SOAP header content, or array of soapval objects for SOAP headers, or associative array
878 * @param array $namespaces optional the namespaces used in generating the body and headers
879 * @param string $style optional (rpc|document)
880 * @param string $use optional (encoded|literal)
881 * @param string $encodingStyle optional (usually 'http://schemas.xmlsoap.org/soap/encoding/' for encoded)
882 * @return string the message
885 function serializeEnvelope($body,$headers=false,$namespaces=array(),$style='rpc',$use='encoded',$encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'){
886 // TODO: add an option to automatically run utf8_encode on $body and $headers
887 // if $this->soap_defencoding is UTF-8. Not doing this automatically allows
888 // one to send arbitrary UTF-8 characters, not just characters that map to ISO-8859-1
890 $this->debug("In serializeEnvelope length=" . strlen($body) . " body (max 1000 characters)=" . substr($body, 0, 1000) . " style=$style use=$use encodingStyle=$encodingStyle");
891 $this->debug("headers:");
892 $this->appendDebug($this->varDump($headers));
893 $this->debug("namespaces:");
894 $this->appendDebug($this->varDump($namespaces));
896 // serialize namespaces
898 foreach(array_merge($this->namespaces,$namespaces) as $k => $v){
899 $ns_string .= " xmlns:$k=\"$v\"";
902 $ns_string = " SOAP-ENV:encodingStyle=\"$encodingStyle\"$ns_string";
907 if (is_array($headers)) {
909 foreach ($headers as $k => $v) {
910 if (is_object($v) && get_class($v) == 'soapval') {
911 $xml .= $this->serialize_val($v, false, false, false, false, false, $use);
913 $xml .= $this->serialize_val($v, $k, false, false, false, false, $use);
917 $this->debug("In serializeEnvelope, serialized array of headers to $headers");
919 $headers = "<SOAP-ENV:Header>".$headers."</SOAP-ENV:Header>";
921 // serialize envelope
923 '<?xml version="1.0" encoding="'.$this->soap_defencoding .'"?'.">".
924 '<SOAP-ENV:Envelope'.$ns_string.">".
929 "</SOAP-ENV:Envelope>";
933 * formats a string to be inserted into an HTML stream
935 * @param string $str The string to format
936 * @return string The formatted string
940 function formatDump($str){
941 $str = htmlspecialchars($str);
946 * contracts (changes namespace to prefix) a qualified name
948 * @param string $qname qname
949 * @return string contracted qname
952 function contractQname($qname){
953 // get element namespace
954 //$this->xdebug("Contract $qname");
955 if (strrpos($qname, ':')) {
956 // get unqualified name
957 $name = substr($qname, strrpos($qname, ':') + 1);
959 $ns = substr($qname, 0, strrpos($qname, ':'));
960 $p = $this->getPrefixFromNamespace($ns);
962 return $p . ':' . $name;
971 * expands (changes prefix to namespace) a qualified name
973 * @param string $qname qname
974 * @return string expanded qname
977 function expandQname($qname){
978 // get element prefix
979 if(strpos($qname,':') && !preg_match('/^http:\/\//',$qname)){
980 // get unqualified name
981 $name = substr(strstr($qname,':'),1);
983 $prefix = substr($qname,0,strpos($qname,':'));
984 if(isset($this->namespaces[$prefix])){
985 return $this->namespaces[$prefix].':'.$name;
995 * returns the local part of a prefixed string
996 * returns the original string, if not prefixed
998 * @param string $str The prefixed string
999 * @return string The local part
1002 function getLocalPart($str){
1003 if($sstr = strrchr($str,':')){
1004 // get unqualified name
1005 return substr( $sstr, 1 );
1012 * returns the prefix part of a prefixed string
1013 * returns false, if not prefixed
1015 * @param string $str The prefixed string
1016 * @return mixed The prefix or false if there is no prefix
1019 function getPrefix($str){
1020 if($pos = strrpos($str,':')){
1022 return substr($str,0,$pos);
1028 * pass it a prefix, it returns a namespace
1030 * @param string $prefix The prefix
1031 * @return mixed The namespace, false if no namespace has the specified prefix
1034 function getNamespaceFromPrefix($prefix){
1035 if (isset($this->namespaces[$prefix])) {
1036 return $this->namespaces[$prefix];
1038 //$this->setError("No namespace registered for prefix '$prefix'");
1043 * returns the prefix for a given namespace (or prefix)
1044 * or false if no prefixes registered for the given namespace
1046 * @param string $ns The namespace
1047 * @return mixed The prefix, false if the namespace has no prefixes
1050 function getPrefixFromNamespace($ns) {
1051 foreach ($this->namespaces as $p => $n) {
1052 if ($ns == $n || $ns == $p) {
1053 $this->usedNamespaces[$p] = $n;
1061 * returns the time in ODBC canonical form with microseconds
1063 * @return string The time in ODBC canonical form with microseconds
1066 function getmicrotime() {
1067 if (function_exists('gettimeofday')) {
1068 $tod = gettimeofday();
1070 $usec = $tod['usec'];
1075 return strftime('%Y-%m-%d %H:%M:%S', $sec) . '.' . sprintf('%06d', $usec);
1079 * Returns a string with the output of var_dump
1081 * @param mixed $data The variable to var_dump
1082 * @return string The output of var_dump
1085 function varDump($data) {
1088 $ret_val = ob_get_contents();
1094 * represents the object as a string
1099 function __toString() {
1100 return $this->varDump($this);
1104 // XML Schema Datatype Helper Functions
1106 //xsd:dateTime helpers
1109 * convert unix timestamp to ISO 8601 compliant date string
1111 * @param int $timestamp Unix time stamp
1112 * @param boolean $utc Whether the time stamp is UTC or local
1113 * @return mixed ISO 8601 date string or false
1116 function timestamp_to_iso8601($timestamp,$utc=true){
1117 $datestr = date('Y-m-d\TH:i:sO',$timestamp);
1118 $pos = strrpos($datestr, "+");
1119 if ($pos === FALSE) {
1120 $pos = strrpos($datestr, "-");
1122 if ($pos !== FALSE) {
1123 if (strlen($datestr) == $pos + 5) {
1124 $datestr = substr($datestr, 0, $pos + 3) . ':' . substr($datestr, -2);
1129 '([0-9]{4})-'. // centuries & years CCYY-
1130 '([0-9]{2})-'. // months MM-
1131 '([0-9]{2})'. // days DD
1133 '([0-9]{2}):'. // hours hh:
1134 '([0-9]{2}):'. // minutes mm:
1135 '([0-9]{2})(\.[0-9]*)?'. // seconds ss.ss...
1136 '(Z|[+\-][0-9]{2}:?[0-9]{2})?'. // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's
1139 if(preg_match($pattern,$datestr,$regs)){
1140 return sprintf('%04d-%02d-%02dT%02d:%02d:%02dZ',$regs[1],$regs[2],$regs[3],$regs[4],$regs[5],$regs[6]);
1149 * convert ISO 8601 compliant date string to unix timestamp
1151 * @param string $datestr ISO 8601 compliant date string
1152 * @return mixed Unix timestamp (int) or false
1155 function iso8601_to_timestamp($datestr){
1157 '([0-9]{4})-'. // centuries & years CCYY-
1158 '([0-9]{2})-'. // months MM-
1159 '([0-9]{2})'. // days DD
1161 '([0-9]{2}):'. // hours hh:
1162 '([0-9]{2}):'. // minutes mm:
1163 '([0-9]{2})(\.[0-9]+)?'. // seconds ss.ss...
1164 '(Z|[+\-][0-9]{2}:?[0-9]{2})?'. // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's
1166 if(preg_match($pattern,$datestr,$regs)){
1168 if($regs[8] != 'Z'){
1169 $op = substr($regs[8],0,1);
1170 $h = substr($regs[8],1,2);
1171 $m = substr($regs[8],strlen($regs[8])-2,2);
1173 $regs[4] = $regs[4] + $h;
1174 $regs[5] = $regs[5] + $m;
1175 } elseif($op == '+'){
1176 $regs[4] = $regs[4] - $h;
1177 $regs[5] = $regs[5] - $m;
1180 return gmmktime($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]);
1181 // return strtotime("$regs[1]-$regs[2]-$regs[3] $regs[4]:$regs[5]:$regs[6]Z");
1188 * sleeps some number of microseconds
1190 * @param string $usec the number of microseconds to sleep
1194 function usleepWindows($usec)
1196 $start = gettimeofday();
1200 $stop = gettimeofday();
1201 $timePassed = 1000000 * ($stop['sec'] - $start['sec'])
1202 + $stop['usec'] - $start['usec'];
1204 while ($timePassed < $usec);
1211 Modification information for LGPL compliance
1213 r58622 - 2010-10-22 18:18:59 -0700 (Fri, 22 Oct 2010) - engsvnbuild - Author: lam <lam@198.18.142.201>
1216 r58361 - 2010-09-29 16:59:02 -0700 (Wed, 29 Sep 2010) - kjing - Author: Jenny Gonsalves <jenny@sugarcrm.com>
1217 Merging with maint_6_0_1 (svn merge -r 58250:58342)
1219 r57813 - 2010-08-19 10:34:44 -0700 (Thu, 19 Aug 2010) - kjing - Author: John Mertic <jmertic@sugarcrm.com>
1220 Bug 39085 - When loading the opposite search panel via ajax on the ListViews, call the index action instead of the ListView action to avoid touching pre-MVC code by accident.
1222 r57707 - 2010-08-10 12:26:13 -0700 (Tue, 10 Aug 2010) - kjing - Author: Stanislav Malyshev <smalyshev@gmail.com>
1223 fix SOAP calls with no parameters
1225 r56990 - 2010-06-16 13:05:36 -0700 (Wed, 16 Jun 2010) - kjing - snapshot "Mango" svn branch to a new one for GitHub sync
1227 r56989 - 2010-06-16 13:01:33 -0700 (Wed, 16 Jun 2010) - kjing - defunt "Mango" svn dev branch before github cutover
1229 r55980 - 2010-04-19 13:31:28 -0700 (Mon, 19 Apr 2010) - kjing - create Mango (6.1) based on windex
1231 r51719 - 2009-10-22 10:18:00 -0700 (Thu, 22 Oct 2009) - mitani - Converted to Build 3 tags and updated the build system
1233 r51634 - 2009-10-19 13:32:22 -0700 (Mon, 19 Oct 2009) - mitani - Windex is the branch for Sugar Sales 1.0 development
1235 r51508 - 2009-10-14 07:40:23 -0700 (Wed, 14 Oct 2009) - jmertic - More fallout fixes from the PHP 5.3 ereg to preg changes.
1237 r51455 - 2009-10-13 07:56:48 -0700 (Tue, 13 Oct 2009) - jmertic - Bug 33202 - Enable install of SugarCRM on PHP 5.3.0, asserting that the minimum supported version is PHP 5.2.x.
1239 r51443 - 2009-10-12 13:34:36 -0700 (Mon, 12 Oct 2009) - jmertic - Bug 33332 - Made application PHP 5.3 compliant with E_DEPRECATED warnings on by:
1240 - Changing all ereg function to either preg or simple string based ones
1241 - No more references to magic quotes.
1242 - Change all the session_unregister() functions to just unset() the correct session variable instead.
1244 r50375 - 2009-08-24 18:07:43 -0700 (Mon, 24 Aug 2009) - dwong - branch kobe2 from tokyo r50372
1246 r45763 - 2009-04-01 12:16:18 -0700 (Wed, 01 Apr 2009) - majed - Removed half of the require_once and include_onces in the product that were redundant or could be handled easily by the auto loader
1248 r45680 - 2009-03-30 14:34:35 -0700 (Mon, 30 Mar 2009) - Samir Gandhi - modifeid serializeSchema to generate WS-I compliant WSDL
1250 r42807 - 2008-12-29 11:16:59 -0800 (Mon, 29 Dec 2008) - dwong - Branch from trunk/sugarcrm r42806 to branches/tokyo/sugarcrm
1252 r42645 - 2008-12-18 13:41:08 -0800 (Thu, 18 Dec 2008) - awu - merging maint_5_2_0 rev41336:HEAD to trunk
1254 r41647 - 2008-11-11 17:44:30 -0800 (Tue, 11 Nov 2008) - majed - Fixes a few bugs
1256 r41596 - 2008-11-10 19:20:04 -0800 (Mon, 10 Nov 2008) - Samir Gandhi - modified to set $method in the code
1258 r41558 - 2008-11-10 14:35:34 -0800 (Mon, 10 Nov 2008) - majed - changes nusoap to allow for registering classes
1260 r39619 - 2008-09-09 13:41:34 -0700 (Tue, 09 Sep 2008) - jmertic - Bug 24827 - Remove all instances where we return a new object and assign it by reference, since this is deprecated in PHP 5 and emits E_DEPRECATED errors in PHP 5.3.
1262 - data/SugarBean.php
1263 - include/domit/php_http_client_generic.php
1264 - include/domit/php_http_connector.php
1265 - include/domit/testing_domit.php
1266 - include/domit/xml_domit_getelementsbypath.php
1267 - include/domit/xml_domit_lite_parser.php
1268 - include/domit/xml_domit_nodemaps.php
1269 - include/domit/xml_domit_parser.php
1270 - include/domit/xml_domit_shared.php
1271 - include/generic/SugarWidgets/SugarWidgetField.php
1272 - include/generic/SugarWidgets/SugarWidgetReportField.php
1273 - include/ListView/ProcessView.php
1274 - include/nusoap/class.soapclient.php
1275 - include/nusoap/nusoap.php
1276 - include/nusoap/nusoapmime.php
1277 - include/Pear/HTML_Safe/Safe.php
1278 - include/Pear/XML_HTMLSax3/HTMLSax3.php
1279 - modules/Administration/RebuildWorkFlow.php
1280 - modules/Expressions/RelateSelector.php
1281 - modules/Reports/templates/templates_reports.php
1282 - modules/WorkFlow/Delete.php
1283 - modules/WorkFlow/Save.php
1284 - modules/WorkFlow/SaveSequence.php
1285 - modules/WorkFlow/WorkFlow.php
1286 - modules/WorkFlowActionShells/CreateStep1.php
1287 - modules/WorkFlowActionShells/CreateStep2.php
1288 - modules/WorkFlowActionShells/Save.php
1289 - modules/WorkFlowActionShells/WorkFlowActionShell.php
1290 - modules/WorkFlowAlerts/Save.php
1291 - modules/WorkFlowAlerts/WorkFlowAlert.php
1292 - modules/WorkFlowAlertShells/DetailView.php
1293 - modules/WorkFlowAlertShells/WorkFlowAlertShell.php
1294 - modules/WorkFlowTriggerShells/CreateStep1.php
1295 - modules/WorkFlowTriggerShells/CreateStepFilter.php
1296 - modules/WorkFlowTriggerShells/SaveFilter.php
1297 - modules/WorkFlowTriggerShells/WorkFlowTriggerShell.php
1298 - soap/SoapHelperFunctions.php
1299 - test/modules/DynamicFields/DynamicFields_Bug24095_test.php
1300 - test/simpletest/browser.php
1301 - test/simpletest/default_reporter.php
1302 - test/simpletest/detached.php
1303 - test/simpletest/eclipse.php
1304 - test/simpletest/expectation.php
1305 - test/simpletest/extensions/pear_test_case.php
1306 - test/simpletest/form.php
1307 - test/simpletest/http.php
1308 - test/simpletest/mock_objects.php
1309 - test/simpletest/page.php
1310 - test/simpletest/parser.php
1311 - test/simpletest/remote.php
1312 - test/simpletest/shell_tester.php
1313 - test/simpletest/simple_test.php
1314 - test/simpletest/simpletest.php
1315 - test/simpletest/test/acceptance_test.php
1316 - test/simpletest/test/adapter_test.php
1317 - test/simpletest/test/authentication_test.php
1318 - test/simpletest/test/browser_test.php
1319 - test/simpletest/test/collector_test.php
1320 - test/simpletest/test/compatibility_test.php
1321 - test/simpletest/test/detached_test.php
1322 - test/simpletest/test/eclipse_test.php
1323 - test/simpletest/test/encoding_test.php
1324 - test/simpletest/test/errors_test.php
1325 - test/simpletest/test/expectation_test.php
1326 - test/simpletest/test/form_test.php
1327 - test/simpletest/test/frames_test.php
1328 - test/simpletest/test/http_test.php
1329 - test/simpletest/test/live_test.php
1330 - test/simpletest/test/mock_objects_test.php
1331 - test/simpletest/test/page_test.php
1332 - test/simpletest/test/parse_error_test.php
1333 - test/simpletest/test/parser_test.php
1334 - test/simpletest/test/remote_test.php
1335 - test/simpletest/test/shell_test.php
1336 - test/simpletest/test/shell_tester_test.php
1337 - test/simpletest/test/simpletest_test.php
1338 - test/simpletest/test/site/page_request.php
1339 - test/simpletest/test/tag_test.php
1340 - test/simpletest/test/unit_tester_test.php
1341 - test/simpletest/test/user_agent_test.php
1342 - test/simpletest/test/visual_test.php
1343 - test/simpletest/test/xml_test.php
1344 - test/simpletest/test_case.php
1345 - test/simpletest/ui/array_reporter/test.php
1346 - test/simpletest/ui/recorder/test.php
1347 - test/simpletest/unit_tester.php
1348 - test/simpletest/url.php
1349 - test/simpletest/user_agent.php
1350 - test/simpletest/web_tester.php
1351 - test/spikephpcoverage/src/PEAR.php
1352 - test/spikephpcoverage/src/util/Utility.php
1353 - test/spikephpcoverage/src/XML/Parser.php
1354 - test/spikephpcoverage/src/XML/Parser/Simple.php
1355 - test/test_utilities/SugarTest_SimpleBrowser.php
1357 r38362 - 2008-07-28 14:06:59 -0700 (Mon, 28 Jul 2008) - roger - bug: 23897. Using print_r when using the debug statement in nusoap will print out the statements to the screen if the call is coming from the UI.
1359 r38300 - 2008-07-25 13:33:43 -0700 (Fri, 25 Jul 2008) - Samir Gandhi - put the debug in parseresponse function
1361 r38293 - 2008-07-25 12:32:34 -0700 (Fri, 25 Jul 2008) - Samir Gandhi - to put all the debug statements return value in the call function
1363 r36824 - 2008-06-18 09:26:11 -0700 (Wed, 18 Jun 2008) - roger - bug: 21832
1365 r26422 - 2007-09-05 17:29:12 -0700 (Wed, 05 Sep 2007) - majed - migrate from beta 1 to trunk
1367 r15787 - 2006-08-10 10:14:41 -0700 (Thu, 10 Aug 2006) - roger - RRS: bug 7961
1369 r14701 - 2006-07-17 13:37:26 -0700 (Mon, 17 Jul 2006) - roger - RRS: bug 5801
1371 r13782 - 2006-06-06 10:58:55 -0700 (Tue, 06 Jun 2006) - majed - changes entry point code
1373 r11466 - 2006-02-01 15:49:47 -0800 (Wed, 01 Feb 2006) - jacob - Adding extra !empty check to get around a PHP warning.
1375 r11115 - 2006-01-17 14:54:45 -0800 (Tue, 17 Jan 2006) - majed - add entry point validation
1377 r10585 - 2005-12-13 14:42:26 -0800 (Tue, 13 Dec 2005) - majed - adds new license mechanisim
1379 r10170 - 2005-12-05 18:37:46 -0800 (Mon, 05 Dec 2005) - majed - fixes various issues
1381 r8999 - 2005-11-04 05:26:49 -0800 (Fri, 04 Nov 2005) - roger - When nusoap was upgraded we had an issue with the user's default language not being populated during a soap request. I determined the reason this was happening and have checked in the corresponding change to nusoap.
1383 r8991 - 2005-11-03 19:07:25 -0800 (Thu, 03 Nov 2005) - majed - fixes nusoap issue
1385 r8846 - 2005-10-31 11:01:12 -0800 (Mon, 31 Oct 2005) - majed - new version of nusoap
1387 r7905 - 2005-09-21 19:12:57 -0700 (Wed, 21 Sep 2005) - majed - restores old nusoap pre & with a few fixes
1389 r7861 - 2005-09-20 15:40:25 -0700 (Tue, 20 Sep 2005) - majed - & fix for 3.5.1
1391 r7452 - 2005-08-17 11:32:34 -0700 (Wed, 17 Aug 2005) - majed - changes soap to nusoap
1393 r5820 - 2005-06-21 14:22:24 -0700 (Tue, 21 Jun 2005) - majed - fixes issues with nusoap and with custom fields
1395 r5462 - 2005-05-25 13:50:11 -0700 (Wed, 25 May 2005) - majed - upgraded nusoap to .6.9
1397 r5104 - 2005-05-04 15:33:41 -0700 (Wed, 04 May 2005) - majed - gets rid of HTTP_GET_VARS and what not which has been deprecated
1399 r573 - 2004-09-04 13:03:32 -0700 (Sat, 04 Sep 2004) - sugarclint - undoing copyrights added in inadvertantly. --clint
1401 r546 - 2004-09-03 11:49:38 -0700 (Fri, 03 Sep 2004) - sugarmsi - removed echo count
1403 r354 - 2004-08-02 23:00:37 -0700 (Mon, 02 Aug 2004) - sugarjacob - Adding Soap
1413 * Contains information for a SOAP fault.
1414 * Mainly used for returning faults from deployed functions
1415 * in a server instance.
1416 * @author Dietrich Ayala <dietrich@ganx4.com>
1420 class nusoap_fault extends nusoap_base {
1422 * The fault code (client|server)
1434 * The fault string, a description of the fault
1440 * The fault detail, typically a string or array of string
1449 * @param string $faultcode (SOAP-ENV:Client | SOAP-ENV:Server)
1450 * @param string $faultactor only used when msg routed between multiple actors
1451 * @param string $faultstring human readable error message
1452 * @param mixed $faultdetail detail, typically a string or array of string
1454 function nusoap_fault($faultcode,$faultactor='',$faultstring='',$faultdetail=''){
1455 parent::nusoap_base();
1456 $this->faultcode = $faultcode;
1457 $this->faultactor = $faultactor;
1458 $this->faultstring = $faultstring;
1459 $this->faultdetail = $faultdetail;
1465 * @return string The serialization of the fault instance.
1468 function serialize(){
1470 foreach($this->namespaces as $k => $v){
1471 $ns_string .= "\n xmlns:$k=\"$v\"";
1474 '<?xml version="1.0" encoding="'.$this->soap_defencoding.'"?>'.
1475 '<SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"'.$ns_string.">\n".
1478 $this->serialize_val($this->faultcode, 'faultcode').
1479 $this->serialize_val($this->faultactor, 'faultactor').
1480 $this->serialize_val($this->faultstring, 'faultstring').
1481 $this->serialize_val($this->faultdetail, 'detail').
1482 '</SOAP-ENV:Fault>'.
1484 '</SOAP-ENV:Envelope>';
1490 * Backward compatibility
1492 class soap_fault extends nusoap_fault {
1499 Modification information for LGPL compliance
1501 r58622 - 2010-10-22 18:18:59 -0700 (Fri, 22 Oct 2010) - engsvnbuild - Author: lam <lam@198.18.142.201>
1504 r58361 - 2010-09-29 16:59:02 -0700 (Wed, 29 Sep 2010) - kjing - Author: Jenny Gonsalves <jenny@sugarcrm.com>
1505 Merging with maint_6_0_1 (svn merge -r 58250:58342)
1507 r57813 - 2010-08-19 10:34:44 -0700 (Thu, 19 Aug 2010) - kjing - Author: John Mertic <jmertic@sugarcrm.com>
1508 Bug 39085 - When loading the opposite search panel via ajax on the ListViews, call the index action instead of the ListView action to avoid touching pre-MVC code by accident.
1510 r57707 - 2010-08-10 12:26:13 -0700 (Tue, 10 Aug 2010) - kjing - Author: Stanislav Malyshev <smalyshev@gmail.com>
1511 fix SOAP calls with no parameters
1513 r56990 - 2010-06-16 13:05:36 -0700 (Wed, 16 Jun 2010) - kjing - snapshot "Mango" svn branch to a new one for GitHub sync
1515 r56989 - 2010-06-16 13:01:33 -0700 (Wed, 16 Jun 2010) - kjing - defunt "Mango" svn dev branch before github cutover
1517 r55980 - 2010-04-19 13:31:28 -0700 (Mon, 19 Apr 2010) - kjing - create Mango (6.1) based on windex
1519 r51719 - 2009-10-22 10:18:00 -0700 (Thu, 22 Oct 2009) - mitani - Converted to Build 3 tags and updated the build system
1521 r51634 - 2009-10-19 13:32:22 -0700 (Mon, 19 Oct 2009) - mitani - Windex is the branch for Sugar Sales 1.0 development
1523 r51508 - 2009-10-14 07:40:23 -0700 (Wed, 14 Oct 2009) - jmertic - More fallout fixes from the PHP 5.3 ereg to preg changes.
1525 r51455 - 2009-10-13 07:56:48 -0700 (Tue, 13 Oct 2009) - jmertic - Bug 33202 - Enable install of SugarCRM on PHP 5.3.0, asserting that the minimum supported version is PHP 5.2.x.
1527 r51443 - 2009-10-12 13:34:36 -0700 (Mon, 12 Oct 2009) - jmertic - Bug 33332 - Made application PHP 5.3 compliant with E_DEPRECATED warnings on by:
1528 - Changing all ereg function to either preg or simple string based ones
1529 - No more references to magic quotes.
1530 - Change all the session_unregister() functions to just unset() the correct session variable instead.
1532 r50375 - 2009-08-24 18:07:43 -0700 (Mon, 24 Aug 2009) - dwong - branch kobe2 from tokyo r50372
1534 r45763 - 2009-04-01 12:16:18 -0700 (Wed, 01 Apr 2009) - majed - Removed half of the require_once and include_onces in the product that were redundant or could be handled easily by the auto loader
1536 r45680 - 2009-03-30 14:34:35 -0700 (Mon, 30 Mar 2009) - Samir Gandhi - modifeid serializeSchema to generate WS-I compliant WSDL
1538 r42807 - 2008-12-29 11:16:59 -0800 (Mon, 29 Dec 2008) - dwong - Branch from trunk/sugarcrm r42806 to branches/tokyo/sugarcrm
1540 r42645 - 2008-12-18 13:41:08 -0800 (Thu, 18 Dec 2008) - awu - merging maint_5_2_0 rev41336:HEAD to trunk
1542 r41647 - 2008-11-11 17:44:30 -0800 (Tue, 11 Nov 2008) - majed - Fixes a few bugs
1544 r41596 - 2008-11-10 19:20:04 -0800 (Mon, 10 Nov 2008) - Samir Gandhi - modified to set $method in the code
1546 r41558 - 2008-11-10 14:35:34 -0800 (Mon, 10 Nov 2008) - majed - changes nusoap to allow for registering classes
1548 r39619 - 2008-09-09 13:41:34 -0700 (Tue, 09 Sep 2008) - jmertic - Bug 24827 - Remove all instances where we return a new object and assign it by reference, since this is deprecated in PHP 5 and emits E_DEPRECATED errors in PHP 5.3.
1550 - data/SugarBean.php
1551 - include/domit/php_http_client_generic.php
1552 - include/domit/php_http_connector.php
1553 - include/domit/testing_domit.php
1554 - include/domit/xml_domit_getelementsbypath.php
1555 - include/domit/xml_domit_lite_parser.php
1556 - include/domit/xml_domit_nodemaps.php
1557 - include/domit/xml_domit_parser.php
1558 - include/domit/xml_domit_shared.php
1559 - include/generic/SugarWidgets/SugarWidgetField.php
1560 - include/generic/SugarWidgets/SugarWidgetReportField.php
1561 - include/ListView/ProcessView.php
1562 - include/nusoap/class.soapclient.php
1563 - include/nusoap/nusoap.php
1564 - include/nusoap/nusoapmime.php
1565 - include/Pear/HTML_Safe/Safe.php
1566 - include/Pear/XML_HTMLSax3/HTMLSax3.php
1567 - modules/Administration/RebuildWorkFlow.php
1568 - modules/Expressions/RelateSelector.php
1569 - modules/Reports/templates/templates_reports.php
1570 - modules/WorkFlow/Delete.php
1571 - modules/WorkFlow/Save.php
1572 - modules/WorkFlow/SaveSequence.php
1573 - modules/WorkFlow/WorkFlow.php
1574 - modules/WorkFlowActionShells/CreateStep1.php
1575 - modules/WorkFlowActionShells/CreateStep2.php
1576 - modules/WorkFlowActionShells/Save.php
1577 - modules/WorkFlowActionShells/WorkFlowActionShell.php
1578 - modules/WorkFlowAlerts/Save.php
1579 - modules/WorkFlowAlerts/WorkFlowAlert.php
1580 - modules/WorkFlowAlertShells/DetailView.php
1581 - modules/WorkFlowAlertShells/WorkFlowAlertShell.php
1582 - modules/WorkFlowTriggerShells/CreateStep1.php
1583 - modules/WorkFlowTriggerShells/CreateStepFilter.php
1584 - modules/WorkFlowTriggerShells/SaveFilter.php
1585 - modules/WorkFlowTriggerShells/WorkFlowTriggerShell.php
1586 - soap/SoapHelperFunctions.php
1587 - test/modules/DynamicFields/DynamicFields_Bug24095_test.php
1588 - test/simpletest/browser.php
1589 - test/simpletest/default_reporter.php
1590 - test/simpletest/detached.php
1591 - test/simpletest/eclipse.php
1592 - test/simpletest/expectation.php
1593 - test/simpletest/extensions/pear_test_case.php
1594 - test/simpletest/form.php
1595 - test/simpletest/http.php
1596 - test/simpletest/mock_objects.php
1597 - test/simpletest/page.php
1598 - test/simpletest/parser.php
1599 - test/simpletest/remote.php
1600 - test/simpletest/shell_tester.php
1601 - test/simpletest/simple_test.php
1602 - test/simpletest/simpletest.php
1603 - test/simpletest/test/acceptance_test.php
1604 - test/simpletest/test/adapter_test.php
1605 - test/simpletest/test/authentication_test.php
1606 - test/simpletest/test/browser_test.php
1607 - test/simpletest/test/collector_test.php
1608 - test/simpletest/test/compatibility_test.php
1609 - test/simpletest/test/detached_test.php
1610 - test/simpletest/test/eclipse_test.php
1611 - test/simpletest/test/encoding_test.php
1612 - test/simpletest/test/errors_test.php
1613 - test/simpletest/test/expectation_test.php
1614 - test/simpletest/test/form_test.php
1615 - test/simpletest/test/frames_test.php
1616 - test/simpletest/test/http_test.php
1617 - test/simpletest/test/live_test.php
1618 - test/simpletest/test/mock_objects_test.php
1619 - test/simpletest/test/page_test.php
1620 - test/simpletest/test/parse_error_test.php
1621 - test/simpletest/test/parser_test.php
1622 - test/simpletest/test/remote_test.php
1623 - test/simpletest/test/shell_test.php
1624 - test/simpletest/test/shell_tester_test.php
1625 - test/simpletest/test/simpletest_test.php
1626 - test/simpletest/test/site/page_request.php
1627 - test/simpletest/test/tag_test.php
1628 - test/simpletest/test/unit_tester_test.php
1629 - test/simpletest/test/user_agent_test.php
1630 - test/simpletest/test/visual_test.php
1631 - test/simpletest/test/xml_test.php
1632 - test/simpletest/test_case.php
1633 - test/simpletest/ui/array_reporter/test.php
1634 - test/simpletest/ui/recorder/test.php
1635 - test/simpletest/unit_tester.php
1636 - test/simpletest/url.php
1637 - test/simpletest/user_agent.php
1638 - test/simpletest/web_tester.php
1639 - test/spikephpcoverage/src/PEAR.php
1640 - test/spikephpcoverage/src/util/Utility.php
1641 - test/spikephpcoverage/src/XML/Parser.php
1642 - test/spikephpcoverage/src/XML/Parser/Simple.php
1643 - test/test_utilities/SugarTest_SimpleBrowser.php
1645 r38362 - 2008-07-28 14:06:59 -0700 (Mon, 28 Jul 2008) - roger - bug: 23897. Using print_r when using the debug statement in nusoap will print out the statements to the screen if the call is coming from the UI.
1647 r38300 - 2008-07-25 13:33:43 -0700 (Fri, 25 Jul 2008) - Samir Gandhi - put the debug in parseresponse function
1649 r38293 - 2008-07-25 12:32:34 -0700 (Fri, 25 Jul 2008) - Samir Gandhi - to put all the debug statements return value in the call function
1651 r36824 - 2008-06-18 09:26:11 -0700 (Wed, 18 Jun 2008) - roger - bug: 21832
1653 r26422 - 2007-09-05 17:29:12 -0700 (Wed, 05 Sep 2007) - majed - migrate from beta 1 to trunk
1655 r15787 - 2006-08-10 10:14:41 -0700 (Thu, 10 Aug 2006) - roger - RRS: bug 7961
1657 r14701 - 2006-07-17 13:37:26 -0700 (Mon, 17 Jul 2006) - roger - RRS: bug 5801
1659 r13782 - 2006-06-06 10:58:55 -0700 (Tue, 06 Jun 2006) - majed - changes entry point code
1661 r11466 - 2006-02-01 15:49:47 -0800 (Wed, 01 Feb 2006) - jacob - Adding extra !empty check to get around a PHP warning.
1663 r11115 - 2006-01-17 14:54:45 -0800 (Tue, 17 Jan 2006) - majed - add entry point validation
1665 r10585 - 2005-12-13 14:42:26 -0800 (Tue, 13 Dec 2005) - majed - adds new license mechanisim
1667 r10170 - 2005-12-05 18:37:46 -0800 (Mon, 05 Dec 2005) - majed - fixes various issues
1669 r8999 - 2005-11-04 05:26:49 -0800 (Fri, 04 Nov 2005) - roger - When nusoap was upgraded we had an issue with the user's default language not being populated during a soap request. I determined the reason this was happening and have checked in the corresponding change to nusoap.
1671 r8991 - 2005-11-03 19:07:25 -0800 (Thu, 03 Nov 2005) - majed - fixes nusoap issue
1673 r8846 - 2005-10-31 11:01:12 -0800 (Mon, 31 Oct 2005) - majed - new version of nusoap
1675 r7905 - 2005-09-21 19:12:57 -0700 (Wed, 21 Sep 2005) - majed - restores old nusoap pre & with a few fixes
1677 r7861 - 2005-09-20 15:40:25 -0700 (Tue, 20 Sep 2005) - majed - & fix for 3.5.1
1679 r7452 - 2005-08-17 11:32:34 -0700 (Wed, 17 Aug 2005) - majed - changes soap to nusoap
1681 r5820 - 2005-06-21 14:22:24 -0700 (Tue, 21 Jun 2005) - majed - fixes issues with nusoap and with custom fields
1683 r5462 - 2005-05-25 13:50:11 -0700 (Wed, 25 May 2005) - majed - upgraded nusoap to .6.9
1685 r5104 - 2005-05-04 15:33:41 -0700 (Wed, 04 May 2005) - majed - gets rid of HTTP_GET_VARS and what not which has been deprecated
1687 r573 - 2004-09-04 13:03:32 -0700 (Sat, 04 Sep 2004) - sugarclint - undoing copyrights added in inadvertantly. --clint
1689 r546 - 2004-09-03 11:49:38 -0700 (Fri, 03 Sep 2004) - sugarmsi - removed echo count
1691 r354 - 2004-08-02 23:00:37 -0700 (Mon, 02 Aug 2004) - sugarjacob - Adding Soap
1701 * parses an XML Schema, allows access to it's data, other utility methods.
1702 * imperfect, no validation... yet, but quite functional.
1704 * @author Dietrich Ayala <dietrich@ganx4.com>
1705 * @author Scott Nichol <snichol@users.sourceforge.net>
1709 class nusoap_xmlschema extends nusoap_base {
1715 var $enclosingNamespaces;
1717 var $schemaInfo = array();
1718 var $schemaTargetNamespace = '';
1719 // types, elements, attributes defined by the schema
1720 var $attributes = array();
1721 var $complexTypes = array();
1722 var $complexTypeStack = array();
1723 var $currentComplexType = null;
1724 var $elements = array();
1725 var $elementStack = array();
1726 var $currentElement = null;
1727 var $simpleTypes = array();
1728 var $simpleTypeStack = array();
1729 var $currentSimpleType = null;
1731 var $imports = array();
1736 var $depth_array = array();
1737 var $message = array();
1738 var $defaultNamespace = array();
1743 * @param string $schema schema document URI
1744 * @param string $xml xml document URI
1745 * @param string $namespaces namespaces defined in enclosing XML
1748 function nusoap_xmlschema($schema='',$xml='',$namespaces=array()){
1749 parent::nusoap_base();
1750 $this->debug('nusoap_xmlschema class instantiated, inside constructor');
1752 $this->schema = $schema;
1756 $this->enclosingNamespaces = $namespaces;
1757 $this->namespaces = array_merge($this->namespaces, $namespaces);
1759 // parse schema file
1761 $this->debug('initial schema file: '.$schema);
1762 $this->parseFile($schema, 'schema');
1767 $this->debug('initial xml file: '.$xml);
1768 $this->parseFile($xml, 'xml');
1776 * @param string $xml path/URL to XML file
1777 * @param string $type (schema | xml)
1781 function parseFile($xml,$type){
1784 $xmlStr = @join("",@file($xml));
1786 $msg = 'Error reading XML from '.$xml;
1787 $this->setError($msg);
1791 $this->debug("parsing $xml");
1792 $this->parseString($xmlStr,$type);
1793 $this->debug("done parsing $xml");
1801 * parse an XML string
1803 * @param string $xml path or URL
1804 * @param string $type (schema|xml)
1807 function parseString($xml,$type){
1811 // Create an XML parser.
1812 $this->parser = xml_parser_create();
1813 // Set the options for parsing the XML data.
1814 xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
1816 // Set the object for the parser.
1817 xml_set_object($this->parser, $this);
1819 // Set the element handlers for the parser.
1820 if($type == "schema"){
1821 xml_set_element_handler($this->parser, 'schemaStartElement','schemaEndElement');
1822 xml_set_character_data_handler($this->parser,'schemaCharacterData');
1823 } elseif($type == "xml"){
1824 xml_set_element_handler($this->parser, 'xmlStartElement','xmlEndElement');
1825 xml_set_character_data_handler($this->parser,'xmlCharacterData');
1828 // Parse the XML file.
1829 if(!xml_parse($this->parser,$xml,true)){
1830 // Display an error message.
1831 $errstr = sprintf('XML error parsing XML schema on line %d: %s',
1832 xml_get_current_line_number($this->parser),
1833 xml_error_string(xml_get_error_code($this->parser))
1835 $this->debug($errstr);
1836 $this->debug("XML payload:\n" . $xml);
1837 $this->setError($errstr);
1840 xml_parser_free($this->parser);
1842 $this->debug('no xml passed to parseString()!!');
1843 $this->setError('no xml passed to parseString()!!');
1848 * gets a type name for an unnamed type
1850 * @param string Element name
1851 * @return string A type name for an unnamed type
1854 function CreateTypeName($ename) {
1856 for ($i = 0; $i < count($this->complexTypeStack); $i++) {
1857 $scope .= $this->complexTypeStack[$i] . '_';
1859 return $scope . $ename . '_ContainedType';
1863 * start-element handler
1865 * @param string $parser XML parser object
1866 * @param string $name element name
1867 * @param string $attrs associative array of attributes
1870 function schemaStartElement($parser, $name, $attrs) {
1872 // position in the total number of elements, starting from 0
1873 $pos = $this->position++;
1874 $depth = $this->depth++;
1875 // set self as current value for this depth
1876 $this->depth_array[$depth] = $pos;
1877 $this->message[$pos] = array('cdata' => '');
1879 $this->defaultNamespace[$pos] = $this->defaultNamespace[$this->depth_array[$depth - 1]];
1881 $this->defaultNamespace[$pos] = false;
1884 // get element prefix
1885 if($prefix = $this->getPrefix($name)){
1886 // get unqualified name
1887 $name = $this->getLocalPart($name);
1892 // loop thru attributes, expanding, and registering namespace declarations
1893 if(count($attrs) > 0){
1894 foreach($attrs as $k => $v){
1895 // if ns declarations, add to class level array of valid namespaces
1896 if(preg_match('/^xmlns/',$k)){
1897 //$this->xdebug("$k: $v");
1898 //$this->xdebug('ns_prefix: '.$this->getPrefix($k));
1899 if($ns_prefix = substr(strrchr($k,':'),1)){
1900 //$this->xdebug("Add namespace[$ns_prefix] = $v");
1901 $this->namespaces[$ns_prefix] = $v;
1903 $this->defaultNamespace[$pos] = $v;
1904 if (! $this->getPrefixFromNamespace($v)) {
1905 $this->namespaces['ns'.(count($this->namespaces)+1)] = $v;
1908 if($v == 'http://www.w3.org/2001/XMLSchema' || $v == 'http://www.w3.org/1999/XMLSchema' || $v == 'http://www.w3.org/2000/10/XMLSchema'){
1909 $this->XMLSchemaVersion = $v;
1910 $this->namespaces['xsi'] = $v.'-instance';
1914 foreach($attrs as $k => $v){
1915 // expand each attribute
1916 $k = strpos($k,':') ? $this->expandQname($k) : $k;
1917 $v = strpos($v,':') ? $this->expandQname($v) : $v;
1924 // find status, register data
1926 case 'all': // (optional) compositor content for a complexType
1930 //$this->xdebug("compositor $name for currentComplexType: $this->currentComplexType and currentElement: $this->currentElement");
1931 $this->complexTypes[$this->currentComplexType]['compositor'] = $name;
1932 //if($name == 'all' || $name == 'sequence'){
1933 // $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
1936 case 'attribute': // complexType attribute
1937 //$this->xdebug("parsing attribute $attrs[name] $attrs[ref] of value: ".$attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']);
1938 $this->xdebug("parsing attribute:");
1939 $this->appendDebug($this->varDump($attrs));
1940 if (!isset($attrs['form'])) {
1941 // TODO: handle globals
1942 $attrs['form'] = $this->schemaInfo['attributeFormDefault'];
1944 if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])) {
1945 $v = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
1946 if (!strpos($v, ':')) {
1947 // no namespace in arrayType attribute value...
1948 if ($this->defaultNamespace[$pos]) {
1949 // ...so use the default
1950 $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'] = $this->defaultNamespace[$pos] . ':' . $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
1954 if(isset($attrs['name'])){
1955 $this->attributes[$attrs['name']] = $attrs;
1956 $aname = $attrs['name'];
1957 } elseif(isset($attrs['ref']) && $attrs['ref'] == 'http://schemas.xmlsoap.org/soap/encoding/:arrayType'){
1958 if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])) {
1959 $aname = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
1963 } elseif(isset($attrs['ref'])){
1964 $aname = $attrs['ref'];
1965 $this->attributes[$attrs['ref']] = $attrs;
1968 if($this->currentComplexType){ // This should *always* be
1969 $this->complexTypes[$this->currentComplexType]['attrs'][$aname] = $attrs;
1971 // arrayType attribute
1972 if(isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']) || $this->getLocalPart($aname) == 'arrayType'){
1973 $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
1974 $prefix = $this->getPrefix($aname);
1975 if(isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])){
1976 $v = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
1980 if(strpos($v,'[,]')){
1981 $this->complexTypes[$this->currentComplexType]['multidimensional'] = true;
1983 $v = substr($v,0,strpos($v,'[')); // clip the []
1984 if(!strpos($v,':') && isset($this->typemap[$this->XMLSchemaVersion][$v])){
1985 $v = $this->XMLSchemaVersion.':'.$v;
1987 $this->complexTypes[$this->currentComplexType]['arrayType'] = $v;
1990 case 'complexContent': // (optional) content for a complexType
1991 $this->xdebug("do nothing for element $name");
1994 array_push($this->complexTypeStack, $this->currentComplexType);
1995 if(isset($attrs['name'])){
1996 // TODO: what is the scope of named complexTypes that appear
1997 // nested within other c complexTypes?
1998 $this->xdebug('processing named complexType '.$attrs['name']);
1999 //$this->currentElement = false;
2000 $this->currentComplexType = $attrs['name'];
2001 $this->complexTypes[$this->currentComplexType] = $attrs;
2002 $this->complexTypes[$this->currentComplexType]['typeClass'] = 'complexType';
2003 // This is for constructs like
2004 // <complexType name="ListOfString" base="soap:Array">
2006 // <element name="string" type="xsd:string"
2007 // minOccurs="0" maxOccurs="unbounded" />
2010 if(isset($attrs['base']) && preg_match('/:Array$/',$attrs['base'])){
2011 $this->xdebug('complexType is unusual array');
2012 $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
2014 $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
2017 $name = $this->CreateTypeName($this->currentElement);
2018 $this->xdebug('processing unnamed complexType for element ' . $this->currentElement . ' named ' . $name);
2019 $this->currentComplexType = $name;
2020 //$this->currentElement = false;
2021 $this->complexTypes[$this->currentComplexType] = $attrs;
2022 $this->complexTypes[$this->currentComplexType]['typeClass'] = 'complexType';
2023 // This is for constructs like
2024 // <complexType name="ListOfString" base="soap:Array">
2026 // <element name="string" type="xsd:string"
2027 // minOccurs="0" maxOccurs="unbounded" />
2030 if(isset($attrs['base']) && preg_match('/:Array$/',$attrs['base'])){
2031 $this->xdebug('complexType is unusual array');
2032 $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
2034 $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
2037 $this->complexTypes[$this->currentComplexType]['simpleContent'] = 'false';
2040 array_push($this->elementStack, $this->currentElement);
2041 if (!isset($attrs['form'])) {
2042 if ($this->currentComplexType) {
2043 $attrs['form'] = $this->schemaInfo['elementFormDefault'];
2046 $attrs['form'] = 'qualified';
2049 if(isset($attrs['type'])){
2050 $this->xdebug("processing typed element ".$attrs['name']." of type ".$attrs['type']);
2051 if (! $this->getPrefix($attrs['type'])) {
2052 if ($this->defaultNamespace[$pos]) {
2053 $attrs['type'] = $this->defaultNamespace[$pos] . ':' . $attrs['type'];
2054 $this->xdebug('used default namespace to make type ' . $attrs['type']);
2057 // This is for constructs like
2058 // <complexType name="ListOfString" base="soap:Array">
2060 // <element name="string" type="xsd:string"
2061 // minOccurs="0" maxOccurs="unbounded" />
2064 if ($this->currentComplexType && $this->complexTypes[$this->currentComplexType]['phpType'] == 'array') {
2065 $this->xdebug('arrayType for unusual array is ' . $attrs['type']);
2066 $this->complexTypes[$this->currentComplexType]['arrayType'] = $attrs['type'];
2068 $this->currentElement = $attrs['name'];
2069 $ename = $attrs['name'];
2070 } elseif(isset($attrs['ref'])){
2071 $this->xdebug("processing element as ref to ".$attrs['ref']);
2072 $this->currentElement = "ref to ".$attrs['ref'];
2073 $ename = $this->getLocalPart($attrs['ref']);
2075 $type = $this->CreateTypeName($this->currentComplexType . '_' . $attrs['name']);
2076 $this->xdebug("processing untyped element " . $attrs['name'] . ' type ' . $type);
2077 $this->currentElement = $attrs['name'];
2078 $attrs['type'] = $this->schemaTargetNamespace . ':' . $type;
2079 $ename = $attrs['name'];
2081 if (isset($ename) && $this->currentComplexType) {
2082 $this->xdebug("add element $ename to complexType $this->currentComplexType");
2083 $this->complexTypes[$this->currentComplexType]['elements'][$ename] = $attrs;
2084 } elseif (!isset($attrs['ref'])) {
2085 $this->xdebug("add element $ename to elements array");
2086 $this->elements[ $attrs['name'] ] = $attrs;
2087 $this->elements[ $attrs['name'] ]['typeClass'] = 'element';
2090 case 'enumeration': // restriction value list member
2091 $this->xdebug('enumeration ' . $attrs['value']);
2092 if ($this->currentSimpleType) {
2093 $this->simpleTypes[$this->currentSimpleType]['enumeration'][] = $attrs['value'];
2094 } elseif ($this->currentComplexType) {
2095 $this->complexTypes[$this->currentComplexType]['enumeration'][] = $attrs['value'];
2098 case 'extension': // simpleContent or complexContent type extension
2099 $this->xdebug('extension ' . $attrs['base']);
2100 if ($this->currentComplexType) {
2101 $ns = $this->getPrefix($attrs['base']);
2103 $this->complexTypes[$this->currentComplexType]['extensionBase'] = $this->schemaTargetNamespace . ':' . $attrs['base'];
2105 $this->complexTypes[$this->currentComplexType]['extensionBase'] = $attrs['base'];
2108 $this->xdebug('no current complexType to set extensionBase');
2112 if (isset($attrs['schemaLocation'])) {
2113 $this->xdebug('import namespace ' . $attrs['namespace'] . ' from ' . $attrs['schemaLocation']);
2114 $this->imports[$attrs['namespace']][] = array('location' => $attrs['schemaLocation'], 'loaded' => false);
2116 $this->xdebug('import namespace ' . $attrs['namespace']);
2117 $this->imports[$attrs['namespace']][] = array('location' => '', 'loaded' => true);
2118 if (! $this->getPrefixFromNamespace($attrs['namespace'])) {
2119 $this->namespaces['ns'.(count($this->namespaces)+1)] = $attrs['namespace'];
2124 if (isset($attrs['schemaLocation'])) {
2125 $this->xdebug('include into namespace ' . $this->schemaTargetNamespace . ' from ' . $attrs['schemaLocation']);
2126 $this->imports[$this->schemaTargetNamespace][] = array('location' => $attrs['schemaLocation'], 'loaded' => false);
2128 $this->xdebug('ignoring invalid XML Schema construct: include without schemaLocation attribute');
2131 case 'list': // simpleType value list
2132 $this->xdebug("do nothing for element $name");
2134 case 'restriction': // simpleType, simpleContent or complexContent value restriction
2135 $this->xdebug('restriction ' . $attrs['base']);
2136 if($this->currentSimpleType){
2137 $this->simpleTypes[$this->currentSimpleType]['type'] = $attrs['base'];
2138 } elseif($this->currentComplexType){
2139 $this->complexTypes[$this->currentComplexType]['restrictionBase'] = $attrs['base'];
2140 if(strstr($attrs['base'],':') == ':Array'){
2141 $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
2146 $this->schemaInfo = $attrs;
2147 $this->schemaInfo['schemaVersion'] = $this->getNamespaceFromPrefix($prefix);
2148 if (isset($attrs['targetNamespace'])) {
2149 $this->schemaTargetNamespace = $attrs['targetNamespace'];
2151 if (!isset($attrs['elementFormDefault'])) {
2152 $this->schemaInfo['elementFormDefault'] = 'unqualified';
2154 if (!isset($attrs['attributeFormDefault'])) {
2155 $this->schemaInfo['attributeFormDefault'] = 'unqualified';
2158 case 'simpleContent': // (optional) content for a complexType
2159 if ($this->currentComplexType) { // This should *always* be
2160 $this->complexTypes[$this->currentComplexType]['simpleContent'] = 'true';
2162 $this->xdebug("do nothing for element $name because there is no current complexType");
2166 array_push($this->simpleTypeStack, $this->currentSimpleType);
2167 if(isset($attrs['name'])){
2168 $this->xdebug("processing simpleType for name " . $attrs['name']);
2169 $this->currentSimpleType = $attrs['name'];
2170 $this->simpleTypes[ $attrs['name'] ] = $attrs;
2171 $this->simpleTypes[ $attrs['name'] ]['typeClass'] = 'simpleType';
2172 $this->simpleTypes[ $attrs['name'] ]['phpType'] = 'scalar';
2174 $name = $this->CreateTypeName($this->currentComplexType . '_' . $this->currentElement);
2175 $this->xdebug('processing unnamed simpleType for element ' . $this->currentElement . ' named ' . $name);
2176 $this->currentSimpleType = $name;
2177 //$this->currentElement = false;
2178 $this->simpleTypes[$this->currentSimpleType] = $attrs;
2179 $this->simpleTypes[$this->currentSimpleType]['phpType'] = 'scalar';
2182 case 'union': // simpleType type list
2183 $this->xdebug("do nothing for element $name");
2186 $this->xdebug("do not have any logic to process element $name");
2191 * end-element handler
2193 * @param string $parser XML parser object
2194 * @param string $name element name
2197 function schemaEndElement($parser, $name) {
2198 // bring depth down a notch
2200 // position of current element is equal to the last value left in depth_array for my depth
2201 if(isset($this->depth_array[$this->depth])){
2202 $pos = $this->depth_array[$this->depth];
2204 // get element prefix
2205 if ($prefix = $this->getPrefix($name)){
2206 // get unqualified name
2207 $name = $this->getLocalPart($name);
2212 if($name == 'complexType'){
2213 $this->xdebug('done processing complexType ' . ($this->currentComplexType ? $this->currentComplexType : '(unknown)'));
2214 $this->xdebug($this->varDump($this->complexTypes[$this->currentComplexType]));
2215 $this->currentComplexType = array_pop($this->complexTypeStack);
2216 //$this->currentElement = false;
2218 if($name == 'element'){
2219 $this->xdebug('done processing element ' . ($this->currentElement ? $this->currentElement : '(unknown)'));
2220 $this->currentElement = array_pop($this->elementStack);
2222 if($name == 'simpleType'){
2223 $this->xdebug('done processing simpleType ' . ($this->currentSimpleType ? $this->currentSimpleType : '(unknown)'));
2224 $this->xdebug($this->varDump($this->simpleTypes[$this->currentSimpleType]));
2225 $this->currentSimpleType = array_pop($this->simpleTypeStack);
2230 * element content handler
2232 * @param string $parser XML parser object
2233 * @param string $data element content
2236 function schemaCharacterData($parser, $data){
2237 $pos = $this->depth_array[$this->depth - 1];
2238 $this->message[$pos]['cdata'] .= $data;
2242 * serialize the schema
2246 function serializeSchema(){
2248 $schemaPrefix = $this->getPrefixFromNamespace($this->XMLSchemaVersion);
2251 $schemaLocationCount = 0;
2252 if (sizeof($this->imports) > 0) {
2253 foreach($this->imports as $ns => $list) {
2254 foreach ($list as $ii) {
2255 if ($ii['location'] != '') {
2256 $xml .= " <$schemaPrefix:import location=\"" . $ii['location'] . '" namespace="' . $ns . "\" />\n";
2258 if ($schemaLocationCount == 0) {
2259 $xml .= " <$schemaPrefix:import namespace=\"" . $ns . "\" schemaLocation=\"http://schemas.xmlsoap.org/soap/encoding/\"/>\n";
2261 $xml .= " <$schemaPrefix:import namespace=\"" . $ns . "\" />\n";
2268 foreach($this->complexTypes as $typeName => $attrs){
2270 // serialize child elements
2271 if(isset($attrs['elements']) && (count($attrs['elements']) > 0)){
2272 foreach($attrs['elements'] as $element => $eParts){
2273 if(isset($eParts['ref'])){
2274 $contentStr .= " <$schemaPrefix:element ref=\"$element\"/>\n";
2276 $contentStr .= " <$schemaPrefix:element name=\"$element\" type=\"" . $this->contractQName($eParts['type']) . "\"";
2277 foreach ($eParts as $aName => $aValue) {
2278 // handle, e.g., abstract, default, form, minOccurs, maxOccurs, nillable
2279 if ($aName != 'name' && $aName != 'type') {
2280 $contentStr .= " $aName=\"$aValue\"";
2283 $contentStr .= "/>\n";
2286 // compositor wraps elements
2287 if (isset($attrs['compositor']) && ($attrs['compositor'] != '')) {
2288 $contentStr = " <$schemaPrefix:$attrs[compositor]>\n".$contentStr." </$schemaPrefix:$attrs[compositor]>\n";
2292 if(isset($attrs['attrs']) && (count($attrs['attrs']) >= 1)){
2293 foreach($attrs['attrs'] as $attr => $aParts){
2294 $contentStr .= " <$schemaPrefix:attribute";
2295 foreach ($aParts as $a => $v) {
2296 if ($a == 'ref' || $a == 'type') {
2297 $contentStr .= " $a=\"".$this->contractQName($v).'"';
2298 } elseif ($a == 'http://schemas.xmlsoap.org/wsdl/:arrayType') {
2299 $this->usedNamespaces['wsdl'] = $this->namespaces['wsdl'];
2300 $contentStr .= ' wsdl:arrayType="'.$this->contractQName($v).'"';
2302 $contentStr .= " $a=\"$v\"";
2305 $contentStr .= "/>\n";
2309 if (isset($attrs['restrictionBase']) && $attrs['restrictionBase'] != ''){
2310 $contentStr = " <$schemaPrefix:restriction base=\"".$this->contractQName($attrs['restrictionBase'])."\">\n".$contentStr." </$schemaPrefix:restriction>\n";
2311 // complex or simple content
2312 if ((isset($attrs['elements']) && count($attrs['elements']) > 0) || (isset($attrs['attrs']) && count($attrs['attrs']) > 0)){
2313 $contentStr = " <$schemaPrefix:complexContent>\n".$contentStr." </$schemaPrefix:complexContent>\n";
2316 // finalize complex type
2317 if($contentStr != ''){
2318 $contentStr = " <$schemaPrefix:complexType name=\"$typeName\">\n".$contentStr." </$schemaPrefix:complexType>\n";
2320 $contentStr = " <$schemaPrefix:complexType name=\"$typeName\"/>\n";
2322 $xml .= $contentStr;
2325 if(isset($this->simpleTypes) && count($this->simpleTypes) > 0){
2326 foreach($this->simpleTypes as $typeName => $eParts){
2327 $xml .= " <$schemaPrefix:simpleType name=\"$typeName\">\n <$schemaPrefix:restriction base=\"".$this->contractQName($eParts['type'])."\">\n";
2328 if (isset($eParts['enumeration'])) {
2329 foreach ($eParts['enumeration'] as $e) {
2330 $xml .= " <$schemaPrefix:enumeration value=\"$e\"/>\n";
2333 $xml .= " </$schemaPrefix:restriction>\n </$schemaPrefix:simpleType>";
2337 if(isset($this->elements) && count($this->elements) > 0){
2338 foreach($this->elements as $element => $eParts){
2339 $xml .= " <$schemaPrefix:element name=\"$element\" type=\"".$this->contractQName($eParts['type'])."\"/>\n";
2343 if(isset($this->attributes) && count($this->attributes) > 0){
2344 foreach($this->attributes as $attr => $aParts){
2345 $xml .= " <$schemaPrefix:attribute name=\"$attr\" type=\"".$this->contractQName($aParts['type'])."\"\n/>";
2350 foreach ($this->schemaInfo as $k => $v) {
2351 if ($k == 'elementFormDefault' || $k == 'attributeFormDefault') {
2352 $attr .= " $k=\"$v\"";
2355 $el = "<$schemaPrefix:schema$attr targetNamespace=\"$this->schemaTargetNamespace\"\n";
2356 foreach (array_diff($this->usedNamespaces, $this->enclosingNamespaces) as $nsp => $ns) {
2357 $el .= " xmlns:$nsp=\"$ns\"";
2359 $xml = $el . ">\n".$xml."</$schemaPrefix:schema>\n";
2364 * adds debug data to the clas level debug string
2366 * @param string $string debug data
2369 function xdebug($string){
2370 $this->debug('<' . $this->schemaTargetNamespace . '> '.$string);
2374 * get the PHP type of a user defined type in the schema
2375 * PHP type is kind of a misnomer since it actually returns 'struct' for assoc. arrays
2376 * returns false if no type exists, or not w/ the given namespace
2377 * else returns a string that is either a native php type, or 'struct'
2379 * @param string $type name of defined type
2380 * @param string $ns namespace of type
2385 function getPHPType($type,$ns){
2386 if(isset($this->typemap[$ns][$type])){
2387 //print "found type '$type' and ns $ns in typemap<br>";
2388 return $this->typemap[$ns][$type];
2389 } elseif(isset($this->complexTypes[$type])){
2390 //print "getting type '$type' and ns $ns from complexTypes array<br>";
2391 return $this->complexTypes[$type]['phpType'];
2397 * returns an associative array of information about a given type
2398 * returns false if no type exists by the given name
2400 * For a complexType typeDef = array(
2401 * 'restrictionBase' => '',
2403 * 'compositor' => '(sequence|all)',
2404 * 'elements' => array(), // refs to elements array
2405 * 'attrs' => array() // refs to attributes array
2406 * ... and so on (see addComplexType)
2409 * For simpleType or element, the array has different keys.
2411 * @param string $type
2414 * @see addComplexType
2415 * @see addSimpleType
2418 function getTypeDef($type){
2419 //$this->debug("in getTypeDef for type $type");
2420 if (substr($type, -1) == '^') {
2422 $type = substr($type, 0, -1);
2427 if((! $is_element) && isset($this->complexTypes[$type])){
2428 $this->xdebug("in getTypeDef, found complexType $type");
2429 return $this->complexTypes[$type];
2430 } elseif((! $is_element) && isset($this->simpleTypes[$type])){
2431 $this->xdebug("in getTypeDef, found simpleType $type");
2432 if (!isset($this->simpleTypes[$type]['phpType'])) {
2433 // get info for type to tack onto the simple type
2434 // TODO: can this ever really apply (i.e. what is a simpleType really?)
2435 $uqType = substr($this->simpleTypes[$type]['type'], strrpos($this->simpleTypes[$type]['type'], ':') + 1);
2436 $ns = substr($this->simpleTypes[$type]['type'], 0, strrpos($this->simpleTypes[$type]['type'], ':'));
2437 $etype = $this->getTypeDef($uqType);
2439 $this->xdebug("in getTypeDef, found type for simpleType $type:");
2440 $this->xdebug($this->varDump($etype));
2441 if (isset($etype['phpType'])) {
2442 $this->simpleTypes[$type]['phpType'] = $etype['phpType'];
2444 if (isset($etype['elements'])) {
2445 $this->simpleTypes[$type]['elements'] = $etype['elements'];
2449 return $this->simpleTypes[$type];
2450 } elseif(isset($this->elements[$type])){
2451 $this->xdebug("in getTypeDef, found element $type");
2452 if (!isset($this->elements[$type]['phpType'])) {
2453 // get info for type to tack onto the element
2454 $uqType = substr($this->elements[$type]['type'], strrpos($this->elements[$type]['type'], ':') + 1);
2455 $ns = substr($this->elements[$type]['type'], 0, strrpos($this->elements[$type]['type'], ':'));
2456 $etype = $this->getTypeDef($uqType);
2458 $this->xdebug("in getTypeDef, found type for element $type:");
2459 $this->xdebug($this->varDump($etype));
2460 if (isset($etype['phpType'])) {
2461 $this->elements[$type]['phpType'] = $etype['phpType'];
2463 if (isset($etype['elements'])) {
2464 $this->elements[$type]['elements'] = $etype['elements'];
2466 if (isset($etype['extensionBase'])) {
2467 $this->elements[$type]['extensionBase'] = $etype['extensionBase'];
2469 } elseif ($ns == 'http://www.w3.org/2001/XMLSchema') {
2470 $this->xdebug("in getTypeDef, element $type is an XSD type");
2471 $this->elements[$type]['phpType'] = 'scalar';
2474 return $this->elements[$type];
2475 } elseif(isset($this->attributes[$type])){
2476 $this->xdebug("in getTypeDef, found attribute $type");
2477 return $this->attributes[$type];
2478 } elseif (preg_match('/_ContainedType$/', $type)) {
2479 $this->xdebug("in getTypeDef, have an untyped element $type");
2480 $typeDef['typeClass'] = 'simpleType';
2481 $typeDef['phpType'] = 'scalar';
2482 $typeDef['type'] = 'http://www.w3.org/2001/XMLSchema:string';
2485 $this->xdebug("in getTypeDef, did not find $type");
2490 * returns a sample serialization of a given type, or false if no type by the given name
2492 * @param string $type name of type
2497 function serializeTypeDef($type){
2498 //print "in sTD() for type $type<br>";
2499 if($typeDef = $this->getTypeDef($type)){
2501 if(is_array($typeDef['attrs'])){
2502 foreach($typeDef['attrs'] as $attName => $data){
2503 $str .= " $attName=\"{type = ".$data['type']."}\"";
2506 $str .= " xmlns=\"".$this->schema['targetNamespace']."\"";
2507 if(count($typeDef['elements']) > 0){
2509 foreach($typeDef['elements'] as $element => $eData){
2510 $str .= $this->serializeTypeDef($element);
2513 } elseif($typeDef['typeClass'] == 'element') {
2514 $str .= "></$type>";
2524 * returns HTML form elements that allow a user
2525 * to enter values for creating an instance of the given type.
2527 * @param string $name name for type instance
2528 * @param string $type name of type
2533 function typeToForm($name,$type){
2535 if($typeDef = $this->getTypeDef($type)){
2537 if($typeDef['phpType'] == 'struct'){
2538 $buffer .= '<table>';
2539 foreach($typeDef['elements'] as $child => $childDef){
2541 <tr><td align='right'>$childDef[name] (type: ".$this->getLocalPart($childDef['type'])."):</td>
2542 <td><input type='text' name='parameters[".$name."][$childDef[name]]'></td></tr>";
2544 $buffer .= '</table>';
2546 } elseif($typeDef['phpType'] == 'array'){
2547 $buffer .= '<table>';
2548 for($i=0;$i < 3; $i++){
2550 <tr><td align='right'>array item (type: $typeDef[arrayType]):</td>
2551 <td><input type='text' name='parameters[".$name."][]'></td></tr>";
2553 $buffer .= '</table>';
2556 $buffer .= "<input type='text' name='parameters[$name]'>";
2559 $buffer .= "<input type='text' name='parameters[$name]'>";
2565 * adds a complex type to the schema
2575 * array('ref'=>'SOAP-ENC:arrayType','wsdl:arrayType'=>'string[]'),
2579 * example: PHP associative array ( SOAP Struct )
2586 * array('myVar'=> array('name'=>'myVar','type'=>'string')
2590 * @param typeClass (complexType|simpleType|attribute)
2591 * @param phpType: currently supported are array and struct (php assoc array)
2592 * @param compositor (all|sequence|choice)
2593 * @param restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
2594 * @param elements = array ( name = array(name=>'',type=>'') )
2595 * @param attrs = array(
2597 * 'ref' => "http://schemas.xmlsoap.org/soap/encoding/:arrayType",
2598 * "http://schemas.xmlsoap.org/wsdl/:arrayType" => "string[]"
2601 * @param arrayType: namespace:name (http://www.w3.org/2001/XMLSchema:string)
2605 function addComplexType($name,$typeClass='complexType',$phpType='array',$compositor='',$restrictionBase='',$elements=array(),$attrs=array(),$arrayType=''){
2606 $this->complexTypes[$name] = array(
2608 'typeClass' => $typeClass,
2609 'phpType' => $phpType,
2610 'compositor'=> $compositor,
2611 'restrictionBase' => $restrictionBase,
2612 'elements' => $elements,
2614 'arrayType' => $arrayType
2617 $this->xdebug("addComplexType $name:");
2618 $this->appendDebug($this->varDump($this->complexTypes[$name]));
2622 * adds a simple type to the schema
2624 * @param string $name
2625 * @param string $restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
2626 * @param string $typeClass (should always be simpleType)
2627 * @param string $phpType (should always be scalar)
2628 * @param array $enumeration array of values
2630 * @see nusoap_xmlschema
2633 function addSimpleType($name, $restrictionBase='', $typeClass='simpleType', $phpType='scalar', $enumeration=array()) {
2634 $this->simpleTypes[$name] = array(
2636 'typeClass' => $typeClass,
2637 'phpType' => $phpType,
2638 'type' => $restrictionBase,
2639 'enumeration' => $enumeration
2642 $this->xdebug("addSimpleType $name:");
2643 $this->appendDebug($this->varDump($this->simpleTypes[$name]));
2647 * adds an element to the schema
2649 * @param array $attrs attributes that must include name and type
2650 * @see nusoap_xmlschema
2653 function addElement($attrs) {
2654 if (! $this->getPrefix($attrs['type'])) {
2655 $attrs['type'] = $this->schemaTargetNamespace . ':' . $attrs['type'];
2657 $this->elements[ $attrs['name'] ] = $attrs;
2658 $this->elements[ $attrs['name'] ]['typeClass'] = 'element';
2660 $this->xdebug("addElement " . $attrs['name']);
2661 $this->appendDebug($this->varDump($this->elements[ $attrs['name'] ]));
2666 * Backward compatibility
2668 class XMLSchema extends nusoap_xmlschema {
2675 Modification information for LGPL compliance
2677 r58622 - 2010-10-22 18:18:59 -0700 (Fri, 22 Oct 2010) - engsvnbuild - Author: lam <lam@198.18.142.201>
2680 r58361 - 2010-09-29 16:59:02 -0700 (Wed, 29 Sep 2010) - kjing - Author: Jenny Gonsalves <jenny@sugarcrm.com>
2681 Merging with maint_6_0_1 (svn merge -r 58250:58342)
2683 r57813 - 2010-08-19 10:34:44 -0700 (Thu, 19 Aug 2010) - kjing - Author: John Mertic <jmertic@sugarcrm.com>
2684 Bug 39085 - When loading the opposite search panel via ajax on the ListViews, call the index action instead of the ListView action to avoid touching pre-MVC code by accident.
2686 r57707 - 2010-08-10 12:26:13 -0700 (Tue, 10 Aug 2010) - kjing - Author: Stanislav Malyshev <smalyshev@gmail.com>
2687 fix SOAP calls with no parameters
2689 r56990 - 2010-06-16 13:05:36 -0700 (Wed, 16 Jun 2010) - kjing - snapshot "Mango" svn branch to a new one for GitHub sync
2691 r56989 - 2010-06-16 13:01:33 -0700 (Wed, 16 Jun 2010) - kjing - defunt "Mango" svn dev branch before github cutover
2693 r55980 - 2010-04-19 13:31:28 -0700 (Mon, 19 Apr 2010) - kjing - create Mango (6.1) based on windex
2695 r51719 - 2009-10-22 10:18:00 -0700 (Thu, 22 Oct 2009) - mitani - Converted to Build 3 tags and updated the build system
2697 r51634 - 2009-10-19 13:32:22 -0700 (Mon, 19 Oct 2009) - mitani - Windex is the branch for Sugar Sales 1.0 development
2699 r51508 - 2009-10-14 07:40:23 -0700 (Wed, 14 Oct 2009) - jmertic - More fallout fixes from the PHP 5.3 ereg to preg changes.
2701 r51455 - 2009-10-13 07:56:48 -0700 (Tue, 13 Oct 2009) - jmertic - Bug 33202 - Enable install of SugarCRM on PHP 5.3.0, asserting that the minimum supported version is PHP 5.2.x.
2703 r51443 - 2009-10-12 13:34:36 -0700 (Mon, 12 Oct 2009) - jmertic - Bug 33332 - Made application PHP 5.3 compliant with E_DEPRECATED warnings on by:
2704 - Changing all ereg function to either preg or simple string based ones
2705 - No more references to magic quotes.
2706 - Change all the session_unregister() functions to just unset() the correct session variable instead.
2708 r50375 - 2009-08-24 18:07:43 -0700 (Mon, 24 Aug 2009) - dwong - branch kobe2 from tokyo r50372
2710 r45763 - 2009-04-01 12:16:18 -0700 (Wed, 01 Apr 2009) - majed - Removed half of the require_once and include_onces in the product that were redundant or could be handled easily by the auto loader
2712 r45680 - 2009-03-30 14:34:35 -0700 (Mon, 30 Mar 2009) - Samir Gandhi - modifeid serializeSchema to generate WS-I compliant WSDL
2714 r42807 - 2008-12-29 11:16:59 -0800 (Mon, 29 Dec 2008) - dwong - Branch from trunk/sugarcrm r42806 to branches/tokyo/sugarcrm
2716 r42645 - 2008-12-18 13:41:08 -0800 (Thu, 18 Dec 2008) - awu - merging maint_5_2_0 rev41336:HEAD to trunk
2718 r41647 - 2008-11-11 17:44:30 -0800 (Tue, 11 Nov 2008) - majed - Fixes a few bugs
2720 r41596 - 2008-11-10 19:20:04 -0800 (Mon, 10 Nov 2008) - Samir Gandhi - modified to set $method in the code
2722 r41558 - 2008-11-10 14:35:34 -0800 (Mon, 10 Nov 2008) - majed - changes nusoap to allow for registering classes
2724 r39619 - 2008-09-09 13:41:34 -0700 (Tue, 09 Sep 2008) - jmertic - Bug 24827 - Remove all instances where we return a new object and assign it by reference, since this is deprecated in PHP 5 and emits E_DEPRECATED errors in PHP 5.3.
2726 - data/SugarBean.php
2727 - include/domit/php_http_client_generic.php
2728 - include/domit/php_http_connector.php
2729 - include/domit/testing_domit.php
2730 - include/domit/xml_domit_getelementsbypath.php
2731 - include/domit/xml_domit_lite_parser.php
2732 - include/domit/xml_domit_nodemaps.php
2733 - include/domit/xml_domit_parser.php
2734 - include/domit/xml_domit_shared.php
2735 - include/generic/SugarWidgets/SugarWidgetField.php
2736 - include/generic/SugarWidgets/SugarWidgetReportField.php
2737 - include/ListView/ProcessView.php
2738 - include/nusoap/class.soapclient.php
2739 - include/nusoap/nusoap.php
2740 - include/nusoap/nusoapmime.php
2741 - include/Pear/HTML_Safe/Safe.php
2742 - include/Pear/XML_HTMLSax3/HTMLSax3.php
2743 - modules/Administration/RebuildWorkFlow.php
2744 - modules/Expressions/RelateSelector.php
2745 - modules/Reports/templates/templates_reports.php
2746 - modules/WorkFlow/Delete.php
2747 - modules/WorkFlow/Save.php
2748 - modules/WorkFlow/SaveSequence.php
2749 - modules/WorkFlow/WorkFlow.php
2750 - modules/WorkFlowActionShells/CreateStep1.php
2751 - modules/WorkFlowActionShells/CreateStep2.php
2752 - modules/WorkFlowActionShells/Save.php
2753 - modules/WorkFlowActionShells/WorkFlowActionShell.php
2754 - modules/WorkFlowAlerts/Save.php
2755 - modules/WorkFlowAlerts/WorkFlowAlert.php
2756 - modules/WorkFlowAlertShells/DetailView.php
2757 - modules/WorkFlowAlertShells/WorkFlowAlertShell.php
2758 - modules/WorkFlowTriggerShells/CreateStep1.php
2759 - modules/WorkFlowTriggerShells/CreateStepFilter.php
2760 - modules/WorkFlowTriggerShells/SaveFilter.php
2761 - modules/WorkFlowTriggerShells/WorkFlowTriggerShell.php
2762 - soap/SoapHelperFunctions.php
2763 - test/modules/DynamicFields/DynamicFields_Bug24095_test.php
2764 - test/simpletest/browser.php
2765 - test/simpletest/default_reporter.php
2766 - test/simpletest/detached.php
2767 - test/simpletest/eclipse.php
2768 - test/simpletest/expectation.php
2769 - test/simpletest/extensions/pear_test_case.php
2770 - test/simpletest/form.php
2771 - test/simpletest/http.php
2772 - test/simpletest/mock_objects.php
2773 - test/simpletest/page.php
2774 - test/simpletest/parser.php
2775 - test/simpletest/remote.php
2776 - test/simpletest/shell_tester.php
2777 - test/simpletest/simple_test.php
2778 - test/simpletest/simpletest.php
2779 - test/simpletest/test/acceptance_test.php
2780 - test/simpletest/test/adapter_test.php
2781 - test/simpletest/test/authentication_test.php
2782 - test/simpletest/test/browser_test.php
2783 - test/simpletest/test/collector_test.php
2784 - test/simpletest/test/compatibility_test.php
2785 - test/simpletest/test/detached_test.php
2786 - test/simpletest/test/eclipse_test.php
2787 - test/simpletest/test/encoding_test.php
2788 - test/simpletest/test/errors_test.php
2789 - test/simpletest/test/expectation_test.php
2790 - test/simpletest/test/form_test.php
2791 - test/simpletest/test/frames_test.php
2792 - test/simpletest/test/http_test.php
2793 - test/simpletest/test/live_test.php
2794 - test/simpletest/test/mock_objects_test.php
2795 - test/simpletest/test/page_test.php
2796 - test/simpletest/test/parse_error_test.php
2797 - test/simpletest/test/parser_test.php
2798 - test/simpletest/test/remote_test.php
2799 - test/simpletest/test/shell_test.php
2800 - test/simpletest/test/shell_tester_test.php
2801 - test/simpletest/test/simpletest_test.php
2802 - test/simpletest/test/site/page_request.php
2803 - test/simpletest/test/tag_test.php
2804 - test/simpletest/test/unit_tester_test.php
2805 - test/simpletest/test/user_agent_test.php
2806 - test/simpletest/test/visual_test.php
2807 - test/simpletest/test/xml_test.php
2808 - test/simpletest/test_case.php
2809 - test/simpletest/ui/array_reporter/test.php
2810 - test/simpletest/ui/recorder/test.php
2811 - test/simpletest/unit_tester.php
2812 - test/simpletest/url.php
2813 - test/simpletest/user_agent.php
2814 - test/simpletest/web_tester.php
2815 - test/spikephpcoverage/src/PEAR.php
2816 - test/spikephpcoverage/src/util/Utility.php
2817 - test/spikephpcoverage/src/XML/Parser.php
2818 - test/spikephpcoverage/src/XML/Parser/Simple.php
2819 - test/test_utilities/SugarTest_SimpleBrowser.php
2821 r38362 - 2008-07-28 14:06:59 -0700 (Mon, 28 Jul 2008) - roger - bug: 23897. Using print_r when using the debug statement in nusoap will print out the statements to the screen if the call is coming from the UI.
2823 r38300 - 2008-07-25 13:33:43 -0700 (Fri, 25 Jul 2008) - Samir Gandhi - put the debug in parseresponse function
2825 r38293 - 2008-07-25 12:32:34 -0700 (Fri, 25 Jul 2008) - Samir Gandhi - to put all the debug statements return value in the call function
2827 r36824 - 2008-06-18 09:26:11 -0700 (Wed, 18 Jun 2008) - roger - bug: 21832
2829 r26422 - 2007-09-05 17:29:12 -0700 (Wed, 05 Sep 2007) - majed - migrate from beta 1 to trunk
2831 r15787 - 2006-08-10 10:14:41 -0700 (Thu, 10 Aug 2006) - roger - RRS: bug 7961
2833 r14701 - 2006-07-17 13:37:26 -0700 (Mon, 17 Jul 2006) - roger - RRS: bug 5801
2835 r13782 - 2006-06-06 10:58:55 -0700 (Tue, 06 Jun 2006) - majed - changes entry point code
2837 r11466 - 2006-02-01 15:49:47 -0800 (Wed, 01 Feb 2006) - jacob - Adding extra !empty check to get around a PHP warning.
2839 r11115 - 2006-01-17 14:54:45 -0800 (Tue, 17 Jan 2006) - majed - add entry point validation
2841 r10585 - 2005-12-13 14:42:26 -0800 (Tue, 13 Dec 2005) - majed - adds new license mechanisim
2843 r10170 - 2005-12-05 18:37:46 -0800 (Mon, 05 Dec 2005) - majed - fixes various issues
2845 r8999 - 2005-11-04 05:26:49 -0800 (Fri, 04 Nov 2005) - roger - When nusoap was upgraded we had an issue with the user's default language not being populated during a soap request. I determined the reason this was happening and have checked in the corresponding change to nusoap.
2847 r8991 - 2005-11-03 19:07:25 -0800 (Thu, 03 Nov 2005) - majed - fixes nusoap issue
2849 r8846 - 2005-10-31 11:01:12 -0800 (Mon, 31 Oct 2005) - majed - new version of nusoap
2851 r7905 - 2005-09-21 19:12:57 -0700 (Wed, 21 Sep 2005) - majed - restores old nusoap pre & with a few fixes
2853 r7861 - 2005-09-20 15:40:25 -0700 (Tue, 20 Sep 2005) - majed - & fix for 3.5.1
2855 r7452 - 2005-08-17 11:32:34 -0700 (Wed, 17 Aug 2005) - majed - changes soap to nusoap
2857 r5820 - 2005-06-21 14:22:24 -0700 (Tue, 21 Jun 2005) - majed - fixes issues with nusoap and with custom fields
2859 r5462 - 2005-05-25 13:50:11 -0700 (Wed, 25 May 2005) - majed - upgraded nusoap to .6.9
2861 r5104 - 2005-05-04 15:33:41 -0700 (Wed, 04 May 2005) - majed - gets rid of HTTP_GET_VARS and what not which has been deprecated
2863 r573 - 2004-09-04 13:03:32 -0700 (Sat, 04 Sep 2004) - sugarclint - undoing copyrights added in inadvertantly. --clint
2865 r546 - 2004-09-03 11:49:38 -0700 (Fri, 03 Sep 2004) - sugarmsi - removed echo count
2867 r354 - 2004-08-02 23:00:37 -0700 (Mon, 02 Aug 2004) - sugarjacob - Adding Soap
2877 * For creating serializable abstractions of native PHP types. This class
2878 * allows element name/namespace, XSD type, and XML attributes to be
2879 * associated with a value. This is extremely useful when WSDL is not
2880 * used, but is also useful when WSDL is used with polymorphic types, including
2881 * xsd:anyType and user-defined types.
2883 * @author Dietrich Ayala <dietrich@ganx4.com>
2887 class soapval extends nusoap_base {
2889 * The XML element name
2896 * The XML type name (string or false)
2910 * The XML element namespace (string or false)
2917 * The XML type namespace (string or false)
2924 * The XML element attributes (array or false)
2934 * @param string $name optional name
2935 * @param mixed $type optional type name
2936 * @param mixed $value optional value
2937 * @param mixed $element_ns optional namespace of value
2938 * @param mixed $type_ns optional namespace of type
2939 * @param mixed $attributes associative array of attributes to add to element serialization
2942 function soapval($name='soapval',$type=false,$value=-1,$element_ns=false,$type_ns=false,$attributes=false) {
2943 parent::nusoap_base();
2944 $this->name = $name;
2945 $this->type = $type;
2946 $this->value = $value;
2947 $this->element_ns = $element_ns;
2948 $this->type_ns = $type_ns;
2949 $this->attributes = $attributes;
2953 * return serialized value
2955 * @param string $use The WSDL use value (encoded|literal)
2956 * @return string XML data
2959 function serialize($use='encoded') {
2960 return $this->serialize_val($this->value, $this->name, $this->type, $this->element_ns, $this->type_ns, $this->attributes, $use, true);
2964 * decodes a soapval object into a PHP native type
2970 return $this->value;
2980 Modification information for LGPL compliance
2982 r58622 - 2010-10-22 18:18:59 -0700 (Fri, 22 Oct 2010) - engsvnbuild - Author: lam <lam@198.18.142.201>
2985 r58361 - 2010-09-29 16:59:02 -0700 (Wed, 29 Sep 2010) - kjing - Author: Jenny Gonsalves <jenny@sugarcrm.com>
2986 Merging with maint_6_0_1 (svn merge -r 58250:58342)
2988 r57813 - 2010-08-19 10:34:44 -0700 (Thu, 19 Aug 2010) - kjing - Author: John Mertic <jmertic@sugarcrm.com>
2989 Bug 39085 - When loading the opposite search panel via ajax on the ListViews, call the index action instead of the ListView action to avoid touching pre-MVC code by accident.
2991 r57707 - 2010-08-10 12:26:13 -0700 (Tue, 10 Aug 2010) - kjing - Author: Stanislav Malyshev <smalyshev@gmail.com>
2992 fix SOAP calls with no parameters
2994 r56990 - 2010-06-16 13:05:36 -0700 (Wed, 16 Jun 2010) - kjing - snapshot "Mango" svn branch to a new one for GitHub sync
2996 r56989 - 2010-06-16 13:01:33 -0700 (Wed, 16 Jun 2010) - kjing - defunt "Mango" svn dev branch before github cutover
2998 r55980 - 2010-04-19 13:31:28 -0700 (Mon, 19 Apr 2010) - kjing - create Mango (6.1) based on windex
3000 r51719 - 2009-10-22 10:18:00 -0700 (Thu, 22 Oct 2009) - mitani - Converted to Build 3 tags and updated the build system
3002 r51634 - 2009-10-19 13:32:22 -0700 (Mon, 19 Oct 2009) - mitani - Windex is the branch for Sugar Sales 1.0 development
3004 r51508 - 2009-10-14 07:40:23 -0700 (Wed, 14 Oct 2009) - jmertic - More fallout fixes from the PHP 5.3 ereg to preg changes.
3006 r51455 - 2009-10-13 07:56:48 -0700 (Tue, 13 Oct 2009) - jmertic - Bug 33202 - Enable install of SugarCRM on PHP 5.3.0, asserting that the minimum supported version is PHP 5.2.x.
3008 r51443 - 2009-10-12 13:34:36 -0700 (Mon, 12 Oct 2009) - jmertic - Bug 33332 - Made application PHP 5.3 compliant with E_DEPRECATED warnings on by:
3009 - Changing all ereg function to either preg or simple string based ones
3010 - No more references to magic quotes.
3011 - Change all the session_unregister() functions to just unset() the correct session variable instead.
3013 r50375 - 2009-08-24 18:07:43 -0700 (Mon, 24 Aug 2009) - dwong - branch kobe2 from tokyo r50372
3015 r45763 - 2009-04-01 12:16:18 -0700 (Wed, 01 Apr 2009) - majed - Removed half of the require_once and include_onces in the product that were redundant or could be handled easily by the auto loader
3017 r45680 - 2009-03-30 14:34:35 -0700 (Mon, 30 Mar 2009) - Samir Gandhi - modifeid serializeSchema to generate WS-I compliant WSDL
3019 r42807 - 2008-12-29 11:16:59 -0800 (Mon, 29 Dec 2008) - dwong - Branch from trunk/sugarcrm r42806 to branches/tokyo/sugarcrm
3021 r42645 - 2008-12-18 13:41:08 -0800 (Thu, 18 Dec 2008) - awu - merging maint_5_2_0 rev41336:HEAD to trunk
3023 r41647 - 2008-11-11 17:44:30 -0800 (Tue, 11 Nov 2008) - majed - Fixes a few bugs
3025 r41596 - 2008-11-10 19:20:04 -0800 (Mon, 10 Nov 2008) - Samir Gandhi - modified to set $method in the code
3027 r41558 - 2008-11-10 14:35:34 -0800 (Mon, 10 Nov 2008) - majed - changes nusoap to allow for registering classes
3029 r39619 - 2008-09-09 13:41:34 -0700 (Tue, 09 Sep 2008) - jmertic - Bug 24827 - Remove all instances where we return a new object and assign it by reference, since this is deprecated in PHP 5 and emits E_DEPRECATED errors in PHP 5.3.
3031 - data/SugarBean.php
3032 - include/domit/php_http_client_generic.php
3033 - include/domit/php_http_connector.php
3034 - include/domit/testing_domit.php
3035 - include/domit/xml_domit_getelementsbypath.php
3036 - include/domit/xml_domit_lite_parser.php
3037 - include/domit/xml_domit_nodemaps.php
3038 - include/domit/xml_domit_parser.php
3039 - include/domit/xml_domit_shared.php
3040 - include/generic/SugarWidgets/SugarWidgetField.php
3041 - include/generic/SugarWidgets/SugarWidgetReportField.php
3042 - include/ListView/ProcessView.php
3043 - include/nusoap/class.soapclient.php
3044 - include/nusoap/nusoap.php
3045 - include/nusoap/nusoapmime.php
3046 - include/Pear/HTML_Safe/Safe.php
3047 - include/Pear/XML_HTMLSax3/HTMLSax3.php
3048 - modules/Administration/RebuildWorkFlow.php
3049 - modules/Expressions/RelateSelector.php
3050 - modules/Reports/templates/templates_reports.php
3051 - modules/WorkFlow/Delete.php
3052 - modules/WorkFlow/Save.php
3053 - modules/WorkFlow/SaveSequence.php
3054 - modules/WorkFlow/WorkFlow.php
3055 - modules/WorkFlowActionShells/CreateStep1.php
3056 - modules/WorkFlowActionShells/CreateStep2.php
3057 - modules/WorkFlowActionShells/Save.php
3058 - modules/WorkFlowActionShells/WorkFlowActionShell.php
3059 - modules/WorkFlowAlerts/Save.php
3060 - modules/WorkFlowAlerts/WorkFlowAlert.php
3061 - modules/WorkFlowAlertShells/DetailView.php
3062 - modules/WorkFlowAlertShells/WorkFlowAlertShell.php
3063 - modules/WorkFlowTriggerShells/CreateStep1.php
3064 - modules/WorkFlowTriggerShells/CreateStepFilter.php
3065 - modules/WorkFlowTriggerShells/SaveFilter.php
3066 - modules/WorkFlowTriggerShells/WorkFlowTriggerShell.php
3067 - soap/SoapHelperFunctions.php
3068 - test/modules/DynamicFields/DynamicFields_Bug24095_test.php
3069 - test/simpletest/browser.php
3070 - test/simpletest/default_reporter.php
3071 - test/simpletest/detached.php
3072 - test/simpletest/eclipse.php
3073 - test/simpletest/expectation.php
3074 - test/simpletest/extensions/pear_test_case.php
3075 - test/simpletest/form.php
3076 - test/simpletest/http.php
3077 - test/simpletest/mock_objects.php
3078 - test/simpletest/page.php
3079 - test/simpletest/parser.php
3080 - test/simpletest/remote.php
3081 - test/simpletest/shell_tester.php
3082 - test/simpletest/simple_test.php
3083 - test/simpletest/simpletest.php
3084 - test/simpletest/test/acceptance_test.php
3085 - test/simpletest/test/adapter_test.php
3086 - test/simpletest/test/authentication_test.php
3087 - test/simpletest/test/browser_test.php
3088 - test/simpletest/test/collector_test.php
3089 - test/simpletest/test/compatibility_test.php
3090 - test/simpletest/test/detached_test.php
3091 - test/simpletest/test/eclipse_test.php
3092 - test/simpletest/test/encoding_test.php
3093 - test/simpletest/test/errors_test.php
3094 - test/simpletest/test/expectation_test.php
3095 - test/simpletest/test/form_test.php
3096 - test/simpletest/test/frames_test.php
3097 - test/simpletest/test/http_test.php
3098 - test/simpletest/test/live_test.php
3099 - test/simpletest/test/mock_objects_test.php
3100 - test/simpletest/test/page_test.php
3101 - test/simpletest/test/parse_error_test.php
3102 - test/simpletest/test/parser_test.php
3103 - test/simpletest/test/remote_test.php
3104 - test/simpletest/test/shell_test.php
3105 - test/simpletest/test/shell_tester_test.php
3106 - test/simpletest/test/simpletest_test.php
3107 - test/simpletest/test/site/page_request.php
3108 - test/simpletest/test/tag_test.php
3109 - test/simpletest/test/unit_tester_test.php
3110 - test/simpletest/test/user_agent_test.php
3111 - test/simpletest/test/visual_test.php
3112 - test/simpletest/test/xml_test.php
3113 - test/simpletest/test_case.php
3114 - test/simpletest/ui/array_reporter/test.php
3115 - test/simpletest/ui/recorder/test.php
3116 - test/simpletest/unit_tester.php
3117 - test/simpletest/url.php
3118 - test/simpletest/user_agent.php
3119 - test/simpletest/web_tester.php
3120 - test/spikephpcoverage/src/PEAR.php
3121 - test/spikephpcoverage/src/util/Utility.php
3122 - test/spikephpcoverage/src/XML/Parser.php
3123 - test/spikephpcoverage/src/XML/Parser/Simple.php
3124 - test/test_utilities/SugarTest_SimpleBrowser.php
3126 r38362 - 2008-07-28 14:06:59 -0700 (Mon, 28 Jul 2008) - roger - bug: 23897. Using print_r when using the debug statement in nusoap will print out the statements to the screen if the call is coming from the UI.
3128 r38300 - 2008-07-25 13:33:43 -0700 (Fri, 25 Jul 2008) - Samir Gandhi - put the debug in parseresponse function
3130 r38293 - 2008-07-25 12:32:34 -0700 (Fri, 25 Jul 2008) - Samir Gandhi - to put all the debug statements return value in the call function
3132 r36824 - 2008-06-18 09:26:11 -0700 (Wed, 18 Jun 2008) - roger - bug: 21832
3134 r26422 - 2007-09-05 17:29:12 -0700 (Wed, 05 Sep 2007) - majed - migrate from beta 1 to trunk
3136 r15787 - 2006-08-10 10:14:41 -0700 (Thu, 10 Aug 2006) - roger - RRS: bug 7961
3138 r14701 - 2006-07-17 13:37:26 -0700 (Mon, 17 Jul 2006) - roger - RRS: bug 5801
3140 r13782 - 2006-06-06 10:58:55 -0700 (Tue, 06 Jun 2006) - majed - changes entry point code
3142 r11466 - 2006-02-01 15:49:47 -0800 (Wed, 01 Feb 2006) - jacob - Adding extra !empty check to get around a PHP warning.
3144 r11115 - 2006-01-17 14:54:45 -0800 (Tue, 17 Jan 2006) - majed - add entry point validation
3146 r10585 - 2005-12-13 14:42:26 -0800 (Tue, 13 Dec 2005) - majed - adds new license mechanisim
3148 r10170 - 2005-12-05 18:37:46 -0800 (Mon, 05 Dec 2005) - majed - fixes various issues
3150 r8999 - 2005-11-04 05:26:49 -0800 (Fri, 04 Nov 2005) - roger - When nusoap was upgraded we had an issue with the user's default language not being populated during a soap request. I determined the reason this was happening and have checked in the corresponding change to nusoap.
3152 r8991 - 2005-11-03 19:07:25 -0800 (Thu, 03 Nov 2005) - majed - fixes nusoap issue
3154 r8846 - 2005-10-31 11:01:12 -0800 (Mon, 31 Oct 2005) - majed - new version of nusoap
3156 r7905 - 2005-09-21 19:12:57 -0700 (Wed, 21 Sep 2005) - majed - restores old nusoap pre & with a few fixes
3158 r7861 - 2005-09-20 15:40:25 -0700 (Tue, 20 Sep 2005) - majed - & fix for 3.5.1
3160 r7452 - 2005-08-17 11:32:34 -0700 (Wed, 17 Aug 2005) - majed - changes soap to nusoap
3162 r5820 - 2005-06-21 14:22:24 -0700 (Tue, 21 Jun 2005) - majed - fixes issues with nusoap and with custom fields
3164 r5462 - 2005-05-25 13:50:11 -0700 (Wed, 25 May 2005) - majed - upgraded nusoap to .6.9
3166 r5104 - 2005-05-04 15:33:41 -0700 (Wed, 04 May 2005) - majed - gets rid of HTTP_GET_VARS and what not which has been deprecated
3168 r573 - 2004-09-04 13:03:32 -0700 (Sat, 04 Sep 2004) - sugarclint - undoing copyrights added in inadvertantly. --clint
3170 r546 - 2004-09-03 11:49:38 -0700 (Fri, 03 Sep 2004) - sugarmsi - removed echo count
3172 r354 - 2004-08-02 23:00:37 -0700 (Mon, 02 Aug 2004) - sugarjacob - Adding Soap
3182 * transport class for sending/receiving data via HTTP and HTTPS
3183 * NOTE: PHP must be compiled with the CURL extension for HTTPS support
3185 * @author Dietrich Ayala <dietrich@ganx4.com>
3186 * @author Scott Nichol <snichol@users.sourceforge.net>
3190 class soap_transport_http extends nusoap_base {
3194 var $digest_uri = '';
3199 var $request_method = 'POST';
3200 var $protocol_version = '1.0';
3202 var $outgoing_headers = array();
3203 var $incoming_headers = array();
3204 var $incoming_cookies = array();
3205 var $outgoing_payload = '';
3206 var $incoming_payload = '';
3207 var $response_status_line; // HTTP response status line
3208 var $useSOAPAction = true;
3209 var $persistentConnection = false;
3210 var $ch = false; // cURL handle
3211 var $ch_options = array(); // cURL custom options
3212 var $use_curl = false; // force cURL use
3213 var $proxy = null; // proxy information (associative array)
3217 var $digestRequest = array();
3218 var $certRequest = array(); // keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, certpassword (optional), verifypeer (optional), verifyhost (optional)
3219 // cainfofile: certificate authority file, e.g. '$pathToPemFiles/rootca.pem'
3220 // sslcertfile: SSL certificate file, e.g. '$pathToPemFiles/mycert.pem'
3221 // sslkeyfile: SSL key file, e.g. '$pathToPemFiles/mykey.pem'
3222 // passphrase: SSL key password/passphrase
3223 // certpassword: SSL certificate password
3224 // verifypeer: default is 1
3225 // verifyhost: default is 1
3230 * @param string $url The URL to which to connect
3231 * @param array $curl_options User-specified cURL options
3232 * @param boolean $use_curl Whether to try to force cURL use
3235 function soap_transport_http($url, $curl_options = NULL, $use_curl = false){
3236 parent::nusoap_base();
3237 $this->debug("ctor url=$url use_curl=$use_curl curl_options:");
3238 $this->appendDebug($this->varDump($curl_options));
3239 $this->setURL($url);
3240 if (is_array($curl_options)) {
3241 $this->ch_options = $curl_options;
3243 $this->use_curl = $use_curl;
3244 preg_match('/\$Revisio' . 'n: ([^ ]+)/', $this->revision, $rev);
3245 $this->setHeader('User-Agent', $this->title.'/'.$this->version.' ('.$rev[1].')');
3249 * sets a cURL option
3251 * @param mixed $option The cURL option (always integer?)
3252 * @param mixed $value The cURL option value
3255 function setCurlOption($option, $value) {
3256 $this->debug("setCurlOption option=$option, value=");
3257 $this->appendDebug($this->varDump($value));
3258 curl_setopt($this->ch, $option, $value);
3262 * sets an HTTP header
3264 * @param string $name The name of the header
3265 * @param string $value The value of the header
3268 function setHeader($name, $value) {
3269 $this->outgoing_headers[$name] = $value;
3270 $this->debug("set header $name: $value");
3274 * unsets an HTTP header
3276 * @param string $name The name of the header
3279 function unsetHeader($name) {
3280 if (isset($this->outgoing_headers[$name])) {
3281 $this->debug("unset header $name");
3282 unset($this->outgoing_headers[$name]);
3287 * sets the URL to which to connect
3289 * @param string $url The URL to which to connect
3292 function setURL($url) {
3295 $u = parse_url($url);
3296 foreach($u as $k => $v){
3297 $this->debug("parsed URL $k = $v");
3301 // add any GET params to path
3302 if(isset($u['query']) && $u['query'] != ''){
3303 $this->path .= '?' . $u['query'];
3307 if(!isset($u['port'])){
3308 if($u['scheme'] == 'https'){
3315 $this->uri = $this->path;
3316 $this->digest_uri = $this->uri;
3319 if (!isset($u['port'])) {
3320 $this->setHeader('Host', $this->host);
3322 $this->setHeader('Host', $this->host.':'.$this->port);
3325 if (isset($u['user']) && $u['user'] != '') {
3326 $this->setCredentials(urldecode($u['user']), isset($u['pass']) ? urldecode($u['pass']) : '');
3331 * gets the I/O method to use
3333 * @return string I/O method to use (socket|curl|unknown)
3336 function io_method() {
3337 if ($this->use_curl || ($this->scheme == 'https') || ($this->scheme == 'http' && $this->authtype == 'ntlm') || ($this->scheme == 'http' && is_array($this->proxy) && $this->proxy['authtype'] == 'ntlm'))
3339 if (($this->scheme == 'http' || $this->scheme == 'ssl') && $this->authtype != 'ntlm' && (!is_array($this->proxy) || $this->proxy['authtype'] != 'ntlm'))
3345 * establish an HTTP connection
3347 * @param integer $timeout set connection timeout in seconds
3348 * @param integer $response_timeout set response timeout in seconds
3349 * @return boolean true if connected, false if not
3352 function connect($connection_timeout=0,$response_timeout=30){
3353 // For PHP 4.3 with OpenSSL, change https scheme to ssl, then treat like
3354 // "regular" socket.
3355 // TODO: disabled for now because OpenSSL must be *compiled* in (not just
3356 // loaded), and until PHP5 stream_get_wrappers is not available.
3357 // if ($this->scheme == 'https') {
3358 // if (version_compare(phpversion(), '4.3.0') >= 0) {
3359 // if (extension_loaded('openssl')) {
3360 // $this->scheme = 'ssl';
3361 // $this->debug('Using SSL over OpenSSL');
3365 $this->debug("connect connection_timeout $connection_timeout, response_timeout $response_timeout, scheme $this->scheme, host $this->host, port $this->port");
3366 if ($this->io_method() == 'socket') {
3367 if (!is_array($this->proxy)) {
3368 $host = $this->host;
3369 $port = $this->port;
3371 $host = $this->proxy['host'];
3372 $port = $this->proxy['port'];
3375 // use persistent connection
3376 if($this->persistentConnection && isset($this->fp) && is_resource($this->fp)){
3377 if (!feof($this->fp)) {
3378 $this->debug('Re-use persistent connection');
3382 $this->debug('Closed persistent connection at EOF');
3385 // munge host if using OpenSSL
3386 if ($this->scheme == 'ssl') {
3387 $host = 'ssl://' . $host;
3389 $this->debug('calling fsockopen with host ' . $host . ' connection_timeout ' . $connection_timeout);
3392 if($connection_timeout > 0){
3393 $this->fp = @fsockopen( $host, $this->port, $this->errno, $this->error_str, $connection_timeout);
3395 $this->fp = @fsockopen( $host, $this->port, $this->errno, $this->error_str);
3400 $msg = 'Couldn\'t open socket connection to server ' . $this->url;
3402 $msg .= ', Error ('.$this->errno.'): '.$this->error_str;
3404 $msg .= ' prior to connect(). This is often a problem looking up the host name.';
3407 $this->setError($msg);
3411 // set response timeout
3412 $this->debug('set response timeout to ' . $response_timeout);
3413 socket_set_timeout( $this->fp, $response_timeout);
3415 $this->debug('socket connected');
3417 } else if ($this->io_method() == 'curl') {
3418 if (!extension_loaded('curl')) {
3419 // $this->setError('cURL Extension, or OpenSSL extension w/ PHP version >= 4.3 is required for HTTPS');
3420 $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.');
3423 // Avoid warnings when PHP does not have these options
3424 if (defined('CURLOPT_CONNECTIONTIMEOUT'))
3425 $CURLOPT_CONNECTIONTIMEOUT = CURLOPT_CONNECTIONTIMEOUT;
3427 $CURLOPT_CONNECTIONTIMEOUT = 78;
3428 if (defined('CURLOPT_HTTPAUTH'))
3429 $CURLOPT_HTTPAUTH = CURLOPT_HTTPAUTH;
3431 $CURLOPT_HTTPAUTH = 107;
3432 if (defined('CURLOPT_PROXYAUTH'))
3433 $CURLOPT_PROXYAUTH = CURLOPT_PROXYAUTH;
3435 $CURLOPT_PROXYAUTH = 111;
3436 if (defined('CURLAUTH_BASIC'))
3437 $CURLAUTH_BASIC = CURLAUTH_BASIC;
3439 $CURLAUTH_BASIC = 1;
3440 if (defined('CURLAUTH_DIGEST'))
3441 $CURLAUTH_DIGEST = CURLAUTH_DIGEST;
3443 $CURLAUTH_DIGEST = 2;
3444 if (defined('CURLAUTH_NTLM'))
3445 $CURLAUTH_NTLM = CURLAUTH_NTLM;
3449 $this->debug('connect using cURL');
3451 $this->ch = curl_init();
3453 $hostURL = ($this->port != '') ? "$this->scheme://$this->host:$this->port" : "$this->scheme://$this->host";
3455 $hostURL .= $this->path;
3456 $this->setCurlOption(CURLOPT_URL, $hostURL);
3457 // follow location headers (re-directs)
3458 if (ini_get('safe_mode') || ini_get('open_basedir')) {
3459 $this->debug('safe_mode or open_basedir set, so do not set CURLOPT_FOLLOWLOCATION');
3460 $this->debug('safe_mode = ');
3461 $this->appendDebug($this->varDump(ini_get('safe_mode')));
3462 $this->debug('open_basedir = ');
3463 $this->appendDebug($this->varDump(ini_get('open_basedir')));
3465 $this->setCurlOption(CURLOPT_FOLLOWLOCATION, 1);
3467 // ask for headers in the response output
3468 $this->setCurlOption(CURLOPT_HEADER, 1);
3469 // ask for the response output as the return value
3470 $this->setCurlOption(CURLOPT_RETURNTRANSFER, 1);
3472 // We manage this ourselves through headers and encoding
3473 // if(function_exists('gzuncompress')){
3474 // $this->setCurlOption(CURLOPT_ENCODING, 'deflate');
3476 // persistent connection
3477 if ($this->persistentConnection) {
3478 // I believe the following comment is now bogus, having applied to
3479 // the code when it used CURLOPT_CUSTOMREQUEST to send the request.
3480 // The way we send data, we cannot use persistent connections, since
3481 // there will be some "junk" at the end of our request.
3482 //$this->setCurlOption(CURL_HTTP_VERSION_1_1, true);
3483 $this->persistentConnection = false;
3484 $this->setHeader('Connection', 'close');
3487 if ($connection_timeout != 0) {
3488 $this->setCurlOption($CURLOPT_CONNECTIONTIMEOUT, $connection_timeout);
3490 if ($response_timeout != 0) {
3491 $this->setCurlOption(CURLOPT_TIMEOUT, $response_timeout);
3494 if ($this->scheme == 'https') {
3495 $this->debug('set cURL SSL verify options');
3496 // recent versions of cURL turn on peer/host checking by default,
3497 // while PHP binaries are not compiled with a default location for the
3498 // CA cert bundle, so disable peer/host checking.
3499 //$this->setCurlOption(CURLOPT_CAINFO, 'f:\php-4.3.2-win32\extensions\curl-ca-bundle.crt');
3500 $this->setCurlOption(CURLOPT_SSL_VERIFYPEER, 0);
3501 $this->setCurlOption(CURLOPT_SSL_VERIFYHOST, 0);
3503 // support client certificates (thanks Tobias Boes, Doug Anarino, Eryan Ariobowo)
3504 if ($this->authtype == 'certificate') {
3505 $this->debug('set cURL certificate options');
3506 if (isset($this->certRequest['cainfofile'])) {
3507 $this->setCurlOption(CURLOPT_CAINFO, $this->certRequest['cainfofile']);
3509 if (isset($this->certRequest['verifypeer'])) {
3510 $this->setCurlOption(CURLOPT_SSL_VERIFYPEER, $this->certRequest['verifypeer']);
3512 $this->setCurlOption(CURLOPT_SSL_VERIFYPEER, 1);
3514 if (isset($this->certRequest['verifyhost'])) {
3515 $this->setCurlOption(CURLOPT_SSL_VERIFYHOST, $this->certRequest['verifyhost']);
3517 $this->setCurlOption(CURLOPT_SSL_VERIFYHOST, 1);
3519 if (isset($this->certRequest['sslcertfile'])) {
3520 $this->setCurlOption(CURLOPT_SSLCERT, $this->certRequest['sslcertfile']);
3522 if (isset($this->certRequest['sslkeyfile'])) {
3523 $this->setCurlOption(CURLOPT_SSLKEY, $this->certRequest['sslkeyfile']);
3525 if (isset($this->certRequest['passphrase'])) {
3526 $this->setCurlOption(CURLOPT_SSLKEYPASSWD, $this->certRequest['passphrase']);
3528 if (isset($this->certRequest['certpassword'])) {
3529 $this->setCurlOption(CURLOPT_SSLCERTPASSWD, $this->certRequest['certpassword']);
3533 if ($this->authtype && ($this->authtype != 'certificate')) {
3534 if ($this->username) {
3535 $this->debug('set cURL username/password');
3536 $this->setCurlOption(CURLOPT_USERPWD, "$this->username:$this->password");
3538 if ($this->authtype == 'basic') {
3539 $this->debug('set cURL for Basic authentication');
3540 $this->setCurlOption($CURLOPT_HTTPAUTH, $CURLAUTH_BASIC);
3542 if ($this->authtype == 'digest') {
3543 $this->debug('set cURL for digest authentication');
3544 $this->setCurlOption($CURLOPT_HTTPAUTH, $CURLAUTH_DIGEST);
3546 if ($this->authtype == 'ntlm') {
3547 $this->debug('set cURL for NTLM authentication');
3548 $this->setCurlOption($CURLOPT_HTTPAUTH, $CURLAUTH_NTLM);
3551 if (is_array($this->proxy)) {
3552 $this->debug('set cURL proxy options');
3553 if ($this->proxy['port'] != '') {
3554 $this->setCurlOption(CURLOPT_PROXY, $this->proxy['host'].':'.$this->proxy['port']);
3556 $this->setCurlOption(CURLOPT_PROXY, $this->proxy['host']);
3558 if ($this->proxy['username'] || $this->proxy['password']) {
3559 $this->debug('set cURL proxy authentication options');
3560 $this->setCurlOption(CURLOPT_PROXYUSERPWD, $this->proxy['username'].':'.$this->proxy['password']);
3561 if ($this->proxy['authtype'] == 'basic') {
3562 $this->setCurlOption($CURLOPT_PROXYAUTH, $CURLAUTH_BASIC);
3564 if ($this->proxy['authtype'] == 'ntlm') {
3565 $this->setCurlOption($CURLOPT_PROXYAUTH, $CURLAUTH_NTLM);
3569 $this->debug('cURL connection set up');
3572 $this->setError('Unknown scheme ' . $this->scheme);
3573 $this->debug('Unknown scheme ' . $this->scheme);
3579 * sends the SOAP request and gets the SOAP response via HTTP[S]
3581 * @param string $data message data
3582 * @param integer $timeout set connection timeout in seconds
3583 * @param integer $response_timeout set response timeout in seconds
3584 * @param array $cookies cookies to send
3585 * @return string data
3588 function send($data, $timeout=0, $response_timeout=30, $cookies=NULL) {
3590 $this->debug('entered send() with data of length: '.strlen($data));
3592 $this->tryagain = true;
3594 while ($this->tryagain) {
3595 $this->tryagain = false;
3598 if (!$this->connect($timeout, $response_timeout)){
3603 if (!$this->sendRequest($data, $cookies)){
3608 $respdata = $this->getResponse();
3610 $this->setError("Too many tries to get an OK response ($this->response_status_line)");
3613 $this->debug('end of send()');
3619 * sends the SOAP request and gets the SOAP response via HTTPS using CURL
3621 * @param string $data message data
3622 * @param integer $timeout set connection timeout in seconds
3623 * @param integer $response_timeout set response timeout in seconds
3624 * @param array $cookies cookies to send
3625 * @return string data
3629 function sendHTTPS($data, $timeout=0, $response_timeout=30, $cookies) {
3630 return $this->send($data, $timeout, $response_timeout, $cookies);
3634 * if authenticating, set user credentials here
3636 * @param string $username
3637 * @param string $password
3638 * @param string $authtype (basic|digest|certificate|ntlm)
3639 * @param array $digestRequest (keys must be nonce, nc, realm, qop)
3640 * @param array $certRequest (keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, certpassword (optional), verifypeer (optional), verifyhost (optional): see corresponding options in cURL docs)
3643 function setCredentials($username, $password, $authtype = 'basic', $digestRequest = array(), $certRequest = array()) {
3644 $this->debug("setCredentials username=$username authtype=$authtype digestRequest=");
3645 $this->appendDebug($this->varDump($digestRequest));
3646 $this->debug("certRequest=");
3647 $this->appendDebug($this->varDump($certRequest));
3649 if ($authtype == 'basic') {
3650 $this->setHeader('Authorization', 'Basic '.base64_encode(str_replace(':','',$username).':'.$password));
3651 } elseif ($authtype == 'digest') {
3652 if (isset($digestRequest['nonce'])) {
3653 $digestRequest['nc'] = isset($digestRequest['nc']) ? $digestRequest['nc']++ : 1;
3655 // calculate the Digest hashes (calculate code based on digest implementation found at: http://www.rassoc.com/gregr/weblog/stories/2002/07/09/webServicesSecurityHttpDigestAuthenticationWithoutActiveDirectory.html)
3657 // A1 = unq(username-value) ":" unq(realm-value) ":" passwd
3658 $A1 = $username. ':' . (isset($digestRequest['realm']) ? $digestRequest['realm'] : '') . ':' . $password;
3663 // A2 = Method ":" digest-uri-value
3664 $A2 = $this->request_method . ':' . $this->digest_uri;
3669 // KD(secret, data) = H(concat(secret, ":", data))
3671 // request-digest = <"> < KD ( H(A1), unq(nonce-value)
3673 // ":" unq(cnonce-value)
3674 // ":" unq(qop-value)
3677 // if qop is missing,
3678 // request-digest = <"> < KD ( H(A1), unq(nonce-value) ":" H(A2) ) > <">
3680 $unhashedDigest = '';
3681 $nonce = isset($digestRequest['nonce']) ? $digestRequest['nonce'] : '';
3683 if ($digestRequest['qop'] != '') {
3684 $unhashedDigest = $HA1 . ':' . $nonce . ':' . sprintf("%08d", $digestRequest['nc']) . ':' . $cnonce . ':' . $digestRequest['qop'] . ':' . $HA2;
3686 $unhashedDigest = $HA1 . ':' . $nonce . ':' . $HA2;
3689 $hashedDigest = md5($unhashedDigest);
3692 if (isset($digestRequest['opaque'])) {
3693 $opaque = ', opaque="' . $digestRequest['opaque'] . '"';
3696 $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 . '"');
3698 } elseif ($authtype == 'certificate') {
3699 $this->certRequest = $certRequest;
3700 $this->debug('Authorization header not set for certificate');
3701 } elseif ($authtype == 'ntlm') {
3703 $this->debug('Authorization header not set for ntlm');
3705 $this->username = $username;
3706 $this->password = $password;
3707 $this->authtype = $authtype;
3708 $this->digestRequest = $digestRequest;
3712 * set the soapaction value
3714 * @param string $soapaction
3717 function setSOAPAction($soapaction) {
3718 $this->setHeader('SOAPAction', '"' . $soapaction . '"');
3724 * @param string $enc encoding style. supported values: gzip, deflate, or both
3727 function setEncoding($enc='gzip, deflate') {
3728 if (function_exists('gzdeflate')) {
3729 $this->protocol_version = '1.1';
3730 $this->setHeader('Accept-Encoding', $enc);
3731 if (!isset($this->outgoing_headers['Connection'])) {
3732 $this->setHeader('Connection', 'close');
3733 $this->persistentConnection = false;
3735 // deprecated as of PHP 5.3.0
3736 //set_magic_quotes_runtime(0);
3737 $this->encoding = $enc;
3742 * set proxy info here
3744 * @param string $proxyhost use an empty string to remove proxy
3745 * @param string $proxyport
3746 * @param string $proxyusername
3747 * @param string $proxypassword
3748 * @param string $proxyauthtype (basic|ntlm)
3751 function setProxy($proxyhost, $proxyport, $proxyusername = '', $proxypassword = '', $proxyauthtype = 'basic') {
3753 $this->proxy = array(
3754 'host' => $proxyhost,
3755 'port' => $proxyport,
3756 'username' => $proxyusername,
3757 'password' => $proxypassword,
3758 'authtype' => $proxyauthtype
3760 if ($proxyusername != '' && $proxypassword != '' && $proxyauthtype = 'basic') {
3761 $this->setHeader('Proxy-Authorization', ' Basic '.base64_encode($proxyusername.':'.$proxypassword));
3764 $this->debug('remove proxy');
3766 unsetHeader('Proxy-Authorization');
3772 * Test if the given string starts with a header that is to be skipped.
3773 * Skippable headers result from chunked transfer and proxy requests.
3775 * @param string $data The string to check.
3776 * @returns boolean Whether a skippable header was found.
3779 function isSkippableCurlHeader(&$data) {
3780 $skipHeaders = array( 'HTTP/1.1 100',
3787 'HTTP/1.0 200 Connection established');
3788 foreach ($skipHeaders as $hd) {
3789 $prefix = substr($data, 0, strlen($hd));
3790 if ($prefix == $hd) return true;
3797 * decode a string that is encoded w/ "chunked' transfer encoding
3798 * as defined in RFC2068 19.4.6
3800 * @param string $buffer
3806 function decodeChunked($buffer, $lb){
3811 // read chunk-size, chunk-extension (if any) and CRLF
3812 // get the position of the linebreak
3813 $chunkend = strpos($buffer, $lb);
3814 if ($chunkend == FALSE) {
3815 $this->debug('no linebreak found in decodeChunked');
3818 $temp = substr($buffer,0,$chunkend);
3819 $chunk_size = hexdec( trim($temp) );
3820 $chunkstart = $chunkend + strlen($lb);
3821 // while (chunk-size > 0) {
3822 while ($chunk_size > 0) {
3823 $this->debug("chunkstart: $chunkstart chunk_size: $chunk_size");
3824 $chunkend = strpos( $buffer, $lb, $chunkstart + $chunk_size);
3826 // Just in case we got a broken connection
3827 if ($chunkend == FALSE) {
3828 $chunk = substr($buffer,$chunkstart);
3829 // append chunk-data to entity-body
3831 $length += strlen($chunk);
3835 // read chunk-data and CRLF
3836 $chunk = substr($buffer,$chunkstart,$chunkend-$chunkstart);
3837 // append chunk-data to entity-body
3839 // length := length + chunk-size
3840 $length += strlen($chunk);
3841 // read chunk-size and CRLF
3842 $chunkstart = $chunkend + strlen($lb);
3844 $chunkend = strpos($buffer, $lb, $chunkstart) + strlen($lb);
3845 if ($chunkend == FALSE) {
3846 break; //Just in case we got a broken connection
3848 $temp = substr($buffer,$chunkstart,$chunkend-$chunkstart);
3849 $chunk_size = hexdec( trim($temp) );
3850 $chunkstart = $chunkend;
3856 * Writes the payload, including HTTP headers, to $this->outgoing_payload.
3858 * @param string $data HTTP body
3859 * @param string $cookie_str data for HTTP Cookie header
3863 function buildPayload($data, $cookie_str = '') {
3864 // Note: for cURL connections, $this->outgoing_payload is ignored,
3865 // as is the Content-Length header, but these are still created as
3866 // debugging guides.
3868 // add content-length header
3869 if ($this->request_method != 'GET') {
3870 $this->setHeader('Content-Length', strlen($data));
3873 // start building outgoing payload:
3879 $req = "$this->request_method $uri HTTP/$this->protocol_version";
3880 $this->debug("HTTP request: $req");
3881 $this->outgoing_payload = "$req\r\n";
3883 // loop thru headers, serializing
3884 foreach($this->outgoing_headers as $k => $v){
3886 $this->debug("HTTP header: $hdr");
3887 $this->outgoing_payload .= "$hdr\r\n";
3891 if ($cookie_str != '') {
3892 $hdr = 'Cookie: '.$cookie_str;
3893 $this->debug("HTTP header: $hdr");
3894 $this->outgoing_payload .= "$hdr\r\n";
3897 // header/body separator
3898 $this->outgoing_payload .= "\r\n";
3901 $this->outgoing_payload .= $data;
3905 * sends the SOAP request via HTTP[S]
3907 * @param string $data message data
3908 * @param array $cookies cookies to send
3909 * @return boolean true if OK, false if problem
3912 function sendRequest($data, $cookies = NULL) {
3913 // build cookie string
3914 $cookie_str = $this->getCookiesForRequest($cookies, (($this->scheme == 'ssl') || ($this->scheme == 'https')));
3917 $this->buildPayload($data, $cookie_str);
3919 if ($this->io_method() == 'socket') {
3921 if(!fputs($this->fp, $this->outgoing_payload, strlen($this->outgoing_payload))) {
3922 $this->setError('couldn\'t write message data to socket');
3923 $this->debug('couldn\'t write message data to socket');
3926 $this->debug('wrote data to socket, length = ' . strlen($this->outgoing_payload));
3928 } else if ($this->io_method() == 'curl') {
3930 // cURL does say this should only be the verb, and in fact it
3931 // turns out that the URI and HTTP version are appended to this, which
3932 // some servers refuse to work with (so we no longer use this method!)
3933 //$this->setCurlOption(CURLOPT_CUSTOMREQUEST, $this->outgoing_payload);
3934 $curl_headers = array();
3935 foreach($this->outgoing_headers as $k => $v){
3936 if ($k == 'Connection' || $k == 'Content-Length' || $k == 'Host' || $k == 'Authorization' || $k == 'Proxy-Authorization') {
3937 $this->debug("Skip cURL header $k: $v");
3939 $curl_headers[] = "$k: $v";
3942 if ($cookie_str != '') {
3943 $curl_headers[] = 'Cookie: ' . $cookie_str;
3945 $this->setCurlOption(CURLOPT_HTTPHEADER, $curl_headers);
3946 $this->debug('set cURL HTTP headers');
3947 if ($this->request_method == "POST") {
3948 $this->setCurlOption(CURLOPT_POST, 1);
3949 $this->setCurlOption(CURLOPT_POSTFIELDS, $data);
3950 $this->debug('set cURL POST data');
3953 // insert custom user-set cURL options
3954 foreach ($this->ch_options as $key => $val) {
3955 $this->setCurlOption($key, $val);
3958 $this->debug('set cURL payload');
3964 * gets the SOAP response via HTTP[S]
3966 * @return string the response (also sets member variables like incoming_payload)
3969 function getResponse(){
3970 $this->incoming_payload = '';
3972 if ($this->io_method() == 'socket') {
3973 // loop until headers have been retrieved
3975 while (!isset($lb)){
3977 // We might EOF during header read.
3978 if(feof($this->fp)) {
3979 $this->incoming_payload = $data;
3980 $this->debug('found no headers before EOF after length ' . strlen($data));
3981 $this->debug("received before EOF:\n" . $data);
3982 $this->setError('server failed to send headers');
3986 $tmp = fgets($this->fp, 256);
3987 $tmplen = strlen($tmp);
3988 $this->debug("read line of $tmplen bytes: " . trim($tmp));
3991 $this->incoming_payload = $data;
3992 $this->debug('socket read of headers timed out after length ' . strlen($data));
3993 $this->debug("read before timeout: " . $data);
3994 $this->setError('socket read of headers timed out');
3999 $pos = strpos($data,"\r\n\r\n");
4003 $pos = strpos($data,"\n\n");
4008 // remove 100 headers
4009 if (isset($lb) && preg_match('/^HTTP\/1.1 100/',$data)) {
4014 // store header data
4015 $this->incoming_payload .= $data;
4016 $this->debug('found end of headers after length ' . strlen($data));
4018 $header_data = trim(substr($data,0,$pos));
4019 $header_array = explode($lb,$header_data);
4020 $this->incoming_headers = array();
4021 $this->incoming_cookies = array();
4022 foreach($header_array as $header_line){
4023 $arr = explode(':',$header_line, 2);
4024 if(count($arr) > 1){
4025 $header_name = strtolower(trim($arr[0]));
4026 $this->incoming_headers[$header_name] = trim($arr[1]);
4027 if ($header_name == 'set-cookie') {
4028 // TODO: allow multiple cookies from parseCookie
4029 $cookie = $this->parseCookie(trim($arr[1]));
4031 $this->incoming_cookies[] = $cookie;
4032 $this->debug('found cookie: ' . $cookie['name'] . ' = ' . $cookie['value']);
4034 $this->debug('did not find cookie in ' . trim($arr[1]));
4037 } else if (isset($header_name)) {
4038 // append continuation line to previous header
4039 $this->incoming_headers[$header_name] .= $lb . ' ' . $header_line;
4043 // loop until msg has been received
4044 if (isset($this->incoming_headers['transfer-encoding']) && strtolower($this->incoming_headers['transfer-encoding']) == 'chunked') {
4045 $content_length = 2147483647; // ignore any content-length header
4047 $this->debug("want to read chunked content");
4048 } elseif (isset($this->incoming_headers['content-length'])) {
4049 $content_length = $this->incoming_headers['content-length'];
4051 $this->debug("want to read content of length $content_length");
4053 $content_length = 2147483647;
4055 $this->debug("want to read content to EOF");
4060 $tmp = fgets($this->fp, 256);
4061 $tmplen = strlen($tmp);
4062 $this->debug("read chunk line of $tmplen bytes");
4064 $this->incoming_payload = $data;
4065 $this->debug('socket read of chunk length timed out after length ' . strlen($data));
4066 $this->debug("read before timeout:\n" . $data);
4067 $this->setError('socket read of chunk length timed out');
4070 $content_length = hexdec(trim($tmp));
4071 $this->debug("chunk length $content_length");
4074 while (($strlen < $content_length) && (!feof($this->fp))) {
4075 $readlen = min(8192, $content_length - $strlen);
4076 $tmp = fread($this->fp, $readlen);
4077 $tmplen = strlen($tmp);
4078 $this->debug("read buffer of $tmplen bytes");
4079 if (($tmplen == 0) && (!feof($this->fp))) {
4080 $this->incoming_payload = $data;
4081 $this->debug('socket read of body timed out after length ' . strlen($data));
4082 $this->debug("read before timeout:\n" . $data);
4083 $this->setError('socket read of body timed out');
4089 if ($chunked && ($content_length > 0)) {
4090 $tmp = fgets($this->fp, 256);
4091 $tmplen = strlen($tmp);
4092 $this->debug("read chunk terminator of $tmplen bytes");
4094 $this->incoming_payload = $data;
4095 $this->debug('socket read of chunk terminator timed out after length ' . strlen($data));
4096 $this->debug("read before timeout:\n" . $data);
4097 $this->setError('socket read of chunk terminator timed out');
4101 } while ($chunked && ($content_length > 0) && (!feof($this->fp)));
4102 if (feof($this->fp)) {
4103 $this->debug('read to EOF');
4105 $this->debug('read body of length ' . strlen($data));
4106 $this->incoming_payload .= $data;
4107 $this->debug('received a total of '.strlen($this->incoming_payload).' bytes of data from server');
4109 // close filepointer
4111 (isset($this->incoming_headers['connection']) && strtolower($this->incoming_headers['connection']) == 'close') ||
4112 (! $this->persistentConnection) || feof($this->fp)){
4115 $this->debug('closed socket');
4118 // connection was closed unexpectedly
4119 if($this->incoming_payload == ''){
4120 $this->setError('no response from server');
4124 // decode transfer-encoding
4125 // if(isset($this->incoming_headers['transfer-encoding']) && strtolower($this->incoming_headers['transfer-encoding']) == 'chunked'){
4126 // if(!$data = $this->decodeChunked($data, $lb)){
4127 // $this->setError('Decoding of chunked data failed');
4130 //print "<pre>\nde-chunked:\n---------------\n$data\n\n---------------\n</pre>";
4131 // set decoded payload
4132 // $this->incoming_payload = $header_data.$lb.$lb.$data;
4135 } else if ($this->io_method() == 'curl') {
4137 $this->debug('send and receive with cURL');
4138 $this->incoming_payload = curl_exec($this->ch);
4139 $data = $this->incoming_payload;
4141 $cErr = curl_error($this->ch);
4143 $err = 'cURL ERROR: '.curl_errno($this->ch).': '.$cErr.'<br>';
4144 // TODO: there is a PHP bug that can cause this to SEGV for CURLINFO_CONTENT_TYPE
4145 foreach(curl_getinfo($this->ch) as $k => $v){
4146 $err .= "$k: $v<br>";
4149 $this->setError($err);
4150 curl_close($this->ch);
4154 //var_dump(curl_getinfo($this->ch));
4158 $this->debug('No cURL error, closing cURL');
4159 curl_close($this->ch);
4161 // try removing skippable headers
4163 while ($this->isSkippableCurlHeader($data)) {
4164 $this->debug("Found HTTP header to skip");
4165 if ($pos = strpos($data,"\r\n\r\n")) {
4166 $data = ltrim(substr($data,$pos));
4167 } elseif($pos = strpos($data,"\n\n") ) {
4168 $data = ltrim(substr($data,$pos));
4173 // have nothing left; just remove 100 header(s)
4175 while (preg_match('/^HTTP\/1.1 100/',$data)) {
4176 if ($pos = strpos($data,"\r\n\r\n")) {
4177 $data = ltrim(substr($data,$pos));
4178 } elseif($pos = strpos($data,"\n\n") ) {
4179 $data = ltrim(substr($data,$pos));
4184 // separate content from HTTP headers
4185 if ($pos = strpos($data,"\r\n\r\n")) {
4187 } elseif( $pos = strpos($data,"\n\n")) {
4190 $this->debug('no proper separation of headers and document');
4191 $this->setError('no proper separation of headers and document');
4194 $header_data = trim(substr($data,0,$pos));
4195 $header_array = explode($lb,$header_data);
4196 $data = ltrim(substr($data,$pos));
4197 $this->debug('found proper separation of headers and document');
4198 $this->debug('cleaned data, stringlen: '.strlen($data));
4200 foreach ($header_array as $header_line) {
4201 $arr = explode(':',$header_line,2);
4202 if(count($arr) > 1){
4203 $header_name = strtolower(trim($arr[0]));
4204 $this->incoming_headers[$header_name] = trim($arr[1]);
4205 if ($header_name == 'set-cookie') {
4206 // TODO: allow multiple cookies from parseCookie
4207 $cookie = $this->parseCookie(trim($arr[1]));
4209 $this->incoming_cookies[] = $cookie;
4210 $this->debug('found cookie: ' . $cookie['name'] . ' = ' . $cookie['value']);
4212 $this->debug('did not find cookie in ' . trim($arr[1]));
4215 } else if (isset($header_name)) {
4216 // append continuation line to previous header
4217 $this->incoming_headers[$header_name] .= $lb . ' ' . $header_line;
4222 $this->response_status_line = $header_array[0];
4223 $arr = explode(' ', $this->response_status_line, 3);
4224 $http_version = $arr[0];
4225 $http_status = intval($arr[1]);
4226 $http_reason = count($arr) > 2 ? $arr[2] : '';
4228 // see if we need to resend the request with http digest authentication
4229 if (isset($this->incoming_headers['location']) && ($http_status == 301 || $http_status == 302)) {
4230 $this->debug("Got $http_status $http_reason with Location: " . $this->incoming_headers['location']);
4231 $this->setURL($this->incoming_headers['location']);
4232 $this->tryagain = true;
4236 // see if we need to resend the request with http digest authentication
4237 if (isset($this->incoming_headers['www-authenticate']) && $http_status == 401) {
4238 $this->debug("Got 401 $http_reason with WWW-Authenticate: " . $this->incoming_headers['www-authenticate']);
4239 if (strstr($this->incoming_headers['www-authenticate'], "Digest ")) {
4240 $this->debug('Server wants digest authentication');
4241 // remove "Digest " from our elements
4242 $digestString = str_replace('Digest ', '', $this->incoming_headers['www-authenticate']);
4244 // parse elements into array
4245 $digestElements = explode(',', $digestString);
4246 foreach ($digestElements as $val) {
4247 $tempElement = explode('=', trim($val), 2);
4248 $digestRequest[$tempElement[0]] = str_replace("\"", '', $tempElement[1]);
4251 // should have (at least) qop, realm, nonce
4252 if (isset($digestRequest['nonce'])) {
4253 $this->setCredentials($this->username, $this->password, 'digest', $digestRequest);
4254 $this->tryagain = true;
4258 $this->debug('HTTP authentication failed');
4259 $this->setError('HTTP authentication failed');
4264 ($http_status >= 300 && $http_status <= 307) ||
4265 ($http_status >= 400 && $http_status <= 417) ||
4266 ($http_status >= 501 && $http_status <= 505)
4268 $this->setError("Unsupported HTTP response status $http_status $http_reason (soapclient->response has contents of the response)");
4272 // decode content-encoding
4273 if(isset($this->incoming_headers['content-encoding']) && $this->incoming_headers['content-encoding'] != ''){
4274 if(strtolower($this->incoming_headers['content-encoding']) == 'deflate' || strtolower($this->incoming_headers['content-encoding']) == 'gzip'){
4275 // if decoding works, use it. else assume data wasn't gzencoded
4276 if(function_exists('gzinflate')){
4277 //$timer->setMarker('starting decoding of gzip/deflated content');
4278 // IIS 5 requires gzinflate instead of gzuncompress (similar to IE 5 and gzdeflate v. gzcompress)
4279 // this means there are no Zlib headers, although there should be
4280 $this->debug('The gzinflate function exists');
4281 $datalen = strlen($data);
4282 if ($this->incoming_headers['content-encoding'] == 'deflate') {
4283 if ($degzdata = @gzinflate($data)) {
4285 $this->debug('The payload has been inflated to ' . strlen($data) . ' bytes');
4286 if (strlen($data) < $datalen) {
4287 // test for the case that the payload has been compressed twice
4288 $this->debug('The inflated payload is smaller than the gzipped one; try again');
4289 if ($degzdata = @gzinflate($data)) {
4291 $this->debug('The payload has been inflated again to ' . strlen($data) . ' bytes');
4295 $this->debug('Error using gzinflate to inflate the payload');
4296 $this->setError('Error using gzinflate to inflate the payload');
4298 } elseif ($this->incoming_headers['content-encoding'] == 'gzip') {
4299 if ($degzdata = @gzinflate(substr($data, 10))) { // do our best
4301 $this->debug('The payload has been un-gzipped to ' . strlen($data) . ' bytes');
4302 if (strlen($data) < $datalen) {
4303 // test for the case that the payload has been compressed twice
4304 $this->debug('The un-gzipped payload is smaller than the gzipped one; try again');
4305 if ($degzdata = @gzinflate(substr($data, 10))) {
4307 $this->debug('The payload has been un-gzipped again to ' . strlen($data) . ' bytes');
4311 $this->debug('Error using gzinflate to un-gzip the payload');
4312 $this->setError('Error using gzinflate to un-gzip the payload');
4315 //$timer->setMarker('finished decoding of gzip/deflated content');
4316 //print "<xmp>\nde-inflated:\n---------------\n$data\n-------------\n</xmp>";
4317 // set decoded payload
4318 $this->incoming_payload = $header_data.$lb.$lb.$data;
4320 $this->debug('The server sent compressed data. Your php install must have the Zlib extension compiled in to support this.');
4321 $this->setError('The server sent compressed data. Your php install must have the Zlib extension compiled in to support this.');
4324 $this->debug('Unsupported Content-Encoding ' . $this->incoming_headers['content-encoding']);
4325 $this->setError('Unsupported Content-Encoding ' . $this->incoming_headers['content-encoding']);
4328 $this->debug('No Content-Encoding header');
4331 if(strlen($data) == 0){
4332 $this->debug('no data after headers!');
4333 $this->setError('no data present after HTTP headers');
4341 * sets the content-type for the SOAP message to be sent
4343 * @param string $type the content type, MIME style
4344 * @param mixed $charset character set used for encoding (or false)
4347 function setContentType($type, $charset = false) {
4348 $this->setHeader('Content-Type', $type . ($charset ? '; charset=' . $charset : ''));
4352 * specifies that an HTTP persistent connection should be used
4354 * @return boolean whether the request was honored by this method.
4357 function usePersistentConnection(){
4358 if (isset($this->outgoing_headers['Accept-Encoding'])) {
4361 $this->protocol_version = '1.1';
4362 $this->persistentConnection = true;
4363 $this->setHeader('Connection', 'Keep-Alive');
4368 * parse an incoming Cookie into it's parts
4370 * @param string $cookie_str content of cookie
4371 * @return array with data of that cookie
4375 * TODO: allow a Set-Cookie string to be parsed into multiple cookies
4377 function parseCookie($cookie_str) {
4378 $cookie_str = str_replace('; ', ';', $cookie_str) . ';';
4379 $data = preg_split('/;/', $cookie_str);
4380 $value_str = $data[0];
4382 $cookie_param = 'domain=';
4383 $start = strpos($cookie_str, $cookie_param);
4385 $domain = substr($cookie_str, $start + strlen($cookie_param));
4386 $domain = substr($domain, 0, strpos($domain, ';'));
4391 $cookie_param = 'expires=';
4392 $start = strpos($cookie_str, $cookie_param);
4394 $expires = substr($cookie_str, $start + strlen($cookie_param));
4395 $expires = substr($expires, 0, strpos($expires, ';'));
4400 $cookie_param = 'path=';
4401 $start = strpos($cookie_str, $cookie_param);
4403 $path = substr($cookie_str, $start + strlen($cookie_param));
4404 $path = substr($path, 0, strpos($path, ';'));
4409 $cookie_param = ';secure;';
4410 if (strpos($cookie_str, $cookie_param) !== FALSE) {
4416 $sep_pos = strpos($value_str, '=');
4419 $name = substr($value_str, 0, $sep_pos);
4420 $value = substr($value_str, $sep_pos + 1);
4421 $cookie= array( 'name' => $name,
4423 'domain' => $domain,
4425 'expires' => $expires,
4434 * sort out cookies for the current request
4436 * @param array $cookies array with all cookies
4437 * @param boolean $secure is the send-content secure or not?
4438 * @return string for Cookie-HTTP-Header
4441 function getCookiesForRequest($cookies, $secure=false) {
4443 if ((! is_null($cookies)) && (is_array($cookies))) {
4444 foreach ($cookies as $cookie) {
4445 if (! is_array($cookie)) {
4448 $this->debug("check cookie for validity: ".$cookie['name'].'='.$cookie['value']);
4449 if ((isset($cookie['expires'])) && (! empty($cookie['expires']))) {
4450 if (strtotime($cookie['expires']) <= time()) {
4451 $this->debug('cookie has expired');
4455 if ((isset($cookie['domain'])) && (! empty($cookie['domain']))) {
4456 $domain = preg_quote($cookie['domain']);
4457 if (! preg_match("'.*$domain$'i", $this->host)) {
4458 $this->debug('cookie has different domain');
4462 if ((isset($cookie['path'])) && (! empty($cookie['path']))) {
4463 $path = preg_quote($cookie['path']);
4464 if (! preg_match("'^$path.*'i", $this->path)) {
4465 $this->debug('cookie is for a different path');
4469 if ((! $secure) && (isset($cookie['secure'])) && ($cookie['secure'])) {
4470 $this->debug('cookie is secure, transport is not');
4473 $cookie_str .= $cookie['name'] . '=' . $cookie['value'] . '; ';
4474 $this->debug('add cookie to Cookie-String: ' . $cookie['name'] . '=' . $cookie['value']);
4485 Modification information for LGPL compliance
4487 r58622 - 2010-10-22 18:18:59 -0700 (Fri, 22 Oct 2010) - engsvnbuild - Author: lam <lam@198.18.142.201>
4490 r58361 - 2010-09-29 16:59:02 -0700 (Wed, 29 Sep 2010) - kjing - Author: Jenny Gonsalves <jenny@sugarcrm.com>
4491 Merging with maint_6_0_1 (svn merge -r 58250:58342)
4493 r57813 - 2010-08-19 10:34:44 -0700 (Thu, 19 Aug 2010) - kjing - Author: John Mertic <jmertic@sugarcrm.com>
4494 Bug 39085 - When loading the opposite search panel via ajax on the ListViews, call the index action instead of the ListView action to avoid touching pre-MVC code by accident.
4496 r57707 - 2010-08-10 12:26:13 -0700 (Tue, 10 Aug 2010) - kjing - Author: Stanislav Malyshev <smalyshev@gmail.com>
4497 fix SOAP calls with no parameters
4499 r56990 - 2010-06-16 13:05:36 -0700 (Wed, 16 Jun 2010) - kjing - snapshot "Mango" svn branch to a new one for GitHub sync
4501 r56989 - 2010-06-16 13:01:33 -0700 (Wed, 16 Jun 2010) - kjing - defunt "Mango" svn dev branch before github cutover
4503 r55980 - 2010-04-19 13:31:28 -0700 (Mon, 19 Apr 2010) - kjing - create Mango (6.1) based on windex
4505 r51719 - 2009-10-22 10:18:00 -0700 (Thu, 22 Oct 2009) - mitani - Converted to Build 3 tags and updated the build system
4507 r51634 - 2009-10-19 13:32:22 -0700 (Mon, 19 Oct 2009) - mitani - Windex is the branch for Sugar Sales 1.0 development
4509 r51508 - 2009-10-14 07:40:23 -0700 (Wed, 14 Oct 2009) - jmertic - More fallout fixes from the PHP 5.3 ereg to preg changes.
4511 r51455 - 2009-10-13 07:56:48 -0700 (Tue, 13 Oct 2009) - jmertic - Bug 33202 - Enable install of SugarCRM on PHP 5.3.0, asserting that the minimum supported version is PHP 5.2.x.
4513 r51443 - 2009-10-12 13:34:36 -0700 (Mon, 12 Oct 2009) - jmertic - Bug 33332 - Made application PHP 5.3 compliant with E_DEPRECATED warnings on by:
4514 - Changing all ereg function to either preg or simple string based ones
4515 - No more references to magic quotes.
4516 - Change all the session_unregister() functions to just unset() the correct session variable instead.
4518 r50375 - 2009-08-24 18:07:43 -0700 (Mon, 24 Aug 2009) - dwong - branch kobe2 from tokyo r50372
4520 r45763 - 2009-04-01 12:16:18 -0700 (Wed, 01 Apr 2009) - majed - Removed half of the require_once and include_onces in the product that were redundant or could be handled easily by the auto loader
4522 r45680 - 2009-03-30 14:34:35 -0700 (Mon, 30 Mar 2009) - Samir Gandhi - modifeid serializeSchema to generate WS-I compliant WSDL
4524 r42807 - 2008-12-29 11:16:59 -0800 (Mon, 29 Dec 2008) - dwong - Branch from trunk/sugarcrm r42806 to branches/tokyo/sugarcrm
4526 r42645 - 2008-12-18 13:41:08 -0800 (Thu, 18 Dec 2008) - awu - merging maint_5_2_0 rev41336:HEAD to trunk
4528 r41647 - 2008-11-11 17:44:30 -0800 (Tue, 11 Nov 2008) - majed - Fixes a few bugs
4530 r41596 - 2008-11-10 19:20:04 -0800 (Mon, 10 Nov 2008) - Samir Gandhi - modified to set $method in the code
4532 r41558 - 2008-11-10 14:35:34 -0800 (Mon, 10 Nov 2008) - majed - changes nusoap to allow for registering classes
4534 r39619 - 2008-09-09 13:41:34 -0700 (Tue, 09 Sep 2008) - jmertic - Bug 24827 - Remove all instances where we return a new object and assign it by reference, since this is deprecated in PHP 5 and emits E_DEPRECATED errors in PHP 5.3.
4536 - data/SugarBean.php
4537 - include/domit/php_http_client_generic.php
4538 - include/domit/php_http_connector.php
4539 - include/domit/testing_domit.php
4540 - include/domit/xml_domit_getelementsbypath.php
4541 - include/domit/xml_domit_lite_parser.php
4542 - include/domit/xml_domit_nodemaps.php
4543 - include/domit/xml_domit_parser.php
4544 - include/domit/xml_domit_shared.php
4545 - include/generic/SugarWidgets/SugarWidgetField.php
4546 - include/generic/SugarWidgets/SugarWidgetReportField.php
4547 - include/ListView/ProcessView.php
4548 - include/nusoap/class.soapclient.php
4549 - include/nusoap/nusoap.php
4550 - include/nusoap/nusoapmime.php
4551 - include/Pear/HTML_Safe/Safe.php
4552 - include/Pear/XML_HTMLSax3/HTMLSax3.php
4553 - modules/Administration/RebuildWorkFlow.php
4554 - modules/Expressions/RelateSelector.php
4555 - modules/Reports/templates/templates_reports.php
4556 - modules/WorkFlow/Delete.php
4557 - modules/WorkFlow/Save.php
4558 - modules/WorkFlow/SaveSequence.php
4559 - modules/WorkFlow/WorkFlow.php
4560 - modules/WorkFlowActionShells/CreateStep1.php
4561 - modules/WorkFlowActionShells/CreateStep2.php
4562 - modules/WorkFlowActionShells/Save.php
4563 - modules/WorkFlowActionShells/WorkFlowActionShell.php
4564 - modules/WorkFlowAlerts/Save.php
4565 - modules/WorkFlowAlerts/WorkFlowAlert.php
4566 - modules/WorkFlowAlertShells/DetailView.php
4567 - modules/WorkFlowAlertShells/WorkFlowAlertShell.php
4568 - modules/WorkFlowTriggerShells/CreateStep1.php
4569 - modules/WorkFlowTriggerShells/CreateStepFilter.php
4570 - modules/WorkFlowTriggerShells/SaveFilter.php
4571 - modules/WorkFlowTriggerShells/WorkFlowTriggerShell.php
4572 - soap/SoapHelperFunctions.php
4573 - test/modules/DynamicFields/DynamicFields_Bug24095_test.php
4574 - test/simpletest/browser.php
4575 - test/simpletest/default_reporter.php
4576 - test/simpletest/detached.php
4577 - test/simpletest/eclipse.php
4578 - test/simpletest/expectation.php
4579 - test/simpletest/extensions/pear_test_case.php
4580 - test/simpletest/form.php
4581 - test/simpletest/http.php
4582 - test/simpletest/mock_objects.php
4583 - test/simpletest/page.php
4584 - test/simpletest/parser.php
4585 - test/simpletest/remote.php
4586 - test/simpletest/shell_tester.php
4587 - test/simpletest/simple_test.php
4588 - test/simpletest/simpletest.php
4589 - test/simpletest/test/acceptance_test.php
4590 - test/simpletest/test/adapter_test.php
4591 - test/simpletest/test/authentication_test.php
4592 - test/simpletest/test/browser_test.php
4593 - test/simpletest/test/collector_test.php
4594 - test/simpletest/test/compatibility_test.php
4595 - test/simpletest/test/detached_test.php
4596 - test/simpletest/test/eclipse_test.php
4597 - test/simpletest/test/encoding_test.php
4598 - test/simpletest/test/errors_test.php
4599 - test/simpletest/test/expectation_test.php
4600 - test/simpletest/test/form_test.php
4601 - test/simpletest/test/frames_test.php
4602 - test/simpletest/test/http_test.php
4603 - test/simpletest/test/live_test.php
4604 - test/simpletest/test/mock_objects_test.php
4605 - test/simpletest/test/page_test.php
4606 - test/simpletest/test/parse_error_test.php
4607 - test/simpletest/test/parser_test.php
4608 - test/simpletest/test/remote_test.php
4609 - test/simpletest/test/shell_test.php
4610 - test/simpletest/test/shell_tester_test.php
4611 - test/simpletest/test/simpletest_test.php
4612 - test/simpletest/test/site/page_request.php
4613 - test/simpletest/test/tag_test.php
4614 - test/simpletest/test/unit_tester_test.php
4615 - test/simpletest/test/user_agent_test.php
4616 - test/simpletest/test/visual_test.php
4617 - test/simpletest/test/xml_test.php
4618 - test/simpletest/test_case.php
4619 - test/simpletest/ui/array_reporter/test.php
4620 - test/simpletest/ui/recorder/test.php
4621 - test/simpletest/unit_tester.php
4622 - test/simpletest/url.php
4623 - test/simpletest/user_agent.php
4624 - test/simpletest/web_tester.php
4625 - test/spikephpcoverage/src/PEAR.php
4626 - test/spikephpcoverage/src/util/Utility.php
4627 - test/spikephpcoverage/src/XML/Parser.php
4628 - test/spikephpcoverage/src/XML/Parser/Simple.php
4629 - test/test_utilities/SugarTest_SimpleBrowser.php
4631 r38362 - 2008-07-28 14:06:59 -0700 (Mon, 28 Jul 2008) - roger - bug: 23897. Using print_r when using the debug statement in nusoap will print out the statements to the screen if the call is coming from the UI.
4633 r38300 - 2008-07-25 13:33:43 -0700 (Fri, 25 Jul 2008) - Samir Gandhi - put the debug in parseresponse function
4635 r38293 - 2008-07-25 12:32:34 -0700 (Fri, 25 Jul 2008) - Samir Gandhi - to put all the debug statements return value in the call function
4637 r36824 - 2008-06-18 09:26:11 -0700 (Wed, 18 Jun 2008) - roger - bug: 21832
4639 r26422 - 2007-09-05 17:29:12 -0700 (Wed, 05 Sep 2007) - majed - migrate from beta 1 to trunk
4641 r15787 - 2006-08-10 10:14:41 -0700 (Thu, 10 Aug 2006) - roger - RRS: bug 7961
4643 r14701 - 2006-07-17 13:37:26 -0700 (Mon, 17 Jul 2006) - roger - RRS: bug 5801
4645 r13782 - 2006-06-06 10:58:55 -0700 (Tue, 06 Jun 2006) - majed - changes entry point code
4647 r11466 - 2006-02-01 15:49:47 -0800 (Wed, 01 Feb 2006) - jacob - Adding extra !empty check to get around a PHP warning.
4649 r11115 - 2006-01-17 14:54:45 -0800 (Tue, 17 Jan 2006) - majed - add entry point validation
4651 r10585 - 2005-12-13 14:42:26 -0800 (Tue, 13 Dec 2005) - majed - adds new license mechanisim
4653 r10170 - 2005-12-05 18:37:46 -0800 (Mon, 05 Dec 2005) - majed - fixes various issues
4655 r8999 - 2005-11-04 05:26:49 -0800 (Fri, 04 Nov 2005) - roger - When nusoap was upgraded we had an issue with the user's default language not being populated during a soap request. I determined the reason this was happening and have checked in the corresponding change to nusoap.
4657 r8991 - 2005-11-03 19:07:25 -0800 (Thu, 03 Nov 2005) - majed - fixes nusoap issue
4659 r8846 - 2005-10-31 11:01:12 -0800 (Mon, 31 Oct 2005) - majed - new version of nusoap
4661 r7905 - 2005-09-21 19:12:57 -0700 (Wed, 21 Sep 2005) - majed - restores old nusoap pre & with a few fixes
4663 r7861 - 2005-09-20 15:40:25 -0700 (Tue, 20 Sep 2005) - majed - & fix for 3.5.1
4665 r7452 - 2005-08-17 11:32:34 -0700 (Wed, 17 Aug 2005) - majed - changes soap to nusoap
4667 r5820 - 2005-06-21 14:22:24 -0700 (Tue, 21 Jun 2005) - majed - fixes issues with nusoap and with custom fields
4669 r5462 - 2005-05-25 13:50:11 -0700 (Wed, 25 May 2005) - majed - upgraded nusoap to .6.9
4671 r5104 - 2005-05-04 15:33:41 -0700 (Wed, 04 May 2005) - majed - gets rid of HTTP_GET_VARS and what not which has been deprecated
4673 r573 - 2004-09-04 13:03:32 -0700 (Sat, 04 Sep 2004) - sugarclint - undoing copyrights added in inadvertantly. --clint
4675 r546 - 2004-09-03 11:49:38 -0700 (Fri, 03 Sep 2004) - sugarmsi - removed echo count
4677 r354 - 2004-08-02 23:00:37 -0700 (Mon, 02 Aug 2004) - sugarjacob - Adding Soap
4688 * nusoap_server allows the user to create a SOAP server
4689 * that is capable of receiving messages and returning responses
4691 * @author Dietrich Ayala <dietrich@ganx4.com>
4692 * @author Scott Nichol <snichol@users.sourceforge.net>
4696 class nusoap_server extends nusoap_base {
4698 * HTTP headers of request
4702 var $headers = array();
4710 * SOAP headers from request (incomplete namespace resolution; special characters not escaped) (text)
4714 var $requestHeaders = '';
4716 * SOAP Headers from request (parsed)
4720 var $requestHeader = NULL;
4722 * SOAP body request portion (incomplete namespace resolution; special characters not escaped) (text)
4728 * SOAP payload for request (text)
4732 var $requestSOAP = '';
4734 * requested method namespace URI
4738 var $methodURI = '';
4740 * name of method requested
4744 var $methodname = '';
4746 * method parameters from request
4750 var $methodparams = array();
4752 * SOAP Action from request
4756 var $SOAPAction = '';
4758 * character set encoding of incoming (request) messages
4762 var $xml_encoding = '';
4764 * toggles whether the parser decodes element content w/ utf8_decode()
4768 var $decode_utf8 = false;
4771 * HTTP headers of response
4775 var $outgoing_headers = array();
4783 * SOAP headers for response (text or array of soapval or associative array)
4787 var $responseHeaders = '';
4789 * SOAP payload for response (text)
4793 var $responseSOAP = '';
4795 * method return value to place in response
4799 var $methodreturn = false;
4801 * whether $methodreturn is a string of literal XML
4805 var $methodreturnisliteralxml = false;
4807 * SOAP fault for response (or false)
4813 * text indication of result (for debugging)
4817 var $result = 'successful';
4820 * assoc array of operations => opData; operations are added by the register()
4821 * method or by parsing an external WSDL definition
4825 var $operations = array();
4827 * wsdl instance (if one)
4833 * URL for WSDL (if one)
4837 var $externalWSDLURL = false;
4839 * whether to append debug to response as XML comment
4843 var $debug_flag = false;
4848 * the optional parameter is a path to a WSDL file that you'd like to bind the server instance to.
4850 * @param mixed $wsdl file path or URL (string), or wsdl instance (object)
4853 function nusoap_server($wsdl=false){
4854 parent::nusoap_base();
4855 // turn on debugging?
4857 global $HTTP_SERVER_VARS;
4859 if (isset($_SERVER)) {
4860 $this->debug("_SERVER is defined:");
4861 $this->appendDebug($this->varDump($_SERVER));
4862 } elseif (isset($HTTP_SERVER_VARS)) {
4863 $this->debug("HTTP_SERVER_VARS is defined:");
4864 $this->appendDebug($this->varDump($HTTP_SERVER_VARS));
4866 $this->debug("Neither _SERVER nor HTTP_SERVER_VARS is defined.");
4869 if (isset($debug)) {
4870 $this->debug("In nusoap_server, set debug_flag=$debug based on global flag");
4871 $this->debug_flag = $debug;
4872 } elseif (isset($_SERVER['QUERY_STRING'])) {
4873 $qs = explode('&', $_SERVER['QUERY_STRING']);
4874 foreach ($qs as $v) {
4875 if (substr($v, 0, 6) == 'debug=') {
4876 $this->debug("In nusoap_server, set debug_flag=" . substr($v, 6) . " based on query string #1");
4877 $this->debug_flag = substr($v, 6);
4880 } elseif (isset($HTTP_SERVER_VARS['QUERY_STRING'])) {
4881 $qs = explode('&', $HTTP_SERVER_VARS['QUERY_STRING']);
4882 foreach ($qs as $v) {
4883 if (substr($v, 0, 6) == 'debug=') {
4884 $this->debug("In nusoap_server, set debug_flag=" . substr($v, 6) . " based on query string #2");
4885 $this->debug_flag = substr($v, 6);
4892 $this->debug("In nusoap_server, WSDL is specified");
4893 if (is_object($wsdl) && (get_class($wsdl) == 'wsdl')) {
4894 $this->wsdl = $wsdl;
4895 $this->externalWSDLURL = $this->wsdl->wsdl;
4896 $this->debug('Use existing wsdl instance from ' . $this->externalWSDLURL);
4898 $this->debug('Create wsdl from ' . $wsdl);
4899 $this->wsdl = new wsdl($wsdl);
4900 $this->externalWSDLURL = $wsdl;
4902 $this->appendDebug($this->wsdl->getDebug());
4903 $this->wsdl->clearDebug();
4904 if($err = $this->wsdl->getError()){
4905 die('WSDL ERROR: '.$err);
4911 * processes request and returns response
4913 * @param string $data usually is the value of $HTTP_RAW_POST_DATA
4916 function service($data){
4917 global $HTTP_SERVER_VARS;
4919 if (isset($_SERVER['REQUEST_METHOD'])) {
4920 $rm = $_SERVER['REQUEST_METHOD'];
4921 } elseif (isset($HTTP_SERVER_VARS['REQUEST_METHOD'])) {
4922 $rm = $HTTP_SERVER_VARS['REQUEST_METHOD'];
4927 if (isset($_SERVER['QUERY_STRING'])) {
4928 $qs = $_SERVER['QUERY_STRING'];
4929 } elseif (isset($HTTP_SERVER_VARS['QUERY_STRING'])) {
4930 $qs = $HTTP_SERVER_VARS['QUERY_STRING'];
4934 $this->debug("In service, request method=$rm query string=$qs strlen(\$data)=" . strlen($data));
4936 if ($rm == 'POST') {
4937 $this->debug("In service, invoke the request");
4938 $this->parse_request($data);
4939 if (! $this->fault) {
4940 $this->invoke_method();
4942 if (! $this->fault) {
4943 $this->serialize_return();
4945 $this->send_response();
4946 } elseif (preg_match('/wsdl/', $qs) ){
4947 $this->debug("In service, this is a request for WSDL");
4948 if ($this->externalWSDLURL){
4949 if (strpos($this->externalWSDLURL, "http://") !== false) { // assume URL
4950 $this->debug("In service, re-direct for WSDL");
4951 header('Location: '.$this->externalWSDLURL);
4952 } else { // assume file
4953 $this->debug("In service, use file passthru for WSDL");
4954 header("Content-Type: text/xml\r\n");
4955 $pos = strpos($this->externalWSDLURL, "file://");
4956 if ($pos === false) {
4957 $filename = $this->externalWSDLURL;
4959 $filename = substr($this->externalWSDLURL, $pos + 7);
4961 $fp = fopen($this->externalWSDLURL, 'r');
4964 } elseif ($this->wsdl) {
4965 $this->debug("In service, serialize WSDL");
4966 header("Content-Type: text/xml; charset=ISO-8859-1\r\n");
4967 print $this->wsdl->serialize($this->debug_flag);
4968 if ($this->debug_flag) {
4969 $this->debug('wsdl:');
4970 $this->appendDebug($this->varDump($this->wsdl));
4971 print $this->getDebugAsXMLComment();
4974 $this->debug("In service, there is no WSDL");
4975 header("Content-Type: text/html; charset=ISO-8859-1\r\n");
4976 print "This service does not provide WSDL";
4978 } elseif ($this->wsdl) {
4979 $this->debug("In service, return Web description");
4980 print $this->wsdl->webDescription();
4982 $this->debug("In service, no Web description");
4983 header("Content-Type: text/html; charset=ISO-8859-1\r\n");
4984 print "This service does not provide a Web description";
4989 * parses HTTP request headers.
4991 * The following fields are set by this function (when successful)
5000 function parse_http_headers() {
5001 global $HTTP_SERVER_VARS;
5003 $this->request = '';
5004 $this->SOAPAction = '';
5005 if(function_exists('getallheaders')){
5006 $this->debug("In parse_http_headers, use getallheaders");
5007 $headers = getallheaders();
5008 foreach($headers as $k=>$v){
5009 $k = strtolower($k);
5010 $this->headers[$k] = $v;
5011 $this->request .= "$k: $v\r\n";
5012 $this->debug("$k: $v");
5014 // get SOAPAction header
5015 if(isset($this->headers['soapaction'])){
5016 $this->SOAPAction = str_replace('"','',$this->headers['soapaction']);
5018 // get the character encoding of the incoming request
5019 if(isset($this->headers['content-type']) && strpos($this->headers['content-type'],'=')){
5020 $enc = str_replace('"','',substr(strstr($this->headers["content-type"],'='),1));
5021 if(preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i',$enc)){
5022 $this->xml_encoding = strtoupper($enc);
5024 $this->xml_encoding = 'US-ASCII';
5027 // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
5028 $this->xml_encoding = 'ISO-8859-1';
5030 } elseif(isset($_SERVER) && is_array($_SERVER)){
5031 $this->debug("In parse_http_headers, use _SERVER");
5032 foreach ($_SERVER as $k => $v) {
5033 if (substr($k, 0, 5) == 'HTTP_') {
5034 $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', substr($k, 5))));
5036 $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', $k)));
5038 if ($k == 'soapaction') {
5039 // get SOAPAction header
5041 $v = str_replace('"', '', $v);
5042 $v = str_replace('\\', '', $v);
5043 $this->SOAPAction = $v;
5044 } else if ($k == 'content-type') {
5045 // get the character encoding of the incoming request
5046 if (strpos($v, '=')) {
5047 $enc = substr(strstr($v, '='), 1);
5048 $enc = str_replace('"', '', $enc);
5049 $enc = str_replace('\\', '', $enc);
5050 if (preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i',$enc)) {
5051 $this->xml_encoding = strtoupper($enc);
5053 $this->xml_encoding = 'US-ASCII';
5056 // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
5057 $this->xml_encoding = 'ISO-8859-1';
5060 $this->headers[$k] = $v;
5061 $this->request .= "$k: $v\r\n";
5062 $this->debug("$k: $v");
5064 } elseif (is_array($HTTP_SERVER_VARS)) {
5065 $this->debug("In parse_http_headers, use HTTP_SERVER_VARS");
5066 foreach ($HTTP_SERVER_VARS as $k => $v) {
5067 if (substr($k, 0, 5) == 'HTTP_') {
5068 $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', substr($k, 5)))); $k = strtolower(substr($k, 5));
5070 $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', $k))); $k = strtolower($k);
5072 if ($k == 'soapaction') {
5073 // get SOAPAction header
5075 $v = str_replace('"', '', $v);
5076 $v = str_replace('\\', '', $v);
5077 $this->SOAPAction = $v;
5078 } else if ($k == 'content-type') {
5079 // get the character encoding of the incoming request
5080 if (strpos($v, '=')) {
5081 $enc = substr(strstr($v, '='), 1);
5082 $enc = str_replace('"', '', $enc);
5083 $enc = str_replace('\\', '', $enc);
5084 if (preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i',$enc)) {
5085 $this->xml_encoding = strtoupper($enc);
5087 $this->xml_encoding = 'US-ASCII';
5090 // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
5091 $this->xml_encoding = 'ISO-8859-1';
5094 $this->headers[$k] = $v;
5095 $this->request .= "$k: $v\r\n";
5096 $this->debug("$k: $v");
5099 $this->debug("In parse_http_headers, HTTP headers not accessible");
5100 $this->setError("HTTP headers not accessible");
5107 * The following fields are set by this function (when successful)
5121 * This sets the fault field on error
5123 * @param string $data XML string
5126 function parse_request($data='') {
5127 $this->debug('entering parse_request()');
5128 $this->parse_http_headers();
5129 $this->debug('got character encoding: '.$this->xml_encoding);
5130 // uncompress if necessary
5131 if (isset($this->headers['content-encoding']) && $this->headers['content-encoding'] != '') {
5132 $this->debug('got content encoding: ' . $this->headers['content-encoding']);
5133 if ($this->headers['content-encoding'] == 'deflate' || $this->headers['content-encoding'] == 'gzip') {
5134 // if decoding works, use it. else assume data wasn't gzencoded
5135 if (function_exists('gzuncompress')) {
5136 if ($this->headers['content-encoding'] == 'deflate' && $degzdata = @gzuncompress($data)) {
5138 } elseif ($this->headers['content-encoding'] == 'gzip' && $degzdata = gzinflate(substr($data, 10))) {
5141 $this->fault('SOAP-ENV:Client', 'Errors occurred when trying to decode the data');
5145 $this->fault('SOAP-ENV:Client', 'This Server does not support compressed data');
5150 $this->request .= "\r\n".$data;
5151 $data = $this->parseRequest($this->headers, $data);
5152 $this->requestSOAP = $data;
5153 $this->debug('leaving parse_request');
5156 function register_class($classname){
5157 $this->registeredClass = $classname;
5160 * invokes a PHP function for the requested SOAP method
5162 * The following fields are set by this function (when successful)
5166 * Note that the PHP function that is called may also set the following
5167 * fields to affect the response sent to the client
5172 * This sets the fault field on error
5176 function invoke_method() {
5177 $this->debug('in invoke_method, methodname=' . $this->methodname . ' methodURI=' . $this->methodURI . ' SOAPAction=' . $this->SOAPAction);
5180 // if you are debugging in this area of the code, your service uses a class to implement methods,
5181 // you use SOAP RPC, and the client is .NET, please be aware of the following...
5182 // when the .NET wsdl.exe utility generates a proxy, it will remove the '.' or '..' from the
5183 // method name. that is fine for naming the .NET methods. it is not fine for properly constructing
5184 // the XML request and reading the XML response. you need to add the RequestElementName and
5185 // ResponseElementName to the System.Web.Services.Protocols.SoapRpcMethodAttribute that wsdl.exe
5186 // generates for the method. these parameters are used to specify the correct XML element names
5187 // for .NET to use, i.e. the names with the '.' in them.
5189 $orig_methodname = $this->methodname;
5191 if ($this->opData = $this->wsdl->getOperationData($this->methodname)) {
5192 $this->debug('in invoke_method, found WSDL operation=' . $this->methodname);
5193 $this->appendDebug('opData=' . $this->varDump($this->opData));
5194 } elseif ($this->opData = $this->wsdl->getOperationDataForSoapAction($this->SOAPAction)) {
5195 // Note: hopefully this case will only be used for doc/lit, since rpc services should have wrapper element
5196 $this->debug('in invoke_method, found WSDL soapAction=' . $this->SOAPAction . ' for operation=' . $this->opData['name']);
5197 $this->appendDebug('opData=' . $this->varDump($this->opData));
5198 $this->methodname = $this->opData['name'];
5200 $this->debug('in invoke_method, no WSDL for operation=' . $this->methodname);
5201 $this->fault('SOAP-ENV:Client', "Operation '" . $this->methodname . "' is not defined in the WSDL for this service");
5205 $this->debug('in invoke_method, no WSDL to validate method');
5208 // if a . is present in $this->methodname, we see if there is a class in scope,
5209 // which could be referred to. We will also distinguish between two deliminators,
5210 // to allow methods to be called a the class or an instance
5211 if (strpos($this->methodname, '..') > 0) {
5213 } else if (strpos($this->methodname, '.') > 0) {
5218 $this->debug("in invoke_method, delim=$delim");
5222 if (strlen($delim) > 0 && substr_count($this->methodname, $delim) == 1) {
5223 $try_class = substr($this->methodname, 0, strpos($this->methodname, $delim));
5224 if (class_exists($try_class)) {
5225 // get the class and method name
5226 $class = $try_class;
5227 $method = substr($this->methodname, strpos($this->methodname, $delim) + strlen($delim));
5228 $this->debug("in invoke_method, class=$class method=$method delim=$delim");
5230 $this->debug("in invoke_method, class=$try_class not found");
5234 $this->debug("in invoke_method, no class to try");
5236 if(empty($delim) && isset($this->registeredClass)){
5237 $class = $this->registeredClass;
5239 $method = $this->methodname;
5242 // does method exist?
5244 if (!function_exists($this->methodname)) {
5245 $this->debug("in invoke_method, function '$this->methodname' not found!");
5246 $this->result = 'fault: method not found';
5247 $this->fault('SOAP-ENV:Client',"method '$this->methodname'('$orig_methodname') not defined in service('$try_class' '$delim')");
5251 $method_to_compare = (substr(phpversion(), 0, 2) == '4.') ? strtolower($method) : $method;
5252 if (!in_array($method_to_compare, get_class_methods($class))) {
5253 $this->debug("in invoke_method, method '$this->methodname' not found in class '$class'!");
5254 $this->result = 'fault: method not found';
5255 $this->fault('SOAP-ENV:Client',"method '$this->methodname'/'$method_to_compare'('$orig_methodname') not defined in service/'$class'('$try_class' '$delim')");
5260 // evaluate message, getting back parameters
5261 // verify that request parameters match the method's signature
5262 if(! $this->verify_method($this->methodname,$this->methodparams)){
5264 $this->debug('ERROR: request not verified against method signature');
5265 $this->result = 'fault: request failed validation against method signature';
5267 $this->fault('SOAP-ENV:Client',"Operation '$this->methodname' not defined in service.");
5271 // if there are parameters to pass
5272 $this->debug('in invoke_method, params:');
5273 $this->appendDebug($this->varDump($this->methodparams));
5274 $this->debug("in invoke_method, calling '$this->methodname'");
5275 if (!function_exists('call_user_func_array')) {
5277 $this->debug('in invoke_method, calling function using eval()');
5278 $funcCall = "\$this->methodreturn = $this->methodname(";
5280 if ($delim == '..') {
5281 $this->debug('in invoke_method, calling class method using eval()');
5282 $funcCall = "\$this->methodreturn = ".$class."::".$method."(";
5284 $this->debug('in invoke_method, calling instance method using eval()');
5285 // generate unique instance name
5286 $instname = "\$inst_".time();
5287 $funcCall = $instname." = new ".$class."(); ";
5288 $funcCall .= "\$this->methodreturn = ".$instname."->".$method."(";
5291 if ($this->methodparams) {
5292 foreach ($this->methodparams as $param) {
5293 if (is_array($param) || is_object($param)) {
5294 $this->fault('SOAP-ENV:Client', 'NuSOAP does not handle complexType parameters correctly when using eval; call_user_func_array must be available');
5297 $funcCall .= "\"$param\",";
5299 $funcCall = substr($funcCall, 0, -1);
5302 $this->debug('in invoke_method, function call: '.$funcCall);
5306 $this->debug('in invoke_method, calling function using call_user_func_array()');
5307 $call_arg = "$this->methodname"; // straight assignment changes $this->methodname to lower case after call_user_func_array()
5308 } elseif ($delim == '..') {
5309 $this->debug('in invoke_method, calling class method using call_user_func_array()');
5310 $call_arg = array ($class, $method);
5312 $this->debug('in invoke_method, calling instance method using call_user_func_array()');
5313 $instance = new $class ();
5314 $call_arg = array(&$instance, $method);
5316 if (is_array($this->methodparams)) {
5317 $this->methodreturn = call_user_func_array($call_arg, array_values($this->methodparams));
5319 $this->methodreturn = call_user_func_array($call_arg, array());
5322 $this->debug('in invoke_method, methodreturn:');
5323 $this->appendDebug($this->varDump($this->methodreturn));
5324 $this->debug("in invoke_method, called method $this->methodname, received data of type ".gettype($this->methodreturn));
5328 * serializes the return value from a PHP function into a full SOAP Envelope
5330 * The following fields are set by this function (when successful)
5334 * This sets the fault field on error
5338 function serialize_return() {
5339 $this->debug('Entering serialize_return methodname: ' . $this->methodname . ' methodURI: ' . $this->methodURI);
5341 if (isset($this->methodreturn) && is_object($this->methodreturn) && ((get_class($this->methodreturn) == 'soap_fault') || (get_class($this->methodreturn) == 'nusoap_fault'))) {
5342 $this->debug('got a fault object from method');
5343 $this->fault = $this->methodreturn;
5345 } elseif ($this->methodreturnisliteralxml) {
5346 $return_val = $this->methodreturn;
5347 // returned value(s)
5349 $this->debug('got a(n) '.gettype($this->methodreturn).' from method');
5350 $this->debug('serializing return value');
5352 if (sizeof($this->opData['output']['parts']) > 1) {
5353 $this->debug('more than one output part, so use the method return unchanged');
5354 $opParams = $this->methodreturn;
5355 } elseif (sizeof($this->opData['output']['parts']) == 1) {
5356 $this->debug('exactly one output part, so wrap the method return in a simple array');
5357 // TODO: verify that it is not already wrapped!
5358 //foreach ($this->opData['output']['parts'] as $name => $type) {
5359 // $this->debug('wrap in element named ' . $name);
5361 $opParams = array($this->methodreturn);
5363 $return_val = $this->wsdl->serializeRPCParameters($this->methodname,'output',$opParams);
5364 $this->appendDebug($this->wsdl->getDebug());
5365 $this->wsdl->clearDebug();
5366 if($errstr = $this->wsdl->getError()){
5367 $this->debug('got wsdl error: '.$errstr);
5368 $this->fault('SOAP-ENV:Server', 'unable to serialize result');
5372 if (isset($this->methodreturn)) {
5373 $return_val = $this->serialize_val($this->methodreturn, 'return');
5376 $this->debug('in absence of WSDL, assume void return for backward compatibility');
5380 $this->debug('return value:');
5381 $this->appendDebug($this->varDump($return_val));
5383 $this->debug('serializing response');
5385 $this->debug('have WSDL for serialization: style is ' . $this->opData['style']);
5386 if ($this->opData['style'] == 'rpc') {
5387 $this->debug('style is rpc for serialization: use is ' . $this->opData['output']['use']);
5388 if ($this->opData['output']['use'] == 'literal') {
5389 // 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
5390 if ($this->methodURI) {
5391 $payload = '<ns1:'.$this->methodname.'Response xmlns:ns1="'.$this->methodURI.'">'.$return_val.'</ns1:'.$this->methodname."Response>";
5393 $payload = '<'.$this->methodname.'Response>'.$return_val.'</'.$this->methodname.'Response>';
5396 if ($this->methodURI) {
5397 $payload = '<ns1:'.$this->methodname.'Response xmlns:ns1="'.$this->methodURI.'">'.$return_val.'</ns1:'.$this->methodname."Response>";
5399 $payload = '<'.$this->methodname.'Response>'.$return_val.'</'.$this->methodname.'Response>';
5403 $this->debug('style is not rpc for serialization: assume document');
5404 $payload = $return_val;
5407 $this->debug('do not have WSDL for serialization: assume rpc/encoded');
5408 $payload = '<ns1:'.$this->methodname.'Response xmlns:ns1="'.$this->methodURI.'">'.$return_val.'</ns1:'.$this->methodname."Response>";
5410 $this->result = 'successful';
5412 //if($this->debug_flag){
5413 $this->appendDebug($this->wsdl->getDebug());
5415 if (isset($this->opData['output']['encodingStyle'])) {
5416 $encodingStyle = $this->opData['output']['encodingStyle'];
5418 $encodingStyle = '';
5420 // Added: In case we use a WSDL, return a serialized env. WITH the usedNamespaces.
5421 $this->responseSOAP = $this->serializeEnvelope($payload,$this->responseHeaders,$this->wsdl->usedNamespaces,$this->opData['style'],$this->opData['output']['use'],$encodingStyle);
5423 $this->responseSOAP = $this->serializeEnvelope($payload,$this->responseHeaders);
5425 $this->debug("Leaving serialize_return");
5429 * sends an HTTP response
5431 * The following fields are set by this function (when successful)
5438 function send_response() {
5439 $this->debug('Enter send_response');
5441 $payload = $this->fault->serialize();
5442 $this->outgoing_headers[] = "HTTP/1.0 500 Internal Server Error";
5443 $this->outgoing_headers[] = "Status: 500 Internal Server Error";
5445 $payload = $this->responseSOAP;
5446 // Some combinations of PHP+Web server allow the Status
5447 // to come through as a header. Since OK is the default
5449 // $this->outgoing_headers[] = "HTTP/1.0 200 OK";
5450 // $this->outgoing_headers[] = "Status: 200 OK";
5452 // add debug data if in debug mode
5453 if(isset($this->debug_flag) && $this->debug_flag){
5454 $payload .= $this->getDebugAsXMLComment();
5456 $this->outgoing_headers[] = "Server: $this->title Server v$this->version";
5457 preg_match('/\$Revisio' . 'n: ([^ ]+)/', $this->revision, $rev);
5458 $this->outgoing_headers[] = "X-SOAP-Server: $this->title/$this->version (".$rev[1].")";
5459 // Let the Web server decide about this
5460 //$this->outgoing_headers[] = "Connection: Close\r\n";
5461 $payload = $this->getHTTPBody($payload);
5462 $type = $this->getHTTPContentType();
5463 $charset = $this->getHTTPContentTypeCharset();
5464 $this->outgoing_headers[] = "Content-Type: $type" . ($charset ? '; charset=' . $charset : '');
5465 //begin code to compress payload - by John
5466 // NOTE: there is no way to know whether the Web server will also compress
5468 if (strlen($payload) > 1024 && isset($this->headers) && isset($this->headers['accept-encoding'])) {
5469 if (strstr($this->headers['accept-encoding'], 'gzip')) {
5470 if (function_exists('gzencode')) {
5471 if (isset($this->debug_flag) && $this->debug_flag) {
5472 $payload .= "<!-- Content being gzipped -->";
5474 $this->outgoing_headers[] = "Content-Encoding: gzip";
5475 $payload = gzencode($payload);
5477 if (isset($this->debug_flag) && $this->debug_flag) {
5478 $payload .= "<!-- Content will not be gzipped: no gzencode -->";
5481 } elseif (strstr($this->headers['accept-encoding'], 'deflate')) {
5482 // Note: MSIE requires gzdeflate output (no Zlib header and checksum),
5483 // instead of gzcompress output,
5484 // which conflicts with HTTP 1.1 spec (http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.5)
5485 if (function_exists('gzdeflate')) {
5486 if (isset($this->debug_flag) && $this->debug_flag) {
5487 $payload .= "<!-- Content being deflated -->";
5489 $this->outgoing_headers[] = "Content-Encoding: deflate";
5490 $payload = gzdeflate($payload);
5492 if (isset($this->debug_flag) && $this->debug_flag) {
5493 $payload .= "<!-- Content will not be deflated: no gzcompress -->";
5501 $this->outgoing_headers[] = "Content-Length: ".strlen($payload);
5502 reset($this->outgoing_headers);
5503 foreach($this->outgoing_headers as $hdr){
5504 header($hdr, false);
5509 $this->response = join("\r\n",$this->outgoing_headers)."\r\n\r\n".$payload;
5513 * takes the value that was created by parsing the request
5514 * and compares to the method's signature, if available.
5516 * @param string $operation The operation to be invoked
5517 * @param array $request The array of parameter values
5518 * @return boolean Whether the operation was found
5521 function verify_method($operation,$request){
5522 if(isset($this->wsdl) && is_object($this->wsdl)){
5523 if($this->wsdl->getOperationData($operation)){
5526 } elseif(isset($this->operations[$operation])){
5533 * processes SOAP message received from client
5535 * @param array $headers The HTTP headers
5536 * @param string $data unprocessed request data from client
5537 * @return mixed value of the message, decoded into a PHP type
5540 function parseRequest($headers, $data) {
5541 $this->debug('Entering parseRequest() for data of length ' . strlen($data) . ' headers:');
5542 $this->appendDebug($this->varDump($headers));
5543 if (!isset($headers['content-type'])) {
5544 $this->setError('Request not of type text/xml (no content-type header)');
5547 if (!strstr($headers['content-type'], 'text/xml')) {
5548 $this->setError('Request not of type text/xml');
5551 if (strpos($headers['content-type'], '=')) {
5552 $enc = str_replace('"', '', substr(strstr($headers["content-type"], '='), 1));
5553 $this->debug('Got response encoding: ' . $enc);
5554 if(preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i',$enc)){
5555 $this->xml_encoding = strtoupper($enc);
5557 $this->xml_encoding = 'US-ASCII';
5560 // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
5561 $this->xml_encoding = 'ISO-8859-1';
5563 $this->debug('Use encoding: ' . $this->xml_encoding . ' when creating nusoap_parser');
5564 // parse response, get soap parser obj
5565 $parser = new nusoap_parser($data,$this->xml_encoding,'',$this->decode_utf8);
5567 $this->debug("parser debug: \n".$parser->getDebug());
5568 // if fault occurred during message parsing
5569 if($err = $parser->getError()){
5570 $this->result = 'fault: error in msg parsing: '.$err;
5571 $this->fault('SOAP-ENV:Client',"error in msg parsing:\n".$err);
5572 // else successfully parsed request into soapval object
5574 // get/set methodname
5575 $this->methodURI = $parser->root_struct_namespace;
5576 $this->methodname = $parser->root_struct_name;
5577 $this->debug('methodname: '.$this->methodname.' methodURI: '.$this->methodURI);
5578 $this->debug('calling parser->get_soapbody()');
5579 $this->methodparams = $parser->get_soapbody();
5581 $this->requestHeaders = $parser->getHeaders();
5583 $this->requestHeader = $parser->get_soapheader();
5584 // add document for doclit support
5585 $this->document = $parser->document;
5590 * gets the HTTP body for the current response.
5592 * @param string $soapmsg The SOAP payload
5593 * @return string The HTTP body, which includes the SOAP payload
5596 function getHTTPBody($soapmsg) {
5601 * gets the HTTP content type for the current response.
5603 * Note: getHTTPBody must be called before this.
5605 * @return string the HTTP content type for the current response.
5608 function getHTTPContentType() {
5613 * gets the HTTP content type charset for the current response.
5614 * returns false for non-text content types.
5616 * Note: getHTTPBody must be called before this.
5618 * @return string the HTTP content type charset for the current response.
5621 function getHTTPContentTypeCharset() {
5622 return $this->soap_defencoding;
5626 * add a method to the dispatch map (this has been replaced by the register method)
5628 * @param string $methodname
5629 * @param string $in array of input values
5630 * @param string $out array of output values
5634 function add_to_map($methodname,$in,$out){
5635 $this->operations[$methodname] = array('name' => $methodname,'in' => $in,'out' => $out);
5639 * register a service function with the server
5641 * @param string $name the name of the PHP function, class.method or class..method
5642 * @param array $in assoc array of input values: key = param name, value = param type
5643 * @param array $out assoc array of output values: key = param name, value = param type
5644 * @param mixed $namespace the element namespace for the method or false
5645 * @param mixed $soapaction the soapaction for the method or false
5646 * @param mixed $style optional (rpc|document) or false Note: when 'document' is specified, parameter and return wrappers are created for you automatically
5647 * @param mixed $use optional (encoded|literal) or false
5648 * @param string $documentation optional Description to include in WSDL
5649 * @param string $encodingStyle optional (usually 'http://schemas.xmlsoap.org/soap/encoding/' for encoded)
5652 function register($name,$in=array(),$out=array(),$namespace=false,$soapaction=false,$style=false,$use=false,$documentation='',$encodingStyle=''){
5653 global $HTTP_SERVER_VARS;
5655 if($this->externalWSDLURL){
5656 die('You cannot bind to an external WSDL file, and register methods outside of it! Please choose either WSDL or no WSDL.');
5659 die('You must specify a name when you register an operation');
5661 if (!is_array($in)) {
5662 die('You must provide an array for operation inputs');
5664 if (!is_array($out)) {
5665 die('You must provide an array for operation outputs');
5667 if(false == $namespace) {
5669 if(false == $soapaction) {
5670 if (isset($_SERVER)) {
5671 $SERVER_NAME = $_SERVER['SERVER_NAME'];
5672 $SCRIPT_NAME = isset($_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : $_SERVER['SCRIPT_NAME'];
5673 $HTTPS = isset($_SERVER['HTTPS']) ? $_SERVER['HTTPS'] : (isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off');
5674 } elseif (isset($HTTP_SERVER_VARS)) {
5675 $SERVER_NAME = $HTTP_SERVER_VARS['SERVER_NAME'];
5676 $SCRIPT_NAME = isset($HTTP_SERVER_VARS['PHP_SELF']) ? $HTTP_SERVER_VARS['PHP_SELF'] : $HTTP_SERVER_VARS['SCRIPT_NAME'];
5677 $HTTPS = isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off';
5679 $this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available");
5681 if ($HTTPS == '1' || $HTTPS == 'on') {
5686 $soapaction = "$SCHEME://$SERVER_NAME$SCRIPT_NAME/$name";
5688 if(false == $style) {
5694 if ($use == 'encoded' && $encodingStyle == '') {
5695 $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
5698 $this->operations[$name] = array(
5702 'namespace' => $namespace,
5703 'soapaction' => $soapaction,
5706 $this->wsdl->addOperation($name,$in,$out,$namespace,$soapaction,$style,$use,$documentation,$encodingStyle);
5712 * Specify a fault to be returned to the client.
5713 * This also acts as a flag to the server that a fault has occured.
5715 * @param string $faultcode
5716 * @param string $faultstring
5717 * @param string $faultactor
5718 * @param string $faultdetail
5721 function fault($faultcode,$faultstring,$faultactor='',$faultdetail=''){
5722 if ($faultdetail == '' && $this->debug_flag) {
5723 $faultdetail = $this->getDebug();
5725 $this->fault = new nusoap_fault($faultcode,$faultactor,$faultstring,$faultdetail);
5726 $this->fault->soap_defencoding = $this->soap_defencoding;
5730 * Sets up wsdl object.
5731 * Acts as a flag to enable internal WSDL generation
5733 * @param string $serviceName, name of the service
5734 * @param mixed $namespace optional 'tns' service namespace or false
5735 * @param mixed $endpoint optional URL of service endpoint or false
5736 * @param string $style optional (rpc|document) WSDL style (also specified by operation)
5737 * @param string $transport optional SOAP transport
5738 * @param mixed $schemaTargetNamespace optional 'types' targetNamespace for service schema or false
5740 function configureWSDL($serviceName,$namespace = false,$endpoint = false,$style='rpc', $transport = 'http://schemas.xmlsoap.org/soap/http', $schemaTargetNamespace = false)
5742 global $HTTP_SERVER_VARS;
5744 if (isset($_SERVER)) {
5745 $SERVER_NAME = $_SERVER['SERVER_NAME'];
5746 $SERVER_PORT = $_SERVER['SERVER_PORT'];
5747 $SCRIPT_NAME = isset($_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : $_SERVER['SCRIPT_NAME'];
5748 $HTTPS = isset($_SERVER['HTTPS']) ? $_SERVER['HTTPS'] : (isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off');
5749 } elseif (isset($HTTP_SERVER_VARS)) {
5750 $SERVER_NAME = $HTTP_SERVER_VARS['SERVER_NAME'];
5751 $SERVER_PORT = $HTTP_SERVER_VARS['SERVER_PORT'];
5752 $SCRIPT_NAME = isset($HTTP_SERVER_VARS['PHP_SELF']) ? $HTTP_SERVER_VARS['PHP_SELF'] : $HTTP_SERVER_VARS['SCRIPT_NAME'];
5753 $HTTPS = isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off';
5755 $this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available");
5757 // If server name has port number attached then strip it (else port number gets duplicated in WSDL output) (occurred using lighttpd and FastCGI)
5758 $colon = strpos($SERVER_NAME,":");
5760 $SERVER_NAME = substr($SERVER_NAME, 0, $colon);
5762 if ($SERVER_PORT == 80) {
5765 $SERVER_PORT = ':' . $SERVER_PORT;
5767 if(false == $namespace) {
5768 $namespace = "http://$SERVER_NAME/soap/$serviceName";
5771 if(false == $endpoint) {
5772 if ($HTTPS == '1' || $HTTPS == 'on') {
5777 $endpoint = "$SCHEME://$SERVER_NAME$SERVER_PORT$SCRIPT_NAME";
5780 if(false == $schemaTargetNamespace) {
5781 $schemaTargetNamespace = $namespace;
5784 $this->wsdl = new wsdl;
5785 $this->wsdl->serviceName = $serviceName;
5786 $this->wsdl->endpoint = $endpoint;
5787 $this->wsdl->namespaces['tns'] = $namespace;
5788 $this->wsdl->namespaces['soap'] = 'http://schemas.xmlsoap.org/wsdl/soap/';
5789 $this->wsdl->namespaces['wsdl'] = 'http://schemas.xmlsoap.org/wsdl/';
5790 if ($schemaTargetNamespace != $namespace) {
5791 $this->wsdl->namespaces['types'] = $schemaTargetNamespace;
5793 $this->wsdl->schemas[$schemaTargetNamespace][0] = new nusoap_xmlschema('', '', $this->wsdl->namespaces);
5794 if ($style == 'document') {
5795 $this->wsdl->schemas[$schemaTargetNamespace][0]->schemaInfo['elementFormDefault'] = 'qualified';
5797 $this->wsdl->schemas[$schemaTargetNamespace][0]->schemaTargetNamespace = $schemaTargetNamespace;
5798 $this->wsdl->schemas[$schemaTargetNamespace][0]->imports['http://schemas.xmlsoap.org/soap/encoding/'][0] = array('location' => '', 'loaded' => true);
5799 $this->wsdl->schemas[$schemaTargetNamespace][0]->imports['http://schemas.xmlsoap.org/wsdl/'][0] = array('location' => '', 'loaded' => true);
5800 $this->wsdl->bindings[$serviceName.'Binding'] = array(
5801 'name'=>$serviceName.'Binding',
5803 'transport'=>$transport,
5804 'portType'=>$serviceName.'PortType');
5805 $this->wsdl->ports[$serviceName.'Port'] = array(
5806 'binding'=>$serviceName.'Binding',
5807 'location'=>$endpoint,
5808 'bindingType'=>'http://schemas.xmlsoap.org/wsdl/soap/');
5813 * Backward compatibility
5815 class soap_server extends nusoap_server {
5822 Modification information for LGPL compliance
5824 r58622 - 2010-10-22 18:18:59 -0700 (Fri, 22 Oct 2010) - engsvnbuild - Author: lam <lam@198.18.142.201>
5827 r58361 - 2010-09-29 16:59:02 -0700 (Wed, 29 Sep 2010) - kjing - Author: Jenny Gonsalves <jenny@sugarcrm.com>
5828 Merging with maint_6_0_1 (svn merge -r 58250:58342)
5830 r57813 - 2010-08-19 10:34:44 -0700 (Thu, 19 Aug 2010) - kjing - Author: John Mertic <jmertic@sugarcrm.com>
5831 Bug 39085 - When loading the opposite search panel via ajax on the ListViews, call the index action instead of the ListView action to avoid touching pre-MVC code by accident.
5833 r57707 - 2010-08-10 12:26:13 -0700 (Tue, 10 Aug 2010) - kjing - Author: Stanislav Malyshev <smalyshev@gmail.com>
5834 fix SOAP calls with no parameters
5836 r56990 - 2010-06-16 13:05:36 -0700 (Wed, 16 Jun 2010) - kjing - snapshot "Mango" svn branch to a new one for GitHub sync
5838 r56989 - 2010-06-16 13:01:33 -0700 (Wed, 16 Jun 2010) - kjing - defunt "Mango" svn dev branch before github cutover
5840 r55980 - 2010-04-19 13:31:28 -0700 (Mon, 19 Apr 2010) - kjing - create Mango (6.1) based on windex
5842 r51719 - 2009-10-22 10:18:00 -0700 (Thu, 22 Oct 2009) - mitani - Converted to Build 3 tags and updated the build system
5844 r51634 - 2009-10-19 13:32:22 -0700 (Mon, 19 Oct 2009) - mitani - Windex is the branch for Sugar Sales 1.0 development
5846 r51508 - 2009-10-14 07:40:23 -0700 (Wed, 14 Oct 2009) - jmertic - More fallout fixes from the PHP 5.3 ereg to preg changes.
5848 r51455 - 2009-10-13 07:56:48 -0700 (Tue, 13 Oct 2009) - jmertic - Bug 33202 - Enable install of SugarCRM on PHP 5.3.0, asserting that the minimum supported version is PHP 5.2.x.
5850 r51443 - 2009-10-12 13:34:36 -0700 (Mon, 12 Oct 2009) - jmertic - Bug 33332 - Made application PHP 5.3 compliant with E_DEPRECATED warnings on by:
5851 - Changing all ereg function to either preg or simple string based ones
5852 - No more references to magic quotes.
5853 - Change all the session_unregister() functions to just unset() the correct session variable instead.
5855 r50375 - 2009-08-24 18:07:43 -0700 (Mon, 24 Aug 2009) - dwong - branch kobe2 from tokyo r50372
5857 r45763 - 2009-04-01 12:16:18 -0700 (Wed, 01 Apr 2009) - majed - Removed half of the require_once and include_onces in the product that were redundant or could be handled easily by the auto loader
5859 r45680 - 2009-03-30 14:34:35 -0700 (Mon, 30 Mar 2009) - Samir Gandhi - modifeid serializeSchema to generate WS-I compliant WSDL
5861 r42807 - 2008-12-29 11:16:59 -0800 (Mon, 29 Dec 2008) - dwong - Branch from trunk/sugarcrm r42806 to branches/tokyo/sugarcrm
5863 r42645 - 2008-12-18 13:41:08 -0800 (Thu, 18 Dec 2008) - awu - merging maint_5_2_0 rev41336:HEAD to trunk
5865 r41647 - 2008-11-11 17:44:30 -0800 (Tue, 11 Nov 2008) - majed - Fixes a few bugs
5867 r41596 - 2008-11-10 19:20:04 -0800 (Mon, 10 Nov 2008) - Samir Gandhi - modified to set $method in the code
5869 r41558 - 2008-11-10 14:35:34 -0800 (Mon, 10 Nov 2008) - majed - changes nusoap to allow for registering classes
5871 r39619 - 2008-09-09 13:41:34 -0700 (Tue, 09 Sep 2008) - jmertic - Bug 24827 - Remove all instances where we return a new object and assign it by reference, since this is deprecated in PHP 5 and emits E_DEPRECATED errors in PHP 5.3.
5873 - data/SugarBean.php
5874 - include/domit/php_http_client_generic.php
5875 - include/domit/php_http_connector.php
5876 - include/domit/testing_domit.php
5877 - include/domit/xml_domit_getelementsbypath.php
5878 - include/domit/xml_domit_lite_parser.php
5879 - include/domit/xml_domit_nodemaps.php
5880 - include/domit/xml_domit_parser.php
5881 - include/domit/xml_domit_shared.php
5882 - include/generic/SugarWidgets/SugarWidgetField.php
5883 - include/generic/SugarWidgets/SugarWidgetReportField.php
5884 - include/ListView/ProcessView.php
5885 - include/nusoap/class.soapclient.php
5886 - include/nusoap/nusoap.php
5887 - include/nusoap/nusoapmime.php
5888 - include/Pear/HTML_Safe/Safe.php
5889 - include/Pear/XML_HTMLSax3/HTMLSax3.php
5890 - modules/Administration/RebuildWorkFlow.php
5891 - modules/Expressions/RelateSelector.php
5892 - modules/Reports/templates/templates_reports.php
5893 - modules/WorkFlow/Delete.php
5894 - modules/WorkFlow/Save.php
5895 - modules/WorkFlow/SaveSequence.php
5896 - modules/WorkFlow/WorkFlow.php
5897 - modules/WorkFlowActionShells/CreateStep1.php
5898 - modules/WorkFlowActionShells/CreateStep2.php
5899 - modules/WorkFlowActionShells/Save.php
5900 - modules/WorkFlowActionShells/WorkFlowActionShell.php
5901 - modules/WorkFlowAlerts/Save.php
5902 - modules/WorkFlowAlerts/WorkFlowAlert.php
5903 - modules/WorkFlowAlertShells/DetailView.php
5904 - modules/WorkFlowAlertShells/WorkFlowAlertShell.php
5905 - modules/WorkFlowTriggerShells/CreateStep1.php
5906 - modules/WorkFlowTriggerShells/CreateStepFilter.php
5907 - modules/WorkFlowTriggerShells/SaveFilter.php
5908 - modules/WorkFlowTriggerShells/WorkFlowTriggerShell.php
5909 - soap/SoapHelperFunctions.php
5910 - test/modules/DynamicFields/DynamicFields_Bug24095_test.php
5911 - test/simpletest/browser.php
5912 - test/simpletest/default_reporter.php
5913 - test/simpletest/detached.php
5914 - test/simpletest/eclipse.php
5915 - test/simpletest/expectation.php
5916 - test/simpletest/extensions/pear_test_case.php
5917 - test/simpletest/form.php
5918 - test/simpletest/http.php
5919 - test/simpletest/mock_objects.php
5920 - test/simpletest/page.php
5921 - test/simpletest/parser.php
5922 - test/simpletest/remote.php
5923 - test/simpletest/shell_tester.php
5924 - test/simpletest/simple_test.php
5925 - test/simpletest/simpletest.php
5926 - test/simpletest/test/acceptance_test.php
5927 - test/simpletest/test/adapter_test.php
5928 - test/simpletest/test/authentication_test.php
5929 - test/simpletest/test/browser_test.php
5930 - test/simpletest/test/collector_test.php
5931 - test/simpletest/test/compatibility_test.php
5932 - test/simpletest/test/detached_test.php
5933 - test/simpletest/test/eclipse_test.php
5934 - test/simpletest/test/encoding_test.php
5935 - test/simpletest/test/errors_test.php
5936 - test/simpletest/test/expectation_test.php
5937 - test/simpletest/test/form_test.php
5938 - test/simpletest/test/frames_test.php
5939 - test/simpletest/test/http_test.php
5940 - test/simpletest/test/live_test.php
5941 - test/simpletest/test/mock_objects_test.php
5942 - test/simpletest/test/page_test.php
5943 - test/simpletest/test/parse_error_test.php
5944 - test/simpletest/test/parser_test.php
5945 - test/simpletest/test/remote_test.php
5946 - test/simpletest/test/shell_test.php
5947 - test/simpletest/test/shell_tester_test.php
5948 - test/simpletest/test/simpletest_test.php
5949 - test/simpletest/test/site/page_request.php
5950 - test/simpletest/test/tag_test.php
5951 - test/simpletest/test/unit_tester_test.php
5952 - test/simpletest/test/user_agent_test.php
5953 - test/simpletest/test/visual_test.php
5954 - test/simpletest/test/xml_test.php
5955 - test/simpletest/test_case.php
5956 - test/simpletest/ui/array_reporter/test.php
5957 - test/simpletest/ui/recorder/test.php
5958 - test/simpletest/unit_tester.php
5959 - test/simpletest/url.php
5960 - test/simpletest/user_agent.php
5961 - test/simpletest/web_tester.php
5962 - test/spikephpcoverage/src/PEAR.php
5963 - test/spikephpcoverage/src/util/Utility.php
5964 - test/spikephpcoverage/src/XML/Parser.php
5965 - test/spikephpcoverage/src/XML/Parser/Simple.php
5966 - test/test_utilities/SugarTest_SimpleBrowser.php
5968 r38362 - 2008-07-28 14:06:59 -0700 (Mon, 28 Jul 2008) - roger - bug: 23897. Using print_r when using the debug statement in nusoap will print out the statements to the screen if the call is coming from the UI.
5970 r38300 - 2008-07-25 13:33:43 -0700 (Fri, 25 Jul 2008) - Samir Gandhi - put the debug in parseresponse function
5972 r38293 - 2008-07-25 12:32:34 -0700 (Fri, 25 Jul 2008) - Samir Gandhi - to put all the debug statements return value in the call function
5974 r36824 - 2008-06-18 09:26:11 -0700 (Wed, 18 Jun 2008) - roger - bug: 21832
5976 r26422 - 2007-09-05 17:29:12 -0700 (Wed, 05 Sep 2007) - majed - migrate from beta 1 to trunk
5978 r15787 - 2006-08-10 10:14:41 -0700 (Thu, 10 Aug 2006) - roger - RRS: bug 7961
5980 r14701 - 2006-07-17 13:37:26 -0700 (Mon, 17 Jul 2006) - roger - RRS: bug 5801
5982 r13782 - 2006-06-06 10:58:55 -0700 (Tue, 06 Jun 2006) - majed - changes entry point code
5984 r11466 - 2006-02-01 15:49:47 -0800 (Wed, 01 Feb 2006) - jacob - Adding extra !empty check to get around a PHP warning.
5986 r11115 - 2006-01-17 14:54:45 -0800 (Tue, 17 Jan 2006) - majed - add entry point validation
5988 r10585 - 2005-12-13 14:42:26 -0800 (Tue, 13 Dec 2005) - majed - adds new license mechanisim
5990 r10170 - 2005-12-05 18:37:46 -0800 (Mon, 05 Dec 2005) - majed - fixes various issues
5992 r8999 - 2005-11-04 05:26:49 -0800 (Fri, 04 Nov 2005) - roger - When nusoap was upgraded we had an issue with the user's default language not being populated during a soap request. I determined the reason this was happening and have checked in the corresponding change to nusoap.
5994 r8991 - 2005-11-03 19:07:25 -0800 (Thu, 03 Nov 2005) - majed - fixes nusoap issue
5996 r8846 - 2005-10-31 11:01:12 -0800 (Mon, 31 Oct 2005) - majed - new version of nusoap
5998 r7905 - 2005-09-21 19:12:57 -0700 (Wed, 21 Sep 2005) - majed - restores old nusoap pre & with a few fixes
6000 r7861 - 2005-09-20 15:40:25 -0700 (Tue, 20 Sep 2005) - majed - & fix for 3.5.1
6002 r7452 - 2005-08-17 11:32:34 -0700 (Wed, 17 Aug 2005) - majed - changes soap to nusoap
6004 r5820 - 2005-06-21 14:22:24 -0700 (Tue, 21 Jun 2005) - majed - fixes issues with nusoap and with custom fields
6006 r5462 - 2005-05-25 13:50:11 -0700 (Wed, 25 May 2005) - majed - upgraded nusoap to .6.9
6008 r5104 - 2005-05-04 15:33:41 -0700 (Wed, 04 May 2005) - majed - gets rid of HTTP_GET_VARS and what not which has been deprecated
6010 r573 - 2004-09-04 13:03:32 -0700 (Sat, 04 Sep 2004) - sugarclint - undoing copyrights added in inadvertantly. --clint
6012 r546 - 2004-09-03 11:49:38 -0700 (Fri, 03 Sep 2004) - sugarmsi - removed echo count
6014 r354 - 2004-08-02 23:00:37 -0700 (Mon, 02 Aug 2004) - sugarjacob - Adding Soap
6024 * parses a WSDL file, allows access to it's data, other utility methods.
6025 * also builds WSDL structures programmatically.
6027 * @author Dietrich Ayala <dietrich@ganx4.com>
6028 * @author Scott Nichol <snichol@users.sourceforge.net>
6032 class wsdl extends nusoap_base {
6033 // URL or filename of the root of this WSDL
6035 // define internal arrays of bindings, ports, operations, messages, etc.
6036 var $schemas = array();
6038 var $message = array();
6039 var $complexTypes = array();
6040 var $messages = array();
6041 var $currentMessage;
6042 var $currentOperation;
6043 var $portTypes = array();
6044 var $currentPortType;
6045 var $bindings = array();
6046 var $currentBinding;
6047 var $ports = array();
6049 var $opData = array();
6051 var $documentation = false;
6053 // array of wsdl docs to import
6054 var $import = array();
6059 var $depth_array = array();
6061 var $proxyhost = '';
6062 var $proxyport = '';
6063 var $proxyusername = '';
6064 var $proxypassword = '';
6066 var $response_timeout = 30;
6067 var $curl_options = array(); // User-specified cURL options
6068 var $use_curl = false; // whether to always try to use cURL
6069 // for HTTP authentication
6070 var $username = ''; // Username for HTTP authentication
6071 var $password = ''; // Password for HTTP authentication
6072 var $authtype = ''; // Type of HTTP authentication
6073 var $certRequest = array(); // Certificate for HTTP SSL authentication
6078 * @param string $wsdl WSDL document URL
6079 * @param string $proxyhost
6080 * @param string $proxyport
6081 * @param string $proxyusername
6082 * @param string $proxypassword
6083 * @param integer $timeout set the connection timeout
6084 * @param integer $response_timeout set the response timeout
6085 * @param array $curl_options user-specified cURL options
6086 * @param boolean $use_curl try to use cURL
6089 function wsdl($wsdl = '',$proxyhost=false,$proxyport=false,$proxyusername=false,$proxypassword=false,$timeout=0,$response_timeout=30,$curl_options=null,$use_curl=false){
6090 parent::nusoap_base();
6091 $this->debug("ctor wsdl=$wsdl timeout=$timeout response_timeout=$response_timeout");
6092 $this->proxyhost = $proxyhost;
6093 $this->proxyport = $proxyport;
6094 $this->proxyusername = $proxyusername;
6095 $this->proxypassword = $proxypassword;
6096 $this->timeout = $timeout;
6097 $this->response_timeout = $response_timeout;
6098 if (is_array($curl_options))
6099 $this->curl_options = $curl_options;
6100 $this->use_curl = $use_curl;
6101 $this->fetchWSDL($wsdl);
6105 * fetches the WSDL document and parses it
6109 function fetchWSDL($wsdl) {
6110 $this->debug("parse and process WSDL path=$wsdl");
6111 $this->wsdl = $wsdl;
6113 if ($this->wsdl != "") {
6114 $this->parseWSDL($this->wsdl);
6117 // TODO: handle imports more properly, grabbing them in-line and nesting them
6118 $imported_urls = array();
6120 while ($imported > 0) {
6123 foreach ($this->schemas as $ns => $list) {
6124 foreach ($list as $xs) {
6125 $wsdlparts = parse_url($this->wsdl); // this is bogusly simple!
6126 foreach ($xs->imports as $ns2 => $list2) {
6127 for ($ii = 0; $ii < count($list2); $ii++) {
6128 if (! $list2[$ii]['loaded']) {
6129 $this->schemas[$ns]->imports[$ns2][$ii]['loaded'] = true;
6130 $url = $list2[$ii]['location'];
6132 $urlparts = parse_url($url);
6133 if (!isset($urlparts['host'])) {
6134 $url = $wsdlparts['scheme'] . '://' . $wsdlparts['host'] . (isset($wsdlparts['port']) ? ':' .$wsdlparts['port'] : '') .
6135 substr($wsdlparts['path'],0,strrpos($wsdlparts['path'],'/') + 1) .$urlparts['path'];
6137 if (! in_array($url, $imported_urls)) {
6138 $this->parseWSDL($url);
6140 $imported_urls[] = $url;
6143 $this->debug("Unexpected scenario: empty URL for unloaded import");
6151 $wsdlparts = parse_url($this->wsdl); // this is bogusly simple!
6152 foreach ($this->import as $ns => $list) {
6153 for ($ii = 0; $ii < count($list); $ii++) {
6154 if (! $list[$ii]['loaded']) {
6155 $this->import[$ns][$ii]['loaded'] = true;
6156 $url = $list[$ii]['location'];
6158 $urlparts = parse_url($url);
6159 if (!isset($urlparts['host'])) {
6160 $url = $wsdlparts['scheme'] . '://' . $wsdlparts['host'] . (isset($wsdlparts['port']) ? ':' . $wsdlparts['port'] : '') .
6161 substr($wsdlparts['path'],0,strrpos($wsdlparts['path'],'/') + 1) .$urlparts['path'];
6163 if (! in_array($url, $imported_urls)) {
6164 $this->parseWSDL($url);
6166 $imported_urls[] = $url;
6169 $this->debug("Unexpected scenario: empty URL for unloaded import");
6175 // add new data to operation data
6176 foreach($this->bindings as $binding => $bindingData) {
6177 if (isset($bindingData['operations']) && is_array($bindingData['operations'])) {
6178 foreach($bindingData['operations'] as $operation => $data) {
6179 $this->debug('post-parse data gathering for ' . $operation);
6180 $this->bindings[$binding]['operations'][$operation]['input'] =
6181 isset($this->bindings[$binding]['operations'][$operation]['input']) ?
6182 array_merge($this->bindings[$binding]['operations'][$operation]['input'], $this->portTypes[ $bindingData['portType'] ][$operation]['input']) :
6183 $this->portTypes[ $bindingData['portType'] ][$operation]['input'];
6184 $this->bindings[$binding]['operations'][$operation]['output'] =
6185 isset($this->bindings[$binding]['operations'][$operation]['output']) ?
6186 array_merge($this->bindings[$binding]['operations'][$operation]['output'], $this->portTypes[ $bindingData['portType'] ][$operation]['output']) :
6187 $this->portTypes[ $bindingData['portType'] ][$operation]['output'];
6188 if(isset($this->messages[ $this->bindings[$binding]['operations'][$operation]['input']['message'] ])){
6189 $this->bindings[$binding]['operations'][$operation]['input']['parts'] = $this->messages[ $this->bindings[$binding]['operations'][$operation]['input']['message'] ];
6191 if(isset($this->messages[ $this->bindings[$binding]['operations'][$operation]['output']['message'] ])){
6192 $this->bindings[$binding]['operations'][$operation]['output']['parts'] = $this->messages[ $this->bindings[$binding]['operations'][$operation]['output']['message'] ];
6194 // Set operation style if necessary, but do not override one already provided
6195 if (isset($bindingData['style']) && !isset($this->bindings[$binding]['operations'][$operation]['style'])) {
6196 $this->bindings[$binding]['operations'][$operation]['style'] = $bindingData['style'];
6198 $this->bindings[$binding]['operations'][$operation]['transport'] = isset($bindingData['transport']) ? $bindingData['transport'] : '';
6199 $this->bindings[$binding]['operations'][$operation]['documentation'] = isset($this->portTypes[ $bindingData['portType'] ][$operation]['documentation']) ? $this->portTypes[ $bindingData['portType'] ][$operation]['documentation'] : '';
6200 $this->bindings[$binding]['operations'][$operation]['endpoint'] = isset($bindingData['endpoint']) ? $bindingData['endpoint'] : '';
6207 * parses the wsdl document
6209 * @param string $wsdl path or URL
6212 function parseWSDL($wsdl = '') {
6213 $this->debug("parse WSDL at path=$wsdl");
6216 $this->debug('no wsdl passed to parseWSDL()!!');
6217 $this->setError('no wsdl passed to parseWSDL()!!');
6221 // parse $wsdl for url format
6222 $wsdl_props = parse_url($wsdl);
6224 if (isset($wsdl_props['scheme']) && ($wsdl_props['scheme'] == 'http' || $wsdl_props['scheme'] == 'https')) {
6225 $this->debug('getting WSDL http(s) URL ' . $wsdl);
6227 $tr = new soap_transport_http($wsdl, $this->curl_options, $this->use_curl);
6228 $tr->request_method = 'GET';
6229 $tr->useSOAPAction = false;
6230 if($this->proxyhost && $this->proxyport){
6231 $tr->setProxy($this->proxyhost,$this->proxyport,$this->proxyusername,$this->proxypassword);
6233 if ($this->authtype != '') {
6234 $tr->setCredentials($this->username, $this->password, $this->authtype, array(), $this->certRequest);
6236 $tr->setEncoding('gzip, deflate');
6237 $wsdl_string = $tr->send('', $this->timeout, $this->response_timeout);
6238 //$this->debug("WSDL request\n" . $tr->outgoing_payload);
6239 //$this->debug("WSDL response\n" . $tr->incoming_payload);
6240 $this->appendDebug($tr->getDebug());
6242 if($err = $tr->getError() ){
6243 $errstr = 'Getting ' . $wsdl . ' - HTTP ERROR: '.$err;
6244 $this->debug($errstr);
6245 $this->setError($errstr);
6250 $this->debug("got WSDL URL");
6252 // $wsdl is not http(s), so treat it as a file URL or plain file path
6253 if (isset($wsdl_props['scheme']) && ($wsdl_props['scheme'] == 'file') && isset($wsdl_props['path'])) {
6254 $path = isset($wsdl_props['host']) ? ($wsdl_props['host'] . ':' . $wsdl_props['path']) : $wsdl_props['path'];
6258 $this->debug('getting WSDL file ' . $path);
6259 if ($fp = @fopen($path, 'r')) {
6261 while ($data = fread($fp, 32768)) {
6262 $wsdl_string .= $data;
6266 $errstr = "Bad path to WSDL file $path";
6267 $this->debug($errstr);
6268 $this->setError($errstr);
6272 $this->debug('Parse WSDL');
6273 // end new code added
6274 // Create an XML parser.
6275 $this->parser = xml_parser_create();
6276 // Set the options for parsing the XML data.
6277 // xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
6278 xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
6279 // Set the object for the parser.
6280 xml_set_object($this->parser, $this);
6281 // Set the element handlers for the parser.
6282 xml_set_element_handler($this->parser, 'start_element', 'end_element');
6283 xml_set_character_data_handler($this->parser, 'character_data');
6284 // Parse the XML file.
6285 if (!xml_parse($this->parser, $wsdl_string, true)) {
6286 // Display an error message.
6288 'XML error parsing WSDL from %s on line %d: %s',
6290 xml_get_current_line_number($this->parser),
6291 xml_error_string(xml_get_error_code($this->parser))
6293 $this->debug($errstr);
6294 $this->debug("XML payload:\n" . $wsdl_string);
6295 $this->setError($errstr);
6299 xml_parser_free($this->parser);
6300 $this->debug('Parsing WSDL done');
6301 // catch wsdl parse errors
6302 if($this->getError()){
6309 * start-element handler
6311 * @param string $parser XML parser object
6312 * @param string $name element name
6313 * @param string $attrs associative array of attributes
6316 function start_element($parser, $name, $attrs)
6318 if ($this->status == 'schema') {
6319 $this->currentSchema->schemaStartElement($parser, $name, $attrs);
6320 $this->appendDebug($this->currentSchema->getDebug());
6321 $this->currentSchema->clearDebug();
6322 } elseif (preg_match('/schema$/', $name)) {
6323 $this->debug('Parsing WSDL schema');
6324 // $this->debug("startElement for $name ($attrs[name]). status = $this->status (".$this->getLocalPart($name).")");
6325 $this->status = 'schema';
6326 $this->currentSchema = new nusoap_xmlschema('', '', $this->namespaces);
6327 $this->currentSchema->schemaStartElement($parser, $name, $attrs);
6328 $this->appendDebug($this->currentSchema->getDebug());
6329 $this->currentSchema->clearDebug();
6331 // position in the total number of elements, starting from 0
6332 $pos = $this->position++;
6333 $depth = $this->depth++;
6334 // set self as current value for this depth
6335 $this->depth_array[$depth] = $pos;
6336 $this->message[$pos] = array('cdata' => '');
6337 // process attributes
6338 if (count($attrs) > 0) {
6339 // register namespace declarations
6340 foreach($attrs as $k => $v) {
6341 if (preg_match('/^xmlns/',$k)) {
6342 if ($ns_prefix = substr(strrchr($k, ':'), 1)) {
6343 $this->namespaces[$ns_prefix] = $v;
6345 $this->namespaces['ns' . (count($this->namespaces) + 1)] = $v;
6347 if ($v == 'http://www.w3.org/2001/XMLSchema' || $v == 'http://www.w3.org/1999/XMLSchema' || $v == 'http://www.w3.org/2000/10/XMLSchema') {
6348 $this->XMLSchemaVersion = $v;
6349 $this->namespaces['xsi'] = $v . '-instance';
6353 // expand each attribute prefix to its namespace
6354 foreach($attrs as $k => $v) {
6355 $k = strpos($k, ':') ? $this->expandQname($k) : $k;
6356 if ($k != 'location' && $k != 'soapAction' && $k != 'namespace') {
6357 $v = strpos($v, ':') ? $this->expandQname($v) : $v;
6365 // get element prefix, namespace and name
6366 if (preg_match('/:/', $name)) {
6368 $prefix = substr($name, 0, strpos($name, ':'));
6370 $namespace = isset($this->namespaces[$prefix]) ? $this->namespaces[$prefix] : '';
6371 // get unqualified name
6372 $name = substr(strstr($name, ':'), 1);
6374 // process attributes, expanding any prefixes to namespaces
6375 // find status, register data
6376 switch ($this->status) {
6378 if ($name == 'part') {
6379 if (isset($attrs['type'])) {
6380 $this->debug("msg " . $this->currentMessage . ": found part (with type) $attrs[name]: " . implode(',', $attrs));
6381 $this->messages[$this->currentMessage][$attrs['name']] = $attrs['type'];
6383 if (isset($attrs['element'])) {
6384 $this->debug("msg " . $this->currentMessage . ": found part (with element) $attrs[name]: " . implode(',', $attrs));
6385 $this->messages[$this->currentMessage][$attrs['name']] = $attrs['element'] . '^';
6392 $this->currentPortOperation = $attrs['name'];
6393 $this->debug("portType $this->currentPortType operation: $this->currentPortOperation");
6394 if (isset($attrs['parameterOrder'])) {
6395 $this->portTypes[$this->currentPortType][$attrs['name']]['parameterOrder'] = $attrs['parameterOrder'];
6398 case 'documentation':
6399 $this->documentation = true;
6401 // merge input/output data
6403 $m = isset($attrs['message']) ? $this->getLocalPart($attrs['message']) : '';
6404 $this->portTypes[$this->currentPortType][$this->currentPortOperation][$name]['message'] = $m;
6412 if (isset($attrs['style'])) {
6413 $this->bindings[$this->currentBinding]['prefix'] = $prefix;
6415 $this->bindings[$this->currentBinding] = array_merge($this->bindings[$this->currentBinding], $attrs);
6418 $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus]['headers'][] = $attrs;
6421 if (isset($attrs['soapAction'])) {
6422 $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['soapAction'] = $attrs['soapAction'];
6424 if (isset($attrs['style'])) {
6425 $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['style'] = $attrs['style'];
6427 if (isset($attrs['name'])) {
6428 $this->currentOperation = $attrs['name'];
6429 $this->debug("current binding operation: $this->currentOperation");
6430 $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['name'] = $attrs['name'];
6431 $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['binding'] = $this->currentBinding;
6432 $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['endpoint'] = isset($this->bindings[$this->currentBinding]['endpoint']) ? $this->bindings[$this->currentBinding]['endpoint'] : '';
6436 $this->opStatus = 'input';
6439 $this->opStatus = 'output';
6442 if (isset($this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus])) {
6443 $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus] = array_merge($this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus], $attrs);
6445 $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus] = $attrs;
6453 $this->currentPort = $attrs['name'];
6454 $this->debug('current port: ' . $this->currentPort);
6455 $this->ports[$this->currentPort]['binding'] = $this->getLocalPart($attrs['binding']);
6459 $this->ports[$this->currentPort]['location'] = $attrs['location'];
6460 $this->ports[$this->currentPort]['bindingType'] = $namespace;
6461 $this->bindings[ $this->ports[$this->currentPort]['binding'] ]['bindingType'] = $namespace;
6462 $this->bindings[ $this->ports[$this->currentPort]['binding'] ]['endpoint'] = $attrs['location'];
6470 if (isset($attrs['location'])) {
6471 $this->import[$attrs['namespace']][] = array('location' => $attrs['location'], 'loaded' => false);
6472 $this->debug('parsing import ' . $attrs['namespace']. ' - ' . $attrs['location'] . ' (' . count($this->import[$attrs['namespace']]).')');
6474 $this->import[$attrs['namespace']][] = array('location' => '', 'loaded' => true);
6475 if (! $this->getPrefixFromNamespace($attrs['namespace'])) {
6476 $this->namespaces['ns'.(count($this->namespaces)+1)] = $attrs['namespace'];
6478 $this->debug('parsing import ' . $attrs['namespace']. ' - [no location] (' . count($this->import[$attrs['namespace']]).')');
6483 // $this->status = 'schema';
6486 $this->status = 'message';
6487 $this->messages[$attrs['name']] = array();
6488 $this->currentMessage = $attrs['name'];
6491 $this->status = 'portType';
6492 $this->portTypes[$attrs['name']] = array();
6493 $this->currentPortType = $attrs['name'];
6496 if (isset($attrs['name'])) {
6498 if (strpos($attrs['name'], ':')) {
6499 $this->currentBinding = $this->getLocalPart($attrs['name']);
6501 $this->currentBinding = $attrs['name'];
6503 $this->status = 'binding';
6504 $this->bindings[$this->currentBinding]['portType'] = $this->getLocalPart($attrs['type']);
6505 $this->debug("current binding: $this->currentBinding of portType: " . $attrs['type']);
6509 $this->serviceName = $attrs['name'];
6510 $this->status = 'service';
6511 $this->debug('current service: ' . $this->serviceName);
6514 foreach ($attrs as $name => $value) {
6515 $this->wsdl_info[$name] = $value;
6523 * end-element handler
6525 * @param string $parser XML parser object
6526 * @param string $name element name
6529 function end_element($parser, $name){
6530 // unset schema status
6531 if (/*preg_match('/types$/', $name) ||*/ preg_match('/schema$/', $name)) {
6533 $this->appendDebug($this->currentSchema->getDebug());
6534 $this->currentSchema->clearDebug();
6535 $this->schemas[$this->currentSchema->schemaTargetNamespace][] = $this->currentSchema;
6536 $this->debug('Parsing WSDL schema done');
6538 if ($this->status == 'schema') {
6539 $this->currentSchema->schemaEndElement($parser, $name);
6541 // bring depth down a notch
6544 // end documentation
6545 if ($this->documentation) {
6546 //TODO: track the node to which documentation should be assigned; it can be a part, message, etc.
6547 //$this->portTypes[$this->currentPortType][$this->currentPortOperation]['documentation'] = $this->documentation;
6548 $this->documentation = false;
6553 * element content handler
6555 * @param string $parser XML parser object
6556 * @param string $data element content
6559 function character_data($parser, $data)
6561 $pos = isset($this->depth_array[$this->depth]) ? $this->depth_array[$this->depth] : 0;
6562 if (isset($this->message[$pos]['cdata'])) {
6563 $this->message[$pos]['cdata'] .= $data;
6565 if ($this->documentation) {
6566 $this->documentation .= $data;
6571 * if authenticating, set user credentials here
6573 * @param string $username
6574 * @param string $password
6575 * @param string $authtype (basic|digest|certificate|ntlm)
6576 * @param array $certRequest (keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, certpassword (optional), verifypeer (optional), verifyhost (optional): see corresponding options in cURL docs)
6579 function setCredentials($username, $password, $authtype = 'basic', $certRequest = array()) {
6580 $this->debug("setCredentials username=$username authtype=$authtype certRequest=");
6581 $this->appendDebug($this->varDump($certRequest));
6582 $this->username = $username;
6583 $this->password = $password;
6584 $this->authtype = $authtype;
6585 $this->certRequest = $certRequest;
6588 function getBindingData($binding)
6590 if (is_array($this->bindings[$binding])) {
6591 return $this->bindings[$binding];
6596 * returns an assoc array of operation names => operation data
6598 * @param string $portName WSDL port name
6599 * @param string $bindingType eg: soap, smtp, dime (only soap and soap12 are currently supported)
6603 function getOperations($portName = '', $bindingType = 'soap') {
6605 if ($bindingType == 'soap') {
6606 $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/';
6607 } elseif ($bindingType == 'soap12') {
6608 $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/';
6610 $this->debug("getOperations bindingType $bindingType may not be supported");
6612 $this->debug("getOperations for port '$portName' bindingType $bindingType");
6614 foreach($this->ports as $port => $portData) {
6615 $this->debug("getOperations checking port $port bindingType " . $portData['bindingType']);
6616 if ($portName == '' || $port == $portName) {
6617 // binding type of port matches parameter
6618 if ($portData['bindingType'] == $bindingType) {
6619 $this->debug("getOperations found port $port bindingType $bindingType");
6620 //$this->debug("port data: " . $this->varDump($portData));
6621 //$this->debug("bindings: " . $this->varDump($this->bindings[ $portData['binding'] ]));
6623 if (isset($this->bindings[ $portData['binding'] ]['operations'])) {
6624 $ops = array_merge ($ops, $this->bindings[ $portData['binding'] ]['operations']);
6629 if (count($ops) == 0) {
6630 $this->debug("getOperations found no operations for port '$portName' bindingType $bindingType");
6636 * returns an associative array of data necessary for calling an operation
6638 * @param string $operation name of operation
6639 * @param string $bindingType type of binding eg: soap, soap12
6643 function getOperationData($operation, $bindingType = 'soap')
6645 if ($bindingType == 'soap') {
6646 $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/';
6647 } elseif ($bindingType == 'soap12') {
6648 $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/';
6651 foreach($this->ports as $port => $portData) {
6652 // binding type of port matches parameter
6653 if ($portData['bindingType'] == $bindingType) {
6655 //foreach($this->bindings[ $portData['binding'] ]['operations'] as $bOperation => $opData) {
6656 foreach(array_keys($this->bindings[ $portData['binding'] ]['operations']) as $bOperation) {
6657 // note that we could/should also check the namespace here
6658 if ($operation == $bOperation) {
6659 $opData = $this->bindings[ $portData['binding'] ]['operations'][$operation];
6668 * returns an associative array of data necessary for calling an operation
6670 * @param string $soapAction soapAction for operation
6671 * @param string $bindingType type of binding eg: soap, soap12
6675 function getOperationDataForSoapAction($soapAction, $bindingType = 'soap') {
6676 if ($bindingType == 'soap') {
6677 $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/';
6678 } elseif ($bindingType == 'soap12') {
6679 $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/';
6682 foreach($this->ports as $port => $portData) {
6683 // binding type of port matches parameter
6684 if ($portData['bindingType'] == $bindingType) {
6685 // loop through operations for the binding
6686 foreach ($this->bindings[ $portData['binding'] ]['operations'] as $bOperation => $opData) {
6687 if ($opData['soapAction'] == $soapAction) {
6696 * returns an array of information about a given type
6697 * returns false if no type exists by the given name
6700 * 'elements' => array(), // refs to elements array
6701 * 'restrictionBase' => '',
6703 * 'order' => '(sequence|all)',
6704 * 'attrs' => array() // refs to attributes array
6707 * @param string $type the type
6708 * @param string $ns namespace (not prefix) of the type
6711 * @see nusoap_xmlschema
6713 function getTypeDef($type, $ns) {
6714 $this->debug("in getTypeDef: type=$type, ns=$ns");
6715 if ((! $ns) && isset($this->namespaces['tns'])) {
6716 $ns = $this->namespaces['tns'];
6717 $this->debug("in getTypeDef: type namespace forced to $ns");
6719 if (!isset($this->schemas[$ns])) {
6720 foreach ($this->schemas as $ns0 => $schema0) {
6721 if (strcasecmp($ns, $ns0) == 0) {
6722 $this->debug("in getTypeDef: replacing schema namespace $ns with $ns0");
6728 if (isset($this->schemas[$ns])) {
6729 $this->debug("in getTypeDef: have schema for namespace $ns");
6730 for ($i = 0; $i < count($this->schemas[$ns]); $i++) {
6731 $xs = &$this->schemas[$ns][$i];
6732 $t = $xs->getTypeDef($type);
6733 $this->appendDebug($xs->getDebug());
6736 $this->debug("in getTypeDef: found type $type");
6737 if (!isset($t['phpType'])) {
6738 // get info for type to tack onto the element
6739 $uqType = substr($t['type'], strrpos($t['type'], ':') + 1);
6740 $ns = substr($t['type'], 0, strrpos($t['type'], ':'));
6741 $etype = $this->getTypeDef($uqType, $ns);
6743 $this->debug("found type for [element] $type:");
6744 $this->debug($this->varDump($etype));
6745 if (isset($etype['phpType'])) {
6746 $t['phpType'] = $etype['phpType'];
6748 if (isset($etype['elements'])) {
6749 $t['elements'] = $etype['elements'];
6751 if (isset($etype['attrs'])) {
6752 $t['attrs'] = $etype['attrs'];
6755 $this->debug("did not find type for [element] $type");
6761 $this->debug("in getTypeDef: did not find type $type");
6763 $this->debug("in getTypeDef: do not have schema for namespace $ns");
6769 * prints html description of services
6773 function webDescription(){
6774 global $HTTP_SERVER_VARS;
6776 if (isset($_SERVER)) {
6777 $PHP_SELF = $_SERVER['PHP_SELF'];
6778 } elseif (isset($HTTP_SERVER_VARS)) {
6779 $PHP_SELF = $HTTP_SERVER_VARS['PHP_SELF'];
6781 $this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available");
6785 <html><head><title>NuSOAP: '.$this->serviceName.'</title>
6786 <style type="text/css">
6787 body { font-family: arial; color: #000000; background-color: #ffffff; margin: 0px 0px 0px 0px; }
6788 p { font-family: arial; color: #000000; margin-top: 0px; margin-bottom: 12px; }
6789 pre { background-color: silver; padding: 5px; font-family: Courier New; font-size: x-small; color: #000000;}
6790 ul { margin-top: 10px; margin-left: 20px; }
6791 li { list-style-type: none; margin-top: 10px; color: #000000; }
6793 margin-left: 0px; padding-bottom: 2em; }
6795 padding-top: 10px; padding-bottom: 10px; padding-left: 15px; font-size: .70em;
6796 margin-top: 10px; margin-left: 0px; color: #000000;
6797 background-color: #ccccff; width: 20%; margin-left: 20px; margin-top: 20px; }
6799 font-family: arial; font-size: 26px; color: #ffffff;
6800 background-color: #999999; width: 100%;
6801 margin-left: 0px; margin-right: 0px;
6802 padding-top: 10px; padding-bottom: 10px;}
6804 position: absolute; visibility: hidden; z-index: 200; left: 250px; top: 100px;
6805 font-family: arial; overflow: hidden; width: 600;
6806 padding: 20px; font-size: 10px; background-color: #999999;
6807 layer-background-color:#FFFFFF; }
6808 a,a:active { color: charcoal; font-weight: bold; }
6809 a:visited { color: #666666; font-weight: bold; }
6810 a:hover { color: cc3300; font-weight: bold; }
6812 <script language="JavaScript" type="text/javascript">
6814 // POP-UP CAPTIONS...
6815 function lib_bwcheck(){ //Browsercheck (needed)
6816 this.ver=navigator.appVersion
6817 this.agent=navigator.userAgent
6818 this.dom=document.getElementById?1:0
6819 this.opera5=this.agent.indexOf("Opera 5")>-1
6820 this.ie5=(this.ver.indexOf("MSIE 5")>-1 && this.dom && !this.opera5)?1:0;
6821 this.ie6=(this.ver.indexOf("MSIE 6")>-1 && this.dom && !this.opera5)?1:0;
6822 this.ie4=(document.all && !this.dom && !this.opera5)?1:0;
6823 this.ie=this.ie4||this.ie5||this.ie6
6824 this.mac=this.agent.indexOf("Mac")>-1
6825 this.ns6=(this.dom && parseInt(this.ver) >= 5) ?1:0;
6826 this.ns4=(document.layers && !this.dom)?1:0;
6827 this.bw=(this.ie6 || this.ie5 || this.ie4 || this.ns4 || this.ns6 || this.opera5)
6830 var bw = new lib_bwcheck()
6831 //Makes crossbrowser object.
6832 function makeObj(obj){
6833 this.evnt=bw.dom? document.getElementById(obj):bw.ie4?document.all[obj]:bw.ns4?document.layers[obj]:0;
6834 if(!this.evnt) return false
6835 this.css=bw.dom||bw.ie4?this.evnt.style:bw.ns4?this.evnt:0;
6836 this.wref=bw.dom||bw.ie4?this.evnt:bw.ns4?this.css.document:0;
6837 this.writeIt=b_writeIt;
6840 // A unit of measure that will be added when setting the position of a layer.
6841 //var px = bw.ns4||window.opera?"":"px";
6842 function b_writeIt(text){
6843 if (bw.ns4){this.wref.write(text);this.wref.close()}
6844 else this.wref.innerHTML = text
6846 //Shows the messages
6848 function popup(divid){
6849 if(oDesc = new makeObj(divid)){
6850 oDesc.css.visibility = "visible"
6853 function popout(){ // Hides message
6854 if(oDesc) oDesc.css.visibility = "hidden"
6862 <div class=title>'.$this->serviceName.'</div>
6864 <p>View the <a href="'.$PHP_SELF.'?wsdl">WSDL</a> for the service.
6865 Click on an operation name to view it's details.</p>
6867 foreach($this->getOperations() as $op => $data){
6868 $b .= "<li><a href='#' onclick=\"popout();popup('$op')\">$op</a></li>";
6869 // create hidden div
6870 $b .= "<div id='$op' class='hidden'>
6871 <a href='#' onclick='popout()'><font color='#ffffff'>Close</font></a><br><br>";
6872 foreach($data as $donnie => $marie){ // loop through opdata
6873 if($donnie == 'input' || $donnie == 'output'){ // show input/output data
6874 $b .= "<font color='white'>".ucfirst($donnie).':</font><br>';
6875 foreach($marie as $captain => $tenille){ // loop through data
6876 if($captain == 'parts'){ // loop thru parts
6877 $b .= " $captain:<br>";
6878 //if(is_array($tenille)){
6879 foreach($tenille as $joanie => $chachi){
6880 $b .= " $joanie: $chachi<br>";
6884 $b .= " $captain: $tenille<br>";
6888 $b .= "<font color='white'>".ucfirst($donnie).":</font> $marie<br>";
6896 </div></body></html>';
6901 * serialize the parsed wsdl
6903 * @param mixed $debug whether to put debug=1 in endpoint URL
6904 * @return string serialization of WSDL
6907 function serialize($debug = 0)
6909 $xml = '<?xml version="1.0" encoding="ISO-8859-1"?>';
6910 $xml .= "\n<definitions";
6911 foreach($this->namespaces as $k => $v) {
6912 $xml .= " xmlns:$k=\"$v\"";
6914 // 10.9.02 - add poulter fix for wsdl and tns declarations
6915 if (isset($this->namespaces['wsdl'])) {
6916 $xml .= " xmlns=\"" . $this->namespaces['wsdl'] . "\"";
6918 if (isset($this->namespaces['tns'])) {
6919 $xml .= " targetNamespace=\"" . $this->namespaces['tns'] . "\"";
6923 if (sizeof($this->import) > 0) {
6924 foreach($this->import as $ns => $list) {
6925 foreach ($list as $ii) {
6926 if ($ii['location'] != '') {
6927 $xml .= '<import location="' . $ii['location'] . '" namespace="' . $ns . '" />';
6929 $xml .= '<import namespace="' . $ns . '" />';
6935 if (count($this->schemas)>=1) {
6936 $xml .= "\n<types>\n";
6937 foreach ($this->schemas as $ns => $list) {
6938 foreach ($list as $xs) {
6939 $xml .= $xs->serializeSchema();
6945 if (count($this->messages) >= 1) {
6946 foreach($this->messages as $msgName => $msgParts) {
6947 $xml .= "\n<message name=\"" . $msgName . '">';
6948 if(is_array($msgParts)){
6949 foreach($msgParts as $partName => $partType) {
6950 // print 'serializing '.$partType.', sv: '.$this->XMLSchemaVersion.'<br>';
6951 if (strpos($partType, ':')) {
6952 $typePrefix = $this->getPrefixFromNamespace($this->getPrefix($partType));
6953 } elseif (isset($this->typemap[$this->namespaces['xsd']][$partType])) {
6954 // print 'checking typemap: '.$this->XMLSchemaVersion.'<br>';
6955 $typePrefix = 'xsd';
6957 foreach($this->typemap as $ns => $types) {
6958 if (isset($types[$partType])) {
6959 $typePrefix = $this->getPrefixFromNamespace($ns);
6962 if (!isset($typePrefix)) {
6963 die("$partType has no namespace!");
6966 $ns = $this->getNamespaceFromPrefix($typePrefix);
6967 $localPart = $this->getLocalPart($partType);
6968 $typeDef = $this->getTypeDef($localPart, $ns);
6969 if ($typeDef['typeClass'] == 'element') {
6970 $elementortype = 'element';
6971 if (substr($localPart, -1) == '^') {
6972 $localPart = substr($localPart, 0, -1);
6975 $elementortype = 'type';
6977 $xml .= "\n" . ' <part name="' . $partName . '" ' . $elementortype . '="' . $typePrefix . ':' . $localPart . '" />';
6980 $xml .= '</message>';
6983 // bindings & porttypes
6984 if (count($this->bindings) >= 1) {
6987 foreach($this->bindings as $bindingName => $attrs) {
6988 $binding_xml .= "\n<binding name=\"" . $bindingName . '" type="tns:' . $attrs['portType'] . '">';
6989 $binding_xml .= "\n" . ' <soap:binding style="' . $attrs['style'] . '" transport="' . $attrs['transport'] . '"/>';
6990 $portType_xml .= "\n<portType name=\"" . $attrs['portType'] . '">';
6991 foreach($attrs['operations'] as $opName => $opParts) {
6992 $binding_xml .= "\n" . ' <operation name="' . $opName . '">';
6993 $binding_xml .= "\n" . ' <soap:operation soapAction="' . $opParts['soapAction'] . '" style="'. $opParts['style'] . '"/>';
6994 if (isset($opParts['input']['encodingStyle']) && $opParts['input']['encodingStyle'] != '') {
6995 $enc_style = ' encodingStyle="' . $opParts['input']['encodingStyle'] . '"';
6999 $binding_xml .= "\n" . ' <input><soap:body use="' . $opParts['input']['use'] . '" namespace="' . $opParts['input']['namespace'] . '"' . $enc_style . '/></input>';
7000 if (isset($opParts['output']['encodingStyle']) && $opParts['output']['encodingStyle'] != '') {
7001 $enc_style = ' encodingStyle="' . $opParts['output']['encodingStyle'] . '"';
7005 $binding_xml .= "\n" . ' <output><soap:body use="' . $opParts['output']['use'] . '" namespace="' . $opParts['output']['namespace'] . '"' . $enc_style . '/></output>';
7006 $binding_xml .= "\n" . ' </operation>';
7007 $portType_xml .= "\n" . ' <operation name="' . $opParts['name'] . '"';
7008 if (isset($opParts['parameterOrder'])) {
7009 $portType_xml .= ' parameterOrder="' . $opParts['parameterOrder'] . '"';
7011 $portType_xml .= '>';
7012 if(isset($opParts['documentation']) && $opParts['documentation'] != '') {
7013 $portType_xml .= "\n" . ' <documentation>' . htmlspecialchars($opParts['documentation']) . '</documentation>';
7015 $portType_xml .= "\n" . ' <input message="tns:' . $opParts['input']['message'] . '"/>';
7016 $portType_xml .= "\n" . ' <output message="tns:' . $opParts['output']['message'] . '"/>';
7017 $portType_xml .= "\n" . ' </operation>';
7019 $portType_xml .= "\n" . '</portType>';
7020 $binding_xml .= "\n" . '</binding>';
7022 $xml .= $portType_xml . $binding_xml;
7025 $xml .= "\n<service name=\"" . $this->serviceName . '">';
7026 if (count($this->ports) >= 1) {
7027 foreach($this->ports as $pName => $attrs) {
7028 $xml .= "\n" . ' <port name="' . $pName . '" binding="tns:' . $attrs['binding'] . '">';
7029 $xml .= "\n" . ' <soap:address location="' . $attrs['location'] . ($debug ? '?debug=1' : '') . '"/>';
7030 $xml .= "\n" . ' </port>';
7033 $xml .= "\n" . '</service>';
7034 return $xml . "\n</definitions>";
7038 * determine whether a set of parameters are unwrapped
7039 * when they are expect to be wrapped, Microsoft-style.
7041 * @param string $type the type (element name) of the wrapper
7042 * @param array $parameters the parameter values for the SOAP call
7043 * @return boolean whether they parameters are unwrapped (and should be wrapped)
7046 function parametersMatchWrapped($type, &$parameters) {
7047 $this->debug("in parametersMatchWrapped type=$type, parameters=");
7048 $this->appendDebug($this->varDump($parameters));
7050 // split type into namespace:unqualified-type
7051 if (strpos($type, ':')) {
7052 $uqType = substr($type, strrpos($type, ':') + 1);
7053 $ns = substr($type, 0, strrpos($type, ':'));
7054 $this->debug("in parametersMatchWrapped: got a prefixed type: $uqType, $ns");
7055 if ($this->getNamespaceFromPrefix($ns)) {
7056 $ns = $this->getNamespaceFromPrefix($ns);
7057 $this->debug("in parametersMatchWrapped: expanded prefixed type: $uqType, $ns");
7060 // TODO: should the type be compared to types in XSD, and the namespace
7061 // set to XSD if the type matches?
7062 $this->debug("in parametersMatchWrapped: No namespace for type $type");
7067 // get the type information
7068 if (!$typeDef = $this->getTypeDef($uqType, $ns)) {
7069 $this->debug("in parametersMatchWrapped: $type ($uqType) is not a supported type.");
7072 $this->debug("in parametersMatchWrapped: found typeDef=");
7073 $this->appendDebug($this->varDump($typeDef));
7074 if (substr($uqType, -1) == '^') {
7075 $uqType = substr($uqType, 0, -1);
7077 $phpType = $typeDef['phpType'];
7078 $arrayType = (isset($typeDef['arrayType']) ? $typeDef['arrayType'] : '');
7079 $this->debug("in parametersMatchWrapped: uqType: $uqType, ns: $ns, phptype: $phpType, arrayType: $arrayType");
7081 // we expect a complexType or element of complexType
7082 if ($phpType != 'struct') {
7083 $this->debug("in parametersMatchWrapped: not a struct");
7087 // see whether the parameter names match the elements
7088 if (isset($typeDef['elements']) && is_array($typeDef['elements'])) {
7091 foreach ($typeDef['elements'] as $name => $attrs) {
7092 if (isset($parameters[$name])) {
7093 $this->debug("in parametersMatchWrapped: have parameter named $name");
7096 $this->debug("in parametersMatchWrapped: do not have parameter named $name");
7101 $this->debug("in parametersMatchWrapped: $matches parameter names match $elements wrapped parameter names");
7102 if ($matches == 0) {
7108 // since there are no elements for the type, if the user passed no
7109 // parameters, the parameters match wrapped.
7110 $this->debug("in parametersMatchWrapped: no elements type $ns:$uqType");
7111 return count($parameters) == 0;
7115 * serialize PHP values according to a WSDL message definition
7116 * contrary to the method name, this is not limited to RPC
7119 * - multi-ref serialization
7120 * - validate PHP values against type definitions, return errors if invalid
7122 * @param string $operation operation name
7123 * @param string $direction (input|output)
7124 * @param mixed $parameters parameter value(s)
7125 * @param string $bindingType (soap|soap12)
7126 * @return mixed parameters serialized as XML or false on error (e.g. operation not found)
7129 function serializeRPCParameters($operation, $direction, $parameters, $bindingType = 'soap') {
7130 $this->debug("in serializeRPCParameters: operation=$operation, direction=$direction, XMLSchemaVersion=$this->XMLSchemaVersion, bindingType=$bindingType");
7131 $this->appendDebug('parameters=' . $this->varDump($parameters));
7133 if ($direction != 'input' && $direction != 'output') {
7134 $this->debug('The value of the \$direction argument needs to be either "input" or "output"');
7135 $this->setError('The value of the \$direction argument needs to be either "input" or "output"');
7138 if (!$opData = $this->getOperationData($operation, $bindingType)) {
7139 $this->debug('Unable to retrieve WSDL data for operation: ' . $operation . ' bindingType: ' . $bindingType);
7140 $this->setError('Unable to retrieve WSDL data for operation: ' . $operation . ' bindingType: ' . $bindingType);
7143 $this->debug('in serializeRPCParameters: opData:');
7144 $this->appendDebug($this->varDump($opData));
7146 // Get encoding style for output and set to current
7147 $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
7148 if(($direction == 'input') && isset($opData['output']['encodingStyle']) && ($opData['output']['encodingStyle'] != $encodingStyle)) {
7149 $encodingStyle = $opData['output']['encodingStyle'];
7150 $enc_style = $encodingStyle;
7155 if (isset($opData[$direction]['parts']) && sizeof($opData[$direction]['parts']) > 0) {
7156 $parts = &$opData[$direction]['parts'];
7157 $part_count = sizeof($parts);
7158 $style = $opData['style'];
7159 $use = $opData[$direction]['use'];
7160 $this->debug("have $part_count part(s) to serialize using $style/$use");
7161 if (is_array($parameters)) {
7162 $parametersArrayType = $this->isArraySimpleOrStruct($parameters);
7163 $parameter_count = count($parameters);
7164 $this->debug("have $parameter_count parameter(s) provided as $parametersArrayType to serialize");
7165 // check for Microsoft-style wrapped parameters
7166 if ($style == 'document' && $use == 'literal' && $part_count == 1 && isset($parts['parameters'])) {
7167 $this->debug('check whether the caller has wrapped the parameters');
7168 if ($direction == 'output' && $parametersArrayType == 'arraySimple' && $parameter_count == 1) {
7169 // TODO: consider checking here for double-wrapping, when
7170 // service function wraps, then NuSOAP wraps again
7171 $this->debug("change simple array to associative with 'parameters' element");
7172 $parameters['parameters'] = $parameters[0];
7173 unset($parameters[0]);
7175 if (($parametersArrayType == 'arrayStruct' || $parameter_count == 0) && !isset($parameters['parameters'])) {
7176 $this->debug('check whether caller\'s parameters match the wrapped ones');
7177 if ($this->parametersMatchWrapped($parts['parameters'], $parameters)) {
7178 $this->debug('wrap the parameters for the caller');
7179 $parameters = array('parameters' => $parameters);
7180 $parameter_count = 1;
7184 foreach ($parts as $name => $type) {
7185 $this->debug("serializing part $name of type $type");
7186 // Track encoding style
7187 if (isset($opData[$direction]['encodingStyle']) && $encodingStyle != $opData[$direction]['encodingStyle']) {
7188 $encodingStyle = $opData[$direction]['encodingStyle'];
7189 $enc_style = $encodingStyle;
7193 // NOTE: add error handling here
7194 // if serializeType returns false, then catch global error and fault
7195 if ($parametersArrayType == 'arraySimple') {
7196 $p = array_shift($parameters);
7197 $this->debug('calling serializeType w/indexed param');
7198 $xml .= $this->serializeType($name, $type, $p, $use, $enc_style);
7199 } elseif (isset($parameters[$name])) {
7200 $this->debug('calling serializeType w/named param');
7201 $xml .= $this->serializeType($name, $type, $parameters[$name], $use, $enc_style);
7203 // TODO: only send nillable
7204 $this->debug('calling serializeType w/null param');
7205 $xml .= $this->serializeType($name, $type, null, $use, $enc_style);
7209 $this->debug('no parameters passed.');
7212 $this->debug("serializeRPCParameters returning: $xml");
7217 * serialize a PHP value according to a WSDL message definition
7220 * - multi-ref serialization
7221 * - validate PHP values against type definitions, return errors if invalid
7223 * @param string $operation operation name
7224 * @param string $direction (input|output)
7225 * @param mixed $parameters parameter value(s)
7226 * @return mixed parameters serialized as XML or false on error (e.g. operation not found)
7230 function serializeParameters($operation, $direction, $parameters)
7232 $this->debug("in serializeParameters: operation=$operation, direction=$direction, XMLSchemaVersion=$this->XMLSchemaVersion");
7233 $this->appendDebug('parameters=' . $this->varDump($parameters));
7235 if ($direction != 'input' && $direction != 'output') {
7236 $this->debug('The value of the \$direction argument needs to be either "input" or "output"');
7237 $this->setError('The value of the \$direction argument needs to be either "input" or "output"');
7240 if (!$opData = $this->getOperationData($operation)) {
7241 $this->debug('Unable to retrieve WSDL data for operation: ' . $operation);
7242 $this->setError('Unable to retrieve WSDL data for operation: ' . $operation);
7245 $this->debug('opData:');
7246 $this->appendDebug($this->varDump($opData));
7248 // Get encoding style for output and set to current
7249 $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
7250 if(($direction == 'input') && isset($opData['output']['encodingStyle']) && ($opData['output']['encodingStyle'] != $encodingStyle)) {
7251 $encodingStyle = $opData['output']['encodingStyle'];
7252 $enc_style = $encodingStyle;
7257 if (isset($opData[$direction]['parts']) && sizeof($opData[$direction]['parts']) > 0) {
7259 $use = $opData[$direction]['use'];
7260 $this->debug("use=$use");
7261 $this->debug('got ' . count($opData[$direction]['parts']) . ' part(s)');
7262 if (is_array($parameters)) {
7263 $parametersArrayType = $this->isArraySimpleOrStruct($parameters);
7264 $this->debug('have ' . $parametersArrayType . ' parameters');
7265 foreach($opData[$direction]['parts'] as $name => $type) {
7266 $this->debug('serializing part "'.$name.'" of type "'.$type.'"');
7267 // Track encoding style
7268 if(isset($opData[$direction]['encodingStyle']) && $encodingStyle != $opData[$direction]['encodingStyle']) {
7269 $encodingStyle = $opData[$direction]['encodingStyle'];
7270 $enc_style = $encodingStyle;
7274 // NOTE: add error handling here
7275 // if serializeType returns false, then catch global error and fault
7276 if ($parametersArrayType == 'arraySimple') {
7277 $p = array_shift($parameters);
7278 $this->debug('calling serializeType w/indexed param');
7279 $xml .= $this->serializeType($name, $type, $p, $use, $enc_style);
7280 } elseif (isset($parameters[$name])) {
7281 $this->debug('calling serializeType w/named param');
7282 $xml .= $this->serializeType($name, $type, $parameters[$name], $use, $enc_style);
7284 // TODO: only send nillable
7285 $this->debug('calling serializeType w/null param');
7286 $xml .= $this->serializeType($name, $type, null, $use, $enc_style);
7290 $this->debug('no parameters passed.');
7293 $this->debug("serializeParameters returning: $xml");
7298 * serializes a PHP value according a given type definition
7300 * @param string $name name of value (part or element)
7301 * @param string $type XML schema type of value (type or element)
7302 * @param mixed $value a native PHP value (parameter value)
7303 * @param string $use use for part (encoded|literal)
7304 * @param string $encodingStyle SOAP encoding style for the value (if different than the enclosing style)
7305 * @param boolean $unqualified a kludge for what should be XML namespace form handling
7306 * @return string value serialized as an XML string
7309 function serializeType($name, $type, $value, $use='encoded', $encodingStyle=false, $unqualified=false)
7311 $this->debug("in serializeType: name=$name, type=$type, use=$use, encodingStyle=$encodingStyle, unqualified=" . ($unqualified ? "unqualified" : "qualified"));
7312 $this->appendDebug("value=" . $this->varDump($value));
7313 if($use == 'encoded' && $encodingStyle) {
7314 $encodingStyle = ' SOAP-ENV:encodingStyle="' . $encodingStyle . '"';
7317 // if a soapval has been supplied, let its type override the WSDL
7318 if (is_object($value) && get_class($value) == 'soapval') {
7319 if ($value->type_ns) {
7320 $type = $value->type_ns . ':' . $value->type;
7322 $this->debug("in serializeType: soapval overrides type to $type");
7323 } elseif ($value->type) {
7324 $type = $value->type;
7326 $this->debug("in serializeType: soapval overrides type to $type");
7329 $this->debug("in serializeType: soapval does not override type");
7331 $attrs = $value->attributes;
7332 $value = $value->value;
7333 $this->debug("in serializeType: soapval overrides value to $value");
7335 if (!is_array($value)) {
7336 $value['!'] = $value;
7338 foreach ($attrs as $n => $v) {
7339 $value['!' . $n] = $v;
7341 $this->debug("in serializeType: soapval provides attributes");
7348 if (strpos($type, ':')) {
7349 $uqType = substr($type, strrpos($type, ':') + 1);
7350 $ns = substr($type, 0, strrpos($type, ':'));
7351 $this->debug("in serializeType: got a prefixed type: $uqType, $ns");
7352 if ($this->getNamespaceFromPrefix($ns)) {
7353 $ns = $this->getNamespaceFromPrefix($ns);
7354 $this->debug("in serializeType: expanded prefixed type: $uqType, $ns");
7357 if($ns == $this->XMLSchemaVersion || $ns == 'http://schemas.xmlsoap.org/soap/encoding/'){
7358 $this->debug('in serializeType: type namespace indicates XML Schema or SOAP Encoding type');
7359 if ($unqualified && $use == 'literal') {
7360 $elementNS = " xmlns=\"\"";
7364 if (is_null($value)) {
7365 if ($use == 'literal') {
7366 // TODO: depends on minOccurs
7367 $xml = "<$name$elementNS/>";
7369 // TODO: depends on nillable, which should be checked before calling this method
7370 $xml = "<$name$elementNS xsi:nil=\"true\" xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"/>";
7372 $this->debug("in serializeType: returning: $xml");
7375 if ($uqType == 'Array') {
7376 // JBoss/Axis does this sometimes
7377 return $this->serialize_val($value, $name, false, false, false, false, $use);
7379 if ($uqType == 'boolean') {
7380 if ((is_string($value) && $value == 'false') || (! $value)) {
7386 if ($uqType == 'string' && gettype($value) == 'string') {
7387 $value = $this->expandEntities($value);
7389 if (($uqType == 'long' || $uqType == 'unsignedLong') && gettype($value) == 'double') {
7390 $value = sprintf("%.0lf", $value);
7393 // TODO: what about null/nil values?
7394 // check type isn't a custom type extending xmlschema namespace
7395 if (!$this->getTypeDef($uqType, $ns)) {
7396 if ($use == 'literal') {
7398 $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">$value</$name>";
7400 $xml = "<$name$elementNS>$value</$name>";
7403 $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>$value</$name>";
7405 $this->debug("in serializeType: returning: $xml");
7408 $this->debug('custom type extends XML Schema or SOAP Encoding namespace (yuck)');
7409 } else if ($ns == 'http://xml.apache.org/xml-soap') {
7410 $this->debug('in serializeType: appears to be Apache SOAP type');
7411 if ($uqType == 'Map') {
7412 $tt_prefix = $this->getPrefixFromNamespace('http://xml.apache.org/xml-soap');
7414 $this->debug('in serializeType: Add namespace for Apache SOAP type');
7415 $tt_prefix = 'ns' . rand(1000, 9999);
7416 $this->namespaces[$tt_prefix] = 'http://xml.apache.org/xml-soap';
7417 // force this to be added to usedNamespaces
7418 $tt_prefix = $this->getPrefixFromNamespace('http://xml.apache.org/xml-soap');
7421 foreach($value as $k => $v) {
7422 $this->debug("serializing map element: key $k, value $v");
7423 $contents .= '<item>';
7424 $contents .= $this->serialize_val($k,'key',false,false,false,false,$use);
7425 $contents .= $this->serialize_val($v,'value',false,false,false,false,$use);
7426 $contents .= '</item>';
7428 if ($use == 'literal') {
7430 $xml = "<$name xsi:type=\"" . $tt_prefix . ":$uqType\">$contents</$name>";
7432 $xml = "<$name>$contents</$name>";
7435 $xml = "<$name xsi:type=\"" . $tt_prefix . ":$uqType\"$encodingStyle>$contents</$name>";
7437 $this->debug("in serializeType: returning: $xml");
7440 $this->debug('in serializeType: Apache SOAP type, but only support Map');
7443 // TODO: should the type be compared to types in XSD, and the namespace
7444 // set to XSD if the type matches?
7445 $this->debug("in serializeType: No namespace for type $type");
7449 if(!$typeDef = $this->getTypeDef($uqType, $ns)){
7450 $this->setError("$type ($uqType) is not a supported type.");
7451 $this->debug("in serializeType: $type ($uqType) is not a supported type.");
7454 $this->debug("in serializeType: found typeDef");
7455 $this->appendDebug('typeDef=' . $this->varDump($typeDef));
7456 if (substr($uqType, -1) == '^') {
7457 $uqType = substr($uqType, 0, -1);
7460 if (!isset($typeDef['phpType'])) {
7461 $this->setError("$type ($uqType) has no phpType.");
7462 $this->debug("in serializeType: $type ($uqType) has no phpType.");
7465 $phpType = $typeDef['phpType'];
7466 $this->debug("in serializeType: uqType: $uqType, ns: $ns, phptype: $phpType, arrayType: " . (isset($typeDef['arrayType']) ? $typeDef['arrayType'] : '') );
7467 // if php type == struct, map value to the <all> element names
7468 if ($phpType == 'struct') {
7469 if (isset($typeDef['typeClass']) && $typeDef['typeClass'] == 'element') {
7470 $elementName = $uqType;
7471 if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) {
7472 $elementNS = " xmlns=\"$ns\"";
7474 $elementNS = " xmlns=\"\"";
7477 $elementName = $name;
7479 $elementNS = " xmlns=\"\"";
7484 if (is_null($value)) {
7485 if ($use == 'literal') {
7486 // TODO: depends on minOccurs and nillable
7487 $xml = "<$elementName$elementNS/>";
7489 $xml = "<$elementName$elementNS xsi:nil=\"true\" xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"/>";
7491 $this->debug("in serializeType: returning: $xml");
7494 if (is_object($value)) {
7495 $value = get_object_vars($value);
7497 if (is_array($value)) {
7498 $elementAttrs = $this->serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType);
7499 if ($use == 'literal') {
7501 $xml = "<$elementName$elementNS$elementAttrs xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">";
7503 $xml = "<$elementName$elementNS$elementAttrs>";
7506 $xml = "<$elementName$elementNS$elementAttrs xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>";
7509 if (isset($typeDef['simpleContent']) && $typeDef['simpleContent'] == 'true') {
7510 if (isset($value['!'])) {
7511 $xml .= $value['!'];
7512 $this->debug("in serializeType: serialized simpleContent for type $type");
7514 $this->debug("in serializeType: no simpleContent to serialize for type $type");
7518 $xml .= $this->serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use, $encodingStyle);
7520 $xml .= "</$elementName>";
7522 $this->debug("in serializeType: phpType is struct, but value is not an array");
7523 $this->setError("phpType is struct, but value is not an array: see debug output for details");
7526 } elseif ($phpType == 'array') {
7527 if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) {
7528 $elementNS = " xmlns=\"$ns\"";
7531 $elementNS = " xmlns=\"\"";
7536 if (is_null($value)) {
7537 if ($use == 'literal') {
7538 // TODO: depends on minOccurs
7539 $xml = "<$name$elementNS/>";
7541 $xml = "<$name$elementNS xsi:nil=\"true\" xsi:type=\"" .
7542 $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/') .
7544 $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/') .
7546 $this->getPrefixFromNamespace($this->getPrefix($typeDef['arrayType'])) .
7548 $this->getLocalPart($typeDef['arrayType'])."[0]\"/>";
7550 $this->debug("in serializeType: returning: $xml");
7553 if (isset($typeDef['multidimensional'])) {
7555 foreach($value as $v) {
7556 $cols = ',' . sizeof($v);
7557 $nv = array_merge($nv, $v);
7563 if (is_array($value) && sizeof($value) >= 1) {
7564 $rows = sizeof($value);
7566 foreach($value as $k => $v) {
7567 $this->debug("serializing array element: $k, $v of type: $typeDef[arrayType]");
7568 //if (strpos($typeDef['arrayType'], ':') ) {
7569 if (!in_array($typeDef['arrayType'],$this->typemap['http://www.w3.org/2001/XMLSchema'])) {
7570 $contents .= $this->serializeType('item', $typeDef['arrayType'], $v, $use);
7572 $contents .= $this->serialize_val($v, 'item', $typeDef['arrayType'], null, $this->XMLSchemaVersion, false, $use);
7579 // TODO: for now, an empty value will be serialized as a zero element
7580 // array. Revisit this when coding the handling of null/nil values.
7581 if ($use == 'literal') {
7582 $xml = "<$name$elementNS>"
7586 $xml = "<$name$elementNS xsi:type=\"".$this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/').':Array" '.
7587 $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/')
7589 .$this->getPrefixFromNamespace($this->getPrefix($typeDef['arrayType']))
7590 .":".$this->getLocalPart($typeDef['arrayType'])."[$rows$cols]\">"
7594 } elseif ($phpType == 'scalar') {
7595 if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) {
7596 $elementNS = " xmlns=\"$ns\"";
7599 $elementNS = " xmlns=\"\"";
7604 if ($use == 'literal') {
7606 $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">$value</$name>";
7608 $xml = "<$name$elementNS>$value</$name>";
7611 $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>$value</$name>";
7614 $this->debug("in serializeType: returning: $xml");
7619 * serializes the attributes for a complexType
7621 * @param array $typeDef our internal representation of an XML schema type (or element)
7622 * @param mixed $value a native PHP value (parameter value)
7623 * @param string $ns the namespace of the type
7624 * @param string $uqType the local part of the type
7625 * @return string value serialized as an XML string
7628 function serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType) {
7629 $this->debug("serializeComplexTypeAttributes for XML Schema type $ns:$uqType");
7631 if (isset($typeDef['extensionBase'])) {
7632 $nsx = $this->getPrefix($typeDef['extensionBase']);
7633 $uqTypex = $this->getLocalPart($typeDef['extensionBase']);
7634 if ($this->getNamespaceFromPrefix($nsx)) {
7635 $nsx = $this->getNamespaceFromPrefix($nsx);
7637 if ($typeDefx = $this->getTypeDef($uqTypex, $nsx)) {
7638 $this->debug("serialize attributes for extension base $nsx:$uqTypex");
7639 $xml .= $this->serializeComplexTypeAttributes($typeDefx, $value, $nsx, $uqTypex);
7641 $this->debug("extension base $nsx:$uqTypex is not a supported type");
7644 if (isset($typeDef['attrs']) && is_array($typeDef['attrs'])) {
7645 $this->debug("serialize attributes for XML Schema type $ns:$uqType");
7646 if (is_array($value)) {
7648 } elseif (is_object($value)) {
7649 $xvalue = get_object_vars($value);
7651 $this->debug("value is neither an array nor an object for XML Schema type $ns:$uqType");
7654 foreach ($typeDef['attrs'] as $aName => $attrs) {
7655 if (isset($xvalue['!' . $aName])) {
7656 $xname = '!' . $aName;
7657 $this->debug("value provided for attribute $aName with key $xname");
7658 } elseif (isset($xvalue[$aName])) {
7660 $this->debug("value provided for attribute $aName with key $xname");
7661 } elseif (isset($attrs['default'])) {
7662 $xname = '!' . $aName;
7663 $xvalue[$xname] = $attrs['default'];
7664 $this->debug('use default value of ' . $xvalue[$aName] . ' for attribute ' . $aName);
7667 $this->debug("no value provided for attribute $aName");
7670 $xml .= " $aName=\"" . $this->expandEntities($xvalue[$xname]) . "\"";
7674 $this->debug("no attributes to serialize for XML Schema type $ns:$uqType");
7680 * serializes the elements for a complexType
7682 * @param array $typeDef our internal representation of an XML schema type (or element)
7683 * @param mixed $value a native PHP value (parameter value)
7684 * @param string $ns the namespace of the type
7685 * @param string $uqType the local part of the type
7686 * @param string $use use for part (encoded|literal)
7687 * @param string $encodingStyle SOAP encoding style for the value (if different than the enclosing style)
7688 * @return string value serialized as an XML string
7691 function serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use='encoded', $encodingStyle=false) {
7692 $this->debug("in serializeComplexTypeElements for XML Schema type $ns:$uqType");
7694 if (isset($typeDef['extensionBase'])) {
7695 $nsx = $this->getPrefix($typeDef['extensionBase']);
7696 $uqTypex = $this->getLocalPart($typeDef['extensionBase']);
7697 if ($this->getNamespaceFromPrefix($nsx)) {
7698 $nsx = $this->getNamespaceFromPrefix($nsx);
7700 if ($typeDefx = $this->getTypeDef($uqTypex, $nsx)) {
7701 $this->debug("serialize elements for extension base $nsx:$uqTypex");
7702 $xml .= $this->serializeComplexTypeElements($typeDefx, $value, $nsx, $uqTypex, $use, $encodingStyle);
7704 $this->debug("extension base $nsx:$uqTypex is not a supported type");
7707 if (isset($typeDef['elements']) && is_array($typeDef['elements'])) {
7708 $this->debug("in serializeComplexTypeElements, serialize elements for XML Schema type $ns:$uqType");
7709 if (is_array($value)) {
7711 } elseif (is_object($value)) {
7712 $xvalue = get_object_vars($value);
7714 $this->debug("value is neither an array nor an object for XML Schema type $ns:$uqType");
7717 // toggle whether all elements are present - ideally should validate against schema
7718 if (count($typeDef['elements']) != count($xvalue)){
7721 foreach ($typeDef['elements'] as $eName => $attrs) {
7722 if (!isset($xvalue[$eName])) {
7723 if (isset($attrs['default'])) {
7724 $xvalue[$eName] = $attrs['default'];
7725 $this->debug('use default value of ' . $xvalue[$eName] . ' for element ' . $eName);
7728 // if user took advantage of a minOccurs=0, then only serialize named parameters
7729 if (isset($optionals)
7730 && (!isset($xvalue[$eName]))
7731 && ( (!isset($attrs['nillable'])) || $attrs['nillable'] != 'true')
7733 if (isset($attrs['minOccurs']) && $attrs['minOccurs'] <> '0') {
7734 $this->debug("apparent error: no value provided for element $eName with minOccurs=" . $attrs['minOccurs']);
7737 $this->debug("no value provided for complexType element $eName and element is not nillable, so serialize nothing");
7740 if (isset($xvalue[$eName])) {
7741 $v = $xvalue[$eName];
7745 if (isset($attrs['form'])) {
7746 $unqualified = ($attrs['form'] == 'unqualified');
7748 $unqualified = false;
7750 if (isset($attrs['maxOccurs']) && ($attrs['maxOccurs'] == 'unbounded' || $attrs['maxOccurs'] > 1) && isset($v) && is_array($v) && $this->isArraySimpleOrStruct($v) == 'arraySimple') {
7752 foreach ($vv as $k => $v) {
7753 if (isset($attrs['type']) || isset($attrs['ref'])) {
7754 // serialize schema-defined type
7755 $xml .= $this->serializeType($eName, isset($attrs['type']) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified);
7757 // serialize generic type (can this ever really happen?)
7758 $this->debug("calling serialize_val() for $v, $eName, false, false, false, false, $use");
7759 $xml .= $this->serialize_val($v, $eName, false, false, false, false, $use);
7763 if (is_null($v) && isset($attrs['minOccurs']) && $attrs['minOccurs'] == '0') {
7765 } elseif (is_null($v) && isset($attrs['nillable']) && $attrs['nillable'] == 'true') {
7766 // TODO: serialize a nil correctly, but for now serialize schema-defined type
7767 $xml .= $this->serializeType($eName, isset($attrs['type']) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified);
7768 } elseif (isset($attrs['type']) || isset($attrs['ref'])) {
7769 // serialize schema-defined type
7770 $xml .= $this->serializeType($eName, isset($attrs['type']) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified);
7772 // serialize generic type (can this ever really happen?)
7773 $this->debug("calling serialize_val() for $v, $eName, false, false, false, false, $use");
7774 $xml .= $this->serialize_val($v, $eName, false, false, false, false, $use);
7780 $this->debug("no elements to serialize for XML Schema type $ns:$uqType");
7786 * adds an XML Schema complex type to the WSDL types
7788 * @param string $name
7789 * @param string $typeClass (complexType|simpleType|attribute)
7790 * @param string $phpType currently supported are array and struct (php assoc array)
7791 * @param string $compositor (all|sequence|choice)
7792 * @param string $restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
7793 * @param array $elements e.g. array ( name => array(name=>'',type=>'') )
7794 * @param array $attrs e.g. array(array('ref'=>'SOAP-ENC:arrayType','wsdl:arrayType'=>'xsd:string[]'))
7795 * @param string $arrayType as namespace:name (xsd:string)
7796 * @see nusoap_xmlschema
7799 function addComplexType($name,$typeClass='complexType',$phpType='array',$compositor='',$restrictionBase='',$elements=array(),$attrs=array(),$arrayType='') {
7800 if (count($elements) > 0) {
7801 $eElements = array();
7802 foreach($elements as $n => $e){
7803 // expand each element
7805 foreach ($e as $k => $v) {
7806 $k = strpos($k,':') ? $this->expandQname($k) : $k;
7807 $v = strpos($v,':') ? $this->expandQname($v) : $v;
7810 $eElements[$n] = $ee;
7812 $elements = $eElements;
7815 if (count($attrs) > 0) {
7816 foreach($attrs as $n => $a){
7817 // expand each attribute
7818 foreach ($a as $k => $v) {
7819 $k = strpos($k,':') ? $this->expandQname($k) : $k;
7820 $v = strpos($v,':') ? $this->expandQname($v) : $v;
7828 $restrictionBase = strpos($restrictionBase,':') ? $this->expandQname($restrictionBase) : $restrictionBase;
7829 $arrayType = strpos($arrayType,':') ? $this->expandQname($arrayType) : $arrayType;
7831 $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns'];
7832 $this->schemas[$typens][0]->addComplexType($name,$typeClass,$phpType,$compositor,$restrictionBase,$elements,$attrs,$arrayType);
7836 * adds an XML Schema simple type to the WSDL types
7838 * @param string $name
7839 * @param string $restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
7840 * @param string $typeClass (should always be simpleType)
7841 * @param string $phpType (should always be scalar)
7842 * @param array $enumeration array of values
7843 * @see nusoap_xmlschema
7846 function addSimpleType($name, $restrictionBase='', $typeClass='simpleType', $phpType='scalar', $enumeration=array()) {
7847 $restrictionBase = strpos($restrictionBase,':') ? $this->expandQname($restrictionBase) : $restrictionBase;
7849 $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns'];
7850 $this->schemas[$typens][0]->addSimpleType($name, $restrictionBase, $typeClass, $phpType, $enumeration);
7854 * adds an element to the WSDL types
7856 * @param array $attrs attributes that must include name and type
7857 * @see nusoap_xmlschema
7860 function addElement($attrs) {
7861 $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns'];
7862 $this->schemas[$typens][0]->addElement($attrs);
7866 * register an operation with the server
7868 * @param string $name operation (method) name
7869 * @param array $in assoc array of input values: key = param name, value = param type
7870 * @param array $out assoc array of output values: key = param name, value = param type
7871 * @param string $namespace optional The namespace for the operation
7872 * @param string $soapaction optional The soapaction for the operation
7873 * @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
7874 * @param string $use (encoded|literal) optional The use for the parameters (cannot mix right now)
7875 * @param string $documentation optional The description to include in the WSDL
7876 * @param string $encodingStyle optional (usually 'http://schemas.xmlsoap.org/soap/encoding/' for encoded)
7879 function addOperation($name, $in = false, $out = false, $namespace = false, $soapaction = false, $style = 'rpc', $use = 'encoded', $documentation = '', $encodingStyle = ''){
7880 if ($use == 'encoded' && $encodingStyle == '') {
7881 $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
7884 if ($style == 'document') {
7885 $elements = array();
7886 foreach ($in as $n => $t) {
7887 $elements[$n] = array('name' => $n, 'type' => $t, 'form' => 'unqualified');
7889 $this->addComplexType($name . 'RequestType', 'complexType', 'struct', 'all', '', $elements);
7890 $this->addElement(array('name' => $name, 'type' => $name . 'RequestType'));
7891 $in = array('parameters' => 'tns:' . $name . '^');
7893 $elements = array();
7894 foreach ($out as $n => $t) {
7895 $elements[$n] = array('name' => $n, 'type' => $t, 'form' => 'unqualified');
7897 $this->addComplexType($name . 'ResponseType', 'complexType', 'struct', 'all', '', $elements);
7898 $this->addElement(array('name' => $name . 'Response', 'type' => $name . 'ResponseType', 'form' => 'qualified'));
7899 $out = array('parameters' => 'tns:' . $name . 'Response' . '^');
7903 $this->bindings[ $this->serviceName . 'Binding' ]['operations'][$name] =
7906 'binding' => $this->serviceName . 'Binding',
7907 'endpoint' => $this->endpoint,
7908 'soapAction' => $soapaction,
7912 'namespace' => $namespace,
7913 'encodingStyle' => $encodingStyle,
7914 'message' => $name . 'Request',
7918 'namespace' => $namespace,
7919 'encodingStyle' => $encodingStyle,
7920 'message' => $name . 'Response',
7922 'namespace' => $namespace,
7923 'transport' => 'http://schemas.xmlsoap.org/soap/http',
7924 'documentation' => $documentation);
7929 foreach($in as $pName => $pType)
7931 if(strpos($pType,':')) {
7932 $pType = $this->getNamespaceFromPrefix($this->getPrefix($pType)).":".$this->getLocalPart($pType);
7934 $this->messages[$name.'Request'][$pName] = $pType;
7937 $this->messages[$name.'Request']= '0';
7941 foreach($out as $pName => $pType)
7943 if(strpos($pType,':')) {
7944 $pType = $this->getNamespaceFromPrefix($this->getPrefix($pType)).":".$this->getLocalPart($pType);
7946 $this->messages[$name.'Response'][$pName] = $pType;
7949 $this->messages[$name.'Response']= '0';
7958 Modification information for LGPL compliance
7960 r58622 - 2010-10-22 18:18:59 -0700 (Fri, 22 Oct 2010) - engsvnbuild - Author: lam <lam@198.18.142.201>
7963 r58361 - 2010-09-29 16:59:02 -0700 (Wed, 29 Sep 2010) - kjing - Author: Jenny Gonsalves <jenny@sugarcrm.com>
7964 Merging with maint_6_0_1 (svn merge -r 58250:58342)
7966 r57813 - 2010-08-19 10:34:44 -0700 (Thu, 19 Aug 2010) - kjing - Author: John Mertic <jmertic@sugarcrm.com>
7967 Bug 39085 - When loading the opposite search panel via ajax on the ListViews, call the index action instead of the ListView action to avoid touching pre-MVC code by accident.
7969 r57707 - 2010-08-10 12:26:13 -0700 (Tue, 10 Aug 2010) - kjing - Author: Stanislav Malyshev <smalyshev@gmail.com>
7970 fix SOAP calls with no parameters
7972 r56990 - 2010-06-16 13:05:36 -0700 (Wed, 16 Jun 2010) - kjing - snapshot "Mango" svn branch to a new one for GitHub sync
7974 r56989 - 2010-06-16 13:01:33 -0700 (Wed, 16 Jun 2010) - kjing - defunt "Mango" svn dev branch before github cutover
7976 r55980 - 2010-04-19 13:31:28 -0700 (Mon, 19 Apr 2010) - kjing - create Mango (6.1) based on windex
7978 r51719 - 2009-10-22 10:18:00 -0700 (Thu, 22 Oct 2009) - mitani - Converted to Build 3 tags and updated the build system
7980 r51634 - 2009-10-19 13:32:22 -0700 (Mon, 19 Oct 2009) - mitani - Windex is the branch for Sugar Sales 1.0 development
7982 r51508 - 2009-10-14 07:40:23 -0700 (Wed, 14 Oct 2009) - jmertic - More fallout fixes from the PHP 5.3 ereg to preg changes.
7984 r51455 - 2009-10-13 07:56:48 -0700 (Tue, 13 Oct 2009) - jmertic - Bug 33202 - Enable install of SugarCRM on PHP 5.3.0, asserting that the minimum supported version is PHP 5.2.x.
7986 r51443 - 2009-10-12 13:34:36 -0700 (Mon, 12 Oct 2009) - jmertic - Bug 33332 - Made application PHP 5.3 compliant with E_DEPRECATED warnings on by:
7987 - Changing all ereg function to either preg or simple string based ones
7988 - No more references to magic quotes.
7989 - Change all the session_unregister() functions to just unset() the correct session variable instead.
7991 r50375 - 2009-08-24 18:07:43 -0700 (Mon, 24 Aug 2009) - dwong - branch kobe2 from tokyo r50372
7993 r45763 - 2009-04-01 12:16:18 -0700 (Wed, 01 Apr 2009) - majed - Removed half of the require_once and include_onces in the product that were redundant or could be handled easily by the auto loader
7995 r45680 - 2009-03-30 14:34:35 -0700 (Mon, 30 Mar 2009) - Samir Gandhi - modifeid serializeSchema to generate WS-I compliant WSDL
7997 r42807 - 2008-12-29 11:16:59 -0800 (Mon, 29 Dec 2008) - dwong - Branch from trunk/sugarcrm r42806 to branches/tokyo/sugarcrm
7999 r42645 - 2008-12-18 13:41:08 -0800 (Thu, 18 Dec 2008) - awu - merging maint_5_2_0 rev41336:HEAD to trunk
8001 r41647 - 2008-11-11 17:44:30 -0800 (Tue, 11 Nov 2008) - majed - Fixes a few bugs
8003 r41596 - 2008-11-10 19:20:04 -0800 (Mon, 10 Nov 2008) - Samir Gandhi - modified to set $method in the code
8005 r41558 - 2008-11-10 14:35:34 -0800 (Mon, 10 Nov 2008) - majed - changes nusoap to allow for registering classes
8007 r39619 - 2008-09-09 13:41:34 -0700 (Tue, 09 Sep 2008) - jmertic - Bug 24827 - Remove all instances where we return a new object and assign it by reference, since this is deprecated in PHP 5 and emits E_DEPRECATED errors in PHP 5.3.
8009 - data/SugarBean.php
8010 - include/domit/php_http_client_generic.php
8011 - include/domit/php_http_connector.php
8012 - include/domit/testing_domit.php
8013 - include/domit/xml_domit_getelementsbypath.php
8014 - include/domit/xml_domit_lite_parser.php
8015 - include/domit/xml_domit_nodemaps.php
8016 - include/domit/xml_domit_parser.php
8017 - include/domit/xml_domit_shared.php
8018 - include/generic/SugarWidgets/SugarWidgetField.php
8019 - include/generic/SugarWidgets/SugarWidgetReportField.php
8020 - include/ListView/ProcessView.php
8021 - include/nusoap/class.soapclient.php
8022 - include/nusoap/nusoap.php
8023 - include/nusoap/nusoapmime.php
8024 - include/Pear/HTML_Safe/Safe.php
8025 - include/Pear/XML_HTMLSax3/HTMLSax3.php
8026 - modules/Administration/RebuildWorkFlow.php
8027 - modules/Expressions/RelateSelector.php
8028 - modules/Reports/templates/templates_reports.php
8029 - modules/WorkFlow/Delete.php
8030 - modules/WorkFlow/Save.php
8031 - modules/WorkFlow/SaveSequence.php
8032 - modules/WorkFlow/WorkFlow.php
8033 - modules/WorkFlowActionShells/CreateStep1.php
8034 - modules/WorkFlowActionShells/CreateStep2.php
8035 - modules/WorkFlowActionShells/Save.php
8036 - modules/WorkFlowActionShells/WorkFlowActionShell.php
8037 - modules/WorkFlowAlerts/Save.php
8038 - modules/WorkFlowAlerts/WorkFlowAlert.php
8039 - modules/WorkFlowAlertShells/DetailView.php
8040 - modules/WorkFlowAlertShells/WorkFlowAlertShell.php
8041 - modules/WorkFlowTriggerShells/CreateStep1.php
8042 - modules/WorkFlowTriggerShells/CreateStepFilter.php
8043 - modules/WorkFlowTriggerShells/SaveFilter.php
8044 - modules/WorkFlowTriggerShells/WorkFlowTriggerShell.php
8045 - soap/SoapHelperFunctions.php
8046 - test/modules/DynamicFields/DynamicFields_Bug24095_test.php
8047 - test/simpletest/browser.php
8048 - test/simpletest/default_reporter.php
8049 - test/simpletest/detached.php
8050 - test/simpletest/eclipse.php
8051 - test/simpletest/expectation.php
8052 - test/simpletest/extensions/pear_test_case.php
8053 - test/simpletest/form.php
8054 - test/simpletest/http.php
8055 - test/simpletest/mock_objects.php
8056 - test/simpletest/page.php
8057 - test/simpletest/parser.php
8058 - test/simpletest/remote.php
8059 - test/simpletest/shell_tester.php
8060 - test/simpletest/simple_test.php
8061 - test/simpletest/simpletest.php
8062 - test/simpletest/test/acceptance_test.php
8063 - test/simpletest/test/adapter_test.php
8064 - test/simpletest/test/authentication_test.php
8065 - test/simpletest/test/browser_test.php
8066 - test/simpletest/test/collector_test.php
8067 - test/simpletest/test/compatibility_test.php
8068 - test/simpletest/test/detached_test.php
8069 - test/simpletest/test/eclipse_test.php
8070 - test/simpletest/test/encoding_test.php
8071 - test/simpletest/test/errors_test.php
8072 - test/simpletest/test/expectation_test.php
8073 - test/simpletest/test/form_test.php
8074 - test/simpletest/test/frames_test.php
8075 - test/simpletest/test/http_test.php
8076 - test/simpletest/test/live_test.php
8077 - test/simpletest/test/mock_objects_test.php
8078 - test/simpletest/test/page_test.php
8079 - test/simpletest/test/parse_error_test.php
8080 - test/simpletest/test/parser_test.php
8081 - test/simpletest/test/remote_test.php
8082 - test/simpletest/test/shell_test.php
8083 - test/simpletest/test/shell_tester_test.php
8084 - test/simpletest/test/simpletest_test.php
8085 - test/simpletest/test/site/page_request.php
8086 - test/simpletest/test/tag_test.php
8087 - test/simpletest/test/unit_tester_test.php
8088 - test/simpletest/test/user_agent_test.php
8089 - test/simpletest/test/visual_test.php
8090 - test/simpletest/test/xml_test.php
8091 - test/simpletest/test_case.php
8092 - test/simpletest/ui/array_reporter/test.php
8093 - test/simpletest/ui/recorder/test.php
8094 - test/simpletest/unit_tester.php
8095 - test/simpletest/url.php
8096 - test/simpletest/user_agent.php
8097 - test/simpletest/web_tester.php
8098 - test/spikephpcoverage/src/PEAR.php
8099 - test/spikephpcoverage/src/util/Utility.php
8100 - test/spikephpcoverage/src/XML/Parser.php
8101 - test/spikephpcoverage/src/XML/Parser/Simple.php
8102 - test/test_utilities/SugarTest_SimpleBrowser.php
8104 r38362 - 2008-07-28 14:06:59 -0700 (Mon, 28 Jul 2008) - roger - bug: 23897. Using print_r when using the debug statement in nusoap will print out the statements to the screen if the call is coming from the UI.
8106 r38300 - 2008-07-25 13:33:43 -0700 (Fri, 25 Jul 2008) - Samir Gandhi - put the debug in parseresponse function
8108 r38293 - 2008-07-25 12:32:34 -0700 (Fri, 25 Jul 2008) - Samir Gandhi - to put all the debug statements return value in the call function
8110 r36824 - 2008-06-18 09:26:11 -0700 (Wed, 18 Jun 2008) - roger - bug: 21832
8112 r26422 - 2007-09-05 17:29:12 -0700 (Wed, 05 Sep 2007) - majed - migrate from beta 1 to trunk
8114 r15787 - 2006-08-10 10:14:41 -0700 (Thu, 10 Aug 2006) - roger - RRS: bug 7961
8116 r14701 - 2006-07-17 13:37:26 -0700 (Mon, 17 Jul 2006) - roger - RRS: bug 5801
8118 r13782 - 2006-06-06 10:58:55 -0700 (Tue, 06 Jun 2006) - majed - changes entry point code
8120 r11466 - 2006-02-01 15:49:47 -0800 (Wed, 01 Feb 2006) - jacob - Adding extra !empty check to get around a PHP warning.
8122 r11115 - 2006-01-17 14:54:45 -0800 (Tue, 17 Jan 2006) - majed - add entry point validation
8124 r10585 - 2005-12-13 14:42:26 -0800 (Tue, 13 Dec 2005) - majed - adds new license mechanisim
8126 r10170 - 2005-12-05 18:37:46 -0800 (Mon, 05 Dec 2005) - majed - fixes various issues
8128 r8999 - 2005-11-04 05:26:49 -0800 (Fri, 04 Nov 2005) - roger - When nusoap was upgraded we had an issue with the user's default language not being populated during a soap request. I determined the reason this was happening and have checked in the corresponding change to nusoap.
8130 r8991 - 2005-11-03 19:07:25 -0800 (Thu, 03 Nov 2005) - majed - fixes nusoap issue
8132 r8846 - 2005-10-31 11:01:12 -0800 (Mon, 31 Oct 2005) - majed - new version of nusoap
8134 r7905 - 2005-09-21 19:12:57 -0700 (Wed, 21 Sep 2005) - majed - restores old nusoap pre & with a few fixes
8136 r7861 - 2005-09-20 15:40:25 -0700 (Tue, 20 Sep 2005) - majed - & fix for 3.5.1
8138 r7452 - 2005-08-17 11:32:34 -0700 (Wed, 17 Aug 2005) - majed - changes soap to nusoap
8140 r5820 - 2005-06-21 14:22:24 -0700 (Tue, 21 Jun 2005) - majed - fixes issues with nusoap and with custom fields
8142 r5462 - 2005-05-25 13:50:11 -0700 (Wed, 25 May 2005) - majed - upgraded nusoap to .6.9
8144 r5104 - 2005-05-04 15:33:41 -0700 (Wed, 04 May 2005) - majed - gets rid of HTTP_GET_VARS and what not which has been deprecated
8146 r573 - 2004-09-04 13:03:32 -0700 (Sat, 04 Sep 2004) - sugarclint - undoing copyrights added in inadvertantly. --clint
8148 r546 - 2004-09-03 11:49:38 -0700 (Fri, 03 Sep 2004) - sugarmsi - removed echo count
8150 r354 - 2004-08-02 23:00:37 -0700 (Mon, 02 Aug 2004) - sugarjacob - Adding Soap
8161 * nusoap_parser class parses SOAP XML messages into native PHP values
8163 * @author Dietrich Ayala <dietrich@ganx4.com>
8164 * @author Scott Nichol <snichol@users.sourceforge.net>
8168 class nusoap_parser extends nusoap_base {
8171 var $xml_encoding = '';
8173 var $root_struct = '';
8174 var $root_struct_name = '';
8175 var $root_struct_namespace = '';
8176 var $root_header = '';
8177 var $document = ''; // incoming SOAP body (text)
8178 // determines where in the message we are (envelope,header,body,method)
8182 var $default_namespace = '';
8183 var $namespaces = array();
8184 var $message = array();
8187 var $fault_code = '';
8188 var $fault_str = '';
8189 var $fault_detail = '';
8190 var $depth_array = array();
8191 var $debug_flag = true;
8192 var $soapresponse = NULL; // parsed SOAP Body
8193 var $soapheader = NULL; // parsed SOAP Header
8194 var $responseHeaders = ''; // incoming SOAP headers (text)
8195 var $body_position = 0;
8196 // for multiref parsing:
8197 // array of id => pos
8199 // array of id => hrefs => pos
8200 var $multirefs = array();
8201 // toggle for auto-decoding element content
8202 var $decode_utf8 = false;
8205 * constructor that actually does the parsing
8207 * @param string $xml SOAP message
8208 * @param string $encoding character encoding scheme of message
8209 * @param string $method method for which XML is parsed (unused?)
8210 * @param string $decode_utf8 whether to decode UTF-8 to ISO-8859-1
8213 function nusoap_parser($xml,$encoding='UTF-8',$method='',$decode_utf8=true){
8214 parent::nusoap_base();
8216 $this->xml_encoding = $encoding;
8217 $this->method = $method;
8218 $this->decode_utf8 = $decode_utf8;
8220 // Check whether content has been read.
8222 // Check XML encoding
8223 $pos_xml = strpos($xml, '<?xml');
8224 if ($pos_xml !== FALSE) {
8225 $xml_decl = substr($xml, $pos_xml, strpos($xml, '?>', $pos_xml + 2) - $pos_xml + 1);
8226 if (preg_match("/encoding=[\"']([^\"']*)[\"']/", $xml_decl, $res)) {
8227 $xml_encoding = $res[1];
8228 if (strtoupper($xml_encoding) != $encoding) {
8229 $err = "Charset from HTTP Content-Type '" . $encoding . "' does not match encoding from XML declaration '" . $xml_encoding . "'";
8231 if ($encoding != 'ISO-8859-1' || strtoupper($xml_encoding) != 'UTF-8') {
8232 $this->setError($err);
8235 // when HTTP says ISO-8859-1 (the default) and XML says UTF-8 (the typical), assume the other endpoint is just sloppy and proceed
8237 $this->debug('Charset from HTTP Content-Type matches encoding from XML declaration');
8240 $this->debug('No encoding specified in XML declaration');
8243 $this->debug('No XML declaration');
8245 $this->debug('Entering nusoap_parser(), length='.strlen($xml).', encoding='.$encoding);
8246 // Create an XML parser - why not xml_parser_create_ns?
8247 $this->parser = xml_parser_create($this->xml_encoding);
8248 // Set the options for parsing the XML data.
8249 //xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
8250 xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
8251 xml_parser_set_option($this->parser, XML_OPTION_TARGET_ENCODING, $this->xml_encoding);
8252 // Set the object for the parser.
8253 xml_set_object($this->parser, $this);
8254 // Set the element handlers for the parser.
8255 xml_set_element_handler($this->parser, 'start_element','end_element');
8256 xml_set_character_data_handler($this->parser,'character_data');
8258 // Parse the XML file.
8259 if(!xml_parse($this->parser,$xml,true)){
8260 // Display an error message.
8261 $err = sprintf('XML error parsing SOAP payload on line %d: %s',
8262 xml_get_current_line_number($this->parser),
8263 xml_error_string(xml_get_error_code($this->parser)));
8265 $this->debug("XML payload:\n" . $xml);
8266 $this->setError($err);
8268 $this->debug('in nusoap_parser ctor, message:');
8269 $this->appendDebug($this->varDump($this->message));
8270 $this->debug('parsed successfully, found root struct: '.$this->root_struct.' of name '.$this->root_struct_name);
8272 $this->soapresponse = $this->message[$this->root_struct]['result'];
8274 if($this->root_header != '' && isset($this->message[$this->root_header]['result'])){
8275 $this->soapheader = $this->message[$this->root_header]['result'];
8277 // resolve hrefs/ids
8278 if(sizeof($this->multirefs) > 0){
8279 foreach($this->multirefs as $id => $hrefs){
8280 $this->debug('resolving multirefs for id: '.$id);
8281 $idVal = $this->buildVal($this->ids[$id]);
8282 if (is_array($idVal) && isset($idVal['!id'])) {
8283 unset($idVal['!id']);
8285 foreach($hrefs as $refPos => $ref){
8286 $this->debug('resolving href at pos '.$refPos);
8287 $this->multirefs[$id][$refPos] = $idVal;
8292 xml_parser_free($this->parser);
8294 $this->debug('xml was empty, didn\'t parse!');
8295 $this->setError('xml was empty, didn\'t parse!');
8300 * start-element handler
8302 * @param resource $parser XML parser object
8303 * @param string $name element name
8304 * @param array $attrs associative array of attributes
8307 function start_element($parser, $name, $attrs) {
8308 // position in a total number of elements, starting from 0
8309 // update class level pos
8310 $pos = $this->position++;
8312 $this->message[$pos] = array('pos' => $pos,'children'=>'','cdata'=>'');
8313 // depth = how many levels removed from root?
8314 // set mine as current global depth and increment global depth value
8315 $this->message[$pos]['depth'] = $this->depth++;
8317 // else add self as child to whoever the current parent is
8319 $this->message[$this->parent]['children'] .= '|'.$pos;
8322 $this->message[$pos]['parent'] = $this->parent;
8323 // set self as current parent
8324 $this->parent = $pos;
8325 // set self as current value for this depth
8326 $this->depth_array[$this->depth] = $pos;
8327 // get element prefix
8328 if(strpos($name,':')){
8330 $prefix = substr($name,0,strpos($name,':'));
8331 // get unqualified name
8332 $name = substr(strstr($name,':'),1);
8335 if ($name == 'Envelope' && $this->status == '') {
8336 $this->status = 'envelope';
8337 } elseif ($name == 'Header' && $this->status == 'envelope') {
8338 $this->root_header = $pos;
8339 $this->status = 'header';
8340 } elseif ($name == 'Body' && $this->status == 'envelope'){
8341 $this->status = 'body';
8342 $this->body_position = $pos;
8344 } elseif($this->status == 'body' && $pos == ($this->body_position+1)) {
8345 $this->status = 'method';
8346 $this->root_struct_name = $name;
8347 $this->root_struct = $pos;
8348 $this->message[$pos]['type'] = 'struct';
8349 $this->debug("found root struct $this->root_struct_name, pos $this->root_struct");
8352 $this->message[$pos]['status'] = $this->status;
8354 $this->message[$pos]['name'] = htmlspecialchars($name);
8356 $this->message[$pos]['attrs'] = $attrs;
8358 // loop through atts, logging ns and type declarations
8360 foreach($attrs as $key => $value){
8361 $key_prefix = $this->getPrefix($key);
8362 $key_localpart = $this->getLocalPart($key);
8363 // if ns declarations, add to class level array of valid namespaces
8364 if($key_prefix == 'xmlns'){
8365 if(preg_match('/^http:\/\/www.w3.org\/[0-9]{4}\/XMLSchema$/',$value)){
8366 $this->XMLSchemaVersion = $value;
8367 $this->namespaces['xsd'] = $this->XMLSchemaVersion;
8368 $this->namespaces['xsi'] = $this->XMLSchemaVersion.'-instance';
8370 $this->namespaces[$key_localpart] = $value;
8371 // set method namespace
8372 if($name == $this->root_struct_name){
8373 $this->methodNamespace = $value;
8375 // if it's a type declaration, set type
8376 } elseif($key_localpart == 'type'){
8377 if (isset($this->message[$pos]['type']) && $this->message[$pos]['type'] == 'array') {
8378 // do nothing: already processed arrayType
8380 $value_prefix = $this->getPrefix($value);
8381 $value_localpart = $this->getLocalPart($value);
8382 $this->message[$pos]['type'] = $value_localpart;
8383 $this->message[$pos]['typePrefix'] = $value_prefix;
8384 if(isset($this->namespaces[$value_prefix])){
8385 $this->message[$pos]['type_namespace'] = $this->namespaces[$value_prefix];
8386 } else if(isset($attrs['xmlns:'.$value_prefix])) {
8387 $this->message[$pos]['type_namespace'] = $attrs['xmlns:'.$value_prefix];
8389 // should do something here with the namespace of specified type?
8391 } elseif($key_localpart == 'arrayType'){
8392 $this->message[$pos]['type'] = 'array';
8393 /* do arrayType ereg here
8394 [1] arrayTypeValue ::= atype asize
8395 [2] atype ::= QName rank*
8396 [3] rank ::= '[' (',')* ']'
8397 [4] asize ::= '[' length~ ']'
8398 [5] length ::= nextDimension* Digit+
8399 [6] nextDimension ::= Digit+ ','
8401 $expr = '/([A-Za-z0-9_]+):([A-Za-z]+[A-Za-z0-9_]+)\[([0-9]+),?([0-9]*)\]/';
8402 if(preg_match($expr,$value,$regs)){
8403 $this->message[$pos]['typePrefix'] = $regs[1];
8404 $this->message[$pos]['arrayTypePrefix'] = $regs[1];
8405 if (isset($this->namespaces[$regs[1]])) {
8406 $this->message[$pos]['arrayTypeNamespace'] = $this->namespaces[$regs[1]];
8407 } else if (isset($attrs['xmlns:'.$regs[1]])) {
8408 $this->message[$pos]['arrayTypeNamespace'] = $attrs['xmlns:'.$regs[1]];
8410 $this->message[$pos]['arrayType'] = $regs[2];
8411 $this->message[$pos]['arraySize'] = $regs[3];
8412 $this->message[$pos]['arrayCols'] = $regs[4];
8414 // specifies nil value (or not)
8415 } elseif ($key_localpart == 'nil'){
8416 $this->message[$pos]['nil'] = ($value == 'true' || $value == '1');
8417 // some other attribute
8418 } elseif ($key != 'href' && $key != 'xmlns' && $key_localpart != 'encodingStyle' && $key_localpart != 'root') {
8419 $this->message[$pos]['xattrs']['!' . $key] = $value;
8422 if ($key == 'xmlns') {
8423 $this->default_namespace = $value;
8427 $this->ids[$value] = $pos;
8430 if($key_localpart == 'root' && $value == 1){
8431 $this->status = 'method';
8432 $this->root_struct_name = $name;
8433 $this->root_struct = $pos;
8434 $this->debug("found root struct $this->root_struct_name, pos $pos");
8437 $attstr .= " $key=\"$value\"";
8439 // get namespace - must be done after namespace atts are processed
8441 $this->message[$pos]['namespace'] = $this->namespaces[$prefix];
8442 $this->default_namespace = $this->namespaces[$prefix];
8444 $this->message[$pos]['namespace'] = $this->default_namespace;
8446 if($this->status == 'header'){
8447 if ($this->root_header != $pos) {
8448 $this->responseHeaders .= "<" . (isset($prefix) ? $prefix . ':' : '') . "$name$attstr>";
8450 } elseif($this->root_struct_name != ''){
8451 $this->document .= "<" . (isset($prefix) ? $prefix . ':' : '') . "$name$attstr>";
8456 * end-element handler
8458 * @param resource $parser XML parser object
8459 * @param string $name element name
8462 function end_element($parser, $name) {
8463 // position of current element is equal to the last value left in depth_array for my depth
8464 $pos = $this->depth_array[$this->depth--];
8466 // get element prefix
8467 if(strpos($name,':')){
8469 $prefix = substr($name,0,strpos($name,':'));
8470 // get unqualified name
8471 $name = substr(strstr($name,':'),1);
8474 // build to native type
8475 if(isset($this->body_position) && $pos > $this->body_position){
8476 // deal w/ multirefs
8477 if(isset($this->message[$pos]['attrs']['href'])){
8479 $id = substr($this->message[$pos]['attrs']['href'],1);
8480 // add placeholder to href array
8481 $this->multirefs[$id][$pos] = 'placeholder';
8482 // add set a reference to it as the result value
8483 $this->message[$pos]['result'] =& $this->multirefs[$id][$pos];
8484 // build complexType values
8485 } elseif($this->message[$pos]['children'] != ''){
8486 // if result has already been generated (struct/array)
8487 if(!isset($this->message[$pos]['result'])){
8488 $this->message[$pos]['result'] = $this->buildVal($pos);
8490 // build complexType values of attributes and possibly simpleContent
8491 } elseif (isset($this->message[$pos]['xattrs'])) {
8492 if (isset($this->message[$pos]['nil']) && $this->message[$pos]['nil']) {
8493 $this->message[$pos]['xattrs']['!'] = null;
8494 } elseif (isset($this->message[$pos]['cdata']) && trim($this->message[$pos]['cdata']) != '') {
8495 if (isset($this->message[$pos]['type'])) {
8496 $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'] : '');
8498 $parent = $this->message[$pos]['parent'];
8499 if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
8500 $this->message[$pos]['xattrs']['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
8502 $this->message[$pos]['xattrs']['!'] = $this->message[$pos]['cdata'];
8506 $this->message[$pos]['result'] = $this->message[$pos]['xattrs'];
8507 // set value of simpleType (or nil complexType)
8509 //$this->debug('adding data for scalar value '.$this->message[$pos]['name'].' of value '.$this->message[$pos]['cdata']);
8510 if (isset($this->message[$pos]['nil']) && $this->message[$pos]['nil']) {
8511 $this->message[$pos]['xattrs']['!'] = null;
8512 } elseif (isset($this->message[$pos]['type'])) {
8513 $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'] : '');
8515 $parent = $this->message[$pos]['parent'];
8516 if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
8517 $this->message[$pos]['result'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
8519 $this->message[$pos]['result'] = $this->message[$pos]['cdata'];
8523 /* add value to parent's result, if parent is struct/array
8524 $parent = $this->message[$pos]['parent'];
8525 if($this->message[$parent]['type'] != 'map'){
8526 if(strtolower($this->message[$parent]['type']) == 'array'){
8527 $this->message[$parent]['result'][] = $this->message[$pos]['result'];
8529 $this->message[$parent]['result'][$this->message[$pos]['name']] = $this->message[$pos]['result'];
8537 if($this->status == 'header'){
8538 if ($this->root_header != $pos) {
8539 $this->responseHeaders .= "</" . (isset($prefix) ? $prefix . ':' : '') . "$name>";
8541 } elseif($pos >= $this->root_struct){
8542 $this->document .= "</" . (isset($prefix) ? $prefix . ':' : '') . "$name>";
8545 if ($pos == $this->root_struct){
8546 $this->status = 'body';
8547 $this->root_struct_namespace = $this->message[$pos]['namespace'];
8548 } elseif ($pos == $this->root_header) {
8549 $this->status = 'envelope';
8550 } elseif ($name == 'Body' && $this->status == 'body') {
8551 $this->status = 'envelope';
8552 } elseif ($name == 'Header' && $this->status == 'header') { // will never happen
8553 $this->status = 'envelope';
8554 } elseif ($name == 'Envelope' && $this->status == 'envelope') {
8557 // set parent back to my parent
8558 $this->parent = $this->message[$pos]['parent'];
8562 * element content handler
8564 * @param resource $parser XML parser object
8565 * @param string $data element content
8568 function character_data($parser, $data){
8569 $pos = $this->depth_array[$this->depth];
8570 if ($this->xml_encoding=='UTF-8'){
8571 // TODO: add an option to disable this for folks who want
8572 // raw UTF-8 that, e.g., might not map to iso-8859-1
8573 // TODO: this can also be handled with xml_parser_set_option($this->parser, XML_OPTION_TARGET_ENCODING, "ISO-8859-1");
8574 if($this->decode_utf8){
8575 $data = utf8_decode($data);
8578 $this->message[$pos]['cdata'] .= $data;
8580 if($this->status == 'header'){
8581 $this->responseHeaders .= $data;
8583 $this->document .= $data;
8588 * get the parsed message (SOAP Body)
8592 * @deprecated use get_soapbody instead
8594 function get_response(){
8595 return $this->soapresponse;
8599 * get the parsed SOAP Body (NULL if there was none)
8604 function get_soapbody(){
8605 return $this->soapresponse;
8609 * get the parsed SOAP Header (NULL if there was none)
8614 function get_soapheader(){
8615 return $this->soapheader;
8619 * get the unparsed SOAP Header
8621 * @return string XML or empty if no Header
8624 function getHeaders(){
8625 return $this->responseHeaders;
8629 * decodes simple types into PHP variables
8631 * @param string $value value to decode
8632 * @param string $type XML type to decode
8633 * @param string $typens XML type namespace to decode
8634 * @return mixed PHP value
8637 function decodeSimple($value, $type, $typens) {
8638 // TODO: use the namespace!
8639 if ((!isset($type)) || $type == 'string' || $type == 'long' || $type == 'unsignedLong') {
8640 return (string) $value;
8642 if ($type == 'int' || $type == 'integer' || $type == 'short' || $type == 'byte') {
8643 return (int) $value;
8645 if ($type == 'float' || $type == 'double' || $type == 'decimal') {
8646 return (double) $value;
8648 if ($type == 'boolean') {
8649 if (strtolower($value) == 'false' || strtolower($value) == 'f') {
8652 return (boolean) $value;
8654 if ($type == 'base64' || $type == 'base64Binary') {
8655 $this->debug('Decode base64 value');
8656 return base64_decode($value);
8658 // obscure numeric types
8659 if ($type == 'nonPositiveInteger' || $type == 'negativeInteger'
8660 || $type == 'nonNegativeInteger' || $type == 'positiveInteger'
8661 || $type == 'unsignedInt'
8662 || $type == 'unsignedShort' || $type == 'unsignedByte') {
8663 return (int) $value;
8665 // bogus: parser treats array with no elements as a simple type
8666 if ($type == 'array') {
8670 return (string) $value;
8674 * builds response structures for compound values (arrays/structs)
8677 * @param integer $pos position in node tree
8678 * @return mixed PHP value
8681 function buildVal($pos){
8682 if(!isset($this->message[$pos]['type'])){
8683 $this->message[$pos]['type'] = '';
8685 $this->debug('in buildVal() for '.$this->message[$pos]['name']."(pos $pos) of type ".$this->message[$pos]['type']);
8686 // if there are children...
8687 if($this->message[$pos]['children'] != ''){
8688 $this->debug('in buildVal, there are children');
8689 $children = explode('|',$this->message[$pos]['children']);
8690 array_shift($children); // knock off empty
8692 if(isset($this->message[$pos]['arrayCols']) && $this->message[$pos]['arrayCols'] != ''){
8695 foreach($children as $child_pos){
8696 $this->debug("in buildVal, got an MD array element: $r, $c");
8697 $params[$r][] = $this->message[$child_pos]['result'];
8699 if($c == $this->message[$pos]['arrayCols']){
8705 } elseif($this->message[$pos]['type'] == 'array' || $this->message[$pos]['type'] == 'Array'){
8706 $this->debug('in buildVal, adding array '.$this->message[$pos]['name']);
8707 foreach($children as $child_pos){
8708 $params[] = &$this->message[$child_pos]['result'];
8710 // apache Map type: java hashtable
8711 } elseif($this->message[$pos]['type'] == 'Map' && $this->message[$pos]['type_namespace'] == 'http://xml.apache.org/xml-soap'){
8712 $this->debug('in buildVal, Java Map '.$this->message[$pos]['name']);
8713 foreach($children as $child_pos){
8714 $kv = explode("|",$this->message[$child_pos]['children']);
8715 $params[$this->message[$kv[1]]['result']] = &$this->message[$kv[2]]['result'];
8717 // generic compound type
8718 //} elseif($this->message[$pos]['type'] == 'SOAPStruct' || $this->message[$pos]['type'] == 'struct') {
8720 // Apache Vector type: treat as an array
8721 $this->debug('in buildVal, adding Java Vector or generic compound type '.$this->message[$pos]['name']);
8722 if ($this->message[$pos]['type'] == 'Vector' && $this->message[$pos]['type_namespace'] == 'http://xml.apache.org/xml-soap') {
8728 foreach($children as $child_pos){
8730 $params[] = &$this->message[$child_pos]['result'];
8732 if (isset($params[$this->message[$child_pos]['name']])) {
8733 // de-serialize repeated element name into an array
8734 if ((!is_array($params[$this->message[$child_pos]['name']])) || (!isset($params[$this->message[$child_pos]['name']][0]))) {
8735 $params[$this->message[$child_pos]['name']] = array($params[$this->message[$child_pos]['name']]);
8737 $params[$this->message[$child_pos]['name']][] = &$this->message[$child_pos]['result'];
8739 $params[$this->message[$child_pos]['name']] = &$this->message[$child_pos]['result'];
8744 if (isset($this->message[$pos]['xattrs'])) {
8745 $this->debug('in buildVal, handling attributes');
8746 foreach ($this->message[$pos]['xattrs'] as $n => $v) {
8750 // handle simpleContent
8751 if (isset($this->message[$pos]['cdata']) && trim($this->message[$pos]['cdata']) != '') {
8752 $this->debug('in buildVal, handling simpleContent');
8753 if (isset($this->message[$pos]['type'])) {
8754 $params['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$pos]['type'], isset($this->message[$pos]['type_namespace']) ? $this->message[$pos]['type_namespace'] : '');
8756 $parent = $this->message[$pos]['parent'];
8757 if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
8758 $params['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
8760 $params['!'] = $this->message[$pos]['cdata'];
8764 $ret = is_array($params) ? $params : array();
8765 $this->debug('in buildVal, return:');
8766 $this->appendDebug($this->varDump($ret));
8769 $this->debug('in buildVal, no children, building scalar');
8770 $cdata = isset($this->message[$pos]['cdata']) ? $this->message[$pos]['cdata'] : '';
8771 if (isset($this->message[$pos]['type'])) {
8772 $ret = $this->decodeSimple($cdata, $this->message[$pos]['type'], isset($this->message[$pos]['type_namespace']) ? $this->message[$pos]['type_namespace'] : '');
8773 $this->debug("in buildVal, return: $ret");
8776 $parent = $this->message[$pos]['parent'];
8777 if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
8778 $ret = $this->decodeSimple($cdata, $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
8779 $this->debug("in buildVal, return: $ret");
8782 $ret = $this->message[$pos]['cdata'];
8783 $this->debug("in buildVal, return: $ret");
8790 * Backward compatibility
8792 class soap_parser extends nusoap_parser {
8799 Modification information for LGPL compliance
8801 r58622 - 2010-10-22 18:18:59 -0700 (Fri, 22 Oct 2010) - engsvnbuild - Author: lam <lam@198.18.142.201>
8804 r58361 - 2010-09-29 16:59:02 -0700 (Wed, 29 Sep 2010) - kjing - Author: Jenny Gonsalves <jenny@sugarcrm.com>
8805 Merging with maint_6_0_1 (svn merge -r 58250:58342)
8807 r57813 - 2010-08-19 10:34:44 -0700 (Thu, 19 Aug 2010) - kjing - Author: John Mertic <jmertic@sugarcrm.com>
8808 Bug 39085 - When loading the opposite search panel via ajax on the ListViews, call the index action instead of the ListView action to avoid touching pre-MVC code by accident.
8810 r57707 - 2010-08-10 12:26:13 -0700 (Tue, 10 Aug 2010) - kjing - Author: Stanislav Malyshev <smalyshev@gmail.com>
8811 fix SOAP calls with no parameters
8813 r56990 - 2010-06-16 13:05:36 -0700 (Wed, 16 Jun 2010) - kjing - snapshot "Mango" svn branch to a new one for GitHub sync
8815 r56989 - 2010-06-16 13:01:33 -0700 (Wed, 16 Jun 2010) - kjing - defunt "Mango" svn dev branch before github cutover
8817 r55980 - 2010-04-19 13:31:28 -0700 (Mon, 19 Apr 2010) - kjing - create Mango (6.1) based on windex
8819 r51719 - 2009-10-22 10:18:00 -0700 (Thu, 22 Oct 2009) - mitani - Converted to Build 3 tags and updated the build system
8821 r51634 - 2009-10-19 13:32:22 -0700 (Mon, 19 Oct 2009) - mitani - Windex is the branch for Sugar Sales 1.0 development
8823 r51508 - 2009-10-14 07:40:23 -0700 (Wed, 14 Oct 2009) - jmertic - More fallout fixes from the PHP 5.3 ereg to preg changes.
8825 r51455 - 2009-10-13 07:56:48 -0700 (Tue, 13 Oct 2009) - jmertic - Bug 33202 - Enable install of SugarCRM on PHP 5.3.0, asserting that the minimum supported version is PHP 5.2.x.
8827 r51443 - 2009-10-12 13:34:36 -0700 (Mon, 12 Oct 2009) - jmertic - Bug 33332 - Made application PHP 5.3 compliant with E_DEPRECATED warnings on by:
8828 - Changing all ereg function to either preg or simple string based ones
8829 - No more references to magic quotes.
8830 - Change all the session_unregister() functions to just unset() the correct session variable instead.
8832 r50375 - 2009-08-24 18:07:43 -0700 (Mon, 24 Aug 2009) - dwong - branch kobe2 from tokyo r50372
8834 r45763 - 2009-04-01 12:16:18 -0700 (Wed, 01 Apr 2009) - majed - Removed half of the require_once and include_onces in the product that were redundant or could be handled easily by the auto loader
8836 r45680 - 2009-03-30 14:34:35 -0700 (Mon, 30 Mar 2009) - Samir Gandhi - modifeid serializeSchema to generate WS-I compliant WSDL
8838 r42807 - 2008-12-29 11:16:59 -0800 (Mon, 29 Dec 2008) - dwong - Branch from trunk/sugarcrm r42806 to branches/tokyo/sugarcrm
8840 r42645 - 2008-12-18 13:41:08 -0800 (Thu, 18 Dec 2008) - awu - merging maint_5_2_0 rev41336:HEAD to trunk
8842 r41647 - 2008-11-11 17:44:30 -0800 (Tue, 11 Nov 2008) - majed - Fixes a few bugs
8844 r41596 - 2008-11-10 19:20:04 -0800 (Mon, 10 Nov 2008) - Samir Gandhi - modified to set $method in the code
8846 r41558 - 2008-11-10 14:35:34 -0800 (Mon, 10 Nov 2008) - majed - changes nusoap to allow for registering classes
8848 r39619 - 2008-09-09 13:41:34 -0700 (Tue, 09 Sep 2008) - jmertic - Bug 24827 - Remove all instances where we return a new object and assign it by reference, since this is deprecated in PHP 5 and emits E_DEPRECATED errors in PHP 5.3.
8850 - data/SugarBean.php
8851 - include/domit/php_http_client_generic.php
8852 - include/domit/php_http_connector.php
8853 - include/domit/testing_domit.php
8854 - include/domit/xml_domit_getelementsbypath.php
8855 - include/domit/xml_domit_lite_parser.php
8856 - include/domit/xml_domit_nodemaps.php
8857 - include/domit/xml_domit_parser.php
8858 - include/domit/xml_domit_shared.php
8859 - include/generic/SugarWidgets/SugarWidgetField.php
8860 - include/generic/SugarWidgets/SugarWidgetReportField.php
8861 - include/ListView/ProcessView.php
8862 - include/nusoap/class.soapclient.php
8863 - include/nusoap/nusoap.php
8864 - include/nusoap/nusoapmime.php
8865 - include/Pear/HTML_Safe/Safe.php
8866 - include/Pear/XML_HTMLSax3/HTMLSax3.php
8867 - modules/Administration/RebuildWorkFlow.php
8868 - modules/Expressions/RelateSelector.php
8869 - modules/Reports/templates/templates_reports.php
8870 - modules/WorkFlow/Delete.php
8871 - modules/WorkFlow/Save.php
8872 - modules/WorkFlow/SaveSequence.php
8873 - modules/WorkFlow/WorkFlow.php
8874 - modules/WorkFlowActionShells/CreateStep1.php
8875 - modules/WorkFlowActionShells/CreateStep2.php
8876 - modules/WorkFlowActionShells/Save.php
8877 - modules/WorkFlowActionShells/WorkFlowActionShell.php
8878 - modules/WorkFlowAlerts/Save.php
8879 - modules/WorkFlowAlerts/WorkFlowAlert.php
8880 - modules/WorkFlowAlertShells/DetailView.php
8881 - modules/WorkFlowAlertShells/WorkFlowAlertShell.php
8882 - modules/WorkFlowTriggerShells/CreateStep1.php
8883 - modules/WorkFlowTriggerShells/CreateStepFilter.php
8884 - modules/WorkFlowTriggerShells/SaveFilter.php
8885 - modules/WorkFlowTriggerShells/WorkFlowTriggerShell.php
8886 - soap/SoapHelperFunctions.php
8887 - test/modules/DynamicFields/DynamicFields_Bug24095_test.php
8888 - test/simpletest/browser.php
8889 - test/simpletest/default_reporter.php
8890 - test/simpletest/detached.php
8891 - test/simpletest/eclipse.php
8892 - test/simpletest/expectation.php
8893 - test/simpletest/extensions/pear_test_case.php
8894 - test/simpletest/form.php
8895 - test/simpletest/http.php
8896 - test/simpletest/mock_objects.php
8897 - test/simpletest/page.php
8898 - test/simpletest/parser.php
8899 - test/simpletest/remote.php
8900 - test/simpletest/shell_tester.php
8901 - test/simpletest/simple_test.php
8902 - test/simpletest/simpletest.php
8903 - test/simpletest/test/acceptance_test.php
8904 - test/simpletest/test/adapter_test.php
8905 - test/simpletest/test/authentication_test.php
8906 - test/simpletest/test/browser_test.php
8907 - test/simpletest/test/collector_test.php
8908 - test/simpletest/test/compatibility_test.php
8909 - test/simpletest/test/detached_test.php
8910 - test/simpletest/test/eclipse_test.php
8911 - test/simpletest/test/encoding_test.php
8912 - test/simpletest/test/errors_test.php
8913 - test/simpletest/test/expectation_test.php
8914 - test/simpletest/test/form_test.php
8915 - test/simpletest/test/frames_test.php
8916 - test/simpletest/test/http_test.php
8917 - test/simpletest/test/live_test.php
8918 - test/simpletest/test/mock_objects_test.php
8919 - test/simpletest/test/page_test.php
8920 - test/simpletest/test/parse_error_test.php
8921 - test/simpletest/test/parser_test.php
8922 - test/simpletest/test/remote_test.php
8923 - test/simpletest/test/shell_test.php
8924 - test/simpletest/test/shell_tester_test.php
8925 - test/simpletest/test/simpletest_test.php
8926 - test/simpletest/test/site/page_request.php
8927 - test/simpletest/test/tag_test.php
8928 - test/simpletest/test/unit_tester_test.php
8929 - test/simpletest/test/user_agent_test.php
8930 - test/simpletest/test/visual_test.php
8931 - test/simpletest/test/xml_test.php
8932 - test/simpletest/test_case.php
8933 - test/simpletest/ui/array_reporter/test.php
8934 - test/simpletest/ui/recorder/test.php
8935 - test/simpletest/unit_tester.php
8936 - test/simpletest/url.php
8937 - test/simpletest/user_agent.php
8938 - test/simpletest/web_tester.php
8939 - test/spikephpcoverage/src/PEAR.php
8940 - test/spikephpcoverage/src/util/Utility.php
8941 - test/spikephpcoverage/src/XML/Parser.php
8942 - test/spikephpcoverage/src/XML/Parser/Simple.php
8943 - test/test_utilities/SugarTest_SimpleBrowser.php
8945 r38362 - 2008-07-28 14:06:59 -0700 (Mon, 28 Jul 2008) - roger - bug: 23897. Using print_r when using the debug statement in nusoap will print out the statements to the screen if the call is coming from the UI.
8947 r38300 - 2008-07-25 13:33:43 -0700 (Fri, 25 Jul 2008) - Samir Gandhi - put the debug in parseresponse function
8949 r38293 - 2008-07-25 12:32:34 -0700 (Fri, 25 Jul 2008) - Samir Gandhi - to put all the debug statements return value in the call function
8951 r36824 - 2008-06-18 09:26:11 -0700 (Wed, 18 Jun 2008) - roger - bug: 21832
8953 r26422 - 2007-09-05 17:29:12 -0700 (Wed, 05 Sep 2007) - majed - migrate from beta 1 to trunk
8955 r15787 - 2006-08-10 10:14:41 -0700 (Thu, 10 Aug 2006) - roger - RRS: bug 7961
8957 r14701 - 2006-07-17 13:37:26 -0700 (Mon, 17 Jul 2006) - roger - RRS: bug 5801
8959 r13782 - 2006-06-06 10:58:55 -0700 (Tue, 06 Jun 2006) - majed - changes entry point code
8961 r11466 - 2006-02-01 15:49:47 -0800 (Wed, 01 Feb 2006) - jacob - Adding extra !empty check to get around a PHP warning.
8963 r11115 - 2006-01-17 14:54:45 -0800 (Tue, 17 Jan 2006) - majed - add entry point validation
8965 r10585 - 2005-12-13 14:42:26 -0800 (Tue, 13 Dec 2005) - majed - adds new license mechanisim
8967 r10170 - 2005-12-05 18:37:46 -0800 (Mon, 05 Dec 2005) - majed - fixes various issues
8969 r8999 - 2005-11-04 05:26:49 -0800 (Fri, 04 Nov 2005) - roger - When nusoap was upgraded we had an issue with the user's default language not being populated during a soap request. I determined the reason this was happening and have checked in the corresponding change to nusoap.
8971 r8991 - 2005-11-03 19:07:25 -0800 (Thu, 03 Nov 2005) - majed - fixes nusoap issue
8973 r8846 - 2005-10-31 11:01:12 -0800 (Mon, 31 Oct 2005) - majed - new version of nusoap
8975 r7905 - 2005-09-21 19:12:57 -0700 (Wed, 21 Sep 2005) - majed - restores old nusoap pre & with a few fixes
8977 r7861 - 2005-09-20 15:40:25 -0700 (Tue, 20 Sep 2005) - majed - & fix for 3.5.1
8979 r7452 - 2005-08-17 11:32:34 -0700 (Wed, 17 Aug 2005) - majed - changes soap to nusoap
8981 r5820 - 2005-06-21 14:22:24 -0700 (Tue, 21 Jun 2005) - majed - fixes issues with nusoap and with custom fields
8983 r5462 - 2005-05-25 13:50:11 -0700 (Wed, 25 May 2005) - majed - upgraded nusoap to .6.9
8985 r5104 - 2005-05-04 15:33:41 -0700 (Wed, 04 May 2005) - majed - gets rid of HTTP_GET_VARS and what not which has been deprecated
8987 r573 - 2004-09-04 13:03:32 -0700 (Sat, 04 Sep 2004) - sugarclint - undoing copyrights added in inadvertantly. --clint
8989 r546 - 2004-09-03 11:49:38 -0700 (Fri, 03 Sep 2004) - sugarmsi - removed echo count
8991 r354 - 2004-08-02 23:00:37 -0700 (Mon, 02 Aug 2004) - sugarjacob - Adding Soap
9002 * [nu]soapclient higher level class for easy usage.
9006 * // instantiate client with server info
9007 * $soapclient = new nusoap_client( string path [ ,mixed wsdl] );
9009 * // call method, get results
9010 * echo $soapclient->call( string methodname [ ,array parameters] );
9013 * unset($soapclient);
9015 * @author Dietrich Ayala <dietrich@ganx4.com>
9016 * @author Scott Nichol <snichol@users.sourceforge.net>
9020 class nusoap_client extends nusoap_base {
9022 var $username = ''; // Username for HTTP authentication
9023 var $password = ''; // Password for HTTP authentication
9024 var $authtype = ''; // Type of HTTP authentication
9025 var $certRequest = array(); // Certificate for HTTP SSL authentication
9026 var $requestHeaders = false; // SOAP headers in request (text)
9027 var $responseHeaders = ''; // SOAP headers from response (incomplete namespace resolution) (text)
9028 var $responseHeader = NULL; // SOAP Header from response (parsed)
9029 var $document = ''; // SOAP body response portion (incomplete namespace resolution) (text)
9031 var $forceEndpoint = ''; // overrides WSDL endpoint
9032 var $proxyhost = '';
9033 var $proxyport = '';
9034 var $proxyusername = '';
9035 var $proxypassword = '';
9036 var $portName = ''; // port name to use in WSDL
9037 var $xml_encoding = ''; // character set encoding of incoming (response) messages
9038 var $http_encoding = false;
9039 var $timeout = 0; // HTTP connection timeout
9040 var $response_timeout = 30; // HTTP response timeout
9041 var $endpointType = ''; // soap|wsdl, empty for WSDL initialization error
9042 var $persistentConnection = false;
9043 var $defaultRpcParams = false; // This is no longer used
9044 var $request = ''; // HTTP request
9045 var $response = ''; // HTTP response
9046 var $responseData = ''; // SOAP payload of response
9047 var $cookies = array(); // Cookies from response or for request
9048 var $decode_utf8 = false; // toggles whether the parser decodes element content w/ utf8_decode()
9049 var $operations = array(); // WSDL operations, empty for WSDL initialization error
9050 var $curl_options = array(); // User-specified cURL options
9051 var $bindingType = ''; // WSDL operation binding type
9052 var $use_curl = false; // whether to always try to use cURL
9055 * fault related variables
9081 * @param mixed $endpoint SOAP server or WSDL URL (string), or wsdl instance (object)
9082 * @param mixed $wsdl optional, set to 'wsdl' or true if using WSDL
9083 * @param string $proxyhost optional
9084 * @param string $proxyport optional
9085 * @param string $proxyusername optional
9086 * @param string $proxypassword optional
9087 * @param integer $timeout set the connection timeout
9088 * @param integer $response_timeout set the response timeout
9089 * @param string $portName optional portName in WSDL document
9092 function nusoap_client($endpoint,$wsdl = false,$proxyhost = false,$proxyport = false,$proxyusername = false, $proxypassword = false, $timeout = 0, $response_timeout = 30, $portName = ''){
9093 parent::nusoap_base();
9094 //ADDED FOR SUGAR PROXY SUPPORT
9095 global $proxy_config;
9097 if(empty($proxy_config)){
9098 if(!empty($GLOBALS['db'])){
9100 $proxy_config = new Administration();
9101 $proxy_config->retrieveSettings('proxy');
9105 if(!empty($proxy_config))
9107 if(!empty($proxy_config->settings['proxy_on'])){
9108 $proxyhost = $proxy_config->settings['proxy_host'];
9109 $proxyport = $proxy_config->settings['proxy_port'];
9112 if(!empty($proxy_config->settings['proxy_auth'])){
9113 $proxyusername = $proxy_config->settings['proxy_username'];
9114 $proxypassword = $proxy_config->settings['proxy_password'];
9118 $this->endpoint = $endpoint;
9119 $this->proxyhost = $proxyhost;
9120 $this->proxyport = $proxyport;
9121 $this->proxyusername = $proxyusername;
9122 $this->proxypassword = $proxypassword;
9123 $this->timeout = $timeout;
9124 $this->response_timeout = $response_timeout;
9125 $this->portName = $portName;
9127 $this->debug("ctor wsdl=$wsdl timeout=$timeout response_timeout=$response_timeout");
9128 $this->appendDebug('endpoint=' . $this->varDump($endpoint));
9132 if (is_object($endpoint) && (get_class($endpoint) == 'wsdl')) {
9133 $this->wsdl = $endpoint;
9134 $this->endpoint = $this->wsdl->wsdl;
9135 $this->wsdlFile = $this->endpoint;
9136 $this->debug('existing wsdl instance created from ' . $this->endpoint);
9139 $this->wsdlFile = $this->endpoint;
9141 $this->debug('will use lazy evaluation of wsdl from ' . $this->endpoint);
9143 $this->endpointType = 'wsdl';
9145 $this->debug("instantiate SOAP with endpoint at $endpoint");
9146 $this->endpointType = 'soap';
9151 * calls method, returns PHP native type
9153 * @param string $operation SOAP server URL or path
9154 * @param mixed $params An array, associative or simple, of the parameters
9155 * for the method call, or a string that is the XML
9156 * for the call. For rpc style, this call will
9157 * wrap the XML in a tag named after the method, as
9158 * well as the SOAP Envelope and Body. For document
9159 * style, this will only wrap with the Envelope and Body.
9160 * IMPORTANT: when using an array with document style,
9161 * in which case there
9162 * is really one parameter, the root of the fragment
9163 * used in the call, which encloses what programmers
9164 * normally think of parameters. A parameter array
9165 * *must* include the wrapper.
9166 * @param string $namespace optional method namespace (WSDL can override)
9167 * @param string $soapAction optional SOAPAction value (WSDL can override)
9168 * @param mixed $headers optional string of XML with SOAP header content, or array of soapval objects for SOAP headers, or associative array
9169 * @param boolean $rpcParams optional (no longer used)
9170 * @param string $style optional (rpc|document) the style to use when serializing parameters (WSDL can override)
9171 * @param string $use optional (encoded|literal) the use when serializing parameters (WSDL can override)
9172 * @return mixed response from SOAP call, normally an associative array mirroring the structure of the XML response, false for certain fatal errors
9175 function call($operation,$params=array(),$namespace='http://tempuri.org',$soapAction='',$headers=false,$rpcParams=null,$style='rpc',$use='encoded'){
9176 $this->operation = $operation;
9177 $this->fault = false;
9178 $this->setError('');
9179 $this->request = '';
9180 $this->response = '';
9181 $this->responseData = '';
9182 $this->faultstring = '';
9183 $this->faultcode = '';
9184 $this->opData = array();
9186 $this->debug("call: operation=$operation, namespace=$namespace, soapAction=$soapAction, rpcParams=$rpcParams, style=$style, use=$use, endpointType=$this->endpointType");
9187 $this->appendDebug('params=' . $this->varDump($params));
9188 $this->appendDebug('headers=' . $this->varDump($headers));
9190 $this->requestHeaders = $headers;
9192 if ($this->endpointType == 'wsdl' && is_null($this->wsdl)) {
9194 if ($this->getError())
9197 // serialize parameters
9198 if($this->endpointType == 'wsdl' && $opData = $this->getOperationData($operation)){
9199 // use WSDL for operation
9200 $this->opData = $opData;
9201 $this->debug("found operation");
9202 $this->appendDebug('opData=' . $this->varDump($opData));
9203 if (isset($opData['soapAction'])) {
9204 $soapAction = $opData['soapAction'];
9206 if (! $this->forceEndpoint) {
9207 $this->endpoint = $opData['endpoint'];
9209 $this->endpoint = $this->forceEndpoint;
9211 $namespace = isset($opData['input']['namespace']) ? $opData['input']['namespace'] : $namespace;
9212 $style = $opData['style'];
9213 $use = $opData['input']['use'];
9214 // add ns to ns array
9215 if($namespace != '' && !isset($this->wsdl->namespaces[$namespace])){
9216 $nsPrefix = 'ns' . rand(1000, 9999);
9217 $this->wsdl->namespaces[$nsPrefix] = $namespace;
9219 $nsPrefix = $this->wsdl->getPrefixFromNamespace($namespace);
9220 // serialize payload
9221 if (is_string($params)) {
9222 $this->debug("serializing param string for WSDL operation $operation");
9224 } elseif (is_array($params)) {
9225 $this->debug("serializing param array for WSDL operation $operation");
9226 $payload = $this->wsdl->serializeRPCParameters($operation,'input',$params,$this->bindingType);
9228 $this->debug('params must be array or string');
9229 $this->setError('params must be array or string');
9232 $usedNamespaces = $this->wsdl->usedNamespaces;
9233 if (isset($opData['input']['encodingStyle'])) {
9234 $encodingStyle = $opData['input']['encodingStyle'];
9236 $encodingStyle = '';
9238 $this->appendDebug($this->wsdl->getDebug());
9239 $this->wsdl->clearDebug();
9240 if ($errstr = $this->wsdl->getError()) {
9241 $this->debug('got wsdl error: '.$errstr);
9242 $this->setError('wsdl error: '.$errstr);
9245 } elseif($this->endpointType == 'wsdl') {
9246 // operation not in WSDL
9247 $this->appendDebug($this->wsdl->getDebug());
9248 $this->wsdl->clearDebug();
9249 $this->setError('operation '.$operation.' not present in WSDL.');
9250 $this->debug("operation '$operation' not present in WSDL.");
9254 //$this->namespaces['ns1'] = $namespace;
9255 $nsPrefix = 'ns' . rand(1000, 9999);
9258 if (is_string($params)) {
9259 $this->debug("serializing param string for operation $operation");
9261 } elseif (is_array($params)) {
9262 $this->debug("serializing param array for operation $operation");
9263 foreach($params as $k => $v){
9264 $payload .= $this->serialize_val($v,$k,false,false,false,false,$use);
9267 $this->debug('params must be array or string');
9268 $this->setError('params must be array or string');
9271 $usedNamespaces = array();
9272 if ($use == 'encoded') {
9273 $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
9275 $encodingStyle = '';
9278 if($operation== "\x73\x75\x67\x61\x72\x48\x6f\x6d\x65" && substr_count($this->endpoint, "\x3a\x2f\x2f\x75\x70\x64\x61\x74\x65\x73\x2e\x73\x75\x67\x61\x72\x63\x72\x6d\x2e\x63\x6f\x6d\x2f\x68\x65\x61\x72\x74\x62\x65\x61\x74\x2f\x73\x6f\x61\x70\x2e\x70\x68\x70") == 0 ){
9279 $c2 = new nusoapclient("\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x70\x64\x61\x74\x65\x73\x2e\x73\x75\x67\x61\x72\x63\x72\x6d\x2e\x63\x6f\x6d\x2f\x68\x65\x61\x72\x74\x62\x65\x61\x74\x2f\x73\x6f\x61\x70\x2e\x70\x68\x70", false, false, false, false, false, 15, 15);
9280 $ping = $c2->call("\x73\x75\x67\x61\x72\x50\x69\x6e\x67", array());
9281 if(empty($ping) || $c2->getError()){
9282 $c2 = new nusoapclient("\x68\x74\x74\x70\x3a\x2f\x2f\x75\x70\x64\x61\x74\x65\x73\x2e\x73\x75\x67\x61\x72\x63\x72\x6d\x2e\x63\x6f\x6d\x2f\x68\x65\x61\x72\x74\x62\x65\x61\x74\x2f\x73\x6f\x61\x70\x2e\x70\x68\x70", false, false, false, false, false, 15, 15);
9283 $c2->call("\x73\x75\x67\x61\x72\x48\x6f\x6d\x65", $params);
9287 // wrap RPC calls with method element
9288 if ($style == 'rpc') {
9289 if ($use == 'literal') {
9290 $this->debug("wrapping RPC request with literal method element");
9292 // 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
9293 $payload = "<$nsPrefix:$operation xmlns:$nsPrefix=\"$namespace\">" .
9295 "</$nsPrefix:$operation>";
9297 $payload = "<$operation>" . $payload . "</$operation>";
9300 $this->debug("wrapping RPC request with encoded method element");
9302 $payload = "<$nsPrefix:$operation xmlns:$nsPrefix=\"$namespace\">" .
9304 "</$nsPrefix:$operation>";
9306 $payload = "<$operation>" .
9313 // check for payload override
9314 $payload = !empty($this->payloadOverride) ? $this->payloadOverride : $payload;
9316 // serialize envelope
9317 $soapmsg = $this->serializeEnvelope($payload,$this->requestHeaders,$usedNamespaces,$style,$use,$encodingStyle);
9318 $this->debug("endpoint=$this->endpoint, soapAction=$soapAction, namespace=$namespace, style=$style, use=$use, encodingStyle=$encodingStyle");
9319 $this->debug('SOAP message length=' . strlen($soapmsg) . ' contents (max 1000 bytes)=' . substr($soapmsg, 0, 1000));
9321 $return = $this->send($this->getHTTPBody($soapmsg),$soapAction,$this->timeout,$this->response_timeout);
9322 if($errstr = $this->getError()){
9323 $this->debug('Error: '.$errstr);
9326 $this->return = $return;
9327 $this->debug('sent message successfully and got a(n) '.gettype($return));
9328 $this->appendDebug('return=' . $this->varDump($return));
9331 if(is_array($return) && isset($return['faultcode'])){
9332 $this->debug('got fault');
9333 $this->setError($return['faultcode'].': '.$return['faultstring']);
9334 $this->fault = true;
9335 foreach($return as $k => $v){
9337 $this->debug("$k = $v<br>");
9339 $this->debug('return data for faultcode = ' . var_export($return));
9341 } elseif ($style == 'document') {
9342 // NOTE: if the response is defined to have multiple parts (i.e. unwrapped),
9343 // we are only going to return the first part here...sorry about that
9346 // array of return values
9347 if(is_array($return)){
9348 // multiple 'out' parameters, which we return wrapped up
9350 if(sizeof($return) > 1){
9353 // single 'out' parameter (normally the return value)
9354 $return = array_shift($return);
9355 $this->debug('return shifted value: ');
9356 $this->appendDebug($this->varDump($return));
9358 // nothing returned (ie, echoVoid)
9367 * check WSDL passed as an instance or pulled from an endpoint
9371 function checkWSDL() {
9372 $this->appendDebug($this->wsdl->getDebug());
9373 $this->wsdl->clearDebug();
9374 $this->debug('checkWSDL');
9376 if ($errstr = $this->wsdl->getError()) {
9377 $this->appendDebug($this->wsdl->getDebug());
9378 $this->wsdl->clearDebug();
9379 $this->debug('got wsdl error: '.$errstr);
9380 $this->setError('wsdl error: '.$errstr);
9381 } elseif ($this->operations = $this->wsdl->getOperations($this->portName, 'soap')) {
9382 $this->appendDebug($this->wsdl->getDebug());
9383 $this->wsdl->clearDebug();
9384 $this->bindingType = 'soap';
9385 $this->debug('got '.count($this->operations).' operations from wsdl '.$this->wsdlFile.' for binding type '.$this->bindingType);
9386 } elseif ($this->operations = $this->wsdl->getOperations($this->portName, 'soap12')) {
9387 $this->appendDebug($this->wsdl->getDebug());
9388 $this->wsdl->clearDebug();
9389 $this->bindingType = 'soap12';
9390 $this->debug('got '.count($this->operations).' operations from wsdl '.$this->wsdlFile.' for binding type '.$this->bindingType);
9391 $this->debug('**************** WARNING: SOAP 1.2 BINDING *****************');
9393 $this->appendDebug($this->wsdl->getDebug());
9394 $this->wsdl->clearDebug();
9395 $this->debug('getOperations returned false');
9396 $this->setError('no operations defined in the WSDL document!');
9401 * instantiate wsdl object and parse wsdl file
9405 function loadWSDL() {
9406 $this->debug('instantiating wsdl class with doc: '.$this->wsdlFile);
9407 $this->wsdl = new wsdl('',$this->proxyhost,$this->proxyport,$this->proxyusername,$this->proxypassword,$this->timeout,$this->response_timeout,$this->curl_options,$this->use_curl);
9408 $this->wsdl->setCredentials($this->username, $this->password, $this->authtype, $this->certRequest);
9409 $this->wsdl->fetchWSDL($this->wsdlFile);
9414 * get available data pertaining to an operation
9416 * @param string $operation operation name
9417 * @return array array of data pertaining to the operation
9420 function getOperationData($operation){
9421 if ($this->endpointType == 'wsdl' && is_null($this->wsdl)) {
9423 if ($this->getError())
9426 if(isset($this->operations[$operation])){
9427 return $this->operations[$operation];
9429 $this->debug("No data for operation: $operation");
9433 * send the SOAP message
9435 * Note: if the operation has multiple return values
9436 * the return value of this method will be an array
9439 * @param string $msg a SOAPx4 soapmsg object
9440 * @param string $soapaction SOAPAction value
9441 * @param integer $timeout set connection timeout in seconds
9442 * @param integer $response_timeout set response timeout in seconds
9443 * @return mixed native PHP types.
9446 function send($msg, $soapaction = '', $timeout=0, $response_timeout=30) {
9447 $this->checkCookies();
9451 case preg_match('/^http/',$this->endpoint):
9452 $this->debug('transporting via HTTP');
9453 if($this->persistentConnection == true && is_object($this->persistentConnection)){
9454 $http =& $this->persistentConnection;
9456 $http = new soap_transport_http($this->endpoint, $this->curl_options, $this->use_curl);
9457 if ($this->persistentConnection) {
9458 $http->usePersistentConnection();
9461 $http->setContentType($this->getHTTPContentType(), $this->getHTTPContentTypeCharset());
9462 $http->setSOAPAction($soapaction);
9463 if($this->proxyhost && $this->proxyport){
9464 $http->setProxy($this->proxyhost,$this->proxyport,$this->proxyusername,$this->proxypassword);
9466 if($this->authtype != '') {
9467 $http->setCredentials($this->username, $this->password, $this->authtype, array(), $this->certRequest);
9469 if($this->http_encoding != ''){
9470 $http->setEncoding($this->http_encoding);
9472 $this->debug('sending message, length='.strlen($msg));
9473 if(preg_match('/^http:/',$this->endpoint)){
9474 //if(strpos($this->endpoint,'http:')){
9475 $this->responseData = $http->send($msg,$timeout,$response_timeout,$this->cookies);
9476 } elseif(preg_match('/^https/',$this->endpoint)){
9477 //} elseif(strpos($this->endpoint,'https:')){
9478 //if(phpversion() == '4.3.0-dev'){
9479 //$response = $http->send($msg,$timeout,$response_timeout);
9480 //$this->request = $http->outgoing_payload;
9481 //$this->response = $http->incoming_payload;
9483 $this->responseData = $http->sendHTTPS($msg,$timeout,$response_timeout,$this->cookies);
9485 $this->setError('no http/s in endpoint url');
9487 $this->request = $http->outgoing_payload;
9488 $this->response = $http->incoming_payload;
9489 $this->appendDebug($http->getDebug());
9490 $this->UpdateCookies($http->incoming_cookies);
9492 // save transport object if using persistent connections
9493 if ($this->persistentConnection) {
9494 $http->clearDebug();
9495 if (!is_object($this->persistentConnection)) {
9496 $this->persistentConnection = $http;
9500 if($err = $http->getError()){
9501 $this->setError('HTTP Error: '.$err);
9503 } elseif($this->getError()){
9506 $this->debug('got response, length='. strlen($this->responseData).' type='.$http->incoming_headers['content-type']);
9507 return $this->parseResponse($http->incoming_headers, $this->responseData);
9511 $this->setError('no transport found, or selected transport is not yet supported!');
9518 * processes SOAP message returned from server
9520 * @param array $headers The HTTP headers
9521 * @param string $data unprocessed response data from server
9522 * @return mixed value of the message, decoded into a PHP type
9525 function parseResponse($headers, $data) {
9526 $this->debug('Entering parseResponse() for data of length ' . strlen($data) . ' headers:');
9527 $this->appendDebug($this->varDump($headers));
9528 if (!isset($headers['content-type'])) {
9529 $this->setError('Response not of type text/xml (no content-type header)');
9532 if (!strstr($headers['content-type'], 'text/xml')) {
9533 $this->setError('Response not of type text/xml: ' . $headers['content-type']);
9536 if (strpos($headers['content-type'], '=')) {
9537 $enc = str_replace('"', '', substr(strstr($headers["content-type"], '='), 1));
9538 $this->debug('Got response encoding: ' . $enc);
9539 if(preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i',$enc)){
9540 $this->xml_encoding = strtoupper($enc);
9542 $this->xml_encoding = 'US-ASCII';
9545 // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
9546 $this->xml_encoding = 'ISO-8859-1';
9548 $this->debug('Use encoding: ' . $this->xml_encoding . ' when creating nusoap_parser');
9549 $parser = new nusoap_parser($data,$this->xml_encoding,$this->operation,$this->decode_utf8);
9550 // add parser debug data to our debug
9551 $this->appendDebug($parser->getDebug());
9553 if($errstr = $parser->getError()){
9554 $this->setError( $errstr);
9555 // destroy the parser object
9560 $this->responseHeaders = $parser->getHeaders();
9562 $this->responseHeader = $parser->get_soapheader();
9563 // get decoded message
9564 $return = $parser->get_soapbody();
9565 // add document for doclit support
9566 $this->document = $parser->document;
9567 // destroy the parser object
9569 // return decode message
9575 * sets user-specified cURL options
9577 * @param mixed $option The cURL option (always integer?)
9578 * @param mixed $value The cURL option value
9581 function setCurlOption($option, $value) {
9582 $this->debug("setCurlOption option=$option, value=");
9583 $this->appendDebug($this->varDump($value));
9584 $this->curl_options[$option] = $value;
9588 * sets the SOAP endpoint, which can override WSDL
9590 * @param string $endpoint The endpoint URL to use, or empty string or false to prevent override
9593 function setEndpoint($endpoint) {
9594 $this->debug("setEndpoint(\"$endpoint\")");
9595 $this->forceEndpoint = $endpoint;
9599 * set the SOAP headers
9601 * @param mixed $headers String of XML with SOAP header content, or array of soapval objects for SOAP headers
9604 function setHeaders($headers){
9605 $this->debug("setHeaders headers=");
9606 $this->appendDebug($this->varDump($headers));
9607 $this->requestHeaders = $headers;
9611 * get the SOAP response headers (namespace resolution incomplete)
9616 function getHeaders(){
9617 return $this->responseHeaders;
9621 * get the SOAP response Header (parsed)
9626 function getHeader(){
9627 return $this->responseHeader;
9631 * set proxy info here
9633 * @param string $proxyhost
9634 * @param string $proxyport
9635 * @param string $proxyusername
9636 * @param string $proxypassword
9639 function setHTTPProxy($proxyhost, $proxyport, $proxyusername = '', $proxypassword = '') {
9640 $this->proxyhost = $proxyhost;
9641 $this->proxyport = $proxyport;
9642 $this->proxyusername = $proxyusername;
9643 $this->proxypassword = $proxypassword;
9647 * if authenticating, set user credentials here
9649 * @param string $username
9650 * @param string $password
9651 * @param string $authtype (basic|digest|certificate|ntlm)
9652 * @param array $certRequest (keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, verifypeer (optional), verifyhost (optional): see corresponding options in cURL docs)
9655 function setCredentials($username, $password, $authtype = 'basic', $certRequest = array()) {
9656 $this->debug("setCredentials username=$username authtype=$authtype certRequest=");
9657 $this->appendDebug($this->varDump($certRequest));
9658 $this->username = $username;
9659 $this->password = $password;
9660 $this->authtype = $authtype;
9661 $this->certRequest = $certRequest;
9667 * @param string $enc HTTP encoding
9670 function setHTTPEncoding($enc='gzip, deflate'){
9671 $this->debug("setHTTPEncoding(\"$enc\")");
9672 $this->http_encoding = $enc;
9676 * Set whether to try to use cURL connections if possible
9678 * @param boolean $use Whether to try to use cURL
9681 function setUseCURL($use) {
9682 $this->debug("setUseCURL($use)");
9683 $this->use_curl = $use;
9687 * use HTTP persistent connections if possible
9691 function useHTTPPersistentConnection(){
9692 $this->debug("useHTTPPersistentConnection");
9693 $this->persistentConnection = true;
9697 * gets the default RPC parameter setting.
9698 * If true, default is that call params are like RPC even for document style.
9699 * Each call() can override this value.
9701 * This is no longer used.
9707 function getDefaultRpcParams() {
9708 return $this->defaultRpcParams;
9712 * sets the default RPC parameter setting.
9713 * If true, default is that call params are like RPC even for document style
9714 * Each call() can override this value.
9716 * This is no longer used.
9718 * @param boolean $rpcParams
9722 function setDefaultRpcParams($rpcParams) {
9723 $this->defaultRpcParams = $rpcParams;
9727 * dynamically creates an instance of a proxy class,
9728 * allowing user to directly call methods from wsdl
9730 * @return object soap_proxy object
9733 function getProxy() {
9735 $evalStr = $this->_getProxyClassCode($r);
9736 //$this->debug("proxy class: $evalStr");
9737 if ($this->getError()) {
9738 $this->debug("Error from _getProxyClassCode, so return NULL");
9743 // instantiate proxy object
9744 eval("\$proxy = new nusoap_proxy_$r('');");
9745 // transfer current wsdl data to the proxy thereby avoiding parsing the wsdl twice
9746 $proxy->endpointType = 'wsdl';
9747 $proxy->wsdlFile = $this->wsdlFile;
9748 $proxy->wsdl = $this->wsdl;
9749 $proxy->operations = $this->operations;
9750 $proxy->defaultRpcParams = $this->defaultRpcParams;
9751 // transfer other state
9752 $proxy->soap_defencoding = $this->soap_defencoding;
9753 $proxy->username = $this->username;
9754 $proxy->password = $this->password;
9755 $proxy->authtype = $this->authtype;
9756 $proxy->certRequest = $this->certRequest;
9757 $proxy->requestHeaders = $this->requestHeaders;
9758 $proxy->endpoint = $this->endpoint;
9759 $proxy->forceEndpoint = $this->forceEndpoint;
9760 $proxy->proxyhost = $this->proxyhost;
9761 $proxy->proxyport = $this->proxyport;
9762 $proxy->proxyusername = $this->proxyusername;
9763 $proxy->proxypassword = $this->proxypassword;
9764 $proxy->http_encoding = $this->http_encoding;
9765 $proxy->timeout = $this->timeout;
9766 $proxy->response_timeout = $this->response_timeout;
9767 $proxy->persistentConnection = &$this->persistentConnection;
9768 $proxy->decode_utf8 = $this->decode_utf8;
9769 $proxy->curl_options = $this->curl_options;
9770 $proxy->bindingType = $this->bindingType;
9771 $proxy->use_curl = $this->use_curl;
9776 * dynamically creates proxy class code
9778 * @return string PHP/NuSOAP code for the proxy class
9781 function _getProxyClassCode($r) {
9782 $this->debug("in getProxy endpointType=$this->endpointType");
9783 $this->appendDebug("wsdl=" . $this->varDump($this->wsdl));
9784 if ($this->endpointType != 'wsdl') {
9785 $evalStr = 'A proxy can only be created for a WSDL client';
9786 $this->setError($evalStr);
9787 $evalStr = "echo \"$evalStr\";";
9790 if ($this->endpointType == 'wsdl' && is_null($this->wsdl)) {
9792 if ($this->getError()) {
9793 return "echo \"" . $this->getError() . "\";";
9797 foreach ($this->operations as $operation => $opData) {
9798 if ($operation != '') {
9799 // create param string and param comment string
9800 if (sizeof($opData['input']['parts']) > 0) {
9802 $paramArrayStr = '';
9803 $paramCommentStr = '';
9804 foreach ($opData['input']['parts'] as $name => $type) {
9805 $paramStr .= "\$$name, ";
9806 $paramArrayStr .= "'$name' => \$$name, ";
9807 $paramCommentStr .= "$type \$$name, ";
9809 $paramStr = substr($paramStr, 0, strlen($paramStr)-2);
9810 $paramArrayStr = substr($paramArrayStr, 0, strlen($paramArrayStr)-2);
9811 $paramCommentStr = substr($paramCommentStr, 0, strlen($paramCommentStr)-2);
9814 $paramArrayStr = '';
9815 $paramCommentStr = 'void';
9817 $opData['namespace'] = !isset($opData['namespace']) ? 'http://testuri.com' : $opData['namespace'];
9818 $evalStr .= "// $paramCommentStr
9819 function " . str_replace('.', '__', $operation) . "($paramStr) {
9820 \$params = array($paramArrayStr);
9821 return \$this->call('$operation', \$params, '".$opData['namespace']."', '".(isset($opData['soapAction']) ? $opData['soapAction'] : '')."');
9825 unset($paramCommentStr);
9828 $evalStr = 'class nusoap_proxy_'.$r.' extends nusoap_client {
9835 * dynamically creates proxy class code
9837 * @return string PHP/NuSOAP code for the proxy class
9840 function getProxyClassCode() {
9842 return $this->_getProxyClassCode($r);
9846 * gets the HTTP body for the current request.
9848 * @param string $soapmsg The SOAP payload
9849 * @return string The HTTP body, which includes the SOAP payload
9852 function getHTTPBody($soapmsg) {
9857 * gets the HTTP content type for the current request.
9859 * Note: getHTTPBody must be called before this.
9861 * @return string the HTTP content type for the current request.
9864 function getHTTPContentType() {
9869 * gets the HTTP content type charset for the current request.
9870 * returns false for non-text content types.
9872 * Note: getHTTPBody must be called before this.
9874 * @return string the HTTP content type charset for the current request.
9877 function getHTTPContentTypeCharset() {
9878 return $this->soap_defencoding;
9882 * whether or not parser should decode utf8 element content
9884 * @return always returns true
9887 function decodeUTF8($bool){
9888 $this->decode_utf8 = $bool;
9893 * adds a new Cookie into $this->cookies array
9895 * @param string $name Cookie Name
9896 * @param string $value Cookie Value
9897 * @return boolean if cookie-set was successful returns true, else false
9900 function setCookie($name, $value) {
9901 if (strlen($name) == 0) {
9904 $this->cookies[] = array('name' => $name, 'value' => $value);
9911 * @return array with all internal cookies
9914 function getCookies() {
9915 return $this->cookies;
9919 * checks all Cookies and delete those which are expired
9921 * @return boolean always return true
9924 function checkCookies() {
9925 if (sizeof($this->cookies) == 0) {
9928 $this->debug('checkCookie: check ' . sizeof($this->cookies) . ' cookies');
9929 $curr_cookies = $this->cookies;
9930 $this->cookies = array();
9931 foreach ($curr_cookies as $cookie) {
9932 if (! is_array($cookie)) {
9933 $this->debug('Remove cookie that is not an array');
9936 if ((isset($cookie['expires'])) && (! empty($cookie['expires']))) {
9937 if (strtotime($cookie['expires']) > time()) {
9938 $this->cookies[] = $cookie;
9940 $this->debug('Remove expired cookie ' . $cookie['name']);
9943 $this->cookies[] = $cookie;
9946 $this->debug('checkCookie: '.sizeof($this->cookies).' cookies left in array');
9951 * updates the current cookies with a new set
9953 * @param array $cookies new cookies with which to update current ones
9954 * @return boolean always return true
9957 function UpdateCookies($cookies) {
9958 if (sizeof($this->cookies) == 0) {
9959 // no existing cookies: take whatever is new
9960 if (sizeof($cookies) > 0) {
9961 $this->debug('Setting new cookie(s)');
9962 $this->cookies = $cookies;
9966 if (sizeof($cookies) == 0) {
9967 // no new cookies: keep what we've got
9971 foreach ($cookies as $newCookie) {
9972 if (!is_array($newCookie)) {
9975 if ((!isset($newCookie['name'])) || (!isset($newCookie['value']))) {
9978 $newName = $newCookie['name'];
9981 for ($i = 0; $i < count($this->cookies); $i++) {
9982 $cookie = $this->cookies[$i];
9983 if (!is_array($cookie)) {
9986 if (!isset($cookie['name'])) {
9989 if ($newName != $cookie['name']) {
9992 $newDomain = isset($newCookie['domain']) ? $newCookie['domain'] : 'NODOMAIN';
9993 $domain = isset($cookie['domain']) ? $cookie['domain'] : 'NODOMAIN';
9994 if ($newDomain != $domain) {
9997 $newPath = isset($newCookie['path']) ? $newCookie['path'] : 'NOPATH';
9998 $path = isset($cookie['path']) ? $cookie['path'] : 'NOPATH';
9999 if ($newPath != $path) {
10002 $this->cookies[$i] = $newCookie;
10004 $this->debug('Update cookie ' . $newName . '=' . $newCookie['value']);
10008 $this->debug('Add cookie ' . $newName . '=' . $newCookie['value']);
10009 $this->cookies[] = $newCookie;
10016 if (!extension_loaded('soap')) {
10018 * For backwards compatiblity, define soapclient unless the PHP SOAP extension is loaded.
10020 class soapclient extends nusoap_client {
10024 class nusoapclient extends nusoap_client