4 Modification information for LGPL compliance
6 commit af784931b8ab2263776badac5ac3fc4776c9cd61
7 Author: Stanislav Malyshev <smalyshev@gmail.com>
8 Date: Thu Feb 17 18:09:12 2011 -0800
10 bug 34897 - remove characters that aren't valid in XML
12 commit 1767411d701b8216cc5e043888fd1337e2eca315
13 Author: Stanislav Malyshev <smalyshev@gmail.com>
14 Date: Fri Jan 7 12:19:10 2011 -0800
16 conserve memory when no debug is enabled
18 commit 843510ebf455368865302a05b9d5041815a32c23
19 Author: John Mertic <jmertic@sugarcrm.com>
20 Date: Wed Nov 17 13:18:09 2010 -0500
22 Bug 40716 - Fix WSDL validation problem by removing hardcoded schemaLocation attribute for the <xsd:import> tag.
24 commit 2bd12c02078f3e291bd9c1e76179a144c788ce97
25 Author: Collin Lee <clee@Collin-Lee-MacBook-Pro.local>
26 Date: Fri Oct 22 16:37:42 2010 -0400
30 We traced the error to a combination of the new Hoovers' WSDL + the nusoapclient code that winds up improperly encoding the parameter elem
31 ents (this is because the namespace specified for the soap call did not match that declared in the WSDL). Made changes to nusoap.php so that w
32 e may manually set a payload XML portion that will not apply the namespace encoding to the parameters. Fixed unit tests to reflect the changes
33 and also re-enabled those for Hoovers that were marked skipped.
35 r58622 - 2010-10-22 18:18:59 -0700 (Fri, 22 Oct 2010) - engsvnbuild - Author: lam <lam@198.18.142.201>
38 r58361 - 2010-09-29 16:59:02 -0700 (Wed, 29 Sep 2010) - kjing - Author: Jenny Gonsalves <jenny@sugarcrm.com>
39 Merging with maint_6_0_1 (svn merge -r 58250:58342)
41 r57813 - 2010-08-19 10:34:44 -0700 (Thu, 19 Aug 2010) - kjing - Author: John Mertic <jmertic@sugarcrm.com>
42 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.
44 r57707 - 2010-08-10 12:26:13 -0700 (Tue, 10 Aug 2010) - kjing - Author: Stanislav Malyshev <smalyshev@gmail.com>
45 fix SOAP calls with no parameters
47 r56990 - 2010-06-16 13:05:36 -0700 (Wed, 16 Jun 2010) - kjing - snapshot "Mango" svn branch to a new one for GitHub sync
49 r56989 - 2010-06-16 13:01:33 -0700 (Wed, 16 Jun 2010) - kjing - defunt "Mango" svn dev branch before github cutover
51 r55980 - 2010-04-19 13:31:28 -0700 (Mon, 19 Apr 2010) - kjing - create Mango (6.1) based on windex
53 r51719 - 2009-10-22 10:18:00 -0700 (Thu, 22 Oct 2009) - mitani - Converted to Build 3 tags and updated the build system
55 r51634 - 2009-10-19 13:32:22 -0700 (Mon, 19 Oct 2009) - mitani - Windex is the branch for Sugar Sales 1.0 development
57 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.
59 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.
61 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:
62 - Changing all ereg function to either preg or simple string based ones
63 - No more references to magic quotes.
64 - Change all the session_unregister() functions to just unset() the correct session variable instead.
66 r50375 - 2009-08-24 18:07:43 -0700 (Mon, 24 Aug 2009) - dwong - branch kobe2 from tokyo r50372
68 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
70 r45680 - 2009-03-30 14:34:35 -0700 (Mon, 30 Mar 2009) - Samir Gandhi - modifeid serializeSchema to generate WS-I compliant WSDL
72 r42807 - 2008-12-29 11:16:59 -0800 (Mon, 29 Dec 2008) - dwong - Branch from trunk/sugarcrm r42806 to branches/tokyo/sugarcrm
74 r42645 - 2008-12-18 13:41:08 -0800 (Thu, 18 Dec 2008) - awu - merging maint_5_2_0 rev41336:HEAD to trunk
76 r41647 - 2008-11-11 17:44:30 -0800 (Tue, 11 Nov 2008) - majed - Fixes a few bugs
78 r41596 - 2008-11-10 19:20:04 -0800 (Mon, 10 Nov 2008) - Samir Gandhi - modified to set $method in the code
80 r41558 - 2008-11-10 14:35:34 -0800 (Mon, 10 Nov 2008) - majed - changes nusoap to allow for registering classes
82 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.
85 - include/domit/php_http_client_generic.php
86 - include/domit/php_http_connector.php
87 - include/domit/testing_domit.php
88 - include/domit/xml_domit_getelementsbypath.php
89 - include/domit/xml_domit_lite_parser.php
90 - include/domit/xml_domit_nodemaps.php
91 - include/domit/xml_domit_parser.php
92 - include/domit/xml_domit_shared.php
93 - include/generic/SugarWidgets/SugarWidgetField.php
94 - include/generic/SugarWidgets/SugarWidgetReportField.php
95 - include/ListView/ProcessView.php
96 - include/nusoap/class.soapclient.php
97 - include/nusoap/nusoap.php
98 - include/nusoap/nusoapmime.php
99 - include/Pear/HTML_Safe/Safe.php
100 - include/Pear/XML_HTMLSax3/HTMLSax3.php
101 - modules/Administration/RebuildWorkFlow.php
102 - modules/Expressions/RelateSelector.php
103 - modules/Reports/templates/templates_reports.php
104 - modules/WorkFlow/Delete.php
105 - modules/WorkFlow/Save.php
106 - modules/WorkFlow/SaveSequence.php
107 - modules/WorkFlow/WorkFlow.php
108 - modules/WorkFlowActionShells/CreateStep1.php
109 - modules/WorkFlowActionShells/CreateStep2.php
110 - modules/WorkFlowActionShells/Save.php
111 - modules/WorkFlowActionShells/WorkFlowActionShell.php
112 - modules/WorkFlowAlerts/Save.php
113 - modules/WorkFlowAlerts/WorkFlowAlert.php
114 - modules/WorkFlowAlertShells/DetailView.php
115 - modules/WorkFlowAlertShells/WorkFlowAlertShell.php
116 - modules/WorkFlowTriggerShells/CreateStep1.php
117 - modules/WorkFlowTriggerShells/CreateStepFilter.php
118 - modules/WorkFlowTriggerShells/SaveFilter.php
119 - modules/WorkFlowTriggerShells/WorkFlowTriggerShell.php
120 - soap/SoapHelperFunctions.php
121 - test/modules/DynamicFields/DynamicFields_Bug24095_test.php
122 - test/simpletest/browser.php
123 - test/simpletest/default_reporter.php
124 - test/simpletest/detached.php
125 - test/simpletest/eclipse.php
126 - test/simpletest/expectation.php
127 - test/simpletest/extensions/pear_test_case.php
128 - test/simpletest/form.php
129 - test/simpletest/http.php
130 - test/simpletest/mock_objects.php
131 - test/simpletest/page.php
132 - test/simpletest/parser.php
133 - test/simpletest/remote.php
134 - test/simpletest/shell_tester.php
135 - test/simpletest/simple_test.php
136 - test/simpletest/simpletest.php
137 - test/simpletest/test/acceptance_test.php
138 - test/simpletest/test/adapter_test.php
139 - test/simpletest/test/authentication_test.php
140 - test/simpletest/test/browser_test.php
141 - test/simpletest/test/collector_test.php
142 - test/simpletest/test/compatibility_test.php
143 - test/simpletest/test/detached_test.php
144 - test/simpletest/test/eclipse_test.php
145 - test/simpletest/test/encoding_test.php
146 - test/simpletest/test/errors_test.php
147 - test/simpletest/test/expectation_test.php
148 - test/simpletest/test/form_test.php
149 - test/simpletest/test/frames_test.php
150 - test/simpletest/test/http_test.php
151 - test/simpletest/test/live_test.php
152 - test/simpletest/test/mock_objects_test.php
153 - test/simpletest/test/page_test.php
154 - test/simpletest/test/parse_error_test.php
155 - test/simpletest/test/parser_test.php
156 - test/simpletest/test/remote_test.php
157 - test/simpletest/test/shell_test.php
158 - test/simpletest/test/shell_tester_test.php
159 - test/simpletest/test/simpletest_test.php
160 - test/simpletest/test/site/page_request.php
161 - test/simpletest/test/tag_test.php
162 - test/simpletest/test/unit_tester_test.php
163 - test/simpletest/test/user_agent_test.php
164 - test/simpletest/test/visual_test.php
165 - test/simpletest/test/xml_test.php
166 - test/simpletest/test_case.php
167 - test/simpletest/ui/array_reporter/test.php
168 - test/simpletest/ui/recorder/test.php
169 - test/simpletest/unit_tester.php
170 - test/simpletest/url.php
171 - test/simpletest/user_agent.php
172 - test/simpletest/web_tester.php
173 - test/spikephpcoverage/src/PEAR.php
174 - test/spikephpcoverage/src/util/Utility.php
175 - test/spikephpcoverage/src/XML/Parser.php
176 - test/spikephpcoverage/src/XML/Parser/Simple.php
177 - test/test_utilities/SugarTest_SimpleBrowser.php
179 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.
181 r38300 - 2008-07-25 13:33:43 -0700 (Fri, 25 Jul 2008) - Samir Gandhi - put the debug in parseresponse function
183 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
185 r36824 - 2008-06-18 09:26:11 -0700 (Wed, 18 Jun 2008) - roger - bug: 21832
187 r26422 - 2007-09-05 17:29:12 -0700 (Wed, 05 Sep 2007) - majed - migrate from beta 1 to trunk
189 r15787 - 2006-08-10 10:14:41 -0700 (Thu, 10 Aug 2006) - roger - RRS: bug 7961
191 r14701 - 2006-07-17 13:37:26 -0700 (Mon, 17 Jul 2006) - roger - RRS: bug 5801
193 r13782 - 2006-06-06 10:58:55 -0700 (Tue, 06 Jun 2006) - majed - changes entry point code
195 r11466 - 2006-02-01 15:49:47 -0800 (Wed, 01 Feb 2006) - jacob - Adding extra !empty check to get around a PHP warning.
197 r11115 - 2006-01-17 14:54:45 -0800 (Tue, 17 Jan 2006) - majed - add entry point validation
199 r10585 - 2005-12-13 14:42:26 -0800 (Tue, 13 Dec 2005) - majed - adds new license mechanisim
201 r10170 - 2005-12-05 18:37:46 -0800 (Mon, 05 Dec 2005) - majed - fixes various issues
203 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.
205 r8991 - 2005-11-03 19:07:25 -0800 (Thu, 03 Nov 2005) - majed - fixes nusoap issue
207 r8846 - 2005-10-31 11:01:12 -0800 (Mon, 31 Oct 2005) - majed - new version of nusoap
209 r7905 - 2005-09-21 19:12:57 -0700 (Wed, 21 Sep 2005) - majed - restores old nusoap pre & with a few fixes
211 r7861 - 2005-09-20 15:40:25 -0700 (Tue, 20 Sep 2005) - majed - & fix for 3.5.1
213 r7452 - 2005-08-17 11:32:34 -0700 (Wed, 17 Aug 2005) - majed - changes soap to nusoap
215 r5820 - 2005-06-21 14:22:24 -0700 (Tue, 21 Jun 2005) - majed - fixes issues with nusoap and with custom fields
217 r5462 - 2005-05-25 13:50:11 -0700 (Wed, 25 May 2005) - majed - upgraded nusoap to .6.9
219 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
221 r573 - 2004-09-04 13:03:32 -0700 (Sat, 04 Sep 2004) - sugarclint - undoing copyrights added in inadvertantly. --clint
223 r546 - 2004-09-03 11:49:38 -0700 (Fri, 03 Sep 2004) - sugarmsi - removed echo count
225 r354 - 2004-08-02 23:00:37 -0700 (Mon, 02 Aug 2004) - sugarjacob - Adding Soap
231 if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
234 $Id: nusoap.php 58622 2010-10-23 01:18:59Z engsvnbuild $
236 NuSOAP - Web Services Toolkit for PHP
238 Copyright (c) 2002 NuSphere Corporation
240 This library is free software; you can redistribute it and/or
241 modify it under the terms of the GNU Lesser General Public
242 License as published by the Free Software Foundation; either
243 version 2.1 of the License, or (at your option) any later version.
245 This library is distributed in the hope that it will be useful,
246 but WITHOUT ANY WARRANTY; without even the implied warranty of
247 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
248 Lesser General Public License for more details.
250 You should have received a copy of the GNU Lesser General Public
251 License along with this library; if not, write to the Free Software
252 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
254 The NuSOAP project home is:
255 http://sourceforge.net/projects/nusoap/
257 The primary support for NuSOAP is the Help forum on the project home page.
259 If you have any questions or comments, please email:
263 http://dietrich.ganx4.com/nusoap
266 http://www.nusphere.com
271 * Some of the standards implmented in whole or part by NuSOAP:
273 * SOAP 1.1 (http://www.w3.org/TR/2000/NOTE-SOAP-20000508/)
274 * WSDL 1.1 (http://www.w3.org/TR/2001/NOTE-wsdl-20010315)
275 * SOAP Messages With Attachments (http://www.w3.org/TR/SOAP-attachments)
276 * XML 1.0 (http://www.w3.org/TR/2006/REC-xml-20060816/)
277 * Namespaces in XML 1.0 (http://www.w3.org/TR/2006/REC-xml-names-20060816/)
278 * XML Schema 1.0 (http://www.w3.org/TR/xmlschema-0/)
279 * RFC 2045 Multipurpose Internet Mail Extensions (MIME) Part One: Format of Internet Message Bodies
280 * RFC 2068 Hypertext Transfer Protocol -- HTTP/1.1
281 * RFC 2617 HTTP Authentication: Basic and Digest Access Authentication
287 require_once('class.soapclient.php');
288 require_once('class.soap_val.php');
289 require_once('class.soap_parser.php');
290 require_once('class.soap_fault.php');
293 require_once('class.soap_transport_http.php');
295 // optional add-on classes
296 require_once('class.xmlschema.php');
297 require_once('class.wsdl.php');
300 require_once('class.soap_server.php');*/
302 // class variable emulation
303 // cf. http://www.webkreator.com/php/techniques/php-static-class-variables.html
304 $GLOBALS['_transient']['static']['nusoap_base']['globalDebugLevel'] = 0;
310 * @author Dietrich Ayala <dietrich@ganx4.com>
311 * @author Scott Nichol <snichol@users.sourceforge.net>
317 * Identification for HTTP headers.
322 var $title = 'NuSOAP';
324 * Version for HTTP headers.
329 var $version = '0.9.5';
331 * CVS revision for HTTP headers.
336 var $revision = '$Revision: 58622 $';
338 * Current error string (manipulated by getError/setError)
345 * Current debug string (manipulated by debug/appendDebug/clearDebug/getDebug/getDebugAsXMLComment)
352 * toggles automatic encoding of special characters as entities
353 * (should always be true, I think)
358 var $charencoding = true;
360 * the debug level for this instance
373 var $XMLSchemaVersion = 'http://www.w3.org/2001/XMLSchema';
376 * charset encoding for outgoing messages
381 //var $soap_defencoding = 'ISO-8859-1';
382 var $soap_defencoding = 'UTF-8';
385 * namespaces in an array of prefix => uri
387 * this is "seeded" by a set of constants, but it may be altered by code
392 var $namespaces = array(
393 'SOAP-ENV' => 'http://schemas.xmlsoap.org/soap/envelope/',
394 'xsd' => 'http://www.w3.org/2001/XMLSchema',
395 'xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
396 'SOAP-ENC' => 'http://schemas.xmlsoap.org/soap/encoding/'
400 * namespaces used in the current context, e.g. during serialization
405 var $usedNamespaces = array();
408 * XML Schema types in an array of uri => (array of xml type => php type)
409 * is this legacy yet?
410 * no, this is used by the nusoap_xmlschema class to verify type => namespace mappings.
414 var $typemap = array(
415 'http://www.w3.org/2001/XMLSchema' => array(
416 'string'=>'string','boolean'=>'boolean','float'=>'double','double'=>'double','decimal'=>'double',
417 'duration'=>'','dateTime'=>'string','time'=>'string','date'=>'string','gYearMonth'=>'',
418 'gYear'=>'','gMonthDay'=>'','gDay'=>'','gMonth'=>'','hexBinary'=>'string','base64Binary'=>'string',
419 // abstract "any" types
420 'anyType'=>'string','anySimpleType'=>'string',
422 'normalizedString'=>'string','token'=>'string','language'=>'','NMTOKEN'=>'','NMTOKENS'=>'','Name'=>'','NCName'=>'','ID'=>'',
423 'IDREF'=>'','IDREFS'=>'','ENTITY'=>'','ENTITIES'=>'','integer'=>'integer','nonPositiveInteger'=>'integer',
424 'negativeInteger'=>'integer','long'=>'integer','int'=>'integer','short'=>'integer','byte'=>'integer','nonNegativeInteger'=>'integer',
425 'unsignedLong'=>'','unsignedInt'=>'','unsignedShort'=>'','unsignedByte'=>'','positiveInteger'=>''),
426 'http://www.w3.org/2000/10/XMLSchema' => array(
427 'i4'=>'','int'=>'integer','boolean'=>'boolean','string'=>'string','double'=>'double',
428 'float'=>'double','dateTime'=>'string',
429 'timeInstant'=>'string','base64Binary'=>'string','base64'=>'string','ur-type'=>'array'),
430 'http://www.w3.org/1999/XMLSchema' => array(
431 'i4'=>'','int'=>'integer','boolean'=>'boolean','string'=>'string','double'=>'double',
432 'float'=>'double','dateTime'=>'string',
433 'timeInstant'=>'string','base64Binary'=>'string','base64'=>'string','ur-type'=>'array'),
434 'http://soapinterop.org/xsd' => array('SOAPStruct'=>'struct'),
435 'http://schemas.xmlsoap.org/soap/encoding/' => array('base64'=>'string','array'=>'array','Array'=>'array'),
436 'http://xml.apache.org/xml-soap' => array('Map')
440 * XML entities to convert
445 * @see expandEntities
447 var $xmlEntities = array('quot' => '"','amp' => '&',
448 'lt' => '<','gt' => '>','apos' => "'");
452 * This is to allows us to override the payload to resolve issues where we need to take
453 * control of the xml content
458 var $payloadOverride;
465 function nusoap_base() {
466 $this->debugLevel = $GLOBALS['_transient']['static']['nusoap_base']['globalDebugLevel'];
470 * gets the global debug level, which applies to future instances
472 * @return integer Debug level 0-9, where 0 turns off
475 function getGlobalDebugLevel() {
476 return $GLOBALS['_transient']['static']['nusoap_base']['globalDebugLevel'];
480 * sets the global debug level, which applies to future instances
482 * @param int $level Debug level 0-9, where 0 turns off
485 function setGlobalDebugLevel($level) {
486 $GLOBALS['_transient']['static']['nusoap_base']['globalDebugLevel'] = $level;
490 * gets the debug level for this instance
492 * @return int Debug level 0-9, where 0 turns off
495 function getDebugLevel() {
496 return $this->debugLevel;
500 * sets the debug level for this instance
502 * @param int $level Debug level 0-9, where 0 turns off
505 function setDebugLevel($level) {
506 $this->debugLevel = $level;
510 * adds debug data to the instance debug string with formatting
512 * @param string $string debug data
515 function debug($string){
516 if ($this->debugLevel > 0) {
517 $this->appendDebug($this->getmicrotime().' '.get_class($this).": $string\n");
522 * adds debug data to the instance debug string without formatting
524 * @param string $string debug data
527 function appendDebug($string){
528 if ($this->debugLevel > 0) {
529 // it would be nice to use a memory stream here to use
530 // memory more efficiently
531 $this->debug_str .= $string;
536 * clears the current debug data for this instance
540 function clearDebug() {
541 // it would be nice to use a memory stream here to use
542 // memory more efficiently
543 $this->debug_str = '';
547 * gets the current debug data for this instance
552 function &getDebug() {
553 // it would be nice to use a memory stream here to use
554 // memory more efficiently
555 return $this->debug_str;
559 * gets the current debug data for this instance as an XML comment
560 * this may change the contents of the debug data
562 * @return debug data as an XML comment
565 function &getDebugAsXMLComment() {
566 // it would be nice to use a memory stream here to use
567 // memory more efficiently
568 while (strpos($this->debug_str, '--')) {
569 $this->debug_str = str_replace('--', '- -', $this->debug_str);
571 $ret = "<!--\n" . $this->debug_str . "\n-->";
576 * expands entities, e.g. changes '<' to '<'.
578 * @param string $val The string in which to expand entities.
581 function expandEntities($val) {
582 if ($this->charencoding) {
583 $val = htmlspecialchars($val, ENT_QUOTES, $this->soap_defencoding);
584 // XML 1.0 doesn't allow those...
585 $val = preg_replace("/([\\x00-\\x08\\x0B\\x0C\\x0E-\\x1F])/", '', $val);
591 * returns error string if present
593 * @return mixed error string or false
597 if($this->error_str != ''){
598 return $this->error_str;
606 * @return boolean $string error string
609 function setError($str){
610 $this->error_str = $str;
614 * detect if array is a simple array or a struct (associative array)
616 * @param mixed $val The PHP array
617 * @return string (arraySimple|arrayStruct)
620 function isArraySimpleOrStruct($val) {
621 $keyList = array_keys($val);
622 foreach ($keyList as $keyListValue) {
623 if (!is_int($keyListValue)) {
624 return 'arrayStruct';
627 return 'arraySimple';
631 * serializes PHP values in accordance w/ section 5. Type information is
632 * not serialized if $use == 'literal'.
634 * @param mixed $val The value to serialize
635 * @param string $name The name (local part) of the XML element
636 * @param string $type The XML schema type (local part) for the element
637 * @param string $name_ns The namespace for the name of the XML element
638 * @param string $type_ns The namespace for the type of the element
639 * @param array $attributes The attributes to serialize as name=>value pairs
640 * @param string $use The WSDL "use" (encoded|literal)
641 * @param boolean $soapval Whether this is called from soapval.
642 * @return string The serialized element, possibly with child elements
645 function serialize_val($val,$name=false,$type=false,$name_ns=false,$type_ns=false,$attributes=false,$use='encoded',$soapval=false) {
646 $this->debug("in serialize_val: name=$name, type=$type, name_ns=$name_ns, type_ns=$type_ns, use=$use, soapval=$soapval");
647 $this->appendDebug('value=' . $this->varDump($val));
648 $this->appendDebug('attributes=' . $this->varDump($attributes));
650 if (is_object($val) && get_class($val) == 'soapval' && (! $soapval)) {
651 $this->debug("serialize_val: serialize soapval");
652 $xml = $val->serialize($use);
653 $this->appendDebug($val->getDebug());
655 $this->debug("serialize_val of soapval returning $xml");
658 // force valid name if necessary
659 if (is_numeric($name)) {
660 $name = '__numeric_' . $name;
664 // if name has ns, add ns prefix to name
667 $prefix = 'nu'.rand(1000,9999);
668 $name = $prefix.':'.$name;
669 $xmlns .= " xmlns:$prefix=\"$name_ns\"";
671 // if type is prefixed, create type prefix
672 if($type_ns != '' && $type_ns == $this->namespaces['xsd']){
673 // need to fix this. shouldn't default to xsd if no ns specified
674 // w/o checking against typemap
675 $type_prefix = 'xsd';
677 $type_prefix = 'ns'.rand(1000,9999);
678 $xmlns .= " xmlns:$type_prefix=\"$type_ns\"";
680 // serialize attributes if present
683 foreach($attributes as $k => $v){
684 $atts .= " $k=\"".$this->expandEntities($v).'"';
687 // serialize null value
689 $this->debug("serialize_val: serialize null");
690 if ($use == 'literal') {
691 // TODO: depends on minOccurs
692 $xml = "<$name$xmlns$atts/>";
693 $this->debug("serialize_val returning $xml");
696 if (isset($type) && isset($type_prefix)) {
697 $type_str = " xsi:type=\"$type_prefix:$type\"";
701 $xml = "<$name$xmlns$type_str$atts xsi:nil=\"true\"/>";
702 $this->debug("serialize_val returning $xml");
706 // serialize if an xsd built-in primitive type
707 if($type != '' && isset($this->typemap[$this->XMLSchemaVersion][$type])){
708 $this->debug("serialize_val: serialize xsd built-in primitive type");
710 if ($type == 'boolean') {
711 $val = $val ? 'true' : 'false';
715 } else if (is_string($val)) {
716 $val = $this->expandEntities($val);
718 if ($use == 'literal') {
719 $xml = "<$name$xmlns$atts>$val</$name>";
720 $this->debug("serialize_val returning $xml");
723 $xml = "<$name$xmlns xsi:type=\"xsd:$type\"$atts>$val</$name>";
724 $this->debug("serialize_val returning $xml");
728 // detect type and serialize
731 case (is_bool($val) || $type == 'boolean'):
732 $this->debug("serialize_val: serialize boolean");
733 if ($type == 'boolean') {
734 $val = $val ? 'true' : 'false';
738 if ($use == 'literal') {
739 $xml .= "<$name$xmlns$atts>$val</$name>";
741 $xml .= "<$name$xmlns xsi:type=\"xsd:boolean\"$atts>$val</$name>";
744 case (is_int($val) || is_long($val) || $type == 'int'):
745 $this->debug("serialize_val: serialize int");
746 if ($use == 'literal') {
747 $xml .= "<$name$xmlns$atts>$val</$name>";
749 $xml .= "<$name$xmlns xsi:type=\"xsd:int\"$atts>$val</$name>";
752 case (is_float($val)|| is_double($val) || $type == 'float'):
753 $this->debug("serialize_val: serialize float");
754 if ($use == 'literal') {
755 $xml .= "<$name$xmlns$atts>$val</$name>";
757 $xml .= "<$name$xmlns xsi:type=\"xsd:float\"$atts>$val</$name>";
760 case (is_string($val) || $type == 'string'):
761 $this->debug("serialize_val: serialize string");
762 $val = $this->expandEntities($val);
763 if ($use == 'literal') {
764 $xml .= "<$name$xmlns$atts>$val</$name>";
766 $xml .= "<$name$xmlns xsi:type=\"xsd:string\"$atts>$val</$name>";
769 case is_object($val):
770 $this->debug("serialize_val: serialize object");
771 if (get_class($val) == 'soapval') {
772 $this->debug("serialize_val: serialize soapval object");
773 $pXml = $val->serialize($use);
774 $this->appendDebug($val->getDebug());
778 $name = get_class($val);
779 $this->debug("In serialize_val, used class name $name as element name");
781 $this->debug("In serialize_val, do not override name $name for element name for class " . get_class($val));
783 foreach(get_object_vars($val) as $k => $v){
784 $pXml = isset($pXml) ? $pXml.$this->serialize_val($v,$k,false,false,false,false,$use) : $this->serialize_val($v,$k,false,false,false,false,$use);
787 if(isset($type) && isset($type_prefix)){
788 $type_str = " xsi:type=\"$type_prefix:$type\"";
792 if ($use == 'literal') {
793 $xml .= "<$name$xmlns$atts>$pXml</$name>";
795 $xml .= "<$name$xmlns$type_str$atts>$pXml</$name>";
799 case (is_array($val) || $type):
800 // detect if struct or array
801 $valueType = $this->isArraySimpleOrStruct($val);
802 if($valueType=='arraySimple' || preg_match('/^ArrayOf/',$type)){
803 $this->debug("serialize_val: serialize array");
805 if(is_array($val) && count($val)> 0){
807 if(is_object($v) && get_class($v) == 'soapval'){
808 $tt_ns = $v->type_ns;
810 } elseif (is_array($v)) {
811 $tt = $this->isArraySimpleOrStruct($v);
815 $array_types[$tt] = 1;
816 // TODO: for literal, the name should be $name
817 $xml .= $this->serialize_val($v,'item',false,false,false,false,$use);
820 if(count($array_types) > 1){
821 $array_typename = 'xsd:anyType';
822 } elseif(isset($tt) && isset($this->typemap[$this->XMLSchemaVersion][$tt])) {
823 if ($tt == 'integer') {
826 $array_typename = 'xsd:'.$tt;
827 } elseif(isset($tt) && $tt == 'arraySimple'){
828 $array_typename = 'SOAP-ENC:Array';
829 } elseif(isset($tt) && $tt == 'arrayStruct'){
830 $array_typename = 'unnamed_struct_use_soapval';
832 // if type is prefixed, create type prefix
833 if ($tt_ns != '' && $tt_ns == $this->namespaces['xsd']){
834 $array_typename = 'xsd:' . $tt;
836 $tt_prefix = 'ns' . rand(1000, 9999);
837 $array_typename = "$tt_prefix:$tt";
838 $xmlns .= " xmlns:$tt_prefix=\"$tt_ns\"";
840 $array_typename = $tt;
844 if ($use == 'literal') {
846 } else if (isset($type) && isset($type_prefix)) {
847 $type_str = " xsi:type=\"$type_prefix:$type\"";
849 $type_str = " xsi:type=\"SOAP-ENC:Array\" SOAP-ENC:arrayType=\"".$array_typename."[$array_type]\"";
853 if ($use == 'literal') {
855 } else if (isset($type) && isset($type_prefix)) {
856 $type_str = " xsi:type=\"$type_prefix:$type\"";
858 $type_str = " xsi:type=\"SOAP-ENC:Array\" SOAP-ENC:arrayType=\"xsd:anyType[0]\"";
861 // TODO: for array in literal, there is no wrapper here
862 $xml = "<$name$xmlns$type_str$atts>".$xml."</$name>";
865 $this->debug("serialize_val: serialize struct");
866 if(isset($type) && isset($type_prefix)){
867 $type_str = " xsi:type=\"$type_prefix:$type\"";
871 if ($use == 'literal') {
872 $xml .= "<$name$xmlns$atts>";
874 $xml .= "<$name$xmlns$type_str$atts>";
876 foreach($val as $k => $v){
878 if ($type == 'Map' && $type_ns == 'http://xml.apache.org/xml-soap') {
880 $xml .= $this->serialize_val($k,'key',false,false,false,false,$use);
881 $xml .= $this->serialize_val($v,'value',false,false,false,false,$use);
884 $xml .= $this->serialize_val($v,$k,false,false,false,false,$use);
891 $this->debug("serialize_val: serialize unknown");
892 $xml .= 'not detected, got '.gettype($val).' for '.$val;
895 $this->debug("serialize_val returning $xml");
900 * serializes a message
902 * @param string $body the XML of the SOAP body
903 * @param mixed $headers optional string of XML with SOAP header content, or array of soapval objects for SOAP headers, or associative array
904 * @param array $namespaces optional the namespaces used in generating the body and headers
905 * @param string $style optional (rpc|document)
906 * @param string $use optional (encoded|literal)
907 * @param string $encodingStyle optional (usually 'http://schemas.xmlsoap.org/soap/encoding/' for encoded)
908 * @return string the message
911 function serializeEnvelope($body,$headers=false,$namespaces=array(),$style='rpc',$use='encoded',$encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'){
912 // TODO: add an option to automatically run utf8_encode on $body and $headers
913 // if $this->soap_defencoding is UTF-8. Not doing this automatically allows
914 // one to send arbitrary UTF-8 characters, not just characters that map to ISO-8859-1
916 $this->debug("In serializeEnvelope length=" . strlen($body) . " body (max 1000 characters)=" . substr($body, 0, 1000) . " style=$style use=$use encodingStyle=$encodingStyle");
917 $this->debug("headers:");
918 $this->appendDebug($this->varDump($headers));
919 $this->debug("namespaces:");
920 $this->appendDebug($this->varDump($namespaces));
922 // serialize namespaces
924 foreach(array_merge($this->namespaces,$namespaces) as $k => $v){
925 $ns_string .= " xmlns:$k=\"$v\"";
928 $ns_string = " SOAP-ENV:encodingStyle=\"$encodingStyle\"$ns_string";
933 if (is_array($headers)) {
935 foreach ($headers as $k => $v) {
936 if (is_object($v) && get_class($v) == 'soapval') {
937 $xml .= $this->serialize_val($v, false, false, false, false, false, $use);
939 $xml .= $this->serialize_val($v, $k, false, false, false, false, $use);
943 $this->debug("In serializeEnvelope, serialized array of headers to $headers");
945 $headers = "<SOAP-ENV:Header>".$headers."</SOAP-ENV:Header>";
947 // serialize envelope
949 '<?xml version="1.0" encoding="'.$this->soap_defencoding .'"?'.">".
950 '<SOAP-ENV:Envelope'.$ns_string.">".
955 "</SOAP-ENV:Envelope>";
959 * formats a string to be inserted into an HTML stream
961 * @param string $str The string to format
962 * @return string The formatted string
966 function formatDump($str){
967 $str = htmlspecialchars($str);
972 * contracts (changes namespace to prefix) a qualified name
974 * @param string $qname qname
975 * @return string contracted qname
978 function contractQname($qname){
979 // get element namespace
980 //$this->xdebug("Contract $qname");
981 if (strrpos($qname, ':')) {
982 // get unqualified name
983 $name = substr($qname, strrpos($qname, ':') + 1);
985 $ns = substr($qname, 0, strrpos($qname, ':'));
986 $p = $this->getPrefixFromNamespace($ns);
988 return $p . ':' . $name;
997 * expands (changes prefix to namespace) a qualified name
999 * @param string $qname qname
1000 * @return string expanded qname
1003 function expandQname($qname){
1004 // get element prefix
1005 if(strpos($qname,':') && !preg_match('/^http:\/\//',$qname)){
1006 // get unqualified name
1007 $name = substr(strstr($qname,':'),1);
1009 $prefix = substr($qname,0,strpos($qname,':'));
1010 if(isset($this->namespaces[$prefix])){
1011 return $this->namespaces[$prefix].':'.$name;
1021 * returns the local part of a prefixed string
1022 * returns the original string, if not prefixed
1024 * @param string $str The prefixed string
1025 * @return string The local part
1028 function getLocalPart($str){
1029 if($sstr = strrchr($str,':')){
1030 // get unqualified name
1031 return substr( $sstr, 1 );
1038 * returns the prefix part of a prefixed string
1039 * returns false, if not prefixed
1041 * @param string $str The prefixed string
1042 * @return mixed The prefix or false if there is no prefix
1045 function getPrefix($str){
1046 if($pos = strrpos($str,':')){
1048 return substr($str,0,$pos);
1054 * pass it a prefix, it returns a namespace
1056 * @param string $prefix The prefix
1057 * @return mixed The namespace, false if no namespace has the specified prefix
1060 function getNamespaceFromPrefix($prefix){
1061 if (isset($this->namespaces[$prefix])) {
1062 return $this->namespaces[$prefix];
1064 //$this->setError("No namespace registered for prefix '$prefix'");
1069 * returns the prefix for a given namespace (or prefix)
1070 * or false if no prefixes registered for the given namespace
1072 * @param string $ns The namespace
1073 * @return mixed The prefix, false if the namespace has no prefixes
1076 function getPrefixFromNamespace($ns) {
1077 foreach ($this->namespaces as $p => $n) {
1078 if ($ns == $n || $ns == $p) {
1079 $this->usedNamespaces[$p] = $n;
1087 * returns the time in ODBC canonical form with microseconds
1089 * @return string The time in ODBC canonical form with microseconds
1092 function getmicrotime() {
1093 if (function_exists('gettimeofday')) {
1094 $tod = gettimeofday();
1096 $usec = $tod['usec'];
1101 return strftime('%Y-%m-%d %H:%M:%S', $sec) . '.' . sprintf('%06d', $usec);
1105 * Returns a string with the output of var_dump
1107 * @param mixed $data The variable to var_dump
1108 * @return string The output of var_dump
1111 function varDump($data) {
1112 if ($this->debugLevel <= 0) {
1117 $ret_val = ob_get_contents();
1123 * represents the object as a string
1128 function __toString() {
1129 return $this->varDump($this);
1133 // XML Schema Datatype Helper Functions
1135 //xsd:dateTime helpers
1138 * convert unix timestamp to ISO 8601 compliant date string
1140 * @param int $timestamp Unix time stamp
1141 * @param boolean $utc Whether the time stamp is UTC or local
1142 * @return mixed ISO 8601 date string or false
1145 function timestamp_to_iso8601($timestamp,$utc=true){
1146 $datestr = date('Y-m-d\TH:i:sO',$timestamp);
1147 $pos = strrpos($datestr, "+");
1148 if ($pos === FALSE) {
1149 $pos = strrpos($datestr, "-");
1151 if ($pos !== FALSE) {
1152 if (strlen($datestr) == $pos + 5) {
1153 $datestr = substr($datestr, 0, $pos + 3) . ':' . substr($datestr, -2);
1158 '([0-9]{4})-'. // centuries & years CCYY-
1159 '([0-9]{2})-'. // months MM-
1160 '([0-9]{2})'. // days DD
1162 '([0-9]{2}):'. // hours hh:
1163 '([0-9]{2}):'. // minutes mm:
1164 '([0-9]{2})(\.[0-9]*)?'. // seconds ss.ss...
1165 '(Z|[+\-][0-9]{2}:?[0-9]{2})?'. // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's
1168 if(preg_match($pattern,$datestr,$regs)){
1169 return sprintf('%04d-%02d-%02dT%02d:%02d:%02dZ',$regs[1],$regs[2],$regs[3],$regs[4],$regs[5],$regs[6]);
1178 * convert ISO 8601 compliant date string to unix timestamp
1180 * @param string $datestr ISO 8601 compliant date string
1181 * @return mixed Unix timestamp (int) or false
1184 function iso8601_to_timestamp($datestr){
1186 '([0-9]{4})-'. // centuries & years CCYY-
1187 '([0-9]{2})-'. // months MM-
1188 '([0-9]{2})'. // days DD
1190 '([0-9]{2}):'. // hours hh:
1191 '([0-9]{2}):'. // minutes mm:
1192 '([0-9]{2})(\.[0-9]+)?'. // seconds ss.ss...
1193 '(Z|[+\-][0-9]{2}:?[0-9]{2})?'. // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's
1195 if(preg_match($pattern,$datestr,$regs)){
1197 if($regs[8] != 'Z'){
1198 $op = substr($regs[8],0,1);
1199 $h = substr($regs[8],1,2);
1200 $m = substr($regs[8],strlen($regs[8])-2,2);
1202 $regs[4] = $regs[4] + $h;
1203 $regs[5] = $regs[5] + $m;
1204 } elseif($op == '+'){
1205 $regs[4] = $regs[4] - $h;
1206 $regs[5] = $regs[5] - $m;
1209 return gmmktime($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]);
1210 // return strtotime("$regs[1]-$regs[2]-$regs[3] $regs[4]:$regs[5]:$regs[6]Z");
1217 * sleeps some number of microseconds
1219 * @param string $usec the number of microseconds to sleep
1223 function usleepWindows($usec)
1225 $start = gettimeofday();
1229 $stop = gettimeofday();
1230 $timePassed = 1000000 * ($stop['sec'] - $start['sec'])
1231 + $stop['usec'] - $start['usec'];
1233 while ($timePassed < $usec);
1240 Modification information for LGPL compliance
1242 r58622 - 2010-10-22 18:18:59 -0700 (Fri, 22 Oct 2010) - engsvnbuild - Author: lam <lam@198.18.142.201>
1245 r58361 - 2010-09-29 16:59:02 -0700 (Wed, 29 Sep 2010) - kjing - Author: Jenny Gonsalves <jenny@sugarcrm.com>
1246 Merging with maint_6_0_1 (svn merge -r 58250:58342)
1248 r57813 - 2010-08-19 10:34:44 -0700 (Thu, 19 Aug 2010) - kjing - Author: John Mertic <jmertic@sugarcrm.com>
1249 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.
1251 r57707 - 2010-08-10 12:26:13 -0700 (Tue, 10 Aug 2010) - kjing - Author: Stanislav Malyshev <smalyshev@gmail.com>
1252 fix SOAP calls with no parameters
1254 r56990 - 2010-06-16 13:05:36 -0700 (Wed, 16 Jun 2010) - kjing - snapshot "Mango" svn branch to a new one for GitHub sync
1256 r56989 - 2010-06-16 13:01:33 -0700 (Wed, 16 Jun 2010) - kjing - defunt "Mango" svn dev branch before github cutover
1258 r55980 - 2010-04-19 13:31:28 -0700 (Mon, 19 Apr 2010) - kjing - create Mango (6.1) based on windex
1260 r51719 - 2009-10-22 10:18:00 -0700 (Thu, 22 Oct 2009) - mitani - Converted to Build 3 tags and updated the build system
1262 r51634 - 2009-10-19 13:32:22 -0700 (Mon, 19 Oct 2009) - mitani - Windex is the branch for Sugar Sales 1.0 development
1264 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.
1266 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.
1268 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:
1269 - Changing all ereg function to either preg or simple string based ones
1270 - No more references to magic quotes.
1271 - Change all the session_unregister() functions to just unset() the correct session variable instead.
1273 r50375 - 2009-08-24 18:07:43 -0700 (Mon, 24 Aug 2009) - dwong - branch kobe2 from tokyo r50372
1275 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
1277 r45680 - 2009-03-30 14:34:35 -0700 (Mon, 30 Mar 2009) - Samir Gandhi - modifeid serializeSchema to generate WS-I compliant WSDL
1279 r42807 - 2008-12-29 11:16:59 -0800 (Mon, 29 Dec 2008) - dwong - Branch from trunk/sugarcrm r42806 to branches/tokyo/sugarcrm
1281 r42645 - 2008-12-18 13:41:08 -0800 (Thu, 18 Dec 2008) - awu - merging maint_5_2_0 rev41336:HEAD to trunk
1283 r41647 - 2008-11-11 17:44:30 -0800 (Tue, 11 Nov 2008) - majed - Fixes a few bugs
1285 r41596 - 2008-11-10 19:20:04 -0800 (Mon, 10 Nov 2008) - Samir Gandhi - modified to set $method in the code
1287 r41558 - 2008-11-10 14:35:34 -0800 (Mon, 10 Nov 2008) - majed - changes nusoap to allow for registering classes
1289 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.
1291 - data/SugarBean.php
1292 - include/domit/php_http_client_generic.php
1293 - include/domit/php_http_connector.php
1294 - include/domit/testing_domit.php
1295 - include/domit/xml_domit_getelementsbypath.php
1296 - include/domit/xml_domit_lite_parser.php
1297 - include/domit/xml_domit_nodemaps.php
1298 - include/domit/xml_domit_parser.php
1299 - include/domit/xml_domit_shared.php
1300 - include/generic/SugarWidgets/SugarWidgetField.php
1301 - include/generic/SugarWidgets/SugarWidgetReportField.php
1302 - include/ListView/ProcessView.php
1303 - include/nusoap/class.soapclient.php
1304 - include/nusoap/nusoap.php
1305 - include/nusoap/nusoapmime.php
1306 - include/Pear/HTML_Safe/Safe.php
1307 - include/Pear/XML_HTMLSax3/HTMLSax3.php
1308 - modules/Administration/RebuildWorkFlow.php
1309 - modules/Expressions/RelateSelector.php
1310 - modules/Reports/templates/templates_reports.php
1311 - modules/WorkFlow/Delete.php
1312 - modules/WorkFlow/Save.php
1313 - modules/WorkFlow/SaveSequence.php
1314 - modules/WorkFlow/WorkFlow.php
1315 - modules/WorkFlowActionShells/CreateStep1.php
1316 - modules/WorkFlowActionShells/CreateStep2.php
1317 - modules/WorkFlowActionShells/Save.php
1318 - modules/WorkFlowActionShells/WorkFlowActionShell.php
1319 - modules/WorkFlowAlerts/Save.php
1320 - modules/WorkFlowAlerts/WorkFlowAlert.php
1321 - modules/WorkFlowAlertShells/DetailView.php
1322 - modules/WorkFlowAlertShells/WorkFlowAlertShell.php
1323 - modules/WorkFlowTriggerShells/CreateStep1.php
1324 - modules/WorkFlowTriggerShells/CreateStepFilter.php
1325 - modules/WorkFlowTriggerShells/SaveFilter.php
1326 - modules/WorkFlowTriggerShells/WorkFlowTriggerShell.php
1327 - soap/SoapHelperFunctions.php
1328 - test/modules/DynamicFields/DynamicFields_Bug24095_test.php
1329 - test/simpletest/browser.php
1330 - test/simpletest/default_reporter.php
1331 - test/simpletest/detached.php
1332 - test/simpletest/eclipse.php
1333 - test/simpletest/expectation.php
1334 - test/simpletest/extensions/pear_test_case.php
1335 - test/simpletest/form.php
1336 - test/simpletest/http.php
1337 - test/simpletest/mock_objects.php
1338 - test/simpletest/page.php
1339 - test/simpletest/parser.php
1340 - test/simpletest/remote.php
1341 - test/simpletest/shell_tester.php
1342 - test/simpletest/simple_test.php
1343 - test/simpletest/simpletest.php
1344 - test/simpletest/test/acceptance_test.php
1345 - test/simpletest/test/adapter_test.php
1346 - test/simpletest/test/authentication_test.php
1347 - test/simpletest/test/browser_test.php
1348 - test/simpletest/test/collector_test.php
1349 - test/simpletest/test/compatibility_test.php
1350 - test/simpletest/test/detached_test.php
1351 - test/simpletest/test/eclipse_test.php
1352 - test/simpletest/test/encoding_test.php
1353 - test/simpletest/test/errors_test.php
1354 - test/simpletest/test/expectation_test.php
1355 - test/simpletest/test/form_test.php
1356 - test/simpletest/test/frames_test.php
1357 - test/simpletest/test/http_test.php
1358 - test/simpletest/test/live_test.php
1359 - test/simpletest/test/mock_objects_test.php
1360 - test/simpletest/test/page_test.php
1361 - test/simpletest/test/parse_error_test.php
1362 - test/simpletest/test/parser_test.php
1363 - test/simpletest/test/remote_test.php
1364 - test/simpletest/test/shell_test.php
1365 - test/simpletest/test/shell_tester_test.php
1366 - test/simpletest/test/simpletest_test.php
1367 - test/simpletest/test/site/page_request.php
1368 - test/simpletest/test/tag_test.php
1369 - test/simpletest/test/unit_tester_test.php
1370 - test/simpletest/test/user_agent_test.php
1371 - test/simpletest/test/visual_test.php
1372 - test/simpletest/test/xml_test.php
1373 - test/simpletest/test_case.php
1374 - test/simpletest/ui/array_reporter/test.php
1375 - test/simpletest/ui/recorder/test.php
1376 - test/simpletest/unit_tester.php
1377 - test/simpletest/url.php
1378 - test/simpletest/user_agent.php
1379 - test/simpletest/web_tester.php
1380 - test/spikephpcoverage/src/PEAR.php
1381 - test/spikephpcoverage/src/util/Utility.php
1382 - test/spikephpcoverage/src/XML/Parser.php
1383 - test/spikephpcoverage/src/XML/Parser/Simple.php
1384 - test/test_utilities/SugarTest_SimpleBrowser.php
1386 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.
1388 r38300 - 2008-07-25 13:33:43 -0700 (Fri, 25 Jul 2008) - Samir Gandhi - put the debug in parseresponse function
1390 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
1392 r36824 - 2008-06-18 09:26:11 -0700 (Wed, 18 Jun 2008) - roger - bug: 21832
1394 r26422 - 2007-09-05 17:29:12 -0700 (Wed, 05 Sep 2007) - majed - migrate from beta 1 to trunk
1396 r15787 - 2006-08-10 10:14:41 -0700 (Thu, 10 Aug 2006) - roger - RRS: bug 7961
1398 r14701 - 2006-07-17 13:37:26 -0700 (Mon, 17 Jul 2006) - roger - RRS: bug 5801
1400 r13782 - 2006-06-06 10:58:55 -0700 (Tue, 06 Jun 2006) - majed - changes entry point code
1402 r11466 - 2006-02-01 15:49:47 -0800 (Wed, 01 Feb 2006) - jacob - Adding extra !empty check to get around a PHP warning.
1404 r11115 - 2006-01-17 14:54:45 -0800 (Tue, 17 Jan 2006) - majed - add entry point validation
1406 r10585 - 2005-12-13 14:42:26 -0800 (Tue, 13 Dec 2005) - majed - adds new license mechanisim
1408 r10170 - 2005-12-05 18:37:46 -0800 (Mon, 05 Dec 2005) - majed - fixes various issues
1410 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.
1412 r8991 - 2005-11-03 19:07:25 -0800 (Thu, 03 Nov 2005) - majed - fixes nusoap issue
1414 r8846 - 2005-10-31 11:01:12 -0800 (Mon, 31 Oct 2005) - majed - new version of nusoap
1416 r7905 - 2005-09-21 19:12:57 -0700 (Wed, 21 Sep 2005) - majed - restores old nusoap pre & with a few fixes
1418 r7861 - 2005-09-20 15:40:25 -0700 (Tue, 20 Sep 2005) - majed - & fix for 3.5.1
1420 r7452 - 2005-08-17 11:32:34 -0700 (Wed, 17 Aug 2005) - majed - changes soap to nusoap
1422 r5820 - 2005-06-21 14:22:24 -0700 (Tue, 21 Jun 2005) - majed - fixes issues with nusoap and with custom fields
1424 r5462 - 2005-05-25 13:50:11 -0700 (Wed, 25 May 2005) - majed - upgraded nusoap to .6.9
1426 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
1428 r573 - 2004-09-04 13:03:32 -0700 (Sat, 04 Sep 2004) - sugarclint - undoing copyrights added in inadvertantly. --clint
1430 r546 - 2004-09-03 11:49:38 -0700 (Fri, 03 Sep 2004) - sugarmsi - removed echo count
1432 r354 - 2004-08-02 23:00:37 -0700 (Mon, 02 Aug 2004) - sugarjacob - Adding Soap
1442 * Contains information for a SOAP fault.
1443 * Mainly used for returning faults from deployed functions
1444 * in a server instance.
1445 * @author Dietrich Ayala <dietrich@ganx4.com>
1449 class nusoap_fault extends nusoap_base {
1451 * The fault code (client|server)
1463 * The fault string, a description of the fault
1469 * The fault detail, typically a string or array of string
1478 * @param string $faultcode (SOAP-ENV:Client | SOAP-ENV:Server)
1479 * @param string $faultactor only used when msg routed between multiple actors
1480 * @param string $faultstring human readable error message
1481 * @param mixed $faultdetail detail, typically a string or array of string
1483 function nusoap_fault($faultcode,$faultactor='',$faultstring='',$faultdetail=''){
1484 parent::nusoap_base();
1485 $this->faultcode = $faultcode;
1486 $this->faultactor = $faultactor;
1487 $this->faultstring = $faultstring;
1488 $this->faultdetail = $faultdetail;
1494 * @return string The serialization of the fault instance.
1497 function serialize(){
1499 foreach($this->namespaces as $k => $v){
1500 $ns_string .= "\n xmlns:$k=\"$v\"";
1503 '<?xml version="1.0" encoding="'.$this->soap_defencoding.'"?>'.
1504 '<SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"'.$ns_string.">\n".
1507 $this->serialize_val($this->faultcode, 'faultcode').
1508 $this->serialize_val($this->faultactor, 'faultactor').
1509 $this->serialize_val($this->faultstring, 'faultstring').
1510 $this->serialize_val($this->faultdetail, 'detail').
1511 '</SOAP-ENV:Fault>'.
1513 '</SOAP-ENV:Envelope>';
1519 * Backward compatibility
1521 class soap_fault extends nusoap_fault {
1528 Modification information for LGPL compliance
1530 r58622 - 2010-10-22 18:18:59 -0700 (Fri, 22 Oct 2010) - engsvnbuild - Author: lam <lam@198.18.142.201>
1533 r58361 - 2010-09-29 16:59:02 -0700 (Wed, 29 Sep 2010) - kjing - Author: Jenny Gonsalves <jenny@sugarcrm.com>
1534 Merging with maint_6_0_1 (svn merge -r 58250:58342)
1536 r57813 - 2010-08-19 10:34:44 -0700 (Thu, 19 Aug 2010) - kjing - Author: John Mertic <jmertic@sugarcrm.com>
1537 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.
1539 r57707 - 2010-08-10 12:26:13 -0700 (Tue, 10 Aug 2010) - kjing - Author: Stanislav Malyshev <smalyshev@gmail.com>
1540 fix SOAP calls with no parameters
1542 r56990 - 2010-06-16 13:05:36 -0700 (Wed, 16 Jun 2010) - kjing - snapshot "Mango" svn branch to a new one for GitHub sync
1544 r56989 - 2010-06-16 13:01:33 -0700 (Wed, 16 Jun 2010) - kjing - defunt "Mango" svn dev branch before github cutover
1546 r55980 - 2010-04-19 13:31:28 -0700 (Mon, 19 Apr 2010) - kjing - create Mango (6.1) based on windex
1548 r51719 - 2009-10-22 10:18:00 -0700 (Thu, 22 Oct 2009) - mitani - Converted to Build 3 tags and updated the build system
1550 r51634 - 2009-10-19 13:32:22 -0700 (Mon, 19 Oct 2009) - mitani - Windex is the branch for Sugar Sales 1.0 development
1552 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.
1554 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.
1556 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:
1557 - Changing all ereg function to either preg or simple string based ones
1558 - No more references to magic quotes.
1559 - Change all the session_unregister() functions to just unset() the correct session variable instead.
1561 r50375 - 2009-08-24 18:07:43 -0700 (Mon, 24 Aug 2009) - dwong - branch kobe2 from tokyo r50372
1563 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
1565 r45680 - 2009-03-30 14:34:35 -0700 (Mon, 30 Mar 2009) - Samir Gandhi - modifeid serializeSchema to generate WS-I compliant WSDL
1567 r42807 - 2008-12-29 11:16:59 -0800 (Mon, 29 Dec 2008) - dwong - Branch from trunk/sugarcrm r42806 to branches/tokyo/sugarcrm
1569 r42645 - 2008-12-18 13:41:08 -0800 (Thu, 18 Dec 2008) - awu - merging maint_5_2_0 rev41336:HEAD to trunk
1571 r41647 - 2008-11-11 17:44:30 -0800 (Tue, 11 Nov 2008) - majed - Fixes a few bugs
1573 r41596 - 2008-11-10 19:20:04 -0800 (Mon, 10 Nov 2008) - Samir Gandhi - modified to set $method in the code
1575 r41558 - 2008-11-10 14:35:34 -0800 (Mon, 10 Nov 2008) - majed - changes nusoap to allow for registering classes
1577 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.
1579 - data/SugarBean.php
1580 - include/domit/php_http_client_generic.php
1581 - include/domit/php_http_connector.php
1582 - include/domit/testing_domit.php
1583 - include/domit/xml_domit_getelementsbypath.php
1584 - include/domit/xml_domit_lite_parser.php
1585 - include/domit/xml_domit_nodemaps.php
1586 - include/domit/xml_domit_parser.php
1587 - include/domit/xml_domit_shared.php
1588 - include/generic/SugarWidgets/SugarWidgetField.php
1589 - include/generic/SugarWidgets/SugarWidgetReportField.php
1590 - include/ListView/ProcessView.php
1591 - include/nusoap/class.soapclient.php
1592 - include/nusoap/nusoap.php
1593 - include/nusoap/nusoapmime.php
1594 - include/Pear/HTML_Safe/Safe.php
1595 - include/Pear/XML_HTMLSax3/HTMLSax3.php
1596 - modules/Administration/RebuildWorkFlow.php
1597 - modules/Expressions/RelateSelector.php
1598 - modules/Reports/templates/templates_reports.php
1599 - modules/WorkFlow/Delete.php
1600 - modules/WorkFlow/Save.php
1601 - modules/WorkFlow/SaveSequence.php
1602 - modules/WorkFlow/WorkFlow.php
1603 - modules/WorkFlowActionShells/CreateStep1.php
1604 - modules/WorkFlowActionShells/CreateStep2.php
1605 - modules/WorkFlowActionShells/Save.php
1606 - modules/WorkFlowActionShells/WorkFlowActionShell.php
1607 - modules/WorkFlowAlerts/Save.php
1608 - modules/WorkFlowAlerts/WorkFlowAlert.php
1609 - modules/WorkFlowAlertShells/DetailView.php
1610 - modules/WorkFlowAlertShells/WorkFlowAlertShell.php
1611 - modules/WorkFlowTriggerShells/CreateStep1.php
1612 - modules/WorkFlowTriggerShells/CreateStepFilter.php
1613 - modules/WorkFlowTriggerShells/SaveFilter.php
1614 - modules/WorkFlowTriggerShells/WorkFlowTriggerShell.php
1615 - soap/SoapHelperFunctions.php
1616 - test/modules/DynamicFields/DynamicFields_Bug24095_test.php
1617 - test/simpletest/browser.php
1618 - test/simpletest/default_reporter.php
1619 - test/simpletest/detached.php
1620 - test/simpletest/eclipse.php
1621 - test/simpletest/expectation.php
1622 - test/simpletest/extensions/pear_test_case.php
1623 - test/simpletest/form.php
1624 - test/simpletest/http.php
1625 - test/simpletest/mock_objects.php
1626 - test/simpletest/page.php
1627 - test/simpletest/parser.php
1628 - test/simpletest/remote.php
1629 - test/simpletest/shell_tester.php
1630 - test/simpletest/simple_test.php
1631 - test/simpletest/simpletest.php
1632 - test/simpletest/test/acceptance_test.php
1633 - test/simpletest/test/adapter_test.php
1634 - test/simpletest/test/authentication_test.php
1635 - test/simpletest/test/browser_test.php
1636 - test/simpletest/test/collector_test.php
1637 - test/simpletest/test/compatibility_test.php
1638 - test/simpletest/test/detached_test.php
1639 - test/simpletest/test/eclipse_test.php
1640 - test/simpletest/test/encoding_test.php
1641 - test/simpletest/test/errors_test.php
1642 - test/simpletest/test/expectation_test.php
1643 - test/simpletest/test/form_test.php
1644 - test/simpletest/test/frames_test.php
1645 - test/simpletest/test/http_test.php
1646 - test/simpletest/test/live_test.php
1647 - test/simpletest/test/mock_objects_test.php
1648 - test/simpletest/test/page_test.php
1649 - test/simpletest/test/parse_error_test.php
1650 - test/simpletest/test/parser_test.php
1651 - test/simpletest/test/remote_test.php
1652 - test/simpletest/test/shell_test.php
1653 - test/simpletest/test/shell_tester_test.php
1654 - test/simpletest/test/simpletest_test.php
1655 - test/simpletest/test/site/page_request.php
1656 - test/simpletest/test/tag_test.php
1657 - test/simpletest/test/unit_tester_test.php
1658 - test/simpletest/test/user_agent_test.php
1659 - test/simpletest/test/visual_test.php
1660 - test/simpletest/test/xml_test.php
1661 - test/simpletest/test_case.php
1662 - test/simpletest/ui/array_reporter/test.php
1663 - test/simpletest/ui/recorder/test.php
1664 - test/simpletest/unit_tester.php
1665 - test/simpletest/url.php
1666 - test/simpletest/user_agent.php
1667 - test/simpletest/web_tester.php
1668 - test/spikephpcoverage/src/PEAR.php
1669 - test/spikephpcoverage/src/util/Utility.php
1670 - test/spikephpcoverage/src/XML/Parser.php
1671 - test/spikephpcoverage/src/XML/Parser/Simple.php
1672 - test/test_utilities/SugarTest_SimpleBrowser.php
1674 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.
1676 r38300 - 2008-07-25 13:33:43 -0700 (Fri, 25 Jul 2008) - Samir Gandhi - put the debug in parseresponse function
1678 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
1680 r36824 - 2008-06-18 09:26:11 -0700 (Wed, 18 Jun 2008) - roger - bug: 21832
1682 r26422 - 2007-09-05 17:29:12 -0700 (Wed, 05 Sep 2007) - majed - migrate from beta 1 to trunk
1684 r15787 - 2006-08-10 10:14:41 -0700 (Thu, 10 Aug 2006) - roger - RRS: bug 7961
1686 r14701 - 2006-07-17 13:37:26 -0700 (Mon, 17 Jul 2006) - roger - RRS: bug 5801
1688 r13782 - 2006-06-06 10:58:55 -0700 (Tue, 06 Jun 2006) - majed - changes entry point code
1690 r11466 - 2006-02-01 15:49:47 -0800 (Wed, 01 Feb 2006) - jacob - Adding extra !empty check to get around a PHP warning.
1692 r11115 - 2006-01-17 14:54:45 -0800 (Tue, 17 Jan 2006) - majed - add entry point validation
1694 r10585 - 2005-12-13 14:42:26 -0800 (Tue, 13 Dec 2005) - majed - adds new license mechanisim
1696 r10170 - 2005-12-05 18:37:46 -0800 (Mon, 05 Dec 2005) - majed - fixes various issues
1698 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.
1700 r8991 - 2005-11-03 19:07:25 -0800 (Thu, 03 Nov 2005) - majed - fixes nusoap issue
1702 r8846 - 2005-10-31 11:01:12 -0800 (Mon, 31 Oct 2005) - majed - new version of nusoap
1704 r7905 - 2005-09-21 19:12:57 -0700 (Wed, 21 Sep 2005) - majed - restores old nusoap pre & with a few fixes
1706 r7861 - 2005-09-20 15:40:25 -0700 (Tue, 20 Sep 2005) - majed - & fix for 3.5.1
1708 r7452 - 2005-08-17 11:32:34 -0700 (Wed, 17 Aug 2005) - majed - changes soap to nusoap
1710 r5820 - 2005-06-21 14:22:24 -0700 (Tue, 21 Jun 2005) - majed - fixes issues with nusoap and with custom fields
1712 r5462 - 2005-05-25 13:50:11 -0700 (Wed, 25 May 2005) - majed - upgraded nusoap to .6.9
1714 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
1716 r573 - 2004-09-04 13:03:32 -0700 (Sat, 04 Sep 2004) - sugarclint - undoing copyrights added in inadvertantly. --clint
1718 r546 - 2004-09-03 11:49:38 -0700 (Fri, 03 Sep 2004) - sugarmsi - removed echo count
1720 r354 - 2004-08-02 23:00:37 -0700 (Mon, 02 Aug 2004) - sugarjacob - Adding Soap
1730 * parses an XML Schema, allows access to it's data, other utility methods.
1731 * imperfect, no validation... yet, but quite functional.
1733 * @author Dietrich Ayala <dietrich@ganx4.com>
1734 * @author Scott Nichol <snichol@users.sourceforge.net>
1738 class nusoap_xmlschema extends nusoap_base {
1744 var $enclosingNamespaces;
1746 var $schemaInfo = array();
1747 var $schemaTargetNamespace = '';
1748 // types, elements, attributes defined by the schema
1749 var $attributes = array();
1750 var $complexTypes = array();
1751 var $complexTypeStack = array();
1752 var $currentComplexType = null;
1753 var $elements = array();
1754 var $elementStack = array();
1755 var $currentElement = null;
1756 var $simpleTypes = array();
1757 var $simpleTypeStack = array();
1758 var $currentSimpleType = null;
1760 var $imports = array();
1765 var $depth_array = array();
1766 var $message = array();
1767 var $defaultNamespace = array();
1772 * @param string $schema schema document URI
1773 * @param string $xml xml document URI
1774 * @param string $namespaces namespaces defined in enclosing XML
1777 function nusoap_xmlschema($schema='',$xml='',$namespaces=array()){
1778 parent::nusoap_base();
1779 $this->debug('nusoap_xmlschema class instantiated, inside constructor');
1781 $this->schema = $schema;
1785 $this->enclosingNamespaces = $namespaces;
1786 $this->namespaces = array_merge($this->namespaces, $namespaces);
1788 // parse schema file
1790 $this->debug('initial schema file: '.$schema);
1791 $this->parseFile($schema, 'schema');
1796 $this->debug('initial xml file: '.$xml);
1797 $this->parseFile($xml, 'xml');
1805 * @param string $xml path/URL to XML file
1806 * @param string $type (schema | xml)
1810 function parseFile($xml,$type){
1813 $xmlStr = @join("",@file($xml));
1815 $msg = 'Error reading XML from '.$xml;
1816 $this->setError($msg);
1820 $this->debug("parsing $xml");
1821 $this->parseString($xmlStr,$type);
1822 $this->debug("done parsing $xml");
1830 * parse an XML string
1832 * @param string $xml path or URL
1833 * @param string $type (schema|xml)
1836 function parseString($xml,$type){
1840 // Create an XML parser.
1841 $this->parser = xml_parser_create();
1842 // Set the options for parsing the XML data.
1843 xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
1845 // Set the object for the parser.
1846 xml_set_object($this->parser, $this);
1848 // Set the element handlers for the parser.
1849 if($type == "schema"){
1850 xml_set_element_handler($this->parser, 'schemaStartElement','schemaEndElement');
1851 xml_set_character_data_handler($this->parser,'schemaCharacterData');
1852 } elseif($type == "xml"){
1853 xml_set_element_handler($this->parser, 'xmlStartElement','xmlEndElement');
1854 xml_set_character_data_handler($this->parser,'xmlCharacterData');
1857 // Parse the XML file.
1858 if(!xml_parse($this->parser,$xml,true)){
1859 // Display an error message.
1860 $errstr = sprintf('XML error parsing XML schema on line %d: %s',
1861 xml_get_current_line_number($this->parser),
1862 xml_error_string(xml_get_error_code($this->parser))
1864 $this->debug($errstr);
1865 $this->debug("XML payload:\n" . $xml);
1866 $this->setError($errstr);
1869 xml_parser_free($this->parser);
1871 $this->debug('no xml passed to parseString()!!');
1872 $this->setError('no xml passed to parseString()!!');
1877 * gets a type name for an unnamed type
1879 * @param string Element name
1880 * @return string A type name for an unnamed type
1883 function CreateTypeName($ename) {
1885 for ($i = 0; $i < count($this->complexTypeStack); $i++) {
1886 $scope .= $this->complexTypeStack[$i] . '_';
1888 return $scope . $ename . '_ContainedType';
1892 * start-element handler
1894 * @param string $parser XML parser object
1895 * @param string $name element name
1896 * @param string $attrs associative array of attributes
1899 function schemaStartElement($parser, $name, $attrs) {
1901 // position in the total number of elements, starting from 0
1902 $pos = $this->position++;
1903 $depth = $this->depth++;
1904 // set self as current value for this depth
1905 $this->depth_array[$depth] = $pos;
1906 $this->message[$pos] = array('cdata' => '');
1908 $this->defaultNamespace[$pos] = $this->defaultNamespace[$this->depth_array[$depth - 1]];
1910 $this->defaultNamespace[$pos] = false;
1913 // get element prefix
1914 if($prefix = $this->getPrefix($name)){
1915 // get unqualified name
1916 $name = $this->getLocalPart($name);
1921 // loop thru attributes, expanding, and registering namespace declarations
1922 if(count($attrs) > 0){
1923 foreach($attrs as $k => $v){
1924 // if ns declarations, add to class level array of valid namespaces
1925 if(preg_match('/^xmlns/',$k)){
1926 //$this->xdebug("$k: $v");
1927 //$this->xdebug('ns_prefix: '.$this->getPrefix($k));
1928 if($ns_prefix = substr(strrchr($k,':'),1)){
1929 //$this->xdebug("Add namespace[$ns_prefix] = $v");
1930 $this->namespaces[$ns_prefix] = $v;
1932 $this->defaultNamespace[$pos] = $v;
1933 if (! $this->getPrefixFromNamespace($v)) {
1934 $this->namespaces['ns'.(count($this->namespaces)+1)] = $v;
1937 if($v == 'http://www.w3.org/2001/XMLSchema' || $v == 'http://www.w3.org/1999/XMLSchema' || $v == 'http://www.w3.org/2000/10/XMLSchema'){
1938 $this->XMLSchemaVersion = $v;
1939 $this->namespaces['xsi'] = $v.'-instance';
1943 foreach($attrs as $k => $v){
1944 // expand each attribute
1945 $k = strpos($k,':') ? $this->expandQname($k) : $k;
1946 $v = strpos($v,':') ? $this->expandQname($v) : $v;
1953 // find status, register data
1955 case 'all': // (optional) compositor content for a complexType
1959 //$this->xdebug("compositor $name for currentComplexType: $this->currentComplexType and currentElement: $this->currentElement");
1960 $this->complexTypes[$this->currentComplexType]['compositor'] = $name;
1961 //if($name == 'all' || $name == 'sequence'){
1962 // $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
1965 case 'attribute': // complexType attribute
1966 //$this->xdebug("parsing attribute $attrs[name] $attrs[ref] of value: ".$attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']);
1967 $this->xdebug("parsing attribute:");
1968 $this->appendDebug($this->varDump($attrs));
1969 if (!isset($attrs['form'])) {
1970 // TODO: handle globals
1971 $attrs['form'] = $this->schemaInfo['attributeFormDefault'];
1973 if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])) {
1974 $v = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
1975 if (!strpos($v, ':')) {
1976 // no namespace in arrayType attribute value...
1977 if ($this->defaultNamespace[$pos]) {
1978 // ...so use the default
1979 $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'] = $this->defaultNamespace[$pos] . ':' . $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
1983 if(isset($attrs['name'])){
1984 $this->attributes[$attrs['name']] = $attrs;
1985 $aname = $attrs['name'];
1986 } elseif(isset($attrs['ref']) && $attrs['ref'] == 'http://schemas.xmlsoap.org/soap/encoding/:arrayType'){
1987 if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])) {
1988 $aname = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
1992 } elseif(isset($attrs['ref'])){
1993 $aname = $attrs['ref'];
1994 $this->attributes[$attrs['ref']] = $attrs;
1997 if($this->currentComplexType){ // This should *always* be
1998 $this->complexTypes[$this->currentComplexType]['attrs'][$aname] = $attrs;
2000 // arrayType attribute
2001 if(isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']) || $this->getLocalPart($aname) == 'arrayType'){
2002 $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
2003 $prefix = $this->getPrefix($aname);
2004 if(isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])){
2005 $v = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
2009 if(strpos($v,'[,]')){
2010 $this->complexTypes[$this->currentComplexType]['multidimensional'] = true;
2012 $v = substr($v,0,strpos($v,'[')); // clip the []
2013 if(!strpos($v,':') && isset($this->typemap[$this->XMLSchemaVersion][$v])){
2014 $v = $this->XMLSchemaVersion.':'.$v;
2016 $this->complexTypes[$this->currentComplexType]['arrayType'] = $v;
2019 case 'complexContent': // (optional) content for a complexType
2020 $this->xdebug("do nothing for element $name");
2023 array_push($this->complexTypeStack, $this->currentComplexType);
2024 if(isset($attrs['name'])){
2025 // TODO: what is the scope of named complexTypes that appear
2026 // nested within other c complexTypes?
2027 $this->xdebug('processing named complexType '.$attrs['name']);
2028 //$this->currentElement = false;
2029 $this->currentComplexType = $attrs['name'];
2030 $this->complexTypes[$this->currentComplexType] = $attrs;
2031 $this->complexTypes[$this->currentComplexType]['typeClass'] = 'complexType';
2032 // This is for constructs like
2033 // <complexType name="ListOfString" base="soap:Array">
2035 // <element name="string" type="xsd:string"
2036 // minOccurs="0" maxOccurs="unbounded" />
2039 if(isset($attrs['base']) && preg_match('/:Array$/',$attrs['base'])){
2040 $this->xdebug('complexType is unusual array');
2041 $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
2043 $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
2046 $name = $this->CreateTypeName($this->currentElement);
2047 $this->xdebug('processing unnamed complexType for element ' . $this->currentElement . ' named ' . $name);
2048 $this->currentComplexType = $name;
2049 //$this->currentElement = false;
2050 $this->complexTypes[$this->currentComplexType] = $attrs;
2051 $this->complexTypes[$this->currentComplexType]['typeClass'] = 'complexType';
2052 // This is for constructs like
2053 // <complexType name="ListOfString" base="soap:Array">
2055 // <element name="string" type="xsd:string"
2056 // minOccurs="0" maxOccurs="unbounded" />
2059 if(isset($attrs['base']) && preg_match('/:Array$/',$attrs['base'])){
2060 $this->xdebug('complexType is unusual array');
2061 $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
2063 $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
2066 $this->complexTypes[$this->currentComplexType]['simpleContent'] = 'false';
2069 array_push($this->elementStack, $this->currentElement);
2070 if (!isset($attrs['form'])) {
2071 if ($this->currentComplexType) {
2072 $attrs['form'] = $this->schemaInfo['elementFormDefault'];
2075 $attrs['form'] = 'qualified';
2078 if(isset($attrs['type'])){
2079 $this->xdebug("processing typed element ".$attrs['name']." of type ".$attrs['type']);
2080 if (! $this->getPrefix($attrs['type'])) {
2081 if ($this->defaultNamespace[$pos]) {
2082 $attrs['type'] = $this->defaultNamespace[$pos] . ':' . $attrs['type'];
2083 $this->xdebug('used default namespace to make type ' . $attrs['type']);
2086 // This is for constructs like
2087 // <complexType name="ListOfString" base="soap:Array">
2089 // <element name="string" type="xsd:string"
2090 // minOccurs="0" maxOccurs="unbounded" />
2093 if ($this->currentComplexType && $this->complexTypes[$this->currentComplexType]['phpType'] == 'array') {
2094 $this->xdebug('arrayType for unusual array is ' . $attrs['type']);
2095 $this->complexTypes[$this->currentComplexType]['arrayType'] = $attrs['type'];
2097 $this->currentElement = $attrs['name'];
2098 $ename = $attrs['name'];
2099 } elseif(isset($attrs['ref'])){
2100 $this->xdebug("processing element as ref to ".$attrs['ref']);
2101 $this->currentElement = "ref to ".$attrs['ref'];
2102 $ename = $this->getLocalPart($attrs['ref']);
2104 $type = $this->CreateTypeName($this->currentComplexType . '_' . $attrs['name']);
2105 $this->xdebug("processing untyped element " . $attrs['name'] . ' type ' . $type);
2106 $this->currentElement = $attrs['name'];
2107 $attrs['type'] = $this->schemaTargetNamespace . ':' . $type;
2108 $ename = $attrs['name'];
2110 if (isset($ename) && $this->currentComplexType) {
2111 $this->xdebug("add element $ename to complexType $this->currentComplexType");
2112 $this->complexTypes[$this->currentComplexType]['elements'][$ename] = $attrs;
2113 } elseif (!isset($attrs['ref'])) {
2114 $this->xdebug("add element $ename to elements array");
2115 $this->elements[ $attrs['name'] ] = $attrs;
2116 $this->elements[ $attrs['name'] ]['typeClass'] = 'element';
2119 case 'enumeration': // restriction value list member
2120 $this->xdebug('enumeration ' . $attrs['value']);
2121 if ($this->currentSimpleType) {
2122 $this->simpleTypes[$this->currentSimpleType]['enumeration'][] = $attrs['value'];
2123 } elseif ($this->currentComplexType) {
2124 $this->complexTypes[$this->currentComplexType]['enumeration'][] = $attrs['value'];
2127 case 'extension': // simpleContent or complexContent type extension
2128 $this->xdebug('extension ' . $attrs['base']);
2129 if ($this->currentComplexType) {
2130 $ns = $this->getPrefix($attrs['base']);
2132 $this->complexTypes[$this->currentComplexType]['extensionBase'] = $this->schemaTargetNamespace . ':' . $attrs['base'];
2134 $this->complexTypes[$this->currentComplexType]['extensionBase'] = $attrs['base'];
2137 $this->xdebug('no current complexType to set extensionBase');
2141 if (isset($attrs['schemaLocation'])) {
2142 $this->xdebug('import namespace ' . $attrs['namespace'] . ' from ' . $attrs['schemaLocation']);
2143 $this->imports[$attrs['namespace']][] = array('location' => $attrs['schemaLocation'], 'loaded' => false);
2145 $this->xdebug('import namespace ' . $attrs['namespace']);
2146 $this->imports[$attrs['namespace']][] = array('location' => '', 'loaded' => true);
2147 if (! $this->getPrefixFromNamespace($attrs['namespace'])) {
2148 $this->namespaces['ns'.(count($this->namespaces)+1)] = $attrs['namespace'];
2153 if (isset($attrs['schemaLocation'])) {
2154 $this->xdebug('include into namespace ' . $this->schemaTargetNamespace . ' from ' . $attrs['schemaLocation']);
2155 $this->imports[$this->schemaTargetNamespace][] = array('location' => $attrs['schemaLocation'], 'loaded' => false);
2157 $this->xdebug('ignoring invalid XML Schema construct: include without schemaLocation attribute');
2160 case 'list': // simpleType value list
2161 $this->xdebug("do nothing for element $name");
2163 case 'restriction': // simpleType, simpleContent or complexContent value restriction
2164 $this->xdebug('restriction ' . $attrs['base']);
2165 if($this->currentSimpleType){
2166 $this->simpleTypes[$this->currentSimpleType]['type'] = $attrs['base'];
2167 } elseif($this->currentComplexType){
2168 $this->complexTypes[$this->currentComplexType]['restrictionBase'] = $attrs['base'];
2169 if(strstr($attrs['base'],':') == ':Array'){
2170 $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
2175 $this->schemaInfo = $attrs;
2176 $this->schemaInfo['schemaVersion'] = $this->getNamespaceFromPrefix($prefix);
2177 if (isset($attrs['targetNamespace'])) {
2178 $this->schemaTargetNamespace = $attrs['targetNamespace'];
2180 if (!isset($attrs['elementFormDefault'])) {
2181 $this->schemaInfo['elementFormDefault'] = 'unqualified';
2183 if (!isset($attrs['attributeFormDefault'])) {
2184 $this->schemaInfo['attributeFormDefault'] = 'unqualified';
2187 case 'simpleContent': // (optional) content for a complexType
2188 if ($this->currentComplexType) { // This should *always* be
2189 $this->complexTypes[$this->currentComplexType]['simpleContent'] = 'true';
2191 $this->xdebug("do nothing for element $name because there is no current complexType");
2195 array_push($this->simpleTypeStack, $this->currentSimpleType);
2196 if(isset($attrs['name'])){
2197 $this->xdebug("processing simpleType for name " . $attrs['name']);
2198 $this->currentSimpleType = $attrs['name'];
2199 $this->simpleTypes[ $attrs['name'] ] = $attrs;
2200 $this->simpleTypes[ $attrs['name'] ]['typeClass'] = 'simpleType';
2201 $this->simpleTypes[ $attrs['name'] ]['phpType'] = 'scalar';
2203 $name = $this->CreateTypeName($this->currentComplexType . '_' . $this->currentElement);
2204 $this->xdebug('processing unnamed simpleType for element ' . $this->currentElement . ' named ' . $name);
2205 $this->currentSimpleType = $name;
2206 //$this->currentElement = false;
2207 $this->simpleTypes[$this->currentSimpleType] = $attrs;
2208 $this->simpleTypes[$this->currentSimpleType]['phpType'] = 'scalar';
2211 case 'union': // simpleType type list
2212 $this->xdebug("do nothing for element $name");
2215 $this->xdebug("do not have any logic to process element $name");
2220 * end-element handler
2222 * @param string $parser XML parser object
2223 * @param string $name element name
2226 function schemaEndElement($parser, $name) {
2227 // bring depth down a notch
2229 // position of current element is equal to the last value left in depth_array for my depth
2230 if(isset($this->depth_array[$this->depth])){
2231 $pos = $this->depth_array[$this->depth];
2233 // get element prefix
2234 if ($prefix = $this->getPrefix($name)){
2235 // get unqualified name
2236 $name = $this->getLocalPart($name);
2241 if($name == 'complexType'){
2242 $this->xdebug('done processing complexType ' . ($this->currentComplexType ? $this->currentComplexType : '(unknown)'));
2243 $this->xdebug($this->varDump($this->complexTypes[$this->currentComplexType]));
2244 $this->currentComplexType = array_pop($this->complexTypeStack);
2245 //$this->currentElement = false;
2247 if($name == 'element'){
2248 $this->xdebug('done processing element ' . ($this->currentElement ? $this->currentElement : '(unknown)'));
2249 $this->currentElement = array_pop($this->elementStack);
2251 if($name == 'simpleType'){
2252 $this->xdebug('done processing simpleType ' . ($this->currentSimpleType ? $this->currentSimpleType : '(unknown)'));
2253 $this->xdebug($this->varDump($this->simpleTypes[$this->currentSimpleType]));
2254 $this->currentSimpleType = array_pop($this->simpleTypeStack);
2259 * element content handler
2261 * @param string $parser XML parser object
2262 * @param string $data element content
2265 function schemaCharacterData($parser, $data){
2266 $pos = $this->depth_array[$this->depth - 1];
2267 $this->message[$pos]['cdata'] .= $data;
2271 * serialize the schema
2275 function serializeSchema(){
2277 $schemaPrefix = $this->getPrefixFromNamespace($this->XMLSchemaVersion);
2280 $schemaLocationCount = 0;
2281 if (sizeof($this->imports) > 0) {
2282 foreach($this->imports as $ns => $list) {
2283 foreach ($list as $ii) {
2284 if ($ii['location'] != '') {
2285 $xml .= " <$schemaPrefix:import location=\"" . $ii['location'] . '" namespace="' . $ns . "\" />\n";
2287 if ($schemaLocationCount == 0) {
2288 $xml .= " <$schemaPrefix:import namespace=\"" . $ns . "\" schemaLocation=\"" . $ns . "\"/>\n";
2290 $xml .= " <$schemaPrefix:import namespace=\"" . $ns . "\" />\n";
2297 foreach($this->complexTypes as $typeName => $attrs){
2299 // serialize child elements
2300 if(isset($attrs['elements']) && (count($attrs['elements']) > 0)){
2301 foreach($attrs['elements'] as $element => $eParts){
2302 if(isset($eParts['ref'])){
2303 $contentStr .= " <$schemaPrefix:element ref=\"$element\"/>\n";
2305 $contentStr .= " <$schemaPrefix:element name=\"$element\" type=\"" . $this->contractQName($eParts['type']) . "\"";
2306 foreach ($eParts as $aName => $aValue) {
2307 // handle, e.g., abstract, default, form, minOccurs, maxOccurs, nillable
2308 if ($aName != 'name' && $aName != 'type') {
2309 $contentStr .= " $aName=\"$aValue\"";
2312 $contentStr .= "/>\n";
2315 // compositor wraps elements
2316 if (isset($attrs['compositor']) && ($attrs['compositor'] != '')) {
2317 $contentStr = " <$schemaPrefix:$attrs[compositor]>\n".$contentStr." </$schemaPrefix:$attrs[compositor]>\n";
2321 if(isset($attrs['attrs']) && (count($attrs['attrs']) >= 1)){
2322 foreach($attrs['attrs'] as $attr => $aParts){
2323 $contentStr .= " <$schemaPrefix:attribute";
2324 foreach ($aParts as $a => $v) {
2325 if ($a == 'ref' || $a == 'type') {
2326 $contentStr .= " $a=\"".$this->contractQName($v).'"';
2327 } elseif ($a == 'http://schemas.xmlsoap.org/wsdl/:arrayType') {
2328 $this->usedNamespaces['wsdl'] = $this->namespaces['wsdl'];
2329 $contentStr .= ' wsdl:arrayType="'.$this->contractQName($v).'"';
2331 $contentStr .= " $a=\"$v\"";
2334 $contentStr .= "/>\n";
2338 if (isset($attrs['restrictionBase']) && $attrs['restrictionBase'] != ''){
2339 $contentStr = " <$schemaPrefix:restriction base=\"".$this->contractQName($attrs['restrictionBase'])."\">\n".$contentStr." </$schemaPrefix:restriction>\n";
2340 // complex or simple content
2341 if ((isset($attrs['elements']) && count($attrs['elements']) > 0) || (isset($attrs['attrs']) && count($attrs['attrs']) > 0)){
2342 $contentStr = " <$schemaPrefix:complexContent>\n".$contentStr." </$schemaPrefix:complexContent>\n";
2345 // finalize complex type
2346 if($contentStr != ''){
2347 $contentStr = " <$schemaPrefix:complexType name=\"$typeName\">\n".$contentStr." </$schemaPrefix:complexType>\n";
2349 $contentStr = " <$schemaPrefix:complexType name=\"$typeName\"/>\n";
2351 $xml .= $contentStr;
2354 if(isset($this->simpleTypes) && count($this->simpleTypes) > 0){
2355 foreach($this->simpleTypes as $typeName => $eParts){
2356 $xml .= " <$schemaPrefix:simpleType name=\"$typeName\">\n <$schemaPrefix:restriction base=\"".$this->contractQName($eParts['type'])."\">\n";
2357 if (isset($eParts['enumeration'])) {
2358 foreach ($eParts['enumeration'] as $e) {
2359 $xml .= " <$schemaPrefix:enumeration value=\"$e\"/>\n";
2362 $xml .= " </$schemaPrefix:restriction>\n </$schemaPrefix:simpleType>";
2366 if(isset($this->elements) && count($this->elements) > 0){
2367 foreach($this->elements as $element => $eParts){
2368 $xml .= " <$schemaPrefix:element name=\"$element\" type=\"".$this->contractQName($eParts['type'])."\"/>\n";
2372 if(isset($this->attributes) && count($this->attributes) > 0){
2373 foreach($this->attributes as $attr => $aParts){
2374 $xml .= " <$schemaPrefix:attribute name=\"$attr\" type=\"".$this->contractQName($aParts['type'])."\"\n/>";
2379 foreach ($this->schemaInfo as $k => $v) {
2380 if ($k == 'elementFormDefault' || $k == 'attributeFormDefault') {
2381 $attr .= " $k=\"$v\"";
2384 $el = "<$schemaPrefix:schema$attr targetNamespace=\"$this->schemaTargetNamespace\"\n";
2385 foreach (array_diff($this->usedNamespaces, $this->enclosingNamespaces) as $nsp => $ns) {
2386 $el .= " xmlns:$nsp=\"$ns\"";
2388 $xml = $el . ">\n".$xml."</$schemaPrefix:schema>\n";
2393 * adds debug data to the clas level debug string
2395 * @param string $string debug data
2398 function xdebug($string){
2399 if($this->debugLevel > 0) {
2400 $this->debug('<' . $this->schemaTargetNamespace . '> '.$string);
2405 * get the PHP type of a user defined type in the schema
2406 * PHP type is kind of a misnomer since it actually returns 'struct' for assoc. arrays
2407 * returns false if no type exists, or not w/ the given namespace
2408 * else returns a string that is either a native php type, or 'struct'
2410 * @param string $type name of defined type
2411 * @param string $ns namespace of type
2416 function getPHPType($type,$ns){
2417 if(isset($this->typemap[$ns][$type])){
2418 //print "found type '$type' and ns $ns in typemap<br>";
2419 return $this->typemap[$ns][$type];
2420 } elseif(isset($this->complexTypes[$type])){
2421 //print "getting type '$type' and ns $ns from complexTypes array<br>";
2422 return $this->complexTypes[$type]['phpType'];
2428 * returns an associative array of information about a given type
2429 * returns false if no type exists by the given name
2431 * For a complexType typeDef = array(
2432 * 'restrictionBase' => '',
2434 * 'compositor' => '(sequence|all)',
2435 * 'elements' => array(), // refs to elements array
2436 * 'attrs' => array() // refs to attributes array
2437 * ... and so on (see addComplexType)
2440 * For simpleType or element, the array has different keys.
2442 * @param string $type
2445 * @see addComplexType
2446 * @see addSimpleType
2449 function getTypeDef($type){
2450 //$this->debug("in getTypeDef for type $type");
2451 if (substr($type, -1) == '^') {
2453 $type = substr($type, 0, -1);
2458 if((! $is_element) && isset($this->complexTypes[$type])){
2459 $this->xdebug("in getTypeDef, found complexType $type");
2460 return $this->complexTypes[$type];
2461 } elseif((! $is_element) && isset($this->simpleTypes[$type])){
2462 $this->xdebug("in getTypeDef, found simpleType $type");
2463 if (!isset($this->simpleTypes[$type]['phpType'])) {
2464 // get info for type to tack onto the simple type
2465 // TODO: can this ever really apply (i.e. what is a simpleType really?)
2466 $uqType = substr($this->simpleTypes[$type]['type'], strrpos($this->simpleTypes[$type]['type'], ':') + 1);
2467 $ns = substr($this->simpleTypes[$type]['type'], 0, strrpos($this->simpleTypes[$type]['type'], ':'));
2468 $etype = $this->getTypeDef($uqType);
2470 $this->xdebug("in getTypeDef, found type for simpleType $type:");
2471 $this->xdebug($this->varDump($etype));
2472 if (isset($etype['phpType'])) {
2473 $this->simpleTypes[$type]['phpType'] = $etype['phpType'];
2475 if (isset($etype['elements'])) {
2476 $this->simpleTypes[$type]['elements'] = $etype['elements'];
2480 return $this->simpleTypes[$type];
2481 } elseif(isset($this->elements[$type])){
2482 $this->xdebug("in getTypeDef, found element $type");
2483 if (!isset($this->elements[$type]['phpType'])) {
2484 // get info for type to tack onto the element
2485 $uqType = substr($this->elements[$type]['type'], strrpos($this->elements[$type]['type'], ':') + 1);
2486 $ns = substr($this->elements[$type]['type'], 0, strrpos($this->elements[$type]['type'], ':'));
2487 $etype = $this->getTypeDef($uqType);
2489 $this->xdebug("in getTypeDef, found type for element $type:");
2490 $this->xdebug($this->varDump($etype));
2491 if (isset($etype['phpType'])) {
2492 $this->elements[$type]['phpType'] = $etype['phpType'];
2494 if (isset($etype['elements'])) {
2495 $this->elements[$type]['elements'] = $etype['elements'];
2497 if (isset($etype['extensionBase'])) {
2498 $this->elements[$type]['extensionBase'] = $etype['extensionBase'];
2500 } elseif ($ns == 'http://www.w3.org/2001/XMLSchema') {
2501 $this->xdebug("in getTypeDef, element $type is an XSD type");
2502 $this->elements[$type]['phpType'] = 'scalar';
2505 return $this->elements[$type];
2506 } elseif(isset($this->attributes[$type])){
2507 $this->xdebug("in getTypeDef, found attribute $type");
2508 return $this->attributes[$type];
2509 } elseif (preg_match('/_ContainedType$/', $type)) {
2510 $this->xdebug("in getTypeDef, have an untyped element $type");
2511 $typeDef['typeClass'] = 'simpleType';
2512 $typeDef['phpType'] = 'scalar';
2513 $typeDef['type'] = 'http://www.w3.org/2001/XMLSchema:string';
2516 $this->xdebug("in getTypeDef, did not find $type");
2521 * returns a sample serialization of a given type, or false if no type by the given name
2523 * @param string $type name of type
2528 function serializeTypeDef($type){
2529 //print "in sTD() for type $type<br>";
2530 if($typeDef = $this->getTypeDef($type)){
2532 if(is_array($typeDef['attrs'])){
2533 foreach($typeDef['attrs'] as $attName => $data){
2534 $str .= " $attName=\"{type = ".$data['type']."}\"";
2537 $str .= " xmlns=\"".$this->schema['targetNamespace']."\"";
2538 if(count($typeDef['elements']) > 0){
2540 foreach($typeDef['elements'] as $element => $eData){
2541 $str .= $this->serializeTypeDef($element);
2544 } elseif($typeDef['typeClass'] == 'element') {
2545 $str .= "></$type>";
2555 * returns HTML form elements that allow a user
2556 * to enter values for creating an instance of the given type.
2558 * @param string $name name for type instance
2559 * @param string $type name of type
2564 function typeToForm($name,$type){
2566 if($typeDef = $this->getTypeDef($type)){
2568 if($typeDef['phpType'] == 'struct'){
2569 $buffer .= '<table>';
2570 foreach($typeDef['elements'] as $child => $childDef){
2572 <tr><td align='right'>$childDef[name] (type: ".$this->getLocalPart($childDef['type'])."):</td>
2573 <td><input type='text' name='parameters[".$name."][$childDef[name]]'></td></tr>";
2575 $buffer .= '</table>';
2577 } elseif($typeDef['phpType'] == 'array'){
2578 $buffer .= '<table>';
2579 for($i=0;$i < 3; $i++){
2581 <tr><td align='right'>array item (type: $typeDef[arrayType]):</td>
2582 <td><input type='text' name='parameters[".$name."][]'></td></tr>";
2584 $buffer .= '</table>';
2587 $buffer .= "<input type='text' name='parameters[$name]'>";
2590 $buffer .= "<input type='text' name='parameters[$name]'>";
2596 * adds a complex type to the schema
2606 * array('ref'=>'SOAP-ENC:arrayType','wsdl:arrayType'=>'string[]'),
2610 * example: PHP associative array ( SOAP Struct )
2617 * array('myVar'=> array('name'=>'myVar','type'=>'string')
2621 * @param typeClass (complexType|simpleType|attribute)
2622 * @param phpType: currently supported are array and struct (php assoc array)
2623 * @param compositor (all|sequence|choice)
2624 * @param restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
2625 * @param elements = array ( name = array(name=>'',type=>'') )
2626 * @param attrs = array(
2628 * 'ref' => "http://schemas.xmlsoap.org/soap/encoding/:arrayType",
2629 * "http://schemas.xmlsoap.org/wsdl/:arrayType" => "string[]"
2632 * @param arrayType: namespace:name (http://www.w3.org/2001/XMLSchema:string)
2636 function addComplexType($name,$typeClass='complexType',$phpType='array',$compositor='',$restrictionBase='',$elements=array(),$attrs=array(),$arrayType=''){
2637 $this->complexTypes[$name] = array(
2639 'typeClass' => $typeClass,
2640 'phpType' => $phpType,
2641 'compositor'=> $compositor,
2642 'restrictionBase' => $restrictionBase,
2643 'elements' => $elements,
2645 'arrayType' => $arrayType
2648 $this->xdebug("addComplexType $name:");
2649 $this->appendDebug($this->varDump($this->complexTypes[$name]));
2653 * adds a simple type to the schema
2655 * @param string $name
2656 * @param string $restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
2657 * @param string $typeClass (should always be simpleType)
2658 * @param string $phpType (should always be scalar)
2659 * @param array $enumeration array of values
2661 * @see nusoap_xmlschema
2664 function addSimpleType($name, $restrictionBase='', $typeClass='simpleType', $phpType='scalar', $enumeration=array()) {
2665 $this->simpleTypes[$name] = array(
2667 'typeClass' => $typeClass,
2668 'phpType' => $phpType,
2669 'type' => $restrictionBase,
2670 'enumeration' => $enumeration
2673 $this->xdebug("addSimpleType $name:");
2674 $this->appendDebug($this->varDump($this->simpleTypes[$name]));
2678 * adds an element to the schema
2680 * @param array $attrs attributes that must include name and type
2681 * @see nusoap_xmlschema
2684 function addElement($attrs) {
2685 if (! $this->getPrefix($attrs['type'])) {
2686 $attrs['type'] = $this->schemaTargetNamespace . ':' . $attrs['type'];
2688 $this->elements[ $attrs['name'] ] = $attrs;
2689 $this->elements[ $attrs['name'] ]['typeClass'] = 'element';
2691 $this->xdebug("addElement " . $attrs['name']);
2692 $this->appendDebug($this->varDump($this->elements[ $attrs['name'] ]));
2697 * Backward compatibility
2699 class XMLSchema extends nusoap_xmlschema {
2706 Modification information for LGPL compliance
2708 r58622 - 2010-10-22 18:18:59 -0700 (Fri, 22 Oct 2010) - engsvnbuild - Author: lam <lam@198.18.142.201>
2711 r58361 - 2010-09-29 16:59:02 -0700 (Wed, 29 Sep 2010) - kjing - Author: Jenny Gonsalves <jenny@sugarcrm.com>
2712 Merging with maint_6_0_1 (svn merge -r 58250:58342)
2714 r57813 - 2010-08-19 10:34:44 -0700 (Thu, 19 Aug 2010) - kjing - Author: John Mertic <jmertic@sugarcrm.com>
2715 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.
2717 r57707 - 2010-08-10 12:26:13 -0700 (Tue, 10 Aug 2010) - kjing - Author: Stanislav Malyshev <smalyshev@gmail.com>
2718 fix SOAP calls with no parameters
2720 r56990 - 2010-06-16 13:05:36 -0700 (Wed, 16 Jun 2010) - kjing - snapshot "Mango" svn branch to a new one for GitHub sync
2722 r56989 - 2010-06-16 13:01:33 -0700 (Wed, 16 Jun 2010) - kjing - defunt "Mango" svn dev branch before github cutover
2724 r55980 - 2010-04-19 13:31:28 -0700 (Mon, 19 Apr 2010) - kjing - create Mango (6.1) based on windex
2726 r51719 - 2009-10-22 10:18:00 -0700 (Thu, 22 Oct 2009) - mitani - Converted to Build 3 tags and updated the build system
2728 r51634 - 2009-10-19 13:32:22 -0700 (Mon, 19 Oct 2009) - mitani - Windex is the branch for Sugar Sales 1.0 development
2730 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.
2732 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.
2734 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:
2735 - Changing all ereg function to either preg or simple string based ones
2736 - No more references to magic quotes.
2737 - Change all the session_unregister() functions to just unset() the correct session variable instead.
2739 r50375 - 2009-08-24 18:07:43 -0700 (Mon, 24 Aug 2009) - dwong - branch kobe2 from tokyo r50372
2741 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
2743 r45680 - 2009-03-30 14:34:35 -0700 (Mon, 30 Mar 2009) - Samir Gandhi - modifeid serializeSchema to generate WS-I compliant WSDL
2745 r42807 - 2008-12-29 11:16:59 -0800 (Mon, 29 Dec 2008) - dwong - Branch from trunk/sugarcrm r42806 to branches/tokyo/sugarcrm
2747 r42645 - 2008-12-18 13:41:08 -0800 (Thu, 18 Dec 2008) - awu - merging maint_5_2_0 rev41336:HEAD to trunk
2749 r41647 - 2008-11-11 17:44:30 -0800 (Tue, 11 Nov 2008) - majed - Fixes a few bugs
2751 r41596 - 2008-11-10 19:20:04 -0800 (Mon, 10 Nov 2008) - Samir Gandhi - modified to set $method in the code
2753 r41558 - 2008-11-10 14:35:34 -0800 (Mon, 10 Nov 2008) - majed - changes nusoap to allow for registering classes
2755 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.
2757 - data/SugarBean.php
2758 - include/domit/php_http_client_generic.php
2759 - include/domit/php_http_connector.php
2760 - include/domit/testing_domit.php
2761 - include/domit/xml_domit_getelementsbypath.php
2762 - include/domit/xml_domit_lite_parser.php
2763 - include/domit/xml_domit_nodemaps.php
2764 - include/domit/xml_domit_parser.php
2765 - include/domit/xml_domit_shared.php
2766 - include/generic/SugarWidgets/SugarWidgetField.php
2767 - include/generic/SugarWidgets/SugarWidgetReportField.php
2768 - include/ListView/ProcessView.php
2769 - include/nusoap/class.soapclient.php
2770 - include/nusoap/nusoap.php
2771 - include/nusoap/nusoapmime.php
2772 - include/Pear/HTML_Safe/Safe.php
2773 - include/Pear/XML_HTMLSax3/HTMLSax3.php
2774 - modules/Administration/RebuildWorkFlow.php
2775 - modules/Expressions/RelateSelector.php
2776 - modules/Reports/templates/templates_reports.php
2777 - modules/WorkFlow/Delete.php
2778 - modules/WorkFlow/Save.php
2779 - modules/WorkFlow/SaveSequence.php
2780 - modules/WorkFlow/WorkFlow.php
2781 - modules/WorkFlowActionShells/CreateStep1.php
2782 - modules/WorkFlowActionShells/CreateStep2.php
2783 - modules/WorkFlowActionShells/Save.php
2784 - modules/WorkFlowActionShells/WorkFlowActionShell.php
2785 - modules/WorkFlowAlerts/Save.php
2786 - modules/WorkFlowAlerts/WorkFlowAlert.php
2787 - modules/WorkFlowAlertShells/DetailView.php
2788 - modules/WorkFlowAlertShells/WorkFlowAlertShell.php
2789 - modules/WorkFlowTriggerShells/CreateStep1.php
2790 - modules/WorkFlowTriggerShells/CreateStepFilter.php
2791 - modules/WorkFlowTriggerShells/SaveFilter.php
2792 - modules/WorkFlowTriggerShells/WorkFlowTriggerShell.php
2793 - soap/SoapHelperFunctions.php
2794 - test/modules/DynamicFields/DynamicFields_Bug24095_test.php
2795 - test/simpletest/browser.php
2796 - test/simpletest/default_reporter.php
2797 - test/simpletest/detached.php
2798 - test/simpletest/eclipse.php
2799 - test/simpletest/expectation.php
2800 - test/simpletest/extensions/pear_test_case.php
2801 - test/simpletest/form.php
2802 - test/simpletest/http.php
2803 - test/simpletest/mock_objects.php
2804 - test/simpletest/page.php
2805 - test/simpletest/parser.php
2806 - test/simpletest/remote.php
2807 - test/simpletest/shell_tester.php
2808 - test/simpletest/simple_test.php
2809 - test/simpletest/simpletest.php
2810 - test/simpletest/test/acceptance_test.php
2811 - test/simpletest/test/adapter_test.php
2812 - test/simpletest/test/authentication_test.php
2813 - test/simpletest/test/browser_test.php
2814 - test/simpletest/test/collector_test.php
2815 - test/simpletest/test/compatibility_test.php
2816 - test/simpletest/test/detached_test.php
2817 - test/simpletest/test/eclipse_test.php
2818 - test/simpletest/test/encoding_test.php
2819 - test/simpletest/test/errors_test.php
2820 - test/simpletest/test/expectation_test.php
2821 - test/simpletest/test/form_test.php
2822 - test/simpletest/test/frames_test.php
2823 - test/simpletest/test/http_test.php
2824 - test/simpletest/test/live_test.php
2825 - test/simpletest/test/mock_objects_test.php
2826 - test/simpletest/test/page_test.php
2827 - test/simpletest/test/parse_error_test.php
2828 - test/simpletest/test/parser_test.php
2829 - test/simpletest/test/remote_test.php
2830 - test/simpletest/test/shell_test.php
2831 - test/simpletest/test/shell_tester_test.php
2832 - test/simpletest/test/simpletest_test.php
2833 - test/simpletest/test/site/page_request.php
2834 - test/simpletest/test/tag_test.php
2835 - test/simpletest/test/unit_tester_test.php
2836 - test/simpletest/test/user_agent_test.php
2837 - test/simpletest/test/visual_test.php
2838 - test/simpletest/test/xml_test.php
2839 - test/simpletest/test_case.php
2840 - test/simpletest/ui/array_reporter/test.php
2841 - test/simpletest/ui/recorder/test.php
2842 - test/simpletest/unit_tester.php
2843 - test/simpletest/url.php
2844 - test/simpletest/user_agent.php
2845 - test/simpletest/web_tester.php
2846 - test/spikephpcoverage/src/PEAR.php
2847 - test/spikephpcoverage/src/util/Utility.php
2848 - test/spikephpcoverage/src/XML/Parser.php
2849 - test/spikephpcoverage/src/XML/Parser/Simple.php
2850 - test/test_utilities/SugarTest_SimpleBrowser.php
2852 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.
2854 r38300 - 2008-07-25 13:33:43 -0700 (Fri, 25 Jul 2008) - Samir Gandhi - put the debug in parseresponse function
2856 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
2858 r36824 - 2008-06-18 09:26:11 -0700 (Wed, 18 Jun 2008) - roger - bug: 21832
2860 r26422 - 2007-09-05 17:29:12 -0700 (Wed, 05 Sep 2007) - majed - migrate from beta 1 to trunk
2862 r15787 - 2006-08-10 10:14:41 -0700 (Thu, 10 Aug 2006) - roger - RRS: bug 7961
2864 r14701 - 2006-07-17 13:37:26 -0700 (Mon, 17 Jul 2006) - roger - RRS: bug 5801
2866 r13782 - 2006-06-06 10:58:55 -0700 (Tue, 06 Jun 2006) - majed - changes entry point code
2868 r11466 - 2006-02-01 15:49:47 -0800 (Wed, 01 Feb 2006) - jacob - Adding extra !empty check to get around a PHP warning.
2870 r11115 - 2006-01-17 14:54:45 -0800 (Tue, 17 Jan 2006) - majed - add entry point validation
2872 r10585 - 2005-12-13 14:42:26 -0800 (Tue, 13 Dec 2005) - majed - adds new license mechanisim
2874 r10170 - 2005-12-05 18:37:46 -0800 (Mon, 05 Dec 2005) - majed - fixes various issues
2876 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.
2878 r8991 - 2005-11-03 19:07:25 -0800 (Thu, 03 Nov 2005) - majed - fixes nusoap issue
2880 r8846 - 2005-10-31 11:01:12 -0800 (Mon, 31 Oct 2005) - majed - new version of nusoap
2882 r7905 - 2005-09-21 19:12:57 -0700 (Wed, 21 Sep 2005) - majed - restores old nusoap pre & with a few fixes
2884 r7861 - 2005-09-20 15:40:25 -0700 (Tue, 20 Sep 2005) - majed - & fix for 3.5.1
2886 r7452 - 2005-08-17 11:32:34 -0700 (Wed, 17 Aug 2005) - majed - changes soap to nusoap
2888 r5820 - 2005-06-21 14:22:24 -0700 (Tue, 21 Jun 2005) - majed - fixes issues with nusoap and with custom fields
2890 r5462 - 2005-05-25 13:50:11 -0700 (Wed, 25 May 2005) - majed - upgraded nusoap to .6.9
2892 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
2894 r573 - 2004-09-04 13:03:32 -0700 (Sat, 04 Sep 2004) - sugarclint - undoing copyrights added in inadvertantly. --clint
2896 r546 - 2004-09-03 11:49:38 -0700 (Fri, 03 Sep 2004) - sugarmsi - removed echo count
2898 r354 - 2004-08-02 23:00:37 -0700 (Mon, 02 Aug 2004) - sugarjacob - Adding Soap
2908 * For creating serializable abstractions of native PHP types. This class
2909 * allows element name/namespace, XSD type, and XML attributes to be
2910 * associated with a value. This is extremely useful when WSDL is not
2911 * used, but is also useful when WSDL is used with polymorphic types, including
2912 * xsd:anyType and user-defined types.
2914 * @author Dietrich Ayala <dietrich@ganx4.com>
2918 class soapval extends nusoap_base {
2920 * The XML element name
2927 * The XML type name (string or false)
2941 * The XML element namespace (string or false)
2948 * The XML type namespace (string or false)
2955 * The XML element attributes (array or false)
2965 * @param string $name optional name
2966 * @param mixed $type optional type name
2967 * @param mixed $value optional value
2968 * @param mixed $element_ns optional namespace of value
2969 * @param mixed $type_ns optional namespace of type
2970 * @param mixed $attributes associative array of attributes to add to element serialization
2973 function soapval($name='soapval',$type=false,$value=-1,$element_ns=false,$type_ns=false,$attributes=false) {
2974 parent::nusoap_base();
2975 $this->name = $name;
2976 $this->type = $type;
2977 $this->value = $value;
2978 $this->element_ns = $element_ns;
2979 $this->type_ns = $type_ns;
2980 $this->attributes = $attributes;
2984 * return serialized value
2986 * @param string $use The WSDL use value (encoded|literal)
2987 * @return string XML data
2990 function serialize($use='encoded') {
2991 return $this->serialize_val($this->value, $this->name, $this->type, $this->element_ns, $this->type_ns, $this->attributes, $use, true);
2995 * decodes a soapval object into a PHP native type
3001 return $this->value;
3011 Modification information for LGPL compliance
3013 r58622 - 2010-10-22 18:18:59 -0700 (Fri, 22 Oct 2010) - engsvnbuild - Author: lam <lam@198.18.142.201>
3016 r58361 - 2010-09-29 16:59:02 -0700 (Wed, 29 Sep 2010) - kjing - Author: Jenny Gonsalves <jenny@sugarcrm.com>
3017 Merging with maint_6_0_1 (svn merge -r 58250:58342)
3019 r57813 - 2010-08-19 10:34:44 -0700 (Thu, 19 Aug 2010) - kjing - Author: John Mertic <jmertic@sugarcrm.com>
3020 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.
3022 r57707 - 2010-08-10 12:26:13 -0700 (Tue, 10 Aug 2010) - kjing - Author: Stanislav Malyshev <smalyshev@gmail.com>
3023 fix SOAP calls with no parameters
3025 r56990 - 2010-06-16 13:05:36 -0700 (Wed, 16 Jun 2010) - kjing - snapshot "Mango" svn branch to a new one for GitHub sync
3027 r56989 - 2010-06-16 13:01:33 -0700 (Wed, 16 Jun 2010) - kjing - defunt "Mango" svn dev branch before github cutover
3029 r55980 - 2010-04-19 13:31:28 -0700 (Mon, 19 Apr 2010) - kjing - create Mango (6.1) based on windex
3031 r51719 - 2009-10-22 10:18:00 -0700 (Thu, 22 Oct 2009) - mitani - Converted to Build 3 tags and updated the build system
3033 r51634 - 2009-10-19 13:32:22 -0700 (Mon, 19 Oct 2009) - mitani - Windex is the branch for Sugar Sales 1.0 development
3035 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.
3037 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.
3039 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:
3040 - Changing all ereg function to either preg or simple string based ones
3041 - No more references to magic quotes.
3042 - Change all the session_unregister() functions to just unset() the correct session variable instead.
3044 r50375 - 2009-08-24 18:07:43 -0700 (Mon, 24 Aug 2009) - dwong - branch kobe2 from tokyo r50372
3046 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
3048 r45680 - 2009-03-30 14:34:35 -0700 (Mon, 30 Mar 2009) - Samir Gandhi - modifeid serializeSchema to generate WS-I compliant WSDL
3050 r42807 - 2008-12-29 11:16:59 -0800 (Mon, 29 Dec 2008) - dwong - Branch from trunk/sugarcrm r42806 to branches/tokyo/sugarcrm
3052 r42645 - 2008-12-18 13:41:08 -0800 (Thu, 18 Dec 2008) - awu - merging maint_5_2_0 rev41336:HEAD to trunk
3054 r41647 - 2008-11-11 17:44:30 -0800 (Tue, 11 Nov 2008) - majed - Fixes a few bugs
3056 r41596 - 2008-11-10 19:20:04 -0800 (Mon, 10 Nov 2008) - Samir Gandhi - modified to set $method in the code
3058 r41558 - 2008-11-10 14:35:34 -0800 (Mon, 10 Nov 2008) - majed - changes nusoap to allow for registering classes
3060 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.
3062 - data/SugarBean.php
3063 - include/domit/php_http_client_generic.php
3064 - include/domit/php_http_connector.php
3065 - include/domit/testing_domit.php
3066 - include/domit/xml_domit_getelementsbypath.php
3067 - include/domit/xml_domit_lite_parser.php
3068 - include/domit/xml_domit_nodemaps.php
3069 - include/domit/xml_domit_parser.php
3070 - include/domit/xml_domit_shared.php
3071 - include/generic/SugarWidgets/SugarWidgetField.php
3072 - include/generic/SugarWidgets/SugarWidgetReportField.php
3073 - include/ListView/ProcessView.php
3074 - include/nusoap/class.soapclient.php
3075 - include/nusoap/nusoap.php
3076 - include/nusoap/nusoapmime.php
3077 - include/Pear/HTML_Safe/Safe.php
3078 - include/Pear/XML_HTMLSax3/HTMLSax3.php
3079 - modules/Administration/RebuildWorkFlow.php
3080 - modules/Expressions/RelateSelector.php
3081 - modules/Reports/templates/templates_reports.php
3082 - modules/WorkFlow/Delete.php
3083 - modules/WorkFlow/Save.php
3084 - modules/WorkFlow/SaveSequence.php
3085 - modules/WorkFlow/WorkFlow.php
3086 - modules/WorkFlowActionShells/CreateStep1.php
3087 - modules/WorkFlowActionShells/CreateStep2.php
3088 - modules/WorkFlowActionShells/Save.php
3089 - modules/WorkFlowActionShells/WorkFlowActionShell.php
3090 - modules/WorkFlowAlerts/Save.php
3091 - modules/WorkFlowAlerts/WorkFlowAlert.php
3092 - modules/WorkFlowAlertShells/DetailView.php
3093 - modules/WorkFlowAlertShells/WorkFlowAlertShell.php
3094 - modules/WorkFlowTriggerShells/CreateStep1.php
3095 - modules/WorkFlowTriggerShells/CreateStepFilter.php
3096 - modules/WorkFlowTriggerShells/SaveFilter.php
3097 - modules/WorkFlowTriggerShells/WorkFlowTriggerShell.php
3098 - soap/SoapHelperFunctions.php
3099 - test/modules/DynamicFields/DynamicFields_Bug24095_test.php
3100 - test/simpletest/browser.php
3101 - test/simpletest/default_reporter.php
3102 - test/simpletest/detached.php
3103 - test/simpletest/eclipse.php
3104 - test/simpletest/expectation.php
3105 - test/simpletest/extensions/pear_test_case.php
3106 - test/simpletest/form.php
3107 - test/simpletest/http.php
3108 - test/simpletest/mock_objects.php
3109 - test/simpletest/page.php
3110 - test/simpletest/parser.php
3111 - test/simpletest/remote.php
3112 - test/simpletest/shell_tester.php
3113 - test/simpletest/simple_test.php
3114 - test/simpletest/simpletest.php
3115 - test/simpletest/test/acceptance_test.php
3116 - test/simpletest/test/adapter_test.php
3117 - test/simpletest/test/authentication_test.php
3118 - test/simpletest/test/browser_test.php
3119 - test/simpletest/test/collector_test.php
3120 - test/simpletest/test/compatibility_test.php
3121 - test/simpletest/test/detached_test.php
3122 - test/simpletest/test/eclipse_test.php
3123 - test/simpletest/test/encoding_test.php
3124 - test/simpletest/test/errors_test.php
3125 - test/simpletest/test/expectation_test.php
3126 - test/simpletest/test/form_test.php
3127 - test/simpletest/test/frames_test.php
3128 - test/simpletest/test/http_test.php
3129 - test/simpletest/test/live_test.php
3130 - test/simpletest/test/mock_objects_test.php
3131 - test/simpletest/test/page_test.php
3132 - test/simpletest/test/parse_error_test.php
3133 - test/simpletest/test/parser_test.php
3134 - test/simpletest/test/remote_test.php
3135 - test/simpletest/test/shell_test.php
3136 - test/simpletest/test/shell_tester_test.php
3137 - test/simpletest/test/simpletest_test.php
3138 - test/simpletest/test/site/page_request.php
3139 - test/simpletest/test/tag_test.php
3140 - test/simpletest/test/unit_tester_test.php
3141 - test/simpletest/test/user_agent_test.php
3142 - test/simpletest/test/visual_test.php
3143 - test/simpletest/test/xml_test.php
3144 - test/simpletest/test_case.php
3145 - test/simpletest/ui/array_reporter/test.php
3146 - test/simpletest/ui/recorder/test.php
3147 - test/simpletest/unit_tester.php
3148 - test/simpletest/url.php
3149 - test/simpletest/user_agent.php
3150 - test/simpletest/web_tester.php
3151 - test/spikephpcoverage/src/PEAR.php
3152 - test/spikephpcoverage/src/util/Utility.php
3153 - test/spikephpcoverage/src/XML/Parser.php
3154 - test/spikephpcoverage/src/XML/Parser/Simple.php
3155 - test/test_utilities/SugarTest_SimpleBrowser.php
3157 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.
3159 r38300 - 2008-07-25 13:33:43 -0700 (Fri, 25 Jul 2008) - Samir Gandhi - put the debug in parseresponse function
3161 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
3163 r36824 - 2008-06-18 09:26:11 -0700 (Wed, 18 Jun 2008) - roger - bug: 21832
3165 r26422 - 2007-09-05 17:29:12 -0700 (Wed, 05 Sep 2007) - majed - migrate from beta 1 to trunk
3167 r15787 - 2006-08-10 10:14:41 -0700 (Thu, 10 Aug 2006) - roger - RRS: bug 7961
3169 r14701 - 2006-07-17 13:37:26 -0700 (Mon, 17 Jul 2006) - roger - RRS: bug 5801
3171 r13782 - 2006-06-06 10:58:55 -0700 (Tue, 06 Jun 2006) - majed - changes entry point code
3173 r11466 - 2006-02-01 15:49:47 -0800 (Wed, 01 Feb 2006) - jacob - Adding extra !empty check to get around a PHP warning.
3175 r11115 - 2006-01-17 14:54:45 -0800 (Tue, 17 Jan 2006) - majed - add entry point validation
3177 r10585 - 2005-12-13 14:42:26 -0800 (Tue, 13 Dec 2005) - majed - adds new license mechanisim
3179 r10170 - 2005-12-05 18:37:46 -0800 (Mon, 05 Dec 2005) - majed - fixes various issues
3181 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.
3183 r8991 - 2005-11-03 19:07:25 -0800 (Thu, 03 Nov 2005) - majed - fixes nusoap issue
3185 r8846 - 2005-10-31 11:01:12 -0800 (Mon, 31 Oct 2005) - majed - new version of nusoap
3187 r7905 - 2005-09-21 19:12:57 -0700 (Wed, 21 Sep 2005) - majed - restores old nusoap pre & with a few fixes
3189 r7861 - 2005-09-20 15:40:25 -0700 (Tue, 20 Sep 2005) - majed - & fix for 3.5.1
3191 r7452 - 2005-08-17 11:32:34 -0700 (Wed, 17 Aug 2005) - majed - changes soap to nusoap
3193 r5820 - 2005-06-21 14:22:24 -0700 (Tue, 21 Jun 2005) - majed - fixes issues with nusoap and with custom fields
3195 r5462 - 2005-05-25 13:50:11 -0700 (Wed, 25 May 2005) - majed - upgraded nusoap to .6.9
3197 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
3199 r573 - 2004-09-04 13:03:32 -0700 (Sat, 04 Sep 2004) - sugarclint - undoing copyrights added in inadvertantly. --clint
3201 r546 - 2004-09-03 11:49:38 -0700 (Fri, 03 Sep 2004) - sugarmsi - removed echo count
3203 r354 - 2004-08-02 23:00:37 -0700 (Mon, 02 Aug 2004) - sugarjacob - Adding Soap
3213 * transport class for sending/receiving data via HTTP and HTTPS
3214 * NOTE: PHP must be compiled with the CURL extension for HTTPS support
3216 * @author Dietrich Ayala <dietrich@ganx4.com>
3217 * @author Scott Nichol <snichol@users.sourceforge.net>
3221 class soap_transport_http extends nusoap_base {
3225 var $digest_uri = '';
3230 var $request_method = 'POST';
3231 var $protocol_version = '1.0';
3233 var $outgoing_headers = array();
3234 var $incoming_headers = array();
3235 var $incoming_cookies = array();
3236 var $outgoing_payload = '';
3237 var $incoming_payload = '';
3238 var $response_status_line; // HTTP response status line
3239 var $useSOAPAction = true;
3240 var $persistentConnection = false;
3241 var $ch = false; // cURL handle
3242 var $ch_options = array(); // cURL custom options
3243 var $use_curl = false; // force cURL use
3244 var $proxy = null; // proxy information (associative array)
3248 var $digestRequest = array();
3249 var $certRequest = array(); // keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, certpassword (optional), verifypeer (optional), verifyhost (optional)
3250 // cainfofile: certificate authority file, e.g. '$pathToPemFiles/rootca.pem'
3251 // sslcertfile: SSL certificate file, e.g. '$pathToPemFiles/mycert.pem'
3252 // sslkeyfile: SSL key file, e.g. '$pathToPemFiles/mykey.pem'
3253 // passphrase: SSL key password/passphrase
3254 // certpassword: SSL certificate password
3255 // verifypeer: default is 1
3256 // verifyhost: default is 1
3261 * @param string $url The URL to which to connect
3262 * @param array $curl_options User-specified cURL options
3263 * @param boolean $use_curl Whether to try to force cURL use
3266 function soap_transport_http($url, $curl_options = NULL, $use_curl = false){
3267 parent::nusoap_base();
3268 $this->debug("ctor url=$url use_curl=$use_curl curl_options:");
3269 $this->appendDebug($this->varDump($curl_options));
3270 $this->setURL($url);
3271 if (is_array($curl_options)) {
3272 $this->ch_options = $curl_options;
3274 $this->use_curl = $use_curl;
3275 preg_match('/\$Revisio' . 'n: ([^ ]+)/', $this->revision, $rev);
3276 $this->setHeader('User-Agent', $this->title.'/'.$this->version.' ('.$rev[1].')');
3280 * sets a cURL option
3282 * @param mixed $option The cURL option (always integer?)
3283 * @param mixed $value The cURL option value
3286 function setCurlOption($option, $value) {
3287 $this->debug("setCurlOption option=$option, value=");
3288 $this->appendDebug($this->varDump($value));
3289 curl_setopt($this->ch, $option, $value);
3293 * sets an HTTP header
3295 * @param string $name The name of the header
3296 * @param string $value The value of the header
3299 function setHeader($name, $value) {
3300 $this->outgoing_headers[$name] = $value;
3301 $this->debug("set header $name: $value");
3305 * unsets an HTTP header
3307 * @param string $name The name of the header
3310 function unsetHeader($name) {
3311 if (isset($this->outgoing_headers[$name])) {
3312 $this->debug("unset header $name");
3313 unset($this->outgoing_headers[$name]);
3318 * sets the URL to which to connect
3320 * @param string $url The URL to which to connect
3323 function setURL($url) {
3326 $u = parse_url($url);
3327 foreach($u as $k => $v){
3328 $this->debug("parsed URL $k = $v");
3332 // add any GET params to path
3333 if(isset($u['query']) && $u['query'] != ''){
3334 $this->path .= '?' . $u['query'];
3338 if(!isset($u['port'])){
3339 if($u['scheme'] == 'https'){
3346 $this->uri = $this->path;
3347 $this->digest_uri = $this->uri;
3350 if (!isset($u['port'])) {
3351 $this->setHeader('Host', $this->host);
3353 $this->setHeader('Host', $this->host.':'.$this->port);
3356 if (isset($u['user']) && $u['user'] != '') {
3357 $this->setCredentials(urldecode($u['user']), isset($u['pass']) ? urldecode($u['pass']) : '');
3362 * gets the I/O method to use
3364 * @return string I/O method to use (socket|curl|unknown)
3367 function io_method() {
3368 if ($this->use_curl || ($this->scheme == 'https') || ($this->scheme == 'http' && $this->authtype == 'ntlm') || ($this->scheme == 'http' && is_array($this->proxy) && $this->proxy['authtype'] == 'ntlm'))
3370 if (($this->scheme == 'http' || $this->scheme == 'ssl') && $this->authtype != 'ntlm' && (!is_array($this->proxy) || $this->proxy['authtype'] != 'ntlm'))
3376 * establish an HTTP connection
3378 * @param integer $timeout set connection timeout in seconds
3379 * @param integer $response_timeout set response timeout in seconds
3380 * @return boolean true if connected, false if not
3383 function connect($connection_timeout=0,$response_timeout=30){
3384 // For PHP 4.3 with OpenSSL, change https scheme to ssl, then treat like
3385 // "regular" socket.
3386 // TODO: disabled for now because OpenSSL must be *compiled* in (not just
3387 // loaded), and until PHP5 stream_get_wrappers is not available.
3388 // if ($this->scheme == 'https') {
3389 // if (version_compare(phpversion(), '4.3.0') >= 0) {
3390 // if (extension_loaded('openssl')) {
3391 // $this->scheme = 'ssl';
3392 // $this->debug('Using SSL over OpenSSL');
3396 $this->debug("connect connection_timeout $connection_timeout, response_timeout $response_timeout, scheme $this->scheme, host $this->host, port $this->port");
3397 if ($this->io_method() == 'socket') {
3398 if (!is_array($this->proxy)) {
3399 $host = $this->host;
3400 $port = $this->port;
3402 $host = $this->proxy['host'];
3403 $port = $this->proxy['port'];
3406 // use persistent connection
3407 if($this->persistentConnection && isset($this->fp) && is_resource($this->fp)){
3408 if (!feof($this->fp)) {
3409 $this->debug('Re-use persistent connection');
3413 $this->debug('Closed persistent connection at EOF');
3416 // munge host if using OpenSSL
3417 if ($this->scheme == 'ssl') {
3418 $host = 'ssl://' . $host;
3420 $this->debug('calling fsockopen with host ' . $host . ' connection_timeout ' . $connection_timeout);
3423 if($connection_timeout > 0){
3424 $this->fp = @fsockopen( $host, $this->port, $this->errno, $this->error_str, $connection_timeout);
3426 $this->fp = @fsockopen( $host, $this->port, $this->errno, $this->error_str);
3431 $msg = 'Couldn\'t open socket connection to server ' . $this->url;
3433 $msg .= ', Error ('.$this->errno.'): '.$this->error_str;
3435 $msg .= ' prior to connect(). This is often a problem looking up the host name.';
3438 $this->setError($msg);
3442 // set response timeout
3443 $this->debug('set response timeout to ' . $response_timeout);
3444 socket_set_timeout( $this->fp, $response_timeout);
3446 $this->debug('socket connected');
3448 } else if ($this->io_method() == 'curl') {
3449 if (!extension_loaded('curl')) {
3450 // $this->setError('cURL Extension, or OpenSSL extension w/ PHP version >= 4.3 is required for HTTPS');
3451 $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.');
3454 // Avoid warnings when PHP does not have these options
3455 if (defined('CURLOPT_CONNECTIONTIMEOUT'))
3456 $CURLOPT_CONNECTIONTIMEOUT = CURLOPT_CONNECTIONTIMEOUT;
3458 $CURLOPT_CONNECTIONTIMEOUT = 78;
3459 if (defined('CURLOPT_HTTPAUTH'))
3460 $CURLOPT_HTTPAUTH = CURLOPT_HTTPAUTH;
3462 $CURLOPT_HTTPAUTH = 107;
3463 if (defined('CURLOPT_PROXYAUTH'))
3464 $CURLOPT_PROXYAUTH = CURLOPT_PROXYAUTH;
3466 $CURLOPT_PROXYAUTH = 111;
3467 if (defined('CURLAUTH_BASIC'))
3468 $CURLAUTH_BASIC = CURLAUTH_BASIC;
3470 $CURLAUTH_BASIC = 1;
3471 if (defined('CURLAUTH_DIGEST'))
3472 $CURLAUTH_DIGEST = CURLAUTH_DIGEST;
3474 $CURLAUTH_DIGEST = 2;
3475 if (defined('CURLAUTH_NTLM'))
3476 $CURLAUTH_NTLM = CURLAUTH_NTLM;
3480 $this->debug('connect using cURL');
3482 $this->ch = curl_init();
3484 $hostURL = ($this->port != '') ? "$this->scheme://$this->host:$this->port" : "$this->scheme://$this->host";
3486 $hostURL .= $this->path;
3487 $this->setCurlOption(CURLOPT_URL, $hostURL);
3488 // follow location headers (re-directs)
3489 if (ini_get('safe_mode') || ini_get('open_basedir')) {
3490 $this->debug('safe_mode or open_basedir set, so do not set CURLOPT_FOLLOWLOCATION');
3491 $this->debug('safe_mode = ');
3492 $this->appendDebug($this->varDump(ini_get('safe_mode')));
3493 $this->debug('open_basedir = ');
3494 $this->appendDebug($this->varDump(ini_get('open_basedir')));
3496 $this->setCurlOption(CURLOPT_FOLLOWLOCATION, 1);
3498 // ask for headers in the response output
3499 $this->setCurlOption(CURLOPT_HEADER, 1);
3500 // ask for the response output as the return value
3501 $this->setCurlOption(CURLOPT_RETURNTRANSFER, 1);
3503 // We manage this ourselves through headers and encoding
3504 // if(function_exists('gzuncompress')){
3505 // $this->setCurlOption(CURLOPT_ENCODING, 'deflate');
3507 // persistent connection
3508 if ($this->persistentConnection) {
3509 // I believe the following comment is now bogus, having applied to
3510 // the code when it used CURLOPT_CUSTOMREQUEST to send the request.
3511 // The way we send data, we cannot use persistent connections, since
3512 // there will be some "junk" at the end of our request.
3513 //$this->setCurlOption(CURL_HTTP_VERSION_1_1, true);
3514 $this->persistentConnection = false;
3515 $this->setHeader('Connection', 'close');
3518 if ($connection_timeout != 0) {
3519 $this->setCurlOption($CURLOPT_CONNECTIONTIMEOUT, $connection_timeout);
3521 if ($response_timeout != 0) {
3522 $this->setCurlOption(CURLOPT_TIMEOUT, $response_timeout);
3525 if ($this->scheme == 'https') {
3526 $this->debug('set cURL SSL verify options');
3527 // recent versions of cURL turn on peer/host checking by default,
3528 // while PHP binaries are not compiled with a default location for the
3529 // CA cert bundle, so disable peer/host checking.
3530 //$this->setCurlOption(CURLOPT_CAINFO, 'f:\php-4.3.2-win32\extensions\curl-ca-bundle.crt');
3531 $this->setCurlOption(CURLOPT_SSL_VERIFYPEER, 0);
3532 $this->setCurlOption(CURLOPT_SSL_VERIFYHOST, 0);
3534 // support client certificates (thanks Tobias Boes, Doug Anarino, Eryan Ariobowo)
3535 if ($this->authtype == 'certificate') {
3536 $this->debug('set cURL certificate options');
3537 if (isset($this->certRequest['cainfofile'])) {
3538 $this->setCurlOption(CURLOPT_CAINFO, $this->certRequest['cainfofile']);
3540 if (isset($this->certRequest['verifypeer'])) {
3541 $this->setCurlOption(CURLOPT_SSL_VERIFYPEER, $this->certRequest['verifypeer']);
3543 $this->setCurlOption(CURLOPT_SSL_VERIFYPEER, 1);
3545 if (isset($this->certRequest['verifyhost'])) {
3546 $this->setCurlOption(CURLOPT_SSL_VERIFYHOST, $this->certRequest['verifyhost']);
3548 $this->setCurlOption(CURLOPT_SSL_VERIFYHOST, 1);
3550 if (isset($this->certRequest['sslcertfile'])) {
3551 $this->setCurlOption(CURLOPT_SSLCERT, $this->certRequest['sslcertfile']);
3553 if (isset($this->certRequest['sslkeyfile'])) {
3554 $this->setCurlOption(CURLOPT_SSLKEY, $this->certRequest['sslkeyfile']);
3556 if (isset($this->certRequest['passphrase'])) {
3557 $this->setCurlOption(CURLOPT_SSLKEYPASSWD, $this->certRequest['passphrase']);
3559 if (isset($this->certRequest['certpassword'])) {
3560 $this->setCurlOption(CURLOPT_SSLCERTPASSWD, $this->certRequest['certpassword']);
3564 if ($this->authtype && ($this->authtype != 'certificate')) {
3565 if ($this->username) {
3566 $this->debug('set cURL username/password');
3567 $this->setCurlOption(CURLOPT_USERPWD, "$this->username:$this->password");
3569 if ($this->authtype == 'basic') {
3570 $this->debug('set cURL for Basic authentication');
3571 $this->setCurlOption($CURLOPT_HTTPAUTH, $CURLAUTH_BASIC);
3573 if ($this->authtype == 'digest') {
3574 $this->debug('set cURL for digest authentication');
3575 $this->setCurlOption($CURLOPT_HTTPAUTH, $CURLAUTH_DIGEST);
3577 if ($this->authtype == 'ntlm') {
3578 $this->debug('set cURL for NTLM authentication');
3579 $this->setCurlOption($CURLOPT_HTTPAUTH, $CURLAUTH_NTLM);
3582 if (is_array($this->proxy)) {
3583 $this->debug('set cURL proxy options');
3584 if ($this->proxy['port'] != '') {
3585 $this->setCurlOption(CURLOPT_PROXY, $this->proxy['host'].':'.$this->proxy['port']);
3587 $this->setCurlOption(CURLOPT_PROXY, $this->proxy['host']);
3589 if ($this->proxy['username'] || $this->proxy['password']) {
3590 $this->debug('set cURL proxy authentication options');
3591 $this->setCurlOption(CURLOPT_PROXYUSERPWD, $this->proxy['username'].':'.$this->proxy['password']);
3592 if ($this->proxy['authtype'] == 'basic') {
3593 $this->setCurlOption($CURLOPT_PROXYAUTH, $CURLAUTH_BASIC);
3595 if ($this->proxy['authtype'] == 'ntlm') {
3596 $this->setCurlOption($CURLOPT_PROXYAUTH, $CURLAUTH_NTLM);
3600 $this->debug('cURL connection set up');
3603 $this->setError('Unknown scheme ' . $this->scheme);
3604 $this->debug('Unknown scheme ' . $this->scheme);
3610 * sends the SOAP request and gets the SOAP response via HTTP[S]
3612 * @param string $data message data
3613 * @param integer $timeout set connection timeout in seconds
3614 * @param integer $response_timeout set response timeout in seconds
3615 * @param array $cookies cookies to send
3616 * @return string data
3619 function send($data, $timeout=0, $response_timeout=30, $cookies=NULL) {
3621 $this->debug('entered send() with data of length: '.strlen($data));
3623 $this->tryagain = true;
3625 while ($this->tryagain) {
3626 $this->tryagain = false;
3629 if (!$this->connect($timeout, $response_timeout)){
3634 if (!$this->sendRequest($data, $cookies)){
3639 $respdata = $this->getResponse();
3641 $this->setError("Too many tries to get an OK response ($this->response_status_line)");
3644 $this->debug('end of send()');
3650 * sends the SOAP request and gets the SOAP response via HTTPS using CURL
3652 * @param string $data message data
3653 * @param integer $timeout set connection timeout in seconds
3654 * @param integer $response_timeout set response timeout in seconds
3655 * @param array $cookies cookies to send
3656 * @return string data
3660 function sendHTTPS($data, $timeout=0, $response_timeout=30, $cookies) {
3661 return $this->send($data, $timeout, $response_timeout, $cookies);
3665 * if authenticating, set user credentials here
3667 * @param string $username
3668 * @param string $password
3669 * @param string $authtype (basic|digest|certificate|ntlm)
3670 * @param array $digestRequest (keys must be nonce, nc, realm, qop)
3671 * @param array $certRequest (keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, certpassword (optional), verifypeer (optional), verifyhost (optional): see corresponding options in cURL docs)
3674 function setCredentials($username, $password, $authtype = 'basic', $digestRequest = array(), $certRequest = array()) {
3675 $this->debug("setCredentials username=$username authtype=$authtype digestRequest=");
3676 $this->appendDebug($this->varDump($digestRequest));
3677 $this->debug("certRequest=");
3678 $this->appendDebug($this->varDump($certRequest));
3680 if ($authtype == 'basic') {
3681 $this->setHeader('Authorization', 'Basic '.base64_encode(str_replace(':','',$username).':'.$password));
3682 } elseif ($authtype == 'digest') {
3683 if (isset($digestRequest['nonce'])) {
3684 $digestRequest['nc'] = isset($digestRequest['nc']) ? $digestRequest['nc']++ : 1;
3686 // calculate the Digest hashes (calculate code based on digest implementation found at: http://www.rassoc.com/gregr/weblog/stories/2002/07/09/webServicesSecurityHttpDigestAuthenticationWithoutActiveDirectory.html)
3688 // A1 = unq(username-value) ":" unq(realm-value) ":" passwd
3689 $A1 = $username. ':' . (isset($digestRequest['realm']) ? $digestRequest['realm'] : '') . ':' . $password;
3694 // A2 = Method ":" digest-uri-value
3695 $A2 = $this->request_method . ':' . $this->digest_uri;
3700 // KD(secret, data) = H(concat(secret, ":", data))
3702 // request-digest = <"> < KD ( H(A1), unq(nonce-value)
3704 // ":" unq(cnonce-value)
3705 // ":" unq(qop-value)
3708 // if qop is missing,
3709 // request-digest = <"> < KD ( H(A1), unq(nonce-value) ":" H(A2) ) > <">
3711 $unhashedDigest = '';
3712 $nonce = isset($digestRequest['nonce']) ? $digestRequest['nonce'] : '';
3714 if ($digestRequest['qop'] != '') {
3715 $unhashedDigest = $HA1 . ':' . $nonce . ':' . sprintf("%08d", $digestRequest['nc']) . ':' . $cnonce . ':' . $digestRequest['qop'] . ':' . $HA2;
3717 $unhashedDigest = $HA1 . ':' . $nonce . ':' . $HA2;
3720 $hashedDigest = md5($unhashedDigest);
3723 if (isset($digestRequest['opaque'])) {
3724 $opaque = ', opaque="' . $digestRequest['opaque'] . '"';
3727 $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 . '"');
3729 } elseif ($authtype == 'certificate') {
3730 $this->certRequest = $certRequest;
3731 $this->debug('Authorization header not set for certificate');
3732 } elseif ($authtype == 'ntlm') {
3734 $this->debug('Authorization header not set for ntlm');
3736 $this->username = $username;
3737 $this->password = $password;
3738 $this->authtype = $authtype;
3739 $this->digestRequest = $digestRequest;
3743 * set the soapaction value
3745 * @param string $soapaction
3748 function setSOAPAction($soapaction) {
3749 $this->setHeader('SOAPAction', '"' . $soapaction . '"');
3755 * @param string $enc encoding style. supported values: gzip, deflate, or both
3758 function setEncoding($enc='gzip, deflate') {
3759 if (function_exists('gzdeflate')) {
3760 $this->protocol_version = '1.1';
3761 $this->setHeader('Accept-Encoding', $enc);
3762 if (!isset($this->outgoing_headers['Connection'])) {
3763 $this->setHeader('Connection', 'close');
3764 $this->persistentConnection = false;
3766 // deprecated as of PHP 5.3.0
3767 //set_magic_quotes_runtime(0);
3768 $this->encoding = $enc;
3773 * set proxy info here
3775 * @param string $proxyhost use an empty string to remove proxy
3776 * @param string $proxyport
3777 * @param string $proxyusername
3778 * @param string $proxypassword
3779 * @param string $proxyauthtype (basic|ntlm)
3782 function setProxy($proxyhost, $proxyport, $proxyusername = '', $proxypassword = '', $proxyauthtype = 'basic') {
3784 $this->proxy = array(
3785 'host' => $proxyhost,
3786 'port' => $proxyport,
3787 'username' => $proxyusername,
3788 'password' => $proxypassword,
3789 'authtype' => $proxyauthtype
3791 if ($proxyusername != '' && $proxypassword != '' && $proxyauthtype = 'basic') {
3792 $this->setHeader('Proxy-Authorization', ' Basic '.base64_encode($proxyusername.':'.$proxypassword));
3795 $this->debug('remove proxy');
3797 unsetHeader('Proxy-Authorization');
3803 * Test if the given string starts with a header that is to be skipped.
3804 * Skippable headers result from chunked transfer and proxy requests.
3806 * @param string $data The string to check.
3807 * @returns boolean Whether a skippable header was found.
3810 function isSkippableCurlHeader(&$data) {
3811 $skipHeaders = array( 'HTTP/1.1 100',
3818 'HTTP/1.0 200 Connection established');
3819 foreach ($skipHeaders as $hd) {
3820 $prefix = substr($data, 0, strlen($hd));
3821 if ($prefix == $hd) return true;
3828 * decode a string that is encoded w/ "chunked' transfer encoding
3829 * as defined in RFC2068 19.4.6
3831 * @param string $buffer
3837 function decodeChunked($buffer, $lb){
3842 // read chunk-size, chunk-extension (if any) and CRLF
3843 // get the position of the linebreak
3844 $chunkend = strpos($buffer, $lb);
3845 if ($chunkend == FALSE) {
3846 $this->debug('no linebreak found in decodeChunked');
3849 $temp = substr($buffer,0,$chunkend);
3850 $chunk_size = hexdec( trim($temp) );
3851 $chunkstart = $chunkend + strlen($lb);
3852 // while (chunk-size > 0) {
3853 while ($chunk_size > 0) {
3854 $this->debug("chunkstart: $chunkstart chunk_size: $chunk_size");
3855 $chunkend = strpos( $buffer, $lb, $chunkstart + $chunk_size);
3857 // Just in case we got a broken connection
3858 if ($chunkend == FALSE) {
3859 $chunk = substr($buffer,$chunkstart);
3860 // append chunk-data to entity-body
3862 $length += strlen($chunk);
3866 // read chunk-data and CRLF
3867 $chunk = substr($buffer,$chunkstart,$chunkend-$chunkstart);
3868 // append chunk-data to entity-body
3870 // length := length + chunk-size
3871 $length += strlen($chunk);
3872 // read chunk-size and CRLF
3873 $chunkstart = $chunkend + strlen($lb);
3875 $chunkend = strpos($buffer, $lb, $chunkstart) + strlen($lb);
3876 if ($chunkend == FALSE) {
3877 break; //Just in case we got a broken connection
3879 $temp = substr($buffer,$chunkstart,$chunkend-$chunkstart);
3880 $chunk_size = hexdec( trim($temp) );
3881 $chunkstart = $chunkend;
3887 * Writes the payload, including HTTP headers, to $this->outgoing_payload.
3889 * @param string $data HTTP body
3890 * @param string $cookie_str data for HTTP Cookie header
3894 function buildPayload($data, $cookie_str = '') {
3895 // Note: for cURL connections, $this->outgoing_payload is ignored,
3896 // as is the Content-Length header, but these are still created as
3897 // debugging guides.
3899 // add content-length header
3900 if ($this->request_method != 'GET') {
3901 $this->setHeader('Content-Length', strlen($data));
3904 // start building outgoing payload:
3910 $req = "$this->request_method $uri HTTP/$this->protocol_version";
3911 $this->debug("HTTP request: $req");
3912 $this->outgoing_payload = "$req\r\n";
3914 // loop thru headers, serializing
3915 foreach($this->outgoing_headers as $k => $v){
3917 $this->debug("HTTP header: $hdr");
3918 $this->outgoing_payload .= "$hdr\r\n";
3922 if ($cookie_str != '') {
3923 $hdr = 'Cookie: '.$cookie_str;
3924 $this->debug("HTTP header: $hdr");
3925 $this->outgoing_payload .= "$hdr\r\n";
3928 // header/body separator
3929 $this->outgoing_payload .= "\r\n";
3932 $this->outgoing_payload .= $data;
3936 * sends the SOAP request via HTTP[S]
3938 * @param string $data message data
3939 * @param array $cookies cookies to send
3940 * @return boolean true if OK, false if problem
3943 function sendRequest($data, $cookies = NULL) {
3944 // build cookie string
3945 $cookie_str = $this->getCookiesForRequest($cookies, (($this->scheme == 'ssl') || ($this->scheme == 'https')));
3948 $this->buildPayload($data, $cookie_str);
3950 if ($this->io_method() == 'socket') {
3952 if(!fputs($this->fp, $this->outgoing_payload, strlen($this->outgoing_payload))) {
3953 $this->setError('couldn\'t write message data to socket');
3954 $this->debug('couldn\'t write message data to socket');
3957 $this->debug('wrote data to socket, length = ' . strlen($this->outgoing_payload));
3959 } else if ($this->io_method() == 'curl') {
3961 // cURL does say this should only be the verb, and in fact it
3962 // turns out that the URI and HTTP version are appended to this, which
3963 // some servers refuse to work with (so we no longer use this method!)
3964 //$this->setCurlOption(CURLOPT_CUSTOMREQUEST, $this->outgoing_payload);
3965 $curl_headers = array();
3966 foreach($this->outgoing_headers as $k => $v){
3967 if ($k == 'Connection' || $k == 'Content-Length' || $k == 'Host' || $k == 'Authorization' || $k == 'Proxy-Authorization') {
3968 $this->debug("Skip cURL header $k: $v");
3970 $curl_headers[] = "$k: $v";
3973 if ($cookie_str != '') {
3974 $curl_headers[] = 'Cookie: ' . $cookie_str;
3976 $this->setCurlOption(CURLOPT_HTTPHEADER, $curl_headers);
3977 $this->debug('set cURL HTTP headers');
3978 if ($this->request_method == "POST") {
3979 $this->setCurlOption(CURLOPT_POST, 1);
3980 $this->setCurlOption(CURLOPT_POSTFIELDS, $data);
3981 $this->debug('set cURL POST data');
3984 // insert custom user-set cURL options
3985 foreach ($this->ch_options as $key => $val) {
3986 $this->setCurlOption($key, $val);
3989 $this->debug('set cURL payload');
3995 * gets the SOAP response via HTTP[S]
3997 * @return string the response (also sets member variables like incoming_payload)
4000 function getResponse(){
4001 $this->incoming_payload = '';
4003 if ($this->io_method() == 'socket') {
4004 // loop until headers have been retrieved
4006 while (!isset($lb)){
4008 // We might EOF during header read.
4009 if(feof($this->fp)) {
4010 $this->incoming_payload = $data;
4011 $this->debug('found no headers before EOF after length ' . strlen($data));
4012 $this->debug("received before EOF:\n" . $data);
4013 $this->setError('server failed to send headers');
4017 $tmp = fgets($this->fp, 256);
4018 $tmplen = strlen($tmp);
4019 $this->debug("read line of $tmplen bytes: " . trim($tmp));
4022 $this->incoming_payload = $data;
4023 $this->debug('socket read of headers timed out after length ' . strlen($data));
4024 $this->debug("read before timeout: " . $data);
4025 $this->setError('socket read of headers timed out');
4030 $pos = strpos($data,"\r\n\r\n");
4034 $pos = strpos($data,"\n\n");
4039 // remove 100 headers
4040 if (isset($lb) && preg_match('/^HTTP\/1.1 100/',$data)) {
4045 // store header data
4046 $this->incoming_payload .= $data;
4047 $this->debug('found end of headers after length ' . strlen($data));
4049 $header_data = trim(substr($data,0,$pos));
4050 $header_array = explode($lb,$header_data);
4051 $this->incoming_headers = array();
4052 $this->incoming_cookies = array();
4053 foreach($header_array as $header_line){
4054 $arr = explode(':',$header_line, 2);
4055 if(count($arr) > 1){
4056 $header_name = strtolower(trim($arr[0]));
4057 $this->incoming_headers[$header_name] = trim($arr[1]);
4058 if ($header_name == 'set-cookie') {
4059 // TODO: allow multiple cookies from parseCookie
4060 $cookie = $this->parseCookie(trim($arr[1]));
4062 $this->incoming_cookies[] = $cookie;
4063 $this->debug('found cookie: ' . $cookie['name'] . ' = ' . $cookie['value']);
4065 $this->debug('did not find cookie in ' . trim($arr[1]));
4068 } else if (isset($header_name)) {
4069 // append continuation line to previous header
4070 $this->incoming_headers[$header_name] .= $lb . ' ' . $header_line;
4074 // loop until msg has been received
4075 if (isset($this->incoming_headers['transfer-encoding']) && strtolower($this->incoming_headers['transfer-encoding']) == 'chunked') {
4076 $content_length = 2147483647; // ignore any content-length header
4078 $this->debug("want to read chunked content");
4079 } elseif (isset($this->incoming_headers['content-length'])) {
4080 $content_length = $this->incoming_headers['content-length'];
4082 $this->debug("want to read content of length $content_length");
4084 $content_length = 2147483647;
4086 $this->debug("want to read content to EOF");
4091 $tmp = fgets($this->fp, 256);
4092 $tmplen = strlen($tmp);
4093 $this->debug("read chunk line of $tmplen bytes");
4095 $this->incoming_payload = $data;
4096 $this->debug('socket read of chunk length timed out after length ' . strlen($data));
4097 $this->debug("read before timeout:\n" . $data);
4098 $this->setError('socket read of chunk length timed out');
4101 $content_length = hexdec(trim($tmp));
4102 $this->debug("chunk length $content_length");
4105 while (($strlen < $content_length) && (!feof($this->fp))) {
4106 $readlen = min(8192, $content_length - $strlen);
4107 $tmp = fread($this->fp, $readlen);
4108 $tmplen = strlen($tmp);
4109 $this->debug("read buffer of $tmplen bytes");
4110 if (($tmplen == 0) && (!feof($this->fp))) {
4111 $this->incoming_payload = $data;
4112 $this->debug('socket read of body timed out after length ' . strlen($data));
4113 $this->debug("read before timeout:\n" . $data);
4114 $this->setError('socket read of body timed out');
4120 if ($chunked && ($content_length > 0)) {
4121 $tmp = fgets($this->fp, 256);
4122 $tmplen = strlen($tmp);
4123 $this->debug("read chunk terminator of $tmplen bytes");
4125 $this->incoming_payload = $data;
4126 $this->debug('socket read of chunk terminator timed out after length ' . strlen($data));
4127 $this->debug("read before timeout:\n" . $data);
4128 $this->setError('socket read of chunk terminator timed out');
4132 } while ($chunked && ($content_length > 0) && (!feof($this->fp)));
4133 if (feof($this->fp)) {
4134 $this->debug('read to EOF');
4136 $this->debug('read body of length ' . strlen($data));
4137 $this->incoming_payload .= $data;
4138 $this->debug('received a total of '.strlen($this->incoming_payload).' bytes of data from server');
4140 // close filepointer
4142 (isset($this->incoming_headers['connection']) && strtolower($this->incoming_headers['connection']) == 'close') ||
4143 (! $this->persistentConnection) || feof($this->fp)){
4146 $this->debug('closed socket');
4149 // connection was closed unexpectedly
4150 if($this->incoming_payload == ''){
4151 $this->setError('no response from server');
4155 // decode transfer-encoding
4156 // if(isset($this->incoming_headers['transfer-encoding']) && strtolower($this->incoming_headers['transfer-encoding']) == 'chunked'){
4157 // if(!$data = $this->decodeChunked($data, $lb)){
4158 // $this->setError('Decoding of chunked data failed');
4161 //print "<pre>\nde-chunked:\n---------------\n$data\n\n---------------\n</pre>";
4162 // set decoded payload
4163 // $this->incoming_payload = $header_data.$lb.$lb.$data;
4166 } else if ($this->io_method() == 'curl') {
4168 $this->debug('send and receive with cURL');
4169 $this->incoming_payload = curl_exec($this->ch);
4170 $data = $this->incoming_payload;
4172 $cErr = curl_error($this->ch);
4174 $err = 'cURL ERROR: '.curl_errno($this->ch).': '.$cErr.'<br>';
4175 // TODO: there is a PHP bug that can cause this to SEGV for CURLINFO_CONTENT_TYPE
4176 foreach(curl_getinfo($this->ch) as $k => $v){
4177 $err .= "$k: $v<br>";
4180 $this->setError($err);
4181 curl_close($this->ch);
4185 //var_dump(curl_getinfo($this->ch));
4189 $this->debug('No cURL error, closing cURL');
4190 curl_close($this->ch);
4192 // try removing skippable headers
4194 while ($this->isSkippableCurlHeader($data)) {
4195 $this->debug("Found HTTP header to skip");
4196 if ($pos = strpos($data,"\r\n\r\n")) {
4197 $data = ltrim(substr($data,$pos));
4198 } elseif($pos = strpos($data,"\n\n") ) {
4199 $data = ltrim(substr($data,$pos));
4204 // have nothing left; just remove 100 header(s)
4206 while (preg_match('/^HTTP\/1.1 100/',$data)) {
4207 if ($pos = strpos($data,"\r\n\r\n")) {
4208 $data = ltrim(substr($data,$pos));
4209 } elseif($pos = strpos($data,"\n\n") ) {
4210 $data = ltrim(substr($data,$pos));
4215 // separate content from HTTP headers
4216 if ($pos = strpos($data,"\r\n\r\n")) {
4218 } elseif( $pos = strpos($data,"\n\n")) {
4221 $this->debug('no proper separation of headers and document');
4222 $this->setError('no proper separation of headers and document');
4225 $header_data = trim(substr($data,0,$pos));
4226 $header_array = explode($lb,$header_data);
4227 $data = ltrim(substr($data,$pos));
4228 $this->debug('found proper separation of headers and document');
4229 $this->debug('cleaned data, stringlen: '.strlen($data));
4231 foreach ($header_array as $header_line) {
4232 $arr = explode(':',$header_line,2);
4233 if(count($arr) > 1){
4234 $header_name = strtolower(trim($arr[0]));
4235 $this->incoming_headers[$header_name] = trim($arr[1]);
4236 if ($header_name == 'set-cookie') {
4237 // TODO: allow multiple cookies from parseCookie
4238 $cookie = $this->parseCookie(trim($arr[1]));
4240 $this->incoming_cookies[] = $cookie;
4241 $this->debug('found cookie: ' . $cookie['name'] . ' = ' . $cookie['value']);
4243 $this->debug('did not find cookie in ' . trim($arr[1]));
4246 } else if (isset($header_name)) {
4247 // append continuation line to previous header
4248 $this->incoming_headers[$header_name] .= $lb . ' ' . $header_line;
4253 $this->response_status_line = $header_array[0];
4254 $arr = explode(' ', $this->response_status_line, 3);
4255 $http_version = $arr[0];
4256 $http_status = intval($arr[1]);
4257 $http_reason = count($arr) > 2 ? $arr[2] : '';
4259 // see if we need to resend the request with http digest authentication
4260 if (isset($this->incoming_headers['location']) && ($http_status == 301 || $http_status == 302)) {
4261 $this->debug("Got $http_status $http_reason with Location: " . $this->incoming_headers['location']);
4262 $this->setURL($this->incoming_headers['location']);
4263 $this->tryagain = true;
4267 // see if we need to resend the request with http digest authentication
4268 if (isset($this->incoming_headers['www-authenticate']) && $http_status == 401) {
4269 $this->debug("Got 401 $http_reason with WWW-Authenticate: " . $this->incoming_headers['www-authenticate']);
4270 if (strstr($this->incoming_headers['www-authenticate'], "Digest ")) {
4271 $this->debug('Server wants digest authentication');
4272 // remove "Digest " from our elements
4273 $digestString = str_replace('Digest ', '', $this->incoming_headers['www-authenticate']);
4275 // parse elements into array
4276 $digestElements = explode(',', $digestString);
4277 foreach ($digestElements as $val) {
4278 $tempElement = explode('=', trim($val), 2);
4279 $digestRequest[$tempElement[0]] = str_replace("\"", '', $tempElement[1]);
4282 // should have (at least) qop, realm, nonce
4283 if (isset($digestRequest['nonce'])) {
4284 $this->setCredentials($this->username, $this->password, 'digest', $digestRequest);
4285 $this->tryagain = true;
4289 $this->debug('HTTP authentication failed');
4290 $this->setError('HTTP authentication failed');
4295 ($http_status >= 300 && $http_status <= 307) ||
4296 ($http_status >= 400 && $http_status <= 417) ||
4297 ($http_status >= 501 && $http_status <= 505)
4299 $this->setError("Unsupported HTTP response status $http_status $http_reason (soapclient->response has contents of the response)");
4303 // decode content-encoding
4304 if(isset($this->incoming_headers['content-encoding']) && $this->incoming_headers['content-encoding'] != ''){
4305 if(strtolower($this->incoming_headers['content-encoding']) == 'deflate' || strtolower($this->incoming_headers['content-encoding']) == 'gzip'){
4306 // if decoding works, use it. else assume data wasn't gzencoded
4307 if(function_exists('gzinflate')){
4308 //$timer->setMarker('starting decoding of gzip/deflated content');
4309 // IIS 5 requires gzinflate instead of gzuncompress (similar to IE 5 and gzdeflate v. gzcompress)
4310 // this means there are no Zlib headers, although there should be
4311 $this->debug('The gzinflate function exists');
4312 $datalen = strlen($data);
4313 if ($this->incoming_headers['content-encoding'] == 'deflate') {
4314 if ($degzdata = @gzinflate($data)) {
4316 $this->debug('The payload has been inflated to ' . strlen($data) . ' bytes');
4317 if (strlen($data) < $datalen) {
4318 // test for the case that the payload has been compressed twice
4319 $this->debug('The inflated payload is smaller than the gzipped one; try again');
4320 if ($degzdata = @gzinflate($data)) {
4322 $this->debug('The payload has been inflated again to ' . strlen($data) . ' bytes');
4326 $this->debug('Error using gzinflate to inflate the payload');
4327 $this->setError('Error using gzinflate to inflate the payload');
4329 } elseif ($this->incoming_headers['content-encoding'] == 'gzip') {
4330 if ($degzdata = @gzinflate(substr($data, 10))) { // do our best
4332 $this->debug('The payload has been un-gzipped to ' . strlen($data) . ' bytes');
4333 if (strlen($data) < $datalen) {
4334 // test for the case that the payload has been compressed twice
4335 $this->debug('The un-gzipped payload is smaller than the gzipped one; try again');
4336 if ($degzdata = @gzinflate(substr($data, 10))) {
4338 $this->debug('The payload has been un-gzipped again to ' . strlen($data) . ' bytes');
4342 $this->debug('Error using gzinflate to un-gzip the payload');
4343 $this->setError('Error using gzinflate to un-gzip the payload');
4346 //$timer->setMarker('finished decoding of gzip/deflated content');
4347 //print "<xmp>\nde-inflated:\n---------------\n$data\n-------------\n</xmp>";
4348 // set decoded payload
4349 $this->incoming_payload = $header_data.$lb.$lb.$data;
4351 $this->debug('The server sent compressed data. Your php install must have the Zlib extension compiled in to support this.');
4352 $this->setError('The server sent compressed data. Your php install must have the Zlib extension compiled in to support this.');
4355 $this->debug('Unsupported Content-Encoding ' . $this->incoming_headers['content-encoding']);
4356 $this->setError('Unsupported Content-Encoding ' . $this->incoming_headers['content-encoding']);
4359 $this->debug('No Content-Encoding header');
4362 if(strlen($data) == 0){
4363 $this->debug('no data after headers!');
4364 $this->setError('no data present after HTTP headers');
4372 * sets the content-type for the SOAP message to be sent
4374 * @param string $type the content type, MIME style
4375 * @param mixed $charset character set used for encoding (or false)
4378 function setContentType($type, $charset = false) {
4379 $this->setHeader('Content-Type', $type . ($charset ? '; charset=' . $charset : ''));
4383 * specifies that an HTTP persistent connection should be used
4385 * @return boolean whether the request was honored by this method.
4388 function usePersistentConnection(){
4389 if (isset($this->outgoing_headers['Accept-Encoding'])) {
4392 $this->protocol_version = '1.1';
4393 $this->persistentConnection = true;
4394 $this->setHeader('Connection', 'Keep-Alive');
4399 * parse an incoming Cookie into it's parts
4401 * @param string $cookie_str content of cookie
4402 * @return array with data of that cookie
4406 * TODO: allow a Set-Cookie string to be parsed into multiple cookies
4408 function parseCookie($cookie_str) {
4409 $cookie_str = str_replace('; ', ';', $cookie_str) . ';';
4410 $data = preg_split('/;/', $cookie_str);
4411 $value_str = $data[0];
4413 $cookie_param = 'domain=';
4414 $start = strpos($cookie_str, $cookie_param);
4416 $domain = substr($cookie_str, $start + strlen($cookie_param));
4417 $domain = substr($domain, 0, strpos($domain, ';'));
4422 $cookie_param = 'expires=';
4423 $start = strpos($cookie_str, $cookie_param);
4425 $expires = substr($cookie_str, $start + strlen($cookie_param));
4426 $expires = substr($expires, 0, strpos($expires, ';'));
4431 $cookie_param = 'path=';
4432 $start = strpos($cookie_str, $cookie_param);
4434 $path = substr($cookie_str, $start + strlen($cookie_param));
4435 $path = substr($path, 0, strpos($path, ';'));
4440 $cookie_param = ';secure;';
4441 if (strpos($cookie_str, $cookie_param) !== FALSE) {
4447 $sep_pos = strpos($value_str, '=');
4450 $name = substr($value_str, 0, $sep_pos);
4451 $value = substr($value_str, $sep_pos + 1);
4452 $cookie= array( 'name' => $name,
4454 'domain' => $domain,
4456 'expires' => $expires,
4465 * sort out cookies for the current request
4467 * @param array $cookies array with all cookies
4468 * @param boolean $secure is the send-content secure or not?
4469 * @return string for Cookie-HTTP-Header
4472 function getCookiesForRequest($cookies, $secure=false) {
4474 if ((! is_null($cookies)) && (is_array($cookies))) {
4475 foreach ($cookies as $cookie) {
4476 if (! is_array($cookie)) {
4479 $this->debug("check cookie for validity: ".$cookie['name'].'='.$cookie['value']);
4480 if ((isset($cookie['expires'])) && (! empty($cookie['expires']))) {
4481 if (strtotime($cookie['expires']) <= time()) {
4482 $this->debug('cookie has expired');
4486 if ((isset($cookie['domain'])) && (! empty($cookie['domain']))) {
4487 $domain = preg_quote($cookie['domain']);
4488 if (! preg_match("'.*$domain$'i", $this->host)) {
4489 $this->debug('cookie has different domain');
4493 if ((isset($cookie['path'])) && (! empty($cookie['path']))) {
4494 $path = preg_quote($cookie['path']);
4495 if (! preg_match("'^$path.*'i", $this->path)) {
4496 $this->debug('cookie is for a different path');
4500 if ((! $secure) && (isset($cookie['secure'])) && ($cookie['secure'])) {
4501 $this->debug('cookie is secure, transport is not');
4504 $cookie_str .= $cookie['name'] . '=' . $cookie['value'] . '; ';
4505 $this->debug('add cookie to Cookie-String: ' . $cookie['name'] . '=' . $cookie['value']);
4516 Modification information for LGPL compliance
4518 r58622 - 2010-10-22 18:18:59 -0700 (Fri, 22 Oct 2010) - engsvnbuild - Author: lam <lam@198.18.142.201>
4521 r58361 - 2010-09-29 16:59:02 -0700 (Wed, 29 Sep 2010) - kjing - Author: Jenny Gonsalves <jenny@sugarcrm.com>
4522 Merging with maint_6_0_1 (svn merge -r 58250:58342)
4524 r57813 - 2010-08-19 10:34:44 -0700 (Thu, 19 Aug 2010) - kjing - Author: John Mertic <jmertic@sugarcrm.com>
4525 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.
4527 r57707 - 2010-08-10 12:26:13 -0700 (Tue, 10 Aug 2010) - kjing - Author: Stanislav Malyshev <smalyshev@gmail.com>
4528 fix SOAP calls with no parameters
4530 r56990 - 2010-06-16 13:05:36 -0700 (Wed, 16 Jun 2010) - kjing - snapshot "Mango" svn branch to a new one for GitHub sync
4532 r56989 - 2010-06-16 13:01:33 -0700 (Wed, 16 Jun 2010) - kjing - defunt "Mango" svn dev branch before github cutover
4534 r55980 - 2010-04-19 13:31:28 -0700 (Mon, 19 Apr 2010) - kjing - create Mango (6.1) based on windex
4536 r51719 - 2009-10-22 10:18:00 -0700 (Thu, 22 Oct 2009) - mitani - Converted to Build 3 tags and updated the build system
4538 r51634 - 2009-10-19 13:32:22 -0700 (Mon, 19 Oct 2009) - mitani - Windex is the branch for Sugar Sales 1.0 development
4540 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.
4542 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.
4544 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:
4545 - Changing all ereg function to either preg or simple string based ones
4546 - No more references to magic quotes.
4547 - Change all the session_unregister() functions to just unset() the correct session variable instead.
4549 r50375 - 2009-08-24 18:07:43 -0700 (Mon, 24 Aug 2009) - dwong - branch kobe2 from tokyo r50372
4551 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
4553 r45680 - 2009-03-30 14:34:35 -0700 (Mon, 30 Mar 2009) - Samir Gandhi - modifeid serializeSchema to generate WS-I compliant WSDL
4555 r42807 - 2008-12-29 11:16:59 -0800 (Mon, 29 Dec 2008) - dwong - Branch from trunk/sugarcrm r42806 to branches/tokyo/sugarcrm
4557 r42645 - 2008-12-18 13:41:08 -0800 (Thu, 18 Dec 2008) - awu - merging maint_5_2_0 rev41336:HEAD to trunk
4559 r41647 - 2008-11-11 17:44:30 -0800 (Tue, 11 Nov 2008) - majed - Fixes a few bugs
4561 r41596 - 2008-11-10 19:20:04 -0800 (Mon, 10 Nov 2008) - Samir Gandhi - modified to set $method in the code
4563 r41558 - 2008-11-10 14:35:34 -0800 (Mon, 10 Nov 2008) - majed - changes nusoap to allow for registering classes
4565 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.
4567 - data/SugarBean.php
4568 - include/domit/php_http_client_generic.php
4569 - include/domit/php_http_connector.php
4570 - include/domit/testing_domit.php
4571 - include/domit/xml_domit_getelementsbypath.php
4572 - include/domit/xml_domit_lite_parser.php
4573 - include/domit/xml_domit_nodemaps.php
4574 - include/domit/xml_domit_parser.php
4575 - include/domit/xml_domit_shared.php
4576 - include/generic/SugarWidgets/SugarWidgetField.php
4577 - include/generic/SugarWidgets/SugarWidgetReportField.php
4578 - include/ListView/ProcessView.php
4579 - include/nusoap/class.soapclient.php
4580 - include/nusoap/nusoap.php
4581 - include/nusoap/nusoapmime.php
4582 - include/Pear/HTML_Safe/Safe.php
4583 - include/Pear/XML_HTMLSax3/HTMLSax3.php
4584 - modules/Administration/RebuildWorkFlow.php
4585 - modules/Expressions/RelateSelector.php
4586 - modules/Reports/templates/templates_reports.php
4587 - modules/WorkFlow/Delete.php
4588 - modules/WorkFlow/Save.php
4589 - modules/WorkFlow/SaveSequence.php
4590 - modules/WorkFlow/WorkFlow.php
4591 - modules/WorkFlowActionShells/CreateStep1.php
4592 - modules/WorkFlowActionShells/CreateStep2.php
4593 - modules/WorkFlowActionShells/Save.php
4594 - modules/WorkFlowActionShells/WorkFlowActionShell.php
4595 - modules/WorkFlowAlerts/Save.php
4596 - modules/WorkFlowAlerts/WorkFlowAlert.php
4597 - modules/WorkFlowAlertShells/DetailView.php
4598 - modules/WorkFlowAlertShells/WorkFlowAlertShell.php
4599 - modules/WorkFlowTriggerShells/CreateStep1.php
4600 - modules/WorkFlowTriggerShells/CreateStepFilter.php
4601 - modules/WorkFlowTriggerShells/SaveFilter.php
4602 - modules/WorkFlowTriggerShells/WorkFlowTriggerShell.php
4603 - soap/SoapHelperFunctions.php
4604 - test/modules/DynamicFields/DynamicFields_Bug24095_test.php
4605 - test/simpletest/browser.php
4606 - test/simpletest/default_reporter.php
4607 - test/simpletest/detached.php
4608 - test/simpletest/eclipse.php
4609 - test/simpletest/expectation.php
4610 - test/simpletest/extensions/pear_test_case.php
4611 - test/simpletest/form.php
4612 - test/simpletest/http.php
4613 - test/simpletest/mock_objects.php
4614 - test/simpletest/page.php
4615 - test/simpletest/parser.php
4616 - test/simpletest/remote.php
4617 - test/simpletest/shell_tester.php
4618 - test/simpletest/simple_test.php
4619 - test/simpletest/simpletest.php
4620 - test/simpletest/test/acceptance_test.php
4621 - test/simpletest/test/adapter_test.php
4622 - test/simpletest/test/authentication_test.php
4623 - test/simpletest/test/browser_test.php
4624 - test/simpletest/test/collector_test.php
4625 - test/simpletest/test/compatibility_test.php
4626 - test/simpletest/test/detached_test.php
4627 - test/simpletest/test/eclipse_test.php
4628 - test/simpletest/test/encoding_test.php
4629 - test/simpletest/test/errors_test.php
4630 - test/simpletest/test/expectation_test.php
4631 - test/simpletest/test/form_test.php
4632 - test/simpletest/test/frames_test.php
4633 - test/simpletest/test/http_test.php
4634 - test/simpletest/test/live_test.php
4635 - test/simpletest/test/mock_objects_test.php
4636 - test/simpletest/test/page_test.php
4637 - test/simpletest/test/parse_error_test.php
4638 - test/simpletest/test/parser_test.php
4639 - test/simpletest/test/remote_test.php
4640 - test/simpletest/test/shell_test.php
4641 - test/simpletest/test/shell_tester_test.php
4642 - test/simpletest/test/simpletest_test.php
4643 - test/simpletest/test/site/page_request.php
4644 - test/simpletest/test/tag_test.php
4645 - test/simpletest/test/unit_tester_test.php
4646 - test/simpletest/test/user_agent_test.php
4647 - test/simpletest/test/visual_test.php
4648 - test/simpletest/test/xml_test.php
4649 - test/simpletest/test_case.php
4650 - test/simpletest/ui/array_reporter/test.php
4651 - test/simpletest/ui/recorder/test.php
4652 - test/simpletest/unit_tester.php
4653 - test/simpletest/url.php
4654 - test/simpletest/user_agent.php
4655 - test/simpletest/web_tester.php
4656 - test/spikephpcoverage/src/PEAR.php
4657 - test/spikephpcoverage/src/util/Utility.php
4658 - test/spikephpcoverage/src/XML/Parser.php
4659 - test/spikephpcoverage/src/XML/Parser/Simple.php
4660 - test/test_utilities/SugarTest_SimpleBrowser.php
4662 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.
4664 r38300 - 2008-07-25 13:33:43 -0700 (Fri, 25 Jul 2008) - Samir Gandhi - put the debug in parseresponse function
4666 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
4668 r36824 - 2008-06-18 09:26:11 -0700 (Wed, 18 Jun 2008) - roger - bug: 21832
4670 r26422 - 2007-09-05 17:29:12 -0700 (Wed, 05 Sep 2007) - majed - migrate from beta 1 to trunk
4672 r15787 - 2006-08-10 10:14:41 -0700 (Thu, 10 Aug 2006) - roger - RRS: bug 7961
4674 r14701 - 2006-07-17 13:37:26 -0700 (Mon, 17 Jul 2006) - roger - RRS: bug 5801
4676 r13782 - 2006-06-06 10:58:55 -0700 (Tue, 06 Jun 2006) - majed - changes entry point code
4678 r11466 - 2006-02-01 15:49:47 -0800 (Wed, 01 Feb 2006) - jacob - Adding extra !empty check to get around a PHP warning.
4680 r11115 - 2006-01-17 14:54:45 -0800 (Tue, 17 Jan 2006) - majed - add entry point validation
4682 r10585 - 2005-12-13 14:42:26 -0800 (Tue, 13 Dec 2005) - majed - adds new license mechanisim
4684 r10170 - 2005-12-05 18:37:46 -0800 (Mon, 05 Dec 2005) - majed - fixes various issues
4686 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.
4688 r8991 - 2005-11-03 19:07:25 -0800 (Thu, 03 Nov 2005) - majed - fixes nusoap issue
4690 r8846 - 2005-10-31 11:01:12 -0800 (Mon, 31 Oct 2005) - majed - new version of nusoap
4692 r7905 - 2005-09-21 19:12:57 -0700 (Wed, 21 Sep 2005) - majed - restores old nusoap pre & with a few fixes
4694 r7861 - 2005-09-20 15:40:25 -0700 (Tue, 20 Sep 2005) - majed - & fix for 3.5.1
4696 r7452 - 2005-08-17 11:32:34 -0700 (Wed, 17 Aug 2005) - majed - changes soap to nusoap
4698 r5820 - 2005-06-21 14:22:24 -0700 (Tue, 21 Jun 2005) - majed - fixes issues with nusoap and with custom fields
4700 r5462 - 2005-05-25 13:50:11 -0700 (Wed, 25 May 2005) - majed - upgraded nusoap to .6.9
4702 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
4704 r573 - 2004-09-04 13:03:32 -0700 (Sat, 04 Sep 2004) - sugarclint - undoing copyrights added in inadvertantly. --clint
4706 r546 - 2004-09-03 11:49:38 -0700 (Fri, 03 Sep 2004) - sugarmsi - removed echo count
4708 r354 - 2004-08-02 23:00:37 -0700 (Mon, 02 Aug 2004) - sugarjacob - Adding Soap
4719 * nusoap_server allows the user to create a SOAP server
4720 * that is capable of receiving messages and returning responses
4722 * @author Dietrich Ayala <dietrich@ganx4.com>
4723 * @author Scott Nichol <snichol@users.sourceforge.net>
4727 class nusoap_server extends nusoap_base {
4729 * HTTP headers of request
4733 var $headers = array();
4741 * SOAP headers from request (incomplete namespace resolution; special characters not escaped) (text)
4745 var $requestHeaders = '';
4747 * SOAP Headers from request (parsed)
4751 var $requestHeader = NULL;
4753 * SOAP body request portion (incomplete namespace resolution; special characters not escaped) (text)
4759 * SOAP payload for request (text)
4763 var $requestSOAP = '';
4765 * requested method namespace URI
4769 var $methodURI = '';
4771 * name of method requested
4775 var $methodname = '';
4777 * method parameters from request
4781 var $methodparams = array();
4783 * SOAP Action from request
4787 var $SOAPAction = '';
4789 * character set encoding of incoming (request) messages
4793 var $xml_encoding = '';
4795 * toggles whether the parser decodes element content w/ utf8_decode()
4799 var $decode_utf8 = false;
4802 * HTTP headers of response
4806 var $outgoing_headers = array();
4814 * SOAP headers for response (text or array of soapval or associative array)
4818 var $responseHeaders = '';
4820 * SOAP payload for response (text)
4824 var $responseSOAP = '';
4826 * method return value to place in response
4830 var $methodreturn = false;
4832 * whether $methodreturn is a string of literal XML
4836 var $methodreturnisliteralxml = false;
4838 * SOAP fault for response (or false)
4844 * text indication of result (for debugging)
4848 var $result = 'successful';
4851 * assoc array of operations => opData; operations are added by the register()
4852 * method or by parsing an external WSDL definition
4856 var $operations = array();
4858 * wsdl instance (if one)
4864 * URL for WSDL (if one)
4868 var $externalWSDLURL = false;
4870 * whether to append debug to response as XML comment
4874 var $debug_flag = false;
4879 * the optional parameter is a path to a WSDL file that you'd like to bind the server instance to.
4881 * @param mixed $wsdl file path or URL (string), or wsdl instance (object)
4884 function nusoap_server($wsdl=false){
4885 parent::nusoap_base();
4886 // turn on debugging?
4888 global $HTTP_SERVER_VARS;
4890 if (isset($_SERVER)) {
4891 $this->debug("_SERVER is defined:");
4892 $this->appendDebug($this->varDump($_SERVER));
4893 } elseif (isset($HTTP_SERVER_VARS)) {
4894 $this->debug("HTTP_SERVER_VARS is defined:");
4895 $this->appendDebug($this->varDump($HTTP_SERVER_VARS));
4897 $this->debug("Neither _SERVER nor HTTP_SERVER_VARS is defined.");
4900 if (isset($debug)) {
4901 $this->debug("In nusoap_server, set debug_flag=$debug based on global flag");
4902 $this->debug_flag = $debug;
4903 } elseif (isset($_SERVER['QUERY_STRING'])) {
4904 $qs = explode('&', $_SERVER['QUERY_STRING']);
4905 foreach ($qs as $v) {
4906 if (substr($v, 0, 6) == 'debug=') {
4907 $this->debug("In nusoap_server, set debug_flag=" . substr($v, 6) . " based on query string #1");
4908 $this->debug_flag = substr($v, 6);
4911 } elseif (isset($HTTP_SERVER_VARS['QUERY_STRING'])) {
4912 $qs = explode('&', $HTTP_SERVER_VARS['QUERY_STRING']);
4913 foreach ($qs as $v) {
4914 if (substr($v, 0, 6) == 'debug=') {
4915 $this->debug("In nusoap_server, set debug_flag=" . substr($v, 6) . " based on query string #2");
4916 $this->debug_flag = substr($v, 6);
4923 $this->debug("In nusoap_server, WSDL is specified");
4924 if (is_object($wsdl) && (get_class($wsdl) == 'wsdl')) {
4925 $this->wsdl = $wsdl;
4926 $this->externalWSDLURL = $this->wsdl->wsdl;
4927 $this->debug('Use existing wsdl instance from ' . $this->externalWSDLURL);
4929 $this->debug('Create wsdl from ' . $wsdl);
4930 $this->wsdl = new wsdl($wsdl);
4931 $this->externalWSDLURL = $wsdl;
4933 $this->appendDebug($this->wsdl->getDebug());
4934 $this->wsdl->clearDebug();
4935 if($err = $this->wsdl->getError()){
4936 die('WSDL ERROR: '.$err);
4942 * processes request and returns response
4944 * @param string $data usually is the value of $HTTP_RAW_POST_DATA
4947 function service($data){
4948 global $HTTP_SERVER_VARS;
4950 if (isset($_SERVER['REQUEST_METHOD'])) {
4951 $rm = $_SERVER['REQUEST_METHOD'];
4952 } elseif (isset($HTTP_SERVER_VARS['REQUEST_METHOD'])) {
4953 $rm = $HTTP_SERVER_VARS['REQUEST_METHOD'];
4958 if (isset($_SERVER['QUERY_STRING'])) {
4959 $qs = $_SERVER['QUERY_STRING'];
4960 } elseif (isset($HTTP_SERVER_VARS['QUERY_STRING'])) {
4961 $qs = $HTTP_SERVER_VARS['QUERY_STRING'];
4965 $this->debug("In service, request method=$rm query string=$qs strlen(\$data)=" . strlen($data));
4967 if ($rm == 'POST') {
4968 $this->debug("In service, invoke the request");
4969 $this->parse_request($data);
4970 if (! $this->fault) {
4971 $this->invoke_method();
4973 if (! $this->fault) {
4974 $this->serialize_return();
4976 $this->send_response();
4977 } elseif (preg_match('/wsdl/', $qs) ){
4978 $this->debug("In service, this is a request for WSDL");
4979 if ($this->externalWSDLURL){
4980 if (strpos($this->externalWSDLURL, "http://") !== false) { // assume URL
4981 $this->debug("In service, re-direct for WSDL");
4982 header('Location: '.$this->externalWSDLURL);
4983 } else { // assume file
4984 $this->debug("In service, use file passthru for WSDL");
4985 header("Content-Type: text/xml\r\n");
4986 $pos = strpos($this->externalWSDLURL, "file://");
4987 if ($pos === false) {
4988 $filename = $this->externalWSDLURL;
4990 $filename = substr($this->externalWSDLURL, $pos + 7);
4992 $fp = fopen($this->externalWSDLURL, 'r');
4995 } elseif ($this->wsdl) {
4996 $this->debug("In service, serialize WSDL");
4997 header("Content-Type: text/xml; charset=ISO-8859-1\r\n");
4998 print $this->wsdl->serialize($this->debug_flag);
4999 if ($this->debug_flag) {
5000 $this->debug('wsdl:');
5001 $this->appendDebug($this->varDump($this->wsdl));
5002 print $this->getDebugAsXMLComment();
5005 $this->debug("In service, there is no WSDL");
5006 header("Content-Type: text/html; charset=ISO-8859-1\r\n");
5007 print "This service does not provide WSDL";
5009 } elseif ($this->wsdl) {
5010 $this->debug("In service, return Web description");
5011 print $this->wsdl->webDescription();
5013 $this->debug("In service, no Web description");
5014 header("Content-Type: text/html; charset=ISO-8859-1\r\n");
5015 print "This service does not provide a Web description";
5020 * parses HTTP request headers.
5022 * The following fields are set by this function (when successful)
5031 function parse_http_headers() {
5032 global $HTTP_SERVER_VARS;
5034 $this->request = '';
5035 $this->SOAPAction = '';
5036 if(function_exists('getallheaders')){
5037 $this->debug("In parse_http_headers, use getallheaders");
5038 $headers = getallheaders();
5039 foreach($headers as $k=>$v){
5040 $k = strtolower($k);
5041 $this->headers[$k] = $v;
5042 $this->request .= "$k: $v\r\n";
5043 $this->debug("$k: $v");
5045 // get SOAPAction header
5046 if(isset($this->headers['soapaction'])){
5047 $this->SOAPAction = str_replace('"','',$this->headers['soapaction']);
5049 // get the character encoding of the incoming request
5050 if(isset($this->headers['content-type']) && strpos($this->headers['content-type'],'=')){
5051 $enc = str_replace('"','',substr(strstr($this->headers["content-type"],'='),1));
5052 if(preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i',$enc)){
5053 $this->xml_encoding = strtoupper($enc);
5055 $this->xml_encoding = 'US-ASCII';
5058 // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
5059 $this->xml_encoding = 'ISO-8859-1';
5061 } elseif(isset($_SERVER) && is_array($_SERVER)){
5062 $this->debug("In parse_http_headers, use _SERVER");
5063 foreach ($_SERVER as $k => $v) {
5064 if (substr($k, 0, 5) == 'HTTP_') {
5065 $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', substr($k, 5))));
5067 $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', $k)));
5069 if ($k == 'soapaction') {
5070 // get SOAPAction header
5072 $v = str_replace('"', '', $v);
5073 $v = str_replace('\\', '', $v);
5074 $this->SOAPAction = $v;
5075 } else if ($k == 'content-type') {
5076 // get the character encoding of the incoming request
5077 if (strpos($v, '=')) {
5078 $enc = substr(strstr($v, '='), 1);
5079 $enc = str_replace('"', '', $enc);
5080 $enc = str_replace('\\', '', $enc);
5081 if (preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i',$enc)) {
5082 $this->xml_encoding = strtoupper($enc);
5084 $this->xml_encoding = 'US-ASCII';
5087 // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
5088 $this->xml_encoding = 'ISO-8859-1';
5091 $this->headers[$k] = $v;
5092 $this->request .= "$k: $v\r\n";
5093 $this->debug("$k: $v");
5095 } elseif (is_array($HTTP_SERVER_VARS)) {
5096 $this->debug("In parse_http_headers, use HTTP_SERVER_VARS");
5097 foreach ($HTTP_SERVER_VARS as $k => $v) {
5098 if (substr($k, 0, 5) == 'HTTP_') {
5099 $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', substr($k, 5)))); $k = strtolower(substr($k, 5));
5101 $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', $k))); $k = strtolower($k);
5103 if ($k == 'soapaction') {
5104 // get SOAPAction header
5106 $v = str_replace('"', '', $v);
5107 $v = str_replace('\\', '', $v);
5108 $this->SOAPAction = $v;
5109 } else if ($k == 'content-type') {
5110 // get the character encoding of the incoming request
5111 if (strpos($v, '=')) {
5112 $enc = substr(strstr($v, '='), 1);
5113 $enc = str_replace('"', '', $enc);
5114 $enc = str_replace('\\', '', $enc);
5115 if (preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i',$enc)) {
5116 $this->xml_encoding = strtoupper($enc);
5118 $this->xml_encoding = 'US-ASCII';
5121 // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
5122 $this->xml_encoding = 'ISO-8859-1';
5125 $this->headers[$k] = $v;
5126 $this->request .= "$k: $v\r\n";
5127 $this->debug("$k: $v");
5130 $this->debug("In parse_http_headers, HTTP headers not accessible");
5131 $this->setError("HTTP headers not accessible");
5138 * The following fields are set by this function (when successful)
5152 * This sets the fault field on error
5154 * @param string $data XML string
5157 function parse_request($data='') {
5158 $this->debug('entering parse_request()');
5159 $this->parse_http_headers();
5160 $this->debug('got character encoding: '.$this->xml_encoding);
5161 // uncompress if necessary
5162 if (isset($this->headers['content-encoding']) && $this->headers['content-encoding'] != '') {
5163 $this->debug('got content encoding: ' . $this->headers['content-encoding']);
5164 if ($this->headers['content-encoding'] == 'deflate' || $this->headers['content-encoding'] == 'gzip') {
5165 // if decoding works, use it. else assume data wasn't gzencoded
5166 if (function_exists('gzuncompress')) {
5167 if ($this->headers['content-encoding'] == 'deflate' && $degzdata = @gzuncompress($data)) {
5169 } elseif ($this->headers['content-encoding'] == 'gzip' && $degzdata = gzinflate(substr($data, 10))) {
5172 $this->fault('SOAP-ENV:Client', 'Errors occurred when trying to decode the data');
5176 $this->fault('SOAP-ENV:Client', 'This Server does not support compressed data');
5181 $this->request .= "\r\n".$data;
5182 $data = $this->parseRequest($this->headers, $data);
5183 $this->requestSOAP = $data;
5184 $this->debug('leaving parse_request');
5187 function register_class($classname){
5188 $this->registeredClass = $classname;
5191 * invokes a PHP function for the requested SOAP method
5193 * The following fields are set by this function (when successful)
5197 * Note that the PHP function that is called may also set the following
5198 * fields to affect the response sent to the client
5203 * This sets the fault field on error
5207 function invoke_method() {
5208 $this->debug('in invoke_method, methodname=' . $this->methodname . ' methodURI=' . $this->methodURI . ' SOAPAction=' . $this->SOAPAction);
5211 // if you are debugging in this area of the code, your service uses a class to implement methods,
5212 // you use SOAP RPC, and the client is .NET, please be aware of the following...
5213 // when the .NET wsdl.exe utility generates a proxy, it will remove the '.' or '..' from the
5214 // method name. that is fine for naming the .NET methods. it is not fine for properly constructing
5215 // the XML request and reading the XML response. you need to add the RequestElementName and
5216 // ResponseElementName to the System.Web.Services.Protocols.SoapRpcMethodAttribute that wsdl.exe
5217 // generates for the method. these parameters are used to specify the correct XML element names
5218 // for .NET to use, i.e. the names with the '.' in them.
5220 $orig_methodname = $this->methodname;
5222 if ($this->opData = $this->wsdl->getOperationData($this->methodname)) {
5223 $this->debug('in invoke_method, found WSDL operation=' . $this->methodname);
5224 $this->appendDebug('opData=' . $this->varDump($this->opData));
5225 } elseif ($this->opData = $this->wsdl->getOperationDataForSoapAction($this->SOAPAction)) {
5226 // Note: hopefully this case will only be used for doc/lit, since rpc services should have wrapper element
5227 $this->debug('in invoke_method, found WSDL soapAction=' . $this->SOAPAction . ' for operation=' . $this->opData['name']);
5228 $this->appendDebug('opData=' . $this->varDump($this->opData));
5229 $this->methodname = $this->opData['name'];
5231 $this->debug('in invoke_method, no WSDL for operation=' . $this->methodname);
5232 $this->fault('SOAP-ENV:Client', "Operation '" . $this->methodname . "' is not defined in the WSDL for this service");
5236 $this->debug('in invoke_method, no WSDL to validate method');
5239 // if a . is present in $this->methodname, we see if there is a class in scope,
5240 // which could be referred to. We will also distinguish between two deliminators,
5241 // to allow methods to be called a the class or an instance
5242 if (strpos($this->methodname, '..') > 0) {
5244 } else if (strpos($this->methodname, '.') > 0) {
5249 $this->debug("in invoke_method, delim=$delim");
5253 if (strlen($delim) > 0 && substr_count($this->methodname, $delim) == 1) {
5254 $try_class = substr($this->methodname, 0, strpos($this->methodname, $delim));
5255 if (class_exists($try_class)) {
5256 // get the class and method name
5257 $class = $try_class;
5258 $method = substr($this->methodname, strpos($this->methodname, $delim) + strlen($delim));
5259 $this->debug("in invoke_method, class=$class method=$method delim=$delim");
5261 $this->debug("in invoke_method, class=$try_class not found");
5265 $this->debug("in invoke_method, no class to try");
5267 if(empty($delim) && isset($this->registeredClass)){
5268 $class = $this->registeredClass;
5270 $method = $this->methodname;
5273 // does method exist?
5275 if (!function_exists($this->methodname)) {
5276 $this->debug("in invoke_method, function '$this->methodname' not found!");
5277 $this->result = 'fault: method not found';
5278 $this->fault('SOAP-ENV:Client',"method '$this->methodname'('$orig_methodname') not defined in service('$try_class' '$delim')");
5282 $method_to_compare = (substr(phpversion(), 0, 2) == '4.') ? strtolower($method) : $method;
5283 if (!in_array($method_to_compare, get_class_methods($class))) {
5284 $this->debug("in invoke_method, method '$this->methodname' not found in class '$class'!");
5285 $this->result = 'fault: method not found';
5286 $this->fault('SOAP-ENV:Client',"method '$this->methodname'/'$method_to_compare'('$orig_methodname') not defined in service/'$class'('$try_class' '$delim')");
5291 // evaluate message, getting back parameters
5292 // verify that request parameters match the method's signature
5293 if(! $this->verify_method($this->methodname,$this->methodparams)){
5295 $this->debug('ERROR: request not verified against method signature');
5296 $this->result = 'fault: request failed validation against method signature';
5298 $this->fault('SOAP-ENV:Client',"Operation '$this->methodname' not defined in service.");
5302 // if there are parameters to pass
5303 $this->debug('in invoke_method, params:');
5304 $this->appendDebug($this->varDump($this->methodparams));
5305 $this->debug("in invoke_method, calling '$this->methodname'");
5306 if (!function_exists('call_user_func_array')) {
5308 $this->debug('in invoke_method, calling function using eval()');
5309 $funcCall = "\$this->methodreturn = $this->methodname(";
5311 if ($delim == '..') {
5312 $this->debug('in invoke_method, calling class method using eval()');
5313 $funcCall = "\$this->methodreturn = ".$class."::".$method."(";
5315 $this->debug('in invoke_method, calling instance method using eval()');
5316 // generate unique instance name
5317 $instname = "\$inst_".time();
5318 $funcCall = $instname." = new ".$class."(); ";
5319 $funcCall .= "\$this->methodreturn = ".$instname."->".$method."(";
5322 if ($this->methodparams) {
5323 foreach ($this->methodparams as $param) {
5324 if (is_array($param) || is_object($param)) {
5325 $this->fault('SOAP-ENV:Client', 'NuSOAP does not handle complexType parameters correctly when using eval; call_user_func_array must be available');
5328 $funcCall .= "\"$param\",";
5330 $funcCall = substr($funcCall, 0, -1);
5333 $this->debug('in invoke_method, function call: '.$funcCall);
5337 $this->debug('in invoke_method, calling function using call_user_func_array()');
5338 $call_arg = "$this->methodname"; // straight assignment changes $this->methodname to lower case after call_user_func_array()
5339 } elseif ($delim == '..') {
5340 $this->debug('in invoke_method, calling class method using call_user_func_array()');
5341 $call_arg = array ($class, $method);
5343 $this->debug('in invoke_method, calling instance method using call_user_func_array()');
5344 $instance = new $class ();
5345 $call_arg = array(&$instance, $method);
5347 if (is_array($this->methodparams)) {
5348 $this->methodreturn = call_user_func_array($call_arg, array_values($this->methodparams));
5350 $this->methodreturn = call_user_func_array($call_arg, array());
5353 $this->debug('in invoke_method, methodreturn:');
5354 $this->appendDebug($this->varDump($this->methodreturn));
5355 $this->debug("in invoke_method, called method $this->methodname, received data of type ".gettype($this->methodreturn));
5359 * serializes the return value from a PHP function into a full SOAP Envelope
5361 * The following fields are set by this function (when successful)
5365 * This sets the fault field on error
5369 function serialize_return() {
5370 $this->debug('Entering serialize_return methodname: ' . $this->methodname . ' methodURI: ' . $this->methodURI);
5372 if (isset($this->methodreturn) && is_object($this->methodreturn) && ((get_class($this->methodreturn) == 'soap_fault') || (get_class($this->methodreturn) == 'nusoap_fault'))) {
5373 $this->debug('got a fault object from method');
5374 $this->fault = $this->methodreturn;
5376 } elseif ($this->methodreturnisliteralxml) {
5377 $return_val = $this->methodreturn;
5378 // returned value(s)
5380 $this->debug('got a(n) '.gettype($this->methodreturn).' from method');
5381 $this->debug('serializing return value');
5383 if (sizeof($this->opData['output']['parts']) > 1) {
5384 $this->debug('more than one output part, so use the method return unchanged');
5385 $opParams = $this->methodreturn;
5386 } elseif (sizeof($this->opData['output']['parts']) == 1) {
5387 $this->debug('exactly one output part, so wrap the method return in a simple array');
5388 // TODO: verify that it is not already wrapped!
5389 //foreach ($this->opData['output']['parts'] as $name => $type) {
5390 // $this->debug('wrap in element named ' . $name);
5392 $opParams = array($this->methodreturn);
5394 $return_val = $this->wsdl->serializeRPCParameters($this->methodname,'output',$opParams);
5395 $this->appendDebug($this->wsdl->getDebug());
5396 $this->wsdl->clearDebug();
5397 if($errstr = $this->wsdl->getError()){
5398 $this->debug('got wsdl error: '.$errstr);
5399 $this->fault('SOAP-ENV:Server', 'unable to serialize result');
5403 if (isset($this->methodreturn)) {
5404 $return_val = $this->serialize_val($this->methodreturn, 'return');
5407 $this->debug('in absence of WSDL, assume void return for backward compatibility');
5411 $this->debug('return value:');
5412 $this->appendDebug($this->varDump($return_val));
5414 $this->debug('serializing response');
5416 $this->debug('have WSDL for serialization: style is ' . $this->opData['style']);
5417 if ($this->opData['style'] == 'rpc') {
5418 $this->debug('style is rpc for serialization: use is ' . $this->opData['output']['use']);
5419 if ($this->opData['output']['use'] == 'literal') {
5420 // 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
5421 if ($this->methodURI) {
5422 $payload = '<ns1:'.$this->methodname.'Response xmlns:ns1="'.$this->methodURI.'">'.$return_val.'</ns1:'.$this->methodname."Response>";
5424 $payload = '<'.$this->methodname.'Response>'.$return_val.'</'.$this->methodname.'Response>';
5427 if ($this->methodURI) {
5428 $payload = '<ns1:'.$this->methodname.'Response xmlns:ns1="'.$this->methodURI.'">'.$return_val.'</ns1:'.$this->methodname."Response>";
5430 $payload = '<'.$this->methodname.'Response>'.$return_val.'</'.$this->methodname.'Response>';
5434 $this->debug('style is not rpc for serialization: assume document');
5435 $payload = $return_val;
5438 $this->debug('do not have WSDL for serialization: assume rpc/encoded');
5439 $payload = '<ns1:'.$this->methodname.'Response xmlns:ns1="'.$this->methodURI.'">'.$return_val.'</ns1:'.$this->methodname."Response>";
5441 $this->result = 'successful';
5443 //if($this->debug_flag){
5444 $this->appendDebug($this->wsdl->getDebug());
5446 if (isset($this->opData['output']['encodingStyle'])) {
5447 $encodingStyle = $this->opData['output']['encodingStyle'];
5449 $encodingStyle = '';
5451 // Added: In case we use a WSDL, return a serialized env. WITH the usedNamespaces.
5452 $this->responseSOAP = $this->serializeEnvelope($payload,$this->responseHeaders,$this->wsdl->usedNamespaces,$this->opData['style'],$this->opData['output']['use'],$encodingStyle);
5454 $this->responseSOAP = $this->serializeEnvelope($payload,$this->responseHeaders);
5456 $this->debug("Leaving serialize_return");
5460 * sends an HTTP response
5462 * The following fields are set by this function (when successful)
5469 function send_response() {
5470 $this->debug('Enter send_response');
5472 $payload = $this->fault->serialize();
5473 $this->outgoing_headers[] = "HTTP/1.0 500 Internal Server Error";
5474 $this->outgoing_headers[] = "Status: 500 Internal Server Error";
5476 $payload = $this->responseSOAP;
5477 // Some combinations of PHP+Web server allow the Status
5478 // to come through as a header. Since OK is the default
5480 // $this->outgoing_headers[] = "HTTP/1.0 200 OK";
5481 // $this->outgoing_headers[] = "Status: 200 OK";
5483 // add debug data if in debug mode
5484 if(isset($this->debug_flag) && $this->debug_flag){
5485 $payload .= $this->getDebugAsXMLComment();
5487 $this->outgoing_headers[] = "Server: $this->title Server v$this->version";
5488 preg_match('/\$Revisio' . 'n: ([^ ]+)/', $this->revision, $rev);
5489 $this->outgoing_headers[] = "X-SOAP-Server: $this->title/$this->version (".$rev[1].")";
5490 // Let the Web server decide about this
5491 //$this->outgoing_headers[] = "Connection: Close\r\n";
5492 $payload = $this->getHTTPBody($payload);
5493 $type = $this->getHTTPContentType();
5494 $charset = $this->getHTTPContentTypeCharset();
5495 $this->outgoing_headers[] = "Content-Type: $type" . ($charset ? '; charset=' . $charset : '');
5496 //begin code to compress payload - by John
5497 // NOTE: there is no way to know whether the Web server will also compress
5499 if (strlen($payload) > 1024 && isset($this->headers) && isset($this->headers['accept-encoding'])) {
5500 if (strstr($this->headers['accept-encoding'], 'gzip')) {
5501 if (function_exists('gzencode')) {
5502 if (isset($this->debug_flag) && $this->debug_flag) {
5503 $payload .= "<!-- Content being gzipped -->";
5505 $this->outgoing_headers[] = "Content-Encoding: gzip";
5506 $payload = gzencode($payload);
5508 if (isset($this->debug_flag) && $this->debug_flag) {
5509 $payload .= "<!-- Content will not be gzipped: no gzencode -->";
5512 } elseif (strstr($this->headers['accept-encoding'], 'deflate')) {
5513 // Note: MSIE requires gzdeflate output (no Zlib header and checksum),
5514 // instead of gzcompress output,
5515 // which conflicts with HTTP 1.1 spec (http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.5)
5516 if (function_exists('gzdeflate')) {
5517 if (isset($this->debug_flag) && $this->debug_flag) {
5518 $payload .= "<!-- Content being deflated -->";
5520 $this->outgoing_headers[] = "Content-Encoding: deflate";
5521 $payload = gzdeflate($payload);
5523 if (isset($this->debug_flag) && $this->debug_flag) {
5524 $payload .= "<!-- Content will not be deflated: no gzcompress -->";
5532 $this->outgoing_headers[] = "Content-Length: ".strlen($payload);
5533 reset($this->outgoing_headers);
5534 foreach($this->outgoing_headers as $hdr){
5535 header($hdr, false);
5540 $this->response = join("\r\n",$this->outgoing_headers)."\r\n\r\n".$payload;
5544 * takes the value that was created by parsing the request
5545 * and compares to the method's signature, if available.
5547 * @param string $operation The operation to be invoked
5548 * @param array $request The array of parameter values
5549 * @return boolean Whether the operation was found
5552 function verify_method($operation,$request){
5553 if(isset($this->wsdl) && is_object($this->wsdl)){
5554 if($this->wsdl->getOperationData($operation)){
5557 } elseif(isset($this->operations[$operation])){
5564 * processes SOAP message received from client
5566 * @param array $headers The HTTP headers
5567 * @param string $data unprocessed request data from client
5568 * @return mixed value of the message, decoded into a PHP type
5571 function parseRequest($headers, $data) {
5572 $this->debug('Entering parseRequest() for data of length ' . strlen($data) . ' headers:');
5573 $this->appendDebug($this->varDump($headers));
5574 if (!isset($headers['content-type'])) {
5575 $this->setError('Request not of type text/xml (no content-type header)');
5578 if (!strstr($headers['content-type'], 'text/xml')) {
5579 $this->setError('Request not of type text/xml');
5582 if (strpos($headers['content-type'], '=')) {
5583 $enc = str_replace('"', '', substr(strstr($headers["content-type"], '='), 1));
5584 $this->debug('Got response encoding: ' . $enc);
5585 if(preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i',$enc)){
5586 $this->xml_encoding = strtoupper($enc);
5588 $this->xml_encoding = 'US-ASCII';
5591 // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
5592 $this->xml_encoding = 'ISO-8859-1';
5594 $this->debug('Use encoding: ' . $this->xml_encoding . ' when creating nusoap_parser');
5595 // parse response, get soap parser obj
5596 $parser = new nusoap_parser($data,$this->xml_encoding,'',$this->decode_utf8);
5598 $this->debug("parser debug: \n".$parser->getDebug());
5599 // if fault occurred during message parsing
5600 if($err = $parser->getError()){
5601 $this->result = 'fault: error in msg parsing: '.$err;
5602 $this->fault('SOAP-ENV:Client',"error in msg parsing:\n".$err);
5603 // else successfully parsed request into soapval object
5605 // get/set methodname
5606 $this->methodURI = $parser->root_struct_namespace;
5607 $this->methodname = $parser->root_struct_name;
5608 $this->debug('methodname: '.$this->methodname.' methodURI: '.$this->methodURI);
5609 $this->debug('calling parser->get_soapbody()');
5610 $this->methodparams = $parser->get_soapbody();
5612 $this->requestHeaders = $parser->getHeaders();
5614 $this->requestHeader = $parser->get_soapheader();
5615 // add document for doclit support
5616 $this->document = $parser->document;
5621 * gets the HTTP body for the current response.
5623 * @param string $soapmsg The SOAP payload
5624 * @return string The HTTP body, which includes the SOAP payload
5627 function getHTTPBody($soapmsg) {
5632 * gets the HTTP content type for the current response.
5634 * Note: getHTTPBody must be called before this.
5636 * @return string the HTTP content type for the current response.
5639 function getHTTPContentType() {
5644 * gets the HTTP content type charset for the current response.
5645 * returns false for non-text content types.
5647 * Note: getHTTPBody must be called before this.
5649 * @return string the HTTP content type charset for the current response.
5652 function getHTTPContentTypeCharset() {
5653 return $this->soap_defencoding;
5657 * add a method to the dispatch map (this has been replaced by the register method)
5659 * @param string $methodname
5660 * @param string $in array of input values
5661 * @param string $out array of output values
5665 function add_to_map($methodname,$in,$out){
5666 $this->operations[$methodname] = array('name' => $methodname,'in' => $in,'out' => $out);
5670 * register a service function with the server
5672 * @param string $name the name of the PHP function, class.method or class..method
5673 * @param array $in assoc array of input values: key = param name, value = param type
5674 * @param array $out assoc array of output values: key = param name, value = param type
5675 * @param mixed $namespace the element namespace for the method or false
5676 * @param mixed $soapaction the soapaction for the method or false
5677 * @param mixed $style optional (rpc|document) or false Note: when 'document' is specified, parameter and return wrappers are created for you automatically
5678 * @param mixed $use optional (encoded|literal) or false
5679 * @param string $documentation optional Description to include in WSDL
5680 * @param string $encodingStyle optional (usually 'http://schemas.xmlsoap.org/soap/encoding/' for encoded)
5683 function register($name,$in=array(),$out=array(),$namespace=false,$soapaction=false,$style=false,$use=false,$documentation='',$encodingStyle=''){
5684 global $HTTP_SERVER_VARS;
5686 if($this->externalWSDLURL){
5687 die('You cannot bind to an external WSDL file, and register methods outside of it! Please choose either WSDL or no WSDL.');
5690 die('You must specify a name when you register an operation');
5692 if (!is_array($in)) {
5693 die('You must provide an array for operation inputs');
5695 if (!is_array($out)) {
5696 die('You must provide an array for operation outputs');
5698 if(false == $namespace) {
5700 if(false == $soapaction) {
5701 if (isset($_SERVER)) {
5702 $SERVER_NAME = $_SERVER['SERVER_NAME'];
5703 $SCRIPT_NAME = isset($_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : $_SERVER['SCRIPT_NAME'];
5704 $HTTPS = isset($_SERVER['HTTPS']) ? $_SERVER['HTTPS'] : (isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off');
5705 } elseif (isset($HTTP_SERVER_VARS)) {
5706 $SERVER_NAME = $HTTP_SERVER_VARS['SERVER_NAME'];
5707 $SCRIPT_NAME = isset($HTTP_SERVER_VARS['PHP_SELF']) ? $HTTP_SERVER_VARS['PHP_SELF'] : $HTTP_SERVER_VARS['SCRIPT_NAME'];
5708 $HTTPS = isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off';
5710 $this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available");
5712 if ($HTTPS == '1' || $HTTPS == 'on') {
5717 $soapaction = "$SCHEME://$SERVER_NAME$SCRIPT_NAME/$name";
5719 if(false == $style) {
5725 if ($use == 'encoded' && $encodingStyle == '') {
5726 $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
5729 $this->operations[$name] = array(
5733 'namespace' => $namespace,
5734 'soapaction' => $soapaction,
5737 $this->wsdl->addOperation($name,$in,$out,$namespace,$soapaction,$style,$use,$documentation,$encodingStyle);
5743 * Specify a fault to be returned to the client.
5744 * This also acts as a flag to the server that a fault has occured.
5746 * @param string $faultcode
5747 * @param string $faultstring
5748 * @param string $faultactor
5749 * @param string $faultdetail
5752 function fault($faultcode,$faultstring,$faultactor='',$faultdetail=''){
5753 if ($faultdetail == '' && $this->debug_flag) {
5754 $faultdetail = $this->getDebug();
5756 $this->fault = new nusoap_fault($faultcode,$faultactor,$faultstring,$faultdetail);
5757 $this->fault->soap_defencoding = $this->soap_defencoding;
5761 * Sets up wsdl object.
5762 * Acts as a flag to enable internal WSDL generation
5764 * @param string $serviceName, name of the service
5765 * @param mixed $namespace optional 'tns' service namespace or false
5766 * @param mixed $endpoint optional URL of service endpoint or false
5767 * @param string $style optional (rpc|document) WSDL style (also specified by operation)
5768 * @param string $transport optional SOAP transport
5769 * @param mixed $schemaTargetNamespace optional 'types' targetNamespace for service schema or false
5771 function configureWSDL($serviceName,$namespace = false,$endpoint = false,$style='rpc', $transport = 'http://schemas.xmlsoap.org/soap/http', $schemaTargetNamespace = false)
5773 global $HTTP_SERVER_VARS;
5775 if (isset($_SERVER)) {
5776 $SERVER_NAME = $_SERVER['SERVER_NAME'];
5777 $SERVER_PORT = $_SERVER['SERVER_PORT'];
5778 $SCRIPT_NAME = isset($_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : $_SERVER['SCRIPT_NAME'];
5779 $HTTPS = isset($_SERVER['HTTPS']) ? $_SERVER['HTTPS'] : (isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off');
5780 } elseif (isset($HTTP_SERVER_VARS)) {
5781 $SERVER_NAME = $HTTP_SERVER_VARS['SERVER_NAME'];
5782 $SERVER_PORT = $HTTP_SERVER_VARS['SERVER_PORT'];
5783 $SCRIPT_NAME = isset($HTTP_SERVER_VARS['PHP_SELF']) ? $HTTP_SERVER_VARS['PHP_SELF'] : $HTTP_SERVER_VARS['SCRIPT_NAME'];
5784 $HTTPS = isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off';
5786 $this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available");
5788 // If server name has port number attached then strip it (else port number gets duplicated in WSDL output) (occurred using lighttpd and FastCGI)
5789 $colon = strpos($SERVER_NAME,":");
5791 $SERVER_NAME = substr($SERVER_NAME, 0, $colon);
5793 if ($SERVER_PORT == 80) {
5796 $SERVER_PORT = ':' . $SERVER_PORT;
5798 if(false == $namespace) {
5799 $namespace = "http://$SERVER_NAME/soap/$serviceName";
5802 if(false == $endpoint) {
5803 if ($HTTPS == '1' || $HTTPS == 'on') {
5808 $endpoint = "$SCHEME://$SERVER_NAME$SERVER_PORT$SCRIPT_NAME";
5811 if(false == $schemaTargetNamespace) {
5812 $schemaTargetNamespace = $namespace;
5815 $this->wsdl = new wsdl;
5816 $this->wsdl->serviceName = $serviceName;
5817 $this->wsdl->endpoint = $endpoint;
5818 $this->wsdl->namespaces['tns'] = $namespace;
5819 $this->wsdl->namespaces['soap'] = 'http://schemas.xmlsoap.org/wsdl/soap/';
5820 $this->wsdl->namespaces['wsdl'] = 'http://schemas.xmlsoap.org/wsdl/';
5821 if ($schemaTargetNamespace != $namespace) {
5822 $this->wsdl->namespaces['types'] = $schemaTargetNamespace;
5824 $this->wsdl->schemas[$schemaTargetNamespace][0] = new nusoap_xmlschema('', '', $this->wsdl->namespaces);
5825 if ($style == 'document') {
5826 $this->wsdl->schemas[$schemaTargetNamespace][0]->schemaInfo['elementFormDefault'] = 'qualified';
5828 $this->wsdl->schemas[$schemaTargetNamespace][0]->schemaTargetNamespace = $schemaTargetNamespace;
5829 $this->wsdl->schemas[$schemaTargetNamespace][0]->imports['http://schemas.xmlsoap.org/soap/encoding/'][0] = array('location' => '', 'loaded' => true);
5830 $this->wsdl->schemas[$schemaTargetNamespace][0]->imports['http://schemas.xmlsoap.org/wsdl/'][0] = array('location' => '', 'loaded' => true);
5831 $this->wsdl->bindings[$serviceName.'Binding'] = array(
5832 'name'=>$serviceName.'Binding',
5834 'transport'=>$transport,
5835 'portType'=>$serviceName.'PortType');
5836 $this->wsdl->ports[$serviceName.'Port'] = array(
5837 'binding'=>$serviceName.'Binding',
5838 'location'=>$endpoint,
5839 'bindingType'=>'http://schemas.xmlsoap.org/wsdl/soap/');
5844 * Backward compatibility
5846 class soap_server extends nusoap_server {
5853 Modification information for LGPL compliance
5855 r58622 - 2010-10-22 18:18:59 -0700 (Fri, 22 Oct 2010) - engsvnbuild - Author: lam <lam@198.18.142.201>
5858 r58361 - 2010-09-29 16:59:02 -0700 (Wed, 29 Sep 2010) - kjing - Author: Jenny Gonsalves <jenny@sugarcrm.com>
5859 Merging with maint_6_0_1 (svn merge -r 58250:58342)
5861 r57813 - 2010-08-19 10:34:44 -0700 (Thu, 19 Aug 2010) - kjing - Author: John Mertic <jmertic@sugarcrm.com>
5862 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.
5864 r57707 - 2010-08-10 12:26:13 -0700 (Tue, 10 Aug 2010) - kjing - Author: Stanislav Malyshev <smalyshev@gmail.com>
5865 fix SOAP calls with no parameters
5867 r56990 - 2010-06-16 13:05:36 -0700 (Wed, 16 Jun 2010) - kjing - snapshot "Mango" svn branch to a new one for GitHub sync
5869 r56989 - 2010-06-16 13:01:33 -0700 (Wed, 16 Jun 2010) - kjing - defunt "Mango" svn dev branch before github cutover
5871 r55980 - 2010-04-19 13:31:28 -0700 (Mon, 19 Apr 2010) - kjing - create Mango (6.1) based on windex
5873 r51719 - 2009-10-22 10:18:00 -0700 (Thu, 22 Oct 2009) - mitani - Converted to Build 3 tags and updated the build system
5875 r51634 - 2009-10-19 13:32:22 -0700 (Mon, 19 Oct 2009) - mitani - Windex is the branch for Sugar Sales 1.0 development
5877 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.
5879 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.
5881 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:
5882 - Changing all ereg function to either preg or simple string based ones
5883 - No more references to magic quotes.
5884 - Change all the session_unregister() functions to just unset() the correct session variable instead.
5886 r50375 - 2009-08-24 18:07:43 -0700 (Mon, 24 Aug 2009) - dwong - branch kobe2 from tokyo r50372
5888 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
5890 r45680 - 2009-03-30 14:34:35 -0700 (Mon, 30 Mar 2009) - Samir Gandhi - modifeid serializeSchema to generate WS-I compliant WSDL
5892 r42807 - 2008-12-29 11:16:59 -0800 (Mon, 29 Dec 2008) - dwong - Branch from trunk/sugarcrm r42806 to branches/tokyo/sugarcrm
5894 r42645 - 2008-12-18 13:41:08 -0800 (Thu, 18 Dec 2008) - awu - merging maint_5_2_0 rev41336:HEAD to trunk
5896 r41647 - 2008-11-11 17:44:30 -0800 (Tue, 11 Nov 2008) - majed - Fixes a few bugs
5898 r41596 - 2008-11-10 19:20:04 -0800 (Mon, 10 Nov 2008) - Samir Gandhi - modified to set $method in the code
5900 r41558 - 2008-11-10 14:35:34 -0800 (Mon, 10 Nov 2008) - majed - changes nusoap to allow for registering classes
5902 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.
5904 - data/SugarBean.php
5905 - include/domit/php_http_client_generic.php
5906 - include/domit/php_http_connector.php
5907 - include/domit/testing_domit.php
5908 - include/domit/xml_domit_getelementsbypath.php
5909 - include/domit/xml_domit_lite_parser.php
5910 - include/domit/xml_domit_nodemaps.php
5911 - include/domit/xml_domit_parser.php
5912 - include/domit/xml_domit_shared.php
5913 - include/generic/SugarWidgets/SugarWidgetField.php
5914 - include/generic/SugarWidgets/SugarWidgetReportField.php
5915 - include/ListView/ProcessView.php
5916 - include/nusoap/class.soapclient.php
5917 - include/nusoap/nusoap.php
5918 - include/nusoap/nusoapmime.php
5919 - include/Pear/HTML_Safe/Safe.php
5920 - include/Pear/XML_HTMLSax3/HTMLSax3.php
5921 - modules/Administration/RebuildWorkFlow.php
5922 - modules/Expressions/RelateSelector.php
5923 - modules/Reports/templates/templates_reports.php
5924 - modules/WorkFlow/Delete.php
5925 - modules/WorkFlow/Save.php
5926 - modules/WorkFlow/SaveSequence.php
5927 - modules/WorkFlow/WorkFlow.php
5928 - modules/WorkFlowActionShells/CreateStep1.php
5929 - modules/WorkFlowActionShells/CreateStep2.php
5930 - modules/WorkFlowActionShells/Save.php
5931 - modules/WorkFlowActionShells/WorkFlowActionShell.php
5932 - modules/WorkFlowAlerts/Save.php
5933 - modules/WorkFlowAlerts/WorkFlowAlert.php
5934 - modules/WorkFlowAlertShells/DetailView.php
5935 - modules/WorkFlowAlertShells/WorkFlowAlertShell.php
5936 - modules/WorkFlowTriggerShells/CreateStep1.php
5937 - modules/WorkFlowTriggerShells/CreateStepFilter.php
5938 - modules/WorkFlowTriggerShells/SaveFilter.php
5939 - modules/WorkFlowTriggerShells/WorkFlowTriggerShell.php
5940 - soap/SoapHelperFunctions.php
5941 - test/modules/DynamicFields/DynamicFields_Bug24095_test.php
5942 - test/simpletest/browser.php
5943 - test/simpletest/default_reporter.php
5944 - test/simpletest/detached.php
5945 - test/simpletest/eclipse.php
5946 - test/simpletest/expectation.php
5947 - test/simpletest/extensions/pear_test_case.php
5948 - test/simpletest/form.php
5949 - test/simpletest/http.php
5950 - test/simpletest/mock_objects.php
5951 - test/simpletest/page.php
5952 - test/simpletest/parser.php
5953 - test/simpletest/remote.php
5954 - test/simpletest/shell_tester.php
5955 - test/simpletest/simple_test.php
5956 - test/simpletest/simpletest.php
5957 - test/simpletest/test/acceptance_test.php
5958 - test/simpletest/test/adapter_test.php
5959 - test/simpletest/test/authentication_test.php
5960 - test/simpletest/test/browser_test.php
5961 - test/simpletest/test/collector_test.php
5962 - test/simpletest/test/compatibility_test.php
5963 - test/simpletest/test/detached_test.php
5964 - test/simpletest/test/eclipse_test.php
5965 - test/simpletest/test/encoding_test.php
5966 - test/simpletest/test/errors_test.php
5967 - test/simpletest/test/expectation_test.php
5968 - test/simpletest/test/form_test.php
5969 - test/simpletest/test/frames_test.php
5970 - test/simpletest/test/http_test.php
5971 - test/simpletest/test/live_test.php
5972 - test/simpletest/test/mock_objects_test.php
5973 - test/simpletest/test/page_test.php
5974 - test/simpletest/test/parse_error_test.php
5975 - test/simpletest/test/parser_test.php
5976 - test/simpletest/test/remote_test.php
5977 - test/simpletest/test/shell_test.php
5978 - test/simpletest/test/shell_tester_test.php
5979 - test/simpletest/test/simpletest_test.php
5980 - test/simpletest/test/site/page_request.php
5981 - test/simpletest/test/tag_test.php
5982 - test/simpletest/test/unit_tester_test.php
5983 - test/simpletest/test/user_agent_test.php
5984 - test/simpletest/test/visual_test.php
5985 - test/simpletest/test/xml_test.php
5986 - test/simpletest/test_case.php
5987 - test/simpletest/ui/array_reporter/test.php
5988 - test/simpletest/ui/recorder/test.php
5989 - test/simpletest/unit_tester.php
5990 - test/simpletest/url.php
5991 - test/simpletest/user_agent.php
5992 - test/simpletest/web_tester.php
5993 - test/spikephpcoverage/src/PEAR.php
5994 - test/spikephpcoverage/src/util/Utility.php
5995 - test/spikephpcoverage/src/XML/Parser.php
5996 - test/spikephpcoverage/src/XML/Parser/Simple.php
5997 - test/test_utilities/SugarTest_SimpleBrowser.php
5999 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.
6001 r38300 - 2008-07-25 13:33:43 -0700 (Fri, 25 Jul 2008) - Samir Gandhi - put the debug in parseresponse function
6003 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
6005 r36824 - 2008-06-18 09:26:11 -0700 (Wed, 18 Jun 2008) - roger - bug: 21832
6007 r26422 - 2007-09-05 17:29:12 -0700 (Wed, 05 Sep 2007) - majed - migrate from beta 1 to trunk
6009 r15787 - 2006-08-10 10:14:41 -0700 (Thu, 10 Aug 2006) - roger - RRS: bug 7961
6011 r14701 - 2006-07-17 13:37:26 -0700 (Mon, 17 Jul 2006) - roger - RRS: bug 5801
6013 r13782 - 2006-06-06 10:58:55 -0700 (Tue, 06 Jun 2006) - majed - changes entry point code
6015 r11466 - 2006-02-01 15:49:47 -0800 (Wed, 01 Feb 2006) - jacob - Adding extra !empty check to get around a PHP warning.
6017 r11115 - 2006-01-17 14:54:45 -0800 (Tue, 17 Jan 2006) - majed - add entry point validation
6019 r10585 - 2005-12-13 14:42:26 -0800 (Tue, 13 Dec 2005) - majed - adds new license mechanisim
6021 r10170 - 2005-12-05 18:37:46 -0800 (Mon, 05 Dec 2005) - majed - fixes various issues
6023 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.
6025 r8991 - 2005-11-03 19:07:25 -0800 (Thu, 03 Nov 2005) - majed - fixes nusoap issue
6027 r8846 - 2005-10-31 11:01:12 -0800 (Mon, 31 Oct 2005) - majed - new version of nusoap
6029 r7905 - 2005-09-21 19:12:57 -0700 (Wed, 21 Sep 2005) - majed - restores old nusoap pre & with a few fixes
6031 r7861 - 2005-09-20 15:40:25 -0700 (Tue, 20 Sep 2005) - majed - & fix for 3.5.1
6033 r7452 - 2005-08-17 11:32:34 -0700 (Wed, 17 Aug 2005) - majed - changes soap to nusoap
6035 r5820 - 2005-06-21 14:22:24 -0700 (Tue, 21 Jun 2005) - majed - fixes issues with nusoap and with custom fields
6037 r5462 - 2005-05-25 13:50:11 -0700 (Wed, 25 May 2005) - majed - upgraded nusoap to .6.9
6039 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
6041 r573 - 2004-09-04 13:03:32 -0700 (Sat, 04 Sep 2004) - sugarclint - undoing copyrights added in inadvertantly. --clint
6043 r546 - 2004-09-03 11:49:38 -0700 (Fri, 03 Sep 2004) - sugarmsi - removed echo count
6045 r354 - 2004-08-02 23:00:37 -0700 (Mon, 02 Aug 2004) - sugarjacob - Adding Soap
6055 * parses a WSDL file, allows access to it's data, other utility methods.
6056 * also builds WSDL structures programmatically.
6058 * @author Dietrich Ayala <dietrich@ganx4.com>
6059 * @author Scott Nichol <snichol@users.sourceforge.net>
6063 class wsdl extends nusoap_base {
6064 // URL or filename of the root of this WSDL
6066 // define internal arrays of bindings, ports, operations, messages, etc.
6067 var $schemas = array();
6069 var $message = array();
6070 var $complexTypes = array();
6071 var $messages = array();
6072 var $currentMessage;
6073 var $currentOperation;
6074 var $portTypes = array();
6075 var $currentPortType;
6076 var $bindings = array();
6077 var $currentBinding;
6078 var $ports = array();
6080 var $opData = array();
6082 var $documentation = false;
6084 // array of wsdl docs to import
6085 var $import = array();
6090 var $depth_array = array();
6092 var $proxyhost = '';
6093 var $proxyport = '';
6094 var $proxyusername = '';
6095 var $proxypassword = '';
6097 var $response_timeout = 30;
6098 var $curl_options = array(); // User-specified cURL options
6099 var $use_curl = false; // whether to always try to use cURL
6100 // for HTTP authentication
6101 var $username = ''; // Username for HTTP authentication
6102 var $password = ''; // Password for HTTP authentication
6103 var $authtype = ''; // Type of HTTP authentication
6104 var $certRequest = array(); // Certificate for HTTP SSL authentication
6109 * @param string $wsdl WSDL document URL
6110 * @param string $proxyhost
6111 * @param string $proxyport
6112 * @param string $proxyusername
6113 * @param string $proxypassword
6114 * @param integer $timeout set the connection timeout
6115 * @param integer $response_timeout set the response timeout
6116 * @param array $curl_options user-specified cURL options
6117 * @param boolean $use_curl try to use cURL
6120 function wsdl($wsdl = '',$proxyhost=false,$proxyport=false,$proxyusername=false,$proxypassword=false,$timeout=0,$response_timeout=30,$curl_options=null,$use_curl=false){
6121 parent::nusoap_base();
6122 $this->debug("ctor wsdl=$wsdl timeout=$timeout response_timeout=$response_timeout");
6123 $this->proxyhost = $proxyhost;
6124 $this->proxyport = $proxyport;
6125 $this->proxyusername = $proxyusername;
6126 $this->proxypassword = $proxypassword;
6127 $this->timeout = $timeout;
6128 $this->response_timeout = $response_timeout;
6129 if (is_array($curl_options))
6130 $this->curl_options = $curl_options;
6131 $this->use_curl = $use_curl;
6132 $this->fetchWSDL($wsdl);
6136 * fetches the WSDL document and parses it
6140 function fetchWSDL($wsdl) {
6141 $this->debug("parse and process WSDL path=$wsdl");
6142 $this->wsdl = $wsdl;
6144 if ($this->wsdl != "") {
6145 $this->parseWSDL($this->wsdl);
6148 // TODO: handle imports more properly, grabbing them in-line and nesting them
6149 $imported_urls = array();
6151 while ($imported > 0) {
6154 foreach ($this->schemas as $ns => $list) {
6155 foreach ($list as $xs) {
6156 $wsdlparts = parse_url($this->wsdl); // this is bogusly simple!
6157 foreach ($xs->imports as $ns2 => $list2) {
6158 for ($ii = 0; $ii < count($list2); $ii++) {
6159 if (! $list2[$ii]['loaded']) {
6160 $this->schemas[$ns]->imports[$ns2][$ii]['loaded'] = true;
6161 $url = $list2[$ii]['location'];
6163 $urlparts = parse_url($url);
6164 if (!isset($urlparts['host'])) {
6165 $url = $wsdlparts['scheme'] . '://' . $wsdlparts['host'] . (isset($wsdlparts['port']) ? ':' .$wsdlparts['port'] : '') .
6166 substr($wsdlparts['path'],0,strrpos($wsdlparts['path'],'/') + 1) .$urlparts['path'];
6168 if (! in_array($url, $imported_urls)) {
6169 $this->parseWSDL($url);
6171 $imported_urls[] = $url;
6174 $this->debug("Unexpected scenario: empty URL for unloaded import");
6182 $wsdlparts = parse_url($this->wsdl); // this is bogusly simple!
6183 foreach ($this->import as $ns => $list) {
6184 for ($ii = 0; $ii < count($list); $ii++) {
6185 if (! $list[$ii]['loaded']) {
6186 $this->import[$ns][$ii]['loaded'] = true;
6187 $url = $list[$ii]['location'];
6189 $urlparts = parse_url($url);
6190 if (!isset($urlparts['host'])) {
6191 $url = $wsdlparts['scheme'] . '://' . $wsdlparts['host'] . (isset($wsdlparts['port']) ? ':' . $wsdlparts['port'] : '') .
6192 substr($wsdlparts['path'],0,strrpos($wsdlparts['path'],'/') + 1) .$urlparts['path'];
6194 if (! in_array($url, $imported_urls)) {
6195 $this->parseWSDL($url);
6197 $imported_urls[] = $url;
6200 $this->debug("Unexpected scenario: empty URL for unloaded import");
6206 // add new data to operation data
6207 foreach($this->bindings as $binding => $bindingData) {
6208 if (isset($bindingData['operations']) && is_array($bindingData['operations'])) {
6209 foreach($bindingData['operations'] as $operation => $data) {
6210 $this->debug('post-parse data gathering for ' . $operation);
6211 $this->bindings[$binding]['operations'][$operation]['input'] =
6212 isset($this->bindings[$binding]['operations'][$operation]['input']) ?
6213 array_merge($this->bindings[$binding]['operations'][$operation]['input'], $this->portTypes[ $bindingData['portType'] ][$operation]['input']) :
6214 $this->portTypes[ $bindingData['portType'] ][$operation]['input'];
6215 $this->bindings[$binding]['operations'][$operation]['output'] =
6216 isset($this->bindings[$binding]['operations'][$operation]['output']) ?
6217 array_merge($this->bindings[$binding]['operations'][$operation]['output'], $this->portTypes[ $bindingData['portType'] ][$operation]['output']) :
6218 $this->portTypes[ $bindingData['portType'] ][$operation]['output'];
6219 if(isset($this->messages[ $this->bindings[$binding]['operations'][$operation]['input']['message'] ])){
6220 $this->bindings[$binding]['operations'][$operation]['input']['parts'] = $this->messages[ $this->bindings[$binding]['operations'][$operation]['input']['message'] ];
6222 if(isset($this->messages[ $this->bindings[$binding]['operations'][$operation]['output']['message'] ])){
6223 $this->bindings[$binding]['operations'][$operation]['output']['parts'] = $this->messages[ $this->bindings[$binding]['operations'][$operation]['output']['message'] ];
6225 // Set operation style if necessary, but do not override one already provided
6226 if (isset($bindingData['style']) && !isset($this->bindings[$binding]['operations'][$operation]['style'])) {
6227 $this->bindings[$binding]['operations'][$operation]['style'] = $bindingData['style'];
6229 $this->bindings[$binding]['operations'][$operation]['transport'] = isset($bindingData['transport']) ? $bindingData['transport'] : '';
6230 $this->bindings[$binding]['operations'][$operation]['documentation'] = isset($this->portTypes[ $bindingData['portType'] ][$operation]['documentation']) ? $this->portTypes[ $bindingData['portType'] ][$operation]['documentation'] : '';
6231 $this->bindings[$binding]['operations'][$operation]['endpoint'] = isset($bindingData['endpoint']) ? $bindingData['endpoint'] : '';
6238 * parses the wsdl document
6240 * @param string $wsdl path or URL
6243 function parseWSDL($wsdl = '') {
6244 $this->debug("parse WSDL at path=$wsdl");
6247 $this->debug('no wsdl passed to parseWSDL()!!');
6248 $this->setError('no wsdl passed to parseWSDL()!!');
6252 // parse $wsdl for url format
6253 $wsdl_props = parse_url($wsdl);
6255 if (isset($wsdl_props['scheme']) && ($wsdl_props['scheme'] == 'http' || $wsdl_props['scheme'] == 'https')) {
6256 $this->debug('getting WSDL http(s) URL ' . $wsdl);
6258 $tr = new soap_transport_http($wsdl, $this->curl_options, $this->use_curl);
6259 $tr->request_method = 'GET';
6260 $tr->useSOAPAction = false;
6261 if($this->proxyhost && $this->proxyport){
6262 $tr->setProxy($this->proxyhost,$this->proxyport,$this->proxyusername,$this->proxypassword);
6264 if ($this->authtype != '') {
6265 $tr->setCredentials($this->username, $this->password, $this->authtype, array(), $this->certRequest);
6267 $tr->setEncoding('gzip, deflate');
6268 $wsdl_string = $tr->send('', $this->timeout, $this->response_timeout);
6269 //$this->debug("WSDL request\n" . $tr->outgoing_payload);
6270 //$this->debug("WSDL response\n" . $tr->incoming_payload);
6271 $this->appendDebug($tr->getDebug());
6273 if($err = $tr->getError() ){
6274 $errstr = 'Getting ' . $wsdl . ' - HTTP ERROR: '.$err;
6275 $this->debug($errstr);
6276 $this->setError($errstr);
6281 $this->debug("got WSDL URL");
6283 // $wsdl is not http(s), so treat it as a file URL or plain file path
6284 if (isset($wsdl_props['scheme']) && ($wsdl_props['scheme'] == 'file') && isset($wsdl_props['path'])) {
6285 $path = isset($wsdl_props['host']) ? ($wsdl_props['host'] . ':' . $wsdl_props['path']) : $wsdl_props['path'];
6289 $this->debug('getting WSDL file ' . $path);
6290 if ($fp = @fopen($path, 'r')) {
6292 while ($data = fread($fp, 32768)) {
6293 $wsdl_string .= $data;
6297 $errstr = "Bad path to WSDL file $path";
6298 $this->debug($errstr);
6299 $this->setError($errstr);
6303 $this->debug('Parse WSDL');
6304 // end new code added
6305 // Create an XML parser.
6306 $this->parser = xml_parser_create();
6307 // Set the options for parsing the XML data.
6308 // xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
6309 xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
6310 // Set the object for the parser.
6311 xml_set_object($this->parser, $this);
6312 // Set the element handlers for the parser.
6313 xml_set_element_handler($this->parser, 'start_element', 'end_element');
6314 xml_set_character_data_handler($this->parser, 'character_data');
6315 // Parse the XML file.
6316 if (!xml_parse($this->parser, $wsdl_string, true)) {
6317 // Display an error message.
6319 'XML error parsing WSDL from %s on line %d: %s',
6321 xml_get_current_line_number($this->parser),
6322 xml_error_string(xml_get_error_code($this->parser))
6324 $this->debug($errstr);
6325 $this->debug("XML payload:\n" . $wsdl_string);
6326 $this->setError($errstr);
6330 xml_parser_free($this->parser);
6331 $this->debug('Parsing WSDL done');
6332 // catch wsdl parse errors
6333 if($this->getError()){
6340 * start-element handler
6342 * @param string $parser XML parser object
6343 * @param string $name element name
6344 * @param string $attrs associative array of attributes
6347 function start_element($parser, $name, $attrs)
6349 if ($this->status == 'schema') {
6350 $this->currentSchema->schemaStartElement($parser, $name, $attrs);
6351 $this->appendDebug($this->currentSchema->getDebug());
6352 $this->currentSchema->clearDebug();
6353 } elseif (preg_match('/schema$/', $name)) {
6354 $this->debug('Parsing WSDL schema');
6355 // $this->debug("startElement for $name ($attrs[name]). status = $this->status (".$this->getLocalPart($name).")");
6356 $this->status = 'schema';
6357 $this->currentSchema = new nusoap_xmlschema('', '', $this->namespaces);
6358 $this->currentSchema->schemaStartElement($parser, $name, $attrs);
6359 $this->appendDebug($this->currentSchema->getDebug());
6360 $this->currentSchema->clearDebug();
6362 // position in the total number of elements, starting from 0
6363 $pos = $this->position++;
6364 $depth = $this->depth++;
6365 // set self as current value for this depth
6366 $this->depth_array[$depth] = $pos;
6367 $this->message[$pos] = array('cdata' => '');
6368 // process attributes
6369 if (count($attrs) > 0) {
6370 // register namespace declarations
6371 foreach($attrs as $k => $v) {
6372 if (preg_match('/^xmlns/',$k)) {
6373 if ($ns_prefix = substr(strrchr($k, ':'), 1)) {
6374 $this->namespaces[$ns_prefix] = $v;
6376 $this->namespaces['ns' . (count($this->namespaces) + 1)] = $v;
6378 if ($v == 'http://www.w3.org/2001/XMLSchema' || $v == 'http://www.w3.org/1999/XMLSchema' || $v == 'http://www.w3.org/2000/10/XMLSchema') {
6379 $this->XMLSchemaVersion = $v;
6380 $this->namespaces['xsi'] = $v . '-instance';
6384 // expand each attribute prefix to its namespace
6385 foreach($attrs as $k => $v) {
6386 $k = strpos($k, ':') ? $this->expandQname($k) : $k;
6387 if ($k != 'location' && $k != 'soapAction' && $k != 'namespace') {
6388 $v = strpos($v, ':') ? $this->expandQname($v) : $v;
6396 // get element prefix, namespace and name
6397 if (preg_match('/:/', $name)) {
6399 $prefix = substr($name, 0, strpos($name, ':'));
6401 $namespace = isset($this->namespaces[$prefix]) ? $this->namespaces[$prefix] : '';
6402 // get unqualified name
6403 $name = substr(strstr($name, ':'), 1);
6405 // process attributes, expanding any prefixes to namespaces
6406 // find status, register data
6407 switch ($this->status) {
6409 if ($name == 'part') {
6410 if (isset($attrs['type'])) {
6411 $this->debug("msg " . $this->currentMessage . ": found part (with type) $attrs[name]: " . implode(',', $attrs));
6412 $this->messages[$this->currentMessage][$attrs['name']] = $attrs['type'];
6414 if (isset($attrs['element'])) {
6415 $this->debug("msg " . $this->currentMessage . ": found part (with element) $attrs[name]: " . implode(',', $attrs));
6416 $this->messages[$this->currentMessage][$attrs['name']] = $attrs['element'] . '^';
6423 $this->currentPortOperation = $attrs['name'];
6424 $this->debug("portType $this->currentPortType operation: $this->currentPortOperation");
6425 if (isset($attrs['parameterOrder'])) {
6426 $this->portTypes[$this->currentPortType][$attrs['name']]['parameterOrder'] = $attrs['parameterOrder'];
6429 case 'documentation':
6430 $this->documentation = true;
6432 // merge input/output data
6434 $m = isset($attrs['message']) ? $this->getLocalPart($attrs['message']) : '';
6435 $this->portTypes[$this->currentPortType][$this->currentPortOperation][$name]['message'] = $m;
6443 if (isset($attrs['style'])) {
6444 $this->bindings[$this->currentBinding]['prefix'] = $prefix;
6446 $this->bindings[$this->currentBinding] = array_merge($this->bindings[$this->currentBinding], $attrs);
6449 $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus]['headers'][] = $attrs;
6452 if (isset($attrs['soapAction'])) {
6453 $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['soapAction'] = $attrs['soapAction'];
6455 if (isset($attrs['style'])) {
6456 $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['style'] = $attrs['style'];
6458 if (isset($attrs['name'])) {
6459 $this->currentOperation = $attrs['name'];
6460 $this->debug("current binding operation: $this->currentOperation");
6461 $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['name'] = $attrs['name'];
6462 $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['binding'] = $this->currentBinding;
6463 $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['endpoint'] = isset($this->bindings[$this->currentBinding]['endpoint']) ? $this->bindings[$this->currentBinding]['endpoint'] : '';
6467 $this->opStatus = 'input';
6470 $this->opStatus = 'output';
6473 if (isset($this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus])) {
6474 $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus] = array_merge($this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus], $attrs);
6476 $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus] = $attrs;
6484 $this->currentPort = $attrs['name'];
6485 $this->debug('current port: ' . $this->currentPort);
6486 $this->ports[$this->currentPort]['binding'] = $this->getLocalPart($attrs['binding']);
6490 $this->ports[$this->currentPort]['location'] = $attrs['location'];
6491 $this->ports[$this->currentPort]['bindingType'] = $namespace;
6492 $this->bindings[ $this->ports[$this->currentPort]['binding'] ]['bindingType'] = $namespace;
6493 $this->bindings[ $this->ports[$this->currentPort]['binding'] ]['endpoint'] = $attrs['location'];
6501 if (isset($attrs['location'])) {
6502 $this->import[$attrs['namespace']][] = array('location' => $attrs['location'], 'loaded' => false);
6503 $this->debug('parsing import ' . $attrs['namespace']. ' - ' . $attrs['location'] . ' (' . count($this->import[$attrs['namespace']]).')');
6505 $this->import[$attrs['namespace']][] = array('location' => '', 'loaded' => true);
6506 if (! $this->getPrefixFromNamespace($attrs['namespace'])) {
6507 $this->namespaces['ns'.(count($this->namespaces)+1)] = $attrs['namespace'];
6509 $this->debug('parsing import ' . $attrs['namespace']. ' - [no location] (' . count($this->import[$attrs['namespace']]).')');
6514 // $this->status = 'schema';
6517 $this->status = 'message';
6518 $this->messages[$attrs['name']] = array();
6519 $this->currentMessage = $attrs['name'];
6522 $this->status = 'portType';
6523 $this->portTypes[$attrs['name']] = array();
6524 $this->currentPortType = $attrs['name'];
6527 if (isset($attrs['name'])) {
6529 if (strpos($attrs['name'], ':')) {
6530 $this->currentBinding = $this->getLocalPart($attrs['name']);
6532 $this->currentBinding = $attrs['name'];
6534 $this->status = 'binding';
6535 $this->bindings[$this->currentBinding]['portType'] = $this->getLocalPart($attrs['type']);
6536 $this->debug("current binding: $this->currentBinding of portType: " . $attrs['type']);
6540 $this->serviceName = $attrs['name'];
6541 $this->status = 'service';
6542 $this->debug('current service: ' . $this->serviceName);
6545 foreach ($attrs as $name => $value) {
6546 $this->wsdl_info[$name] = $value;
6554 * end-element handler
6556 * @param string $parser XML parser object
6557 * @param string $name element name
6560 function end_element($parser, $name){
6561 // unset schema status
6562 if (/*preg_match('/types$/', $name) ||*/ preg_match('/schema$/', $name)) {
6564 $this->appendDebug($this->currentSchema->getDebug());
6565 $this->currentSchema->clearDebug();
6566 $this->schemas[$this->currentSchema->schemaTargetNamespace][] = $this->currentSchema;
6567 $this->debug('Parsing WSDL schema done');
6569 if ($this->status == 'schema') {
6570 $this->currentSchema->schemaEndElement($parser, $name);
6572 // bring depth down a notch
6575 // end documentation
6576 if ($this->documentation) {
6577 //TODO: track the node to which documentation should be assigned; it can be a part, message, etc.
6578 //$this->portTypes[$this->currentPortType][$this->currentPortOperation]['documentation'] = $this->documentation;
6579 $this->documentation = false;
6584 * element content handler
6586 * @param string $parser XML parser object
6587 * @param string $data element content
6590 function character_data($parser, $data)
6592 $pos = isset($this->depth_array[$this->depth]) ? $this->depth_array[$this->depth] : 0;
6593 if (isset($this->message[$pos]['cdata'])) {
6594 $this->message[$pos]['cdata'] .= $data;
6596 if ($this->documentation) {
6597 $this->documentation .= $data;
6602 * if authenticating, set user credentials here
6604 * @param string $username
6605 * @param string $password
6606 * @param string $authtype (basic|digest|certificate|ntlm)
6607 * @param array $certRequest (keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, certpassword (optional), verifypeer (optional), verifyhost (optional): see corresponding options in cURL docs)
6610 function setCredentials($username, $password, $authtype = 'basic', $certRequest = array()) {
6611 $this->debug("setCredentials username=$username authtype=$authtype certRequest=");
6612 $this->appendDebug($this->varDump($certRequest));
6613 $this->username = $username;
6614 $this->password = $password;
6615 $this->authtype = $authtype;
6616 $this->certRequest = $certRequest;
6619 function getBindingData($binding)
6621 if (is_array($this->bindings[$binding])) {
6622 return $this->bindings[$binding];
6627 * returns an assoc array of operation names => operation data
6629 * @param string $portName WSDL port name
6630 * @param string $bindingType eg: soap, smtp, dime (only soap and soap12 are currently supported)
6634 function getOperations($portName = '', $bindingType = 'soap') {
6636 if ($bindingType == 'soap') {
6637 $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/';
6638 } elseif ($bindingType == 'soap12') {
6639 $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/';
6641 $this->debug("getOperations bindingType $bindingType may not be supported");
6643 $this->debug("getOperations for port '$portName' bindingType $bindingType");
6645 foreach($this->ports as $port => $portData) {
6646 $this->debug("getOperations checking port $port bindingType " . $portData['bindingType']);
6647 if ($portName == '' || $port == $portName) {
6648 // binding type of port matches parameter
6649 if ($portData['bindingType'] == $bindingType) {
6650 $this->debug("getOperations found port $port bindingType $bindingType");
6651 //$this->debug("port data: " . $this->varDump($portData));
6652 //$this->debug("bindings: " . $this->varDump($this->bindings[ $portData['binding'] ]));
6654 if (isset($this->bindings[ $portData['binding'] ]['operations'])) {
6655 $ops = array_merge ($ops, $this->bindings[ $portData['binding'] ]['operations']);
6660 if (count($ops) == 0) {
6661 $this->debug("getOperations found no operations for port '$portName' bindingType $bindingType");
6667 * returns an associative array of data necessary for calling an operation
6669 * @param string $operation name of operation
6670 * @param string $bindingType type of binding eg: soap, soap12
6674 function getOperationData($operation, $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) {
6686 //foreach($this->bindings[ $portData['binding'] ]['operations'] as $bOperation => $opData) {
6687 foreach(array_keys($this->bindings[ $portData['binding'] ]['operations']) as $bOperation) {
6688 // note that we could/should also check the namespace here
6689 if ($operation == $bOperation) {
6690 $opData = $this->bindings[ $portData['binding'] ]['operations'][$operation];
6699 * returns an associative array of data necessary for calling an operation
6701 * @param string $soapAction soapAction for operation
6702 * @param string $bindingType type of binding eg: soap, soap12
6706 function getOperationDataForSoapAction($soapAction, $bindingType = 'soap') {
6707 if ($bindingType == 'soap') {
6708 $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/';
6709 } elseif ($bindingType == 'soap12') {
6710 $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/';
6713 foreach($this->ports as $port => $portData) {
6714 // binding type of port matches parameter
6715 if ($portData['bindingType'] == $bindingType) {
6716 // loop through operations for the binding
6717 foreach ($this->bindings[ $portData['binding'] ]['operations'] as $bOperation => $opData) {
6718 if ($opData['soapAction'] == $soapAction) {
6727 * returns an array of information about a given type
6728 * returns false if no type exists by the given name
6731 * 'elements' => array(), // refs to elements array
6732 * 'restrictionBase' => '',
6734 * 'order' => '(sequence|all)',
6735 * 'attrs' => array() // refs to attributes array
6738 * @param string $type the type
6739 * @param string $ns namespace (not prefix) of the type
6742 * @see nusoap_xmlschema
6744 function getTypeDef($type, $ns) {
6745 $this->debug("in getTypeDef: type=$type, ns=$ns");
6746 if ((! $ns) && isset($this->namespaces['tns'])) {
6747 $ns = $this->namespaces['tns'];
6748 $this->debug("in getTypeDef: type namespace forced to $ns");
6750 if (!isset($this->schemas[$ns])) {
6751 foreach ($this->schemas as $ns0 => $schema0) {
6752 if (strcasecmp($ns, $ns0) == 0) {
6753 $this->debug("in getTypeDef: replacing schema namespace $ns with $ns0");
6759 if (isset($this->schemas[$ns])) {
6760 $this->debug("in getTypeDef: have schema for namespace $ns");
6761 for ($i = 0; $i < count($this->schemas[$ns]); $i++) {
6762 $xs = &$this->schemas[$ns][$i];
6763 $t = $xs->getTypeDef($type);
6764 $this->appendDebug($xs->getDebug());
6767 $this->debug("in getTypeDef: found type $type");
6768 if (!isset($t['phpType'])) {
6769 // get info for type to tack onto the element
6770 $uqType = substr($t['type'], strrpos($t['type'], ':') + 1);
6771 $ns = substr($t['type'], 0, strrpos($t['type'], ':'));
6772 $etype = $this->getTypeDef($uqType, $ns);
6774 $this->debug("found type for [element] $type:");
6775 $this->debug($this->varDump($etype));
6776 if (isset($etype['phpType'])) {
6777 $t['phpType'] = $etype['phpType'];
6779 if (isset($etype['elements'])) {
6780 $t['elements'] = $etype['elements'];
6782 if (isset($etype['attrs'])) {
6783 $t['attrs'] = $etype['attrs'];
6786 $this->debug("did not find type for [element] $type");
6792 $this->debug("in getTypeDef: did not find type $type");
6794 $this->debug("in getTypeDef: do not have schema for namespace $ns");
6800 * prints html description of services
6804 function webDescription(){
6805 global $HTTP_SERVER_VARS;
6807 if (isset($_SERVER)) {
6808 $PHP_SELF = $_SERVER['PHP_SELF'];
6809 } elseif (isset($HTTP_SERVER_VARS)) {
6810 $PHP_SELF = $HTTP_SERVER_VARS['PHP_SELF'];
6812 $this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available");
6816 <html><head><title>NuSOAP: '.$this->serviceName.'</title>
6817 <style type="text/css">
6818 body { font-family: arial; color: #000000; background-color: #ffffff; margin: 0px 0px 0px 0px; }
6819 p { font-family: arial; color: #000000; margin-top: 0px; margin-bottom: 12px; }
6820 pre { background-color: silver; padding: 5px; font-family: Courier New; font-size: x-small; color: #000000;}
6821 ul { margin-top: 10px; margin-left: 20px; }
6822 li { list-style-type: none; margin-top: 10px; color: #000000; }
6824 margin-left: 0px; padding-bottom: 2em; }
6826 padding-top: 10px; padding-bottom: 10px; padding-left: 15px; font-size: .70em;
6827 margin-top: 10px; margin-left: 0px; color: #000000;
6828 background-color: #ccccff; width: 20%; margin-left: 20px; margin-top: 20px; }
6830 font-family: arial; font-size: 26px; color: #ffffff;
6831 background-color: #999999; width: 100%;
6832 margin-left: 0px; margin-right: 0px;
6833 padding-top: 10px; padding-bottom: 10px;}
6835 position: absolute; visibility: hidden; z-index: 200; left: 250px; top: 100px;
6836 font-family: arial; overflow: hidden; width: 600;
6837 padding: 20px; font-size: 10px; background-color: #999999;
6838 layer-background-color:#FFFFFF; }
6839 a,a:active { color: charcoal; font-weight: bold; }
6840 a:visited { color: #666666; font-weight: bold; }
6841 a:hover { color: cc3300; font-weight: bold; }
6843 <script language="JavaScript" type="text/javascript">
6845 // POP-UP CAPTIONS...
6846 function lib_bwcheck(){ //Browsercheck (needed)
6847 this.ver=navigator.appVersion
6848 this.agent=navigator.userAgent
6849 this.dom=document.getElementById?1:0
6850 this.opera5=this.agent.indexOf("Opera 5")>-1
6851 this.ie5=(this.ver.indexOf("MSIE 5")>-1 && this.dom && !this.opera5)?1:0;
6852 this.ie6=(this.ver.indexOf("MSIE 6")>-1 && this.dom && !this.opera5)?1:0;
6853 this.ie4=(document.all && !this.dom && !this.opera5)?1:0;
6854 this.ie=this.ie4||this.ie5||this.ie6
6855 this.mac=this.agent.indexOf("Mac")>-1
6856 this.ns6=(this.dom && parseInt(this.ver) >= 5) ?1:0;
6857 this.ns4=(document.layers && !this.dom)?1:0;
6858 this.bw=(this.ie6 || this.ie5 || this.ie4 || this.ns4 || this.ns6 || this.opera5)
6861 var bw = new lib_bwcheck()
6862 //Makes crossbrowser object.
6863 function makeObj(obj){
6864 this.evnt=bw.dom? document.getElementById(obj):bw.ie4?document.all[obj]:bw.ns4?document.layers[obj]:0;
6865 if(!this.evnt) return false
6866 this.css=bw.dom||bw.ie4?this.evnt.style:bw.ns4?this.evnt:0;
6867 this.wref=bw.dom||bw.ie4?this.evnt:bw.ns4?this.css.document:0;
6868 this.writeIt=b_writeIt;
6871 // A unit of measure that will be added when setting the position of a layer.
6872 //var px = bw.ns4||window.opera?"":"px";
6873 function b_writeIt(text){
6874 if (bw.ns4){this.wref.write(text);this.wref.close()}
6875 else this.wref.innerHTML = text
6877 //Shows the messages
6879 function popup(divid){
6880 if(oDesc = new makeObj(divid)){
6881 oDesc.css.visibility = "visible"
6884 function popout(){ // Hides message
6885 if(oDesc) oDesc.css.visibility = "hidden"
6893 <div class=title>'.$this->serviceName.'</div>
6895 <p>View the <a href="'.$PHP_SELF.'?wsdl">WSDL</a> for the service.
6896 Click on an operation name to view it's details.</p>
6898 foreach($this->getOperations() as $op => $data){
6899 $b .= "<li><a href='#' onclick=\"popout();popup('$op')\">$op</a></li>";
6900 // create hidden div
6901 $b .= "<div id='$op' class='hidden'>
6902 <a href='#' onclick='popout()'><font color='#ffffff'>Close</font></a><br><br>";
6903 foreach($data as $donnie => $marie){ // loop through opdata
6904 if($donnie == 'input' || $donnie == 'output'){ // show input/output data
6905 $b .= "<font color='white'>".ucfirst($donnie).':</font><br>';
6906 foreach($marie as $captain => $tenille){ // loop through data
6907 if($captain == 'parts'){ // loop thru parts
6908 $b .= " $captain:<br>";
6909 //if(is_array($tenille)){
6910 foreach($tenille as $joanie => $chachi){
6911 $b .= " $joanie: $chachi<br>";
6915 $b .= " $captain: $tenille<br>";
6919 $b .= "<font color='white'>".ucfirst($donnie).":</font> $marie<br>";
6927 </div></body></html>';
6932 * serialize the parsed wsdl
6934 * @param mixed $debug whether to put debug=1 in endpoint URL
6935 * @return string serialization of WSDL
6938 function serialize($debug = 0)
6940 $xml = '<?xml version="1.0" encoding="ISO-8859-1"?>';
6941 $xml .= "\n<definitions";
6942 foreach($this->namespaces as $k => $v) {
6943 $xml .= " xmlns:$k=\"$v\"";
6945 // 10.9.02 - add poulter fix for wsdl and tns declarations
6946 if (isset($this->namespaces['wsdl'])) {
6947 $xml .= " xmlns=\"" . $this->namespaces['wsdl'] . "\"";
6949 if (isset($this->namespaces['tns'])) {
6950 $xml .= " targetNamespace=\"" . $this->namespaces['tns'] . "\"";
6954 if (sizeof($this->import) > 0) {
6955 foreach($this->import as $ns => $list) {
6956 foreach ($list as $ii) {
6957 if ($ii['location'] != '') {
6958 $xml .= '<import location="' . $ii['location'] . '" namespace="' . $ns . '" />';
6960 $xml .= '<import namespace="' . $ns . '" />';
6966 if (count($this->schemas)>=1) {
6967 $xml .= "\n<types>\n";
6968 foreach ($this->schemas as $ns => $list) {
6969 foreach ($list as $xs) {
6970 $xml .= $xs->serializeSchema();
6976 if (count($this->messages) >= 1) {
6977 foreach($this->messages as $msgName => $msgParts) {
6978 $xml .= "\n<message name=\"" . $msgName . '">';
6979 if(is_array($msgParts)){
6980 foreach($msgParts as $partName => $partType) {
6981 // print 'serializing '.$partType.', sv: '.$this->XMLSchemaVersion.'<br>';
6982 if (strpos($partType, ':')) {
6983 $typePrefix = $this->getPrefixFromNamespace($this->getPrefix($partType));
6984 } elseif (isset($this->typemap[$this->namespaces['xsd']][$partType])) {
6985 // print 'checking typemap: '.$this->XMLSchemaVersion.'<br>';
6986 $typePrefix = 'xsd';
6988 foreach($this->typemap as $ns => $types) {
6989 if (isset($types[$partType])) {
6990 $typePrefix = $this->getPrefixFromNamespace($ns);
6993 if (!isset($typePrefix)) {
6994 die("$partType has no namespace!");
6997 $ns = $this->getNamespaceFromPrefix($typePrefix);
6998 $localPart = $this->getLocalPart($partType);
6999 $typeDef = $this->getTypeDef($localPart, $ns);
7000 if ($typeDef['typeClass'] == 'element') {
7001 $elementortype = 'element';
7002 if (substr($localPart, -1) == '^') {
7003 $localPart = substr($localPart, 0, -1);
7006 $elementortype = 'type';
7008 $xml .= "\n" . ' <part name="' . $partName . '" ' . $elementortype . '="' . $typePrefix . ':' . $localPart . '" />';
7011 $xml .= '</message>';
7014 // bindings & porttypes
7015 if (count($this->bindings) >= 1) {
7018 foreach($this->bindings as $bindingName => $attrs) {
7019 $binding_xml .= "\n<binding name=\"" . $bindingName . '" type="tns:' . $attrs['portType'] . '">';
7020 $binding_xml .= "\n" . ' <soap:binding style="' . $attrs['style'] . '" transport="' . $attrs['transport'] . '"/>';
7021 $portType_xml .= "\n<portType name=\"" . $attrs['portType'] . '">';
7022 foreach($attrs['operations'] as $opName => $opParts) {
7023 $binding_xml .= "\n" . ' <operation name="' . $opName . '">';
7024 $binding_xml .= "\n" . ' <soap:operation soapAction="' . $opParts['soapAction'] . '" style="'. $opParts['style'] . '"/>';
7025 if (isset($opParts['input']['encodingStyle']) && $opParts['input']['encodingStyle'] != '') {
7026 $enc_style = ' encodingStyle="' . $opParts['input']['encodingStyle'] . '"';
7030 $binding_xml .= "\n" . ' <input><soap:body use="' . $opParts['input']['use'] . '" namespace="' . $opParts['input']['namespace'] . '"' . $enc_style . '/></input>';
7031 if (isset($opParts['output']['encodingStyle']) && $opParts['output']['encodingStyle'] != '') {
7032 $enc_style = ' encodingStyle="' . $opParts['output']['encodingStyle'] . '"';
7036 $binding_xml .= "\n" . ' <output><soap:body use="' . $opParts['output']['use'] . '" namespace="' . $opParts['output']['namespace'] . '"' . $enc_style . '/></output>';
7037 $binding_xml .= "\n" . ' </operation>';
7038 $portType_xml .= "\n" . ' <operation name="' . $opParts['name'] . '"';
7039 if (isset($opParts['parameterOrder'])) {
7040 $portType_xml .= ' parameterOrder="' . $opParts['parameterOrder'] . '"';
7042 $portType_xml .= '>';
7043 if(isset($opParts['documentation']) && $opParts['documentation'] != '') {
7044 $portType_xml .= "\n" . ' <documentation>' . htmlspecialchars($opParts['documentation']) . '</documentation>';
7046 $portType_xml .= "\n" . ' <input message="tns:' . $opParts['input']['message'] . '"/>';
7047 $portType_xml .= "\n" . ' <output message="tns:' . $opParts['output']['message'] . '"/>';
7048 $portType_xml .= "\n" . ' </operation>';
7050 $portType_xml .= "\n" . '</portType>';
7051 $binding_xml .= "\n" . '</binding>';
7053 $xml .= $portType_xml . $binding_xml;
7056 $xml .= "\n<service name=\"" . $this->serviceName . '">';
7057 if (count($this->ports) >= 1) {
7058 foreach($this->ports as $pName => $attrs) {
7059 $xml .= "\n" . ' <port name="' . $pName . '" binding="tns:' . $attrs['binding'] . '">';
7060 $xml .= "\n" . ' <soap:address location="' . $attrs['location'] . ($debug ? '?debug=1' : '') . '"/>';
7061 $xml .= "\n" . ' </port>';
7064 $xml .= "\n" . '</service>';
7065 return $xml . "\n</definitions>";
7069 * determine whether a set of parameters are unwrapped
7070 * when they are expect to be wrapped, Microsoft-style.
7072 * @param string $type the type (element name) of the wrapper
7073 * @param array $parameters the parameter values for the SOAP call
7074 * @return boolean whether they parameters are unwrapped (and should be wrapped)
7077 function parametersMatchWrapped($type, &$parameters) {
7078 $this->debug("in parametersMatchWrapped type=$type, parameters=");
7079 $this->appendDebug($this->varDump($parameters));
7081 // split type into namespace:unqualified-type
7082 if (strpos($type, ':')) {
7083 $uqType = substr($type, strrpos($type, ':') + 1);
7084 $ns = substr($type, 0, strrpos($type, ':'));
7085 $this->debug("in parametersMatchWrapped: got a prefixed type: $uqType, $ns");
7086 if ($this->getNamespaceFromPrefix($ns)) {
7087 $ns = $this->getNamespaceFromPrefix($ns);
7088 $this->debug("in parametersMatchWrapped: expanded prefixed type: $uqType, $ns");
7091 // TODO: should the type be compared to types in XSD, and the namespace
7092 // set to XSD if the type matches?
7093 $this->debug("in parametersMatchWrapped: No namespace for type $type");
7098 // get the type information
7099 if (!$typeDef = $this->getTypeDef($uqType, $ns)) {
7100 $this->debug("in parametersMatchWrapped: $type ($uqType) is not a supported type.");
7103 $this->debug("in parametersMatchWrapped: found typeDef=");
7104 $this->appendDebug($this->varDump($typeDef));
7105 if (substr($uqType, -1) == '^') {
7106 $uqType = substr($uqType, 0, -1);
7108 $phpType = $typeDef['phpType'];
7109 $arrayType = (isset($typeDef['arrayType']) ? $typeDef['arrayType'] : '');
7110 $this->debug("in parametersMatchWrapped: uqType: $uqType, ns: $ns, phptype: $phpType, arrayType: $arrayType");
7112 // we expect a complexType or element of complexType
7113 if ($phpType != 'struct') {
7114 $this->debug("in parametersMatchWrapped: not a struct");
7118 // see whether the parameter names match the elements
7119 if (isset($typeDef['elements']) && is_array($typeDef['elements'])) {
7122 foreach ($typeDef['elements'] as $name => $attrs) {
7123 if (isset($parameters[$name])) {
7124 $this->debug("in parametersMatchWrapped: have parameter named $name");
7127 $this->debug("in parametersMatchWrapped: do not have parameter named $name");
7132 $this->debug("in parametersMatchWrapped: $matches parameter names match $elements wrapped parameter names");
7133 if ($matches == 0) {
7139 // since there are no elements for the type, if the user passed no
7140 // parameters, the parameters match wrapped.
7141 $this->debug("in parametersMatchWrapped: no elements type $ns:$uqType");
7142 return count($parameters) == 0;
7146 * serialize PHP values according to a WSDL message definition
7147 * contrary to the method name, this is not limited to RPC
7150 * - multi-ref serialization
7151 * - validate PHP values against type definitions, return errors if invalid
7153 * @param string $operation operation name
7154 * @param string $direction (input|output)
7155 * @param mixed $parameters parameter value(s)
7156 * @param string $bindingType (soap|soap12)
7157 * @return mixed parameters serialized as XML or false on error (e.g. operation not found)
7160 function serializeRPCParameters($operation, $direction, $parameters, $bindingType = 'soap') {
7161 $this->debug("in serializeRPCParameters: operation=$operation, direction=$direction, XMLSchemaVersion=$this->XMLSchemaVersion, bindingType=$bindingType");
7162 $this->appendDebug('parameters=' . $this->varDump($parameters));
7164 if ($direction != 'input' && $direction != 'output') {
7165 $this->debug('The value of the \$direction argument needs to be either "input" or "output"');
7166 $this->setError('The value of the \$direction argument needs to be either "input" or "output"');
7169 if (!$opData = $this->getOperationData($operation, $bindingType)) {
7170 $this->debug('Unable to retrieve WSDL data for operation: ' . $operation . ' bindingType: ' . $bindingType);
7171 $this->setError('Unable to retrieve WSDL data for operation: ' . $operation . ' bindingType: ' . $bindingType);
7174 $this->debug('in serializeRPCParameters: opData:');
7175 $this->appendDebug($this->varDump($opData));
7177 // Get encoding style for output and set to current
7178 $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
7179 if(($direction == 'input') && isset($opData['output']['encodingStyle']) && ($opData['output']['encodingStyle'] != $encodingStyle)) {
7180 $encodingStyle = $opData['output']['encodingStyle'];
7181 $enc_style = $encodingStyle;
7186 if (isset($opData[$direction]['parts']) && sizeof($opData[$direction]['parts']) > 0) {
7187 $parts = &$opData[$direction]['parts'];
7188 $part_count = sizeof($parts);
7189 $style = $opData['style'];
7190 $use = $opData[$direction]['use'];
7191 $this->debug("have $part_count part(s) to serialize using $style/$use");
7192 if (is_array($parameters)) {
7193 $parametersArrayType = $this->isArraySimpleOrStruct($parameters);
7194 $parameter_count = count($parameters);
7195 $this->debug("have $parameter_count parameter(s) provided as $parametersArrayType to serialize");
7196 // check for Microsoft-style wrapped parameters
7197 if ($style == 'document' && $use == 'literal' && $part_count == 1 && isset($parts['parameters'])) {
7198 $this->debug('check whether the caller has wrapped the parameters');
7199 if ($direction == 'output' && $parametersArrayType == 'arraySimple' && $parameter_count == 1) {
7200 // TODO: consider checking here for double-wrapping, when
7201 // service function wraps, then NuSOAP wraps again
7202 $this->debug("change simple array to associative with 'parameters' element");
7203 $parameters['parameters'] = $parameters[0];
7204 unset($parameters[0]);
7206 if (($parametersArrayType == 'arrayStruct' || $parameter_count == 0) && !isset($parameters['parameters'])) {
7207 $this->debug('check whether caller\'s parameters match the wrapped ones');
7208 if ($this->parametersMatchWrapped($parts['parameters'], $parameters)) {
7209 $this->debug('wrap the parameters for the caller');
7210 $parameters = array('parameters' => $parameters);
7211 $parameter_count = 1;
7215 foreach ($parts as $name => $type) {
7216 $this->debug("serializing part $name of type $type");
7217 // Track encoding style
7218 if (isset($opData[$direction]['encodingStyle']) && $encodingStyle != $opData[$direction]['encodingStyle']) {
7219 $encodingStyle = $opData[$direction]['encodingStyle'];
7220 $enc_style = $encodingStyle;
7224 // NOTE: add error handling here
7225 // if serializeType returns false, then catch global error and fault
7226 if ($parametersArrayType == 'arraySimple') {
7227 $p = array_shift($parameters);
7228 $this->debug('calling serializeType w/indexed param');
7229 $xml .= $this->serializeType($name, $type, $p, $use, $enc_style);
7230 } elseif (isset($parameters[$name])) {
7231 $this->debug('calling serializeType w/named param');
7232 $xml .= $this->serializeType($name, $type, $parameters[$name], $use, $enc_style);
7234 // TODO: only send nillable
7235 $this->debug('calling serializeType w/null param');
7236 $xml .= $this->serializeType($name, $type, null, $use, $enc_style);
7240 $this->debug('no parameters passed.');
7243 $this->debug("serializeRPCParameters returning: $xml");
7248 * serialize a PHP value according to a WSDL message definition
7251 * - multi-ref serialization
7252 * - validate PHP values against type definitions, return errors if invalid
7254 * @param string $operation operation name
7255 * @param string $direction (input|output)
7256 * @param mixed $parameters parameter value(s)
7257 * @return mixed parameters serialized as XML or false on error (e.g. operation not found)
7261 function serializeParameters($operation, $direction, $parameters)
7263 $this->debug("in serializeParameters: operation=$operation, direction=$direction, XMLSchemaVersion=$this->XMLSchemaVersion");
7264 $this->appendDebug('parameters=' . $this->varDump($parameters));
7266 if ($direction != 'input' && $direction != 'output') {
7267 $this->debug('The value of the \$direction argument needs to be either "input" or "output"');
7268 $this->setError('The value of the \$direction argument needs to be either "input" or "output"');
7271 if (!$opData = $this->getOperationData($operation)) {
7272 $this->debug('Unable to retrieve WSDL data for operation: ' . $operation);
7273 $this->setError('Unable to retrieve WSDL data for operation: ' . $operation);
7276 $this->debug('opData:');
7277 $this->appendDebug($this->varDump($opData));
7279 // Get encoding style for output and set to current
7280 $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
7281 if(($direction == 'input') && isset($opData['output']['encodingStyle']) && ($opData['output']['encodingStyle'] != $encodingStyle)) {
7282 $encodingStyle = $opData['output']['encodingStyle'];
7283 $enc_style = $encodingStyle;
7288 if (isset($opData[$direction]['parts']) && sizeof($opData[$direction]['parts']) > 0) {
7290 $use = $opData[$direction]['use'];
7291 $this->debug("use=$use");
7292 $this->debug('got ' . count($opData[$direction]['parts']) . ' part(s)');
7293 if (is_array($parameters)) {
7294 $parametersArrayType = $this->isArraySimpleOrStruct($parameters);
7295 $this->debug('have ' . $parametersArrayType . ' parameters');
7296 foreach($opData[$direction]['parts'] as $name => $type) {
7297 $this->debug('serializing part "'.$name.'" of type "'.$type.'"');
7298 // Track encoding style
7299 if(isset($opData[$direction]['encodingStyle']) && $encodingStyle != $opData[$direction]['encodingStyle']) {
7300 $encodingStyle = $opData[$direction]['encodingStyle'];
7301 $enc_style = $encodingStyle;
7305 // NOTE: add error handling here
7306 // if serializeType returns false, then catch global error and fault
7307 if ($parametersArrayType == 'arraySimple') {
7308 $p = array_shift($parameters);
7309 $this->debug('calling serializeType w/indexed param');
7310 $xml .= $this->serializeType($name, $type, $p, $use, $enc_style);
7311 } elseif (isset($parameters[$name])) {
7312 $this->debug('calling serializeType w/named param');
7313 $xml .= $this->serializeType($name, $type, $parameters[$name], $use, $enc_style);
7315 // TODO: only send nillable
7316 $this->debug('calling serializeType w/null param');
7317 $xml .= $this->serializeType($name, $type, null, $use, $enc_style);
7321 $this->debug('no parameters passed.');
7324 $this->debug("serializeParameters returning: $xml");
7329 * serializes a PHP value according a given type definition
7331 * @param string $name name of value (part or element)
7332 * @param string $type XML schema type of value (type or element)
7333 * @param mixed $value a native PHP value (parameter value)
7334 * @param string $use use for part (encoded|literal)
7335 * @param string $encodingStyle SOAP encoding style for the value (if different than the enclosing style)
7336 * @param boolean $unqualified a kludge for what should be XML namespace form handling
7337 * @return string value serialized as an XML string
7340 function serializeType($name, $type, $value, $use='encoded', $encodingStyle=false, $unqualified=false)
7342 $this->debug("in serializeType: name=$name, type=$type, use=$use, encodingStyle=$encodingStyle, unqualified=" . ($unqualified ? "unqualified" : "qualified"));
7343 $this->appendDebug("value=" . $this->varDump($value));
7344 if($use == 'encoded' && $encodingStyle) {
7345 $encodingStyle = ' SOAP-ENV:encodingStyle="' . $encodingStyle . '"';
7348 // if a soapval has been supplied, let its type override the WSDL
7349 if (is_object($value) && get_class($value) == 'soapval') {
7350 if ($value->type_ns) {
7351 $type = $value->type_ns . ':' . $value->type;
7353 $this->debug("in serializeType: soapval overrides type to $type");
7354 } elseif ($value->type) {
7355 $type = $value->type;
7357 $this->debug("in serializeType: soapval overrides type to $type");
7360 $this->debug("in serializeType: soapval does not override type");
7362 $attrs = $value->attributes;
7363 $value = $value->value;
7364 $this->debug("in serializeType: soapval overrides value to $value");
7366 if (!is_array($value)) {
7367 $value['!'] = $value;
7369 foreach ($attrs as $n => $v) {
7370 $value['!' . $n] = $v;
7372 $this->debug("in serializeType: soapval provides attributes");
7379 if (strpos($type, ':')) {
7380 $uqType = substr($type, strrpos($type, ':') + 1);
7381 $ns = substr($type, 0, strrpos($type, ':'));
7382 $this->debug("in serializeType: got a prefixed type: $uqType, $ns");
7383 if ($this->getNamespaceFromPrefix($ns)) {
7384 $ns = $this->getNamespaceFromPrefix($ns);
7385 $this->debug("in serializeType: expanded prefixed type: $uqType, $ns");
7388 if($ns == $this->XMLSchemaVersion || $ns == 'http://schemas.xmlsoap.org/soap/encoding/'){
7389 $this->debug('in serializeType: type namespace indicates XML Schema or SOAP Encoding type');
7390 if ($unqualified && $use == 'literal') {
7391 $elementNS = " xmlns=\"\"";
7395 if (is_null($value)) {
7396 if ($use == 'literal') {
7397 // TODO: depends on minOccurs
7398 $xml = "<$name$elementNS/>";
7400 // TODO: depends on nillable, which should be checked before calling this method
7401 $xml = "<$name$elementNS xsi:nil=\"true\" xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"/>";
7403 $this->debug("in serializeType: returning: $xml");
7406 if ($uqType == 'Array') {
7407 // JBoss/Axis does this sometimes
7408 return $this->serialize_val($value, $name, false, false, false, false, $use);
7410 if ($uqType == 'boolean') {
7411 if ((is_string($value) && $value == 'false') || (! $value)) {
7417 if ($uqType == 'string' && gettype($value) == 'string') {
7418 $value = $this->expandEntities($value);
7420 if (($uqType == 'long' || $uqType == 'unsignedLong') && gettype($value) == 'double') {
7421 $value = sprintf("%.0lf", $value);
7424 // TODO: what about null/nil values?
7425 // check type isn't a custom type extending xmlschema namespace
7426 if (!$this->getTypeDef($uqType, $ns)) {
7427 if ($use == 'literal') {
7429 $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">$value</$name>";
7431 $xml = "<$name$elementNS>$value</$name>";
7434 $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>$value</$name>";
7436 $this->debug("in serializeType: returning: $xml");
7439 $this->debug('custom type extends XML Schema or SOAP Encoding namespace (yuck)');
7440 } else if ($ns == 'http://xml.apache.org/xml-soap') {
7441 $this->debug('in serializeType: appears to be Apache SOAP type');
7442 if ($uqType == 'Map') {
7443 $tt_prefix = $this->getPrefixFromNamespace('http://xml.apache.org/xml-soap');
7445 $this->debug('in serializeType: Add namespace for Apache SOAP type');
7446 $tt_prefix = 'ns' . rand(1000, 9999);
7447 $this->namespaces[$tt_prefix] = 'http://xml.apache.org/xml-soap';
7448 // force this to be added to usedNamespaces
7449 $tt_prefix = $this->getPrefixFromNamespace('http://xml.apache.org/xml-soap');
7452 foreach($value as $k => $v) {
7453 $this->debug("serializing map element: key $k, value $v");
7454 $contents .= '<item>';
7455 $contents .= $this->serialize_val($k,'key',false,false,false,false,$use);
7456 $contents .= $this->serialize_val($v,'value',false,false,false,false,$use);
7457 $contents .= '</item>';
7459 if ($use == 'literal') {
7461 $xml = "<$name xsi:type=\"" . $tt_prefix . ":$uqType\">$contents</$name>";
7463 $xml = "<$name>$contents</$name>";
7466 $xml = "<$name xsi:type=\"" . $tt_prefix . ":$uqType\"$encodingStyle>$contents</$name>";
7468 $this->debug("in serializeType: returning: $xml");
7471 $this->debug('in serializeType: Apache SOAP type, but only support Map');
7474 // TODO: should the type be compared to types in XSD, and the namespace
7475 // set to XSD if the type matches?
7476 $this->debug("in serializeType: No namespace for type $type");
7480 if(!$typeDef = $this->getTypeDef($uqType, $ns)){
7481 $this->setError("$type ($uqType) is not a supported type.");
7482 $this->debug("in serializeType: $type ($uqType) is not a supported type.");
7485 $this->debug("in serializeType: found typeDef");
7486 $this->appendDebug('typeDef=' . $this->varDump($typeDef));
7487 if (substr($uqType, -1) == '^') {
7488 $uqType = substr($uqType, 0, -1);
7491 if (!isset($typeDef['phpType'])) {
7492 $this->setError("$type ($uqType) has no phpType.");
7493 $this->debug("in serializeType: $type ($uqType) has no phpType.");
7496 $phpType = $typeDef['phpType'];
7497 $this->debug("in serializeType: uqType: $uqType, ns: $ns, phptype: $phpType, arrayType: " . (isset($typeDef['arrayType']) ? $typeDef['arrayType'] : '') );
7498 // if php type == struct, map value to the <all> element names
7499 if ($phpType == 'struct') {
7500 if (isset($typeDef['typeClass']) && $typeDef['typeClass'] == 'element') {
7501 $elementName = $uqType;
7502 if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) {
7503 $elementNS = " xmlns=\"$ns\"";
7505 $elementNS = " xmlns=\"\"";
7508 $elementName = $name;
7510 $elementNS = " xmlns=\"\"";
7515 if (is_null($value)) {
7516 if ($use == 'literal') {
7517 // TODO: depends on minOccurs and nillable
7518 $xml = "<$elementName$elementNS/>";
7520 $xml = "<$elementName$elementNS xsi:nil=\"true\" xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"/>";
7522 $this->debug("in serializeType: returning: $xml");
7525 if (is_object($value)) {
7526 $value = get_object_vars($value);
7528 if (is_array($value)) {
7529 $elementAttrs = $this->serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType);
7530 if ($use == 'literal') {
7532 $xml = "<$elementName$elementNS$elementAttrs xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">";
7534 $xml = "<$elementName$elementNS$elementAttrs>";
7537 $xml = "<$elementName$elementNS$elementAttrs xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>";
7540 if (isset($typeDef['simpleContent']) && $typeDef['simpleContent'] == 'true') {
7541 if (isset($value['!'])) {
7542 $xml .= $value['!'];
7543 $this->debug("in serializeType: serialized simpleContent for type $type");
7545 $this->debug("in serializeType: no simpleContent to serialize for type $type");
7549 $xml .= $this->serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use, $encodingStyle);
7551 $xml .= "</$elementName>";
7553 $this->debug("in serializeType: phpType is struct, but value is not an array");
7554 $this->setError("phpType is struct, but value is not an array: see debug output for details");
7557 } elseif ($phpType == 'array') {
7558 if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) {
7559 $elementNS = " xmlns=\"$ns\"";
7562 $elementNS = " xmlns=\"\"";
7567 if (is_null($value)) {
7568 if ($use == 'literal') {
7569 // TODO: depends on minOccurs
7570 $xml = "<$name$elementNS/>";
7572 $xml = "<$name$elementNS xsi:nil=\"true\" xsi:type=\"" .
7573 $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/') .
7575 $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/') .
7577 $this->getPrefixFromNamespace($this->getPrefix($typeDef['arrayType'])) .
7579 $this->getLocalPart($typeDef['arrayType'])."[0]\"/>";
7581 $this->debug("in serializeType: returning: $xml");
7584 if (isset($typeDef['multidimensional'])) {
7586 foreach($value as $v) {
7587 $cols = ',' . sizeof($v);
7588 $nv = array_merge($nv, $v);
7594 if (is_array($value) && sizeof($value) >= 1) {
7595 $rows = sizeof($value);
7597 foreach($value as $k => $v) {
7598 $this->debug("serializing array element: $k, $v of type: $typeDef[arrayType]");
7599 //if (strpos($typeDef['arrayType'], ':') ) {
7600 if (!in_array($typeDef['arrayType'],$this->typemap['http://www.w3.org/2001/XMLSchema'])) {
7601 $contents .= $this->serializeType('item', $typeDef['arrayType'], $v, $use);
7603 $contents .= $this->serialize_val($v, 'item', $typeDef['arrayType'], null, $this->XMLSchemaVersion, false, $use);
7610 // TODO: for now, an empty value will be serialized as a zero element
7611 // array. Revisit this when coding the handling of null/nil values.
7612 if ($use == 'literal') {
7613 $xml = "<$name$elementNS>"
7617 $xml = "<$name$elementNS xsi:type=\"".$this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/').':Array" '.
7618 $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/')
7620 .$this->getPrefixFromNamespace($this->getPrefix($typeDef['arrayType']))
7621 .":".$this->getLocalPart($typeDef['arrayType'])."[$rows$cols]\">"
7625 } elseif ($phpType == 'scalar') {
7626 if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) {
7627 $elementNS = " xmlns=\"$ns\"";
7630 $elementNS = " xmlns=\"\"";
7635 if ($use == 'literal') {
7637 $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">$value</$name>";
7639 $xml = "<$name$elementNS>$value</$name>";
7642 $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>$value</$name>";
7645 $this->debug("in serializeType: returning: $xml");
7650 * serializes the attributes for a complexType
7652 * @param array $typeDef our internal representation of an XML schema type (or element)
7653 * @param mixed $value a native PHP value (parameter value)
7654 * @param string $ns the namespace of the type
7655 * @param string $uqType the local part of the type
7656 * @return string value serialized as an XML string
7659 function serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType) {
7660 $this->debug("serializeComplexTypeAttributes for XML Schema type $ns:$uqType");
7662 if (isset($typeDef['extensionBase'])) {
7663 $nsx = $this->getPrefix($typeDef['extensionBase']);
7664 $uqTypex = $this->getLocalPart($typeDef['extensionBase']);
7665 if ($this->getNamespaceFromPrefix($nsx)) {
7666 $nsx = $this->getNamespaceFromPrefix($nsx);
7668 if ($typeDefx = $this->getTypeDef($uqTypex, $nsx)) {
7669 $this->debug("serialize attributes for extension base $nsx:$uqTypex");
7670 $xml .= $this->serializeComplexTypeAttributes($typeDefx, $value, $nsx, $uqTypex);
7672 $this->debug("extension base $nsx:$uqTypex is not a supported type");
7675 if (isset($typeDef['attrs']) && is_array($typeDef['attrs'])) {
7676 $this->debug("serialize attributes for XML Schema type $ns:$uqType");
7677 if (is_array($value)) {
7679 } elseif (is_object($value)) {
7680 $xvalue = get_object_vars($value);
7682 $this->debug("value is neither an array nor an object for XML Schema type $ns:$uqType");
7685 foreach ($typeDef['attrs'] as $aName => $attrs) {
7686 if (isset($xvalue['!' . $aName])) {
7687 $xname = '!' . $aName;
7688 $this->debug("value provided for attribute $aName with key $xname");
7689 } elseif (isset($xvalue[$aName])) {
7691 $this->debug("value provided for attribute $aName with key $xname");
7692 } elseif (isset($attrs['default'])) {
7693 $xname = '!' . $aName;
7694 $xvalue[$xname] = $attrs['default'];
7695 $this->debug('use default value of ' . $xvalue[$aName] . ' for attribute ' . $aName);
7698 $this->debug("no value provided for attribute $aName");
7701 $xml .= " $aName=\"" . $this->expandEntities($xvalue[$xname]) . "\"";
7705 $this->debug("no attributes to serialize for XML Schema type $ns:$uqType");
7711 * serializes the elements for a complexType
7713 * @param array $typeDef our internal representation of an XML schema type (or element)
7714 * @param mixed $value a native PHP value (parameter value)
7715 * @param string $ns the namespace of the type
7716 * @param string $uqType the local part of the type
7717 * @param string $use use for part (encoded|literal)
7718 * @param string $encodingStyle SOAP encoding style for the value (if different than the enclosing style)
7719 * @return string value serialized as an XML string
7722 function serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use='encoded', $encodingStyle=false) {
7723 $this->debug("in serializeComplexTypeElements for XML Schema type $ns:$uqType");
7725 if (isset($typeDef['extensionBase'])) {
7726 $nsx = $this->getPrefix($typeDef['extensionBase']);
7727 $uqTypex = $this->getLocalPart($typeDef['extensionBase']);
7728 if ($this->getNamespaceFromPrefix($nsx)) {
7729 $nsx = $this->getNamespaceFromPrefix($nsx);
7731 if ($typeDefx = $this->getTypeDef($uqTypex, $nsx)) {
7732 $this->debug("serialize elements for extension base $nsx:$uqTypex");
7733 $xml .= $this->serializeComplexTypeElements($typeDefx, $value, $nsx, $uqTypex, $use, $encodingStyle);
7735 $this->debug("extension base $nsx:$uqTypex is not a supported type");
7738 if (isset($typeDef['elements']) && is_array($typeDef['elements'])) {
7739 $this->debug("in serializeComplexTypeElements, serialize elements for XML Schema type $ns:$uqType");
7740 if (is_array($value)) {
7742 } elseif (is_object($value)) {
7743 $xvalue = get_object_vars($value);
7745 $this->debug("value is neither an array nor an object for XML Schema type $ns:$uqType");
7748 // toggle whether all elements are present - ideally should validate against schema
7749 if (count($typeDef['elements']) != count($xvalue)){
7752 foreach ($typeDef['elements'] as $eName => $attrs) {
7753 if (!isset($xvalue[$eName])) {
7754 if (isset($attrs['default'])) {
7755 $xvalue[$eName] = $attrs['default'];
7756 $this->debug('use default value of ' . $xvalue[$eName] . ' for element ' . $eName);
7759 // if user took advantage of a minOccurs=0, then only serialize named parameters
7760 if (isset($optionals)
7761 && (!isset($xvalue[$eName]))
7762 && ( (!isset($attrs['nillable'])) || $attrs['nillable'] != 'true')
7764 if (isset($attrs['minOccurs']) && $attrs['minOccurs'] <> '0') {
7765 $this->debug("apparent error: no value provided for element $eName with minOccurs=" . $attrs['minOccurs']);
7768 $this->debug("no value provided for complexType element $eName and element is not nillable, so serialize nothing");
7771 if (isset($xvalue[$eName])) {
7772 $v = $xvalue[$eName];
7776 if (isset($attrs['form'])) {
7777 $unqualified = ($attrs['form'] == 'unqualified');
7779 $unqualified = false;
7781 if (isset($attrs['maxOccurs']) && ($attrs['maxOccurs'] == 'unbounded' || $attrs['maxOccurs'] > 1) && isset($v) && is_array($v) && $this->isArraySimpleOrStruct($v) == 'arraySimple') {
7783 foreach ($vv as $k => $v) {
7784 if (isset($attrs['type']) || isset($attrs['ref'])) {
7785 // serialize schema-defined type
7786 $xml .= $this->serializeType($eName, isset($attrs['type']) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified);
7788 // serialize generic type (can this ever really happen?)
7789 $this->debug("calling serialize_val() for $v, $eName, false, false, false, false, $use");
7790 $xml .= $this->serialize_val($v, $eName, false, false, false, false, $use);
7794 if (is_null($v) && isset($attrs['minOccurs']) && $attrs['minOccurs'] == '0') {
7796 } elseif (is_null($v) && isset($attrs['nillable']) && $attrs['nillable'] == 'true') {
7797 // TODO: serialize a nil correctly, but for now serialize schema-defined type
7798 $xml .= $this->serializeType($eName, isset($attrs['type']) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified);
7799 } elseif (isset($attrs['type']) || isset($attrs['ref'])) {
7800 // serialize schema-defined type
7801 $xml .= $this->serializeType($eName, isset($attrs['type']) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified);
7803 // serialize generic type (can this ever really happen?)
7804 $this->debug("calling serialize_val() for $v, $eName, false, false, false, false, $use");
7805 $xml .= $this->serialize_val($v, $eName, false, false, false, false, $use);
7811 $this->debug("no elements to serialize for XML Schema type $ns:$uqType");
7817 * adds an XML Schema complex type to the WSDL types
7819 * @param string $name
7820 * @param string $typeClass (complexType|simpleType|attribute)
7821 * @param string $phpType currently supported are array and struct (php assoc array)
7822 * @param string $compositor (all|sequence|choice)
7823 * @param string $restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
7824 * @param array $elements e.g. array ( name => array(name=>'',type=>'') )
7825 * @param array $attrs e.g. array(array('ref'=>'SOAP-ENC:arrayType','wsdl:arrayType'=>'xsd:string[]'))
7826 * @param string $arrayType as namespace:name (xsd:string)
7827 * @see nusoap_xmlschema
7830 function addComplexType($name,$typeClass='complexType',$phpType='array',$compositor='',$restrictionBase='',$elements=array(),$attrs=array(),$arrayType='') {
7831 if (count($elements) > 0) {
7832 $eElements = array();
7833 foreach($elements as $n => $e){
7834 // expand each element
7836 foreach ($e as $k => $v) {
7837 $k = strpos($k,':') ? $this->expandQname($k) : $k;
7838 $v = strpos($v,':') ? $this->expandQname($v) : $v;
7841 $eElements[$n] = $ee;
7843 $elements = $eElements;
7846 if (count($attrs) > 0) {
7847 foreach($attrs as $n => $a){
7848 // expand each attribute
7849 foreach ($a as $k => $v) {
7850 $k = strpos($k,':') ? $this->expandQname($k) : $k;
7851 $v = strpos($v,':') ? $this->expandQname($v) : $v;
7859 $restrictionBase = strpos($restrictionBase,':') ? $this->expandQname($restrictionBase) : $restrictionBase;
7860 $arrayType = strpos($arrayType,':') ? $this->expandQname($arrayType) : $arrayType;
7862 $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns'];
7863 $this->schemas[$typens][0]->addComplexType($name,$typeClass,$phpType,$compositor,$restrictionBase,$elements,$attrs,$arrayType);
7867 * adds an XML Schema simple type to the WSDL types
7869 * @param string $name
7870 * @param string $restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
7871 * @param string $typeClass (should always be simpleType)
7872 * @param string $phpType (should always be scalar)
7873 * @param array $enumeration array of values
7874 * @see nusoap_xmlschema
7877 function addSimpleType($name, $restrictionBase='', $typeClass='simpleType', $phpType='scalar', $enumeration=array()) {
7878 $restrictionBase = strpos($restrictionBase,':') ? $this->expandQname($restrictionBase) : $restrictionBase;
7880 $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns'];
7881 $this->schemas[$typens][0]->addSimpleType($name, $restrictionBase, $typeClass, $phpType, $enumeration);
7885 * adds an element to the WSDL types
7887 * @param array $attrs attributes that must include name and type
7888 * @see nusoap_xmlschema
7891 function addElement($attrs) {
7892 $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns'];
7893 $this->schemas[$typens][0]->addElement($attrs);
7897 * register an operation with the server
7899 * @param string $name operation (method) name
7900 * @param array $in assoc array of input values: key = param name, value = param type
7901 * @param array $out assoc array of output values: key = param name, value = param type
7902 * @param string $namespace optional The namespace for the operation
7903 * @param string $soapaction optional The soapaction for the operation
7904 * @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
7905 * @param string $use (encoded|literal) optional The use for the parameters (cannot mix right now)
7906 * @param string $documentation optional The description to include in the WSDL
7907 * @param string $encodingStyle optional (usually 'http://schemas.xmlsoap.org/soap/encoding/' for encoded)
7910 function addOperation($name, $in = false, $out = false, $namespace = false, $soapaction = false, $style = 'rpc', $use = 'encoded', $documentation = '', $encodingStyle = ''){
7911 if ($use == 'encoded' && $encodingStyle == '') {
7912 $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
7915 if ($style == 'document') {
7916 $elements = array();
7917 foreach ($in as $n => $t) {
7918 $elements[$n] = array('name' => $n, 'type' => $t, 'form' => 'unqualified');
7920 $this->addComplexType($name . 'RequestType', 'complexType', 'struct', 'all', '', $elements);
7921 $this->addElement(array('name' => $name, 'type' => $name . 'RequestType'));
7922 $in = array('parameters' => 'tns:' . $name . '^');
7924 $elements = array();
7925 foreach ($out as $n => $t) {
7926 $elements[$n] = array('name' => $n, 'type' => $t, 'form' => 'unqualified');
7928 $this->addComplexType($name . 'ResponseType', 'complexType', 'struct', 'all', '', $elements);
7929 $this->addElement(array('name' => $name . 'Response', 'type' => $name . 'ResponseType', 'form' => 'qualified'));
7930 $out = array('parameters' => 'tns:' . $name . 'Response' . '^');
7934 $this->bindings[ $this->serviceName . 'Binding' ]['operations'][$name] =
7937 'binding' => $this->serviceName . 'Binding',
7938 'endpoint' => $this->endpoint,
7939 'soapAction' => $soapaction,
7943 'namespace' => $namespace,
7944 'encodingStyle' => $encodingStyle,
7945 'message' => $name . 'Request',
7949 'namespace' => $namespace,
7950 'encodingStyle' => $encodingStyle,
7951 'message' => $name . 'Response',
7953 'namespace' => $namespace,
7954 'transport' => 'http://schemas.xmlsoap.org/soap/http',
7955 'documentation' => $documentation);
7960 foreach($in as $pName => $pType)
7962 if(strpos($pType,':')) {
7963 $pType = $this->getNamespaceFromPrefix($this->getPrefix($pType)).":".$this->getLocalPart($pType);
7965 $this->messages[$name.'Request'][$pName] = $pType;
7968 $this->messages[$name.'Request']= '0';
7972 foreach($out as $pName => $pType)
7974 if(strpos($pType,':')) {
7975 $pType = $this->getNamespaceFromPrefix($this->getPrefix($pType)).":".$this->getLocalPart($pType);
7977 $this->messages[$name.'Response'][$pName] = $pType;
7980 $this->messages[$name.'Response']= '0';
7989 Modification information for LGPL compliance
7991 r58622 - 2010-10-22 18:18:59 -0700 (Fri, 22 Oct 2010) - engsvnbuild - Author: lam <lam@198.18.142.201>
7994 r58361 - 2010-09-29 16:59:02 -0700 (Wed, 29 Sep 2010) - kjing - Author: Jenny Gonsalves <jenny@sugarcrm.com>
7995 Merging with maint_6_0_1 (svn merge -r 58250:58342)
7997 r57813 - 2010-08-19 10:34:44 -0700 (Thu, 19 Aug 2010) - kjing - Author: John Mertic <jmertic@sugarcrm.com>
7998 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.
8000 r57707 - 2010-08-10 12:26:13 -0700 (Tue, 10 Aug 2010) - kjing - Author: Stanislav Malyshev <smalyshev@gmail.com>
8001 fix SOAP calls with no parameters
8003 r56990 - 2010-06-16 13:05:36 -0700 (Wed, 16 Jun 2010) - kjing - snapshot "Mango" svn branch to a new one for GitHub sync
8005 r56989 - 2010-06-16 13:01:33 -0700 (Wed, 16 Jun 2010) - kjing - defunt "Mango" svn dev branch before github cutover
8007 r55980 - 2010-04-19 13:31:28 -0700 (Mon, 19 Apr 2010) - kjing - create Mango (6.1) based on windex
8009 r51719 - 2009-10-22 10:18:00 -0700 (Thu, 22 Oct 2009) - mitani - Converted to Build 3 tags and updated the build system
8011 r51634 - 2009-10-19 13:32:22 -0700 (Mon, 19 Oct 2009) - mitani - Windex is the branch for Sugar Sales 1.0 development
8013 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.
8015 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.
8017 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:
8018 - Changing all ereg function to either preg or simple string based ones
8019 - No more references to magic quotes.
8020 - Change all the session_unregister() functions to just unset() the correct session variable instead.
8022 r50375 - 2009-08-24 18:07:43 -0700 (Mon, 24 Aug 2009) - dwong - branch kobe2 from tokyo r50372
8024 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
8026 r45680 - 2009-03-30 14:34:35 -0700 (Mon, 30 Mar 2009) - Samir Gandhi - modifeid serializeSchema to generate WS-I compliant WSDL
8028 r42807 - 2008-12-29 11:16:59 -0800 (Mon, 29 Dec 2008) - dwong - Branch from trunk/sugarcrm r42806 to branches/tokyo/sugarcrm
8030 r42645 - 2008-12-18 13:41:08 -0800 (Thu, 18 Dec 2008) - awu - merging maint_5_2_0 rev41336:HEAD to trunk
8032 r41647 - 2008-11-11 17:44:30 -0800 (Tue, 11 Nov 2008) - majed - Fixes a few bugs
8034 r41596 - 2008-11-10 19:20:04 -0800 (Mon, 10 Nov 2008) - Samir Gandhi - modified to set $method in the code
8036 r41558 - 2008-11-10 14:35:34 -0800 (Mon, 10 Nov 2008) - majed - changes nusoap to allow for registering classes
8038 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.
8040 - data/SugarBean.php
8041 - include/domit/php_http_client_generic.php
8042 - include/domit/php_http_connector.php
8043 - include/domit/testing_domit.php
8044 - include/domit/xml_domit_getelementsbypath.php
8045 - include/domit/xml_domit_lite_parser.php
8046 - include/domit/xml_domit_nodemaps.php
8047 - include/domit/xml_domit_parser.php
8048 - include/domit/xml_domit_shared.php
8049 - include/generic/SugarWidgets/SugarWidgetField.php
8050 - include/generic/SugarWidgets/SugarWidgetReportField.php
8051 - include/ListView/ProcessView.php
8052 - include/nusoap/class.soapclient.php
8053 - include/nusoap/nusoap.php
8054 - include/nusoap/nusoapmime.php
8055 - include/Pear/HTML_Safe/Safe.php
8056 - include/Pear/XML_HTMLSax3/HTMLSax3.php
8057 - modules/Administration/RebuildWorkFlow.php
8058 - modules/Expressions/RelateSelector.php
8059 - modules/Reports/templates/templates_reports.php
8060 - modules/WorkFlow/Delete.php
8061 - modules/WorkFlow/Save.php
8062 - modules/WorkFlow/SaveSequence.php
8063 - modules/WorkFlow/WorkFlow.php
8064 - modules/WorkFlowActionShells/CreateStep1.php
8065 - modules/WorkFlowActionShells/CreateStep2.php
8066 - modules/WorkFlowActionShells/Save.php
8067 - modules/WorkFlowActionShells/WorkFlowActionShell.php
8068 - modules/WorkFlowAlerts/Save.php
8069 - modules/WorkFlowAlerts/WorkFlowAlert.php
8070 - modules/WorkFlowAlertShells/DetailView.php
8071 - modules/WorkFlowAlertShells/WorkFlowAlertShell.php
8072 - modules/WorkFlowTriggerShells/CreateStep1.php
8073 - modules/WorkFlowTriggerShells/CreateStepFilter.php
8074 - modules/WorkFlowTriggerShells/SaveFilter.php
8075 - modules/WorkFlowTriggerShells/WorkFlowTriggerShell.php
8076 - soap/SoapHelperFunctions.php
8077 - test/modules/DynamicFields/DynamicFields_Bug24095_test.php
8078 - test/simpletest/browser.php
8079 - test/simpletest/default_reporter.php
8080 - test/simpletest/detached.php
8081 - test/simpletest/eclipse.php
8082 - test/simpletest/expectation.php
8083 - test/simpletest/extensions/pear_test_case.php
8084 - test/simpletest/form.php
8085 - test/simpletest/http.php
8086 - test/simpletest/mock_objects.php
8087 - test/simpletest/page.php
8088 - test/simpletest/parser.php
8089 - test/simpletest/remote.php
8090 - test/simpletest/shell_tester.php
8091 - test/simpletest/simple_test.php
8092 - test/simpletest/simpletest.php
8093 - test/simpletest/test/acceptance_test.php
8094 - test/simpletest/test/adapter_test.php
8095 - test/simpletest/test/authentication_test.php
8096 - test/simpletest/test/browser_test.php
8097 - test/simpletest/test/collector_test.php
8098 - test/simpletest/test/compatibility_test.php
8099 - test/simpletest/test/detached_test.php
8100 - test/simpletest/test/eclipse_test.php
8101 - test/simpletest/test/encoding_test.php
8102 - test/simpletest/test/errors_test.php
8103 - test/simpletest/test/expectation_test.php
8104 - test/simpletest/test/form_test.php
8105 - test/simpletest/test/frames_test.php
8106 - test/simpletest/test/http_test.php
8107 - test/simpletest/test/live_test.php
8108 - test/simpletest/test/mock_objects_test.php
8109 - test/simpletest/test/page_test.php
8110 - test/simpletest/test/parse_error_test.php
8111 - test/simpletest/test/parser_test.php
8112 - test/simpletest/test/remote_test.php
8113 - test/simpletest/test/shell_test.php
8114 - test/simpletest/test/shell_tester_test.php
8115 - test/simpletest/test/simpletest_test.php
8116 - test/simpletest/test/site/page_request.php
8117 - test/simpletest/test/tag_test.php
8118 - test/simpletest/test/unit_tester_test.php
8119 - test/simpletest/test/user_agent_test.php
8120 - test/simpletest/test/visual_test.php
8121 - test/simpletest/test/xml_test.php
8122 - test/simpletest/test_case.php
8123 - test/simpletest/ui/array_reporter/test.php
8124 - test/simpletest/ui/recorder/test.php
8125 - test/simpletest/unit_tester.php
8126 - test/simpletest/url.php
8127 - test/simpletest/user_agent.php
8128 - test/simpletest/web_tester.php
8129 - test/spikephpcoverage/src/PEAR.php
8130 - test/spikephpcoverage/src/util/Utility.php
8131 - test/spikephpcoverage/src/XML/Parser.php
8132 - test/spikephpcoverage/src/XML/Parser/Simple.php
8133 - test/test_utilities/SugarTest_SimpleBrowser.php
8135 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.
8137 r38300 - 2008-07-25 13:33:43 -0700 (Fri, 25 Jul 2008) - Samir Gandhi - put the debug in parseresponse function
8139 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
8141 r36824 - 2008-06-18 09:26:11 -0700 (Wed, 18 Jun 2008) - roger - bug: 21832
8143 r26422 - 2007-09-05 17:29:12 -0700 (Wed, 05 Sep 2007) - majed - migrate from beta 1 to trunk
8145 r15787 - 2006-08-10 10:14:41 -0700 (Thu, 10 Aug 2006) - roger - RRS: bug 7961
8147 r14701 - 2006-07-17 13:37:26 -0700 (Mon, 17 Jul 2006) - roger - RRS: bug 5801
8149 r13782 - 2006-06-06 10:58:55 -0700 (Tue, 06 Jun 2006) - majed - changes entry point code
8151 r11466 - 2006-02-01 15:49:47 -0800 (Wed, 01 Feb 2006) - jacob - Adding extra !empty check to get around a PHP warning.
8153 r11115 - 2006-01-17 14:54:45 -0800 (Tue, 17 Jan 2006) - majed - add entry point validation
8155 r10585 - 2005-12-13 14:42:26 -0800 (Tue, 13 Dec 2005) - majed - adds new license mechanisim
8157 r10170 - 2005-12-05 18:37:46 -0800 (Mon, 05 Dec 2005) - majed - fixes various issues
8159 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.
8161 r8991 - 2005-11-03 19:07:25 -0800 (Thu, 03 Nov 2005) - majed - fixes nusoap issue
8163 r8846 - 2005-10-31 11:01:12 -0800 (Mon, 31 Oct 2005) - majed - new version of nusoap
8165 r7905 - 2005-09-21 19:12:57 -0700 (Wed, 21 Sep 2005) - majed - restores old nusoap pre & with a few fixes
8167 r7861 - 2005-09-20 15:40:25 -0700 (Tue, 20 Sep 2005) - majed - & fix for 3.5.1
8169 r7452 - 2005-08-17 11:32:34 -0700 (Wed, 17 Aug 2005) - majed - changes soap to nusoap
8171 r5820 - 2005-06-21 14:22:24 -0700 (Tue, 21 Jun 2005) - majed - fixes issues with nusoap and with custom fields
8173 r5462 - 2005-05-25 13:50:11 -0700 (Wed, 25 May 2005) - majed - upgraded nusoap to .6.9
8175 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
8177 r573 - 2004-09-04 13:03:32 -0700 (Sat, 04 Sep 2004) - sugarclint - undoing copyrights added in inadvertantly. --clint
8179 r546 - 2004-09-03 11:49:38 -0700 (Fri, 03 Sep 2004) - sugarmsi - removed echo count
8181 r354 - 2004-08-02 23:00:37 -0700 (Mon, 02 Aug 2004) - sugarjacob - Adding Soap
8192 * nusoap_parser class parses SOAP XML messages into native PHP values
8194 * @author Dietrich Ayala <dietrich@ganx4.com>
8195 * @author Scott Nichol <snichol@users.sourceforge.net>
8199 class nusoap_parser extends nusoap_base {
8202 var $xml_encoding = '';
8204 var $root_struct = '';
8205 var $root_struct_name = '';
8206 var $root_struct_namespace = '';
8207 var $root_header = '';
8208 var $document = ''; // incoming SOAP body (text)
8209 // determines where in the message we are (envelope,header,body,method)
8213 var $default_namespace = '';
8214 var $namespaces = array();
8215 var $message = array();
8218 var $fault_code = '';
8219 var $fault_str = '';
8220 var $fault_detail = '';
8221 var $depth_array = array();
8222 var $debug_flag = true;
8223 var $soapresponse = NULL; // parsed SOAP Body
8224 var $soapheader = NULL; // parsed SOAP Header
8225 var $responseHeaders = ''; // incoming SOAP headers (text)
8226 var $body_position = 0;
8227 // for multiref parsing:
8228 // array of id => pos
8230 // array of id => hrefs => pos
8231 var $multirefs = array();
8232 // toggle for auto-decoding element content
8233 var $decode_utf8 = false;
8236 * constructor that actually does the parsing
8238 * @param string $xml SOAP message
8239 * @param string $encoding character encoding scheme of message
8240 * @param string $method method for which XML is parsed (unused?)
8241 * @param string $decode_utf8 whether to decode UTF-8 to ISO-8859-1
8244 function nusoap_parser($xml,$encoding='UTF-8',$method='',$decode_utf8=true){
8245 parent::nusoap_base();
8247 $this->xml_encoding = $encoding;
8248 $this->method = $method;
8249 $this->decode_utf8 = $decode_utf8;
8251 // Check whether content has been read.
8253 // Check XML encoding
8254 $pos_xml = strpos($xml, '<?xml');
8255 if ($pos_xml !== FALSE) {
8256 $xml_decl = substr($xml, $pos_xml, strpos($xml, '?>', $pos_xml + 2) - $pos_xml + 1);
8257 if (preg_match("/encoding=[\"']([^\"']*)[\"']/", $xml_decl, $res)) {
8258 $xml_encoding = $res[1];
8259 if (strtoupper($xml_encoding) != $encoding) {
8260 $err = "Charset from HTTP Content-Type '" . $encoding . "' does not match encoding from XML declaration '" . $xml_encoding . "'";
8262 if ($encoding != 'ISO-8859-1' || strtoupper($xml_encoding) != 'UTF-8') {
8263 $this->setError($err);
8266 // when HTTP says ISO-8859-1 (the default) and XML says UTF-8 (the typical), assume the other endpoint is just sloppy and proceed
8268 $this->debug('Charset from HTTP Content-Type matches encoding from XML declaration');
8271 $this->debug('No encoding specified in XML declaration');
8274 $this->debug('No XML declaration');
8276 $this->debug('Entering nusoap_parser(), length='.strlen($xml).', encoding='.$encoding);
8277 // Create an XML parser - why not xml_parser_create_ns?
8278 $this->parser = xml_parser_create($this->xml_encoding);
8279 // Set the options for parsing the XML data.
8280 //xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
8281 xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
8282 xml_parser_set_option($this->parser, XML_OPTION_TARGET_ENCODING, $this->xml_encoding);
8283 // Set the object for the parser.
8284 xml_set_object($this->parser, $this);
8285 // Set the element handlers for the parser.
8286 xml_set_element_handler($this->parser, 'start_element','end_element');
8287 xml_set_character_data_handler($this->parser,'character_data');
8289 // Parse the XML file.
8290 if(!xml_parse($this->parser,$xml,true)){
8291 // Display an error message.
8292 $err = sprintf('XML error parsing SOAP payload on line %d: %s',
8293 xml_get_current_line_number($this->parser),
8294 xml_error_string(xml_get_error_code($this->parser)));
8296 $this->debug("XML payload:\n" . $xml);
8297 $this->setError($err);
8299 $this->debug('in nusoap_parser ctor, message:');
8300 $this->appendDebug($this->varDump($this->message));
8301 $this->debug('parsed successfully, found root struct: '.$this->root_struct.' of name '.$this->root_struct_name);
8303 $this->soapresponse = $this->message[$this->root_struct]['result'];
8305 if($this->root_header != '' && isset($this->message[$this->root_header]['result'])){
8306 $this->soapheader = $this->message[$this->root_header]['result'];
8308 // resolve hrefs/ids
8309 if(sizeof($this->multirefs) > 0){
8310 foreach($this->multirefs as $id => $hrefs){
8311 $this->debug('resolving multirefs for id: '.$id);
8312 $idVal = $this->buildVal($this->ids[$id]);
8313 if (is_array($idVal) && isset($idVal['!id'])) {
8314 unset($idVal['!id']);
8316 foreach($hrefs as $refPos => $ref){
8317 $this->debug('resolving href at pos '.$refPos);
8318 $this->multirefs[$id][$refPos] = $idVal;
8323 xml_parser_free($this->parser);
8325 $this->debug('xml was empty, didn\'t parse!');
8326 $this->setError('xml was empty, didn\'t parse!');
8331 * start-element handler
8333 * @param resource $parser XML parser object
8334 * @param string $name element name
8335 * @param array $attrs associative array of attributes
8338 function start_element($parser, $name, $attrs) {
8339 // position in a total number of elements, starting from 0
8340 // update class level pos
8341 $pos = $this->position++;
8343 $this->message[$pos] = array('pos' => $pos,'children'=>'','cdata'=>'');
8344 // depth = how many levels removed from root?
8345 // set mine as current global depth and increment global depth value
8346 $this->message[$pos]['depth'] = $this->depth++;
8348 // else add self as child to whoever the current parent is
8350 $this->message[$this->parent]['children'] .= '|'.$pos;
8353 $this->message[$pos]['parent'] = $this->parent;
8354 // set self as current parent
8355 $this->parent = $pos;
8356 // set self as current value for this depth
8357 $this->depth_array[$this->depth] = $pos;
8358 // get element prefix
8359 if(strpos($name,':')){
8361 $prefix = substr($name,0,strpos($name,':'));
8362 // get unqualified name
8363 $name = substr(strstr($name,':'),1);
8366 if ($name == 'Envelope' && $this->status == '') {
8367 $this->status = 'envelope';
8368 } elseif ($name == 'Header' && $this->status == 'envelope') {
8369 $this->root_header = $pos;
8370 $this->status = 'header';
8371 } elseif ($name == 'Body' && $this->status == 'envelope'){
8372 $this->status = 'body';
8373 $this->body_position = $pos;
8375 } elseif($this->status == 'body' && $pos == ($this->body_position+1)) {
8376 $this->status = 'method';
8377 $this->root_struct_name = $name;
8378 $this->root_struct = $pos;
8379 $this->message[$pos]['type'] = 'struct';
8380 $this->debug("found root struct $this->root_struct_name, pos $this->root_struct");
8383 $this->message[$pos]['status'] = $this->status;
8385 $this->message[$pos]['name'] = htmlspecialchars($name);
8387 $this->message[$pos]['attrs'] = $attrs;
8389 // loop through atts, logging ns and type declarations
8391 foreach($attrs as $key => $value){
8392 $key_prefix = $this->getPrefix($key);
8393 $key_localpart = $this->getLocalPart($key);
8394 // if ns declarations, add to class level array of valid namespaces
8395 if($key_prefix == 'xmlns'){
8396 if(preg_match('/^http:\/\/www.w3.org\/[0-9]{4}\/XMLSchema$/',$value)){
8397 $this->XMLSchemaVersion = $value;
8398 $this->namespaces['xsd'] = $this->XMLSchemaVersion;
8399 $this->namespaces['xsi'] = $this->XMLSchemaVersion.'-instance';
8401 $this->namespaces[$key_localpart] = $value;
8402 // set method namespace
8403 if($name == $this->root_struct_name){
8404 $this->methodNamespace = $value;
8406 // if it's a type declaration, set type
8407 } elseif($key_localpart == 'type'){
8408 if (isset($this->message[$pos]['type']) && $this->message[$pos]['type'] == 'array') {
8409 // do nothing: already processed arrayType
8411 $value_prefix = $this->getPrefix($value);
8412 $value_localpart = $this->getLocalPart($value);
8413 $this->message[$pos]['type'] = $value_localpart;
8414 $this->message[$pos]['typePrefix'] = $value_prefix;
8415 if(isset($this->namespaces[$value_prefix])){
8416 $this->message[$pos]['type_namespace'] = $this->namespaces[$value_prefix];
8417 } else if(isset($attrs['xmlns:'.$value_prefix])) {
8418 $this->message[$pos]['type_namespace'] = $attrs['xmlns:'.$value_prefix];
8420 // should do something here with the namespace of specified type?
8422 } elseif($key_localpart == 'arrayType'){
8423 $this->message[$pos]['type'] = 'array';
8424 /* do arrayType ereg here
8425 [1] arrayTypeValue ::= atype asize
8426 [2] atype ::= QName rank*
8427 [3] rank ::= '[' (',')* ']'
8428 [4] asize ::= '[' length~ ']'
8429 [5] length ::= nextDimension* Digit+
8430 [6] nextDimension ::= Digit+ ','
8432 $expr = '/([A-Za-z0-9_]+):([A-Za-z]+[A-Za-z0-9_]+)\[([0-9]+),?([0-9]*)\]/';
8433 if(preg_match($expr,$value,$regs)){
8434 $this->message[$pos]['typePrefix'] = $regs[1];
8435 $this->message[$pos]['arrayTypePrefix'] = $regs[1];
8436 if (isset($this->namespaces[$regs[1]])) {
8437 $this->message[$pos]['arrayTypeNamespace'] = $this->namespaces[$regs[1]];
8438 } else if (isset($attrs['xmlns:'.$regs[1]])) {
8439 $this->message[$pos]['arrayTypeNamespace'] = $attrs['xmlns:'.$regs[1]];
8441 $this->message[$pos]['arrayType'] = $regs[2];
8442 $this->message[$pos]['arraySize'] = $regs[3];
8443 $this->message[$pos]['arrayCols'] = $regs[4];
8445 // specifies nil value (or not)
8446 } elseif ($key_localpart == 'nil'){
8447 $this->message[$pos]['nil'] = ($value == 'true' || $value == '1');
8448 // some other attribute
8449 } elseif ($key != 'href' && $key != 'xmlns' && $key_localpart != 'encodingStyle' && $key_localpart != 'root') {
8450 $this->message[$pos]['xattrs']['!' . $key] = $value;
8453 if ($key == 'xmlns') {
8454 $this->default_namespace = $value;
8458 $this->ids[$value] = $pos;
8461 if($key_localpart == 'root' && $value == 1){
8462 $this->status = 'method';
8463 $this->root_struct_name = $name;
8464 $this->root_struct = $pos;
8465 $this->debug("found root struct $this->root_struct_name, pos $pos");
8468 $attstr .= " $key=\"$value\"";
8470 // get namespace - must be done after namespace atts are processed
8472 $this->message[$pos]['namespace'] = $this->namespaces[$prefix];
8473 $this->default_namespace = $this->namespaces[$prefix];
8475 $this->message[$pos]['namespace'] = $this->default_namespace;
8477 if($this->status == 'header'){
8478 if ($this->root_header != $pos) {
8479 $this->responseHeaders .= "<" . (isset($prefix) ? $prefix . ':' : '') . "$name$attstr>";
8481 } elseif($this->root_struct_name != ''){
8482 $this->document .= "<" . (isset($prefix) ? $prefix . ':' : '') . "$name$attstr>";
8487 * end-element handler
8489 * @param resource $parser XML parser object
8490 * @param string $name element name
8493 function end_element($parser, $name) {
8494 // position of current element is equal to the last value left in depth_array for my depth
8495 $pos = $this->depth_array[$this->depth--];
8497 // get element prefix
8498 if(strpos($name,':')){
8500 $prefix = substr($name,0,strpos($name,':'));
8501 // get unqualified name
8502 $name = substr(strstr($name,':'),1);
8505 // build to native type
8506 if(isset($this->body_position) && $pos > $this->body_position){
8507 // deal w/ multirefs
8508 if(isset($this->message[$pos]['attrs']['href'])){
8510 $id = substr($this->message[$pos]['attrs']['href'],1);
8511 // add placeholder to href array
8512 $this->multirefs[$id][$pos] = 'placeholder';
8513 // add set a reference to it as the result value
8514 $this->message[$pos]['result'] =& $this->multirefs[$id][$pos];
8515 // build complexType values
8516 } elseif($this->message[$pos]['children'] != ''){
8517 // if result has already been generated (struct/array)
8518 if(!isset($this->message[$pos]['result'])){
8519 $this->message[$pos]['result'] = $this->buildVal($pos);
8521 // build complexType values of attributes and possibly simpleContent
8522 } elseif (isset($this->message[$pos]['xattrs'])) {
8523 if (isset($this->message[$pos]['nil']) && $this->message[$pos]['nil']) {
8524 $this->message[$pos]['xattrs']['!'] = null;
8525 } elseif (isset($this->message[$pos]['cdata']) && trim($this->message[$pos]['cdata']) != '') {
8526 if (isset($this->message[$pos]['type'])) {
8527 $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'] : '');
8529 $parent = $this->message[$pos]['parent'];
8530 if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
8531 $this->message[$pos]['xattrs']['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
8533 $this->message[$pos]['xattrs']['!'] = $this->message[$pos]['cdata'];
8537 $this->message[$pos]['result'] = $this->message[$pos]['xattrs'];
8538 // set value of simpleType (or nil complexType)
8540 //$this->debug('adding data for scalar value '.$this->message[$pos]['name'].' of value '.$this->message[$pos]['cdata']);
8541 if (isset($this->message[$pos]['nil']) && $this->message[$pos]['nil']) {
8542 $this->message[$pos]['xattrs']['!'] = null;
8543 } elseif (isset($this->message[$pos]['type'])) {
8544 $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'] : '');
8546 $parent = $this->message[$pos]['parent'];
8547 if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
8548 $this->message[$pos]['result'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
8550 $this->message[$pos]['result'] = $this->message[$pos]['cdata'];
8554 /* add value to parent's result, if parent is struct/array
8555 $parent = $this->message[$pos]['parent'];
8556 if($this->message[$parent]['type'] != 'map'){
8557 if(strtolower($this->message[$parent]['type']) == 'array'){
8558 $this->message[$parent]['result'][] = $this->message[$pos]['result'];
8560 $this->message[$parent]['result'][$this->message[$pos]['name']] = $this->message[$pos]['result'];
8568 if($this->status == 'header'){
8569 if ($this->root_header != $pos) {
8570 $this->responseHeaders .= "</" . (isset($prefix) ? $prefix . ':' : '') . "$name>";
8572 } elseif($pos >= $this->root_struct){
8573 $this->document .= "</" . (isset($prefix) ? $prefix . ':' : '') . "$name>";
8576 if ($pos == $this->root_struct){
8577 $this->status = 'body';
8578 $this->root_struct_namespace = $this->message[$pos]['namespace'];
8579 } elseif ($pos == $this->root_header) {
8580 $this->status = 'envelope';
8581 } elseif ($name == 'Body' && $this->status == 'body') {
8582 $this->status = 'envelope';
8583 } elseif ($name == 'Header' && $this->status == 'header') { // will never happen
8584 $this->status = 'envelope';
8585 } elseif ($name == 'Envelope' && $this->status == 'envelope') {
8588 // set parent back to my parent
8589 $this->parent = $this->message[$pos]['parent'];
8593 * element content handler
8595 * @param resource $parser XML parser object
8596 * @param string $data element content
8599 function character_data($parser, $data){
8600 $pos = $this->depth_array[$this->depth];
8601 if ($this->xml_encoding=='UTF-8'){
8602 // TODO: add an option to disable this for folks who want
8603 // raw UTF-8 that, e.g., might not map to iso-8859-1
8604 // TODO: this can also be handled with xml_parser_set_option($this->parser, XML_OPTION_TARGET_ENCODING, "ISO-8859-1");
8605 if($this->decode_utf8){
8606 $data = utf8_decode($data);
8609 $this->message[$pos]['cdata'] .= $data;
8611 if($this->status == 'header'){
8612 $this->responseHeaders .= $data;
8614 $this->document .= $data;
8619 * get the parsed message (SOAP Body)
8623 * @deprecated use get_soapbody instead
8625 function get_response(){
8626 return $this->soapresponse;
8630 * get the parsed SOAP Body (NULL if there was none)
8635 function get_soapbody(){
8636 return $this->soapresponse;
8640 * get the parsed SOAP Header (NULL if there was none)
8645 function get_soapheader(){
8646 return $this->soapheader;
8650 * get the unparsed SOAP Header
8652 * @return string XML or empty if no Header
8655 function getHeaders(){
8656 return $this->responseHeaders;
8660 * decodes simple types into PHP variables
8662 * @param string $value value to decode
8663 * @param string $type XML type to decode
8664 * @param string $typens XML type namespace to decode
8665 * @return mixed PHP value
8668 function decodeSimple($value, $type, $typens) {
8669 // TODO: use the namespace!
8670 if ((!isset($type)) || $type == 'string' || $type == 'long' || $type == 'unsignedLong') {
8671 return (string) $value;
8673 if ($type == 'int' || $type == 'integer' || $type == 'short' || $type == 'byte') {
8674 return (int) $value;
8676 if ($type == 'float' || $type == 'double' || $type == 'decimal') {
8677 return (double) $value;
8679 if ($type == 'boolean') {
8680 if (strtolower($value) == 'false' || strtolower($value) == 'f') {
8683 return (boolean) $value;
8685 if ($type == 'base64' || $type == 'base64Binary') {
8686 $this->debug('Decode base64 value');
8687 return base64_decode($value);
8689 // obscure numeric types
8690 if ($type == 'nonPositiveInteger' || $type == 'negativeInteger'
8691 || $type == 'nonNegativeInteger' || $type == 'positiveInteger'
8692 || $type == 'unsignedInt'
8693 || $type == 'unsignedShort' || $type == 'unsignedByte') {
8694 return (int) $value;
8696 // bogus: parser treats array with no elements as a simple type
8697 if ($type == 'array') {
8701 return (string) $value;
8705 * builds response structures for compound values (arrays/structs)
8708 * @param integer $pos position in node tree
8709 * @return mixed PHP value
8712 function buildVal($pos){
8713 if(!isset($this->message[$pos]['type'])){
8714 $this->message[$pos]['type'] = '';
8716 $this->debug('in buildVal() for '.$this->message[$pos]['name']."(pos $pos) of type ".$this->message[$pos]['type']);
8717 // if there are children...
8718 if($this->message[$pos]['children'] != ''){
8719 $this->debug('in buildVal, there are children');
8720 $children = explode('|',$this->message[$pos]['children']);
8721 array_shift($children); // knock off empty
8723 if(isset($this->message[$pos]['arrayCols']) && $this->message[$pos]['arrayCols'] != ''){
8726 foreach($children as $child_pos){
8727 $this->debug("in buildVal, got an MD array element: $r, $c");
8728 $params[$r][] = $this->message[$child_pos]['result'];
8730 if($c == $this->message[$pos]['arrayCols']){
8736 } elseif($this->message[$pos]['type'] == 'array' || $this->message[$pos]['type'] == 'Array'){
8737 $this->debug('in buildVal, adding array '.$this->message[$pos]['name']);
8738 foreach($children as $child_pos){
8739 $params[] = &$this->message[$child_pos]['result'];
8741 // apache Map type: java hashtable
8742 } elseif($this->message[$pos]['type'] == 'Map' && $this->message[$pos]['type_namespace'] == 'http://xml.apache.org/xml-soap'){
8743 $this->debug('in buildVal, Java Map '.$this->message[$pos]['name']);
8744 foreach($children as $child_pos){
8745 $kv = explode("|",$this->message[$child_pos]['children']);
8746 $params[$this->message[$kv[1]]['result']] = &$this->message[$kv[2]]['result'];
8748 // generic compound type
8749 //} elseif($this->message[$pos]['type'] == 'SOAPStruct' || $this->message[$pos]['type'] == 'struct') {
8751 // Apache Vector type: treat as an array
8752 $this->debug('in buildVal, adding Java Vector or generic compound type '.$this->message[$pos]['name']);
8753 if ($this->message[$pos]['type'] == 'Vector' && $this->message[$pos]['type_namespace'] == 'http://xml.apache.org/xml-soap') {
8759 foreach($children as $child_pos){
8761 $params[] = &$this->message[$child_pos]['result'];
8763 if (isset($params[$this->message[$child_pos]['name']])) {
8764 // de-serialize repeated element name into an array
8765 if ((!is_array($params[$this->message[$child_pos]['name']])) || (!isset($params[$this->message[$child_pos]['name']][0]))) {
8766 $params[$this->message[$child_pos]['name']] = array($params[$this->message[$child_pos]['name']]);
8768 $params[$this->message[$child_pos]['name']][] = &$this->message[$child_pos]['result'];
8770 $params[$this->message[$child_pos]['name']] = &$this->message[$child_pos]['result'];
8775 if (isset($this->message[$pos]['xattrs'])) {
8776 $this->debug('in buildVal, handling attributes');
8777 foreach ($this->message[$pos]['xattrs'] as $n => $v) {
8781 // handle simpleContent
8782 if (isset($this->message[$pos]['cdata']) && trim($this->message[$pos]['cdata']) != '') {
8783 $this->debug('in buildVal, handling simpleContent');
8784 if (isset($this->message[$pos]['type'])) {
8785 $params['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$pos]['type'], isset($this->message[$pos]['type_namespace']) ? $this->message[$pos]['type_namespace'] : '');
8787 $parent = $this->message[$pos]['parent'];
8788 if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
8789 $params['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
8791 $params['!'] = $this->message[$pos]['cdata'];
8795 $ret = is_array($params) ? $params : array();
8796 $this->debug('in buildVal, return:');
8797 $this->appendDebug($this->varDump($ret));
8800 $this->debug('in buildVal, no children, building scalar');
8801 $cdata = isset($this->message[$pos]['cdata']) ? $this->message[$pos]['cdata'] : '';
8802 if (isset($this->message[$pos]['type'])) {
8803 $ret = $this->decodeSimple($cdata, $this->message[$pos]['type'], isset($this->message[$pos]['type_namespace']) ? $this->message[$pos]['type_namespace'] : '');
8804 $this->debug("in buildVal, return: $ret");
8807 $parent = $this->message[$pos]['parent'];
8808 if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
8809 $ret = $this->decodeSimple($cdata, $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
8810 $this->debug("in buildVal, return: $ret");
8813 $ret = $this->message[$pos]['cdata'];
8814 $this->debug("in buildVal, return: $ret");
8821 * Backward compatibility
8823 class soap_parser extends nusoap_parser {
8830 Modification information for LGPL compliance
8832 r58622 - 2010-10-22 18:18:59 -0700 (Fri, 22 Oct 2010) - engsvnbuild - Author: lam <lam@198.18.142.201>
8835 r58361 - 2010-09-29 16:59:02 -0700 (Wed, 29 Sep 2010) - kjing - Author: Jenny Gonsalves <jenny@sugarcrm.com>
8836 Merging with maint_6_0_1 (svn merge -r 58250:58342)
8838 r57813 - 2010-08-19 10:34:44 -0700 (Thu, 19 Aug 2010) - kjing - Author: John Mertic <jmertic@sugarcrm.com>
8839 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.
8841 r57707 - 2010-08-10 12:26:13 -0700 (Tue, 10 Aug 2010) - kjing - Author: Stanislav Malyshev <smalyshev@gmail.com>
8842 fix SOAP calls with no parameters
8844 r56990 - 2010-06-16 13:05:36 -0700 (Wed, 16 Jun 2010) - kjing - snapshot "Mango" svn branch to a new one for GitHub sync
8846 r56989 - 2010-06-16 13:01:33 -0700 (Wed, 16 Jun 2010) - kjing - defunt "Mango" svn dev branch before github cutover
8848 r55980 - 2010-04-19 13:31:28 -0700 (Mon, 19 Apr 2010) - kjing - create Mango (6.1) based on windex
8850 r51719 - 2009-10-22 10:18:00 -0700 (Thu, 22 Oct 2009) - mitani - Converted to Build 3 tags and updated the build system
8852 r51634 - 2009-10-19 13:32:22 -0700 (Mon, 19 Oct 2009) - mitani - Windex is the branch for Sugar Sales 1.0 development
8854 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.
8856 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.
8858 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:
8859 - Changing all ereg function to either preg or simple string based ones
8860 - No more references to magic quotes.
8861 - Change all the session_unregister() functions to just unset() the correct session variable instead.
8863 r50375 - 2009-08-24 18:07:43 -0700 (Mon, 24 Aug 2009) - dwong - branch kobe2 from tokyo r50372
8865 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
8867 r45680 - 2009-03-30 14:34:35 -0700 (Mon, 30 Mar 2009) - Samir Gandhi - modifeid serializeSchema to generate WS-I compliant WSDL
8869 r42807 - 2008-12-29 11:16:59 -0800 (Mon, 29 Dec 2008) - dwong - Branch from trunk/sugarcrm r42806 to branches/tokyo/sugarcrm
8871 r42645 - 2008-12-18 13:41:08 -0800 (Thu, 18 Dec 2008) - awu - merging maint_5_2_0 rev41336:HEAD to trunk
8873 r41647 - 2008-11-11 17:44:30 -0800 (Tue, 11 Nov 2008) - majed - Fixes a few bugs
8875 r41596 - 2008-11-10 19:20:04 -0800 (Mon, 10 Nov 2008) - Samir Gandhi - modified to set $method in the code
8877 r41558 - 2008-11-10 14:35:34 -0800 (Mon, 10 Nov 2008) - majed - changes nusoap to allow for registering classes
8879 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.
8881 - data/SugarBean.php
8882 - include/domit/php_http_client_generic.php
8883 - include/domit/php_http_connector.php
8884 - include/domit/testing_domit.php
8885 - include/domit/xml_domit_getelementsbypath.php
8886 - include/domit/xml_domit_lite_parser.php
8887 - include/domit/xml_domit_nodemaps.php
8888 - include/domit/xml_domit_parser.php
8889 - include/domit/xml_domit_shared.php
8890 - include/generic/SugarWidgets/SugarWidgetField.php
8891 - include/generic/SugarWidgets/SugarWidgetReportField.php
8892 - include/ListView/ProcessView.php
8893 - include/nusoap/class.soapclient.php
8894 - include/nusoap/nusoap.php
8895 - include/nusoap/nusoapmime.php
8896 - include/Pear/HTML_Safe/Safe.php
8897 - include/Pear/XML_HTMLSax3/HTMLSax3.php
8898 - modules/Administration/RebuildWorkFlow.php
8899 - modules/Expressions/RelateSelector.php
8900 - modules/Reports/templates/templates_reports.php
8901 - modules/WorkFlow/Delete.php
8902 - modules/WorkFlow/Save.php
8903 - modules/WorkFlow/SaveSequence.php
8904 - modules/WorkFlow/WorkFlow.php
8905 - modules/WorkFlowActionShells/CreateStep1.php
8906 - modules/WorkFlowActionShells/CreateStep2.php
8907 - modules/WorkFlowActionShells/Save.php
8908 - modules/WorkFlowActionShells/WorkFlowActionShell.php
8909 - modules/WorkFlowAlerts/Save.php
8910 - modules/WorkFlowAlerts/WorkFlowAlert.php
8911 - modules/WorkFlowAlertShells/DetailView.php
8912 - modules/WorkFlowAlertShells/WorkFlowAlertShell.php
8913 - modules/WorkFlowTriggerShells/CreateStep1.php
8914 - modules/WorkFlowTriggerShells/CreateStepFilter.php
8915 - modules/WorkFlowTriggerShells/SaveFilter.php
8916 - modules/WorkFlowTriggerShells/WorkFlowTriggerShell.php
8917 - soap/SoapHelperFunctions.php
8918 - test/modules/DynamicFields/DynamicFields_Bug24095_test.php
8919 - test/simpletest/browser.php
8920 - test/simpletest/default_reporter.php
8921 - test/simpletest/detached.php
8922 - test/simpletest/eclipse.php
8923 - test/simpletest/expectation.php
8924 - test/simpletest/extensions/pear_test_case.php
8925 - test/simpletest/form.php
8926 - test/simpletest/http.php
8927 - test/simpletest/mock_objects.php
8928 - test/simpletest/page.php
8929 - test/simpletest/parser.php
8930 - test/simpletest/remote.php
8931 - test/simpletest/shell_tester.php
8932 - test/simpletest/simple_test.php
8933 - test/simpletest/simpletest.php
8934 - test/simpletest/test/acceptance_test.php
8935 - test/simpletest/test/adapter_test.php
8936 - test/simpletest/test/authentication_test.php
8937 - test/simpletest/test/browser_test.php
8938 - test/simpletest/test/collector_test.php
8939 - test/simpletest/test/compatibility_test.php
8940 - test/simpletest/test/detached_test.php
8941 - test/simpletest/test/eclipse_test.php
8942 - test/simpletest/test/encoding_test.php
8943 - test/simpletest/test/errors_test.php
8944 - test/simpletest/test/expectation_test.php
8945 - test/simpletest/test/form_test.php
8946 - test/simpletest/test/frames_test.php
8947 - test/simpletest/test/http_test.php
8948 - test/simpletest/test/live_test.php
8949 - test/simpletest/test/mock_objects_test.php
8950 - test/simpletest/test/page_test.php
8951 - test/simpletest/test/parse_error_test.php
8952 - test/simpletest/test/parser_test.php
8953 - test/simpletest/test/remote_test.php
8954 - test/simpletest/test/shell_test.php
8955 - test/simpletest/test/shell_tester_test.php
8956 - test/simpletest/test/simpletest_test.php
8957 - test/simpletest/test/site/page_request.php
8958 - test/simpletest/test/tag_test.php
8959 - test/simpletest/test/unit_tester_test.php
8960 - test/simpletest/test/user_agent_test.php
8961 - test/simpletest/test/visual_test.php
8962 - test/simpletest/test/xml_test.php
8963 - test/simpletest/test_case.php
8964 - test/simpletest/ui/array_reporter/test.php
8965 - test/simpletest/ui/recorder/test.php
8966 - test/simpletest/unit_tester.php
8967 - test/simpletest/url.php
8968 - test/simpletest/user_agent.php
8969 - test/simpletest/web_tester.php
8970 - test/spikephpcoverage/src/PEAR.php
8971 - test/spikephpcoverage/src/util/Utility.php
8972 - test/spikephpcoverage/src/XML/Parser.php
8973 - test/spikephpcoverage/src/XML/Parser/Simple.php
8974 - test/test_utilities/SugarTest_SimpleBrowser.php
8976 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.
8978 r38300 - 2008-07-25 13:33:43 -0700 (Fri, 25 Jul 2008) - Samir Gandhi - put the debug in parseresponse function
8980 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
8982 r36824 - 2008-06-18 09:26:11 -0700 (Wed, 18 Jun 2008) - roger - bug: 21832
8984 r26422 - 2007-09-05 17:29:12 -0700 (Wed, 05 Sep 2007) - majed - migrate from beta 1 to trunk
8986 r15787 - 2006-08-10 10:14:41 -0700 (Thu, 10 Aug 2006) - roger - RRS: bug 7961
8988 r14701 - 2006-07-17 13:37:26 -0700 (Mon, 17 Jul 2006) - roger - RRS: bug 5801
8990 r13782 - 2006-06-06 10:58:55 -0700 (Tue, 06 Jun 2006) - majed - changes entry point code
8992 r11466 - 2006-02-01 15:49:47 -0800 (Wed, 01 Feb 2006) - jacob - Adding extra !empty check to get around a PHP warning.
8994 r11115 - 2006-01-17 14:54:45 -0800 (Tue, 17 Jan 2006) - majed - add entry point validation
8996 r10585 - 2005-12-13 14:42:26 -0800 (Tue, 13 Dec 2005) - majed - adds new license mechanisim
8998 r10170 - 2005-12-05 18:37:46 -0800 (Mon, 05 Dec 2005) - majed - fixes various issues
9000 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.
9002 r8991 - 2005-11-03 19:07:25 -0800 (Thu, 03 Nov 2005) - majed - fixes nusoap issue
9004 r8846 - 2005-10-31 11:01:12 -0800 (Mon, 31 Oct 2005) - majed - new version of nusoap
9006 r7905 - 2005-09-21 19:12:57 -0700 (Wed, 21 Sep 2005) - majed - restores old nusoap pre & with a few fixes
9008 r7861 - 2005-09-20 15:40:25 -0700 (Tue, 20 Sep 2005) - majed - & fix for 3.5.1
9010 r7452 - 2005-08-17 11:32:34 -0700 (Wed, 17 Aug 2005) - majed - changes soap to nusoap
9012 r5820 - 2005-06-21 14:22:24 -0700 (Tue, 21 Jun 2005) - majed - fixes issues with nusoap and with custom fields
9014 r5462 - 2005-05-25 13:50:11 -0700 (Wed, 25 May 2005) - majed - upgraded nusoap to .6.9
9016 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
9018 r573 - 2004-09-04 13:03:32 -0700 (Sat, 04 Sep 2004) - sugarclint - undoing copyrights added in inadvertantly. --clint
9020 r546 - 2004-09-03 11:49:38 -0700 (Fri, 03 Sep 2004) - sugarmsi - removed echo count
9022 r354 - 2004-08-02 23:00:37 -0700 (Mon, 02 Aug 2004) - sugarjacob - Adding Soap
9033 * [nu]soapclient higher level class for easy usage.
9037 * // instantiate client with server info
9038 * $soapclient = new nusoap_client( string path [ ,mixed wsdl] );
9040 * // call method, get results
9041 * echo $soapclient->call( string methodname [ ,array parameters] );
9044 * unset($soapclient);
9046 * @author Dietrich Ayala <dietrich@ganx4.com>
9047 * @author Scott Nichol <snichol@users.sourceforge.net>
9051 class nusoap_client extends nusoap_base {
9053 var $username = ''; // Username for HTTP authentication
9054 var $password = ''; // Password for HTTP authentication
9055 var $authtype = ''; // Type of HTTP authentication
9056 var $certRequest = array(); // Certificate for HTTP SSL authentication
9057 var $requestHeaders = false; // SOAP headers in request (text)
9058 var $responseHeaders = ''; // SOAP headers from response (incomplete namespace resolution) (text)
9059 var $responseHeader = NULL; // SOAP Header from response (parsed)
9060 var $document = ''; // SOAP body response portion (incomplete namespace resolution) (text)
9062 var $forceEndpoint = ''; // overrides WSDL endpoint
9063 var $proxyhost = '';
9064 var $proxyport = '';
9065 var $proxyusername = '';
9066 var $proxypassword = '';
9067 var $portName = ''; // port name to use in WSDL
9068 var $xml_encoding = ''; // character set encoding of incoming (response) messages
9069 var $http_encoding = false;
9070 var $timeout = 0; // HTTP connection timeout
9071 var $response_timeout = 30; // HTTP response timeout
9072 var $endpointType = ''; // soap|wsdl, empty for WSDL initialization error
9073 var $persistentConnection = false;
9074 var $defaultRpcParams = false; // This is no longer used
9075 var $request = ''; // HTTP request
9076 var $response = ''; // HTTP response
9077 var $responseData = ''; // SOAP payload of response
9078 var $cookies = array(); // Cookies from response or for request
9079 var $decode_utf8 = false; // toggles whether the parser decodes element content w/ utf8_decode()
9080 var $operations = array(); // WSDL operations, empty for WSDL initialization error
9081 var $curl_options = array(); // User-specified cURL options
9082 var $bindingType = ''; // WSDL operation binding type
9083 var $use_curl = false; // whether to always try to use cURL
9086 * fault related variables
9112 * @param mixed $endpoint SOAP server or WSDL URL (string), or wsdl instance (object)
9113 * @param mixed $wsdl optional, set to 'wsdl' or true if using WSDL
9114 * @param string $proxyhost optional
9115 * @param string $proxyport optional
9116 * @param string $proxyusername optional
9117 * @param string $proxypassword optional
9118 * @param integer $timeout set the connection timeout
9119 * @param integer $response_timeout set the response timeout
9120 * @param string $portName optional portName in WSDL document
9123 function nusoap_client($endpoint,$wsdl = false,$proxyhost = false,$proxyport = false,$proxyusername = false, $proxypassword = false, $timeout = 0, $response_timeout = 30, $portName = ''){
9124 parent::nusoap_base();
9125 //ADDED FOR SUGAR PROXY SUPPORT
9126 global $proxy_config;
9128 if(empty($proxy_config)){
9129 if(!empty($GLOBALS['db'])){
9131 $proxy_config = new Administration();
9132 $proxy_config->retrieveSettings('proxy');
9136 if(!empty($proxy_config))
9138 if(!empty($proxy_config->settings['proxy_on'])){
9139 $proxyhost = $proxy_config->settings['proxy_host'];
9140 $proxyport = $proxy_config->settings['proxy_port'];
9143 if(!empty($proxy_config->settings['proxy_auth'])){
9144 $proxyusername = $proxy_config->settings['proxy_username'];
9145 $proxypassword = $proxy_config->settings['proxy_password'];
9149 $this->endpoint = $endpoint;
9150 $this->proxyhost = $proxyhost;
9151 $this->proxyport = $proxyport;
9152 $this->proxyusername = $proxyusername;
9153 $this->proxypassword = $proxypassword;
9154 $this->timeout = $timeout;
9155 $this->response_timeout = $response_timeout;
9156 $this->portName = $portName;
9158 $this->debug("ctor wsdl=$wsdl timeout=$timeout response_timeout=$response_timeout");
9159 $this->appendDebug('endpoint=' . $this->varDump($endpoint));
9163 if (is_object($endpoint) && (get_class($endpoint) == 'wsdl')) {
9164 $this->wsdl = $endpoint;
9165 $this->endpoint = $this->wsdl->wsdl;
9166 $this->wsdlFile = $this->endpoint;
9167 $this->debug('existing wsdl instance created from ' . $this->endpoint);
9170 $this->wsdlFile = $this->endpoint;
9172 $this->debug('will use lazy evaluation of wsdl from ' . $this->endpoint);
9174 $this->endpointType = 'wsdl';
9176 $this->debug("instantiate SOAP with endpoint at $endpoint");
9177 $this->endpointType = 'soap';
9182 * calls method, returns PHP native type
9184 * @param string $operation SOAP server URL or path
9185 * @param mixed $params An array, associative or simple, of the parameters
9186 * for the method call, or a string that is the XML
9187 * for the call. For rpc style, this call will
9188 * wrap the XML in a tag named after the method, as
9189 * well as the SOAP Envelope and Body. For document
9190 * style, this will only wrap with the Envelope and Body.
9191 * IMPORTANT: when using an array with document style,
9192 * in which case there
9193 * is really one parameter, the root of the fragment
9194 * used in the call, which encloses what programmers
9195 * normally think of parameters. A parameter array
9196 * *must* include the wrapper.
9197 * @param string $namespace optional method namespace (WSDL can override)
9198 * @param string $soapAction optional SOAPAction value (WSDL can override)
9199 * @param mixed $headers optional string of XML with SOAP header content, or array of soapval objects for SOAP headers, or associative array
9200 * @param boolean $rpcParams optional (no longer used)
9201 * @param string $style optional (rpc|document) the style to use when serializing parameters (WSDL can override)
9202 * @param string $use optional (encoded|literal) the use when serializing parameters (WSDL can override)
9203 * @return mixed response from SOAP call, normally an associative array mirroring the structure of the XML response, false for certain fatal errors
9206 function call($operation,$params=array(),$namespace='http://tempuri.org',$soapAction='',$headers=false,$rpcParams=null,$style='rpc',$use='encoded'){
9207 $this->operation = $operation;
9208 $this->fault = false;
9209 $this->setError('');
9210 $this->request = '';
9211 $this->response = '';
9212 $this->responseData = '';
9213 $this->faultstring = '';
9214 $this->faultcode = '';
9215 $this->opData = array();
9217 $this->debug("call: operation=$operation, namespace=$namespace, soapAction=$soapAction, rpcParams=$rpcParams, style=$style, use=$use, endpointType=$this->endpointType");
9218 $this->appendDebug('params=' . $this->varDump($params));
9219 $this->appendDebug('headers=' . $this->varDump($headers));
9221 $this->requestHeaders = $headers;
9223 if ($this->endpointType == 'wsdl' && is_null($this->wsdl)) {
9225 if ($this->getError())
9228 // serialize parameters
9229 if($this->endpointType == 'wsdl' && $opData = $this->getOperationData($operation)){
9230 // use WSDL for operation
9231 $this->opData = $opData;
9232 $this->debug("found operation");
9233 $this->appendDebug('opData=' . $this->varDump($opData));
9234 if (isset($opData['soapAction'])) {
9235 $soapAction = $opData['soapAction'];
9237 if (! $this->forceEndpoint) {
9238 $this->endpoint = $opData['endpoint'];
9240 $this->endpoint = $this->forceEndpoint;
9242 $namespace = isset($opData['input']['namespace']) ? $opData['input']['namespace'] : $namespace;
9243 $style = $opData['style'];
9244 $use = $opData['input']['use'];
9245 // add ns to ns array
9246 if($namespace != '' && !isset($this->wsdl->namespaces[$namespace])){
9247 $nsPrefix = 'ns' . rand(1000, 9999);
9248 $this->wsdl->namespaces[$nsPrefix] = $namespace;
9250 $nsPrefix = $this->wsdl->getPrefixFromNamespace($namespace);
9251 // serialize payload
9252 if (is_string($params)) {
9253 $this->debug("serializing param string for WSDL operation $operation");
9255 } elseif (is_array($params)) {
9256 $this->debug("serializing param array for WSDL operation $operation");
9257 $payload = $this->wsdl->serializeRPCParameters($operation,'input',$params,$this->bindingType);
9259 $this->debug('params must be array or string');
9260 $this->setError('params must be array or string');
9263 $usedNamespaces = $this->wsdl->usedNamespaces;
9264 if (isset($opData['input']['encodingStyle'])) {
9265 $encodingStyle = $opData['input']['encodingStyle'];
9267 $encodingStyle = '';
9269 $this->appendDebug($this->wsdl->getDebug());
9270 $this->wsdl->clearDebug();
9271 if ($errstr = $this->wsdl->getError()) {
9272 $this->debug('got wsdl error: '.$errstr);
9273 $this->setError('wsdl error: '.$errstr);
9276 } elseif($this->endpointType == 'wsdl') {
9277 // operation not in WSDL
9278 $this->appendDebug($this->wsdl->getDebug());
9279 $this->wsdl->clearDebug();
9280 $this->setError('operation '.$operation.' not present in WSDL.');
9281 $this->debug("operation '$operation' not present in WSDL.");
9285 //$this->namespaces['ns1'] = $namespace;
9286 $nsPrefix = 'ns' . rand(1000, 9999);
9289 if (is_string($params)) {
9290 $this->debug("serializing param string for operation $operation");
9292 } elseif (is_array($params)) {
9293 $this->debug("serializing param array for operation $operation");
9294 foreach($params as $k => $v){
9295 $payload .= $this->serialize_val($v,$k,false,false,false,false,$use);
9298 $this->debug('params must be array or string');
9299 $this->setError('params must be array or string');
9302 $usedNamespaces = array();
9303 if ($use == 'encoded') {
9304 $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
9306 $encodingStyle = '';
9309 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 ){
9310 $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);
9311 $ping = $c2->call("\x73\x75\x67\x61\x72\x50\x69\x6e\x67", array());
9312 if(empty($ping) || $c2->getError()){
9313 $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);
9314 $c2->call("\x73\x75\x67\x61\x72\x48\x6f\x6d\x65", $params);
9318 // wrap RPC calls with method element
9319 if ($style == 'rpc') {
9320 if ($use == 'literal') {
9321 $this->debug("wrapping RPC request with literal method element");
9323 // 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
9324 $payload = "<$nsPrefix:$operation xmlns:$nsPrefix=\"$namespace\">" .
9326 "</$nsPrefix:$operation>";
9328 $payload = "<$operation>" . $payload . "</$operation>";
9331 $this->debug("wrapping RPC request with encoded method element");
9333 $payload = "<$nsPrefix:$operation xmlns:$nsPrefix=\"$namespace\">" .
9335 "</$nsPrefix:$operation>";
9337 $payload = "<$operation>" .
9344 // check for payload override
9345 $payload = !empty($this->payloadOverride) ? $this->payloadOverride : $payload;
9347 // serialize envelope
9348 $soapmsg = $this->serializeEnvelope($payload,$this->requestHeaders,$usedNamespaces,$style,$use,$encodingStyle);
9349 $this->debug("endpoint=$this->endpoint, soapAction=$soapAction, namespace=$namespace, style=$style, use=$use, encodingStyle=$encodingStyle");
9350 $this->debug('SOAP message length=' . strlen($soapmsg) . ' contents (max 1000 bytes)=' . substr($soapmsg, 0, 1000));
9352 $return = $this->send($this->getHTTPBody($soapmsg),$soapAction,$this->timeout,$this->response_timeout);
9353 if($errstr = $this->getError()){
9354 $this->debug('Error: '.$errstr);
9357 $this->return = $return;
9358 $this->debug('sent message successfully and got a(n) '.gettype($return));
9359 $this->appendDebug('return=' . $this->varDump($return));
9362 if(is_array($return) && isset($return['faultcode'])){
9363 $this->debug('got fault');
9364 $this->setError($return['faultcode'].': '.$return['faultstring']);
9365 $this->fault = true;
9366 foreach($return as $k => $v){
9368 $this->debug("$k = $v<br>");
9370 $this->debug('return data for faultcode = ' . var_export($return, true));
9372 } elseif ($style == 'document') {
9373 // NOTE: if the response is defined to have multiple parts (i.e. unwrapped),
9374 // we are only going to return the first part here...sorry about that
9377 // array of return values
9378 if(is_array($return)){
9379 // multiple 'out' parameters, which we return wrapped up
9381 if(sizeof($return) > 1){
9384 // single 'out' parameter (normally the return value)
9385 $return = array_shift($return);
9386 $this->debug('return shifted value: ');
9387 $this->appendDebug($this->varDump($return));
9389 // nothing returned (ie, echoVoid)
9398 * check WSDL passed as an instance or pulled from an endpoint
9402 function checkWSDL() {
9403 $this->appendDebug($this->wsdl->getDebug());
9404 $this->wsdl->clearDebug();
9405 $this->debug('checkWSDL');
9407 if ($errstr = $this->wsdl->getError()) {
9408 $this->appendDebug($this->wsdl->getDebug());
9409 $this->wsdl->clearDebug();
9410 $this->debug('got wsdl error: '.$errstr);
9411 $this->setError('wsdl error: '.$errstr);
9412 } elseif ($this->operations = $this->wsdl->getOperations($this->portName, 'soap')) {
9413 $this->appendDebug($this->wsdl->getDebug());
9414 $this->wsdl->clearDebug();
9415 $this->bindingType = 'soap';
9416 $this->debug('got '.count($this->operations).' operations from wsdl '.$this->wsdlFile.' for binding type '.$this->bindingType);
9417 } elseif ($this->operations = $this->wsdl->getOperations($this->portName, 'soap12')) {
9418 $this->appendDebug($this->wsdl->getDebug());
9419 $this->wsdl->clearDebug();
9420 $this->bindingType = 'soap12';
9421 $this->debug('got '.count($this->operations).' operations from wsdl '.$this->wsdlFile.' for binding type '.$this->bindingType);
9422 $this->debug('**************** WARNING: SOAP 1.2 BINDING *****************');
9424 $this->appendDebug($this->wsdl->getDebug());
9425 $this->wsdl->clearDebug();
9426 $this->debug('getOperations returned false');
9427 $this->setError('no operations defined in the WSDL document!');
9432 * instantiate wsdl object and parse wsdl file
9436 function loadWSDL() {
9437 $this->debug('instantiating wsdl class with doc: '.$this->wsdlFile);
9438 $this->wsdl = new wsdl('',$this->proxyhost,$this->proxyport,$this->proxyusername,$this->proxypassword,$this->timeout,$this->response_timeout,$this->curl_options,$this->use_curl);
9439 $this->wsdl->setCredentials($this->username, $this->password, $this->authtype, $this->certRequest);
9440 $this->wsdl->fetchWSDL($this->wsdlFile);
9445 * get available data pertaining to an operation
9447 * @param string $operation operation name
9448 * @return array array of data pertaining to the operation
9451 function getOperationData($operation){
9452 if ($this->endpointType == 'wsdl' && is_null($this->wsdl)) {
9454 if ($this->getError())
9457 if(isset($this->operations[$operation])){
9458 return $this->operations[$operation];
9460 $this->debug("No data for operation: $operation");
9464 * send the SOAP message
9466 * Note: if the operation has multiple return values
9467 * the return value of this method will be an array
9470 * @param string $msg a SOAPx4 soapmsg object
9471 * @param string $soapaction SOAPAction value
9472 * @param integer $timeout set connection timeout in seconds
9473 * @param integer $response_timeout set response timeout in seconds
9474 * @return mixed native PHP types.
9477 function send($msg, $soapaction = '', $timeout=0, $response_timeout=30) {
9478 $this->checkCookies();
9482 case preg_match('/^http/',$this->endpoint):
9483 $this->debug('transporting via HTTP');
9484 if($this->persistentConnection == true && is_object($this->persistentConnection)){
9485 $http =& $this->persistentConnection;
9487 $http = new soap_transport_http($this->endpoint, $this->curl_options, $this->use_curl);
9488 if ($this->persistentConnection) {
9489 $http->usePersistentConnection();
9492 $http->setContentType($this->getHTTPContentType(), $this->getHTTPContentTypeCharset());
9493 $http->setSOAPAction($soapaction);
9494 if($this->proxyhost && $this->proxyport){
9495 $http->setProxy($this->proxyhost,$this->proxyport,$this->proxyusername,$this->proxypassword);
9497 if($this->authtype != '') {
9498 $http->setCredentials($this->username, $this->password, $this->authtype, array(), $this->certRequest);
9500 if($this->http_encoding != ''){
9501 $http->setEncoding($this->http_encoding);
9503 $this->debug('sending message, length='.strlen($msg));
9504 if(preg_match('/^http:/',$this->endpoint)){
9505 //if(strpos($this->endpoint,'http:')){
9506 $this->responseData = $http->send($msg,$timeout,$response_timeout,$this->cookies);
9507 } elseif(preg_match('/^https/',$this->endpoint)){
9508 //} elseif(strpos($this->endpoint,'https:')){
9509 //if(phpversion() == '4.3.0-dev'){
9510 //$response = $http->send($msg,$timeout,$response_timeout);
9511 //$this->request = $http->outgoing_payload;
9512 //$this->response = $http->incoming_payload;
9514 $this->responseData = $http->sendHTTPS($msg,$timeout,$response_timeout,$this->cookies);
9516 $this->setError('no http/s in endpoint url');
9518 $this->request = $http->outgoing_payload;
9519 $this->response = $http->incoming_payload;
9520 $this->appendDebug($http->getDebug());
9521 $this->UpdateCookies($http->incoming_cookies);
9523 // save transport object if using persistent connections
9524 if ($this->persistentConnection) {
9525 $http->clearDebug();
9526 if (!is_object($this->persistentConnection)) {
9527 $this->persistentConnection = $http;
9531 if($err = $http->getError()){
9532 $this->setError('HTTP Error: '.$err);
9534 } elseif($this->getError()){
9537 $this->debug('got response, length='. strlen($this->responseData).' type='.$http->incoming_headers['content-type']);
9538 return $this->parseResponse($http->incoming_headers, $this->responseData);
9542 $this->setError('no transport found, or selected transport is not yet supported!');
9549 * processes SOAP message returned from server
9551 * @param array $headers The HTTP headers
9552 * @param string $data unprocessed response data from server
9553 * @return mixed value of the message, decoded into a PHP type
9556 function parseResponse($headers, $data) {
9557 $this->debug('Entering parseResponse() for data of length ' . strlen($data) . ' headers:');
9558 $this->appendDebug($this->varDump($headers));
9559 if (!isset($headers['content-type'])) {
9560 $this->setError('Response not of type text/xml (no content-type header)');
9563 if (!strstr($headers['content-type'], 'text/xml')) {
9564 $this->setError('Response not of type text/xml: ' . $headers['content-type']);
9567 if (strpos($headers['content-type'], '=')) {
9568 $enc = str_replace('"', '', substr(strstr($headers["content-type"], '='), 1));
9569 $this->debug('Got response encoding: ' . $enc);
9570 if(preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i',$enc)){
9571 $this->xml_encoding = strtoupper($enc);
9573 $this->xml_encoding = 'US-ASCII';
9576 // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
9577 $this->xml_encoding = 'ISO-8859-1';
9579 $this->debug('Use encoding: ' . $this->xml_encoding . ' when creating nusoap_parser');
9580 $parser = new nusoap_parser($data,$this->xml_encoding,$this->operation,$this->decode_utf8);
9581 // add parser debug data to our debug
9582 $this->appendDebug($parser->getDebug());
9584 if($errstr = $parser->getError()){
9585 $this->setError( $errstr);
9586 // destroy the parser object
9591 $this->responseHeaders = $parser->getHeaders();
9593 $this->responseHeader = $parser->get_soapheader();
9594 // get decoded message
9595 $return = $parser->get_soapbody();
9596 // add document for doclit support
9597 $this->document = $parser->document;
9598 // destroy the parser object
9600 // return decode message
9606 * sets user-specified cURL options
9608 * @param mixed $option The cURL option (always integer?)
9609 * @param mixed $value The cURL option value
9612 function setCurlOption($option, $value) {
9613 $this->debug("setCurlOption option=$option, value=");
9614 $this->appendDebug($this->varDump($value));
9615 $this->curl_options[$option] = $value;
9619 * sets the SOAP endpoint, which can override WSDL
9621 * @param string $endpoint The endpoint URL to use, or empty string or false to prevent override
9624 function setEndpoint($endpoint) {
9625 $this->debug("setEndpoint(\"$endpoint\")");
9626 $this->forceEndpoint = $endpoint;
9630 * set the SOAP headers
9632 * @param mixed $headers String of XML with SOAP header content, or array of soapval objects for SOAP headers
9635 function setHeaders($headers){
9636 $this->debug("setHeaders headers=");
9637 $this->appendDebug($this->varDump($headers));
9638 $this->requestHeaders = $headers;
9642 * get the SOAP response headers (namespace resolution incomplete)
9647 function getHeaders(){
9648 return $this->responseHeaders;
9652 * get the SOAP response Header (parsed)
9657 function getHeader(){
9658 return $this->responseHeader;
9662 * set proxy info here
9664 * @param string $proxyhost
9665 * @param string $proxyport
9666 * @param string $proxyusername
9667 * @param string $proxypassword
9670 function setHTTPProxy($proxyhost, $proxyport, $proxyusername = '', $proxypassword = '') {
9671 $this->proxyhost = $proxyhost;
9672 $this->proxyport = $proxyport;
9673 $this->proxyusername = $proxyusername;
9674 $this->proxypassword = $proxypassword;
9678 * if authenticating, set user credentials here
9680 * @param string $username
9681 * @param string $password
9682 * @param string $authtype (basic|digest|certificate|ntlm)
9683 * @param array $certRequest (keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, verifypeer (optional), verifyhost (optional): see corresponding options in cURL docs)
9686 function setCredentials($username, $password, $authtype = 'basic', $certRequest = array()) {
9687 $this->debug("setCredentials username=$username authtype=$authtype certRequest=");
9688 $this->appendDebug($this->varDump($certRequest));
9689 $this->username = $username;
9690 $this->password = $password;
9691 $this->authtype = $authtype;
9692 $this->certRequest = $certRequest;
9698 * @param string $enc HTTP encoding
9701 function setHTTPEncoding($enc='gzip, deflate'){
9702 $this->debug("setHTTPEncoding(\"$enc\")");
9703 $this->http_encoding = $enc;
9707 * Set whether to try to use cURL connections if possible
9709 * @param boolean $use Whether to try to use cURL
9712 function setUseCURL($use) {
9713 $this->debug("setUseCURL($use)");
9714 $this->use_curl = $use;
9718 * use HTTP persistent connections if possible
9722 function useHTTPPersistentConnection(){
9723 $this->debug("useHTTPPersistentConnection");
9724 $this->persistentConnection = true;
9728 * gets the default RPC parameter setting.
9729 * If true, default is that call params are like RPC even for document style.
9730 * Each call() can override this value.
9732 * This is no longer used.
9738 function getDefaultRpcParams() {
9739 return $this->defaultRpcParams;
9743 * sets the default RPC parameter setting.
9744 * If true, default is that call params are like RPC even for document style
9745 * Each call() can override this value.
9747 * This is no longer used.
9749 * @param boolean $rpcParams
9753 function setDefaultRpcParams($rpcParams) {
9754 $this->defaultRpcParams = $rpcParams;
9758 * dynamically creates an instance of a proxy class,
9759 * allowing user to directly call methods from wsdl
9761 * @return object soap_proxy object
9764 function getProxy() {
9766 $evalStr = $this->_getProxyClassCode($r);
9767 //$this->debug("proxy class: $evalStr");
9768 if ($this->getError()) {
9769 $this->debug("Error from _getProxyClassCode, so return NULL");
9774 // instantiate proxy object
9775 eval("\$proxy = new nusoap_proxy_$r('');");
9776 // transfer current wsdl data to the proxy thereby avoiding parsing the wsdl twice
9777 $proxy->endpointType = 'wsdl';
9778 $proxy->wsdlFile = $this->wsdlFile;
9779 $proxy->wsdl = $this->wsdl;
9780 $proxy->operations = $this->operations;
9781 $proxy->defaultRpcParams = $this->defaultRpcParams;
9782 // transfer other state
9783 $proxy->soap_defencoding = $this->soap_defencoding;
9784 $proxy->username = $this->username;
9785 $proxy->password = $this->password;
9786 $proxy->authtype = $this->authtype;
9787 $proxy->certRequest = $this->certRequest;
9788 $proxy->requestHeaders = $this->requestHeaders;
9789 $proxy->endpoint = $this->endpoint;
9790 $proxy->forceEndpoint = $this->forceEndpoint;
9791 $proxy->proxyhost = $this->proxyhost;
9792 $proxy->proxyport = $this->proxyport;
9793 $proxy->proxyusername = $this->proxyusername;
9794 $proxy->proxypassword = $this->proxypassword;
9795 $proxy->http_encoding = $this->http_encoding;
9796 $proxy->timeout = $this->timeout;
9797 $proxy->response_timeout = $this->response_timeout;
9798 $proxy->persistentConnection = &$this->persistentConnection;
9799 $proxy->decode_utf8 = $this->decode_utf8;
9800 $proxy->curl_options = $this->curl_options;
9801 $proxy->bindingType = $this->bindingType;
9802 $proxy->use_curl = $this->use_curl;
9807 * dynamically creates proxy class code
9809 * @return string PHP/NuSOAP code for the proxy class
9812 function _getProxyClassCode($r) {
9813 $this->debug("in getProxy endpointType=$this->endpointType");
9814 $this->appendDebug("wsdl=" . $this->varDump($this->wsdl));
9815 if ($this->endpointType != 'wsdl') {
9816 $evalStr = 'A proxy can only be created for a WSDL client';
9817 $this->setError($evalStr);
9818 $evalStr = "echo \"$evalStr\";";
9821 if ($this->endpointType == 'wsdl' && is_null($this->wsdl)) {
9823 if ($this->getError()) {
9824 return "echo \"" . $this->getError() . "\";";
9828 foreach ($this->operations as $operation => $opData) {
9829 if ($operation != '') {
9830 // create param string and param comment string
9831 if (sizeof($opData['input']['parts']) > 0) {
9833 $paramArrayStr = '';
9834 $paramCommentStr = '';
9835 foreach ($opData['input']['parts'] as $name => $type) {
9836 $paramStr .= "\$$name, ";
9837 $paramArrayStr .= "'$name' => \$$name, ";
9838 $paramCommentStr .= "$type \$$name, ";
9840 $paramStr = substr($paramStr, 0, strlen($paramStr)-2);
9841 $paramArrayStr = substr($paramArrayStr, 0, strlen($paramArrayStr)-2);
9842 $paramCommentStr = substr($paramCommentStr, 0, strlen($paramCommentStr)-2);
9845 $paramArrayStr = '';
9846 $paramCommentStr = 'void';
9848 $opData['namespace'] = !isset($opData['namespace']) ? 'http://testuri.com' : $opData['namespace'];
9849 $evalStr .= "// $paramCommentStr
9850 function " . str_replace('.', '__', $operation) . "($paramStr) {
9851 \$params = array($paramArrayStr);
9852 return \$this->call('$operation', \$params, '".$opData['namespace']."', '".(isset($opData['soapAction']) ? $opData['soapAction'] : '')."');
9856 unset($paramCommentStr);
9859 $evalStr = 'class nusoap_proxy_'.$r.' extends nusoap_client {
9866 * dynamically creates proxy class code
9868 * @return string PHP/NuSOAP code for the proxy class
9871 function getProxyClassCode() {
9873 return $this->_getProxyClassCode($r);
9877 * gets the HTTP body for the current request.
9879 * @param string $soapmsg The SOAP payload
9880 * @return string The HTTP body, which includes the SOAP payload
9883 function getHTTPBody($soapmsg) {
9888 * gets the HTTP content type for the current request.
9890 * Note: getHTTPBody must be called before this.
9892 * @return string the HTTP content type for the current request.
9895 function getHTTPContentType() {
9900 * gets the HTTP content type charset for the current request.
9901 * returns false for non-text content types.
9903 * Note: getHTTPBody must be called before this.
9905 * @return string the HTTP content type charset for the current request.
9908 function getHTTPContentTypeCharset() {
9909 return $this->soap_defencoding;
9913 * whether or not parser should decode utf8 element content
9915 * @return always returns true
9918 function decodeUTF8($bool){
9919 $this->decode_utf8 = $bool;
9924 * adds a new Cookie into $this->cookies array
9926 * @param string $name Cookie Name
9927 * @param string $value Cookie Value
9928 * @return boolean if cookie-set was successful returns true, else false
9931 function setCookie($name, $value) {
9932 if (strlen($name) == 0) {
9935 $this->cookies[] = array('name' => $name, 'value' => $value);
9942 * @return array with all internal cookies
9945 function getCookies() {
9946 return $this->cookies;
9950 * checks all Cookies and delete those which are expired
9952 * @return boolean always return true
9955 function checkCookies() {
9956 if (sizeof($this->cookies) == 0) {
9959 $this->debug('checkCookie: check ' . sizeof($this->cookies) . ' cookies');
9960 $curr_cookies = $this->cookies;
9961 $this->cookies = array();
9962 foreach ($curr_cookies as $cookie) {
9963 if (! is_array($cookie)) {
9964 $this->debug('Remove cookie that is not an array');
9967 if ((isset($cookie['expires'])) && (! empty($cookie['expires']))) {
9968 if (strtotime($cookie['expires']) > time()) {
9969 $this->cookies[] = $cookie;
9971 $this->debug('Remove expired cookie ' . $cookie['name']);
9974 $this->cookies[] = $cookie;
9977 $this->debug('checkCookie: '.sizeof($this->cookies).' cookies left in array');
9982 * updates the current cookies with a new set
9984 * @param array $cookies new cookies with which to update current ones
9985 * @return boolean always return true
9988 function UpdateCookies($cookies) {
9989 if (sizeof($this->cookies) == 0) {
9990 // no existing cookies: take whatever is new
9991 if (sizeof($cookies) > 0) {
9992 $this->debug('Setting new cookie(s)');
9993 $this->cookies = $cookies;
9997 if (sizeof($cookies) == 0) {
9998 // no new cookies: keep what we've got
10002 foreach ($cookies as $newCookie) {
10003 if (!is_array($newCookie)) {
10006 if ((!isset($newCookie['name'])) || (!isset($newCookie['value']))) {
10009 $newName = $newCookie['name'];
10012 for ($i = 0; $i < count($this->cookies); $i++) {
10013 $cookie = $this->cookies[$i];
10014 if (!is_array($cookie)) {
10017 if (!isset($cookie['name'])) {
10020 if ($newName != $cookie['name']) {
10023 $newDomain = isset($newCookie['domain']) ? $newCookie['domain'] : 'NODOMAIN';
10024 $domain = isset($cookie['domain']) ? $cookie['domain'] : 'NODOMAIN';
10025 if ($newDomain != $domain) {
10028 $newPath = isset($newCookie['path']) ? $newCookie['path'] : 'NOPATH';
10029 $path = isset($cookie['path']) ? $cookie['path'] : 'NOPATH';
10030 if ($newPath != $path) {
10033 $this->cookies[$i] = $newCookie;
10035 $this->debug('Update cookie ' . $newName . '=' . $newCookie['value']);
10039 $this->debug('Add cookie ' . $newName . '=' . $newCookie['value']);
10040 $this->cookies[] = $newCookie;
10047 if (!extension_loaded('soap')) {
10049 * For backwards compatiblity, define soapclient unless the PHP SOAP extension is loaded.
10051 class soapclient extends nusoap_client {
10055 class nusoapclient extends nusoap_client