4 Modification information for LGPL compliance
6 commit 76702f8945b5e4076d406d8e3388c23d7959a2e3
7 Author: Stanislav Malyshev <smalyshev@gmail.com>
8 Date: Mon Nov 26 15:35:58 2012 -0800
10 bug #50736 - fix proxy with different port
12 commit 70759790576f88f2b0480b50d35c95c84b9e6879
13 Author: Stanislav Malyshev <smalyshev@gmail.com>
14 Date: Thu Feb 17 18:09:12 2011 -0800
16 bug 34897 - remove characters that aren't valid in XML
18 commit 1767411d701b8216cc5e043888fd1337e2eca315
19 Author: Stanislav Malyshev <smalyshev@gmail.com>
20 Date: Fri Jan 7 12:19:10 2011 -0800
22 conserve memory when no debug is enabled
24 commit 843510ebf455368865302a05b9d5041815a32c23
25 Author: John Mertic <jmertic@sugarcrm.com>
26 Date: Wed Nov 17 13:18:09 2010 -0500
28 Bug 40716 - Fix WSDL validation problem by removing hardcoded schemaLocation attribute for the <xsd:import> tag.
30 commit 2bd12c02078f3e291bd9c1e76179a144c788ce97
31 Author: Collin Lee <clee@Collin-Lee-MacBook-Pro.local>
32 Date: Fri Oct 22 16:37:42 2010 -0400
36 We traced the error to a combination of the new Hoovers' WSDL + the nusoapclient code that winds up improperly encoding the parameter elem
37 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
38 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
39 and also re-enabled those for Hoovers that were marked skipped.
41 r58622 - 2010-10-22 18:18:59 -0700 (Fri, 22 Oct 2010) - engsvnbuild - Author: lam <lam@198.18.142.201>
44 r58361 - 2010-09-29 16:59:02 -0700 (Wed, 29 Sep 2010) - kjing - Author: Jenny Gonsalves <jenny@sugarcrm.com>
45 Merging with maint_6_0_1 (svn merge -r 58250:58342)
47 r57813 - 2010-08-19 10:34:44 -0700 (Thu, 19 Aug 2010) - kjing - Author: John Mertic <jmertic@sugarcrm.com>
48 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.
50 r57707 - 2010-08-10 12:26:13 -0700 (Tue, 10 Aug 2010) - kjing - Author: Stanislav Malyshev <smalyshev@gmail.com>
51 fix SOAP calls with no parameters
53 r56990 - 2010-06-16 13:05:36 -0700 (Wed, 16 Jun 2010) - kjing - snapshot "Mango" svn branch to a new one for GitHub sync
55 r56989 - 2010-06-16 13:01:33 -0700 (Wed, 16 Jun 2010) - kjing - defunt "Mango" svn dev branch before github cutover
57 r55980 - 2010-04-19 13:31:28 -0700 (Mon, 19 Apr 2010) - kjing - create Mango (6.1) based on windex
59 r51719 - 2009-10-22 10:18:00 -0700 (Thu, 22 Oct 2009) - mitani - Converted to Build 3 tags and updated the build system
61 r51634 - 2009-10-19 13:32:22 -0700 (Mon, 19 Oct 2009) - mitani - Windex is the branch for Sugar Sales 1.0 development
63 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.
65 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.
67 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:
68 - Changing all ereg function to either preg or simple string based ones
69 - No more references to magic quotes.
70 - Change all the session_unregister() functions to just unset() the correct session variable instead.
72 r50375 - 2009-08-24 18:07:43 -0700 (Mon, 24 Aug 2009) - dwong - branch kobe2 from tokyo r50372
74 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
76 r45680 - 2009-03-30 14:34:35 -0700 (Mon, 30 Mar 2009) - Samir Gandhi - modifeid serializeSchema to generate WS-I compliant WSDL
78 r42807 - 2008-12-29 11:16:59 -0800 (Mon, 29 Dec 2008) - dwong - Branch from trunk/sugarcrm r42806 to branches/tokyo/sugarcrm
80 r42645 - 2008-12-18 13:41:08 -0800 (Thu, 18 Dec 2008) - awu - merging maint_5_2_0 rev41336:HEAD to trunk
82 r41647 - 2008-11-11 17:44:30 -0800 (Tue, 11 Nov 2008) - majed - Fixes a few bugs
84 r41596 - 2008-11-10 19:20:04 -0800 (Mon, 10 Nov 2008) - Samir Gandhi - modified to set $method in the code
86 r41558 - 2008-11-10 14:35:34 -0800 (Mon, 10 Nov 2008) - majed - changes nusoap to allow for registering classes
88 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.
91 - include/domit/php_http_client_generic.php
92 - include/domit/php_http_connector.php
93 - include/domit/testing_domit.php
94 - include/domit/xml_domit_getelementsbypath.php
95 - include/domit/xml_domit_lite_parser.php
96 - include/domit/xml_domit_nodemaps.php
97 - include/domit/xml_domit_parser.php
98 - include/domit/xml_domit_shared.php
99 - include/generic/SugarWidgets/SugarWidgetField.php
100 - include/generic/SugarWidgets/SugarWidgetReportField.php
101 - include/ListView/ProcessView.php
102 - include/nusoap/class.soapclient.php
103 - include/nusoap/nusoap.php
104 - include/nusoap/nusoapmime.php
105 - include/Pear/HTML_Safe/Safe.php
106 - include/Pear/XML_HTMLSax3/HTMLSax3.php
107 - modules/Administration/RebuildWorkFlow.php
108 - modules/Expressions/RelateSelector.php
109 - modules/Reports/templates/templates_reports.php
110 - modules/WorkFlow/Delete.php
111 - modules/WorkFlow/Save.php
112 - modules/WorkFlow/SaveSequence.php
113 - modules/WorkFlow/WorkFlow.php
114 - modules/WorkFlowActionShells/CreateStep1.php
115 - modules/WorkFlowActionShells/CreateStep2.php
116 - modules/WorkFlowActionShells/Save.php
117 - modules/WorkFlowActionShells/WorkFlowActionShell.php
118 - modules/WorkFlowAlerts/Save.php
119 - modules/WorkFlowAlerts/WorkFlowAlert.php
120 - modules/WorkFlowAlertShells/DetailView.php
121 - modules/WorkFlowAlertShells/WorkFlowAlertShell.php
122 - modules/WorkFlowTriggerShells/CreateStep1.php
123 - modules/WorkFlowTriggerShells/CreateStepFilter.php
124 - modules/WorkFlowTriggerShells/SaveFilter.php
125 - modules/WorkFlowTriggerShells/WorkFlowTriggerShell.php
126 - soap/SoapHelperFunctions.php
127 - test/modules/DynamicFields/DynamicFields_Bug24095_test.php
128 - test/simpletest/browser.php
129 - test/simpletest/default_reporter.php
130 - test/simpletest/detached.php
131 - test/simpletest/eclipse.php
132 - test/simpletest/expectation.php
133 - test/simpletest/extensions/pear_test_case.php
134 - test/simpletest/form.php
135 - test/simpletest/http.php
136 - test/simpletest/mock_objects.php
137 - test/simpletest/page.php
138 - test/simpletest/parser.php
139 - test/simpletest/remote.php
140 - test/simpletest/shell_tester.php
141 - test/simpletest/simple_test.php
142 - test/simpletest/simpletest.php
143 - test/simpletest/test/acceptance_test.php
144 - test/simpletest/test/adapter_test.php
145 - test/simpletest/test/authentication_test.php
146 - test/simpletest/test/browser_test.php
147 - test/simpletest/test/collector_test.php
148 - test/simpletest/test/compatibility_test.php
149 - test/simpletest/test/detached_test.php
150 - test/simpletest/test/eclipse_test.php
151 - test/simpletest/test/encoding_test.php
152 - test/simpletest/test/errors_test.php
153 - test/simpletest/test/expectation_test.php
154 - test/simpletest/test/form_test.php
155 - test/simpletest/test/frames_test.php
156 - test/simpletest/test/http_test.php
157 - test/simpletest/test/live_test.php
158 - test/simpletest/test/mock_objects_test.php
159 - test/simpletest/test/page_test.php
160 - test/simpletest/test/parse_error_test.php
161 - test/simpletest/test/parser_test.php
162 - test/simpletest/test/remote_test.php
163 - test/simpletest/test/shell_test.php
164 - test/simpletest/test/shell_tester_test.php
165 - test/simpletest/test/simpletest_test.php
166 - test/simpletest/test/site/page_request.php
167 - test/simpletest/test/tag_test.php
168 - test/simpletest/test/unit_tester_test.php
169 - test/simpletest/test/user_agent_test.php
170 - test/simpletest/test/visual_test.php
171 - test/simpletest/test/xml_test.php
172 - test/simpletest/test_case.php
173 - test/simpletest/ui/array_reporter/test.php
174 - test/simpletest/ui/recorder/test.php
175 - test/simpletest/unit_tester.php
176 - test/simpletest/url.php
177 - test/simpletest/user_agent.php
178 - test/simpletest/web_tester.php
179 - test/spikephpcoverage/src/PEAR.php
180 - test/spikephpcoverage/src/util/Utility.php
181 - test/spikephpcoverage/src/XML/Parser.php
182 - test/spikephpcoverage/src/XML/Parser/Simple.php
183 - test/test_utilities/SugarTest_SimpleBrowser.php
185 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.
187 r38300 - 2008-07-25 13:33:43 -0700 (Fri, 25 Jul 2008) - Samir Gandhi - put the debug in parseresponse function
189 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
191 r36824 - 2008-06-18 09:26:11 -0700 (Wed, 18 Jun 2008) - roger - bug: 21832
193 r26422 - 2007-09-05 17:29:12 -0700 (Wed, 05 Sep 2007) - majed - migrate from beta 1 to trunk
195 r15787 - 2006-08-10 10:14:41 -0700 (Thu, 10 Aug 2006) - roger - RRS: bug 7961
197 r14701 - 2006-07-17 13:37:26 -0700 (Mon, 17 Jul 2006) - roger - RRS: bug 5801
199 r13782 - 2006-06-06 10:58:55 -0700 (Tue, 06 Jun 2006) - majed - changes entry point code
201 r11466 - 2006-02-01 15:49:47 -0800 (Wed, 01 Feb 2006) - jacob - Adding extra !empty check to get around a PHP warning.
203 r11115 - 2006-01-17 14:54:45 -0800 (Tue, 17 Jan 2006) - majed - add entry point validation
205 r10585 - 2005-12-13 14:42:26 -0800 (Tue, 13 Dec 2005) - majed - adds new license mechanisim
207 r10170 - 2005-12-05 18:37:46 -0800 (Mon, 05 Dec 2005) - majed - fixes various issues
209 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.
211 r8991 - 2005-11-03 19:07:25 -0800 (Thu, 03 Nov 2005) - majed - fixes nusoap issue
213 r8846 - 2005-10-31 11:01:12 -0800 (Mon, 31 Oct 2005) - majed - new version of nusoap
215 r7905 - 2005-09-21 19:12:57 -0700 (Wed, 21 Sep 2005) - majed - restores old nusoap pre & with a few fixes
217 r7861 - 2005-09-20 15:40:25 -0700 (Tue, 20 Sep 2005) - majed - & fix for 3.5.1
219 r7452 - 2005-08-17 11:32:34 -0700 (Wed, 17 Aug 2005) - majed - changes soap to nusoap
221 r5820 - 2005-06-21 14:22:24 -0700 (Tue, 21 Jun 2005) - majed - fixes issues with nusoap and with custom fields
223 r5462 - 2005-05-25 13:50:11 -0700 (Wed, 25 May 2005) - majed - upgraded nusoap to .6.9
225 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
227 r573 - 2004-09-04 13:03:32 -0700 (Sat, 04 Sep 2004) - sugarclint - undoing copyrights added in inadvertantly. --clint
229 r546 - 2004-09-03 11:49:38 -0700 (Fri, 03 Sep 2004) - sugarmsi - removed echo count
231 r354 - 2004-08-02 23:00:37 -0700 (Mon, 02 Aug 2004) - sugarjacob - Adding Soap
237 if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
240 $Id: nusoap.php 58622 2010-10-23 01:18:59Z engsvnbuild $
242 NuSOAP - Web Services Toolkit for PHP
244 Copyright (c) 2002 NuSphere Corporation
246 This library is free software; you can redistribute it and/or
247 modify it under the terms of the GNU Lesser General Public
248 License as published by the Free Software Foundation; either
249 version 2.1 of the License, or (at your option) any later version.
251 This library is distributed in the hope that it will be useful,
252 but WITHOUT ANY WARRANTY; without even the implied warranty of
253 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
254 Lesser General Public License for more details.
256 You should have received a copy of the GNU Lesser General Public
257 License along with this library; if not, write to the Free Software
258 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
260 The NuSOAP project home is:
261 http://sourceforge.net/projects/nusoap/
263 The primary support for NuSOAP is the Help forum on the project home page.
265 If you have any questions or comments, please email:
269 http://dietrich.ganx4.com/nusoap
272 http://www.nusphere.com
277 * Some of the standards implmented in whole or part by NuSOAP:
279 * SOAP 1.1 (http://www.w3.org/TR/2000/NOTE-SOAP-20000508/)
280 * WSDL 1.1 (http://www.w3.org/TR/2001/NOTE-wsdl-20010315)
281 * SOAP Messages With Attachments (http://www.w3.org/TR/SOAP-attachments)
282 * XML 1.0 (http://www.w3.org/TR/2006/REC-xml-20060816/)
283 * Namespaces in XML 1.0 (http://www.w3.org/TR/2006/REC-xml-names-20060816/)
284 * XML Schema 1.0 (http://www.w3.org/TR/xmlschema-0/)
285 * RFC 2045 Multipurpose Internet Mail Extensions (MIME) Part One: Format of Internet Message Bodies
286 * RFC 2068 Hypertext Transfer Protocol -- HTTP/1.1
287 * RFC 2617 HTTP Authentication: Basic and Digest Access Authentication
293 require_once('class.soapclient.php');
294 require_once('class.soap_val.php');
295 require_once('class.soap_parser.php');
296 require_once('class.soap_fault.php');
299 require_once('class.soap_transport_http.php');
301 // optional add-on classes
302 require_once('class.xmlschema.php');
303 require_once('class.wsdl.php');
306 require_once('class.soap_server.php');*/
308 // class variable emulation
309 // cf. http://www.webkreator.com/php/techniques/php-static-class-variables.html
310 $GLOBALS['_transient']['static']['nusoap_base']['globalDebugLevel'] = 0;
316 * @author Dietrich Ayala <dietrich@ganx4.com>
317 * @author Scott Nichol <snichol@users.sourceforge.net>
323 * Identification for HTTP headers.
328 var $title = 'NuSOAP';
330 * Version for HTTP headers.
335 var $version = '0.9.5';
337 * CVS revision for HTTP headers.
342 var $revision = '$Revision: 58622 $';
344 * Current error string (manipulated by getError/setError)
351 * Current debug string (manipulated by debug/appendDebug/clearDebug/getDebug/getDebugAsXMLComment)
358 * toggles automatic encoding of special characters as entities
359 * (should always be true, I think)
364 var $charencoding = true;
366 * the debug level for this instance
379 var $XMLSchemaVersion = 'http://www.w3.org/2001/XMLSchema';
382 * charset encoding for outgoing messages
387 //var $soap_defencoding = 'ISO-8859-1';
388 var $soap_defencoding = 'UTF-8';
391 * namespaces in an array of prefix => uri
393 * this is "seeded" by a set of constants, but it may be altered by code
398 var $namespaces = array(
399 'SOAP-ENV' => 'http://schemas.xmlsoap.org/soap/envelope/',
400 'xsd' => 'http://www.w3.org/2001/XMLSchema',
401 'xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
402 'SOAP-ENC' => 'http://schemas.xmlsoap.org/soap/encoding/'
406 * namespaces used in the current context, e.g. during serialization
411 var $usedNamespaces = array();
414 * XML Schema types in an array of uri => (array of xml type => php type)
415 * is this legacy yet?
416 * no, this is used by the nusoap_xmlschema class to verify type => namespace mappings.
420 var $typemap = array(
421 'http://www.w3.org/2001/XMLSchema' => array(
422 'string'=>'string','boolean'=>'boolean','float'=>'double','double'=>'double','decimal'=>'double',
423 'duration'=>'','dateTime'=>'string','time'=>'string','date'=>'string','gYearMonth'=>'',
424 'gYear'=>'','gMonthDay'=>'','gDay'=>'','gMonth'=>'','hexBinary'=>'string','base64Binary'=>'string',
425 // abstract "any" types
426 'anyType'=>'string','anySimpleType'=>'string',
428 'normalizedString'=>'string','token'=>'string','language'=>'','NMTOKEN'=>'','NMTOKENS'=>'','Name'=>'','NCName'=>'','ID'=>'',
429 'IDREF'=>'','IDREFS'=>'','ENTITY'=>'','ENTITIES'=>'','integer'=>'integer','nonPositiveInteger'=>'integer',
430 'negativeInteger'=>'integer','long'=>'integer','int'=>'integer','short'=>'integer','byte'=>'integer','nonNegativeInteger'=>'integer',
431 'unsignedLong'=>'','unsignedInt'=>'','unsignedShort'=>'','unsignedByte'=>'','positiveInteger'=>''),
432 'http://www.w3.org/2000/10/XMLSchema' => array(
433 'i4'=>'','int'=>'integer','boolean'=>'boolean','string'=>'string','double'=>'double',
434 'float'=>'double','dateTime'=>'string',
435 'timeInstant'=>'string','base64Binary'=>'string','base64'=>'string','ur-type'=>'array'),
436 'http://www.w3.org/1999/XMLSchema' => array(
437 'i4'=>'','int'=>'integer','boolean'=>'boolean','string'=>'string','double'=>'double',
438 'float'=>'double','dateTime'=>'string',
439 'timeInstant'=>'string','base64Binary'=>'string','base64'=>'string','ur-type'=>'array'),
440 'http://soapinterop.org/xsd' => array('SOAPStruct'=>'struct'),
441 'http://schemas.xmlsoap.org/soap/encoding/' => array('base64'=>'string','array'=>'array','Array'=>'array'),
442 'http://xml.apache.org/xml-soap' => array('Map')
446 * XML entities to convert
451 * @see expandEntities
453 var $xmlEntities = array('quot' => '"','amp' => '&',
454 'lt' => '<','gt' => '>','apos' => "'");
458 * This is to allows us to override the payload to resolve issues where we need to take
459 * control of the xml content
464 var $payloadOverride;
471 function nusoap_base() {
472 $this->debugLevel = $GLOBALS['_transient']['static']['nusoap_base']['globalDebugLevel'];
476 * gets the global debug level, which applies to future instances
478 * @return integer Debug level 0-9, where 0 turns off
481 function getGlobalDebugLevel() {
482 return $GLOBALS['_transient']['static']['nusoap_base']['globalDebugLevel'];
486 * sets the global debug level, which applies to future instances
488 * @param int $level Debug level 0-9, where 0 turns off
491 function setGlobalDebugLevel($level) {
492 $GLOBALS['_transient']['static']['nusoap_base']['globalDebugLevel'] = $level;
496 * gets the debug level for this instance
498 * @return int Debug level 0-9, where 0 turns off
501 function getDebugLevel() {
502 return $this->debugLevel;
506 * sets the debug level for this instance
508 * @param int $level Debug level 0-9, where 0 turns off
511 function setDebugLevel($level) {
512 $this->debugLevel = $level;
516 * adds debug data to the instance debug string with formatting
518 * @param string $string debug data
521 function debug($string){
522 if ($this->debugLevel > 0) {
523 $this->appendDebug($this->getmicrotime().' '.get_class($this).": $string\n");
528 * adds debug data to the instance debug string without formatting
530 * @param string $string debug data
533 function appendDebug($string){
534 if ($this->debugLevel > 0) {
535 // it would be nice to use a memory stream here to use
536 // memory more efficiently
537 $this->debug_str .= $string;
542 * clears the current debug data for this instance
546 function clearDebug() {
547 // it would be nice to use a memory stream here to use
548 // memory more efficiently
549 $this->debug_str = '';
553 * gets the current debug data for this instance
558 function &getDebug() {
559 // it would be nice to use a memory stream here to use
560 // memory more efficiently
561 return $this->debug_str;
565 * gets the current debug data for this instance as an XML comment
566 * this may change the contents of the debug data
568 * @return debug data as an XML comment
571 function &getDebugAsXMLComment() {
572 // it would be nice to use a memory stream here to use
573 // memory more efficiently
574 while (strpos($this->debug_str, '--')) {
575 $this->debug_str = str_replace('--', '- -', $this->debug_str);
577 $ret = "<!--\n" . $this->debug_str . "\n-->";
582 * expands entities, e.g. changes '<' to '<'.
584 * @param string $val The string in which to expand entities.
587 function expandEntities($val) {
588 if ($this->charencoding) {
589 $val = htmlspecialchars($val, ENT_QUOTES, $this->soap_defencoding);
590 // XML 1.0 doesn't allow those...
591 $val = preg_replace("/([\\x00-\\x08\\x0B\\x0C\\x0E-\\x1F])/", '', $val);
597 * returns error string if present
599 * @return mixed error string or false
603 if($this->error_str != ''){
604 return $this->error_str;
612 * @return boolean $string error string
615 function setError($str){
616 $this->error_str = $str;
620 * detect if array is a simple array or a struct (associative array)
622 * @param mixed $val The PHP array
623 * @return string (arraySimple|arrayStruct)
626 function isArraySimpleOrStruct($val) {
627 $keyList = array_keys($val);
628 foreach ($keyList as $keyListValue) {
629 if (!is_int($keyListValue)) {
630 return 'arrayStruct';
633 return 'arraySimple';
637 * serializes PHP values in accordance w/ section 5. Type information is
638 * not serialized if $use == 'literal'.
640 * @param mixed $val The value to serialize
641 * @param string $name The name (local part) of the XML element
642 * @param string $type The XML schema type (local part) for the element
643 * @param string $name_ns The namespace for the name of the XML element
644 * @param string $type_ns The namespace for the type of the element
645 * @param array $attributes The attributes to serialize as name=>value pairs
646 * @param string $use The WSDL "use" (encoded|literal)
647 * @param boolean $soapval Whether this is called from soapval.
648 * @return string The serialized element, possibly with child elements
651 function serialize_val($val,$name=false,$type=false,$name_ns=false,$type_ns=false,$attributes=false,$use='encoded',$soapval=false) {
652 $this->debug("in serialize_val: name=$name, type=$type, name_ns=$name_ns, type_ns=$type_ns, use=$use, soapval=$soapval");
653 $this->appendDebug('value=' . $this->varDump($val));
654 $this->appendDebug('attributes=' . $this->varDump($attributes));
656 if (is_object($val) && get_class($val) == 'soapval' && (! $soapval)) {
657 $this->debug("serialize_val: serialize soapval");
658 $xml = $val->serialize($use);
659 $this->appendDebug($val->getDebug());
661 $this->debug("serialize_val of soapval returning $xml");
664 // force valid name if necessary
665 if (is_numeric($name)) {
666 $name = '__numeric_' . $name;
670 // if name has ns, add ns prefix to name
673 $prefix = 'nu'.rand(1000,9999);
674 $name = $prefix.':'.$name;
675 $xmlns .= " xmlns:$prefix=\"$name_ns\"";
677 // if type is prefixed, create type prefix
678 if($type_ns != '' && $type_ns == $this->namespaces['xsd']){
679 // need to fix this. shouldn't default to xsd if no ns specified
680 // w/o checking against typemap
681 $type_prefix = 'xsd';
683 $type_prefix = 'ns'.rand(1000,9999);
684 $xmlns .= " xmlns:$type_prefix=\"$type_ns\"";
686 // serialize attributes if present
689 foreach($attributes as $k => $v){
690 $atts .= " $k=\"".$this->expandEntities($v).'"';
693 // serialize null value
695 $this->debug("serialize_val: serialize null");
696 if ($use == 'literal') {
697 // TODO: depends on minOccurs
698 $xml = "<$name$xmlns$atts/>";
699 $this->debug("serialize_val returning $xml");
702 if (isset($type) && isset($type_prefix)) {
703 $type_str = " xsi:type=\"$type_prefix:$type\"";
707 $xml = "<$name$xmlns$type_str$atts xsi:nil=\"true\"/>";
708 $this->debug("serialize_val returning $xml");
712 // serialize if an xsd built-in primitive type
713 if($type != '' && isset($this->typemap[$this->XMLSchemaVersion][$type])){
714 $this->debug("serialize_val: serialize xsd built-in primitive type");
716 if ($type == 'boolean') {
717 $val = $val ? 'true' : 'false';
721 } else if (is_string($val)) {
722 $val = $this->expandEntities($val);
724 if ($use == 'literal') {
725 $xml = "<$name$xmlns$atts>$val</$name>";
726 $this->debug("serialize_val returning $xml");
729 $xml = "<$name$xmlns xsi:type=\"xsd:$type\"$atts>$val</$name>";
730 $this->debug("serialize_val returning $xml");
734 // detect type and serialize
737 case (is_bool($val) || $type == 'boolean'):
738 $this->debug("serialize_val: serialize boolean");
739 if ($type == 'boolean') {
740 $val = $val ? 'true' : 'false';
744 if ($use == 'literal') {
745 $xml .= "<$name$xmlns$atts>$val</$name>";
747 $xml .= "<$name$xmlns xsi:type=\"xsd:boolean\"$atts>$val</$name>";
750 case (is_int($val) || is_long($val) || $type == 'int'):
751 $this->debug("serialize_val: serialize int");
752 if ($use == 'literal') {
753 $xml .= "<$name$xmlns$atts>$val</$name>";
755 $xml .= "<$name$xmlns xsi:type=\"xsd:int\"$atts>$val</$name>";
758 case (is_float($val)|| is_double($val) || $type == 'float'):
759 $this->debug("serialize_val: serialize float");
760 if ($use == 'literal') {
761 $xml .= "<$name$xmlns$atts>$val</$name>";
763 $xml .= "<$name$xmlns xsi:type=\"xsd:float\"$atts>$val</$name>";
766 case (is_string($val) || $type == 'string'):
767 $this->debug("serialize_val: serialize string");
768 $val = $this->expandEntities($val);
769 if ($use == 'literal') {
770 $xml .= "<$name$xmlns$atts>$val</$name>";
772 $xml .= "<$name$xmlns xsi:type=\"xsd:string\"$atts>$val</$name>";
775 case is_object($val):
776 $this->debug("serialize_val: serialize object");
777 if (get_class($val) == 'soapval') {
778 $this->debug("serialize_val: serialize soapval object");
779 $pXml = $val->serialize($use);
780 $this->appendDebug($val->getDebug());
784 $name = get_class($val);
785 $this->debug("In serialize_val, used class name $name as element name");
787 $this->debug("In serialize_val, do not override name $name for element name for class " . get_class($val));
789 foreach(get_object_vars($val) as $k => $v){
790 $pXml = isset($pXml) ? $pXml.$this->serialize_val($v,$k,false,false,false,false,$use) : $this->serialize_val($v,$k,false,false,false,false,$use);
793 if(isset($type) && isset($type_prefix)){
794 $type_str = " xsi:type=\"$type_prefix:$type\"";
798 if ($use == 'literal') {
799 $xml .= "<$name$xmlns$atts>$pXml</$name>";
801 $xml .= "<$name$xmlns$type_str$atts>$pXml</$name>";
805 case (is_array($val) || $type):
806 // detect if struct or array
807 $valueType = $this->isArraySimpleOrStruct($val);
808 if($valueType=='arraySimple' || preg_match('/^ArrayOf/',$type)){
809 $this->debug("serialize_val: serialize array");
811 if(is_array($val) && count($val)> 0){
813 if(is_object($v) && get_class($v) == 'soapval'){
814 $tt_ns = $v->type_ns;
816 } elseif (is_array($v)) {
817 $tt = $this->isArraySimpleOrStruct($v);
821 $array_types[$tt] = 1;
822 // TODO: for literal, the name should be $name
823 $xml .= $this->serialize_val($v,'item',false,false,false,false,$use);
826 if(count($array_types) > 1){
827 $array_typename = 'xsd:anyType';
828 } elseif(isset($tt) && isset($this->typemap[$this->XMLSchemaVersion][$tt])) {
829 if ($tt == 'integer') {
832 $array_typename = 'xsd:'.$tt;
833 } elseif(isset($tt) && $tt == 'arraySimple'){
834 $array_typename = 'SOAP-ENC:Array';
835 } elseif(isset($tt) && $tt == 'arrayStruct'){
836 $array_typename = 'unnamed_struct_use_soapval';
838 // if type is prefixed, create type prefix
839 if ($tt_ns != '' && $tt_ns == $this->namespaces['xsd']){
840 $array_typename = 'xsd:' . $tt;
842 $tt_prefix = 'ns' . rand(1000, 9999);
843 $array_typename = "$tt_prefix:$tt";
844 $xmlns .= " xmlns:$tt_prefix=\"$tt_ns\"";
846 $array_typename = $tt;
850 if ($use == 'literal') {
852 } else if (isset($type) && isset($type_prefix)) {
853 $type_str = " xsi:type=\"$type_prefix:$type\"";
855 $type_str = " xsi:type=\"SOAP-ENC:Array\" SOAP-ENC:arrayType=\"".$array_typename."[$array_type]\"";
859 if ($use == 'literal') {
861 } else if (isset($type) && isset($type_prefix)) {
862 $type_str = " xsi:type=\"$type_prefix:$type\"";
864 $type_str = " xsi:type=\"SOAP-ENC:Array\" SOAP-ENC:arrayType=\"xsd:anyType[0]\"";
867 // TODO: for array in literal, there is no wrapper here
868 $xml = "<$name$xmlns$type_str$atts>".$xml."</$name>";
871 $this->debug("serialize_val: serialize struct");
872 if(isset($type) && isset($type_prefix)){
873 $type_str = " xsi:type=\"$type_prefix:$type\"";
877 if ($use == 'literal') {
878 $xml .= "<$name$xmlns$atts>";
880 $xml .= "<$name$xmlns$type_str$atts>";
882 foreach($val as $k => $v){
884 if ($type == 'Map' && $type_ns == 'http://xml.apache.org/xml-soap') {
886 $xml .= $this->serialize_val($k,'key',false,false,false,false,$use);
887 $xml .= $this->serialize_val($v,'value',false,false,false,false,$use);
890 $xml .= $this->serialize_val($v,$k,false,false,false,false,$use);
897 $this->debug("serialize_val: serialize unknown");
898 $xml .= 'not detected, got '.gettype($val).' for '.$val;
901 $this->debug("serialize_val returning $xml");
906 * serializes a message
908 * @param string $body the XML of the SOAP body
909 * @param mixed $headers optional string of XML with SOAP header content, or array of soapval objects for SOAP headers, or associative array
910 * @param array $namespaces optional the namespaces used in generating the body and headers
911 * @param string $style optional (rpc|document)
912 * @param string $use optional (encoded|literal)
913 * @param string $encodingStyle optional (usually 'http://schemas.xmlsoap.org/soap/encoding/' for encoded)
914 * @return string the message
917 function serializeEnvelope($body,$headers=false,$namespaces=array(),$style='rpc',$use='encoded',$encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'){
918 // TODO: add an option to automatically run utf8_encode on $body and $headers
919 // if $this->soap_defencoding is UTF-8. Not doing this automatically allows
920 // one to send arbitrary UTF-8 characters, not just characters that map to ISO-8859-1
922 $this->debug("In serializeEnvelope length=" . strlen($body) . " body (max 1000 characters)=" . substr($body, 0, 1000) . " style=$style use=$use encodingStyle=$encodingStyle");
923 $this->debug("headers:");
924 $this->appendDebug($this->varDump($headers));
925 $this->debug("namespaces:");
926 $this->appendDebug($this->varDump($namespaces));
928 // serialize namespaces
930 foreach(array_merge($this->namespaces,$namespaces) as $k => $v){
931 $ns_string .= " xmlns:$k=\"$v\"";
934 $ns_string = " SOAP-ENV:encodingStyle=\"$encodingStyle\"$ns_string";
939 if (is_array($headers)) {
941 foreach ($headers as $k => $v) {
942 if (is_object($v) && get_class($v) == 'soapval') {
943 $xml .= $this->serialize_val($v, false, false, false, false, false, $use);
945 $xml .= $this->serialize_val($v, $k, false, false, false, false, $use);
949 $this->debug("In serializeEnvelope, serialized array of headers to $headers");
951 $headers = "<SOAP-ENV:Header>".$headers."</SOAP-ENV:Header>";
953 // serialize envelope
955 '<?xml version="1.0" encoding="'.$this->soap_defencoding .'"?'.">".
956 '<SOAP-ENV:Envelope'.$ns_string.">".
961 "</SOAP-ENV:Envelope>";
965 * formats a string to be inserted into an HTML stream
967 * @param string $str The string to format
968 * @return string The formatted string
972 function formatDump($str){
973 $str = htmlspecialchars($str);
978 * contracts (changes namespace to prefix) a qualified name
980 * @param string $qname qname
981 * @return string contracted qname
984 function contractQname($qname){
985 // get element namespace
986 //$this->xdebug("Contract $qname");
987 if (strrpos($qname, ':')) {
988 // get unqualified name
989 $name = substr($qname, strrpos($qname, ':') + 1);
991 $ns = substr($qname, 0, strrpos($qname, ':'));
992 $p = $this->getPrefixFromNamespace($ns);
994 return $p . ':' . $name;
1003 * expands (changes prefix to namespace) a qualified name
1005 * @param string $qname qname
1006 * @return string expanded qname
1009 function expandQname($qname){
1010 // get element prefix
1011 if(strpos($qname,':') && !preg_match('/^http:\/\//',$qname)){
1012 // get unqualified name
1013 $name = substr(strstr($qname,':'),1);
1015 $prefix = substr($qname,0,strpos($qname,':'));
1016 if(isset($this->namespaces[$prefix])){
1017 return $this->namespaces[$prefix].':'.$name;
1027 * returns the local part of a prefixed string
1028 * returns the original string, if not prefixed
1030 * @param string $str The prefixed string
1031 * @return string The local part
1034 function getLocalPart($str){
1035 if($sstr = strrchr($str,':')){
1036 // get unqualified name
1037 return substr( $sstr, 1 );
1044 * returns the prefix part of a prefixed string
1045 * returns false, if not prefixed
1047 * @param string $str The prefixed string
1048 * @return mixed The prefix or false if there is no prefix
1051 function getPrefix($str){
1052 if($pos = strrpos($str,':')){
1054 return substr($str,0,$pos);
1060 * pass it a prefix, it returns a namespace
1062 * @param string $prefix The prefix
1063 * @return mixed The namespace, false if no namespace has the specified prefix
1066 function getNamespaceFromPrefix($prefix){
1067 if (isset($this->namespaces[$prefix])) {
1068 return $this->namespaces[$prefix];
1070 //$this->setError("No namespace registered for prefix '$prefix'");
1075 * returns the prefix for a given namespace (or prefix)
1076 * or false if no prefixes registered for the given namespace
1078 * @param string $ns The namespace
1079 * @return mixed The prefix, false if the namespace has no prefixes
1082 function getPrefixFromNamespace($ns) {
1083 foreach ($this->namespaces as $p => $n) {
1084 if ($ns == $n || $ns == $p) {
1085 $this->usedNamespaces[$p] = $n;
1093 * returns the time in ODBC canonical form with microseconds
1095 * @return string The time in ODBC canonical form with microseconds
1098 function getmicrotime() {
1099 if (function_exists('gettimeofday')) {
1100 $tod = gettimeofday();
1102 $usec = $tod['usec'];
1107 return strftime('%Y-%m-%d %H:%M:%S', $sec) . '.' . sprintf('%06d', $usec);
1111 * Returns a string with the output of var_dump
1113 * @param mixed $data The variable to var_dump
1114 * @return string The output of var_dump
1117 function varDump($data) {
1118 if ($this->debugLevel <= 0) {
1123 $ret_val = ob_get_contents();
1129 * represents the object as a string
1134 function __toString() {
1135 return $this->varDump($this);
1139 // XML Schema Datatype Helper Functions
1141 //xsd:dateTime helpers
1144 * convert unix timestamp to ISO 8601 compliant date string
1146 * @param int $timestamp Unix time stamp
1147 * @param boolean $utc Whether the time stamp is UTC or local
1148 * @return mixed ISO 8601 date string or false
1151 function timestamp_to_iso8601($timestamp,$utc=true){
1152 $datestr = date('Y-m-d\TH:i:sO',$timestamp);
1153 $pos = strrpos($datestr, "+");
1154 if ($pos === FALSE) {
1155 $pos = strrpos($datestr, "-");
1157 if ($pos !== FALSE) {
1158 if (strlen($datestr) == $pos + 5) {
1159 $datestr = substr($datestr, 0, $pos + 3) . ':' . substr($datestr, -2);
1164 '([0-9]{4})-'. // centuries & years CCYY-
1165 '([0-9]{2})-'. // months MM-
1166 '([0-9]{2})'. // days DD
1168 '([0-9]{2}):'. // hours hh:
1169 '([0-9]{2}):'. // minutes mm:
1170 '([0-9]{2})(\.[0-9]*)?'. // seconds ss.ss...
1171 '(Z|[+\-][0-9]{2}:?[0-9]{2})?'. // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's
1174 if(preg_match($pattern,$datestr,$regs)){
1175 return sprintf('%04d-%02d-%02dT%02d:%02d:%02dZ',$regs[1],$regs[2],$regs[3],$regs[4],$regs[5],$regs[6]);
1184 * convert ISO 8601 compliant date string to unix timestamp
1186 * @param string $datestr ISO 8601 compliant date string
1187 * @return mixed Unix timestamp (int) or false
1190 function iso8601_to_timestamp($datestr){
1192 '([0-9]{4})-'. // centuries & years CCYY-
1193 '([0-9]{2})-'. // months MM-
1194 '([0-9]{2})'. // days DD
1196 '([0-9]{2}):'. // hours hh:
1197 '([0-9]{2}):'. // minutes mm:
1198 '([0-9]{2})(\.[0-9]+)?'. // seconds ss.ss...
1199 '(Z|[+\-][0-9]{2}:?[0-9]{2})?'. // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's
1201 if(preg_match($pattern,$datestr,$regs)){
1203 if($regs[8] != 'Z'){
1204 $op = substr($regs[8],0,1);
1205 $h = substr($regs[8],1,2);
1206 $m = substr($regs[8],strlen($regs[8])-2,2);
1208 $regs[4] = $regs[4] + $h;
1209 $regs[5] = $regs[5] + $m;
1210 } elseif($op == '+'){
1211 $regs[4] = $regs[4] - $h;
1212 $regs[5] = $regs[5] - $m;
1215 return gmmktime($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]);
1216 // return strtotime("$regs[1]-$regs[2]-$regs[3] $regs[4]:$regs[5]:$regs[6]Z");
1223 * sleeps some number of microseconds
1225 * @param string $usec the number of microseconds to sleep
1229 function usleepWindows($usec)
1231 $start = gettimeofday();
1235 $stop = gettimeofday();
1236 $timePassed = 1000000 * ($stop['sec'] - $start['sec'])
1237 + $stop['usec'] - $start['usec'];
1239 while ($timePassed < $usec);
1246 Modification information for LGPL compliance
1248 r58622 - 2010-10-22 18:18:59 -0700 (Fri, 22 Oct 2010) - engsvnbuild - Author: lam <lam@198.18.142.201>
1251 r58361 - 2010-09-29 16:59:02 -0700 (Wed, 29 Sep 2010) - kjing - Author: Jenny Gonsalves <jenny@sugarcrm.com>
1252 Merging with maint_6_0_1 (svn merge -r 58250:58342)
1254 r57813 - 2010-08-19 10:34:44 -0700 (Thu, 19 Aug 2010) - kjing - Author: John Mertic <jmertic@sugarcrm.com>
1255 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.
1257 r57707 - 2010-08-10 12:26:13 -0700 (Tue, 10 Aug 2010) - kjing - Author: Stanislav Malyshev <smalyshev@gmail.com>
1258 fix SOAP calls with no parameters
1260 r56990 - 2010-06-16 13:05:36 -0700 (Wed, 16 Jun 2010) - kjing - snapshot "Mango" svn branch to a new one for GitHub sync
1262 r56989 - 2010-06-16 13:01:33 -0700 (Wed, 16 Jun 2010) - kjing - defunt "Mango" svn dev branch before github cutover
1264 r55980 - 2010-04-19 13:31:28 -0700 (Mon, 19 Apr 2010) - kjing - create Mango (6.1) based on windex
1266 r51719 - 2009-10-22 10:18:00 -0700 (Thu, 22 Oct 2009) - mitani - Converted to Build 3 tags and updated the build system
1268 r51634 - 2009-10-19 13:32:22 -0700 (Mon, 19 Oct 2009) - mitani - Windex is the branch for Sugar Sales 1.0 development
1270 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.
1272 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.
1274 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:
1275 - Changing all ereg function to either preg or simple string based ones
1276 - No more references to magic quotes.
1277 - Change all the session_unregister() functions to just unset() the correct session variable instead.
1279 r50375 - 2009-08-24 18:07:43 -0700 (Mon, 24 Aug 2009) - dwong - branch kobe2 from tokyo r50372
1281 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
1283 r45680 - 2009-03-30 14:34:35 -0700 (Mon, 30 Mar 2009) - Samir Gandhi - modifeid serializeSchema to generate WS-I compliant WSDL
1285 r42807 - 2008-12-29 11:16:59 -0800 (Mon, 29 Dec 2008) - dwong - Branch from trunk/sugarcrm r42806 to branches/tokyo/sugarcrm
1287 r42645 - 2008-12-18 13:41:08 -0800 (Thu, 18 Dec 2008) - awu - merging maint_5_2_0 rev41336:HEAD to trunk
1289 r41647 - 2008-11-11 17:44:30 -0800 (Tue, 11 Nov 2008) - majed - Fixes a few bugs
1291 r41596 - 2008-11-10 19:20:04 -0800 (Mon, 10 Nov 2008) - Samir Gandhi - modified to set $method in the code
1293 r41558 - 2008-11-10 14:35:34 -0800 (Mon, 10 Nov 2008) - majed - changes nusoap to allow for registering classes
1295 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.
1297 - data/SugarBean.php
1298 - include/domit/php_http_client_generic.php
1299 - include/domit/php_http_connector.php
1300 - include/domit/testing_domit.php
1301 - include/domit/xml_domit_getelementsbypath.php
1302 - include/domit/xml_domit_lite_parser.php
1303 - include/domit/xml_domit_nodemaps.php
1304 - include/domit/xml_domit_parser.php
1305 - include/domit/xml_domit_shared.php
1306 - include/generic/SugarWidgets/SugarWidgetField.php
1307 - include/generic/SugarWidgets/SugarWidgetReportField.php
1308 - include/ListView/ProcessView.php
1309 - include/nusoap/class.soapclient.php
1310 - include/nusoap/nusoap.php
1311 - include/nusoap/nusoapmime.php
1312 - include/Pear/HTML_Safe/Safe.php
1313 - include/Pear/XML_HTMLSax3/HTMLSax3.php
1314 - modules/Administration/RebuildWorkFlow.php
1315 - modules/Expressions/RelateSelector.php
1316 - modules/Reports/templates/templates_reports.php
1317 - modules/WorkFlow/Delete.php
1318 - modules/WorkFlow/Save.php
1319 - modules/WorkFlow/SaveSequence.php
1320 - modules/WorkFlow/WorkFlow.php
1321 - modules/WorkFlowActionShells/CreateStep1.php
1322 - modules/WorkFlowActionShells/CreateStep2.php
1323 - modules/WorkFlowActionShells/Save.php
1324 - modules/WorkFlowActionShells/WorkFlowActionShell.php
1325 - modules/WorkFlowAlerts/Save.php
1326 - modules/WorkFlowAlerts/WorkFlowAlert.php
1327 - modules/WorkFlowAlertShells/DetailView.php
1328 - modules/WorkFlowAlertShells/WorkFlowAlertShell.php
1329 - modules/WorkFlowTriggerShells/CreateStep1.php
1330 - modules/WorkFlowTriggerShells/CreateStepFilter.php
1331 - modules/WorkFlowTriggerShells/SaveFilter.php
1332 - modules/WorkFlowTriggerShells/WorkFlowTriggerShell.php
1333 - soap/SoapHelperFunctions.php
1334 - test/modules/DynamicFields/DynamicFields_Bug24095_test.php
1335 - test/simpletest/browser.php
1336 - test/simpletest/default_reporter.php
1337 - test/simpletest/detached.php
1338 - test/simpletest/eclipse.php
1339 - test/simpletest/expectation.php
1340 - test/simpletest/extensions/pear_test_case.php
1341 - test/simpletest/form.php
1342 - test/simpletest/http.php
1343 - test/simpletest/mock_objects.php
1344 - test/simpletest/page.php
1345 - test/simpletest/parser.php
1346 - test/simpletest/remote.php
1347 - test/simpletest/shell_tester.php
1348 - test/simpletest/simple_test.php
1349 - test/simpletest/simpletest.php
1350 - test/simpletest/test/acceptance_test.php
1351 - test/simpletest/test/adapter_test.php
1352 - test/simpletest/test/authentication_test.php
1353 - test/simpletest/test/browser_test.php
1354 - test/simpletest/test/collector_test.php
1355 - test/simpletest/test/compatibility_test.php
1356 - test/simpletest/test/detached_test.php
1357 - test/simpletest/test/eclipse_test.php
1358 - test/simpletest/test/encoding_test.php
1359 - test/simpletest/test/errors_test.php
1360 - test/simpletest/test/expectation_test.php
1361 - test/simpletest/test/form_test.php
1362 - test/simpletest/test/frames_test.php
1363 - test/simpletest/test/http_test.php
1364 - test/simpletest/test/live_test.php
1365 - test/simpletest/test/mock_objects_test.php
1366 - test/simpletest/test/page_test.php
1367 - test/simpletest/test/parse_error_test.php
1368 - test/simpletest/test/parser_test.php
1369 - test/simpletest/test/remote_test.php
1370 - test/simpletest/test/shell_test.php
1371 - test/simpletest/test/shell_tester_test.php
1372 - test/simpletest/test/simpletest_test.php
1373 - test/simpletest/test/site/page_request.php
1374 - test/simpletest/test/tag_test.php
1375 - test/simpletest/test/unit_tester_test.php
1376 - test/simpletest/test/user_agent_test.php
1377 - test/simpletest/test/visual_test.php
1378 - test/simpletest/test/xml_test.php
1379 - test/simpletest/test_case.php
1380 - test/simpletest/ui/array_reporter/test.php
1381 - test/simpletest/ui/recorder/test.php
1382 - test/simpletest/unit_tester.php
1383 - test/simpletest/url.php
1384 - test/simpletest/user_agent.php
1385 - test/simpletest/web_tester.php
1386 - test/spikephpcoverage/src/PEAR.php
1387 - test/spikephpcoverage/src/util/Utility.php
1388 - test/spikephpcoverage/src/XML/Parser.php
1389 - test/spikephpcoverage/src/XML/Parser/Simple.php
1390 - test/test_utilities/SugarTest_SimpleBrowser.php
1392 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.
1394 r38300 - 2008-07-25 13:33:43 -0700 (Fri, 25 Jul 2008) - Samir Gandhi - put the debug in parseresponse function
1396 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
1398 r36824 - 2008-06-18 09:26:11 -0700 (Wed, 18 Jun 2008) - roger - bug: 21832
1400 r26422 - 2007-09-05 17:29:12 -0700 (Wed, 05 Sep 2007) - majed - migrate from beta 1 to trunk
1402 r15787 - 2006-08-10 10:14:41 -0700 (Thu, 10 Aug 2006) - roger - RRS: bug 7961
1404 r14701 - 2006-07-17 13:37:26 -0700 (Mon, 17 Jul 2006) - roger - RRS: bug 5801
1406 r13782 - 2006-06-06 10:58:55 -0700 (Tue, 06 Jun 2006) - majed - changes entry point code
1408 r11466 - 2006-02-01 15:49:47 -0800 (Wed, 01 Feb 2006) - jacob - Adding extra !empty check to get around a PHP warning.
1410 r11115 - 2006-01-17 14:54:45 -0800 (Tue, 17 Jan 2006) - majed - add entry point validation
1412 r10585 - 2005-12-13 14:42:26 -0800 (Tue, 13 Dec 2005) - majed - adds new license mechanisim
1414 r10170 - 2005-12-05 18:37:46 -0800 (Mon, 05 Dec 2005) - majed - fixes various issues
1416 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.
1418 r8991 - 2005-11-03 19:07:25 -0800 (Thu, 03 Nov 2005) - majed - fixes nusoap issue
1420 r8846 - 2005-10-31 11:01:12 -0800 (Mon, 31 Oct 2005) - majed - new version of nusoap
1422 r7905 - 2005-09-21 19:12:57 -0700 (Wed, 21 Sep 2005) - majed - restores old nusoap pre & with a few fixes
1424 r7861 - 2005-09-20 15:40:25 -0700 (Tue, 20 Sep 2005) - majed - & fix for 3.5.1
1426 r7452 - 2005-08-17 11:32:34 -0700 (Wed, 17 Aug 2005) - majed - changes soap to nusoap
1428 r5820 - 2005-06-21 14:22:24 -0700 (Tue, 21 Jun 2005) - majed - fixes issues with nusoap and with custom fields
1430 r5462 - 2005-05-25 13:50:11 -0700 (Wed, 25 May 2005) - majed - upgraded nusoap to .6.9
1432 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
1434 r573 - 2004-09-04 13:03:32 -0700 (Sat, 04 Sep 2004) - sugarclint - undoing copyrights added in inadvertantly. --clint
1436 r546 - 2004-09-03 11:49:38 -0700 (Fri, 03 Sep 2004) - sugarmsi - removed echo count
1438 r354 - 2004-08-02 23:00:37 -0700 (Mon, 02 Aug 2004) - sugarjacob - Adding Soap
1448 * Contains information for a SOAP fault.
1449 * Mainly used for returning faults from deployed functions
1450 * in a server instance.
1451 * @author Dietrich Ayala <dietrich@ganx4.com>
1455 class nusoap_fault extends nusoap_base {
1457 * The fault code (client|server)
1469 * The fault string, a description of the fault
1475 * The fault detail, typically a string or array of string
1484 * @param string $faultcode (SOAP-ENV:Client | SOAP-ENV:Server)
1485 * @param string $faultactor only used when msg routed between multiple actors
1486 * @param string $faultstring human readable error message
1487 * @param mixed $faultdetail detail, typically a string or array of string
1489 function nusoap_fault($faultcode,$faultactor='',$faultstring='',$faultdetail=''){
1490 parent::nusoap_base();
1491 $this->faultcode = $faultcode;
1492 $this->faultactor = $faultactor;
1493 $this->faultstring = $faultstring;
1494 $this->faultdetail = $faultdetail;
1500 * @return string The serialization of the fault instance.
1503 function serialize(){
1505 foreach($this->namespaces as $k => $v){
1506 $ns_string .= "\n xmlns:$k=\"$v\"";
1509 '<?xml version="1.0" encoding="'.$this->soap_defencoding.'"?>'.
1510 '<SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"'.$ns_string.">\n".
1513 $this->serialize_val($this->faultcode, 'faultcode').
1514 $this->serialize_val($this->faultactor, 'faultactor').
1515 $this->serialize_val($this->faultstring, 'faultstring').
1516 $this->serialize_val($this->faultdetail, 'detail').
1517 '</SOAP-ENV:Fault>'.
1519 '</SOAP-ENV:Envelope>';
1525 * Backward compatibility
1527 class soap_fault extends nusoap_fault {
1534 Modification information for LGPL compliance
1536 r58622 - 2010-10-22 18:18:59 -0700 (Fri, 22 Oct 2010) - engsvnbuild - Author: lam <lam@198.18.142.201>
1539 r58361 - 2010-09-29 16:59:02 -0700 (Wed, 29 Sep 2010) - kjing - Author: Jenny Gonsalves <jenny@sugarcrm.com>
1540 Merging with maint_6_0_1 (svn merge -r 58250:58342)
1542 r57813 - 2010-08-19 10:34:44 -0700 (Thu, 19 Aug 2010) - kjing - Author: John Mertic <jmertic@sugarcrm.com>
1543 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.
1545 r57707 - 2010-08-10 12:26:13 -0700 (Tue, 10 Aug 2010) - kjing - Author: Stanislav Malyshev <smalyshev@gmail.com>
1546 fix SOAP calls with no parameters
1548 r56990 - 2010-06-16 13:05:36 -0700 (Wed, 16 Jun 2010) - kjing - snapshot "Mango" svn branch to a new one for GitHub sync
1550 r56989 - 2010-06-16 13:01:33 -0700 (Wed, 16 Jun 2010) - kjing - defunt "Mango" svn dev branch before github cutover
1552 r55980 - 2010-04-19 13:31:28 -0700 (Mon, 19 Apr 2010) - kjing - create Mango (6.1) based on windex
1554 r51719 - 2009-10-22 10:18:00 -0700 (Thu, 22 Oct 2009) - mitani - Converted to Build 3 tags and updated the build system
1556 r51634 - 2009-10-19 13:32:22 -0700 (Mon, 19 Oct 2009) - mitani - Windex is the branch for Sugar Sales 1.0 development
1558 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.
1560 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.
1562 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:
1563 - Changing all ereg function to either preg or simple string based ones
1564 - No more references to magic quotes.
1565 - Change all the session_unregister() functions to just unset() the correct session variable instead.
1567 r50375 - 2009-08-24 18:07:43 -0700 (Mon, 24 Aug 2009) - dwong - branch kobe2 from tokyo r50372
1569 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
1571 r45680 - 2009-03-30 14:34:35 -0700 (Mon, 30 Mar 2009) - Samir Gandhi - modifeid serializeSchema to generate WS-I compliant WSDL
1573 r42807 - 2008-12-29 11:16:59 -0800 (Mon, 29 Dec 2008) - dwong - Branch from trunk/sugarcrm r42806 to branches/tokyo/sugarcrm
1575 r42645 - 2008-12-18 13:41:08 -0800 (Thu, 18 Dec 2008) - awu - merging maint_5_2_0 rev41336:HEAD to trunk
1577 r41647 - 2008-11-11 17:44:30 -0800 (Tue, 11 Nov 2008) - majed - Fixes a few bugs
1579 r41596 - 2008-11-10 19:20:04 -0800 (Mon, 10 Nov 2008) - Samir Gandhi - modified to set $method in the code
1581 r41558 - 2008-11-10 14:35:34 -0800 (Mon, 10 Nov 2008) - majed - changes nusoap to allow for registering classes
1583 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.
1585 - data/SugarBean.php
1586 - include/domit/php_http_client_generic.php
1587 - include/domit/php_http_connector.php
1588 - include/domit/testing_domit.php
1589 - include/domit/xml_domit_getelementsbypath.php
1590 - include/domit/xml_domit_lite_parser.php
1591 - include/domit/xml_domit_nodemaps.php
1592 - include/domit/xml_domit_parser.php
1593 - include/domit/xml_domit_shared.php
1594 - include/generic/SugarWidgets/SugarWidgetField.php
1595 - include/generic/SugarWidgets/SugarWidgetReportField.php
1596 - include/ListView/ProcessView.php
1597 - include/nusoap/class.soapclient.php
1598 - include/nusoap/nusoap.php
1599 - include/nusoap/nusoapmime.php
1600 - include/Pear/HTML_Safe/Safe.php
1601 - include/Pear/XML_HTMLSax3/HTMLSax3.php
1602 - modules/Administration/RebuildWorkFlow.php
1603 - modules/Expressions/RelateSelector.php
1604 - modules/Reports/templates/templates_reports.php
1605 - modules/WorkFlow/Delete.php
1606 - modules/WorkFlow/Save.php
1607 - modules/WorkFlow/SaveSequence.php
1608 - modules/WorkFlow/WorkFlow.php
1609 - modules/WorkFlowActionShells/CreateStep1.php
1610 - modules/WorkFlowActionShells/CreateStep2.php
1611 - modules/WorkFlowActionShells/Save.php
1612 - modules/WorkFlowActionShells/WorkFlowActionShell.php
1613 - modules/WorkFlowAlerts/Save.php
1614 - modules/WorkFlowAlerts/WorkFlowAlert.php
1615 - modules/WorkFlowAlertShells/DetailView.php
1616 - modules/WorkFlowAlertShells/WorkFlowAlertShell.php
1617 - modules/WorkFlowTriggerShells/CreateStep1.php
1618 - modules/WorkFlowTriggerShells/CreateStepFilter.php
1619 - modules/WorkFlowTriggerShells/SaveFilter.php
1620 - modules/WorkFlowTriggerShells/WorkFlowTriggerShell.php
1621 - soap/SoapHelperFunctions.php
1622 - test/modules/DynamicFields/DynamicFields_Bug24095_test.php
1623 - test/simpletest/browser.php
1624 - test/simpletest/default_reporter.php
1625 - test/simpletest/detached.php
1626 - test/simpletest/eclipse.php
1627 - test/simpletest/expectation.php
1628 - test/simpletest/extensions/pear_test_case.php
1629 - test/simpletest/form.php
1630 - test/simpletest/http.php
1631 - test/simpletest/mock_objects.php
1632 - test/simpletest/page.php
1633 - test/simpletest/parser.php
1634 - test/simpletest/remote.php
1635 - test/simpletest/shell_tester.php
1636 - test/simpletest/simple_test.php
1637 - test/simpletest/simpletest.php
1638 - test/simpletest/test/acceptance_test.php
1639 - test/simpletest/test/adapter_test.php
1640 - test/simpletest/test/authentication_test.php
1641 - test/simpletest/test/browser_test.php
1642 - test/simpletest/test/collector_test.php
1643 - test/simpletest/test/compatibility_test.php
1644 - test/simpletest/test/detached_test.php
1645 - test/simpletest/test/eclipse_test.php
1646 - test/simpletest/test/encoding_test.php
1647 - test/simpletest/test/errors_test.php
1648 - test/simpletest/test/expectation_test.php
1649 - test/simpletest/test/form_test.php
1650 - test/simpletest/test/frames_test.php
1651 - test/simpletest/test/http_test.php
1652 - test/simpletest/test/live_test.php
1653 - test/simpletest/test/mock_objects_test.php
1654 - test/simpletest/test/page_test.php
1655 - test/simpletest/test/parse_error_test.php
1656 - test/simpletest/test/parser_test.php
1657 - test/simpletest/test/remote_test.php
1658 - test/simpletest/test/shell_test.php
1659 - test/simpletest/test/shell_tester_test.php
1660 - test/simpletest/test/simpletest_test.php
1661 - test/simpletest/test/site/page_request.php
1662 - test/simpletest/test/tag_test.php
1663 - test/simpletest/test/unit_tester_test.php
1664 - test/simpletest/test/user_agent_test.php
1665 - test/simpletest/test/visual_test.php
1666 - test/simpletest/test/xml_test.php
1667 - test/simpletest/test_case.php
1668 - test/simpletest/ui/array_reporter/test.php
1669 - test/simpletest/ui/recorder/test.php
1670 - test/simpletest/unit_tester.php
1671 - test/simpletest/url.php
1672 - test/simpletest/user_agent.php
1673 - test/simpletest/web_tester.php
1674 - test/spikephpcoverage/src/PEAR.php
1675 - test/spikephpcoverage/src/util/Utility.php
1676 - test/spikephpcoverage/src/XML/Parser.php
1677 - test/spikephpcoverage/src/XML/Parser/Simple.php
1678 - test/test_utilities/SugarTest_SimpleBrowser.php
1680 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.
1682 r38300 - 2008-07-25 13:33:43 -0700 (Fri, 25 Jul 2008) - Samir Gandhi - put the debug in parseresponse function
1684 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
1686 r36824 - 2008-06-18 09:26:11 -0700 (Wed, 18 Jun 2008) - roger - bug: 21832
1688 r26422 - 2007-09-05 17:29:12 -0700 (Wed, 05 Sep 2007) - majed - migrate from beta 1 to trunk
1690 r15787 - 2006-08-10 10:14:41 -0700 (Thu, 10 Aug 2006) - roger - RRS: bug 7961
1692 r14701 - 2006-07-17 13:37:26 -0700 (Mon, 17 Jul 2006) - roger - RRS: bug 5801
1694 r13782 - 2006-06-06 10:58:55 -0700 (Tue, 06 Jun 2006) - majed - changes entry point code
1696 r11466 - 2006-02-01 15:49:47 -0800 (Wed, 01 Feb 2006) - jacob - Adding extra !empty check to get around a PHP warning.
1698 r11115 - 2006-01-17 14:54:45 -0800 (Tue, 17 Jan 2006) - majed - add entry point validation
1700 r10585 - 2005-12-13 14:42:26 -0800 (Tue, 13 Dec 2005) - majed - adds new license mechanisim
1702 r10170 - 2005-12-05 18:37:46 -0800 (Mon, 05 Dec 2005) - majed - fixes various issues
1704 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.
1706 r8991 - 2005-11-03 19:07:25 -0800 (Thu, 03 Nov 2005) - majed - fixes nusoap issue
1708 r8846 - 2005-10-31 11:01:12 -0800 (Mon, 31 Oct 2005) - majed - new version of nusoap
1710 r7905 - 2005-09-21 19:12:57 -0700 (Wed, 21 Sep 2005) - majed - restores old nusoap pre & with a few fixes
1712 r7861 - 2005-09-20 15:40:25 -0700 (Tue, 20 Sep 2005) - majed - & fix for 3.5.1
1714 r7452 - 2005-08-17 11:32:34 -0700 (Wed, 17 Aug 2005) - majed - changes soap to nusoap
1716 r5820 - 2005-06-21 14:22:24 -0700 (Tue, 21 Jun 2005) - majed - fixes issues with nusoap and with custom fields
1718 r5462 - 2005-05-25 13:50:11 -0700 (Wed, 25 May 2005) - majed - upgraded nusoap to .6.9
1720 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
1722 r573 - 2004-09-04 13:03:32 -0700 (Sat, 04 Sep 2004) - sugarclint - undoing copyrights added in inadvertantly. --clint
1724 r546 - 2004-09-03 11:49:38 -0700 (Fri, 03 Sep 2004) - sugarmsi - removed echo count
1726 r354 - 2004-08-02 23:00:37 -0700 (Mon, 02 Aug 2004) - sugarjacob - Adding Soap
1736 * parses an XML Schema, allows access to it's data, other utility methods.
1737 * imperfect, no validation... yet, but quite functional.
1739 * @author Dietrich Ayala <dietrich@ganx4.com>
1740 * @author Scott Nichol <snichol@users.sourceforge.net>
1744 class nusoap_xmlschema extends nusoap_base {
1750 var $enclosingNamespaces;
1752 var $schemaInfo = array();
1753 var $schemaTargetNamespace = '';
1754 // types, elements, attributes defined by the schema
1755 var $attributes = array();
1756 var $complexTypes = array();
1757 var $complexTypeStack = array();
1758 var $currentComplexType = null;
1759 var $elements = array();
1760 var $elementStack = array();
1761 var $currentElement = null;
1762 var $simpleTypes = array();
1763 var $simpleTypeStack = array();
1764 var $currentSimpleType = null;
1766 var $imports = array();
1771 var $depth_array = array();
1772 var $message = array();
1773 var $defaultNamespace = array();
1778 * @param string $schema schema document URI
1779 * @param string $xml xml document URI
1780 * @param string $namespaces namespaces defined in enclosing XML
1783 function nusoap_xmlschema($schema='',$xml='',$namespaces=array()){
1784 parent::nusoap_base();
1785 $this->debug('nusoap_xmlschema class instantiated, inside constructor');
1787 $this->schema = $schema;
1791 $this->enclosingNamespaces = $namespaces;
1792 $this->namespaces = array_merge($this->namespaces, $namespaces);
1794 // parse schema file
1796 $this->debug('initial schema file: '.$schema);
1797 $this->parseFile($schema, 'schema');
1802 $this->debug('initial xml file: '.$xml);
1803 $this->parseFile($xml, 'xml');
1811 * @param string $xml path/URL to XML file
1812 * @param string $type (schema | xml)
1816 function parseFile($xml,$type){
1819 $xmlStr = @join("",@file($xml));
1821 $msg = 'Error reading XML from '.$xml;
1822 $this->setError($msg);
1826 $this->debug("parsing $xml");
1827 $this->parseString($xmlStr,$type);
1828 $this->debug("done parsing $xml");
1836 * parse an XML string
1838 * @param string $xml path or URL
1839 * @param string $type (schema|xml)
1842 function parseString($xml,$type){
1846 // Create an XML parser.
1847 $this->parser = xml_parser_create();
1848 // Set the options for parsing the XML data.
1849 xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
1851 // Set the object for the parser.
1852 xml_set_object($this->parser, $this);
1854 // Set the element handlers for the parser.
1855 if($type == "schema"){
1856 xml_set_element_handler($this->parser, 'schemaStartElement','schemaEndElement');
1857 xml_set_character_data_handler($this->parser,'schemaCharacterData');
1858 } elseif($type == "xml"){
1859 xml_set_element_handler($this->parser, 'xmlStartElement','xmlEndElement');
1860 xml_set_character_data_handler($this->parser,'xmlCharacterData');
1863 // Parse the XML file.
1864 if(!xml_parse($this->parser,$xml,true)){
1865 // Display an error message.
1866 $errstr = sprintf('XML error parsing XML schema on line %d: %s',
1867 xml_get_current_line_number($this->parser),
1868 xml_error_string(xml_get_error_code($this->parser))
1870 $this->debug($errstr);
1871 $this->debug("XML payload:\n" . $xml);
1872 $this->setError($errstr);
1875 xml_parser_free($this->parser);
1877 $this->debug('no xml passed to parseString()!!');
1878 $this->setError('no xml passed to parseString()!!');
1883 * gets a type name for an unnamed type
1885 * @param string Element name
1886 * @return string A type name for an unnamed type
1889 function CreateTypeName($ename) {
1891 for ($i = 0; $i < count($this->complexTypeStack); $i++) {
1892 $scope .= $this->complexTypeStack[$i] . '_';
1894 return $scope . $ename . '_ContainedType';
1898 * start-element handler
1900 * @param string $parser XML parser object
1901 * @param string $name element name
1902 * @param string $attrs associative array of attributes
1905 function schemaStartElement($parser, $name, $attrs) {
1907 // position in the total number of elements, starting from 0
1908 $pos = $this->position++;
1909 $depth = $this->depth++;
1910 // set self as current value for this depth
1911 $this->depth_array[$depth] = $pos;
1912 $this->message[$pos] = array('cdata' => '');
1914 $this->defaultNamespace[$pos] = $this->defaultNamespace[$this->depth_array[$depth - 1]];
1916 $this->defaultNamespace[$pos] = false;
1919 // get element prefix
1920 if($prefix = $this->getPrefix($name)){
1921 // get unqualified name
1922 $name = $this->getLocalPart($name);
1927 // loop thru attributes, expanding, and registering namespace declarations
1928 if(count($attrs) > 0){
1929 foreach($attrs as $k => $v){
1930 // if ns declarations, add to class level array of valid namespaces
1931 if(preg_match('/^xmlns/',$k)){
1932 //$this->xdebug("$k: $v");
1933 //$this->xdebug('ns_prefix: '.$this->getPrefix($k));
1934 if($ns_prefix = substr(strrchr($k,':'),1)){
1935 //$this->xdebug("Add namespace[$ns_prefix] = $v");
1936 $this->namespaces[$ns_prefix] = $v;
1938 $this->defaultNamespace[$pos] = $v;
1939 if (! $this->getPrefixFromNamespace($v)) {
1940 $this->namespaces['ns'.(count($this->namespaces)+1)] = $v;
1943 if($v == 'http://www.w3.org/2001/XMLSchema' || $v == 'http://www.w3.org/1999/XMLSchema' || $v == 'http://www.w3.org/2000/10/XMLSchema'){
1944 $this->XMLSchemaVersion = $v;
1945 $this->namespaces['xsi'] = $v.'-instance';
1949 foreach($attrs as $k => $v){
1950 // expand each attribute
1951 $k = strpos($k,':') ? $this->expandQname($k) : $k;
1952 $v = strpos($v,':') ? $this->expandQname($v) : $v;
1959 // find status, register data
1961 case 'all': // (optional) compositor content for a complexType
1965 //$this->xdebug("compositor $name for currentComplexType: $this->currentComplexType and currentElement: $this->currentElement");
1966 $this->complexTypes[$this->currentComplexType]['compositor'] = $name;
1967 //if($name == 'all' || $name == 'sequence'){
1968 // $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
1971 case 'attribute': // complexType attribute
1972 //$this->xdebug("parsing attribute $attrs[name] $attrs[ref] of value: ".$attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']);
1973 $this->xdebug("parsing attribute:");
1974 $this->appendDebug($this->varDump($attrs));
1975 if (!isset($attrs['form'])) {
1976 // TODO: handle globals
1977 $attrs['form'] = $this->schemaInfo['attributeFormDefault'];
1979 if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])) {
1980 $v = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
1981 if (!strpos($v, ':')) {
1982 // no namespace in arrayType attribute value...
1983 if ($this->defaultNamespace[$pos]) {
1984 // ...so use the default
1985 $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'] = $this->defaultNamespace[$pos] . ':' . $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
1989 if(isset($attrs['name'])){
1990 $this->attributes[$attrs['name']] = $attrs;
1991 $aname = $attrs['name'];
1992 } elseif(isset($attrs['ref']) && $attrs['ref'] == 'http://schemas.xmlsoap.org/soap/encoding/:arrayType'){
1993 if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])) {
1994 $aname = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
1998 } elseif(isset($attrs['ref'])){
1999 $aname = $attrs['ref'];
2000 $this->attributes[$attrs['ref']] = $attrs;
2003 if($this->currentComplexType){ // This should *always* be
2004 $this->complexTypes[$this->currentComplexType]['attrs'][$aname] = $attrs;
2006 // arrayType attribute
2007 if(isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']) || $this->getLocalPart($aname) == 'arrayType'){
2008 $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
2009 $prefix = $this->getPrefix($aname);
2010 if(isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])){
2011 $v = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
2015 if(strpos($v,'[,]')){
2016 $this->complexTypes[$this->currentComplexType]['multidimensional'] = true;
2018 $v = substr($v,0,strpos($v,'[')); // clip the []
2019 if(!strpos($v,':') && isset($this->typemap[$this->XMLSchemaVersion][$v])){
2020 $v = $this->XMLSchemaVersion.':'.$v;
2022 $this->complexTypes[$this->currentComplexType]['arrayType'] = $v;
2025 case 'complexContent': // (optional) content for a complexType
2026 $this->xdebug("do nothing for element $name");
2029 array_push($this->complexTypeStack, $this->currentComplexType);
2030 if(isset($attrs['name'])){
2031 // TODO: what is the scope of named complexTypes that appear
2032 // nested within other c complexTypes?
2033 $this->xdebug('processing named complexType '.$attrs['name']);
2034 //$this->currentElement = false;
2035 $this->currentComplexType = $attrs['name'];
2036 $this->complexTypes[$this->currentComplexType] = $attrs;
2037 $this->complexTypes[$this->currentComplexType]['typeClass'] = 'complexType';
2038 // This is for constructs like
2039 // <complexType name="ListOfString" base="soap:Array">
2041 // <element name="string" type="xsd:string"
2042 // minOccurs="0" maxOccurs="unbounded" />
2045 if(isset($attrs['base']) && preg_match('/:Array$/',$attrs['base'])){
2046 $this->xdebug('complexType is unusual array');
2047 $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
2049 $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
2052 $name = $this->CreateTypeName($this->currentElement);
2053 $this->xdebug('processing unnamed complexType for element ' . $this->currentElement . ' named ' . $name);
2054 $this->currentComplexType = $name;
2055 //$this->currentElement = false;
2056 $this->complexTypes[$this->currentComplexType] = $attrs;
2057 $this->complexTypes[$this->currentComplexType]['typeClass'] = 'complexType';
2058 // This is for constructs like
2059 // <complexType name="ListOfString" base="soap:Array">
2061 // <element name="string" type="xsd:string"
2062 // minOccurs="0" maxOccurs="unbounded" />
2065 if(isset($attrs['base']) && preg_match('/:Array$/',$attrs['base'])){
2066 $this->xdebug('complexType is unusual array');
2067 $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
2069 $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
2072 $this->complexTypes[$this->currentComplexType]['simpleContent'] = 'false';
2075 array_push($this->elementStack, $this->currentElement);
2076 if (!isset($attrs['form'])) {
2077 if ($this->currentComplexType) {
2078 $attrs['form'] = $this->schemaInfo['elementFormDefault'];
2081 $attrs['form'] = 'qualified';
2084 if(isset($attrs['type'])){
2085 $this->xdebug("processing typed element ".$attrs['name']." of type ".$attrs['type']);
2086 if (! $this->getPrefix($attrs['type'])) {
2087 if ($this->defaultNamespace[$pos]) {
2088 $attrs['type'] = $this->defaultNamespace[$pos] . ':' . $attrs['type'];
2089 $this->xdebug('used default namespace to make type ' . $attrs['type']);
2092 // This is for constructs like
2093 // <complexType name="ListOfString" base="soap:Array">
2095 // <element name="string" type="xsd:string"
2096 // minOccurs="0" maxOccurs="unbounded" />
2099 if ($this->currentComplexType && $this->complexTypes[$this->currentComplexType]['phpType'] == 'array') {
2100 $this->xdebug('arrayType for unusual array is ' . $attrs['type']);
2101 $this->complexTypes[$this->currentComplexType]['arrayType'] = $attrs['type'];
2103 $this->currentElement = $attrs['name'];
2104 $ename = $attrs['name'];
2105 } elseif(isset($attrs['ref'])){
2106 $this->xdebug("processing element as ref to ".$attrs['ref']);
2107 $this->currentElement = "ref to ".$attrs['ref'];
2108 $ename = $this->getLocalPart($attrs['ref']);
2110 $type = $this->CreateTypeName($this->currentComplexType . '_' . $attrs['name']);
2111 $this->xdebug("processing untyped element " . $attrs['name'] . ' type ' . $type);
2112 $this->currentElement = $attrs['name'];
2113 $attrs['type'] = $this->schemaTargetNamespace . ':' . $type;
2114 $ename = $attrs['name'];
2116 if (isset($ename) && $this->currentComplexType) {
2117 $this->xdebug("add element $ename to complexType $this->currentComplexType");
2118 $this->complexTypes[$this->currentComplexType]['elements'][$ename] = $attrs;
2119 } elseif (!isset($attrs['ref'])) {
2120 $this->xdebug("add element $ename to elements array");
2121 $this->elements[ $attrs['name'] ] = $attrs;
2122 $this->elements[ $attrs['name'] ]['typeClass'] = 'element';
2125 case 'enumeration': // restriction value list member
2126 $this->xdebug('enumeration ' . $attrs['value']);
2127 if ($this->currentSimpleType) {
2128 $this->simpleTypes[$this->currentSimpleType]['enumeration'][] = $attrs['value'];
2129 } elseif ($this->currentComplexType) {
2130 $this->complexTypes[$this->currentComplexType]['enumeration'][] = $attrs['value'];
2133 case 'extension': // simpleContent or complexContent type extension
2134 $this->xdebug('extension ' . $attrs['base']);
2135 if ($this->currentComplexType) {
2136 $ns = $this->getPrefix($attrs['base']);
2138 $this->complexTypes[$this->currentComplexType]['extensionBase'] = $this->schemaTargetNamespace . ':' . $attrs['base'];
2140 $this->complexTypes[$this->currentComplexType]['extensionBase'] = $attrs['base'];
2143 $this->xdebug('no current complexType to set extensionBase');
2147 if (isset($attrs['schemaLocation'])) {
2148 $this->xdebug('import namespace ' . $attrs['namespace'] . ' from ' . $attrs['schemaLocation']);
2149 $this->imports[$attrs['namespace']][] = array('location' => $attrs['schemaLocation'], 'loaded' => false);
2151 $this->xdebug('import namespace ' . $attrs['namespace']);
2152 $this->imports[$attrs['namespace']][] = array('location' => '', 'loaded' => true);
2153 if (! $this->getPrefixFromNamespace($attrs['namespace'])) {
2154 $this->namespaces['ns'.(count($this->namespaces)+1)] = $attrs['namespace'];
2159 if (isset($attrs['schemaLocation'])) {
2160 $this->xdebug('include into namespace ' . $this->schemaTargetNamespace . ' from ' . $attrs['schemaLocation']);
2161 $this->imports[$this->schemaTargetNamespace][] = array('location' => $attrs['schemaLocation'], 'loaded' => false);
2163 $this->xdebug('ignoring invalid XML Schema construct: include without schemaLocation attribute');
2166 case 'list': // simpleType value list
2167 $this->xdebug("do nothing for element $name");
2169 case 'restriction': // simpleType, simpleContent or complexContent value restriction
2170 $this->xdebug('restriction ' . $attrs['base']);
2171 if($this->currentSimpleType){
2172 $this->simpleTypes[$this->currentSimpleType]['type'] = $attrs['base'];
2173 } elseif($this->currentComplexType){
2174 $this->complexTypes[$this->currentComplexType]['restrictionBase'] = $attrs['base'];
2175 if(strstr($attrs['base'],':') == ':Array'){
2176 $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
2181 $this->schemaInfo = $attrs;
2182 $this->schemaInfo['schemaVersion'] = $this->getNamespaceFromPrefix($prefix);
2183 if (isset($attrs['targetNamespace'])) {
2184 $this->schemaTargetNamespace = $attrs['targetNamespace'];
2186 if (!isset($attrs['elementFormDefault'])) {
2187 $this->schemaInfo['elementFormDefault'] = 'unqualified';
2189 if (!isset($attrs['attributeFormDefault'])) {
2190 $this->schemaInfo['attributeFormDefault'] = 'unqualified';
2193 case 'simpleContent': // (optional) content for a complexType
2194 if ($this->currentComplexType) { // This should *always* be
2195 $this->complexTypes[$this->currentComplexType]['simpleContent'] = 'true';
2197 $this->xdebug("do nothing for element $name because there is no current complexType");
2201 array_push($this->simpleTypeStack, $this->currentSimpleType);
2202 if(isset($attrs['name'])){
2203 $this->xdebug("processing simpleType for name " . $attrs['name']);
2204 $this->currentSimpleType = $attrs['name'];
2205 $this->simpleTypes[ $attrs['name'] ] = $attrs;
2206 $this->simpleTypes[ $attrs['name'] ]['typeClass'] = 'simpleType';
2207 $this->simpleTypes[ $attrs['name'] ]['phpType'] = 'scalar';
2209 $name = $this->CreateTypeName($this->currentComplexType . '_' . $this->currentElement);
2210 $this->xdebug('processing unnamed simpleType for element ' . $this->currentElement . ' named ' . $name);
2211 $this->currentSimpleType = $name;
2212 //$this->currentElement = false;
2213 $this->simpleTypes[$this->currentSimpleType] = $attrs;
2214 $this->simpleTypes[$this->currentSimpleType]['phpType'] = 'scalar';
2217 case 'union': // simpleType type list
2218 $this->xdebug("do nothing for element $name");
2221 $this->xdebug("do not have any logic to process element $name");
2226 * end-element handler
2228 * @param string $parser XML parser object
2229 * @param string $name element name
2232 function schemaEndElement($parser, $name) {
2233 // bring depth down a notch
2235 // position of current element is equal to the last value left in depth_array for my depth
2236 if(isset($this->depth_array[$this->depth])){
2237 $pos = $this->depth_array[$this->depth];
2239 // get element prefix
2240 if ($prefix = $this->getPrefix($name)){
2241 // get unqualified name
2242 $name = $this->getLocalPart($name);
2247 if($name == 'complexType'){
2248 $this->xdebug('done processing complexType ' . ($this->currentComplexType ? $this->currentComplexType : '(unknown)'));
2249 $this->xdebug($this->varDump($this->complexTypes[$this->currentComplexType]));
2250 $this->currentComplexType = array_pop($this->complexTypeStack);
2251 //$this->currentElement = false;
2253 if($name == 'element'){
2254 $this->xdebug('done processing element ' . ($this->currentElement ? $this->currentElement : '(unknown)'));
2255 $this->currentElement = array_pop($this->elementStack);
2257 if($name == 'simpleType'){
2258 $this->xdebug('done processing simpleType ' . ($this->currentSimpleType ? $this->currentSimpleType : '(unknown)'));
2259 $this->xdebug($this->varDump($this->simpleTypes[$this->currentSimpleType]));
2260 $this->currentSimpleType = array_pop($this->simpleTypeStack);
2265 * element content handler
2267 * @param string $parser XML parser object
2268 * @param string $data element content
2271 function schemaCharacterData($parser, $data){
2272 $pos = $this->depth_array[$this->depth - 1];
2273 $this->message[$pos]['cdata'] .= $data;
2277 * serialize the schema
2281 function serializeSchema(){
2283 $schemaPrefix = $this->getPrefixFromNamespace($this->XMLSchemaVersion);
2286 $schemaLocationCount = 0;
2287 if (sizeof($this->imports) > 0) {
2288 foreach($this->imports as $ns => $list) {
2289 foreach ($list as $ii) {
2290 if ($ii['location'] != '') {
2291 $xml .= " <$schemaPrefix:import location=\"" . $ii['location'] . '" namespace="' . $ns . "\" />\n";
2293 if ($schemaLocationCount == 0) {
2294 $xml .= " <$schemaPrefix:import namespace=\"" . $ns . "\" schemaLocation=\"" . $ns . "\"/>\n";
2296 $xml .= " <$schemaPrefix:import namespace=\"" . $ns . "\" />\n";
2303 foreach($this->complexTypes as $typeName => $attrs){
2305 // serialize child elements
2306 if(isset($attrs['elements']) && (count($attrs['elements']) > 0)){
2307 foreach($attrs['elements'] as $element => $eParts){
2308 if(isset($eParts['ref'])){
2309 $contentStr .= " <$schemaPrefix:element ref=\"$element\"/>\n";
2311 $contentStr .= " <$schemaPrefix:element name=\"$element\" type=\"" . $this->contractQName($eParts['type']) . "\"";
2312 foreach ($eParts as $aName => $aValue) {
2313 // handle, e.g., abstract, default, form, minOccurs, maxOccurs, nillable
2314 if ($aName != 'name' && $aName != 'type') {
2315 $contentStr .= " $aName=\"$aValue\"";
2318 $contentStr .= "/>\n";
2321 // compositor wraps elements
2322 if (isset($attrs['compositor']) && ($attrs['compositor'] != '')) {
2323 $contentStr = " <$schemaPrefix:$attrs[compositor]>\n".$contentStr." </$schemaPrefix:$attrs[compositor]>\n";
2327 if(isset($attrs['attrs']) && (count($attrs['attrs']) >= 1)){
2328 foreach($attrs['attrs'] as $attr => $aParts){
2329 $contentStr .= " <$schemaPrefix:attribute";
2330 foreach ($aParts as $a => $v) {
2331 if ($a == 'ref' || $a == 'type') {
2332 $contentStr .= " $a=\"".$this->contractQName($v).'"';
2333 } elseif ($a == 'http://schemas.xmlsoap.org/wsdl/:arrayType') {
2334 $this->usedNamespaces['wsdl'] = $this->namespaces['wsdl'];
2335 $contentStr .= ' wsdl:arrayType="'.$this->contractQName($v).'"';
2337 $contentStr .= " $a=\"$v\"";
2340 $contentStr .= "/>\n";
2344 if (isset($attrs['restrictionBase']) && $attrs['restrictionBase'] != ''){
2345 $contentStr = " <$schemaPrefix:restriction base=\"".$this->contractQName($attrs['restrictionBase'])."\">\n".$contentStr." </$schemaPrefix:restriction>\n";
2346 // complex or simple content
2347 if ((isset($attrs['elements']) && count($attrs['elements']) > 0) || (isset($attrs['attrs']) && count($attrs['attrs']) > 0)){
2348 $contentStr = " <$schemaPrefix:complexContent>\n".$contentStr." </$schemaPrefix:complexContent>\n";
2351 // finalize complex type
2352 if($contentStr != ''){
2353 $contentStr = " <$schemaPrefix:complexType name=\"$typeName\">\n".$contentStr." </$schemaPrefix:complexType>\n";
2355 $contentStr = " <$schemaPrefix:complexType name=\"$typeName\"/>\n";
2357 $xml .= $contentStr;
2360 if(isset($this->simpleTypes) && count($this->simpleTypes) > 0){
2361 foreach($this->simpleTypes as $typeName => $eParts){
2362 $xml .= " <$schemaPrefix:simpleType name=\"$typeName\">\n <$schemaPrefix:restriction base=\"".$this->contractQName($eParts['type'])."\">\n";
2363 if (isset($eParts['enumeration'])) {
2364 foreach ($eParts['enumeration'] as $e) {
2365 $xml .= " <$schemaPrefix:enumeration value=\"$e\"/>\n";
2368 $xml .= " </$schemaPrefix:restriction>\n </$schemaPrefix:simpleType>";
2372 if(isset($this->elements) && count($this->elements) > 0){
2373 foreach($this->elements as $element => $eParts){
2374 $xml .= " <$schemaPrefix:element name=\"$element\" type=\"".$this->contractQName($eParts['type'])."\"/>\n";
2378 if(isset($this->attributes) && count($this->attributes) > 0){
2379 foreach($this->attributes as $attr => $aParts){
2380 $xml .= " <$schemaPrefix:attribute name=\"$attr\" type=\"".$this->contractQName($aParts['type'])."\"\n/>";
2385 foreach ($this->schemaInfo as $k => $v) {
2386 if ($k == 'elementFormDefault' || $k == 'attributeFormDefault') {
2387 $attr .= " $k=\"$v\"";
2390 $el = "<$schemaPrefix:schema$attr targetNamespace=\"$this->schemaTargetNamespace\"\n";
2391 foreach (array_diff($this->usedNamespaces, $this->enclosingNamespaces) as $nsp => $ns) {
2392 $el .= " xmlns:$nsp=\"$ns\"";
2394 $xml = $el . ">\n".$xml."</$schemaPrefix:schema>\n";
2399 * adds debug data to the clas level debug string
2401 * @param string $string debug data
2404 function xdebug($string){
2405 if($this->debugLevel > 0) {
2406 $this->debug('<' . $this->schemaTargetNamespace . '> '.$string);
2411 * get the PHP type of a user defined type in the schema
2412 * PHP type is kind of a misnomer since it actually returns 'struct' for assoc. arrays
2413 * returns false if no type exists, or not w/ the given namespace
2414 * else returns a string that is either a native php type, or 'struct'
2416 * @param string $type name of defined type
2417 * @param string $ns namespace of type
2422 function getPHPType($type,$ns){
2423 if(isset($this->typemap[$ns][$type])){
2424 //print "found type '$type' and ns $ns in typemap<br>";
2425 return $this->typemap[$ns][$type];
2426 } elseif(isset($this->complexTypes[$type])){
2427 //print "getting type '$type' and ns $ns from complexTypes array<br>";
2428 return $this->complexTypes[$type]['phpType'];
2434 * returns an associative array of information about a given type
2435 * returns false if no type exists by the given name
2437 * For a complexType typeDef = array(
2438 * 'restrictionBase' => '',
2440 * 'compositor' => '(sequence|all)',
2441 * 'elements' => array(), // refs to elements array
2442 * 'attrs' => array() // refs to attributes array
2443 * ... and so on (see addComplexType)
2446 * For simpleType or element, the array has different keys.
2448 * @param string $type
2451 * @see addComplexType
2452 * @see addSimpleType
2455 function getTypeDef($type){
2456 //$this->debug("in getTypeDef for type $type");
2457 if (substr($type, -1) == '^') {
2459 $type = substr($type, 0, -1);
2464 if((! $is_element) && isset($this->complexTypes[$type])){
2465 $this->xdebug("in getTypeDef, found complexType $type");
2466 return $this->complexTypes[$type];
2467 } elseif((! $is_element) && isset($this->simpleTypes[$type])){
2468 $this->xdebug("in getTypeDef, found simpleType $type");
2469 if (!isset($this->simpleTypes[$type]['phpType'])) {
2470 // get info for type to tack onto the simple type
2471 // TODO: can this ever really apply (i.e. what is a simpleType really?)
2472 $uqType = substr($this->simpleTypes[$type]['type'], strrpos($this->simpleTypes[$type]['type'], ':') + 1);
2473 $ns = substr($this->simpleTypes[$type]['type'], 0, strrpos($this->simpleTypes[$type]['type'], ':'));
2474 $etype = $this->getTypeDef($uqType);
2476 $this->xdebug("in getTypeDef, found type for simpleType $type:");
2477 $this->xdebug($this->varDump($etype));
2478 if (isset($etype['phpType'])) {
2479 $this->simpleTypes[$type]['phpType'] = $etype['phpType'];
2481 if (isset($etype['elements'])) {
2482 $this->simpleTypes[$type]['elements'] = $etype['elements'];
2486 return $this->simpleTypes[$type];
2487 } elseif(isset($this->elements[$type])){
2488 $this->xdebug("in getTypeDef, found element $type");
2489 if (!isset($this->elements[$type]['phpType'])) {
2490 // get info for type to tack onto the element
2491 $uqType = substr($this->elements[$type]['type'], strrpos($this->elements[$type]['type'], ':') + 1);
2492 $ns = substr($this->elements[$type]['type'], 0, strrpos($this->elements[$type]['type'], ':'));
2493 $etype = $this->getTypeDef($uqType);
2495 $this->xdebug("in getTypeDef, found type for element $type:");
2496 $this->xdebug($this->varDump($etype));
2497 if (isset($etype['phpType'])) {
2498 $this->elements[$type]['phpType'] = $etype['phpType'];
2500 if (isset($etype['elements'])) {
2501 $this->elements[$type]['elements'] = $etype['elements'];
2503 if (isset($etype['extensionBase'])) {
2504 $this->elements[$type]['extensionBase'] = $etype['extensionBase'];
2506 } elseif ($ns == 'http://www.w3.org/2001/XMLSchema') {
2507 $this->xdebug("in getTypeDef, element $type is an XSD type");
2508 $this->elements[$type]['phpType'] = 'scalar';
2511 return $this->elements[$type];
2512 } elseif(isset($this->attributes[$type])){
2513 $this->xdebug("in getTypeDef, found attribute $type");
2514 return $this->attributes[$type];
2515 } elseif (preg_match('/_ContainedType$/', $type)) {
2516 $this->xdebug("in getTypeDef, have an untyped element $type");
2517 $typeDef['typeClass'] = 'simpleType';
2518 $typeDef['phpType'] = 'scalar';
2519 $typeDef['type'] = 'http://www.w3.org/2001/XMLSchema:string';
2522 $this->xdebug("in getTypeDef, did not find $type");
2527 * returns a sample serialization of a given type, or false if no type by the given name
2529 * @param string $type name of type
2534 function serializeTypeDef($type){
2535 //print "in sTD() for type $type<br>";
2536 if($typeDef = $this->getTypeDef($type)){
2538 if(is_array($typeDef['attrs'])){
2539 foreach($typeDef['attrs'] as $attName => $data){
2540 $str .= " $attName=\"{type = ".$data['type']."}\"";
2543 $str .= " xmlns=\"".$this->schema['targetNamespace']."\"";
2544 if(count($typeDef['elements']) > 0){
2546 foreach($typeDef['elements'] as $element => $eData){
2547 $str .= $this->serializeTypeDef($element);
2550 } elseif($typeDef['typeClass'] == 'element') {
2551 $str .= "></$type>";
2561 * returns HTML form elements that allow a user
2562 * to enter values for creating an instance of the given type.
2564 * @param string $name name for type instance
2565 * @param string $type name of type
2570 function typeToForm($name,$type){
2572 if($typeDef = $this->getTypeDef($type)){
2574 if($typeDef['phpType'] == 'struct'){
2575 $buffer .= '<table>';
2576 foreach($typeDef['elements'] as $child => $childDef){
2578 <tr><td align='right'>$childDef[name] (type: ".$this->getLocalPart($childDef['type'])."):</td>
2579 <td><input type='text' name='parameters[".$name."][$childDef[name]]'></td></tr>";
2581 $buffer .= '</table>';
2583 } elseif($typeDef['phpType'] == 'array'){
2584 $buffer .= '<table>';
2585 for($i=0;$i < 3; $i++){
2587 <tr><td align='right'>array item (type: $typeDef[arrayType]):</td>
2588 <td><input type='text' name='parameters[".$name."][]'></td></tr>";
2590 $buffer .= '</table>';
2593 $buffer .= "<input type='text' name='parameters[$name]'>";
2596 $buffer .= "<input type='text' name='parameters[$name]'>";
2602 * adds a complex type to the schema
2612 * array('ref'=>'SOAP-ENC:arrayType','wsdl:arrayType'=>'string[]'),
2616 * example: PHP associative array ( SOAP Struct )
2623 * array('myVar'=> array('name'=>'myVar','type'=>'string')
2627 * @param typeClass (complexType|simpleType|attribute)
2628 * @param phpType: currently supported are array and struct (php assoc array)
2629 * @param compositor (all|sequence|choice)
2630 * @param restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
2631 * @param elements = array ( name = array(name=>'',type=>'') )
2632 * @param attrs = array(
2634 * 'ref' => "http://schemas.xmlsoap.org/soap/encoding/:arrayType",
2635 * "http://schemas.xmlsoap.org/wsdl/:arrayType" => "string[]"
2638 * @param arrayType: namespace:name (http://www.w3.org/2001/XMLSchema:string)
2642 function addComplexType($name,$typeClass='complexType',$phpType='array',$compositor='',$restrictionBase='',$elements=array(),$attrs=array(),$arrayType=''){
2643 $this->complexTypes[$name] = array(
2645 'typeClass' => $typeClass,
2646 'phpType' => $phpType,
2647 'compositor'=> $compositor,
2648 'restrictionBase' => $restrictionBase,
2649 'elements' => $elements,
2651 'arrayType' => $arrayType
2654 $this->xdebug("addComplexType $name:");
2655 $this->appendDebug($this->varDump($this->complexTypes[$name]));
2659 * adds a simple type to the schema
2661 * @param string $name
2662 * @param string $restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
2663 * @param string $typeClass (should always be simpleType)
2664 * @param string $phpType (should always be scalar)
2665 * @param array $enumeration array of values
2667 * @see nusoap_xmlschema
2670 function addSimpleType($name, $restrictionBase='', $typeClass='simpleType', $phpType='scalar', $enumeration=array()) {
2671 $this->simpleTypes[$name] = array(
2673 'typeClass' => $typeClass,
2674 'phpType' => $phpType,
2675 'type' => $restrictionBase,
2676 'enumeration' => $enumeration
2679 $this->xdebug("addSimpleType $name:");
2680 $this->appendDebug($this->varDump($this->simpleTypes[$name]));
2684 * adds an element to the schema
2686 * @param array $attrs attributes that must include name and type
2687 * @see nusoap_xmlschema
2690 function addElement($attrs) {
2691 if (! $this->getPrefix($attrs['type'])) {
2692 $attrs['type'] = $this->schemaTargetNamespace . ':' . $attrs['type'];
2694 $this->elements[ $attrs['name'] ] = $attrs;
2695 $this->elements[ $attrs['name'] ]['typeClass'] = 'element';
2697 $this->xdebug("addElement " . $attrs['name']);
2698 $this->appendDebug($this->varDump($this->elements[ $attrs['name'] ]));
2703 * Backward compatibility
2705 class XMLSchema extends nusoap_xmlschema {
2712 Modification information for LGPL compliance
2714 r58622 - 2010-10-22 18:18:59 -0700 (Fri, 22 Oct 2010) - engsvnbuild - Author: lam <lam@198.18.142.201>
2717 r58361 - 2010-09-29 16:59:02 -0700 (Wed, 29 Sep 2010) - kjing - Author: Jenny Gonsalves <jenny@sugarcrm.com>
2718 Merging with maint_6_0_1 (svn merge -r 58250:58342)
2720 r57813 - 2010-08-19 10:34:44 -0700 (Thu, 19 Aug 2010) - kjing - Author: John Mertic <jmertic@sugarcrm.com>
2721 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.
2723 r57707 - 2010-08-10 12:26:13 -0700 (Tue, 10 Aug 2010) - kjing - Author: Stanislav Malyshev <smalyshev@gmail.com>
2724 fix SOAP calls with no parameters
2726 r56990 - 2010-06-16 13:05:36 -0700 (Wed, 16 Jun 2010) - kjing - snapshot "Mango" svn branch to a new one for GitHub sync
2728 r56989 - 2010-06-16 13:01:33 -0700 (Wed, 16 Jun 2010) - kjing - defunt "Mango" svn dev branch before github cutover
2730 r55980 - 2010-04-19 13:31:28 -0700 (Mon, 19 Apr 2010) - kjing - create Mango (6.1) based on windex
2732 r51719 - 2009-10-22 10:18:00 -0700 (Thu, 22 Oct 2009) - mitani - Converted to Build 3 tags and updated the build system
2734 r51634 - 2009-10-19 13:32:22 -0700 (Mon, 19 Oct 2009) - mitani - Windex is the branch for Sugar Sales 1.0 development
2736 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.
2738 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.
2740 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:
2741 - Changing all ereg function to either preg or simple string based ones
2742 - No more references to magic quotes.
2743 - Change all the session_unregister() functions to just unset() the correct session variable instead.
2745 r50375 - 2009-08-24 18:07:43 -0700 (Mon, 24 Aug 2009) - dwong - branch kobe2 from tokyo r50372
2747 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
2749 r45680 - 2009-03-30 14:34:35 -0700 (Mon, 30 Mar 2009) - Samir Gandhi - modifeid serializeSchema to generate WS-I compliant WSDL
2751 r42807 - 2008-12-29 11:16:59 -0800 (Mon, 29 Dec 2008) - dwong - Branch from trunk/sugarcrm r42806 to branches/tokyo/sugarcrm
2753 r42645 - 2008-12-18 13:41:08 -0800 (Thu, 18 Dec 2008) - awu - merging maint_5_2_0 rev41336:HEAD to trunk
2755 r41647 - 2008-11-11 17:44:30 -0800 (Tue, 11 Nov 2008) - majed - Fixes a few bugs
2757 r41596 - 2008-11-10 19:20:04 -0800 (Mon, 10 Nov 2008) - Samir Gandhi - modified to set $method in the code
2759 r41558 - 2008-11-10 14:35:34 -0800 (Mon, 10 Nov 2008) - majed - changes nusoap to allow for registering classes
2761 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.
2763 - data/SugarBean.php
2764 - include/domit/php_http_client_generic.php
2765 - include/domit/php_http_connector.php
2766 - include/domit/testing_domit.php
2767 - include/domit/xml_domit_getelementsbypath.php
2768 - include/domit/xml_domit_lite_parser.php
2769 - include/domit/xml_domit_nodemaps.php
2770 - include/domit/xml_domit_parser.php
2771 - include/domit/xml_domit_shared.php
2772 - include/generic/SugarWidgets/SugarWidgetField.php
2773 - include/generic/SugarWidgets/SugarWidgetReportField.php
2774 - include/ListView/ProcessView.php
2775 - include/nusoap/class.soapclient.php
2776 - include/nusoap/nusoap.php
2777 - include/nusoap/nusoapmime.php
2778 - include/Pear/HTML_Safe/Safe.php
2779 - include/Pear/XML_HTMLSax3/HTMLSax3.php
2780 - modules/Administration/RebuildWorkFlow.php
2781 - modules/Expressions/RelateSelector.php
2782 - modules/Reports/templates/templates_reports.php
2783 - modules/WorkFlow/Delete.php
2784 - modules/WorkFlow/Save.php
2785 - modules/WorkFlow/SaveSequence.php
2786 - modules/WorkFlow/WorkFlow.php
2787 - modules/WorkFlowActionShells/CreateStep1.php
2788 - modules/WorkFlowActionShells/CreateStep2.php
2789 - modules/WorkFlowActionShells/Save.php
2790 - modules/WorkFlowActionShells/WorkFlowActionShell.php
2791 - modules/WorkFlowAlerts/Save.php
2792 - modules/WorkFlowAlerts/WorkFlowAlert.php
2793 - modules/WorkFlowAlertShells/DetailView.php
2794 - modules/WorkFlowAlertShells/WorkFlowAlertShell.php
2795 - modules/WorkFlowTriggerShells/CreateStep1.php
2796 - modules/WorkFlowTriggerShells/CreateStepFilter.php
2797 - modules/WorkFlowTriggerShells/SaveFilter.php
2798 - modules/WorkFlowTriggerShells/WorkFlowTriggerShell.php
2799 - soap/SoapHelperFunctions.php
2800 - test/modules/DynamicFields/DynamicFields_Bug24095_test.php
2801 - test/simpletest/browser.php
2802 - test/simpletest/default_reporter.php
2803 - test/simpletest/detached.php
2804 - test/simpletest/eclipse.php
2805 - test/simpletest/expectation.php
2806 - test/simpletest/extensions/pear_test_case.php
2807 - test/simpletest/form.php
2808 - test/simpletest/http.php
2809 - test/simpletest/mock_objects.php
2810 - test/simpletest/page.php
2811 - test/simpletest/parser.php
2812 - test/simpletest/remote.php
2813 - test/simpletest/shell_tester.php
2814 - test/simpletest/simple_test.php
2815 - test/simpletest/simpletest.php
2816 - test/simpletest/test/acceptance_test.php
2817 - test/simpletest/test/adapter_test.php
2818 - test/simpletest/test/authentication_test.php
2819 - test/simpletest/test/browser_test.php
2820 - test/simpletest/test/collector_test.php
2821 - test/simpletest/test/compatibility_test.php
2822 - test/simpletest/test/detached_test.php
2823 - test/simpletest/test/eclipse_test.php
2824 - test/simpletest/test/encoding_test.php
2825 - test/simpletest/test/errors_test.php
2826 - test/simpletest/test/expectation_test.php
2827 - test/simpletest/test/form_test.php
2828 - test/simpletest/test/frames_test.php
2829 - test/simpletest/test/http_test.php
2830 - test/simpletest/test/live_test.php
2831 - test/simpletest/test/mock_objects_test.php
2832 - test/simpletest/test/page_test.php
2833 - test/simpletest/test/parse_error_test.php
2834 - test/simpletest/test/parser_test.php
2835 - test/simpletest/test/remote_test.php
2836 - test/simpletest/test/shell_test.php
2837 - test/simpletest/test/shell_tester_test.php
2838 - test/simpletest/test/simpletest_test.php
2839 - test/simpletest/test/site/page_request.php
2840 - test/simpletest/test/tag_test.php
2841 - test/simpletest/test/unit_tester_test.php
2842 - test/simpletest/test/user_agent_test.php
2843 - test/simpletest/test/visual_test.php
2844 - test/simpletest/test/xml_test.php
2845 - test/simpletest/test_case.php
2846 - test/simpletest/ui/array_reporter/test.php
2847 - test/simpletest/ui/recorder/test.php
2848 - test/simpletest/unit_tester.php
2849 - test/simpletest/url.php
2850 - test/simpletest/user_agent.php
2851 - test/simpletest/web_tester.php
2852 - test/spikephpcoverage/src/PEAR.php
2853 - test/spikephpcoverage/src/util/Utility.php
2854 - test/spikephpcoverage/src/XML/Parser.php
2855 - test/spikephpcoverage/src/XML/Parser/Simple.php
2856 - test/test_utilities/SugarTest_SimpleBrowser.php
2858 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.
2860 r38300 - 2008-07-25 13:33:43 -0700 (Fri, 25 Jul 2008) - Samir Gandhi - put the debug in parseresponse function
2862 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
2864 r36824 - 2008-06-18 09:26:11 -0700 (Wed, 18 Jun 2008) - roger - bug: 21832
2866 r26422 - 2007-09-05 17:29:12 -0700 (Wed, 05 Sep 2007) - majed - migrate from beta 1 to trunk
2868 r15787 - 2006-08-10 10:14:41 -0700 (Thu, 10 Aug 2006) - roger - RRS: bug 7961
2870 r14701 - 2006-07-17 13:37:26 -0700 (Mon, 17 Jul 2006) - roger - RRS: bug 5801
2872 r13782 - 2006-06-06 10:58:55 -0700 (Tue, 06 Jun 2006) - majed - changes entry point code
2874 r11466 - 2006-02-01 15:49:47 -0800 (Wed, 01 Feb 2006) - jacob - Adding extra !empty check to get around a PHP warning.
2876 r11115 - 2006-01-17 14:54:45 -0800 (Tue, 17 Jan 2006) - majed - add entry point validation
2878 r10585 - 2005-12-13 14:42:26 -0800 (Tue, 13 Dec 2005) - majed - adds new license mechanisim
2880 r10170 - 2005-12-05 18:37:46 -0800 (Mon, 05 Dec 2005) - majed - fixes various issues
2882 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.
2884 r8991 - 2005-11-03 19:07:25 -0800 (Thu, 03 Nov 2005) - majed - fixes nusoap issue
2886 r8846 - 2005-10-31 11:01:12 -0800 (Mon, 31 Oct 2005) - majed - new version of nusoap
2888 r7905 - 2005-09-21 19:12:57 -0700 (Wed, 21 Sep 2005) - majed - restores old nusoap pre & with a few fixes
2890 r7861 - 2005-09-20 15:40:25 -0700 (Tue, 20 Sep 2005) - majed - & fix for 3.5.1
2892 r7452 - 2005-08-17 11:32:34 -0700 (Wed, 17 Aug 2005) - majed - changes soap to nusoap
2894 r5820 - 2005-06-21 14:22:24 -0700 (Tue, 21 Jun 2005) - majed - fixes issues with nusoap and with custom fields
2896 r5462 - 2005-05-25 13:50:11 -0700 (Wed, 25 May 2005) - majed - upgraded nusoap to .6.9
2898 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
2900 r573 - 2004-09-04 13:03:32 -0700 (Sat, 04 Sep 2004) - sugarclint - undoing copyrights added in inadvertantly. --clint
2902 r546 - 2004-09-03 11:49:38 -0700 (Fri, 03 Sep 2004) - sugarmsi - removed echo count
2904 r354 - 2004-08-02 23:00:37 -0700 (Mon, 02 Aug 2004) - sugarjacob - Adding Soap
2914 * For creating serializable abstractions of native PHP types. This class
2915 * allows element name/namespace, XSD type, and XML attributes to be
2916 * associated with a value. This is extremely useful when WSDL is not
2917 * used, but is also useful when WSDL is used with polymorphic types, including
2918 * xsd:anyType and user-defined types.
2920 * @author Dietrich Ayala <dietrich@ganx4.com>
2924 class soapval extends nusoap_base {
2926 * The XML element name
2933 * The XML type name (string or false)
2947 * The XML element namespace (string or false)
2954 * The XML type namespace (string or false)
2961 * The XML element attributes (array or false)
2971 * @param string $name optional name
2972 * @param mixed $type optional type name
2973 * @param mixed $value optional value
2974 * @param mixed $element_ns optional namespace of value
2975 * @param mixed $type_ns optional namespace of type
2976 * @param mixed $attributes associative array of attributes to add to element serialization
2979 function soapval($name='soapval',$type=false,$value=-1,$element_ns=false,$type_ns=false,$attributes=false) {
2980 parent::nusoap_base();
2981 $this->name = $name;
2982 $this->type = $type;
2983 $this->value = $value;
2984 $this->element_ns = $element_ns;
2985 $this->type_ns = $type_ns;
2986 $this->attributes = $attributes;
2990 * return serialized value
2992 * @param string $use The WSDL use value (encoded|literal)
2993 * @return string XML data
2996 function serialize($use='encoded') {
2997 return $this->serialize_val($this->value, $this->name, $this->type, $this->element_ns, $this->type_ns, $this->attributes, $use, true);
3001 * decodes a soapval object into a PHP native type
3007 return $this->value;
3017 Modification information for LGPL compliance
3019 r58622 - 2010-10-22 18:18:59 -0700 (Fri, 22 Oct 2010) - engsvnbuild - Author: lam <lam@198.18.142.201>
3022 r58361 - 2010-09-29 16:59:02 -0700 (Wed, 29 Sep 2010) - kjing - Author: Jenny Gonsalves <jenny@sugarcrm.com>
3023 Merging with maint_6_0_1 (svn merge -r 58250:58342)
3025 r57813 - 2010-08-19 10:34:44 -0700 (Thu, 19 Aug 2010) - kjing - Author: John Mertic <jmertic@sugarcrm.com>
3026 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.
3028 r57707 - 2010-08-10 12:26:13 -0700 (Tue, 10 Aug 2010) - kjing - Author: Stanislav Malyshev <smalyshev@gmail.com>
3029 fix SOAP calls with no parameters
3031 r56990 - 2010-06-16 13:05:36 -0700 (Wed, 16 Jun 2010) - kjing - snapshot "Mango" svn branch to a new one for GitHub sync
3033 r56989 - 2010-06-16 13:01:33 -0700 (Wed, 16 Jun 2010) - kjing - defunt "Mango" svn dev branch before github cutover
3035 r55980 - 2010-04-19 13:31:28 -0700 (Mon, 19 Apr 2010) - kjing - create Mango (6.1) based on windex
3037 r51719 - 2009-10-22 10:18:00 -0700 (Thu, 22 Oct 2009) - mitani - Converted to Build 3 tags and updated the build system
3039 r51634 - 2009-10-19 13:32:22 -0700 (Mon, 19 Oct 2009) - mitani - Windex is the branch for Sugar Sales 1.0 development
3041 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.
3043 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.
3045 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:
3046 - Changing all ereg function to either preg or simple string based ones
3047 - No more references to magic quotes.
3048 - Change all the session_unregister() functions to just unset() the correct session variable instead.
3050 r50375 - 2009-08-24 18:07:43 -0700 (Mon, 24 Aug 2009) - dwong - branch kobe2 from tokyo r50372
3052 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
3054 r45680 - 2009-03-30 14:34:35 -0700 (Mon, 30 Mar 2009) - Samir Gandhi - modifeid serializeSchema to generate WS-I compliant WSDL
3056 r42807 - 2008-12-29 11:16:59 -0800 (Mon, 29 Dec 2008) - dwong - Branch from trunk/sugarcrm r42806 to branches/tokyo/sugarcrm
3058 r42645 - 2008-12-18 13:41:08 -0800 (Thu, 18 Dec 2008) - awu - merging maint_5_2_0 rev41336:HEAD to trunk
3060 r41647 - 2008-11-11 17:44:30 -0800 (Tue, 11 Nov 2008) - majed - Fixes a few bugs
3062 r41596 - 2008-11-10 19:20:04 -0800 (Mon, 10 Nov 2008) - Samir Gandhi - modified to set $method in the code
3064 r41558 - 2008-11-10 14:35:34 -0800 (Mon, 10 Nov 2008) - majed - changes nusoap to allow for registering classes
3066 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.
3068 - data/SugarBean.php
3069 - include/domit/php_http_client_generic.php
3070 - include/domit/php_http_connector.php
3071 - include/domit/testing_domit.php
3072 - include/domit/xml_domit_getelementsbypath.php
3073 - include/domit/xml_domit_lite_parser.php
3074 - include/domit/xml_domit_nodemaps.php
3075 - include/domit/xml_domit_parser.php
3076 - include/domit/xml_domit_shared.php
3077 - include/generic/SugarWidgets/SugarWidgetField.php
3078 - include/generic/SugarWidgets/SugarWidgetReportField.php
3079 - include/ListView/ProcessView.php
3080 - include/nusoap/class.soapclient.php
3081 - include/nusoap/nusoap.php
3082 - include/nusoap/nusoapmime.php
3083 - include/Pear/HTML_Safe/Safe.php
3084 - include/Pear/XML_HTMLSax3/HTMLSax3.php
3085 - modules/Administration/RebuildWorkFlow.php
3086 - modules/Expressions/RelateSelector.php
3087 - modules/Reports/templates/templates_reports.php
3088 - modules/WorkFlow/Delete.php
3089 - modules/WorkFlow/Save.php
3090 - modules/WorkFlow/SaveSequence.php
3091 - modules/WorkFlow/WorkFlow.php
3092 - modules/WorkFlowActionShells/CreateStep1.php
3093 - modules/WorkFlowActionShells/CreateStep2.php
3094 - modules/WorkFlowActionShells/Save.php
3095 - modules/WorkFlowActionShells/WorkFlowActionShell.php
3096 - modules/WorkFlowAlerts/Save.php
3097 - modules/WorkFlowAlerts/WorkFlowAlert.php
3098 - modules/WorkFlowAlertShells/DetailView.php
3099 - modules/WorkFlowAlertShells/WorkFlowAlertShell.php
3100 - modules/WorkFlowTriggerShells/CreateStep1.php
3101 - modules/WorkFlowTriggerShells/CreateStepFilter.php
3102 - modules/WorkFlowTriggerShells/SaveFilter.php
3103 - modules/WorkFlowTriggerShells/WorkFlowTriggerShell.php
3104 - soap/SoapHelperFunctions.php
3105 - test/modules/DynamicFields/DynamicFields_Bug24095_test.php
3106 - test/simpletest/browser.php
3107 - test/simpletest/default_reporter.php
3108 - test/simpletest/detached.php
3109 - test/simpletest/eclipse.php
3110 - test/simpletest/expectation.php
3111 - test/simpletest/extensions/pear_test_case.php
3112 - test/simpletest/form.php
3113 - test/simpletest/http.php
3114 - test/simpletest/mock_objects.php
3115 - test/simpletest/page.php
3116 - test/simpletest/parser.php
3117 - test/simpletest/remote.php
3118 - test/simpletest/shell_tester.php
3119 - test/simpletest/simple_test.php
3120 - test/simpletest/simpletest.php
3121 - test/simpletest/test/acceptance_test.php
3122 - test/simpletest/test/adapter_test.php
3123 - test/simpletest/test/authentication_test.php
3124 - test/simpletest/test/browser_test.php
3125 - test/simpletest/test/collector_test.php
3126 - test/simpletest/test/compatibility_test.php
3127 - test/simpletest/test/detached_test.php
3128 - test/simpletest/test/eclipse_test.php
3129 - test/simpletest/test/encoding_test.php
3130 - test/simpletest/test/errors_test.php
3131 - test/simpletest/test/expectation_test.php
3132 - test/simpletest/test/form_test.php
3133 - test/simpletest/test/frames_test.php
3134 - test/simpletest/test/http_test.php
3135 - test/simpletest/test/live_test.php
3136 - test/simpletest/test/mock_objects_test.php
3137 - test/simpletest/test/page_test.php
3138 - test/simpletest/test/parse_error_test.php
3139 - test/simpletest/test/parser_test.php
3140 - test/simpletest/test/remote_test.php
3141 - test/simpletest/test/shell_test.php
3142 - test/simpletest/test/shell_tester_test.php
3143 - test/simpletest/test/simpletest_test.php
3144 - test/simpletest/test/site/page_request.php
3145 - test/simpletest/test/tag_test.php
3146 - test/simpletest/test/unit_tester_test.php
3147 - test/simpletest/test/user_agent_test.php
3148 - test/simpletest/test/visual_test.php
3149 - test/simpletest/test/xml_test.php
3150 - test/simpletest/test_case.php
3151 - test/simpletest/ui/array_reporter/test.php
3152 - test/simpletest/ui/recorder/test.php
3153 - test/simpletest/unit_tester.php
3154 - test/simpletest/url.php
3155 - test/simpletest/user_agent.php
3156 - test/simpletest/web_tester.php
3157 - test/spikephpcoverage/src/PEAR.php
3158 - test/spikephpcoverage/src/util/Utility.php
3159 - test/spikephpcoverage/src/XML/Parser.php
3160 - test/spikephpcoverage/src/XML/Parser/Simple.php
3161 - test/test_utilities/SugarTest_SimpleBrowser.php
3163 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.
3165 r38300 - 2008-07-25 13:33:43 -0700 (Fri, 25 Jul 2008) - Samir Gandhi - put the debug in parseresponse function
3167 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
3169 r36824 - 2008-06-18 09:26:11 -0700 (Wed, 18 Jun 2008) - roger - bug: 21832
3171 r26422 - 2007-09-05 17:29:12 -0700 (Wed, 05 Sep 2007) - majed - migrate from beta 1 to trunk
3173 r15787 - 2006-08-10 10:14:41 -0700 (Thu, 10 Aug 2006) - roger - RRS: bug 7961
3175 r14701 - 2006-07-17 13:37:26 -0700 (Mon, 17 Jul 2006) - roger - RRS: bug 5801
3177 r13782 - 2006-06-06 10:58:55 -0700 (Tue, 06 Jun 2006) - majed - changes entry point code
3179 r11466 - 2006-02-01 15:49:47 -0800 (Wed, 01 Feb 2006) - jacob - Adding extra !empty check to get around a PHP warning.
3181 r11115 - 2006-01-17 14:54:45 -0800 (Tue, 17 Jan 2006) - majed - add entry point validation
3183 r10585 - 2005-12-13 14:42:26 -0800 (Tue, 13 Dec 2005) - majed - adds new license mechanisim
3185 r10170 - 2005-12-05 18:37:46 -0800 (Mon, 05 Dec 2005) - majed - fixes various issues
3187 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.
3189 r8991 - 2005-11-03 19:07:25 -0800 (Thu, 03 Nov 2005) - majed - fixes nusoap issue
3191 r8846 - 2005-10-31 11:01:12 -0800 (Mon, 31 Oct 2005) - majed - new version of nusoap
3193 r7905 - 2005-09-21 19:12:57 -0700 (Wed, 21 Sep 2005) - majed - restores old nusoap pre & with a few fixes
3195 r7861 - 2005-09-20 15:40:25 -0700 (Tue, 20 Sep 2005) - majed - & fix for 3.5.1
3197 r7452 - 2005-08-17 11:32:34 -0700 (Wed, 17 Aug 2005) - majed - changes soap to nusoap
3199 r5820 - 2005-06-21 14:22:24 -0700 (Tue, 21 Jun 2005) - majed - fixes issues with nusoap and with custom fields
3201 r5462 - 2005-05-25 13:50:11 -0700 (Wed, 25 May 2005) - majed - upgraded nusoap to .6.9
3203 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
3205 r573 - 2004-09-04 13:03:32 -0700 (Sat, 04 Sep 2004) - sugarclint - undoing copyrights added in inadvertantly. --clint
3207 r546 - 2004-09-03 11:49:38 -0700 (Fri, 03 Sep 2004) - sugarmsi - removed echo count
3209 r354 - 2004-08-02 23:00:37 -0700 (Mon, 02 Aug 2004) - sugarjacob - Adding Soap
3219 * transport class for sending/receiving data via HTTP and HTTPS
3220 * NOTE: PHP must be compiled with the CURL extension for HTTPS support
3222 * @author Dietrich Ayala <dietrich@ganx4.com>
3223 * @author Scott Nichol <snichol@users.sourceforge.net>
3227 class soap_transport_http extends nusoap_base {
3231 var $digest_uri = '';
3236 var $request_method = 'POST';
3237 var $protocol_version = '1.0';
3239 var $outgoing_headers = array();
3240 var $incoming_headers = array();
3241 var $incoming_cookies = array();
3242 var $outgoing_payload = '';
3243 var $incoming_payload = '';
3244 var $response_status_line; // HTTP response status line
3245 var $useSOAPAction = true;
3246 var $persistentConnection = false;
3247 var $ch = false; // cURL handle
3248 var $ch_options = array(); // cURL custom options
3249 var $use_curl = false; // force cURL use
3250 var $proxy = null; // proxy information (associative array)
3254 var $digestRequest = array();
3255 var $certRequest = array(); // keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, certpassword (optional), verifypeer (optional), verifyhost (optional)
3256 // cainfofile: certificate authority file, e.g. '$pathToPemFiles/rootca.pem'
3257 // sslcertfile: SSL certificate file, e.g. '$pathToPemFiles/mycert.pem'
3258 // sslkeyfile: SSL key file, e.g. '$pathToPemFiles/mykey.pem'
3259 // passphrase: SSL key password/passphrase
3260 // certpassword: SSL certificate password
3261 // verifypeer: default is 1
3262 // verifyhost: default is 1
3267 * @param string $url The URL to which to connect
3268 * @param array $curl_options User-specified cURL options
3269 * @param boolean $use_curl Whether to try to force cURL use
3272 function soap_transport_http($url, $curl_options = NULL, $use_curl = false){
3273 parent::nusoap_base();
3274 $this->debug("ctor url=$url use_curl=$use_curl curl_options:");
3275 $this->appendDebug($this->varDump($curl_options));
3276 $this->setURL($url);
3277 if (is_array($curl_options)) {
3278 $this->ch_options = $curl_options;
3280 $this->use_curl = $use_curl;
3281 preg_match('/\$Revisio' . 'n: ([^ ]+)/', $this->revision, $rev);
3282 $this->setHeader('User-Agent', $this->title.'/'.$this->version.' ('.$rev[1].')');
3286 * sets a cURL option
3288 * @param mixed $option The cURL option (always integer?)
3289 * @param mixed $value The cURL option value
3292 function setCurlOption($option, $value) {
3293 $this->debug("setCurlOption option=$option, value=");
3294 $this->appendDebug($this->varDump($value));
3295 curl_setopt($this->ch, $option, $value);
3299 * sets an HTTP header
3301 * @param string $name The name of the header
3302 * @param string $value The value of the header
3305 function setHeader($name, $value) {
3306 $this->outgoing_headers[$name] = $value;
3307 $this->debug("set header $name: $value");
3311 * unsets an HTTP header
3313 * @param string $name The name of the header
3316 function unsetHeader($name) {
3317 if (isset($this->outgoing_headers[$name])) {
3318 $this->debug("unset header $name");
3319 unset($this->outgoing_headers[$name]);
3324 * sets the URL to which to connect
3326 * @param string $url The URL to which to connect
3329 function setURL($url) {
3332 $u = parse_url($url);
3333 foreach($u as $k => $v){
3334 $this->debug("parsed URL $k = $v");
3338 // add any GET params to path
3339 if(isset($u['query']) && $u['query'] != ''){
3340 $this->path .= '?' . $u['query'];
3344 if(!isset($u['port'])){
3345 if($u['scheme'] == 'https'){
3352 $this->uri = $this->path;
3353 $this->digest_uri = $this->uri;
3356 if (!isset($u['port'])) {
3357 $this->setHeader('Host', $this->host);
3359 $this->setHeader('Host', $this->host.':'.$this->port);
3362 if (isset($u['user']) && $u['user'] != '') {
3363 $this->setCredentials(urldecode($u['user']), isset($u['pass']) ? urldecode($u['pass']) : '');
3368 * gets the I/O method to use
3370 * @return string I/O method to use (socket|curl|unknown)
3373 function io_method() {
3374 if ($this->use_curl || ($this->scheme == 'https') || ($this->scheme == 'http' && $this->authtype == 'ntlm') || ($this->scheme == 'http' && is_array($this->proxy) && $this->proxy['authtype'] == 'ntlm'))
3376 if (($this->scheme == 'http' || $this->scheme == 'ssl') && $this->authtype != 'ntlm' && (!is_array($this->proxy) || $this->proxy['authtype'] != 'ntlm'))
3382 * establish an HTTP connection
3384 * @param integer $timeout set connection timeout in seconds
3385 * @param integer $response_timeout set response timeout in seconds
3386 * @return boolean true if connected, false if not
3389 function connect($connection_timeout=0,$response_timeout=30){
3390 // For PHP 4.3 with OpenSSL, change https scheme to ssl, then treat like
3391 // "regular" socket.
3392 // TODO: disabled for now because OpenSSL must be *compiled* in (not just
3393 // loaded), and until PHP5 stream_get_wrappers is not available.
3394 // if ($this->scheme == 'https') {
3395 // if (version_compare(phpversion(), '4.3.0') >= 0) {
3396 // if (extension_loaded('openssl')) {
3397 // $this->scheme = 'ssl';
3398 // $this->debug('Using SSL over OpenSSL');
3402 $this->debug("connect connection_timeout $connection_timeout, response_timeout $response_timeout, scheme $this->scheme, host $this->host, port $this->port");
3403 if ($this->io_method() == 'socket') {
3404 if (!is_array($this->proxy)) {
3405 $host = $this->host;
3406 $port = $this->port;
3408 $host = $this->proxy['host'];
3409 $port = $this->proxy['port'];
3412 // use persistent connection
3413 if($this->persistentConnection && isset($this->fp) && is_resource($this->fp)){
3414 if (!feof($this->fp)) {
3415 $this->debug('Re-use persistent connection');
3419 $this->debug('Closed persistent connection at EOF');
3422 // munge host if using OpenSSL
3423 if ($this->scheme == 'ssl') {
3424 $host = 'ssl://' . $host;
3426 $this->debug('calling fsockopen with host ' . $host . ' connection_timeout ' . $connection_timeout);
3429 if($connection_timeout > 0){
3430 $this->fp = @fsockopen( $host, $port, $this->errno, $this->error_str, $connection_timeout);
3432 $this->fp = @fsockopen( $host, $port, $this->errno, $this->error_str);
3437 $msg = 'Couldn\'t open socket connection to server ' . $this->url;
3439 $msg .= ', Error ('.$this->errno.'): '.$this->error_str;
3441 $msg .= ' prior to connect(). This is often a problem looking up the host name.';
3444 $this->setError($msg);
3448 // set response timeout
3449 $this->debug('set response timeout to ' . $response_timeout);
3450 socket_set_timeout( $this->fp, $response_timeout);
3452 $this->debug('socket connected');
3454 } else if ($this->io_method() == 'curl') {
3455 if (!extension_loaded('curl')) {
3456 // $this->setError('cURL Extension, or OpenSSL extension w/ PHP version >= 4.3 is required for HTTPS');
3457 $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.');
3460 // Avoid warnings when PHP does not have these options
3461 if (defined('CURLOPT_CONNECTIONTIMEOUT'))
3462 $CURLOPT_CONNECTIONTIMEOUT = CURLOPT_CONNECTIONTIMEOUT;
3464 $CURLOPT_CONNECTIONTIMEOUT = 78;
3465 if (defined('CURLOPT_HTTPAUTH'))
3466 $CURLOPT_HTTPAUTH = CURLOPT_HTTPAUTH;
3468 $CURLOPT_HTTPAUTH = 107;
3469 if (defined('CURLOPT_PROXYAUTH'))
3470 $CURLOPT_PROXYAUTH = CURLOPT_PROXYAUTH;
3472 $CURLOPT_PROXYAUTH = 111;
3473 if (defined('CURLAUTH_BASIC'))
3474 $CURLAUTH_BASIC = CURLAUTH_BASIC;
3476 $CURLAUTH_BASIC = 1;
3477 if (defined('CURLAUTH_DIGEST'))
3478 $CURLAUTH_DIGEST = CURLAUTH_DIGEST;
3480 $CURLAUTH_DIGEST = 2;
3481 if (defined('CURLAUTH_NTLM'))
3482 $CURLAUTH_NTLM = CURLAUTH_NTLM;
3486 $this->debug('connect using cURL');
3488 $this->ch = curl_init();
3490 $hostURL = ($this->port != '') ? "$this->scheme://$this->host:$this->port" : "$this->scheme://$this->host";
3492 $hostURL .= $this->path;
3493 $this->setCurlOption(CURLOPT_URL, $hostURL);
3494 // follow location headers (re-directs)
3495 if (ini_get('safe_mode') || ini_get('open_basedir')) {
3496 $this->debug('safe_mode or open_basedir set, so do not set CURLOPT_FOLLOWLOCATION');
3497 $this->debug('safe_mode = ');
3498 $this->appendDebug($this->varDump(ini_get('safe_mode')));
3499 $this->debug('open_basedir = ');
3500 $this->appendDebug($this->varDump(ini_get('open_basedir')));
3502 $this->setCurlOption(CURLOPT_FOLLOWLOCATION, 1);
3504 // ask for headers in the response output
3505 $this->setCurlOption(CURLOPT_HEADER, 1);
3506 // ask for the response output as the return value
3507 $this->setCurlOption(CURLOPT_RETURNTRANSFER, 1);
3509 // We manage this ourselves through headers and encoding
3510 // if(function_exists('gzuncompress')){
3511 // $this->setCurlOption(CURLOPT_ENCODING, 'deflate');
3513 // persistent connection
3514 if ($this->persistentConnection) {
3515 // I believe the following comment is now bogus, having applied to
3516 // the code when it used CURLOPT_CUSTOMREQUEST to send the request.
3517 // The way we send data, we cannot use persistent connections, since
3518 // there will be some "junk" at the end of our request.
3519 //$this->setCurlOption(CURL_HTTP_VERSION_1_1, true);
3520 $this->persistentConnection = false;
3521 $this->setHeader('Connection', 'close');
3524 if ($connection_timeout != 0) {
3525 $this->setCurlOption($CURLOPT_CONNECTIONTIMEOUT, $connection_timeout);
3527 if ($response_timeout != 0) {
3528 $this->setCurlOption(CURLOPT_TIMEOUT, $response_timeout);
3531 if ($this->scheme == 'https') {
3532 $this->debug('set cURL SSL verify options');
3533 // recent versions of cURL turn on peer/host checking by default,
3534 // while PHP binaries are not compiled with a default location for the
3535 // CA cert bundle, so disable peer/host checking.
3536 //$this->setCurlOption(CURLOPT_CAINFO, 'f:\php-4.3.2-win32\extensions\curl-ca-bundle.crt');
3537 $this->setCurlOption(CURLOPT_SSL_VERIFYPEER, 0);
3538 $this->setCurlOption(CURLOPT_SSL_VERIFYHOST, 0);
3540 // support client certificates (thanks Tobias Boes, Doug Anarino, Eryan Ariobowo)
3541 if ($this->authtype == 'certificate') {
3542 $this->debug('set cURL certificate options');
3543 if (isset($this->certRequest['cainfofile'])) {
3544 $this->setCurlOption(CURLOPT_CAINFO, $this->certRequest['cainfofile']);
3546 if (isset($this->certRequest['verifypeer'])) {
3547 $this->setCurlOption(CURLOPT_SSL_VERIFYPEER, $this->certRequest['verifypeer']);
3549 $this->setCurlOption(CURLOPT_SSL_VERIFYPEER, 1);
3551 if (isset($this->certRequest['verifyhost'])) {
3552 $this->setCurlOption(CURLOPT_SSL_VERIFYHOST, $this->certRequest['verifyhost']);
3554 $this->setCurlOption(CURLOPT_SSL_VERIFYHOST, 1);
3556 if (isset($this->certRequest['sslcertfile'])) {
3557 $this->setCurlOption(CURLOPT_SSLCERT, $this->certRequest['sslcertfile']);
3559 if (isset($this->certRequest['sslkeyfile'])) {
3560 $this->setCurlOption(CURLOPT_SSLKEY, $this->certRequest['sslkeyfile']);
3562 if (isset($this->certRequest['passphrase'])) {
3563 $this->setCurlOption(CURLOPT_SSLKEYPASSWD, $this->certRequest['passphrase']);
3565 if (isset($this->certRequest['certpassword'])) {
3566 $this->setCurlOption(CURLOPT_SSLCERTPASSWD, $this->certRequest['certpassword']);
3570 if ($this->authtype && ($this->authtype != 'certificate')) {
3571 if ($this->username) {
3572 $this->debug('set cURL username/password');
3573 $this->setCurlOption(CURLOPT_USERPWD, "$this->username:$this->password");
3575 if ($this->authtype == 'basic') {
3576 $this->debug('set cURL for Basic authentication');
3577 $this->setCurlOption($CURLOPT_HTTPAUTH, $CURLAUTH_BASIC);
3579 if ($this->authtype == 'digest') {
3580 $this->debug('set cURL for digest authentication');
3581 $this->setCurlOption($CURLOPT_HTTPAUTH, $CURLAUTH_DIGEST);
3583 if ($this->authtype == 'ntlm') {
3584 $this->debug('set cURL for NTLM authentication');
3585 $this->setCurlOption($CURLOPT_HTTPAUTH, $CURLAUTH_NTLM);
3588 if (is_array($this->proxy)) {
3589 $this->debug('set cURL proxy options');
3590 if ($this->proxy['port'] != '') {
3591 $this->setCurlOption(CURLOPT_PROXY, $this->proxy['host'].':'.$this->proxy['port']);
3593 $this->setCurlOption(CURLOPT_PROXY, $this->proxy['host']);
3595 if ($this->proxy['username'] || $this->proxy['password']) {
3596 $this->debug('set cURL proxy authentication options');
3597 $this->setCurlOption(CURLOPT_PROXYUSERPWD, $this->proxy['username'].':'.$this->proxy['password']);
3598 if ($this->proxy['authtype'] == 'basic') {
3599 $this->setCurlOption($CURLOPT_PROXYAUTH, $CURLAUTH_BASIC);
3601 if ($this->proxy['authtype'] == 'ntlm') {
3602 $this->setCurlOption($CURLOPT_PROXYAUTH, $CURLAUTH_NTLM);
3606 $this->debug('cURL connection set up');
3609 $this->setError('Unknown scheme ' . $this->scheme);
3610 $this->debug('Unknown scheme ' . $this->scheme);
3616 * sends the SOAP request and gets the SOAP response via HTTP[S]
3618 * @param string $data message data
3619 * @param integer $timeout set connection timeout in seconds
3620 * @param integer $response_timeout set response timeout in seconds
3621 * @param array $cookies cookies to send
3622 * @return string data
3625 function send($data, $timeout=0, $response_timeout=30, $cookies=NULL) {
3627 $this->debug('entered send() with data of length: '.strlen($data));
3629 $this->tryagain = true;
3631 while ($this->tryagain) {
3632 $this->tryagain = false;
3635 if (!$this->connect($timeout, $response_timeout)){
3640 if (!$this->sendRequest($data, $cookies)){
3645 $respdata = $this->getResponse();
3647 $this->setError("Too many tries to get an OK response ($this->response_status_line)");
3650 $this->debug('end of send()');
3656 * sends the SOAP request and gets the SOAP response via HTTPS using CURL
3658 * @param string $data message data
3659 * @param integer $timeout set connection timeout in seconds
3660 * @param integer $response_timeout set response timeout in seconds
3661 * @param array $cookies cookies to send
3662 * @return string data
3666 function sendHTTPS($data, $timeout=0, $response_timeout=30, $cookies) {
3667 return $this->send($data, $timeout, $response_timeout, $cookies);
3671 * if authenticating, set user credentials here
3673 * @param string $username
3674 * @param string $password
3675 * @param string $authtype (basic|digest|certificate|ntlm)
3676 * @param array $digestRequest (keys must be nonce, nc, realm, qop)
3677 * @param array $certRequest (keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, certpassword (optional), verifypeer (optional), verifyhost (optional): see corresponding options in cURL docs)
3680 function setCredentials($username, $password, $authtype = 'basic', $digestRequest = array(), $certRequest = array()) {
3681 $this->debug("setCredentials username=$username authtype=$authtype digestRequest=");
3682 $this->appendDebug($this->varDump($digestRequest));
3683 $this->debug("certRequest=");
3684 $this->appendDebug($this->varDump($certRequest));
3686 if ($authtype == 'basic') {
3687 $this->setHeader('Authorization', 'Basic '.base64_encode(str_replace(':','',$username).':'.$password));
3688 } elseif ($authtype == 'digest') {
3689 if (isset($digestRequest['nonce'])) {
3690 $digestRequest['nc'] = isset($digestRequest['nc']) ? $digestRequest['nc']++ : 1;
3692 // calculate the Digest hashes (calculate code based on digest implementation found at: http://www.rassoc.com/gregr/weblog/stories/2002/07/09/webServicesSecurityHttpDigestAuthenticationWithoutActiveDirectory.html)
3694 // A1 = unq(username-value) ":" unq(realm-value) ":" passwd
3695 $A1 = $username. ':' . (isset($digestRequest['realm']) ? $digestRequest['realm'] : '') . ':' . $password;
3700 // A2 = Method ":" digest-uri-value
3701 $A2 = $this->request_method . ':' . $this->digest_uri;
3706 // KD(secret, data) = H(concat(secret, ":", data))
3708 // request-digest = <"> < KD ( H(A1), unq(nonce-value)
3710 // ":" unq(cnonce-value)
3711 // ":" unq(qop-value)
3714 // if qop is missing,
3715 // request-digest = <"> < KD ( H(A1), unq(nonce-value) ":" H(A2) ) > <">
3717 $unhashedDigest = '';
3718 $nonce = isset($digestRequest['nonce']) ? $digestRequest['nonce'] : '';
3720 if ($digestRequest['qop'] != '') {
3721 $unhashedDigest = $HA1 . ':' . $nonce . ':' . sprintf("%08d", $digestRequest['nc']) . ':' . $cnonce . ':' . $digestRequest['qop'] . ':' . $HA2;
3723 $unhashedDigest = $HA1 . ':' . $nonce . ':' . $HA2;
3726 $hashedDigest = md5($unhashedDigest);
3729 if (isset($digestRequest['opaque'])) {
3730 $opaque = ', opaque="' . $digestRequest['opaque'] . '"';
3733 $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 . '"');
3735 } elseif ($authtype == 'certificate') {
3736 $this->certRequest = $certRequest;
3737 $this->debug('Authorization header not set for certificate');
3738 } elseif ($authtype == 'ntlm') {
3740 $this->debug('Authorization header not set for ntlm');
3742 $this->username = $username;
3743 $this->password = $password;
3744 $this->authtype = $authtype;
3745 $this->digestRequest = $digestRequest;
3749 * set the soapaction value
3751 * @param string $soapaction
3754 function setSOAPAction($soapaction) {
3755 $this->setHeader('SOAPAction', '"' . $soapaction . '"');
3761 * @param string $enc encoding style. supported values: gzip, deflate, or both
3764 function setEncoding($enc='gzip, deflate') {
3765 if (function_exists('gzdeflate')) {
3766 $this->protocol_version = '1.1';
3767 $this->setHeader('Accept-Encoding', $enc);
3768 if (!isset($this->outgoing_headers['Connection'])) {
3769 $this->setHeader('Connection', 'close');
3770 $this->persistentConnection = false;
3772 // deprecated as of PHP 5.3.0
3773 //set_magic_quotes_runtime(0);
3774 $this->encoding = $enc;
3779 * set proxy info here
3781 * @param string $proxyhost use an empty string to remove proxy
3782 * @param string $proxyport
3783 * @param string $proxyusername
3784 * @param string $proxypassword
3785 * @param string $proxyauthtype (basic|ntlm)
3788 function setProxy($proxyhost, $proxyport, $proxyusername = '', $proxypassword = '', $proxyauthtype = 'basic') {
3790 $this->proxy = array(
3791 'host' => $proxyhost,
3792 'port' => $proxyport,
3793 'username' => $proxyusername,
3794 'password' => $proxypassword,
3795 'authtype' => $proxyauthtype
3797 if ($proxyusername != '' && $proxypassword != '' && $proxyauthtype = 'basic') {
3798 $this->setHeader('Proxy-Authorization', ' Basic '.base64_encode($proxyusername.':'.$proxypassword));
3801 $this->debug('remove proxy');
3803 unsetHeader('Proxy-Authorization');
3809 * Test if the given string starts with a header that is to be skipped.
3810 * Skippable headers result from chunked transfer and proxy requests.
3812 * @param string $data The string to check.
3813 * @returns boolean Whether a skippable header was found.
3816 function isSkippableCurlHeader(&$data) {
3817 $skipHeaders = array( 'HTTP/1.1 100',
3824 'HTTP/1.0 200 Connection established');
3825 foreach ($skipHeaders as $hd) {
3826 $prefix = substr($data, 0, strlen($hd));
3827 if ($prefix == $hd) return true;
3834 * decode a string that is encoded w/ "chunked' transfer encoding
3835 * as defined in RFC2068 19.4.6
3837 * @param string $buffer
3843 function decodeChunked($buffer, $lb){
3848 // read chunk-size, chunk-extension (if any) and CRLF
3849 // get the position of the linebreak
3850 $chunkend = strpos($buffer, $lb);
3851 if ($chunkend == FALSE) {
3852 $this->debug('no linebreak found in decodeChunked');
3855 $temp = substr($buffer,0,$chunkend);
3856 $chunk_size = hexdec( trim($temp) );
3857 $chunkstart = $chunkend + strlen($lb);
3858 // while (chunk-size > 0) {
3859 while ($chunk_size > 0) {
3860 $this->debug("chunkstart: $chunkstart chunk_size: $chunk_size");
3861 $chunkend = strpos( $buffer, $lb, $chunkstart + $chunk_size);
3863 // Just in case we got a broken connection
3864 if ($chunkend == FALSE) {
3865 $chunk = substr($buffer,$chunkstart);
3866 // append chunk-data to entity-body
3868 $length += strlen($chunk);
3872 // read chunk-data and CRLF
3873 $chunk = substr($buffer,$chunkstart,$chunkend-$chunkstart);
3874 // append chunk-data to entity-body
3876 // length := length + chunk-size
3877 $length += strlen($chunk);
3878 // read chunk-size and CRLF
3879 $chunkstart = $chunkend + strlen($lb);
3881 $chunkend = strpos($buffer, $lb, $chunkstart) + strlen($lb);
3882 if ($chunkend == FALSE) {
3883 break; //Just in case we got a broken connection
3885 $temp = substr($buffer,$chunkstart,$chunkend-$chunkstart);
3886 $chunk_size = hexdec( trim($temp) );
3887 $chunkstart = $chunkend;
3893 * Writes the payload, including HTTP headers, to $this->outgoing_payload.
3895 * @param string $data HTTP body
3896 * @param string $cookie_str data for HTTP Cookie header
3900 function buildPayload($data, $cookie_str = '') {
3901 // Note: for cURL connections, $this->outgoing_payload is ignored,
3902 // as is the Content-Length header, but these are still created as
3903 // debugging guides.
3905 // add content-length header
3906 if ($this->request_method != 'GET') {
3907 $this->setHeader('Content-Length', strlen($data));
3910 // start building outgoing payload:
3916 $req = "$this->request_method $uri HTTP/$this->protocol_version";
3917 $this->debug("HTTP request: $req");
3918 $this->outgoing_payload = "$req\r\n";
3920 // loop thru headers, serializing
3921 foreach($this->outgoing_headers as $k => $v){
3923 $this->debug("HTTP header: $hdr");
3924 $this->outgoing_payload .= "$hdr\r\n";
3928 if ($cookie_str != '') {
3929 $hdr = 'Cookie: '.$cookie_str;
3930 $this->debug("HTTP header: $hdr");
3931 $this->outgoing_payload .= "$hdr\r\n";
3934 // header/body separator
3935 $this->outgoing_payload .= "\r\n";
3938 $this->outgoing_payload .= $data;
3942 * sends the SOAP request via HTTP[S]
3944 * @param string $data message data
3945 * @param array $cookies cookies to send
3946 * @return boolean true if OK, false if problem
3949 function sendRequest($data, $cookies = NULL) {
3950 // build cookie string
3951 $cookie_str = $this->getCookiesForRequest($cookies, (($this->scheme == 'ssl') || ($this->scheme == 'https')));
3954 $this->buildPayload($data, $cookie_str);
3956 if ($this->io_method() == 'socket') {
3958 if(!fputs($this->fp, $this->outgoing_payload, strlen($this->outgoing_payload))) {
3959 $this->setError('couldn\'t write message data to socket');
3960 $this->debug('couldn\'t write message data to socket');
3963 $this->debug('wrote data to socket, length = ' . strlen($this->outgoing_payload));
3965 } else if ($this->io_method() == 'curl') {
3967 // cURL does say this should only be the verb, and in fact it
3968 // turns out that the URI and HTTP version are appended to this, which
3969 // some servers refuse to work with (so we no longer use this method!)
3970 //$this->setCurlOption(CURLOPT_CUSTOMREQUEST, $this->outgoing_payload);
3971 $curl_headers = array();
3972 foreach($this->outgoing_headers as $k => $v){
3973 if ($k == 'Connection' || $k == 'Content-Length' || $k == 'Host' || $k == 'Authorization' || $k == 'Proxy-Authorization') {
3974 $this->debug("Skip cURL header $k: $v");
3976 $curl_headers[] = "$k: $v";
3979 if ($cookie_str != '') {
3980 $curl_headers[] = 'Cookie: ' . $cookie_str;
3982 $this->setCurlOption(CURLOPT_HTTPHEADER, $curl_headers);
3983 $this->debug('set cURL HTTP headers');
3984 if ($this->request_method == "POST") {
3985 $this->setCurlOption(CURLOPT_POST, 1);
3986 $this->setCurlOption(CURLOPT_POSTFIELDS, $data);
3987 $this->debug('set cURL POST data');
3990 // insert custom user-set cURL options
3991 foreach ($this->ch_options as $key => $val) {
3992 $this->setCurlOption($key, $val);
3995 $this->debug('set cURL payload');
4001 * gets the SOAP response via HTTP[S]
4003 * @return string the response (also sets member variables like incoming_payload)
4006 function getResponse(){
4007 $this->incoming_payload = '';
4009 if ($this->io_method() == 'socket') {
4010 // loop until headers have been retrieved
4012 while (!isset($lb)){
4014 // We might EOF during header read.
4015 if(feof($this->fp)) {
4016 $this->incoming_payload = $data;
4017 $this->debug('found no headers before EOF after length ' . strlen($data));
4018 $this->debug("received before EOF:\n" . $data);
4019 $this->setError('server failed to send headers');
4023 $tmp = fgets($this->fp, 256);
4024 $tmplen = strlen($tmp);
4025 $this->debug("read line of $tmplen bytes: " . trim($tmp));
4028 $this->incoming_payload = $data;
4029 $this->debug('socket read of headers timed out after length ' . strlen($data));
4030 $this->debug("read before timeout: " . $data);
4031 $this->setError('socket read of headers timed out');
4036 $pos = strpos($data,"\r\n\r\n");
4040 $pos = strpos($data,"\n\n");
4045 // remove 100 headers
4046 if (isset($lb) && preg_match('/^HTTP\/1.1 100/',$data)) {
4051 // store header data
4052 $this->incoming_payload .= $data;
4053 $this->debug('found end of headers after length ' . strlen($data));
4055 $header_data = trim(substr($data,0,$pos));
4056 $header_array = explode($lb,$header_data);
4057 $this->incoming_headers = array();
4058 $this->incoming_cookies = array();
4059 foreach($header_array as $header_line){
4060 $arr = explode(':',$header_line, 2);
4061 if(count($arr) > 1){
4062 $header_name = strtolower(trim($arr[0]));
4063 $this->incoming_headers[$header_name] = trim($arr[1]);
4064 if ($header_name == 'set-cookie') {
4065 // TODO: allow multiple cookies from parseCookie
4066 $cookie = $this->parseCookie(trim($arr[1]));
4068 $this->incoming_cookies[] = $cookie;
4069 $this->debug('found cookie: ' . $cookie['name'] . ' = ' . $cookie['value']);
4071 $this->debug('did not find cookie in ' . trim($arr[1]));
4074 } else if (isset($header_name)) {
4075 // append continuation line to previous header
4076 $this->incoming_headers[$header_name] .= $lb . ' ' . $header_line;
4080 // loop until msg has been received
4081 if (isset($this->incoming_headers['transfer-encoding']) && strtolower($this->incoming_headers['transfer-encoding']) == 'chunked') {
4082 $content_length = 2147483647; // ignore any content-length header
4084 $this->debug("want to read chunked content");
4085 } elseif (isset($this->incoming_headers['content-length'])) {
4086 $content_length = $this->incoming_headers['content-length'];
4088 $this->debug("want to read content of length $content_length");
4090 $content_length = 2147483647;
4092 $this->debug("want to read content to EOF");
4097 $tmp = fgets($this->fp, 256);
4098 $tmplen = strlen($tmp);
4099 $this->debug("read chunk line of $tmplen bytes");
4101 $this->incoming_payload = $data;
4102 $this->debug('socket read of chunk length timed out after length ' . strlen($data));
4103 $this->debug("read before timeout:\n" . $data);
4104 $this->setError('socket read of chunk length timed out');
4107 $content_length = hexdec(trim($tmp));
4108 $this->debug("chunk length $content_length");
4111 while (($strlen < $content_length) && (!feof($this->fp))) {
4112 $readlen = min(8192, $content_length - $strlen);
4113 $tmp = fread($this->fp, $readlen);
4114 $tmplen = strlen($tmp);
4115 $this->debug("read buffer of $tmplen bytes");
4116 if (($tmplen == 0) && (!feof($this->fp))) {
4117 $this->incoming_payload = $data;
4118 $this->debug('socket read of body timed out after length ' . strlen($data));
4119 $this->debug("read before timeout:\n" . $data);
4120 $this->setError('socket read of body timed out');
4126 if ($chunked && ($content_length > 0)) {
4127 $tmp = fgets($this->fp, 256);
4128 $tmplen = strlen($tmp);
4129 $this->debug("read chunk terminator of $tmplen bytes");
4131 $this->incoming_payload = $data;
4132 $this->debug('socket read of chunk terminator timed out after length ' . strlen($data));
4133 $this->debug("read before timeout:\n" . $data);
4134 $this->setError('socket read of chunk terminator timed out');
4138 } while ($chunked && ($content_length > 0) && (!feof($this->fp)));
4139 if (feof($this->fp)) {
4140 $this->debug('read to EOF');
4142 $this->debug('read body of length ' . strlen($data));
4143 $this->incoming_payload .= $data;
4144 $this->debug('received a total of '.strlen($this->incoming_payload).' bytes of data from server');
4146 // close filepointer
4148 (isset($this->incoming_headers['connection']) && strtolower($this->incoming_headers['connection']) == 'close') ||
4149 (! $this->persistentConnection) || feof($this->fp)){
4152 $this->debug('closed socket');
4155 // connection was closed unexpectedly
4156 if($this->incoming_payload == ''){
4157 $this->setError('no response from server');
4161 // decode transfer-encoding
4162 // if(isset($this->incoming_headers['transfer-encoding']) && strtolower($this->incoming_headers['transfer-encoding']) == 'chunked'){
4163 // if(!$data = $this->decodeChunked($data, $lb)){
4164 // $this->setError('Decoding of chunked data failed');
4167 //print "<pre>\nde-chunked:\n---------------\n$data\n\n---------------\n</pre>";
4168 // set decoded payload
4169 // $this->incoming_payload = $header_data.$lb.$lb.$data;
4172 } else if ($this->io_method() == 'curl') {
4174 $this->debug('send and receive with cURL');
4175 $this->incoming_payload = curl_exec($this->ch);
4176 $data = $this->incoming_payload;
4178 $cErr = curl_error($this->ch);
4180 $err = 'cURL ERROR: '.curl_errno($this->ch).': '.$cErr.'<br>';
4181 // TODO: there is a PHP bug that can cause this to SEGV for CURLINFO_CONTENT_TYPE
4182 foreach(curl_getinfo($this->ch) as $k => $v){
4183 $err .= "$k: $v<br>";
4186 $this->setError($err);
4187 curl_close($this->ch);
4191 //var_dump(curl_getinfo($this->ch));
4195 $this->debug('No cURL error, closing cURL');
4196 curl_close($this->ch);
4198 // try removing skippable headers
4200 while ($this->isSkippableCurlHeader($data)) {
4201 $this->debug("Found HTTP header to skip");
4202 if ($pos = strpos($data,"\r\n\r\n")) {
4203 $data = ltrim(substr($data,$pos));
4204 } elseif($pos = strpos($data,"\n\n") ) {
4205 $data = ltrim(substr($data,$pos));
4210 // have nothing left; just remove 100 header(s)
4212 while (preg_match('/^HTTP\/1.1 100/',$data)) {
4213 if ($pos = strpos($data,"\r\n\r\n")) {
4214 $data = ltrim(substr($data,$pos));
4215 } elseif($pos = strpos($data,"\n\n") ) {
4216 $data = ltrim(substr($data,$pos));
4221 // separate content from HTTP headers
4222 if ($pos = strpos($data,"\r\n\r\n")) {
4224 } elseif( $pos = strpos($data,"\n\n")) {
4227 $this->debug('no proper separation of headers and document');
4228 $this->setError('no proper separation of headers and document');
4231 $header_data = trim(substr($data,0,$pos));
4232 $header_array = explode($lb,$header_data);
4233 $data = ltrim(substr($data,$pos));
4234 $this->debug('found proper separation of headers and document');
4235 $this->debug('cleaned data, stringlen: '.strlen($data));
4237 foreach ($header_array as $header_line) {
4238 $arr = explode(':',$header_line,2);
4239 if(count($arr) > 1){
4240 $header_name = strtolower(trim($arr[0]));
4241 $this->incoming_headers[$header_name] = trim($arr[1]);
4242 if ($header_name == 'set-cookie') {
4243 // TODO: allow multiple cookies from parseCookie
4244 $cookie = $this->parseCookie(trim($arr[1]));
4246 $this->incoming_cookies[] = $cookie;
4247 $this->debug('found cookie: ' . $cookie['name'] . ' = ' . $cookie['value']);
4249 $this->debug('did not find cookie in ' . trim($arr[1]));
4252 } else if (isset($header_name)) {
4253 // append continuation line to previous header
4254 $this->incoming_headers[$header_name] .= $lb . ' ' . $header_line;
4259 $this->response_status_line = $header_array[0];
4260 $arr = explode(' ', $this->response_status_line, 3);
4261 $http_version = $arr[0];
4262 $http_status = intval($arr[1]);
4263 $http_reason = count($arr) > 2 ? $arr[2] : '';
4265 // see if we need to resend the request with http digest authentication
4266 if (isset($this->incoming_headers['location']) && ($http_status == 301 || $http_status == 302)) {
4267 $this->debug("Got $http_status $http_reason with Location: " . $this->incoming_headers['location']);
4268 $this->setURL($this->incoming_headers['location']);
4269 $this->tryagain = true;
4273 // see if we need to resend the request with http digest authentication
4274 if (isset($this->incoming_headers['www-authenticate']) && $http_status == 401) {
4275 $this->debug("Got 401 $http_reason with WWW-Authenticate: " . $this->incoming_headers['www-authenticate']);
4276 if (strstr($this->incoming_headers['www-authenticate'], "Digest ")) {
4277 $this->debug('Server wants digest authentication');
4278 // remove "Digest " from our elements
4279 $digestString = str_replace('Digest ', '', $this->incoming_headers['www-authenticate']);
4281 // parse elements into array
4282 $digestElements = explode(',', $digestString);
4283 foreach ($digestElements as $val) {
4284 $tempElement = explode('=', trim($val), 2);
4285 $digestRequest[$tempElement[0]] = str_replace("\"", '', $tempElement[1]);
4288 // should have (at least) qop, realm, nonce
4289 if (isset($digestRequest['nonce'])) {
4290 $this->setCredentials($this->username, $this->password, 'digest', $digestRequest);
4291 $this->tryagain = true;
4295 $this->debug('HTTP authentication failed');
4296 $this->setError('HTTP authentication failed');
4301 ($http_status >= 300 && $http_status <= 307) ||
4302 ($http_status >= 400 && $http_status <= 417) ||
4303 ($http_status >= 501 && $http_status <= 505)
4305 $this->setError("Unsupported HTTP response status $http_status $http_reason (soapclient->response has contents of the response)");
4309 // decode content-encoding
4310 if(isset($this->incoming_headers['content-encoding']) && $this->incoming_headers['content-encoding'] != ''){
4311 if(strtolower($this->incoming_headers['content-encoding']) == 'deflate' || strtolower($this->incoming_headers['content-encoding']) == 'gzip'){
4312 // if decoding works, use it. else assume data wasn't gzencoded
4313 if(function_exists('gzinflate')){
4314 //$timer->setMarker('starting decoding of gzip/deflated content');
4315 // IIS 5 requires gzinflate instead of gzuncompress (similar to IE 5 and gzdeflate v. gzcompress)
4316 // this means there are no Zlib headers, although there should be
4317 $this->debug('The gzinflate function exists');
4318 $datalen = strlen($data);
4319 if ($this->incoming_headers['content-encoding'] == 'deflate') {
4320 if ($degzdata = @gzinflate($data)) {
4322 $this->debug('The payload has been inflated to ' . strlen($data) . ' bytes');
4323 if (strlen($data) < $datalen) {
4324 // test for the case that the payload has been compressed twice
4325 $this->debug('The inflated payload is smaller than the gzipped one; try again');
4326 if ($degzdata = @gzinflate($data)) {
4328 $this->debug('The payload has been inflated again to ' . strlen($data) . ' bytes');
4332 $this->debug('Error using gzinflate to inflate the payload');
4333 $this->setError('Error using gzinflate to inflate the payload');
4335 } elseif ($this->incoming_headers['content-encoding'] == 'gzip') {
4336 if ($degzdata = @gzinflate(substr($data, 10))) { // do our best
4338 $this->debug('The payload has been un-gzipped to ' . strlen($data) . ' bytes');
4339 if (strlen($data) < $datalen) {
4340 // test for the case that the payload has been compressed twice
4341 $this->debug('The un-gzipped payload is smaller than the gzipped one; try again');
4342 if ($degzdata = @gzinflate(substr($data, 10))) {
4344 $this->debug('The payload has been un-gzipped again to ' . strlen($data) . ' bytes');
4348 $this->debug('Error using gzinflate to un-gzip the payload');
4349 $this->setError('Error using gzinflate to un-gzip the payload');
4352 //$timer->setMarker('finished decoding of gzip/deflated content');
4353 //print "<xmp>\nde-inflated:\n---------------\n$data\n-------------\n</xmp>";
4354 // set decoded payload
4355 $this->incoming_payload = $header_data.$lb.$lb.$data;
4357 $this->debug('The server sent compressed data. Your php install must have the Zlib extension compiled in to support this.');
4358 $this->setError('The server sent compressed data. Your php install must have the Zlib extension compiled in to support this.');
4361 $this->debug('Unsupported Content-Encoding ' . $this->incoming_headers['content-encoding']);
4362 $this->setError('Unsupported Content-Encoding ' . $this->incoming_headers['content-encoding']);
4365 $this->debug('No Content-Encoding header');
4368 if(strlen($data) == 0){
4369 $this->debug('no data after headers!');
4370 $this->setError('no data present after HTTP headers');
4378 * sets the content-type for the SOAP message to be sent
4380 * @param string $type the content type, MIME style
4381 * @param mixed $charset character set used for encoding (or false)
4384 function setContentType($type, $charset = false) {
4385 $this->setHeader('Content-Type', $type . ($charset ? '; charset=' . $charset : ''));
4389 * specifies that an HTTP persistent connection should be used
4391 * @return boolean whether the request was honored by this method.
4394 function usePersistentConnection(){
4395 if (isset($this->outgoing_headers['Accept-Encoding'])) {
4398 $this->protocol_version = '1.1';
4399 $this->persistentConnection = true;
4400 $this->setHeader('Connection', 'Keep-Alive');
4405 * parse an incoming Cookie into it's parts
4407 * @param string $cookie_str content of cookie
4408 * @return array with data of that cookie
4412 * TODO: allow a Set-Cookie string to be parsed into multiple cookies
4414 function parseCookie($cookie_str) {
4415 $cookie_str = str_replace('; ', ';', $cookie_str) . ';';
4416 $data = preg_split('/;/', $cookie_str);
4417 $value_str = $data[0];
4419 $cookie_param = 'domain=';
4420 $start = strpos($cookie_str, $cookie_param);
4422 $domain = substr($cookie_str, $start + strlen($cookie_param));
4423 $domain = substr($domain, 0, strpos($domain, ';'));
4428 $cookie_param = 'expires=';
4429 $start = strpos($cookie_str, $cookie_param);
4431 $expires = substr($cookie_str, $start + strlen($cookie_param));
4432 $expires = substr($expires, 0, strpos($expires, ';'));
4437 $cookie_param = 'path=';
4438 $start = strpos($cookie_str, $cookie_param);
4440 $path = substr($cookie_str, $start + strlen($cookie_param));
4441 $path = substr($path, 0, strpos($path, ';'));
4446 $cookie_param = ';secure;';
4447 if (strpos($cookie_str, $cookie_param) !== FALSE) {
4453 $sep_pos = strpos($value_str, '=');
4456 $name = substr($value_str, 0, $sep_pos);
4457 $value = substr($value_str, $sep_pos + 1);
4458 $cookie= array( 'name' => $name,
4460 'domain' => $domain,
4462 'expires' => $expires,
4471 * sort out cookies for the current request
4473 * @param array $cookies array with all cookies
4474 * @param boolean $secure is the send-content secure or not?
4475 * @return string for Cookie-HTTP-Header
4478 function getCookiesForRequest($cookies, $secure=false) {
4480 if ((! is_null($cookies)) && (is_array($cookies))) {
4481 foreach ($cookies as $cookie) {
4482 if (! is_array($cookie)) {
4485 $this->debug("check cookie for validity: ".$cookie['name'].'='.$cookie['value']);
4486 if ((isset($cookie['expires'])) && (! empty($cookie['expires']))) {
4487 if (strtotime($cookie['expires']) <= time()) {
4488 $this->debug('cookie has expired');
4492 if ((isset($cookie['domain'])) && (! empty($cookie['domain']))) {
4493 $domain = preg_quote($cookie['domain']);
4494 if (! preg_match("'.*$domain$'i", $this->host)) {
4495 $this->debug('cookie has different domain');
4499 if ((isset($cookie['path'])) && (! empty($cookie['path']))) {
4500 $path = preg_quote($cookie['path']);
4501 if (! preg_match("'^$path.*'i", $this->path)) {
4502 $this->debug('cookie is for a different path');
4506 if ((! $secure) && (isset($cookie['secure'])) && ($cookie['secure'])) {
4507 $this->debug('cookie is secure, transport is not');
4510 $cookie_str .= $cookie['name'] . '=' . $cookie['value'] . '; ';
4511 $this->debug('add cookie to Cookie-String: ' . $cookie['name'] . '=' . $cookie['value']);
4522 Modification information for LGPL compliance
4524 r58622 - 2010-10-22 18:18:59 -0700 (Fri, 22 Oct 2010) - engsvnbuild - Author: lam <lam@198.18.142.201>
4527 r58361 - 2010-09-29 16:59:02 -0700 (Wed, 29 Sep 2010) - kjing - Author: Jenny Gonsalves <jenny@sugarcrm.com>
4528 Merging with maint_6_0_1 (svn merge -r 58250:58342)
4530 r57813 - 2010-08-19 10:34:44 -0700 (Thu, 19 Aug 2010) - kjing - Author: John Mertic <jmertic@sugarcrm.com>
4531 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.
4533 r57707 - 2010-08-10 12:26:13 -0700 (Tue, 10 Aug 2010) - kjing - Author: Stanislav Malyshev <smalyshev@gmail.com>
4534 fix SOAP calls with no parameters
4536 r56990 - 2010-06-16 13:05:36 -0700 (Wed, 16 Jun 2010) - kjing - snapshot "Mango" svn branch to a new one for GitHub sync
4538 r56989 - 2010-06-16 13:01:33 -0700 (Wed, 16 Jun 2010) - kjing - defunt "Mango" svn dev branch before github cutover
4540 r55980 - 2010-04-19 13:31:28 -0700 (Mon, 19 Apr 2010) - kjing - create Mango (6.1) based on windex
4542 r51719 - 2009-10-22 10:18:00 -0700 (Thu, 22 Oct 2009) - mitani - Converted to Build 3 tags and updated the build system
4544 r51634 - 2009-10-19 13:32:22 -0700 (Mon, 19 Oct 2009) - mitani - Windex is the branch for Sugar Sales 1.0 development
4546 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.
4548 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.
4550 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:
4551 - Changing all ereg function to either preg or simple string based ones
4552 - No more references to magic quotes.
4553 - Change all the session_unregister() functions to just unset() the correct session variable instead.
4555 r50375 - 2009-08-24 18:07:43 -0700 (Mon, 24 Aug 2009) - dwong - branch kobe2 from tokyo r50372
4557 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
4559 r45680 - 2009-03-30 14:34:35 -0700 (Mon, 30 Mar 2009) - Samir Gandhi - modifeid serializeSchema to generate WS-I compliant WSDL
4561 r42807 - 2008-12-29 11:16:59 -0800 (Mon, 29 Dec 2008) - dwong - Branch from trunk/sugarcrm r42806 to branches/tokyo/sugarcrm
4563 r42645 - 2008-12-18 13:41:08 -0800 (Thu, 18 Dec 2008) - awu - merging maint_5_2_0 rev41336:HEAD to trunk
4565 r41647 - 2008-11-11 17:44:30 -0800 (Tue, 11 Nov 2008) - majed - Fixes a few bugs
4567 r41596 - 2008-11-10 19:20:04 -0800 (Mon, 10 Nov 2008) - Samir Gandhi - modified to set $method in the code
4569 r41558 - 2008-11-10 14:35:34 -0800 (Mon, 10 Nov 2008) - majed - changes nusoap to allow for registering classes
4571 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.
4573 - data/SugarBean.php
4574 - include/domit/php_http_client_generic.php
4575 - include/domit/php_http_connector.php
4576 - include/domit/testing_domit.php
4577 - include/domit/xml_domit_getelementsbypath.php
4578 - include/domit/xml_domit_lite_parser.php
4579 - include/domit/xml_domit_nodemaps.php
4580 - include/domit/xml_domit_parser.php
4581 - include/domit/xml_domit_shared.php
4582 - include/generic/SugarWidgets/SugarWidgetField.php
4583 - include/generic/SugarWidgets/SugarWidgetReportField.php
4584 - include/ListView/ProcessView.php
4585 - include/nusoap/class.soapclient.php
4586 - include/nusoap/nusoap.php
4587 - include/nusoap/nusoapmime.php
4588 - include/Pear/HTML_Safe/Safe.php
4589 - include/Pear/XML_HTMLSax3/HTMLSax3.php
4590 - modules/Administration/RebuildWorkFlow.php
4591 - modules/Expressions/RelateSelector.php
4592 - modules/Reports/templates/templates_reports.php
4593 - modules/WorkFlow/Delete.php
4594 - modules/WorkFlow/Save.php
4595 - modules/WorkFlow/SaveSequence.php
4596 - modules/WorkFlow/WorkFlow.php
4597 - modules/WorkFlowActionShells/CreateStep1.php
4598 - modules/WorkFlowActionShells/CreateStep2.php
4599 - modules/WorkFlowActionShells/Save.php
4600 - modules/WorkFlowActionShells/WorkFlowActionShell.php
4601 - modules/WorkFlowAlerts/Save.php
4602 - modules/WorkFlowAlerts/WorkFlowAlert.php
4603 - modules/WorkFlowAlertShells/DetailView.php
4604 - modules/WorkFlowAlertShells/WorkFlowAlertShell.php
4605 - modules/WorkFlowTriggerShells/CreateStep1.php
4606 - modules/WorkFlowTriggerShells/CreateStepFilter.php
4607 - modules/WorkFlowTriggerShells/SaveFilter.php
4608 - modules/WorkFlowTriggerShells/WorkFlowTriggerShell.php
4609 - soap/SoapHelperFunctions.php
4610 - test/modules/DynamicFields/DynamicFields_Bug24095_test.php
4611 - test/simpletest/browser.php
4612 - test/simpletest/default_reporter.php
4613 - test/simpletest/detached.php
4614 - test/simpletest/eclipse.php
4615 - test/simpletest/expectation.php
4616 - test/simpletest/extensions/pear_test_case.php
4617 - test/simpletest/form.php
4618 - test/simpletest/http.php
4619 - test/simpletest/mock_objects.php
4620 - test/simpletest/page.php
4621 - test/simpletest/parser.php
4622 - test/simpletest/remote.php
4623 - test/simpletest/shell_tester.php
4624 - test/simpletest/simple_test.php
4625 - test/simpletest/simpletest.php
4626 - test/simpletest/test/acceptance_test.php
4627 - test/simpletest/test/adapter_test.php
4628 - test/simpletest/test/authentication_test.php
4629 - test/simpletest/test/browser_test.php
4630 - test/simpletest/test/collector_test.php
4631 - test/simpletest/test/compatibility_test.php
4632 - test/simpletest/test/detached_test.php
4633 - test/simpletest/test/eclipse_test.php
4634 - test/simpletest/test/encoding_test.php
4635 - test/simpletest/test/errors_test.php
4636 - test/simpletest/test/expectation_test.php
4637 - test/simpletest/test/form_test.php
4638 - test/simpletest/test/frames_test.php
4639 - test/simpletest/test/http_test.php
4640 - test/simpletest/test/live_test.php
4641 - test/simpletest/test/mock_objects_test.php
4642 - test/simpletest/test/page_test.php
4643 - test/simpletest/test/parse_error_test.php
4644 - test/simpletest/test/parser_test.php
4645 - test/simpletest/test/remote_test.php
4646 - test/simpletest/test/shell_test.php
4647 - test/simpletest/test/shell_tester_test.php
4648 - test/simpletest/test/simpletest_test.php
4649 - test/simpletest/test/site/page_request.php
4650 - test/simpletest/test/tag_test.php
4651 - test/simpletest/test/unit_tester_test.php
4652 - test/simpletest/test/user_agent_test.php
4653 - test/simpletest/test/visual_test.php
4654 - test/simpletest/test/xml_test.php
4655 - test/simpletest/test_case.php
4656 - test/simpletest/ui/array_reporter/test.php
4657 - test/simpletest/ui/recorder/test.php
4658 - test/simpletest/unit_tester.php
4659 - test/simpletest/url.php
4660 - test/simpletest/user_agent.php
4661 - test/simpletest/web_tester.php
4662 - test/spikephpcoverage/src/PEAR.php
4663 - test/spikephpcoverage/src/util/Utility.php
4664 - test/spikephpcoverage/src/XML/Parser.php
4665 - test/spikephpcoverage/src/XML/Parser/Simple.php
4666 - test/test_utilities/SugarTest_SimpleBrowser.php
4668 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.
4670 r38300 - 2008-07-25 13:33:43 -0700 (Fri, 25 Jul 2008) - Samir Gandhi - put the debug in parseresponse function
4672 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
4674 r36824 - 2008-06-18 09:26:11 -0700 (Wed, 18 Jun 2008) - roger - bug: 21832
4676 r26422 - 2007-09-05 17:29:12 -0700 (Wed, 05 Sep 2007) - majed - migrate from beta 1 to trunk
4678 r15787 - 2006-08-10 10:14:41 -0700 (Thu, 10 Aug 2006) - roger - RRS: bug 7961
4680 r14701 - 2006-07-17 13:37:26 -0700 (Mon, 17 Jul 2006) - roger - RRS: bug 5801
4682 r13782 - 2006-06-06 10:58:55 -0700 (Tue, 06 Jun 2006) - majed - changes entry point code
4684 r11466 - 2006-02-01 15:49:47 -0800 (Wed, 01 Feb 2006) - jacob - Adding extra !empty check to get around a PHP warning.
4686 r11115 - 2006-01-17 14:54:45 -0800 (Tue, 17 Jan 2006) - majed - add entry point validation
4688 r10585 - 2005-12-13 14:42:26 -0800 (Tue, 13 Dec 2005) - majed - adds new license mechanisim
4690 r10170 - 2005-12-05 18:37:46 -0800 (Mon, 05 Dec 2005) - majed - fixes various issues
4692 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.
4694 r8991 - 2005-11-03 19:07:25 -0800 (Thu, 03 Nov 2005) - majed - fixes nusoap issue
4696 r8846 - 2005-10-31 11:01:12 -0800 (Mon, 31 Oct 2005) - majed - new version of nusoap
4698 r7905 - 2005-09-21 19:12:57 -0700 (Wed, 21 Sep 2005) - majed - restores old nusoap pre & with a few fixes
4700 r7861 - 2005-09-20 15:40:25 -0700 (Tue, 20 Sep 2005) - majed - & fix for 3.5.1
4702 r7452 - 2005-08-17 11:32:34 -0700 (Wed, 17 Aug 2005) - majed - changes soap to nusoap
4704 r5820 - 2005-06-21 14:22:24 -0700 (Tue, 21 Jun 2005) - majed - fixes issues with nusoap and with custom fields
4706 r5462 - 2005-05-25 13:50:11 -0700 (Wed, 25 May 2005) - majed - upgraded nusoap to .6.9
4708 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
4710 r573 - 2004-09-04 13:03:32 -0700 (Sat, 04 Sep 2004) - sugarclint - undoing copyrights added in inadvertantly. --clint
4712 r546 - 2004-09-03 11:49:38 -0700 (Fri, 03 Sep 2004) - sugarmsi - removed echo count
4714 r354 - 2004-08-02 23:00:37 -0700 (Mon, 02 Aug 2004) - sugarjacob - Adding Soap
4725 * nusoap_server allows the user to create a SOAP server
4726 * that is capable of receiving messages and returning responses
4728 * @author Dietrich Ayala <dietrich@ganx4.com>
4729 * @author Scott Nichol <snichol@users.sourceforge.net>
4733 class nusoap_server extends nusoap_base {
4735 * HTTP headers of request
4739 var $headers = array();
4747 * SOAP headers from request (incomplete namespace resolution; special characters not escaped) (text)
4751 var $requestHeaders = '';
4753 * SOAP Headers from request (parsed)
4757 var $requestHeader = NULL;
4759 * SOAP body request portion (incomplete namespace resolution; special characters not escaped) (text)
4765 * SOAP payload for request (text)
4769 var $requestSOAP = '';
4771 * requested method namespace URI
4775 var $methodURI = '';
4777 * name of method requested
4781 var $methodname = '';
4783 * method parameters from request
4787 var $methodparams = array();
4789 * SOAP Action from request
4793 var $SOAPAction = '';
4795 * character set encoding of incoming (request) messages
4799 var $xml_encoding = '';
4801 * toggles whether the parser decodes element content w/ utf8_decode()
4805 var $decode_utf8 = false;
4808 * HTTP headers of response
4812 var $outgoing_headers = array();
4820 * SOAP headers for response (text or array of soapval or associative array)
4824 var $responseHeaders = '';
4826 * SOAP payload for response (text)
4830 var $responseSOAP = '';
4832 * method return value to place in response
4836 var $methodreturn = false;
4838 * whether $methodreturn is a string of literal XML
4842 var $methodreturnisliteralxml = false;
4844 * SOAP fault for response (or false)
4850 * text indication of result (for debugging)
4854 var $result = 'successful';
4857 * assoc array of operations => opData; operations are added by the register()
4858 * method or by parsing an external WSDL definition
4862 var $operations = array();
4864 * wsdl instance (if one)
4870 * URL for WSDL (if one)
4874 var $externalWSDLURL = false;
4876 * whether to append debug to response as XML comment
4880 var $debug_flag = false;
4885 * the optional parameter is a path to a WSDL file that you'd like to bind the server instance to.
4887 * @param mixed $wsdl file path or URL (string), or wsdl instance (object)
4890 function nusoap_server($wsdl=false){
4891 parent::nusoap_base();
4892 // turn on debugging?
4894 global $HTTP_SERVER_VARS;
4896 if (isset($_SERVER)) {
4897 $this->debug("_SERVER is defined:");
4898 $this->appendDebug($this->varDump($_SERVER));
4899 } elseif (isset($HTTP_SERVER_VARS)) {
4900 $this->debug("HTTP_SERVER_VARS is defined:");
4901 $this->appendDebug($this->varDump($HTTP_SERVER_VARS));
4903 $this->debug("Neither _SERVER nor HTTP_SERVER_VARS is defined.");
4906 if (isset($debug)) {
4907 $this->debug("In nusoap_server, set debug_flag=$debug based on global flag");
4908 $this->debug_flag = $debug;
4909 } elseif (isset($_SERVER['QUERY_STRING'])) {
4910 $qs = explode('&', $_SERVER['QUERY_STRING']);
4911 foreach ($qs as $v) {
4912 if (substr($v, 0, 6) == 'debug=') {
4913 $this->debug("In nusoap_server, set debug_flag=" . substr($v, 6) . " based on query string #1");
4914 $this->debug_flag = substr($v, 6);
4917 } elseif (isset($HTTP_SERVER_VARS['QUERY_STRING'])) {
4918 $qs = explode('&', $HTTP_SERVER_VARS['QUERY_STRING']);
4919 foreach ($qs as $v) {
4920 if (substr($v, 0, 6) == 'debug=') {
4921 $this->debug("In nusoap_server, set debug_flag=" . substr($v, 6) . " based on query string #2");
4922 $this->debug_flag = substr($v, 6);
4929 $this->debug("In nusoap_server, WSDL is specified");
4930 if (is_object($wsdl) && (get_class($wsdl) == 'wsdl')) {
4931 $this->wsdl = $wsdl;
4932 $this->externalWSDLURL = $this->wsdl->wsdl;
4933 $this->debug('Use existing wsdl instance from ' . $this->externalWSDLURL);
4935 $this->debug('Create wsdl from ' . $wsdl);
4936 $this->wsdl = new wsdl($wsdl);
4937 $this->externalWSDLURL = $wsdl;
4939 $this->appendDebug($this->wsdl->getDebug());
4940 $this->wsdl->clearDebug();
4941 if($err = $this->wsdl->getError()){
4942 die('WSDL ERROR: '.$err);
4948 * processes request and returns response
4950 * @param string $data usually is the value of $HTTP_RAW_POST_DATA
4953 function service($data){
4954 global $HTTP_SERVER_VARS;
4956 if (isset($_SERVER['REQUEST_METHOD'])) {
4957 $rm = $_SERVER['REQUEST_METHOD'];
4958 } elseif (isset($HTTP_SERVER_VARS['REQUEST_METHOD'])) {
4959 $rm = $HTTP_SERVER_VARS['REQUEST_METHOD'];
4964 if (isset($_SERVER['QUERY_STRING'])) {
4965 $qs = $_SERVER['QUERY_STRING'];
4966 } elseif (isset($HTTP_SERVER_VARS['QUERY_STRING'])) {
4967 $qs = $HTTP_SERVER_VARS['QUERY_STRING'];
4971 $this->debug("In service, request method=$rm query string=$qs strlen(\$data)=" . strlen($data));
4973 if ($rm == 'POST') {
4974 $this->debug("In service, invoke the request");
4975 $this->parse_request($data);
4976 if (! $this->fault) {
4977 $this->invoke_method();
4979 if (! $this->fault) {
4980 $this->serialize_return();
4982 $this->send_response();
4983 } elseif (preg_match('/wsdl/', $qs) ){
4984 $this->debug("In service, this is a request for WSDL");
4985 if ($this->externalWSDLURL){
4986 if (strpos($this->externalWSDLURL, "http://") !== false) { // assume URL
4987 $this->debug("In service, re-direct for WSDL");
4988 header('Location: '.$this->externalWSDLURL);
4989 } else { // assume file
4990 $this->debug("In service, use file passthru for WSDL");
4991 header("Content-Type: text/xml\r\n");
4992 $pos = strpos($this->externalWSDLURL, "file://");
4993 if ($pos === false) {
4994 $filename = $this->externalWSDLURL;
4996 $filename = substr($this->externalWSDLURL, $pos + 7);
4998 $fp = fopen($this->externalWSDLURL, 'r');
5001 } elseif ($this->wsdl) {
5002 $this->debug("In service, serialize WSDL");
5003 header("Content-Type: text/xml; charset=ISO-8859-1\r\n");
5004 print $this->wsdl->serialize($this->debug_flag);
5005 if ($this->debug_flag) {
5006 $this->debug('wsdl:');
5007 $this->appendDebug($this->varDump($this->wsdl));
5008 print $this->getDebugAsXMLComment();
5011 $this->debug("In service, there is no WSDL");
5012 header("Content-Type: text/html; charset=ISO-8859-1\r\n");
5013 print "This service does not provide WSDL";
5015 } elseif ($this->wsdl) {
5016 $this->debug("In service, return Web description");
5017 print $this->wsdl->webDescription();
5019 $this->debug("In service, no Web description");
5020 header("Content-Type: text/html; charset=ISO-8859-1\r\n");
5021 print "This service does not provide a Web description";
5026 * parses HTTP request headers.
5028 * The following fields are set by this function (when successful)
5037 function parse_http_headers() {
5038 global $HTTP_SERVER_VARS;
5040 $this->request = '';
5041 $this->SOAPAction = '';
5042 if(function_exists('getallheaders')){
5043 $this->debug("In parse_http_headers, use getallheaders");
5044 $headers = getallheaders();
5045 foreach($headers as $k=>$v){
5046 $k = strtolower($k);
5047 $this->headers[$k] = $v;
5048 $this->request .= "$k: $v\r\n";
5049 $this->debug("$k: $v");
5051 // get SOAPAction header
5052 if(isset($this->headers['soapaction'])){
5053 $this->SOAPAction = str_replace('"','',$this->headers['soapaction']);
5055 // get the character encoding of the incoming request
5056 if(isset($this->headers['content-type']) && strpos($this->headers['content-type'],'=')){
5057 $enc = str_replace('"','',substr(strstr($this->headers["content-type"],'='),1));
5058 if(preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i',$enc)){
5059 $this->xml_encoding = strtoupper($enc);
5061 $this->xml_encoding = 'US-ASCII';
5064 // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
5065 $this->xml_encoding = 'ISO-8859-1';
5067 } elseif(isset($_SERVER) && is_array($_SERVER)){
5068 $this->debug("In parse_http_headers, use _SERVER");
5069 foreach ($_SERVER as $k => $v) {
5070 if (substr($k, 0, 5) == 'HTTP_') {
5071 $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', substr($k, 5))));
5073 $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', $k)));
5075 if ($k == 'soapaction') {
5076 // get SOAPAction header
5078 $v = str_replace('"', '', $v);
5079 $v = str_replace('\\', '', $v);
5080 $this->SOAPAction = $v;
5081 } else if ($k == 'content-type') {
5082 // get the character encoding of the incoming request
5083 if (strpos($v, '=')) {
5084 $enc = substr(strstr($v, '='), 1);
5085 $enc = str_replace('"', '', $enc);
5086 $enc = str_replace('\\', '', $enc);
5087 if (preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i',$enc)) {
5088 $this->xml_encoding = strtoupper($enc);
5090 $this->xml_encoding = 'US-ASCII';
5093 // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
5094 $this->xml_encoding = 'ISO-8859-1';
5097 $this->headers[$k] = $v;
5098 $this->request .= "$k: $v\r\n";
5099 $this->debug("$k: $v");
5101 } elseif (is_array($HTTP_SERVER_VARS)) {
5102 $this->debug("In parse_http_headers, use HTTP_SERVER_VARS");
5103 foreach ($HTTP_SERVER_VARS as $k => $v) {
5104 if (substr($k, 0, 5) == 'HTTP_') {
5105 $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', substr($k, 5)))); $k = strtolower(substr($k, 5));
5107 $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', $k))); $k = strtolower($k);
5109 if ($k == 'soapaction') {
5110 // get SOAPAction header
5112 $v = str_replace('"', '', $v);
5113 $v = str_replace('\\', '', $v);
5114 $this->SOAPAction = $v;
5115 } else if ($k == 'content-type') {
5116 // get the character encoding of the incoming request
5117 if (strpos($v, '=')) {
5118 $enc = substr(strstr($v, '='), 1);
5119 $enc = str_replace('"', '', $enc);
5120 $enc = str_replace('\\', '', $enc);
5121 if (preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i',$enc)) {
5122 $this->xml_encoding = strtoupper($enc);
5124 $this->xml_encoding = 'US-ASCII';
5127 // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
5128 $this->xml_encoding = 'ISO-8859-1';
5131 $this->headers[$k] = $v;
5132 $this->request .= "$k: $v\r\n";
5133 $this->debug("$k: $v");
5136 $this->debug("In parse_http_headers, HTTP headers not accessible");
5137 $this->setError("HTTP headers not accessible");
5144 * The following fields are set by this function (when successful)
5158 * This sets the fault field on error
5160 * @param string $data XML string
5163 function parse_request($data='') {
5164 $this->debug('entering parse_request()');
5165 $this->parse_http_headers();
5166 $this->debug('got character encoding: '.$this->xml_encoding);
5167 // uncompress if necessary
5168 if (isset($this->headers['content-encoding']) && $this->headers['content-encoding'] != '') {
5169 $this->debug('got content encoding: ' . $this->headers['content-encoding']);
5170 if ($this->headers['content-encoding'] == 'deflate' || $this->headers['content-encoding'] == 'gzip') {
5171 // if decoding works, use it. else assume data wasn't gzencoded
5172 if (function_exists('gzuncompress')) {
5173 if ($this->headers['content-encoding'] == 'deflate' && $degzdata = @gzuncompress($data)) {
5175 } elseif ($this->headers['content-encoding'] == 'gzip' && $degzdata = gzinflate(substr($data, 10))) {
5178 $this->fault('SOAP-ENV:Client', 'Errors occurred when trying to decode the data');
5182 $this->fault('SOAP-ENV:Client', 'This Server does not support compressed data');
5187 $this->request .= "\r\n".$data;
5188 $data = $this->parseRequest($this->headers, $data);
5189 $this->requestSOAP = $data;
5190 $this->debug('leaving parse_request');
5193 function register_class($classname){
5194 $this->registeredClass = $classname;
5197 * invokes a PHP function for the requested SOAP method
5199 * The following fields are set by this function (when successful)
5203 * Note that the PHP function that is called may also set the following
5204 * fields to affect the response sent to the client
5209 * This sets the fault field on error
5213 function invoke_method() {
5214 $this->debug('in invoke_method, methodname=' . $this->methodname . ' methodURI=' . $this->methodURI . ' SOAPAction=' . $this->SOAPAction);
5217 // if you are debugging in this area of the code, your service uses a class to implement methods,
5218 // you use SOAP RPC, and the client is .NET, please be aware of the following...
5219 // when the .NET wsdl.exe utility generates a proxy, it will remove the '.' or '..' from the
5220 // method name. that is fine for naming the .NET methods. it is not fine for properly constructing
5221 // the XML request and reading the XML response. you need to add the RequestElementName and
5222 // ResponseElementName to the System.Web.Services.Protocols.SoapRpcMethodAttribute that wsdl.exe
5223 // generates for the method. these parameters are used to specify the correct XML element names
5224 // for .NET to use, i.e. the names with the '.' in them.
5226 $orig_methodname = $this->methodname;
5228 if ($this->opData = $this->wsdl->getOperationData($this->methodname)) {
5229 $this->debug('in invoke_method, found WSDL operation=' . $this->methodname);
5230 $this->appendDebug('opData=' . $this->varDump($this->opData));
5231 } elseif ($this->opData = $this->wsdl->getOperationDataForSoapAction($this->SOAPAction)) {
5232 // Note: hopefully this case will only be used for doc/lit, since rpc services should have wrapper element
5233 $this->debug('in invoke_method, found WSDL soapAction=' . $this->SOAPAction . ' for operation=' . $this->opData['name']);
5234 $this->appendDebug('opData=' . $this->varDump($this->opData));
5235 $this->methodname = $this->opData['name'];
5237 $this->debug('in invoke_method, no WSDL for operation=' . $this->methodname);
5238 $this->fault('SOAP-ENV:Client', "Operation '" . $this->methodname . "' is not defined in the WSDL for this service");
5242 $this->debug('in invoke_method, no WSDL to validate method');
5245 // if a . is present in $this->methodname, we see if there is a class in scope,
5246 // which could be referred to. We will also distinguish between two deliminators,
5247 // to allow methods to be called a the class or an instance
5248 if (strpos($this->methodname, '..') > 0) {
5250 } else if (strpos($this->methodname, '.') > 0) {
5255 $this->debug("in invoke_method, delim=$delim");
5259 if (strlen($delim) > 0 && substr_count($this->methodname, $delim) == 1) {
5260 $try_class = substr($this->methodname, 0, strpos($this->methodname, $delim));
5261 if (class_exists($try_class)) {
5262 // get the class and method name
5263 $class = $try_class;
5264 $method = substr($this->methodname, strpos($this->methodname, $delim) + strlen($delim));
5265 $this->debug("in invoke_method, class=$class method=$method delim=$delim");
5267 $this->debug("in invoke_method, class=$try_class not found");
5271 $this->debug("in invoke_method, no class to try");
5273 if(empty($delim) && isset($this->registeredClass)){
5274 $class = $this->registeredClass;
5276 $method = $this->methodname;
5279 // does method exist?
5281 if (!function_exists($this->methodname)) {
5282 $this->debug("in invoke_method, function '$this->methodname' not found!");
5283 $this->result = 'fault: method not found';
5284 $this->fault('SOAP-ENV:Client',"method '$this->methodname'('$orig_methodname') not defined in service('$try_class' '$delim')");
5288 $method_to_compare = (substr(phpversion(), 0, 2) == '4.') ? strtolower($method) : $method;
5289 if (!in_array($method_to_compare, get_class_methods($class))) {
5290 $this->debug("in invoke_method, method '$this->methodname' not found in class '$class'!");
5291 $this->result = 'fault: method not found';
5292 $this->fault('SOAP-ENV:Client',"method '$this->methodname'/'$method_to_compare'('$orig_methodname') not defined in service/'$class'('$try_class' '$delim')");
5297 // evaluate message, getting back parameters
5298 // verify that request parameters match the method's signature
5299 if(! $this->verify_method($this->methodname,$this->methodparams)){
5301 $this->debug('ERROR: request not verified against method signature');
5302 $this->result = 'fault: request failed validation against method signature';
5304 $this->fault('SOAP-ENV:Client',"Operation '$this->methodname' not defined in service.");
5308 // if there are parameters to pass
5309 $this->debug('in invoke_method, params:');
5310 $this->appendDebug($this->varDump($this->methodparams));
5311 $this->debug("in invoke_method, calling '$this->methodname'");
5312 if (!function_exists('call_user_func_array')) {
5314 $this->debug('in invoke_method, calling function using eval()');
5315 $funcCall = "\$this->methodreturn = $this->methodname(";
5317 if ($delim == '..') {
5318 $this->debug('in invoke_method, calling class method using eval()');
5319 $funcCall = "\$this->methodreturn = ".$class."::".$method."(";
5321 $this->debug('in invoke_method, calling instance method using eval()');
5322 // generate unique instance name
5323 $instname = "\$inst_".time();
5324 $funcCall = $instname." = new ".$class."(); ";
5325 $funcCall .= "\$this->methodreturn = ".$instname."->".$method."(";
5328 if ($this->methodparams) {
5329 foreach ($this->methodparams as $param) {
5330 if (is_array($param) || is_object($param)) {
5331 $this->fault('SOAP-ENV:Client', 'NuSOAP does not handle complexType parameters correctly when using eval; call_user_func_array must be available');
5334 $funcCall .= "\"$param\",";
5336 $funcCall = substr($funcCall, 0, -1);
5339 $this->debug('in invoke_method, function call: '.$funcCall);
5343 $this->debug('in invoke_method, calling function using call_user_func_array()');
5344 $call_arg = "$this->methodname"; // straight assignment changes $this->methodname to lower case after call_user_func_array()
5345 } elseif ($delim == '..') {
5346 $this->debug('in invoke_method, calling class method using call_user_func_array()');
5347 $call_arg = array ($class, $method);
5349 $this->debug('in invoke_method, calling instance method using call_user_func_array()');
5350 $instance = new $class ();
5351 $call_arg = array(&$instance, $method);
5353 if (is_array($this->methodparams)) {
5354 $this->methodreturn = call_user_func_array($call_arg, array_values($this->methodparams));
5356 $this->methodreturn = call_user_func_array($call_arg, array());
5359 $this->debug('in invoke_method, methodreturn:');
5360 $this->appendDebug($this->varDump($this->methodreturn));
5361 $this->debug("in invoke_method, called method $this->methodname, received data of type ".gettype($this->methodreturn));
5365 * serializes the return value from a PHP function into a full SOAP Envelope
5367 * The following fields are set by this function (when successful)
5371 * This sets the fault field on error
5375 function serialize_return() {
5376 $this->debug('Entering serialize_return methodname: ' . $this->methodname . ' methodURI: ' . $this->methodURI);
5378 if (isset($this->methodreturn) && is_object($this->methodreturn) && ((get_class($this->methodreturn) == 'soap_fault') || (get_class($this->methodreturn) == 'nusoap_fault'))) {
5379 $this->debug('got a fault object from method');
5380 $this->fault = $this->methodreturn;
5382 } elseif ($this->methodreturnisliteralxml) {
5383 $return_val = $this->methodreturn;
5384 // returned value(s)
5386 $this->debug('got a(n) '.gettype($this->methodreturn).' from method');
5387 $this->debug('serializing return value');
5389 if (sizeof($this->opData['output']['parts']) > 1) {
5390 $this->debug('more than one output part, so use the method return unchanged');
5391 $opParams = $this->methodreturn;
5392 } elseif (sizeof($this->opData['output']['parts']) == 1) {
5393 $this->debug('exactly one output part, so wrap the method return in a simple array');
5394 // TODO: verify that it is not already wrapped!
5395 //foreach ($this->opData['output']['parts'] as $name => $type) {
5396 // $this->debug('wrap in element named ' . $name);
5398 $opParams = array($this->methodreturn);
5400 $return_val = $this->wsdl->serializeRPCParameters($this->methodname,'output',$opParams);
5401 $this->appendDebug($this->wsdl->getDebug());
5402 $this->wsdl->clearDebug();
5403 if($errstr = $this->wsdl->getError()){
5404 $this->debug('got wsdl error: '.$errstr);
5405 $this->fault('SOAP-ENV:Server', 'unable to serialize result');
5409 if (isset($this->methodreturn)) {
5410 $return_val = $this->serialize_val($this->methodreturn, 'return');
5413 $this->debug('in absence of WSDL, assume void return for backward compatibility');
5417 $this->debug('return value:');
5418 $this->appendDebug($this->varDump($return_val));
5420 $this->debug('serializing response');
5422 $this->debug('have WSDL for serialization: style is ' . $this->opData['style']);
5423 if ($this->opData['style'] == 'rpc') {
5424 $this->debug('style is rpc for serialization: use is ' . $this->opData['output']['use']);
5425 if ($this->opData['output']['use'] == 'literal') {
5426 // 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
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>';
5433 if ($this->methodURI) {
5434 $payload = '<ns1:'.$this->methodname.'Response xmlns:ns1="'.$this->methodURI.'">'.$return_val.'</ns1:'.$this->methodname."Response>";
5436 $payload = '<'.$this->methodname.'Response>'.$return_val.'</'.$this->methodname.'Response>';
5440 $this->debug('style is not rpc for serialization: assume document');
5441 $payload = $return_val;
5444 $this->debug('do not have WSDL for serialization: assume rpc/encoded');
5445 $payload = '<ns1:'.$this->methodname.'Response xmlns:ns1="'.$this->methodURI.'">'.$return_val.'</ns1:'.$this->methodname."Response>";
5447 $this->result = 'successful';
5449 //if($this->debug_flag){
5450 $this->appendDebug($this->wsdl->getDebug());
5452 if (isset($this->opData['output']['encodingStyle'])) {
5453 $encodingStyle = $this->opData['output']['encodingStyle'];
5455 $encodingStyle = '';
5457 // Added: In case we use a WSDL, return a serialized env. WITH the usedNamespaces.
5458 $this->responseSOAP = $this->serializeEnvelope($payload,$this->responseHeaders,$this->wsdl->usedNamespaces,$this->opData['style'],$this->opData['output']['use'],$encodingStyle);
5460 $this->responseSOAP = $this->serializeEnvelope($payload,$this->responseHeaders);
5462 $this->debug("Leaving serialize_return");
5466 * sends an HTTP response
5468 * The following fields are set by this function (when successful)
5475 function send_response() {
5476 $this->debug('Enter send_response');
5478 $payload = $this->fault->serialize();
5479 $this->outgoing_headers[] = "HTTP/1.0 500 Internal Server Error";
5480 $this->outgoing_headers[] = "Status: 500 Internal Server Error";
5482 $payload = $this->responseSOAP;
5483 // Some combinations of PHP+Web server allow the Status
5484 // to come through as a header. Since OK is the default
5486 // $this->outgoing_headers[] = "HTTP/1.0 200 OK";
5487 // $this->outgoing_headers[] = "Status: 200 OK";
5489 // add debug data if in debug mode
5490 if(isset($this->debug_flag) && $this->debug_flag){
5491 $payload .= $this->getDebugAsXMLComment();
5493 $this->outgoing_headers[] = "Server: $this->title Server v$this->version";
5494 preg_match('/\$Revisio' . 'n: ([^ ]+)/', $this->revision, $rev);
5495 $this->outgoing_headers[] = "X-SOAP-Server: $this->title/$this->version (".$rev[1].")";
5496 // Let the Web server decide about this
5497 //$this->outgoing_headers[] = "Connection: Close\r\n";
5498 $payload = $this->getHTTPBody($payload);
5499 $type = $this->getHTTPContentType();
5500 $charset = $this->getHTTPContentTypeCharset();
5501 $this->outgoing_headers[] = "Content-Type: $type" . ($charset ? '; charset=' . $charset : '');
5502 //begin code to compress payload - by John
5503 // NOTE: there is no way to know whether the Web server will also compress
5505 if (strlen($payload) > 1024 && isset($this->headers) && isset($this->headers['accept-encoding'])) {
5506 if (strstr($this->headers['accept-encoding'], 'gzip')) {
5507 if (function_exists('gzencode')) {
5508 if (isset($this->debug_flag) && $this->debug_flag) {
5509 $payload .= "<!-- Content being gzipped -->";
5511 $this->outgoing_headers[] = "Content-Encoding: gzip";
5512 $payload = gzencode($payload);
5514 if (isset($this->debug_flag) && $this->debug_flag) {
5515 $payload .= "<!-- Content will not be gzipped: no gzencode -->";
5518 } elseif (strstr($this->headers['accept-encoding'], 'deflate')) {
5519 // Note: MSIE requires gzdeflate output (no Zlib header and checksum),
5520 // instead of gzcompress output,
5521 // which conflicts with HTTP 1.1 spec (http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.5)
5522 if (function_exists('gzdeflate')) {
5523 if (isset($this->debug_flag) && $this->debug_flag) {
5524 $payload .= "<!-- Content being deflated -->";
5526 $this->outgoing_headers[] = "Content-Encoding: deflate";
5527 $payload = gzdeflate($payload);
5529 if (isset($this->debug_flag) && $this->debug_flag) {
5530 $payload .= "<!-- Content will not be deflated: no gzcompress -->";
5538 $this->outgoing_headers[] = "Content-Length: ".strlen($payload);
5539 reset($this->outgoing_headers);
5540 foreach($this->outgoing_headers as $hdr){
5541 header($hdr, false);
5546 $this->response = join("\r\n",$this->outgoing_headers)."\r\n\r\n".$payload;
5550 * takes the value that was created by parsing the request
5551 * and compares to the method's signature, if available.
5553 * @param string $operation The operation to be invoked
5554 * @param array $request The array of parameter values
5555 * @return boolean Whether the operation was found
5558 function verify_method($operation,$request){
5559 if(isset($this->wsdl) && is_object($this->wsdl)){
5560 if($this->wsdl->getOperationData($operation)){
5563 } elseif(isset($this->operations[$operation])){
5570 * processes SOAP message received from client
5572 * @param array $headers The HTTP headers
5573 * @param string $data unprocessed request data from client
5574 * @return mixed value of the message, decoded into a PHP type
5577 function parseRequest($headers, $data) {
5578 $this->debug('Entering parseRequest() for data of length ' . strlen($data) . ' headers:');
5579 $this->appendDebug($this->varDump($headers));
5580 if (!isset($headers['content-type'])) {
5581 $this->setError('Request not of type text/xml (no content-type header)');
5584 if (!strstr($headers['content-type'], 'text/xml')) {
5585 $this->setError('Request not of type text/xml');
5588 if (strpos($headers['content-type'], '=')) {
5589 $enc = str_replace('"', '', substr(strstr($headers["content-type"], '='), 1));
5590 $this->debug('Got response encoding: ' . $enc);
5591 if(preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i',$enc)){
5592 $this->xml_encoding = strtoupper($enc);
5594 $this->xml_encoding = 'US-ASCII';
5597 // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
5598 $this->xml_encoding = 'ISO-8859-1';
5600 $this->debug('Use encoding: ' . $this->xml_encoding . ' when creating nusoap_parser');
5601 // parse response, get soap parser obj
5602 $parser = new nusoap_parser($data,$this->xml_encoding,'',$this->decode_utf8);
5604 $this->debug("parser debug: \n".$parser->getDebug());
5605 // if fault occurred during message parsing
5606 if($err = $parser->getError()){
5607 $this->result = 'fault: error in msg parsing: '.$err;
5608 $this->fault('SOAP-ENV:Client',"error in msg parsing:\n".$err);
5609 // else successfully parsed request into soapval object
5611 // get/set methodname
5612 $this->methodURI = $parser->root_struct_namespace;
5613 $this->methodname = $parser->root_struct_name;
5614 $this->debug('methodname: '.$this->methodname.' methodURI: '.$this->methodURI);
5615 $this->debug('calling parser->get_soapbody()');
5616 $this->methodparams = $parser->get_soapbody();
5618 $this->requestHeaders = $parser->getHeaders();
5620 $this->requestHeader = $parser->get_soapheader();
5621 // add document for doclit support
5622 $this->document = $parser->document;
5627 * gets the HTTP body for the current response.
5629 * @param string $soapmsg The SOAP payload
5630 * @return string The HTTP body, which includes the SOAP payload
5633 function getHTTPBody($soapmsg) {
5638 * gets the HTTP content type for the current response.
5640 * Note: getHTTPBody must be called before this.
5642 * @return string the HTTP content type for the current response.
5645 function getHTTPContentType() {
5650 * gets the HTTP content type charset for the current response.
5651 * returns false for non-text content types.
5653 * Note: getHTTPBody must be called before this.
5655 * @return string the HTTP content type charset for the current response.
5658 function getHTTPContentTypeCharset() {
5659 return $this->soap_defencoding;
5663 * add a method to the dispatch map (this has been replaced by the register method)
5665 * @param string $methodname
5666 * @param string $in array of input values
5667 * @param string $out array of output values
5671 function add_to_map($methodname,$in,$out){
5672 $this->operations[$methodname] = array('name' => $methodname,'in' => $in,'out' => $out);
5676 * register a service function with the server
5678 * @param string $name the name of the PHP function, class.method or class..method
5679 * @param array $in assoc array of input values: key = param name, value = param type
5680 * @param array $out assoc array of output values: key = param name, value = param type
5681 * @param mixed $namespace the element namespace for the method or false
5682 * @param mixed $soapaction the soapaction for the method or false
5683 * @param mixed $style optional (rpc|document) or false Note: when 'document' is specified, parameter and return wrappers are created for you automatically
5684 * @param mixed $use optional (encoded|literal) or false
5685 * @param string $documentation optional Description to include in WSDL
5686 * @param string $encodingStyle optional (usually 'http://schemas.xmlsoap.org/soap/encoding/' for encoded)
5689 function register($name,$in=array(),$out=array(),$namespace=false,$soapaction=false,$style=false,$use=false,$documentation='',$encodingStyle=''){
5690 global $HTTP_SERVER_VARS;
5692 if($this->externalWSDLURL){
5693 die('You cannot bind to an external WSDL file, and register methods outside of it! Please choose either WSDL or no WSDL.');
5696 die('You must specify a name when you register an operation');
5698 if (!is_array($in)) {
5699 die('You must provide an array for operation inputs');
5701 if (!is_array($out)) {
5702 die('You must provide an array for operation outputs');
5704 if(false == $namespace) {
5706 if(false == $soapaction) {
5707 if (isset($_SERVER)) {
5708 $SERVER_NAME = $_SERVER['SERVER_NAME'];
5709 $SCRIPT_NAME = isset($_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : $_SERVER['SCRIPT_NAME'];
5710 $HTTPS = isset($_SERVER['HTTPS']) ? $_SERVER['HTTPS'] : (isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off');
5711 } elseif (isset($HTTP_SERVER_VARS)) {
5712 $SERVER_NAME = $HTTP_SERVER_VARS['SERVER_NAME'];
5713 $SCRIPT_NAME = isset($HTTP_SERVER_VARS['PHP_SELF']) ? $HTTP_SERVER_VARS['PHP_SELF'] : $HTTP_SERVER_VARS['SCRIPT_NAME'];
5714 $HTTPS = isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off';
5716 $this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available");
5718 if ($HTTPS == '1' || $HTTPS == 'on') {
5723 $soapaction = "$SCHEME://$SERVER_NAME$SCRIPT_NAME/$name";
5725 if(false == $style) {
5731 if ($use == 'encoded' && $encodingStyle == '') {
5732 $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
5735 $this->operations[$name] = array(
5739 'namespace' => $namespace,
5740 'soapaction' => $soapaction,
5743 $this->wsdl->addOperation($name,$in,$out,$namespace,$soapaction,$style,$use,$documentation,$encodingStyle);
5749 * Specify a fault to be returned to the client.
5750 * This also acts as a flag to the server that a fault has occured.
5752 * @param string $faultcode
5753 * @param string $faultstring
5754 * @param string $faultactor
5755 * @param string $faultdetail
5758 function fault($faultcode,$faultstring,$faultactor='',$faultdetail=''){
5759 if ($faultdetail == '' && $this->debug_flag) {
5760 $faultdetail = $this->getDebug();
5762 $this->fault = new nusoap_fault($faultcode,$faultactor,$faultstring,$faultdetail);
5763 $this->fault->soap_defencoding = $this->soap_defencoding;
5767 * Sets up wsdl object.
5768 * Acts as a flag to enable internal WSDL generation
5770 * @param string $serviceName, name of the service
5771 * @param mixed $namespace optional 'tns' service namespace or false
5772 * @param mixed $endpoint optional URL of service endpoint or false
5773 * @param string $style optional (rpc|document) WSDL style (also specified by operation)
5774 * @param string $transport optional SOAP transport
5775 * @param mixed $schemaTargetNamespace optional 'types' targetNamespace for service schema or false
5777 function configureWSDL($serviceName,$namespace = false,$endpoint = false,$style='rpc', $transport = 'http://schemas.xmlsoap.org/soap/http', $schemaTargetNamespace = false)
5779 global $HTTP_SERVER_VARS;
5781 if (isset($_SERVER)) {
5782 $SERVER_NAME = $_SERVER['SERVER_NAME'];
5783 $SERVER_PORT = $_SERVER['SERVER_PORT'];
5784 $SCRIPT_NAME = isset($_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : $_SERVER['SCRIPT_NAME'];
5785 $HTTPS = isset($_SERVER['HTTPS']) ? $_SERVER['HTTPS'] : (isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off');
5786 } elseif (isset($HTTP_SERVER_VARS)) {
5787 $SERVER_NAME = $HTTP_SERVER_VARS['SERVER_NAME'];
5788 $SERVER_PORT = $HTTP_SERVER_VARS['SERVER_PORT'];
5789 $SCRIPT_NAME = isset($HTTP_SERVER_VARS['PHP_SELF']) ? $HTTP_SERVER_VARS['PHP_SELF'] : $HTTP_SERVER_VARS['SCRIPT_NAME'];
5790 $HTTPS = isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off';
5792 $this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available");
5794 // If server name has port number attached then strip it (else port number gets duplicated in WSDL output) (occurred using lighttpd and FastCGI)
5795 $colon = strpos($SERVER_NAME,":");
5797 $SERVER_NAME = substr($SERVER_NAME, 0, $colon);
5799 if ($SERVER_PORT == 80) {
5802 $SERVER_PORT = ':' . $SERVER_PORT;
5804 if(false == $namespace) {
5805 $namespace = "http://$SERVER_NAME/soap/$serviceName";
5808 if(false == $endpoint) {
5809 if ($HTTPS == '1' || $HTTPS == 'on') {
5814 $endpoint = "$SCHEME://$SERVER_NAME$SERVER_PORT$SCRIPT_NAME";
5817 if(false == $schemaTargetNamespace) {
5818 $schemaTargetNamespace = $namespace;
5821 $this->wsdl = new wsdl;
5822 $this->wsdl->serviceName = $serviceName;
5823 $this->wsdl->endpoint = $endpoint;
5824 $this->wsdl->namespaces['tns'] = $namespace;
5825 $this->wsdl->namespaces['soap'] = 'http://schemas.xmlsoap.org/wsdl/soap/';
5826 $this->wsdl->namespaces['wsdl'] = 'http://schemas.xmlsoap.org/wsdl/';
5827 if ($schemaTargetNamespace != $namespace) {
5828 $this->wsdl->namespaces['types'] = $schemaTargetNamespace;
5830 $this->wsdl->schemas[$schemaTargetNamespace][0] = new nusoap_xmlschema('', '', $this->wsdl->namespaces);
5831 if ($style == 'document') {
5832 $this->wsdl->schemas[$schemaTargetNamespace][0]->schemaInfo['elementFormDefault'] = 'qualified';
5834 $this->wsdl->schemas[$schemaTargetNamespace][0]->schemaTargetNamespace = $schemaTargetNamespace;
5835 $this->wsdl->schemas[$schemaTargetNamespace][0]->imports['http://schemas.xmlsoap.org/soap/encoding/'][0] = array('location' => '', 'loaded' => true);
5836 $this->wsdl->schemas[$schemaTargetNamespace][0]->imports['http://schemas.xmlsoap.org/wsdl/'][0] = array('location' => '', 'loaded' => true);
5837 $this->wsdl->bindings[$serviceName.'Binding'] = array(
5838 'name'=>$serviceName.'Binding',
5840 'transport'=>$transport,
5841 'portType'=>$serviceName.'PortType');
5842 $this->wsdl->ports[$serviceName.'Port'] = array(
5843 'binding'=>$serviceName.'Binding',
5844 'location'=>$endpoint,
5845 'bindingType'=>'http://schemas.xmlsoap.org/wsdl/soap/');
5850 * Backward compatibility
5852 class soap_server extends nusoap_server {
5859 Modification information for LGPL compliance
5861 r58622 - 2010-10-22 18:18:59 -0700 (Fri, 22 Oct 2010) - engsvnbuild - Author: lam <lam@198.18.142.201>
5864 r58361 - 2010-09-29 16:59:02 -0700 (Wed, 29 Sep 2010) - kjing - Author: Jenny Gonsalves <jenny@sugarcrm.com>
5865 Merging with maint_6_0_1 (svn merge -r 58250:58342)
5867 r57813 - 2010-08-19 10:34:44 -0700 (Thu, 19 Aug 2010) - kjing - Author: John Mertic <jmertic@sugarcrm.com>
5868 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.
5870 r57707 - 2010-08-10 12:26:13 -0700 (Tue, 10 Aug 2010) - kjing - Author: Stanislav Malyshev <smalyshev@gmail.com>
5871 fix SOAP calls with no parameters
5873 r56990 - 2010-06-16 13:05:36 -0700 (Wed, 16 Jun 2010) - kjing - snapshot "Mango" svn branch to a new one for GitHub sync
5875 r56989 - 2010-06-16 13:01:33 -0700 (Wed, 16 Jun 2010) - kjing - defunt "Mango" svn dev branch before github cutover
5877 r55980 - 2010-04-19 13:31:28 -0700 (Mon, 19 Apr 2010) - kjing - create Mango (6.1) based on windex
5879 r51719 - 2009-10-22 10:18:00 -0700 (Thu, 22 Oct 2009) - mitani - Converted to Build 3 tags and updated the build system
5881 r51634 - 2009-10-19 13:32:22 -0700 (Mon, 19 Oct 2009) - mitani - Windex is the branch for Sugar Sales 1.0 development
5883 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.
5885 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.
5887 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:
5888 - Changing all ereg function to either preg or simple string based ones
5889 - No more references to magic quotes.
5890 - Change all the session_unregister() functions to just unset() the correct session variable instead.
5892 r50375 - 2009-08-24 18:07:43 -0700 (Mon, 24 Aug 2009) - dwong - branch kobe2 from tokyo r50372
5894 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
5896 r45680 - 2009-03-30 14:34:35 -0700 (Mon, 30 Mar 2009) - Samir Gandhi - modifeid serializeSchema to generate WS-I compliant WSDL
5898 r42807 - 2008-12-29 11:16:59 -0800 (Mon, 29 Dec 2008) - dwong - Branch from trunk/sugarcrm r42806 to branches/tokyo/sugarcrm
5900 r42645 - 2008-12-18 13:41:08 -0800 (Thu, 18 Dec 2008) - awu - merging maint_5_2_0 rev41336:HEAD to trunk
5902 r41647 - 2008-11-11 17:44:30 -0800 (Tue, 11 Nov 2008) - majed - Fixes a few bugs
5904 r41596 - 2008-11-10 19:20:04 -0800 (Mon, 10 Nov 2008) - Samir Gandhi - modified to set $method in the code
5906 r41558 - 2008-11-10 14:35:34 -0800 (Mon, 10 Nov 2008) - majed - changes nusoap to allow for registering classes
5908 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.
5910 - data/SugarBean.php
5911 - include/domit/php_http_client_generic.php
5912 - include/domit/php_http_connector.php
5913 - include/domit/testing_domit.php
5914 - include/domit/xml_domit_getelementsbypath.php
5915 - include/domit/xml_domit_lite_parser.php
5916 - include/domit/xml_domit_nodemaps.php
5917 - include/domit/xml_domit_parser.php
5918 - include/domit/xml_domit_shared.php
5919 - include/generic/SugarWidgets/SugarWidgetField.php
5920 - include/generic/SugarWidgets/SugarWidgetReportField.php
5921 - include/ListView/ProcessView.php
5922 - include/nusoap/class.soapclient.php
5923 - include/nusoap/nusoap.php
5924 - include/nusoap/nusoapmime.php
5925 - include/Pear/HTML_Safe/Safe.php
5926 - include/Pear/XML_HTMLSax3/HTMLSax3.php
5927 - modules/Administration/RebuildWorkFlow.php
5928 - modules/Expressions/RelateSelector.php
5929 - modules/Reports/templates/templates_reports.php
5930 - modules/WorkFlow/Delete.php
5931 - modules/WorkFlow/Save.php
5932 - modules/WorkFlow/SaveSequence.php
5933 - modules/WorkFlow/WorkFlow.php
5934 - modules/WorkFlowActionShells/CreateStep1.php
5935 - modules/WorkFlowActionShells/CreateStep2.php
5936 - modules/WorkFlowActionShells/Save.php
5937 - modules/WorkFlowActionShells/WorkFlowActionShell.php
5938 - modules/WorkFlowAlerts/Save.php
5939 - modules/WorkFlowAlerts/WorkFlowAlert.php
5940 - modules/WorkFlowAlertShells/DetailView.php
5941 - modules/WorkFlowAlertShells/WorkFlowAlertShell.php
5942 - modules/WorkFlowTriggerShells/CreateStep1.php
5943 - modules/WorkFlowTriggerShells/CreateStepFilter.php
5944 - modules/WorkFlowTriggerShells/SaveFilter.php
5945 - modules/WorkFlowTriggerShells/WorkFlowTriggerShell.php
5946 - soap/SoapHelperFunctions.php
5947 - test/modules/DynamicFields/DynamicFields_Bug24095_test.php
5948 - test/simpletest/browser.php
5949 - test/simpletest/default_reporter.php
5950 - test/simpletest/detached.php
5951 - test/simpletest/eclipse.php
5952 - test/simpletest/expectation.php
5953 - test/simpletest/extensions/pear_test_case.php
5954 - test/simpletest/form.php
5955 - test/simpletest/http.php
5956 - test/simpletest/mock_objects.php
5957 - test/simpletest/page.php
5958 - test/simpletest/parser.php
5959 - test/simpletest/remote.php
5960 - test/simpletest/shell_tester.php
5961 - test/simpletest/simple_test.php
5962 - test/simpletest/simpletest.php
5963 - test/simpletest/test/acceptance_test.php
5964 - test/simpletest/test/adapter_test.php
5965 - test/simpletest/test/authentication_test.php
5966 - test/simpletest/test/browser_test.php
5967 - test/simpletest/test/collector_test.php
5968 - test/simpletest/test/compatibility_test.php
5969 - test/simpletest/test/detached_test.php
5970 - test/simpletest/test/eclipse_test.php
5971 - test/simpletest/test/encoding_test.php
5972 - test/simpletest/test/errors_test.php
5973 - test/simpletest/test/expectation_test.php
5974 - test/simpletest/test/form_test.php
5975 - test/simpletest/test/frames_test.php
5976 - test/simpletest/test/http_test.php
5977 - test/simpletest/test/live_test.php
5978 - test/simpletest/test/mock_objects_test.php
5979 - test/simpletest/test/page_test.php
5980 - test/simpletest/test/parse_error_test.php
5981 - test/simpletest/test/parser_test.php
5982 - test/simpletest/test/remote_test.php
5983 - test/simpletest/test/shell_test.php
5984 - test/simpletest/test/shell_tester_test.php
5985 - test/simpletest/test/simpletest_test.php
5986 - test/simpletest/test/site/page_request.php
5987 - test/simpletest/test/tag_test.php
5988 - test/simpletest/test/unit_tester_test.php
5989 - test/simpletest/test/user_agent_test.php
5990 - test/simpletest/test/visual_test.php
5991 - test/simpletest/test/xml_test.php
5992 - test/simpletest/test_case.php
5993 - test/simpletest/ui/array_reporter/test.php
5994 - test/simpletest/ui/recorder/test.php
5995 - test/simpletest/unit_tester.php
5996 - test/simpletest/url.php
5997 - test/simpletest/user_agent.php
5998 - test/simpletest/web_tester.php
5999 - test/spikephpcoverage/src/PEAR.php
6000 - test/spikephpcoverage/src/util/Utility.php
6001 - test/spikephpcoverage/src/XML/Parser.php
6002 - test/spikephpcoverage/src/XML/Parser/Simple.php
6003 - test/test_utilities/SugarTest_SimpleBrowser.php
6005 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.
6007 r38300 - 2008-07-25 13:33:43 -0700 (Fri, 25 Jul 2008) - Samir Gandhi - put the debug in parseresponse function
6009 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
6011 r36824 - 2008-06-18 09:26:11 -0700 (Wed, 18 Jun 2008) - roger - bug: 21832
6013 r26422 - 2007-09-05 17:29:12 -0700 (Wed, 05 Sep 2007) - majed - migrate from beta 1 to trunk
6015 r15787 - 2006-08-10 10:14:41 -0700 (Thu, 10 Aug 2006) - roger - RRS: bug 7961
6017 r14701 - 2006-07-17 13:37:26 -0700 (Mon, 17 Jul 2006) - roger - RRS: bug 5801
6019 r13782 - 2006-06-06 10:58:55 -0700 (Tue, 06 Jun 2006) - majed - changes entry point code
6021 r11466 - 2006-02-01 15:49:47 -0800 (Wed, 01 Feb 2006) - jacob - Adding extra !empty check to get around a PHP warning.
6023 r11115 - 2006-01-17 14:54:45 -0800 (Tue, 17 Jan 2006) - majed - add entry point validation
6025 r10585 - 2005-12-13 14:42:26 -0800 (Tue, 13 Dec 2005) - majed - adds new license mechanisim
6027 r10170 - 2005-12-05 18:37:46 -0800 (Mon, 05 Dec 2005) - majed - fixes various issues
6029 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.
6031 r8991 - 2005-11-03 19:07:25 -0800 (Thu, 03 Nov 2005) - majed - fixes nusoap issue
6033 r8846 - 2005-10-31 11:01:12 -0800 (Mon, 31 Oct 2005) - majed - new version of nusoap
6035 r7905 - 2005-09-21 19:12:57 -0700 (Wed, 21 Sep 2005) - majed - restores old nusoap pre & with a few fixes
6037 r7861 - 2005-09-20 15:40:25 -0700 (Tue, 20 Sep 2005) - majed - & fix for 3.5.1
6039 r7452 - 2005-08-17 11:32:34 -0700 (Wed, 17 Aug 2005) - majed - changes soap to nusoap
6041 r5820 - 2005-06-21 14:22:24 -0700 (Tue, 21 Jun 2005) - majed - fixes issues with nusoap and with custom fields
6043 r5462 - 2005-05-25 13:50:11 -0700 (Wed, 25 May 2005) - majed - upgraded nusoap to .6.9
6045 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
6047 r573 - 2004-09-04 13:03:32 -0700 (Sat, 04 Sep 2004) - sugarclint - undoing copyrights added in inadvertantly. --clint
6049 r546 - 2004-09-03 11:49:38 -0700 (Fri, 03 Sep 2004) - sugarmsi - removed echo count
6051 r354 - 2004-08-02 23:00:37 -0700 (Mon, 02 Aug 2004) - sugarjacob - Adding Soap
6061 * parses a WSDL file, allows access to it's data, other utility methods.
6062 * also builds WSDL structures programmatically.
6064 * @author Dietrich Ayala <dietrich@ganx4.com>
6065 * @author Scott Nichol <snichol@users.sourceforge.net>
6069 class wsdl extends nusoap_base {
6070 // URL or filename of the root of this WSDL
6072 // define internal arrays of bindings, ports, operations, messages, etc.
6073 var $schemas = array();
6075 var $message = array();
6076 var $complexTypes = array();
6077 var $messages = array();
6078 var $currentMessage;
6079 var $currentOperation;
6080 var $portTypes = array();
6081 var $currentPortType;
6082 var $bindings = array();
6083 var $currentBinding;
6084 var $ports = array();
6086 var $opData = array();
6088 var $documentation = false;
6090 // array of wsdl docs to import
6091 var $import = array();
6096 var $depth_array = array();
6098 var $proxyhost = '';
6099 var $proxyport = '';
6100 var $proxyusername = '';
6101 var $proxypassword = '';
6103 var $response_timeout = 30;
6104 var $curl_options = array(); // User-specified cURL options
6105 var $use_curl = false; // whether to always try to use cURL
6106 // for HTTP authentication
6107 var $username = ''; // Username for HTTP authentication
6108 var $password = ''; // Password for HTTP authentication
6109 var $authtype = ''; // Type of HTTP authentication
6110 var $certRequest = array(); // Certificate for HTTP SSL authentication
6115 * @param string $wsdl WSDL document URL
6116 * @param string $proxyhost
6117 * @param string $proxyport
6118 * @param string $proxyusername
6119 * @param string $proxypassword
6120 * @param integer $timeout set the connection timeout
6121 * @param integer $response_timeout set the response timeout
6122 * @param array $curl_options user-specified cURL options
6123 * @param boolean $use_curl try to use cURL
6126 function wsdl($wsdl = '',$proxyhost=false,$proxyport=false,$proxyusername=false,$proxypassword=false,$timeout=0,$response_timeout=30,$curl_options=null,$use_curl=false){
6127 parent::nusoap_base();
6128 $this->debug("ctor wsdl=$wsdl timeout=$timeout response_timeout=$response_timeout");
6129 $this->proxyhost = $proxyhost;
6130 $this->proxyport = $proxyport;
6131 $this->proxyusername = $proxyusername;
6132 $this->proxypassword = $proxypassword;
6133 $this->timeout = $timeout;
6134 $this->response_timeout = $response_timeout;
6135 if (is_array($curl_options))
6136 $this->curl_options = $curl_options;
6137 $this->use_curl = $use_curl;
6138 $this->fetchWSDL($wsdl);
6142 * fetches the WSDL document and parses it
6146 function fetchWSDL($wsdl) {
6147 $this->debug("parse and process WSDL path=$wsdl");
6148 $this->wsdl = $wsdl;
6150 if ($this->wsdl != "") {
6151 $this->parseWSDL($this->wsdl);
6154 // TODO: handle imports more properly, grabbing them in-line and nesting them
6155 $imported_urls = array();
6157 while ($imported > 0) {
6160 foreach ($this->schemas as $ns => $list) {
6161 foreach ($list as $xs) {
6162 $wsdlparts = parse_url($this->wsdl); // this is bogusly simple!
6163 foreach ($xs->imports as $ns2 => $list2) {
6164 for ($ii = 0; $ii < count($list2); $ii++) {
6165 if (! $list2[$ii]['loaded']) {
6166 $this->schemas[$ns]->imports[$ns2][$ii]['loaded'] = true;
6167 $url = $list2[$ii]['location'];
6169 $urlparts = parse_url($url);
6170 if (!isset($urlparts['host'])) {
6171 $url = $wsdlparts['scheme'] . '://' . $wsdlparts['host'] . (isset($wsdlparts['port']) ? ':' .$wsdlparts['port'] : '') .
6172 substr($wsdlparts['path'],0,strrpos($wsdlparts['path'],'/') + 1) .$urlparts['path'];
6174 if (! in_array($url, $imported_urls)) {
6175 $this->parseWSDL($url);
6177 $imported_urls[] = $url;
6180 $this->debug("Unexpected scenario: empty URL for unloaded import");
6188 $wsdlparts = parse_url($this->wsdl); // this is bogusly simple!
6189 foreach ($this->import as $ns => $list) {
6190 for ($ii = 0; $ii < count($list); $ii++) {
6191 if (! $list[$ii]['loaded']) {
6192 $this->import[$ns][$ii]['loaded'] = true;
6193 $url = $list[$ii]['location'];
6195 $urlparts = parse_url($url);
6196 if (!isset($urlparts['host'])) {
6197 $url = $wsdlparts['scheme'] . '://' . $wsdlparts['host'] . (isset($wsdlparts['port']) ? ':' . $wsdlparts['port'] : '') .
6198 substr($wsdlparts['path'],0,strrpos($wsdlparts['path'],'/') + 1) .$urlparts['path'];
6200 if (! in_array($url, $imported_urls)) {
6201 $this->parseWSDL($url);
6203 $imported_urls[] = $url;
6206 $this->debug("Unexpected scenario: empty URL for unloaded import");
6212 // add new data to operation data
6213 foreach($this->bindings as $binding => $bindingData) {
6214 if (isset($bindingData['operations']) && is_array($bindingData['operations'])) {
6215 foreach($bindingData['operations'] as $operation => $data) {
6216 $this->debug('post-parse data gathering for ' . $operation);
6217 $this->bindings[$binding]['operations'][$operation]['input'] =
6218 isset($this->bindings[$binding]['operations'][$operation]['input']) ?
6219 array_merge($this->bindings[$binding]['operations'][$operation]['input'], $this->portTypes[ $bindingData['portType'] ][$operation]['input']) :
6220 $this->portTypes[ $bindingData['portType'] ][$operation]['input'];
6221 $this->bindings[$binding]['operations'][$operation]['output'] =
6222 isset($this->bindings[$binding]['operations'][$operation]['output']) ?
6223 array_merge($this->bindings[$binding]['operations'][$operation]['output'], $this->portTypes[ $bindingData['portType'] ][$operation]['output']) :
6224 $this->portTypes[ $bindingData['portType'] ][$operation]['output'];
6225 if(isset($this->messages[ $this->bindings[$binding]['operations'][$operation]['input']['message'] ])){
6226 $this->bindings[$binding]['operations'][$operation]['input']['parts'] = $this->messages[ $this->bindings[$binding]['operations'][$operation]['input']['message'] ];
6228 if(isset($this->messages[ $this->bindings[$binding]['operations'][$operation]['output']['message'] ])){
6229 $this->bindings[$binding]['operations'][$operation]['output']['parts'] = $this->messages[ $this->bindings[$binding]['operations'][$operation]['output']['message'] ];
6231 // Set operation style if necessary, but do not override one already provided
6232 if (isset($bindingData['style']) && !isset($this->bindings[$binding]['operations'][$operation]['style'])) {
6233 $this->bindings[$binding]['operations'][$operation]['style'] = $bindingData['style'];
6235 $this->bindings[$binding]['operations'][$operation]['transport'] = isset($bindingData['transport']) ? $bindingData['transport'] : '';
6236 $this->bindings[$binding]['operations'][$operation]['documentation'] = isset($this->portTypes[ $bindingData['portType'] ][$operation]['documentation']) ? $this->portTypes[ $bindingData['portType'] ][$operation]['documentation'] : '';
6237 $this->bindings[$binding]['operations'][$operation]['endpoint'] = isset($bindingData['endpoint']) ? $bindingData['endpoint'] : '';
6244 * parses the wsdl document
6246 * @param string $wsdl path or URL
6249 function parseWSDL($wsdl = '') {
6250 $this->debug("parse WSDL at path=$wsdl");
6253 $this->debug('no wsdl passed to parseWSDL()!!');
6254 $this->setError('no wsdl passed to parseWSDL()!!');
6258 // parse $wsdl for url format
6259 $wsdl_props = parse_url($wsdl);
6261 if (isset($wsdl_props['scheme']) && ($wsdl_props['scheme'] == 'http' || $wsdl_props['scheme'] == 'https')) {
6262 $this->debug('getting WSDL http(s) URL ' . $wsdl);
6264 $tr = new soap_transport_http($wsdl, $this->curl_options, $this->use_curl);
6265 $tr->request_method = 'GET';
6266 $tr->useSOAPAction = false;
6267 if($this->proxyhost && $this->proxyport){
6268 $tr->setProxy($this->proxyhost,$this->proxyport,$this->proxyusername,$this->proxypassword);
6270 if ($this->authtype != '') {
6271 $tr->setCredentials($this->username, $this->password, $this->authtype, array(), $this->certRequest);
6273 $tr->setEncoding('gzip, deflate');
6274 $wsdl_string = $tr->send('', $this->timeout, $this->response_timeout);
6275 //$this->debug("WSDL request\n" . $tr->outgoing_payload);
6276 //$this->debug("WSDL response\n" . $tr->incoming_payload);
6277 $this->appendDebug($tr->getDebug());
6279 if($err = $tr->getError() ){
6280 $errstr = 'Getting ' . $wsdl . ' - HTTP ERROR: '.$err;
6281 $this->debug($errstr);
6282 $this->setError($errstr);
6287 $this->debug("got WSDL URL");
6289 // $wsdl is not http(s), so treat it as a file URL or plain file path
6290 if (isset($wsdl_props['scheme']) && ($wsdl_props['scheme'] == 'file') && isset($wsdl_props['path'])) {
6291 $path = isset($wsdl_props['host']) ? ($wsdl_props['host'] . ':' . $wsdl_props['path']) : $wsdl_props['path'];
6295 $this->debug('getting WSDL file ' . $path);
6296 if ($fp = @fopen($path, 'r')) {
6298 while ($data = fread($fp, 32768)) {
6299 $wsdl_string .= $data;
6303 $errstr = "Bad path to WSDL file $path";
6304 $this->debug($errstr);
6305 $this->setError($errstr);
6309 $this->debug('Parse WSDL');
6310 // end new code added
6311 // Create an XML parser.
6312 $this->parser = xml_parser_create();
6313 // Set the options for parsing the XML data.
6314 // xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
6315 xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
6316 // Set the object for the parser.
6317 xml_set_object($this->parser, $this);
6318 // Set the element handlers for the parser.
6319 xml_set_element_handler($this->parser, 'start_element', 'end_element');
6320 xml_set_character_data_handler($this->parser, 'character_data');
6321 // Parse the XML file.
6322 if (!xml_parse($this->parser, $wsdl_string, true)) {
6323 // Display an error message.
6325 'XML error parsing WSDL from %s on line %d: %s',
6327 xml_get_current_line_number($this->parser),
6328 xml_error_string(xml_get_error_code($this->parser))
6330 $this->debug($errstr);
6331 $this->debug("XML payload:\n" . $wsdl_string);
6332 $this->setError($errstr);
6336 xml_parser_free($this->parser);
6337 $this->debug('Parsing WSDL done');
6338 // catch wsdl parse errors
6339 if($this->getError()){
6346 * start-element handler
6348 * @param string $parser XML parser object
6349 * @param string $name element name
6350 * @param string $attrs associative array of attributes
6353 function start_element($parser, $name, $attrs)
6355 if ($this->status == 'schema') {
6356 $this->currentSchema->schemaStartElement($parser, $name, $attrs);
6357 $this->appendDebug($this->currentSchema->getDebug());
6358 $this->currentSchema->clearDebug();
6359 } elseif (preg_match('/schema$/', $name)) {
6360 $this->debug('Parsing WSDL schema');
6361 // $this->debug("startElement for $name ($attrs[name]). status = $this->status (".$this->getLocalPart($name).")");
6362 $this->status = 'schema';
6363 $this->currentSchema = new nusoap_xmlschema('', '', $this->namespaces);
6364 $this->currentSchema->schemaStartElement($parser, $name, $attrs);
6365 $this->appendDebug($this->currentSchema->getDebug());
6366 $this->currentSchema->clearDebug();
6368 // position in the total number of elements, starting from 0
6369 $pos = $this->position++;
6370 $depth = $this->depth++;
6371 // set self as current value for this depth
6372 $this->depth_array[$depth] = $pos;
6373 $this->message[$pos] = array('cdata' => '');
6374 // process attributes
6375 if (count($attrs) > 0) {
6376 // register namespace declarations
6377 foreach($attrs as $k => $v) {
6378 if (preg_match('/^xmlns/',$k)) {
6379 if ($ns_prefix = substr(strrchr($k, ':'), 1)) {
6380 $this->namespaces[$ns_prefix] = $v;
6382 $this->namespaces['ns' . (count($this->namespaces) + 1)] = $v;
6384 if ($v == 'http://www.w3.org/2001/XMLSchema' || $v == 'http://www.w3.org/1999/XMLSchema' || $v == 'http://www.w3.org/2000/10/XMLSchema') {
6385 $this->XMLSchemaVersion = $v;
6386 $this->namespaces['xsi'] = $v . '-instance';
6390 // expand each attribute prefix to its namespace
6391 foreach($attrs as $k => $v) {
6392 $k = strpos($k, ':') ? $this->expandQname($k) : $k;
6393 if ($k != 'location' && $k != 'soapAction' && $k != 'namespace') {
6394 $v = strpos($v, ':') ? $this->expandQname($v) : $v;
6402 // get element prefix, namespace and name
6403 if (preg_match('/:/', $name)) {
6405 $prefix = substr($name, 0, strpos($name, ':'));
6407 $namespace = isset($this->namespaces[$prefix]) ? $this->namespaces[$prefix] : '';
6408 // get unqualified name
6409 $name = substr(strstr($name, ':'), 1);
6411 // process attributes, expanding any prefixes to namespaces
6412 // find status, register data
6413 switch ($this->status) {
6415 if ($name == 'part') {
6416 if (isset($attrs['type'])) {
6417 $this->debug("msg " . $this->currentMessage . ": found part (with type) $attrs[name]: " . implode(',', $attrs));
6418 $this->messages[$this->currentMessage][$attrs['name']] = $attrs['type'];
6420 if (isset($attrs['element'])) {
6421 $this->debug("msg " . $this->currentMessage . ": found part (with element) $attrs[name]: " . implode(',', $attrs));
6422 $this->messages[$this->currentMessage][$attrs['name']] = $attrs['element'] . '^';
6429 $this->currentPortOperation = $attrs['name'];
6430 $this->debug("portType $this->currentPortType operation: $this->currentPortOperation");
6431 if (isset($attrs['parameterOrder'])) {
6432 $this->portTypes[$this->currentPortType][$attrs['name']]['parameterOrder'] = $attrs['parameterOrder'];
6435 case 'documentation':
6436 $this->documentation = true;
6438 // merge input/output data
6440 $m = isset($attrs['message']) ? $this->getLocalPart($attrs['message']) : '';
6441 $this->portTypes[$this->currentPortType][$this->currentPortOperation][$name]['message'] = $m;
6449 if (isset($attrs['style'])) {
6450 $this->bindings[$this->currentBinding]['prefix'] = $prefix;
6452 $this->bindings[$this->currentBinding] = array_merge($this->bindings[$this->currentBinding], $attrs);
6455 $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus]['headers'][] = $attrs;
6458 if (isset($attrs['soapAction'])) {
6459 $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['soapAction'] = $attrs['soapAction'];
6461 if (isset($attrs['style'])) {
6462 $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['style'] = $attrs['style'];
6464 if (isset($attrs['name'])) {
6465 $this->currentOperation = $attrs['name'];
6466 $this->debug("current binding operation: $this->currentOperation");
6467 $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['name'] = $attrs['name'];
6468 $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['binding'] = $this->currentBinding;
6469 $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['endpoint'] = isset($this->bindings[$this->currentBinding]['endpoint']) ? $this->bindings[$this->currentBinding]['endpoint'] : '';
6473 $this->opStatus = 'input';
6476 $this->opStatus = 'output';
6479 if (isset($this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus])) {
6480 $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus] = array_merge($this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus], $attrs);
6482 $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus] = $attrs;
6490 $this->currentPort = $attrs['name'];
6491 $this->debug('current port: ' . $this->currentPort);
6492 $this->ports[$this->currentPort]['binding'] = $this->getLocalPart($attrs['binding']);
6496 $this->ports[$this->currentPort]['location'] = $attrs['location'];
6497 $this->ports[$this->currentPort]['bindingType'] = $namespace;
6498 $this->bindings[ $this->ports[$this->currentPort]['binding'] ]['bindingType'] = $namespace;
6499 $this->bindings[ $this->ports[$this->currentPort]['binding'] ]['endpoint'] = $attrs['location'];
6507 if (isset($attrs['location'])) {
6508 $this->import[$attrs['namespace']][] = array('location' => $attrs['location'], 'loaded' => false);
6509 $this->debug('parsing import ' . $attrs['namespace']. ' - ' . $attrs['location'] . ' (' . count($this->import[$attrs['namespace']]).')');
6511 $this->import[$attrs['namespace']][] = array('location' => '', 'loaded' => true);
6512 if (! $this->getPrefixFromNamespace($attrs['namespace'])) {
6513 $this->namespaces['ns'.(count($this->namespaces)+1)] = $attrs['namespace'];
6515 $this->debug('parsing import ' . $attrs['namespace']. ' - [no location] (' . count($this->import[$attrs['namespace']]).')');
6520 // $this->status = 'schema';
6523 $this->status = 'message';
6524 $this->messages[$attrs['name']] = array();
6525 $this->currentMessage = $attrs['name'];
6528 $this->status = 'portType';
6529 $this->portTypes[$attrs['name']] = array();
6530 $this->currentPortType = $attrs['name'];
6533 if (isset($attrs['name'])) {
6535 if (strpos($attrs['name'], ':')) {
6536 $this->currentBinding = $this->getLocalPart($attrs['name']);
6538 $this->currentBinding = $attrs['name'];
6540 $this->status = 'binding';
6541 $this->bindings[$this->currentBinding]['portType'] = $this->getLocalPart($attrs['type']);
6542 $this->debug("current binding: $this->currentBinding of portType: " . $attrs['type']);
6546 $this->serviceName = $attrs['name'];
6547 $this->status = 'service';
6548 $this->debug('current service: ' . $this->serviceName);
6551 foreach ($attrs as $name => $value) {
6552 $this->wsdl_info[$name] = $value;
6560 * end-element handler
6562 * @param string $parser XML parser object
6563 * @param string $name element name
6566 function end_element($parser, $name){
6567 // unset schema status
6568 if (/*preg_match('/types$/', $name) ||*/ preg_match('/schema$/', $name)) {
6570 $this->appendDebug($this->currentSchema->getDebug());
6571 $this->currentSchema->clearDebug();
6572 $this->schemas[$this->currentSchema->schemaTargetNamespace][] = $this->currentSchema;
6573 $this->debug('Parsing WSDL schema done');
6575 if ($this->status == 'schema') {
6576 $this->currentSchema->schemaEndElement($parser, $name);
6578 // bring depth down a notch
6581 // end documentation
6582 if ($this->documentation) {
6583 //TODO: track the node to which documentation should be assigned; it can be a part, message, etc.
6584 //$this->portTypes[$this->currentPortType][$this->currentPortOperation]['documentation'] = $this->documentation;
6585 $this->documentation = false;
6590 * element content handler
6592 * @param string $parser XML parser object
6593 * @param string $data element content
6596 function character_data($parser, $data)
6598 $pos = isset($this->depth_array[$this->depth]) ? $this->depth_array[$this->depth] : 0;
6599 if (isset($this->message[$pos]['cdata'])) {
6600 $this->message[$pos]['cdata'] .= $data;
6602 if ($this->documentation) {
6603 $this->documentation .= $data;
6608 * if authenticating, set user credentials here
6610 * @param string $username
6611 * @param string $password
6612 * @param string $authtype (basic|digest|certificate|ntlm)
6613 * @param array $certRequest (keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, certpassword (optional), verifypeer (optional), verifyhost (optional): see corresponding options in cURL docs)
6616 function setCredentials($username, $password, $authtype = 'basic', $certRequest = array()) {
6617 $this->debug("setCredentials username=$username authtype=$authtype certRequest=");
6618 $this->appendDebug($this->varDump($certRequest));
6619 $this->username = $username;
6620 $this->password = $password;
6621 $this->authtype = $authtype;
6622 $this->certRequest = $certRequest;
6625 function getBindingData($binding)
6627 if (is_array($this->bindings[$binding])) {
6628 return $this->bindings[$binding];
6633 * returns an assoc array of operation names => operation data
6635 * @param string $portName WSDL port name
6636 * @param string $bindingType eg: soap, smtp, dime (only soap and soap12 are currently supported)
6640 function getOperations($portName = '', $bindingType = 'soap') {
6642 if ($bindingType == 'soap') {
6643 $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/';
6644 } elseif ($bindingType == 'soap12') {
6645 $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/';
6647 $this->debug("getOperations bindingType $bindingType may not be supported");
6649 $this->debug("getOperations for port '$portName' bindingType $bindingType");
6651 foreach($this->ports as $port => $portData) {
6652 $this->debug("getOperations checking port $port bindingType " . $portData['bindingType']);
6653 if ($portName == '' || $port == $portName) {
6654 // binding type of port matches parameter
6655 if ($portData['bindingType'] == $bindingType) {
6656 $this->debug("getOperations found port $port bindingType $bindingType");
6657 //$this->debug("port data: " . $this->varDump($portData));
6658 //$this->debug("bindings: " . $this->varDump($this->bindings[ $portData['binding'] ]));
6660 if (isset($this->bindings[ $portData['binding'] ]['operations'])) {
6661 $ops = array_merge ($ops, $this->bindings[ $portData['binding'] ]['operations']);
6666 if (count($ops) == 0) {
6667 $this->debug("getOperations found no operations for port '$portName' bindingType $bindingType");
6673 * returns an associative array of data necessary for calling an operation
6675 * @param string $operation name of operation
6676 * @param string $bindingType type of binding eg: soap, soap12
6680 function getOperationData($operation, $bindingType = 'soap')
6682 if ($bindingType == 'soap') {
6683 $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/';
6684 } elseif ($bindingType == 'soap12') {
6685 $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/';
6688 foreach($this->ports as $port => $portData) {
6689 // binding type of port matches parameter
6690 if ($portData['bindingType'] == $bindingType) {
6692 //foreach($this->bindings[ $portData['binding'] ]['operations'] as $bOperation => $opData) {
6693 foreach(array_keys($this->bindings[ $portData['binding'] ]['operations']) as $bOperation) {
6694 // note that we could/should also check the namespace here
6695 if ($operation == $bOperation) {
6696 $opData = $this->bindings[ $portData['binding'] ]['operations'][$operation];
6705 * returns an associative array of data necessary for calling an operation
6707 * @param string $soapAction soapAction for operation
6708 * @param string $bindingType type of binding eg: soap, soap12
6712 function getOperationDataForSoapAction($soapAction, $bindingType = 'soap') {
6713 if ($bindingType == 'soap') {
6714 $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/';
6715 } elseif ($bindingType == 'soap12') {
6716 $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/';
6719 foreach($this->ports as $port => $portData) {
6720 // binding type of port matches parameter
6721 if ($portData['bindingType'] == $bindingType) {
6722 // loop through operations for the binding
6723 foreach ($this->bindings[ $portData['binding'] ]['operations'] as $bOperation => $opData) {
6724 if ($opData['soapAction'] == $soapAction) {
6733 * returns an array of information about a given type
6734 * returns false if no type exists by the given name
6737 * 'elements' => array(), // refs to elements array
6738 * 'restrictionBase' => '',
6740 * 'order' => '(sequence|all)',
6741 * 'attrs' => array() // refs to attributes array
6744 * @param string $type the type
6745 * @param string $ns namespace (not prefix) of the type
6748 * @see nusoap_xmlschema
6750 function getTypeDef($type, $ns) {
6751 $this->debug("in getTypeDef: type=$type, ns=$ns");
6752 if ((! $ns) && isset($this->namespaces['tns'])) {
6753 $ns = $this->namespaces['tns'];
6754 $this->debug("in getTypeDef: type namespace forced to $ns");
6756 if (!isset($this->schemas[$ns])) {
6757 foreach ($this->schemas as $ns0 => $schema0) {
6758 if (strcasecmp($ns, $ns0) == 0) {
6759 $this->debug("in getTypeDef: replacing schema namespace $ns with $ns0");
6765 if (isset($this->schemas[$ns])) {
6766 $this->debug("in getTypeDef: have schema for namespace $ns");
6767 for ($i = 0; $i < count($this->schemas[$ns]); $i++) {
6768 $xs = &$this->schemas[$ns][$i];
6769 $t = $xs->getTypeDef($type);
6770 $this->appendDebug($xs->getDebug());
6773 $this->debug("in getTypeDef: found type $type");
6774 if (!isset($t['phpType'])) {
6775 // get info for type to tack onto the element
6776 $uqType = substr($t['type'], strrpos($t['type'], ':') + 1);
6777 $ns = substr($t['type'], 0, strrpos($t['type'], ':'));
6778 $etype = $this->getTypeDef($uqType, $ns);
6780 $this->debug("found type for [element] $type:");
6781 $this->debug($this->varDump($etype));
6782 if (isset($etype['phpType'])) {
6783 $t['phpType'] = $etype['phpType'];
6785 if (isset($etype['elements'])) {
6786 $t['elements'] = $etype['elements'];
6788 if (isset($etype['attrs'])) {
6789 $t['attrs'] = $etype['attrs'];
6792 $this->debug("did not find type for [element] $type");
6798 $this->debug("in getTypeDef: did not find type $type");
6800 $this->debug("in getTypeDef: do not have schema for namespace $ns");
6806 * prints html description of services
6810 function webDescription(){
6811 global $HTTP_SERVER_VARS;
6813 if (isset($_SERVER)) {
6814 $PHP_SELF = $_SERVER['PHP_SELF'];
6815 } elseif (isset($HTTP_SERVER_VARS)) {
6816 $PHP_SELF = $HTTP_SERVER_VARS['PHP_SELF'];
6818 $this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available");
6822 <html><head><title>NuSOAP: '.$this->serviceName.'</title>
6823 <style type="text/css">
6824 body { font-family: arial; color: #000000; background-color: #ffffff; margin: 0px 0px 0px 0px; }
6825 p { font-family: arial; color: #000000; margin-top: 0px; margin-bottom: 12px; }
6826 pre { background-color: silver; padding: 5px; font-family: Courier New; font-size: x-small; color: #000000;}
6827 ul { margin-top: 10px; margin-left: 20px; }
6828 li { list-style-type: none; margin-top: 10px; color: #000000; }
6830 margin-left: 0px; padding-bottom: 2em; }
6832 padding-top: 10px; padding-bottom: 10px; padding-left: 15px; font-size: .70em;
6833 margin-top: 10px; margin-left: 0px; color: #000000;
6834 background-color: #ccccff; width: 20%; margin-left: 20px; margin-top: 20px; }
6836 font-family: arial; font-size: 26px; color: #ffffff;
6837 background-color: #999999; width: 100%;
6838 margin-left: 0px; margin-right: 0px;
6839 padding-top: 10px; padding-bottom: 10px;}
6841 position: absolute; visibility: hidden; z-index: 200; left: 250px; top: 100px;
6842 font-family: arial; overflow: hidden; width: 600;
6843 padding: 20px; font-size: 10px; background-color: #999999;
6844 layer-background-color:#FFFFFF; }
6845 a,a:active { color: charcoal; font-weight: bold; }
6846 a:visited { color: #666666; font-weight: bold; }
6847 a:hover { color: cc3300; font-weight: bold; }
6849 <script language="JavaScript" type="text/javascript">
6851 // POP-UP CAPTIONS...
6852 function lib_bwcheck(){ //Browsercheck (needed)
6853 this.ver=navigator.appVersion
6854 this.agent=navigator.userAgent
6855 this.dom=document.getElementById?1:0
6856 this.opera5=this.agent.indexOf("Opera 5")>-1
6857 this.ie5=(this.ver.indexOf("MSIE 5")>-1 && this.dom && !this.opera5)?1:0;
6858 this.ie6=(this.ver.indexOf("MSIE 6")>-1 && this.dom && !this.opera5)?1:0;
6859 this.ie4=(document.all && !this.dom && !this.opera5)?1:0;
6860 this.ie=this.ie4||this.ie5||this.ie6
6861 this.mac=this.agent.indexOf("Mac")>-1
6862 this.ns6=(this.dom && parseInt(this.ver) >= 5) ?1:0;
6863 this.ns4=(document.layers && !this.dom)?1:0;
6864 this.bw=(this.ie6 || this.ie5 || this.ie4 || this.ns4 || this.ns6 || this.opera5)
6867 var bw = new lib_bwcheck()
6868 //Makes crossbrowser object.
6869 function makeObj(obj){
6870 this.evnt=bw.dom? document.getElementById(obj):bw.ie4?document.all[obj]:bw.ns4?document.layers[obj]:0;
6871 if(!this.evnt) return false
6872 this.css=bw.dom||bw.ie4?this.evnt.style:bw.ns4?this.evnt:0;
6873 this.wref=bw.dom||bw.ie4?this.evnt:bw.ns4?this.css.document:0;
6874 this.writeIt=b_writeIt;
6877 // A unit of measure that will be added when setting the position of a layer.
6878 //var px = bw.ns4||window.opera?"":"px";
6879 function b_writeIt(text){
6880 if (bw.ns4){this.wref.write(text);this.wref.close()}
6881 else this.wref.innerHTML = text
6883 //Shows the messages
6885 function popup(divid){
6886 if(oDesc = new makeObj(divid)){
6887 oDesc.css.visibility = "visible"
6890 function popout(){ // Hides message
6891 if(oDesc) oDesc.css.visibility = "hidden"
6899 <div class=title>'.$this->serviceName.'</div>
6901 <p>View the <a href="'.$PHP_SELF.'?wsdl">WSDL</a> for the service.
6902 Click on an operation name to view it's details.</p>
6904 foreach($this->getOperations() as $op => $data){
6905 $b .= "<li><a href='#' onclick=\"popout();popup('$op')\">$op</a></li>";
6906 // create hidden div
6907 $b .= "<div id='$op' class='hidden'>
6908 <a href='#' onclick='popout()'><font color='#ffffff'>Close</font></a><br><br>";
6909 foreach($data as $donnie => $marie){ // loop through opdata
6910 if($donnie == 'input' || $donnie == 'output'){ // show input/output data
6911 $b .= "<font color='white'>".ucfirst($donnie).':</font><br>';
6912 foreach($marie as $captain => $tenille){ // loop through data
6913 if($captain == 'parts'){ // loop thru parts
6914 $b .= " $captain:<br>";
6915 //if(is_array($tenille)){
6916 foreach($tenille as $joanie => $chachi){
6917 $b .= " $joanie: $chachi<br>";
6921 $b .= " $captain: $tenille<br>";
6925 $b .= "<font color='white'>".ucfirst($donnie).":</font> $marie<br>";
6933 </div></body></html>';
6938 * serialize the parsed wsdl
6940 * @param mixed $debug whether to put debug=1 in endpoint URL
6941 * @return string serialization of WSDL
6944 function serialize($debug = 0)
6946 $xml = '<?xml version="1.0" encoding="ISO-8859-1"?>';
6947 $xml .= "\n<definitions";
6948 foreach($this->namespaces as $k => $v) {
6949 $xml .= " xmlns:$k=\"$v\"";
6951 // 10.9.02 - add poulter fix for wsdl and tns declarations
6952 if (isset($this->namespaces['wsdl'])) {
6953 $xml .= " xmlns=\"" . $this->namespaces['wsdl'] . "\"";
6955 if (isset($this->namespaces['tns'])) {
6956 $xml .= " targetNamespace=\"" . $this->namespaces['tns'] . "\"";
6960 if (sizeof($this->import) > 0) {
6961 foreach($this->import as $ns => $list) {
6962 foreach ($list as $ii) {
6963 if ($ii['location'] != '') {
6964 $xml .= '<import location="' . $ii['location'] . '" namespace="' . $ns . '" />';
6966 $xml .= '<import namespace="' . $ns . '" />';
6972 if (count($this->schemas)>=1) {
6973 $xml .= "\n<types>\n";
6974 foreach ($this->schemas as $ns => $list) {
6975 foreach ($list as $xs) {
6976 $xml .= $xs->serializeSchema();
6982 if (count($this->messages) >= 1) {
6983 foreach($this->messages as $msgName => $msgParts) {
6984 $xml .= "\n<message name=\"" . $msgName . '">';
6985 if(is_array($msgParts)){
6986 foreach($msgParts as $partName => $partType) {
6987 // print 'serializing '.$partType.', sv: '.$this->XMLSchemaVersion.'<br>';
6988 if (strpos($partType, ':')) {
6989 $typePrefix = $this->getPrefixFromNamespace($this->getPrefix($partType));
6990 } elseif (isset($this->typemap[$this->namespaces['xsd']][$partType])) {
6991 // print 'checking typemap: '.$this->XMLSchemaVersion.'<br>';
6992 $typePrefix = 'xsd';
6994 foreach($this->typemap as $ns => $types) {
6995 if (isset($types[$partType])) {
6996 $typePrefix = $this->getPrefixFromNamespace($ns);
6999 if (!isset($typePrefix)) {
7000 die("$partType has no namespace!");
7003 $ns = $this->getNamespaceFromPrefix($typePrefix);
7004 $localPart = $this->getLocalPart($partType);
7005 $typeDef = $this->getTypeDef($localPart, $ns);
7006 if ($typeDef['typeClass'] == 'element') {
7007 $elementortype = 'element';
7008 if (substr($localPart, -1) == '^') {
7009 $localPart = substr($localPart, 0, -1);
7012 $elementortype = 'type';
7014 $xml .= "\n" . ' <part name="' . $partName . '" ' . $elementortype . '="' . $typePrefix . ':' . $localPart . '" />';
7017 $xml .= '</message>';
7020 // bindings & porttypes
7021 if (count($this->bindings) >= 1) {
7024 foreach($this->bindings as $bindingName => $attrs) {
7025 $binding_xml .= "\n<binding name=\"" . $bindingName . '" type="tns:' . $attrs['portType'] . '">';
7026 $binding_xml .= "\n" . ' <soap:binding style="' . $attrs['style'] . '" transport="' . $attrs['transport'] . '"/>';
7027 $portType_xml .= "\n<portType name=\"" . $attrs['portType'] . '">';
7028 foreach($attrs['operations'] as $opName => $opParts) {
7029 $binding_xml .= "\n" . ' <operation name="' . $opName . '">';
7030 $binding_xml .= "\n" . ' <soap:operation soapAction="' . $opParts['soapAction'] . '" style="'. $opParts['style'] . '"/>';
7031 if (isset($opParts['input']['encodingStyle']) && $opParts['input']['encodingStyle'] != '') {
7032 $enc_style = ' encodingStyle="' . $opParts['input']['encodingStyle'] . '"';
7036 $binding_xml .= "\n" . ' <input><soap:body use="' . $opParts['input']['use'] . '" namespace="' . $opParts['input']['namespace'] . '"' . $enc_style . '/></input>';
7037 if (isset($opParts['output']['encodingStyle']) && $opParts['output']['encodingStyle'] != '') {
7038 $enc_style = ' encodingStyle="' . $opParts['output']['encodingStyle'] . '"';
7042 $binding_xml .= "\n" . ' <output><soap:body use="' . $opParts['output']['use'] . '" namespace="' . $opParts['output']['namespace'] . '"' . $enc_style . '/></output>';
7043 $binding_xml .= "\n" . ' </operation>';
7044 $portType_xml .= "\n" . ' <operation name="' . $opParts['name'] . '"';
7045 if (isset($opParts['parameterOrder'])) {
7046 $portType_xml .= ' parameterOrder="' . $opParts['parameterOrder'] . '"';
7048 $portType_xml .= '>';
7049 if(isset($opParts['documentation']) && $opParts['documentation'] != '') {
7050 $portType_xml .= "\n" . ' <documentation>' . htmlspecialchars($opParts['documentation']) . '</documentation>';
7052 $portType_xml .= "\n" . ' <input message="tns:' . $opParts['input']['message'] . '"/>';
7053 $portType_xml .= "\n" . ' <output message="tns:' . $opParts['output']['message'] . '"/>';
7054 $portType_xml .= "\n" . ' </operation>';
7056 $portType_xml .= "\n" . '</portType>';
7057 $binding_xml .= "\n" . '</binding>';
7059 $xml .= $portType_xml . $binding_xml;
7062 $xml .= "\n<service name=\"" . $this->serviceName . '">';
7063 if (count($this->ports) >= 1) {
7064 foreach($this->ports as $pName => $attrs) {
7065 $xml .= "\n" . ' <port name="' . $pName . '" binding="tns:' . $attrs['binding'] . '">';
7066 $xml .= "\n" . ' <soap:address location="' . $attrs['location'] . ($debug ? '?debug=1' : '') . '"/>';
7067 $xml .= "\n" . ' </port>';
7070 $xml .= "\n" . '</service>';
7071 return $xml . "\n</definitions>";
7075 * determine whether a set of parameters are unwrapped
7076 * when they are expect to be wrapped, Microsoft-style.
7078 * @param string $type the type (element name) of the wrapper
7079 * @param array $parameters the parameter values for the SOAP call
7080 * @return boolean whether they parameters are unwrapped (and should be wrapped)
7083 function parametersMatchWrapped($type, &$parameters) {
7084 $this->debug("in parametersMatchWrapped type=$type, parameters=");
7085 $this->appendDebug($this->varDump($parameters));
7087 // split type into namespace:unqualified-type
7088 if (strpos($type, ':')) {
7089 $uqType = substr($type, strrpos($type, ':') + 1);
7090 $ns = substr($type, 0, strrpos($type, ':'));
7091 $this->debug("in parametersMatchWrapped: got a prefixed type: $uqType, $ns");
7092 if ($this->getNamespaceFromPrefix($ns)) {
7093 $ns = $this->getNamespaceFromPrefix($ns);
7094 $this->debug("in parametersMatchWrapped: expanded prefixed type: $uqType, $ns");
7097 // TODO: should the type be compared to types in XSD, and the namespace
7098 // set to XSD if the type matches?
7099 $this->debug("in parametersMatchWrapped: No namespace for type $type");
7104 // get the type information
7105 if (!$typeDef = $this->getTypeDef($uqType, $ns)) {
7106 $this->debug("in parametersMatchWrapped: $type ($uqType) is not a supported type.");
7109 $this->debug("in parametersMatchWrapped: found typeDef=");
7110 $this->appendDebug($this->varDump($typeDef));
7111 if (substr($uqType, -1) == '^') {
7112 $uqType = substr($uqType, 0, -1);
7114 $phpType = $typeDef['phpType'];
7115 $arrayType = (isset($typeDef['arrayType']) ? $typeDef['arrayType'] : '');
7116 $this->debug("in parametersMatchWrapped: uqType: $uqType, ns: $ns, phptype: $phpType, arrayType: $arrayType");
7118 // we expect a complexType or element of complexType
7119 if ($phpType != 'struct') {
7120 $this->debug("in parametersMatchWrapped: not a struct");
7124 // see whether the parameter names match the elements
7125 if (isset($typeDef['elements']) && is_array($typeDef['elements'])) {
7128 foreach ($typeDef['elements'] as $name => $attrs) {
7129 if (isset($parameters[$name])) {
7130 $this->debug("in parametersMatchWrapped: have parameter named $name");
7133 $this->debug("in parametersMatchWrapped: do not have parameter named $name");
7138 $this->debug("in parametersMatchWrapped: $matches parameter names match $elements wrapped parameter names");
7139 if ($matches == 0) {
7145 // since there are no elements for the type, if the user passed no
7146 // parameters, the parameters match wrapped.
7147 $this->debug("in parametersMatchWrapped: no elements type $ns:$uqType");
7148 return count($parameters) == 0;
7152 * serialize PHP values according to a WSDL message definition
7153 * contrary to the method name, this is not limited to RPC
7156 * - multi-ref serialization
7157 * - validate PHP values against type definitions, return errors if invalid
7159 * @param string $operation operation name
7160 * @param string $direction (input|output)
7161 * @param mixed $parameters parameter value(s)
7162 * @param string $bindingType (soap|soap12)
7163 * @return mixed parameters serialized as XML or false on error (e.g. operation not found)
7166 function serializeRPCParameters($operation, $direction, $parameters, $bindingType = 'soap') {
7167 $this->debug("in serializeRPCParameters: operation=$operation, direction=$direction, XMLSchemaVersion=$this->XMLSchemaVersion, bindingType=$bindingType");
7168 $this->appendDebug('parameters=' . $this->varDump($parameters));
7170 if ($direction != 'input' && $direction != 'output') {
7171 $this->debug('The value of the \$direction argument needs to be either "input" or "output"');
7172 $this->setError('The value of the \$direction argument needs to be either "input" or "output"');
7175 if (!$opData = $this->getOperationData($operation, $bindingType)) {
7176 $this->debug('Unable to retrieve WSDL data for operation: ' . $operation . ' bindingType: ' . $bindingType);
7177 $this->setError('Unable to retrieve WSDL data for operation: ' . $operation . ' bindingType: ' . $bindingType);
7180 $this->debug('in serializeRPCParameters: opData:');
7181 $this->appendDebug($this->varDump($opData));
7183 // Get encoding style for output and set to current
7184 $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
7185 if(($direction == 'input') && isset($opData['output']['encodingStyle']) && ($opData['output']['encodingStyle'] != $encodingStyle)) {
7186 $encodingStyle = $opData['output']['encodingStyle'];
7187 $enc_style = $encodingStyle;
7192 if (isset($opData[$direction]['parts']) && sizeof($opData[$direction]['parts']) > 0) {
7193 $parts = &$opData[$direction]['parts'];
7194 $part_count = sizeof($parts);
7195 $style = $opData['style'];
7196 $use = $opData[$direction]['use'];
7197 $this->debug("have $part_count part(s) to serialize using $style/$use");
7198 if (is_array($parameters)) {
7199 $parametersArrayType = $this->isArraySimpleOrStruct($parameters);
7200 $parameter_count = count($parameters);
7201 $this->debug("have $parameter_count parameter(s) provided as $parametersArrayType to serialize");
7202 // check for Microsoft-style wrapped parameters
7203 if ($style == 'document' && $use == 'literal' && $part_count == 1 && isset($parts['parameters'])) {
7204 $this->debug('check whether the caller has wrapped the parameters');
7205 if ($direction == 'output' && $parametersArrayType == 'arraySimple' && $parameter_count == 1) {
7206 // TODO: consider checking here for double-wrapping, when
7207 // service function wraps, then NuSOAP wraps again
7208 $this->debug("change simple array to associative with 'parameters' element");
7209 $parameters['parameters'] = $parameters[0];
7210 unset($parameters[0]);
7212 if (($parametersArrayType == 'arrayStruct' || $parameter_count == 0) && !isset($parameters['parameters'])) {
7213 $this->debug('check whether caller\'s parameters match the wrapped ones');
7214 if ($this->parametersMatchWrapped($parts['parameters'], $parameters)) {
7215 $this->debug('wrap the parameters for the caller');
7216 $parameters = array('parameters' => $parameters);
7217 $parameter_count = 1;
7221 foreach ($parts as $name => $type) {
7222 $this->debug("serializing part $name of type $type");
7223 // Track encoding style
7224 if (isset($opData[$direction]['encodingStyle']) && $encodingStyle != $opData[$direction]['encodingStyle']) {
7225 $encodingStyle = $opData[$direction]['encodingStyle'];
7226 $enc_style = $encodingStyle;
7230 // NOTE: add error handling here
7231 // if serializeType returns false, then catch global error and fault
7232 if ($parametersArrayType == 'arraySimple') {
7233 $p = array_shift($parameters);
7234 $this->debug('calling serializeType w/indexed param');
7235 $xml .= $this->serializeType($name, $type, $p, $use, $enc_style);
7236 } elseif (isset($parameters[$name])) {
7237 $this->debug('calling serializeType w/named param');
7238 $xml .= $this->serializeType($name, $type, $parameters[$name], $use, $enc_style);
7240 // TODO: only send nillable
7241 $this->debug('calling serializeType w/null param');
7242 $xml .= $this->serializeType($name, $type, null, $use, $enc_style);
7246 $this->debug('no parameters passed.');
7249 $this->debug("serializeRPCParameters returning: $xml");
7254 * serialize a PHP value according to a WSDL message definition
7257 * - multi-ref serialization
7258 * - validate PHP values against type definitions, return errors if invalid
7260 * @param string $operation operation name
7261 * @param string $direction (input|output)
7262 * @param mixed $parameters parameter value(s)
7263 * @return mixed parameters serialized as XML or false on error (e.g. operation not found)
7267 function serializeParameters($operation, $direction, $parameters)
7269 $this->debug("in serializeParameters: operation=$operation, direction=$direction, XMLSchemaVersion=$this->XMLSchemaVersion");
7270 $this->appendDebug('parameters=' . $this->varDump($parameters));
7272 if ($direction != 'input' && $direction != 'output') {
7273 $this->debug('The value of the \$direction argument needs to be either "input" or "output"');
7274 $this->setError('The value of the \$direction argument needs to be either "input" or "output"');
7277 if (!$opData = $this->getOperationData($operation)) {
7278 $this->debug('Unable to retrieve WSDL data for operation: ' . $operation);
7279 $this->setError('Unable to retrieve WSDL data for operation: ' . $operation);
7282 $this->debug('opData:');
7283 $this->appendDebug($this->varDump($opData));
7285 // Get encoding style for output and set to current
7286 $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
7287 if(($direction == 'input') && isset($opData['output']['encodingStyle']) && ($opData['output']['encodingStyle'] != $encodingStyle)) {
7288 $encodingStyle = $opData['output']['encodingStyle'];
7289 $enc_style = $encodingStyle;
7294 if (isset($opData[$direction]['parts']) && sizeof($opData[$direction]['parts']) > 0) {
7296 $use = $opData[$direction]['use'];
7297 $this->debug("use=$use");
7298 $this->debug('got ' . count($opData[$direction]['parts']) . ' part(s)');
7299 if (is_array($parameters)) {
7300 $parametersArrayType = $this->isArraySimpleOrStruct($parameters);
7301 $this->debug('have ' . $parametersArrayType . ' parameters');
7302 foreach($opData[$direction]['parts'] as $name => $type) {
7303 $this->debug('serializing part "'.$name.'" of type "'.$type.'"');
7304 // Track encoding style
7305 if(isset($opData[$direction]['encodingStyle']) && $encodingStyle != $opData[$direction]['encodingStyle']) {
7306 $encodingStyle = $opData[$direction]['encodingStyle'];
7307 $enc_style = $encodingStyle;
7311 // NOTE: add error handling here
7312 // if serializeType returns false, then catch global error and fault
7313 if ($parametersArrayType == 'arraySimple') {
7314 $p = array_shift($parameters);
7315 $this->debug('calling serializeType w/indexed param');
7316 $xml .= $this->serializeType($name, $type, $p, $use, $enc_style);
7317 } elseif (isset($parameters[$name])) {
7318 $this->debug('calling serializeType w/named param');
7319 $xml .= $this->serializeType($name, $type, $parameters[$name], $use, $enc_style);
7321 // TODO: only send nillable
7322 $this->debug('calling serializeType w/null param');
7323 $xml .= $this->serializeType($name, $type, null, $use, $enc_style);
7327 $this->debug('no parameters passed.');
7330 $this->debug("serializeParameters returning: $xml");
7335 * serializes a PHP value according a given type definition
7337 * @param string $name name of value (part or element)
7338 * @param string $type XML schema type of value (type or element)
7339 * @param mixed $value a native PHP value (parameter value)
7340 * @param string $use use for part (encoded|literal)
7341 * @param string $encodingStyle SOAP encoding style for the value (if different than the enclosing style)
7342 * @param boolean $unqualified a kludge for what should be XML namespace form handling
7343 * @return string value serialized as an XML string
7346 function serializeType($name, $type, $value, $use='encoded', $encodingStyle=false, $unqualified=false)
7348 $this->debug("in serializeType: name=$name, type=$type, use=$use, encodingStyle=$encodingStyle, unqualified=" . ($unqualified ? "unqualified" : "qualified"));
7349 $this->appendDebug("value=" . $this->varDump($value));
7350 if($use == 'encoded' && $encodingStyle) {
7351 $encodingStyle = ' SOAP-ENV:encodingStyle="' . $encodingStyle . '"';
7354 // if a soapval has been supplied, let its type override the WSDL
7355 if (is_object($value) && get_class($value) == 'soapval') {
7356 if ($value->type_ns) {
7357 $type = $value->type_ns . ':' . $value->type;
7359 $this->debug("in serializeType: soapval overrides type to $type");
7360 } elseif ($value->type) {
7361 $type = $value->type;
7363 $this->debug("in serializeType: soapval overrides type to $type");
7366 $this->debug("in serializeType: soapval does not override type");
7368 $attrs = $value->attributes;
7369 $value = $value->value;
7370 $this->debug("in serializeType: soapval overrides value to $value");
7372 if (!is_array($value)) {
7373 $value['!'] = $value;
7375 foreach ($attrs as $n => $v) {
7376 $value['!' . $n] = $v;
7378 $this->debug("in serializeType: soapval provides attributes");
7385 if (strpos($type, ':')) {
7386 $uqType = substr($type, strrpos($type, ':') + 1);
7387 $ns = substr($type, 0, strrpos($type, ':'));
7388 $this->debug("in serializeType: got a prefixed type: $uqType, $ns");
7389 if ($this->getNamespaceFromPrefix($ns)) {
7390 $ns = $this->getNamespaceFromPrefix($ns);
7391 $this->debug("in serializeType: expanded prefixed type: $uqType, $ns");
7394 if($ns == $this->XMLSchemaVersion || $ns == 'http://schemas.xmlsoap.org/soap/encoding/'){
7395 $this->debug('in serializeType: type namespace indicates XML Schema or SOAP Encoding type');
7396 if ($unqualified && $use == 'literal') {
7397 $elementNS = " xmlns=\"\"";
7401 if (is_null($value)) {
7402 if ($use == 'literal') {
7403 // TODO: depends on minOccurs
7404 $xml = "<$name$elementNS/>";
7406 // TODO: depends on nillable, which should be checked before calling this method
7407 $xml = "<$name$elementNS xsi:nil=\"true\" xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"/>";
7409 $this->debug("in serializeType: returning: $xml");
7412 if ($uqType == 'Array') {
7413 // JBoss/Axis does this sometimes
7414 return $this->serialize_val($value, $name, false, false, false, false, $use);
7416 if ($uqType == 'boolean') {
7417 if ((is_string($value) && $value == 'false') || (! $value)) {
7423 if ($uqType == 'string' && gettype($value) == 'string') {
7424 $value = $this->expandEntities($value);
7426 if (($uqType == 'long' || $uqType == 'unsignedLong') && gettype($value) == 'double') {
7427 $value = sprintf("%.0lf", $value);
7430 // TODO: what about null/nil values?
7431 // check type isn't a custom type extending xmlschema namespace
7432 if (!$this->getTypeDef($uqType, $ns)) {
7433 if ($use == 'literal') {
7435 $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">$value</$name>";
7437 $xml = "<$name$elementNS>$value</$name>";
7440 $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>$value</$name>";
7442 $this->debug("in serializeType: returning: $xml");
7445 $this->debug('custom type extends XML Schema or SOAP Encoding namespace (yuck)');
7446 } else if ($ns == 'http://xml.apache.org/xml-soap') {
7447 $this->debug('in serializeType: appears to be Apache SOAP type');
7448 if ($uqType == 'Map') {
7449 $tt_prefix = $this->getPrefixFromNamespace('http://xml.apache.org/xml-soap');
7451 $this->debug('in serializeType: Add namespace for Apache SOAP type');
7452 $tt_prefix = 'ns' . rand(1000, 9999);
7453 $this->namespaces[$tt_prefix] = 'http://xml.apache.org/xml-soap';
7454 // force this to be added to usedNamespaces
7455 $tt_prefix = $this->getPrefixFromNamespace('http://xml.apache.org/xml-soap');
7458 foreach($value as $k => $v) {
7459 $this->debug("serializing map element: key $k, value $v");
7460 $contents .= '<item>';
7461 $contents .= $this->serialize_val($k,'key',false,false,false,false,$use);
7462 $contents .= $this->serialize_val($v,'value',false,false,false,false,$use);
7463 $contents .= '</item>';
7465 if ($use == 'literal') {
7467 $xml = "<$name xsi:type=\"" . $tt_prefix . ":$uqType\">$contents</$name>";
7469 $xml = "<$name>$contents</$name>";
7472 $xml = "<$name xsi:type=\"" . $tt_prefix . ":$uqType\"$encodingStyle>$contents</$name>";
7474 $this->debug("in serializeType: returning: $xml");
7477 $this->debug('in serializeType: Apache SOAP type, but only support Map');
7480 // TODO: should the type be compared to types in XSD, and the namespace
7481 // set to XSD if the type matches?
7482 $this->debug("in serializeType: No namespace for type $type");
7486 if(!$typeDef = $this->getTypeDef($uqType, $ns)){
7487 $this->setError("$type ($uqType) is not a supported type.");
7488 $this->debug("in serializeType: $type ($uqType) is not a supported type.");
7491 $this->debug("in serializeType: found typeDef");
7492 $this->appendDebug('typeDef=' . $this->varDump($typeDef));
7493 if (substr($uqType, -1) == '^') {
7494 $uqType = substr($uqType, 0, -1);
7497 if (!isset($typeDef['phpType'])) {
7498 $this->setError("$type ($uqType) has no phpType.");
7499 $this->debug("in serializeType: $type ($uqType) has no phpType.");
7502 $phpType = $typeDef['phpType'];
7503 $this->debug("in serializeType: uqType: $uqType, ns: $ns, phptype: $phpType, arrayType: " . (isset($typeDef['arrayType']) ? $typeDef['arrayType'] : '') );
7504 // if php type == struct, map value to the <all> element names
7505 if ($phpType == 'struct') {
7506 if (isset($typeDef['typeClass']) && $typeDef['typeClass'] == 'element') {
7507 $elementName = $uqType;
7508 if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) {
7509 $elementNS = " xmlns=\"$ns\"";
7511 $elementNS = " xmlns=\"\"";
7514 $elementName = $name;
7516 $elementNS = " xmlns=\"\"";
7521 if (is_null($value)) {
7522 if ($use == 'literal') {
7523 // TODO: depends on minOccurs and nillable
7524 $xml = "<$elementName$elementNS/>";
7526 $xml = "<$elementName$elementNS xsi:nil=\"true\" xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"/>";
7528 $this->debug("in serializeType: returning: $xml");
7531 if (is_object($value)) {
7532 $value = get_object_vars($value);
7534 if (is_array($value)) {
7535 $elementAttrs = $this->serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType);
7536 if ($use == 'literal') {
7538 $xml = "<$elementName$elementNS$elementAttrs xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">";
7540 $xml = "<$elementName$elementNS$elementAttrs>";
7543 $xml = "<$elementName$elementNS$elementAttrs xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>";
7546 if (isset($typeDef['simpleContent']) && $typeDef['simpleContent'] == 'true') {
7547 if (isset($value['!'])) {
7548 $xml .= $value['!'];
7549 $this->debug("in serializeType: serialized simpleContent for type $type");
7551 $this->debug("in serializeType: no simpleContent to serialize for type $type");
7555 $xml .= $this->serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use, $encodingStyle);
7557 $xml .= "</$elementName>";
7559 $this->debug("in serializeType: phpType is struct, but value is not an array");
7560 $this->setError("phpType is struct, but value is not an array: see debug output for details");
7563 } elseif ($phpType == 'array') {
7564 if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) {
7565 $elementNS = " xmlns=\"$ns\"";
7568 $elementNS = " xmlns=\"\"";
7573 if (is_null($value)) {
7574 if ($use == 'literal') {
7575 // TODO: depends on minOccurs
7576 $xml = "<$name$elementNS/>";
7578 $xml = "<$name$elementNS xsi:nil=\"true\" xsi:type=\"" .
7579 $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/') .
7581 $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/') .
7583 $this->getPrefixFromNamespace($this->getPrefix($typeDef['arrayType'])) .
7585 $this->getLocalPart($typeDef['arrayType'])."[0]\"/>";
7587 $this->debug("in serializeType: returning: $xml");
7590 if (isset($typeDef['multidimensional'])) {
7592 foreach($value as $v) {
7593 $cols = ',' . sizeof($v);
7594 $nv = array_merge($nv, $v);
7600 if (is_array($value) && sizeof($value) >= 1) {
7601 $rows = sizeof($value);
7603 foreach($value as $k => $v) {
7604 $this->debug("serializing array element: $k, $v of type: $typeDef[arrayType]");
7605 //if (strpos($typeDef['arrayType'], ':') ) {
7606 if (!in_array($typeDef['arrayType'],$this->typemap['http://www.w3.org/2001/XMLSchema'])) {
7607 $contents .= $this->serializeType('item', $typeDef['arrayType'], $v, $use);
7609 $contents .= $this->serialize_val($v, 'item', $typeDef['arrayType'], null, $this->XMLSchemaVersion, false, $use);
7616 // TODO: for now, an empty value will be serialized as a zero element
7617 // array. Revisit this when coding the handling of null/nil values.
7618 if ($use == 'literal') {
7619 $xml = "<$name$elementNS>"
7623 $xml = "<$name$elementNS xsi:type=\"".$this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/').':Array" '.
7624 $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/')
7626 .$this->getPrefixFromNamespace($this->getPrefix($typeDef['arrayType']))
7627 .":".$this->getLocalPart($typeDef['arrayType'])."[$rows$cols]\">"
7631 } elseif ($phpType == 'scalar') {
7632 if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) {
7633 $elementNS = " xmlns=\"$ns\"";
7636 $elementNS = " xmlns=\"\"";
7641 if ($use == 'literal') {
7643 $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">$value</$name>";
7645 $xml = "<$name$elementNS>$value</$name>";
7648 $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>$value</$name>";
7651 $this->debug("in serializeType: returning: $xml");
7656 * serializes the attributes for a complexType
7658 * @param array $typeDef our internal representation of an XML schema type (or element)
7659 * @param mixed $value a native PHP value (parameter value)
7660 * @param string $ns the namespace of the type
7661 * @param string $uqType the local part of the type
7662 * @return string value serialized as an XML string
7665 function serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType) {
7666 $this->debug("serializeComplexTypeAttributes for XML Schema type $ns:$uqType");
7668 if (isset($typeDef['extensionBase'])) {
7669 $nsx = $this->getPrefix($typeDef['extensionBase']);
7670 $uqTypex = $this->getLocalPart($typeDef['extensionBase']);
7671 if ($this->getNamespaceFromPrefix($nsx)) {
7672 $nsx = $this->getNamespaceFromPrefix($nsx);
7674 if ($typeDefx = $this->getTypeDef($uqTypex, $nsx)) {
7675 $this->debug("serialize attributes for extension base $nsx:$uqTypex");
7676 $xml .= $this->serializeComplexTypeAttributes($typeDefx, $value, $nsx, $uqTypex);
7678 $this->debug("extension base $nsx:$uqTypex is not a supported type");
7681 if (isset($typeDef['attrs']) && is_array($typeDef['attrs'])) {
7682 $this->debug("serialize attributes for XML Schema type $ns:$uqType");
7683 if (is_array($value)) {
7685 } elseif (is_object($value)) {
7686 $xvalue = get_object_vars($value);
7688 $this->debug("value is neither an array nor an object for XML Schema type $ns:$uqType");
7691 foreach ($typeDef['attrs'] as $aName => $attrs) {
7692 if (isset($xvalue['!' . $aName])) {
7693 $xname = '!' . $aName;
7694 $this->debug("value provided for attribute $aName with key $xname");
7695 } elseif (isset($xvalue[$aName])) {
7697 $this->debug("value provided for attribute $aName with key $xname");
7698 } elseif (isset($attrs['default'])) {
7699 $xname = '!' . $aName;
7700 $xvalue[$xname] = $attrs['default'];
7701 $this->debug('use default value of ' . $xvalue[$aName] . ' for attribute ' . $aName);
7704 $this->debug("no value provided for attribute $aName");
7707 $xml .= " $aName=\"" . $this->expandEntities($xvalue[$xname]) . "\"";
7711 $this->debug("no attributes to serialize for XML Schema type $ns:$uqType");
7717 * serializes the elements for a complexType
7719 * @param array $typeDef our internal representation of an XML schema type (or element)
7720 * @param mixed $value a native PHP value (parameter value)
7721 * @param string $ns the namespace of the type
7722 * @param string $uqType the local part of the type
7723 * @param string $use use for part (encoded|literal)
7724 * @param string $encodingStyle SOAP encoding style for the value (if different than the enclosing style)
7725 * @return string value serialized as an XML string
7728 function serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use='encoded', $encodingStyle=false) {
7729 $this->debug("in serializeComplexTypeElements for XML Schema type $ns:$uqType");
7731 if (isset($typeDef['extensionBase'])) {
7732 $nsx = $this->getPrefix($typeDef['extensionBase']);
7733 $uqTypex = $this->getLocalPart($typeDef['extensionBase']);
7734 if ($this->getNamespaceFromPrefix($nsx)) {
7735 $nsx = $this->getNamespaceFromPrefix($nsx);
7737 if ($typeDefx = $this->getTypeDef($uqTypex, $nsx)) {
7738 $this->debug("serialize elements for extension base $nsx:$uqTypex");
7739 $xml .= $this->serializeComplexTypeElements($typeDefx, $value, $nsx, $uqTypex, $use, $encodingStyle);
7741 $this->debug("extension base $nsx:$uqTypex is not a supported type");
7744 if (isset($typeDef['elements']) && is_array($typeDef['elements'])) {
7745 $this->debug("in serializeComplexTypeElements, serialize elements for XML Schema type $ns:$uqType");
7746 if (is_array($value)) {
7748 } elseif (is_object($value)) {
7749 $xvalue = get_object_vars($value);
7751 $this->debug("value is neither an array nor an object for XML Schema type $ns:$uqType");
7754 // toggle whether all elements are present - ideally should validate against schema
7755 if (count($typeDef['elements']) != count($xvalue)){
7758 foreach ($typeDef['elements'] as $eName => $attrs) {
7759 if (!isset($xvalue[$eName])) {
7760 if (isset($attrs['default'])) {
7761 $xvalue[$eName] = $attrs['default'];
7762 $this->debug('use default value of ' . $xvalue[$eName] . ' for element ' . $eName);
7765 // if user took advantage of a minOccurs=0, then only serialize named parameters
7766 if (isset($optionals)
7767 && (!isset($xvalue[$eName]))
7768 && ( (!isset($attrs['nillable'])) || $attrs['nillable'] != 'true')
7770 if (isset($attrs['minOccurs']) && $attrs['minOccurs'] <> '0') {
7771 $this->debug("apparent error: no value provided for element $eName with minOccurs=" . $attrs['minOccurs']);
7774 $this->debug("no value provided for complexType element $eName and element is not nillable, so serialize nothing");
7777 if (isset($xvalue[$eName])) {
7778 $v = $xvalue[$eName];
7782 if (isset($attrs['form'])) {
7783 $unqualified = ($attrs['form'] == 'unqualified');
7785 $unqualified = false;
7787 if (isset($attrs['maxOccurs']) && ($attrs['maxOccurs'] == 'unbounded' || $attrs['maxOccurs'] > 1) && isset($v) && is_array($v) && $this->isArraySimpleOrStruct($v) == 'arraySimple') {
7789 foreach ($vv as $k => $v) {
7790 if (isset($attrs['type']) || isset($attrs['ref'])) {
7791 // serialize schema-defined type
7792 $xml .= $this->serializeType($eName, isset($attrs['type']) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified);
7794 // serialize generic type (can this ever really happen?)
7795 $this->debug("calling serialize_val() for $v, $eName, false, false, false, false, $use");
7796 $xml .= $this->serialize_val($v, $eName, false, false, false, false, $use);
7800 if (is_null($v) && isset($attrs['minOccurs']) && $attrs['minOccurs'] == '0') {
7802 } elseif (is_null($v) && isset($attrs['nillable']) && $attrs['nillable'] == 'true') {
7803 // TODO: serialize a nil correctly, but for now serialize schema-defined type
7804 $xml .= $this->serializeType($eName, isset($attrs['type']) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified);
7805 } elseif (isset($attrs['type']) || isset($attrs['ref'])) {
7806 // serialize schema-defined type
7807 $xml .= $this->serializeType($eName, isset($attrs['type']) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified);
7809 // serialize generic type (can this ever really happen?)
7810 $this->debug("calling serialize_val() for $v, $eName, false, false, false, false, $use");
7811 $xml .= $this->serialize_val($v, $eName, false, false, false, false, $use);
7817 $this->debug("no elements to serialize for XML Schema type $ns:$uqType");
7823 * adds an XML Schema complex type to the WSDL types
7825 * @param string $name
7826 * @param string $typeClass (complexType|simpleType|attribute)
7827 * @param string $phpType currently supported are array and struct (php assoc array)
7828 * @param string $compositor (all|sequence|choice)
7829 * @param string $restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
7830 * @param array $elements e.g. array ( name => array(name=>'',type=>'') )
7831 * @param array $attrs e.g. array(array('ref'=>'SOAP-ENC:arrayType','wsdl:arrayType'=>'xsd:string[]'))
7832 * @param string $arrayType as namespace:name (xsd:string)
7833 * @see nusoap_xmlschema
7836 function addComplexType($name,$typeClass='complexType',$phpType='array',$compositor='',$restrictionBase='',$elements=array(),$attrs=array(),$arrayType='') {
7837 if (count($elements) > 0) {
7838 $eElements = array();
7839 foreach($elements as $n => $e){
7840 // expand each element
7842 foreach ($e as $k => $v) {
7843 $k = strpos($k,':') ? $this->expandQname($k) : $k;
7844 $v = strpos($v,':') ? $this->expandQname($v) : $v;
7847 $eElements[$n] = $ee;
7849 $elements = $eElements;
7852 if (count($attrs) > 0) {
7853 foreach($attrs as $n => $a){
7854 // expand each attribute
7855 foreach ($a as $k => $v) {
7856 $k = strpos($k,':') ? $this->expandQname($k) : $k;
7857 $v = strpos($v,':') ? $this->expandQname($v) : $v;
7865 $restrictionBase = strpos($restrictionBase,':') ? $this->expandQname($restrictionBase) : $restrictionBase;
7866 $arrayType = strpos($arrayType,':') ? $this->expandQname($arrayType) : $arrayType;
7868 $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns'];
7869 $this->schemas[$typens][0]->addComplexType($name,$typeClass,$phpType,$compositor,$restrictionBase,$elements,$attrs,$arrayType);
7873 * adds an XML Schema simple type to the WSDL types
7875 * @param string $name
7876 * @param string $restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
7877 * @param string $typeClass (should always be simpleType)
7878 * @param string $phpType (should always be scalar)
7879 * @param array $enumeration array of values
7880 * @see nusoap_xmlschema
7883 function addSimpleType($name, $restrictionBase='', $typeClass='simpleType', $phpType='scalar', $enumeration=array()) {
7884 $restrictionBase = strpos($restrictionBase,':') ? $this->expandQname($restrictionBase) : $restrictionBase;
7886 $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns'];
7887 $this->schemas[$typens][0]->addSimpleType($name, $restrictionBase, $typeClass, $phpType, $enumeration);
7891 * adds an element to the WSDL types
7893 * @param array $attrs attributes that must include name and type
7894 * @see nusoap_xmlschema
7897 function addElement($attrs) {
7898 $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns'];
7899 $this->schemas[$typens][0]->addElement($attrs);
7903 * register an operation with the server
7905 * @param string $name operation (method) name
7906 * @param array $in assoc array of input values: key = param name, value = param type
7907 * @param array $out assoc array of output values: key = param name, value = param type
7908 * @param string $namespace optional The namespace for the operation
7909 * @param string $soapaction optional The soapaction for the operation
7910 * @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
7911 * @param string $use (encoded|literal) optional The use for the parameters (cannot mix right now)
7912 * @param string $documentation optional The description to include in the WSDL
7913 * @param string $encodingStyle optional (usually 'http://schemas.xmlsoap.org/soap/encoding/' for encoded)
7916 function addOperation($name, $in = false, $out = false, $namespace = false, $soapaction = false, $style = 'rpc', $use = 'encoded', $documentation = '', $encodingStyle = ''){
7917 if ($use == 'encoded' && $encodingStyle == '') {
7918 $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
7921 if ($style == 'document') {
7922 $elements = array();
7923 foreach ($in as $n => $t) {
7924 $elements[$n] = array('name' => $n, 'type' => $t, 'form' => 'unqualified');
7926 $this->addComplexType($name . 'RequestType', 'complexType', 'struct', 'all', '', $elements);
7927 $this->addElement(array('name' => $name, 'type' => $name . 'RequestType'));
7928 $in = array('parameters' => 'tns:' . $name . '^');
7930 $elements = array();
7931 foreach ($out as $n => $t) {
7932 $elements[$n] = array('name' => $n, 'type' => $t, 'form' => 'unqualified');
7934 $this->addComplexType($name . 'ResponseType', 'complexType', 'struct', 'all', '', $elements);
7935 $this->addElement(array('name' => $name . 'Response', 'type' => $name . 'ResponseType', 'form' => 'qualified'));
7936 $out = array('parameters' => 'tns:' . $name . 'Response' . '^');
7940 $this->bindings[ $this->serviceName . 'Binding' ]['operations'][$name] =
7943 'binding' => $this->serviceName . 'Binding',
7944 'endpoint' => $this->endpoint,
7945 'soapAction' => $soapaction,
7949 'namespace' => $namespace,
7950 'encodingStyle' => $encodingStyle,
7951 'message' => $name . 'Request',
7955 'namespace' => $namespace,
7956 'encodingStyle' => $encodingStyle,
7957 'message' => $name . 'Response',
7959 'namespace' => $namespace,
7960 'transport' => 'http://schemas.xmlsoap.org/soap/http',
7961 'documentation' => $documentation);
7966 foreach($in as $pName => $pType)
7968 if(strpos($pType,':')) {
7969 $pType = $this->getNamespaceFromPrefix($this->getPrefix($pType)).":".$this->getLocalPart($pType);
7971 $this->messages[$name.'Request'][$pName] = $pType;
7974 $this->messages[$name.'Request']= '0';
7978 foreach($out as $pName => $pType)
7980 if(strpos($pType,':')) {
7981 $pType = $this->getNamespaceFromPrefix($this->getPrefix($pType)).":".$this->getLocalPart($pType);
7983 $this->messages[$name.'Response'][$pName] = $pType;
7986 $this->messages[$name.'Response']= '0';
7995 Modification information for LGPL compliance
7997 r58622 - 2010-10-22 18:18:59 -0700 (Fri, 22 Oct 2010) - engsvnbuild - Author: lam <lam@198.18.142.201>
8000 r58361 - 2010-09-29 16:59:02 -0700 (Wed, 29 Sep 2010) - kjing - Author: Jenny Gonsalves <jenny@sugarcrm.com>
8001 Merging with maint_6_0_1 (svn merge -r 58250:58342)
8003 r57813 - 2010-08-19 10:34:44 -0700 (Thu, 19 Aug 2010) - kjing - Author: John Mertic <jmertic@sugarcrm.com>
8004 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.
8006 r57707 - 2010-08-10 12:26:13 -0700 (Tue, 10 Aug 2010) - kjing - Author: Stanislav Malyshev <smalyshev@gmail.com>
8007 fix SOAP calls with no parameters
8009 r56990 - 2010-06-16 13:05:36 -0700 (Wed, 16 Jun 2010) - kjing - snapshot "Mango" svn branch to a new one for GitHub sync
8011 r56989 - 2010-06-16 13:01:33 -0700 (Wed, 16 Jun 2010) - kjing - defunt "Mango" svn dev branch before github cutover
8013 r55980 - 2010-04-19 13:31:28 -0700 (Mon, 19 Apr 2010) - kjing - create Mango (6.1) based on windex
8015 r51719 - 2009-10-22 10:18:00 -0700 (Thu, 22 Oct 2009) - mitani - Converted to Build 3 tags and updated the build system
8017 r51634 - 2009-10-19 13:32:22 -0700 (Mon, 19 Oct 2009) - mitani - Windex is the branch for Sugar Sales 1.0 development
8019 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.
8021 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.
8023 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:
8024 - Changing all ereg function to either preg or simple string based ones
8025 - No more references to magic quotes.
8026 - Change all the session_unregister() functions to just unset() the correct session variable instead.
8028 r50375 - 2009-08-24 18:07:43 -0700 (Mon, 24 Aug 2009) - dwong - branch kobe2 from tokyo r50372
8030 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
8032 r45680 - 2009-03-30 14:34:35 -0700 (Mon, 30 Mar 2009) - Samir Gandhi - modifeid serializeSchema to generate WS-I compliant WSDL
8034 r42807 - 2008-12-29 11:16:59 -0800 (Mon, 29 Dec 2008) - dwong - Branch from trunk/sugarcrm r42806 to branches/tokyo/sugarcrm
8036 r42645 - 2008-12-18 13:41:08 -0800 (Thu, 18 Dec 2008) - awu - merging maint_5_2_0 rev41336:HEAD to trunk
8038 r41647 - 2008-11-11 17:44:30 -0800 (Tue, 11 Nov 2008) - majed - Fixes a few bugs
8040 r41596 - 2008-11-10 19:20:04 -0800 (Mon, 10 Nov 2008) - Samir Gandhi - modified to set $method in the code
8042 r41558 - 2008-11-10 14:35:34 -0800 (Mon, 10 Nov 2008) - majed - changes nusoap to allow for registering classes
8044 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.
8046 - data/SugarBean.php
8047 - include/domit/php_http_client_generic.php
8048 - include/domit/php_http_connector.php
8049 - include/domit/testing_domit.php
8050 - include/domit/xml_domit_getelementsbypath.php
8051 - include/domit/xml_domit_lite_parser.php
8052 - include/domit/xml_domit_nodemaps.php
8053 - include/domit/xml_domit_parser.php
8054 - include/domit/xml_domit_shared.php
8055 - include/generic/SugarWidgets/SugarWidgetField.php
8056 - include/generic/SugarWidgets/SugarWidgetReportField.php
8057 - include/ListView/ProcessView.php
8058 - include/nusoap/class.soapclient.php
8059 - include/nusoap/nusoap.php
8060 - include/nusoap/nusoapmime.php
8061 - include/Pear/HTML_Safe/Safe.php
8062 - include/Pear/XML_HTMLSax3/HTMLSax3.php
8063 - modules/Administration/RebuildWorkFlow.php
8064 - modules/Expressions/RelateSelector.php
8065 - modules/Reports/templates/templates_reports.php
8066 - modules/WorkFlow/Delete.php
8067 - modules/WorkFlow/Save.php
8068 - modules/WorkFlow/SaveSequence.php
8069 - modules/WorkFlow/WorkFlow.php
8070 - modules/WorkFlowActionShells/CreateStep1.php
8071 - modules/WorkFlowActionShells/CreateStep2.php
8072 - modules/WorkFlowActionShells/Save.php
8073 - modules/WorkFlowActionShells/WorkFlowActionShell.php
8074 - modules/WorkFlowAlerts/Save.php
8075 - modules/WorkFlowAlerts/WorkFlowAlert.php
8076 - modules/WorkFlowAlertShells/DetailView.php
8077 - modules/WorkFlowAlertShells/WorkFlowAlertShell.php
8078 - modules/WorkFlowTriggerShells/CreateStep1.php
8079 - modules/WorkFlowTriggerShells/CreateStepFilter.php
8080 - modules/WorkFlowTriggerShells/SaveFilter.php
8081 - modules/WorkFlowTriggerShells/WorkFlowTriggerShell.php
8082 - soap/SoapHelperFunctions.php
8083 - test/modules/DynamicFields/DynamicFields_Bug24095_test.php
8084 - test/simpletest/browser.php
8085 - test/simpletest/default_reporter.php
8086 - test/simpletest/detached.php
8087 - test/simpletest/eclipse.php
8088 - test/simpletest/expectation.php
8089 - test/simpletest/extensions/pear_test_case.php
8090 - test/simpletest/form.php
8091 - test/simpletest/http.php
8092 - test/simpletest/mock_objects.php
8093 - test/simpletest/page.php
8094 - test/simpletest/parser.php
8095 - test/simpletest/remote.php
8096 - test/simpletest/shell_tester.php
8097 - test/simpletest/simple_test.php
8098 - test/simpletest/simpletest.php
8099 - test/simpletest/test/acceptance_test.php
8100 - test/simpletest/test/adapter_test.php
8101 - test/simpletest/test/authentication_test.php
8102 - test/simpletest/test/browser_test.php
8103 - test/simpletest/test/collector_test.php
8104 - test/simpletest/test/compatibility_test.php
8105 - test/simpletest/test/detached_test.php
8106 - test/simpletest/test/eclipse_test.php
8107 - test/simpletest/test/encoding_test.php
8108 - test/simpletest/test/errors_test.php
8109 - test/simpletest/test/expectation_test.php
8110 - test/simpletest/test/form_test.php
8111 - test/simpletest/test/frames_test.php
8112 - test/simpletest/test/http_test.php
8113 - test/simpletest/test/live_test.php
8114 - test/simpletest/test/mock_objects_test.php
8115 - test/simpletest/test/page_test.php
8116 - test/simpletest/test/parse_error_test.php
8117 - test/simpletest/test/parser_test.php
8118 - test/simpletest/test/remote_test.php
8119 - test/simpletest/test/shell_test.php
8120 - test/simpletest/test/shell_tester_test.php
8121 - test/simpletest/test/simpletest_test.php
8122 - test/simpletest/test/site/page_request.php
8123 - test/simpletest/test/tag_test.php
8124 - test/simpletest/test/unit_tester_test.php
8125 - test/simpletest/test/user_agent_test.php
8126 - test/simpletest/test/visual_test.php
8127 - test/simpletest/test/xml_test.php
8128 - test/simpletest/test_case.php
8129 - test/simpletest/ui/array_reporter/test.php
8130 - test/simpletest/ui/recorder/test.php
8131 - test/simpletest/unit_tester.php
8132 - test/simpletest/url.php
8133 - test/simpletest/user_agent.php
8134 - test/simpletest/web_tester.php
8135 - test/spikephpcoverage/src/PEAR.php
8136 - test/spikephpcoverage/src/util/Utility.php
8137 - test/spikephpcoverage/src/XML/Parser.php
8138 - test/spikephpcoverage/src/XML/Parser/Simple.php
8139 - test/test_utilities/SugarTest_SimpleBrowser.php
8141 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.
8143 r38300 - 2008-07-25 13:33:43 -0700 (Fri, 25 Jul 2008) - Samir Gandhi - put the debug in parseresponse function
8145 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
8147 r36824 - 2008-06-18 09:26:11 -0700 (Wed, 18 Jun 2008) - roger - bug: 21832
8149 r26422 - 2007-09-05 17:29:12 -0700 (Wed, 05 Sep 2007) - majed - migrate from beta 1 to trunk
8151 r15787 - 2006-08-10 10:14:41 -0700 (Thu, 10 Aug 2006) - roger - RRS: bug 7961
8153 r14701 - 2006-07-17 13:37:26 -0700 (Mon, 17 Jul 2006) - roger - RRS: bug 5801
8155 r13782 - 2006-06-06 10:58:55 -0700 (Tue, 06 Jun 2006) - majed - changes entry point code
8157 r11466 - 2006-02-01 15:49:47 -0800 (Wed, 01 Feb 2006) - jacob - Adding extra !empty check to get around a PHP warning.
8159 r11115 - 2006-01-17 14:54:45 -0800 (Tue, 17 Jan 2006) - majed - add entry point validation
8161 r10585 - 2005-12-13 14:42:26 -0800 (Tue, 13 Dec 2005) - majed - adds new license mechanisim
8163 r10170 - 2005-12-05 18:37:46 -0800 (Mon, 05 Dec 2005) - majed - fixes various issues
8165 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.
8167 r8991 - 2005-11-03 19:07:25 -0800 (Thu, 03 Nov 2005) - majed - fixes nusoap issue
8169 r8846 - 2005-10-31 11:01:12 -0800 (Mon, 31 Oct 2005) - majed - new version of nusoap
8171 r7905 - 2005-09-21 19:12:57 -0700 (Wed, 21 Sep 2005) - majed - restores old nusoap pre & with a few fixes
8173 r7861 - 2005-09-20 15:40:25 -0700 (Tue, 20 Sep 2005) - majed - & fix for 3.5.1
8175 r7452 - 2005-08-17 11:32:34 -0700 (Wed, 17 Aug 2005) - majed - changes soap to nusoap
8177 r5820 - 2005-06-21 14:22:24 -0700 (Tue, 21 Jun 2005) - majed - fixes issues with nusoap and with custom fields
8179 r5462 - 2005-05-25 13:50:11 -0700 (Wed, 25 May 2005) - majed - upgraded nusoap to .6.9
8181 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
8183 r573 - 2004-09-04 13:03:32 -0700 (Sat, 04 Sep 2004) - sugarclint - undoing copyrights added in inadvertantly. --clint
8185 r546 - 2004-09-03 11:49:38 -0700 (Fri, 03 Sep 2004) - sugarmsi - removed echo count
8187 r354 - 2004-08-02 23:00:37 -0700 (Mon, 02 Aug 2004) - sugarjacob - Adding Soap
8198 * nusoap_parser class parses SOAP XML messages into native PHP values
8200 * @author Dietrich Ayala <dietrich@ganx4.com>
8201 * @author Scott Nichol <snichol@users.sourceforge.net>
8205 class nusoap_parser extends nusoap_base {
8208 var $xml_encoding = '';
8210 var $root_struct = '';
8211 var $root_struct_name = '';
8212 var $root_struct_namespace = '';
8213 var $root_header = '';
8214 var $document = ''; // incoming SOAP body (text)
8215 // determines where in the message we are (envelope,header,body,method)
8219 var $default_namespace = '';
8220 var $namespaces = array();
8221 var $message = array();
8224 var $fault_code = '';
8225 var $fault_str = '';
8226 var $fault_detail = '';
8227 var $depth_array = array();
8228 var $debug_flag = true;
8229 var $soapresponse = NULL; // parsed SOAP Body
8230 var $soapheader = NULL; // parsed SOAP Header
8231 var $responseHeaders = ''; // incoming SOAP headers (text)
8232 var $body_position = 0;
8233 // for multiref parsing:
8234 // array of id => pos
8236 // array of id => hrefs => pos
8237 var $multirefs = array();
8238 // toggle for auto-decoding element content
8239 var $decode_utf8 = false;
8242 * constructor that actually does the parsing
8244 * @param string $xml SOAP message
8245 * @param string $encoding character encoding scheme of message
8246 * @param string $method method for which XML is parsed (unused?)
8247 * @param string $decode_utf8 whether to decode UTF-8 to ISO-8859-1
8250 function nusoap_parser($xml,$encoding='UTF-8',$method='',$decode_utf8=true){
8251 parent::nusoap_base();
8253 $this->xml_encoding = $encoding;
8254 $this->method = $method;
8255 $this->decode_utf8 = $decode_utf8;
8257 // Check whether content has been read.
8259 // Check XML encoding
8260 $pos_xml = strpos($xml, '<?xml');
8261 if ($pos_xml !== FALSE) {
8262 $xml_decl = substr($xml, $pos_xml, strpos($xml, '?>', $pos_xml + 2) - $pos_xml + 1);
8263 if (preg_match("/encoding=[\"']([^\"']*)[\"']/", $xml_decl, $res)) {
8264 $xml_encoding = $res[1];
8265 if (strtoupper($xml_encoding) != $encoding) {
8266 $err = "Charset from HTTP Content-Type '" . $encoding . "' does not match encoding from XML declaration '" . $xml_encoding . "'";
8268 if ($encoding != 'ISO-8859-1' || strtoupper($xml_encoding) != 'UTF-8') {
8269 $this->setError($err);
8272 // when HTTP says ISO-8859-1 (the default) and XML says UTF-8 (the typical), assume the other endpoint is just sloppy and proceed
8274 $this->debug('Charset from HTTP Content-Type matches encoding from XML declaration');
8277 $this->debug('No encoding specified in XML declaration');
8280 $this->debug('No XML declaration');
8282 $this->debug('Entering nusoap_parser(), length='.strlen($xml).', encoding='.$encoding);
8283 // Create an XML parser - why not xml_parser_create_ns?
8284 $this->parser = xml_parser_create($this->xml_encoding);
8285 // Set the options for parsing the XML data.
8286 //xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
8287 xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
8288 xml_parser_set_option($this->parser, XML_OPTION_TARGET_ENCODING, $this->xml_encoding);
8289 // Set the object for the parser.
8290 xml_set_object($this->parser, $this);
8291 // Set the element handlers for the parser.
8292 xml_set_element_handler($this->parser, 'start_element','end_element');
8293 xml_set_character_data_handler($this->parser,'character_data');
8295 // Parse the XML file.
8296 if(!xml_parse($this->parser,$xml,true)){
8297 // Display an error message.
8298 $err = sprintf('XML error parsing SOAP payload on line %d: %s',
8299 xml_get_current_line_number($this->parser),
8300 xml_error_string(xml_get_error_code($this->parser)));
8302 $this->debug("XML payload:\n" . $xml);
8303 $this->setError($err);
8305 $this->debug('in nusoap_parser ctor, message:');
8306 $this->appendDebug($this->varDump($this->message));
8307 $this->debug('parsed successfully, found root struct: '.$this->root_struct.' of name '.$this->root_struct_name);
8309 $this->soapresponse = $this->message[$this->root_struct]['result'];
8311 if($this->root_header != '' && isset($this->message[$this->root_header]['result'])){
8312 $this->soapheader = $this->message[$this->root_header]['result'];
8314 // resolve hrefs/ids
8315 if(sizeof($this->multirefs) > 0){
8316 foreach($this->multirefs as $id => $hrefs){
8317 $this->debug('resolving multirefs for id: '.$id);
8318 $idVal = $this->buildVal($this->ids[$id]);
8319 if (is_array($idVal) && isset($idVal['!id'])) {
8320 unset($idVal['!id']);
8322 foreach($hrefs as $refPos => $ref){
8323 $this->debug('resolving href at pos '.$refPos);
8324 $this->multirefs[$id][$refPos] = $idVal;
8329 xml_parser_free($this->parser);
8331 $this->debug('xml was empty, didn\'t parse!');
8332 $this->setError('xml was empty, didn\'t parse!');
8337 * start-element handler
8339 * @param resource $parser XML parser object
8340 * @param string $name element name
8341 * @param array $attrs associative array of attributes
8344 function start_element($parser, $name, $attrs) {
8345 // position in a total number of elements, starting from 0
8346 // update class level pos
8347 $pos = $this->position++;
8349 $this->message[$pos] = array('pos' => $pos,'children'=>'','cdata'=>'');
8350 // depth = how many levels removed from root?
8351 // set mine as current global depth and increment global depth value
8352 $this->message[$pos]['depth'] = $this->depth++;
8354 // else add self as child to whoever the current parent is
8356 $this->message[$this->parent]['children'] .= '|'.$pos;
8359 $this->message[$pos]['parent'] = $this->parent;
8360 // set self as current parent
8361 $this->parent = $pos;
8362 // set self as current value for this depth
8363 $this->depth_array[$this->depth] = $pos;
8364 // get element prefix
8365 if(strpos($name,':')){
8367 $prefix = substr($name,0,strpos($name,':'));
8368 // get unqualified name
8369 $name = substr(strstr($name,':'),1);
8372 if ($name == 'Envelope' && $this->status == '') {
8373 $this->status = 'envelope';
8374 } elseif ($name == 'Header' && $this->status == 'envelope') {
8375 $this->root_header = $pos;
8376 $this->status = 'header';
8377 } elseif ($name == 'Body' && $this->status == 'envelope'){
8378 $this->status = 'body';
8379 $this->body_position = $pos;
8381 } elseif($this->status == 'body' && $pos == ($this->body_position+1)) {
8382 $this->status = 'method';
8383 $this->root_struct_name = $name;
8384 $this->root_struct = $pos;
8385 $this->message[$pos]['type'] = 'struct';
8386 $this->debug("found root struct $this->root_struct_name, pos $this->root_struct");
8389 $this->message[$pos]['status'] = $this->status;
8391 $this->message[$pos]['name'] = htmlspecialchars($name);
8393 $this->message[$pos]['attrs'] = $attrs;
8395 // loop through atts, logging ns and type declarations
8397 foreach($attrs as $key => $value){
8398 $key_prefix = $this->getPrefix($key);
8399 $key_localpart = $this->getLocalPart($key);
8400 // if ns declarations, add to class level array of valid namespaces
8401 if($key_prefix == 'xmlns'){
8402 if(preg_match('/^http:\/\/www.w3.org\/[0-9]{4}\/XMLSchema$/',$value)){
8403 $this->XMLSchemaVersion = $value;
8404 $this->namespaces['xsd'] = $this->XMLSchemaVersion;
8405 $this->namespaces['xsi'] = $this->XMLSchemaVersion.'-instance';
8407 $this->namespaces[$key_localpart] = $value;
8408 // set method namespace
8409 if($name == $this->root_struct_name){
8410 $this->methodNamespace = $value;
8412 // if it's a type declaration, set type
8413 } elseif($key_localpart == 'type'){
8414 if (isset($this->message[$pos]['type']) && $this->message[$pos]['type'] == 'array') {
8415 // do nothing: already processed arrayType
8417 $value_prefix = $this->getPrefix($value);
8418 $value_localpart = $this->getLocalPart($value);
8419 $this->message[$pos]['type'] = $value_localpart;
8420 $this->message[$pos]['typePrefix'] = $value_prefix;
8421 if(isset($this->namespaces[$value_prefix])){
8422 $this->message[$pos]['type_namespace'] = $this->namespaces[$value_prefix];
8423 } else if(isset($attrs['xmlns:'.$value_prefix])) {
8424 $this->message[$pos]['type_namespace'] = $attrs['xmlns:'.$value_prefix];
8426 // should do something here with the namespace of specified type?
8428 } elseif($key_localpart == 'arrayType'){
8429 $this->message[$pos]['type'] = 'array';
8430 /* do arrayType ereg here
8431 [1] arrayTypeValue ::= atype asize
8432 [2] atype ::= QName rank*
8433 [3] rank ::= '[' (',')* ']'
8434 [4] asize ::= '[' length~ ']'
8435 [5] length ::= nextDimension* Digit+
8436 [6] nextDimension ::= Digit+ ','
8438 $expr = '/([A-Za-z0-9_]+):([A-Za-z]+[A-Za-z0-9_]+)\[([0-9]+),?([0-9]*)\]/';
8439 if(preg_match($expr,$value,$regs)){
8440 $this->message[$pos]['typePrefix'] = $regs[1];
8441 $this->message[$pos]['arrayTypePrefix'] = $regs[1];
8442 if (isset($this->namespaces[$regs[1]])) {
8443 $this->message[$pos]['arrayTypeNamespace'] = $this->namespaces[$regs[1]];
8444 } else if (isset($attrs['xmlns:'.$regs[1]])) {
8445 $this->message[$pos]['arrayTypeNamespace'] = $attrs['xmlns:'.$regs[1]];
8447 $this->message[$pos]['arrayType'] = $regs[2];
8448 $this->message[$pos]['arraySize'] = $regs[3];
8449 $this->message[$pos]['arrayCols'] = $regs[4];
8451 // specifies nil value (or not)
8452 } elseif ($key_localpart == 'nil'){
8453 $this->message[$pos]['nil'] = ($value == 'true' || $value == '1');
8454 // some other attribute
8455 } elseif ($key != 'href' && $key != 'xmlns' && $key_localpart != 'encodingStyle' && $key_localpart != 'root') {
8456 $this->message[$pos]['xattrs']['!' . $key] = $value;
8459 if ($key == 'xmlns') {
8460 $this->default_namespace = $value;
8464 $this->ids[$value] = $pos;
8467 if($key_localpart == 'root' && $value == 1){
8468 $this->status = 'method';
8469 $this->root_struct_name = $name;
8470 $this->root_struct = $pos;
8471 $this->debug("found root struct $this->root_struct_name, pos $pos");
8474 $attstr .= " $key=\"$value\"";
8476 // get namespace - must be done after namespace atts are processed
8478 $this->message[$pos]['namespace'] = $this->namespaces[$prefix];
8479 $this->default_namespace = $this->namespaces[$prefix];
8481 $this->message[$pos]['namespace'] = $this->default_namespace;
8483 if($this->status == 'header'){
8484 if ($this->root_header != $pos) {
8485 $this->responseHeaders .= "<" . (isset($prefix) ? $prefix . ':' : '') . "$name$attstr>";
8487 } elseif($this->root_struct_name != ''){
8488 $this->document .= "<" . (isset($prefix) ? $prefix . ':' : '') . "$name$attstr>";
8493 * end-element handler
8495 * @param resource $parser XML parser object
8496 * @param string $name element name
8499 function end_element($parser, $name) {
8500 // position of current element is equal to the last value left in depth_array for my depth
8501 $pos = $this->depth_array[$this->depth--];
8503 // get element prefix
8504 if(strpos($name,':')){
8506 $prefix = substr($name,0,strpos($name,':'));
8507 // get unqualified name
8508 $name = substr(strstr($name,':'),1);
8511 // build to native type
8512 if(isset($this->body_position) && $pos > $this->body_position){
8513 // deal w/ multirefs
8514 if(isset($this->message[$pos]['attrs']['href'])){
8516 $id = substr($this->message[$pos]['attrs']['href'],1);
8517 // add placeholder to href array
8518 $this->multirefs[$id][$pos] = 'placeholder';
8519 // add set a reference to it as the result value
8520 $this->message[$pos]['result'] =& $this->multirefs[$id][$pos];
8521 // build complexType values
8522 } elseif($this->message[$pos]['children'] != ''){
8523 // if result has already been generated (struct/array)
8524 if(!isset($this->message[$pos]['result'])){
8525 $this->message[$pos]['result'] = $this->buildVal($pos);
8527 // build complexType values of attributes and possibly simpleContent
8528 } elseif (isset($this->message[$pos]['xattrs'])) {
8529 if (isset($this->message[$pos]['nil']) && $this->message[$pos]['nil']) {
8530 $this->message[$pos]['xattrs']['!'] = null;
8531 } elseif (isset($this->message[$pos]['cdata']) && trim($this->message[$pos]['cdata']) != '') {
8532 if (isset($this->message[$pos]['type'])) {
8533 $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'] : '');
8535 $parent = $this->message[$pos]['parent'];
8536 if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
8537 $this->message[$pos]['xattrs']['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
8539 $this->message[$pos]['xattrs']['!'] = $this->message[$pos]['cdata'];
8543 $this->message[$pos]['result'] = $this->message[$pos]['xattrs'];
8544 // set value of simpleType (or nil complexType)
8546 //$this->debug('adding data for scalar value '.$this->message[$pos]['name'].' of value '.$this->message[$pos]['cdata']);
8547 if (isset($this->message[$pos]['nil']) && $this->message[$pos]['nil']) {
8548 $this->message[$pos]['xattrs']['!'] = null;
8549 } elseif (isset($this->message[$pos]['type'])) {
8550 $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'] : '');
8552 $parent = $this->message[$pos]['parent'];
8553 if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
8554 $this->message[$pos]['result'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
8556 $this->message[$pos]['result'] = $this->message[$pos]['cdata'];
8560 /* add value to parent's result, if parent is struct/array
8561 $parent = $this->message[$pos]['parent'];
8562 if($this->message[$parent]['type'] != 'map'){
8563 if(strtolower($this->message[$parent]['type']) == 'array'){
8564 $this->message[$parent]['result'][] = $this->message[$pos]['result'];
8566 $this->message[$parent]['result'][$this->message[$pos]['name']] = $this->message[$pos]['result'];
8574 if($this->status == 'header'){
8575 if ($this->root_header != $pos) {
8576 $this->responseHeaders .= "</" . (isset($prefix) ? $prefix . ':' : '') . "$name>";
8578 } elseif($pos >= $this->root_struct){
8579 $this->document .= "</" . (isset($prefix) ? $prefix . ':' : '') . "$name>";
8582 if ($pos == $this->root_struct){
8583 $this->status = 'body';
8584 $this->root_struct_namespace = $this->message[$pos]['namespace'];
8585 } elseif ($pos == $this->root_header) {
8586 $this->status = 'envelope';
8587 } elseif ($name == 'Body' && $this->status == 'body') {
8588 $this->status = 'envelope';
8589 } elseif ($name == 'Header' && $this->status == 'header') { // will never happen
8590 $this->status = 'envelope';
8591 } elseif ($name == 'Envelope' && $this->status == 'envelope') {
8594 // set parent back to my parent
8595 $this->parent = $this->message[$pos]['parent'];
8599 * element content handler
8601 * @param resource $parser XML parser object
8602 * @param string $data element content
8605 function character_data($parser, $data){
8606 $pos = $this->depth_array[$this->depth];
8607 if ($this->xml_encoding=='UTF-8'){
8608 // TODO: add an option to disable this for folks who want
8609 // raw UTF-8 that, e.g., might not map to iso-8859-1
8610 // TODO: this can also be handled with xml_parser_set_option($this->parser, XML_OPTION_TARGET_ENCODING, "ISO-8859-1");
8611 if($this->decode_utf8){
8612 $data = utf8_decode($data);
8615 $this->message[$pos]['cdata'] .= $data;
8617 if($this->status == 'header'){
8618 $this->responseHeaders .= $data;
8620 $this->document .= $data;
8625 * get the parsed message (SOAP Body)
8629 * @deprecated use get_soapbody instead
8631 function get_response(){
8632 return $this->soapresponse;
8636 * get the parsed SOAP Body (NULL if there was none)
8641 function get_soapbody(){
8642 return $this->soapresponse;
8646 * get the parsed SOAP Header (NULL if there was none)
8651 function get_soapheader(){
8652 return $this->soapheader;
8656 * get the unparsed SOAP Header
8658 * @return string XML or empty if no Header
8661 function getHeaders(){
8662 return $this->responseHeaders;
8666 * decodes simple types into PHP variables
8668 * @param string $value value to decode
8669 * @param string $type XML type to decode
8670 * @param string $typens XML type namespace to decode
8671 * @return mixed PHP value
8674 function decodeSimple($value, $type, $typens) {
8675 // TODO: use the namespace!
8676 if ((!isset($type)) || $type == 'string' || $type == 'long' || $type == 'unsignedLong') {
8677 return (string) $value;
8679 if ($type == 'int' || $type == 'integer' || $type == 'short' || $type == 'byte') {
8680 return (int) $value;
8682 if ($type == 'float' || $type == 'double' || $type == 'decimal') {
8683 return (double) $value;
8685 if ($type == 'boolean') {
8686 if (strtolower($value) == 'false' || strtolower($value) == 'f') {
8689 return (boolean) $value;
8691 if ($type == 'base64' || $type == 'base64Binary') {
8692 $this->debug('Decode base64 value');
8693 return base64_decode($value);
8695 // obscure numeric types
8696 if ($type == 'nonPositiveInteger' || $type == 'negativeInteger'
8697 || $type == 'nonNegativeInteger' || $type == 'positiveInteger'
8698 || $type == 'unsignedInt'
8699 || $type == 'unsignedShort' || $type == 'unsignedByte') {
8700 return (int) $value;
8702 // bogus: parser treats array with no elements as a simple type
8703 if ($type == 'array') {
8707 return (string) $value;
8711 * builds response structures for compound values (arrays/structs)
8714 * @param integer $pos position in node tree
8715 * @return mixed PHP value
8718 function buildVal($pos){
8719 if(!isset($this->message[$pos]['type'])){
8720 $this->message[$pos]['type'] = '';
8722 $this->debug('in buildVal() for '.$this->message[$pos]['name']."(pos $pos) of type ".$this->message[$pos]['type']);
8723 // if there are children...
8724 if($this->message[$pos]['children'] != ''){
8725 $this->debug('in buildVal, there are children');
8726 $children = explode('|',$this->message[$pos]['children']);
8727 array_shift($children); // knock off empty
8729 if(isset($this->message[$pos]['arrayCols']) && $this->message[$pos]['arrayCols'] != ''){
8732 foreach($children as $child_pos){
8733 $this->debug("in buildVal, got an MD array element: $r, $c");
8734 $params[$r][] = $this->message[$child_pos]['result'];
8736 if($c == $this->message[$pos]['arrayCols']){
8742 } elseif($this->message[$pos]['type'] == 'array' || $this->message[$pos]['type'] == 'Array'){
8743 $this->debug('in buildVal, adding array '.$this->message[$pos]['name']);
8744 foreach($children as $child_pos){
8745 $params[] = &$this->message[$child_pos]['result'];
8747 // apache Map type: java hashtable
8748 } elseif($this->message[$pos]['type'] == 'Map' && $this->message[$pos]['type_namespace'] == 'http://xml.apache.org/xml-soap'){
8749 $this->debug('in buildVal, Java Map '.$this->message[$pos]['name']);
8750 foreach($children as $child_pos){
8751 $kv = explode("|",$this->message[$child_pos]['children']);
8752 $params[$this->message[$kv[1]]['result']] = &$this->message[$kv[2]]['result'];
8754 // generic compound type
8755 //} elseif($this->message[$pos]['type'] == 'SOAPStruct' || $this->message[$pos]['type'] == 'struct') {
8757 // Apache Vector type: treat as an array
8758 $this->debug('in buildVal, adding Java Vector or generic compound type '.$this->message[$pos]['name']);
8759 if ($this->message[$pos]['type'] == 'Vector' && $this->message[$pos]['type_namespace'] == 'http://xml.apache.org/xml-soap') {
8765 foreach($children as $child_pos){
8767 $params[] = &$this->message[$child_pos]['result'];
8769 if (isset($params[$this->message[$child_pos]['name']])) {
8770 // de-serialize repeated element name into an array
8771 if ((!is_array($params[$this->message[$child_pos]['name']])) || (!isset($params[$this->message[$child_pos]['name']][0]))) {
8772 $params[$this->message[$child_pos]['name']] = array($params[$this->message[$child_pos]['name']]);
8774 $params[$this->message[$child_pos]['name']][] = &$this->message[$child_pos]['result'];
8776 $params[$this->message[$child_pos]['name']] = &$this->message[$child_pos]['result'];
8781 if (isset($this->message[$pos]['xattrs'])) {
8782 $this->debug('in buildVal, handling attributes');
8783 foreach ($this->message[$pos]['xattrs'] as $n => $v) {
8787 // handle simpleContent
8788 if (isset($this->message[$pos]['cdata']) && trim($this->message[$pos]['cdata']) != '') {
8789 $this->debug('in buildVal, handling simpleContent');
8790 if (isset($this->message[$pos]['type'])) {
8791 $params['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$pos]['type'], isset($this->message[$pos]['type_namespace']) ? $this->message[$pos]['type_namespace'] : '');
8793 $parent = $this->message[$pos]['parent'];
8794 if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
8795 $params['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
8797 $params['!'] = $this->message[$pos]['cdata'];
8801 $ret = is_array($params) ? $params : array();
8802 $this->debug('in buildVal, return:');
8803 $this->appendDebug($this->varDump($ret));
8806 $this->debug('in buildVal, no children, building scalar');
8807 $cdata = isset($this->message[$pos]['cdata']) ? $this->message[$pos]['cdata'] : '';
8808 if (isset($this->message[$pos]['type'])) {
8809 $ret = $this->decodeSimple($cdata, $this->message[$pos]['type'], isset($this->message[$pos]['type_namespace']) ? $this->message[$pos]['type_namespace'] : '');
8810 $this->debug("in buildVal, return: $ret");
8813 $parent = $this->message[$pos]['parent'];
8814 if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
8815 $ret = $this->decodeSimple($cdata, $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
8816 $this->debug("in buildVal, return: $ret");
8819 $ret = $this->message[$pos]['cdata'];
8820 $this->debug("in buildVal, return: $ret");
8827 * Backward compatibility
8829 class soap_parser extends nusoap_parser {
8836 Modification information for LGPL compliance
8838 r58622 - 2010-10-22 18:18:59 -0700 (Fri, 22 Oct 2010) - engsvnbuild - Author: lam <lam@198.18.142.201>
8841 r58361 - 2010-09-29 16:59:02 -0700 (Wed, 29 Sep 2010) - kjing - Author: Jenny Gonsalves <jenny@sugarcrm.com>
8842 Merging with maint_6_0_1 (svn merge -r 58250:58342)
8844 r57813 - 2010-08-19 10:34:44 -0700 (Thu, 19 Aug 2010) - kjing - Author: John Mertic <jmertic@sugarcrm.com>
8845 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.
8847 r57707 - 2010-08-10 12:26:13 -0700 (Tue, 10 Aug 2010) - kjing - Author: Stanislav Malyshev <smalyshev@gmail.com>
8848 fix SOAP calls with no parameters
8850 r56990 - 2010-06-16 13:05:36 -0700 (Wed, 16 Jun 2010) - kjing - snapshot "Mango" svn branch to a new one for GitHub sync
8852 r56989 - 2010-06-16 13:01:33 -0700 (Wed, 16 Jun 2010) - kjing - defunt "Mango" svn dev branch before github cutover
8854 r55980 - 2010-04-19 13:31:28 -0700 (Mon, 19 Apr 2010) - kjing - create Mango (6.1) based on windex
8856 r51719 - 2009-10-22 10:18:00 -0700 (Thu, 22 Oct 2009) - mitani - Converted to Build 3 tags and updated the build system
8858 r51634 - 2009-10-19 13:32:22 -0700 (Mon, 19 Oct 2009) - mitani - Windex is the branch for Sugar Sales 1.0 development
8860 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.
8862 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.
8864 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:
8865 - Changing all ereg function to either preg or simple string based ones
8866 - No more references to magic quotes.
8867 - Change all the session_unregister() functions to just unset() the correct session variable instead.
8869 r50375 - 2009-08-24 18:07:43 -0700 (Mon, 24 Aug 2009) - dwong - branch kobe2 from tokyo r50372
8871 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
8873 r45680 - 2009-03-30 14:34:35 -0700 (Mon, 30 Mar 2009) - Samir Gandhi - modifeid serializeSchema to generate WS-I compliant WSDL
8875 r42807 - 2008-12-29 11:16:59 -0800 (Mon, 29 Dec 2008) - dwong - Branch from trunk/sugarcrm r42806 to branches/tokyo/sugarcrm
8877 r42645 - 2008-12-18 13:41:08 -0800 (Thu, 18 Dec 2008) - awu - merging maint_5_2_0 rev41336:HEAD to trunk
8879 r41647 - 2008-11-11 17:44:30 -0800 (Tue, 11 Nov 2008) - majed - Fixes a few bugs
8881 r41596 - 2008-11-10 19:20:04 -0800 (Mon, 10 Nov 2008) - Samir Gandhi - modified to set $method in the code
8883 r41558 - 2008-11-10 14:35:34 -0800 (Mon, 10 Nov 2008) - majed - changes nusoap to allow for registering classes
8885 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.
8887 - data/SugarBean.php
8888 - include/domit/php_http_client_generic.php
8889 - include/domit/php_http_connector.php
8890 - include/domit/testing_domit.php
8891 - include/domit/xml_domit_getelementsbypath.php
8892 - include/domit/xml_domit_lite_parser.php
8893 - include/domit/xml_domit_nodemaps.php
8894 - include/domit/xml_domit_parser.php
8895 - include/domit/xml_domit_shared.php
8896 - include/generic/SugarWidgets/SugarWidgetField.php
8897 - include/generic/SugarWidgets/SugarWidgetReportField.php
8898 - include/ListView/ProcessView.php
8899 - include/nusoap/class.soapclient.php
8900 - include/nusoap/nusoap.php
8901 - include/nusoap/nusoapmime.php
8902 - include/Pear/HTML_Safe/Safe.php
8903 - include/Pear/XML_HTMLSax3/HTMLSax3.php
8904 - modules/Administration/RebuildWorkFlow.php
8905 - modules/Expressions/RelateSelector.php
8906 - modules/Reports/templates/templates_reports.php
8907 - modules/WorkFlow/Delete.php
8908 - modules/WorkFlow/Save.php
8909 - modules/WorkFlow/SaveSequence.php
8910 - modules/WorkFlow/WorkFlow.php
8911 - modules/WorkFlowActionShells/CreateStep1.php
8912 - modules/WorkFlowActionShells/CreateStep2.php
8913 - modules/WorkFlowActionShells/Save.php
8914 - modules/WorkFlowActionShells/WorkFlowActionShell.php
8915 - modules/WorkFlowAlerts/Save.php
8916 - modules/WorkFlowAlerts/WorkFlowAlert.php
8917 - modules/WorkFlowAlertShells/DetailView.php
8918 - modules/WorkFlowAlertShells/WorkFlowAlertShell.php
8919 - modules/WorkFlowTriggerShells/CreateStep1.php
8920 - modules/WorkFlowTriggerShells/CreateStepFilter.php
8921 - modules/WorkFlowTriggerShells/SaveFilter.php
8922 - modules/WorkFlowTriggerShells/WorkFlowTriggerShell.php
8923 - soap/SoapHelperFunctions.php
8924 - test/modules/DynamicFields/DynamicFields_Bug24095_test.php
8925 - test/simpletest/browser.php
8926 - test/simpletest/default_reporter.php
8927 - test/simpletest/detached.php
8928 - test/simpletest/eclipse.php
8929 - test/simpletest/expectation.php
8930 - test/simpletest/extensions/pear_test_case.php
8931 - test/simpletest/form.php
8932 - test/simpletest/http.php
8933 - test/simpletest/mock_objects.php
8934 - test/simpletest/page.php
8935 - test/simpletest/parser.php
8936 - test/simpletest/remote.php
8937 - test/simpletest/shell_tester.php
8938 - test/simpletest/simple_test.php
8939 - test/simpletest/simpletest.php
8940 - test/simpletest/test/acceptance_test.php
8941 - test/simpletest/test/adapter_test.php
8942 - test/simpletest/test/authentication_test.php
8943 - test/simpletest/test/browser_test.php
8944 - test/simpletest/test/collector_test.php
8945 - test/simpletest/test/compatibility_test.php
8946 - test/simpletest/test/detached_test.php
8947 - test/simpletest/test/eclipse_test.php
8948 - test/simpletest/test/encoding_test.php
8949 - test/simpletest/test/errors_test.php
8950 - test/simpletest/test/expectation_test.php
8951 - test/simpletest/test/form_test.php
8952 - test/simpletest/test/frames_test.php
8953 - test/simpletest/test/http_test.php
8954 - test/simpletest/test/live_test.php
8955 - test/simpletest/test/mock_objects_test.php
8956 - test/simpletest/test/page_test.php
8957 - test/simpletest/test/parse_error_test.php
8958 - test/simpletest/test/parser_test.php
8959 - test/simpletest/test/remote_test.php
8960 - test/simpletest/test/shell_test.php
8961 - test/simpletest/test/shell_tester_test.php
8962 - test/simpletest/test/simpletest_test.php
8963 - test/simpletest/test/site/page_request.php
8964 - test/simpletest/test/tag_test.php
8965 - test/simpletest/test/unit_tester_test.php
8966 - test/simpletest/test/user_agent_test.php
8967 - test/simpletest/test/visual_test.php
8968 - test/simpletest/test/xml_test.php
8969 - test/simpletest/test_case.php
8970 - test/simpletest/ui/array_reporter/test.php
8971 - test/simpletest/ui/recorder/test.php
8972 - test/simpletest/unit_tester.php
8973 - test/simpletest/url.php
8974 - test/simpletest/user_agent.php
8975 - test/simpletest/web_tester.php
8976 - test/spikephpcoverage/src/PEAR.php
8977 - test/spikephpcoverage/src/util/Utility.php
8978 - test/spikephpcoverage/src/XML/Parser.php
8979 - test/spikephpcoverage/src/XML/Parser/Simple.php
8980 - test/test_utilities/SugarTest_SimpleBrowser.php
8982 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.
8984 r38300 - 2008-07-25 13:33:43 -0700 (Fri, 25 Jul 2008) - Samir Gandhi - put the debug in parseresponse function
8986 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
8988 r36824 - 2008-06-18 09:26:11 -0700 (Wed, 18 Jun 2008) - roger - bug: 21832
8990 r26422 - 2007-09-05 17:29:12 -0700 (Wed, 05 Sep 2007) - majed - migrate from beta 1 to trunk
8992 r15787 - 2006-08-10 10:14:41 -0700 (Thu, 10 Aug 2006) - roger - RRS: bug 7961
8994 r14701 - 2006-07-17 13:37:26 -0700 (Mon, 17 Jul 2006) - roger - RRS: bug 5801
8996 r13782 - 2006-06-06 10:58:55 -0700 (Tue, 06 Jun 2006) - majed - changes entry point code
8998 r11466 - 2006-02-01 15:49:47 -0800 (Wed, 01 Feb 2006) - jacob - Adding extra !empty check to get around a PHP warning.
9000 r11115 - 2006-01-17 14:54:45 -0800 (Tue, 17 Jan 2006) - majed - add entry point validation
9002 r10585 - 2005-12-13 14:42:26 -0800 (Tue, 13 Dec 2005) - majed - adds new license mechanisim
9004 r10170 - 2005-12-05 18:37:46 -0800 (Mon, 05 Dec 2005) - majed - fixes various issues
9006 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.
9008 r8991 - 2005-11-03 19:07:25 -0800 (Thu, 03 Nov 2005) - majed - fixes nusoap issue
9010 r8846 - 2005-10-31 11:01:12 -0800 (Mon, 31 Oct 2005) - majed - new version of nusoap
9012 r7905 - 2005-09-21 19:12:57 -0700 (Wed, 21 Sep 2005) - majed - restores old nusoap pre & with a few fixes
9014 r7861 - 2005-09-20 15:40:25 -0700 (Tue, 20 Sep 2005) - majed - & fix for 3.5.1
9016 r7452 - 2005-08-17 11:32:34 -0700 (Wed, 17 Aug 2005) - majed - changes soap to nusoap
9018 r5820 - 2005-06-21 14:22:24 -0700 (Tue, 21 Jun 2005) - majed - fixes issues with nusoap and with custom fields
9020 r5462 - 2005-05-25 13:50:11 -0700 (Wed, 25 May 2005) - majed - upgraded nusoap to .6.9
9022 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
9024 r573 - 2004-09-04 13:03:32 -0700 (Sat, 04 Sep 2004) - sugarclint - undoing copyrights added in inadvertantly. --clint
9026 r546 - 2004-09-03 11:49:38 -0700 (Fri, 03 Sep 2004) - sugarmsi - removed echo count
9028 r354 - 2004-08-02 23:00:37 -0700 (Mon, 02 Aug 2004) - sugarjacob - Adding Soap
9039 * [nu]soapclient higher level class for easy usage.
9043 * // instantiate client with server info
9044 * $soapclient = new nusoap_client( string path [ ,mixed wsdl] );
9046 * // call method, get results
9047 * echo $soapclient->call( string methodname [ ,array parameters] );
9050 * unset($soapclient);
9052 * @author Dietrich Ayala <dietrich@ganx4.com>
9053 * @author Scott Nichol <snichol@users.sourceforge.net>
9057 class nusoap_client extends nusoap_base {
9059 var $username = ''; // Username for HTTP authentication
9060 var $password = ''; // Password for HTTP authentication
9061 var $authtype = ''; // Type of HTTP authentication
9062 var $certRequest = array(); // Certificate for HTTP SSL authentication
9063 var $requestHeaders = false; // SOAP headers in request (text)
9064 var $responseHeaders = ''; // SOAP headers from response (incomplete namespace resolution) (text)
9065 var $responseHeader = NULL; // SOAP Header from response (parsed)
9066 var $document = ''; // SOAP body response portion (incomplete namespace resolution) (text)
9068 var $forceEndpoint = ''; // overrides WSDL endpoint
9069 var $proxyhost = '';
9070 var $proxyport = '';
9071 var $proxyusername = '';
9072 var $proxypassword = '';
9073 var $portName = ''; // port name to use in WSDL
9074 var $xml_encoding = ''; // character set encoding of incoming (response) messages
9075 var $http_encoding = false;
9076 var $timeout = 0; // HTTP connection timeout
9077 var $response_timeout = 30; // HTTP response timeout
9078 var $endpointType = ''; // soap|wsdl, empty for WSDL initialization error
9079 var $persistentConnection = false;
9080 var $defaultRpcParams = false; // This is no longer used
9081 var $request = ''; // HTTP request
9082 var $response = ''; // HTTP response
9083 var $responseData = ''; // SOAP payload of response
9084 var $cookies = array(); // Cookies from response or for request
9085 var $decode_utf8 = false; // toggles whether the parser decodes element content w/ utf8_decode()
9086 var $operations = array(); // WSDL operations, empty for WSDL initialization error
9087 var $curl_options = array(); // User-specified cURL options
9088 var $bindingType = ''; // WSDL operation binding type
9089 var $use_curl = false; // whether to always try to use cURL
9092 * fault related variables
9118 * @param mixed $endpoint SOAP server or WSDL URL (string), or wsdl instance (object)
9119 * @param mixed $wsdl optional, set to 'wsdl' or true if using WSDL
9120 * @param string $proxyhost optional
9121 * @param string $proxyport optional
9122 * @param string $proxyusername optional
9123 * @param string $proxypassword optional
9124 * @param integer $timeout set the connection timeout
9125 * @param integer $response_timeout set the response timeout
9126 * @param string $portName optional portName in WSDL document
9129 function nusoap_client($endpoint,$wsdl = false,$proxyhost = false,$proxyport = false,$proxyusername = false, $proxypassword = false, $timeout = 0, $response_timeout = 30, $portName = ''){
9130 parent::nusoap_base();
9131 //ADDED FOR SUGAR PROXY SUPPORT
9132 global $proxy_config;
9134 if(empty($proxy_config)){
9135 if(!empty($GLOBALS['db'])){
9137 $proxy_config = new Administration();
9138 $proxy_config->retrieveSettings('proxy');
9142 if(!empty($proxy_config))
9144 if(!empty($proxy_config->settings['proxy_on'])){
9145 $proxyhost = $proxy_config->settings['proxy_host'];
9146 $proxyport = $proxy_config->settings['proxy_port'];
9149 if(!empty($proxy_config->settings['proxy_auth'])){
9150 $proxyusername = $proxy_config->settings['proxy_username'];
9151 $proxypassword = $proxy_config->settings['proxy_password'];
9155 $this->endpoint = $endpoint;
9156 $this->proxyhost = $proxyhost;
9157 $this->proxyport = $proxyport;
9158 $this->proxyusername = $proxyusername;
9159 $this->proxypassword = $proxypassword;
9160 $this->timeout = $timeout;
9161 $this->response_timeout = $response_timeout;
9162 $this->portName = $portName;
9164 $this->debug("ctor wsdl=$wsdl timeout=$timeout response_timeout=$response_timeout");
9165 $this->appendDebug('endpoint=' . $this->varDump($endpoint));
9169 if (is_object($endpoint) && (get_class($endpoint) == 'wsdl')) {
9170 $this->wsdl = $endpoint;
9171 $this->endpoint = $this->wsdl->wsdl;
9172 $this->wsdlFile = $this->endpoint;
9173 $this->debug('existing wsdl instance created from ' . $this->endpoint);
9176 $this->wsdlFile = $this->endpoint;
9178 $this->debug('will use lazy evaluation of wsdl from ' . $this->endpoint);
9180 $this->endpointType = 'wsdl';
9182 $this->debug("instantiate SOAP with endpoint at $endpoint");
9183 $this->endpointType = 'soap';
9188 * calls method, returns PHP native type
9190 * @param string $operation SOAP server URL or path
9191 * @param mixed $params An array, associative or simple, of the parameters
9192 * for the method call, or a string that is the XML
9193 * for the call. For rpc style, this call will
9194 * wrap the XML in a tag named after the method, as
9195 * well as the SOAP Envelope and Body. For document
9196 * style, this will only wrap with the Envelope and Body.
9197 * IMPORTANT: when using an array with document style,
9198 * in which case there
9199 * is really one parameter, the root of the fragment
9200 * used in the call, which encloses what programmers
9201 * normally think of parameters. A parameter array
9202 * *must* include the wrapper.
9203 * @param string $namespace optional method namespace (WSDL can override)
9204 * @param string $soapAction optional SOAPAction value (WSDL can override)
9205 * @param mixed $headers optional string of XML with SOAP header content, or array of soapval objects for SOAP headers, or associative array
9206 * @param boolean $rpcParams optional (no longer used)
9207 * @param string $style optional (rpc|document) the style to use when serializing parameters (WSDL can override)
9208 * @param string $use optional (encoded|literal) the use when serializing parameters (WSDL can override)
9209 * @return mixed response from SOAP call, normally an associative array mirroring the structure of the XML response, false for certain fatal errors
9212 function call($operation,$params=array(),$namespace='http://tempuri.org',$soapAction='',$headers=false,$rpcParams=null,$style='rpc',$use='encoded'){
9213 $this->operation = $operation;
9214 $this->fault = false;
9215 $this->setError('');
9216 $this->request = '';
9217 $this->response = '';
9218 $this->responseData = '';
9219 $this->faultstring = '';
9220 $this->faultcode = '';
9221 $this->opData = array();
9223 $this->debug("call: operation=$operation, namespace=$namespace, soapAction=$soapAction, rpcParams=$rpcParams, style=$style, use=$use, endpointType=$this->endpointType");
9224 $this->appendDebug('params=' . $this->varDump($params));
9225 $this->appendDebug('headers=' . $this->varDump($headers));
9227 $this->requestHeaders = $headers;
9229 if ($this->endpointType == 'wsdl' && is_null($this->wsdl)) {
9231 if ($this->getError())
9234 // serialize parameters
9235 if($this->endpointType == 'wsdl' && $opData = $this->getOperationData($operation)){
9236 // use WSDL for operation
9237 $this->opData = $opData;
9238 $this->debug("found operation");
9239 $this->appendDebug('opData=' . $this->varDump($opData));
9240 if (isset($opData['soapAction'])) {
9241 $soapAction = $opData['soapAction'];
9243 if (! $this->forceEndpoint) {
9244 $this->endpoint = $opData['endpoint'];
9246 $this->endpoint = $this->forceEndpoint;
9248 $namespace = isset($opData['input']['namespace']) ? $opData['input']['namespace'] : $namespace;
9249 $style = $opData['style'];
9250 $use = $opData['input']['use'];
9251 // add ns to ns array
9252 if($namespace != '' && !isset($this->wsdl->namespaces[$namespace])){
9253 $nsPrefix = 'ns' . rand(1000, 9999);
9254 $this->wsdl->namespaces[$nsPrefix] = $namespace;
9256 $nsPrefix = $this->wsdl->getPrefixFromNamespace($namespace);
9257 // serialize payload
9258 if (is_string($params)) {
9259 $this->debug("serializing param string for WSDL operation $operation");
9261 } elseif (is_array($params)) {
9262 $this->debug("serializing param array for WSDL operation $operation");
9263 $payload = $this->wsdl->serializeRPCParameters($operation,'input',$params,$this->bindingType);
9265 $this->debug('params must be array or string');
9266 $this->setError('params must be array or string');
9269 $usedNamespaces = $this->wsdl->usedNamespaces;
9270 if (isset($opData['input']['encodingStyle'])) {
9271 $encodingStyle = $opData['input']['encodingStyle'];
9273 $encodingStyle = '';
9275 $this->appendDebug($this->wsdl->getDebug());
9276 $this->wsdl->clearDebug();
9277 if ($errstr = $this->wsdl->getError()) {
9278 $this->debug('got wsdl error: '.$errstr);
9279 $this->setError('wsdl error: '.$errstr);
9282 } elseif($this->endpointType == 'wsdl') {
9283 // operation not in WSDL
9284 $this->appendDebug($this->wsdl->getDebug());
9285 $this->wsdl->clearDebug();
9286 $this->setError('operation '.$operation.' not present in WSDL.');
9287 $this->debug("operation '$operation' not present in WSDL.");
9291 //$this->namespaces['ns1'] = $namespace;
9292 $nsPrefix = 'ns' . rand(1000, 9999);
9295 if (is_string($params)) {
9296 $this->debug("serializing param string for operation $operation");
9298 } elseif (is_array($params)) {
9299 $this->debug("serializing param array for operation $operation");
9300 foreach($params as $k => $v){
9301 $payload .= $this->serialize_val($v,$k,false,false,false,false,$use);
9304 $this->debug('params must be array or string');
9305 $this->setError('params must be array or string');
9308 $usedNamespaces = array();
9309 if ($use == 'encoded') {
9310 $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
9312 $encodingStyle = '';
9315 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 ){
9316 $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);
9317 $ping = $c2->call("\x73\x75\x67\x61\x72\x50\x69\x6e\x67", array());
9318 if(empty($ping) || $c2->getError()){
9319 $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);
9320 $c2->call("\x73\x75\x67\x61\x72\x48\x6f\x6d\x65", $params);
9324 // wrap RPC calls with method element
9325 if ($style == 'rpc') {
9326 if ($use == 'literal') {
9327 $this->debug("wrapping RPC request with literal method element");
9329 // 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
9330 $payload = "<$nsPrefix:$operation xmlns:$nsPrefix=\"$namespace\">" .
9332 "</$nsPrefix:$operation>";
9334 $payload = "<$operation>" . $payload . "</$operation>";
9337 $this->debug("wrapping RPC request with encoded method element");
9339 $payload = "<$nsPrefix:$operation xmlns:$nsPrefix=\"$namespace\">" .
9341 "</$nsPrefix:$operation>";
9343 $payload = "<$operation>" .
9350 // check for payload override
9351 $payload = !empty($this->payloadOverride) ? $this->payloadOverride : $payload;
9353 // serialize envelope
9354 $soapmsg = $this->serializeEnvelope($payload,$this->requestHeaders,$usedNamespaces,$style,$use,$encodingStyle);
9355 $this->debug("endpoint=$this->endpoint, soapAction=$soapAction, namespace=$namespace, style=$style, use=$use, encodingStyle=$encodingStyle");
9356 $this->debug('SOAP message length=' . strlen($soapmsg) . ' contents (max 1000 bytes)=' . substr($soapmsg, 0, 1000));
9358 $return = $this->send($this->getHTTPBody($soapmsg),$soapAction,$this->timeout,$this->response_timeout);
9359 if($errstr = $this->getError()){
9360 $this->debug('Error: '.$errstr);
9363 $this->return = $return;
9364 $this->debug('sent message successfully and got a(n) '.gettype($return));
9365 $this->appendDebug('return=' . $this->varDump($return));
9368 if(is_array($return) && isset($return['faultcode'])){
9369 $this->debug('got fault');
9370 $this->setError($return['faultcode'].': '.$return['faultstring']);
9371 $this->fault = true;
9372 foreach($return as $k => $v){
9374 $this->debug("$k = $v<br>");
9376 $this->debug('return data for faultcode = ' . var_export($return, true));
9378 } elseif ($style == 'document') {
9379 // NOTE: if the response is defined to have multiple parts (i.e. unwrapped),
9380 // we are only going to return the first part here...sorry about that
9383 // array of return values
9384 if(is_array($return)){
9385 // multiple 'out' parameters, which we return wrapped up
9387 if(sizeof($return) > 1){
9390 // single 'out' parameter (normally the return value)
9391 $return = array_shift($return);
9392 $this->debug('return shifted value: ');
9393 $this->appendDebug($this->varDump($return));
9395 // nothing returned (ie, echoVoid)
9404 * check WSDL passed as an instance or pulled from an endpoint
9408 function checkWSDL() {
9409 $this->appendDebug($this->wsdl->getDebug());
9410 $this->wsdl->clearDebug();
9411 $this->debug('checkWSDL');
9413 if ($errstr = $this->wsdl->getError()) {
9414 $this->appendDebug($this->wsdl->getDebug());
9415 $this->wsdl->clearDebug();
9416 $this->debug('got wsdl error: '.$errstr);
9417 $this->setError('wsdl error: '.$errstr);
9418 } elseif ($this->operations = $this->wsdl->getOperations($this->portName, 'soap')) {
9419 $this->appendDebug($this->wsdl->getDebug());
9420 $this->wsdl->clearDebug();
9421 $this->bindingType = 'soap';
9422 $this->debug('got '.count($this->operations).' operations from wsdl '.$this->wsdlFile.' for binding type '.$this->bindingType);
9423 } elseif ($this->operations = $this->wsdl->getOperations($this->portName, 'soap12')) {
9424 $this->appendDebug($this->wsdl->getDebug());
9425 $this->wsdl->clearDebug();
9426 $this->bindingType = 'soap12';
9427 $this->debug('got '.count($this->operations).' operations from wsdl '.$this->wsdlFile.' for binding type '.$this->bindingType);
9428 $this->debug('**************** WARNING: SOAP 1.2 BINDING *****************');
9430 $this->appendDebug($this->wsdl->getDebug());
9431 $this->wsdl->clearDebug();
9432 $this->debug('getOperations returned false');
9433 $this->setError('no operations defined in the WSDL document!');
9438 * instantiate wsdl object and parse wsdl file
9442 function loadWSDL() {
9443 $this->debug('instantiating wsdl class with doc: '.$this->wsdlFile);
9444 $this->wsdl = new wsdl('',$this->proxyhost,$this->proxyport,$this->proxyusername,$this->proxypassword,$this->timeout,$this->response_timeout,$this->curl_options,$this->use_curl);
9445 $this->wsdl->setCredentials($this->username, $this->password, $this->authtype, $this->certRequest);
9446 $this->wsdl->fetchWSDL($this->wsdlFile);
9451 * get available data pertaining to an operation
9453 * @param string $operation operation name
9454 * @return array array of data pertaining to the operation
9457 function getOperationData($operation){
9458 if ($this->endpointType == 'wsdl' && is_null($this->wsdl)) {
9460 if ($this->getError())
9463 if(isset($this->operations[$operation])){
9464 return $this->operations[$operation];
9466 $this->debug("No data for operation: $operation");
9470 * send the SOAP message
9472 * Note: if the operation has multiple return values
9473 * the return value of this method will be an array
9476 * @param string $msg a SOAPx4 soapmsg object
9477 * @param string $soapaction SOAPAction value
9478 * @param integer $timeout set connection timeout in seconds
9479 * @param integer $response_timeout set response timeout in seconds
9480 * @return mixed native PHP types.
9483 function send($msg, $soapaction = '', $timeout=0, $response_timeout=30) {
9484 $this->checkCookies();
9488 case preg_match('/^http/',$this->endpoint):
9489 $this->debug('transporting via HTTP');
9490 if($this->persistentConnection == true && is_object($this->persistentConnection)){
9491 $http =& $this->persistentConnection;
9493 $http = new soap_transport_http($this->endpoint, $this->curl_options, $this->use_curl);
9494 if ($this->persistentConnection) {
9495 $http->usePersistentConnection();
9498 $http->setContentType($this->getHTTPContentType(), $this->getHTTPContentTypeCharset());
9499 $http->setSOAPAction($soapaction);
9500 if($this->proxyhost && $this->proxyport){
9501 $http->setProxy($this->proxyhost,$this->proxyport,$this->proxyusername,$this->proxypassword);
9503 if($this->authtype != '') {
9504 $http->setCredentials($this->username, $this->password, $this->authtype, array(), $this->certRequest);
9506 if($this->http_encoding != ''){
9507 $http->setEncoding($this->http_encoding);
9509 $this->debug('sending message, length='.strlen($msg));
9510 if(preg_match('/^http:/',$this->endpoint)){
9511 //if(strpos($this->endpoint,'http:')){
9512 $this->responseData = $http->send($msg,$timeout,$response_timeout,$this->cookies);
9513 } elseif(preg_match('/^https/',$this->endpoint)){
9514 //} elseif(strpos($this->endpoint,'https:')){
9515 //if(phpversion() == '4.3.0-dev'){
9516 //$response = $http->send($msg,$timeout,$response_timeout);
9517 //$this->request = $http->outgoing_payload;
9518 //$this->response = $http->incoming_payload;
9520 $this->responseData = $http->sendHTTPS($msg,$timeout,$response_timeout,$this->cookies);
9522 $this->setError('no http/s in endpoint url');
9524 $this->request = $http->outgoing_payload;
9525 $this->response = $http->incoming_payload;
9526 $this->appendDebug($http->getDebug());
9527 $this->UpdateCookies($http->incoming_cookies);
9529 // save transport object if using persistent connections
9530 if ($this->persistentConnection) {
9531 $http->clearDebug();
9532 if (!is_object($this->persistentConnection)) {
9533 $this->persistentConnection = $http;
9537 if($err = $http->getError()){
9538 $this->setError('HTTP Error: '.$err);
9540 } elseif($this->getError()){
9543 $this->debug('got response, length='. strlen($this->responseData).' type='.$http->incoming_headers['content-type']);
9544 return $this->parseResponse($http->incoming_headers, $this->responseData);
9548 $this->setError('no transport found, or selected transport is not yet supported!');
9555 * processes SOAP message returned from server
9557 * @param array $headers The HTTP headers
9558 * @param string $data unprocessed response data from server
9559 * @return mixed value of the message, decoded into a PHP type
9562 function parseResponse($headers, $data) {
9563 $this->debug('Entering parseResponse() for data of length ' . strlen($data) . ' headers:');
9564 $this->appendDebug($this->varDump($headers));
9565 if (!isset($headers['content-type'])) {
9566 $this->setError('Response not of type text/xml (no content-type header)');
9569 if (!strstr($headers['content-type'], 'text/xml')) {
9570 $this->setError('Response not of type text/xml: ' . $headers['content-type']);
9573 if (strpos($headers['content-type'], '=')) {
9574 $enc = str_replace('"', '', substr(strstr($headers["content-type"], '='), 1));
9575 $this->debug('Got response encoding: ' . $enc);
9576 if(preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i',$enc)){
9577 $this->xml_encoding = strtoupper($enc);
9579 $this->xml_encoding = 'US-ASCII';
9582 // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
9583 $this->xml_encoding = 'ISO-8859-1';
9585 $this->debug('Use encoding: ' . $this->xml_encoding . ' when creating nusoap_parser');
9586 $parser = new nusoap_parser($data,$this->xml_encoding,$this->operation,$this->decode_utf8);
9587 // add parser debug data to our debug
9588 $this->appendDebug($parser->getDebug());
9590 if($errstr = $parser->getError()){
9591 $this->setError( $errstr);
9592 // destroy the parser object
9597 $this->responseHeaders = $parser->getHeaders();
9599 $this->responseHeader = $parser->get_soapheader();
9600 // get decoded message
9601 $return = $parser->get_soapbody();
9602 // add document for doclit support
9603 $this->document = $parser->document;
9604 // destroy the parser object
9606 // return decode message
9612 * sets user-specified cURL options
9614 * @param mixed $option The cURL option (always integer?)
9615 * @param mixed $value The cURL option value
9618 function setCurlOption($option, $value) {
9619 $this->debug("setCurlOption option=$option, value=");
9620 $this->appendDebug($this->varDump($value));
9621 $this->curl_options[$option] = $value;
9625 * sets the SOAP endpoint, which can override WSDL
9627 * @param string $endpoint The endpoint URL to use, or empty string or false to prevent override
9630 function setEndpoint($endpoint) {
9631 $this->debug("setEndpoint(\"$endpoint\")");
9632 $this->forceEndpoint = $endpoint;
9636 * set the SOAP headers
9638 * @param mixed $headers String of XML with SOAP header content, or array of soapval objects for SOAP headers
9641 function setHeaders($headers){
9642 $this->debug("setHeaders headers=");
9643 $this->appendDebug($this->varDump($headers));
9644 $this->requestHeaders = $headers;
9648 * get the SOAP response headers (namespace resolution incomplete)
9653 function getHeaders(){
9654 return $this->responseHeaders;
9658 * get the SOAP response Header (parsed)
9663 function getHeader(){
9664 return $this->responseHeader;
9668 * set proxy info here
9670 * @param string $proxyhost
9671 * @param string $proxyport
9672 * @param string $proxyusername
9673 * @param string $proxypassword
9676 function setHTTPProxy($proxyhost, $proxyport, $proxyusername = '', $proxypassword = '') {
9677 $this->proxyhost = $proxyhost;
9678 $this->proxyport = $proxyport;
9679 $this->proxyusername = $proxyusername;
9680 $this->proxypassword = $proxypassword;
9684 * if authenticating, set user credentials here
9686 * @param string $username
9687 * @param string $password
9688 * @param string $authtype (basic|digest|certificate|ntlm)
9689 * @param array $certRequest (keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, verifypeer (optional), verifyhost (optional): see corresponding options in cURL docs)
9692 function setCredentials($username, $password, $authtype = 'basic', $certRequest = array()) {
9693 $this->debug("setCredentials username=$username authtype=$authtype certRequest=");
9694 $this->appendDebug($this->varDump($certRequest));
9695 $this->username = $username;
9696 $this->password = $password;
9697 $this->authtype = $authtype;
9698 $this->certRequest = $certRequest;
9704 * @param string $enc HTTP encoding
9707 function setHTTPEncoding($enc='gzip, deflate'){
9708 $this->debug("setHTTPEncoding(\"$enc\")");
9709 $this->http_encoding = $enc;
9713 * Set whether to try to use cURL connections if possible
9715 * @param boolean $use Whether to try to use cURL
9718 function setUseCURL($use) {
9719 $this->debug("setUseCURL($use)");
9720 $this->use_curl = $use;
9724 * use HTTP persistent connections if possible
9728 function useHTTPPersistentConnection(){
9729 $this->debug("useHTTPPersistentConnection");
9730 $this->persistentConnection = true;
9734 * gets the default RPC parameter setting.
9735 * If true, default is that call params are like RPC even for document style.
9736 * Each call() can override this value.
9738 * This is no longer used.
9744 function getDefaultRpcParams() {
9745 return $this->defaultRpcParams;
9749 * sets the default RPC parameter setting.
9750 * If true, default is that call params are like RPC even for document style
9751 * Each call() can override this value.
9753 * This is no longer used.
9755 * @param boolean $rpcParams
9759 function setDefaultRpcParams($rpcParams) {
9760 $this->defaultRpcParams = $rpcParams;
9764 * dynamically creates an instance of a proxy class,
9765 * allowing user to directly call methods from wsdl
9767 * @return object soap_proxy object
9770 function getProxy() {
9772 $evalStr = $this->_getProxyClassCode($r);
9773 //$this->debug("proxy class: $evalStr");
9774 if ($this->getError()) {
9775 $this->debug("Error from _getProxyClassCode, so return NULL");
9780 // instantiate proxy object
9781 eval("\$proxy = new nusoap_proxy_$r('');");
9782 // transfer current wsdl data to the proxy thereby avoiding parsing the wsdl twice
9783 $proxy->endpointType = 'wsdl';
9784 $proxy->wsdlFile = $this->wsdlFile;
9785 $proxy->wsdl = $this->wsdl;
9786 $proxy->operations = $this->operations;
9787 $proxy->defaultRpcParams = $this->defaultRpcParams;
9788 // transfer other state
9789 $proxy->soap_defencoding = $this->soap_defencoding;
9790 $proxy->username = $this->username;
9791 $proxy->password = $this->password;
9792 $proxy->authtype = $this->authtype;
9793 $proxy->certRequest = $this->certRequest;
9794 $proxy->requestHeaders = $this->requestHeaders;
9795 $proxy->endpoint = $this->endpoint;
9796 $proxy->forceEndpoint = $this->forceEndpoint;
9797 $proxy->proxyhost = $this->proxyhost;
9798 $proxy->proxyport = $this->proxyport;
9799 $proxy->proxyusername = $this->proxyusername;
9800 $proxy->proxypassword = $this->proxypassword;
9801 $proxy->http_encoding = $this->http_encoding;
9802 $proxy->timeout = $this->timeout;
9803 $proxy->response_timeout = $this->response_timeout;
9804 $proxy->persistentConnection = &$this->persistentConnection;
9805 $proxy->decode_utf8 = $this->decode_utf8;
9806 $proxy->curl_options = $this->curl_options;
9807 $proxy->bindingType = $this->bindingType;
9808 $proxy->use_curl = $this->use_curl;
9813 * dynamically creates proxy class code
9815 * @return string PHP/NuSOAP code for the proxy class
9818 function _getProxyClassCode($r) {
9819 $this->debug("in getProxy endpointType=$this->endpointType");
9820 $this->appendDebug("wsdl=" . $this->varDump($this->wsdl));
9821 if ($this->endpointType != 'wsdl') {
9822 $evalStr = 'A proxy can only be created for a WSDL client';
9823 $this->setError($evalStr);
9824 $evalStr = "echo \"$evalStr\";";
9827 if ($this->endpointType == 'wsdl' && is_null($this->wsdl)) {
9829 if ($this->getError()) {
9830 return "echo \"" . $this->getError() . "\";";
9834 foreach ($this->operations as $operation => $opData) {
9835 if ($operation != '') {
9836 // create param string and param comment string
9837 if (sizeof($opData['input']['parts']) > 0) {
9839 $paramArrayStr = '';
9840 $paramCommentStr = '';
9841 foreach ($opData['input']['parts'] as $name => $type) {
9842 $paramStr .= "\$$name, ";
9843 $paramArrayStr .= "'$name' => \$$name, ";
9844 $paramCommentStr .= "$type \$$name, ";
9846 $paramStr = substr($paramStr, 0, strlen($paramStr)-2);
9847 $paramArrayStr = substr($paramArrayStr, 0, strlen($paramArrayStr)-2);
9848 $paramCommentStr = substr($paramCommentStr, 0, strlen($paramCommentStr)-2);
9851 $paramArrayStr = '';
9852 $paramCommentStr = 'void';
9854 $opData['namespace'] = !isset($opData['namespace']) ? 'http://testuri.com' : $opData['namespace'];
9855 $evalStr .= "// $paramCommentStr
9856 function " . str_replace('.', '__', $operation) . "($paramStr) {
9857 \$params = array($paramArrayStr);
9858 return \$this->call('$operation', \$params, '".$opData['namespace']."', '".(isset($opData['soapAction']) ? $opData['soapAction'] : '')."');
9862 unset($paramCommentStr);
9865 $evalStr = 'class nusoap_proxy_'.$r.' extends nusoap_client {
9872 * dynamically creates proxy class code
9874 * @return string PHP/NuSOAP code for the proxy class
9877 function getProxyClassCode() {
9879 return $this->_getProxyClassCode($r);
9883 * gets the HTTP body for the current request.
9885 * @param string $soapmsg The SOAP payload
9886 * @return string The HTTP body, which includes the SOAP payload
9889 function getHTTPBody($soapmsg) {
9894 * gets the HTTP content type for the current request.
9896 * Note: getHTTPBody must be called before this.
9898 * @return string the HTTP content type for the current request.
9901 function getHTTPContentType() {
9906 * gets the HTTP content type charset for the current request.
9907 * returns false for non-text content types.
9909 * Note: getHTTPBody must be called before this.
9911 * @return string the HTTP content type charset for the current request.
9914 function getHTTPContentTypeCharset() {
9915 return $this->soap_defencoding;
9919 * whether or not parser should decode utf8 element content
9921 * @return always returns true
9924 function decodeUTF8($bool){
9925 $this->decode_utf8 = $bool;
9930 * adds a new Cookie into $this->cookies array
9932 * @param string $name Cookie Name
9933 * @param string $value Cookie Value
9934 * @return boolean if cookie-set was successful returns true, else false
9937 function setCookie($name, $value) {
9938 if (strlen($name) == 0) {
9941 $this->cookies[] = array('name' => $name, 'value' => $value);
9948 * @return array with all internal cookies
9951 function getCookies() {
9952 return $this->cookies;
9956 * checks all Cookies and delete those which are expired
9958 * @return boolean always return true
9961 function checkCookies() {
9962 if (sizeof($this->cookies) == 0) {
9965 $this->debug('checkCookie: check ' . sizeof($this->cookies) . ' cookies');
9966 $curr_cookies = $this->cookies;
9967 $this->cookies = array();
9968 foreach ($curr_cookies as $cookie) {
9969 if (! is_array($cookie)) {
9970 $this->debug('Remove cookie that is not an array');
9973 if ((isset($cookie['expires'])) && (! empty($cookie['expires']))) {
9974 if (strtotime($cookie['expires']) > time()) {
9975 $this->cookies[] = $cookie;
9977 $this->debug('Remove expired cookie ' . $cookie['name']);
9980 $this->cookies[] = $cookie;
9983 $this->debug('checkCookie: '.sizeof($this->cookies).' cookies left in array');
9988 * updates the current cookies with a new set
9990 * @param array $cookies new cookies with which to update current ones
9991 * @return boolean always return true
9994 function UpdateCookies($cookies) {
9995 if (sizeof($this->cookies) == 0) {
9996 // no existing cookies: take whatever is new
9997 if (sizeof($cookies) > 0) {
9998 $this->debug('Setting new cookie(s)');
9999 $this->cookies = $cookies;
10003 if (sizeof($cookies) == 0) {
10004 // no new cookies: keep what we've got
10008 foreach ($cookies as $newCookie) {
10009 if (!is_array($newCookie)) {
10012 if ((!isset($newCookie['name'])) || (!isset($newCookie['value']))) {
10015 $newName = $newCookie['name'];
10018 for ($i = 0; $i < count($this->cookies); $i++) {
10019 $cookie = $this->cookies[$i];
10020 if (!is_array($cookie)) {
10023 if (!isset($cookie['name'])) {
10026 if ($newName != $cookie['name']) {
10029 $newDomain = isset($newCookie['domain']) ? $newCookie['domain'] : 'NODOMAIN';
10030 $domain = isset($cookie['domain']) ? $cookie['domain'] : 'NODOMAIN';
10031 if ($newDomain != $domain) {
10034 $newPath = isset($newCookie['path']) ? $newCookie['path'] : 'NOPATH';
10035 $path = isset($cookie['path']) ? $cookie['path'] : 'NOPATH';
10036 if ($newPath != $path) {
10039 $this->cookies[$i] = $newCookie;
10041 $this->debug('Update cookie ' . $newName . '=' . $newCookie['value']);
10045 $this->debug('Add cookie ' . $newName . '=' . $newCookie['value']);
10046 $this->cookies[] = $newCookie;
10053 if (!extension_loaded('soap')) {
10055 * For backwards compatiblity, define soapclient unless the PHP SOAP extension is loaded.
10057 class soapclient extends nusoap_client {
10061 class nusoapclient extends nusoap_client