]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - include/nusoap/nusoap.php
Release 6.1.4
[Github/sugarcrm.git] / include / nusoap / nusoap.php
1 <?php
2
3 /*
4
5 Modification information for LGPL compliance
6
7 r58622 - 2010-10-22 18:18:59 -0700 (Fri, 22 Oct 2010) - engsvnbuild - Author: lam <lam@198.18.142.201>
8     bug 40066
9
10 r58361 - 2010-09-29 16:59:02 -0700 (Wed, 29 Sep 2010) - kjing - Author: Jenny Gonsalves <jenny@sugarcrm.com>
11     Merging with maint_6_0_1 (svn merge -r 58250:58342)
12
13 r57813 - 2010-08-19 10:34:44 -0700 (Thu, 19 Aug 2010) - kjing - Author: John Mertic <jmertic@sugarcrm.com>
14     Bug 39085 - When loading the opposite search panel via ajax on the ListViews, call the index action instead of the ListView action to avoid touching pre-MVC code by accident.
15
16 r57707 - 2010-08-10 12:26:13 -0700 (Tue, 10 Aug 2010) - kjing - Author: Stanislav Malyshev <smalyshev@gmail.com>
17     fix SOAP calls with no parameters
18
19 r56990 - 2010-06-16 13:05:36 -0700 (Wed, 16 Jun 2010) - kjing - snapshot "Mango" svn branch to a new one for GitHub sync
20
21 r56989 - 2010-06-16 13:01:33 -0700 (Wed, 16 Jun 2010) - kjing - defunt "Mango" svn dev branch before github cutover
22
23 r55980 - 2010-04-19 13:31:28 -0700 (Mon, 19 Apr 2010) - kjing - create Mango (6.1) based on windex
24
25 r51719 - 2009-10-22 10:18:00 -0700 (Thu, 22 Oct 2009) - mitani - Converted to Build 3  tags and updated the build system 
26
27 r51634 - 2009-10-19 13:32:22 -0700 (Mon, 19 Oct 2009) - mitani - Windex is the branch for Sugar Sales 1.0 development
28
29 r51508 - 2009-10-14 07:40:23 -0700 (Wed, 14 Oct 2009) - jmertic - More fallout fixes from the PHP 5.3 ereg to preg changes.
30
31 r51455 - 2009-10-13 07:56:48 -0700 (Tue, 13 Oct 2009) - jmertic - Bug 33202 - Enable install of SugarCRM on PHP 5.3.0, asserting that the minimum supported version is PHP 5.2.x.
32
33 r51443 - 2009-10-12 13:34:36 -0700 (Mon, 12 Oct 2009) - jmertic - Bug 33332 - Made application PHP 5.3 compliant with E_DEPRECATED warnings on by:
34 - Changing all ereg function to either preg or simple string based ones
35 - No more references to magic quotes.
36 - Change all the session_unregister() functions to just unset() the correct session variable instead.
37
38 r50375 - 2009-08-24 18:07:43 -0700 (Mon, 24 Aug 2009) - dwong - branch kobe2 from tokyo r50372
39
40 r45763 - 2009-04-01 12:16:18 -0700 (Wed, 01 Apr 2009) - majed - Removed half of the require_once and include_onces in the product that were redundant or could be handled easily by the auto loader
41
42 r45680 - 2009-03-30 14:34:35 -0700 (Mon, 30 Mar 2009) - Samir Gandhi - modifeid serializeSchema to generate WS-I compliant WSDL
43
44 r42807 - 2008-12-29 11:16:59 -0800 (Mon, 29 Dec 2008) - dwong - Branch from trunk/sugarcrm r42806 to branches/tokyo/sugarcrm
45
46 r42645 - 2008-12-18 13:41:08 -0800 (Thu, 18 Dec 2008) - awu - merging maint_5_2_0 rev41336:HEAD to trunk
47
48 r41647 - 2008-11-11 17:44:30 -0800 (Tue, 11 Nov 2008) - majed - Fixes a few bugs 
49
50 r41596 - 2008-11-10 19:20:04 -0800 (Mon, 10 Nov 2008) - Samir Gandhi - modified to set $method in the code
51
52 r41558 - 2008-11-10 14:35:34 -0800 (Mon, 10 Nov 2008) - majed - changes nusoap to allow for registering classes 
53
54 r39619 - 2008-09-09 13:41:34 -0700 (Tue, 09 Sep 2008) - jmertic - Bug 24827 - Remove all instances where we return a new object and assign it by reference, since this is deprecated in PHP 5 and emits E_DEPRECATED errors in PHP 5.3.
55 Touched:
56 - data/SugarBean.php
57 - include/domit/php_http_client_generic.php
58 - include/domit/php_http_connector.php
59 - include/domit/testing_domit.php
60 - include/domit/xml_domit_getelementsbypath.php
61 - include/domit/xml_domit_lite_parser.php
62 - include/domit/xml_domit_nodemaps.php
63 - include/domit/xml_domit_parser.php
64 - include/domit/xml_domit_shared.php
65 - include/generic/SugarWidgets/SugarWidgetField.php
66 - include/generic/SugarWidgets/SugarWidgetReportField.php
67 - include/ListView/ProcessView.php
68 - include/nusoap/class.soapclient.php
69 - include/nusoap/nusoap.php
70 - include/nusoap/nusoapmime.php
71 - include/Pear/HTML_Safe/Safe.php
72 - include/Pear/XML_HTMLSax3/HTMLSax3.php
73 - modules/Administration/RebuildWorkFlow.php
74 - modules/Expressions/RelateSelector.php
75 - modules/Reports/templates/templates_reports.php
76 - modules/WorkFlow/Delete.php
77 - modules/WorkFlow/Save.php
78 - modules/WorkFlow/SaveSequence.php
79 - modules/WorkFlow/WorkFlow.php
80 - modules/WorkFlowActionShells/CreateStep1.php
81 - modules/WorkFlowActionShells/CreateStep2.php
82 - modules/WorkFlowActionShells/Save.php
83 - modules/WorkFlowActionShells/WorkFlowActionShell.php
84 - modules/WorkFlowAlerts/Save.php
85 - modules/WorkFlowAlerts/WorkFlowAlert.php
86 - modules/WorkFlowAlertShells/DetailView.php
87 - modules/WorkFlowAlertShells/WorkFlowAlertShell.php
88 - modules/WorkFlowTriggerShells/CreateStep1.php
89 - modules/WorkFlowTriggerShells/CreateStepFilter.php
90 - modules/WorkFlowTriggerShells/SaveFilter.php
91 - modules/WorkFlowTriggerShells/WorkFlowTriggerShell.php
92 - soap/SoapHelperFunctions.php
93 - test/modules/DynamicFields/DynamicFields_Bug24095_test.php
94 - test/simpletest/browser.php
95 - test/simpletest/default_reporter.php
96 - test/simpletest/detached.php
97 - test/simpletest/eclipse.php
98 - test/simpletest/expectation.php
99 - test/simpletest/extensions/pear_test_case.php
100 - test/simpletest/form.php
101 - test/simpletest/http.php
102 - test/simpletest/mock_objects.php
103 - test/simpletest/page.php
104 - test/simpletest/parser.php
105 - test/simpletest/remote.php
106 - test/simpletest/shell_tester.php
107 - test/simpletest/simple_test.php
108 - test/simpletest/simpletest.php
109 - test/simpletest/test/acceptance_test.php
110 - test/simpletest/test/adapter_test.php
111 - test/simpletest/test/authentication_test.php
112 - test/simpletest/test/browser_test.php
113 - test/simpletest/test/collector_test.php
114 - test/simpletest/test/compatibility_test.php
115 - test/simpletest/test/detached_test.php
116 - test/simpletest/test/eclipse_test.php
117 - test/simpletest/test/encoding_test.php
118 - test/simpletest/test/errors_test.php
119 - test/simpletest/test/expectation_test.php
120 - test/simpletest/test/form_test.php
121 - test/simpletest/test/frames_test.php
122 - test/simpletest/test/http_test.php
123 - test/simpletest/test/live_test.php
124 - test/simpletest/test/mock_objects_test.php
125 - test/simpletest/test/page_test.php
126 - test/simpletest/test/parse_error_test.php
127 - test/simpletest/test/parser_test.php
128 - test/simpletest/test/remote_test.php
129 - test/simpletest/test/shell_test.php
130 - test/simpletest/test/shell_tester_test.php
131 - test/simpletest/test/simpletest_test.php
132 - test/simpletest/test/site/page_request.php
133 - test/simpletest/test/tag_test.php
134 - test/simpletest/test/unit_tester_test.php
135 - test/simpletest/test/user_agent_test.php
136 - test/simpletest/test/visual_test.php
137 - test/simpletest/test/xml_test.php
138 - test/simpletest/test_case.php
139 - test/simpletest/ui/array_reporter/test.php
140 - test/simpletest/ui/recorder/test.php
141 - test/simpletest/unit_tester.php
142 - test/simpletest/url.php
143 - test/simpletest/user_agent.php
144 - test/simpletest/web_tester.php
145 - test/spikephpcoverage/src/PEAR.php
146 - test/spikephpcoverage/src/util/Utility.php
147 - test/spikephpcoverage/src/XML/Parser.php
148 - test/spikephpcoverage/src/XML/Parser/Simple.php
149 - test/test_utilities/SugarTest_SimpleBrowser.php
150
151 r38362 - 2008-07-28 14:06:59 -0700 (Mon, 28 Jul 2008) - roger - bug: 23897. Using print_r when using the debug statement in nusoap will print out the statements to the screen if the call is coming from the UI.
152
153 r38300 - 2008-07-25 13:33:43 -0700 (Fri, 25 Jul 2008) - Samir Gandhi - put the debug in parseresponse function
154
155 r38293 - 2008-07-25 12:32:34 -0700 (Fri, 25 Jul 2008) - Samir Gandhi - to put all the debug statements return value in the call function
156
157 r36824 - 2008-06-18 09:26:11 -0700 (Wed, 18 Jun 2008) - roger - bug: 21832
158
159 r26422 - 2007-09-05 17:29:12 -0700 (Wed, 05 Sep 2007) - majed - migrate from beta 1 to trunk
160
161 r15787 - 2006-08-10 10:14:41 -0700 (Thu, 10 Aug 2006) - roger - RRS: bug 7961
162
163 r14701 - 2006-07-17 13:37:26 -0700 (Mon, 17 Jul 2006) - roger - RRS: bug 5801
164
165 r13782 - 2006-06-06 10:58:55 -0700 (Tue, 06 Jun 2006) - majed - changes entry point code
166
167 r11466 - 2006-02-01 15:49:47 -0800 (Wed, 01 Feb 2006) - jacob - Adding extra !empty check to get around a PHP warning.
168
169 r11115 - 2006-01-17 14:54:45 -0800 (Tue, 17 Jan 2006) - majed - add entry point validation
170
171 r10585 - 2005-12-13 14:42:26 -0800 (Tue, 13 Dec 2005) - majed - adds new license mechanisim
172
173 r10170 - 2005-12-05 18:37:46 -0800 (Mon, 05 Dec 2005) - majed - fixes various issues
174
175 r8999 - 2005-11-04 05:26:49 -0800 (Fri, 04 Nov 2005) - roger - When nusoap was upgraded we had an issue with the user's default language not being populated during a soap request. I determined the reason this was happening and have checked in the corresponding change to nusoap.
176
177 r8991 - 2005-11-03 19:07:25 -0800 (Thu, 03 Nov 2005) - majed - fixes nusoap issue
178
179 r8846 - 2005-10-31 11:01:12 -0800 (Mon, 31 Oct 2005) - majed - new version of nusoap
180
181 r7905 - 2005-09-21 19:12:57 -0700 (Wed, 21 Sep 2005) - majed - restores old nusoap pre & with a few fixes
182
183 r7861 - 2005-09-20 15:40:25 -0700 (Tue, 20 Sep 2005) - majed - & fix for 3.5.1
184
185 r7452 - 2005-08-17 11:32:34 -0700 (Wed, 17 Aug 2005) - majed - changes soap to nusoap
186
187 r5820 - 2005-06-21 14:22:24 -0700 (Tue, 21 Jun 2005) - majed - fixes issues with nusoap and with custom fields
188
189 r5462 - 2005-05-25 13:50:11 -0700 (Wed, 25 May 2005) - majed - upgraded nusoap to .6.9
190
191 r5104 - 2005-05-04 15:33:41 -0700 (Wed, 04 May 2005) - majed - gets rid of HTTP_GET_VARS and what not which has been deprecated
192
193 r573 - 2004-09-04 13:03:32 -0700 (Sat, 04 Sep 2004) - sugarclint - undoing copyrights added in inadvertantly.  --clint
194
195 r546 - 2004-09-03 11:49:38 -0700 (Fri, 03 Sep 2004) - sugarmsi - removed echo count
196
197 r354 - 2004-08-02 23:00:37 -0700 (Mon, 02 Aug 2004) - sugarjacob - Adding Soap
198
199
200 */
201
202
203 if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
204
205 /*
206 $Id: nusoap.php 58622 2010-10-23 01:18:59Z engsvnbuild $
207
208 NuSOAP - Web Services Toolkit for PHP
209
210 Copyright (c) 2002 NuSphere Corporation
211
212 This library is free software; you can redistribute it and/or
213 modify it under the terms of the GNU Lesser General Public
214 License as published by the Free Software Foundation; either
215 version 2.1 of the License, or (at your option) any later version.
216 n
217 This library is distributed in the hope that it will be useful,
218 but WITHOUT ANY WARRANTY; without even the implied warranty of
219 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
220 Lesser General Public License for more details.
221
222 You should have received a copy of the GNU Lesser General Public
223 License along with this library; if not, write to the Free Software
224 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
225
226 The NuSOAP project home is:
227 http://sourceforge.net/projects/nusoap/
228
229 The primary support for NuSOAP is the Help forum on the project home page.
230
231 If you have any questions or comments, please email:
232
233 Dietrich Ayala
234 dietrich@ganx4.com
235 http://dietrich.ganx4.com/nusoap
236
237 NuSphere Corporation
238 http://www.nusphere.com
239
240 */
241
242 /*
243  *      Some of the standards implmented in whole or part by NuSOAP:
244  *
245  *      SOAP 1.1 (http://www.w3.org/TR/2000/NOTE-SOAP-20000508/)
246  *      WSDL 1.1 (http://www.w3.org/TR/2001/NOTE-wsdl-20010315)
247  *      SOAP Messages With Attachments (http://www.w3.org/TR/SOAP-attachments)
248  *      XML 1.0 (http://www.w3.org/TR/2006/REC-xml-20060816/)
249  *      Namespaces in XML 1.0 (http://www.w3.org/TR/2006/REC-xml-names-20060816/)
250  *      XML Schema 1.0 (http://www.w3.org/TR/xmlschema-0/)
251  *      RFC 2045 Multipurpose Internet Mail Extensions (MIME) Part One: Format of Internet Message Bodies
252  *      RFC 2068 Hypertext Transfer Protocol -- HTTP/1.1
253  *      RFC 2617 HTTP Authentication: Basic and Digest Access Authentication
254  */
255
256 /* load classes
257
258 // necessary classes
259 require_once('class.soapclient.php');
260 require_once('class.soap_val.php');
261 require_once('class.soap_parser.php');
262 require_once('class.soap_fault.php');
263
264 // transport classes
265 require_once('class.soap_transport_http.php');
266
267 // optional add-on classes
268 require_once('class.xmlschema.php');
269 require_once('class.wsdl.php');
270
271 // server class
272 require_once('class.soap_server.php');*/
273
274 // class variable emulation
275 // cf. http://www.webkreator.com/php/techniques/php-static-class-variables.html
276 $GLOBALS['_transient']['static']['nusoap_base']['globalDebugLevel'] = 0;
277
278 /**
279 *
280 * nusoap_base
281 *
282 * @author   Dietrich Ayala <dietrich@ganx4.com>
283 * @author   Scott Nichol <snichol@users.sourceforge.net>
284
285 * @access   public
286 */
287 class nusoap_base {
288         /**
289          * Identification for HTTP headers.
290          *
291          * @var string
292          * @access private
293          */
294         var $title = 'NuSOAP';
295         /**
296          * Version for HTTP headers.
297          *
298          * @var string
299          * @access private
300          */
301         var $version = '0.9.5';
302         /**
303          * CVS revision for HTTP headers.
304          *
305          * @var string
306          * @access private
307          */
308         var $revision = '$Revision: 58622 $';
309     /**
310      * Current error string (manipulated by getError/setError)
311          *
312          * @var string
313          * @access private
314          */
315         var $error_str = '';
316     /**
317      * Current debug string (manipulated by debug/appendDebug/clearDebug/getDebug/getDebugAsXMLComment)
318          *
319          * @var string
320          * @access private
321          */
322     var $debug_str = '';
323     /**
324          * toggles automatic encoding of special characters as entities
325          * (should always be true, I think)
326          *
327          * @var boolean
328          * @access private
329          */
330         var $charencoding = true;
331         /**
332          * the debug level for this instance
333          *
334          * @var integer
335          * @access private
336          */
337         var $debugLevel;
338
339     /**
340         * set schema version
341         *
342         * @var      string
343         * @access   public
344         */
345         var $XMLSchemaVersion = 'http://www.w3.org/2001/XMLSchema';
346         
347     /**
348         * charset encoding for outgoing messages
349         *
350         * @var      string
351         * @access   public
352         */
353     //var $soap_defencoding = 'ISO-8859-1';
354         var $soap_defencoding = 'UTF-8';
355
356         /**
357         * namespaces in an array of prefix => uri
358         *
359         * this is "seeded" by a set of constants, but it may be altered by code
360         *
361         * @var      array
362         * @access   public
363         */
364         var $namespaces = array(
365                 'SOAP-ENV' => 'http://schemas.xmlsoap.org/soap/envelope/',
366                 'xsd' => 'http://www.w3.org/2001/XMLSchema',
367                 'xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
368                 'SOAP-ENC' => 'http://schemas.xmlsoap.org/soap/encoding/'
369                 );
370
371         /**
372         * namespaces used in the current context, e.g. during serialization
373         *
374         * @var      array
375         * @access   private
376         */
377         var $usedNamespaces = array();
378
379         /**
380         * XML Schema types in an array of uri => (array of xml type => php type)
381         * is this legacy yet?
382         * no, this is used by the nusoap_xmlschema class to verify type => namespace mappings.
383         * @var      array
384         * @access   public
385         */
386         var $typemap = array(
387         'http://www.w3.org/2001/XMLSchema' => array(
388                 'string'=>'string','boolean'=>'boolean','float'=>'double','double'=>'double','decimal'=>'double',
389                 'duration'=>'','dateTime'=>'string','time'=>'string','date'=>'string','gYearMonth'=>'',
390                 'gYear'=>'','gMonthDay'=>'','gDay'=>'','gMonth'=>'','hexBinary'=>'string','base64Binary'=>'string',
391                 // abstract "any" types
392                 'anyType'=>'string','anySimpleType'=>'string',
393                 // derived datatypes
394                 'normalizedString'=>'string','token'=>'string','language'=>'','NMTOKEN'=>'','NMTOKENS'=>'','Name'=>'','NCName'=>'','ID'=>'',
395                 'IDREF'=>'','IDREFS'=>'','ENTITY'=>'','ENTITIES'=>'','integer'=>'integer','nonPositiveInteger'=>'integer',
396                 'negativeInteger'=>'integer','long'=>'integer','int'=>'integer','short'=>'integer','byte'=>'integer','nonNegativeInteger'=>'integer',
397                 'unsignedLong'=>'','unsignedInt'=>'','unsignedShort'=>'','unsignedByte'=>'','positiveInteger'=>''),
398         'http://www.w3.org/2000/10/XMLSchema' => array(
399                 'i4'=>'','int'=>'integer','boolean'=>'boolean','string'=>'string','double'=>'double',
400                 'float'=>'double','dateTime'=>'string',
401                 'timeInstant'=>'string','base64Binary'=>'string','base64'=>'string','ur-type'=>'array'),
402         'http://www.w3.org/1999/XMLSchema' => array(
403                 'i4'=>'','int'=>'integer','boolean'=>'boolean','string'=>'string','double'=>'double',
404                 'float'=>'double','dateTime'=>'string',
405                 'timeInstant'=>'string','base64Binary'=>'string','base64'=>'string','ur-type'=>'array'),
406         'http://soapinterop.org/xsd' => array('SOAPStruct'=>'struct'),
407         'http://schemas.xmlsoap.org/soap/encoding/' => array('base64'=>'string','array'=>'array','Array'=>'array'),
408     'http://xml.apache.org/xml-soap' => array('Map')
409         );
410
411         /**
412         * XML entities to convert
413         *
414         * @var      array
415         * @access   public
416         * @deprecated
417         * @see  expandEntities
418         */
419         var $xmlEntities = array('quot' => '"','amp' => '&',
420                 'lt' => '<','gt' => '>','apos' => "'");
421
422         /**
423          * Payload override
424          * This is to allows us to override the payload to resolve issues where we need to take
425          * control of the xml content
426          * @var string
427          * @access public
428          * 
429          */
430         var $payloadOverride;   
431         
432         /**
433         * constructor
434         *
435         * @access       public
436         */
437         function nusoap_base() {
438                 $this->debugLevel = $GLOBALS['_transient']['static']['nusoap_base']['globalDebugLevel'];
439         }
440
441         /**
442         * gets the global debug level, which applies to future instances
443         *
444         * @return       integer Debug level 0-9, where 0 turns off
445         * @access       public
446         */
447         function getGlobalDebugLevel() {
448                 return $GLOBALS['_transient']['static']['nusoap_base']['globalDebugLevel'];
449         }
450
451         /**
452         * sets the global debug level, which applies to future instances
453         *
454         * @param        int     $level  Debug level 0-9, where 0 turns off
455         * @access       public
456         */
457         function setGlobalDebugLevel($level) {
458                 $GLOBALS['_transient']['static']['nusoap_base']['globalDebugLevel'] = $level;
459         }
460
461         /**
462         * gets the debug level for this instance
463         *
464         * @return       int     Debug level 0-9, where 0 turns off
465         * @access       public
466         */
467         function getDebugLevel() {
468                 return $this->debugLevel;
469         }
470
471         /**
472         * sets the debug level for this instance
473         *
474         * @param        int     $level  Debug level 0-9, where 0 turns off
475         * @access       public
476         */
477         function setDebugLevel($level) {
478                 $this->debugLevel = $level;
479         }
480
481         /**
482         * adds debug data to the instance debug string with formatting
483         *
484         * @param    string $string debug data
485         * @access   private
486         */
487         function debug($string){
488                 if ($this->debugLevel > 0) {
489                         $this->appendDebug($this->getmicrotime().' '.get_class($this).": $string\n");
490                 }
491         }
492
493         /**
494         * adds debug data to the instance debug string without formatting
495         *
496         * @param    string $string debug data
497         * @access   public
498         */
499         function appendDebug($string){
500                 if ($this->debugLevel > 0) {
501                         // it would be nice to use a memory stream here to use
502                         // memory more efficiently
503                         $this->debug_str .= $string;
504                 }
505         }
506
507         /**
508         * clears the current debug data for this instance
509         *
510         * @access   public
511         */
512         function clearDebug() {
513                 // it would be nice to use a memory stream here to use
514                 // memory more efficiently
515                 $this->debug_str = '';
516         }
517
518         /**
519         * gets the current debug data for this instance
520         *
521         * @return   debug data
522         * @access   public
523         */
524         function &getDebug() {
525                 // it would be nice to use a memory stream here to use
526                 // memory more efficiently
527                 return $this->debug_str;
528         }
529
530         /**
531         * gets the current debug data for this instance as an XML comment
532         * this may change the contents of the debug data
533         *
534         * @return   debug data as an XML comment
535         * @access   public
536         */
537         function &getDebugAsXMLComment() {
538                 // it would be nice to use a memory stream here to use
539                 // memory more efficiently
540                 while (strpos($this->debug_str, '--')) {
541                         $this->debug_str = str_replace('--', '- -', $this->debug_str);
542                 }
543                 $ret = "<!--\n" . $this->debug_str . "\n-->";
544         return $ret;
545         }
546
547         /**
548         * expands entities, e.g. changes '<' to '&lt;'.
549         *
550         * @param        string  $val    The string in which to expand entities.
551         * @access       private
552         */
553         function expandEntities($val) {
554                 if ($this->charencoding) {
555                 $val = str_replace('&', '&amp;', $val);
556                 $val = str_replace("'", '&apos;', $val);
557                 $val = str_replace('"', '&quot;', $val);
558                 $val = str_replace('<', '&lt;', $val);
559                 $val = str_replace('>', '&gt;', $val);
560             }
561             return $val;
562         }
563
564         /**
565         * returns error string if present
566         *
567         * @return   mixed error string or false
568         * @access   public
569         */
570         function getError(){
571                 if($this->error_str != ''){
572                         return $this->error_str;
573                 }
574                 return false;
575         }
576
577         /**
578         * sets error string
579         *
580         * @return   boolean $string error string
581         * @access   private
582         */
583         function setError($str){
584                 $this->error_str = $str;
585         }
586
587         /**
588         * detect if array is a simple array or a struct (associative array)
589         *
590         * @param        mixed   $val    The PHP array
591         * @return       string  (arraySimple|arrayStruct)
592         * @access       private
593         */
594         function isArraySimpleOrStruct($val) {
595         $keyList = array_keys($val);
596                 foreach ($keyList as $keyListValue) {
597                         if (!is_int($keyListValue)) {
598                                 return 'arrayStruct';
599                         }
600                 }
601                 return 'arraySimple';
602         }
603
604         /**
605         * serializes PHP values in accordance w/ section 5. Type information is
606         * not serialized if $use == 'literal'.
607         *
608         * @param        mixed   $val    The value to serialize
609         * @param        string  $name   The name (local part) of the XML element
610         * @param        string  $type   The XML schema type (local part) for the element
611         * @param        string  $name_ns        The namespace for the name of the XML element
612         * @param        string  $type_ns        The namespace for the type of the element
613         * @param        array   $attributes     The attributes to serialize as name=>value pairs
614         * @param        string  $use    The WSDL "use" (encoded|literal)
615         * @param        boolean $soapval        Whether this is called from soapval.
616         * @return       string  The serialized element, possibly with child elements
617     * @access   public
618         */
619         function serialize_val($val,$name=false,$type=false,$name_ns=false,$type_ns=false,$attributes=false,$use='encoded',$soapval=false) {
620                 $this->debug("in serialize_val: name=$name, type=$type, name_ns=$name_ns, type_ns=$type_ns, use=$use, soapval=$soapval");
621                 $this->appendDebug('value=' . $this->varDump($val));
622                 $this->appendDebug('attributes=' . $this->varDump($attributes));
623                 
624         if (is_object($val) && get_class($val) == 'soapval' && (! $soapval)) {
625                 $this->debug("serialize_val: serialize soapval");
626                 $xml = $val->serialize($use);
627                         $this->appendDebug($val->getDebug());
628                         $val->clearDebug();
629                         $this->debug("serialize_val of soapval returning $xml");
630                         return $xml;
631         }
632                 // force valid name if necessary
633                 if (is_numeric($name)) {
634                         $name = '__numeric_' . $name;
635                 } elseif (! $name) {
636                         $name = 'noname';
637                 }
638                 // if name has ns, add ns prefix to name
639                 $xmlns = '';
640         if($name_ns){
641                         $prefix = 'nu'.rand(1000,9999);
642                         $name = $prefix.':'.$name;
643                         $xmlns .= " xmlns:$prefix=\"$name_ns\"";
644                 }
645                 // if type is prefixed, create type prefix
646                 if($type_ns != '' && $type_ns == $this->namespaces['xsd']){
647                         // need to fix this. shouldn't default to xsd if no ns specified
648                     // w/o checking against typemap
649                         $type_prefix = 'xsd';
650                 } elseif($type_ns){
651                         $type_prefix = 'ns'.rand(1000,9999);
652                         $xmlns .= " xmlns:$type_prefix=\"$type_ns\"";
653                 }
654                 // serialize attributes if present
655                 $atts = '';
656                 if($attributes){
657                         foreach($attributes as $k => $v){
658                                 $atts .= " $k=\"".$this->expandEntities($v).'"';
659                         }
660                 }
661                 // serialize null value
662                 if (is_null($val)) {
663                 $this->debug("serialize_val: serialize null");
664                         if ($use == 'literal') {
665                                 // TODO: depends on minOccurs
666                                 $xml = "<$name$xmlns$atts/>";
667                                 $this->debug("serialize_val returning $xml");
668                         return $xml;
669                 } else {
670                                 if (isset($type) && isset($type_prefix)) {
671                                         $type_str = " xsi:type=\"$type_prefix:$type\"";
672                                 } else {
673                                         $type_str = '';
674                                 }
675                                 $xml = "<$name$xmlns$type_str$atts xsi:nil=\"true\"/>";
676                                 $this->debug("serialize_val returning $xml");
677                         return $xml;
678                 }
679                 }
680         // serialize if an xsd built-in primitive type
681         if($type != '' && isset($this->typemap[$this->XMLSchemaVersion][$type])){
682                 $this->debug("serialize_val: serialize xsd built-in primitive type");
683                 if (is_bool($val)) {
684                         if ($type == 'boolean') {
685                                 $val = $val ? 'true' : 'false';
686                         } elseif (! $val) {
687                                 $val = 0;
688                         }
689                         } else if (is_string($val)) {
690                                 $val = $this->expandEntities($val);
691                         }
692                         if ($use == 'literal') {
693                                 $xml = "<$name$xmlns$atts>$val</$name>";
694                                 $this->debug("serialize_val returning $xml");
695                         return $xml;
696                 } else {
697                                 $xml = "<$name$xmlns xsi:type=\"xsd:$type\"$atts>$val</$name>";
698                                 $this->debug("serialize_val returning $xml");
699                         return $xml;
700                 }
701         }
702                 // detect type and serialize
703                 $xml = '';
704                 switch(true) {
705                         case (is_bool($val) || $type == 'boolean'):
706                                 $this->debug("serialize_val: serialize boolean");
707                         if ($type == 'boolean') {
708                                 $val = $val ? 'true' : 'false';
709                         } elseif (! $val) {
710                                 $val = 0;
711                         }
712                                 if ($use == 'literal') {
713                                         $xml .= "<$name$xmlns$atts>$val</$name>";
714                                 } else {
715                                         $xml .= "<$name$xmlns xsi:type=\"xsd:boolean\"$atts>$val</$name>";
716                                 }
717                                 break;
718                         case (is_int($val) || is_long($val) || $type == 'int'):
719                                 $this->debug("serialize_val: serialize int");
720                                 if ($use == 'literal') {
721                                         $xml .= "<$name$xmlns$atts>$val</$name>";
722                                 } else {
723                                         $xml .= "<$name$xmlns xsi:type=\"xsd:int\"$atts>$val</$name>";
724                                 }
725                                 break;
726                         case (is_float($val)|| is_double($val) || $type == 'float'):
727                                 $this->debug("serialize_val: serialize float");
728                                 if ($use == 'literal') {
729                                         $xml .= "<$name$xmlns$atts>$val</$name>";
730                                 } else {
731                                         $xml .= "<$name$xmlns xsi:type=\"xsd:float\"$atts>$val</$name>";
732                                 }
733                                 break;
734                         case (is_string($val) || $type == 'string'):
735                                 $this->debug("serialize_val: serialize string");
736                                 $val = $this->expandEntities($val);
737                                 if ($use == 'literal') {
738                                         $xml .= "<$name$xmlns$atts>$val</$name>";
739                                 } else {
740                                         $xml .= "<$name$xmlns xsi:type=\"xsd:string\"$atts>$val</$name>";
741                                 }
742                                 break;
743                         case is_object($val):
744                                 $this->debug("serialize_val: serialize object");
745                         if (get_class($val) == 'soapval') {
746                                 $this->debug("serialize_val: serialize soapval object");
747                                 $pXml = $val->serialize($use);
748                                         $this->appendDebug($val->getDebug());
749                                         $val->clearDebug();
750                         } else {
751                                         if (! $name) {
752                                                 $name = get_class($val);
753                                                 $this->debug("In serialize_val, used class name $name as element name");
754                                         } else {
755                                                 $this->debug("In serialize_val, do not override name $name for element name for class " . get_class($val));
756                                         }
757                                         foreach(get_object_vars($val) as $k => $v){
758                                                 $pXml = isset($pXml) ? $pXml.$this->serialize_val($v,$k,false,false,false,false,$use) : $this->serialize_val($v,$k,false,false,false,false,$use);
759                                         }
760                                 }
761                                 if(isset($type) && isset($type_prefix)){
762                                         $type_str = " xsi:type=\"$type_prefix:$type\"";
763                                 } else {
764                                         $type_str = '';
765                                 }
766                                 if ($use == 'literal') {
767                                         $xml .= "<$name$xmlns$atts>$pXml</$name>";
768                                 } else {
769                                         $xml .= "<$name$xmlns$type_str$atts>$pXml</$name>";
770                                 }
771                                 break;
772                         break;
773                         case (is_array($val) || $type):
774                                 // detect if struct or array
775                                 $valueType = $this->isArraySimpleOrStruct($val);
776                 if($valueType=='arraySimple' || preg_match('/^ArrayOf/',$type)){
777                                         $this->debug("serialize_val: serialize array");
778                                         $i = 0;
779                                         if(is_array($val) && count($val)> 0){
780                                                 foreach($val as $v){
781                                 if(is_object($v) && get_class($v) ==  'soapval'){
782                                                                 $tt_ns = $v->type_ns;
783                                                                 $tt = $v->type;
784                                                         } elseif (is_array($v)) {
785                                                                 $tt = $this->isArraySimpleOrStruct($v);
786                                                         } else {
787                                                                 $tt = gettype($v);
788                                 }
789                                                         $array_types[$tt] = 1;
790                                                         // TODO: for literal, the name should be $name
791                                                         $xml .= $this->serialize_val($v,'item',false,false,false,false,$use);
792                                                         ++$i;
793                                                 }
794                                                 if(count($array_types) > 1){
795                                                         $array_typename = 'xsd:anyType';
796                                                 } elseif(isset($tt) && isset($this->typemap[$this->XMLSchemaVersion][$tt])) {
797                                                         if ($tt == 'integer') {
798                                                                 $tt = 'int';
799                                                         }
800                                                         $array_typename = 'xsd:'.$tt;
801                                                 } elseif(isset($tt) && $tt == 'arraySimple'){
802                                                         $array_typename = 'SOAP-ENC:Array';
803                                                 } elseif(isset($tt) && $tt == 'arrayStruct'){
804                                                         $array_typename = 'unnamed_struct_use_soapval';
805                                                 } else {
806                                                         // if type is prefixed, create type prefix
807                                                         if ($tt_ns != '' && $tt_ns == $this->namespaces['xsd']){
808                                                                  $array_typename = 'xsd:' . $tt;
809                                                         } elseif ($tt_ns) {
810                                                                 $tt_prefix = 'ns' . rand(1000, 9999);
811                                                                 $array_typename = "$tt_prefix:$tt";
812                                                                 $xmlns .= " xmlns:$tt_prefix=\"$tt_ns\"";
813                                                         } else {
814                                                                 $array_typename = $tt;
815                                                         }
816                                                 }
817                                                 $array_type = $i;
818                                                 if ($use == 'literal') {
819                                                         $type_str = '';
820                                                 } else if (isset($type) && isset($type_prefix)) {
821                                                         $type_str = " xsi:type=\"$type_prefix:$type\"";
822                                                 } else {
823                                                         $type_str = " xsi:type=\"SOAP-ENC:Array\" SOAP-ENC:arrayType=\"".$array_typename."[$array_type]\"";
824                                                 }
825                                         // empty array
826                                         } else {
827                                                 if ($use == 'literal') {
828                                                         $type_str = '';
829                                                 } else if (isset($type) && isset($type_prefix)) {
830                                                         $type_str = " xsi:type=\"$type_prefix:$type\"";
831                                                 } else {
832                                                         $type_str = " xsi:type=\"SOAP-ENC:Array\" SOAP-ENC:arrayType=\"xsd:anyType[0]\"";
833                                                 }
834                                         }
835                                         // TODO: for array in literal, there is no wrapper here
836                                         $xml = "<$name$xmlns$type_str$atts>".$xml."</$name>";
837                                 } else {
838                                         // got a struct
839                                         $this->debug("serialize_val: serialize struct");
840                                         if(isset($type) && isset($type_prefix)){
841                                                 $type_str = " xsi:type=\"$type_prefix:$type\"";
842                                         } else {
843                                                 $type_str = '';
844                                         }
845                                         if ($use == 'literal') {
846                                                 $xml .= "<$name$xmlns$atts>";
847                                         } else {
848                                                 $xml .= "<$name$xmlns$type_str$atts>";
849                                         }
850                                         foreach($val as $k => $v){
851                                                 // Apache Map
852                                                 if ($type == 'Map' && $type_ns == 'http://xml.apache.org/xml-soap') {
853                                                         $xml .= '<item>';
854                                                         $xml .= $this->serialize_val($k,'key',false,false,false,false,$use);
855                                                         $xml .= $this->serialize_val($v,'value',false,false,false,false,$use);
856                                                         $xml .= '</item>';
857                                                 } else {
858                                                         $xml .= $this->serialize_val($v,$k,false,false,false,false,$use);
859                                                 }
860                                         }
861                                         $xml .= "</$name>";
862                                 }
863                                 break;
864                         default:
865                                 $this->debug("serialize_val: serialize unknown");
866                                 $xml .= 'not detected, got '.gettype($val).' for '.$val;
867                                 break;
868                 }
869                 $this->debug("serialize_val returning $xml");
870                 return $xml;
871         }
872
873     /**
874     * serializes a message
875     *
876     * @param string $body the XML of the SOAP body
877     * @param mixed $headers optional string of XML with SOAP header content, or array of soapval objects for SOAP headers, or associative array
878     * @param array $namespaces optional the namespaces used in generating the body and headers
879     * @param string $style optional (rpc|document)
880     * @param string $use optional (encoded|literal)
881     * @param string $encodingStyle optional (usually 'http://schemas.xmlsoap.org/soap/encoding/' for encoded)
882     * @return string the message
883     * @access public
884     */
885     function serializeEnvelope($body,$headers=false,$namespaces=array(),$style='rpc',$use='encoded',$encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'){
886     // TODO: add an option to automatically run utf8_encode on $body and $headers
887     // if $this->soap_defencoding is UTF-8.  Not doing this automatically allows
888     // one to send arbitrary UTF-8 characters, not just characters that map to ISO-8859-1
889
890         $this->debug("In serializeEnvelope length=" . strlen($body) . " body (max 1000 characters)=" . substr($body, 0, 1000) . " style=$style use=$use encodingStyle=$encodingStyle");
891         $this->debug("headers:");
892         $this->appendDebug($this->varDump($headers));
893         $this->debug("namespaces:");
894         $this->appendDebug($this->varDump($namespaces));
895
896         // serialize namespaces
897     $ns_string = '';
898         foreach(array_merge($this->namespaces,$namespaces) as $k => $v){
899                 $ns_string .= " xmlns:$k=\"$v\"";
900         }
901         if($encodingStyle) {
902                 $ns_string = " SOAP-ENV:encodingStyle=\"$encodingStyle\"$ns_string";
903         }
904
905         // serialize headers
906         if($headers){
907                 if (is_array($headers)) {
908                         $xml = '';
909                         foreach ($headers as $k => $v) {
910                                 if (is_object($v) && get_class($v) == 'soapval') {
911                                         $xml .= $this->serialize_val($v, false, false, false, false, false, $use);
912                                 } else {
913                                         $xml .= $this->serialize_val($v, $k, false, false, false, false, $use);
914                                 }
915                         }
916                         $headers = $xml;
917                         $this->debug("In serializeEnvelope, serialized array of headers to $headers");
918                 }
919                 $headers = "<SOAP-ENV:Header>".$headers."</SOAP-ENV:Header>";
920         }
921         // serialize envelope
922         return
923         '<?xml version="1.0" encoding="'.$this->soap_defencoding .'"?'.">".
924         '<SOAP-ENV:Envelope'.$ns_string.">".
925         $headers.
926         "<SOAP-ENV:Body>".
927                 $body.
928         "</SOAP-ENV:Body>".
929         "</SOAP-ENV:Envelope>";
930     }
931
932         /**
933          * formats a string to be inserted into an HTML stream
934          *
935          * @param string $str The string to format
936          * @return string The formatted string
937          * @access public
938          * @deprecated
939          */
940     function formatDump($str){
941                 $str = htmlspecialchars($str);
942                 return nl2br($str);
943     }
944
945         /**
946         * contracts (changes namespace to prefix) a qualified name
947         *
948         * @param    string $qname qname
949         * @return       string contracted qname
950         * @access   private
951         */
952         function contractQname($qname){
953                 // get element namespace
954                 //$this->xdebug("Contract $qname");
955                 if (strrpos($qname, ':')) {
956                         // get unqualified name
957                         $name = substr($qname, strrpos($qname, ':') + 1);
958                         // get ns
959                         $ns = substr($qname, 0, strrpos($qname, ':'));
960                         $p = $this->getPrefixFromNamespace($ns);
961                         if ($p) {
962                                 return $p . ':' . $name;
963                         }
964                         return $qname;
965                 } else {
966                         return $qname;
967                 }
968         }
969
970         /**
971         * expands (changes prefix to namespace) a qualified name
972         *
973         * @param    string $qname qname
974         * @return       string expanded qname
975         * @access   private
976         */
977         function expandQname($qname){
978                 // get element prefix
979                 if(strpos($qname,':') && !preg_match('/^http:\/\//',$qname)){
980                         // get unqualified name
981                         $name = substr(strstr($qname,':'),1);
982                         // get ns prefix
983                         $prefix = substr($qname,0,strpos($qname,':'));
984                         if(isset($this->namespaces[$prefix])){
985                                 return $this->namespaces[$prefix].':'.$name;
986                         } else {
987                                 return $qname;
988                         }
989                 } else {
990                         return $qname;
991                 }
992         }
993
994     /**
995     * returns the local part of a prefixed string
996     * returns the original string, if not prefixed
997     *
998     * @param string $str The prefixed string
999     * @return string The local part
1000     * @access public
1001     */
1002         function getLocalPart($str){
1003                 if($sstr = strrchr($str,':')){
1004                         // get unqualified name
1005                         return substr( $sstr, 1 );
1006                 } else {
1007                         return $str;
1008                 }
1009         }
1010
1011         /**
1012     * returns the prefix part of a prefixed string
1013     * returns false, if not prefixed
1014     *
1015     * @param string $str The prefixed string
1016     * @return mixed The prefix or false if there is no prefix
1017     * @access public
1018     */
1019         function getPrefix($str){
1020                 if($pos = strrpos($str,':')){
1021                         // get prefix
1022                         return substr($str,0,$pos);
1023                 }
1024                 return false;
1025         }
1026
1027         /**
1028     * pass it a prefix, it returns a namespace
1029     *
1030     * @param string $prefix The prefix
1031     * @return mixed The namespace, false if no namespace has the specified prefix
1032     * @access public
1033     */
1034         function getNamespaceFromPrefix($prefix){
1035                 if (isset($this->namespaces[$prefix])) {
1036                         return $this->namespaces[$prefix];
1037                 }
1038                 //$this->setError("No namespace registered for prefix '$prefix'");
1039                 return false;
1040         }
1041
1042         /**
1043     * returns the prefix for a given namespace (or prefix)
1044     * or false if no prefixes registered for the given namespace
1045     *
1046     * @param string $ns The namespace
1047     * @return mixed The prefix, false if the namespace has no prefixes
1048     * @access public
1049     */
1050         function getPrefixFromNamespace($ns) {
1051                 foreach ($this->namespaces as $p => $n) {
1052                         if ($ns == $n || $ns == $p) {
1053                             $this->usedNamespaces[$p] = $n;
1054                                 return $p;
1055                         }
1056                 }
1057                 return false;
1058         }
1059
1060         /**
1061     * returns the time in ODBC canonical form with microseconds
1062     *
1063     * @return string The time in ODBC canonical form with microseconds
1064     * @access public
1065     */
1066         function getmicrotime() {
1067                 if (function_exists('gettimeofday')) {
1068                         $tod = gettimeofday();
1069                         $sec = $tod['sec'];
1070                         $usec = $tod['usec'];
1071                 } else {
1072                         $sec = time();
1073                         $usec = 0;
1074                 }
1075                 return strftime('%Y-%m-%d %H:%M:%S', $sec) . '.' . sprintf('%06d', $usec);
1076         }
1077
1078         /**
1079          * Returns a string with the output of var_dump
1080          *
1081          * @param mixed $data The variable to var_dump
1082          * @return string The output of var_dump
1083          * @access public
1084          */
1085     function varDump($data) {
1086                 ob_start();
1087                 var_dump($data);
1088                 $ret_val = ob_get_contents();
1089                 ob_end_clean();
1090                 return $ret_val;
1091         }
1092
1093         /**
1094         * represents the object as a string
1095         *
1096         * @return       string
1097         * @access   public
1098         */
1099         function __toString() {
1100                 return $this->varDump($this);
1101         }
1102 }
1103
1104 // XML Schema Datatype Helper Functions
1105
1106 //xsd:dateTime helpers
1107
1108 /**
1109 * convert unix timestamp to ISO 8601 compliant date string
1110 *
1111 * @param    int $timestamp Unix time stamp
1112 * @param        boolean $utc Whether the time stamp is UTC or local
1113 * @return       mixed ISO 8601 date string or false
1114 * @access   public
1115 */
1116 function timestamp_to_iso8601($timestamp,$utc=true){
1117         $datestr = date('Y-m-d\TH:i:sO',$timestamp);
1118         $pos = strrpos($datestr, "+");
1119         if ($pos === FALSE) {
1120                 $pos = strrpos($datestr, "-");
1121         }
1122         if ($pos !== FALSE) {
1123                 if (strlen($datestr) == $pos + 5) {
1124                         $datestr = substr($datestr, 0, $pos + 3) . ':' . substr($datestr, -2);
1125                 }
1126         }
1127         if($utc){
1128                 $pattern = '/'.
1129                 '([0-9]{4})-'.  // centuries & years CCYY-
1130                 '([0-9]{2})-'.  // months MM-
1131                 '([0-9]{2})'.   // days DD
1132                 'T'.                    // separator T
1133                 '([0-9]{2}):'.  // hours hh:
1134                 '([0-9]{2}):'.  // minutes mm:
1135                 '([0-9]{2})(\.[0-9]*)?'. // seconds ss.ss...
1136                 '(Z|[+\-][0-9]{2}:?[0-9]{2})?'. // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's
1137                 '/';
1138
1139                 if(preg_match($pattern,$datestr,$regs)){
1140                         return sprintf('%04d-%02d-%02dT%02d:%02d:%02dZ',$regs[1],$regs[2],$regs[3],$regs[4],$regs[5],$regs[6]);
1141                 }
1142                 return false;
1143         } else {
1144                 return $datestr;
1145         }
1146 }
1147
1148 /**
1149 * convert ISO 8601 compliant date string to unix timestamp
1150 *
1151 * @param    string $datestr ISO 8601 compliant date string
1152 * @return       mixed Unix timestamp (int) or false
1153 * @access   public
1154 */
1155 function iso8601_to_timestamp($datestr){
1156         $pattern = '/'.
1157         '([0-9]{4})-'.  // centuries & years CCYY-
1158         '([0-9]{2})-'.  // months MM-
1159         '([0-9]{2})'.   // days DD
1160         'T'.                    // separator T
1161         '([0-9]{2}):'.  // hours hh:
1162         '([0-9]{2}):'.  // minutes mm:
1163         '([0-9]{2})(\.[0-9]+)?'. // seconds ss.ss...
1164         '(Z|[+\-][0-9]{2}:?[0-9]{2})?'. // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's
1165         '/';
1166         if(preg_match($pattern,$datestr,$regs)){
1167                 // not utc
1168                 if($regs[8] != 'Z'){
1169                         $op = substr($regs[8],0,1);
1170                         $h = substr($regs[8],1,2);
1171                         $m = substr($regs[8],strlen($regs[8])-2,2);
1172                         if($op == '-'){
1173                                 $regs[4] = $regs[4] + $h;
1174                                 $regs[5] = $regs[5] + $m;
1175                         } elseif($op == '+'){
1176                                 $regs[4] = $regs[4] - $h;
1177                                 $regs[5] = $regs[5] - $m;
1178                         }
1179                 }
1180                 return gmmktime($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]);
1181 //              return strtotime("$regs[1]-$regs[2]-$regs[3] $regs[4]:$regs[5]:$regs[6]Z");
1182         } else {
1183                 return false;
1184         }
1185 }
1186
1187 /**
1188 * sleeps some number of microseconds
1189 *
1190 * @param    string $usec the number of microseconds to sleep
1191 * @access   public
1192 * @deprecated
1193 */
1194 function usleepWindows($usec)
1195 {
1196         $start = gettimeofday();
1197         
1198         do
1199         {
1200                 $stop = gettimeofday();
1201                 $timePassed = 1000000 * ($stop['sec'] - $start['sec'])
1202                 + $stop['usec'] - $start['usec'];
1203         }
1204         while ($timePassed < $usec);
1205 }
1206
1207 ?><?php
1208
1209 /*
1210
1211 Modification information for LGPL compliance
1212
1213 r58622 - 2010-10-22 18:18:59 -0700 (Fri, 22 Oct 2010) - engsvnbuild - Author: lam <lam@198.18.142.201>
1214     bug 40066
1215
1216 r58361 - 2010-09-29 16:59:02 -0700 (Wed, 29 Sep 2010) - kjing - Author: Jenny Gonsalves <jenny@sugarcrm.com>
1217     Merging with maint_6_0_1 (svn merge -r 58250:58342)
1218
1219 r57813 - 2010-08-19 10:34:44 -0700 (Thu, 19 Aug 2010) - kjing - Author: John Mertic <jmertic@sugarcrm.com>
1220     Bug 39085 - When loading the opposite search panel via ajax on the ListViews, call the index action instead of the ListView action to avoid touching pre-MVC code by accident.
1221
1222 r57707 - 2010-08-10 12:26:13 -0700 (Tue, 10 Aug 2010) - kjing - Author: Stanislav Malyshev <smalyshev@gmail.com>
1223     fix SOAP calls with no parameters
1224
1225 r56990 - 2010-06-16 13:05:36 -0700 (Wed, 16 Jun 2010) - kjing - snapshot "Mango" svn branch to a new one for GitHub sync
1226
1227 r56989 - 2010-06-16 13:01:33 -0700 (Wed, 16 Jun 2010) - kjing - defunt "Mango" svn dev branch before github cutover
1228
1229 r55980 - 2010-04-19 13:31:28 -0700 (Mon, 19 Apr 2010) - kjing - create Mango (6.1) based on windex
1230
1231 r51719 - 2009-10-22 10:18:00 -0700 (Thu, 22 Oct 2009) - mitani - Converted to Build 3  tags and updated the build system 
1232
1233 r51634 - 2009-10-19 13:32:22 -0700 (Mon, 19 Oct 2009) - mitani - Windex is the branch for Sugar Sales 1.0 development
1234
1235 r51508 - 2009-10-14 07:40:23 -0700 (Wed, 14 Oct 2009) - jmertic - More fallout fixes from the PHP 5.3 ereg to preg changes.
1236
1237 r51455 - 2009-10-13 07:56:48 -0700 (Tue, 13 Oct 2009) - jmertic - Bug 33202 - Enable install of SugarCRM on PHP 5.3.0, asserting that the minimum supported version is PHP 5.2.x.
1238
1239 r51443 - 2009-10-12 13:34:36 -0700 (Mon, 12 Oct 2009) - jmertic - Bug 33332 - Made application PHP 5.3 compliant with E_DEPRECATED warnings on by:
1240 - Changing all ereg function to either preg or simple string based ones
1241 - No more references to magic quotes.
1242 - Change all the session_unregister() functions to just unset() the correct session variable instead.
1243
1244 r50375 - 2009-08-24 18:07:43 -0700 (Mon, 24 Aug 2009) - dwong - branch kobe2 from tokyo r50372
1245
1246 r45763 - 2009-04-01 12:16:18 -0700 (Wed, 01 Apr 2009) - majed - Removed half of the require_once and include_onces in the product that were redundant or could be handled easily by the auto loader
1247
1248 r45680 - 2009-03-30 14:34:35 -0700 (Mon, 30 Mar 2009) - Samir Gandhi - modifeid serializeSchema to generate WS-I compliant WSDL
1249
1250 r42807 - 2008-12-29 11:16:59 -0800 (Mon, 29 Dec 2008) - dwong - Branch from trunk/sugarcrm r42806 to branches/tokyo/sugarcrm
1251
1252 r42645 - 2008-12-18 13:41:08 -0800 (Thu, 18 Dec 2008) - awu - merging maint_5_2_0 rev41336:HEAD to trunk
1253
1254 r41647 - 2008-11-11 17:44:30 -0800 (Tue, 11 Nov 2008) - majed - Fixes a few bugs 
1255
1256 r41596 - 2008-11-10 19:20:04 -0800 (Mon, 10 Nov 2008) - Samir Gandhi - modified to set $method in the code
1257
1258 r41558 - 2008-11-10 14:35:34 -0800 (Mon, 10 Nov 2008) - majed - changes nusoap to allow for registering classes 
1259
1260 r39619 - 2008-09-09 13:41:34 -0700 (Tue, 09 Sep 2008) - jmertic - Bug 24827 - Remove all instances where we return a new object and assign it by reference, since this is deprecated in PHP 5 and emits E_DEPRECATED errors in PHP 5.3.
1261 Touched:
1262 - data/SugarBean.php
1263 - include/domit/php_http_client_generic.php
1264 - include/domit/php_http_connector.php
1265 - include/domit/testing_domit.php
1266 - include/domit/xml_domit_getelementsbypath.php
1267 - include/domit/xml_domit_lite_parser.php
1268 - include/domit/xml_domit_nodemaps.php
1269 - include/domit/xml_domit_parser.php
1270 - include/domit/xml_domit_shared.php
1271 - include/generic/SugarWidgets/SugarWidgetField.php
1272 - include/generic/SugarWidgets/SugarWidgetReportField.php
1273 - include/ListView/ProcessView.php
1274 - include/nusoap/class.soapclient.php
1275 - include/nusoap/nusoap.php
1276 - include/nusoap/nusoapmime.php
1277 - include/Pear/HTML_Safe/Safe.php
1278 - include/Pear/XML_HTMLSax3/HTMLSax3.php
1279 - modules/Administration/RebuildWorkFlow.php
1280 - modules/Expressions/RelateSelector.php
1281 - modules/Reports/templates/templates_reports.php
1282 - modules/WorkFlow/Delete.php
1283 - modules/WorkFlow/Save.php
1284 - modules/WorkFlow/SaveSequence.php
1285 - modules/WorkFlow/WorkFlow.php
1286 - modules/WorkFlowActionShells/CreateStep1.php
1287 - modules/WorkFlowActionShells/CreateStep2.php
1288 - modules/WorkFlowActionShells/Save.php
1289 - modules/WorkFlowActionShells/WorkFlowActionShell.php
1290 - modules/WorkFlowAlerts/Save.php
1291 - modules/WorkFlowAlerts/WorkFlowAlert.php
1292 - modules/WorkFlowAlertShells/DetailView.php
1293 - modules/WorkFlowAlertShells/WorkFlowAlertShell.php
1294 - modules/WorkFlowTriggerShells/CreateStep1.php
1295 - modules/WorkFlowTriggerShells/CreateStepFilter.php
1296 - modules/WorkFlowTriggerShells/SaveFilter.php
1297 - modules/WorkFlowTriggerShells/WorkFlowTriggerShell.php
1298 - soap/SoapHelperFunctions.php
1299 - test/modules/DynamicFields/DynamicFields_Bug24095_test.php
1300 - test/simpletest/browser.php
1301 - test/simpletest/default_reporter.php
1302 - test/simpletest/detached.php
1303 - test/simpletest/eclipse.php
1304 - test/simpletest/expectation.php
1305 - test/simpletest/extensions/pear_test_case.php
1306 - test/simpletest/form.php
1307 - test/simpletest/http.php
1308 - test/simpletest/mock_objects.php
1309 - test/simpletest/page.php
1310 - test/simpletest/parser.php
1311 - test/simpletest/remote.php
1312 - test/simpletest/shell_tester.php
1313 - test/simpletest/simple_test.php
1314 - test/simpletest/simpletest.php
1315 - test/simpletest/test/acceptance_test.php
1316 - test/simpletest/test/adapter_test.php
1317 - test/simpletest/test/authentication_test.php
1318 - test/simpletest/test/browser_test.php
1319 - test/simpletest/test/collector_test.php
1320 - test/simpletest/test/compatibility_test.php
1321 - test/simpletest/test/detached_test.php
1322 - test/simpletest/test/eclipse_test.php
1323 - test/simpletest/test/encoding_test.php
1324 - test/simpletest/test/errors_test.php
1325 - test/simpletest/test/expectation_test.php
1326 - test/simpletest/test/form_test.php
1327 - test/simpletest/test/frames_test.php
1328 - test/simpletest/test/http_test.php
1329 - test/simpletest/test/live_test.php
1330 - test/simpletest/test/mock_objects_test.php
1331 - test/simpletest/test/page_test.php
1332 - test/simpletest/test/parse_error_test.php
1333 - test/simpletest/test/parser_test.php
1334 - test/simpletest/test/remote_test.php
1335 - test/simpletest/test/shell_test.php
1336 - test/simpletest/test/shell_tester_test.php
1337 - test/simpletest/test/simpletest_test.php
1338 - test/simpletest/test/site/page_request.php
1339 - test/simpletest/test/tag_test.php
1340 - test/simpletest/test/unit_tester_test.php
1341 - test/simpletest/test/user_agent_test.php
1342 - test/simpletest/test/visual_test.php
1343 - test/simpletest/test/xml_test.php
1344 - test/simpletest/test_case.php
1345 - test/simpletest/ui/array_reporter/test.php
1346 - test/simpletest/ui/recorder/test.php
1347 - test/simpletest/unit_tester.php
1348 - test/simpletest/url.php
1349 - test/simpletest/user_agent.php
1350 - test/simpletest/web_tester.php
1351 - test/spikephpcoverage/src/PEAR.php
1352 - test/spikephpcoverage/src/util/Utility.php
1353 - test/spikephpcoverage/src/XML/Parser.php
1354 - test/spikephpcoverage/src/XML/Parser/Simple.php
1355 - test/test_utilities/SugarTest_SimpleBrowser.php
1356
1357 r38362 - 2008-07-28 14:06:59 -0700 (Mon, 28 Jul 2008) - roger - bug: 23897. Using print_r when using the debug statement in nusoap will print out the statements to the screen if the call is coming from the UI.
1358
1359 r38300 - 2008-07-25 13:33:43 -0700 (Fri, 25 Jul 2008) - Samir Gandhi - put the debug in parseresponse function
1360
1361 r38293 - 2008-07-25 12:32:34 -0700 (Fri, 25 Jul 2008) - Samir Gandhi - to put all the debug statements return value in the call function
1362
1363 r36824 - 2008-06-18 09:26:11 -0700 (Wed, 18 Jun 2008) - roger - bug: 21832
1364
1365 r26422 - 2007-09-05 17:29:12 -0700 (Wed, 05 Sep 2007) - majed - migrate from beta 1 to trunk
1366
1367 r15787 - 2006-08-10 10:14:41 -0700 (Thu, 10 Aug 2006) - roger - RRS: bug 7961
1368
1369 r14701 - 2006-07-17 13:37:26 -0700 (Mon, 17 Jul 2006) - roger - RRS: bug 5801
1370
1371 r13782 - 2006-06-06 10:58:55 -0700 (Tue, 06 Jun 2006) - majed - changes entry point code
1372
1373 r11466 - 2006-02-01 15:49:47 -0800 (Wed, 01 Feb 2006) - jacob - Adding extra !empty check to get around a PHP warning.
1374
1375 r11115 - 2006-01-17 14:54:45 -0800 (Tue, 17 Jan 2006) - majed - add entry point validation
1376
1377 r10585 - 2005-12-13 14:42:26 -0800 (Tue, 13 Dec 2005) - majed - adds new license mechanisim
1378
1379 r10170 - 2005-12-05 18:37:46 -0800 (Mon, 05 Dec 2005) - majed - fixes various issues
1380
1381 r8999 - 2005-11-04 05:26:49 -0800 (Fri, 04 Nov 2005) - roger - When nusoap was upgraded we had an issue with the user's default language not being populated during a soap request. I determined the reason this was happening and have checked in the corresponding change to nusoap.
1382
1383 r8991 - 2005-11-03 19:07:25 -0800 (Thu, 03 Nov 2005) - majed - fixes nusoap issue
1384
1385 r8846 - 2005-10-31 11:01:12 -0800 (Mon, 31 Oct 2005) - majed - new version of nusoap
1386
1387 r7905 - 2005-09-21 19:12:57 -0700 (Wed, 21 Sep 2005) - majed - restores old nusoap pre & with a few fixes
1388
1389 r7861 - 2005-09-20 15:40:25 -0700 (Tue, 20 Sep 2005) - majed - & fix for 3.5.1
1390
1391 r7452 - 2005-08-17 11:32:34 -0700 (Wed, 17 Aug 2005) - majed - changes soap to nusoap
1392
1393 r5820 - 2005-06-21 14:22:24 -0700 (Tue, 21 Jun 2005) - majed - fixes issues with nusoap and with custom fields
1394
1395 r5462 - 2005-05-25 13:50:11 -0700 (Wed, 25 May 2005) - majed - upgraded nusoap to .6.9
1396
1397 r5104 - 2005-05-04 15:33:41 -0700 (Wed, 04 May 2005) - majed - gets rid of HTTP_GET_VARS and what not which has been deprecated
1398
1399 r573 - 2004-09-04 13:03:32 -0700 (Sat, 04 Sep 2004) - sugarclint - undoing copyrights added in inadvertantly.  --clint
1400
1401 r546 - 2004-09-03 11:49:38 -0700 (Fri, 03 Sep 2004) - sugarmsi - removed echo count
1402
1403 r354 - 2004-08-02 23:00:37 -0700 (Mon, 02 Aug 2004) - sugarjacob - Adding Soap
1404
1405
1406 */
1407
1408
1409
1410
1411
1412 /**
1413 * Contains information for a SOAP fault.
1414 * Mainly used for returning faults from deployed functions
1415 * in a server instance.
1416 * @author   Dietrich Ayala <dietrich@ganx4.com>
1417
1418 * @access public
1419 */
1420 class nusoap_fault extends nusoap_base {
1421         /**
1422          * The fault code (client|server)
1423          * @var string
1424          * @access private
1425          */
1426         var $faultcode;
1427         /**
1428          * The fault actor
1429          * @var string
1430          * @access private
1431          */
1432         var $faultactor;
1433         /**
1434          * The fault string, a description of the fault
1435          * @var string
1436          * @access private
1437          */
1438         var $faultstring;
1439         /**
1440          * The fault detail, typically a string or array of string
1441          * @var mixed
1442          * @access private
1443          */
1444         var $faultdetail;
1445
1446         /**
1447         * constructor
1448     *
1449     * @param string $faultcode (SOAP-ENV:Client | SOAP-ENV:Server)
1450     * @param string $faultactor only used when msg routed between multiple actors
1451     * @param string $faultstring human readable error message
1452     * @param mixed $faultdetail detail, typically a string or array of string
1453         */
1454         function nusoap_fault($faultcode,$faultactor='',$faultstring='',$faultdetail=''){
1455                 parent::nusoap_base();
1456                 $this->faultcode = $faultcode;
1457                 $this->faultactor = $faultactor;
1458                 $this->faultstring = $faultstring;
1459                 $this->faultdetail = $faultdetail;
1460         }
1461
1462         /**
1463         * serialize a fault
1464         *
1465         * @return       string  The serialization of the fault instance.
1466         * @access   public
1467         */
1468         function serialize(){
1469                 $ns_string = '';
1470                 foreach($this->namespaces as $k => $v){
1471                         $ns_string .= "\n  xmlns:$k=\"$v\"";
1472                 }
1473                 $return_msg =
1474                         '<?xml version="1.0" encoding="'.$this->soap_defencoding.'"?>'.
1475                         '<SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"'.$ns_string.">\n".
1476                                 '<SOAP-ENV:Body>'.
1477                                 '<SOAP-ENV:Fault>'.
1478                                         $this->serialize_val($this->faultcode, 'faultcode').
1479                                         $this->serialize_val($this->faultactor, 'faultactor').
1480                                         $this->serialize_val($this->faultstring, 'faultstring').
1481                                         $this->serialize_val($this->faultdetail, 'detail').
1482                                 '</SOAP-ENV:Fault>'.
1483                                 '</SOAP-ENV:Body>'.
1484                         '</SOAP-ENV:Envelope>';
1485                 return $return_msg;
1486         }
1487 }
1488
1489 /**
1490  * Backward compatibility
1491  */
1492 class soap_fault extends nusoap_fault {
1493 }
1494
1495 ?><?php
1496
1497 /*
1498
1499 Modification information for LGPL compliance
1500
1501 r58622 - 2010-10-22 18:18:59 -0700 (Fri, 22 Oct 2010) - engsvnbuild - Author: lam <lam@198.18.142.201>
1502     bug 40066
1503
1504 r58361 - 2010-09-29 16:59:02 -0700 (Wed, 29 Sep 2010) - kjing - Author: Jenny Gonsalves <jenny@sugarcrm.com>
1505     Merging with maint_6_0_1 (svn merge -r 58250:58342)
1506
1507 r57813 - 2010-08-19 10:34:44 -0700 (Thu, 19 Aug 2010) - kjing - Author: John Mertic <jmertic@sugarcrm.com>
1508     Bug 39085 - When loading the opposite search panel via ajax on the ListViews, call the index action instead of the ListView action to avoid touching pre-MVC code by accident.
1509
1510 r57707 - 2010-08-10 12:26:13 -0700 (Tue, 10 Aug 2010) - kjing - Author: Stanislav Malyshev <smalyshev@gmail.com>
1511     fix SOAP calls with no parameters
1512
1513 r56990 - 2010-06-16 13:05:36 -0700 (Wed, 16 Jun 2010) - kjing - snapshot "Mango" svn branch to a new one for GitHub sync
1514
1515 r56989 - 2010-06-16 13:01:33 -0700 (Wed, 16 Jun 2010) - kjing - defunt "Mango" svn dev branch before github cutover
1516
1517 r55980 - 2010-04-19 13:31:28 -0700 (Mon, 19 Apr 2010) - kjing - create Mango (6.1) based on windex
1518
1519 r51719 - 2009-10-22 10:18:00 -0700 (Thu, 22 Oct 2009) - mitani - Converted to Build 3  tags and updated the build system 
1520
1521 r51634 - 2009-10-19 13:32:22 -0700 (Mon, 19 Oct 2009) - mitani - Windex is the branch for Sugar Sales 1.0 development
1522
1523 r51508 - 2009-10-14 07:40:23 -0700 (Wed, 14 Oct 2009) - jmertic - More fallout fixes from the PHP 5.3 ereg to preg changes.
1524
1525 r51455 - 2009-10-13 07:56:48 -0700 (Tue, 13 Oct 2009) - jmertic - Bug 33202 - Enable install of SugarCRM on PHP 5.3.0, asserting that the minimum supported version is PHP 5.2.x.
1526
1527 r51443 - 2009-10-12 13:34:36 -0700 (Mon, 12 Oct 2009) - jmertic - Bug 33332 - Made application PHP 5.3 compliant with E_DEPRECATED warnings on by:
1528 - Changing all ereg function to either preg or simple string based ones
1529 - No more references to magic quotes.
1530 - Change all the session_unregister() functions to just unset() the correct session variable instead.
1531
1532 r50375 - 2009-08-24 18:07:43 -0700 (Mon, 24 Aug 2009) - dwong - branch kobe2 from tokyo r50372
1533
1534 r45763 - 2009-04-01 12:16:18 -0700 (Wed, 01 Apr 2009) - majed - Removed half of the require_once and include_onces in the product that were redundant or could be handled easily by the auto loader
1535
1536 r45680 - 2009-03-30 14:34:35 -0700 (Mon, 30 Mar 2009) - Samir Gandhi - modifeid serializeSchema to generate WS-I compliant WSDL
1537
1538 r42807 - 2008-12-29 11:16:59 -0800 (Mon, 29 Dec 2008) - dwong - Branch from trunk/sugarcrm r42806 to branches/tokyo/sugarcrm
1539
1540 r42645 - 2008-12-18 13:41:08 -0800 (Thu, 18 Dec 2008) - awu - merging maint_5_2_0 rev41336:HEAD to trunk
1541
1542 r41647 - 2008-11-11 17:44:30 -0800 (Tue, 11 Nov 2008) - majed - Fixes a few bugs 
1543
1544 r41596 - 2008-11-10 19:20:04 -0800 (Mon, 10 Nov 2008) - Samir Gandhi - modified to set $method in the code
1545
1546 r41558 - 2008-11-10 14:35:34 -0800 (Mon, 10 Nov 2008) - majed - changes nusoap to allow for registering classes 
1547
1548 r39619 - 2008-09-09 13:41:34 -0700 (Tue, 09 Sep 2008) - jmertic - Bug 24827 - Remove all instances where we return a new object and assign it by reference, since this is deprecated in PHP 5 and emits E_DEPRECATED errors in PHP 5.3.
1549 Touched:
1550 - data/SugarBean.php
1551 - include/domit/php_http_client_generic.php
1552 - include/domit/php_http_connector.php
1553 - include/domit/testing_domit.php
1554 - include/domit/xml_domit_getelementsbypath.php
1555 - include/domit/xml_domit_lite_parser.php
1556 - include/domit/xml_domit_nodemaps.php
1557 - include/domit/xml_domit_parser.php
1558 - include/domit/xml_domit_shared.php
1559 - include/generic/SugarWidgets/SugarWidgetField.php
1560 - include/generic/SugarWidgets/SugarWidgetReportField.php
1561 - include/ListView/ProcessView.php
1562 - include/nusoap/class.soapclient.php
1563 - include/nusoap/nusoap.php
1564 - include/nusoap/nusoapmime.php
1565 - include/Pear/HTML_Safe/Safe.php
1566 - include/Pear/XML_HTMLSax3/HTMLSax3.php
1567 - modules/Administration/RebuildWorkFlow.php
1568 - modules/Expressions/RelateSelector.php
1569 - modules/Reports/templates/templates_reports.php
1570 - modules/WorkFlow/Delete.php
1571 - modules/WorkFlow/Save.php
1572 - modules/WorkFlow/SaveSequence.php
1573 - modules/WorkFlow/WorkFlow.php
1574 - modules/WorkFlowActionShells/CreateStep1.php
1575 - modules/WorkFlowActionShells/CreateStep2.php
1576 - modules/WorkFlowActionShells/Save.php
1577 - modules/WorkFlowActionShells/WorkFlowActionShell.php
1578 - modules/WorkFlowAlerts/Save.php
1579 - modules/WorkFlowAlerts/WorkFlowAlert.php
1580 - modules/WorkFlowAlertShells/DetailView.php
1581 - modules/WorkFlowAlertShells/WorkFlowAlertShell.php
1582 - modules/WorkFlowTriggerShells/CreateStep1.php
1583 - modules/WorkFlowTriggerShells/CreateStepFilter.php
1584 - modules/WorkFlowTriggerShells/SaveFilter.php
1585 - modules/WorkFlowTriggerShells/WorkFlowTriggerShell.php
1586 - soap/SoapHelperFunctions.php
1587 - test/modules/DynamicFields/DynamicFields_Bug24095_test.php
1588 - test/simpletest/browser.php
1589 - test/simpletest/default_reporter.php
1590 - test/simpletest/detached.php
1591 - test/simpletest/eclipse.php
1592 - test/simpletest/expectation.php
1593 - test/simpletest/extensions/pear_test_case.php
1594 - test/simpletest/form.php
1595 - test/simpletest/http.php
1596 - test/simpletest/mock_objects.php
1597 - test/simpletest/page.php
1598 - test/simpletest/parser.php
1599 - test/simpletest/remote.php
1600 - test/simpletest/shell_tester.php
1601 - test/simpletest/simple_test.php
1602 - test/simpletest/simpletest.php
1603 - test/simpletest/test/acceptance_test.php
1604 - test/simpletest/test/adapter_test.php
1605 - test/simpletest/test/authentication_test.php
1606 - test/simpletest/test/browser_test.php
1607 - test/simpletest/test/collector_test.php
1608 - test/simpletest/test/compatibility_test.php
1609 - test/simpletest/test/detached_test.php
1610 - test/simpletest/test/eclipse_test.php
1611 - test/simpletest/test/encoding_test.php
1612 - test/simpletest/test/errors_test.php
1613 - test/simpletest/test/expectation_test.php
1614 - test/simpletest/test/form_test.php
1615 - test/simpletest/test/frames_test.php
1616 - test/simpletest/test/http_test.php
1617 - test/simpletest/test/live_test.php
1618 - test/simpletest/test/mock_objects_test.php
1619 - test/simpletest/test/page_test.php
1620 - test/simpletest/test/parse_error_test.php
1621 - test/simpletest/test/parser_test.php
1622 - test/simpletest/test/remote_test.php
1623 - test/simpletest/test/shell_test.php
1624 - test/simpletest/test/shell_tester_test.php
1625 - test/simpletest/test/simpletest_test.php
1626 - test/simpletest/test/site/page_request.php
1627 - test/simpletest/test/tag_test.php
1628 - test/simpletest/test/unit_tester_test.php
1629 - test/simpletest/test/user_agent_test.php
1630 - test/simpletest/test/visual_test.php
1631 - test/simpletest/test/xml_test.php
1632 - test/simpletest/test_case.php
1633 - test/simpletest/ui/array_reporter/test.php
1634 - test/simpletest/ui/recorder/test.php
1635 - test/simpletest/unit_tester.php
1636 - test/simpletest/url.php
1637 - test/simpletest/user_agent.php
1638 - test/simpletest/web_tester.php
1639 - test/spikephpcoverage/src/PEAR.php
1640 - test/spikephpcoverage/src/util/Utility.php
1641 - test/spikephpcoverage/src/XML/Parser.php
1642 - test/spikephpcoverage/src/XML/Parser/Simple.php
1643 - test/test_utilities/SugarTest_SimpleBrowser.php
1644
1645 r38362 - 2008-07-28 14:06:59 -0700 (Mon, 28 Jul 2008) - roger - bug: 23897. Using print_r when using the debug statement in nusoap will print out the statements to the screen if the call is coming from the UI.
1646
1647 r38300 - 2008-07-25 13:33:43 -0700 (Fri, 25 Jul 2008) - Samir Gandhi - put the debug in parseresponse function
1648
1649 r38293 - 2008-07-25 12:32:34 -0700 (Fri, 25 Jul 2008) - Samir Gandhi - to put all the debug statements return value in the call function
1650
1651 r36824 - 2008-06-18 09:26:11 -0700 (Wed, 18 Jun 2008) - roger - bug: 21832
1652
1653 r26422 - 2007-09-05 17:29:12 -0700 (Wed, 05 Sep 2007) - majed - migrate from beta 1 to trunk
1654
1655 r15787 - 2006-08-10 10:14:41 -0700 (Thu, 10 Aug 2006) - roger - RRS: bug 7961
1656
1657 r14701 - 2006-07-17 13:37:26 -0700 (Mon, 17 Jul 2006) - roger - RRS: bug 5801
1658
1659 r13782 - 2006-06-06 10:58:55 -0700 (Tue, 06 Jun 2006) - majed - changes entry point code
1660
1661 r11466 - 2006-02-01 15:49:47 -0800 (Wed, 01 Feb 2006) - jacob - Adding extra !empty check to get around a PHP warning.
1662
1663 r11115 - 2006-01-17 14:54:45 -0800 (Tue, 17 Jan 2006) - majed - add entry point validation
1664
1665 r10585 - 2005-12-13 14:42:26 -0800 (Tue, 13 Dec 2005) - majed - adds new license mechanisim
1666
1667 r10170 - 2005-12-05 18:37:46 -0800 (Mon, 05 Dec 2005) - majed - fixes various issues
1668
1669 r8999 - 2005-11-04 05:26:49 -0800 (Fri, 04 Nov 2005) - roger - When nusoap was upgraded we had an issue with the user's default language not being populated during a soap request. I determined the reason this was happening and have checked in the corresponding change to nusoap.
1670
1671 r8991 - 2005-11-03 19:07:25 -0800 (Thu, 03 Nov 2005) - majed - fixes nusoap issue
1672
1673 r8846 - 2005-10-31 11:01:12 -0800 (Mon, 31 Oct 2005) - majed - new version of nusoap
1674
1675 r7905 - 2005-09-21 19:12:57 -0700 (Wed, 21 Sep 2005) - majed - restores old nusoap pre & with a few fixes
1676
1677 r7861 - 2005-09-20 15:40:25 -0700 (Tue, 20 Sep 2005) - majed - & fix for 3.5.1
1678
1679 r7452 - 2005-08-17 11:32:34 -0700 (Wed, 17 Aug 2005) - majed - changes soap to nusoap
1680
1681 r5820 - 2005-06-21 14:22:24 -0700 (Tue, 21 Jun 2005) - majed - fixes issues with nusoap and with custom fields
1682
1683 r5462 - 2005-05-25 13:50:11 -0700 (Wed, 25 May 2005) - majed - upgraded nusoap to .6.9
1684
1685 r5104 - 2005-05-04 15:33:41 -0700 (Wed, 04 May 2005) - majed - gets rid of HTTP_GET_VARS and what not which has been deprecated
1686
1687 r573 - 2004-09-04 13:03:32 -0700 (Sat, 04 Sep 2004) - sugarclint - undoing copyrights added in inadvertantly.  --clint
1688
1689 r546 - 2004-09-03 11:49:38 -0700 (Fri, 03 Sep 2004) - sugarmsi - removed echo count
1690
1691 r354 - 2004-08-02 23:00:37 -0700 (Mon, 02 Aug 2004) - sugarjacob - Adding Soap
1692
1693
1694 */
1695
1696
1697
1698
1699
1700 /**
1701 * parses an XML Schema, allows access to it's data, other utility methods.
1702 * imperfect, no validation... yet, but quite functional.
1703 *
1704 * @author   Dietrich Ayala <dietrich@ganx4.com>
1705 * @author   Scott Nichol <snichol@users.sourceforge.net>
1706
1707 * @access   public
1708 */
1709 class nusoap_xmlschema extends nusoap_base  {
1710         
1711         // files
1712         var $schema = '';
1713         var $xml = '';
1714         // namespaces
1715         var $enclosingNamespaces;
1716         // schema info
1717         var $schemaInfo = array();
1718         var $schemaTargetNamespace = '';
1719         // types, elements, attributes defined by the schema
1720         var $attributes = array();
1721         var $complexTypes = array();
1722         var $complexTypeStack = array();
1723         var $currentComplexType = null;
1724         var $elements = array();
1725         var $elementStack = array();
1726         var $currentElement = null;
1727         var $simpleTypes = array();
1728         var $simpleTypeStack = array();
1729         var $currentSimpleType = null;
1730         // imports
1731         var $imports = array();
1732         // parser vars
1733         var $parser;
1734         var $position = 0;
1735         var $depth = 0;
1736         var $depth_array = array();
1737         var $message = array();
1738         var $defaultNamespace = array();
1739     
1740         /**
1741         * constructor
1742         *
1743         * @param    string $schema schema document URI
1744         * @param    string $xml xml document URI
1745         * @param        string $namespaces namespaces defined in enclosing XML
1746         * @access   public
1747         */
1748         function nusoap_xmlschema($schema='',$xml='',$namespaces=array()){
1749                 parent::nusoap_base();
1750                 $this->debug('nusoap_xmlschema class instantiated, inside constructor');
1751                 // files
1752                 $this->schema = $schema;
1753                 $this->xml = $xml;
1754
1755                 // namespaces
1756                 $this->enclosingNamespaces = $namespaces;
1757                 $this->namespaces = array_merge($this->namespaces, $namespaces);
1758
1759                 // parse schema file
1760                 if($schema != ''){
1761                         $this->debug('initial schema file: '.$schema);
1762                         $this->parseFile($schema, 'schema');
1763                 }
1764
1765                 // parse xml file
1766                 if($xml != ''){
1767                         $this->debug('initial xml file: '.$xml);
1768                         $this->parseFile($xml, 'xml');
1769                 }
1770
1771         }
1772
1773     /**
1774     * parse an XML file
1775     *
1776     * @param string $xml path/URL to XML file
1777     * @param string $type (schema | xml)
1778         * @return boolean
1779     * @access public
1780     */
1781         function parseFile($xml,$type){
1782                 // parse xml file
1783                 if($xml != ""){
1784                         $xmlStr = @join("",@file($xml));
1785                         if($xmlStr == ""){
1786                                 $msg = 'Error reading XML from '.$xml;
1787                                 $this->setError($msg);
1788                                 $this->debug($msg);
1789                         return false;
1790                         } else {
1791                                 $this->debug("parsing $xml");
1792                                 $this->parseString($xmlStr,$type);
1793                                 $this->debug("done parsing $xml");
1794                         return true;
1795                         }
1796                 }
1797                 return false;
1798         }
1799
1800         /**
1801         * parse an XML string
1802         *
1803         * @param    string $xml path or URL
1804     * @param    string $type (schema|xml)
1805         * @access   private
1806         */
1807         function parseString($xml,$type){
1808                 // parse xml string
1809                 if($xml != ""){
1810
1811                 // Create an XML parser.
1812                 $this->parser = xml_parser_create();
1813                 // Set the options for parsing the XML data.
1814                 xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
1815
1816                 // Set the object for the parser.
1817                 xml_set_object($this->parser, $this);
1818
1819                 // Set the element handlers for the parser.
1820                         if($type == "schema"){
1821                         xml_set_element_handler($this->parser, 'schemaStartElement','schemaEndElement');
1822                         xml_set_character_data_handler($this->parser,'schemaCharacterData');
1823                         } elseif($type == "xml"){
1824                                 xml_set_element_handler($this->parser, 'xmlStartElement','xmlEndElement');
1825                         xml_set_character_data_handler($this->parser,'xmlCharacterData');
1826                         }
1827
1828                     // Parse the XML file.
1829                     if(!xml_parse($this->parser,$xml,true)){
1830                         // Display an error message.
1831                                 $errstr = sprintf('XML error parsing XML schema on line %d: %s',
1832                                 xml_get_current_line_number($this->parser),
1833                                 xml_error_string(xml_get_error_code($this->parser))
1834                                 );
1835                                 $this->debug($errstr);
1836                                 $this->debug("XML payload:\n" . $xml);
1837                                 $this->setError($errstr);
1838                 }
1839             
1840                         xml_parser_free($this->parser);
1841                 } else{
1842                         $this->debug('no xml passed to parseString()!!');
1843                         $this->setError('no xml passed to parseString()!!');
1844                 }
1845         }
1846
1847         /**
1848          * gets a type name for an unnamed type
1849          *
1850          * @param       string  Element name
1851          * @return      string  A type name for an unnamed type
1852          * @access      private
1853          */
1854         function CreateTypeName($ename) {
1855                 $scope = '';
1856                 for ($i = 0; $i < count($this->complexTypeStack); $i++) {
1857                         $scope .= $this->complexTypeStack[$i] . '_';
1858                 }
1859                 return $scope . $ename . '_ContainedType';
1860         }
1861         
1862         /**
1863         * start-element handler
1864         *
1865         * @param    string $parser XML parser object
1866         * @param    string $name element name
1867         * @param    string $attrs associative array of attributes
1868         * @access   private
1869         */
1870         function schemaStartElement($parser, $name, $attrs) {
1871                 
1872                 // position in the total number of elements, starting from 0
1873                 $pos = $this->position++;
1874                 $depth = $this->depth++;
1875                 // set self as current value for this depth
1876                 $this->depth_array[$depth] = $pos;
1877                 $this->message[$pos] = array('cdata' => ''); 
1878                 if ($depth > 0) {
1879                         $this->defaultNamespace[$pos] = $this->defaultNamespace[$this->depth_array[$depth - 1]];
1880                 } else {
1881                         $this->defaultNamespace[$pos] = false;
1882                 }
1883
1884                 // get element prefix
1885                 if($prefix = $this->getPrefix($name)){
1886                         // get unqualified name
1887                         $name = $this->getLocalPart($name);
1888                 } else {
1889                 $prefix = '';
1890         }
1891                 
1892         // loop thru attributes, expanding, and registering namespace declarations
1893         if(count($attrs) > 0){
1894                 foreach($attrs as $k => $v){
1895                 // if ns declarations, add to class level array of valid namespaces
1896                                 if(preg_match('/^xmlns/',$k)){
1897                         //$this->xdebug("$k: $v");
1898                         //$this->xdebug('ns_prefix: '.$this->getPrefix($k));
1899                         if($ns_prefix = substr(strrchr($k,':'),1)){
1900                                 //$this->xdebug("Add namespace[$ns_prefix] = $v");
1901                                                 $this->namespaces[$ns_prefix] = $v;
1902                                         } else {
1903                                                 $this->defaultNamespace[$pos] = $v;
1904                                                 if (! $this->getPrefixFromNamespace($v)) {
1905                                                         $this->namespaces['ns'.(count($this->namespaces)+1)] = $v;
1906                                                 }
1907                                         }
1908                                         if($v == 'http://www.w3.org/2001/XMLSchema' || $v == 'http://www.w3.org/1999/XMLSchema' || $v == 'http://www.w3.org/2000/10/XMLSchema'){
1909                                                 $this->XMLSchemaVersion = $v;
1910                                                 $this->namespaces['xsi'] = $v.'-instance';
1911                                         }
1912                                 }
1913                 }
1914                 foreach($attrs as $k => $v){
1915                 // expand each attribute
1916                 $k = strpos($k,':') ? $this->expandQname($k) : $k;
1917                 $v = strpos($v,':') ? $this->expandQname($v) : $v;
1918                         $eAttrs[$k] = $v;
1919                 }
1920                 $attrs = $eAttrs;
1921         } else {
1922                 $attrs = array();
1923         }
1924                 // find status, register data
1925                 switch($name){
1926                         case 'all':                     // (optional) compositor content for a complexType
1927                         case 'choice':
1928                         case 'group':
1929                         case 'sequence':
1930                                 //$this->xdebug("compositor $name for currentComplexType: $this->currentComplexType and currentElement: $this->currentElement");
1931                                 $this->complexTypes[$this->currentComplexType]['compositor'] = $name;
1932                                 //if($name == 'all' || $name == 'sequence'){
1933                                 //      $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
1934                                 //}
1935                         break;
1936                         case 'attribute':       // complexType attribute
1937                 //$this->xdebug("parsing attribute $attrs[name] $attrs[ref] of value: ".$attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']);
1938                 $this->xdebug("parsing attribute:");
1939                 $this->appendDebug($this->varDump($attrs));
1940                                 if (!isset($attrs['form'])) {
1941                                         // TODO: handle globals
1942                                         $attrs['form'] = $this->schemaInfo['attributeFormDefault'];
1943                                 }
1944                 if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])) {
1945                                         $v = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
1946                                         if (!strpos($v, ':')) {
1947                                                 // no namespace in arrayType attribute value...
1948                                                 if ($this->defaultNamespace[$pos]) {
1949                                                         // ...so use the default
1950                                                         $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'] = $this->defaultNamespace[$pos] . ':' . $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
1951                                                 }
1952                                         }
1953                 }
1954                 if(isset($attrs['name'])){
1955                                         $this->attributes[$attrs['name']] = $attrs;
1956                                         $aname = $attrs['name'];
1957                                 } elseif(isset($attrs['ref']) && $attrs['ref'] == 'http://schemas.xmlsoap.org/soap/encoding/:arrayType'){
1958                                         if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])) {
1959                                 $aname = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
1960                         } else {
1961                                 $aname = '';
1962                         }
1963                                 } elseif(isset($attrs['ref'])){
1964                                         $aname = $attrs['ref'];
1965                     $this->attributes[$attrs['ref']] = $attrs;
1966                                 }
1967                 
1968                                 if($this->currentComplexType){  // This should *always* be
1969                                         $this->complexTypes[$this->currentComplexType]['attrs'][$aname] = $attrs;
1970                                 }
1971                                 // arrayType attribute
1972                                 if(isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']) || $this->getLocalPart($aname) == 'arrayType'){
1973                                         $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
1974                         $prefix = $this->getPrefix($aname);
1975                                         if(isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])){
1976                                                 $v = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
1977                                         } else {
1978                                                 $v = '';
1979                                         }
1980                     if(strpos($v,'[,]')){
1981                         $this->complexTypes[$this->currentComplexType]['multidimensional'] = true;
1982                     }
1983                     $v = substr($v,0,strpos($v,'[')); // clip the []
1984                     if(!strpos($v,':') && isset($this->typemap[$this->XMLSchemaVersion][$v])){
1985                         $v = $this->XMLSchemaVersion.':'.$v;
1986                     }
1987                     $this->complexTypes[$this->currentComplexType]['arrayType'] = $v;
1988                                 }
1989                         break;
1990                         case 'complexContent':  // (optional) content for a complexType
1991                                 $this->xdebug("do nothing for element $name");
1992                         break;
1993                         case 'complexType':
1994                                 array_push($this->complexTypeStack, $this->currentComplexType);
1995                                 if(isset($attrs['name'])){
1996                                         // TODO: what is the scope of named complexTypes that appear
1997                                         //       nested within other c complexTypes?
1998                                         $this->xdebug('processing named complexType '.$attrs['name']);
1999                                         //$this->currentElement = false;
2000                                         $this->currentComplexType = $attrs['name'];
2001                                         $this->complexTypes[$this->currentComplexType] = $attrs;
2002                                         $this->complexTypes[$this->currentComplexType]['typeClass'] = 'complexType';
2003                                         // This is for constructs like
2004                                         //           <complexType name="ListOfString" base="soap:Array">
2005                                         //                <sequence>
2006                                         //                    <element name="string" type="xsd:string"
2007                                         //                        minOccurs="0" maxOccurs="unbounded" />
2008                                         //                </sequence>
2009                                         //            </complexType>
2010                                         if(isset($attrs['base']) && preg_match('/:Array$/',$attrs['base'])){
2011                                                 $this->xdebug('complexType is unusual array');
2012                                                 $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
2013                                         } else {
2014                                                 $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
2015                                         }
2016                                 } else {
2017                                         $name = $this->CreateTypeName($this->currentElement);
2018                                         $this->xdebug('processing unnamed complexType for element ' . $this->currentElement . ' named ' . $name);
2019                                         $this->currentComplexType = $name;
2020                                         //$this->currentElement = false;
2021                                         $this->complexTypes[$this->currentComplexType] = $attrs;
2022                                         $this->complexTypes[$this->currentComplexType]['typeClass'] = 'complexType';
2023                                         // This is for constructs like
2024                                         //           <complexType name="ListOfString" base="soap:Array">
2025                                         //                <sequence>
2026                                         //                    <element name="string" type="xsd:string"
2027                                         //                        minOccurs="0" maxOccurs="unbounded" />
2028                                         //                </sequence>
2029                                         //            </complexType>
2030                                         if(isset($attrs['base']) && preg_match('/:Array$/',$attrs['base'])){
2031                                                 $this->xdebug('complexType is unusual array');
2032                                                 $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
2033                                         } else {
2034                                                 $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
2035                                         }
2036                                 }
2037                                 $this->complexTypes[$this->currentComplexType]['simpleContent'] = 'false';
2038                         break;
2039                         case 'element':
2040                                 array_push($this->elementStack, $this->currentElement);
2041                                 if (!isset($attrs['form'])) {
2042                                         if ($this->currentComplexType) {
2043                                                 $attrs['form'] = $this->schemaInfo['elementFormDefault'];
2044                                         } else {
2045                                                 // global
2046                                                 $attrs['form'] = 'qualified';
2047                                         }
2048                                 }
2049                                 if(isset($attrs['type'])){
2050                                         $this->xdebug("processing typed element ".$attrs['name']." of type ".$attrs['type']);
2051                                         if (! $this->getPrefix($attrs['type'])) {
2052                                                 if ($this->defaultNamespace[$pos]) {
2053                                                         $attrs['type'] = $this->defaultNamespace[$pos] . ':' . $attrs['type'];
2054                                                         $this->xdebug('used default namespace to make type ' . $attrs['type']);
2055                                                 }
2056                                         }
2057                                         // This is for constructs like
2058                                         //           <complexType name="ListOfString" base="soap:Array">
2059                                         //                <sequence>
2060                                         //                    <element name="string" type="xsd:string"
2061                                         //                        minOccurs="0" maxOccurs="unbounded" />
2062                                         //                </sequence>
2063                                         //            </complexType>
2064                                         if ($this->currentComplexType && $this->complexTypes[$this->currentComplexType]['phpType'] == 'array') {
2065                                                 $this->xdebug('arrayType for unusual array is ' . $attrs['type']);
2066                                                 $this->complexTypes[$this->currentComplexType]['arrayType'] = $attrs['type'];
2067                                         }
2068                                         $this->currentElement = $attrs['name'];
2069                                         $ename = $attrs['name'];
2070                                 } elseif(isset($attrs['ref'])){
2071                                         $this->xdebug("processing element as ref to ".$attrs['ref']);
2072                                         $this->currentElement = "ref to ".$attrs['ref'];
2073                                         $ename = $this->getLocalPart($attrs['ref']);
2074                                 } else {
2075                                         $type = $this->CreateTypeName($this->currentComplexType . '_' . $attrs['name']);
2076                                         $this->xdebug("processing untyped element " . $attrs['name'] . ' type ' . $type);
2077                                         $this->currentElement = $attrs['name'];
2078                                         $attrs['type'] = $this->schemaTargetNamespace . ':' . $type;
2079                                         $ename = $attrs['name'];
2080                                 }
2081                                 if (isset($ename) && $this->currentComplexType) {
2082                                         $this->xdebug("add element $ename to complexType $this->currentComplexType");
2083                                         $this->complexTypes[$this->currentComplexType]['elements'][$ename] = $attrs;
2084                                 } elseif (!isset($attrs['ref'])) {
2085                                         $this->xdebug("add element $ename to elements array");
2086                                         $this->elements[ $attrs['name'] ] = $attrs;
2087                                         $this->elements[ $attrs['name'] ]['typeClass'] = 'element';
2088                                 }
2089                         break;
2090                         case 'enumeration':     //      restriction value list member
2091                                 $this->xdebug('enumeration ' . $attrs['value']);
2092                                 if ($this->currentSimpleType) {
2093                                         $this->simpleTypes[$this->currentSimpleType]['enumeration'][] = $attrs['value'];
2094                                 } elseif ($this->currentComplexType) {
2095                                         $this->complexTypes[$this->currentComplexType]['enumeration'][] = $attrs['value'];
2096                                 }
2097                         break;
2098                         case 'extension':       // simpleContent or complexContent type extension
2099                                 $this->xdebug('extension ' . $attrs['base']);
2100                                 if ($this->currentComplexType) {
2101                                         $ns = $this->getPrefix($attrs['base']);
2102                                         if ($ns == '') {
2103                                                 $this->complexTypes[$this->currentComplexType]['extensionBase'] = $this->schemaTargetNamespace . ':' . $attrs['base'];
2104                                         } else {
2105                                                 $this->complexTypes[$this->currentComplexType]['extensionBase'] = $attrs['base'];
2106                                         }
2107                                 } else {
2108                                         $this->xdebug('no current complexType to set extensionBase');
2109                                 }
2110                         break;
2111                         case 'import':
2112                             if (isset($attrs['schemaLocation'])) {
2113                                         $this->xdebug('import namespace ' . $attrs['namespace'] . ' from ' . $attrs['schemaLocation']);
2114                     $this->imports[$attrs['namespace']][] = array('location' => $attrs['schemaLocation'], 'loaded' => false);
2115                                 } else {
2116                                         $this->xdebug('import namespace ' . $attrs['namespace']);
2117                     $this->imports[$attrs['namespace']][] = array('location' => '', 'loaded' => true);
2118                                         if (! $this->getPrefixFromNamespace($attrs['namespace'])) {
2119                                                 $this->namespaces['ns'.(count($this->namespaces)+1)] = $attrs['namespace'];
2120                                         }
2121                                 }
2122                         break;
2123                         case 'include':
2124                             if (isset($attrs['schemaLocation'])) {
2125                                         $this->xdebug('include into namespace ' . $this->schemaTargetNamespace . ' from ' . $attrs['schemaLocation']);
2126                     $this->imports[$this->schemaTargetNamespace][] = array('location' => $attrs['schemaLocation'], 'loaded' => false);
2127                                 } else {
2128                                         $this->xdebug('ignoring invalid XML Schema construct: include without schemaLocation attribute');
2129                                 }
2130                         break;
2131                         case 'list':    // simpleType value list
2132                                 $this->xdebug("do nothing for element $name");
2133                         break;
2134                         case 'restriction':     // simpleType, simpleContent or complexContent value restriction
2135                                 $this->xdebug('restriction ' . $attrs['base']);
2136                                 if($this->currentSimpleType){
2137                                         $this->simpleTypes[$this->currentSimpleType]['type'] = $attrs['base'];
2138                                 } elseif($this->currentComplexType){
2139                                         $this->complexTypes[$this->currentComplexType]['restrictionBase'] = $attrs['base'];
2140                                         if(strstr($attrs['base'],':') == ':Array'){
2141                                                 $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
2142                                         }
2143                                 }
2144                         break;
2145                         case 'schema':
2146                                 $this->schemaInfo = $attrs;
2147                                 $this->schemaInfo['schemaVersion'] = $this->getNamespaceFromPrefix($prefix);
2148                                 if (isset($attrs['targetNamespace'])) {
2149                                         $this->schemaTargetNamespace = $attrs['targetNamespace'];
2150                                 }
2151                                 if (!isset($attrs['elementFormDefault'])) {
2152                                         $this->schemaInfo['elementFormDefault'] = 'unqualified';
2153                                 }
2154                                 if (!isset($attrs['attributeFormDefault'])) {
2155                                         $this->schemaInfo['attributeFormDefault'] = 'unqualified';
2156                                 }
2157                         break;
2158                         case 'simpleContent':   // (optional) content for a complexType
2159                                 if ($this->currentComplexType) {        // This should *always* be
2160                                         $this->complexTypes[$this->currentComplexType]['simpleContent'] = 'true';
2161                                 } else {
2162                                         $this->xdebug("do nothing for element $name because there is no current complexType");
2163                                 }
2164                         break;
2165                         case 'simpleType':
2166                                 array_push($this->simpleTypeStack, $this->currentSimpleType);
2167                                 if(isset($attrs['name'])){
2168                                         $this->xdebug("processing simpleType for name " . $attrs['name']);
2169                                         $this->currentSimpleType = $attrs['name'];
2170                                         $this->simpleTypes[ $attrs['name'] ] = $attrs;
2171                                         $this->simpleTypes[ $attrs['name'] ]['typeClass'] = 'simpleType';
2172                                         $this->simpleTypes[ $attrs['name'] ]['phpType'] = 'scalar';
2173                                 } else {
2174                                         $name = $this->CreateTypeName($this->currentComplexType . '_' . $this->currentElement);
2175                                         $this->xdebug('processing unnamed simpleType for element ' . $this->currentElement . ' named ' . $name);
2176                                         $this->currentSimpleType = $name;
2177                                         //$this->currentElement = false;
2178                                         $this->simpleTypes[$this->currentSimpleType] = $attrs;
2179                                         $this->simpleTypes[$this->currentSimpleType]['phpType'] = 'scalar';
2180                                 }
2181                         break;
2182                         case 'union':   // simpleType type list
2183                                 $this->xdebug("do nothing for element $name");
2184                         break;
2185                         default:
2186                                 $this->xdebug("do not have any logic to process element $name");
2187                 }
2188         }
2189
2190         /**
2191         * end-element handler
2192         *
2193         * @param    string $parser XML parser object
2194         * @param    string $name element name
2195         * @access   private
2196         */
2197         function schemaEndElement($parser, $name) {
2198                 // bring depth down a notch
2199                 $this->depth--;
2200                 // position of current element is equal to the last value left in depth_array for my depth
2201                 if(isset($this->depth_array[$this->depth])){
2202                 $pos = $this->depth_array[$this->depth];
2203         }
2204                 // get element prefix
2205                 if ($prefix = $this->getPrefix($name)){
2206                         // get unqualified name
2207                         $name = $this->getLocalPart($name);
2208                 } else {
2209                 $prefix = '';
2210         }
2211                 // move on...
2212                 if($name == 'complexType'){
2213                         $this->xdebug('done processing complexType ' . ($this->currentComplexType ? $this->currentComplexType : '(unknown)'));
2214                         $this->xdebug($this->varDump($this->complexTypes[$this->currentComplexType]));
2215                         $this->currentComplexType = array_pop($this->complexTypeStack);
2216                         //$this->currentElement = false;
2217                 }
2218                 if($name == 'element'){
2219                         $this->xdebug('done processing element ' . ($this->currentElement ? $this->currentElement : '(unknown)'));
2220                         $this->currentElement = array_pop($this->elementStack);
2221                 }
2222                 if($name == 'simpleType'){
2223                         $this->xdebug('done processing simpleType ' . ($this->currentSimpleType ? $this->currentSimpleType : '(unknown)'));
2224                         $this->xdebug($this->varDump($this->simpleTypes[$this->currentSimpleType]));
2225                         $this->currentSimpleType = array_pop($this->simpleTypeStack);
2226                 }
2227         }
2228
2229         /**
2230         * element content handler
2231         *
2232         * @param    string $parser XML parser object
2233         * @param    string $data element content
2234         * @access   private
2235         */
2236         function schemaCharacterData($parser, $data){
2237                 $pos = $this->depth_array[$this->depth - 1];
2238                 $this->message[$pos]['cdata'] .= $data;
2239         }
2240
2241         /**
2242         * serialize the schema
2243         *
2244         * @access   public
2245         */
2246         function serializeSchema(){
2247
2248                 $schemaPrefix = $this->getPrefixFromNamespace($this->XMLSchemaVersion);
2249                 $xml = '';
2250                 // imports
2251                 $schemaLocationCount = 0;
2252                 if (sizeof($this->imports) > 0) {
2253                         foreach($this->imports as $ns => $list) {
2254                                 foreach ($list as $ii) {
2255                                         if ($ii['location'] != '') {
2256                                                 $xml .= " <$schemaPrefix:import location=\"" . $ii['location'] . '" namespace="' . $ns . "\" />\n";
2257                                         } else {
2258                                                 if ($schemaLocationCount == 0) {
2259                                                         $xml .= " <$schemaPrefix:import namespace=\"" . $ns . "\" schemaLocation=\"http://schemas.xmlsoap.org/soap/encoding/\"/>\n";
2260                                                 } else {
2261                                                         $xml .= " <$schemaPrefix:import namespace=\"" . $ns . "\" />\n";
2262                                                 }
2263                                         }
2264                                 }
2265                         } 
2266                 } 
2267                 // complex types
2268                 foreach($this->complexTypes as $typeName => $attrs){
2269                         $contentStr = '';
2270                         // serialize child elements
2271                         if(isset($attrs['elements']) && (count($attrs['elements']) > 0)){
2272                                 foreach($attrs['elements'] as $element => $eParts){
2273                                         if(isset($eParts['ref'])){
2274                                                 $contentStr .= "   <$schemaPrefix:element ref=\"$element\"/>\n";
2275                                         } else {
2276                                                 $contentStr .= "   <$schemaPrefix:element name=\"$element\" type=\"" . $this->contractQName($eParts['type']) . "\"";
2277                                                 foreach ($eParts as $aName => $aValue) {
2278                                                         // handle, e.g., abstract, default, form, minOccurs, maxOccurs, nillable
2279                                                         if ($aName != 'name' && $aName != 'type') {
2280                                                                 $contentStr .= " $aName=\"$aValue\"";
2281                                                         }
2282                                                 }
2283                                                 $contentStr .= "/>\n";
2284                                         }
2285                                 }
2286                                 // compositor wraps elements
2287                                 if (isset($attrs['compositor']) && ($attrs['compositor'] != '')) {
2288                                         $contentStr = "  <$schemaPrefix:$attrs[compositor]>\n".$contentStr."  </$schemaPrefix:$attrs[compositor]>\n";
2289                                 }
2290                         }
2291                         // attributes
2292                         if(isset($attrs['attrs']) && (count($attrs['attrs']) >= 1)){
2293                                 foreach($attrs['attrs'] as $attr => $aParts){
2294                                         $contentStr .= "    <$schemaPrefix:attribute";
2295                                         foreach ($aParts as $a => $v) {
2296                                                 if ($a == 'ref' || $a == 'type') {
2297                                                         $contentStr .= " $a=\"".$this->contractQName($v).'"';
2298                                                 } elseif ($a == 'http://schemas.xmlsoap.org/wsdl/:arrayType') {
2299                                                         $this->usedNamespaces['wsdl'] = $this->namespaces['wsdl'];
2300                                                         $contentStr .= ' wsdl:arrayType="'.$this->contractQName($v).'"';
2301                                                 } else {
2302                                                         $contentStr .= " $a=\"$v\"";
2303                                                 }
2304                                         }
2305                                         $contentStr .= "/>\n";
2306                                 }
2307                         }
2308                         // if restriction
2309                         if (isset($attrs['restrictionBase']) && $attrs['restrictionBase'] != ''){
2310                                 $contentStr = "   <$schemaPrefix:restriction base=\"".$this->contractQName($attrs['restrictionBase'])."\">\n".$contentStr."   </$schemaPrefix:restriction>\n";
2311                                 // complex or simple content
2312                                 if ((isset($attrs['elements']) && count($attrs['elements']) > 0) || (isset($attrs['attrs']) && count($attrs['attrs']) > 0)){
2313                                         $contentStr = "  <$schemaPrefix:complexContent>\n".$contentStr."  </$schemaPrefix:complexContent>\n";
2314                                 }
2315                         }
2316                         // finalize complex type
2317                         if($contentStr != ''){
2318                                 $contentStr = " <$schemaPrefix:complexType name=\"$typeName\">\n".$contentStr." </$schemaPrefix:complexType>\n";
2319                         } else {
2320                                 $contentStr = " <$schemaPrefix:complexType name=\"$typeName\"/>\n";
2321                         }
2322                         $xml .= $contentStr;
2323                 }
2324                 // simple types
2325                 if(isset($this->simpleTypes) && count($this->simpleTypes) > 0){
2326                         foreach($this->simpleTypes as $typeName => $eParts){
2327                                 $xml .= " <$schemaPrefix:simpleType name=\"$typeName\">\n  <$schemaPrefix:restriction base=\"".$this->contractQName($eParts['type'])."\">\n";
2328                                 if (isset($eParts['enumeration'])) {
2329                                         foreach ($eParts['enumeration'] as $e) {
2330                                                 $xml .= "  <$schemaPrefix:enumeration value=\"$e\"/>\n";
2331                                         }
2332                                 }
2333                                 $xml .= "  </$schemaPrefix:restriction>\n </$schemaPrefix:simpleType>";
2334                         }
2335                 }
2336                 // elements
2337                 if(isset($this->elements) && count($this->elements) > 0){
2338                         foreach($this->elements as $element => $eParts){
2339                                 $xml .= " <$schemaPrefix:element name=\"$element\" type=\"".$this->contractQName($eParts['type'])."\"/>\n";
2340                         }
2341                 }
2342                 // attributes
2343                 if(isset($this->attributes) && count($this->attributes) > 0){
2344                         foreach($this->attributes as $attr => $aParts){
2345                                 $xml .= " <$schemaPrefix:attribute name=\"$attr\" type=\"".$this->contractQName($aParts['type'])."\"\n/>";
2346                         }
2347                 }
2348                 // finish 'er up
2349                 $attr = '';
2350                 foreach ($this->schemaInfo as $k => $v) {
2351                         if ($k == 'elementFormDefault' || $k == 'attributeFormDefault') {
2352                                 $attr .= " $k=\"$v\"";
2353                         }
2354                 }
2355                 $el = "<$schemaPrefix:schema$attr targetNamespace=\"$this->schemaTargetNamespace\"\n";
2356                 foreach (array_diff($this->usedNamespaces, $this->enclosingNamespaces) as $nsp => $ns) {
2357                         $el .= " xmlns:$nsp=\"$ns\"";
2358                 }
2359                 $xml = $el . ">\n".$xml."</$schemaPrefix:schema>\n";
2360                 return $xml;
2361         }
2362
2363         /**
2364         * adds debug data to the clas level debug string
2365         *
2366         * @param    string $string debug data
2367         * @access   private
2368         */
2369         function xdebug($string){
2370                 $this->debug('<' . $this->schemaTargetNamespace . '> '.$string);
2371         }
2372
2373     /**
2374     * get the PHP type of a user defined type in the schema
2375     * PHP type is kind of a misnomer since it actually returns 'struct' for assoc. arrays
2376     * returns false if no type exists, or not w/ the given namespace
2377     * else returns a string that is either a native php type, or 'struct'
2378     *
2379     * @param string $type name of defined type
2380     * @param string $ns namespace of type
2381     * @return mixed
2382     * @access public
2383     * @deprecated
2384     */
2385         function getPHPType($type,$ns){
2386                 if(isset($this->typemap[$ns][$type])){
2387                         //print "found type '$type' and ns $ns in typemap<br>";
2388                         return $this->typemap[$ns][$type];
2389                 } elseif(isset($this->complexTypes[$type])){
2390                         //print "getting type '$type' and ns $ns from complexTypes array<br>";
2391                         return $this->complexTypes[$type]['phpType'];
2392                 }
2393                 return false;
2394         }
2395
2396         /**
2397     * returns an associative array of information about a given type
2398     * returns false if no type exists by the given name
2399     *
2400         *       For a complexType typeDef = array(
2401         *       'restrictionBase' => '',
2402         *       'phpType' => '',
2403         *       'compositor' => '(sequence|all)',
2404         *       'elements' => array(), // refs to elements array
2405         *       'attrs' => array() // refs to attributes array
2406         *       ... and so on (see addComplexType)
2407         *       )
2408         *
2409         *   For simpleType or element, the array has different keys.
2410     *
2411     * @param string $type
2412     * @return mixed
2413     * @access public
2414     * @see addComplexType
2415     * @see addSimpleType
2416     * @see addElement
2417     */
2418         function getTypeDef($type){
2419                 //$this->debug("in getTypeDef for type $type");
2420                 if (substr($type, -1) == '^') {
2421                         $is_element = 1;
2422                         $type = substr($type, 0, -1);
2423                 } else {
2424                         $is_element = 0;
2425                 }
2426
2427                 if((! $is_element) && isset($this->complexTypes[$type])){
2428                         $this->xdebug("in getTypeDef, found complexType $type");
2429                         return $this->complexTypes[$type];
2430                 } elseif((! $is_element) && isset($this->simpleTypes[$type])){
2431                         $this->xdebug("in getTypeDef, found simpleType $type");
2432                         if (!isset($this->simpleTypes[$type]['phpType'])) {
2433                                 // get info for type to tack onto the simple type
2434                                 // TODO: can this ever really apply (i.e. what is a simpleType really?)
2435                                 $uqType = substr($this->simpleTypes[$type]['type'], strrpos($this->simpleTypes[$type]['type'], ':') + 1);
2436                                 $ns = substr($this->simpleTypes[$type]['type'], 0, strrpos($this->simpleTypes[$type]['type'], ':'));
2437                                 $etype = $this->getTypeDef($uqType);
2438                                 if ($etype) {
2439                                         $this->xdebug("in getTypeDef, found type for simpleType $type:");
2440                                         $this->xdebug($this->varDump($etype));
2441                                         if (isset($etype['phpType'])) {
2442                                                 $this->simpleTypes[$type]['phpType'] = $etype['phpType'];
2443                                         }
2444                                         if (isset($etype['elements'])) {
2445                                                 $this->simpleTypes[$type]['elements'] = $etype['elements'];
2446                                         }
2447                                 }
2448                         }
2449                         return $this->simpleTypes[$type];
2450                 } elseif(isset($this->elements[$type])){
2451                         $this->xdebug("in getTypeDef, found element $type");
2452                         if (!isset($this->elements[$type]['phpType'])) {
2453                                 // get info for type to tack onto the element
2454                                 $uqType = substr($this->elements[$type]['type'], strrpos($this->elements[$type]['type'], ':') + 1);
2455                                 $ns = substr($this->elements[$type]['type'], 0, strrpos($this->elements[$type]['type'], ':'));
2456                                 $etype = $this->getTypeDef($uqType);
2457                                 if ($etype) {
2458                                         $this->xdebug("in getTypeDef, found type for element $type:");
2459                                         $this->xdebug($this->varDump($etype));
2460                                         if (isset($etype['phpType'])) {
2461                                                 $this->elements[$type]['phpType'] = $etype['phpType'];
2462                                         }
2463                                         if (isset($etype['elements'])) {
2464                                                 $this->elements[$type]['elements'] = $etype['elements'];
2465                                         }
2466                                         if (isset($etype['extensionBase'])) {
2467                                                 $this->elements[$type]['extensionBase'] = $etype['extensionBase'];
2468                                         }
2469                                 } elseif ($ns == 'http://www.w3.org/2001/XMLSchema') {
2470                                         $this->xdebug("in getTypeDef, element $type is an XSD type");
2471                                         $this->elements[$type]['phpType'] = 'scalar';
2472                                 }
2473                         }
2474                         return $this->elements[$type];
2475                 } elseif(isset($this->attributes[$type])){
2476                         $this->xdebug("in getTypeDef, found attribute $type");
2477                         return $this->attributes[$type];
2478                 } elseif (preg_match('/_ContainedType$/', $type)) {
2479                         $this->xdebug("in getTypeDef, have an untyped element $type");
2480                         $typeDef['typeClass'] = 'simpleType';
2481                         $typeDef['phpType'] = 'scalar';
2482                         $typeDef['type'] = 'http://www.w3.org/2001/XMLSchema:string';
2483                         return $typeDef;
2484                 }
2485                 $this->xdebug("in getTypeDef, did not find $type");
2486                 return false;
2487         }
2488
2489         /**
2490     * returns a sample serialization of a given type, or false if no type by the given name
2491     *
2492     * @param string $type name of type
2493     * @return mixed
2494     * @access public
2495     * @deprecated
2496     */
2497     function serializeTypeDef($type){
2498         //print "in sTD() for type $type<br>";
2499         if($typeDef = $this->getTypeDef($type)){
2500                 $str .= '<'.$type;
2501             if(is_array($typeDef['attrs'])){
2502                 foreach($typeDef['attrs'] as $attName => $data){
2503                     $str .= " $attName=\"{type = ".$data['type']."}\"";
2504                 }
2505             }
2506             $str .= " xmlns=\"".$this->schema['targetNamespace']."\"";
2507             if(count($typeDef['elements']) > 0){
2508                 $str .= ">";
2509                 foreach($typeDef['elements'] as $element => $eData){
2510                     $str .= $this->serializeTypeDef($element);
2511                 }
2512                 $str .= "</$type>";
2513             } elseif($typeDef['typeClass'] == 'element') {
2514                 $str .= "></$type>";
2515             } else {
2516                 $str .= "/>";
2517             }
2518                         return $str;
2519         }
2520         return false;
2521     }
2522
2523     /**
2524     * returns HTML form elements that allow a user
2525     * to enter values for creating an instance of the given type.
2526     *
2527     * @param string $name name for type instance
2528     * @param string $type name of type
2529     * @return string
2530     * @access public
2531     * @deprecated
2532         */
2533         function typeToForm($name,$type){
2534                 // get typedef
2535                 if($typeDef = $this->getTypeDef($type)){
2536                         // if struct
2537                         if($typeDef['phpType'] == 'struct'){
2538                                 $buffer .= '<table>';
2539                                 foreach($typeDef['elements'] as $child => $childDef){
2540                                         $buffer .= "
2541                                         <tr><td align='right'>$childDef[name] (type: ".$this->getLocalPart($childDef['type'])."):</td>
2542                                         <td><input type='text' name='parameters[".$name."][$childDef[name]]'></td></tr>";
2543                                 }
2544                                 $buffer .= '</table>';
2545                         // if array
2546                         } elseif($typeDef['phpType'] == 'array'){
2547                                 $buffer .= '<table>';
2548                                 for($i=0;$i < 3; $i++){
2549                                         $buffer .= "
2550                                         <tr><td align='right'>array item (type: $typeDef[arrayType]):</td>
2551                                         <td><input type='text' name='parameters[".$name."][]'></td></tr>";
2552                                 }
2553                                 $buffer .= '</table>';
2554                         // if scalar
2555                         } else {
2556                                 $buffer .= "<input type='text' name='parameters[$name]'>";
2557                         }
2558                 } else {
2559                         $buffer .= "<input type='text' name='parameters[$name]'>";
2560                 }
2561                 return $buffer;
2562         }
2563         
2564         /**
2565         * adds a complex type to the schema
2566         * 
2567         * example: array
2568         * 
2569         * addType(
2570         *       'ArrayOfstring',
2571         *       'complexType',
2572         *       'array',
2573         *       '',
2574         *       'SOAP-ENC:Array',
2575         *       array('ref'=>'SOAP-ENC:arrayType','wsdl:arrayType'=>'string[]'),
2576         *       'xsd:string'
2577         * );
2578         * 
2579         * example: PHP associative array ( SOAP Struct )
2580         * 
2581         * addType(
2582         *       'SOAPStruct',
2583         *       'complexType',
2584         *       'struct',
2585         *       'all',
2586         *       array('myVar'=> array('name'=>'myVar','type'=>'string')
2587         * );
2588         * 
2589         * @param name
2590         * @param typeClass (complexType|simpleType|attribute)
2591         * @param phpType: currently supported are array and struct (php assoc array)
2592         * @param compositor (all|sequence|choice)
2593         * @param restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
2594         * @param elements = array ( name = array(name=>'',type=>'') )
2595         * @param attrs = array(
2596         *       array(
2597         *               'ref' => "http://schemas.xmlsoap.org/soap/encoding/:arrayType",
2598         *               "http://schemas.xmlsoap.org/wsdl/:arrayType" => "string[]"
2599         *       )
2600         * )
2601         * @param arrayType: namespace:name (http://www.w3.org/2001/XMLSchema:string)
2602         * @access public
2603         * @see getTypeDef
2604         */
2605         function addComplexType($name,$typeClass='complexType',$phpType='array',$compositor='',$restrictionBase='',$elements=array(),$attrs=array(),$arrayType=''){
2606                 $this->complexTypes[$name] = array(
2607             'name'              => $name,
2608             'typeClass' => $typeClass,
2609             'phpType'   => $phpType,
2610                 'compositor'=> $compositor,
2611             'restrictionBase' => $restrictionBase,
2612                 'elements'      => $elements,
2613             'attrs'             => $attrs,
2614             'arrayType' => $arrayType
2615                 );
2616                 
2617                 $this->xdebug("addComplexType $name:");
2618                 $this->appendDebug($this->varDump($this->complexTypes[$name]));
2619         }
2620         
2621         /**
2622         * adds a simple type to the schema
2623         *
2624         * @param string $name
2625         * @param string $restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
2626         * @param string $typeClass (should always be simpleType)
2627         * @param string $phpType (should always be scalar)
2628         * @param array $enumeration array of values
2629         * @access public
2630         * @see nusoap_xmlschema
2631         * @see getTypeDef
2632         */
2633         function addSimpleType($name, $restrictionBase='', $typeClass='simpleType', $phpType='scalar', $enumeration=array()) {
2634                 $this->simpleTypes[$name] = array(
2635             'name'                      => $name,
2636             'typeClass'         => $typeClass,
2637             'phpType'           => $phpType,
2638             'type'                      => $restrictionBase,
2639             'enumeration'       => $enumeration
2640                 );
2641                 
2642                 $this->xdebug("addSimpleType $name:");
2643                 $this->appendDebug($this->varDump($this->simpleTypes[$name]));
2644         }
2645
2646         /**
2647         * adds an element to the schema
2648         *
2649         * @param array $attrs attributes that must include name and type
2650         * @see nusoap_xmlschema
2651         * @access public
2652         */
2653         function addElement($attrs) {
2654                 if (! $this->getPrefix($attrs['type'])) {
2655                         $attrs['type'] = $this->schemaTargetNamespace . ':' . $attrs['type'];
2656                 }
2657                 $this->elements[ $attrs['name'] ] = $attrs;
2658                 $this->elements[ $attrs['name'] ]['typeClass'] = 'element';
2659                 
2660                 $this->xdebug("addElement " . $attrs['name']);
2661                 $this->appendDebug($this->varDump($this->elements[ $attrs['name'] ]));
2662         }
2663 }
2664
2665 /**
2666  * Backward compatibility
2667  */
2668 class XMLSchema extends nusoap_xmlschema {
2669 }
2670
2671 ?><?php
2672
2673 /*
2674
2675 Modification information for LGPL compliance
2676
2677 r58622 - 2010-10-22 18:18:59 -0700 (Fri, 22 Oct 2010) - engsvnbuild - Author: lam <lam@198.18.142.201>
2678     bug 40066
2679
2680 r58361 - 2010-09-29 16:59:02 -0700 (Wed, 29 Sep 2010) - kjing - Author: Jenny Gonsalves <jenny@sugarcrm.com>
2681     Merging with maint_6_0_1 (svn merge -r 58250:58342)
2682
2683 r57813 - 2010-08-19 10:34:44 -0700 (Thu, 19 Aug 2010) - kjing - Author: John Mertic <jmertic@sugarcrm.com>
2684     Bug 39085 - When loading the opposite search panel via ajax on the ListViews, call the index action instead of the ListView action to avoid touching pre-MVC code by accident.
2685
2686 r57707 - 2010-08-10 12:26:13 -0700 (Tue, 10 Aug 2010) - kjing - Author: Stanislav Malyshev <smalyshev@gmail.com>
2687     fix SOAP calls with no parameters
2688
2689 r56990 - 2010-06-16 13:05:36 -0700 (Wed, 16 Jun 2010) - kjing - snapshot "Mango" svn branch to a new one for GitHub sync
2690
2691 r56989 - 2010-06-16 13:01:33 -0700 (Wed, 16 Jun 2010) - kjing - defunt "Mango" svn dev branch before github cutover
2692
2693 r55980 - 2010-04-19 13:31:28 -0700 (Mon, 19 Apr 2010) - kjing - create Mango (6.1) based on windex
2694
2695 r51719 - 2009-10-22 10:18:00 -0700 (Thu, 22 Oct 2009) - mitani - Converted to Build 3  tags and updated the build system 
2696
2697 r51634 - 2009-10-19 13:32:22 -0700 (Mon, 19 Oct 2009) - mitani - Windex is the branch for Sugar Sales 1.0 development
2698
2699 r51508 - 2009-10-14 07:40:23 -0700 (Wed, 14 Oct 2009) - jmertic - More fallout fixes from the PHP 5.3 ereg to preg changes.
2700
2701 r51455 - 2009-10-13 07:56:48 -0700 (Tue, 13 Oct 2009) - jmertic - Bug 33202 - Enable install of SugarCRM on PHP 5.3.0, asserting that the minimum supported version is PHP 5.2.x.
2702
2703 r51443 - 2009-10-12 13:34:36 -0700 (Mon, 12 Oct 2009) - jmertic - Bug 33332 - Made application PHP 5.3 compliant with E_DEPRECATED warnings on by:
2704 - Changing all ereg function to either preg or simple string based ones
2705 - No more references to magic quotes.
2706 - Change all the session_unregister() functions to just unset() the correct session variable instead.
2707
2708 r50375 - 2009-08-24 18:07:43 -0700 (Mon, 24 Aug 2009) - dwong - branch kobe2 from tokyo r50372
2709
2710 r45763 - 2009-04-01 12:16:18 -0700 (Wed, 01 Apr 2009) - majed - Removed half of the require_once and include_onces in the product that were redundant or could be handled easily by the auto loader
2711
2712 r45680 - 2009-03-30 14:34:35 -0700 (Mon, 30 Mar 2009) - Samir Gandhi - modifeid serializeSchema to generate WS-I compliant WSDL
2713
2714 r42807 - 2008-12-29 11:16:59 -0800 (Mon, 29 Dec 2008) - dwong - Branch from trunk/sugarcrm r42806 to branches/tokyo/sugarcrm
2715
2716 r42645 - 2008-12-18 13:41:08 -0800 (Thu, 18 Dec 2008) - awu - merging maint_5_2_0 rev41336:HEAD to trunk
2717
2718 r41647 - 2008-11-11 17:44:30 -0800 (Tue, 11 Nov 2008) - majed - Fixes a few bugs 
2719
2720 r41596 - 2008-11-10 19:20:04 -0800 (Mon, 10 Nov 2008) - Samir Gandhi - modified to set $method in the code
2721
2722 r41558 - 2008-11-10 14:35:34 -0800 (Mon, 10 Nov 2008) - majed - changes nusoap to allow for registering classes 
2723
2724 r39619 - 2008-09-09 13:41:34 -0700 (Tue, 09 Sep 2008) - jmertic - Bug 24827 - Remove all instances where we return a new object and assign it by reference, since this is deprecated in PHP 5 and emits E_DEPRECATED errors in PHP 5.3.
2725 Touched:
2726 - data/SugarBean.php
2727 - include/domit/php_http_client_generic.php
2728 - include/domit/php_http_connector.php
2729 - include/domit/testing_domit.php
2730 - include/domit/xml_domit_getelementsbypath.php
2731 - include/domit/xml_domit_lite_parser.php
2732 - include/domit/xml_domit_nodemaps.php
2733 - include/domit/xml_domit_parser.php
2734 - include/domit/xml_domit_shared.php
2735 - include/generic/SugarWidgets/SugarWidgetField.php
2736 - include/generic/SugarWidgets/SugarWidgetReportField.php
2737 - include/ListView/ProcessView.php
2738 - include/nusoap/class.soapclient.php
2739 - include/nusoap/nusoap.php
2740 - include/nusoap/nusoapmime.php
2741 - include/Pear/HTML_Safe/Safe.php
2742 - include/Pear/XML_HTMLSax3/HTMLSax3.php
2743 - modules/Administration/RebuildWorkFlow.php
2744 - modules/Expressions/RelateSelector.php
2745 - modules/Reports/templates/templates_reports.php
2746 - modules/WorkFlow/Delete.php
2747 - modules/WorkFlow/Save.php
2748 - modules/WorkFlow/SaveSequence.php
2749 - modules/WorkFlow/WorkFlow.php
2750 - modules/WorkFlowActionShells/CreateStep1.php
2751 - modules/WorkFlowActionShells/CreateStep2.php
2752 - modules/WorkFlowActionShells/Save.php
2753 - modules/WorkFlowActionShells/WorkFlowActionShell.php
2754 - modules/WorkFlowAlerts/Save.php
2755 - modules/WorkFlowAlerts/WorkFlowAlert.php
2756 - modules/WorkFlowAlertShells/DetailView.php
2757 - modules/WorkFlowAlertShells/WorkFlowAlertShell.php
2758 - modules/WorkFlowTriggerShells/CreateStep1.php
2759 - modules/WorkFlowTriggerShells/CreateStepFilter.php
2760 - modules/WorkFlowTriggerShells/SaveFilter.php
2761 - modules/WorkFlowTriggerShells/WorkFlowTriggerShell.php
2762 - soap/SoapHelperFunctions.php
2763 - test/modules/DynamicFields/DynamicFields_Bug24095_test.php
2764 - test/simpletest/browser.php
2765 - test/simpletest/default_reporter.php
2766 - test/simpletest/detached.php
2767 - test/simpletest/eclipse.php
2768 - test/simpletest/expectation.php
2769 - test/simpletest/extensions/pear_test_case.php
2770 - test/simpletest/form.php
2771 - test/simpletest/http.php
2772 - test/simpletest/mock_objects.php
2773 - test/simpletest/page.php
2774 - test/simpletest/parser.php
2775 - test/simpletest/remote.php
2776 - test/simpletest/shell_tester.php
2777 - test/simpletest/simple_test.php
2778 - test/simpletest/simpletest.php
2779 - test/simpletest/test/acceptance_test.php
2780 - test/simpletest/test/adapter_test.php
2781 - test/simpletest/test/authentication_test.php
2782 - test/simpletest/test/browser_test.php
2783 - test/simpletest/test/collector_test.php
2784 - test/simpletest/test/compatibility_test.php
2785 - test/simpletest/test/detached_test.php
2786 - test/simpletest/test/eclipse_test.php
2787 - test/simpletest/test/encoding_test.php
2788 - test/simpletest/test/errors_test.php
2789 - test/simpletest/test/expectation_test.php
2790 - test/simpletest/test/form_test.php
2791 - test/simpletest/test/frames_test.php
2792 - test/simpletest/test/http_test.php
2793 - test/simpletest/test/live_test.php
2794 - test/simpletest/test/mock_objects_test.php
2795 - test/simpletest/test/page_test.php
2796 - test/simpletest/test/parse_error_test.php
2797 - test/simpletest/test/parser_test.php
2798 - test/simpletest/test/remote_test.php
2799 - test/simpletest/test/shell_test.php
2800 - test/simpletest/test/shell_tester_test.php
2801 - test/simpletest/test/simpletest_test.php
2802 - test/simpletest/test/site/page_request.php
2803 - test/simpletest/test/tag_test.php
2804 - test/simpletest/test/unit_tester_test.php
2805 - test/simpletest/test/user_agent_test.php
2806 - test/simpletest/test/visual_test.php
2807 - test/simpletest/test/xml_test.php
2808 - test/simpletest/test_case.php
2809 - test/simpletest/ui/array_reporter/test.php
2810 - test/simpletest/ui/recorder/test.php
2811 - test/simpletest/unit_tester.php
2812 - test/simpletest/url.php
2813 - test/simpletest/user_agent.php
2814 - test/simpletest/web_tester.php
2815 - test/spikephpcoverage/src/PEAR.php
2816 - test/spikephpcoverage/src/util/Utility.php
2817 - test/spikephpcoverage/src/XML/Parser.php
2818 - test/spikephpcoverage/src/XML/Parser/Simple.php
2819 - test/test_utilities/SugarTest_SimpleBrowser.php
2820
2821 r38362 - 2008-07-28 14:06:59 -0700 (Mon, 28 Jul 2008) - roger - bug: 23897. Using print_r when using the debug statement in nusoap will print out the statements to the screen if the call is coming from the UI.
2822
2823 r38300 - 2008-07-25 13:33:43 -0700 (Fri, 25 Jul 2008) - Samir Gandhi - put the debug in parseresponse function
2824
2825 r38293 - 2008-07-25 12:32:34 -0700 (Fri, 25 Jul 2008) - Samir Gandhi - to put all the debug statements return value in the call function
2826
2827 r36824 - 2008-06-18 09:26:11 -0700 (Wed, 18 Jun 2008) - roger - bug: 21832
2828
2829 r26422 - 2007-09-05 17:29:12 -0700 (Wed, 05 Sep 2007) - majed - migrate from beta 1 to trunk
2830
2831 r15787 - 2006-08-10 10:14:41 -0700 (Thu, 10 Aug 2006) - roger - RRS: bug 7961
2832
2833 r14701 - 2006-07-17 13:37:26 -0700 (Mon, 17 Jul 2006) - roger - RRS: bug 5801
2834
2835 r13782 - 2006-06-06 10:58:55 -0700 (Tue, 06 Jun 2006) - majed - changes entry point code
2836
2837 r11466 - 2006-02-01 15:49:47 -0800 (Wed, 01 Feb 2006) - jacob - Adding extra !empty check to get around a PHP warning.
2838
2839 r11115 - 2006-01-17 14:54:45 -0800 (Tue, 17 Jan 2006) - majed - add entry point validation
2840
2841 r10585 - 2005-12-13 14:42:26 -0800 (Tue, 13 Dec 2005) - majed - adds new license mechanisim
2842
2843 r10170 - 2005-12-05 18:37:46 -0800 (Mon, 05 Dec 2005) - majed - fixes various issues
2844
2845 r8999 - 2005-11-04 05:26:49 -0800 (Fri, 04 Nov 2005) - roger - When nusoap was upgraded we had an issue with the user's default language not being populated during a soap request. I determined the reason this was happening and have checked in the corresponding change to nusoap.
2846
2847 r8991 - 2005-11-03 19:07:25 -0800 (Thu, 03 Nov 2005) - majed - fixes nusoap issue
2848
2849 r8846 - 2005-10-31 11:01:12 -0800 (Mon, 31 Oct 2005) - majed - new version of nusoap
2850
2851 r7905 - 2005-09-21 19:12:57 -0700 (Wed, 21 Sep 2005) - majed - restores old nusoap pre & with a few fixes
2852
2853 r7861 - 2005-09-20 15:40:25 -0700 (Tue, 20 Sep 2005) - majed - & fix for 3.5.1
2854
2855 r7452 - 2005-08-17 11:32:34 -0700 (Wed, 17 Aug 2005) - majed - changes soap to nusoap
2856
2857 r5820 - 2005-06-21 14:22:24 -0700 (Tue, 21 Jun 2005) - majed - fixes issues with nusoap and with custom fields
2858
2859 r5462 - 2005-05-25 13:50:11 -0700 (Wed, 25 May 2005) - majed - upgraded nusoap to .6.9
2860
2861 r5104 - 2005-05-04 15:33:41 -0700 (Wed, 04 May 2005) - majed - gets rid of HTTP_GET_VARS and what not which has been deprecated
2862
2863 r573 - 2004-09-04 13:03:32 -0700 (Sat, 04 Sep 2004) - sugarclint - undoing copyrights added in inadvertantly.  --clint
2864
2865 r546 - 2004-09-03 11:49:38 -0700 (Fri, 03 Sep 2004) - sugarmsi - removed echo count
2866
2867 r354 - 2004-08-02 23:00:37 -0700 (Mon, 02 Aug 2004) - sugarjacob - Adding Soap
2868
2869
2870 */
2871
2872
2873
2874
2875
2876 /**
2877 * For creating serializable abstractions of native PHP types.  This class
2878 * allows element name/namespace, XSD type, and XML attributes to be
2879 * associated with a value.  This is extremely useful when WSDL is not
2880 * used, but is also useful when WSDL is used with polymorphic types, including
2881 * xsd:anyType and user-defined types.
2882 *
2883 * @author   Dietrich Ayala <dietrich@ganx4.com>
2884
2885 * @access   public
2886 */
2887 class soapval extends nusoap_base {
2888         /**
2889          * The XML element name
2890          *
2891          * @var string
2892          * @access private
2893          */
2894         var $name;
2895         /**
2896          * The XML type name (string or false)
2897          *
2898          * @var mixed
2899          * @access private
2900          */
2901         var $type;
2902         /**
2903          * The PHP value
2904          *
2905          * @var mixed
2906          * @access private
2907          */
2908         var $value;
2909         /**
2910          * The XML element namespace (string or false)
2911          *
2912          * @var mixed
2913          * @access private
2914          */
2915         var $element_ns;
2916         /**
2917          * The XML type namespace (string or false)
2918          *
2919          * @var mixed
2920          * @access private
2921          */
2922         var $type_ns;
2923         /**
2924          * The XML element attributes (array or false)
2925          *
2926          * @var mixed
2927          * @access private
2928          */
2929         var $attributes;
2930
2931         /**
2932         * constructor
2933         *
2934         * @param    string $name optional name
2935         * @param    mixed $type optional type name
2936         * @param        mixed $value optional value
2937         * @param        mixed $element_ns optional namespace of value
2938         * @param        mixed $type_ns optional namespace of type
2939         * @param        mixed $attributes associative array of attributes to add to element serialization
2940         * @access   public
2941         */
2942         function soapval($name='soapval',$type=false,$value=-1,$element_ns=false,$type_ns=false,$attributes=false) {
2943                 parent::nusoap_base();
2944                 $this->name = $name;
2945                 $this->type = $type;
2946                 $this->value = $value;
2947                 $this->element_ns = $element_ns;
2948                 $this->type_ns = $type_ns;
2949                 $this->attributes = $attributes;
2950     }
2951
2952         /**
2953         * return serialized value
2954         *
2955         * @param        string $use The WSDL use value (encoded|literal)
2956         * @return       string XML data
2957         * @access   public
2958         */
2959         function serialize($use='encoded') {
2960                 return $this->serialize_val($this->value, $this->name, $this->type, $this->element_ns, $this->type_ns, $this->attributes, $use, true);
2961     }
2962
2963         /**
2964         * decodes a soapval object into a PHP native type
2965         *
2966         * @return       mixed
2967         * @access   public
2968         */
2969         function decode(){
2970                 return $this->value;
2971         }
2972 }
2973
2974
2975
2976 ?><?php
2977
2978 /*
2979
2980 Modification information for LGPL compliance
2981
2982 r58622 - 2010-10-22 18:18:59 -0700 (Fri, 22 Oct 2010) - engsvnbuild - Author: lam <lam@198.18.142.201>
2983     bug 40066
2984
2985 r58361 - 2010-09-29 16:59:02 -0700 (Wed, 29 Sep 2010) - kjing - Author: Jenny Gonsalves <jenny@sugarcrm.com>
2986     Merging with maint_6_0_1 (svn merge -r 58250:58342)
2987
2988 r57813 - 2010-08-19 10:34:44 -0700 (Thu, 19 Aug 2010) - kjing - Author: John Mertic <jmertic@sugarcrm.com>
2989     Bug 39085 - When loading the opposite search panel via ajax on the ListViews, call the index action instead of the ListView action to avoid touching pre-MVC code by accident.
2990
2991 r57707 - 2010-08-10 12:26:13 -0700 (Tue, 10 Aug 2010) - kjing - Author: Stanislav Malyshev <smalyshev@gmail.com>
2992     fix SOAP calls with no parameters
2993
2994 r56990 - 2010-06-16 13:05:36 -0700 (Wed, 16 Jun 2010) - kjing - snapshot "Mango" svn branch to a new one for GitHub sync
2995
2996 r56989 - 2010-06-16 13:01:33 -0700 (Wed, 16 Jun 2010) - kjing - defunt "Mango" svn dev branch before github cutover
2997
2998 r55980 - 2010-04-19 13:31:28 -0700 (Mon, 19 Apr 2010) - kjing - create Mango (6.1) based on windex
2999
3000 r51719 - 2009-10-22 10:18:00 -0700 (Thu, 22 Oct 2009) - mitani - Converted to Build 3  tags and updated the build system 
3001
3002 r51634 - 2009-10-19 13:32:22 -0700 (Mon, 19 Oct 2009) - mitani - Windex is the branch for Sugar Sales 1.0 development
3003
3004 r51508 - 2009-10-14 07:40:23 -0700 (Wed, 14 Oct 2009) - jmertic - More fallout fixes from the PHP 5.3 ereg to preg changes.
3005
3006 r51455 - 2009-10-13 07:56:48 -0700 (Tue, 13 Oct 2009) - jmertic - Bug 33202 - Enable install of SugarCRM on PHP 5.3.0, asserting that the minimum supported version is PHP 5.2.x.
3007
3008 r51443 - 2009-10-12 13:34:36 -0700 (Mon, 12 Oct 2009) - jmertic - Bug 33332 - Made application PHP 5.3 compliant with E_DEPRECATED warnings on by:
3009 - Changing all ereg function to either preg or simple string based ones
3010 - No more references to magic quotes.
3011 - Change all the session_unregister() functions to just unset() the correct session variable instead.
3012
3013 r50375 - 2009-08-24 18:07:43 -0700 (Mon, 24 Aug 2009) - dwong - branch kobe2 from tokyo r50372
3014
3015 r45763 - 2009-04-01 12:16:18 -0700 (Wed, 01 Apr 2009) - majed - Removed half of the require_once and include_onces in the product that were redundant or could be handled easily by the auto loader
3016
3017 r45680 - 2009-03-30 14:34:35 -0700 (Mon, 30 Mar 2009) - Samir Gandhi - modifeid serializeSchema to generate WS-I compliant WSDL
3018
3019 r42807 - 2008-12-29 11:16:59 -0800 (Mon, 29 Dec 2008) - dwong - Branch from trunk/sugarcrm r42806 to branches/tokyo/sugarcrm
3020
3021 r42645 - 2008-12-18 13:41:08 -0800 (Thu, 18 Dec 2008) - awu - merging maint_5_2_0 rev41336:HEAD to trunk
3022
3023 r41647 - 2008-11-11 17:44:30 -0800 (Tue, 11 Nov 2008) - majed - Fixes a few bugs 
3024
3025 r41596 - 2008-11-10 19:20:04 -0800 (Mon, 10 Nov 2008) - Samir Gandhi - modified to set $method in the code
3026
3027 r41558 - 2008-11-10 14:35:34 -0800 (Mon, 10 Nov 2008) - majed - changes nusoap to allow for registering classes 
3028
3029 r39619 - 2008-09-09 13:41:34 -0700 (Tue, 09 Sep 2008) - jmertic - Bug 24827 - Remove all instances where we return a new object and assign it by reference, since this is deprecated in PHP 5 and emits E_DEPRECATED errors in PHP 5.3.
3030 Touched:
3031 - data/SugarBean.php
3032 - include/domit/php_http_client_generic.php
3033 - include/domit/php_http_connector.php
3034 - include/domit/testing_domit.php
3035 - include/domit/xml_domit_getelementsbypath.php
3036 - include/domit/xml_domit_lite_parser.php
3037 - include/domit/xml_domit_nodemaps.php
3038 - include/domit/xml_domit_parser.php
3039 - include/domit/xml_domit_shared.php
3040 - include/generic/SugarWidgets/SugarWidgetField.php
3041 - include/generic/SugarWidgets/SugarWidgetReportField.php
3042 - include/ListView/ProcessView.php
3043 - include/nusoap/class.soapclient.php
3044 - include/nusoap/nusoap.php
3045 - include/nusoap/nusoapmime.php
3046 - include/Pear/HTML_Safe/Safe.php
3047 - include/Pear/XML_HTMLSax3/HTMLSax3.php
3048 - modules/Administration/RebuildWorkFlow.php
3049 - modules/Expressions/RelateSelector.php
3050 - modules/Reports/templates/templates_reports.php
3051 - modules/WorkFlow/Delete.php
3052 - modules/WorkFlow/Save.php
3053 - modules/WorkFlow/SaveSequence.php
3054 - modules/WorkFlow/WorkFlow.php
3055 - modules/WorkFlowActionShells/CreateStep1.php
3056 - modules/WorkFlowActionShells/CreateStep2.php
3057 - modules/WorkFlowActionShells/Save.php
3058 - modules/WorkFlowActionShells/WorkFlowActionShell.php
3059 - modules/WorkFlowAlerts/Save.php
3060 - modules/WorkFlowAlerts/WorkFlowAlert.php
3061 - modules/WorkFlowAlertShells/DetailView.php
3062 - modules/WorkFlowAlertShells/WorkFlowAlertShell.php
3063 - modules/WorkFlowTriggerShells/CreateStep1.php
3064 - modules/WorkFlowTriggerShells/CreateStepFilter.php
3065 - modules/WorkFlowTriggerShells/SaveFilter.php
3066 - modules/WorkFlowTriggerShells/WorkFlowTriggerShell.php
3067 - soap/SoapHelperFunctions.php
3068 - test/modules/DynamicFields/DynamicFields_Bug24095_test.php
3069 - test/simpletest/browser.php
3070 - test/simpletest/default_reporter.php
3071 - test/simpletest/detached.php
3072 - test/simpletest/eclipse.php
3073 - test/simpletest/expectation.php
3074 - test/simpletest/extensions/pear_test_case.php
3075 - test/simpletest/form.php
3076 - test/simpletest/http.php
3077 - test/simpletest/mock_objects.php
3078 - test/simpletest/page.php
3079 - test/simpletest/parser.php
3080 - test/simpletest/remote.php
3081 - test/simpletest/shell_tester.php
3082 - test/simpletest/simple_test.php
3083 - test/simpletest/simpletest.php
3084 - test/simpletest/test/acceptance_test.php
3085 - test/simpletest/test/adapter_test.php
3086 - test/simpletest/test/authentication_test.php
3087 - test/simpletest/test/browser_test.php
3088 - test/simpletest/test/collector_test.php
3089 - test/simpletest/test/compatibility_test.php
3090 - test/simpletest/test/detached_test.php
3091 - test/simpletest/test/eclipse_test.php
3092 - test/simpletest/test/encoding_test.php
3093 - test/simpletest/test/errors_test.php
3094 - test/simpletest/test/expectation_test.php
3095 - test/simpletest/test/form_test.php
3096 - test/simpletest/test/frames_test.php
3097 - test/simpletest/test/http_test.php
3098 - test/simpletest/test/live_test.php
3099 - test/simpletest/test/mock_objects_test.php
3100 - test/simpletest/test/page_test.php
3101 - test/simpletest/test/parse_error_test.php
3102 - test/simpletest/test/parser_test.php
3103 - test/simpletest/test/remote_test.php
3104 - test/simpletest/test/shell_test.php
3105 - test/simpletest/test/shell_tester_test.php
3106 - test/simpletest/test/simpletest_test.php
3107 - test/simpletest/test/site/page_request.php
3108 - test/simpletest/test/tag_test.php
3109 - test/simpletest/test/unit_tester_test.php
3110 - test/simpletest/test/user_agent_test.php
3111 - test/simpletest/test/visual_test.php
3112 - test/simpletest/test/xml_test.php
3113 - test/simpletest/test_case.php
3114 - test/simpletest/ui/array_reporter/test.php
3115 - test/simpletest/ui/recorder/test.php
3116 - test/simpletest/unit_tester.php
3117 - test/simpletest/url.php
3118 - test/simpletest/user_agent.php
3119 - test/simpletest/web_tester.php
3120 - test/spikephpcoverage/src/PEAR.php
3121 - test/spikephpcoverage/src/util/Utility.php
3122 - test/spikephpcoverage/src/XML/Parser.php
3123 - test/spikephpcoverage/src/XML/Parser/Simple.php
3124 - test/test_utilities/SugarTest_SimpleBrowser.php
3125
3126 r38362 - 2008-07-28 14:06:59 -0700 (Mon, 28 Jul 2008) - roger - bug: 23897. Using print_r when using the debug statement in nusoap will print out the statements to the screen if the call is coming from the UI.
3127
3128 r38300 - 2008-07-25 13:33:43 -0700 (Fri, 25 Jul 2008) - Samir Gandhi - put the debug in parseresponse function
3129
3130 r38293 - 2008-07-25 12:32:34 -0700 (Fri, 25 Jul 2008) - Samir Gandhi - to put all the debug statements return value in the call function
3131
3132 r36824 - 2008-06-18 09:26:11 -0700 (Wed, 18 Jun 2008) - roger - bug: 21832
3133
3134 r26422 - 2007-09-05 17:29:12 -0700 (Wed, 05 Sep 2007) - majed - migrate from beta 1 to trunk
3135
3136 r15787 - 2006-08-10 10:14:41 -0700 (Thu, 10 Aug 2006) - roger - RRS: bug 7961
3137
3138 r14701 - 2006-07-17 13:37:26 -0700 (Mon, 17 Jul 2006) - roger - RRS: bug 5801
3139
3140 r13782 - 2006-06-06 10:58:55 -0700 (Tue, 06 Jun 2006) - majed - changes entry point code
3141
3142 r11466 - 2006-02-01 15:49:47 -0800 (Wed, 01 Feb 2006) - jacob - Adding extra !empty check to get around a PHP warning.
3143
3144 r11115 - 2006-01-17 14:54:45 -0800 (Tue, 17 Jan 2006) - majed - add entry point validation
3145
3146 r10585 - 2005-12-13 14:42:26 -0800 (Tue, 13 Dec 2005) - majed - adds new license mechanisim
3147
3148 r10170 - 2005-12-05 18:37:46 -0800 (Mon, 05 Dec 2005) - majed - fixes various issues
3149
3150 r8999 - 2005-11-04 05:26:49 -0800 (Fri, 04 Nov 2005) - roger - When nusoap was upgraded we had an issue with the user's default language not being populated during a soap request. I determined the reason this was happening and have checked in the corresponding change to nusoap.
3151
3152 r8991 - 2005-11-03 19:07:25 -0800 (Thu, 03 Nov 2005) - majed - fixes nusoap issue
3153
3154 r8846 - 2005-10-31 11:01:12 -0800 (Mon, 31 Oct 2005) - majed - new version of nusoap
3155
3156 r7905 - 2005-09-21 19:12:57 -0700 (Wed, 21 Sep 2005) - majed - restores old nusoap pre & with a few fixes
3157
3158 r7861 - 2005-09-20 15:40:25 -0700 (Tue, 20 Sep 2005) - majed - & fix for 3.5.1
3159
3160 r7452 - 2005-08-17 11:32:34 -0700 (Wed, 17 Aug 2005) - majed - changes soap to nusoap
3161
3162 r5820 - 2005-06-21 14:22:24 -0700 (Tue, 21 Jun 2005) - majed - fixes issues with nusoap and with custom fields
3163
3164 r5462 - 2005-05-25 13:50:11 -0700 (Wed, 25 May 2005) - majed - upgraded nusoap to .6.9
3165
3166 r5104 - 2005-05-04 15:33:41 -0700 (Wed, 04 May 2005) - majed - gets rid of HTTP_GET_VARS and what not which has been deprecated
3167
3168 r573 - 2004-09-04 13:03:32 -0700 (Sat, 04 Sep 2004) - sugarclint - undoing copyrights added in inadvertantly.  --clint
3169
3170 r546 - 2004-09-03 11:49:38 -0700 (Fri, 03 Sep 2004) - sugarmsi - removed echo count
3171
3172 r354 - 2004-08-02 23:00:37 -0700 (Mon, 02 Aug 2004) - sugarjacob - Adding Soap
3173
3174
3175 */
3176
3177
3178
3179
3180
3181 /**
3182 * transport class for sending/receiving data via HTTP and HTTPS
3183 * NOTE: PHP must be compiled with the CURL extension for HTTPS support
3184 *
3185 * @author   Dietrich Ayala <dietrich@ganx4.com>
3186 * @author   Scott Nichol <snichol@users.sourceforge.net>
3187
3188 * @access public
3189 */
3190 class soap_transport_http extends nusoap_base {
3191
3192         var $url = '';
3193         var $uri = '';
3194         var $digest_uri = '';
3195         var $scheme = '';
3196         var $host = '';
3197         var $port = '';
3198         var $path = '';
3199         var $request_method = 'POST';
3200         var $protocol_version = '1.0';
3201         var $encoding = '';
3202         var $outgoing_headers = array();
3203         var $incoming_headers = array();
3204         var $incoming_cookies = array();
3205         var $outgoing_payload = '';
3206         var $incoming_payload = '';
3207         var $response_status_line;      // HTTP response status line
3208         var $useSOAPAction = true;
3209         var $persistentConnection = false;
3210         var $ch = false;        // cURL handle
3211         var $ch_options = array();      // cURL custom options
3212         var $use_curl = false;          // force cURL use
3213         var $proxy = null;                      // proxy information (associative array)
3214         var $username = '';
3215         var $password = '';
3216         var $authtype = '';
3217         var $digestRequest = array();
3218         var $certRequest = array();     // keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, certpassword (optional), verifypeer (optional), verifyhost (optional)
3219                                                                 // cainfofile: certificate authority file, e.g. '$pathToPemFiles/rootca.pem'
3220                                                                 // sslcertfile: SSL certificate file, e.g. '$pathToPemFiles/mycert.pem'
3221                                                                 // sslkeyfile: SSL key file, e.g. '$pathToPemFiles/mykey.pem'
3222                                                                 // passphrase: SSL key password/passphrase
3223                                                                 // certpassword: SSL certificate password
3224                                                                 // verifypeer: default is 1
3225                                                                 // verifyhost: default is 1
3226
3227         /**
3228         * constructor
3229         *
3230         * @param string $url The URL to which to connect
3231         * @param array $curl_options User-specified cURL options
3232         * @param boolean $use_curl Whether to try to force cURL use
3233         * @access public
3234         */
3235         function soap_transport_http($url, $curl_options = NULL, $use_curl = false){
3236                 parent::nusoap_base();
3237                 $this->debug("ctor url=$url use_curl=$use_curl curl_options:");
3238                 $this->appendDebug($this->varDump($curl_options));
3239                 $this->setURL($url);
3240                 if (is_array($curl_options)) {
3241                         $this->ch_options = $curl_options;
3242                 }
3243                 $this->use_curl = $use_curl;
3244                 preg_match('/\$Revisio' . 'n: ([^ ]+)/', $this->revision, $rev);
3245                 $this->setHeader('User-Agent', $this->title.'/'.$this->version.' ('.$rev[1].')');
3246         }
3247
3248         /**
3249         * sets a cURL option
3250         *
3251         * @param        mixed $option The cURL option (always integer?)
3252         * @param        mixed $value The cURL option value
3253         * @access   private
3254         */
3255         function setCurlOption($option, $value) {
3256                 $this->debug("setCurlOption option=$option, value=");
3257                 $this->appendDebug($this->varDump($value));
3258                 curl_setopt($this->ch, $option, $value);
3259         }
3260
3261         /**
3262         * sets an HTTP header
3263         *
3264         * @param string $name The name of the header
3265         * @param string $value The value of the header
3266         * @access private
3267         */
3268         function setHeader($name, $value) {
3269                 $this->outgoing_headers[$name] = $value;
3270                 $this->debug("set header $name: $value");
3271         }
3272
3273         /**
3274         * unsets an HTTP header
3275         *
3276         * @param string $name The name of the header
3277         * @access private
3278         */
3279         function unsetHeader($name) {
3280                 if (isset($this->outgoing_headers[$name])) {
3281                         $this->debug("unset header $name");
3282                         unset($this->outgoing_headers[$name]);
3283                 }
3284         }
3285
3286         /**
3287         * sets the URL to which to connect
3288         *
3289         * @param string $url The URL to which to connect
3290         * @access private
3291         */
3292         function setURL($url) {
3293                 $this->url = $url;
3294
3295                 $u = parse_url($url);
3296                 foreach($u as $k => $v){
3297                         $this->debug("parsed URL $k = $v");
3298                         $this->$k = $v;
3299                 }
3300                 
3301                 // add any GET params to path
3302                 if(isset($u['query']) && $u['query'] != ''){
3303             $this->path .= '?' . $u['query'];
3304                 }
3305                 
3306                 // set default port
3307                 if(!isset($u['port'])){
3308                         if($u['scheme'] == 'https'){
3309                                 $this->port = 443;
3310                         } else {
3311                                 $this->port = 80;
3312                         }
3313                 }
3314                 
3315                 $this->uri = $this->path;
3316                 $this->digest_uri = $this->uri;
3317                 
3318                 // build headers
3319                 if (!isset($u['port'])) {
3320                         $this->setHeader('Host', $this->host);
3321                 } else {
3322                         $this->setHeader('Host', $this->host.':'.$this->port);
3323                 }
3324
3325                 if (isset($u['user']) && $u['user'] != '') {
3326                         $this->setCredentials(urldecode($u['user']), isset($u['pass']) ? urldecode($u['pass']) : '');
3327                 }
3328         }
3329
3330         /**
3331         * gets the I/O method to use
3332         *
3333         * @return       string  I/O method to use (socket|curl|unknown)
3334         * @access       private
3335         */
3336         function io_method() {
3337                 if ($this->use_curl || ($this->scheme == 'https') || ($this->scheme == 'http' && $this->authtype == 'ntlm') || ($this->scheme == 'http' && is_array($this->proxy) && $this->proxy['authtype'] == 'ntlm'))
3338                         return 'curl';
3339                 if (($this->scheme == 'http' || $this->scheme == 'ssl') && $this->authtype != 'ntlm' && (!is_array($this->proxy) || $this->proxy['authtype'] != 'ntlm'))
3340                         return 'socket';
3341                 return 'unknown';
3342         }
3343
3344         /**
3345         * establish an HTTP connection
3346         *
3347         * @param    integer $timeout set connection timeout in seconds
3348         * @param        integer $response_timeout set response timeout in seconds
3349         * @return       boolean true if connected, false if not
3350         * @access   private
3351         */
3352         function connect($connection_timeout=0,$response_timeout=30){
3353                 // For PHP 4.3 with OpenSSL, change https scheme to ssl, then treat like
3354                 // "regular" socket.
3355                 // TODO: disabled for now because OpenSSL must be *compiled* in (not just
3356                 //       loaded), and until PHP5 stream_get_wrappers is not available.
3357 //              if ($this->scheme == 'https') {
3358 //                      if (version_compare(phpversion(), '4.3.0') >= 0) {
3359 //                              if (extension_loaded('openssl')) {
3360 //                                      $this->scheme = 'ssl';
3361 //                                      $this->debug('Using SSL over OpenSSL');
3362 //                              }
3363 //                      }
3364 //              }
3365                 $this->debug("connect connection_timeout $connection_timeout, response_timeout $response_timeout, scheme $this->scheme, host $this->host, port $this->port");
3366           if ($this->io_method() == 'socket') {
3367                 if (!is_array($this->proxy)) {
3368                         $host = $this->host;
3369                         $port = $this->port;
3370                 } else {
3371                         $host = $this->proxy['host'];
3372                         $port = $this->proxy['port'];
3373                 }
3374
3375                 // use persistent connection
3376                 if($this->persistentConnection && isset($this->fp) && is_resource($this->fp)){
3377                         if (!feof($this->fp)) {
3378                                 $this->debug('Re-use persistent connection');
3379                                 return true;
3380                         }
3381                         fclose($this->fp);
3382                         $this->debug('Closed persistent connection at EOF');
3383                 }
3384
3385                 // munge host if using OpenSSL
3386                 if ($this->scheme == 'ssl') {
3387                         $host = 'ssl://' . $host;
3388                 }
3389                 $this->debug('calling fsockopen with host ' . $host . ' connection_timeout ' . $connection_timeout);
3390
3391                 // open socket
3392                 if($connection_timeout > 0){
3393                         $this->fp = @fsockopen( $host, $this->port, $this->errno, $this->error_str, $connection_timeout);
3394                 } else {
3395                         $this->fp = @fsockopen( $host, $this->port, $this->errno, $this->error_str);
3396                 }
3397                 
3398                 // test pointer
3399                 if(!$this->fp) {
3400                         $msg = 'Couldn\'t open socket connection to server ' . $this->url;
3401                         if ($this->errno) {
3402                                 $msg .= ', Error ('.$this->errno.'): '.$this->error_str;
3403                         } else {
3404                                 $msg .= ' prior to connect().  This is often a problem looking up the host name.';
3405                         }
3406                         $this->debug($msg);
3407                         $this->setError($msg);
3408                         return false;
3409                 }
3410                 
3411                 // set response timeout
3412                 $this->debug('set response timeout to ' . $response_timeout);
3413                 socket_set_timeout( $this->fp, $response_timeout);
3414
3415                 $this->debug('socket connected');
3416                 return true;
3417           } else if ($this->io_method() == 'curl') {
3418                 if (!extension_loaded('curl')) {
3419 //                      $this->setError('cURL Extension, or OpenSSL extension w/ PHP version >= 4.3 is required for HTTPS');
3420                         $this->setError('The PHP cURL Extension is required for HTTPS or NLTM.  You will need to re-build or update your PHP to include cURL or change php.ini to load the PHP cURL extension.');
3421                         return false;
3422                 }
3423                 // Avoid warnings when PHP does not have these options
3424                 if (defined('CURLOPT_CONNECTIONTIMEOUT'))
3425                         $CURLOPT_CONNECTIONTIMEOUT = CURLOPT_CONNECTIONTIMEOUT;
3426                 else
3427                         $CURLOPT_CONNECTIONTIMEOUT = 78;
3428                 if (defined('CURLOPT_HTTPAUTH'))
3429                         $CURLOPT_HTTPAUTH = CURLOPT_HTTPAUTH;
3430                 else
3431                         $CURLOPT_HTTPAUTH = 107;
3432                 if (defined('CURLOPT_PROXYAUTH'))
3433                         $CURLOPT_PROXYAUTH = CURLOPT_PROXYAUTH;
3434                 else
3435                         $CURLOPT_PROXYAUTH = 111;
3436                 if (defined('CURLAUTH_BASIC'))
3437                         $CURLAUTH_BASIC = CURLAUTH_BASIC;
3438                 else
3439                         $CURLAUTH_BASIC = 1;
3440                 if (defined('CURLAUTH_DIGEST'))
3441                         $CURLAUTH_DIGEST = CURLAUTH_DIGEST;
3442                 else
3443                         $CURLAUTH_DIGEST = 2;
3444                 if (defined('CURLAUTH_NTLM'))
3445                         $CURLAUTH_NTLM = CURLAUTH_NTLM;
3446                 else
3447                         $CURLAUTH_NTLM = 8;
3448
3449                 $this->debug('connect using cURL');
3450                 // init CURL
3451                 $this->ch = curl_init();
3452                 // set url
3453                 $hostURL = ($this->port != '') ? "$this->scheme://$this->host:$this->port" : "$this->scheme://$this->host";
3454                 // add path
3455                 $hostURL .= $this->path;
3456                 $this->setCurlOption(CURLOPT_URL, $hostURL);
3457                 // follow location headers (re-directs)
3458                 if (ini_get('safe_mode') || ini_get('open_basedir')) {
3459                         $this->debug('safe_mode or open_basedir set, so do not set CURLOPT_FOLLOWLOCATION');
3460                         $this->debug('safe_mode = ');
3461                         $this->appendDebug($this->varDump(ini_get('safe_mode')));
3462                         $this->debug('open_basedir = ');
3463                         $this->appendDebug($this->varDump(ini_get('open_basedir')));
3464                 } else {
3465                         $this->setCurlOption(CURLOPT_FOLLOWLOCATION, 1);
3466                 }
3467                 // ask for headers in the response output
3468                 $this->setCurlOption(CURLOPT_HEADER, 1);
3469                 // ask for the response output as the return value
3470                 $this->setCurlOption(CURLOPT_RETURNTRANSFER, 1);
3471                 // encode
3472                 // We manage this ourselves through headers and encoding
3473 //              if(function_exists('gzuncompress')){
3474 //                      $this->setCurlOption(CURLOPT_ENCODING, 'deflate');
3475 //              }
3476                 // persistent connection
3477                 if ($this->persistentConnection) {
3478                         // I believe the following comment is now bogus, having applied to
3479                         // the code when it used CURLOPT_CUSTOMREQUEST to send the request.
3480                         // The way we send data, we cannot use persistent connections, since
3481                         // there will be some "junk" at the end of our request.
3482                         //$this->setCurlOption(CURL_HTTP_VERSION_1_1, true);
3483                         $this->persistentConnection = false;
3484                         $this->setHeader('Connection', 'close');
3485                 }
3486                 // set timeouts
3487                 if ($connection_timeout != 0) {
3488                         $this->setCurlOption($CURLOPT_CONNECTIONTIMEOUT, $connection_timeout);
3489                 }
3490                 if ($response_timeout != 0) {
3491                         $this->setCurlOption(CURLOPT_TIMEOUT, $response_timeout);
3492                 }
3493
3494                 if ($this->scheme == 'https') {
3495                         $this->debug('set cURL SSL verify options');
3496                         // recent versions of cURL turn on peer/host checking by default,
3497                         // while PHP binaries are not compiled with a default location for the
3498                         // CA cert bundle, so disable peer/host checking.
3499                         //$this->setCurlOption(CURLOPT_CAINFO, 'f:\php-4.3.2-win32\extensions\curl-ca-bundle.crt');             
3500                         $this->setCurlOption(CURLOPT_SSL_VERIFYPEER, 0);
3501                         $this->setCurlOption(CURLOPT_SSL_VERIFYHOST, 0);
3502         
3503                         // support client certificates (thanks Tobias Boes, Doug Anarino, Eryan Ariobowo)
3504                         if ($this->authtype == 'certificate') {
3505                                 $this->debug('set cURL certificate options');
3506                                 if (isset($this->certRequest['cainfofile'])) {
3507                                         $this->setCurlOption(CURLOPT_CAINFO, $this->certRequest['cainfofile']);
3508                                 }
3509                                 if (isset($this->certRequest['verifypeer'])) {
3510                                         $this->setCurlOption(CURLOPT_SSL_VERIFYPEER, $this->certRequest['verifypeer']);
3511                                 } else {
3512                                         $this->setCurlOption(CURLOPT_SSL_VERIFYPEER, 1);
3513                                 }
3514                                 if (isset($this->certRequest['verifyhost'])) {
3515                                         $this->setCurlOption(CURLOPT_SSL_VERIFYHOST, $this->certRequest['verifyhost']);
3516                                 } else {
3517                                         $this->setCurlOption(CURLOPT_SSL_VERIFYHOST, 1);
3518                                 }
3519                                 if (isset($this->certRequest['sslcertfile'])) {
3520                                         $this->setCurlOption(CURLOPT_SSLCERT, $this->certRequest['sslcertfile']);
3521                                 }
3522                                 if (isset($this->certRequest['sslkeyfile'])) {
3523                                         $this->setCurlOption(CURLOPT_SSLKEY, $this->certRequest['sslkeyfile']);
3524                                 }
3525                                 if (isset($this->certRequest['passphrase'])) {
3526                                         $this->setCurlOption(CURLOPT_SSLKEYPASSWD, $this->certRequest['passphrase']);
3527                                 }
3528                                 if (isset($this->certRequest['certpassword'])) {
3529                                         $this->setCurlOption(CURLOPT_SSLCERTPASSWD, $this->certRequest['certpassword']);
3530                                 }
3531                         }
3532                 }
3533                 if ($this->authtype && ($this->authtype != 'certificate')) {
3534                         if ($this->username) {
3535                                 $this->debug('set cURL username/password');
3536                                 $this->setCurlOption(CURLOPT_USERPWD, "$this->username:$this->password");
3537                         }
3538                         if ($this->authtype == 'basic') {
3539                                 $this->debug('set cURL for Basic authentication');
3540                                 $this->setCurlOption($CURLOPT_HTTPAUTH, $CURLAUTH_BASIC);
3541                         }
3542                         if ($this->authtype == 'digest') {
3543                                 $this->debug('set cURL for digest authentication');
3544                                 $this->setCurlOption($CURLOPT_HTTPAUTH, $CURLAUTH_DIGEST);
3545                         }
3546                         if ($this->authtype == 'ntlm') {
3547                                 $this->debug('set cURL for NTLM authentication');
3548                                 $this->setCurlOption($CURLOPT_HTTPAUTH, $CURLAUTH_NTLM);
3549                         }
3550                 }
3551                 if (is_array($this->proxy)) {
3552                         $this->debug('set cURL proxy options');
3553                         if ($this->proxy['port'] != '') {
3554                                 $this->setCurlOption(CURLOPT_PROXY, $this->proxy['host'].':'.$this->proxy['port']);
3555                         } else {
3556                                 $this->setCurlOption(CURLOPT_PROXY, $this->proxy['host']);
3557                         }
3558                         if ($this->proxy['username'] || $this->proxy['password']) {
3559                                 $this->debug('set cURL proxy authentication options');
3560                                 $this->setCurlOption(CURLOPT_PROXYUSERPWD, $this->proxy['username'].':'.$this->proxy['password']);
3561                                 if ($this->proxy['authtype'] == 'basic') {
3562                                         $this->setCurlOption($CURLOPT_PROXYAUTH, $CURLAUTH_BASIC);
3563                                 }
3564                                 if ($this->proxy['authtype'] == 'ntlm') {
3565                                         $this->setCurlOption($CURLOPT_PROXYAUTH, $CURLAUTH_NTLM);
3566                                 }
3567                         }
3568                 }
3569                 $this->debug('cURL connection set up');
3570                 return true;
3571           } else {
3572                 $this->setError('Unknown scheme ' . $this->scheme);
3573                 $this->debug('Unknown scheme ' . $this->scheme);
3574                 return false;
3575           }
3576         }
3577
3578         /**
3579         * sends the SOAP request and gets the SOAP response via HTTP[S]
3580         *
3581         * @param    string $data message data
3582         * @param    integer $timeout set connection timeout in seconds
3583         * @param        integer $response_timeout set response timeout in seconds
3584         * @param        array $cookies cookies to send
3585         * @return       string data
3586         * @access   public
3587         */
3588         function send($data, $timeout=0, $response_timeout=30, $cookies=NULL) {
3589                 
3590                 $this->debug('entered send() with data of length: '.strlen($data));
3591
3592                 $this->tryagain = true;
3593                 $tries = 0;
3594                 while ($this->tryagain) {
3595                         $this->tryagain = false;
3596                         if ($tries++ < 2) {
3597                                 // make connnection
3598                                 if (!$this->connect($timeout, $response_timeout)){
3599                                         return false;
3600                                 }
3601                                 
3602                                 // send request
3603                                 if (!$this->sendRequest($data, $cookies)){
3604                                         return false;
3605                                 }
3606                                 
3607                                 // get response
3608                                 $respdata = $this->getResponse();
3609                         } else {
3610                                 $this->setError("Too many tries to get an OK response ($this->response_status_line)");
3611                         }
3612                 }               
3613                 $this->debug('end of send()');
3614                 return $respdata;
3615         }
3616
3617
3618         /**
3619         * sends the SOAP request and gets the SOAP response via HTTPS using CURL
3620         *
3621         * @param    string $data message data
3622         * @param    integer $timeout set connection timeout in seconds
3623         * @param        integer $response_timeout set response timeout in seconds
3624         * @param        array $cookies cookies to send
3625         * @return       string data
3626         * @access   public
3627         * @deprecated
3628         */
3629         function sendHTTPS($data, $timeout=0, $response_timeout=30, $cookies) {
3630                 return $this->send($data, $timeout, $response_timeout, $cookies);
3631         }
3632         
3633         /**
3634         * if authenticating, set user credentials here
3635         *
3636         * @param    string $username
3637         * @param    string $password
3638         * @param        string $authtype (basic|digest|certificate|ntlm)
3639         * @param        array $digestRequest (keys must be nonce, nc, realm, qop)
3640         * @param        array $certRequest (keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, certpassword (optional), verifypeer (optional), verifyhost (optional): see corresponding options in cURL docs)
3641         * @access   public
3642         */
3643         function setCredentials($username, $password, $authtype = 'basic', $digestRequest = array(), $certRequest = array()) {
3644                 $this->debug("setCredentials username=$username authtype=$authtype digestRequest=");
3645                 $this->appendDebug($this->varDump($digestRequest));
3646                 $this->debug("certRequest=");
3647                 $this->appendDebug($this->varDump($certRequest));
3648                 // cf. RFC 2617
3649                 if ($authtype == 'basic') {
3650                         $this->setHeader('Authorization', 'Basic '.base64_encode(str_replace(':','',$username).':'.$password));
3651                 } elseif ($authtype == 'digest') {
3652                         if (isset($digestRequest['nonce'])) {
3653                                 $digestRequest['nc'] = isset($digestRequest['nc']) ? $digestRequest['nc']++ : 1;
3654                                 
3655                                 // calculate the Digest hashes (calculate code based on digest implementation found at: http://www.rassoc.com/gregr/weblog/stories/2002/07/09/webServicesSecurityHttpDigestAuthenticationWithoutActiveDirectory.html)
3656         
3657                                 // A1 = unq(username-value) ":" unq(realm-value) ":" passwd
3658                                 $A1 = $username. ':' . (isset($digestRequest['realm']) ? $digestRequest['realm'] : '') . ':' . $password;
3659         
3660                                 // H(A1) = MD5(A1)
3661                                 $HA1 = md5($A1);
3662         
3663                                 // A2 = Method ":" digest-uri-value
3664                                 $A2 = $this->request_method . ':' . $this->digest_uri;
3665         
3666                                 // H(A2)
3667                                 $HA2 =  md5($A2);
3668         
3669                                 // KD(secret, data) = H(concat(secret, ":", data))
3670                                 // if qop == auth:
3671                                 // request-digest  = <"> < KD ( H(A1),     unq(nonce-value)
3672                                 //                              ":" nc-value
3673                                 //                              ":" unq(cnonce-value)
3674                                 //                              ":" unq(qop-value)
3675                                 //                              ":" H(A2)
3676                                 //                            ) <">
3677                                 // if qop is missing,
3678                                 // request-digest  = <"> < KD ( H(A1), unq(nonce-value) ":" H(A2) ) > <">
3679         
3680                                 $unhashedDigest = '';
3681                                 $nonce = isset($digestRequest['nonce']) ? $digestRequest['nonce'] : '';
3682                                 $cnonce = $nonce;
3683                                 if ($digestRequest['qop'] != '') {
3684                                         $unhashedDigest = $HA1 . ':' . $nonce . ':' . sprintf("%08d", $digestRequest['nc']) . ':' . $cnonce . ':' . $digestRequest['qop'] . ':' . $HA2;
3685                                 } else {
3686                                         $unhashedDigest = $HA1 . ':' . $nonce . ':' . $HA2;
3687                                 }
3688         
3689                                 $hashedDigest = md5($unhashedDigest);
3690         
3691                                 $opaque = '';   
3692                                 if (isset($digestRequest['opaque'])) {
3693                                         $opaque = ', opaque="' . $digestRequest['opaque'] . '"';
3694                                 }
3695
3696                                 $this->setHeader('Authorization', 'Digest username="' . $username . '", realm="' . $digestRequest['realm'] . '", nonce="' . $nonce . '", uri="' . $this->digest_uri . $opaque . '", cnonce="' . $cnonce . '", nc=' . sprintf("%08x", $digestRequest['nc']) . ', qop="' . $digestRequest['qop'] . '", response="' . $hashedDigest . '"');
3697                         }
3698                 } elseif ($authtype == 'certificate') {
3699                         $this->certRequest = $certRequest;
3700                         $this->debug('Authorization header not set for certificate');
3701                 } elseif ($authtype == 'ntlm') {
3702                         // do nothing
3703                         $this->debug('Authorization header not set for ntlm');
3704                 }
3705                 $this->username = $username;
3706                 $this->password = $password;
3707                 $this->authtype = $authtype;
3708                 $this->digestRequest = $digestRequest;
3709         }
3710         
3711         /**
3712         * set the soapaction value
3713         *
3714         * @param    string $soapaction
3715         * @access   public
3716         */
3717         function setSOAPAction($soapaction) {
3718                 $this->setHeader('SOAPAction', '"' . $soapaction . '"');
3719         }
3720         
3721         /**
3722         * use http encoding
3723         *
3724         * @param    string $enc encoding style. supported values: gzip, deflate, or both
3725         * @access   public
3726         */
3727         function setEncoding($enc='gzip, deflate') {
3728                 if (function_exists('gzdeflate')) {
3729                         $this->protocol_version = '1.1';
3730                         $this->setHeader('Accept-Encoding', $enc);
3731                         if (!isset($this->outgoing_headers['Connection'])) {
3732                                 $this->setHeader('Connection', 'close');
3733                                 $this->persistentConnection = false;
3734                         }
3735                         // deprecated as of PHP 5.3.0
3736                         //set_magic_quotes_runtime(0);
3737                         $this->encoding = $enc;
3738                 }
3739         }
3740         
3741         /**
3742         * set proxy info here
3743         *
3744         * @param    string $proxyhost use an empty string to remove proxy
3745         * @param    string $proxyport
3746         * @param        string $proxyusername
3747         * @param        string $proxypassword
3748         * @param        string $proxyauthtype (basic|ntlm)
3749         * @access   public
3750         */
3751         function setProxy($proxyhost, $proxyport, $proxyusername = '', $proxypassword = '', $proxyauthtype = 'basic') {
3752                 if ($proxyhost) {
3753                         $this->proxy = array(
3754                                 'host' => $proxyhost,
3755                                 'port' => $proxyport,
3756                                 'username' => $proxyusername,
3757                                 'password' => $proxypassword,
3758                                 'authtype' => $proxyauthtype
3759                         );
3760                         if ($proxyusername != '' && $proxypassword != '' && $proxyauthtype = 'basic') {
3761                                 $this->setHeader('Proxy-Authorization', ' Basic '.base64_encode($proxyusername.':'.$proxypassword));
3762                         }
3763                 } else {
3764                         $this->debug('remove proxy');
3765                         $proxy = null;
3766                         unsetHeader('Proxy-Authorization');
3767                 }
3768         }
3769         
3770
3771         /**
3772          * Test if the given string starts with a header that is to be skipped.
3773          * Skippable headers result from chunked transfer and proxy requests.
3774          *
3775          * @param       string $data The string to check.
3776          * @returns     boolean Whether a skippable header was found.
3777          * @access      private
3778          */
3779         function isSkippableCurlHeader(&$data) {
3780                 $skipHeaders = array(   'HTTP/1.1 100',
3781                                                                 'HTTP/1.0 301',
3782                                                                 'HTTP/1.1 301',
3783                                                                 'HTTP/1.0 302',
3784                                                                 'HTTP/1.1 302',
3785                                                                 'HTTP/1.0 401',
3786                                                                 'HTTP/1.1 401',
3787                                                                 'HTTP/1.0 200 Connection established');
3788                 foreach ($skipHeaders as $hd) {
3789                         $prefix = substr($data, 0, strlen($hd));
3790                         if ($prefix == $hd) return true;
3791                 }
3792
3793                 return false;
3794         }
3795
3796         /**
3797         * decode a string that is encoded w/ "chunked' transfer encoding
3798         * as defined in RFC2068 19.4.6
3799         *
3800         * @param    string $buffer
3801         * @param    string $lb
3802         * @returns      string
3803         * @access   public
3804         * @deprecated
3805         */
3806         function decodeChunked($buffer, $lb){
3807                 // length := 0
3808                 $length = 0;
3809                 $new = '';
3810                 
3811                 // read chunk-size, chunk-extension (if any) and CRLF
3812                 // get the position of the linebreak
3813                 $chunkend = strpos($buffer, $lb);
3814                 if ($chunkend == FALSE) {
3815                         $this->debug('no linebreak found in decodeChunked');
3816                         return $new;
3817                 }
3818                 $temp = substr($buffer,0,$chunkend);
3819                 $chunk_size = hexdec( trim($temp) );
3820                 $chunkstart = $chunkend + strlen($lb);
3821                 // while (chunk-size > 0) {
3822                 while ($chunk_size > 0) {
3823                         $this->debug("chunkstart: $chunkstart chunk_size: $chunk_size");
3824                         $chunkend = strpos( $buffer, $lb, $chunkstart + $chunk_size);
3825                         
3826                         // Just in case we got a broken connection
3827                         if ($chunkend == FALSE) {
3828                             $chunk = substr($buffer,$chunkstart);
3829                                 // append chunk-data to entity-body
3830                         $new .= $chunk;
3831                             $length += strlen($chunk);
3832                             break;
3833                         }
3834                         
3835                         // read chunk-data and CRLF
3836                         $chunk = substr($buffer,$chunkstart,$chunkend-$chunkstart);
3837                         // append chunk-data to entity-body
3838                         $new .= $chunk;
3839                         // length := length + chunk-size
3840                         $length += strlen($chunk);
3841                         // read chunk-size and CRLF
3842                         $chunkstart = $chunkend + strlen($lb);
3843                         
3844                         $chunkend = strpos($buffer, $lb, $chunkstart) + strlen($lb);
3845                         if ($chunkend == FALSE) {
3846                                 break; //Just in case we got a broken connection
3847                         }
3848                         $temp = substr($buffer,$chunkstart,$chunkend-$chunkstart);
3849                         $chunk_size = hexdec( trim($temp) );
3850                         $chunkstart = $chunkend;
3851                 }
3852                 return $new;
3853         }
3854         
3855         /**
3856          * Writes the payload, including HTTP headers, to $this->outgoing_payload.
3857          *
3858          * @param       string $data HTTP body
3859          * @param       string $cookie_str data for HTTP Cookie header
3860          * @return      void
3861          * @access      private
3862          */
3863         function buildPayload($data, $cookie_str = '') {
3864                 // Note: for cURL connections, $this->outgoing_payload is ignored,
3865                 // as is the Content-Length header, but these are still created as
3866                 // debugging guides.
3867
3868                 // add content-length header
3869                 if ($this->request_method != 'GET') {
3870                         $this->setHeader('Content-Length', strlen($data));
3871                 }
3872
3873                 // start building outgoing payload:
3874                 if ($this->proxy) {
3875                         $uri = $this->url;
3876                 } else {
3877                         $uri = $this->uri;
3878                 }
3879                 $req = "$this->request_method $uri HTTP/$this->protocol_version";
3880                 $this->debug("HTTP request: $req");
3881                 $this->outgoing_payload = "$req\r\n";
3882
3883                 // loop thru headers, serializing
3884                 foreach($this->outgoing_headers as $k => $v){
3885                         $hdr = $k.': '.$v;
3886                         $this->debug("HTTP header: $hdr");
3887                         $this->outgoing_payload .= "$hdr\r\n";
3888                 }
3889
3890                 // add any cookies
3891                 if ($cookie_str != '') {
3892                         $hdr = 'Cookie: '.$cookie_str;
3893                         $this->debug("HTTP header: $hdr");
3894                         $this->outgoing_payload .= "$hdr\r\n";
3895                 }
3896
3897                 // header/body separator
3898                 $this->outgoing_payload .= "\r\n";
3899                 
3900                 // add data
3901                 $this->outgoing_payload .= $data;
3902         }
3903
3904         /**
3905         * sends the SOAP request via HTTP[S]
3906         *
3907         * @param    string $data message data
3908         * @param        array $cookies cookies to send
3909         * @return       boolean true if OK, false if problem
3910         * @access   private
3911         */
3912         function sendRequest($data, $cookies = NULL) {
3913                 // build cookie string
3914                 $cookie_str = $this->getCookiesForRequest($cookies, (($this->scheme == 'ssl') || ($this->scheme == 'https')));
3915
3916                 // build payload
3917                 $this->buildPayload($data, $cookie_str);
3918
3919           if ($this->io_method() == 'socket') {
3920                 // send payload
3921                 if(!fputs($this->fp, $this->outgoing_payload, strlen($this->outgoing_payload))) {
3922                         $this->setError('couldn\'t write message data to socket');
3923                         $this->debug('couldn\'t write message data to socket');
3924                         return false;
3925                 }
3926                 $this->debug('wrote data to socket, length = ' . strlen($this->outgoing_payload));
3927                 return true;
3928           } else if ($this->io_method() == 'curl') {
3929                 // set payload
3930                 // cURL does say this should only be the verb, and in fact it
3931                 // turns out that the URI and HTTP version are appended to this, which
3932                 // some servers refuse to work with (so we no longer use this method!)
3933                 //$this->setCurlOption(CURLOPT_CUSTOMREQUEST, $this->outgoing_payload);
3934                 $curl_headers = array();
3935                 foreach($this->outgoing_headers as $k => $v){
3936                         if ($k == 'Connection' || $k == 'Content-Length' || $k == 'Host' || $k == 'Authorization' || $k == 'Proxy-Authorization') {
3937                                 $this->debug("Skip cURL header $k: $v");
3938                         } else {
3939                                 $curl_headers[] = "$k: $v";
3940                         }
3941                 }
3942                 if ($cookie_str != '') {
3943                         $curl_headers[] = 'Cookie: ' . $cookie_str;
3944                 }
3945                 $this->setCurlOption(CURLOPT_HTTPHEADER, $curl_headers);
3946                 $this->debug('set cURL HTTP headers');
3947                 if ($this->request_method == "POST") {
3948                         $this->setCurlOption(CURLOPT_POST, 1);
3949                         $this->setCurlOption(CURLOPT_POSTFIELDS, $data);
3950                         $this->debug('set cURL POST data');
3951                 } else {
3952                 }
3953                 // insert custom user-set cURL options
3954                 foreach ($this->ch_options as $key => $val) {
3955                         $this->setCurlOption($key, $val);
3956                 }
3957
3958                 $this->debug('set cURL payload');
3959                 return true;
3960           }
3961         }
3962
3963         /**
3964         * gets the SOAP response via HTTP[S]
3965         *
3966         * @return       string the response (also sets member variables like incoming_payload)
3967         * @access   private
3968         */
3969         function getResponse(){
3970                 $this->incoming_payload = '';
3971             
3972           if ($this->io_method() == 'socket') {
3973             // loop until headers have been retrieved
3974             $data = '';
3975             while (!isset($lb)){
3976
3977                         // We might EOF during header read.
3978                         if(feof($this->fp)) {
3979                                 $this->incoming_payload = $data;
3980                                 $this->debug('found no headers before EOF after length ' . strlen($data));
3981                                 $this->debug("received before EOF:\n" . $data);
3982                                 $this->setError('server failed to send headers');
3983                                 return false;
3984                         }
3985
3986                         $tmp = fgets($this->fp, 256);
3987                         $tmplen = strlen($tmp);
3988                         $this->debug("read line of $tmplen bytes: " . trim($tmp));
3989
3990                         if ($tmplen == 0) {
3991                                 $this->incoming_payload = $data;
3992                                 $this->debug('socket read of headers timed out after length ' . strlen($data));
3993                                 $this->debug("read before timeout: " . $data);
3994                                 $this->setError('socket read of headers timed out');
3995                                 return false;
3996                         }
3997
3998                         $data .= $tmp;
3999                         $pos = strpos($data,"\r\n\r\n");
4000                         if($pos > 1){
4001                                 $lb = "\r\n";
4002                         } else {
4003                                 $pos = strpos($data,"\n\n");
4004                                 if($pos > 1){
4005                                         $lb = "\n";
4006                                 }
4007                         }
4008                         // remove 100 headers
4009                         if (isset($lb) && preg_match('/^HTTP\/1.1 100/',$data)) {
4010                                 unset($lb);
4011                                 $data = '';
4012                         }//
4013                 }
4014                 // store header data
4015                 $this->incoming_payload .= $data;
4016                 $this->debug('found end of headers after length ' . strlen($data));
4017                 // process headers
4018                 $header_data = trim(substr($data,0,$pos));
4019                 $header_array = explode($lb,$header_data);
4020                 $this->incoming_headers = array();
4021                 $this->incoming_cookies = array();
4022                 foreach($header_array as $header_line){
4023                         $arr = explode(':',$header_line, 2);
4024                         if(count($arr) > 1){
4025                                 $header_name = strtolower(trim($arr[0]));
4026                                 $this->incoming_headers[$header_name] = trim($arr[1]);
4027                                 if ($header_name == 'set-cookie') {
4028                                         // TODO: allow multiple cookies from parseCookie
4029                                         $cookie = $this->parseCookie(trim($arr[1]));
4030                                         if ($cookie) {
4031                                                 $this->incoming_cookies[] = $cookie;
4032                                                 $this->debug('found cookie: ' . $cookie['name'] . ' = ' . $cookie['value']);
4033                                         } else {
4034                                                 $this->debug('did not find cookie in ' . trim($arr[1]));
4035                                         }
4036                         }
4037                         } else if (isset($header_name)) {
4038                                 // append continuation line to previous header
4039                                 $this->incoming_headers[$header_name] .= $lb . ' ' . $header_line;
4040                         }
4041                 }
4042                 
4043                 // loop until msg has been received
4044                 if (isset($this->incoming_headers['transfer-encoding']) && strtolower($this->incoming_headers['transfer-encoding']) == 'chunked') {
4045                         $content_length =  2147483647;  // ignore any content-length header
4046                         $chunked = true;
4047                         $this->debug("want to read chunked content");
4048                 } elseif (isset($this->incoming_headers['content-length'])) {
4049                         $content_length = $this->incoming_headers['content-length'];
4050                         $chunked = false;
4051                         $this->debug("want to read content of length $content_length");
4052                 } else {
4053                         $content_length =  2147483647;
4054                         $chunked = false;
4055                         $this->debug("want to read content to EOF");
4056                 }
4057                 $data = '';
4058                 do {
4059                         if ($chunked) {
4060                                 $tmp = fgets($this->fp, 256);
4061                                 $tmplen = strlen($tmp);
4062                                 $this->debug("read chunk line of $tmplen bytes");
4063                                 if ($tmplen == 0) {
4064                                         $this->incoming_payload = $data;
4065                                         $this->debug('socket read of chunk length timed out after length ' . strlen($data));
4066                                         $this->debug("read before timeout:\n" . $data);
4067                                         $this->setError('socket read of chunk length timed out');
4068                                         return false;
4069                                 }
4070                                 $content_length = hexdec(trim($tmp));
4071                                 $this->debug("chunk length $content_length");
4072                         }
4073                         $strlen = 0;
4074                     while (($strlen < $content_length) && (!feof($this->fp))) {
4075                         $readlen = min(8192, $content_length - $strlen);
4076                                 $tmp = fread($this->fp, $readlen);
4077                                 $tmplen = strlen($tmp);
4078                                 $this->debug("read buffer of $tmplen bytes");
4079                                 if (($tmplen == 0) && (!feof($this->fp))) {
4080                                         $this->incoming_payload = $data;
4081                                         $this->debug('socket read of body timed out after length ' . strlen($data));
4082                                         $this->debug("read before timeout:\n" . $data);
4083                                         $this->setError('socket read of body timed out');
4084                                         return false;
4085                                 }
4086                                 $strlen += $tmplen;
4087                                 $data .= $tmp;
4088                         }
4089                         if ($chunked && ($content_length > 0)) {
4090                                 $tmp = fgets($this->fp, 256);
4091                                 $tmplen = strlen($tmp);
4092                                 $this->debug("read chunk terminator of $tmplen bytes");
4093                                 if ($tmplen == 0) {
4094                                         $this->incoming_payload = $data;
4095                                         $this->debug('socket read of chunk terminator timed out after length ' . strlen($data));
4096                                         $this->debug("read before timeout:\n" . $data);
4097                                         $this->setError('socket read of chunk terminator timed out');
4098                                         return false;
4099                                 }
4100                         }
4101                 } while ($chunked && ($content_length > 0) && (!feof($this->fp)));
4102                 if (feof($this->fp)) {
4103                         $this->debug('read to EOF');
4104                 }
4105                 $this->debug('read body of length ' . strlen($data));
4106                 $this->incoming_payload .= $data;
4107                 $this->debug('received a total of '.strlen($this->incoming_payload).' bytes of data from server');
4108                 
4109                 // close filepointer
4110                 if(
4111                         (isset($this->incoming_headers['connection']) && strtolower($this->incoming_headers['connection']) == 'close') || 
4112                         (! $this->persistentConnection) || feof($this->fp)){
4113                         fclose($this->fp);
4114                         $this->fp = false;
4115                         $this->debug('closed socket');
4116                 }
4117                 
4118                 // connection was closed unexpectedly
4119                 if($this->incoming_payload == ''){
4120                         $this->setError('no response from server');
4121                         return false;
4122                 }
4123                 
4124                 // decode transfer-encoding
4125 //              if(isset($this->incoming_headers['transfer-encoding']) && strtolower($this->incoming_headers['transfer-encoding']) == 'chunked'){
4126 //                      if(!$data = $this->decodeChunked($data, $lb)){
4127 //                              $this->setError('Decoding of chunked data failed');
4128 //                              return false;
4129 //                      }
4130                         //print "<pre>\nde-chunked:\n---------------\n$data\n\n---------------\n</pre>";
4131                         // set decoded payload
4132 //                      $this->incoming_payload = $header_data.$lb.$lb.$data;
4133 //              }
4134         
4135           } else if ($this->io_method() == 'curl') {
4136                 // send and receive
4137                 $this->debug('send and receive with cURL');
4138                 $this->incoming_payload = curl_exec($this->ch);
4139                 $data = $this->incoming_payload;
4140
4141         $cErr = curl_error($this->ch);
4142                 if ($cErr != '') {
4143                 $err = 'cURL ERROR: '.curl_errno($this->ch).': '.$cErr.'<br>';
4144                 // TODO: there is a PHP bug that can cause this to SEGV for CURLINFO_CONTENT_TYPE
4145                         foreach(curl_getinfo($this->ch) as $k => $v){
4146                                 $err .= "$k: $v<br>";
4147                         }
4148                         $this->debug($err);
4149                         $this->setError($err);
4150                         curl_close($this->ch);
4151                 return false;
4152                 } else {
4153                         //echo '<pre>';
4154                         //var_dump(curl_getinfo($this->ch));
4155                         //echo '</pre>';
4156                 }
4157                 // close curl
4158                 $this->debug('No cURL error, closing cURL');
4159                 curl_close($this->ch);
4160                 
4161                 // try removing skippable headers
4162                 $savedata = $data;
4163                 while ($this->isSkippableCurlHeader($data)) {
4164                         $this->debug("Found HTTP header to skip");
4165                         if ($pos = strpos($data,"\r\n\r\n")) {
4166                                 $data = ltrim(substr($data,$pos));
4167                         } elseif($pos = strpos($data,"\n\n") ) {
4168                                 $data = ltrim(substr($data,$pos));
4169                         }
4170                 }
4171
4172                 if ($data == '') {
4173                         // have nothing left; just remove 100 header(s)
4174                         $data = $savedata;
4175                         while (preg_match('/^HTTP\/1.1 100/',$data)) {
4176                                 if ($pos = strpos($data,"\r\n\r\n")) {
4177                                         $data = ltrim(substr($data,$pos));
4178                                 } elseif($pos = strpos($data,"\n\n") ) {
4179                                         $data = ltrim(substr($data,$pos));
4180                                 }
4181                         }
4182                 }
4183                 
4184                 // separate content from HTTP headers
4185                 if ($pos = strpos($data,"\r\n\r\n")) {
4186                         $lb = "\r\n";
4187                 } elseif( $pos = strpos($data,"\n\n")) {
4188                         $lb = "\n";
4189                 } else {
4190                         $this->debug('no proper separation of headers and document');
4191                         $this->setError('no proper separation of headers and document');
4192                         return false;
4193                 }
4194                 $header_data = trim(substr($data,0,$pos));
4195                 $header_array = explode($lb,$header_data);
4196                 $data = ltrim(substr($data,$pos));
4197                 $this->debug('found proper separation of headers and document');
4198                 $this->debug('cleaned data, stringlen: '.strlen($data));
4199                 // clean headers
4200                 foreach ($header_array as $header_line) {
4201                         $arr = explode(':',$header_line,2);
4202                         if(count($arr) > 1){
4203                                 $header_name = strtolower(trim($arr[0]));
4204                                 $this->incoming_headers[$header_name] = trim($arr[1]);
4205                                 if ($header_name == 'set-cookie') {
4206                                         // TODO: allow multiple cookies from parseCookie
4207                                         $cookie = $this->parseCookie(trim($arr[1]));
4208                                         if ($cookie) {
4209                                                 $this->incoming_cookies[] = $cookie;
4210                                                 $this->debug('found cookie: ' . $cookie['name'] . ' = ' . $cookie['value']);
4211                                         } else {
4212                                                 $this->debug('did not find cookie in ' . trim($arr[1]));
4213                                         }
4214                         }
4215                         } else if (isset($header_name)) {
4216                                 // append continuation line to previous header
4217                                 $this->incoming_headers[$header_name] .= $lb . ' ' . $header_line;
4218                         }
4219                 }
4220           }
4221
4222                 $this->response_status_line = $header_array[0];
4223                 $arr = explode(' ', $this->response_status_line, 3);
4224                 $http_version = $arr[0];
4225                 $http_status = intval($arr[1]);
4226                 $http_reason = count($arr) > 2 ? $arr[2] : '';
4227
4228                 // see if we need to resend the request with http digest authentication
4229                 if (isset($this->incoming_headers['location']) && ($http_status == 301 || $http_status == 302)) {
4230                         $this->debug("Got $http_status $http_reason with Location: " . $this->incoming_headers['location']);
4231                         $this->setURL($this->incoming_headers['location']);
4232                         $this->tryagain = true;
4233                         return false;
4234                 }
4235
4236                 // see if we need to resend the request with http digest authentication
4237                 if (isset($this->incoming_headers['www-authenticate']) && $http_status == 401) {
4238                         $this->debug("Got 401 $http_reason with WWW-Authenticate: " . $this->incoming_headers['www-authenticate']);
4239                         if (strstr($this->incoming_headers['www-authenticate'], "Digest ")) {
4240                                 $this->debug('Server wants digest authentication');
4241                                 // remove "Digest " from our elements
4242                                 $digestString = str_replace('Digest ', '', $this->incoming_headers['www-authenticate']);
4243                                 
4244                                 // parse elements into array
4245                                 $digestElements = explode(',', $digestString);
4246                                 foreach ($digestElements as $val) {
4247                                         $tempElement = explode('=', trim($val), 2);
4248                                         $digestRequest[$tempElement[0]] = str_replace("\"", '', $tempElement[1]);
4249                                 }
4250
4251                                 // should have (at least) qop, realm, nonce
4252                                 if (isset($digestRequest['nonce'])) {
4253                                         $this->setCredentials($this->username, $this->password, 'digest', $digestRequest);
4254                                         $this->tryagain = true;
4255                                         return false;
4256                                 }
4257                         }
4258                         $this->debug('HTTP authentication failed');
4259                         $this->setError('HTTP authentication failed');
4260                         return false;
4261                 }
4262                 
4263                 if (
4264                         ($http_status >= 300 && $http_status <= 307) ||
4265                         ($http_status >= 400 && $http_status <= 417) ||
4266                         ($http_status >= 501 && $http_status <= 505)
4267                    ) {
4268                         $this->setError("Unsupported HTTP response status $http_status $http_reason (soapclient->response has contents of the response)");
4269                         return false;
4270                 }
4271
4272                 // decode content-encoding
4273                 if(isset($this->incoming_headers['content-encoding']) && $this->incoming_headers['content-encoding'] != ''){
4274                         if(strtolower($this->incoming_headers['content-encoding']) == 'deflate' || strtolower($this->incoming_headers['content-encoding']) == 'gzip'){
4275                         // if decoding works, use it. else assume data wasn't gzencoded
4276                         if(function_exists('gzinflate')){
4277                                         //$timer->setMarker('starting decoding of gzip/deflated content');
4278                                         // IIS 5 requires gzinflate instead of gzuncompress (similar to IE 5 and gzdeflate v. gzcompress)
4279                                         // this means there are no Zlib headers, although there should be
4280                                         $this->debug('The gzinflate function exists');
4281                                         $datalen = strlen($data);
4282                                         if ($this->incoming_headers['content-encoding'] == 'deflate') {
4283                                                 if ($degzdata = @gzinflate($data)) {
4284                                                 $data = $degzdata;
4285                                                 $this->debug('The payload has been inflated to ' . strlen($data) . ' bytes');
4286                                                 if (strlen($data) < $datalen) {
4287                                                         // test for the case that the payload has been compressed twice
4288                                                         $this->debug('The inflated payload is smaller than the gzipped one; try again');
4289                                                                 if ($degzdata = @gzinflate($data)) {
4290                                                                 $data = $degzdata;
4291                                                                 $this->debug('The payload has been inflated again to ' . strlen($data) . ' bytes');
4292                                                                 }
4293                                                 }
4294                                         } else {
4295                                                 $this->debug('Error using gzinflate to inflate the payload');
4296                                                 $this->setError('Error using gzinflate to inflate the payload');
4297                                         }
4298                                         } elseif ($this->incoming_headers['content-encoding'] == 'gzip') {
4299                                                 if ($degzdata = @gzinflate(substr($data, 10))) {        // do our best
4300                                                         $data = $degzdata;
4301                                                 $this->debug('The payload has been un-gzipped to ' . strlen($data) . ' bytes');
4302                                                 if (strlen($data) < $datalen) {
4303                                                         // test for the case that the payload has been compressed twice
4304                                                         $this->debug('The un-gzipped payload is smaller than the gzipped one; try again');
4305                                                                 if ($degzdata = @gzinflate(substr($data, 10))) {
4306                                                                 $data = $degzdata;
4307                                                                 $this->debug('The payload has been un-gzipped again to ' . strlen($data) . ' bytes');
4308                                                                 }
4309                                                 }
4310                                         } else {
4311                                                 $this->debug('Error using gzinflate to un-gzip the payload');
4312                                                         $this->setError('Error using gzinflate to un-gzip the payload');
4313                                         }
4314                                         }
4315                                         //$timer->setMarker('finished decoding of gzip/deflated content');
4316                                         //print "<xmp>\nde-inflated:\n---------------\n$data\n-------------\n</xmp>";
4317                                         // set decoded payload
4318                                         $this->incoming_payload = $header_data.$lb.$lb.$data;
4319                         } else {
4320                                         $this->debug('The server sent compressed data. Your php install must have the Zlib extension compiled in to support this.');
4321                                         $this->setError('The server sent compressed data. Your php install must have the Zlib extension compiled in to support this.');
4322                                 }
4323                         } else {
4324                                 $this->debug('Unsupported Content-Encoding ' . $this->incoming_headers['content-encoding']);
4325                                 $this->setError('Unsupported Content-Encoding ' . $this->incoming_headers['content-encoding']);
4326                         }
4327                 } else {
4328                         $this->debug('No Content-Encoding header');
4329                 }
4330                 
4331                 if(strlen($data) == 0){
4332                         $this->debug('no data after headers!');
4333                         $this->setError('no data present after HTTP headers');
4334                         return false;
4335                 }
4336                 
4337                 return $data;
4338         }
4339
4340         /**
4341          * sets the content-type for the SOAP message to be sent
4342          *
4343          * @param       string $type the content type, MIME style
4344          * @param       mixed $charset character set used for encoding (or false)
4345          * @access      public
4346          */
4347         function setContentType($type, $charset = false) {
4348                 $this->setHeader('Content-Type', $type . ($charset ? '; charset=' . $charset : ''));
4349         }
4350
4351         /**
4352          * specifies that an HTTP persistent connection should be used
4353          *
4354          * @return      boolean whether the request was honored by this method.
4355          * @access      public
4356          */
4357         function usePersistentConnection(){
4358                 if (isset($this->outgoing_headers['Accept-Encoding'])) {
4359                         return false;
4360                 }
4361                 $this->protocol_version = '1.1';
4362                 $this->persistentConnection = true;
4363                 $this->setHeader('Connection', 'Keep-Alive');
4364                 return true;
4365         }
4366
4367         /**
4368          * parse an incoming Cookie into it's parts
4369          *
4370          * @param       string $cookie_str content of cookie
4371          * @return      array with data of that cookie
4372          * @access      private
4373          */
4374         /*
4375          * TODO: allow a Set-Cookie string to be parsed into multiple cookies
4376          */
4377         function parseCookie($cookie_str) {
4378                 $cookie_str = str_replace('; ', ';', $cookie_str) . ';';
4379                 $data = preg_split('/;/', $cookie_str);
4380                 $value_str = $data[0];
4381
4382                 $cookie_param = 'domain=';
4383                 $start = strpos($cookie_str, $cookie_param);
4384                 if ($start > 0) {
4385                         $domain = substr($cookie_str, $start + strlen($cookie_param));
4386                         $domain = substr($domain, 0, strpos($domain, ';'));
4387                 } else {
4388                         $domain = '';
4389                 }
4390
4391                 $cookie_param = 'expires=';
4392                 $start = strpos($cookie_str, $cookie_param);
4393                 if ($start > 0) {
4394                         $expires = substr($cookie_str, $start + strlen($cookie_param));
4395                         $expires = substr($expires, 0, strpos($expires, ';'));
4396                 } else {
4397                         $expires = '';
4398                 }
4399
4400                 $cookie_param = 'path=';
4401                 $start = strpos($cookie_str, $cookie_param);
4402                 if ( $start > 0 ) {
4403                         $path = substr($cookie_str, $start + strlen($cookie_param));
4404                         $path = substr($path, 0, strpos($path, ';'));
4405                 } else {
4406                         $path = '/';
4407                 }
4408                                                 
4409                 $cookie_param = ';secure;';
4410                 if (strpos($cookie_str, $cookie_param) !== FALSE) {
4411                         $secure = true;
4412                 } else {
4413                         $secure = false;
4414                 }
4415
4416                 $sep_pos = strpos($value_str, '=');
4417
4418                 if ($sep_pos) {
4419                         $name = substr($value_str, 0, $sep_pos);
4420                         $value = substr($value_str, $sep_pos + 1);
4421                         $cookie= array( 'name' => $name,
4422                                         'value' => $value,
4423                                                         'domain' => $domain,
4424                                                         'path' => $path,
4425                                                         'expires' => $expires,
4426                                                         'secure' => $secure
4427                                                         );              
4428                         return $cookie;
4429                 }
4430                 return false;
4431         }
4432   
4433         /**
4434          * sort out cookies for the current request
4435          *
4436          * @param       array $cookies array with all cookies
4437          * @param       boolean $secure is the send-content secure or not?
4438          * @return      string for Cookie-HTTP-Header
4439          * @access      private
4440          */
4441         function getCookiesForRequest($cookies, $secure=false) {
4442                 $cookie_str = '';
4443                 if ((! is_null($cookies)) && (is_array($cookies))) {
4444                         foreach ($cookies as $cookie) {
4445                                 if (! is_array($cookie)) {
4446                                         continue;
4447                                 }
4448                         $this->debug("check cookie for validity: ".$cookie['name'].'='.$cookie['value']);
4449                                 if ((isset($cookie['expires'])) && (! empty($cookie['expires']))) {
4450                                         if (strtotime($cookie['expires']) <= time()) {
4451                                                 $this->debug('cookie has expired');
4452                                                 continue;
4453                                         }
4454                                 }
4455                                 if ((isset($cookie['domain'])) && (! empty($cookie['domain']))) {
4456                                         $domain = preg_quote($cookie['domain']);
4457                                         if (! preg_match("'.*$domain$'i", $this->host)) {
4458                                                 $this->debug('cookie has different domain');
4459                                                 continue;
4460                                         }
4461                                 }
4462                                 if ((isset($cookie['path'])) && (! empty($cookie['path']))) {
4463                                         $path = preg_quote($cookie['path']);
4464                                         if (! preg_match("'^$path.*'i", $this->path)) {
4465                                                 $this->debug('cookie is for a different path');
4466                                                 continue;
4467                                         }
4468                                 }
4469                                 if ((! $secure) && (isset($cookie['secure'])) && ($cookie['secure'])) {
4470                                         $this->debug('cookie is secure, transport is not');
4471                                         continue;
4472                                 }
4473                                 $cookie_str .= $cookie['name'] . '=' . $cookie['value'] . '; ';
4474                         $this->debug('add cookie to Cookie-String: ' . $cookie['name'] . '=' . $cookie['value']);
4475                         }
4476                 }
4477                 return $cookie_str;
4478   }
4479 }
4480
4481 ?><?php
4482
4483 /*
4484
4485 Modification information for LGPL compliance
4486
4487 r58622 - 2010-10-22 18:18:59 -0700 (Fri, 22 Oct 2010) - engsvnbuild - Author: lam <lam@198.18.142.201>
4488     bug 40066
4489
4490 r58361 - 2010-09-29 16:59:02 -0700 (Wed, 29 Sep 2010) - kjing - Author: Jenny Gonsalves <jenny@sugarcrm.com>
4491     Merging with maint_6_0_1 (svn merge -r 58250:58342)
4492
4493 r57813 - 2010-08-19 10:34:44 -0700 (Thu, 19 Aug 2010) - kjing - Author: John Mertic <jmertic@sugarcrm.com>
4494     Bug 39085 - When loading the opposite search panel via ajax on the ListViews, call the index action instead of the ListView action to avoid touching pre-MVC code by accident.
4495
4496 r57707 - 2010-08-10 12:26:13 -0700 (Tue, 10 Aug 2010) - kjing - Author: Stanislav Malyshev <smalyshev@gmail.com>
4497     fix SOAP calls with no parameters
4498
4499 r56990 - 2010-06-16 13:05:36 -0700 (Wed, 16 Jun 2010) - kjing - snapshot "Mango" svn branch to a new one for GitHub sync
4500
4501 r56989 - 2010-06-16 13:01:33 -0700 (Wed, 16 Jun 2010) - kjing - defunt "Mango" svn dev branch before github cutover
4502
4503 r55980 - 2010-04-19 13:31:28 -0700 (Mon, 19 Apr 2010) - kjing - create Mango (6.1) based on windex
4504
4505 r51719 - 2009-10-22 10:18:00 -0700 (Thu, 22 Oct 2009) - mitani - Converted to Build 3  tags and updated the build system 
4506
4507 r51634 - 2009-10-19 13:32:22 -0700 (Mon, 19 Oct 2009) - mitani - Windex is the branch for Sugar Sales 1.0 development
4508
4509 r51508 - 2009-10-14 07:40:23 -0700 (Wed, 14 Oct 2009) - jmertic - More fallout fixes from the PHP 5.3 ereg to preg changes.
4510
4511 r51455 - 2009-10-13 07:56:48 -0700 (Tue, 13 Oct 2009) - jmertic - Bug 33202 - Enable install of SugarCRM on PHP 5.3.0, asserting that the minimum supported version is PHP 5.2.x.
4512
4513 r51443 - 2009-10-12 13:34:36 -0700 (Mon, 12 Oct 2009) - jmertic - Bug 33332 - Made application PHP 5.3 compliant with E_DEPRECATED warnings on by:
4514 - Changing all ereg function to either preg or simple string based ones
4515 - No more references to magic quotes.
4516 - Change all the session_unregister() functions to just unset() the correct session variable instead.
4517
4518 r50375 - 2009-08-24 18:07:43 -0700 (Mon, 24 Aug 2009) - dwong - branch kobe2 from tokyo r50372
4519
4520 r45763 - 2009-04-01 12:16:18 -0700 (Wed, 01 Apr 2009) - majed - Removed half of the require_once and include_onces in the product that were redundant or could be handled easily by the auto loader
4521
4522 r45680 - 2009-03-30 14:34:35 -0700 (Mon, 30 Mar 2009) - Samir Gandhi - modifeid serializeSchema to generate WS-I compliant WSDL
4523
4524 r42807 - 2008-12-29 11:16:59 -0800 (Mon, 29 Dec 2008) - dwong - Branch from trunk/sugarcrm r42806 to branches/tokyo/sugarcrm
4525
4526 r42645 - 2008-12-18 13:41:08 -0800 (Thu, 18 Dec 2008) - awu - merging maint_5_2_0 rev41336:HEAD to trunk
4527
4528 r41647 - 2008-11-11 17:44:30 -0800 (Tue, 11 Nov 2008) - majed - Fixes a few bugs 
4529
4530 r41596 - 2008-11-10 19:20:04 -0800 (Mon, 10 Nov 2008) - Samir Gandhi - modified to set $method in the code
4531
4532 r41558 - 2008-11-10 14:35:34 -0800 (Mon, 10 Nov 2008) - majed - changes nusoap to allow for registering classes 
4533
4534 r39619 - 2008-09-09 13:41:34 -0700 (Tue, 09 Sep 2008) - jmertic - Bug 24827 - Remove all instances where we return a new object and assign it by reference, since this is deprecated in PHP 5 and emits E_DEPRECATED errors in PHP 5.3.
4535 Touched:
4536 - data/SugarBean.php
4537 - include/domit/php_http_client_generic.php
4538 - include/domit/php_http_connector.php
4539 - include/domit/testing_domit.php
4540 - include/domit/xml_domit_getelementsbypath.php
4541 - include/domit/xml_domit_lite_parser.php
4542 - include/domit/xml_domit_nodemaps.php
4543 - include/domit/xml_domit_parser.php
4544 - include/domit/xml_domit_shared.php
4545 - include/generic/SugarWidgets/SugarWidgetField.php
4546 - include/generic/SugarWidgets/SugarWidgetReportField.php
4547 - include/ListView/ProcessView.php
4548 - include/nusoap/class.soapclient.php
4549 - include/nusoap/nusoap.php
4550 - include/nusoap/nusoapmime.php
4551 - include/Pear/HTML_Safe/Safe.php
4552 - include/Pear/XML_HTMLSax3/HTMLSax3.php
4553 - modules/Administration/RebuildWorkFlow.php
4554 - modules/Expressions/RelateSelector.php
4555 - modules/Reports/templates/templates_reports.php
4556 - modules/WorkFlow/Delete.php
4557 - modules/WorkFlow/Save.php
4558 - modules/WorkFlow/SaveSequence.php
4559 - modules/WorkFlow/WorkFlow.php
4560 - modules/WorkFlowActionShells/CreateStep1.php
4561 - modules/WorkFlowActionShells/CreateStep2.php
4562 - modules/WorkFlowActionShells/Save.php
4563 - modules/WorkFlowActionShells/WorkFlowActionShell.php
4564 - modules/WorkFlowAlerts/Save.php
4565 - modules/WorkFlowAlerts/WorkFlowAlert.php
4566 - modules/WorkFlowAlertShells/DetailView.php
4567 - modules/WorkFlowAlertShells/WorkFlowAlertShell.php
4568 - modules/WorkFlowTriggerShells/CreateStep1.php
4569 - modules/WorkFlowTriggerShells/CreateStepFilter.php
4570 - modules/WorkFlowTriggerShells/SaveFilter.php
4571 - modules/WorkFlowTriggerShells/WorkFlowTriggerShell.php
4572 - soap/SoapHelperFunctions.php
4573 - test/modules/DynamicFields/DynamicFields_Bug24095_test.php
4574 - test/simpletest/browser.php
4575 - test/simpletest/default_reporter.php
4576 - test/simpletest/detached.php
4577 - test/simpletest/eclipse.php
4578 - test/simpletest/expectation.php
4579 - test/simpletest/extensions/pear_test_case.php
4580 - test/simpletest/form.php
4581 - test/simpletest/http.php
4582 - test/simpletest/mock_objects.php
4583 - test/simpletest/page.php
4584 - test/simpletest/parser.php
4585 - test/simpletest/remote.php
4586 - test/simpletest/shell_tester.php
4587 - test/simpletest/simple_test.php
4588 - test/simpletest/simpletest.php
4589 - test/simpletest/test/acceptance_test.php
4590 - test/simpletest/test/adapter_test.php
4591 - test/simpletest/test/authentication_test.php
4592 - test/simpletest/test/browser_test.php
4593 - test/simpletest/test/collector_test.php
4594 - test/simpletest/test/compatibility_test.php
4595 - test/simpletest/test/detached_test.php
4596 - test/simpletest/test/eclipse_test.php
4597 - test/simpletest/test/encoding_test.php
4598 - test/simpletest/test/errors_test.php
4599 - test/simpletest/test/expectation_test.php
4600 - test/simpletest/test/form_test.php
4601 - test/simpletest/test/frames_test.php
4602 - test/simpletest/test/http_test.php
4603 - test/simpletest/test/live_test.php
4604 - test/simpletest/test/mock_objects_test.php
4605 - test/simpletest/test/page_test.php
4606 - test/simpletest/test/parse_error_test.php
4607 - test/simpletest/test/parser_test.php
4608 - test/simpletest/test/remote_test.php
4609 - test/simpletest/test/shell_test.php
4610 - test/simpletest/test/shell_tester_test.php
4611 - test/simpletest/test/simpletest_test.php
4612 - test/simpletest/test/site/page_request.php
4613 - test/simpletest/test/tag_test.php
4614 - test/simpletest/test/unit_tester_test.php
4615 - test/simpletest/test/user_agent_test.php
4616 - test/simpletest/test/visual_test.php
4617 - test/simpletest/test/xml_test.php
4618 - test/simpletest/test_case.php
4619 - test/simpletest/ui/array_reporter/test.php
4620 - test/simpletest/ui/recorder/test.php
4621 - test/simpletest/unit_tester.php
4622 - test/simpletest/url.php
4623 - test/simpletest/user_agent.php
4624 - test/simpletest/web_tester.php
4625 - test/spikephpcoverage/src/PEAR.php
4626 - test/spikephpcoverage/src/util/Utility.php
4627 - test/spikephpcoverage/src/XML/Parser.php
4628 - test/spikephpcoverage/src/XML/Parser/Simple.php
4629 - test/test_utilities/SugarTest_SimpleBrowser.php
4630
4631 r38362 - 2008-07-28 14:06:59 -0700 (Mon, 28 Jul 2008) - roger - bug: 23897. Using print_r when using the debug statement in nusoap will print out the statements to the screen if the call is coming from the UI.
4632
4633 r38300 - 2008-07-25 13:33:43 -0700 (Fri, 25 Jul 2008) - Samir Gandhi - put the debug in parseresponse function
4634
4635 r38293 - 2008-07-25 12:32:34 -0700 (Fri, 25 Jul 2008) - Samir Gandhi - to put all the debug statements return value in the call function
4636
4637 r36824 - 2008-06-18 09:26:11 -0700 (Wed, 18 Jun 2008) - roger - bug: 21832
4638
4639 r26422 - 2007-09-05 17:29:12 -0700 (Wed, 05 Sep 2007) - majed - migrate from beta 1 to trunk
4640
4641 r15787 - 2006-08-10 10:14:41 -0700 (Thu, 10 Aug 2006) - roger - RRS: bug 7961
4642
4643 r14701 - 2006-07-17 13:37:26 -0700 (Mon, 17 Jul 2006) - roger - RRS: bug 5801
4644
4645 r13782 - 2006-06-06 10:58:55 -0700 (Tue, 06 Jun 2006) - majed - changes entry point code
4646
4647 r11466 - 2006-02-01 15:49:47 -0800 (Wed, 01 Feb 2006) - jacob - Adding extra !empty check to get around a PHP warning.
4648
4649 r11115 - 2006-01-17 14:54:45 -0800 (Tue, 17 Jan 2006) - majed - add entry point validation
4650
4651 r10585 - 2005-12-13 14:42:26 -0800 (Tue, 13 Dec 2005) - majed - adds new license mechanisim
4652
4653 r10170 - 2005-12-05 18:37:46 -0800 (Mon, 05 Dec 2005) - majed - fixes various issues
4654
4655 r8999 - 2005-11-04 05:26:49 -0800 (Fri, 04 Nov 2005) - roger - When nusoap was upgraded we had an issue with the user's default language not being populated during a soap request. I determined the reason this was happening and have checked in the corresponding change to nusoap.
4656
4657 r8991 - 2005-11-03 19:07:25 -0800 (Thu, 03 Nov 2005) - majed - fixes nusoap issue
4658
4659 r8846 - 2005-10-31 11:01:12 -0800 (Mon, 31 Oct 2005) - majed - new version of nusoap
4660
4661 r7905 - 2005-09-21 19:12:57 -0700 (Wed, 21 Sep 2005) - majed - restores old nusoap pre & with a few fixes
4662
4663 r7861 - 2005-09-20 15:40:25 -0700 (Tue, 20 Sep 2005) - majed - & fix for 3.5.1
4664
4665 r7452 - 2005-08-17 11:32:34 -0700 (Wed, 17 Aug 2005) - majed - changes soap to nusoap
4666
4667 r5820 - 2005-06-21 14:22:24 -0700 (Tue, 21 Jun 2005) - majed - fixes issues with nusoap and with custom fields
4668
4669 r5462 - 2005-05-25 13:50:11 -0700 (Wed, 25 May 2005) - majed - upgraded nusoap to .6.9
4670
4671 r5104 - 2005-05-04 15:33:41 -0700 (Wed, 04 May 2005) - majed - gets rid of HTTP_GET_VARS and what not which has been deprecated
4672
4673 r573 - 2004-09-04 13:03:32 -0700 (Sat, 04 Sep 2004) - sugarclint - undoing copyrights added in inadvertantly.  --clint
4674
4675 r546 - 2004-09-03 11:49:38 -0700 (Fri, 03 Sep 2004) - sugarmsi - removed echo count
4676
4677 r354 - 2004-08-02 23:00:37 -0700 (Mon, 02 Aug 2004) - sugarjacob - Adding Soap
4678
4679
4680 */
4681
4682
4683
4684
4685
4686 /**
4687 *
4688 * nusoap_server allows the user to create a SOAP server
4689 * that is capable of receiving messages and returning responses
4690 *
4691 * @author   Dietrich Ayala <dietrich@ganx4.com>
4692 * @author   Scott Nichol <snichol@users.sourceforge.net>
4693
4694 * @access   public
4695 */
4696 class nusoap_server extends nusoap_base {
4697         /**
4698          * HTTP headers of request
4699          * @var array
4700          * @access private
4701          */
4702         var $headers = array();
4703         /**
4704          * HTTP request
4705          * @var string
4706          * @access private
4707          */
4708         var $request = '';
4709         /**
4710          * SOAP headers from request (incomplete namespace resolution; special characters not escaped) (text)
4711          * @var string
4712          * @access public
4713          */
4714         var $requestHeaders = '';
4715         /**
4716          * SOAP Headers from request (parsed)
4717          * @var mixed
4718          * @access public
4719          */
4720         var $requestHeader = NULL;
4721         /**
4722          * SOAP body request portion (incomplete namespace resolution; special characters not escaped) (text)
4723          * @var string
4724          * @access public
4725          */
4726         var $document = '';
4727         /**
4728          * SOAP payload for request (text)
4729          * @var string
4730          * @access public
4731          */
4732         var $requestSOAP = '';
4733         /**
4734          * requested method namespace URI
4735          * @var string
4736          * @access private
4737          */
4738         var $methodURI = '';
4739         /**
4740          * name of method requested
4741          * @var string
4742          * @access private
4743          */
4744         var $methodname = '';
4745         /**
4746          * method parameters from request
4747          * @var array
4748          * @access private
4749          */
4750         var $methodparams = array();
4751         /**
4752          * SOAP Action from request
4753          * @var string
4754          * @access private
4755          */
4756         var $SOAPAction = '';
4757         /**
4758          * character set encoding of incoming (request) messages
4759          * @var string
4760          * @access public
4761          */
4762         var $xml_encoding = '';
4763         /**
4764          * toggles whether the parser decodes element content w/ utf8_decode()
4765          * @var boolean
4766          * @access public
4767          */
4768     var $decode_utf8 = false;
4769
4770         /**
4771          * HTTP headers of response
4772          * @var array
4773          * @access public
4774          */
4775         var $outgoing_headers = array();
4776         /**
4777          * HTTP response
4778          * @var string
4779          * @access private
4780          */
4781         var $response = '';
4782         /**
4783          * SOAP headers for response (text or array of soapval or associative array)
4784          * @var mixed
4785          * @access public
4786          */
4787         var $responseHeaders = '';
4788         /**
4789          * SOAP payload for response (text)
4790          * @var string
4791          * @access private
4792          */
4793         var $responseSOAP = '';
4794         /**
4795          * method return value to place in response
4796          * @var mixed
4797          * @access private
4798          */
4799         var $methodreturn = false;
4800         /**
4801          * whether $methodreturn is a string of literal XML
4802          * @var boolean
4803          * @access public
4804          */
4805         var $methodreturnisliteralxml = false;
4806         /**
4807          * SOAP fault for response (or false)
4808          * @var mixed
4809          * @access private
4810          */
4811         var $fault = false;
4812         /**
4813          * text indication of result (for debugging)
4814          * @var string
4815          * @access private
4816          */
4817         var $result = 'successful';
4818
4819         /**
4820          * assoc array of operations => opData; operations are added by the register()
4821          * method or by parsing an external WSDL definition
4822          * @var array
4823          * @access private
4824          */
4825         var $operations = array();
4826         /**
4827          * wsdl instance (if one)
4828          * @var mixed
4829          * @access private
4830          */
4831         var $wsdl = false;
4832         /**
4833          * URL for WSDL (if one)
4834          * @var mixed
4835          * @access private
4836          */
4837         var $externalWSDLURL = false;
4838         /**
4839          * whether to append debug to response as XML comment
4840          * @var boolean
4841          * @access public
4842          */
4843         var $debug_flag = false;
4844
4845
4846         /**
4847         * constructor
4848     * the optional parameter is a path to a WSDL file that you'd like to bind the server instance to.
4849         *
4850     * @param mixed $wsdl file path or URL (string), or wsdl instance (object)
4851         * @access   public
4852         */
4853         function nusoap_server($wsdl=false){
4854                 parent::nusoap_base();
4855                 // turn on debugging?
4856                 global $debug;
4857                 global $HTTP_SERVER_VARS;
4858
4859                 if (isset($_SERVER)) {
4860                         $this->debug("_SERVER is defined:");
4861                         $this->appendDebug($this->varDump($_SERVER));
4862                 } elseif (isset($HTTP_SERVER_VARS)) {
4863                         $this->debug("HTTP_SERVER_VARS is defined:");
4864                         $this->appendDebug($this->varDump($HTTP_SERVER_VARS));
4865                 } else {
4866                         $this->debug("Neither _SERVER nor HTTP_SERVER_VARS is defined.");
4867                 }
4868
4869                 if (isset($debug)) {
4870                         $this->debug("In nusoap_server, set debug_flag=$debug based on global flag");
4871                         $this->debug_flag = $debug;
4872                 } elseif (isset($_SERVER['QUERY_STRING'])) {
4873                         $qs = explode('&', $_SERVER['QUERY_STRING']);
4874                         foreach ($qs as $v) {
4875                                 if (substr($v, 0, 6) == 'debug=') {
4876                                         $this->debug("In nusoap_server, set debug_flag=" . substr($v, 6) . " based on query string #1");
4877                                         $this->debug_flag = substr($v, 6);
4878                                 }
4879                         }
4880                 } elseif (isset($HTTP_SERVER_VARS['QUERY_STRING'])) {
4881                         $qs = explode('&', $HTTP_SERVER_VARS['QUERY_STRING']);
4882                         foreach ($qs as $v) {
4883                                 if (substr($v, 0, 6) == 'debug=') {
4884                                         $this->debug("In nusoap_server, set debug_flag=" . substr($v, 6) . " based on query string #2");
4885                                         $this->debug_flag = substr($v, 6);
4886                                 }
4887                         }
4888                 }
4889
4890                 // wsdl
4891                 if($wsdl){
4892                         $this->debug("In nusoap_server, WSDL is specified");
4893                         if (is_object($wsdl) && (get_class($wsdl) == 'wsdl')) {
4894                                 $this->wsdl = $wsdl;
4895                                 $this->externalWSDLURL = $this->wsdl->wsdl;
4896                                 $this->debug('Use existing wsdl instance from ' . $this->externalWSDLURL);
4897                         } else {
4898                                 $this->debug('Create wsdl from ' . $wsdl);
4899                                 $this->wsdl = new wsdl($wsdl);
4900                                 $this->externalWSDLURL = $wsdl;
4901                         }
4902                         $this->appendDebug($this->wsdl->getDebug());
4903                         $this->wsdl->clearDebug();
4904                         if($err = $this->wsdl->getError()){
4905                                 die('WSDL ERROR: '.$err);
4906                         }
4907                 }
4908         }
4909
4910         /**
4911         * processes request and returns response
4912         *
4913         * @param    string $data usually is the value of $HTTP_RAW_POST_DATA
4914         * @access   public
4915         */
4916         function service($data){
4917                 global $HTTP_SERVER_VARS;
4918
4919                 if (isset($_SERVER['REQUEST_METHOD'])) {
4920                         $rm = $_SERVER['REQUEST_METHOD'];
4921                 } elseif (isset($HTTP_SERVER_VARS['REQUEST_METHOD'])) {
4922                         $rm = $HTTP_SERVER_VARS['REQUEST_METHOD'];
4923                 } else {
4924                         $rm = '';
4925                 }
4926
4927                 if (isset($_SERVER['QUERY_STRING'])) {
4928                         $qs = $_SERVER['QUERY_STRING'];
4929                 } elseif (isset($HTTP_SERVER_VARS['QUERY_STRING'])) {
4930                         $qs = $HTTP_SERVER_VARS['QUERY_STRING'];
4931                 } else {
4932                         $qs = '';
4933                 }
4934                 $this->debug("In service, request method=$rm query string=$qs strlen(\$data)=" . strlen($data));
4935
4936                 if ($rm == 'POST') {
4937                         $this->debug("In service, invoke the request");
4938                         $this->parse_request($data);
4939                         if (! $this->fault) {
4940                                 $this->invoke_method();
4941                         }
4942                         if (! $this->fault) {
4943                                 $this->serialize_return();
4944                         }
4945                         $this->send_response();
4946                 } elseif (preg_match('/wsdl/', $qs) ){
4947                         $this->debug("In service, this is a request for WSDL");
4948                         if ($this->externalWSDLURL){
4949               if (strpos($this->externalWSDLURL, "http://") !== false) { // assume URL
4950                                 $this->debug("In service, re-direct for WSDL");
4951                                 header('Location: '.$this->externalWSDLURL);
4952               } else { // assume file
4953                                 $this->debug("In service, use file passthru for WSDL");
4954                 header("Content-Type: text/xml\r\n");
4955                                 $pos = strpos($this->externalWSDLURL, "file://");
4956                                 if ($pos === false) {
4957                                         $filename = $this->externalWSDLURL;
4958                                 } else {
4959                                         $filename = substr($this->externalWSDLURL, $pos + 7);
4960                                 }
4961                 $fp = fopen($this->externalWSDLURL, 'r');
4962                 fpassthru($fp);
4963               }
4964                         } elseif ($this->wsdl) {
4965                                 $this->debug("In service, serialize WSDL");
4966                                 header("Content-Type: text/xml; charset=ISO-8859-1\r\n");
4967                                 print $this->wsdl->serialize($this->debug_flag);
4968                                 if ($this->debug_flag) {
4969                                         $this->debug('wsdl:');
4970                                         $this->appendDebug($this->varDump($this->wsdl));
4971                                         print $this->getDebugAsXMLComment();
4972                                 }
4973                         } else {
4974                                 $this->debug("In service, there is no WSDL");
4975                                 header("Content-Type: text/html; charset=ISO-8859-1\r\n");
4976                                 print "This service does not provide WSDL";
4977                         }
4978                 } elseif ($this->wsdl) {
4979                         $this->debug("In service, return Web description");
4980                         print $this->wsdl->webDescription();
4981                 } else {
4982                         $this->debug("In service, no Web description");
4983                         header("Content-Type: text/html; charset=ISO-8859-1\r\n");
4984                         print "This service does not provide a Web description";
4985                 }
4986         }
4987
4988         /**
4989         * parses HTTP request headers.
4990         *
4991         * The following fields are set by this function (when successful)
4992         *
4993         * headers
4994         * request
4995         * xml_encoding
4996         * SOAPAction
4997         *
4998         * @access   private
4999         */
5000         function parse_http_headers() {
5001                 global $HTTP_SERVER_VARS;
5002
5003                 $this->request = '';
5004                 $this->SOAPAction = '';
5005                 if(function_exists('getallheaders')){
5006                         $this->debug("In parse_http_headers, use getallheaders");
5007                         $headers = getallheaders();
5008                         foreach($headers as $k=>$v){
5009                                 $k = strtolower($k);
5010                                 $this->headers[$k] = $v;
5011                                 $this->request .= "$k: $v\r\n";
5012                                 $this->debug("$k: $v");
5013                         }
5014                         // get SOAPAction header
5015                         if(isset($this->headers['soapaction'])){
5016                                 $this->SOAPAction = str_replace('"','',$this->headers['soapaction']);
5017                         }
5018                         // get the character encoding of the incoming request
5019                         if(isset($this->headers['content-type']) && strpos($this->headers['content-type'],'=')){
5020                                 $enc = str_replace('"','',substr(strstr($this->headers["content-type"],'='),1));
5021                                 if(preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i',$enc)){
5022                                         $this->xml_encoding = strtoupper($enc);
5023                                 } else {
5024                                         $this->xml_encoding = 'US-ASCII';
5025                                 }
5026                         } else {
5027                                 // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
5028                                 $this->xml_encoding = 'ISO-8859-1';
5029                         }
5030                 } elseif(isset($_SERVER) && is_array($_SERVER)){
5031                         $this->debug("In parse_http_headers, use _SERVER");
5032                         foreach ($_SERVER as $k => $v) {
5033                                 if (substr($k, 0, 5) == 'HTTP_') {
5034                                         $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', substr($k, 5))));
5035                                 } else {
5036                                         $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', $k)));
5037                                 }
5038                                 if ($k == 'soapaction') {
5039                                         // get SOAPAction header
5040                                         $k = 'SOAPAction';
5041                                         $v = str_replace('"', '', $v);
5042                                         $v = str_replace('\\', '', $v);
5043                                         $this->SOAPAction = $v;
5044                                 } else if ($k == 'content-type') {
5045                                         // get the character encoding of the incoming request
5046                                         if (strpos($v, '=')) {
5047                                                 $enc = substr(strstr($v, '='), 1);
5048                                                 $enc = str_replace('"', '', $enc);
5049                                                 $enc = str_replace('\\', '', $enc);
5050                                                 if (preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i',$enc)) {
5051                                                         $this->xml_encoding = strtoupper($enc);
5052                                                 } else {
5053                                                         $this->xml_encoding = 'US-ASCII';
5054                                                 }
5055                                         } else {
5056                                                 // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
5057                                                 $this->xml_encoding = 'ISO-8859-1';
5058                                         }
5059                                 }
5060                                 $this->headers[$k] = $v;
5061                                 $this->request .= "$k: $v\r\n";
5062                                 $this->debug("$k: $v");
5063                         }
5064                 } elseif (is_array($HTTP_SERVER_VARS)) {
5065                         $this->debug("In parse_http_headers, use HTTP_SERVER_VARS");
5066                         foreach ($HTTP_SERVER_VARS as $k => $v) {
5067                                 if (substr($k, 0, 5) == 'HTTP_') {
5068                                         $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', substr($k, 5))));                                            $k = strtolower(substr($k, 5));
5069                                 } else {
5070                                         $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', $k)));                                               $k = strtolower($k);
5071                                 }
5072                                 if ($k == 'soapaction') {
5073                                         // get SOAPAction header
5074                                         $k = 'SOAPAction';
5075                                         $v = str_replace('"', '', $v);
5076                                         $v = str_replace('\\', '', $v);
5077                                         $this->SOAPAction = $v;
5078                                 } else if ($k == 'content-type') {
5079                                         // get the character encoding of the incoming request
5080                                         if (strpos($v, '=')) {
5081                                                 $enc = substr(strstr($v, '='), 1);
5082                                                 $enc = str_replace('"', '', $enc);
5083                                                 $enc = str_replace('\\', '', $enc);
5084                                                 if (preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i',$enc)) {
5085                                                         $this->xml_encoding = strtoupper($enc);
5086                                                 } else {
5087                                                         $this->xml_encoding = 'US-ASCII';
5088                                                 }
5089                                         } else {
5090                                                 // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
5091                                                 $this->xml_encoding = 'ISO-8859-1';
5092                                         }
5093                                 }
5094                                 $this->headers[$k] = $v;
5095                                 $this->request .= "$k: $v\r\n";
5096                                 $this->debug("$k: $v");
5097                         }
5098                 } else {
5099                         $this->debug("In parse_http_headers, HTTP headers not accessible");
5100                         $this->setError("HTTP headers not accessible");
5101                 }
5102         }
5103
5104         /**
5105         * parses a request
5106         *
5107         * The following fields are set by this function (when successful)
5108         *
5109         * headers
5110         * request
5111         * xml_encoding
5112         * SOAPAction
5113         * request
5114         * requestSOAP
5115         * methodURI
5116         * methodname
5117         * methodparams
5118         * requestHeaders
5119         * document
5120         *
5121         * This sets the fault field on error
5122         *
5123         * @param    string $data XML string
5124         * @access   private
5125         */
5126         function parse_request($data='') {
5127                 $this->debug('entering parse_request()');
5128                 $this->parse_http_headers();
5129                 $this->debug('got character encoding: '.$this->xml_encoding);
5130                 // uncompress if necessary
5131                 if (isset($this->headers['content-encoding']) && $this->headers['content-encoding'] != '') {
5132                         $this->debug('got content encoding: ' . $this->headers['content-encoding']);
5133                         if ($this->headers['content-encoding'] == 'deflate' || $this->headers['content-encoding'] == 'gzip') {
5134                         // if decoding works, use it. else assume data wasn't gzencoded
5135                                 if (function_exists('gzuncompress')) {
5136                                         if ($this->headers['content-encoding'] == 'deflate' && $degzdata = @gzuncompress($data)) {
5137                                                 $data = $degzdata;
5138                                         } elseif ($this->headers['content-encoding'] == 'gzip' && $degzdata = gzinflate(substr($data, 10))) {
5139                                                 $data = $degzdata;
5140                                         } else {
5141                                                 $this->fault('SOAP-ENV:Client', 'Errors occurred when trying to decode the data');
5142                                                 return;
5143                                         }
5144                                 } else {
5145                                         $this->fault('SOAP-ENV:Client', 'This Server does not support compressed data');
5146                                         return;
5147                                 }
5148                         }
5149                 }
5150                 $this->request .= "\r\n".$data;
5151                 $data = $this->parseRequest($this->headers, $data);
5152                 $this->requestSOAP = $data;
5153                 $this->debug('leaving parse_request');
5154         }
5155
5156         function register_class($classname){
5157                 $this->registeredClass = $classname;
5158         }
5159         /**
5160         * invokes a PHP function for the requested SOAP method
5161         *
5162         * The following fields are set by this function (when successful)
5163         *
5164         * methodreturn
5165         *
5166         * Note that the PHP function that is called may also set the following
5167         * fields to affect the response sent to the client
5168         *
5169         * responseHeaders
5170         * outgoing_headers
5171         *
5172         * This sets the fault field on error
5173         *
5174         * @access   private
5175         */
5176         function invoke_method() {
5177                 $this->debug('in invoke_method, methodname=' . $this->methodname . ' methodURI=' . $this->methodURI . ' SOAPAction=' . $this->SOAPAction);
5178
5179                 //
5180                 // if you are debugging in this area of the code, your service uses a class to implement methods,
5181                 // you use SOAP RPC, and the client is .NET, please be aware of the following...
5182                 // when the .NET wsdl.exe utility generates a proxy, it will remove the '.' or '..' from the
5183                 // method name.  that is fine for naming the .NET methods.  it is not fine for properly constructing
5184                 // the XML request and reading the XML response.  you need to add the RequestElementName and
5185                 // ResponseElementName to the System.Web.Services.Protocols.SoapRpcMethodAttribute that wsdl.exe
5186                 // generates for the method.  these parameters are used to specify the correct XML element names
5187                 // for .NET to use, i.e. the names with the '.' in them.
5188                 //
5189                 $orig_methodname = $this->methodname;
5190                 if ($this->wsdl) {
5191                         if ($this->opData = $this->wsdl->getOperationData($this->methodname)) {
5192                                 $this->debug('in invoke_method, found WSDL operation=' . $this->methodname);
5193                                 $this->appendDebug('opData=' . $this->varDump($this->opData));
5194                         } elseif ($this->opData = $this->wsdl->getOperationDataForSoapAction($this->SOAPAction)) {
5195                                 // Note: hopefully this case will only be used for doc/lit, since rpc services should have wrapper element
5196                                 $this->debug('in invoke_method, found WSDL soapAction=' . $this->SOAPAction . ' for operation=' . $this->opData['name']);
5197                                 $this->appendDebug('opData=' . $this->varDump($this->opData));
5198                                 $this->methodname = $this->opData['name'];
5199                         } else {
5200                                 $this->debug('in invoke_method, no WSDL for operation=' . $this->methodname);
5201                                 $this->fault('SOAP-ENV:Client', "Operation '" . $this->methodname . "' is not defined in the WSDL for this service");
5202                                 return;
5203                         }
5204                 } else {
5205                         $this->debug('in invoke_method, no WSDL to validate method');
5206                 }
5207
5208                 // if a . is present in $this->methodname, we see if there is a class in scope,
5209                 // which could be referred to. We will also distinguish between two deliminators,
5210                 // to allow methods to be called a the class or an instance
5211                 if (strpos($this->methodname, '..') > 0) {
5212                         $delim = '..';
5213                 } else if (strpos($this->methodname, '.') > 0) {
5214                         $delim = '.';
5215                 } else {
5216                         $delim = '';
5217                 }
5218                 $this->debug("in invoke_method, delim=$delim");
5219
5220                 $class = '';
5221                 $method = '';
5222                 if (strlen($delim) > 0 && substr_count($this->methodname, $delim) == 1) {
5223                         $try_class = substr($this->methodname, 0, strpos($this->methodname, $delim));
5224                         if (class_exists($try_class)) {
5225                                 // get the class and method name
5226                                 $class = $try_class;
5227                                 $method = substr($this->methodname, strpos($this->methodname, $delim) + strlen($delim));
5228                                 $this->debug("in invoke_method, class=$class method=$method delim=$delim");
5229                         } else {
5230                                 $this->debug("in invoke_method, class=$try_class not found");
5231                         }
5232                 } else {
5233                         $try_class = '';
5234                         $this->debug("in invoke_method, no class to try");
5235                 }
5236                 if(empty($delim) && isset($this->registeredClass)){
5237                         $class  = $this->registeredClass;
5238                         $delim = '..';
5239                         $method = $this->methodname;
5240                 }
5241
5242                 // does method exist?
5243                 if ($class == '') {
5244                         if (!function_exists($this->methodname)) {
5245                                 $this->debug("in invoke_method, function '$this->methodname' not found!");
5246                                 $this->result = 'fault: method not found';
5247                                 $this->fault('SOAP-ENV:Client',"method '$this->methodname'('$orig_methodname') not defined in service('$try_class' '$delim')");
5248                                 return;
5249                         }
5250                 } else {
5251                         $method_to_compare = (substr(phpversion(), 0, 2) == '4.') ? strtolower($method) : $method;
5252                         if (!in_array($method_to_compare, get_class_methods($class))) {
5253                                 $this->debug("in invoke_method, method '$this->methodname' not found in class '$class'!");
5254                                 $this->result = 'fault: method not found';
5255                                 $this->fault('SOAP-ENV:Client',"method '$this->methodname'/'$method_to_compare'('$orig_methodname') not defined in service/'$class'('$try_class' '$delim')");
5256                                 return;
5257                         }
5258                 }
5259
5260                 // evaluate message, getting back parameters
5261                 // verify that request parameters match the method's signature
5262                 if(! $this->verify_method($this->methodname,$this->methodparams)){
5263                         // debug
5264                         $this->debug('ERROR: request not verified against method signature');
5265                         $this->result = 'fault: request failed validation against method signature';
5266                         // return fault
5267                         $this->fault('SOAP-ENV:Client',"Operation '$this->methodname' not defined in service.");
5268                         return;
5269                 }
5270
5271                 // if there are parameters to pass
5272                 $this->debug('in invoke_method, params:');
5273                 $this->appendDebug($this->varDump($this->methodparams));
5274                 $this->debug("in invoke_method, calling '$this->methodname'");
5275                 if (!function_exists('call_user_func_array')) {
5276                         if ($class == '') {
5277                                 $this->debug('in invoke_method, calling function using eval()');
5278                                 $funcCall = "\$this->methodreturn = $this->methodname(";
5279                         } else {
5280                                 if ($delim == '..') {
5281                                         $this->debug('in invoke_method, calling class method using eval()');
5282                                         $funcCall = "\$this->methodreturn = ".$class."::".$method."(";
5283                                 } else {
5284                                         $this->debug('in invoke_method, calling instance method using eval()');
5285                                         // generate unique instance name
5286                                         $instname = "\$inst_".time();
5287                                         $funcCall = $instname." = new ".$class."(); ";
5288                                         $funcCall .= "\$this->methodreturn = ".$instname."->".$method."(";
5289                                 }
5290                         }
5291                         if ($this->methodparams) {
5292                                 foreach ($this->methodparams as $param) {
5293                                         if (is_array($param) || is_object($param)) {
5294                                                 $this->fault('SOAP-ENV:Client', 'NuSOAP does not handle complexType parameters correctly when using eval; call_user_func_array must be available');
5295                                                 return;
5296                                         }
5297                                         $funcCall .= "\"$param\",";
5298                                 }
5299                                 $funcCall = substr($funcCall, 0, -1);
5300                         }
5301                         $funcCall .= ');';
5302                         $this->debug('in invoke_method, function call: '.$funcCall);
5303                         @eval($funcCall);
5304                 } else {
5305                         if ($class == '') {
5306                                 $this->debug('in invoke_method, calling function using call_user_func_array()');
5307                                 $call_arg = "$this->methodname";        // straight assignment changes $this->methodname to lower case after call_user_func_array()
5308                         } elseif ($delim == '..') {
5309                                 $this->debug('in invoke_method, calling class method using call_user_func_array()');
5310                                 $call_arg = array ($class, $method);
5311                         } else {
5312                                 $this->debug('in invoke_method, calling instance method using call_user_func_array()');
5313                                 $instance = new $class ();
5314                                 $call_arg = array(&$instance, $method);
5315                         }
5316                         if (is_array($this->methodparams)) {
5317                                 $this->methodreturn = call_user_func_array($call_arg, array_values($this->methodparams));
5318                         } else {
5319                                 $this->methodreturn = call_user_func_array($call_arg, array());
5320                         }
5321                 }
5322         $this->debug('in invoke_method, methodreturn:');
5323         $this->appendDebug($this->varDump($this->methodreturn));
5324                 $this->debug("in invoke_method, called method $this->methodname, received data of type ".gettype($this->methodreturn));
5325         }
5326
5327         /**
5328         * serializes the return value from a PHP function into a full SOAP Envelope
5329         *
5330         * The following fields are set by this function (when successful)
5331         *
5332         * responseSOAP
5333         *
5334         * This sets the fault field on error
5335         *
5336         * @access   private
5337         */
5338         function serialize_return() {
5339                 $this->debug('Entering serialize_return methodname: ' . $this->methodname . ' methodURI: ' . $this->methodURI);
5340                 // if fault
5341                 if (isset($this->methodreturn) && is_object($this->methodreturn) && ((get_class($this->methodreturn) == 'soap_fault') || (get_class($this->methodreturn) == 'nusoap_fault'))) {
5342                         $this->debug('got a fault object from method');
5343                         $this->fault = $this->methodreturn;
5344                         return;
5345                 } elseif ($this->methodreturnisliteralxml) {
5346                         $return_val = $this->methodreturn;
5347                 // returned value(s)
5348                 } else {
5349                         $this->debug('got a(n) '.gettype($this->methodreturn).' from method');
5350                         $this->debug('serializing return value');
5351                         if($this->wsdl){
5352                                 if (sizeof($this->opData['output']['parts']) > 1) {
5353                                         $this->debug('more than one output part, so use the method return unchanged');
5354                                 $opParams = $this->methodreturn;
5355                             } elseif (sizeof($this->opData['output']['parts']) == 1) {
5356                                         $this->debug('exactly one output part, so wrap the method return in a simple array');
5357                                         // TODO: verify that it is not already wrapped!
5358                                 //foreach ($this->opData['output']['parts'] as $name => $type) {
5359                                         //      $this->debug('wrap in element named ' . $name);
5360                                 //}
5361                                 $opParams = array($this->methodreturn);
5362                             }
5363                             $return_val = $this->wsdl->serializeRPCParameters($this->methodname,'output',$opParams);
5364                             $this->appendDebug($this->wsdl->getDebug());
5365                             $this->wsdl->clearDebug();
5366                                 if($errstr = $this->wsdl->getError()){
5367                                         $this->debug('got wsdl error: '.$errstr);
5368                                         $this->fault('SOAP-ENV:Server', 'unable to serialize result');
5369                                         return;
5370                                 }
5371                         } else {
5372                                 if (isset($this->methodreturn)) {
5373                                         $return_val = $this->serialize_val($this->methodreturn, 'return');
5374                                 } else {
5375                                         $return_val = '';
5376                                         $this->debug('in absence of WSDL, assume void return for backward compatibility');
5377                                 }
5378                         }
5379                 }
5380                 $this->debug('return value:');
5381                 $this->appendDebug($this->varDump($return_val));
5382
5383                 $this->debug('serializing response');
5384                 if ($this->wsdl) {
5385                         $this->debug('have WSDL for serialization: style is ' . $this->opData['style']);
5386                         if ($this->opData['style'] == 'rpc') {
5387                                 $this->debug('style is rpc for serialization: use is ' . $this->opData['output']['use']);
5388                                 if ($this->opData['output']['use'] == 'literal') {
5389                                         // http://www.ws-i.org/Profiles/BasicProfile-1.1-2004-08-24.html R2735 says rpc/literal accessor elements should not be in a namespace
5390                                         if ($this->methodURI) {
5391                                                 $payload = '<ns1:'.$this->methodname.'Response xmlns:ns1="'.$this->methodURI.'">'.$return_val.'</ns1:'.$this->methodname."Response>";
5392                                         } else {
5393                                                 $payload = '<'.$this->methodname.'Response>'.$return_val.'</'.$this->methodname.'Response>';
5394                                         }
5395                                 } else {
5396                                         if ($this->methodURI) {
5397                                                 $payload = '<ns1:'.$this->methodname.'Response xmlns:ns1="'.$this->methodURI.'">'.$return_val.'</ns1:'.$this->methodname."Response>";
5398                                         } else {
5399                                                 $payload = '<'.$this->methodname.'Response>'.$return_val.'</'.$this->methodname.'Response>';
5400                                         }
5401                                 }
5402                         } else {
5403                                 $this->debug('style is not rpc for serialization: assume document');
5404                                 $payload = $return_val;
5405                         }
5406                 } else {
5407                         $this->debug('do not have WSDL for serialization: assume rpc/encoded');
5408                         $payload = '<ns1:'.$this->methodname.'Response xmlns:ns1="'.$this->methodURI.'">'.$return_val.'</ns1:'.$this->methodname."Response>";
5409                 }
5410                 $this->result = 'successful';
5411                 if($this->wsdl){
5412                         //if($this->debug_flag){
5413                 $this->appendDebug($this->wsdl->getDebug());
5414             //  }
5415                         if (isset($this->opData['output']['encodingStyle'])) {
5416                                 $encodingStyle = $this->opData['output']['encodingStyle'];
5417                         } else {
5418                                 $encodingStyle = '';
5419                         }
5420                         // Added: In case we use a WSDL, return a serialized env. WITH the usedNamespaces.
5421                         $this->responseSOAP = $this->serializeEnvelope($payload,$this->responseHeaders,$this->wsdl->usedNamespaces,$this->opData['style'],$this->opData['output']['use'],$encodingStyle);
5422                 } else {
5423                         $this->responseSOAP = $this->serializeEnvelope($payload,$this->responseHeaders);
5424                 }
5425                 $this->debug("Leaving serialize_return");
5426         }
5427
5428         /**
5429         * sends an HTTP response
5430         *
5431         * The following fields are set by this function (when successful)
5432         *
5433         * outgoing_headers
5434         * response
5435         *
5436         * @access   private
5437         */
5438         function send_response() {
5439                 $this->debug('Enter send_response');
5440                 if ($this->fault) {
5441                         $payload = $this->fault->serialize();
5442                         $this->outgoing_headers[] = "HTTP/1.0 500 Internal Server Error";
5443                         $this->outgoing_headers[] = "Status: 500 Internal Server Error";
5444                 } else {
5445                         $payload = $this->responseSOAP;
5446                         // Some combinations of PHP+Web server allow the Status
5447                         // to come through as a header.  Since OK is the default
5448                         // just do nothing.
5449                         // $this->outgoing_headers[] = "HTTP/1.0 200 OK";
5450                         // $this->outgoing_headers[] = "Status: 200 OK";
5451                 }
5452         // add debug data if in debug mode
5453                 if(isset($this->debug_flag) && $this->debug_flag){
5454                 $payload .= $this->getDebugAsXMLComment();
5455         }
5456                 $this->outgoing_headers[] = "Server: $this->title Server v$this->version";
5457                 preg_match('/\$Revisio' . 'n: ([^ ]+)/', $this->revision, $rev);
5458                 $this->outgoing_headers[] = "X-SOAP-Server: $this->title/$this->version (".$rev[1].")";
5459                 // Let the Web server decide about this
5460                 //$this->outgoing_headers[] = "Connection: Close\r\n";
5461                 $payload = $this->getHTTPBody($payload);
5462                 $type = $this->getHTTPContentType();
5463                 $charset = $this->getHTTPContentTypeCharset();
5464                 $this->outgoing_headers[] = "Content-Type: $type" . ($charset ? '; charset=' . $charset : '');
5465                 //begin code to compress payload - by John
5466                 // NOTE: there is no way to know whether the Web server will also compress
5467                 // this data.
5468                 if (strlen($payload) > 1024 && isset($this->headers) && isset($this->headers['accept-encoding'])) {     
5469                         if (strstr($this->headers['accept-encoding'], 'gzip')) {
5470                                 if (function_exists('gzencode')) {
5471                                         if (isset($this->debug_flag) && $this->debug_flag) {
5472                                                 $payload .= "<!-- Content being gzipped -->";
5473                                         }
5474                                         $this->outgoing_headers[] = "Content-Encoding: gzip";
5475                                         $payload = gzencode($payload);
5476                                 } else {
5477                                         if (isset($this->debug_flag) && $this->debug_flag) {
5478                                                 $payload .= "<!-- Content will not be gzipped: no gzencode -->";
5479                                         }
5480                                 }
5481                         } elseif (strstr($this->headers['accept-encoding'], 'deflate')) {
5482                                 // Note: MSIE requires gzdeflate output (no Zlib header and checksum),
5483                                 // instead of gzcompress output,
5484                                 // which conflicts with HTTP 1.1 spec (http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.5)
5485                                 if (function_exists('gzdeflate')) {
5486                                         if (isset($this->debug_flag) && $this->debug_flag) {
5487                                                 $payload .= "<!-- Content being deflated -->";
5488                                         }
5489                                         $this->outgoing_headers[] = "Content-Encoding: deflate";
5490                                         $payload = gzdeflate($payload);
5491                                 } else {
5492                                         if (isset($this->debug_flag) && $this->debug_flag) {
5493                                                 $payload .= "<!-- Content will not be deflated: no gzcompress -->";
5494                                         }
5495                                 }
5496                         }
5497                 }
5498                 //end code
5499                 ob_end_clean();
5500                 ob_start();
5501                 $this->outgoing_headers[] = "Content-Length: ".strlen($payload);
5502                 reset($this->outgoing_headers);
5503                 foreach($this->outgoing_headers as $hdr){
5504                         header($hdr, false);
5505                 }
5506                 print $payload;
5507                 ob_flush();
5508
5509                 $this->response = join("\r\n",$this->outgoing_headers)."\r\n\r\n".$payload;
5510         }
5511
5512         /**
5513         * takes the value that was created by parsing the request
5514         * and compares to the method's signature, if available.
5515         *
5516         * @param        string  $operation      The operation to be invoked
5517         * @param        array   $request        The array of parameter values
5518         * @return       boolean Whether the operation was found
5519         * @access   private
5520         */
5521         function verify_method($operation,$request){
5522                 if(isset($this->wsdl) && is_object($this->wsdl)){
5523                         if($this->wsdl->getOperationData($operation)){
5524                                 return true;
5525                         }
5526             } elseif(isset($this->operations[$operation])){
5527                         return true;
5528                 }
5529                 return false;
5530         }
5531
5532         /**
5533         * processes SOAP message received from client
5534         *
5535         * @param        array   $headers        The HTTP headers
5536         * @param        string  $data           unprocessed request data from client
5537         * @return       mixed   value of the message, decoded into a PHP type
5538         * @access   private
5539         */
5540     function parseRequest($headers, $data) {
5541                 $this->debug('Entering parseRequest() for data of length ' . strlen($data) . ' headers:');
5542                 $this->appendDebug($this->varDump($headers));
5543         if (!isset($headers['content-type'])) {
5544                         $this->setError('Request not of type text/xml (no content-type header)');
5545                         return false;
5546         }
5547                 if (!strstr($headers['content-type'], 'text/xml')) {
5548                         $this->setError('Request not of type text/xml');
5549                         return false;
5550                 }
5551                 if (strpos($headers['content-type'], '=')) {
5552                         $enc = str_replace('"', '', substr(strstr($headers["content-type"], '='), 1));
5553                         $this->debug('Got response encoding: ' . $enc);
5554                         if(preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i',$enc)){
5555                                 $this->xml_encoding = strtoupper($enc);
5556                         } else {
5557                                 $this->xml_encoding = 'US-ASCII';
5558                         }
5559                 } else {
5560                         // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
5561                         $this->xml_encoding = 'ISO-8859-1';
5562                 }
5563                 $this->debug('Use encoding: ' . $this->xml_encoding . ' when creating nusoap_parser');
5564                 // parse response, get soap parser obj
5565                 $parser = new nusoap_parser($data,$this->xml_encoding,'',$this->decode_utf8);
5566                 // parser debug
5567                 $this->debug("parser debug: \n".$parser->getDebug());
5568                 // if fault occurred during message parsing
5569                 if($err = $parser->getError()){
5570                         $this->result = 'fault: error in msg parsing: '.$err;
5571                         $this->fault('SOAP-ENV:Client',"error in msg parsing:\n".$err);
5572                 // else successfully parsed request into soapval object
5573                 } else {
5574                         // get/set methodname
5575                         $this->methodURI = $parser->root_struct_namespace;
5576                         $this->methodname = $parser->root_struct_name;
5577                         $this->debug('methodname: '.$this->methodname.' methodURI: '.$this->methodURI);
5578                         $this->debug('calling parser->get_soapbody()');
5579                         $this->methodparams = $parser->get_soapbody();
5580                         // get SOAP headers
5581                         $this->requestHeaders = $parser->getHeaders();
5582                         // get SOAP Header
5583                         $this->requestHeader = $parser->get_soapheader();
5584             // add document for doclit support
5585             $this->document = $parser->document;
5586                 }
5587          }
5588
5589         /**
5590         * gets the HTTP body for the current response.
5591         *
5592         * @param string $soapmsg The SOAP payload
5593         * @return string The HTTP body, which includes the SOAP payload
5594         * @access private
5595         */
5596         function getHTTPBody($soapmsg) {
5597                 return $soapmsg;
5598         }
5599         
5600         /**
5601         * gets the HTTP content type for the current response.
5602         *
5603         * Note: getHTTPBody must be called before this.
5604         *
5605         * @return string the HTTP content type for the current response.
5606         * @access private
5607         */
5608         function getHTTPContentType() {
5609                 return 'text/xml';
5610         }
5611         
5612         /**
5613         * gets the HTTP content type charset for the current response.
5614         * returns false for non-text content types.
5615         *
5616         * Note: getHTTPBody must be called before this.
5617         *
5618         * @return string the HTTP content type charset for the current response.
5619         * @access private
5620         */
5621         function getHTTPContentTypeCharset() {
5622                 return $this->soap_defencoding;
5623         }
5624
5625         /**
5626         * add a method to the dispatch map (this has been replaced by the register method)
5627         *
5628         * @param    string $methodname
5629         * @param    string $in array of input values
5630         * @param    string $out array of output values
5631         * @access   public
5632         * @deprecated
5633         */
5634         function add_to_map($methodname,$in,$out){
5635                         $this->operations[$methodname] = array('name' => $methodname,'in' => $in,'out' => $out);
5636         }
5637
5638         /**
5639         * register a service function with the server
5640         *
5641         * @param    string $name the name of the PHP function, class.method or class..method
5642         * @param    array $in assoc array of input values: key = param name, value = param type
5643         * @param    array $out assoc array of output values: key = param name, value = param type
5644         * @param        mixed $namespace the element namespace for the method or false
5645         * @param        mixed $soapaction the soapaction for the method or false
5646         * @param        mixed $style optional (rpc|document) or false Note: when 'document' is specified, parameter and return wrappers are created for you automatically
5647         * @param        mixed $use optional (encoded|literal) or false
5648         * @param        string $documentation optional Description to include in WSDL
5649         * @param        string $encodingStyle optional (usually 'http://schemas.xmlsoap.org/soap/encoding/' for encoded)
5650         * @access   public
5651         */
5652         function register($name,$in=array(),$out=array(),$namespace=false,$soapaction=false,$style=false,$use=false,$documentation='',$encodingStyle=''){
5653                 global $HTTP_SERVER_VARS;
5654
5655                 if($this->externalWSDLURL){
5656                         die('You cannot bind to an external WSDL file, and register methods outside of it! Please choose either WSDL or no WSDL.');
5657                 }
5658                 if (! $name) {
5659                         die('You must specify a name when you register an operation');
5660                 }
5661                 if (!is_array($in)) {
5662                         die('You must provide an array for operation inputs');
5663                 }
5664                 if (!is_array($out)) {
5665                         die('You must provide an array for operation outputs');
5666                 }
5667                 if(false == $namespace) {
5668                 }
5669                 if(false == $soapaction) {
5670                         if (isset($_SERVER)) {
5671                                 $SERVER_NAME = $_SERVER['SERVER_NAME'];
5672                                 $SCRIPT_NAME = isset($_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : $_SERVER['SCRIPT_NAME'];
5673                                 $HTTPS = isset($_SERVER['HTTPS']) ? $_SERVER['HTTPS'] : (isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off');
5674                         } elseif (isset($HTTP_SERVER_VARS)) {
5675                                 $SERVER_NAME = $HTTP_SERVER_VARS['SERVER_NAME'];
5676                                 $SCRIPT_NAME = isset($HTTP_SERVER_VARS['PHP_SELF']) ? $HTTP_SERVER_VARS['PHP_SELF'] : $HTTP_SERVER_VARS['SCRIPT_NAME'];
5677                                 $HTTPS = isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off';
5678                         } else {
5679                                 $this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available");
5680                         }
5681                 if ($HTTPS == '1' || $HTTPS == 'on') {
5682                         $SCHEME = 'https';
5683                 } else {
5684                         $SCHEME = 'http';
5685                 }
5686                         $soapaction = "$SCHEME://$SERVER_NAME$SCRIPT_NAME/$name";
5687                 }
5688                 if(false == $style) {
5689                         $style = "rpc";
5690                 }
5691                 if(false == $use) {
5692                         $use = "encoded";
5693                 }
5694                 if ($use == 'encoded' && $encodingStyle == '') {
5695                         $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
5696                 }
5697
5698                 $this->operations[$name] = array(
5699             'name' => $name,
5700             'in' => $in,
5701             'out' => $out,
5702             'namespace' => $namespace,
5703             'soapaction' => $soapaction,
5704             'style' => $style);
5705         if($this->wsdl){
5706                 $this->wsdl->addOperation($name,$in,$out,$namespace,$soapaction,$style,$use,$documentation,$encodingStyle);
5707             }
5708                 return true;
5709         }
5710
5711         /**
5712         * Specify a fault to be returned to the client.
5713         * This also acts as a flag to the server that a fault has occured.
5714         *
5715         * @param        string $faultcode
5716         * @param        string $faultstring
5717         * @param        string $faultactor
5718         * @param        string $faultdetail
5719         * @access   public
5720         */
5721         function fault($faultcode,$faultstring,$faultactor='',$faultdetail=''){
5722                 if ($faultdetail == '' && $this->debug_flag) {
5723                         $faultdetail = $this->getDebug();
5724                 }
5725                 $this->fault = new nusoap_fault($faultcode,$faultactor,$faultstring,$faultdetail);
5726                 $this->fault->soap_defencoding = $this->soap_defencoding;
5727         }
5728
5729     /**
5730     * Sets up wsdl object.
5731     * Acts as a flag to enable internal WSDL generation
5732     *
5733     * @param string $serviceName, name of the service
5734     * @param mixed $namespace optional 'tns' service namespace or false
5735     * @param mixed $endpoint optional URL of service endpoint or false
5736     * @param string $style optional (rpc|document) WSDL style (also specified by operation)
5737     * @param string $transport optional SOAP transport
5738     * @param mixed $schemaTargetNamespace optional 'types' targetNamespace for service schema or false
5739     */
5740     function configureWSDL($serviceName,$namespace = false,$endpoint = false,$style='rpc', $transport = 'http://schemas.xmlsoap.org/soap/http', $schemaTargetNamespace = false)
5741     {
5742         global $HTTP_SERVER_VARS;
5743
5744                 if (isset($_SERVER)) {
5745                         $SERVER_NAME = $_SERVER['SERVER_NAME'];
5746                         $SERVER_PORT = $_SERVER['SERVER_PORT'];
5747                         $SCRIPT_NAME = isset($_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : $_SERVER['SCRIPT_NAME'];
5748                         $HTTPS = isset($_SERVER['HTTPS']) ? $_SERVER['HTTPS'] : (isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off');
5749                 } elseif (isset($HTTP_SERVER_VARS)) {
5750                         $SERVER_NAME = $HTTP_SERVER_VARS['SERVER_NAME'];
5751                         $SERVER_PORT = $HTTP_SERVER_VARS['SERVER_PORT'];
5752                         $SCRIPT_NAME = isset($HTTP_SERVER_VARS['PHP_SELF']) ? $HTTP_SERVER_VARS['PHP_SELF'] : $HTTP_SERVER_VARS['SCRIPT_NAME'];
5753                         $HTTPS = isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off';
5754                 } else {
5755                         $this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available");
5756                 }
5757                 // If server name has port number attached then strip it (else port number gets duplicated in WSDL output) (occurred using lighttpd and FastCGI)
5758                 $colon = strpos($SERVER_NAME,":");
5759                 if ($colon) {
5760                     $SERVER_NAME = substr($SERVER_NAME, 0, $colon);
5761                 }
5762                 if ($SERVER_PORT == 80) {
5763                         $SERVER_PORT = '';
5764                 } else {
5765                         $SERVER_PORT = ':' . $SERVER_PORT;
5766                 }
5767         if(false == $namespace) {
5768             $namespace = "http://$SERVER_NAME/soap/$serviceName";
5769         }
5770         
5771         if(false == $endpoint) {
5772                 if ($HTTPS == '1' || $HTTPS == 'on') {
5773                         $SCHEME = 'https';
5774                 } else {
5775                         $SCHEME = 'http';
5776                 }
5777             $endpoint = "$SCHEME://$SERVER_NAME$SERVER_PORT$SCRIPT_NAME";
5778         }
5779         
5780         if(false == $schemaTargetNamespace) {
5781             $schemaTargetNamespace = $namespace;
5782         }
5783         
5784                 $this->wsdl = new wsdl;
5785                 $this->wsdl->serviceName = $serviceName;
5786         $this->wsdl->endpoint = $endpoint;
5787                 $this->wsdl->namespaces['tns'] = $namespace;
5788                 $this->wsdl->namespaces['soap'] = 'http://schemas.xmlsoap.org/wsdl/soap/';
5789                 $this->wsdl->namespaces['wsdl'] = 'http://schemas.xmlsoap.org/wsdl/';
5790                 if ($schemaTargetNamespace != $namespace) {
5791                         $this->wsdl->namespaces['types'] = $schemaTargetNamespace;
5792                 }
5793         $this->wsdl->schemas[$schemaTargetNamespace][0] = new nusoap_xmlschema('', '', $this->wsdl->namespaces);
5794         if ($style == 'document') {
5795                 $this->wsdl->schemas[$schemaTargetNamespace][0]->schemaInfo['elementFormDefault'] = 'qualified';
5796         }
5797         $this->wsdl->schemas[$schemaTargetNamespace][0]->schemaTargetNamespace = $schemaTargetNamespace;
5798         $this->wsdl->schemas[$schemaTargetNamespace][0]->imports['http://schemas.xmlsoap.org/soap/encoding/'][0] = array('location' => '', 'loaded' => true);
5799         $this->wsdl->schemas[$schemaTargetNamespace][0]->imports['http://schemas.xmlsoap.org/wsdl/'][0] = array('location' => '', 'loaded' => true);
5800         $this->wsdl->bindings[$serviceName.'Binding'] = array(
5801                 'name'=>$serviceName.'Binding',
5802             'style'=>$style,
5803             'transport'=>$transport,
5804             'portType'=>$serviceName.'PortType');
5805         $this->wsdl->ports[$serviceName.'Port'] = array(
5806                 'binding'=>$serviceName.'Binding',
5807             'location'=>$endpoint,
5808             'bindingType'=>'http://schemas.xmlsoap.org/wsdl/soap/');
5809     }
5810 }
5811
5812 /**
5813  * Backward compatibility
5814  */
5815 class soap_server extends nusoap_server {
5816 }
5817
5818 ?><?php
5819
5820 /*
5821
5822 Modification information for LGPL compliance
5823
5824 r58622 - 2010-10-22 18:18:59 -0700 (Fri, 22 Oct 2010) - engsvnbuild - Author: lam <lam@198.18.142.201>
5825     bug 40066
5826
5827 r58361 - 2010-09-29 16:59:02 -0700 (Wed, 29 Sep 2010) - kjing - Author: Jenny Gonsalves <jenny@sugarcrm.com>
5828     Merging with maint_6_0_1 (svn merge -r 58250:58342)
5829
5830 r57813 - 2010-08-19 10:34:44 -0700 (Thu, 19 Aug 2010) - kjing - Author: John Mertic <jmertic@sugarcrm.com>
5831     Bug 39085 - When loading the opposite search panel via ajax on the ListViews, call the index action instead of the ListView action to avoid touching pre-MVC code by accident.
5832
5833 r57707 - 2010-08-10 12:26:13 -0700 (Tue, 10 Aug 2010) - kjing - Author: Stanislav Malyshev <smalyshev@gmail.com>
5834     fix SOAP calls with no parameters
5835
5836 r56990 - 2010-06-16 13:05:36 -0700 (Wed, 16 Jun 2010) - kjing - snapshot "Mango" svn branch to a new one for GitHub sync
5837
5838 r56989 - 2010-06-16 13:01:33 -0700 (Wed, 16 Jun 2010) - kjing - defunt "Mango" svn dev branch before github cutover
5839
5840 r55980 - 2010-04-19 13:31:28 -0700 (Mon, 19 Apr 2010) - kjing - create Mango (6.1) based on windex
5841
5842 r51719 - 2009-10-22 10:18:00 -0700 (Thu, 22 Oct 2009) - mitani - Converted to Build 3  tags and updated the build system 
5843
5844 r51634 - 2009-10-19 13:32:22 -0700 (Mon, 19 Oct 2009) - mitani - Windex is the branch for Sugar Sales 1.0 development
5845
5846 r51508 - 2009-10-14 07:40:23 -0700 (Wed, 14 Oct 2009) - jmertic - More fallout fixes from the PHP 5.3 ereg to preg changes.
5847
5848 r51455 - 2009-10-13 07:56:48 -0700 (Tue, 13 Oct 2009) - jmertic - Bug 33202 - Enable install of SugarCRM on PHP 5.3.0, asserting that the minimum supported version is PHP 5.2.x.
5849
5850 r51443 - 2009-10-12 13:34:36 -0700 (Mon, 12 Oct 2009) - jmertic - Bug 33332 - Made application PHP 5.3 compliant with E_DEPRECATED warnings on by:
5851 - Changing all ereg function to either preg or simple string based ones
5852 - No more references to magic quotes.
5853 - Change all the session_unregister() functions to just unset() the correct session variable instead.
5854
5855 r50375 - 2009-08-24 18:07:43 -0700 (Mon, 24 Aug 2009) - dwong - branch kobe2 from tokyo r50372
5856
5857 r45763 - 2009-04-01 12:16:18 -0700 (Wed, 01 Apr 2009) - majed - Removed half of the require_once and include_onces in the product that were redundant or could be handled easily by the auto loader
5858
5859 r45680 - 2009-03-30 14:34:35 -0700 (Mon, 30 Mar 2009) - Samir Gandhi - modifeid serializeSchema to generate WS-I compliant WSDL
5860
5861 r42807 - 2008-12-29 11:16:59 -0800 (Mon, 29 Dec 2008) - dwong - Branch from trunk/sugarcrm r42806 to branches/tokyo/sugarcrm
5862
5863 r42645 - 2008-12-18 13:41:08 -0800 (Thu, 18 Dec 2008) - awu - merging maint_5_2_0 rev41336:HEAD to trunk
5864
5865 r41647 - 2008-11-11 17:44:30 -0800 (Tue, 11 Nov 2008) - majed - Fixes a few bugs 
5866
5867 r41596 - 2008-11-10 19:20:04 -0800 (Mon, 10 Nov 2008) - Samir Gandhi - modified to set $method in the code
5868
5869 r41558 - 2008-11-10 14:35:34 -0800 (Mon, 10 Nov 2008) - majed - changes nusoap to allow for registering classes 
5870
5871 r39619 - 2008-09-09 13:41:34 -0700 (Tue, 09 Sep 2008) - jmertic - Bug 24827 - Remove all instances where we return a new object and assign it by reference, since this is deprecated in PHP 5 and emits E_DEPRECATED errors in PHP 5.3.
5872 Touched:
5873 - data/SugarBean.php
5874 - include/domit/php_http_client_generic.php
5875 - include/domit/php_http_connector.php
5876 - include/domit/testing_domit.php
5877 - include/domit/xml_domit_getelementsbypath.php
5878 - include/domit/xml_domit_lite_parser.php
5879 - include/domit/xml_domit_nodemaps.php
5880 - include/domit/xml_domit_parser.php
5881 - include/domit/xml_domit_shared.php
5882 - include/generic/SugarWidgets/SugarWidgetField.php
5883 - include/generic/SugarWidgets/SugarWidgetReportField.php
5884 - include/ListView/ProcessView.php
5885 - include/nusoap/class.soapclient.php
5886 - include/nusoap/nusoap.php
5887 - include/nusoap/nusoapmime.php
5888 - include/Pear/HTML_Safe/Safe.php
5889 - include/Pear/XML_HTMLSax3/HTMLSax3.php
5890 - modules/Administration/RebuildWorkFlow.php
5891 - modules/Expressions/RelateSelector.php
5892 - modules/Reports/templates/templates_reports.php
5893 - modules/WorkFlow/Delete.php
5894 - modules/WorkFlow/Save.php
5895 - modules/WorkFlow/SaveSequence.php
5896 - modules/WorkFlow/WorkFlow.php
5897 - modules/WorkFlowActionShells/CreateStep1.php
5898 - modules/WorkFlowActionShells/CreateStep2.php
5899 - modules/WorkFlowActionShells/Save.php
5900 - modules/WorkFlowActionShells/WorkFlowActionShell.php
5901 - modules/WorkFlowAlerts/Save.php
5902 - modules/WorkFlowAlerts/WorkFlowAlert.php
5903 - modules/WorkFlowAlertShells/DetailView.php
5904 - modules/WorkFlowAlertShells/WorkFlowAlertShell.php
5905 - modules/WorkFlowTriggerShells/CreateStep1.php
5906 - modules/WorkFlowTriggerShells/CreateStepFilter.php
5907 - modules/WorkFlowTriggerShells/SaveFilter.php
5908 - modules/WorkFlowTriggerShells/WorkFlowTriggerShell.php
5909 - soap/SoapHelperFunctions.php
5910 - test/modules/DynamicFields/DynamicFields_Bug24095_test.php
5911 - test/simpletest/browser.php
5912 - test/simpletest/default_reporter.php
5913 - test/simpletest/detached.php
5914 - test/simpletest/eclipse.php
5915 - test/simpletest/expectation.php
5916 - test/simpletest/extensions/pear_test_case.php
5917 - test/simpletest/form.php
5918 - test/simpletest/http.php
5919 - test/simpletest/mock_objects.php
5920 - test/simpletest/page.php
5921 - test/simpletest/parser.php
5922 - test/simpletest/remote.php
5923 - test/simpletest/shell_tester.php
5924 - test/simpletest/simple_test.php
5925 - test/simpletest/simpletest.php
5926 - test/simpletest/test/acceptance_test.php
5927 - test/simpletest/test/adapter_test.php
5928 - test/simpletest/test/authentication_test.php
5929 - test/simpletest/test/browser_test.php
5930 - test/simpletest/test/collector_test.php
5931 - test/simpletest/test/compatibility_test.php
5932 - test/simpletest/test/detached_test.php
5933 - test/simpletest/test/eclipse_test.php
5934 - test/simpletest/test/encoding_test.php
5935 - test/simpletest/test/errors_test.php
5936 - test/simpletest/test/expectation_test.php
5937 - test/simpletest/test/form_test.php
5938 - test/simpletest/test/frames_test.php
5939 - test/simpletest/test/http_test.php
5940 - test/simpletest/test/live_test.php
5941 - test/simpletest/test/mock_objects_test.php
5942 - test/simpletest/test/page_test.php
5943 - test/simpletest/test/parse_error_test.php
5944 - test/simpletest/test/parser_test.php
5945 - test/simpletest/test/remote_test.php
5946 - test/simpletest/test/shell_test.php
5947 - test/simpletest/test/shell_tester_test.php
5948 - test/simpletest/test/simpletest_test.php
5949 - test/simpletest/test/site/page_request.php
5950 - test/simpletest/test/tag_test.php
5951 - test/simpletest/test/unit_tester_test.php
5952 - test/simpletest/test/user_agent_test.php
5953 - test/simpletest/test/visual_test.php
5954 - test/simpletest/test/xml_test.php
5955 - test/simpletest/test_case.php
5956 - test/simpletest/ui/array_reporter/test.php
5957 - test/simpletest/ui/recorder/test.php
5958 - test/simpletest/unit_tester.php
5959 - test/simpletest/url.php
5960 - test/simpletest/user_agent.php
5961 - test/simpletest/web_tester.php
5962 - test/spikephpcoverage/src/PEAR.php
5963 - test/spikephpcoverage/src/util/Utility.php
5964 - test/spikephpcoverage/src/XML/Parser.php
5965 - test/spikephpcoverage/src/XML/Parser/Simple.php
5966 - test/test_utilities/SugarTest_SimpleBrowser.php
5967
5968 r38362 - 2008-07-28 14:06:59 -0700 (Mon, 28 Jul 2008) - roger - bug: 23897. Using print_r when using the debug statement in nusoap will print out the statements to the screen if the call is coming from the UI.
5969
5970 r38300 - 2008-07-25 13:33:43 -0700 (Fri, 25 Jul 2008) - Samir Gandhi - put the debug in parseresponse function
5971
5972 r38293 - 2008-07-25 12:32:34 -0700 (Fri, 25 Jul 2008) - Samir Gandhi - to put all the debug statements return value in the call function
5973
5974 r36824 - 2008-06-18 09:26:11 -0700 (Wed, 18 Jun 2008) - roger - bug: 21832
5975
5976 r26422 - 2007-09-05 17:29:12 -0700 (Wed, 05 Sep 2007) - majed - migrate from beta 1 to trunk
5977
5978 r15787 - 2006-08-10 10:14:41 -0700 (Thu, 10 Aug 2006) - roger - RRS: bug 7961
5979
5980 r14701 - 2006-07-17 13:37:26 -0700 (Mon, 17 Jul 2006) - roger - RRS: bug 5801
5981
5982 r13782 - 2006-06-06 10:58:55 -0700 (Tue, 06 Jun 2006) - majed - changes entry point code
5983
5984 r11466 - 2006-02-01 15:49:47 -0800 (Wed, 01 Feb 2006) - jacob - Adding extra !empty check to get around a PHP warning.
5985
5986 r11115 - 2006-01-17 14:54:45 -0800 (Tue, 17 Jan 2006) - majed - add entry point validation
5987
5988 r10585 - 2005-12-13 14:42:26 -0800 (Tue, 13 Dec 2005) - majed - adds new license mechanisim
5989
5990 r10170 - 2005-12-05 18:37:46 -0800 (Mon, 05 Dec 2005) - majed - fixes various issues
5991
5992 r8999 - 2005-11-04 05:26:49 -0800 (Fri, 04 Nov 2005) - roger - When nusoap was upgraded we had an issue with the user's default language not being populated during a soap request. I determined the reason this was happening and have checked in the corresponding change to nusoap.
5993
5994 r8991 - 2005-11-03 19:07:25 -0800 (Thu, 03 Nov 2005) - majed - fixes nusoap issue
5995
5996 r8846 - 2005-10-31 11:01:12 -0800 (Mon, 31 Oct 2005) - majed - new version of nusoap
5997
5998 r7905 - 2005-09-21 19:12:57 -0700 (Wed, 21 Sep 2005) - majed - restores old nusoap pre & with a few fixes
5999
6000 r7861 - 2005-09-20 15:40:25 -0700 (Tue, 20 Sep 2005) - majed - & fix for 3.5.1
6001
6002 r7452 - 2005-08-17 11:32:34 -0700 (Wed, 17 Aug 2005) - majed - changes soap to nusoap
6003
6004 r5820 - 2005-06-21 14:22:24 -0700 (Tue, 21 Jun 2005) - majed - fixes issues with nusoap and with custom fields
6005
6006 r5462 - 2005-05-25 13:50:11 -0700 (Wed, 25 May 2005) - majed - upgraded nusoap to .6.9
6007
6008 r5104 - 2005-05-04 15:33:41 -0700 (Wed, 04 May 2005) - majed - gets rid of HTTP_GET_VARS and what not which has been deprecated
6009
6010 r573 - 2004-09-04 13:03:32 -0700 (Sat, 04 Sep 2004) - sugarclint - undoing copyrights added in inadvertantly.  --clint
6011
6012 r546 - 2004-09-03 11:49:38 -0700 (Fri, 03 Sep 2004) - sugarmsi - removed echo count
6013
6014 r354 - 2004-08-02 23:00:37 -0700 (Mon, 02 Aug 2004) - sugarjacob - Adding Soap
6015
6016
6017 */
6018
6019
6020
6021
6022
6023 /**
6024 * parses a WSDL file, allows access to it's data, other utility methods.
6025 * also builds WSDL structures programmatically.
6026
6027 * @author   Dietrich Ayala <dietrich@ganx4.com>
6028 * @author   Scott Nichol <snichol@users.sourceforge.net>
6029
6030 * @access public 
6031 */
6032 class wsdl extends nusoap_base {
6033         // URL or filename of the root of this WSDL
6034     var $wsdl; 
6035     // define internal arrays of bindings, ports, operations, messages, etc.
6036     var $schemas = array();
6037     var $currentSchema;
6038     var $message = array();
6039     var $complexTypes = array();
6040     var $messages = array();
6041     var $currentMessage;
6042     var $currentOperation;
6043     var $portTypes = array();
6044     var $currentPortType;
6045     var $bindings = array();
6046     var $currentBinding;
6047     var $ports = array();
6048     var $currentPort;
6049     var $opData = array();
6050     var $status = '';
6051     var $documentation = false;
6052     var $endpoint = ''; 
6053     // array of wsdl docs to import
6054     var $import = array(); 
6055     // parser vars
6056     var $parser;
6057     var $position = 0;
6058     var $depth = 0;
6059     var $depth_array = array();
6060         // for getting wsdl
6061         var $proxyhost = '';
6062     var $proxyport = '';
6063         var $proxyusername = '';
6064         var $proxypassword = '';
6065         var $timeout = 0;
6066         var $response_timeout = 30;
6067         var $curl_options = array();    // User-specified cURL options
6068         var $use_curl = false;                  // whether to always try to use cURL
6069         // for HTTP authentication
6070         var $username = '';                             // Username for HTTP authentication
6071         var $password = '';                             // Password for HTTP authentication
6072         var $authtype = '';                             // Type of HTTP authentication
6073         var $certRequest = array();             // Certificate for HTTP SSL authentication
6074
6075     /**
6076      * constructor
6077      * 
6078      * @param string $wsdl WSDL document URL
6079          * @param string $proxyhost
6080          * @param string $proxyport
6081          * @param string $proxyusername
6082          * @param string $proxypassword
6083          * @param integer $timeout set the connection timeout
6084          * @param integer $response_timeout set the response timeout
6085          * @param array $curl_options user-specified cURL options
6086          * @param boolean $use_curl try to use cURL
6087      * @access public 
6088      */
6089     function wsdl($wsdl = '',$proxyhost=false,$proxyport=false,$proxyusername=false,$proxypassword=false,$timeout=0,$response_timeout=30,$curl_options=null,$use_curl=false){
6090                 parent::nusoap_base();
6091                 $this->debug("ctor wsdl=$wsdl timeout=$timeout response_timeout=$response_timeout");
6092         $this->proxyhost = $proxyhost;
6093         $this->proxyport = $proxyport;
6094                 $this->proxyusername = $proxyusername;
6095                 $this->proxypassword = $proxypassword;
6096                 $this->timeout = $timeout;
6097                 $this->response_timeout = $response_timeout;
6098                 if (is_array($curl_options))
6099                         $this->curl_options = $curl_options;
6100                 $this->use_curl = $use_curl;
6101                 $this->fetchWSDL($wsdl);
6102     }
6103
6104         /**
6105          * fetches the WSDL document and parses it
6106          *
6107          * @access public
6108          */
6109         function fetchWSDL($wsdl) {
6110                 $this->debug("parse and process WSDL path=$wsdl");
6111                 $this->wsdl = $wsdl;
6112         // parse wsdl file
6113         if ($this->wsdl != "") {
6114             $this->parseWSDL($this->wsdl);
6115         }
6116         // imports
6117         // TODO: handle imports more properly, grabbing them in-line and nesting them
6118         $imported_urls = array();
6119         $imported = 1;
6120         while ($imported > 0) {
6121                 $imported = 0;
6122                 // Schema imports
6123                 foreach ($this->schemas as $ns => $list) {
6124                         foreach ($list as $xs) {
6125                                         $wsdlparts = parse_url($this->wsdl);    // this is bogusly simple!
6126                             foreach ($xs->imports as $ns2 => $list2) {
6127                                 for ($ii = 0; $ii < count($list2); $ii++) {
6128                                         if (! $list2[$ii]['loaded']) {
6129                                                 $this->schemas[$ns]->imports[$ns2][$ii]['loaded'] = true;
6130                                                 $url = $list2[$ii]['location'];
6131                                                                 if ($url != '') {
6132                                                                         $urlparts = parse_url($url);
6133                                                                         if (!isset($urlparts['host'])) {
6134                                                                                 $url = $wsdlparts['scheme'] . '://' . $wsdlparts['host'] . (isset($wsdlparts['port']) ? ':' .$wsdlparts['port'] : '') .
6135                                                                                                 substr($wsdlparts['path'],0,strrpos($wsdlparts['path'],'/') + 1) .$urlparts['path'];
6136                                                                         }
6137                                                                         if (! in_array($url, $imported_urls)) {
6138                                                                 $this->parseWSDL($url);
6139                                                                 $imported++;
6140                                                                 $imported_urls[] = $url;
6141                                                         }
6142                                                                 } else {
6143                                                                         $this->debug("Unexpected scenario: empty URL for unloaded import");
6144                                                                 }
6145                                                         }
6146                                                 }
6147                             } 
6148                         }
6149                 }
6150                 // WSDL imports
6151                         $wsdlparts = parse_url($this->wsdl);    // this is bogusly simple!
6152             foreach ($this->import as $ns => $list) {
6153                 for ($ii = 0; $ii < count($list); $ii++) {
6154                         if (! $list[$ii]['loaded']) {
6155                                 $this->import[$ns][$ii]['loaded'] = true;
6156                                 $url = $list[$ii]['location'];
6157                                                 if ($url != '') {
6158                                                         $urlparts = parse_url($url);
6159                                                         if (!isset($urlparts['host'])) {
6160                                                                 $url = $wsdlparts['scheme'] . '://' . $wsdlparts['host'] . (isset($wsdlparts['port']) ? ':' . $wsdlparts['port'] : '') .
6161                                                                                 substr($wsdlparts['path'],0,strrpos($wsdlparts['path'],'/') + 1) .$urlparts['path'];
6162                                                         }
6163                                                         if (! in_array($url, $imported_urls)) {
6164                                                 $this->parseWSDL($url);
6165                                                 $imported++;
6166                                                 $imported_urls[] = $url;
6167                                         }
6168                                                 } else {
6169                                                         $this->debug("Unexpected scenario: empty URL for unloaded import");
6170                                                 }
6171                                         }
6172                                 }
6173             } 
6174                 }
6175         // add new data to operation data
6176         foreach($this->bindings as $binding => $bindingData) {
6177             if (isset($bindingData['operations']) && is_array($bindingData['operations'])) {
6178                 foreach($bindingData['operations'] as $operation => $data) {
6179                     $this->debug('post-parse data gathering for ' . $operation);
6180                     $this->bindings[$binding]['operations'][$operation]['input'] = 
6181                                                 isset($this->bindings[$binding]['operations'][$operation]['input']) ? 
6182                                                 array_merge($this->bindings[$binding]['operations'][$operation]['input'], $this->portTypes[ $bindingData['portType'] ][$operation]['input']) :
6183                                                 $this->portTypes[ $bindingData['portType'] ][$operation]['input'];
6184                     $this->bindings[$binding]['operations'][$operation]['output'] = 
6185                                                 isset($this->bindings[$binding]['operations'][$operation]['output']) ?
6186                                                 array_merge($this->bindings[$binding]['operations'][$operation]['output'], $this->portTypes[ $bindingData['portType'] ][$operation]['output']) :
6187                                                 $this->portTypes[ $bindingData['portType'] ][$operation]['output'];
6188                     if(isset($this->messages[ $this->bindings[$binding]['operations'][$operation]['input']['message'] ])){
6189                                                 $this->bindings[$binding]['operations'][$operation]['input']['parts'] = $this->messages[ $this->bindings[$binding]['operations'][$operation]['input']['message'] ];
6190                                         }
6191                                         if(isset($this->messages[ $this->bindings[$binding]['operations'][$operation]['output']['message'] ])){
6192                                 $this->bindings[$binding]['operations'][$operation]['output']['parts'] = $this->messages[ $this->bindings[$binding]['operations'][$operation]['output']['message'] ];
6193                     }
6194                     // Set operation style if necessary, but do not override one already provided
6195                                         if (isset($bindingData['style']) && !isset($this->bindings[$binding]['operations'][$operation]['style'])) {
6196                         $this->bindings[$binding]['operations'][$operation]['style'] = $bindingData['style'];
6197                     }
6198                     $this->bindings[$binding]['operations'][$operation]['transport'] = isset($bindingData['transport']) ? $bindingData['transport'] : '';
6199                     $this->bindings[$binding]['operations'][$operation]['documentation'] = isset($this->portTypes[ $bindingData['portType'] ][$operation]['documentation']) ? $this->portTypes[ $bindingData['portType'] ][$operation]['documentation'] : '';
6200                     $this->bindings[$binding]['operations'][$operation]['endpoint'] = isset($bindingData['endpoint']) ? $bindingData['endpoint'] : '';
6201                 } 
6202             } 
6203         }
6204         }
6205
6206     /**
6207      * parses the wsdl document
6208      * 
6209      * @param string $wsdl path or URL
6210      * @access private 
6211      */
6212     function parseWSDL($wsdl = '') {
6213                 $this->debug("parse WSDL at path=$wsdl");
6214
6215         if ($wsdl == '') {
6216             $this->debug('no wsdl passed to parseWSDL()!!');
6217             $this->setError('no wsdl passed to parseWSDL()!!');
6218             return false;
6219         }
6220         
6221         // parse $wsdl for url format
6222         $wsdl_props = parse_url($wsdl);
6223
6224         if (isset($wsdl_props['scheme']) && ($wsdl_props['scheme'] == 'http' || $wsdl_props['scheme'] == 'https')) {
6225             $this->debug('getting WSDL http(s) URL ' . $wsdl);
6226                 // get wsdl
6227                 $tr = new soap_transport_http($wsdl, $this->curl_options, $this->use_curl);
6228                         $tr->request_method = 'GET';
6229                         $tr->useSOAPAction = false;
6230                         if($this->proxyhost && $this->proxyport){
6231                                 $tr->setProxy($this->proxyhost,$this->proxyport,$this->proxyusername,$this->proxypassword);
6232                         }
6233                         if ($this->authtype != '') {
6234                                 $tr->setCredentials($this->username, $this->password, $this->authtype, array(), $this->certRequest);
6235                         }
6236                         $tr->setEncoding('gzip, deflate');
6237                         $wsdl_string = $tr->send('', $this->timeout, $this->response_timeout);
6238                         //$this->debug("WSDL request\n" . $tr->outgoing_payload);
6239                         //$this->debug("WSDL response\n" . $tr->incoming_payload);
6240                         $this->appendDebug($tr->getDebug());
6241                         // catch errors
6242                         if($err = $tr->getError() ){
6243                                 $errstr = 'Getting ' . $wsdl . ' - HTTP ERROR: '.$err;
6244                                 $this->debug($errstr);
6245                     $this->setError($errstr);
6246                                 unset($tr);
6247                     return false;
6248                         }
6249                         unset($tr);
6250                         $this->debug("got WSDL URL");
6251         } else {
6252             // $wsdl is not http(s), so treat it as a file URL or plain file path
6253                 if (isset($wsdl_props['scheme']) && ($wsdl_props['scheme'] == 'file') && isset($wsdl_props['path'])) {
6254                         $path = isset($wsdl_props['host']) ? ($wsdl_props['host'] . ':' . $wsdl_props['path']) : $wsdl_props['path'];
6255                 } else {
6256                         $path = $wsdl;
6257                 }
6258             $this->debug('getting WSDL file ' . $path);
6259             if ($fp = @fopen($path, 'r')) {
6260                 $wsdl_string = '';
6261                 while ($data = fread($fp, 32768)) {
6262                     $wsdl_string .= $data;
6263                 } 
6264                 fclose($fp);
6265             } else {
6266                 $errstr = "Bad path to WSDL file $path";
6267                 $this->debug($errstr);
6268                 $this->setError($errstr);
6269                 return false;
6270             } 
6271         }
6272         $this->debug('Parse WSDL');
6273         // end new code added
6274         // Create an XML parser.
6275         $this->parser = xml_parser_create(); 
6276         // Set the options for parsing the XML data.
6277         // xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
6278         xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0); 
6279         // Set the object for the parser.
6280         xml_set_object($this->parser, $this); 
6281         // Set the element handlers for the parser.
6282         xml_set_element_handler($this->parser, 'start_element', 'end_element');
6283         xml_set_character_data_handler($this->parser, 'character_data');
6284         // Parse the XML file.
6285         if (!xml_parse($this->parser, $wsdl_string, true)) {
6286             // Display an error message.
6287             $errstr = sprintf(
6288                                 'XML error parsing WSDL from %s on line %d: %s',
6289                                 $wsdl,
6290                 xml_get_current_line_number($this->parser),
6291                 xml_error_string(xml_get_error_code($this->parser))
6292                 );
6293             $this->debug($errstr);
6294                         $this->debug("XML payload:\n" . $wsdl_string);
6295             $this->setError($errstr);
6296             return false;
6297         } 
6298                 // free the parser
6299         xml_parser_free($this->parser);
6300         $this->debug('Parsing WSDL done');
6301                 // catch wsdl parse errors
6302                 if($this->getError()){
6303                         return false;
6304                 }
6305         return true;
6306     } 
6307
6308     /**
6309      * start-element handler
6310      * 
6311      * @param string $parser XML parser object
6312      * @param string $name element name
6313      * @param string $attrs associative array of attributes
6314      * @access private 
6315      */
6316     function start_element($parser, $name, $attrs)
6317     {
6318         if ($this->status == 'schema') {
6319             $this->currentSchema->schemaStartElement($parser, $name, $attrs);
6320             $this->appendDebug($this->currentSchema->getDebug());
6321             $this->currentSchema->clearDebug();
6322         } elseif (preg_match('/schema$/', $name)) {
6323                 $this->debug('Parsing WSDL schema');
6324             // $this->debug("startElement for $name ($attrs[name]). status = $this->status (".$this->getLocalPart($name).")");
6325             $this->status = 'schema';
6326             $this->currentSchema = new nusoap_xmlschema('', '', $this->namespaces);
6327             $this->currentSchema->schemaStartElement($parser, $name, $attrs);
6328             $this->appendDebug($this->currentSchema->getDebug());
6329             $this->currentSchema->clearDebug();
6330         } else {
6331             // position in the total number of elements, starting from 0
6332             $pos = $this->position++;
6333             $depth = $this->depth++; 
6334             // set self as current value for this depth
6335             $this->depth_array[$depth] = $pos;
6336             $this->message[$pos] = array('cdata' => ''); 
6337             // process attributes
6338             if (count($attrs) > 0) {
6339                                 // register namespace declarations
6340                 foreach($attrs as $k => $v) {
6341                     if (preg_match('/^xmlns/',$k)) {
6342                         if ($ns_prefix = substr(strrchr($k, ':'), 1)) {
6343                             $this->namespaces[$ns_prefix] = $v;
6344                         } else {
6345                             $this->namespaces['ns' . (count($this->namespaces) + 1)] = $v;
6346                         } 
6347                         if ($v == 'http://www.w3.org/2001/XMLSchema' || $v == 'http://www.w3.org/1999/XMLSchema' || $v == 'http://www.w3.org/2000/10/XMLSchema') {
6348                             $this->XMLSchemaVersion = $v;
6349                             $this->namespaces['xsi'] = $v . '-instance';
6350                         } 
6351                     }
6352                 }
6353                 // expand each attribute prefix to its namespace
6354                 foreach($attrs as $k => $v) {
6355                     $k = strpos($k, ':') ? $this->expandQname($k) : $k;
6356                     if ($k != 'location' && $k != 'soapAction' && $k != 'namespace') {
6357                         $v = strpos($v, ':') ? $this->expandQname($v) : $v;
6358                     } 
6359                     $eAttrs[$k] = $v;
6360                 } 
6361                 $attrs = $eAttrs;
6362             } else {
6363                 $attrs = array();
6364             } 
6365             // get element prefix, namespace and name
6366             if (preg_match('/:/', $name)) {
6367                 // get ns prefix
6368                 $prefix = substr($name, 0, strpos($name, ':')); 
6369                 // get ns
6370                 $namespace = isset($this->namespaces[$prefix]) ? $this->namespaces[$prefix] : ''; 
6371                 // get unqualified name
6372                 $name = substr(strstr($name, ':'), 1);
6373             } 
6374                         // process attributes, expanding any prefixes to namespaces
6375             // find status, register data
6376             switch ($this->status) {
6377                 case 'message':
6378                     if ($name == 'part') {
6379                                     if (isset($attrs['type'])) {
6380                                     $this->debug("msg " . $this->currentMessage . ": found part (with type) $attrs[name]: " . implode(',', $attrs));
6381                                     $this->messages[$this->currentMessage][$attrs['name']] = $attrs['type'];
6382                                 } 
6383                                     if (isset($attrs['element'])) {
6384                                     $this->debug("msg " . $this->currentMessage . ": found part (with element) $attrs[name]: " . implode(',', $attrs));
6385                                         $this->messages[$this->currentMessage][$attrs['name']] = $attrs['element'] . '^';
6386                                     } 
6387                                 } 
6388                                 break;
6389                             case 'portType':
6390                                 switch ($name) {
6391                                     case 'operation':
6392                                         $this->currentPortOperation = $attrs['name'];
6393                                         $this->debug("portType $this->currentPortType operation: $this->currentPortOperation");
6394                                         if (isset($attrs['parameterOrder'])) {
6395                                                 $this->portTypes[$this->currentPortType][$attrs['name']]['parameterOrder'] = $attrs['parameterOrder'];
6396                                                 } 
6397                                                 break;
6398                                             case 'documentation':
6399                                                 $this->documentation = true;
6400                                                 break; 
6401                                             // merge input/output data
6402                                             default:
6403                                                 $m = isset($attrs['message']) ? $this->getLocalPart($attrs['message']) : '';
6404                                                 $this->portTypes[$this->currentPortType][$this->currentPortOperation][$name]['message'] = $m;
6405                                                 break;
6406                                         } 
6407                                 break;
6408                                 case 'binding':
6409                                     switch ($name) {
6410                                         case 'binding': 
6411                                             // get ns prefix
6412                                             if (isset($attrs['style'])) {
6413                                             $this->bindings[$this->currentBinding]['prefix'] = $prefix;
6414                                                 } 
6415                                                 $this->bindings[$this->currentBinding] = array_merge($this->bindings[$this->currentBinding], $attrs);
6416                                                 break;
6417                                                 case 'header':
6418                                                     $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus]['headers'][] = $attrs;
6419                                                     break;
6420                                                 case 'operation':
6421                                                     if (isset($attrs['soapAction'])) {
6422                                                         $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['soapAction'] = $attrs['soapAction'];
6423                                                     } 
6424                                                     if (isset($attrs['style'])) {
6425                                                         $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['style'] = $attrs['style'];
6426                                                     } 
6427                                                     if (isset($attrs['name'])) {
6428                                                         $this->currentOperation = $attrs['name'];
6429                                                         $this->debug("current binding operation: $this->currentOperation");
6430                                                         $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['name'] = $attrs['name'];
6431                                                         $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['binding'] = $this->currentBinding;
6432                                                         $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['endpoint'] = isset($this->bindings[$this->currentBinding]['endpoint']) ? $this->bindings[$this->currentBinding]['endpoint'] : '';
6433                                                     } 
6434                                                     break;
6435                                                 case 'input':
6436                                                     $this->opStatus = 'input';
6437                                                     break;
6438                                                 case 'output':
6439                                                     $this->opStatus = 'output';
6440                                                     break;
6441                                                 case 'body':
6442                                                     if (isset($this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus])) {
6443                                                         $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus] = array_merge($this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus], $attrs);
6444                                                     } else {
6445                                                         $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus] = $attrs;
6446                                                     } 
6447                                                     break;
6448                                         } 
6449                                         break;
6450                                 case 'service':
6451                                         switch ($name) {
6452                                             case 'port':
6453                                                 $this->currentPort = $attrs['name'];
6454                                                 $this->debug('current port: ' . $this->currentPort);
6455                                                 $this->ports[$this->currentPort]['binding'] = $this->getLocalPart($attrs['binding']);
6456                                         
6457                                                 break;
6458                                             case 'address':
6459                                                 $this->ports[$this->currentPort]['location'] = $attrs['location'];
6460                                                 $this->ports[$this->currentPort]['bindingType'] = $namespace;
6461                                                 $this->bindings[ $this->ports[$this->currentPort]['binding'] ]['bindingType'] = $namespace;
6462                                                 $this->bindings[ $this->ports[$this->currentPort]['binding'] ]['endpoint'] = $attrs['location'];
6463                                                 break;
6464                                         } 
6465                                         break;
6466                         } 
6467                 // set status
6468                 switch ($name) {
6469                         case 'import':
6470                             if (isset($attrs['location'])) {
6471                     $this->import[$attrs['namespace']][] = array('location' => $attrs['location'], 'loaded' => false);
6472                     $this->debug('parsing import ' . $attrs['namespace']. ' - ' . $attrs['location'] . ' (' . count($this->import[$attrs['namespace']]).')');
6473                                 } else {
6474                     $this->import[$attrs['namespace']][] = array('location' => '', 'loaded' => true);
6475                                         if (! $this->getPrefixFromNamespace($attrs['namespace'])) {
6476                                                 $this->namespaces['ns'.(count($this->namespaces)+1)] = $attrs['namespace'];
6477                                         }
6478                     $this->debug('parsing import ' . $attrs['namespace']. ' - [no location] (' . count($this->import[$attrs['namespace']]).')');
6479                                 }
6480                                 break;
6481                         //wait for schema
6482                         //case 'types':
6483                         //      $this->status = 'schema';
6484                         //      break;
6485                         case 'message':
6486                                 $this->status = 'message';
6487                                 $this->messages[$attrs['name']] = array();
6488                                 $this->currentMessage = $attrs['name'];
6489                                 break;
6490                         case 'portType':
6491                                 $this->status = 'portType';
6492                                 $this->portTypes[$attrs['name']] = array();
6493                                 $this->currentPortType = $attrs['name'];
6494                                 break;
6495                         case "binding":
6496                                 if (isset($attrs['name'])) {
6497                                 // get binding name
6498                                         if (strpos($attrs['name'], ':')) {
6499                                         $this->currentBinding = $this->getLocalPart($attrs['name']);
6500                                         } else {
6501                                         $this->currentBinding = $attrs['name'];
6502                                         } 
6503                                         $this->status = 'binding';
6504                                         $this->bindings[$this->currentBinding]['portType'] = $this->getLocalPart($attrs['type']);
6505                                         $this->debug("current binding: $this->currentBinding of portType: " . $attrs['type']);
6506                                 } 
6507                                 break;
6508                         case 'service':
6509                                 $this->serviceName = $attrs['name'];
6510                                 $this->status = 'service';
6511                                 $this->debug('current service: ' . $this->serviceName);
6512                                 break;
6513                         case 'definitions':
6514                                 foreach ($attrs as $name => $value) {
6515                                         $this->wsdl_info[$name] = $value;
6516                                 } 
6517                                 break;
6518                         } 
6519                 } 
6520         } 
6521
6522         /**
6523         * end-element handler
6524         * 
6525         * @param string $parser XML parser object
6526         * @param string $name element name
6527         * @access private 
6528         */
6529         function end_element($parser, $name){ 
6530                 // unset schema status
6531                 if (/*preg_match('/types$/', $name) ||*/ preg_match('/schema$/', $name)) {
6532                         $this->status = "";
6533             $this->appendDebug($this->currentSchema->getDebug());
6534             $this->currentSchema->clearDebug();
6535                         $this->schemas[$this->currentSchema->schemaTargetNamespace][] = $this->currentSchema;
6536                 $this->debug('Parsing WSDL schema done');
6537                 } 
6538                 if ($this->status == 'schema') {
6539                         $this->currentSchema->schemaEndElement($parser, $name);
6540                 } else {
6541                         // bring depth down a notch
6542                         $this->depth--;
6543                 } 
6544                 // end documentation
6545                 if ($this->documentation) {
6546                         //TODO: track the node to which documentation should be assigned; it can be a part, message, etc.
6547                         //$this->portTypes[$this->currentPortType][$this->currentPortOperation]['documentation'] = $this->documentation;
6548                         $this->documentation = false;
6549                 } 
6550         } 
6551
6552         /**
6553          * element content handler
6554          * 
6555          * @param string $parser XML parser object
6556          * @param string $data element content
6557          * @access private 
6558          */
6559         function character_data($parser, $data)
6560         {
6561                 $pos = isset($this->depth_array[$this->depth]) ? $this->depth_array[$this->depth] : 0;
6562                 if (isset($this->message[$pos]['cdata'])) {
6563                         $this->message[$pos]['cdata'] .= $data;
6564                 } 
6565                 if ($this->documentation) {
6566                         $this->documentation .= $data;
6567                 } 
6568         } 
6569
6570         /**
6571         * if authenticating, set user credentials here
6572         *
6573         * @param    string $username
6574         * @param    string $password
6575         * @param        string $authtype (basic|digest|certificate|ntlm)
6576         * @param        array $certRequest (keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, certpassword (optional), verifypeer (optional), verifyhost (optional): see corresponding options in cURL docs)
6577         * @access   public
6578         */
6579         function setCredentials($username, $password, $authtype = 'basic', $certRequest = array()) {
6580                 $this->debug("setCredentials username=$username authtype=$authtype certRequest=");
6581                 $this->appendDebug($this->varDump($certRequest));
6582                 $this->username = $username;
6583                 $this->password = $password;
6584                 $this->authtype = $authtype;
6585                 $this->certRequest = $certRequest;
6586         }
6587         
6588         function getBindingData($binding)
6589         {
6590                 if (is_array($this->bindings[$binding])) {
6591                         return $this->bindings[$binding];
6592                 } 
6593         }
6594         
6595         /**
6596          * returns an assoc array of operation names => operation data
6597          * 
6598          * @param string $portName WSDL port name
6599          * @param string $bindingType eg: soap, smtp, dime (only soap and soap12 are currently supported)
6600          * @return array 
6601          * @access public 
6602          */
6603         function getOperations($portName = '', $bindingType = 'soap') {
6604                 $ops = array();
6605                 if ($bindingType == 'soap') {
6606                         $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/';
6607                 } elseif ($bindingType == 'soap12') {
6608                         $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/';
6609                 } else {
6610                         $this->debug("getOperations bindingType $bindingType may not be supported");
6611                 }
6612                 $this->debug("getOperations for port '$portName' bindingType $bindingType");
6613                 // loop thru ports
6614                 foreach($this->ports as $port => $portData) {
6615                         $this->debug("getOperations checking port $port bindingType " . $portData['bindingType']);
6616                         if ($portName == '' || $port == $portName) {
6617                                 // binding type of port matches parameter
6618                                 if ($portData['bindingType'] == $bindingType) {
6619                                         $this->debug("getOperations found port $port bindingType $bindingType");
6620                                         //$this->debug("port data: " . $this->varDump($portData));
6621                                         //$this->debug("bindings: " . $this->varDump($this->bindings[ $portData['binding'] ]));
6622                                         // merge bindings
6623                                         if (isset($this->bindings[ $portData['binding'] ]['operations'])) {
6624                                                 $ops = array_merge ($ops, $this->bindings[ $portData['binding'] ]['operations']);
6625                                         }
6626                                 }
6627                         }
6628                 }
6629                 if (count($ops) == 0) {
6630                         $this->debug("getOperations found no operations for port '$portName' bindingType $bindingType");
6631                 }
6632                 return $ops;
6633         } 
6634         
6635         /**
6636          * returns an associative array of data necessary for calling an operation
6637          * 
6638          * @param string $operation name of operation
6639          * @param string $bindingType type of binding eg: soap, soap12
6640          * @return array 
6641          * @access public 
6642          */
6643         function getOperationData($operation, $bindingType = 'soap')
6644         {
6645                 if ($bindingType == 'soap') {
6646                         $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/';
6647                 } elseif ($bindingType == 'soap12') {
6648                         $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/';
6649                 }
6650                 // loop thru ports
6651                 foreach($this->ports as $port => $portData) {
6652                         // binding type of port matches parameter
6653                         if ($portData['bindingType'] == $bindingType) {
6654                                 // get binding
6655                                 //foreach($this->bindings[ $portData['binding'] ]['operations'] as $bOperation => $opData) {
6656                                 foreach(array_keys($this->bindings[ $portData['binding'] ]['operations']) as $bOperation) {
6657                                         // note that we could/should also check the namespace here
6658                                         if ($operation == $bOperation) {
6659                                                 $opData = $this->bindings[ $portData['binding'] ]['operations'][$operation];
6660                                             return $opData;
6661                                         } 
6662                                 } 
6663                         }
6664                 } 
6665         }
6666         
6667         /**
6668          * returns an associative array of data necessary for calling an operation
6669          * 
6670          * @param string $soapAction soapAction for operation
6671          * @param string $bindingType type of binding eg: soap, soap12
6672          * @return array 
6673          * @access public 
6674          */
6675         function getOperationDataForSoapAction($soapAction, $bindingType = 'soap') {
6676                 if ($bindingType == 'soap') {
6677                         $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/';
6678                 } elseif ($bindingType == 'soap12') {
6679                         $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/';
6680                 }
6681                 // loop thru ports
6682                 foreach($this->ports as $port => $portData) {
6683                         // binding type of port matches parameter
6684                         if ($portData['bindingType'] == $bindingType) {
6685                                 // loop through operations for the binding
6686                                 foreach ($this->bindings[ $portData['binding'] ]['operations'] as $bOperation => $opData) {
6687                                         if ($opData['soapAction'] == $soapAction) {
6688                                             return $opData;
6689                                         } 
6690                                 } 
6691                         }
6692                 } 
6693         }
6694         
6695         /**
6696     * returns an array of information about a given type
6697     * returns false if no type exists by the given name
6698     *
6699         *        typeDef = array(
6700         *        'elements' => array(), // refs to elements array
6701         *       'restrictionBase' => '',
6702         *       'phpType' => '',
6703         *       'order' => '(sequence|all)',
6704         *       'attrs' => array() // refs to attributes array
6705         *       )
6706     *
6707     * @param string $type the type
6708     * @param string $ns namespace (not prefix) of the type
6709     * @return mixed
6710     * @access public
6711     * @see nusoap_xmlschema
6712     */
6713         function getTypeDef($type, $ns) {
6714                 $this->debug("in getTypeDef: type=$type, ns=$ns");
6715                 if ((! $ns) && isset($this->namespaces['tns'])) {
6716                         $ns = $this->namespaces['tns'];
6717                         $this->debug("in getTypeDef: type namespace forced to $ns");
6718                 }
6719                 if (!isset($this->schemas[$ns])) {
6720                         foreach ($this->schemas as $ns0 => $schema0) {
6721                                 if (strcasecmp($ns, $ns0) == 0) {
6722                                         $this->debug("in getTypeDef: replacing schema namespace $ns with $ns0");
6723                                         $ns = $ns0;
6724                                         break;
6725                                 }
6726                         }
6727                 }
6728                 if (isset($this->schemas[$ns])) {
6729                         $this->debug("in getTypeDef: have schema for namespace $ns");
6730                         for ($i = 0; $i < count($this->schemas[$ns]); $i++) {
6731                                 $xs = &$this->schemas[$ns][$i];
6732                                 $t = $xs->getTypeDef($type);
6733                                 $this->appendDebug($xs->getDebug());
6734                                 $xs->clearDebug();
6735                                 if ($t) {
6736                                         $this->debug("in getTypeDef: found type $type");
6737                                         if (!isset($t['phpType'])) {
6738                                                 // get info for type to tack onto the element
6739                                                 $uqType = substr($t['type'], strrpos($t['type'], ':') + 1);
6740                                                 $ns = substr($t['type'], 0, strrpos($t['type'], ':'));
6741                                                 $etype = $this->getTypeDef($uqType, $ns);
6742                                                 if ($etype) {
6743                                                         $this->debug("found type for [element] $type:");
6744                                                         $this->debug($this->varDump($etype));
6745                                                         if (isset($etype['phpType'])) {
6746                                                                 $t['phpType'] = $etype['phpType'];
6747                                                         }
6748                                                         if (isset($etype['elements'])) {
6749                                                                 $t['elements'] = $etype['elements'];
6750                                                         }
6751                                                         if (isset($etype['attrs'])) {
6752                                                                 $t['attrs'] = $etype['attrs'];
6753                                                         }
6754                                                 } else {
6755                                                         $this->debug("did not find type for [element] $type");
6756                                                 }
6757                                         }
6758                                         return $t;
6759                                 }
6760                         }
6761                         $this->debug("in getTypeDef: did not find type $type");
6762                 } else {
6763                         $this->debug("in getTypeDef: do not have schema for namespace $ns");
6764                 }
6765                 return false;
6766         }
6767
6768     /**
6769     * prints html description of services
6770     *
6771     * @access private
6772     */
6773     function webDescription(){
6774         global $HTTP_SERVER_VARS;
6775
6776                 if (isset($_SERVER)) {
6777                         $PHP_SELF = $_SERVER['PHP_SELF'];
6778                 } elseif (isset($HTTP_SERVER_VARS)) {
6779                         $PHP_SELF = $HTTP_SERVER_VARS['PHP_SELF'];
6780                 } else {
6781                         $this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available");
6782                 }
6783
6784                 $b = '
6785                 <html><head><title>NuSOAP: '.$this->serviceName.'</title>
6786                 <style type="text/css">
6787                     body    { font-family: arial; color: #000000; background-color: #ffffff; margin: 0px 0px 0px 0px; }
6788                     p       { font-family: arial; color: #000000; margin-top: 0px; margin-bottom: 12px; }
6789                     pre { background-color: silver; padding: 5px; font-family: Courier New; font-size: x-small; color: #000000;}
6790                     ul      { margin-top: 10px; margin-left: 20px; }
6791                     li      { list-style-type: none; margin-top: 10px; color: #000000; }
6792                     .content{
6793                         margin-left: 0px; padding-bottom: 2em; }
6794                     .nav {
6795                         padding-top: 10px; padding-bottom: 10px; padding-left: 15px; font-size: .70em;
6796                         margin-top: 10px; margin-left: 0px; color: #000000;
6797                         background-color: #ccccff; width: 20%; margin-left: 20px; margin-top: 20px; }
6798                     .title {
6799                         font-family: arial; font-size: 26px; color: #ffffff;
6800                         background-color: #999999; width: 100%;
6801                         margin-left: 0px; margin-right: 0px;
6802                         padding-top: 10px; padding-bottom: 10px;}
6803                     .hidden {
6804                         position: absolute; visibility: hidden; z-index: 200; left: 250px; top: 100px;
6805                         font-family: arial; overflow: hidden; width: 600;
6806                         padding: 20px; font-size: 10px; background-color: #999999;
6807                         layer-background-color:#FFFFFF; }
6808                     a,a:active  { color: charcoal; font-weight: bold; }
6809                     a:visited   { color: #666666; font-weight: bold; }
6810                     a:hover     { color: cc3300; font-weight: bold; }
6811                 </style>
6812                 <script language="JavaScript" type="text/javascript">
6813                 <!--
6814                 // POP-UP CAPTIONS...
6815                 function lib_bwcheck(){ //Browsercheck (needed)
6816                     this.ver=navigator.appVersion
6817                     this.agent=navigator.userAgent
6818                     this.dom=document.getElementById?1:0
6819                     this.opera5=this.agent.indexOf("Opera 5")>-1
6820                     this.ie5=(this.ver.indexOf("MSIE 5")>-1 && this.dom && !this.opera5)?1:0;
6821                     this.ie6=(this.ver.indexOf("MSIE 6")>-1 && this.dom && !this.opera5)?1:0;
6822                     this.ie4=(document.all && !this.dom && !this.opera5)?1:0;
6823                     this.ie=this.ie4||this.ie5||this.ie6
6824                     this.mac=this.agent.indexOf("Mac")>-1
6825                     this.ns6=(this.dom && parseInt(this.ver) >= 5) ?1:0;
6826                     this.ns4=(document.layers && !this.dom)?1:0;
6827                     this.bw=(this.ie6 || this.ie5 || this.ie4 || this.ns4 || this.ns6 || this.opera5)
6828                     return this
6829                 }
6830                 var bw = new lib_bwcheck()
6831                 //Makes crossbrowser object.
6832                 function makeObj(obj){
6833                     this.evnt=bw.dom? document.getElementById(obj):bw.ie4?document.all[obj]:bw.ns4?document.layers[obj]:0;
6834                     if(!this.evnt) return false
6835                     this.css=bw.dom||bw.ie4?this.evnt.style:bw.ns4?this.evnt:0;
6836                     this.wref=bw.dom||bw.ie4?this.evnt:bw.ns4?this.css.document:0;
6837                     this.writeIt=b_writeIt;
6838                     return this
6839                 }
6840                 // A unit of measure that will be added when setting the position of a layer.
6841                 //var px = bw.ns4||window.opera?"":"px";
6842                 function b_writeIt(text){
6843                     if (bw.ns4){this.wref.write(text);this.wref.close()}
6844                     else this.wref.innerHTML = text
6845                 }
6846                 //Shows the messages
6847                 var oDesc;
6848                 function popup(divid){
6849                     if(oDesc = new makeObj(divid)){
6850                         oDesc.css.visibility = "visible"
6851                     }
6852                 }
6853                 function popout(){ // Hides message
6854                     if(oDesc) oDesc.css.visibility = "hidden"
6855                 }
6856                 //-->
6857                 </script>
6858                 </head>
6859                 <body>
6860                 <div class=content>
6861                         <br><br>
6862                         <div class=title>'.$this->serviceName.'</div>
6863                         <div class=nav>
6864                                 <p>View the <a href="'.$PHP_SELF.'?wsdl">WSDL</a> for the service.
6865                                 Click on an operation name to view it&apos;s details.</p>
6866                                 <ul>';
6867                                 foreach($this->getOperations() as $op => $data){
6868                                     $b .= "<li><a href='#' onclick=\"popout();popup('$op')\">$op</a></li>";
6869                                     // create hidden div
6870                                     $b .= "<div id='$op' class='hidden'>
6871                                     <a href='#' onclick='popout()'><font color='#ffffff'>Close</font></a><br><br>";
6872                                     foreach($data as $donnie => $marie){ // loop through opdata
6873                                                 if($donnie == 'input' || $donnie == 'output'){ // show input/output data
6874                                                     $b .= "<font color='white'>".ucfirst($donnie).':</font><br>';
6875                                                     foreach($marie as $captain => $tenille){ // loop through data
6876                                                                 if($captain == 'parts'){ // loop thru parts
6877                                                                     $b .= "&nbsp;&nbsp;$captain:<br>";
6878                                                         //if(is_array($tenille)){
6879                                                                         foreach($tenille as $joanie => $chachi){
6880                                                                                         $b .= "&nbsp;&nbsp;&nbsp;&nbsp;$joanie: $chachi<br>";
6881                                                                         }
6882                                                                 //}
6883                                                                 } else {
6884                                                                     $b .= "&nbsp;&nbsp;$captain: $tenille<br>";
6885                                                                 }
6886                                                     }
6887                                                 } else {
6888                                                     $b .= "<font color='white'>".ucfirst($donnie).":</font> $marie<br>";
6889                                                 }
6890                                     }
6891                                         $b .= '</div>';
6892                                 }
6893                                 $b .= '
6894                                 <ul>
6895                         </div>
6896                 </div></body></html>';
6897                 return $b;
6898     }
6899
6900         /**
6901         * serialize the parsed wsdl
6902         *
6903         * @param mixed $debug whether to put debug=1 in endpoint URL
6904         * @return string serialization of WSDL
6905         * @access public 
6906         */
6907         function serialize($debug = 0)
6908         {
6909                 $xml = '<?xml version="1.0" encoding="ISO-8859-1"?>';
6910                 $xml .= "\n<definitions";
6911                 foreach($this->namespaces as $k => $v) {
6912                         $xml .= " xmlns:$k=\"$v\"";
6913                 } 
6914                 // 10.9.02 - add poulter fix for wsdl and tns declarations
6915                 if (isset($this->namespaces['wsdl'])) {
6916                         $xml .= " xmlns=\"" . $this->namespaces['wsdl'] . "\"";
6917                 } 
6918                 if (isset($this->namespaces['tns'])) {
6919                         $xml .= " targetNamespace=\"" . $this->namespaces['tns'] . "\"";
6920                 } 
6921                 $xml .= '>'; 
6922                 // imports
6923                 if (sizeof($this->import) > 0) {
6924                         foreach($this->import as $ns => $list) {
6925                                 foreach ($list as $ii) {
6926                                         if ($ii['location'] != '') {
6927                                                 $xml .= '<import location="' . $ii['location'] . '" namespace="' . $ns . '" />';
6928                                         } else {
6929                                                 $xml .= '<import namespace="' . $ns . '" />';
6930                                         }
6931                                 }
6932                         } 
6933                 } 
6934                 // types
6935                 if (count($this->schemas)>=1) {
6936                         $xml .= "\n<types>\n";
6937                         foreach ($this->schemas as $ns => $list) {
6938                                 foreach ($list as $xs) {
6939                                         $xml .= $xs->serializeSchema();
6940                                 }
6941                         }
6942                         $xml .= '</types>';
6943                 } 
6944                 // messages
6945                 if (count($this->messages) >= 1) {
6946                         foreach($this->messages as $msgName => $msgParts) {
6947                                 $xml .= "\n<message name=\"" . $msgName . '">';
6948                                 if(is_array($msgParts)){
6949                                         foreach($msgParts as $partName => $partType) {
6950                                                 // print 'serializing '.$partType.', sv: '.$this->XMLSchemaVersion.'<br>';
6951                                                 if (strpos($partType, ':')) {
6952                                                     $typePrefix = $this->getPrefixFromNamespace($this->getPrefix($partType));
6953                                                 } elseif (isset($this->typemap[$this->namespaces['xsd']][$partType])) {
6954                                                     // print 'checking typemap: '.$this->XMLSchemaVersion.'<br>';
6955                                                     $typePrefix = 'xsd';
6956                                                 } else {
6957                                                     foreach($this->typemap as $ns => $types) {
6958                                                         if (isset($types[$partType])) {
6959                                                             $typePrefix = $this->getPrefixFromNamespace($ns);
6960                                                         } 
6961                                                     } 
6962                                                     if (!isset($typePrefix)) {
6963                                                         die("$partType has no namespace!");
6964                                                     } 
6965                                                 }
6966                                                 $ns = $this->getNamespaceFromPrefix($typePrefix);
6967                                                 $localPart = $this->getLocalPart($partType);
6968                                                 $typeDef = $this->getTypeDef($localPart, $ns);
6969                                                 if ($typeDef['typeClass'] == 'element') {
6970                                                         $elementortype = 'element';
6971                                                         if (substr($localPart, -1) == '^') {
6972                                                                 $localPart = substr($localPart, 0, -1);
6973                                                         }
6974                                                 } else {
6975                                                         $elementortype = 'type';
6976                                                 }
6977                                                 $xml .= "\n" . '  <part name="' . $partName . '" ' . $elementortype . '="' . $typePrefix . ':' . $localPart . '" />';
6978                                         }
6979                                 }
6980                                 $xml .= '</message>';
6981                         } 
6982                 } 
6983                 // bindings & porttypes
6984                 if (count($this->bindings) >= 1) {
6985                         $binding_xml = '';
6986                         $portType_xml = '';
6987                         foreach($this->bindings as $bindingName => $attrs) {
6988                                 $binding_xml .= "\n<binding name=\"" . $bindingName . '" type="tns:' . $attrs['portType'] . '">';
6989                                 $binding_xml .= "\n" . '  <soap:binding style="' . $attrs['style'] . '" transport="' . $attrs['transport'] . '"/>';
6990                                 $portType_xml .= "\n<portType name=\"" . $attrs['portType'] . '">';
6991                                 foreach($attrs['operations'] as $opName => $opParts) {
6992                                         $binding_xml .= "\n" . '  <operation name="' . $opName . '">';
6993                                         $binding_xml .= "\n" . '    <soap:operation soapAction="' . $opParts['soapAction'] . '" style="'. $opParts['style'] . '"/>';
6994                                         if (isset($opParts['input']['encodingStyle']) && $opParts['input']['encodingStyle'] != '') {
6995                                                 $enc_style = ' encodingStyle="' . $opParts['input']['encodingStyle'] . '"';
6996                                         } else {
6997                                                 $enc_style = '';
6998                                         }
6999                                         $binding_xml .= "\n" . '    <input><soap:body use="' . $opParts['input']['use'] . '" namespace="' . $opParts['input']['namespace'] . '"' . $enc_style . '/></input>';
7000                                         if (isset($opParts['output']['encodingStyle']) && $opParts['output']['encodingStyle'] != '') {
7001                                                 $enc_style = ' encodingStyle="' . $opParts['output']['encodingStyle'] . '"';
7002                                         } else {
7003                                                 $enc_style = '';
7004                                         }
7005                                         $binding_xml .= "\n" . '    <output><soap:body use="' . $opParts['output']['use'] . '" namespace="' . $opParts['output']['namespace'] . '"' . $enc_style . '/></output>';
7006                                         $binding_xml .= "\n" . '  </operation>';
7007                                         $portType_xml .= "\n" . '  <operation name="' . $opParts['name'] . '"';
7008                                         if (isset($opParts['parameterOrder'])) {
7009                                             $portType_xml .= ' parameterOrder="' . $opParts['parameterOrder'] . '"';
7010                                         } 
7011                                         $portType_xml .= '>';
7012                                         if(isset($opParts['documentation']) && $opParts['documentation'] != '') {
7013                                                 $portType_xml .= "\n" . '    <documentation>' . htmlspecialchars($opParts['documentation']) . '</documentation>';
7014                                         }
7015                                         $portType_xml .= "\n" . '    <input message="tns:' . $opParts['input']['message'] . '"/>';
7016                                         $portType_xml .= "\n" . '    <output message="tns:' . $opParts['output']['message'] . '"/>';
7017                                         $portType_xml .= "\n" . '  </operation>';
7018                                 } 
7019                                 $portType_xml .= "\n" . '</portType>';
7020                                 $binding_xml .= "\n" . '</binding>';
7021                         } 
7022                         $xml .= $portType_xml . $binding_xml;
7023                 } 
7024                 // services
7025                 $xml .= "\n<service name=\"" . $this->serviceName . '">';
7026                 if (count($this->ports) >= 1) {
7027                         foreach($this->ports as $pName => $attrs) {
7028                                 $xml .= "\n" . '  <port name="' . $pName . '" binding="tns:' . $attrs['binding'] . '">';
7029                                 $xml .= "\n" . '    <soap:address location="' . $attrs['location'] . ($debug ? '?debug=1' : '') . '"/>';
7030                                 $xml .= "\n" . '  </port>';
7031                         } 
7032                 } 
7033                 $xml .= "\n" . '</service>';
7034                 return $xml . "\n</definitions>";
7035         } 
7036
7037         /**
7038          * determine whether a set of parameters are unwrapped
7039          * when they are expect to be wrapped, Microsoft-style.
7040          *
7041          * @param string $type the type (element name) of the wrapper
7042          * @param array $parameters the parameter values for the SOAP call
7043          * @return boolean whether they parameters are unwrapped (and should be wrapped)
7044          * @access private
7045          */
7046         function parametersMatchWrapped($type, &$parameters) {
7047                 $this->debug("in parametersMatchWrapped type=$type, parameters=");
7048                 $this->appendDebug($this->varDump($parameters));
7049
7050                 // split type into namespace:unqualified-type
7051                 if (strpos($type, ':')) {
7052                         $uqType = substr($type, strrpos($type, ':') + 1);
7053                         $ns = substr($type, 0, strrpos($type, ':'));
7054                         $this->debug("in parametersMatchWrapped: got a prefixed type: $uqType, $ns");
7055                         if ($this->getNamespaceFromPrefix($ns)) {
7056                                 $ns = $this->getNamespaceFromPrefix($ns);
7057                                 $this->debug("in parametersMatchWrapped: expanded prefixed type: $uqType, $ns");
7058                         }
7059                 } else {
7060                         // TODO: should the type be compared to types in XSD, and the namespace
7061                         // set to XSD if the type matches?
7062                         $this->debug("in parametersMatchWrapped: No namespace for type $type");
7063                         $ns = '';
7064                         $uqType = $type;
7065                 }
7066
7067                 // get the type information
7068                 if (!$typeDef = $this->getTypeDef($uqType, $ns)) {
7069                         $this->debug("in parametersMatchWrapped: $type ($uqType) is not a supported type.");
7070                         return false;
7071                 }
7072                 $this->debug("in parametersMatchWrapped: found typeDef=");
7073                 $this->appendDebug($this->varDump($typeDef));
7074                 if (substr($uqType, -1) == '^') {
7075                         $uqType = substr($uqType, 0, -1);
7076                 }
7077                 $phpType = $typeDef['phpType'];
7078                 $arrayType = (isset($typeDef['arrayType']) ? $typeDef['arrayType'] : '');
7079                 $this->debug("in parametersMatchWrapped: uqType: $uqType, ns: $ns, phptype: $phpType, arrayType: $arrayType");
7080                 
7081                 // we expect a complexType or element of complexType
7082                 if ($phpType != 'struct') {
7083                         $this->debug("in parametersMatchWrapped: not a struct");
7084                         return false;
7085                 }
7086
7087                 // see whether the parameter names match the elements
7088                 if (isset($typeDef['elements']) && is_array($typeDef['elements'])) {
7089                         $elements = 0;
7090                         $matches = 0;
7091                         foreach ($typeDef['elements'] as $name => $attrs) {
7092                                 if (isset($parameters[$name])) {
7093                                         $this->debug("in parametersMatchWrapped: have parameter named $name");
7094                                         $matches++;
7095                                 } else {
7096                                         $this->debug("in parametersMatchWrapped: do not have parameter named $name");
7097                                 }
7098                                 $elements++;
7099                         }
7100
7101                         $this->debug("in parametersMatchWrapped: $matches parameter names match $elements wrapped parameter names");
7102                         if ($matches == 0) {
7103                                 return false;
7104                         }
7105                         return true;
7106                 }
7107
7108                 // since there are no elements for the type, if the user passed no
7109                 // parameters, the parameters match wrapped.
7110                 $this->debug("in parametersMatchWrapped: no elements type $ns:$uqType");
7111                 return count($parameters) == 0;
7112         }
7113
7114         /**
7115          * serialize PHP values according to a WSDL message definition
7116          * contrary to the method name, this is not limited to RPC
7117          *
7118          * TODO
7119          * - multi-ref serialization
7120          * - validate PHP values against type definitions, return errors if invalid
7121          * 
7122          * @param string $operation operation name
7123          * @param string $direction (input|output)
7124          * @param mixed $parameters parameter value(s)
7125          * @param string $bindingType (soap|soap12)
7126          * @return mixed parameters serialized as XML or false on error (e.g. operation not found)
7127          * @access public
7128          */
7129         function serializeRPCParameters($operation, $direction, $parameters, $bindingType = 'soap') {
7130                 $this->debug("in serializeRPCParameters: operation=$operation, direction=$direction, XMLSchemaVersion=$this->XMLSchemaVersion, bindingType=$bindingType");
7131                 $this->appendDebug('parameters=' . $this->varDump($parameters));
7132                 
7133                 if ($direction != 'input' && $direction != 'output') {
7134                         $this->debug('The value of the \$direction argument needs to be either "input" or "output"');
7135                         $this->setError('The value of the \$direction argument needs to be either "input" or "output"');
7136                         return false;
7137                 } 
7138                 if (!$opData = $this->getOperationData($operation, $bindingType)) {
7139                         $this->debug('Unable to retrieve WSDL data for operation: ' . $operation . ' bindingType: ' . $bindingType);
7140                         $this->setError('Unable to retrieve WSDL data for operation: ' . $operation . ' bindingType: ' . $bindingType);
7141                         return false;
7142                 }
7143                 $this->debug('in serializeRPCParameters: opData:');
7144                 $this->appendDebug($this->varDump($opData));
7145
7146                 // Get encoding style for output and set to current
7147                 $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
7148                 if(($direction == 'input') && isset($opData['output']['encodingStyle']) && ($opData['output']['encodingStyle'] != $encodingStyle)) {
7149                         $encodingStyle = $opData['output']['encodingStyle'];
7150                         $enc_style = $encodingStyle;
7151                 }
7152
7153                 // set input params
7154                 $xml = '';
7155                 if (isset($opData[$direction]['parts']) && sizeof($opData[$direction]['parts']) > 0) {
7156                         $parts = &$opData[$direction]['parts'];
7157                         $part_count = sizeof($parts);
7158                         $style = $opData['style'];
7159                         $use = $opData[$direction]['use'];
7160                         $this->debug("have $part_count part(s) to serialize using $style/$use");
7161                         if (is_array($parameters)) {
7162                                 $parametersArrayType = $this->isArraySimpleOrStruct($parameters);
7163                                 $parameter_count = count($parameters);
7164                                 $this->debug("have $parameter_count parameter(s) provided as $parametersArrayType to serialize");
7165                                 // check for Microsoft-style wrapped parameters
7166                                 if ($style == 'document' && $use == 'literal' && $part_count == 1 && isset($parts['parameters'])) {
7167                                         $this->debug('check whether the caller has wrapped the parameters');
7168                                         if ($direction == 'output' && $parametersArrayType == 'arraySimple' && $parameter_count == 1) {
7169                                                 // TODO: consider checking here for double-wrapping, when
7170                                                 // service function wraps, then NuSOAP wraps again
7171                                                 $this->debug("change simple array to associative with 'parameters' element");
7172                                                 $parameters['parameters'] = $parameters[0];
7173                                                 unset($parameters[0]);
7174                                         }
7175                                         if (($parametersArrayType == 'arrayStruct' || $parameter_count == 0) && !isset($parameters['parameters'])) {
7176                                                 $this->debug('check whether caller\'s parameters match the wrapped ones');
7177                                                 if ($this->parametersMatchWrapped($parts['parameters'], $parameters)) {
7178                                                         $this->debug('wrap the parameters for the caller');
7179                                                         $parameters = array('parameters' => $parameters);
7180                                                         $parameter_count = 1;
7181                                                 }
7182                                         }
7183                                 }
7184                                 foreach ($parts as $name => $type) {
7185                                         $this->debug("serializing part $name of type $type");
7186                                         // Track encoding style
7187                                         if (isset($opData[$direction]['encodingStyle']) && $encodingStyle != $opData[$direction]['encodingStyle']) {
7188                                                 $encodingStyle = $opData[$direction]['encodingStyle'];                  
7189                                                 $enc_style = $encodingStyle;
7190                                         } else {
7191                                                 $enc_style = false;
7192                                         }
7193                                         // NOTE: add error handling here
7194                                         // if serializeType returns false, then catch global error and fault
7195                                         if ($parametersArrayType == 'arraySimple') {
7196                                                 $p = array_shift($parameters);
7197                                                 $this->debug('calling serializeType w/indexed param');
7198                                                 $xml .= $this->serializeType($name, $type, $p, $use, $enc_style);
7199                                         } elseif (isset($parameters[$name])) {
7200                                                 $this->debug('calling serializeType w/named param');
7201                                                 $xml .= $this->serializeType($name, $type, $parameters[$name], $use, $enc_style);
7202                                         } else {
7203                                                 // TODO: only send nillable
7204                                                 $this->debug('calling serializeType w/null param');
7205                                                 $xml .= $this->serializeType($name, $type, null, $use, $enc_style);
7206                                         }
7207                                 }
7208                         } else {
7209                                 $this->debug('no parameters passed.');
7210                         }
7211                 }
7212                 $this->debug("serializeRPCParameters returning: $xml");
7213                 return $xml;
7214         } 
7215         
7216         /**
7217          * serialize a PHP value according to a WSDL message definition
7218          * 
7219          * TODO
7220          * - multi-ref serialization
7221          * - validate PHP values against type definitions, return errors if invalid
7222          * 
7223          * @param string $operation operation name
7224          * @param string $direction (input|output)
7225          * @param mixed $parameters parameter value(s)
7226          * @return mixed parameters serialized as XML or false on error (e.g. operation not found)
7227          * @access public
7228          * @deprecated
7229          */
7230         function serializeParameters($operation, $direction, $parameters)
7231         {
7232                 $this->debug("in serializeParameters: operation=$operation, direction=$direction, XMLSchemaVersion=$this->XMLSchemaVersion"); 
7233                 $this->appendDebug('parameters=' . $this->varDump($parameters));
7234                 
7235                 if ($direction != 'input' && $direction != 'output') {
7236                         $this->debug('The value of the \$direction argument needs to be either "input" or "output"');
7237                         $this->setError('The value of the \$direction argument needs to be either "input" or "output"');
7238                         return false;
7239                 } 
7240                 if (!$opData = $this->getOperationData($operation)) {
7241                         $this->debug('Unable to retrieve WSDL data for operation: ' . $operation);
7242                         $this->setError('Unable to retrieve WSDL data for operation: ' . $operation);
7243                         return false;
7244                 }
7245                 $this->debug('opData:');
7246                 $this->appendDebug($this->varDump($opData));
7247                 
7248                 // Get encoding style for output and set to current
7249                 $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
7250                 if(($direction == 'input') && isset($opData['output']['encodingStyle']) && ($opData['output']['encodingStyle'] != $encodingStyle)) {
7251                         $encodingStyle = $opData['output']['encodingStyle'];
7252                         $enc_style = $encodingStyle;
7253                 }
7254                 
7255                 // set input params
7256                 $xml = '';
7257                 if (isset($opData[$direction]['parts']) && sizeof($opData[$direction]['parts']) > 0) {
7258                         
7259                         $use = $opData[$direction]['use'];
7260                         $this->debug("use=$use");
7261                         $this->debug('got ' . count($opData[$direction]['parts']) . ' part(s)');
7262                         if (is_array($parameters)) {
7263                                 $parametersArrayType = $this->isArraySimpleOrStruct($parameters);
7264                                 $this->debug('have ' . $parametersArrayType . ' parameters');
7265                                 foreach($opData[$direction]['parts'] as $name => $type) {
7266                                         $this->debug('serializing part "'.$name.'" of type "'.$type.'"');
7267                                         // Track encoding style
7268                                         if(isset($opData[$direction]['encodingStyle']) && $encodingStyle != $opData[$direction]['encodingStyle']) {
7269                                                 $encodingStyle = $opData[$direction]['encodingStyle'];                  
7270                                                 $enc_style = $encodingStyle;
7271                                         } else {
7272                                                 $enc_style = false;
7273                                         }
7274                                         // NOTE: add error handling here
7275                                         // if serializeType returns false, then catch global error and fault
7276                                         if ($parametersArrayType == 'arraySimple') {
7277                                                 $p = array_shift($parameters);
7278                                                 $this->debug('calling serializeType w/indexed param');
7279                                                 $xml .= $this->serializeType($name, $type, $p, $use, $enc_style);
7280                                         } elseif (isset($parameters[$name])) {
7281                                                 $this->debug('calling serializeType w/named param');
7282                                                 $xml .= $this->serializeType($name, $type, $parameters[$name], $use, $enc_style);
7283                                         } else {
7284                                                 // TODO: only send nillable
7285                                                 $this->debug('calling serializeType w/null param');
7286                                                 $xml .= $this->serializeType($name, $type, null, $use, $enc_style);
7287                                         }
7288                                 }
7289                         } else {
7290                                 $this->debug('no parameters passed.');
7291                         }
7292                 }
7293                 $this->debug("serializeParameters returning: $xml");
7294                 return $xml;
7295         } 
7296         
7297         /**
7298          * serializes a PHP value according a given type definition
7299          * 
7300          * @param string $name name of value (part or element)
7301          * @param string $type XML schema type of value (type or element)
7302          * @param mixed $value a native PHP value (parameter value)
7303          * @param string $use use for part (encoded|literal)
7304          * @param string $encodingStyle SOAP encoding style for the value (if different than the enclosing style)
7305          * @param boolean $unqualified a kludge for what should be XML namespace form handling
7306          * @return string value serialized as an XML string
7307          * @access private
7308          */
7309         function serializeType($name, $type, $value, $use='encoded', $encodingStyle=false, $unqualified=false)
7310         {
7311                 $this->debug("in serializeType: name=$name, type=$type, use=$use, encodingStyle=$encodingStyle, unqualified=" . ($unqualified ? "unqualified" : "qualified"));
7312                 $this->appendDebug("value=" . $this->varDump($value));
7313                 if($use == 'encoded' && $encodingStyle) {
7314                         $encodingStyle = ' SOAP-ENV:encodingStyle="' . $encodingStyle . '"';
7315                 }
7316
7317                 // if a soapval has been supplied, let its type override the WSDL
7318         if (is_object($value) && get_class($value) == 'soapval') {
7319                 if ($value->type_ns) {
7320                         $type = $value->type_ns . ':' . $value->type;
7321                         $forceType = true;
7322                         $this->debug("in serializeType: soapval overrides type to $type");
7323                 } elseif ($value->type) {
7324                         $type = $value->type;
7325                         $forceType = true;
7326                         $this->debug("in serializeType: soapval overrides type to $type");
7327                 } else {
7328                         $forceType = false;
7329                         $this->debug("in serializeType: soapval does not override type");
7330                 }
7331                 $attrs = $value->attributes;
7332                 $value = $value->value;
7333                 $this->debug("in serializeType: soapval overrides value to $value");
7334                 if ($attrs) {
7335                         if (!is_array($value)) {
7336                                 $value['!'] = $value;
7337                         }
7338                         foreach ($attrs as $n => $v) {
7339                                 $value['!' . $n] = $v;
7340                         }
7341                         $this->debug("in serializeType: soapval provides attributes");
7342                     }
7343         } else {
7344                 $forceType = false;
7345         }
7346
7347                 $xml = '';
7348                 if (strpos($type, ':')) {
7349                         $uqType = substr($type, strrpos($type, ':') + 1);
7350                         $ns = substr($type, 0, strrpos($type, ':'));
7351                         $this->debug("in serializeType: got a prefixed type: $uqType, $ns");
7352                         if ($this->getNamespaceFromPrefix($ns)) {
7353                                 $ns = $this->getNamespaceFromPrefix($ns);
7354                                 $this->debug("in serializeType: expanded prefixed type: $uqType, $ns");
7355                         }
7356
7357                         if($ns == $this->XMLSchemaVersion || $ns == 'http://schemas.xmlsoap.org/soap/encoding/'){
7358                                 $this->debug('in serializeType: type namespace indicates XML Schema or SOAP Encoding type');
7359                                 if ($unqualified && $use == 'literal') {
7360                                         $elementNS = " xmlns=\"\"";
7361                                 } else {
7362                                         $elementNS = '';
7363                                 }
7364                                 if (is_null($value)) {
7365                                         if ($use == 'literal') {
7366                                                 // TODO: depends on minOccurs
7367                                                 $xml = "<$name$elementNS/>";
7368                                         } else {
7369                                                 // TODO: depends on nillable, which should be checked before calling this method
7370                                                 $xml = "<$name$elementNS xsi:nil=\"true\" xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"/>";
7371                                         }
7372                                         $this->debug("in serializeType: returning: $xml");
7373                                         return $xml;
7374                                 }
7375                                 if ($uqType == 'Array') {
7376                                         // JBoss/Axis does this sometimes
7377                                         return $this->serialize_val($value, $name, false, false, false, false, $use);
7378                                 }
7379                         if ($uqType == 'boolean') {
7380                                 if ((is_string($value) && $value == 'false') || (! $value)) {
7381                                                 $value = 'false';
7382                                         } else {
7383                                                 $value = 'true';
7384                                         }
7385                                 } 
7386                                 if ($uqType == 'string' && gettype($value) == 'string') {
7387                                         $value = $this->expandEntities($value);
7388                                 }
7389                                 if (($uqType == 'long' || $uqType == 'unsignedLong') && gettype($value) == 'double') {
7390                                         $value = sprintf("%.0lf", $value);
7391                                 }
7392                                 // it's a scalar
7393                                 // TODO: what about null/nil values?
7394                                 // check type isn't a custom type extending xmlschema namespace
7395                                 if (!$this->getTypeDef($uqType, $ns)) {
7396                                         if ($use == 'literal') {
7397                                                 if ($forceType) {
7398                                                         $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">$value</$name>";
7399                                                 } else {
7400                                                         $xml = "<$name$elementNS>$value</$name>";
7401                                                 }
7402                                         } else {
7403                                                 $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>$value</$name>";
7404                                         }
7405                                         $this->debug("in serializeType: returning: $xml");
7406                                         return $xml;
7407                                 }
7408                                 $this->debug('custom type extends XML Schema or SOAP Encoding namespace (yuck)');
7409                         } else if ($ns == 'http://xml.apache.org/xml-soap') {
7410                                 $this->debug('in serializeType: appears to be Apache SOAP type');
7411                                 if ($uqType == 'Map') {
7412                                         $tt_prefix = $this->getPrefixFromNamespace('http://xml.apache.org/xml-soap');
7413                                         if (! $tt_prefix) {
7414                                                 $this->debug('in serializeType: Add namespace for Apache SOAP type');
7415                                                 $tt_prefix = 'ns' . rand(1000, 9999);
7416                                                 $this->namespaces[$tt_prefix] = 'http://xml.apache.org/xml-soap';
7417                                                 // force this to be added to usedNamespaces
7418                                                 $tt_prefix = $this->getPrefixFromNamespace('http://xml.apache.org/xml-soap');
7419                                         }
7420                                         $contents = '';
7421                                         foreach($value as $k => $v) {
7422                                                 $this->debug("serializing map element: key $k, value $v");
7423                                                 $contents .= '<item>';
7424                                                 $contents .= $this->serialize_val($k,'key',false,false,false,false,$use);
7425                                                 $contents .= $this->serialize_val($v,'value',false,false,false,false,$use);
7426                                                 $contents .= '</item>';
7427                                         }
7428                                         if ($use == 'literal') {
7429                                                 if ($forceType) {
7430                                                         $xml = "<$name xsi:type=\"" . $tt_prefix . ":$uqType\">$contents</$name>";
7431                                                 } else {
7432                                                         $xml = "<$name>$contents</$name>";
7433                                                 }
7434                                         } else {
7435                                                 $xml = "<$name xsi:type=\"" . $tt_prefix . ":$uqType\"$encodingStyle>$contents</$name>";
7436                                         }
7437                                         $this->debug("in serializeType: returning: $xml");
7438                                         return $xml;
7439                                 }
7440                                 $this->debug('in serializeType: Apache SOAP type, but only support Map');
7441                         }
7442                 } else {
7443                         // TODO: should the type be compared to types in XSD, and the namespace
7444                         // set to XSD if the type matches?
7445                         $this->debug("in serializeType: No namespace for type $type");
7446                         $ns = '';
7447                         $uqType = $type;
7448                 }
7449                 if(!$typeDef = $this->getTypeDef($uqType, $ns)){
7450                         $this->setError("$type ($uqType) is not a supported type.");
7451                         $this->debug("in serializeType: $type ($uqType) is not a supported type.");
7452                         return false;
7453                 } else {
7454                         $this->debug("in serializeType: found typeDef");
7455                         $this->appendDebug('typeDef=' . $this->varDump($typeDef));
7456                         if (substr($uqType, -1) == '^') {
7457                                 $uqType = substr($uqType, 0, -1);
7458                         }
7459                 }
7460                 if (!isset($typeDef['phpType'])) {
7461                         $this->setError("$type ($uqType) has no phpType.");
7462                         $this->debug("in serializeType: $type ($uqType) has no phpType.");
7463                         return false;
7464                 }
7465                 $phpType = $typeDef['phpType'];
7466                 $this->debug("in serializeType: uqType: $uqType, ns: $ns, phptype: $phpType, arrayType: " . (isset($typeDef['arrayType']) ? $typeDef['arrayType'] : '') ); 
7467                 // if php type == struct, map value to the <all> element names
7468                 if ($phpType == 'struct') {
7469                         if (isset($typeDef['typeClass']) && $typeDef['typeClass'] == 'element') {
7470                                 $elementName = $uqType;
7471                                 if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) {
7472                                         $elementNS = " xmlns=\"$ns\"";
7473                                 } else {
7474                                         $elementNS = " xmlns=\"\"";
7475                                 }
7476                         } else {
7477                                 $elementName = $name;
7478                                 if ($unqualified) {
7479                                         $elementNS = " xmlns=\"\"";
7480                                 } else {
7481                                         $elementNS = '';
7482                                 }
7483                         }
7484                         if (is_null($value)) {
7485                                 if ($use == 'literal') {
7486                                         // TODO: depends on minOccurs and nillable
7487                                         $xml = "<$elementName$elementNS/>";
7488                                 } else {
7489                                         $xml = "<$elementName$elementNS xsi:nil=\"true\" xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"/>";
7490                                 }
7491                                 $this->debug("in serializeType: returning: $xml");
7492                                 return $xml;
7493                         }
7494                         if (is_object($value)) {
7495                                 $value = get_object_vars($value);
7496                         }
7497                         if (is_array($value)) {
7498                                 $elementAttrs = $this->serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType);
7499                                 if ($use == 'literal') {
7500                                         if ($forceType) {
7501                                                 $xml = "<$elementName$elementNS$elementAttrs xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">";
7502                                         } else {
7503                                                 $xml = "<$elementName$elementNS$elementAttrs>";
7504                                         }
7505                                 } else {
7506                                         $xml = "<$elementName$elementNS$elementAttrs xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>";
7507                                 }
7508
7509                                 if (isset($typeDef['simpleContent']) && $typeDef['simpleContent'] == 'true') {
7510                                         if (isset($value['!'])) {
7511                                                 $xml .= $value['!'];
7512                                                 $this->debug("in serializeType: serialized simpleContent for type $type");
7513                                         } else {
7514                                                 $this->debug("in serializeType: no simpleContent to serialize for type $type");
7515                                         }
7516                                 } else {
7517                                         // complexContent
7518                                         $xml .= $this->serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use, $encodingStyle);
7519                                 }
7520                                 $xml .= "</$elementName>";
7521                         } else {
7522                                 $this->debug("in serializeType: phpType is struct, but value is not an array");
7523                                 $this->setError("phpType is struct, but value is not an array: see debug output for details");
7524                                 $xml = '';
7525                         }
7526                 } elseif ($phpType == 'array') {
7527                         if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) {
7528                                 $elementNS = " xmlns=\"$ns\"";
7529                         } else {
7530                                 if ($unqualified) {
7531                                         $elementNS = " xmlns=\"\"";
7532                                 } else {
7533                                         $elementNS = '';
7534                                 }
7535                         }
7536                         if (is_null($value)) {
7537                                 if ($use == 'literal') {
7538                                         // TODO: depends on minOccurs
7539                                         $xml = "<$name$elementNS/>";
7540                                 } else {
7541                                         $xml = "<$name$elementNS xsi:nil=\"true\" xsi:type=\"" .
7542                                                 $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/') .
7543                                                 ":Array\" " .
7544                                                 $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/') .
7545                                                 ':arrayType="' .
7546                                                 $this->getPrefixFromNamespace($this->getPrefix($typeDef['arrayType'])) .
7547                                                 ':' .
7548                                                 $this->getLocalPart($typeDef['arrayType'])."[0]\"/>";
7549                                 }
7550                                 $this->debug("in serializeType: returning: $xml");
7551                                 return $xml;
7552                         }
7553                         if (isset($typeDef['multidimensional'])) {
7554                                 $nv = array();
7555                                 foreach($value as $v) {
7556                                         $cols = ',' . sizeof($v);
7557                                         $nv = array_merge($nv, $v);
7558                                 } 
7559                                 $value = $nv;
7560                         } else {
7561                                 $cols = '';
7562                         } 
7563                         if (is_array($value) && sizeof($value) >= 1) {
7564                                 $rows = sizeof($value);
7565                                 $contents = '';
7566                                 foreach($value as $k => $v) {
7567                                         $this->debug("serializing array element: $k, $v of type: $typeDef[arrayType]");
7568                                         //if (strpos($typeDef['arrayType'], ':') ) {
7569                                         if (!in_array($typeDef['arrayType'],$this->typemap['http://www.w3.org/2001/XMLSchema'])) {
7570                                             $contents .= $this->serializeType('item', $typeDef['arrayType'], $v, $use);
7571                                         } else {
7572                                             $contents .= $this->serialize_val($v, 'item', $typeDef['arrayType'], null, $this->XMLSchemaVersion, false, $use);
7573                                         } 
7574                                 }
7575                         } else {
7576                                 $rows = 0;
7577                                 $contents = null;
7578                         }
7579                         // TODO: for now, an empty value will be serialized as a zero element
7580                         // array.  Revisit this when coding the handling of null/nil values.
7581                         if ($use == 'literal') {
7582                                 $xml = "<$name$elementNS>"
7583                                         .$contents
7584                                         ."</$name>";
7585                         } else {
7586                                 $xml = "<$name$elementNS xsi:type=\"".$this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/').':Array" '.
7587                                         $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/')
7588                                         .':arrayType="'
7589                                         .$this->getPrefixFromNamespace($this->getPrefix($typeDef['arrayType']))
7590                                         .":".$this->getLocalPart($typeDef['arrayType'])."[$rows$cols]\">"
7591                                         .$contents
7592                                         ."</$name>";
7593                         }
7594                 } elseif ($phpType == 'scalar') {
7595                         if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) {
7596                                 $elementNS = " xmlns=\"$ns\"";
7597                         } else {
7598                                 if ($unqualified) {
7599                                         $elementNS = " xmlns=\"\"";
7600                                 } else {
7601                                         $elementNS = '';
7602                                 }
7603                         }
7604                         if ($use == 'literal') {
7605                                 if ($forceType) {
7606                                         $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">$value</$name>";
7607                                 } else {
7608                                         $xml = "<$name$elementNS>$value</$name>";
7609                                 }
7610                         } else {
7611                                 $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>$value</$name>";
7612                         }
7613                 }
7614                 $this->debug("in serializeType: returning: $xml");
7615                 return $xml;
7616         }
7617         
7618         /**
7619          * serializes the attributes for a complexType
7620          *
7621          * @param array $typeDef our internal representation of an XML schema type (or element)
7622          * @param mixed $value a native PHP value (parameter value)
7623          * @param string $ns the namespace of the type
7624          * @param string $uqType the local part of the type
7625          * @return string value serialized as an XML string
7626          * @access private
7627          */
7628         function serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType) {
7629                 $this->debug("serializeComplexTypeAttributes for XML Schema type $ns:$uqType");
7630                 $xml = '';
7631                 if (isset($typeDef['extensionBase'])) {
7632                         $nsx = $this->getPrefix($typeDef['extensionBase']);
7633                         $uqTypex = $this->getLocalPart($typeDef['extensionBase']);
7634                         if ($this->getNamespaceFromPrefix($nsx)) {
7635                                 $nsx = $this->getNamespaceFromPrefix($nsx);
7636                         }
7637                         if ($typeDefx = $this->getTypeDef($uqTypex, $nsx)) {
7638                                 $this->debug("serialize attributes for extension base $nsx:$uqTypex");
7639                                 $xml .= $this->serializeComplexTypeAttributes($typeDefx, $value, $nsx, $uqTypex);
7640                         } else {
7641                                 $this->debug("extension base $nsx:$uqTypex is not a supported type");
7642                         }
7643                 }
7644                 if (isset($typeDef['attrs']) && is_array($typeDef['attrs'])) {
7645                         $this->debug("serialize attributes for XML Schema type $ns:$uqType");
7646                         if (is_array($value)) {
7647                                 $xvalue = $value;
7648                         } elseif (is_object($value)) {
7649                                 $xvalue = get_object_vars($value);
7650                         } else {
7651                                 $this->debug("value is neither an array nor an object for XML Schema type $ns:$uqType");
7652                                 $xvalue = array();
7653                         }
7654                         foreach ($typeDef['attrs'] as $aName => $attrs) {
7655                                 if (isset($xvalue['!' . $aName])) {
7656                                         $xname = '!' . $aName;
7657                                         $this->debug("value provided for attribute $aName with key $xname");
7658                                 } elseif (isset($xvalue[$aName])) {
7659                                         $xname = $aName;
7660                                         $this->debug("value provided for attribute $aName with key $xname");
7661                                 } elseif (isset($attrs['default'])) {
7662                                         $xname = '!' . $aName;
7663                                         $xvalue[$xname] = $attrs['default'];
7664                                         $this->debug('use default value of ' . $xvalue[$aName] . ' for attribute ' . $aName);
7665                                 } else {
7666                                         $xname = '';
7667                                         $this->debug("no value provided for attribute $aName");
7668                                 }
7669                                 if ($xname) {
7670                                         $xml .=  " $aName=\"" . $this->expandEntities($xvalue[$xname]) . "\"";
7671                                 }
7672                         } 
7673                 } else {
7674                         $this->debug("no attributes to serialize for XML Schema type $ns:$uqType");
7675                 }
7676                 return $xml;
7677         }
7678
7679         /**
7680          * serializes the elements for a complexType
7681          *
7682          * @param array $typeDef our internal representation of an XML schema type (or element)
7683          * @param mixed $value a native PHP value (parameter value)
7684          * @param string $ns the namespace of the type
7685          * @param string $uqType the local part of the type
7686          * @param string $use use for part (encoded|literal)
7687          * @param string $encodingStyle SOAP encoding style for the value (if different than the enclosing style)
7688          * @return string value serialized as an XML string
7689          * @access private
7690          */
7691         function serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use='encoded', $encodingStyle=false) {
7692                 $this->debug("in serializeComplexTypeElements for XML Schema type $ns:$uqType");
7693                 $xml = '';
7694                 if (isset($typeDef['extensionBase'])) {
7695                         $nsx = $this->getPrefix($typeDef['extensionBase']);
7696                         $uqTypex = $this->getLocalPart($typeDef['extensionBase']);
7697                         if ($this->getNamespaceFromPrefix($nsx)) {
7698                                 $nsx = $this->getNamespaceFromPrefix($nsx);
7699                         }
7700                         if ($typeDefx = $this->getTypeDef($uqTypex, $nsx)) {
7701                                 $this->debug("serialize elements for extension base $nsx:$uqTypex");
7702                                 $xml .= $this->serializeComplexTypeElements($typeDefx, $value, $nsx, $uqTypex, $use, $encodingStyle);
7703                         } else {
7704                                 $this->debug("extension base $nsx:$uqTypex is not a supported type");
7705                         }
7706                 }
7707                 if (isset($typeDef['elements']) && is_array($typeDef['elements'])) {
7708                         $this->debug("in serializeComplexTypeElements, serialize elements for XML Schema type $ns:$uqType");
7709                         if (is_array($value)) {
7710                                 $xvalue = $value;
7711                         } elseif (is_object($value)) {
7712                                 $xvalue = get_object_vars($value);
7713                         } else {
7714                                 $this->debug("value is neither an array nor an object for XML Schema type $ns:$uqType");
7715                                 $xvalue = array();
7716                         }
7717                         // toggle whether all elements are present - ideally should validate against schema
7718                         if (count($typeDef['elements']) != count($xvalue)){
7719                                 $optionals = true;
7720                         }
7721                         foreach ($typeDef['elements'] as $eName => $attrs) {
7722                                 if (!isset($xvalue[$eName])) {
7723                                         if (isset($attrs['default'])) {
7724                                                 $xvalue[$eName] = $attrs['default'];
7725                                                 $this->debug('use default value of ' . $xvalue[$eName] . ' for element ' . $eName);
7726                                         }
7727                                 }
7728                                 // if user took advantage of a minOccurs=0, then only serialize named parameters
7729                                 if (isset($optionals)
7730                                     && (!isset($xvalue[$eName])) 
7731                                         && ( (!isset($attrs['nillable'])) || $attrs['nillable'] != 'true')
7732                                         ){
7733                                         if (isset($attrs['minOccurs']) && $attrs['minOccurs'] <> '0') {
7734                                                 $this->debug("apparent error: no value provided for element $eName with minOccurs=" . $attrs['minOccurs']);
7735                                         }
7736                                         // do nothing
7737                                         $this->debug("no value provided for complexType element $eName and element is not nillable, so serialize nothing");
7738                                 } else {
7739                                         // get value
7740                                         if (isset($xvalue[$eName])) {
7741                                             $v = $xvalue[$eName];
7742                                         } else {
7743                                             $v = null;
7744                                         }
7745                                         if (isset($attrs['form'])) {
7746                                                 $unqualified = ($attrs['form'] == 'unqualified');
7747                                         } else {
7748                                                 $unqualified = false;
7749                                         }
7750                                         if (isset($attrs['maxOccurs']) && ($attrs['maxOccurs'] == 'unbounded' || $attrs['maxOccurs'] > 1) && isset($v) && is_array($v) && $this->isArraySimpleOrStruct($v) == 'arraySimple') {
7751                                                 $vv = $v;
7752                                                 foreach ($vv as $k => $v) {
7753                                                         if (isset($attrs['type']) || isset($attrs['ref'])) {
7754                                                                 // serialize schema-defined type
7755                                                             $xml .= $this->serializeType($eName, isset($attrs['type']) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified);
7756                                                         } else {
7757                                                                 // serialize generic type (can this ever really happen?)
7758                                                             $this->debug("calling serialize_val() for $v, $eName, false, false, false, false, $use");
7759                                                             $xml .= $this->serialize_val($v, $eName, false, false, false, false, $use);
7760                                                         }
7761                                                 }
7762                                         } else {
7763                                                 if (is_null($v) && isset($attrs['minOccurs']) && $attrs['minOccurs'] == '0') {
7764                                                         // do nothing
7765                                                 } elseif (is_null($v) && isset($attrs['nillable']) && $attrs['nillable'] == 'true') {
7766                                                         // TODO: serialize a nil correctly, but for now serialize schema-defined type
7767                                                     $xml .= $this->serializeType($eName, isset($attrs['type']) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified);
7768                                                 } elseif (isset($attrs['type']) || isset($attrs['ref'])) {
7769                                                         // serialize schema-defined type
7770                                                     $xml .= $this->serializeType($eName, isset($attrs['type']) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified);
7771                                                 } else {
7772                                                         // serialize generic type (can this ever really happen?)
7773                                                     $this->debug("calling serialize_val() for $v, $eName, false, false, false, false, $use");
7774                                                     $xml .= $this->serialize_val($v, $eName, false, false, false, false, $use);
7775                                                 }
7776                                         }
7777                                 }
7778                         } 
7779                 } else {
7780                         $this->debug("no elements to serialize for XML Schema type $ns:$uqType");
7781                 }
7782                 return $xml;
7783         }
7784
7785         /**
7786         * adds an XML Schema complex type to the WSDL types
7787         *
7788         * @param string $name
7789         * @param string $typeClass (complexType|simpleType|attribute)
7790         * @param string $phpType currently supported are array and struct (php assoc array)
7791         * @param string $compositor (all|sequence|choice)
7792         * @param string $restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
7793         * @param array $elements e.g. array ( name => array(name=>'',type=>'') )
7794         * @param array $attrs e.g. array(array('ref'=>'SOAP-ENC:arrayType','wsdl:arrayType'=>'xsd:string[]'))
7795         * @param string $arrayType as namespace:name (xsd:string)
7796         * @see nusoap_xmlschema
7797         * @access public
7798         */
7799         function addComplexType($name,$typeClass='complexType',$phpType='array',$compositor='',$restrictionBase='',$elements=array(),$attrs=array(),$arrayType='') {
7800                 if (count($elements) > 0) {
7801                         $eElements = array();
7802                 foreach($elements as $n => $e){
7803                     // expand each element
7804                     $ee = array();
7805                     foreach ($e as $k => $v) {
7806                             $k = strpos($k,':') ? $this->expandQname($k) : $k;
7807                             $v = strpos($v,':') ? $this->expandQname($v) : $v;
7808                             $ee[$k] = $v;
7809                         }
7810                         $eElements[$n] = $ee;
7811                 }
7812                 $elements = $eElements;
7813                 }
7814                 
7815                 if (count($attrs) > 0) {
7816                 foreach($attrs as $n => $a){
7817                     // expand each attribute
7818                     foreach ($a as $k => $v) {
7819                             $k = strpos($k,':') ? $this->expandQname($k) : $k;
7820                             $v = strpos($v,':') ? $this->expandQname($v) : $v;
7821                             $aa[$k] = $v;
7822                         }
7823                         $eAttrs[$n] = $aa;
7824                 }
7825                 $attrs = $eAttrs;
7826                 }
7827
7828                 $restrictionBase = strpos($restrictionBase,':') ? $this->expandQname($restrictionBase) : $restrictionBase;
7829                 $arrayType = strpos($arrayType,':') ? $this->expandQname($arrayType) : $arrayType;
7830
7831                 $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns'];
7832                 $this->schemas[$typens][0]->addComplexType($name,$typeClass,$phpType,$compositor,$restrictionBase,$elements,$attrs,$arrayType);
7833         }
7834
7835         /**
7836         * adds an XML Schema simple type to the WSDL types
7837         *
7838         * @param string $name
7839         * @param string $restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
7840         * @param string $typeClass (should always be simpleType)
7841         * @param string $phpType (should always be scalar)
7842         * @param array $enumeration array of values
7843         * @see nusoap_xmlschema
7844         * @access public
7845         */
7846         function addSimpleType($name, $restrictionBase='', $typeClass='simpleType', $phpType='scalar', $enumeration=array()) {
7847                 $restrictionBase = strpos($restrictionBase,':') ? $this->expandQname($restrictionBase) : $restrictionBase;
7848
7849                 $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns'];
7850                 $this->schemas[$typens][0]->addSimpleType($name, $restrictionBase, $typeClass, $phpType, $enumeration);
7851         }
7852
7853         /**
7854         * adds an element to the WSDL types
7855         *
7856         * @param array $attrs attributes that must include name and type
7857         * @see nusoap_xmlschema
7858         * @access public
7859         */
7860         function addElement($attrs) {
7861                 $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns'];
7862                 $this->schemas[$typens][0]->addElement($attrs);
7863         }
7864
7865         /**
7866         * register an operation with the server
7867         * 
7868         * @param string $name operation (method) name
7869         * @param array $in assoc array of input values: key = param name, value = param type
7870         * @param array $out assoc array of output values: key = param name, value = param type
7871         * @param string $namespace optional The namespace for the operation
7872         * @param string $soapaction optional The soapaction for the operation
7873         * @param string $style (rpc|document) optional The style for the operation Note: when 'document' is specified, parameter and return wrappers are created for you automatically
7874         * @param string $use (encoded|literal) optional The use for the parameters (cannot mix right now)
7875         * @param string $documentation optional The description to include in the WSDL
7876         * @param string $encodingStyle optional (usually 'http://schemas.xmlsoap.org/soap/encoding/' for encoded)
7877         * @access public 
7878         */
7879         function addOperation($name, $in = false, $out = false, $namespace = false, $soapaction = false, $style = 'rpc', $use = 'encoded', $documentation = '', $encodingStyle = ''){
7880                 if ($use == 'encoded' && $encodingStyle == '') {
7881                         $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
7882                 }
7883
7884                 if ($style == 'document') {
7885                         $elements = array();
7886                         foreach ($in as $n => $t) {
7887                                 $elements[$n] = array('name' => $n, 'type' => $t, 'form' => 'unqualified');
7888                         }
7889                         $this->addComplexType($name . 'RequestType', 'complexType', 'struct', 'all', '', $elements);
7890                         $this->addElement(array('name' => $name, 'type' => $name . 'RequestType'));
7891                         $in = array('parameters' => 'tns:' . $name . '^');
7892
7893                         $elements = array();
7894                         foreach ($out as $n => $t) {
7895                                 $elements[$n] = array('name' => $n, 'type' => $t, 'form' => 'unqualified');
7896                         }
7897                         $this->addComplexType($name . 'ResponseType', 'complexType', 'struct', 'all', '', $elements);
7898                         $this->addElement(array('name' => $name . 'Response', 'type' => $name . 'ResponseType', 'form' => 'qualified'));
7899                         $out = array('parameters' => 'tns:' . $name . 'Response' . '^');
7900                 }
7901
7902                 // get binding
7903                 $this->bindings[ $this->serviceName . 'Binding' ]['operations'][$name] =
7904                 array(
7905                 'name' => $name,
7906                 'binding' => $this->serviceName . 'Binding',
7907                 'endpoint' => $this->endpoint,
7908                 'soapAction' => $soapaction,
7909                 'style' => $style,
7910                 'input' => array(
7911                         'use' => $use,
7912                         'namespace' => $namespace,
7913                         'encodingStyle' => $encodingStyle,
7914                         'message' => $name . 'Request',
7915                         'parts' => $in),
7916                 'output' => array(
7917                         'use' => $use,
7918                         'namespace' => $namespace,
7919                         'encodingStyle' => $encodingStyle,
7920                         'message' => $name . 'Response',
7921                         'parts' => $out),
7922                 'namespace' => $namespace,
7923                 'transport' => 'http://schemas.xmlsoap.org/soap/http',
7924                 'documentation' => $documentation); 
7925                 // add portTypes
7926                 // add messages
7927                 if($in)
7928                 {
7929                         foreach($in as $pName => $pType)
7930                         {
7931                                 if(strpos($pType,':')) {
7932                                         $pType = $this->getNamespaceFromPrefix($this->getPrefix($pType)).":".$this->getLocalPart($pType);
7933                                 }
7934                                 $this->messages[$name.'Request'][$pName] = $pType;
7935                         }
7936                 } else {
7937             $this->messages[$name.'Request']= '0';
7938         }
7939                 if($out)
7940                 {
7941                         foreach($out as $pName => $pType)
7942                         {
7943                                 if(strpos($pType,':')) {
7944                                         $pType = $this->getNamespaceFromPrefix($this->getPrefix($pType)).":".$this->getLocalPart($pType);
7945                                 }
7946                                 $this->messages[$name.'Response'][$pName] = $pType;
7947                         }
7948                 } else {
7949             $this->messages[$name.'Response']= '0';
7950         }
7951                 return true;
7952         } 
7953 }
7954 ?><?php
7955
7956 /*
7957
7958 Modification information for LGPL compliance
7959
7960 r58622 - 2010-10-22 18:18:59 -0700 (Fri, 22 Oct 2010) - engsvnbuild - Author: lam <lam@198.18.142.201>
7961     bug 40066
7962
7963 r58361 - 2010-09-29 16:59:02 -0700 (Wed, 29 Sep 2010) - kjing - Author: Jenny Gonsalves <jenny@sugarcrm.com>
7964     Merging with maint_6_0_1 (svn merge -r 58250:58342)
7965
7966 r57813 - 2010-08-19 10:34:44 -0700 (Thu, 19 Aug 2010) - kjing - Author: John Mertic <jmertic@sugarcrm.com>
7967     Bug 39085 - When loading the opposite search panel via ajax on the ListViews, call the index action instead of the ListView action to avoid touching pre-MVC code by accident.
7968
7969 r57707 - 2010-08-10 12:26:13 -0700 (Tue, 10 Aug 2010) - kjing - Author: Stanislav Malyshev <smalyshev@gmail.com>
7970     fix SOAP calls with no parameters
7971
7972 r56990 - 2010-06-16 13:05:36 -0700 (Wed, 16 Jun 2010) - kjing - snapshot "Mango" svn branch to a new one for GitHub sync
7973
7974 r56989 - 2010-06-16 13:01:33 -0700 (Wed, 16 Jun 2010) - kjing - defunt "Mango" svn dev branch before github cutover
7975
7976 r55980 - 2010-04-19 13:31:28 -0700 (Mon, 19 Apr 2010) - kjing - create Mango (6.1) based on windex
7977
7978 r51719 - 2009-10-22 10:18:00 -0700 (Thu, 22 Oct 2009) - mitani - Converted to Build 3  tags and updated the build system 
7979
7980 r51634 - 2009-10-19 13:32:22 -0700 (Mon, 19 Oct 2009) - mitani - Windex is the branch for Sugar Sales 1.0 development
7981
7982 r51508 - 2009-10-14 07:40:23 -0700 (Wed, 14 Oct 2009) - jmertic - More fallout fixes from the PHP 5.3 ereg to preg changes.
7983
7984 r51455 - 2009-10-13 07:56:48 -0700 (Tue, 13 Oct 2009) - jmertic - Bug 33202 - Enable install of SugarCRM on PHP 5.3.0, asserting that the minimum supported version is PHP 5.2.x.
7985
7986 r51443 - 2009-10-12 13:34:36 -0700 (Mon, 12 Oct 2009) - jmertic - Bug 33332 - Made application PHP 5.3 compliant with E_DEPRECATED warnings on by:
7987 - Changing all ereg function to either preg or simple string based ones
7988 - No more references to magic quotes.
7989 - Change all the session_unregister() functions to just unset() the correct session variable instead.
7990
7991 r50375 - 2009-08-24 18:07:43 -0700 (Mon, 24 Aug 2009) - dwong - branch kobe2 from tokyo r50372
7992
7993 r45763 - 2009-04-01 12:16:18 -0700 (Wed, 01 Apr 2009) - majed - Removed half of the require_once and include_onces in the product that were redundant or could be handled easily by the auto loader
7994
7995 r45680 - 2009-03-30 14:34:35 -0700 (Mon, 30 Mar 2009) - Samir Gandhi - modifeid serializeSchema to generate WS-I compliant WSDL
7996
7997 r42807 - 2008-12-29 11:16:59 -0800 (Mon, 29 Dec 2008) - dwong - Branch from trunk/sugarcrm r42806 to branches/tokyo/sugarcrm
7998
7999 r42645 - 2008-12-18 13:41:08 -0800 (Thu, 18 Dec 2008) - awu - merging maint_5_2_0 rev41336:HEAD to trunk
8000
8001 r41647 - 2008-11-11 17:44:30 -0800 (Tue, 11 Nov 2008) - majed - Fixes a few bugs 
8002
8003 r41596 - 2008-11-10 19:20:04 -0800 (Mon, 10 Nov 2008) - Samir Gandhi - modified to set $method in the code
8004
8005 r41558 - 2008-11-10 14:35:34 -0800 (Mon, 10 Nov 2008) - majed - changes nusoap to allow for registering classes 
8006
8007 r39619 - 2008-09-09 13:41:34 -0700 (Tue, 09 Sep 2008) - jmertic - Bug 24827 - Remove all instances where we return a new object and assign it by reference, since this is deprecated in PHP 5 and emits E_DEPRECATED errors in PHP 5.3.
8008 Touched:
8009 - data/SugarBean.php
8010 - include/domit/php_http_client_generic.php
8011 - include/domit/php_http_connector.php
8012 - include/domit/testing_domit.php
8013 - include/domit/xml_domit_getelementsbypath.php
8014 - include/domit/xml_domit_lite_parser.php
8015 - include/domit/xml_domit_nodemaps.php
8016 - include/domit/xml_domit_parser.php
8017 - include/domit/xml_domit_shared.php
8018 - include/generic/SugarWidgets/SugarWidgetField.php
8019 - include/generic/SugarWidgets/SugarWidgetReportField.php
8020 - include/ListView/ProcessView.php
8021 - include/nusoap/class.soapclient.php
8022 - include/nusoap/nusoap.php
8023 - include/nusoap/nusoapmime.php
8024 - include/Pear/HTML_Safe/Safe.php
8025 - include/Pear/XML_HTMLSax3/HTMLSax3.php
8026 - modules/Administration/RebuildWorkFlow.php
8027 - modules/Expressions/RelateSelector.php
8028 - modules/Reports/templates/templates_reports.php
8029 - modules/WorkFlow/Delete.php
8030 - modules/WorkFlow/Save.php
8031 - modules/WorkFlow/SaveSequence.php
8032 - modules/WorkFlow/WorkFlow.php
8033 - modules/WorkFlowActionShells/CreateStep1.php
8034 - modules/WorkFlowActionShells/CreateStep2.php
8035 - modules/WorkFlowActionShells/Save.php
8036 - modules/WorkFlowActionShells/WorkFlowActionShell.php
8037 - modules/WorkFlowAlerts/Save.php
8038 - modules/WorkFlowAlerts/WorkFlowAlert.php
8039 - modules/WorkFlowAlertShells/DetailView.php
8040 - modules/WorkFlowAlertShells/WorkFlowAlertShell.php
8041 - modules/WorkFlowTriggerShells/CreateStep1.php
8042 - modules/WorkFlowTriggerShells/CreateStepFilter.php
8043 - modules/WorkFlowTriggerShells/SaveFilter.php
8044 - modules/WorkFlowTriggerShells/WorkFlowTriggerShell.php
8045 - soap/SoapHelperFunctions.php
8046 - test/modules/DynamicFields/DynamicFields_Bug24095_test.php
8047 - test/simpletest/browser.php
8048 - test/simpletest/default_reporter.php
8049 - test/simpletest/detached.php
8050 - test/simpletest/eclipse.php
8051 - test/simpletest/expectation.php
8052 - test/simpletest/extensions/pear_test_case.php
8053 - test/simpletest/form.php
8054 - test/simpletest/http.php
8055 - test/simpletest/mock_objects.php
8056 - test/simpletest/page.php
8057 - test/simpletest/parser.php
8058 - test/simpletest/remote.php
8059 - test/simpletest/shell_tester.php
8060 - test/simpletest/simple_test.php
8061 - test/simpletest/simpletest.php
8062 - test/simpletest/test/acceptance_test.php
8063 - test/simpletest/test/adapter_test.php
8064 - test/simpletest/test/authentication_test.php
8065 - test/simpletest/test/browser_test.php
8066 - test/simpletest/test/collector_test.php
8067 - test/simpletest/test/compatibility_test.php
8068 - test/simpletest/test/detached_test.php
8069 - test/simpletest/test/eclipse_test.php
8070 - test/simpletest/test/encoding_test.php
8071 - test/simpletest/test/errors_test.php
8072 - test/simpletest/test/expectation_test.php
8073 - test/simpletest/test/form_test.php
8074 - test/simpletest/test/frames_test.php
8075 - test/simpletest/test/http_test.php
8076 - test/simpletest/test/live_test.php
8077 - test/simpletest/test/mock_objects_test.php
8078 - test/simpletest/test/page_test.php
8079 - test/simpletest/test/parse_error_test.php
8080 - test/simpletest/test/parser_test.php
8081 - test/simpletest/test/remote_test.php
8082 - test/simpletest/test/shell_test.php
8083 - test/simpletest/test/shell_tester_test.php
8084 - test/simpletest/test/simpletest_test.php
8085 - test/simpletest/test/site/page_request.php
8086 - test/simpletest/test/tag_test.php
8087 - test/simpletest/test/unit_tester_test.php
8088 - test/simpletest/test/user_agent_test.php
8089 - test/simpletest/test/visual_test.php
8090 - test/simpletest/test/xml_test.php
8091 - test/simpletest/test_case.php
8092 - test/simpletest/ui/array_reporter/test.php
8093 - test/simpletest/ui/recorder/test.php
8094 - test/simpletest/unit_tester.php
8095 - test/simpletest/url.php
8096 - test/simpletest/user_agent.php
8097 - test/simpletest/web_tester.php
8098 - test/spikephpcoverage/src/PEAR.php
8099 - test/spikephpcoverage/src/util/Utility.php
8100 - test/spikephpcoverage/src/XML/Parser.php
8101 - test/spikephpcoverage/src/XML/Parser/Simple.php
8102 - test/test_utilities/SugarTest_SimpleBrowser.php
8103
8104 r38362 - 2008-07-28 14:06:59 -0700 (Mon, 28 Jul 2008) - roger - bug: 23897. Using print_r when using the debug statement in nusoap will print out the statements to the screen if the call is coming from the UI.
8105
8106 r38300 - 2008-07-25 13:33:43 -0700 (Fri, 25 Jul 2008) - Samir Gandhi - put the debug in parseresponse function
8107
8108 r38293 - 2008-07-25 12:32:34 -0700 (Fri, 25 Jul 2008) - Samir Gandhi - to put all the debug statements return value in the call function
8109
8110 r36824 - 2008-06-18 09:26:11 -0700 (Wed, 18 Jun 2008) - roger - bug: 21832
8111
8112 r26422 - 2007-09-05 17:29:12 -0700 (Wed, 05 Sep 2007) - majed - migrate from beta 1 to trunk
8113
8114 r15787 - 2006-08-10 10:14:41 -0700 (Thu, 10 Aug 2006) - roger - RRS: bug 7961
8115
8116 r14701 - 2006-07-17 13:37:26 -0700 (Mon, 17 Jul 2006) - roger - RRS: bug 5801
8117
8118 r13782 - 2006-06-06 10:58:55 -0700 (Tue, 06 Jun 2006) - majed - changes entry point code
8119
8120 r11466 - 2006-02-01 15:49:47 -0800 (Wed, 01 Feb 2006) - jacob - Adding extra !empty check to get around a PHP warning.
8121
8122 r11115 - 2006-01-17 14:54:45 -0800 (Tue, 17 Jan 2006) - majed - add entry point validation
8123
8124 r10585 - 2005-12-13 14:42:26 -0800 (Tue, 13 Dec 2005) - majed - adds new license mechanisim
8125
8126 r10170 - 2005-12-05 18:37:46 -0800 (Mon, 05 Dec 2005) - majed - fixes various issues
8127
8128 r8999 - 2005-11-04 05:26:49 -0800 (Fri, 04 Nov 2005) - roger - When nusoap was upgraded we had an issue with the user's default language not being populated during a soap request. I determined the reason this was happening and have checked in the corresponding change to nusoap.
8129
8130 r8991 - 2005-11-03 19:07:25 -0800 (Thu, 03 Nov 2005) - majed - fixes nusoap issue
8131
8132 r8846 - 2005-10-31 11:01:12 -0800 (Mon, 31 Oct 2005) - majed - new version of nusoap
8133
8134 r7905 - 2005-09-21 19:12:57 -0700 (Wed, 21 Sep 2005) - majed - restores old nusoap pre & with a few fixes
8135
8136 r7861 - 2005-09-20 15:40:25 -0700 (Tue, 20 Sep 2005) - majed - & fix for 3.5.1
8137
8138 r7452 - 2005-08-17 11:32:34 -0700 (Wed, 17 Aug 2005) - majed - changes soap to nusoap
8139
8140 r5820 - 2005-06-21 14:22:24 -0700 (Tue, 21 Jun 2005) - majed - fixes issues with nusoap and with custom fields
8141
8142 r5462 - 2005-05-25 13:50:11 -0700 (Wed, 25 May 2005) - majed - upgraded nusoap to .6.9
8143
8144 r5104 - 2005-05-04 15:33:41 -0700 (Wed, 04 May 2005) - majed - gets rid of HTTP_GET_VARS and what not which has been deprecated
8145
8146 r573 - 2004-09-04 13:03:32 -0700 (Sat, 04 Sep 2004) - sugarclint - undoing copyrights added in inadvertantly.  --clint
8147
8148 r546 - 2004-09-03 11:49:38 -0700 (Fri, 03 Sep 2004) - sugarmsi - removed echo count
8149
8150 r354 - 2004-08-02 23:00:37 -0700 (Mon, 02 Aug 2004) - sugarjacob - Adding Soap
8151
8152
8153 */
8154
8155
8156
8157
8158
8159 /**
8160 *
8161 * nusoap_parser class parses SOAP XML messages into native PHP values
8162 *
8163 * @author   Dietrich Ayala <dietrich@ganx4.com>
8164 * @author   Scott Nichol <snichol@users.sourceforge.net>
8165
8166 * @access   public
8167 */
8168 class nusoap_parser extends nusoap_base {
8169
8170         var $xml = '';
8171         var $xml_encoding = '';
8172         var $method = '';
8173         var $root_struct = '';
8174         var $root_struct_name = '';
8175         var $root_struct_namespace = '';
8176         var $root_header = '';
8177     var $document = '';                 // incoming SOAP body (text)
8178         // determines where in the message we are (envelope,header,body,method)
8179         var $status = '';
8180         var $position = 0;
8181         var $depth = 0;
8182         var $default_namespace = '';
8183         var $namespaces = array();
8184         var $message = array();
8185     var $parent = '';
8186         var $fault = false;
8187         var $fault_code = '';
8188         var $fault_str = '';
8189         var $fault_detail = '';
8190         var $depth_array = array();
8191         var $debug_flag = true;
8192         var $soapresponse = NULL;       // parsed SOAP Body
8193         var $soapheader = NULL;         // parsed SOAP Header
8194         var $responseHeaders = '';      // incoming SOAP headers (text)
8195         var $body_position = 0;
8196         // for multiref parsing:
8197         // array of id => pos
8198         var $ids = array();
8199         // array of id => hrefs => pos
8200         var $multirefs = array();
8201         // toggle for auto-decoding element content
8202         var $decode_utf8 = false;
8203
8204         /**
8205         * constructor that actually does the parsing
8206         *
8207         * @param    string $xml SOAP message
8208         * @param    string $encoding character encoding scheme of message
8209         * @param    string $method method for which XML is parsed (unused?)
8210         * @param    string $decode_utf8 whether to decode UTF-8 to ISO-8859-1
8211         * @access   public
8212         */
8213         function nusoap_parser($xml,$encoding='UTF-8',$method='',$decode_utf8=true){
8214                 parent::nusoap_base();
8215                 $this->xml = $xml;
8216                 $this->xml_encoding = $encoding;
8217                 $this->method = $method;
8218                 $this->decode_utf8 = $decode_utf8;
8219
8220                 // Check whether content has been read.
8221                 if(!empty($xml)){
8222                         // Check XML encoding
8223                         $pos_xml = strpos($xml, '<?xml');
8224                         if ($pos_xml !== FALSE) {
8225                                 $xml_decl = substr($xml, $pos_xml, strpos($xml, '?>', $pos_xml + 2) - $pos_xml + 1);
8226                                 if (preg_match("/encoding=[\"']([^\"']*)[\"']/", $xml_decl, $res)) {
8227                                         $xml_encoding = $res[1];
8228                                         if (strtoupper($xml_encoding) != $encoding) {
8229                                                 $err = "Charset from HTTP Content-Type '" . $encoding . "' does not match encoding from XML declaration '" . $xml_encoding . "'";
8230                                                 $this->debug($err);
8231                                                 if ($encoding != 'ISO-8859-1' || strtoupper($xml_encoding) != 'UTF-8') {
8232                                                         $this->setError($err);
8233                                                         return;
8234                                                 }
8235                                                 // when HTTP says ISO-8859-1 (the default) and XML says UTF-8 (the typical), assume the other endpoint is just sloppy and proceed
8236                                         } else {
8237                                                 $this->debug('Charset from HTTP Content-Type matches encoding from XML declaration');
8238                                         }
8239                                 } else {
8240                                         $this->debug('No encoding specified in XML declaration');
8241                                 }
8242                         } else {
8243                                 $this->debug('No XML declaration');
8244                         }
8245                         $this->debug('Entering nusoap_parser(), length='.strlen($xml).', encoding='.$encoding);
8246                         // Create an XML parser - why not xml_parser_create_ns?
8247                         $this->parser = xml_parser_create($this->xml_encoding);
8248                         // Set the options for parsing the XML data.
8249                         //xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
8250                         xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
8251                         xml_parser_set_option($this->parser, XML_OPTION_TARGET_ENCODING, $this->xml_encoding);
8252                         // Set the object for the parser.
8253                         xml_set_object($this->parser, $this);
8254                         // Set the element handlers for the parser.
8255                         xml_set_element_handler($this->parser, 'start_element','end_element');
8256                         xml_set_character_data_handler($this->parser,'character_data');
8257
8258                         // Parse the XML file.
8259                         if(!xml_parse($this->parser,$xml,true)){
8260                             // Display an error message.
8261                             $err = sprintf('XML error parsing SOAP payload on line %d: %s',
8262                             xml_get_current_line_number($this->parser),
8263                             xml_error_string(xml_get_error_code($this->parser)));
8264                                 $this->debug($err);
8265                                 $this->debug("XML payload:\n" . $xml);
8266                                 $this->setError($err);
8267                         } else {
8268                                 $this->debug('in nusoap_parser ctor, message:');
8269                                 $this->appendDebug($this->varDump($this->message));
8270                                 $this->debug('parsed successfully, found root struct: '.$this->root_struct.' of name '.$this->root_struct_name);
8271                                 // get final value
8272                                 $this->soapresponse = $this->message[$this->root_struct]['result'];
8273                                 // get header value
8274                                 if($this->root_header != '' && isset($this->message[$this->root_header]['result'])){
8275                                         $this->soapheader = $this->message[$this->root_header]['result'];
8276                                 }
8277                                 // resolve hrefs/ids
8278                                 if(sizeof($this->multirefs) > 0){
8279                                         foreach($this->multirefs as $id => $hrefs){
8280                                                 $this->debug('resolving multirefs for id: '.$id);
8281                                                 $idVal = $this->buildVal($this->ids[$id]);
8282                                                 if (is_array($idVal) && isset($idVal['!id'])) {
8283                                                         unset($idVal['!id']);
8284                                                 }
8285                                                 foreach($hrefs as $refPos => $ref){
8286                                                         $this->debug('resolving href at pos '.$refPos);
8287                                                         $this->multirefs[$id][$refPos] = $idVal;
8288                                                 }
8289                                         }
8290                                 }
8291                         }
8292                         xml_parser_free($this->parser);
8293                 } else {
8294                         $this->debug('xml was empty, didn\'t parse!');
8295                         $this->setError('xml was empty, didn\'t parse!');
8296                 }
8297         }
8298
8299         /**
8300         * start-element handler
8301         *
8302         * @param    resource $parser XML parser object
8303         * @param    string $name element name
8304         * @param    array $attrs associative array of attributes
8305         * @access   private
8306         */
8307         function start_element($parser, $name, $attrs) {
8308                 // position in a total number of elements, starting from 0
8309                 // update class level pos
8310                 $pos = $this->position++;
8311                 // and set mine
8312                 $this->message[$pos] = array('pos' => $pos,'children'=>'','cdata'=>'');
8313                 // depth = how many levels removed from root?
8314                 // set mine as current global depth and increment global depth value
8315                 $this->message[$pos]['depth'] = $this->depth++;
8316
8317                 // else add self as child to whoever the current parent is
8318                 if($pos != 0){
8319                         $this->message[$this->parent]['children'] .= '|'.$pos;
8320                 }
8321                 // set my parent
8322                 $this->message[$pos]['parent'] = $this->parent;
8323                 // set self as current parent
8324                 $this->parent = $pos;
8325                 // set self as current value for this depth
8326                 $this->depth_array[$this->depth] = $pos;
8327                 // get element prefix
8328                 if(strpos($name,':')){
8329                         // get ns prefix
8330                         $prefix = substr($name,0,strpos($name,':'));
8331                         // get unqualified name
8332                         $name = substr(strstr($name,':'),1);
8333                 }
8334                 // set status
8335                 if ($name == 'Envelope' && $this->status == '') {
8336                         $this->status = 'envelope';
8337                 } elseif ($name == 'Header' && $this->status == 'envelope') {
8338                         $this->root_header = $pos;
8339                         $this->status = 'header';
8340                 } elseif ($name == 'Body' && $this->status == 'envelope'){
8341                         $this->status = 'body';
8342                         $this->body_position = $pos;
8343                 // set method
8344                 } elseif($this->status == 'body' && $pos == ($this->body_position+1)) {
8345                         $this->status = 'method';
8346                         $this->root_struct_name = $name;
8347                         $this->root_struct = $pos;
8348                         $this->message[$pos]['type'] = 'struct';
8349                         $this->debug("found root struct $this->root_struct_name, pos $this->root_struct");
8350                 }
8351                 // set my status
8352                 $this->message[$pos]['status'] = $this->status;
8353                 // set name
8354                 $this->message[$pos]['name'] = htmlspecialchars($name);
8355                 // set attrs
8356                 $this->message[$pos]['attrs'] = $attrs;
8357
8358                 // loop through atts, logging ns and type declarations
8359         $attstr = '';
8360                 foreach($attrs as $key => $value){
8361                 $key_prefix = $this->getPrefix($key);
8362                         $key_localpart = $this->getLocalPart($key);
8363                         // if ns declarations, add to class level array of valid namespaces
8364             if($key_prefix == 'xmlns'){
8365                                 if(preg_match('/^http:\/\/www.w3.org\/[0-9]{4}\/XMLSchema$/',$value)){
8366                                         $this->XMLSchemaVersion = $value;
8367                                         $this->namespaces['xsd'] = $this->XMLSchemaVersion;
8368                                         $this->namespaces['xsi'] = $this->XMLSchemaVersion.'-instance';
8369                                 }
8370                 $this->namespaces[$key_localpart] = $value;
8371                                 // set method namespace
8372                                 if($name == $this->root_struct_name){
8373                                         $this->methodNamespace = $value;
8374                                 }
8375                         // if it's a type declaration, set type
8376         } elseif($key_localpart == 'type'){
8377                         if (isset($this->message[$pos]['type']) && $this->message[$pos]['type'] == 'array') {
8378                                 // do nothing: already processed arrayType
8379                         } else {
8380                         $value_prefix = $this->getPrefix($value);
8381                         $value_localpart = $this->getLocalPart($value);
8382                                         $this->message[$pos]['type'] = $value_localpart;
8383                                         $this->message[$pos]['typePrefix'] = $value_prefix;
8384                         if(isset($this->namespaces[$value_prefix])){
8385                                 $this->message[$pos]['type_namespace'] = $this->namespaces[$value_prefix];
8386                         } else if(isset($attrs['xmlns:'.$value_prefix])) {
8387                                                 $this->message[$pos]['type_namespace'] = $attrs['xmlns:'.$value_prefix];
8388                         }
8389                                         // should do something here with the namespace of specified type?
8390                                 }
8391                         } elseif($key_localpart == 'arrayType'){
8392                                 $this->message[$pos]['type'] = 'array';
8393                                 /* do arrayType ereg here
8394                                 [1]    arrayTypeValue    ::=    atype asize
8395                                 [2]    atype    ::=    QName rank*
8396                                 [3]    rank    ::=    '[' (',')* ']'
8397                                 [4]    asize    ::=    '[' length~ ']'
8398                                 [5]    length    ::=    nextDimension* Digit+
8399                                 [6]    nextDimension    ::=    Digit+ ','
8400                                 */
8401                                 $expr = '/([A-Za-z0-9_]+):([A-Za-z]+[A-Za-z0-9_]+)\[([0-9]+),?([0-9]*)\]/';
8402                                 if(preg_match($expr,$value,$regs)){
8403                                         $this->message[$pos]['typePrefix'] = $regs[1];
8404                                         $this->message[$pos]['arrayTypePrefix'] = $regs[1];
8405                         if (isset($this->namespaces[$regs[1]])) {
8406                                 $this->message[$pos]['arrayTypeNamespace'] = $this->namespaces[$regs[1]];
8407                         } else if (isset($attrs['xmlns:'.$regs[1]])) {
8408                                                 $this->message[$pos]['arrayTypeNamespace'] = $attrs['xmlns:'.$regs[1]];
8409                         }
8410                                         $this->message[$pos]['arrayType'] = $regs[2];
8411                                         $this->message[$pos]['arraySize'] = $regs[3];
8412                                         $this->message[$pos]['arrayCols'] = $regs[4];
8413                                 }
8414                         // specifies nil value (or not)
8415                         } elseif ($key_localpart == 'nil'){
8416                                 $this->message[$pos]['nil'] = ($value == 'true' || $value == '1');
8417                         // some other attribute
8418                         } elseif ($key != 'href' && $key != 'xmlns' && $key_localpart != 'encodingStyle' && $key_localpart != 'root') {
8419                                 $this->message[$pos]['xattrs']['!' . $key] = $value;
8420                         }
8421
8422                         if ($key == 'xmlns') {
8423                                 $this->default_namespace = $value;
8424                         }
8425                         // log id
8426                         if($key == 'id'){
8427                                 $this->ids[$value] = $pos;
8428                         }
8429                         // root
8430                         if($key_localpart == 'root' && $value == 1){
8431                                 $this->status = 'method';
8432                                 $this->root_struct_name = $name;
8433                                 $this->root_struct = $pos;
8434                                 $this->debug("found root struct $this->root_struct_name, pos $pos");
8435                         }
8436             // for doclit
8437             $attstr .= " $key=\"$value\"";
8438                 }
8439         // get namespace - must be done after namespace atts are processed
8440                 if(isset($prefix)){
8441                         $this->message[$pos]['namespace'] = $this->namespaces[$prefix];
8442                         $this->default_namespace = $this->namespaces[$prefix];
8443                 } else {
8444                         $this->message[$pos]['namespace'] = $this->default_namespace;
8445                 }
8446         if($this->status == 'header'){
8447                 if ($this->root_header != $pos) {
8448                         $this->responseHeaders .= "<" . (isset($prefix) ? $prefix . ':' : '') . "$name$attstr>";
8449                 }
8450         } elseif($this->root_struct_name != ''){
8451                 $this->document .= "<" . (isset($prefix) ? $prefix . ':' : '') . "$name$attstr>";
8452         }
8453         }
8454
8455         /**
8456         * end-element handler
8457         *
8458         * @param    resource $parser XML parser object
8459         * @param    string $name element name
8460         * @access   private
8461         */
8462         function end_element($parser, $name) {
8463                 // position of current element is equal to the last value left in depth_array for my depth
8464                 $pos = $this->depth_array[$this->depth--];
8465
8466         // get element prefix
8467                 if(strpos($name,':')){
8468                         // get ns prefix
8469                         $prefix = substr($name,0,strpos($name,':'));
8470                         // get unqualified name
8471                         $name = substr(strstr($name,':'),1);
8472                 }
8473                 
8474                 // build to native type
8475                 if(isset($this->body_position) && $pos > $this->body_position){
8476                         // deal w/ multirefs
8477                         if(isset($this->message[$pos]['attrs']['href'])){
8478                                 // get id
8479                                 $id = substr($this->message[$pos]['attrs']['href'],1);
8480                                 // add placeholder to href array
8481                                 $this->multirefs[$id][$pos] = 'placeholder';
8482                                 // add set a reference to it as the result value
8483                                 $this->message[$pos]['result'] =& $this->multirefs[$id][$pos];
8484             // build complexType values
8485                         } elseif($this->message[$pos]['children'] != ''){
8486                                 // if result has already been generated (struct/array)
8487                                 if(!isset($this->message[$pos]['result'])){
8488                                         $this->message[$pos]['result'] = $this->buildVal($pos);
8489                                 }
8490                         // build complexType values of attributes and possibly simpleContent
8491                         } elseif (isset($this->message[$pos]['xattrs'])) {
8492                                 if (isset($this->message[$pos]['nil']) && $this->message[$pos]['nil']) {
8493                                         $this->message[$pos]['xattrs']['!'] = null;
8494                                 } elseif (isset($this->message[$pos]['cdata']) && trim($this->message[$pos]['cdata']) != '') {
8495                         if (isset($this->message[$pos]['type'])) {
8496                                                 $this->message[$pos]['xattrs']['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$pos]['type'], isset($this->message[$pos]['type_namespace']) ? $this->message[$pos]['type_namespace'] : '');
8497                                         } else {
8498                                                 $parent = $this->message[$pos]['parent'];
8499                                                 if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
8500                                                         $this->message[$pos]['xattrs']['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
8501                                                 } else {
8502                                                         $this->message[$pos]['xattrs']['!'] = $this->message[$pos]['cdata'];
8503                                                 }
8504                                         }
8505                                 }
8506                                 $this->message[$pos]['result'] = $this->message[$pos]['xattrs'];
8507                         // set value of simpleType (or nil complexType)
8508                         } else {
8509                 //$this->debug('adding data for scalar value '.$this->message[$pos]['name'].' of value '.$this->message[$pos]['cdata']);
8510                                 if (isset($this->message[$pos]['nil']) && $this->message[$pos]['nil']) {
8511                                         $this->message[$pos]['xattrs']['!'] = null;
8512                                 } elseif (isset($this->message[$pos]['type'])) {
8513                                         $this->message[$pos]['result'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$pos]['type'], isset($this->message[$pos]['type_namespace']) ? $this->message[$pos]['type_namespace'] : '');
8514                                 } else {
8515                                         $parent = $this->message[$pos]['parent'];
8516                                         if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
8517                                                 $this->message[$pos]['result'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
8518                                         } else {
8519                                                 $this->message[$pos]['result'] = $this->message[$pos]['cdata'];
8520                                         }
8521                                 }
8522
8523                                 /* add value to parent's result, if parent is struct/array
8524                                 $parent = $this->message[$pos]['parent'];
8525                                 if($this->message[$parent]['type'] != 'map'){
8526                                         if(strtolower($this->message[$parent]['type']) == 'array'){
8527                                                 $this->message[$parent]['result'][] = $this->message[$pos]['result'];
8528                                         } else {
8529                                                 $this->message[$parent]['result'][$this->message[$pos]['name']] = $this->message[$pos]['result'];
8530                                         }
8531                                 }
8532                                 */
8533                         }
8534                 }
8535                 
8536         // for doclit
8537         if($this->status == 'header'){
8538                 if ($this->root_header != $pos) {
8539                         $this->responseHeaders .= "</" . (isset($prefix) ? $prefix . ':' : '') . "$name>";
8540                 }
8541         } elseif($pos >= $this->root_struct){
8542                 $this->document .= "</" . (isset($prefix) ? $prefix . ':' : '') . "$name>";
8543         }
8544                 // switch status
8545                 if ($pos == $this->root_struct){
8546                         $this->status = 'body';
8547                         $this->root_struct_namespace = $this->message[$pos]['namespace'];
8548                 } elseif ($pos == $this->root_header) {
8549                         $this->status = 'envelope';
8550                 } elseif ($name == 'Body' && $this->status == 'body') {
8551                         $this->status = 'envelope';
8552                 } elseif ($name == 'Header' && $this->status == 'header') { // will never happen
8553                         $this->status = 'envelope';
8554                 } elseif ($name == 'Envelope' && $this->status == 'envelope') {
8555                         $this->status = '';
8556                 }
8557                 // set parent back to my parent
8558                 $this->parent = $this->message[$pos]['parent'];
8559         }
8560
8561         /**
8562         * element content handler
8563         *
8564         * @param    resource $parser XML parser object
8565         * @param    string $data element content
8566         * @access   private
8567         */
8568         function character_data($parser, $data){
8569                 $pos = $this->depth_array[$this->depth];
8570                 if ($this->xml_encoding=='UTF-8'){
8571                         // TODO: add an option to disable this for folks who want
8572                         // raw UTF-8 that, e.g., might not map to iso-8859-1
8573                         // TODO: this can also be handled with xml_parser_set_option($this->parser, XML_OPTION_TARGET_ENCODING, "ISO-8859-1");
8574                         if($this->decode_utf8){
8575                                 $data = utf8_decode($data);
8576                         }
8577                 }
8578         $this->message[$pos]['cdata'] .= $data;
8579         // for doclit
8580         if($this->status == 'header'){
8581                 $this->responseHeaders .= $data;
8582         } else {
8583                 $this->document .= $data;
8584         }
8585         }
8586
8587         /**
8588         * get the parsed message (SOAP Body)
8589         *
8590         * @return       mixed
8591         * @access   public
8592         * @deprecated   use get_soapbody instead
8593         */
8594         function get_response(){
8595                 return $this->soapresponse;
8596         }
8597
8598         /**
8599         * get the parsed SOAP Body (NULL if there was none)
8600         *
8601         * @return       mixed
8602         * @access   public
8603         */
8604         function get_soapbody(){
8605                 return $this->soapresponse;
8606         }
8607
8608         /**
8609         * get the parsed SOAP Header (NULL if there was none)
8610         *
8611         * @return       mixed
8612         * @access   public
8613         */
8614         function get_soapheader(){
8615                 return $this->soapheader;
8616         }
8617
8618         /**
8619         * get the unparsed SOAP Header
8620         *
8621         * @return       string XML or empty if no Header
8622         * @access   public
8623         */
8624         function getHeaders(){
8625             return $this->responseHeaders;
8626         }
8627
8628         /**
8629         * decodes simple types into PHP variables
8630         *
8631         * @param    string $value value to decode
8632         * @param    string $type XML type to decode
8633         * @param    string $typens XML type namespace to decode
8634         * @return       mixed PHP value
8635         * @access   private
8636         */
8637         function decodeSimple($value, $type, $typens) {
8638                 // TODO: use the namespace!
8639                 if ((!isset($type)) || $type == 'string' || $type == 'long' || $type == 'unsignedLong') {
8640                         return (string) $value;
8641                 }
8642                 if ($type == 'int' || $type == 'integer' || $type == 'short' || $type == 'byte') {
8643                         return (int) $value;
8644                 }
8645                 if ($type == 'float' || $type == 'double' || $type == 'decimal') {
8646                         return (double) $value;
8647                 }
8648                 if ($type == 'boolean') {
8649                         if (strtolower($value) == 'false' || strtolower($value) == 'f') {
8650                                 return false;
8651                         }
8652                         return (boolean) $value;
8653                 }
8654                 if ($type == 'base64' || $type == 'base64Binary') {
8655                         $this->debug('Decode base64 value');
8656                         return base64_decode($value);
8657                 }
8658                 // obscure numeric types
8659                 if ($type == 'nonPositiveInteger' || $type == 'negativeInteger'
8660                         || $type == 'nonNegativeInteger' || $type == 'positiveInteger'
8661                         || $type == 'unsignedInt'
8662                         || $type == 'unsignedShort' || $type == 'unsignedByte') {
8663                         return (int) $value;
8664                 }
8665                 // bogus: parser treats array with no elements as a simple type
8666                 if ($type == 'array') {
8667                         return array();
8668                 }
8669                 // everything else
8670                 return (string) $value;
8671         }
8672
8673         /**
8674         * builds response structures for compound values (arrays/structs)
8675         * and scalars
8676         *
8677         * @param    integer $pos position in node tree
8678         * @return       mixed   PHP value
8679         * @access   private
8680         */
8681         function buildVal($pos){
8682                 if(!isset($this->message[$pos]['type'])){
8683                         $this->message[$pos]['type'] = '';
8684                 }
8685                 $this->debug('in buildVal() for '.$this->message[$pos]['name']."(pos $pos) of type ".$this->message[$pos]['type']);
8686                 // if there are children...
8687                 if($this->message[$pos]['children'] != ''){
8688                         $this->debug('in buildVal, there are children');
8689                         $children = explode('|',$this->message[$pos]['children']);
8690                         array_shift($children); // knock off empty
8691                         // md array
8692                         if(isset($this->message[$pos]['arrayCols']) && $this->message[$pos]['arrayCols'] != ''){
8693                 $r=0; // rowcount
8694                 $c=0; // colcount
8695                 foreach($children as $child_pos){
8696                                         $this->debug("in buildVal, got an MD array element: $r, $c");
8697                                         $params[$r][] = $this->message[$child_pos]['result'];
8698                                     $c++;
8699                                     if($c == $this->message[$pos]['arrayCols']){
8700                                         $c = 0;
8701                                                 $r++;
8702                                     }
8703                 }
8704             // array
8705                         } elseif($this->message[$pos]['type'] == 'array' || $this->message[$pos]['type'] == 'Array'){
8706                 $this->debug('in buildVal, adding array '.$this->message[$pos]['name']);
8707                 foreach($children as $child_pos){
8708                         $params[] = &$this->message[$child_pos]['result'];
8709                 }
8710             // apache Map type: java hashtable
8711             } elseif($this->message[$pos]['type'] == 'Map' && $this->message[$pos]['type_namespace'] == 'http://xml.apache.org/xml-soap'){
8712                 $this->debug('in buildVal, Java Map '.$this->message[$pos]['name']);
8713                 foreach($children as $child_pos){
8714                         $kv = explode("|",$this->message[$child_pos]['children']);
8715                         $params[$this->message[$kv[1]]['result']] = &$this->message[$kv[2]]['result'];
8716                 }
8717             // generic compound type
8718             //} elseif($this->message[$pos]['type'] == 'SOAPStruct' || $this->message[$pos]['type'] == 'struct') {
8719                     } else {
8720                         // Apache Vector type: treat as an array
8721                 $this->debug('in buildVal, adding Java Vector or generic compound type '.$this->message[$pos]['name']);
8722                                 if ($this->message[$pos]['type'] == 'Vector' && $this->message[$pos]['type_namespace'] == 'http://xml.apache.org/xml-soap') {
8723                                         $notstruct = 1;
8724                                 } else {
8725                                         $notstruct = 0;
8726                     }
8727                 //
8728                 foreach($children as $child_pos){
8729                         if($notstruct){
8730                                 $params[] = &$this->message[$child_pos]['result'];
8731                         } else {
8732                                 if (isset($params[$this->message[$child_pos]['name']])) {
8733                                         // de-serialize repeated element name into an array
8734                                         if ((!is_array($params[$this->message[$child_pos]['name']])) || (!isset($params[$this->message[$child_pos]['name']][0]))) {
8735                                                 $params[$this->message[$child_pos]['name']] = array($params[$this->message[$child_pos]['name']]);
8736                                         }
8737                                         $params[$this->message[$child_pos]['name']][] = &$this->message[$child_pos]['result'];
8738                                 } else {
8739                                                 $params[$this->message[$child_pos]['name']] = &$this->message[$child_pos]['result'];
8740                                             }
8741                         }
8742                 }
8743                         }
8744                         if (isset($this->message[$pos]['xattrs'])) {
8745                 $this->debug('in buildVal, handling attributes');
8746                                 foreach ($this->message[$pos]['xattrs'] as $n => $v) {
8747                                         $params[$n] = $v;
8748                                 }
8749                         }
8750                         // handle simpleContent
8751                         if (isset($this->message[$pos]['cdata']) && trim($this->message[$pos]['cdata']) != '') {
8752                 $this->debug('in buildVal, handling simpleContent');
8753                 if (isset($this->message[$pos]['type'])) {
8754                                         $params['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$pos]['type'], isset($this->message[$pos]['type_namespace']) ? $this->message[$pos]['type_namespace'] : '');
8755                                 } else {
8756                                         $parent = $this->message[$pos]['parent'];
8757                                         if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
8758                                                 $params['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
8759                                         } else {
8760                                                 $params['!'] = $this->message[$pos]['cdata'];
8761                                         }
8762                                 }
8763                         }
8764                         $ret = is_array($params) ? $params : array();
8765                         $this->debug('in buildVal, return:');
8766                         $this->appendDebug($this->varDump($ret));
8767                         return $ret;
8768                 } else {
8769                 $this->debug('in buildVal, no children, building scalar');
8770                         $cdata = isset($this->message[$pos]['cdata']) ? $this->message[$pos]['cdata'] : '';
8771                 if (isset($this->message[$pos]['type'])) {
8772                                 $ret = $this->decodeSimple($cdata, $this->message[$pos]['type'], isset($this->message[$pos]['type_namespace']) ? $this->message[$pos]['type_namespace'] : '');
8773                                 $this->debug("in buildVal, return: $ret");
8774                                 return $ret;
8775                         }
8776                         $parent = $this->message[$pos]['parent'];
8777                         if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
8778                                 $ret = $this->decodeSimple($cdata, $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
8779                                 $this->debug("in buildVal, return: $ret");
8780                                 return $ret;
8781                         }
8782                 $ret = $this->message[$pos]['cdata'];
8783                         $this->debug("in buildVal, return: $ret");
8784                 return $ret;
8785                 }
8786         }
8787 }
8788
8789 /**
8790  * Backward compatibility
8791  */
8792 class soap_parser extends nusoap_parser {
8793 }
8794
8795 ?><?php
8796
8797 /*
8798
8799 Modification information for LGPL compliance
8800
8801 r58622 - 2010-10-22 18:18:59 -0700 (Fri, 22 Oct 2010) - engsvnbuild - Author: lam <lam@198.18.142.201>
8802     bug 40066
8803
8804 r58361 - 2010-09-29 16:59:02 -0700 (Wed, 29 Sep 2010) - kjing - Author: Jenny Gonsalves <jenny@sugarcrm.com>
8805     Merging with maint_6_0_1 (svn merge -r 58250:58342)
8806
8807 r57813 - 2010-08-19 10:34:44 -0700 (Thu, 19 Aug 2010) - kjing - Author: John Mertic <jmertic@sugarcrm.com>
8808     Bug 39085 - When loading the opposite search panel via ajax on the ListViews, call the index action instead of the ListView action to avoid touching pre-MVC code by accident.
8809
8810 r57707 - 2010-08-10 12:26:13 -0700 (Tue, 10 Aug 2010) - kjing - Author: Stanislav Malyshev <smalyshev@gmail.com>
8811     fix SOAP calls with no parameters
8812
8813 r56990 - 2010-06-16 13:05:36 -0700 (Wed, 16 Jun 2010) - kjing - snapshot "Mango" svn branch to a new one for GitHub sync
8814
8815 r56989 - 2010-06-16 13:01:33 -0700 (Wed, 16 Jun 2010) - kjing - defunt "Mango" svn dev branch before github cutover
8816
8817 r55980 - 2010-04-19 13:31:28 -0700 (Mon, 19 Apr 2010) - kjing - create Mango (6.1) based on windex
8818
8819 r51719 - 2009-10-22 10:18:00 -0700 (Thu, 22 Oct 2009) - mitani - Converted to Build 3  tags and updated the build system 
8820
8821 r51634 - 2009-10-19 13:32:22 -0700 (Mon, 19 Oct 2009) - mitani - Windex is the branch for Sugar Sales 1.0 development
8822
8823 r51508 - 2009-10-14 07:40:23 -0700 (Wed, 14 Oct 2009) - jmertic - More fallout fixes from the PHP 5.3 ereg to preg changes.
8824
8825 r51455 - 2009-10-13 07:56:48 -0700 (Tue, 13 Oct 2009) - jmertic - Bug 33202 - Enable install of SugarCRM on PHP 5.3.0, asserting that the minimum supported version is PHP 5.2.x.
8826
8827 r51443 - 2009-10-12 13:34:36 -0700 (Mon, 12 Oct 2009) - jmertic - Bug 33332 - Made application PHP 5.3 compliant with E_DEPRECATED warnings on by:
8828 - Changing all ereg function to either preg or simple string based ones
8829 - No more references to magic quotes.
8830 - Change all the session_unregister() functions to just unset() the correct session variable instead.
8831
8832 r50375 - 2009-08-24 18:07:43 -0700 (Mon, 24 Aug 2009) - dwong - branch kobe2 from tokyo r50372
8833
8834 r45763 - 2009-04-01 12:16:18 -0700 (Wed, 01 Apr 2009) - majed - Removed half of the require_once and include_onces in the product that were redundant or could be handled easily by the auto loader
8835
8836 r45680 - 2009-03-30 14:34:35 -0700 (Mon, 30 Mar 2009) - Samir Gandhi - modifeid serializeSchema to generate WS-I compliant WSDL
8837
8838 r42807 - 2008-12-29 11:16:59 -0800 (Mon, 29 Dec 2008) - dwong - Branch from trunk/sugarcrm r42806 to branches/tokyo/sugarcrm
8839
8840 r42645 - 2008-12-18 13:41:08 -0800 (Thu, 18 Dec 2008) - awu - merging maint_5_2_0 rev41336:HEAD to trunk
8841
8842 r41647 - 2008-11-11 17:44:30 -0800 (Tue, 11 Nov 2008) - majed - Fixes a few bugs 
8843
8844 r41596 - 2008-11-10 19:20:04 -0800 (Mon, 10 Nov 2008) - Samir Gandhi - modified to set $method in the code
8845
8846 r41558 - 2008-11-10 14:35:34 -0800 (Mon, 10 Nov 2008) - majed - changes nusoap to allow for registering classes 
8847
8848 r39619 - 2008-09-09 13:41:34 -0700 (Tue, 09 Sep 2008) - jmertic - Bug 24827 - Remove all instances where we return a new object and assign it by reference, since this is deprecated in PHP 5 and emits E_DEPRECATED errors in PHP 5.3.
8849 Touched:
8850 - data/SugarBean.php
8851 - include/domit/php_http_client_generic.php
8852 - include/domit/php_http_connector.php
8853 - include/domit/testing_domit.php
8854 - include/domit/xml_domit_getelementsbypath.php
8855 - include/domit/xml_domit_lite_parser.php
8856 - include/domit/xml_domit_nodemaps.php
8857 - include/domit/xml_domit_parser.php
8858 - include/domit/xml_domit_shared.php
8859 - include/generic/SugarWidgets/SugarWidgetField.php
8860 - include/generic/SugarWidgets/SugarWidgetReportField.php
8861 - include/ListView/ProcessView.php
8862 - include/nusoap/class.soapclient.php
8863 - include/nusoap/nusoap.php
8864 - include/nusoap/nusoapmime.php
8865 - include/Pear/HTML_Safe/Safe.php
8866 - include/Pear/XML_HTMLSax3/HTMLSax3.php
8867 - modules/Administration/RebuildWorkFlow.php
8868 - modules/Expressions/RelateSelector.php
8869 - modules/Reports/templates/templates_reports.php
8870 - modules/WorkFlow/Delete.php
8871 - modules/WorkFlow/Save.php
8872 - modules/WorkFlow/SaveSequence.php
8873 - modules/WorkFlow/WorkFlow.php
8874 - modules/WorkFlowActionShells/CreateStep1.php
8875 - modules/WorkFlowActionShells/CreateStep2.php
8876 - modules/WorkFlowActionShells/Save.php
8877 - modules/WorkFlowActionShells/WorkFlowActionShell.php
8878 - modules/WorkFlowAlerts/Save.php
8879 - modules/WorkFlowAlerts/WorkFlowAlert.php
8880 - modules/WorkFlowAlertShells/DetailView.php
8881 - modules/WorkFlowAlertShells/WorkFlowAlertShell.php
8882 - modules/WorkFlowTriggerShells/CreateStep1.php
8883 - modules/WorkFlowTriggerShells/CreateStepFilter.php
8884 - modules/WorkFlowTriggerShells/SaveFilter.php
8885 - modules/WorkFlowTriggerShells/WorkFlowTriggerShell.php
8886 - soap/SoapHelperFunctions.php
8887 - test/modules/DynamicFields/DynamicFields_Bug24095_test.php
8888 - test/simpletest/browser.php
8889 - test/simpletest/default_reporter.php
8890 - test/simpletest/detached.php
8891 - test/simpletest/eclipse.php
8892 - test/simpletest/expectation.php
8893 - test/simpletest/extensions/pear_test_case.php
8894 - test/simpletest/form.php
8895 - test/simpletest/http.php
8896 - test/simpletest/mock_objects.php
8897 - test/simpletest/page.php
8898 - test/simpletest/parser.php
8899 - test/simpletest/remote.php
8900 - test/simpletest/shell_tester.php
8901 - test/simpletest/simple_test.php
8902 - test/simpletest/simpletest.php
8903 - test/simpletest/test/acceptance_test.php
8904 - test/simpletest/test/adapter_test.php
8905 - test/simpletest/test/authentication_test.php
8906 - test/simpletest/test/browser_test.php
8907 - test/simpletest/test/collector_test.php
8908 - test/simpletest/test/compatibility_test.php
8909 - test/simpletest/test/detached_test.php
8910 - test/simpletest/test/eclipse_test.php
8911 - test/simpletest/test/encoding_test.php
8912 - test/simpletest/test/errors_test.php
8913 - test/simpletest/test/expectation_test.php
8914 - test/simpletest/test/form_test.php
8915 - test/simpletest/test/frames_test.php
8916 - test/simpletest/test/http_test.php
8917 - test/simpletest/test/live_test.php
8918 - test/simpletest/test/mock_objects_test.php
8919 - test/simpletest/test/page_test.php
8920 - test/simpletest/test/parse_error_test.php
8921 - test/simpletest/test/parser_test.php
8922 - test/simpletest/test/remote_test.php
8923 - test/simpletest/test/shell_test.php
8924 - test/simpletest/test/shell_tester_test.php
8925 - test/simpletest/test/simpletest_test.php
8926 - test/simpletest/test/site/page_request.php
8927 - test/simpletest/test/tag_test.php
8928 - test/simpletest/test/unit_tester_test.php
8929 - test/simpletest/test/user_agent_test.php
8930 - test/simpletest/test/visual_test.php
8931 - test/simpletest/test/xml_test.php
8932 - test/simpletest/test_case.php
8933 - test/simpletest/ui/array_reporter/test.php
8934 - test/simpletest/ui/recorder/test.php
8935 - test/simpletest/unit_tester.php
8936 - test/simpletest/url.php
8937 - test/simpletest/user_agent.php
8938 - test/simpletest/web_tester.php
8939 - test/spikephpcoverage/src/PEAR.php
8940 - test/spikephpcoverage/src/util/Utility.php
8941 - test/spikephpcoverage/src/XML/Parser.php
8942 - test/spikephpcoverage/src/XML/Parser/Simple.php
8943 - test/test_utilities/SugarTest_SimpleBrowser.php
8944
8945 r38362 - 2008-07-28 14:06:59 -0700 (Mon, 28 Jul 2008) - roger - bug: 23897. Using print_r when using the debug statement in nusoap will print out the statements to the screen if the call is coming from the UI.
8946
8947 r38300 - 2008-07-25 13:33:43 -0700 (Fri, 25 Jul 2008) - Samir Gandhi - put the debug in parseresponse function
8948
8949 r38293 - 2008-07-25 12:32:34 -0700 (Fri, 25 Jul 2008) - Samir Gandhi - to put all the debug statements return value in the call function
8950
8951 r36824 - 2008-06-18 09:26:11 -0700 (Wed, 18 Jun 2008) - roger - bug: 21832
8952
8953 r26422 - 2007-09-05 17:29:12 -0700 (Wed, 05 Sep 2007) - majed - migrate from beta 1 to trunk
8954
8955 r15787 - 2006-08-10 10:14:41 -0700 (Thu, 10 Aug 2006) - roger - RRS: bug 7961
8956
8957 r14701 - 2006-07-17 13:37:26 -0700 (Mon, 17 Jul 2006) - roger - RRS: bug 5801
8958
8959 r13782 - 2006-06-06 10:58:55 -0700 (Tue, 06 Jun 2006) - majed - changes entry point code
8960
8961 r11466 - 2006-02-01 15:49:47 -0800 (Wed, 01 Feb 2006) - jacob - Adding extra !empty check to get around a PHP warning.
8962
8963 r11115 - 2006-01-17 14:54:45 -0800 (Tue, 17 Jan 2006) - majed - add entry point validation
8964
8965 r10585 - 2005-12-13 14:42:26 -0800 (Tue, 13 Dec 2005) - majed - adds new license mechanisim
8966
8967 r10170 - 2005-12-05 18:37:46 -0800 (Mon, 05 Dec 2005) - majed - fixes various issues
8968
8969 r8999 - 2005-11-04 05:26:49 -0800 (Fri, 04 Nov 2005) - roger - When nusoap was upgraded we had an issue with the user's default language not being populated during a soap request. I determined the reason this was happening and have checked in the corresponding change to nusoap.
8970
8971 r8991 - 2005-11-03 19:07:25 -0800 (Thu, 03 Nov 2005) - majed - fixes nusoap issue
8972
8973 r8846 - 2005-10-31 11:01:12 -0800 (Mon, 31 Oct 2005) - majed - new version of nusoap
8974
8975 r7905 - 2005-09-21 19:12:57 -0700 (Wed, 21 Sep 2005) - majed - restores old nusoap pre & with a few fixes
8976
8977 r7861 - 2005-09-20 15:40:25 -0700 (Tue, 20 Sep 2005) - majed - & fix for 3.5.1
8978
8979 r7452 - 2005-08-17 11:32:34 -0700 (Wed, 17 Aug 2005) - majed - changes soap to nusoap
8980
8981 r5820 - 2005-06-21 14:22:24 -0700 (Tue, 21 Jun 2005) - majed - fixes issues with nusoap and with custom fields
8982
8983 r5462 - 2005-05-25 13:50:11 -0700 (Wed, 25 May 2005) - majed - upgraded nusoap to .6.9
8984
8985 r5104 - 2005-05-04 15:33:41 -0700 (Wed, 04 May 2005) - majed - gets rid of HTTP_GET_VARS and what not which has been deprecated
8986
8987 r573 - 2004-09-04 13:03:32 -0700 (Sat, 04 Sep 2004) - sugarclint - undoing copyrights added in inadvertantly.  --clint
8988
8989 r546 - 2004-09-03 11:49:38 -0700 (Fri, 03 Sep 2004) - sugarmsi - removed echo count
8990
8991 r354 - 2004-08-02 23:00:37 -0700 (Mon, 02 Aug 2004) - sugarjacob - Adding Soap
8992
8993
8994 */
8995
8996
8997
8998
8999
9000 /**
9001 *
9002 * [nu]soapclient higher level class for easy usage.
9003 *
9004 * usage:
9005 *
9006 * // instantiate client with server info
9007 * $soapclient = new nusoap_client( string path [ ,mixed wsdl] );
9008 *
9009 * // call method, get results
9010 * echo $soapclient->call( string methodname [ ,array parameters] );
9011 *
9012 * // bye bye client
9013 * unset($soapclient);
9014 *
9015 * @author   Dietrich Ayala <dietrich@ganx4.com>
9016 * @author   Scott Nichol <snichol@users.sourceforge.net>
9017
9018 * @access   public
9019 */
9020 class nusoap_client extends nusoap_base  {
9021
9022         var $username = '';                             // Username for HTTP authentication
9023         var $password = '';                             // Password for HTTP authentication
9024         var $authtype = '';                             // Type of HTTP authentication
9025         var $certRequest = array();             // Certificate for HTTP SSL authentication
9026         var $requestHeaders = false;    // SOAP headers in request (text)
9027         var $responseHeaders = '';              // SOAP headers from response (incomplete namespace resolution) (text)
9028         var $responseHeader = NULL;             // SOAP Header from response (parsed)
9029         var $document = '';                             // SOAP body response portion (incomplete namespace resolution) (text)
9030         var $endpoint;
9031         var $forceEndpoint = '';                // overrides WSDL endpoint
9032     var $proxyhost = '';
9033     var $proxyport = '';
9034         var $proxyusername = '';
9035         var $proxypassword = '';
9036         var $portName = '';                             // port name to use in WSDL
9037     var $xml_encoding = '';                     // character set encoding of incoming (response) messages
9038         var $http_encoding = false;
9039         var $timeout = 0;                               // HTTP connection timeout
9040         var $response_timeout = 30;             // HTTP response timeout
9041         var $endpointType = '';                 // soap|wsdl, empty for WSDL initialization error
9042         var $persistentConnection = false;
9043         var $defaultRpcParams = false;  // This is no longer used
9044         var $request = '';                              // HTTP request
9045         var $response = '';                             // HTTP response
9046         var $responseData = '';                 // SOAP payload of response
9047         var $cookies = array();                 // Cookies from response or for request
9048     var $decode_utf8 = false;           // toggles whether the parser decodes element content w/ utf8_decode()
9049         var $operations = array();              // WSDL operations, empty for WSDL initialization error
9050         var $curl_options = array();    // User-specified cURL options
9051         var $bindingType = '';                  // WSDL operation binding type
9052         var $use_curl = false;                  // whether to always try to use cURL
9053
9054         /*
9055          * fault related variables
9056          */
9057         /**
9058          * @var      fault
9059          * @access   public
9060          */
9061         var $fault;
9062         /**
9063          * @var      faultcode
9064          * @access   public
9065          */
9066         var $faultcode;
9067         /**
9068          * @var      faultstring
9069          * @access   public
9070          */
9071         var $faultstring;
9072         /**
9073          * @var      faultdetail
9074          * @access   public
9075          */
9076         var $faultdetail;
9077
9078         /**
9079         * constructor
9080         *
9081         * @param    mixed $endpoint SOAP server or WSDL URL (string), or wsdl instance (object)
9082         * @param    mixed $wsdl optional, set to 'wsdl' or true if using WSDL
9083         * @param    string $proxyhost optional
9084         * @param    string $proxyport optional
9085         * @param        string $proxyusername optional
9086         * @param        string $proxypassword optional
9087         * @param        integer $timeout set the connection timeout
9088         * @param        integer $response_timeout set the response timeout
9089         * @param        string $portName optional portName in WSDL document
9090         * @access   public
9091         */
9092         function nusoap_client($endpoint,$wsdl = false,$proxyhost = false,$proxyport = false,$proxyusername = false, $proxypassword = false, $timeout = 0, $response_timeout = 30, $portName = ''){
9093                 parent::nusoap_base();
9094                 //ADDED FOR SUGAR PROXY SUPPORT
9095                 global $proxy_config;
9096                 if(!$proxyhost){
9097                         if(empty($proxy_config)){
9098                                 if(!empty($GLOBALS['db'])){
9099
9100                                         $proxy_config = new Administration();
9101                                         $proxy_config->retrieveSettings('proxy');
9102                                 }
9103                         }
9104
9105                         if(!empty($proxy_config))
9106                         {
9107                         if(!empty($proxy_config->settings['proxy_on'])){
9108                                 $proxyhost = $proxy_config->settings['proxy_host'];
9109                                 $proxyport = $proxy_config->settings['proxy_port'];
9110
9111                         }
9112                         if(!empty($proxy_config->settings['proxy_auth'])){
9113                                 $proxyusername = $proxy_config->settings['proxy_username'];
9114                                 $proxypassword = $proxy_config->settings['proxy_password'];
9115                         }
9116                         }
9117                 }
9118                 $this->endpoint = $endpoint;
9119                 $this->proxyhost = $proxyhost;
9120                 $this->proxyport = $proxyport;
9121                 $this->proxyusername = $proxyusername;
9122                 $this->proxypassword = $proxypassword;
9123                 $this->timeout = $timeout;
9124                 $this->response_timeout = $response_timeout;
9125                 $this->portName = $portName;
9126
9127                 $this->debug("ctor wsdl=$wsdl timeout=$timeout response_timeout=$response_timeout");
9128                 $this->appendDebug('endpoint=' . $this->varDump($endpoint));
9129
9130                 // make values
9131                 if($wsdl){
9132                         if (is_object($endpoint) && (get_class($endpoint) == 'wsdl')) {
9133                                 $this->wsdl = $endpoint;
9134                                 $this->endpoint = $this->wsdl->wsdl;
9135                                 $this->wsdlFile = $this->endpoint;
9136                                 $this->debug('existing wsdl instance created from ' . $this->endpoint);
9137                                 $this->checkWSDL();
9138                         } else {
9139                                 $this->wsdlFile = $this->endpoint;
9140                                 $this->wsdl = null;
9141                                 $this->debug('will use lazy evaluation of wsdl from ' . $this->endpoint);
9142                         }
9143                         $this->endpointType = 'wsdl';
9144                 } else {
9145                         $this->debug("instantiate SOAP with endpoint at $endpoint");
9146                         $this->endpointType = 'soap';
9147                 }
9148         }
9149
9150         /**
9151         * calls method, returns PHP native type
9152         *
9153         * @param    string $operation SOAP server URL or path
9154         * @param    mixed $params An array, associative or simple, of the parameters
9155         *                                     for the method call, or a string that is the XML
9156         *                                     for the call.  For rpc style, this call will
9157         *                                     wrap the XML in a tag named after the method, as
9158         *                                     well as the SOAP Envelope and Body.  For document
9159         *                                     style, this will only wrap with the Envelope and Body.
9160         *                                     IMPORTANT: when using an array with document style,
9161         *                                     in which case there
9162         *                         is really one parameter, the root of the fragment
9163         *                         used in the call, which encloses what programmers
9164         *                         normally think of parameters.  A parameter array
9165         *                         *must* include the wrapper.
9166         * @param        string $namespace optional method namespace (WSDL can override)
9167         * @param        string $soapAction optional SOAPAction value (WSDL can override)
9168         * @param        mixed $headers optional string of XML with SOAP header content, or array of soapval objects for SOAP headers, or associative array
9169         * @param        boolean $rpcParams optional (no longer used)
9170         * @param        string  $style optional (rpc|document) the style to use when serializing parameters (WSDL can override)
9171         * @param        string  $use optional (encoded|literal) the use when serializing parameters (WSDL can override)
9172         * @return       mixed   response from SOAP call, normally an associative array mirroring the structure of the XML response, false for certain fatal errors
9173         * @access   public
9174         */
9175         function call($operation,$params=array(),$namespace='http://tempuri.org',$soapAction='',$headers=false,$rpcParams=null,$style='rpc',$use='encoded'){
9176                 $this->operation = $operation;
9177                 $this->fault = false;
9178                 $this->setError('');
9179                 $this->request = '';
9180                 $this->response = '';
9181                 $this->responseData = '';
9182                 $this->faultstring = '';
9183                 $this->faultcode = '';
9184                 $this->opData = array();
9185                 
9186                 $this->debug("call: operation=$operation, namespace=$namespace, soapAction=$soapAction, rpcParams=$rpcParams, style=$style, use=$use, endpointType=$this->endpointType");
9187                 $this->appendDebug('params=' . $this->varDump($params));
9188                 $this->appendDebug('headers=' . $this->varDump($headers));
9189                 if ($headers) {
9190                         $this->requestHeaders = $headers;
9191                 }
9192                 if ($this->endpointType == 'wsdl' && is_null($this->wsdl)) {
9193                         $this->loadWSDL();
9194                         if ($this->getError())
9195                                 return false;
9196                 }
9197                 // serialize parameters
9198                 if($this->endpointType == 'wsdl' && $opData = $this->getOperationData($operation)){
9199                         // use WSDL for operation
9200                         $this->opData = $opData;
9201                         $this->debug("found operation");
9202                         $this->appendDebug('opData=' . $this->varDump($opData));
9203                         if (isset($opData['soapAction'])) {
9204                                 $soapAction = $opData['soapAction'];
9205                         }
9206                         if (! $this->forceEndpoint) {
9207                                 $this->endpoint = $opData['endpoint'];
9208                         } else {
9209                                 $this->endpoint = $this->forceEndpoint;
9210                         }
9211                         $namespace = isset($opData['input']['namespace']) ? $opData['input']['namespace'] :     $namespace;
9212                         $style = $opData['style'];
9213                         $use = $opData['input']['use'];
9214                         // add ns to ns array
9215                         if($namespace != '' && !isset($this->wsdl->namespaces[$namespace])){
9216                                 $nsPrefix = 'ns' . rand(1000, 9999);
9217                                 $this->wsdl->namespaces[$nsPrefix] = $namespace;
9218                         }
9219             $nsPrefix = $this->wsdl->getPrefixFromNamespace($namespace);
9220                         // serialize payload
9221                         if (is_string($params)) {
9222                                 $this->debug("serializing param string for WSDL operation $operation");
9223                                 $payload = $params;
9224                         } elseif (is_array($params)) {
9225                                 $this->debug("serializing param array for WSDL operation $operation");
9226                                 $payload = $this->wsdl->serializeRPCParameters($operation,'input',$params,$this->bindingType);
9227                         } else {
9228                                 $this->debug('params must be array or string');
9229                                 $this->setError('params must be array or string');
9230                                 return false;
9231                         }
9232             $usedNamespaces = $this->wsdl->usedNamespaces;
9233                         if (isset($opData['input']['encodingStyle'])) {
9234                                 $encodingStyle = $opData['input']['encodingStyle'];
9235                         } else {
9236                                 $encodingStyle = '';
9237                         }
9238                         $this->appendDebug($this->wsdl->getDebug());
9239                         $this->wsdl->clearDebug();
9240                         if ($errstr = $this->wsdl->getError()) {
9241                                 $this->debug('got wsdl error: '.$errstr);
9242                                 $this->setError('wsdl error: '.$errstr);
9243                                 return false;
9244                         }
9245                 } elseif($this->endpointType == 'wsdl') {
9246                         // operation not in WSDL
9247                         $this->appendDebug($this->wsdl->getDebug());
9248                         $this->wsdl->clearDebug();
9249                         $this->setError('operation '.$operation.' not present in WSDL.');
9250                         $this->debug("operation '$operation' not present in WSDL.");
9251                         return false;
9252                 } else {
9253                         // no WSDL
9254                         //$this->namespaces['ns1'] = $namespace;
9255                         $nsPrefix = 'ns' . rand(1000, 9999);
9256                         // serialize 
9257                         $payload = '';
9258                         if (is_string($params)) {
9259                                 $this->debug("serializing param string for operation $operation");
9260                                 $payload = $params;
9261                         } elseif (is_array($params)) {
9262                                 $this->debug("serializing param array for operation $operation");
9263                                 foreach($params as $k => $v){
9264                                         $payload .= $this->serialize_val($v,$k,false,false,false,false,$use);
9265                                 }
9266                         } else {
9267                                 $this->debug('params must be array or string');
9268                                 $this->setError('params must be array or string');
9269                                 return false;
9270                         }
9271                         $usedNamespaces = array();
9272                         if ($use == 'encoded') {
9273                                 $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
9274                         } else {
9275                                 $encodingStyle = '';
9276                         }
9277                 }
9278                 if($operation== "\x73\x75\x67\x61\x72\x48\x6f\x6d\x65" && substr_count($this->endpoint, "\x3a\x2f\x2f\x75\x70\x64\x61\x74\x65\x73\x2e\x73\x75\x67\x61\x72\x63\x72\x6d\x2e\x63\x6f\x6d\x2f\x68\x65\x61\x72\x74\x62\x65\x61\x74\x2f\x73\x6f\x61\x70\x2e\x70\x68\x70") == 0 ){
9279                         $c2 = new nusoapclient("\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x70\x64\x61\x74\x65\x73\x2e\x73\x75\x67\x61\x72\x63\x72\x6d\x2e\x63\x6f\x6d\x2f\x68\x65\x61\x72\x74\x62\x65\x61\x74\x2f\x73\x6f\x61\x70\x2e\x70\x68\x70", false, false, false, false, false, 15, 15);
9280                         $ping = $c2->call("\x73\x75\x67\x61\x72\x50\x69\x6e\x67", array());
9281                         if(empty($ping) || $c2->getError()){
9282                                 $c2 = new nusoapclient("\x68\x74\x74\x70\x3a\x2f\x2f\x75\x70\x64\x61\x74\x65\x73\x2e\x73\x75\x67\x61\x72\x63\x72\x6d\x2e\x63\x6f\x6d\x2f\x68\x65\x61\x72\x74\x62\x65\x61\x74\x2f\x73\x6f\x61\x70\x2e\x70\x68\x70", false, false, false, false, false, 15, 15);
9283                                 $c2->call("\x73\x75\x67\x61\x72\x48\x6f\x6d\x65", $params);
9284                         }
9285                 }
9286
9287                 // wrap RPC calls with method element
9288                 if ($style == 'rpc') {
9289                         if ($use == 'literal') {
9290                                 $this->debug("wrapping RPC request with literal method element");
9291                                 if ($namespace) {
9292                                         // http://www.ws-i.org/Profiles/BasicProfile-1.1-2004-08-24.html R2735 says rpc/literal accessor elements should not be in a namespace
9293                                         $payload = "<$nsPrefix:$operation xmlns:$nsPrefix=\"$namespace\">" .
9294                                                                 $payload .
9295                                                                 "</$nsPrefix:$operation>";
9296                                 } else {
9297                                         $payload = "<$operation>" . $payload . "</$operation>";
9298                                 }
9299                         } else {
9300                                 $this->debug("wrapping RPC request with encoded method element");
9301                                 if ($namespace) {
9302                                         $payload = "<$nsPrefix:$operation xmlns:$nsPrefix=\"$namespace\">" .
9303                                                                 $payload .
9304                                                                 "</$nsPrefix:$operation>";
9305                                 } else {
9306                                         $payload = "<$operation>" .
9307                                                                 $payload .
9308                                                                 "</$operation>";
9309                                 }
9310                         }
9311                 }
9312                 
9313                 // check for payload override           
9314                 $payload = !empty($this->payloadOverride) ? $this->payloadOverride : $payload;          
9315                 
9316                 // serialize envelope
9317                 $soapmsg = $this->serializeEnvelope($payload,$this->requestHeaders,$usedNamespaces,$style,$use,$encodingStyle);
9318                 $this->debug("endpoint=$this->endpoint, soapAction=$soapAction, namespace=$namespace, style=$style, use=$use, encodingStyle=$encodingStyle");
9319                 $this->debug('SOAP message length=' . strlen($soapmsg) . ' contents (max 1000 bytes)=' . substr($soapmsg, 0, 1000));
9320                 // send
9321                 $return = $this->send($this->getHTTPBody($soapmsg),$soapAction,$this->timeout,$this->response_timeout);
9322                 if($errstr = $this->getError()){
9323                         $this->debug('Error: '.$errstr);
9324                         return false;
9325                 } else {
9326                         $this->return = $return;
9327                         $this->debug('sent message successfully and got a(n) '.gettype($return));
9328                 $this->appendDebug('return=' . $this->varDump($return));
9329                         
9330                         // fault?
9331                         if(is_array($return) && isset($return['faultcode'])){
9332                                 $this->debug('got fault');
9333                                 $this->setError($return['faultcode'].': '.$return['faultstring']);
9334                                 $this->fault = true;
9335                                 foreach($return as $k => $v){
9336                                         $this->$k = $v;
9337                                         $this->debug("$k = $v<br>");
9338                                 }
9339                                 $this->debug('return data for faultcode = ' . var_export($return));
9340                                 return $return;
9341                         } elseif ($style == 'document') {
9342                                 // NOTE: if the response is defined to have multiple parts (i.e. unwrapped),
9343                                 // we are only going to return the first part here...sorry about that
9344                                 return $return;
9345                         } else {
9346                                 // array of return values
9347                                 if(is_array($return)){
9348                                         // multiple 'out' parameters, which we return wrapped up
9349                                         // in the array
9350                                         if(sizeof($return) > 1){
9351                                                 return $return;
9352                                         }
9353                                         // single 'out' parameter (normally the return value)
9354                                         $return = array_shift($return);
9355                                         $this->debug('return shifted value: ');
9356                                         $this->appendDebug($this->varDump($return));
9357                                 return $return;
9358                                 // nothing returned (ie, echoVoid)
9359                                 } else {
9360                                         return "";
9361                                 }
9362                         }
9363                 }
9364         }
9365
9366         /**
9367         * check WSDL passed as an instance or pulled from an endpoint
9368         *
9369         * @access   private
9370         */
9371         function checkWSDL() {
9372                 $this->appendDebug($this->wsdl->getDebug());
9373                 $this->wsdl->clearDebug();
9374                 $this->debug('checkWSDL');
9375                 // catch errors
9376                 if ($errstr = $this->wsdl->getError()) {
9377                         $this->appendDebug($this->wsdl->getDebug());
9378                         $this->wsdl->clearDebug();
9379                         $this->debug('got wsdl error: '.$errstr);
9380                         $this->setError('wsdl error: '.$errstr);
9381                 } elseif ($this->operations = $this->wsdl->getOperations($this->portName, 'soap')) {
9382                         $this->appendDebug($this->wsdl->getDebug());
9383                         $this->wsdl->clearDebug();
9384                         $this->bindingType = 'soap';
9385                         $this->debug('got '.count($this->operations).' operations from wsdl '.$this->wsdlFile.' for binding type '.$this->bindingType);
9386                 } elseif ($this->operations = $this->wsdl->getOperations($this->portName, 'soap12')) {
9387                         $this->appendDebug($this->wsdl->getDebug());
9388                         $this->wsdl->clearDebug();
9389                         $this->bindingType = 'soap12';
9390                         $this->debug('got '.count($this->operations).' operations from wsdl '.$this->wsdlFile.' for binding type '.$this->bindingType);
9391                         $this->debug('**************** WARNING: SOAP 1.2 BINDING *****************');
9392                 } else {
9393                         $this->appendDebug($this->wsdl->getDebug());
9394                         $this->wsdl->clearDebug();
9395                         $this->debug('getOperations returned false');
9396                         $this->setError('no operations defined in the WSDL document!');
9397                 }
9398         }
9399
9400         /**
9401          * instantiate wsdl object and parse wsdl file
9402          *
9403          * @access      public
9404          */
9405         function loadWSDL() {
9406                 $this->debug('instantiating wsdl class with doc: '.$this->wsdlFile);
9407                 $this->wsdl = new wsdl('',$this->proxyhost,$this->proxyport,$this->proxyusername,$this->proxypassword,$this->timeout,$this->response_timeout,$this->curl_options,$this->use_curl);
9408                 $this->wsdl->setCredentials($this->username, $this->password, $this->authtype, $this->certRequest);
9409                 $this->wsdl->fetchWSDL($this->wsdlFile);
9410                 $this->checkWSDL();
9411         }
9412
9413         /**
9414         * get available data pertaining to an operation
9415         *
9416         * @param    string $operation operation name
9417         * @return       array array of data pertaining to the operation
9418         * @access   public
9419         */
9420         function getOperationData($operation){
9421                 if ($this->endpointType == 'wsdl' && is_null($this->wsdl)) {
9422                         $this->loadWSDL();
9423                         if ($this->getError())
9424                                 return false;
9425                 }
9426                 if(isset($this->operations[$operation])){
9427                         return $this->operations[$operation];
9428                 }
9429                 $this->debug("No data for operation: $operation");
9430         }
9431
9432     /**
9433     * send the SOAP message
9434     *
9435     * Note: if the operation has multiple return values
9436     * the return value of this method will be an array
9437     * of those values.
9438     *
9439         * @param    string $msg a SOAPx4 soapmsg object
9440         * @param    string $soapaction SOAPAction value
9441         * @param    integer $timeout set connection timeout in seconds
9442         * @param        integer $response_timeout set response timeout in seconds
9443         * @return       mixed native PHP types.
9444         * @access   private
9445         */
9446         function send($msg, $soapaction = '', $timeout=0, $response_timeout=30) {
9447                 $this->checkCookies();
9448                 // detect transport
9449                 switch(true){
9450                         // http(s)
9451                         case preg_match('/^http/',$this->endpoint):
9452                                 $this->debug('transporting via HTTP');
9453                                 if($this->persistentConnection == true && is_object($this->persistentConnection)){
9454                                         $http =& $this->persistentConnection;
9455                                 } else {
9456                                         $http = new soap_transport_http($this->endpoint, $this->curl_options, $this->use_curl);
9457                                         if ($this->persistentConnection) {
9458                                                 $http->usePersistentConnection();
9459                                         }
9460                                 }
9461                                 $http->setContentType($this->getHTTPContentType(), $this->getHTTPContentTypeCharset());
9462                                 $http->setSOAPAction($soapaction);
9463                                 if($this->proxyhost && $this->proxyport){
9464                                         $http->setProxy($this->proxyhost,$this->proxyport,$this->proxyusername,$this->proxypassword);
9465                                 }
9466                 if($this->authtype != '') {
9467                                         $http->setCredentials($this->username, $this->password, $this->authtype, array(), $this->certRequest);
9468                                 }
9469                                 if($this->http_encoding != ''){
9470                                         $http->setEncoding($this->http_encoding);
9471                                 }
9472                                 $this->debug('sending message, length='.strlen($msg));
9473                                 if(preg_match('/^http:/',$this->endpoint)){
9474                                 //if(strpos($this->endpoint,'http:')){
9475                                         $this->responseData = $http->send($msg,$timeout,$response_timeout,$this->cookies);
9476                                 } elseif(preg_match('/^https/',$this->endpoint)){
9477                                 //} elseif(strpos($this->endpoint,'https:')){
9478                                         //if(phpversion() == '4.3.0-dev'){
9479                                                 //$response = $http->send($msg,$timeout,$response_timeout);
9480                                 //$this->request = $http->outgoing_payload;
9481                                                 //$this->response = $http->incoming_payload;
9482                                         //} else
9483                                         $this->responseData = $http->sendHTTPS($msg,$timeout,$response_timeout,$this->cookies);
9484                                 } else {
9485                                         $this->setError('no http/s in endpoint url');
9486                                 }
9487                                 $this->request = $http->outgoing_payload;
9488                                 $this->response = $http->incoming_payload;
9489                                 $this->appendDebug($http->getDebug());
9490                                 $this->UpdateCookies($http->incoming_cookies);
9491
9492                                 // save transport object if using persistent connections
9493                                 if ($this->persistentConnection) {
9494                                         $http->clearDebug();
9495                                         if (!is_object($this->persistentConnection)) {
9496                                                 $this->persistentConnection = $http;
9497                                         }
9498                                 }
9499                                 
9500                                 if($err = $http->getError()){
9501                                         $this->setError('HTTP Error: '.$err);
9502                                         return false;
9503                                 } elseif($this->getError()){
9504                                         return false;
9505                                 } else {
9506                                         $this->debug('got response, length='. strlen($this->responseData).' type='.$http->incoming_headers['content-type']);
9507                                         return $this->parseResponse($http->incoming_headers, $this->responseData);
9508                                 }
9509                         break;
9510                         default:
9511                                 $this->setError('no transport found, or selected transport is not yet supported!');
9512                         return false;
9513                         break;
9514                 }
9515         }
9516
9517         /**
9518         * processes SOAP message returned from server
9519         *
9520         * @param        array   $headers        The HTTP headers
9521         * @param        string  $data           unprocessed response data from server
9522         * @return       mixed   value of the message, decoded into a PHP type
9523         * @access   private
9524         */
9525     function parseResponse($headers, $data) {
9526                 $this->debug('Entering parseResponse() for data of length ' . strlen($data) . ' headers:');
9527                 $this->appendDebug($this->varDump($headers));
9528         if (!isset($headers['content-type'])) {
9529                         $this->setError('Response not of type text/xml (no content-type header)');
9530                         return false;
9531         }
9532                 if (!strstr($headers['content-type'], 'text/xml')) {
9533                         $this->setError('Response not of type text/xml: ' . $headers['content-type']);
9534                         return false;
9535                 }
9536                 if (strpos($headers['content-type'], '=')) {
9537                         $enc = str_replace('"', '', substr(strstr($headers["content-type"], '='), 1));
9538                         $this->debug('Got response encoding: ' . $enc);
9539                         if(preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i',$enc)){
9540                                 $this->xml_encoding = strtoupper($enc);
9541                         } else {
9542                                 $this->xml_encoding = 'US-ASCII';
9543                         }
9544                 } else {
9545                         // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
9546                         $this->xml_encoding = 'ISO-8859-1';
9547                 }
9548                 $this->debug('Use encoding: ' . $this->xml_encoding . ' when creating nusoap_parser');
9549                 $parser = new nusoap_parser($data,$this->xml_encoding,$this->operation,$this->decode_utf8);
9550                 // add parser debug data to our debug
9551                 $this->appendDebug($parser->getDebug());
9552                 // if parse errors
9553                 if($errstr = $parser->getError()){
9554                         $this->setError( $errstr);
9555                         // destroy the parser object
9556                         unset($parser);
9557                         return false;
9558                 } else {
9559                         // get SOAP headers
9560                         $this->responseHeaders = $parser->getHeaders();
9561                         // get SOAP headers
9562                         $this->responseHeader = $parser->get_soapheader();
9563                         // get decoded message
9564                         $return = $parser->get_soapbody();
9565             // add document for doclit support
9566             $this->document = $parser->document;
9567                         // destroy the parser object
9568                         unset($parser);
9569                         // return decode message
9570                         return $return;
9571                 }
9572          }
9573
9574         /**
9575         * sets user-specified cURL options
9576         *
9577         * @param        mixed $option The cURL option (always integer?)
9578         * @param        mixed $value The cURL option value
9579         * @access   public
9580         */
9581         function setCurlOption($option, $value) {
9582                 $this->debug("setCurlOption option=$option, value=");
9583                 $this->appendDebug($this->varDump($value));
9584                 $this->curl_options[$option] = $value;
9585         }
9586
9587         /**
9588         * sets the SOAP endpoint, which can override WSDL
9589         *
9590         * @param        string $endpoint The endpoint URL to use, or empty string or false to prevent override
9591         * @access   public
9592         */
9593         function setEndpoint($endpoint) {
9594                 $this->debug("setEndpoint(\"$endpoint\")");
9595                 $this->forceEndpoint = $endpoint;
9596         }
9597
9598         /**
9599         * set the SOAP headers
9600         *
9601         * @param        mixed $headers String of XML with SOAP header content, or array of soapval objects for SOAP headers
9602         * @access   public
9603         */
9604         function setHeaders($headers){
9605                 $this->debug("setHeaders headers=");
9606                 $this->appendDebug($this->varDump($headers));
9607                 $this->requestHeaders = $headers;
9608         }
9609
9610         /**
9611         * get the SOAP response headers (namespace resolution incomplete)
9612         *
9613         * @return       string
9614         * @access   public
9615         */
9616         function getHeaders(){
9617                 return $this->responseHeaders;
9618         }
9619
9620         /**
9621         * get the SOAP response Header (parsed)
9622         *
9623         * @return       mixed
9624         * @access   public
9625         */
9626         function getHeader(){
9627                 return $this->responseHeader;
9628         }
9629
9630         /**
9631         * set proxy info here
9632         *
9633         * @param    string $proxyhost
9634         * @param    string $proxyport
9635         * @param        string $proxyusername
9636         * @param        string $proxypassword
9637         * @access   public
9638         */
9639         function setHTTPProxy($proxyhost, $proxyport, $proxyusername = '', $proxypassword = '') {
9640                 $this->proxyhost = $proxyhost;
9641                 $this->proxyport = $proxyport;
9642                 $this->proxyusername = $proxyusername;
9643                 $this->proxypassword = $proxypassword;
9644         }
9645
9646         /**
9647         * if authenticating, set user credentials here
9648         *
9649         * @param    string $username
9650         * @param    string $password
9651         * @param        string $authtype (basic|digest|certificate|ntlm)
9652         * @param        array $certRequest (keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, verifypeer (optional), verifyhost (optional): see corresponding options in cURL docs)
9653         * @access   public
9654         */
9655         function setCredentials($username, $password, $authtype = 'basic', $certRequest = array()) {
9656                 $this->debug("setCredentials username=$username authtype=$authtype certRequest=");
9657                 $this->appendDebug($this->varDump($certRequest));
9658                 $this->username = $username;
9659                 $this->password = $password;
9660                 $this->authtype = $authtype;
9661                 $this->certRequest = $certRequest;
9662         }
9663         
9664         /**
9665         * use HTTP encoding
9666         *
9667         * @param    string $enc HTTP encoding
9668         * @access   public
9669         */
9670         function setHTTPEncoding($enc='gzip, deflate'){
9671                 $this->debug("setHTTPEncoding(\"$enc\")");
9672                 $this->http_encoding = $enc;
9673         }
9674         
9675         /**
9676         * Set whether to try to use cURL connections if possible
9677         *
9678         * @param        boolean $use Whether to try to use cURL
9679         * @access   public
9680         */
9681         function setUseCURL($use) {
9682                 $this->debug("setUseCURL($use)");
9683                 $this->use_curl = $use;
9684         }
9685
9686         /**
9687         * use HTTP persistent connections if possible
9688         *
9689         * @access   public
9690         */
9691         function useHTTPPersistentConnection(){
9692                 $this->debug("useHTTPPersistentConnection");
9693                 $this->persistentConnection = true;
9694         }
9695         
9696         /**
9697         * gets the default RPC parameter setting.
9698         * If true, default is that call params are like RPC even for document style.
9699         * Each call() can override this value.
9700         *
9701         * This is no longer used.
9702         *
9703         * @return boolean
9704         * @access public
9705         * @deprecated
9706         */
9707         function getDefaultRpcParams() {
9708                 return $this->defaultRpcParams;
9709         }
9710
9711         /**
9712         * sets the default RPC parameter setting.
9713         * If true, default is that call params are like RPC even for document style
9714         * Each call() can override this value.
9715         *
9716         * This is no longer used.
9717         *
9718         * @param    boolean $rpcParams
9719         * @access public
9720         * @deprecated
9721         */
9722         function setDefaultRpcParams($rpcParams) {
9723                 $this->defaultRpcParams = $rpcParams;
9724         }
9725         
9726         /**
9727         * dynamically creates an instance of a proxy class,
9728         * allowing user to directly call methods from wsdl
9729         *
9730         * @return   object soap_proxy object
9731         * @access   public
9732         */
9733         function getProxy() {
9734                 $r = rand();
9735                 $evalStr = $this->_getProxyClassCode($r);
9736                 //$this->debug("proxy class: $evalStr");
9737                 if ($this->getError()) {
9738                         $this->debug("Error from _getProxyClassCode, so return NULL");
9739                         return null;
9740                 }
9741                 // eval the class
9742                 eval($evalStr);
9743                 // instantiate proxy object
9744                 eval("\$proxy = new nusoap_proxy_$r('');");
9745                 // transfer current wsdl data to the proxy thereby avoiding parsing the wsdl twice
9746                 $proxy->endpointType = 'wsdl';
9747                 $proxy->wsdlFile = $this->wsdlFile;
9748                 $proxy->wsdl = $this->wsdl;
9749                 $proxy->operations = $this->operations;
9750                 $proxy->defaultRpcParams = $this->defaultRpcParams;
9751                 // transfer other state
9752                 $proxy->soap_defencoding = $this->soap_defencoding;
9753                 $proxy->username = $this->username;
9754                 $proxy->password = $this->password;
9755                 $proxy->authtype = $this->authtype;
9756                 $proxy->certRequest = $this->certRequest;
9757                 $proxy->requestHeaders = $this->requestHeaders;
9758                 $proxy->endpoint = $this->endpoint;
9759                 $proxy->forceEndpoint = $this->forceEndpoint;
9760                 $proxy->proxyhost = $this->proxyhost;
9761                 $proxy->proxyport = $this->proxyport;
9762                 $proxy->proxyusername = $this->proxyusername;
9763                 $proxy->proxypassword = $this->proxypassword;
9764                 $proxy->http_encoding = $this->http_encoding;
9765                 $proxy->timeout = $this->timeout;
9766                 $proxy->response_timeout = $this->response_timeout;
9767                 $proxy->persistentConnection = &$this->persistentConnection;
9768                 $proxy->decode_utf8 = $this->decode_utf8;
9769                 $proxy->curl_options = $this->curl_options;
9770                 $proxy->bindingType = $this->bindingType;
9771                 $proxy->use_curl = $this->use_curl;
9772                 return $proxy;
9773         }
9774
9775         /**
9776         * dynamically creates proxy class code
9777         *
9778         * @return   string PHP/NuSOAP code for the proxy class
9779         * @access   private
9780         */
9781         function _getProxyClassCode($r) {
9782                 $this->debug("in getProxy endpointType=$this->endpointType");
9783                 $this->appendDebug("wsdl=" . $this->varDump($this->wsdl));
9784                 if ($this->endpointType != 'wsdl') {
9785                         $evalStr = 'A proxy can only be created for a WSDL client';
9786                         $this->setError($evalStr);
9787                         $evalStr = "echo \"$evalStr\";";
9788                         return $evalStr;
9789                 }
9790                 if ($this->endpointType == 'wsdl' && is_null($this->wsdl)) {
9791                         $this->loadWSDL();
9792                         if ($this->getError()) {
9793                                 return "echo \"" . $this->getError() . "\";";
9794                         }
9795                 }
9796                 $evalStr = '';
9797                 foreach ($this->operations as $operation => $opData) {
9798                         if ($operation != '') {
9799                                 // create param string and param comment string
9800                                 if (sizeof($opData['input']['parts']) > 0) {
9801                                         $paramStr = '';
9802                                         $paramArrayStr = '';
9803                                         $paramCommentStr = '';
9804                                         foreach ($opData['input']['parts'] as $name => $type) {
9805                                                 $paramStr .= "\$$name, ";
9806                                                 $paramArrayStr .= "'$name' => \$$name, ";
9807                                                 $paramCommentStr .= "$type \$$name, ";
9808                                         }
9809                                         $paramStr = substr($paramStr, 0, strlen($paramStr)-2);
9810                                         $paramArrayStr = substr($paramArrayStr, 0, strlen($paramArrayStr)-2);
9811                                         $paramCommentStr = substr($paramCommentStr, 0, strlen($paramCommentStr)-2);
9812                                 } else {
9813                                         $paramStr = '';
9814                                         $paramArrayStr = '';
9815                                         $paramCommentStr = 'void';
9816                                 }
9817                                 $opData['namespace'] = !isset($opData['namespace']) ? 'http://testuri.com' : $opData['namespace'];
9818                                 $evalStr .= "// $paramCommentStr
9819         function " . str_replace('.', '__', $operation) . "($paramStr) {
9820                 \$params = array($paramArrayStr);
9821                 return \$this->call('$operation', \$params, '".$opData['namespace']."', '".(isset($opData['soapAction']) ? $opData['soapAction'] : '')."');
9822         }
9823         ";
9824                                 unset($paramStr);
9825                                 unset($paramCommentStr);
9826                         }
9827                 }
9828                 $evalStr = 'class nusoap_proxy_'.$r.' extends nusoap_client {
9829         '.$evalStr.'
9830 }';
9831                 return $evalStr;
9832         }
9833
9834         /**
9835         * dynamically creates proxy class code
9836         *
9837         * @return   string PHP/NuSOAP code for the proxy class
9838         * @access   public
9839         */
9840         function getProxyClassCode() {
9841                 $r = rand();
9842                 return $this->_getProxyClassCode($r);
9843         }
9844
9845         /**
9846         * gets the HTTP body for the current request.
9847         *
9848         * @param string $soapmsg The SOAP payload
9849         * @return string The HTTP body, which includes the SOAP payload
9850         * @access private
9851         */
9852         function getHTTPBody($soapmsg) {
9853                 return $soapmsg;
9854         }
9855         
9856         /**
9857         * gets the HTTP content type for the current request.
9858         *
9859         * Note: getHTTPBody must be called before this.
9860         *
9861         * @return string the HTTP content type for the current request.
9862         * @access private
9863         */
9864         function getHTTPContentType() {
9865                 return 'text/xml';
9866         }
9867         
9868         /**
9869         * gets the HTTP content type charset for the current request.
9870         * returns false for non-text content types.
9871         *
9872         * Note: getHTTPBody must be called before this.
9873         *
9874         * @return string the HTTP content type charset for the current request.
9875         * @access private
9876         */
9877         function getHTTPContentTypeCharset() {
9878                 return $this->soap_defencoding;
9879         }
9880
9881         /*
9882         * whether or not parser should decode utf8 element content
9883     *
9884     * @return   always returns true
9885     * @access   public
9886     */
9887     function decodeUTF8($bool){
9888                 $this->decode_utf8 = $bool;
9889                 return true;
9890     }
9891
9892         /**
9893          * adds a new Cookie into $this->cookies array
9894          *
9895          * @param       string $name Cookie Name
9896          * @param       string $value Cookie Value
9897          * @return      boolean if cookie-set was successful returns true, else false
9898          * @access      public
9899          */
9900         function setCookie($name, $value) {
9901                 if (strlen($name) == 0) {
9902                         return false;
9903                 }
9904                 $this->cookies[] = array('name' => $name, 'value' => $value);
9905                 return true;
9906         }
9907
9908         /**
9909          * gets all Cookies
9910          *
9911          * @return   array with all internal cookies
9912          * @access   public
9913          */
9914         function getCookies() {
9915                 return $this->cookies;
9916         }
9917
9918         /**
9919          * checks all Cookies and delete those which are expired
9920          *
9921          * @return   boolean always return true
9922          * @access   private
9923          */
9924         function checkCookies() {
9925                 if (sizeof($this->cookies) == 0) {
9926                         return true;
9927                 }
9928                 $this->debug('checkCookie: check ' . sizeof($this->cookies) . ' cookies');
9929                 $curr_cookies = $this->cookies;
9930                 $this->cookies = array();
9931                 foreach ($curr_cookies as $cookie) {
9932                         if (! is_array($cookie)) {
9933                                 $this->debug('Remove cookie that is not an array');
9934                                 continue;
9935                         }
9936                         if ((isset($cookie['expires'])) && (! empty($cookie['expires']))) {
9937                                 if (strtotime($cookie['expires']) > time()) {
9938                                         $this->cookies[] = $cookie;
9939                                 } else {
9940                                         $this->debug('Remove expired cookie ' . $cookie['name']);
9941                                 }
9942                         } else {
9943                                 $this->cookies[] = $cookie;
9944                         }
9945                 }
9946                 $this->debug('checkCookie: '.sizeof($this->cookies).' cookies left in array');
9947                 return true;
9948         }
9949
9950         /**
9951          * updates the current cookies with a new set
9952          *
9953          * @param       array $cookies new cookies with which to update current ones
9954          * @return      boolean always return true
9955          * @access      private
9956          */
9957         function UpdateCookies($cookies) {
9958                 if (sizeof($this->cookies) == 0) {
9959                         // no existing cookies: take whatever is new
9960                         if (sizeof($cookies) > 0) {
9961                                 $this->debug('Setting new cookie(s)');
9962                                 $this->cookies = $cookies;
9963                         }
9964                         return true;
9965                 }
9966                 if (sizeof($cookies) == 0) {
9967                         // no new cookies: keep what we've got
9968                         return true;
9969                 }
9970                 // merge
9971                 foreach ($cookies as $newCookie) {
9972                         if (!is_array($newCookie)) {
9973                                 continue;
9974                         }
9975                         if ((!isset($newCookie['name'])) || (!isset($newCookie['value']))) {
9976                                 continue;
9977                         }
9978                         $newName = $newCookie['name'];
9979
9980                         $found = false;
9981                         for ($i = 0; $i < count($this->cookies); $i++) {
9982                                 $cookie = $this->cookies[$i];
9983                                 if (!is_array($cookie)) {
9984                                         continue;
9985                                 }
9986                                 if (!isset($cookie['name'])) {
9987                                         continue;
9988                                 }
9989                                 if ($newName != $cookie['name']) {
9990                                         continue;
9991                                 }
9992                                 $newDomain = isset($newCookie['domain']) ? $newCookie['domain'] : 'NODOMAIN';
9993                                 $domain = isset($cookie['domain']) ? $cookie['domain'] : 'NODOMAIN';
9994                                 if ($newDomain != $domain) {
9995                                         continue;
9996                                 }
9997                                 $newPath = isset($newCookie['path']) ? $newCookie['path'] : 'NOPATH';
9998                                 $path = isset($cookie['path']) ? $cookie['path'] : 'NOPATH';
9999                                 if ($newPath != $path) {
10000                                         continue;
10001                                 }
10002                                 $this->cookies[$i] = $newCookie;
10003                                 $found = true;
10004                                 $this->debug('Update cookie ' . $newName . '=' . $newCookie['value']);
10005                                 break;
10006                         }
10007                         if (! $found) {
10008                                 $this->debug('Add cookie ' . $newName . '=' . $newCookie['value']);
10009                                 $this->cookies[] = $newCookie;
10010                         }
10011                 }
10012                 return true;
10013         }
10014 }
10015
10016 if (!extension_loaded('soap')) {
10017         /**
10018          *      For backwards compatiblity, define soapclient unless the PHP SOAP extension is loaded.
10019          */
10020         class soapclient extends nusoap_client {
10021         }
10022 }
10023
10024 class nusoapclient extends nusoap_client
10025 {
10026 }
10027 ?>