affilinet Performance Ads - Version 1.9.5

Version Description

  • Release Date: May 11, 2018
  • Fix: Nusoap as a fallback if Soap Extension is missing
Download this release

Release Info

Developer Affilinet
Plugin Icon 128x128 affilinet Performance Ads
Version 1.9.5
Comparing to
See all releases

Code changes from version 1.9.4 to 1.9.5

Files changed (4) hide show
  1. affilinet.php +1 -1
  2. classes/Nusoap.php +13 -0
  3. nusoap/nusoap.php +8343 -0
  4. readme.txt +6 -2
affilinet.php CHANGED
@@ -3,7 +3,7 @@
3
  /*
4
  Plugin Name: affilinet Performance Ads
5
  Description: Integrate our data driven and automated performance display plugin into your WordPress platform and serve your users targeted ads in real time.
6
- Version: 1.9.4
7
  Author: affilinet
8
  Author URI: https://www.affili.net/de/publisher/tools/performance-ads
9
  Text Domain: affilinet-performance-module
3
  /*
4
  Plugin Name: affilinet Performance Ads
5
  Description: Integrate our data driven and automated performance display plugin into your WordPress platform and serve your users targeted ads in real time.
6
+ Version: 1.9.5
7
  Author: affilinet
8
  Author URI: https://www.affili.net/de/publisher/tools/performance-ads
9
  Text Domain: affilinet-performance-module
classes/Nusoap.php ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if (!class_exists('SoapClient')) {
4
+
5
+ if (!class_exists('nusoap_client')) {
6
+ require_once (dirname(dirname(__FILE__)) . DIRECTORY_SEPARATOR . 'nusoap/nusoap.php');
7
+ }
8
+
9
+ if (!class_exists('SoapClient')) {
10
+ class SoapClient extends nusoap_client {
11
+ }
12
+ }
13
+ }
nusoap/nusoap.php ADDED
@@ -0,0 +1,8343 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ $Id: nusoap.php,v 1.123 2010/04/26 20:15:08 snichol Exp $
5
+
6
+ NuSOAP - Web Services Toolkit for PHP
7
+
8
+ Copyright (c) 2002 NuSphere Corporation
9
+
10
+ This library is free software; you can redistribute it and/or
11
+ modify it under the terms of the GNU Lesser General Public
12
+ License as published by the Free Software Foundation; either
13
+ version 2.1 of the License, or (at your option) any later version.
14
+
15
+ This library is distributed in the hope that it will be useful,
16
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
17
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18
+ Lesser General Public License for more details.
19
+
20
+ You should have received a copy of the GNU Lesser General Public
21
+ License along with this library; if not, write to the Free Software
22
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23
+
24
+ The NuSOAP project home is:
25
+ http://sourceforge.net/projects/nusoap/
26
+
27
+ The primary support for NuSOAP is the Help forum on the project home page.
28
+
29
+ If you have any questions or comments, please email:
30
+
31
+ Dietrich Ayala
32
+ dietrich@ganx4.com
33
+ http://dietrich.ganx4.com/nusoap
34
+
35
+ NuSphere Corporation
36
+ http://www.nusphere.com
37
+
38
+ */
39
+
40
+ /*
41
+ * Some of the standards implmented in whole or part by NuSOAP:
42
+ *
43
+ * SOAP 1.1 (http://www.w3.org/TR/2000/NOTE-SOAP-20000508/)
44
+ * WSDL 1.1 (http://www.w3.org/TR/2001/NOTE-wsdl-20010315)
45
+ * SOAP Messages With Attachments (http://www.w3.org/TR/SOAP-attachments)
46
+ * XML 1.0 (http://www.w3.org/TR/2006/REC-xml-20060816/)
47
+ * Namespaces in XML 1.0 (http://www.w3.org/TR/2006/REC-xml-names-20060816/)
48
+ * XML Schema 1.0 (http://www.w3.org/TR/xmlschema-0/)
49
+ * RFC 2045 Multipurpose Internet Mail Extensions (MIME) Part One: Format of Internet Message Bodies
50
+ * RFC 2068 Hypertext Transfer Protocol -- HTTP/1.1
51
+ * RFC 2617 HTTP Authentication: Basic and Digest Access Authentication
52
+ */
53
+
54
+ /* load classes
55
+
56
+ // necessary classes
57
+ require_once('class.soapclient.php');
58
+ require_once('class.soap_val.php');
59
+ require_once('class.soap_parser.php');
60
+ require_once('class.soap_fault.php');
61
+
62
+ // transport classes
63
+ require_once('class.soap_transport_http.php');
64
+
65
+ // optional add-on classes
66
+ require_once('class.xmlschema.php');
67
+ require_once('class.wsdl.php');
68
+
69
+ // server class
70
+ require_once('class.soap_server.php');*/
71
+
72
+ // class variable emulation
73
+ // cf. http://www.webkreator.com/php/techniques/php-static-class-variables.html
74
+ $GLOBALS['_transient']['static']['nusoap_base']['globalDebugLevel'] = 9;
75
+
76
+
77
+ /**
78
+ *
79
+ * nusoap_base
80
+ *
81
+ * @author Dietrich Ayala <dietrich@ganx4.com>
82
+ * @author Scott Nichol <snichol@users.sourceforge.net>
83
+ * @version $Id: nusoap.php,v 1.123 2010/04/26 20:15:08 snichol Exp $
84
+ * @access public
85
+ */
86
+ class nusoap_base
87
+ {
88
+ /**
89
+ * Identification for HTTP headers.
90
+ *
91
+ * @var string
92
+ * @access private
93
+ */
94
+ var $title = 'NuSOAP';
95
+ /**
96
+ * Version for HTTP headers.
97
+ *
98
+ * @var string
99
+ * @access private
100
+ */
101
+ var $version = '0.9.5';
102
+ /**
103
+ * CVS revision for HTTP headers.
104
+ *
105
+ * @var string
106
+ * @access private
107
+ */
108
+ var $revision = '$Revision: 1.123 $';
109
+ /**
110
+ * Current error string (manipulated by getError/setError)
111
+ *
112
+ * @var string
113
+ * @access private
114
+ */
115
+ var $error_str = '';
116
+ /**
117
+ * Current debug string (manipulated by debug/appendDebug/clearDebug/getDebug/getDebugAsXMLComment)
118
+ *
119
+ * @var string
120
+ * @access private
121
+ */
122
+ var $debug_str = '';
123
+ /**
124
+ * toggles automatic encoding of special characters as entities
125
+ * (should always be true, I think)
126
+ *
127
+ * @var boolean
128
+ * @access private
129
+ */
130
+ var $charencoding = true;
131
+ /**
132
+ * the debug level for this instance
133
+ *
134
+ * @var integer
135
+ * @access private
136
+ */
137
+ var $debugLevel;
138
+
139
+ /**
140
+ * set schema version
141
+ *
142
+ * @var string
143
+ * @access public
144
+ */
145
+ var $XMLSchemaVersion = 'http://www.w3.org/2001/XMLSchema';
146
+
147
+ /**
148
+ * charset encoding for outgoing messages
149
+ *
150
+ * @var string
151
+ * @access public
152
+ */
153
+ var $soap_defencoding = 'ISO-8859-1';
154
+ //var $soap_defencoding = 'UTF-8';
155
+
156
+ /**
157
+ * namespaces in an array of prefix => uri
158
+ *
159
+ * this is "seeded" by a set of constants, but it may be altered by code
160
+ *
161
+ * @var array
162
+ * @access public
163
+ */
164
+ var $namespaces = array(
165
+ 'SOAP-ENV' => 'http://schemas.xmlsoap.org/soap/envelope/',
166
+ 'xsd' => 'http://www.w3.org/2001/XMLSchema',
167
+ 'xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
168
+ 'SOAP-ENC' => 'http://schemas.xmlsoap.org/soap/encoding/'
169
+ );
170
+
171
+ /**
172
+ * namespaces used in the current context, e.g. during serialization
173
+ *
174
+ * @var array
175
+ * @access private
176
+ */
177
+ var $usedNamespaces = array();
178
+
179
+ /**
180
+ * XML Schema types in an array of uri => (array of xml type => php type)
181
+ * is this legacy yet?
182
+ * no, this is used by the nusoap_xmlschema class to verify type => namespace mappings.
183
+ *
184
+ * @var array
185
+ * @access public
186
+ */
187
+ var $typemap = array(
188
+ 'http://www.w3.org/2001/XMLSchema' => array(
189
+ 'string' => 'string', 'boolean' => 'boolean', 'float' => 'double', 'double' => 'double', 'decimal' => 'double',
190
+ 'duration' => '', 'dateTime' => 'string', 'time' => 'string', 'date' => 'string', 'gYearMonth' => '',
191
+ 'gYear' => '', 'gMonthDay' => '', 'gDay' => '', 'gMonth' => '', 'hexBinary' => 'string', 'base64Binary' => 'string',
192
+ // abstract "any" types
193
+ 'anyType' => 'string', 'anySimpleType' => 'string',
194
+ // derived datatypes
195
+ 'normalizedString' => 'string', 'token' => 'string', 'language' => '', 'NMTOKEN' => '', 'NMTOKENS' => '', 'Name' => '', 'NCName' => '', 'ID' => '',
196
+ 'IDREF' => '', 'IDREFS' => '', 'ENTITY' => '', 'ENTITIES' => '', 'integer' => 'integer', 'nonPositiveInteger' => 'integer',
197
+ 'negativeInteger' => 'integer', 'long' => 'integer', 'int' => 'integer', 'short' => 'integer', 'byte' => 'integer', 'nonNegativeInteger' => 'integer',
198
+ 'unsignedLong' => '', 'unsignedInt' => '', 'unsignedShort' => '', 'unsignedByte' => '', 'positiveInteger' => ''),
199
+ 'http://www.w3.org/2000/10/XMLSchema' => array(
200
+ 'i4' => '', 'int' => 'integer', 'boolean' => 'boolean', 'string' => 'string', 'double' => 'double',
201
+ 'float' => 'double', 'dateTime' => 'string',
202
+ 'timeInstant' => 'string', 'base64Binary' => 'string', 'base64' => 'string', 'ur-type' => 'array'),
203
+ 'http://www.w3.org/1999/XMLSchema' => array(
204
+ 'i4' => '', 'int' => 'integer', 'boolean' => 'boolean', 'string' => 'string', 'double' => 'double',
205
+ 'float' => 'double', 'dateTime' => 'string',
206
+ 'timeInstant' => 'string', 'base64Binary' => 'string', 'base64' => 'string', 'ur-type' => 'array'),
207
+ 'http://soapinterop.org/xsd' => array('SOAPStruct' => 'struct'),
208
+ 'http://schemas.xmlsoap.org/soap/encoding/' => array('base64' => 'string', 'array' => 'array', 'Array' => 'array'),
209
+ 'http://xml.apache.org/xml-soap' => array('Map')
210
+ );
211
+
212
+ /**
213
+ * XML entities to convert
214
+ *
215
+ * @var array
216
+ * @access public
217
+ * @deprecated
218
+ * @see expandEntities
219
+ */
220
+ var $xmlEntities = array('quot' => '"', 'amp' => '&',
221
+ 'lt' => '<', 'gt' => '>', 'apos' => "'");
222
+
223
+ /**
224
+ * constructor
225
+ *
226
+ * @access public
227
+ */
228
+ function __construct()
229
+ {
230
+ $this->debugLevel = $GLOBALS['_transient']['static']['nusoap_base']['globalDebugLevel'];
231
+ }
232
+
233
+ /**
234
+ * gets the global debug level, which applies to future instances
235
+ *
236
+ * @return integer Debug level 0-9, where 0 turns off
237
+ * @access public
238
+ */
239
+ function getGlobalDebugLevel()
240
+ {
241
+ return $GLOBALS['_transient']['static']['nusoap_base']['globalDebugLevel'];
242
+ }
243
+
244
+ /**
245
+ * sets the global debug level, which applies to future instances
246
+ *
247
+ * @param int $level Debug level 0-9, where 0 turns off
248
+ * @access public
249
+ */
250
+ function setGlobalDebugLevel($level)
251
+ {
252
+ $GLOBALS['_transient']['static']['nusoap_base']['globalDebugLevel'] = $level;
253
+ }
254
+
255
+ /**
256
+ * gets the debug level for this instance
257
+ *
258
+ * @return int Debug level 0-9, where 0 turns off
259
+ * @access public
260
+ */
261
+ function getDebugLevel()
262
+ {
263
+ return $this->debugLevel;
264
+ }
265
+
266
+ /**
267
+ * sets the debug level for this instance
268
+ *
269
+ * @param int $level Debug level 0-9, where 0 turns off
270
+ * @access public
271
+ */
272
+ function setDebugLevel($level)
273
+ {
274
+ $this->debugLevel = $level;
275
+ }
276
+
277
+ /**
278
+ * adds debug data to the instance debug string with formatting
279
+ *
280
+ * @param string $string debug data
281
+ * @access private
282
+ */
283
+ function debug($string)
284
+ {
285
+ if ($this->debugLevel > 0) {
286
+ $this->appendDebug($this->getmicrotime() . ' ' . get_class($this) . ": $string\n");
287
+ }
288
+ }
289
+
290
+ /**
291
+ * adds debug data to the instance debug string without formatting
292
+ *
293
+ * @param string $string debug data
294
+ * @access public
295
+ */
296
+ function appendDebug($string)
297
+ {
298
+ if ($this->debugLevel > 0) {
299
+ // it would be nice to use a memory stream here to use
300
+ // memory more efficiently
301
+ $this->debug_str .= $string;
302
+ }
303
+ }
304
+
305
+ /**
306
+ * clears the current debug data for this instance
307
+ *
308
+ * @access public
309
+ */
310
+ function clearDebug()
311
+ {
312
+ // it would be nice to use a memory stream here to use
313
+ // memory more efficiently
314
+ $this->debug_str = '';
315
+ }
316
+
317
+ /**
318
+ * gets the current debug data for this instance
319
+ *
320
+ * @return debug data
321
+ * @access public
322
+ */
323
+ function &getDebug()
324
+ {
325
+ // it would be nice to use a memory stream here to use
326
+ // memory more efficiently
327
+ return $this->debug_str;
328
+ }
329
+
330
+ /**
331
+ * gets the current debug data for this instance as an XML comment
332
+ * this may change the contents of the debug data
333
+ *
334
+ * @return debug data as an XML comment
335
+ * @access public
336
+ */
337
+ function &getDebugAsXMLComment()
338
+ {
339
+ // it would be nice to use a memory stream here to use
340
+ // memory more efficiently
341
+ while (strpos($this->debug_str, '--')) {
342
+ $this->debug_str = str_replace('--', '- -', $this->debug_str);
343
+ }
344
+ $ret = "<!--\n" . $this->debug_str . "\n-->";
345
+ return $ret;
346
+ }
347
+
348
+ /**
349
+ * expands entities, e.g. changes '<' to '&lt;'.
350
+ *
351
+ * @param string $val The string in which to expand entities.
352
+ * @access private
353
+ */
354
+ function expandEntities($val)
355
+ {
356
+ if ($this->charencoding) {
357
+ $val = str_replace('&', '&amp;', $val);
358
+ $val = str_replace("'", '&apos;', $val);
359
+ $val = str_replace('"', '&quot;', $val);
360
+ $val = str_replace('<', '&lt;', $val);
361
+ $val = str_replace('>', '&gt;', $val);
362
+ }
363
+ return $val;
364
+ }
365
+
366
+ /**
367
+ * returns error string if present
368
+ *
369
+ * @return mixed error string or false
370
+ * @access public
371
+ */
372
+ function getError()
373
+ {
374
+ if ($this->error_str != '') {
375
+ return $this->error_str;
376
+ }
377
+ return false;
378
+ }
379
+
380
+ /**
381
+ * sets error string
382
+ *
383
+ * @return boolean $string error string
384
+ * @access private
385
+ */
386
+ function setError($str)
387
+ {
388
+ $this->error_str = $str;
389
+ }
390
+
391
+ /**
392
+ * detect if array is a simple array or a struct (associative array)
393
+ *
394
+ * @param mixed $val The PHP array
395
+ * @return string (arraySimple|arrayStruct)
396
+ * @access private
397
+ */
398
+ function isArraySimpleOrStruct($val)
399
+ {
400
+ $keyList = array_keys($val);
401
+ foreach ($keyList as $keyListValue) {
402
+ if (!is_int($keyListValue)) {
403
+ return 'arrayStruct';
404
+ }
405
+ }
406
+ return 'arraySimple';
407
+ }
408
+
409
+ /**
410
+ * serializes PHP values in accordance w/ section 5. Type information is
411
+ * not serialized if $use == 'literal'.
412
+ *
413
+ * @param mixed $val The value to serialize
414
+ * @param string $name The name (local part) of the XML element
415
+ * @param string $type The XML schema type (local part) for the element
416
+ * @param string $name_ns The namespace for the name of the XML element
417
+ * @param string $type_ns The namespace for the type of the element
418
+ * @param array $attributes The attributes to serialize as name=>value pairs
419
+ * @param string $use The WSDL "use" (encoded|literal)
420
+ * @param boolean $soapval Whether this is called from soapval.
421
+ * @return string The serialized element, possibly with child elements
422
+ * @access public
423
+ */
424
+ function serialize_val($val, $name = false, $type = false, $name_ns = false, $type_ns = false, $attributes = false, $use = 'encoded', $soapval = false)
425
+ {
426
+ $this->debug("in serialize_val: name=$name, type=$type, name_ns=$name_ns, type_ns=$type_ns, use=$use, soapval=$soapval");
427
+ $this->appendDebug('value=' . $this->varDump($val));
428
+ $this->appendDebug('attributes=' . $this->varDump($attributes));
429
+
430
+ if (is_object($val) && get_class($val) == 'soapval' && (!$soapval)) {
431
+ $this->debug("serialize_val: serialize soapval");
432
+ $xml = $val->serialize($use);
433
+ $this->appendDebug($val->getDebug());
434
+ $val->clearDebug();
435
+ $this->debug("serialize_val of soapval returning $xml");
436
+ return $xml;
437
+ }
438
+ // force valid name if necessary
439
+ if (is_numeric($name)) {
440
+ $name = '__numeric_' . $name;
441
+ } elseif (!$name) {
442
+ $name = 'noname';
443
+ }
444
+ // if name has ns, add ns prefix to name
445
+ $xmlns = '';
446
+ if ($name_ns) {
447
+ $prefix = 'nu' . rand(1000, 9999);
448
+ $name = $prefix . ':' . $name;
449
+ $xmlns .= " xmlns:$prefix=\"$name_ns\"";
450
+ }
451
+ // if type is prefixed, create type prefix
452
+ if ($type_ns != '' && $type_ns == $this->namespaces['xsd']) {
453
+ // need to fix this. shouldn't default to xsd if no ns specified
454
+ // w/o checking against typemap
455
+ $type_prefix = 'xsd';
456
+ } elseif ($type_ns) {
457
+ $type_prefix = 'ns' . rand(1000, 9999);
458
+ $xmlns .= " xmlns:$type_prefix=\"$type_ns\"";
459
+ }
460
+ // serialize attributes if present
461
+ $atts = '';
462
+ if ($attributes) {
463
+ foreach ($attributes as $k => $v) {
464
+ $atts .= " $k=\"" . $this->expandEntities($v) . '"';
465
+ }
466
+ }
467
+ // serialize null value
468
+ if (is_null($val)) {
469
+ $this->debug("serialize_val: serialize null");
470
+ if ($use == 'literal') {
471
+ // TODO: depends on minOccurs
472
+ $xml = "<$name$xmlns$atts/>";
473
+ $this->debug("serialize_val returning $xml");
474
+ return $xml;
475
+ } else {
476
+ if (isset($type) && isset($type_prefix)) {
477
+ $type_str = " xsi:type=\"$type_prefix:$type\"";
478
+ } else {
479
+ $type_str = '';
480
+ }
481
+ $xml = "<$name$xmlns$type_str$atts xsi:nil=\"true\"/>";
482
+ $this->debug("serialize_val returning $xml");
483
+ return $xml;
484
+ }
485
+ }
486
+ // serialize if an xsd built-in primitive type
487
+ if ($type != '' && isset($this->typemap[$this->XMLSchemaVersion][$type])) {
488
+ $this->debug("serialize_val: serialize xsd built-in primitive type");
489
+ if (is_bool($val)) {
490
+ if ($type == 'boolean') {
491
+ $val = $val ? 'true' : 'false';
492
+ } elseif (!$val) {
493
+ $val = 0;
494
+ }
495
+ } elseif (is_string($val)) {
496
+ $val = $this->expandEntities($val);
497
+ }
498
+ if ($use == 'literal') {
499
+ $xml = "<$name$xmlns$atts>$val</$name>";
500
+ $this->debug("serialize_val returning $xml");
501
+ return $xml;
502
+ } else {
503
+ $xml = "<$name$xmlns xsi:type=\"xsd:$type\"$atts>$val</$name>";
504
+ $this->debug("serialize_val returning $xml");
505
+ return $xml;
506
+ }
507
+ }
508
+ // detect type and serialize
509
+ $xml = '';
510
+ switch (true) {
511
+ case (is_bool($val) || $type == 'boolean'):
512
+ $this->debug("serialize_val: serialize boolean");
513
+ if ($type == 'boolean') {
514
+ $val = $val ? 'true' : 'false';
515
+ } elseif (!$val) {
516
+ $val = 0;
517
+ }
518
+ if ($use == 'literal') {
519
+ $xml .= "<$name$xmlns$atts>$val</$name>";
520
+ } else {
521
+ $xml .= "<$name$xmlns xsi:type=\"xsd:boolean\"$atts>$val</$name>";
522
+ }
523
+ break;
524
+ case (is_int($val) || is_long($val) || $type == 'int'):
525
+ $this->debug("serialize_val: serialize int");
526
+ if ($use == 'literal') {
527
+ $xml .= "<$name$xmlns$atts>$val</$name>";
528
+ } else {
529
+ $xml .= "<$name$xmlns xsi:type=\"xsd:int\"$atts>$val</$name>";
530
+ }
531
+ break;
532
+ case (is_float($val) || is_double($val) || $type == 'float'):
533
+ $this->debug("serialize_val: serialize float");
534
+ if ($use == 'literal') {
535
+ $xml .= "<$name$xmlns$atts>$val</$name>";
536
+ } else {
537
+ $xml .= "<$name$xmlns xsi:type=\"xsd:float\"$atts>$val</$name>";
538
+ }
539
+ break;
540
+ case (is_string($val) || $type == 'string'):
541
+ $this->debug("serialize_val: serialize string");
542
+ $val = $this->expandEntities($val);
543
+ if ($use == 'literal') {
544
+ $xml .= "<$name$xmlns$atts>$val</$name>";
545
+ } else {
546
+ $xml .= "<$name$xmlns xsi:type=\"xsd:string\"$atts>$val</$name>";
547
+ }
548
+ break;
549
+ case is_object($val):
550
+ $this->debug("serialize_val: serialize object");
551
+ if (get_class($val) == 'soapval') {
552
+ $this->debug("serialize_val: serialize soapval object");
553
+ $pXml = $val->serialize($use);
554
+ $this->appendDebug($val->getDebug());
555
+ $val->clearDebug();
556
+ } else {
557
+ if (!$name) {
558
+ $name = get_class($val);
559
+ $this->debug("In serialize_val, used class name $name as element name");
560
+ } else {
561
+ $this->debug("In serialize_val, do not override name $name for element name for class " . get_class($val));
562
+ }
563
+ foreach (get_object_vars($val) as $k => $v) {
564
+ $pXml = isset($pXml) ? $pXml . $this->serialize_val($v, $k, false, false, false, false, $use) : $this->serialize_val($v, $k, false, false, false, false, $use);
565
+ }
566
+ }
567
+ if (isset($type) && isset($type_prefix)) {
568
+ $type_str = " xsi:type=\"$type_prefix:$type\"";
569
+ } else {
570
+ $type_str = '';
571
+ }
572
+ if ($use == 'literal') {
573
+ $xml .= "<$name$xmlns$atts>$pXml</$name>";
574
+ } else {
575
+ $xml .= "<$name$xmlns$type_str$atts>$pXml</$name>";
576
+ }
577
+ break;
578
+ break;
579
+ case (is_array($val) || $type):
580
+ // detect if struct or array
581
+ $valueType = $this->isArraySimpleOrStruct($val);
582
+ if ($valueType == 'arraySimple' || preg_match('/^ArrayOf/', $type)) {
583
+ $this->debug("serialize_val: serialize array");
584
+ $i = 0;
585
+ if (is_array($val) && count($val) > 0) {
586
+ foreach ($val as $v) {
587
+ if (is_object($v) && get_class($v) == 'soapval') {
588
+ $tt_ns = $v->type_ns;
589
+ $tt = $v->type;
590
+ } elseif (is_array($v)) {
591
+ $tt = $this->isArraySimpleOrStruct($v);
592
+ } else {
593
+ $tt = gettype($v);
594
+ }
595
+ $array_types[$tt] = 1;
596
+ // TODO: for literal, the name should be $name
597
+ $xml .= $this->serialize_val($v, 'item', false, false, false, false, $use);
598
+ ++$i;
599
+ }
600
+ if (count($array_types) > 1) {
601
+ $array_typename = 'xsd:anyType';
602
+ } elseif (isset($tt) && isset($this->typemap[$this->XMLSchemaVersion][$tt])) {
603
+ if ($tt == 'integer') {
604
+ $tt = 'int';
605
+ }
606
+ $array_typename = 'xsd:' . $tt;
607
+ } elseif (isset($tt) && $tt == 'arraySimple') {
608
+ $array_typename = 'SOAP-ENC:Array';
609
+ } elseif (isset($tt) && $tt == 'arrayStruct') {
610
+ $array_typename = 'unnamed_struct_use_soapval';
611
+ } else {
612
+ // if type is prefixed, create type prefix
613
+ if ($tt_ns != '' && $tt_ns == $this->namespaces['xsd']) {
614
+ $array_typename = 'xsd:' . $tt;
615
+ } elseif ($tt_ns) {
616
+ $tt_prefix = 'ns' . rand(1000, 9999);
617
+ $array_typename = "$tt_prefix:$tt";
618
+ $xmlns .= " xmlns:$tt_prefix=\"$tt_ns\"";
619
+ } else {
620
+ $array_typename = $tt;
621
+ }
622
+ }
623
+ $array_type = $i;
624
+ if ($use == 'literal') {
625
+ $type_str = '';
626
+ } elseif (isset($type) && isset($type_prefix)) {
627
+ $type_str = " xsi:type=\"$type_prefix:$type\"";
628
+ } else {
629
+ $type_str = " xsi:type=\"SOAP-ENC:Array\" SOAP-ENC:arrayType=\"" . $array_typename . "[$array_type]\"";
630
+ }
631
+ // empty array
632
+ } else {
633
+ if ($use == 'literal') {
634
+ $type_str = '';
635
+ } elseif (isset($type) && isset($type_prefix)) {
636
+ $type_str = " xsi:type=\"$type_prefix:$type\"";
637
+ } else {
638
+ $type_str = " xsi:type=\"SOAP-ENC:Array\" SOAP-ENC:arrayType=\"xsd:anyType[0]\"";
639
+ }
640
+ }
641
+ // TODO: for array in literal, there is no wrapper here
642
+ $xml = "<$name$xmlns$type_str$atts>" . $xml . "</$name>";
643
+ } else {
644
+ // got a struct
645
+ $this->debug("serialize_val: serialize struct");
646
+ if (isset($type) && isset($type_prefix)) {
647
+ $type_str = " xsi:type=\"$type_prefix:$type\"";
648
+ } else {
649
+ $type_str = '';
650
+ }
651
+ if ($use == 'literal') {
652
+ $xml .= "<$name$xmlns$atts>";
653
+ } else {
654
+ $xml .= "<$name$xmlns$type_str$atts>";
655
+ }
656
+ foreach ($val as $k => $v) {
657
+ // Apache Map
658
+ if ($type == 'Map' && $type_ns == 'http://xml.apache.org/xml-soap') {
659
+ $xml .= '<item>';
660
+ $xml .= $this->serialize_val($k, 'key', false, false, false, false, $use);
661
+ $xml .= $this->serialize_val($v, 'value', false, false, false, false, $use);
662
+ $xml .= '</item>';
663
+ } else {
664
+ $xml .= $this->serialize_val($v, $k, false, false, false, false, $use);
665
+ }
666
+ }
667
+ $xml .= "</$name>";
668
+ }
669
+ break;
670
+ default:
671
+ $this->debug("serialize_val: serialize unknown");
672
+ $xml .= 'not detected, got ' . gettype($val) . ' for ' . $val;
673
+ break;
674
+ }
675
+ $this->debug("serialize_val returning $xml");
676
+ return $xml;
677
+ }
678
+
679
+ /**
680
+ * serializes a message
681
+ *
682
+ * @param string $body the XML of the SOAP body
683
+ * @param mixed $headers optional string of XML with SOAP header content, or array of soapval objects for SOAP headers, or associative array
684
+ * @param array $namespaces optional the namespaces used in generating the body and headers
685
+ * @param string $style optional (rpc|document)
686
+ * @param string $use optional (encoded|literal)
687
+ * @param string $encodingStyle optional (usually 'http://schemas.xmlsoap.org/soap/encoding/' for encoded)
688
+ * @return string the message
689
+ * @access public
690
+ */
691
+ function serializeEnvelope($body, $headers = false, $namespaces = array(), $style = 'rpc', $use = 'encoded', $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/')
692
+ {
693
+ // TODO: add an option to automatically run utf8_encode on $body and $headers
694
+ // if $this->soap_defencoding is UTF-8. Not doing this automatically allows
695
+ // one to send arbitrary UTF-8 characters, not just characters that map to ISO-8859-1
696
+
697
+ $this->debug("In serializeEnvelope length=" . strlen($body) . " body (max 1000 characters)=" . substr($body, 0, 1000) . " style=$style use=$use encodingStyle=$encodingStyle");
698
+ $this->debug("headers:");
699
+ $this->appendDebug($this->varDump($headers));
700
+ $this->debug("namespaces:");
701
+ $this->appendDebug($this->varDump($namespaces));
702
+
703
+ // serialize namespaces
704
+ $ns_string = '';
705
+ foreach (array_merge($this->namespaces, $namespaces) as $k => $v) {
706
+ $ns_string .= " xmlns:$k=\"$v\"";
707
+ }
708
+ if ($encodingStyle) {
709
+ $ns_string = " SOAP-ENV:encodingStyle=\"$encodingStyle\"$ns_string";
710
+ }
711
+
712
+ // serialize headers
713
+ if ($headers) {
714
+ if (is_array($headers)) {
715
+ $xml = '';
716
+ foreach ($headers as $k => $v) {
717
+ if (is_object($v) && get_class($v) == 'soapval') {
718
+ $xml .= $this->serialize_val($v, false, false, false, false, false, $use);
719
+ } else {
720
+ $xml .= $this->serialize_val($v, $k, false, false, false, false, $use);
721
+ }
722
+ }
723
+ $headers = $xml;
724
+ $this->debug("In serializeEnvelope, serialized array of headers to $headers");
725
+ }
726
+ $headers = "<SOAP-ENV:Header>" . $headers . "</SOAP-ENV:Header>";
727
+ }
728
+ // serialize envelope
729
+ return
730
+ '<?xml version="1.0" encoding="' . $this->soap_defencoding . '"?' . ">" .
731
+ '<SOAP-ENV:Envelope' . $ns_string . ">" .
732
+ $headers .
733
+ "<SOAP-ENV:Body>" .
734
+ $body .
735
+ "</SOAP-ENV:Body>" .
736
+ "</SOAP-ENV:Envelope>";
737
+ }
738
+
739
+ /**
740
+ * formats a string to be inserted into an HTML stream
741
+ *
742
+ * @param string $str The string to format
743
+ * @return string The formatted string
744
+ * @access public
745
+ * @deprecated
746
+ */
747
+ function formatDump($str)
748
+ {
749
+ $str = htmlspecialchars($str);
750
+ return nl2br($str);
751
+ }
752
+
753
+ /**
754
+ * contracts (changes namespace to prefix) a qualified name
755
+ *
756
+ * @param string $qname qname
757
+ * @return string contracted qname
758
+ * @access private
759
+ */
760
+ function contractQname($qname)
761
+ {
762
+ // get element namespace
763
+ //$this->xdebug("Contract $qname");
764
+ if (strrpos($qname, ':')) {
765
+ // get unqualified name
766
+ $name = substr($qname, strrpos($qname, ':') + 1);
767
+ // get ns
768
+ $ns = substr($qname, 0, strrpos($qname, ':'));
769
+ $p = $this->getPrefixFromNamespace($ns);
770
+ if ($p) {
771
+ return $p . ':' . $name;
772
+ }
773
+ return $qname;
774
+ } else {
775
+ return $qname;
776
+ }
777
+ }
778
+
779
+ /**
780
+ * expands (changes prefix to namespace) a qualified name
781
+ *
782
+ * @param string $qname qname
783
+ * @return string expanded qname
784
+ * @access private
785
+ */
786
+ function expandQname($qname)
787
+ {
788
+ // get element prefix
789
+ if (strpos($qname, ':') && !preg_match('/^http:\/\//', $qname)) {
790
+ // get unqualified name
791
+ $name = substr(strstr($qname, ':'), 1);
792
+ // get ns prefix
793
+ $prefix = substr($qname, 0, strpos($qname, ':'));
794
+ if (isset($this->namespaces[$prefix])) {
795
+ return $this->namespaces[$prefix] . ':' . $name;
796
+ } else {
797
+ return $qname;
798
+ }
799
+ } else {
800
+ return $qname;
801
+ }
802
+ }
803
+
804
+ /**
805
+ * returns the local part of a prefixed string
806
+ * returns the original string, if not prefixed
807
+ *
808
+ * @param string $str The prefixed string
809
+ * @return string The local part
810
+ * @access public
811
+ */
812
+ function getLocalPart($str)
813
+ {
814
+ if ($sstr = strrchr($str, ':')) {
815
+ // get unqualified name
816
+ return substr($sstr, 1);
817
+ } else {
818
+ return $str;
819
+ }
820
+ }
821
+
822
+ /**
823
+ * returns the prefix part of a prefixed string
824
+ * returns false, if not prefixed
825
+ *
826
+ * @param string $str The prefixed string
827
+ * @return mixed The prefix or false if there is no prefix
828
+ * @access public
829
+ */
830
+ function getPrefix($str)
831
+ {
832
+ if ($pos = strrpos($str, ':')) {
833
+ // get prefix
834
+ return substr($str, 0, $pos);
835
+ }
836
+ return false;
837
+ }
838
+
839
+ /**
840
+ * pass it a prefix, it returns a namespace
841
+ *
842
+ * @param string $prefix The prefix
843
+ * @return mixed The namespace, false if no namespace has the specified prefix
844
+ * @access public
845
+ */
846
+ function getNamespaceFromPrefix($prefix)
847
+ {
848
+ if (isset($this->namespaces[$prefix])) {
849
+ return $this->namespaces[$prefix];
850
+ }
851
+ //$this->setError("No namespace registered for prefix '$prefix'");
852
+ return false;
853
+ }
854
+
855
+ /**
856
+ * returns the prefix for a given namespace (or prefix)
857
+ * or false if no prefixes registered for the given namespace
858
+ *
859
+ * @param string $ns The namespace
860
+ * @return mixed The prefix, false if the namespace has no prefixes
861
+ * @access public
862
+ */
863
+ function getPrefixFromNamespace($ns)
864
+ {
865
+ foreach ($this->namespaces as $p => $n) {
866
+ if ($ns == $n || $ns == $p) {
867
+ $this->usedNamespaces[$p] = $n;
868
+ return $p;
869
+ }
870
+ }
871
+ return false;
872
+ }
873
+
874
+ /**
875
+ * returns the time in ODBC canonical form with microseconds
876
+ *
877
+ * @return string The time in ODBC canonical form with microseconds
878
+ * @access public
879
+ */
880
+ function getmicrotime()
881
+ {
882
+ if (function_exists('gettimeofday')) {
883
+ $tod = gettimeofday();
884
+ $sec = $tod['sec'];
885
+ $usec = $tod['usec'];
886
+ } else {
887
+ $sec = time();
888
+ $usec = 0;
889
+ }
890
+ return strftime('%Y-%m-%d %H:%M:%S', $sec) . '.' . sprintf('%06d', $usec);
891
+ }
892
+
893
+ /**
894
+ * Returns a string with the output of var_dump
895
+ *
896
+ * @param mixed $data The variable to var_dump
897
+ * @return string The output of var_dump
898
+ * @access public
899
+ */
900
+ function varDump($data)
901
+ {
902
+ ob_start();
903
+ var_dump($data);
904
+ $ret_val = ob_get_contents();
905
+ ob_end_clean();
906
+ return $ret_val;
907
+ }
908
+
909
+ /**
910
+ * represents the object as a string
911
+ *
912
+ * @return string
913
+ * @access public
914
+ */
915
+ function __toString()
916
+ {
917
+ return $this->varDump($this);
918
+ }
919
+ }
920
+
921
+ // XML Schema Datatype Helper Functions
922
+
923
+ //xsd:dateTime helpers
924
+
925
+ /**
926
+ * convert unix timestamp to ISO 8601 compliant date string
927
+ *
928
+ * @param int $timestamp Unix time stamp
929
+ * @param boolean $utc Whether the time stamp is UTC or local
930
+ * @return mixed ISO 8601 date string or false
931
+ * @access public
932
+ */
933
+ function timestamp_to_iso8601($timestamp, $utc = true)
934
+ {
935
+ $datestr = date('Y-m-d\TH:i:sO', $timestamp);
936
+ $pos = strrpos($datestr, "+");
937
+ if ($pos === false) {
938
+ $pos = strrpos($datestr, "-");
939
+ }
940
+ if ($pos !== false) {
941
+ if (strlen($datestr) == $pos + 5) {
942
+ $datestr = substr($datestr, 0, $pos + 3) . ':' . substr($datestr, -2);
943
+ }
944
+ }
945
+ if ($utc) {
946
+ $pattern = '/' .
947
+ '([0-9]{4})-' . // centuries & years CCYY-
948
+ '([0-9]{2})-' . // months MM-
949
+ '([0-9]{2})' . // days DD
950
+ 'T' . // separator T
951
+ '([0-9]{2}):' . // hours hh:
952
+ '([0-9]{2}):' . // minutes mm:
953
+ '([0-9]{2})(\.[0-9]*)?' . // seconds ss.ss...
954
+ '(Z|[+\-][0-9]{2}:?[0-9]{2})?' . // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's
955
+ '/';
956
+
957
+ if (preg_match($pattern, $datestr, $regs)) {
958
+ return sprintf('%04d-%02d-%02dT%02d:%02d:%02dZ', $regs[1], $regs[2], $regs[3], $regs[4], $regs[5], $regs[6]);
959
+ }
960
+ return false;
961
+ } else {
962
+ return $datestr;
963
+ }
964
+ }
965
+
966
+ /**
967
+ * convert ISO 8601 compliant date string to unix timestamp
968
+ *
969
+ * @param string $datestr ISO 8601 compliant date string
970
+ * @return mixed Unix timestamp (int) or false
971
+ * @access public
972
+ */
973
+ function iso8601_to_timestamp($datestr)
974
+ {
975
+ $pattern = '/' .
976
+ '([0-9]{4})-' . // centuries & years CCYY-
977
+ '([0-9]{2})-' . // months MM-
978
+ '([0-9]{2})' . // days DD
979
+ 'T' . // separator T
980
+ '([0-9]{2}):' . // hours hh:
981
+ '([0-9]{2}):' . // minutes mm:
982
+ '([0-9]{2})(\.[0-9]+)?' . // seconds ss.ss...
983
+ '(Z|[+\-][0-9]{2}:?[0-9]{2})?' . // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's
984
+ '/';
985
+ if (preg_match($pattern, $datestr, $regs)) {
986
+ // not utc
987
+ if ($regs[8] != 'Z') {
988
+ $op = substr($regs[8], 0, 1);
989
+ $h = substr($regs[8], 1, 2);
990
+ $m = substr($regs[8], strlen($regs[8]) - 2, 2);
991
+ if ($op == '-') {
992
+ $regs[4] = $regs[4] + $h;
993
+ $regs[5] = $regs[5] + $m;
994
+ } elseif ($op == '+') {
995
+ $regs[4] = $regs[4] - $h;
996
+ $regs[5] = $regs[5] - $m;
997
+ }
998
+ }
999
+ return gmmktime($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]);
1000
+ // return strtotime("$regs[1]-$regs[2]-$regs[3] $regs[4]:$regs[5]:$regs[6]Z");
1001
+ } else {
1002
+ return false;
1003
+ }
1004
+ }
1005
+
1006
+ /**
1007
+ * sleeps some number of microseconds
1008
+ *
1009
+ * @param string $usec the number of microseconds to sleep
1010
+ * @access public
1011
+ * @deprecated
1012
+ */
1013
+ function usleepWindows($usec)
1014
+ {
1015
+ $start = gettimeofday();
1016
+
1017
+ do {
1018
+ $stop = gettimeofday();
1019
+ $timePassed = 1000000 * ($stop['sec'] - $start['sec'])
1020
+ + $stop['usec'] - $start['usec'];
1021
+ } while ($timePassed < $usec);
1022
+ }
1023
+
1024
+
1025
+ /**
1026
+ * Contains information for a SOAP fault.
1027
+ * Mainly used for returning faults from deployed functions
1028
+ * in a server instance.
1029
+ *
1030
+ * @author Dietrich Ayala <dietrich@ganx4.com>
1031
+ * @version $Id: nusoap.php,v 1.123 2010/04/26 20:15:08 snichol Exp $
1032
+ * @access public
1033
+ */
1034
+ class nusoap_fault extends nusoap_base
1035
+ {
1036
+ /**
1037
+ * The fault code (client|server)
1038
+ *
1039
+ * @var string
1040
+ * @access private
1041
+ */
1042
+ var $faultcode;
1043
+ /**
1044
+ * The fault actor
1045
+ *
1046
+ * @var string
1047
+ * @access private
1048
+ */
1049
+ var $faultactor;
1050
+ /**
1051
+ * The fault string, a description of the fault
1052
+ *
1053
+ * @var string
1054
+ * @access private
1055
+ */
1056
+ var $faultstring;
1057
+ /**
1058
+ * The fault detail, typically a string or array of string
1059
+ *
1060
+ * @var mixed
1061
+ * @access private
1062
+ */
1063
+ var $faultdetail;
1064
+
1065
+ /**
1066
+ * constructor
1067
+ *
1068
+ * @param string $faultcode (SOAP-ENV:Client | SOAP-ENV:Server)
1069
+ * @param string $faultactor only used when msg routed between multiple actors
1070
+ * @param string $faultstring human readable error message
1071
+ * @param mixed $faultdetail detail, typically a string or array of string
1072
+ */
1073
+ function __construct($faultcode, $faultactor = '', $faultstring = '', $faultdetail = '')
1074
+ {
1075
+ parent::__construct();
1076
+ $this->faultcode = $faultcode;
1077
+ $this->faultactor = $faultactor;
1078
+ $this->faultstring = $faultstring;
1079
+ $this->faultdetail = $faultdetail;
1080
+ }
1081
+
1082
+ /**
1083
+ * serialize a fault
1084
+ *
1085
+ * @return string The serialization of the fault instance.
1086
+ * @access public
1087
+ */
1088
+ function serialize()
1089
+ {
1090
+ $ns_string = '';
1091
+ foreach ($this->namespaces as $k => $v) {
1092
+ $ns_string .= "\n xmlns:$k=\"$v\"";
1093
+ }
1094
+ $return_msg =
1095
+ '<?xml version="1.0" encoding="' . $this->soap_defencoding . '"?>' .
1096
+ '<SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"' . $ns_string . ">\n" .
1097
+ '<SOAP-ENV:Body>' .
1098
+ '<SOAP-ENV:Fault>' .
1099
+ $this->serialize_val($this->faultcode, 'faultcode') .
1100
+ $this->serialize_val($this->faultactor, 'faultactor') .
1101
+ $this->serialize_val($this->faultstring, 'faultstring') .
1102
+ $this->serialize_val($this->faultdetail, 'detail') .
1103
+ '</SOAP-ENV:Fault>' .
1104
+ '</SOAP-ENV:Body>' .
1105
+ '</SOAP-ENV:Envelope>';
1106
+ return $return_msg;
1107
+ }
1108
+ }
1109
+
1110
+
1111
+ /**
1112
+ * Backward compatibility
1113
+ */
1114
+ class soap_fault extends nusoap_fault
1115
+ {
1116
+ }
1117
+
1118
+
1119
+ /**
1120
+ * parses an XML Schema, allows access to it's data, other utility methods.
1121
+ * imperfect, no validation... yet, but quite functional.
1122
+ *
1123
+ * @author Dietrich Ayala <dietrich@ganx4.com>
1124
+ * @author Scott Nichol <snichol@users.sourceforge.net>
1125
+ * @version $Id: nusoap.php,v 1.123 2010/04/26 20:15:08 snichol Exp $
1126
+ * @access public
1127
+ */
1128
+ class nusoap_xmlschema extends nusoap_base
1129
+ {
1130
+
1131
+ // files
1132
+ var $schema = '';
1133
+ var $xml = '';
1134
+ // namespaces
1135
+ var $enclosingNamespaces;
1136
+ // schema info
1137
+ var $schemaInfo = array();
1138
+ var $schemaTargetNamespace = '';
1139
+ // types, elements, attributes defined by the schema
1140
+ var $attributes = array();
1141
+ var $complexTypes = array();
1142
+ var $complexTypeStack = array();
1143
+ var $currentComplexType = null;
1144
+ var $elements = array();
1145
+ var $elementStack = array();
1146
+ var $currentElement = null;
1147
+ var $simpleTypes = array();
1148
+ var $simpleTypeStack = array();
1149
+ var $currentSimpleType = null;
1150
+ // imports
1151
+ var $imports = array();
1152
+ // parser vars
1153
+ var $parser;
1154
+ var $position = 0;
1155
+ var $depth = 0;
1156
+ var $depth_array = array();
1157
+ var $message = array();
1158
+ var $defaultNamespace = array();
1159
+
1160
+ /**
1161
+ * constructor
1162
+ *
1163
+ * @param string $schema schema document URI
1164
+ * @param string $xml xml document URI
1165
+ * @param string $namespaces namespaces defined in enclosing XML
1166
+ * @access public
1167
+ */
1168
+ function __construct($schema = '', $xml = '', $namespaces = array())
1169
+ {
1170
+ parent::__construct();
1171
+ $this->debug('nusoap_xmlschema class instantiated, inside constructor');
1172
+ // files
1173
+ $this->schema = $schema;
1174
+ $this->xml = $xml;
1175
+
1176
+ // namespaces
1177
+ $this->enclosingNamespaces = $namespaces;
1178
+ $this->namespaces = array_merge($this->namespaces, $namespaces);
1179
+
1180
+ // parse schema file
1181
+ if ($schema != '') {
1182
+ $this->debug('initial schema file: ' . $schema);
1183
+ $this->parseFile($schema, 'schema');
1184
+ }
1185
+
1186
+ // parse xml file
1187
+ if ($xml != '') {
1188
+ $this->debug('initial xml file: ' . $xml);
1189
+ $this->parseFile($xml, 'xml');
1190
+ }
1191
+
1192
+ }
1193
+
1194
+ /**
1195
+ * parse an XML file
1196
+ *
1197
+ * @param string $xml path/URL to XML file
1198
+ * @param string $type (schema | xml)
1199
+ * @return boolean
1200
+ * @access public
1201
+ */
1202
+ function parseFile($xml, $type)
1203
+ {
1204
+ // parse xml file
1205
+ if ($xml != "") {
1206
+ $xmlStr = @join("", @file($xml));
1207
+ if ($xmlStr == "") {
1208
+ $msg = 'Error reading XML from ' . $xml;
1209
+ $this->setError($msg);
1210
+ $this->debug($msg);
1211
+ return false;
1212
+ } else {
1213
+ $this->debug("parsing $xml");
1214
+ $this->parseString($xmlStr, $type);
1215
+ $this->debug("done parsing $xml");
1216
+ return true;
1217
+ }
1218
+ }
1219
+ return false;
1220
+ }
1221
+
1222
+ /**
1223
+ * parse an XML string
1224
+ *
1225
+ * @param string $xml path or URL
1226
+ * @param string $type (schema|xml)
1227
+ * @access private
1228
+ */
1229
+ function parseString($xml, $type)
1230
+ {
1231
+ // parse xml string
1232
+ if ($xml != "") {
1233
+
1234
+ // Create an XML parser.
1235
+ $this->parser = xml_parser_create();
1236
+ // Set the options for parsing the XML data.
1237
+ xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
1238
+
1239
+ // Set the object for the parser.
1240
+ xml_set_object($this->parser, $this);
1241
+
1242
+ // Set the element handlers for the parser.
1243
+ if ($type == "schema") {
1244
+ xml_set_element_handler($this->parser, 'schemaStartElement', 'schemaEndElement');
1245
+ xml_set_character_data_handler($this->parser, 'schemaCharacterData');
1246
+ } elseif ($type == "xml") {
1247
+ xml_set_element_handler($this->parser, 'xmlStartElement', 'xmlEndElement');
1248
+ xml_set_character_data_handler($this->parser, 'xmlCharacterData');
1249
+ }
1250
+
1251
+ // Parse the XML file.
1252
+ if (!xml_parse($this->parser, $xml, true)) {
1253
+ // Display an error message.
1254
+ $errstr = sprintf('XML error parsing XML schema on line %d: %s',
1255
+ xml_get_current_line_number($this->parser),
1256
+ xml_error_string(xml_get_error_code($this->parser))
1257
+ );
1258
+ $this->debug($errstr);
1259
+ $this->debug("XML payload:\n" . $xml);
1260
+ $this->setError($errstr);
1261
+ }
1262
+
1263
+ xml_parser_free($this->parser);
1264
+ unset($this->parser);
1265
+ } else {
1266
+ $this->debug('no xml passed to parseString()!!');
1267
+ $this->setError('no xml passed to parseString()!!');
1268
+ }
1269
+ }
1270
+
1271
+ /**
1272
+ * gets a type name for an unnamed type
1273
+ *
1274
+ * @param string Element name
1275
+ * @return string A type name for an unnamed type
1276
+ * @access private
1277
+ */
1278
+ function CreateTypeName($ename)
1279
+ {
1280
+ $scope = '';
1281
+ for ($i = 0; $i < count($this->complexTypeStack); $i++) {
1282
+ $scope .= $this->complexTypeStack[$i] . '_';
1283
+ }
1284
+ return $scope . $ename . '_ContainedType';
1285
+ }
1286
+
1287
+ /**
1288
+ * start-element handler
1289
+ *
1290
+ * @param string $parser XML parser object
1291
+ * @param string $name element name
1292
+ * @param string $attrs associative array of attributes
1293
+ * @access private
1294
+ */
1295
+ function schemaStartElement($parser, $name, $attrs)
1296
+ {
1297
+
1298
+ // position in the total number of elements, starting from 0
1299
+ $pos = $this->position++;
1300
+ $depth = $this->depth++;
1301
+ // set self as current value for this depth
1302
+ $this->depth_array[$depth] = $pos;
1303
+ $this->message[$pos] = array('cdata' => '');
1304
+ if ($depth > 0) {
1305
+ $this->defaultNamespace[$pos] = $this->defaultNamespace[$this->depth_array[$depth - 1]];
1306
+ } else {
1307
+ $this->defaultNamespace[$pos] = false;
1308
+ }
1309
+
1310
+ // get element prefix
1311
+ if ($prefix = $this->getPrefix($name)) {
1312
+ // get unqualified name
1313
+ $name = $this->getLocalPart($name);
1314
+ } else {
1315
+ $prefix = '';
1316
+ }
1317
+
1318
+ // loop thru attributes, expanding, and registering namespace declarations
1319
+ if (count($attrs) > 0) {
1320
+ foreach ($attrs as $k => $v) {
1321
+ // if ns declarations, add to class level array of valid namespaces
1322
+ if (preg_match('/^xmlns/', $k)) {
1323
+ //$this->xdebug("$k: $v");
1324
+ //$this->xdebug('ns_prefix: '.$this->getPrefix($k));
1325
+ if ($ns_prefix = substr(strrchr($k, ':'), 1)) {
1326
+ //$this->xdebug("Add namespace[$ns_prefix] = $v");
1327
+ $this->namespaces[$ns_prefix] = $v;
1328
+ } else {
1329
+ $this->defaultNamespace[$pos] = $v;
1330
+ if (!$this->getPrefixFromNamespace($v)) {
1331
+ $this->namespaces['ns' . (count($this->namespaces) + 1)] = $v;
1332
+ }
1333
+ }
1334
+ if ($v == 'http://www.w3.org/2001/XMLSchema' || $v == 'http://www.w3.org/1999/XMLSchema' || $v == 'http://www.w3.org/2000/10/XMLSchema') {
1335
+ $this->XMLSchemaVersion = $v;
1336
+ $this->namespaces['xsi'] = $v . '-instance';
1337
+ }
1338
+ }
1339
+ }
1340
+ foreach ($attrs as $k => $v) {
1341
+ // expand each attribute
1342
+ $k = strpos($k, ':') ? $this->expandQname($k) : $k;
1343
+ $v = strpos($v, ':') ? $this->expandQname($v) : $v;
1344
+ $eAttrs[$k] = $v;
1345
+ }
1346
+ $attrs = $eAttrs;
1347
+ } else {
1348
+ $attrs = array();
1349
+ }
1350
+ // find status, register data
1351
+ switch ($name) {
1352
+ case 'all': // (optional) compositor content for a complexType
1353
+ case 'choice':
1354
+ case 'group':
1355
+ case 'sequence':
1356
+ //$this->xdebug("compositor $name for currentComplexType: $this->currentComplexType and currentElement: $this->currentElement");
1357
+ $this->complexTypes[$this->currentComplexType]['compositor'] = $name;
1358
+ //if($name == 'all' || $name == 'sequence'){
1359
+ // $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
1360
+ //}
1361
+ break;
1362
+ case 'attribute': // complexType attribute
1363
+ //$this->xdebug("parsing attribute $attrs[name] $attrs[ref] of value: ".$attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']);
1364
+ $this->xdebug("parsing attribute:");
1365
+ $this->appendDebug($this->varDump($attrs));
1366
+ if (!isset($attrs['form'])) {
1367
+ // TODO: handle globals
1368
+ $attrs['form'] = $this->schemaInfo['attributeFormDefault'];
1369
+ }
1370
+ if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])) {
1371
+ $v = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
1372
+ if (!strpos($v, ':')) {
1373
+ // no namespace in arrayType attribute value...
1374
+ if ($this->defaultNamespace[$pos]) {
1375
+ // ...so use the default
1376
+ $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'] = $this->defaultNamespace[$pos] . ':' . $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
1377
+ }
1378
+ }
1379
+ }
1380
+ if (isset($attrs['name'])) {
1381
+ $this->attributes[$attrs['name']] = $attrs;
1382
+ $aname = $attrs['name'];
1383
+ } elseif (isset($attrs['ref']) && $attrs['ref'] == 'http://schemas.xmlsoap.org/soap/encoding/:arrayType') {
1384
+ if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])) {
1385
+ $aname = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
1386
+ } else {
1387
+ $aname = '';
1388
+ }
1389
+ } elseif (isset($attrs['ref'])) {
1390
+ $aname = $attrs['ref'];
1391
+ $this->attributes[$attrs['ref']] = $attrs;
1392
+ }
1393
+
1394
+ if ($this->currentComplexType) { // This should *always* be
1395
+ $this->complexTypes[$this->currentComplexType]['attrs'][$aname] = $attrs;
1396
+ }
1397
+ // arrayType attribute
1398
+ if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']) || $this->getLocalPart($aname) == 'arrayType') {
1399
+ $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
1400
+ $prefix = $this->getPrefix($aname);
1401
+ if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])) {
1402
+ $v = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
1403
+ } else {
1404
+ $v = '';
1405
+ }
1406
+ if (strpos($v, '[,]')) {
1407
+ $this->complexTypes[$this->currentComplexType]['multidimensional'] = true;
1408
+ }
1409
+ $v = substr($v, 0, strpos($v, '[')); // clip the []
1410
+ if (!strpos($v, ':') && isset($this->typemap[$this->XMLSchemaVersion][$v])) {
1411
+ $v = $this->XMLSchemaVersion . ':' . $v;
1412
+ }
1413
+ $this->complexTypes[$this->currentComplexType]['arrayType'] = $v;
1414
+ }
1415
+ break;
1416
+ case 'complexContent': // (optional) content for a complexType
1417
+ $this->xdebug("do nothing for element $name");
1418
+ break;
1419
+ case 'complexType':
1420
+ array_push($this->complexTypeStack, $this->currentComplexType);
1421
+ if (isset($attrs['name'])) {
1422
+ // TODO: what is the scope of named complexTypes that appear
1423
+ // nested within other c complexTypes?
1424
+ $this->xdebug('processing named complexType ' . $attrs['name']);
1425
+ //$this->currentElement = false;
1426
+ $this->currentComplexType = $attrs['name'];
1427
+ $this->complexTypes[$this->currentComplexType] = $attrs;
1428
+ $this->complexTypes[$this->currentComplexType]['typeClass'] = 'complexType';
1429
+ // This is for constructs like
1430
+ // <complexType name="ListOfString" base="soap:Array">
1431
+ // <sequence>
1432
+ // <element name="string" type="xsd:string"
1433
+ // minOccurs="0" maxOccurs="unbounded" />
1434
+ // </sequence>
1435
+ // </complexType>
1436
+ if (isset($attrs['base']) && preg_match('/:Array$/', $attrs['base'])) {
1437
+ $this->xdebug('complexType is unusual array');
1438
+ $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
1439
+ } else {
1440
+ $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
1441
+ }
1442
+ } else {
1443
+ $name = $this->CreateTypeName($this->currentElement);
1444
+ $this->xdebug('processing unnamed complexType for element ' . $this->currentElement . ' named ' . $name);
1445
+ $this->currentComplexType = $name;
1446
+ //$this->currentElement = false;
1447
+ $this->complexTypes[$this->currentComplexType] = $attrs;
1448
+ $this->complexTypes[$this->currentComplexType]['typeClass'] = 'complexType';
1449
+ // This is for constructs like
1450
+ // <complexType name="ListOfString" base="soap:Array">
1451
+ // <sequence>
1452
+ // <element name="string" type="xsd:string"
1453
+ // minOccurs="0" maxOccurs="unbounded" />
1454
+ // </sequence>
1455
+ // </complexType>
1456
+ if (isset($attrs['base']) && preg_match('/:Array$/', $attrs['base'])) {
1457
+ $this->xdebug('complexType is unusual array');
1458
+ $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
1459
+ } else {
1460
+ $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
1461
+ }
1462
+ }
1463
+ $this->complexTypes[$this->currentComplexType]['simpleContent'] = 'false';
1464
+ break;
1465
+ case 'element':
1466
+ array_push($this->elementStack, $this->currentElement);
1467
+ if (!isset($attrs['form'])) {
1468
+ if ($this->currentComplexType) {
1469
+ $attrs['form'] = $this->schemaInfo['elementFormDefault'];
1470
+ } else {
1471
+ // global
1472
+ $attrs['form'] = 'qualified';
1473
+ }
1474
+ }
1475
+ if (isset($attrs['type'])) {
1476
+ $this->xdebug("processing typed element " . $attrs['name'] . " of type " . $attrs['type']);
1477
+ if (!$this->getPrefix($attrs['type'])) {
1478
+ if ($this->defaultNamespace[$pos]) {
1479
+ $attrs['type'] = $this->defaultNamespace[$pos] . ':' . $attrs['type'];
1480
+ $this->xdebug('used default namespace to make type ' . $attrs['type']);
1481
+ }
1482
+ }
1483
+ // This is for constructs like
1484
+ // <complexType name="ListOfString" base="soap:Array">
1485
+ // <sequence>
1486
+ // <element name="string" type="xsd:string"
1487
+ // minOccurs="0" maxOccurs="unbounded" />
1488
+ // </sequence>
1489
+ // </complexType>
1490
+ if ($this->currentComplexType && $this->complexTypes[$this->currentComplexType]['phpType'] == 'array') {
1491
+ $this->xdebug('arrayType for unusual array is ' . $attrs['type']);
1492
+ $this->complexTypes[$this->currentComplexType]['arrayType'] = $attrs['type'];
1493
+ }
1494
+ $this->currentElement = $attrs['name'];
1495
+ $ename = $attrs['name'];
1496
+ } elseif (isset($attrs['ref'])) {
1497
+ $this->xdebug("processing element as ref to " . $attrs['ref']);
1498
+ $this->currentElement = "ref to " . $attrs['ref'];
1499
+ $ename = $this->getLocalPart($attrs['ref']);
1500
+ } else {
1501
+ $type = $this->CreateTypeName($this->currentComplexType . '_' . $attrs['name']);
1502
+ $this->xdebug("processing untyped element " . $attrs['name'] . ' type ' . $type);
1503
+ $this->currentElement = $attrs['name'];
1504
+ $attrs['type'] = $this->schemaTargetNamespace . ':' . $type;
1505
+ $ename = $attrs['name'];
1506
+ }
1507
+ if (isset($ename) && $this->currentComplexType) {
1508
+ $this->xdebug("add element $ename to complexType $this->currentComplexType");
1509
+ $this->complexTypes[$this->currentComplexType]['elements'][$ename] = $attrs;
1510
+ } elseif (!isset($attrs['ref'])) {
1511
+ $this->xdebug("add element $ename to elements array");
1512
+ $this->elements[$attrs['name']] = $attrs;
1513
+ $this->elements[$attrs['name']]['typeClass'] = 'element';
1514
+ }
1515
+ break;
1516
+ case 'enumeration': // restriction value list member
1517
+ $this->xdebug('enumeration ' . $attrs['value']);
1518
+ if ($this->currentSimpleType) {
1519
+ $this->simpleTypes[$this->currentSimpleType]['enumeration'][] = $attrs['value'];
1520
+ } elseif ($this->currentComplexType) {
1521
+ $this->complexTypes[$this->currentComplexType]['enumeration'][] = $attrs['value'];
1522
+ }
1523
+ break;
1524
+ case 'extension': // simpleContent or complexContent type extension
1525
+ $this->xdebug('extension ' . $attrs['base']);
1526
+ if ($this->currentComplexType) {
1527
+ $ns = $this->getPrefix($attrs['base']);
1528
+ if ($ns == '') {
1529
+ $this->complexTypes[$this->currentComplexType]['extensionBase'] = $this->schemaTargetNamespace . ':' . $attrs['base'];
1530
+ } else {
1531
+ $this->complexTypes[$this->currentComplexType]['extensionBase'] = $attrs['base'];
1532
+ }
1533
+ } else {
1534
+ $this->xdebug('no current complexType to set extensionBase');
1535
+ }
1536
+ break;
1537
+ case 'import':
1538
+ if (isset($attrs['schemaLocation'])) {
1539
+ $this->xdebug('import namespace ' . $attrs['namespace'] . ' from ' . $attrs['schemaLocation']);
1540
+ $this->imports[$attrs['namespace']][] = array('location' => $attrs['schemaLocation'], 'loaded' => false);
1541
+ } else {
1542
+ $this->xdebug('import namespace ' . $attrs['namespace']);
1543
+ $this->imports[$attrs['namespace']][] = array('location' => '', 'loaded' => true);
1544
+ if (!$this->getPrefixFromNamespace($attrs['namespace'])) {
1545
+ $this->namespaces['ns' . (count($this->namespaces) + 1)] = $attrs['namespace'];
1546
+ }
1547
+ }
1548
+ break;
1549
+ case 'include':
1550
+ if (isset($attrs['schemaLocation'])) {
1551
+ $this->xdebug('include into namespace ' . $this->schemaTargetNamespace . ' from ' . $attrs['schemaLocation']);
1552
+ $this->imports[$this->schemaTargetNamespace][] = array('location' => $attrs['schemaLocation'], 'loaded' => false);
1553
+ } else {
1554
+ $this->xdebug('ignoring invalid XML Schema construct: include without schemaLocation attribute');
1555
+ }
1556
+ break;
1557
+ case 'list': // simpleType value list
1558
+ $this->xdebug("do nothing for element $name");
1559
+ break;
1560
+ case 'restriction': // simpleType, simpleContent or complexContent value restriction
1561
+ $this->xdebug('restriction ' . $attrs['base']);
1562
+ if ($this->currentSimpleType) {
1563
+ $this->simpleTypes[$this->currentSimpleType]['type'] = $attrs['base'];
1564
+ } elseif ($this->currentComplexType) {
1565
+ $this->complexTypes[$this->currentComplexType]['restrictionBase'] = $attrs['base'];
1566
+ if (strstr($attrs['base'], ':') == ':Array') {
1567
+ $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
1568
+ }
1569
+ }
1570
+ break;
1571
+ case 'schema':
1572
+ $this->schemaInfo = $attrs;
1573
+ $this->schemaInfo['schemaVersion'] = $this->getNamespaceFromPrefix($prefix);
1574
+ if (isset($attrs['targetNamespace'])) {
1575
+ $this->schemaTargetNamespace = $attrs['targetNamespace'];
1576
+ }
1577
+ if (!isset($attrs['elementFormDefault'])) {
1578
+ $this->schemaInfo['elementFormDefault'] = 'unqualified';
1579
+ }
1580
+ if (!isset($attrs['attributeFormDefault'])) {
1581
+ $this->schemaInfo['attributeFormDefault'] = 'unqualified';
1582
+ }
1583
+ break;
1584
+ case 'simpleContent': // (optional) content for a complexType
1585
+ if ($this->currentComplexType) { // This should *always* be
1586
+ $this->complexTypes[$this->currentComplexType]['simpleContent'] = 'true';
1587
+ } else {
1588
+ $this->xdebug("do nothing for element $name because there is no current complexType");
1589
+ }
1590
+ break;
1591
+ case 'simpleType':
1592
+ array_push($this->simpleTypeStack, $this->currentSimpleType);
1593
+ if (isset($attrs['name'])) {
1594
+ $this->xdebug("processing simpleType for name " . $attrs['name']);
1595
+ $this->currentSimpleType = $attrs['name'];
1596
+ $this->simpleTypes[$attrs['name']] = $attrs;
1597
+ $this->simpleTypes[$attrs['name']]['typeClass'] = 'simpleType';
1598
+ $this->simpleTypes[$attrs['name']]['phpType'] = 'scalar';
1599
+ } else {
1600
+ $name = $this->CreateTypeName($this->currentComplexType . '_' . $this->currentElement);
1601
+ $this->xdebug('processing unnamed simpleType for element ' . $this->currentElement . ' named ' . $name);
1602
+ $this->currentSimpleType = $name;
1603
+ //$this->currentElement = false;
1604
+ $this->simpleTypes[$this->currentSimpleType] = $attrs;
1605
+ $this->simpleTypes[$this->currentSimpleType]['phpType'] = 'scalar';
1606
+ }
1607
+ break;
1608
+ case 'union': // simpleType type list
1609
+ $this->xdebug("do nothing for element $name");
1610
+ break;
1611
+ default:
1612
+ $this->xdebug("do not have any logic to process element $name");
1613
+ }
1614
+ }
1615
+
1616
+ /**
1617
+ * end-element handler
1618
+ *
1619
+ * @param string $parser XML parser object
1620
+ * @param string $name element name
1621
+ * @access private
1622
+ */
1623
+ function schemaEndElement($parser, $name)
1624
+ {
1625
+ // bring depth down a notch
1626
+ $this->depth--;
1627
+ // position of current element is equal to the last value left in depth_array for my depth
1628
+ if (isset($this->depth_array[$this->depth])) {
1629
+ $pos = $this->depth_array[$this->depth];
1630
+ }
1631
+ // get element prefix
1632
+ if ($prefix = $this->getPrefix($name)) {
1633
+ // get unqualified name
1634
+ $name = $this->getLocalPart($name);
1635
+ } else {
1636
+ $prefix = '';
1637
+ }
1638
+ // move on...
1639
+ if ($name == 'complexType') {
1640
+ $this->xdebug('done processing complexType ' . ($this->currentComplexType ? $this->currentComplexType : '(unknown)'));
1641
+ $this->xdebug($this->varDump($this->complexTypes[$this->currentComplexType]));
1642
+ $this->currentComplexType = array_pop($this->complexTypeStack);
1643
+ //$this->currentElement = false;
1644
+ }
1645
+ if ($name == 'element') {
1646
+ $this->xdebug('done processing element ' . ($this->currentElement ? $this->currentElement : '(unknown)'));
1647
+ $this->currentElement = array_pop($this->elementStack);
1648
+ }
1649
+ if ($name == 'simpleType') {
1650
+ $this->xdebug('done processing simpleType ' . ($this->currentSimpleType ? $this->currentSimpleType : '(unknown)'));
1651
+ $this->xdebug($this->varDump($this->simpleTypes[$this->currentSimpleType]));
1652
+ $this->currentSimpleType = array_pop($this->simpleTypeStack);
1653
+ }
1654
+ }
1655
+
1656
+ /**
1657
+ * element content handler
1658
+ *
1659
+ * @param string $parser XML parser object
1660
+ * @param string $data element content
1661
+ * @access private
1662
+ */
1663
+ function schemaCharacterData($parser, $data)
1664
+ {
1665
+ $pos = $this->depth_array[$this->depth - 1];
1666
+ $this->message[$pos]['cdata'] .= $data;
1667
+ }
1668
+
1669
+ /**
1670
+ * serialize the schema
1671
+ *
1672
+ * @access public
1673
+ */
1674
+ function serializeSchema()
1675
+ {
1676
+
1677
+ $schemaPrefix = $this->getPrefixFromNamespace($this->XMLSchemaVersion);
1678
+ $xml = '';
1679
+ // imports
1680
+ if (sizeof($this->imports) > 0) {
1681
+ foreach ($this->imports as $ns => $list) {
1682
+ foreach ($list as $ii) {
1683
+ if ($ii['location'] != '') {
1684
+ $xml .= " <$schemaPrefix:import location=\"" . $ii['location'] . '" namespace="' . $ns . "\" />\n";
1685
+ } else {
1686
+ $xml .= " <$schemaPrefix:import namespace=\"" . $ns . "\" />\n";
1687
+ }
1688
+ }
1689
+ }
1690
+ }
1691
+ // complex types
1692
+ foreach ($this->complexTypes as $typeName => $attrs) {
1693
+ $contentStr = '';
1694
+ // serialize child elements
1695
+ if (isset($attrs['elements']) && (count($attrs['elements']) > 0)) {
1696
+ foreach ($attrs['elements'] as $element => $eParts) {
1697
+ if (isset($eParts['ref'])) {
1698
+ $contentStr .= " <$schemaPrefix:element ref=\"$element\"/>\n";
1699
+ } else {
1700
+ $contentStr .= " <$schemaPrefix:element name=\"$element\" type=\"" . $this->contractQName($eParts['type']) . "\"";
1701
+ foreach ($eParts as $aName => $aValue) {
1702
+ // handle, e.g., abstract, default, form, minOccurs, maxOccurs, nillable
1703
+ if ($aName != 'name' && $aName != 'type') {
1704
+ $contentStr .= " $aName=\"$aValue\"";
1705
+ }
1706
+ }
1707
+ $contentStr .= "/>\n";
1708
+ }
1709
+ }
1710
+ // compositor wraps elements
1711
+ if (isset($attrs['compositor']) && ($attrs['compositor'] != '')) {
1712
+ $contentStr = " <$schemaPrefix:$attrs[compositor]>\n" . $contentStr . " </$schemaPrefix:$attrs[compositor]>\n";
1713
+ }
1714
+ }
1715
+ // attributes
1716
+ if (isset($attrs['attrs']) && (count($attrs['attrs']) >= 1)) {
1717
+ foreach ($attrs['attrs'] as $attr => $aParts) {
1718
+ $contentStr .= " <$schemaPrefix:attribute";
1719
+ foreach ($aParts as $a => $v) {
1720
+ if ($a == 'ref' || $a == 'type') {
1721
+ $contentStr .= " $a=\"" . $this->contractQName($v) . '"';
1722
+ } elseif ($a == 'http://schemas.xmlsoap.org/wsdl/:arrayType') {
1723
+ $this->usedNamespaces['wsdl'] = $this->namespaces['wsdl'];
1724
+ $contentStr .= ' wsdl:arrayType="' . $this->contractQName($v) . '"';
1725
+ } else {
1726
+ $contentStr .= " $a=\"$v\"";
1727
+ }
1728
+ }
1729
+ $contentStr .= "/>\n";
1730
+ }
1731
+ }
1732
+ // if restriction
1733
+ if (isset($attrs['restrictionBase']) && $attrs['restrictionBase'] != '') {
1734
+ $contentStr = " <$schemaPrefix:restriction base=\"" . $this->contractQName($attrs['restrictionBase']) . "\">\n" . $contentStr . " </$schemaPrefix:restriction>\n";
1735
+ // complex or simple content
1736
+ if ((isset($attrs['elements']) && count($attrs['elements']) > 0) || (isset($attrs['attrs']) && count($attrs['attrs']) > 0)) {
1737
+ $contentStr = " <$schemaPrefix:complexContent>\n" . $contentStr . " </$schemaPrefix:complexContent>\n";
1738
+ }
1739
+ }
1740
+ // finalize complex type
1741
+ if ($contentStr != '') {
1742
+ $contentStr = " <$schemaPrefix:complexType name=\"$typeName\">\n" . $contentStr . " </$schemaPrefix:complexType>\n";
1743
+ } else {
1744
+ $contentStr = " <$schemaPrefix:complexType name=\"$typeName\"/>\n";
1745
+ }
1746
+ $xml .= $contentStr;
1747
+ }
1748
+ // simple types
1749
+ if (isset($this->simpleTypes) && count($this->simpleTypes) > 0) {
1750
+ foreach ($this->simpleTypes as $typeName => $eParts) {
1751
+ $xml .= " <$schemaPrefix:simpleType name=\"$typeName\">\n <$schemaPrefix:restriction base=\"" . $this->contractQName($eParts['type']) . "\">\n";
1752
+ if (isset($eParts['enumeration'])) {
1753
+ foreach ($eParts['enumeration'] as $e) {
1754
+ $xml .= " <$schemaPrefix:enumeration value=\"$e\"/>\n";
1755
+ }
1756
+ }
1757
+ $xml .= " </$schemaPrefix:restriction>\n </$schemaPrefix:simpleType>";
1758
+ }
1759
+ }
1760
+ // elements
1761
+ if (isset($this->elements) && count($this->elements) > 0) {
1762
+ foreach ($this->elements as $element => $eParts) {
1763
+ $xml .= " <$schemaPrefix:element name=\"$element\" type=\"" . $this->contractQName($eParts['type']) . "\"/>\n";
1764
+ }
1765
+ }
1766
+ // attributes
1767
+ if (isset($this->attributes) && count($this->attributes) > 0) {
1768
+ foreach ($this->attributes as $attr => $aParts) {
1769
+ $xml .= " <$schemaPrefix:attribute name=\"$attr\" type=\"" . $this->contractQName($aParts['type']) . "\"\n/>";
1770
+ }
1771
+ }
1772
+ // finish 'er up
1773
+ $attr = '';
1774
+ foreach ($this->schemaInfo as $k => $v) {
1775
+ if ($k == 'elementFormDefault' || $k == 'attributeFormDefault') {
1776
+ $attr .= " $k=\"$v\"";
1777
+ }
1778
+ }
1779
+ $el = "<$schemaPrefix:schema$attr targetNamespace=\"$this->schemaTargetNamespace\"\n";
1780
+ foreach (array_diff($this->usedNamespaces, $this->enclosingNamespaces) as $nsp => $ns) {
1781
+ $el .= " xmlns:$nsp=\"$ns\"";
1782
+ }
1783
+ $xml = $el . ">\n" . $xml . "</$schemaPrefix:schema>\n";
1784
+ return $xml;
1785
+ }
1786
+
1787
+ /**
1788
+ * adds debug data to the clas level debug string
1789
+ *
1790
+ * @param string $string debug data
1791
+ * @access private
1792
+ */
1793
+ function xdebug($string)
1794
+ {
1795
+ $this->debug('<' . $this->schemaTargetNamespace . '> ' . $string);
1796
+ }
1797
+
1798
+ /**
1799
+ * get the PHP type of a user defined type in the schema
1800
+ * PHP type is kind of a misnomer since it actually returns 'struct' for assoc. arrays
1801
+ * returns false if no type exists, or not w/ the given namespace
1802
+ * else returns a string that is either a native php type, or 'struct'
1803
+ *
1804
+ * @param string $type name of defined type
1805
+ * @param string $ns namespace of type
1806
+ * @return mixed
1807
+ * @access public
1808
+ * @deprecated
1809
+ */
1810
+ function getPHPType($type, $ns)
1811
+ {
1812
+ if (isset($this->typemap[$ns][$type])) {
1813
+ //print "found type '$type' and ns $ns in typemap<br>";
1814
+ return $this->typemap[$ns][$type];
1815
+ } elseif (isset($this->complexTypes[$type])) {
1816
+ //print "getting type '$type' and ns $ns from complexTypes array<br>";
1817
+ return $this->complexTypes[$type]['phpType'];
1818
+ }
1819
+ return false;
1820
+ }
1821
+
1822
+ /**
1823
+ * returns an associative array of information about a given type
1824
+ * returns false if no type exists by the given name
1825
+ *
1826
+ * For a complexType typeDef = array(
1827
+ * 'restrictionBase' => '',
1828
+ * 'phpType' => '',
1829
+ * 'compositor' => '(sequence|all)',
1830
+ * 'elements' => array(), // refs to elements array
1831
+ * 'attrs' => array() // refs to attributes array
1832
+ * ... and so on (see addComplexType)
1833
+ * )
1834
+ *
1835
+ * For simpleType or element, the array has different keys.
1836
+ *
1837
+ * @param string $type
1838
+ * @return mixed
1839
+ * @access public
1840
+ * @see addComplexType
1841
+ * @see addSimpleType
1842
+ * @see addElement
1843
+ */
1844
+ function getTypeDef($type)
1845
+ {
1846
+ //$this->debug("in getTypeDef for type $type");
1847
+ if (substr($type, -1) == '^') {
1848
+ $is_element = 1;
1849
+ $type = substr($type, 0, -1);
1850
+ } else {
1851
+ $is_element = 0;
1852
+ }
1853
+
1854
+ if ((!$is_element) && isset($this->complexTypes[$type])) {
1855
+ $this->xdebug("in getTypeDef, found complexType $type");
1856
+ return $this->complexTypes[$type];
1857
+ } elseif ((!$is_element) && isset($this->simpleTypes[$type])) {
1858
+ $this->xdebug("in getTypeDef, found simpleType $type");
1859
+ if (!isset($this->simpleTypes[$type]['phpType'])) {
1860
+ // get info for type to tack onto the simple type
1861
+ // TODO: can this ever really apply (i.e. what is a simpleType really?)
1862
+ $uqType = substr($this->simpleTypes[$type]['type'], strrpos($this->simpleTypes[$type]['type'], ':') + 1);
1863
+ $ns = substr($this->simpleTypes[$type]['type'], 0, strrpos($this->simpleTypes[$type]['type'], ':'));
1864
+ $etype = $this->getTypeDef($uqType);
1865
+ if ($etype) {
1866
+ $this->xdebug("in getTypeDef, found type for simpleType $type:");
1867
+ $this->xdebug($this->varDump($etype));
1868
+ if (isset($etype['phpType'])) {
1869
+ $this->simpleTypes[$type]['phpType'] = $etype['phpType'];
1870
+ }
1871
+ if (isset($etype['elements'])) {
1872
+ $this->simpleTypes[$type]['elements'] = $etype['elements'];
1873
+ }
1874
+ }
1875
+ }
1876
+ return $this->simpleTypes[$type];
1877
+ } elseif (isset($this->elements[$type])) {
1878
+ $this->xdebug("in getTypeDef, found element $type");
1879
+ if (!isset($this->elements[$type]['phpType'])) {
1880
+ // get info for type to tack onto the element
1881
+ $uqType = substr($this->elements[$type]['type'], strrpos($this->elements[$type]['type'], ':') + 1);
1882
+ $ns = substr($this->elements[$type]['type'], 0, strrpos($this->elements[$type]['type'], ':'));
1883
+ $etype = $this->getTypeDef($uqType);
1884
+ if ($etype) {
1885
+ $this->xdebug("in getTypeDef, found type for element $type:");
1886
+ $this->xdebug($this->varDump($etype));
1887
+ if (isset($etype['phpType'])) {
1888
+ $this->elements[$type]['phpType'] = $etype['phpType'];
1889
+ }
1890
+ if (isset($etype['elements'])) {
1891
+ $this->elements[$type]['elements'] = $etype['elements'];
1892
+ }
1893
+ if (isset($etype['extensionBase'])) {
1894
+ $this->elements[$type]['extensionBase'] = $etype['extensionBase'];
1895
+ }
1896
+ } elseif ($ns == 'http://www.w3.org/2001/XMLSchema') {
1897
+ $this->xdebug("in getTypeDef, element $type is an XSD type");
1898
+ $this->elements[$type]['phpType'] = 'scalar';
1899
+ }
1900
+ }
1901
+ return $this->elements[$type];
1902
+ } elseif (isset($this->attributes[$type])) {
1903
+ $this->xdebug("in getTypeDef, found attribute $type");
1904
+ return $this->attributes[$type];
1905
+ } elseif (preg_match('/_ContainedType$/', $type)) {
1906
+ $this->xdebug("in getTypeDef, have an untyped element $type");
1907
+ $typeDef['typeClass'] = 'simpleType';
1908
+ $typeDef['phpType'] = 'scalar';
1909
+ $typeDef['type'] = 'http://www.w3.org/2001/XMLSchema:string';
1910
+ return $typeDef;
1911
+ }
1912
+ $this->xdebug("in getTypeDef, did not find $type");
1913
+ return false;
1914
+ }
1915
+
1916
+ /**
1917
+ * returns a sample serialization of a given type, or false if no type by the given name
1918
+ *
1919
+ * @param string $type name of type
1920
+ * @return mixed
1921
+ * @access public
1922
+ * @deprecated
1923
+ */
1924
+ function serializeTypeDef($type)
1925
+ {
1926
+ //print "in sTD() for type $type<br>";
1927
+ if ($typeDef = $this->getTypeDef($type)) {
1928
+ $str .= '<' . $type;
1929
+ if (is_array($typeDef['attrs'])) {
1930
+ foreach ($typeDef['attrs'] as $attName => $data) {
1931
+ $str .= " $attName=\"{type = " . $data['type'] . "}\"";
1932
+ }
1933
+ }
1934
+ $str .= " xmlns=\"" . $this->schema['targetNamespace'] . "\"";
1935
+ if (count($typeDef['elements']) > 0) {
1936
+ $str .= ">";
1937
+ foreach ($typeDef['elements'] as $element => $eData) {
1938
+ $str .= $this->serializeTypeDef($element);
1939
+ }
1940
+ $str .= "</$type>";
1941
+ } elseif ($typeDef['typeClass'] == 'element') {
1942
+ $str .= "></$type>";
1943
+ } else {
1944
+ $str .= "/>";
1945
+ }
1946
+ return $str;
1947
+ }
1948
+ return false;
1949
+ }
1950
+
1951
+ /**
1952
+ * returns HTML form elements that allow a user
1953
+ * to enter values for creating an instance of the given type.
1954
+ *
1955
+ * @param string $name name for type instance
1956
+ * @param string $type name of type
1957
+ * @return string
1958
+ * @access public
1959
+ * @deprecated
1960
+ */
1961
+ function typeToForm($name, $type)
1962
+ {
1963
+ // get typedef
1964
+ if ($typeDef = $this->getTypeDef($type)) {
1965
+ // if struct
1966
+ if ($typeDef['phpType'] == 'struct') {
1967
+ $buffer .= '<table>';
1968
+ foreach ($typeDef['elements'] as $child => $childDef) {
1969
+ $buffer .= "
1970
+ <tr><td align='right'>$childDef[name] (type: " . $this->getLocalPart($childDef['type']) . "):</td>
1971
+ <td><input type='text' name='parameters[" . $name . "][$childDef[name]]'></td></tr>";
1972
+ }
1973
+ $buffer .= '</table>';
1974
+ // if array
1975
+ } elseif ($typeDef['phpType'] == 'array') {
1976
+ $buffer .= '<table>';
1977
+ for ($i = 0; $i < 3; $i++) {
1978
+ $buffer .= "
1979
+ <tr><td align='right'>array item (type: $typeDef[arrayType]):</td>
1980
+ <td><input type='text' name='parameters[" . $name . "][]'></td></tr>";
1981
+ }
1982
+ $buffer .= '</table>';
1983
+ // if scalar
1984
+ } else {
1985
+ $buffer .= "<input type='text' name='parameters[$name]'>";
1986
+ }
1987
+ } else {
1988
+ $buffer .= "<input type='text' name='parameters[$name]'>";
1989
+ }
1990
+ return $buffer;
1991
+ }
1992
+
1993
+ /**
1994
+ * adds a complex type to the schema
1995
+ *
1996
+ * example: array
1997
+ *
1998
+ * addType(
1999
+ * 'ArrayOfstring',
2000
+ * 'complexType',
2001
+ * 'array',
2002
+ * '',
2003
+ * 'SOAP-ENC:Array',
2004
+ * array('ref'=>'SOAP-ENC:arrayType','wsdl:arrayType'=>'string[]'),
2005
+ * 'xsd:string'
2006
+ * );
2007
+ *
2008
+ * example: PHP associative array ( SOAP Struct )
2009
+ *
2010
+ * addType(
2011
+ * 'SOAPStruct',
2012
+ * 'complexType',
2013
+ * 'struct',
2014
+ * 'all',
2015
+ * array('myVar'=> array('name'=>'myVar','type'=>'string')
2016
+ * );
2017
+ *
2018
+ * @param name
2019
+ * @param typeClass (complexType|simpleType|attribute)
2020
+ * @param phpType : currently supported are array and struct (php assoc array)
2021
+ * @param compositor (all|sequence|choice)
2022
+ * @param restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
2023
+ * @param elements = array ( name = array(name=>'',type=>'') )
2024
+ * @param attrs = array(
2025
+ * array(
2026
+ * 'ref' => "http://schemas.xmlsoap.org/soap/encoding/:arrayType",
2027
+ * "http://schemas.xmlsoap.org/wsdl/:arrayType" => "string[]"
2028
+ * )
2029
+ * )
2030
+ * @param arrayType : namespace:name (http://www.w3.org/2001/XMLSchema:string)
2031
+ * @access public
2032
+ * @see getTypeDef
2033
+ */
2034
+ function addComplexType($name, $typeClass = 'complexType', $phpType = 'array', $compositor = '', $restrictionBase = '', $elements = array(), $attrs = array(), $arrayType = '')
2035
+ {
2036
+ $this->complexTypes[$name] = array(
2037
+ 'name' => $name,
2038
+ 'typeClass' => $typeClass,
2039
+ 'phpType' => $phpType,
2040
+ 'compositor' => $compositor,
2041
+ 'restrictionBase' => $restrictionBase,
2042
+ 'elements' => $elements,
2043
+ 'attrs' => $attrs,
2044
+ 'arrayType' => $arrayType
2045
+ );
2046
+
2047
+ $this->xdebug("addComplexType $name:");
2048
+ $this->appendDebug($this->varDump($this->complexTypes[$name]));
2049
+ }
2050
+
2051
+ /**
2052
+ * adds a simple type to the schema
2053
+ *
2054
+ * @param string $name
2055
+ * @param string $restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
2056
+ * @param string $typeClass (should always be simpleType)
2057
+ * @param string $phpType (should always be scalar)
2058
+ * @param array $enumeration array of values
2059
+ * @access public
2060
+ * @see nusoap_xmlschema
2061
+ * @see getTypeDef
2062
+ */
2063
+ function addSimpleType($name, $restrictionBase = '', $typeClass = 'simpleType', $phpType = 'scalar', $enumeration = array())
2064
+ {
2065
+ $this->simpleTypes[$name] = array(
2066
+ 'name' => $name,
2067
+ 'typeClass' => $typeClass,
2068
+ 'phpType' => $phpType,
2069
+ 'type' => $restrictionBase,
2070
+ 'enumeration' => $enumeration
2071
+ );
2072
+
2073
+ $this->xdebug("addSimpleType $name:");
2074
+ $this->appendDebug($this->varDump($this->simpleTypes[$name]));
2075
+ }
2076
+
2077
+ /**
2078
+ * adds an element to the schema
2079
+ *
2080
+ * @param array $attrs attributes that must include name and type
2081
+ * @see nusoap_xmlschema
2082
+ * @access public
2083
+ */
2084
+ function addElement($attrs)
2085
+ {
2086
+ if (!$this->getPrefix($attrs['type'])) {
2087
+ $attrs['type'] = $this->schemaTargetNamespace . ':' . $attrs['type'];
2088
+ }
2089
+ $this->elements[$attrs['name']] = $attrs;
2090
+ $this->elements[$attrs['name']]['typeClass'] = 'element';
2091
+
2092
+ $this->xdebug("addElement " . $attrs['name']);
2093
+ $this->appendDebug($this->varDump($this->elements[$attrs['name']]));
2094
+ }
2095
+ }
2096
+
2097
+ /**
2098
+ * Backward compatibility
2099
+ */
2100
+ class XMLSchema extends nusoap_xmlschema
2101
+ {
2102
+ }
2103
+
2104
+
2105
+ /**
2106
+ * For creating serializable abstractions of native PHP types. This class
2107
+ * allows element name/namespace, XSD type, and XML attributes to be
2108
+ * associated with a value. This is extremely useful when WSDL is not
2109
+ * used, but is also useful when WSDL is used with polymorphic types, including
2110
+ * xsd:anyType and user-defined types.
2111
+ *
2112
+ * @author Dietrich Ayala <dietrich@ganx4.com>
2113
+ * @version $Id: nusoap.php,v 1.123 2010/04/26 20:15:08 snichol Exp $
2114
+ * @access public
2115
+ */
2116
+ class soapval extends nusoap_base
2117
+ {
2118
+ /**
2119
+ * The XML element name
2120
+ *
2121
+ * @var string
2122
+ * @access private
2123
+ */
2124
+ var $name;
2125
+ /**
2126
+ * The XML type name (string or false)
2127
+ *
2128
+ * @var mixed
2129
+ * @access private
2130
+ */
2131
+ var $type;
2132
+ /**
2133
+ * The PHP value
2134
+ *
2135
+ * @var mixed
2136
+ * @access private
2137
+ */
2138
+ var $value;
2139
+ /**
2140
+ * The XML element namespace (string or false)
2141
+ *
2142
+ * @var mixed
2143
+ * @access private
2144
+ */
2145
+ var $element_ns;
2146
+ /**
2147
+ * The XML type namespace (string or false)
2148
+ *
2149
+ * @var mixed
2150
+ * @access private
2151
+ */
2152
+ var $type_ns;
2153
+ /**
2154
+ * The XML element attributes (array or false)
2155
+ *
2156
+ * @var mixed
2157
+ * @access private
2158
+ */
2159
+ var $attributes;
2160
+
2161
+ /**
2162
+ * constructor
2163
+ *
2164
+ * @param string $name optional name
2165
+ * @param mixed $type optional type name
2166
+ * @param mixed $value optional value
2167
+ * @param mixed $element_ns optional namespace of value
2168
+ * @param mixed $type_ns optional namespace of type
2169
+ * @param mixed $attributes associative array of attributes to add to element serialization
2170
+ * @access public
2171
+ */
2172
+ function __construct($name = 'soapval', $type = false, $value = -1, $element_ns = false, $type_ns = false, $attributes = false)
2173
+ {
2174
+ parent::__construct();
2175
+ $this->name = $name;
2176
+ $this->type = $type;
2177
+ $this->value = $value;
2178
+ $this->element_ns = $element_ns;
2179
+ $this->type_ns = $type_ns;
2180
+ $this->attributes = $attributes;
2181
+ }
2182
+
2183
+ /**
2184
+ * return serialized value
2185
+ *
2186
+ * @param string $use The WSDL use value (encoded|literal)
2187
+ * @return string XML data
2188
+ * @access public
2189
+ */
2190
+ function serialize($use = 'encoded')
2191
+ {
2192
+ return $this->serialize_val($this->value, $this->name, $this->type, $this->element_ns, $this->type_ns, $this->attributes, $use, true);
2193
+ }
2194
+
2195
+ /**
2196
+ * decodes a soapval object into a PHP native type
2197
+ *
2198
+ * @return mixed
2199
+ * @access public
2200
+ */
2201
+ function decode()
2202
+ {
2203
+ return $this->value;
2204
+ }
2205
+ }
2206
+
2207
+
2208
+ /**
2209
+ * transport class for sending/receiving data via HTTP and HTTPS
2210
+ * NOTE: PHP must be compiled with the CURL extension for HTTPS support
2211
+ *
2212
+ * @author Dietrich Ayala <dietrich@ganx4.com>
2213
+ * @author Scott Nichol <snichol@users.sourceforge.net>
2214
+ * @version $Id: nusoap.php,v 1.123 2010/04/26 20:15:08 snichol Exp $
2215
+ * @access public
2216
+ */
2217
+ class soap_transport_http extends nusoap_base
2218
+ {
2219
+
2220
+ var $url = '';
2221
+ var $uri = '';
2222
+ var $digest_uri = '';
2223
+ var $scheme = '';
2224
+ var $host = '';
2225
+ var $port = '';
2226
+ var $path = '';
2227
+ var $request_method = 'POST';
2228
+ var $protocol_version = '1.0';
2229
+ var $encoding = '';
2230
+ var $outgoing_headers = array();
2231
+ var $incoming_headers = array();
2232
+ var $incoming_cookies = array();
2233
+ var $outgoing_payload = '';
2234
+ var $incoming_payload = '';
2235
+ var $response_status_line; // HTTP response status line
2236
+ var $useSOAPAction = true;
2237
+ var $persistentConnection = false;
2238
+ var $ch = false; // cURL handle
2239
+ var $ch_options = array(); // cURL custom options
2240
+ var $use_curl = false; // force cURL use
2241
+ var $proxy = null; // proxy information (associative array)
2242
+ var $username = '';
2243
+ var $password = '';
2244
+ var $authtype = '';
2245
+ var $digestRequest = array();
2246
+ var $certRequest = array(); // keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, certpassword (optional), verifypeer (optional), verifyhost (optional)
2247
+ // cainfofile: certificate authority file, e.g. '$pathToPemFiles/rootca.pem'
2248
+ // sslcertfile: SSL certificate file, e.g. '$pathToPemFiles/mycert.pem'
2249
+ // sslkeyfile: SSL key file, e.g. '$pathToPemFiles/mykey.pem'
2250
+ // passphrase: SSL key password/passphrase
2251
+ // certpassword: SSL certificate password
2252
+ // verifypeer: default is 1
2253
+ // verifyhost: default is 1
2254
+
2255
+ /**
2256
+ * constructor
2257
+ *
2258
+ * @param string $url The URL to which to connect
2259
+ * @param array $curl_options User-specified cURL options
2260
+ * @param boolean $use_curl Whether to try to force cURL use
2261
+ * @access public
2262
+ */
2263
+ function __construct($url, $curl_options = null, $use_curl = false)
2264
+ {
2265
+ parent::__construct();
2266
+ $this->debug("ctor url=$url use_curl=$use_curl curl_options:");
2267
+ $this->appendDebug($this->varDump($curl_options));
2268
+ $this->setURL($url);
2269
+ if (is_array($curl_options)) {
2270
+ $this->ch_options = $curl_options;
2271
+ }
2272
+ $this->use_curl = $use_curl;
2273
+ preg_match('/\$Revisio' . 'n: ([^ ]+)/', $this->revision, $rev);
2274
+ $this->setHeader('User-Agent', $this->title . '/' . $this->version . ' (' . $rev[1] . ')');
2275
+ }
2276
+
2277
+ /**
2278
+ * sets a cURL option
2279
+ *
2280
+ * @param mixed $option The cURL option (always integer?)
2281
+ * @param mixed $value The cURL option value
2282
+ * @access private
2283
+ */
2284
+ function setCurlOption($option, $value)
2285
+ {
2286
+ $this->debug("setCurlOption option=$option, value=");
2287
+ $this->appendDebug($this->varDump($value));
2288
+ curl_setopt($this->ch, $option, $value);
2289
+ }
2290
+
2291
+ /**
2292
+ * sets an HTTP header
2293
+ *
2294
+ * @param string $name The name of the header
2295
+ * @param string $value The value of the header
2296
+ * @access private
2297
+ */
2298
+ function setHeader($name, $value)
2299
+ {
2300
+ $this->outgoing_headers[$name] = $value;
2301
+ $this->debug("set header $name: $value");
2302
+ }
2303
+
2304
+ /**
2305
+ * unsets an HTTP header
2306
+ *
2307
+ * @param string $name The name of the header
2308
+ * @access private
2309
+ */
2310
+ function unsetHeader($name)
2311
+ {
2312
+ if (isset($this->outgoing_headers[$name])) {
2313
+ $this->debug("unset header $name");
2314
+ unset($this->outgoing_headers[$name]);
2315
+ }
2316
+ }
2317
+
2318
+ /**
2319
+ * sets the URL to which to connect
2320
+ *
2321
+ * @param string $url The URL to which to connect
2322
+ * @access private
2323
+ */
2324
+ function setURL($url)
2325
+ {
2326
+ $this->url = $url;
2327
+
2328
+ $u = parse_url($url);
2329
+ foreach ($u as $k => $v) {
2330
+ $this->debug("parsed URL $k = $v");
2331
+ $this->$k = $v;
2332
+ }
2333
+
2334
+ // add any GET params to path
2335
+ if (isset($u['query']) && $u['query'] != '') {
2336
+ $this->path .= '?' . $u['query'];
2337
+ }
2338
+
2339
+ // set default port
2340
+ if (!isset($u['port'])) {
2341
+ if ($u['scheme'] == 'https') {
2342
+ $this->port = 443;
2343
+ } else {
2344
+ $this->port = 80;
2345
+ }
2346
+ }
2347
+
2348
+ $this->uri = $this->path;
2349
+ $this->digest_uri = $this->uri;
2350
+
2351
+ // build headers
2352
+ if (!isset($u['port'])) {
2353
+ $this->setHeader('Host', $this->host);
2354
+ } else {
2355
+ $this->setHeader('Host', $this->host . ':' . $this->port);
2356
+ }
2357
+
2358
+ if (isset($u['user']) && $u['user'] != '') {
2359
+ $this->setCredentials(urldecode($u['user']), isset($u['pass']) ? urldecode($u['pass']) : '');
2360
+ }
2361
+ }
2362
+
2363
+ /**
2364
+ * gets the I/O method to use
2365
+ *
2366
+ * @return string I/O method to use (socket|curl|unknown)
2367
+ * @access private
2368
+ */
2369
+ function io_method()
2370
+ {
2371
+ if ($this->use_curl || ($this->scheme == 'https') || ($this->scheme == 'http' && $this->authtype == 'ntlm') || ($this->scheme == 'http' && is_array($this->proxy) && $this->proxy['authtype'] == 'ntlm')) {
2372
+ return 'curl';
2373
+ }
2374
+ if (($this->scheme == 'http' || $this->scheme == 'ssl') && $this->authtype != 'ntlm' && (!is_array($this->proxy) || $this->proxy['authtype'] != 'ntlm')) {
2375
+ return 'socket';
2376
+ }
2377
+ return 'unknown';
2378
+ }
2379
+
2380
+ /**
2381
+ * establish an HTTP connection
2382
+ *
2383
+ * @param integer $timeout set connection timeout in seconds
2384
+ * @param integer $response_timeout set response timeout in seconds
2385
+ * @return boolean true if connected, false if not
2386
+ * @access private
2387
+ */
2388
+ function connect($connection_timeout = 0, $response_timeout = 30)
2389
+ {
2390
+ // For PHP 4.3 with OpenSSL, change https scheme to ssl, then treat like
2391
+ // "regular" socket.
2392
+ // TODO: disabled for now because OpenSSL must be *compiled* in (not just
2393
+ // loaded), and until PHP5 stream_get_wrappers is not available.
2394
+ // if ($this->scheme == 'https') {
2395
+ // if (version_compare(phpversion(), '4.3.0') >= 0) {
2396
+ // if (extension_loaded('openssl')) {
2397
+ // $this->scheme = 'ssl';
2398
+ // $this->debug('Using SSL over OpenSSL');
2399
+ // }
2400
+ // }
2401
+ // }
2402
+ $this->debug("connect connection_timeout $connection_timeout, response_timeout $response_timeout, scheme $this->scheme, host $this->host, port $this->port");
2403
+ if ($this->io_method() == 'socket') {
2404
+ if (!is_array($this->proxy)) {
2405
+ $host = $this->host;
2406
+ $port = $this->port;
2407
+ } else {
2408
+ $host = $this->proxy['host'];
2409
+ $port = $this->proxy['port'];
2410
+ }
2411
+
2412
+ // use persistent connection
2413
+ if ($this->persistentConnection && isset($this->fp) && is_resource($this->fp)) {
2414
+ if (!feof($this->fp)) {
2415
+ $this->debug('Re-use persistent connection');
2416
+ return true;
2417
+ }
2418
+ fclose($this->fp);
2419
+ $this->debug('Closed persistent connection at EOF');
2420
+ }
2421
+
2422
+ // munge host if using OpenSSL
2423
+ if ($this->scheme == 'ssl') {
2424
+ $host = 'ssl://' . $host;
2425
+ }
2426
+ $this->debug('calling fsockopen with host ' . $host . ' connection_timeout ' . $connection_timeout);
2427
+
2428
+ // open socket
2429
+ if ($connection_timeout > 0) {
2430
+ $this->fp = @fsockopen($host, $this->port, $this->errno, $this->error_str, $connection_timeout);
2431
+ } else {
2432
+ $this->fp = @fsockopen($host, $this->port, $this->errno, $this->error_str);
2433
+ }
2434
+
2435
+ // test pointer
2436
+ if (!$this->fp) {
2437
+ $msg = 'Couldn\'t open socket connection to server ' . $this->url;
2438
+ if ($this->errno) {
2439
+ $msg .= ', Error (' . $this->errno . '): ' . $this->error_str;
2440
+ } else {
2441
+ $msg .= ' prior to connect(). This is often a problem looking up the host name.';
2442
+ }
2443
+ $this->debug($msg);
2444
+ $this->setError($msg);
2445
+ return false;
2446
+ }
2447
+
2448
+ // set response timeout
2449
+ $this->debug('set response timeout to ' . $response_timeout);
2450
+ socket_set_timeout($this->fp, $response_timeout);
2451
+
2452
+ $this->debug('socket connected');
2453
+ return true;
2454
+ } elseif ($this->io_method() == 'curl') {
2455
+ if (!extension_loaded('curl')) {
2456
+ // $this->setError('cURL Extension, or OpenSSL extension w/ PHP version >= 4.3 is required for HTTPS');
2457
+ $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.');
2458
+ return false;
2459
+ }
2460
+ // Avoid warnings when PHP does not have these options
2461
+ if (defined('CURLOPT_CONNECTIONTIMEOUT')) {
2462
+ $CURLOPT_CONNECTIONTIMEOUT = CURLOPT_CONNECTIONTIMEOUT;
2463
+ } else {
2464
+ $CURLOPT_CONNECTIONTIMEOUT = 78;
2465
+ }
2466
+ if (defined('CURLOPT_HTTPAUTH')) {
2467
+ $CURLOPT_HTTPAUTH = CURLOPT_HTTPAUTH;
2468
+ } else {
2469
+ $CURLOPT_HTTPAUTH = 107;
2470
+ }
2471
+ if (defined('CURLOPT_PROXYAUTH')) {
2472
+ $CURLOPT_PROXYAUTH = CURLOPT_PROXYAUTH;
2473
+ } else {
2474
+ $CURLOPT_PROXYAUTH = 111;
2475
+ }
2476
+ if (defined('CURLAUTH_BASIC')) {
2477
+ $CURLAUTH_BASIC = CURLAUTH_BASIC;
2478
+ } else {
2479
+ $CURLAUTH_BASIC = 1;
2480
+ }
2481
+ if (defined('CURLAUTH_DIGEST')) {
2482
+ $CURLAUTH_DIGEST = CURLAUTH_DIGEST;
2483
+ } else {
2484
+ $CURLAUTH_DIGEST = 2;
2485
+ }
2486
+ if (defined('CURLAUTH_NTLM')) {
2487
+ $CURLAUTH_NTLM = CURLAUTH_NTLM;
2488
+ } else {
2489
+ $CURLAUTH_NTLM = 8;
2490
+ }
2491
+
2492
+ $this->debug('connect using cURL');
2493
+ // init CURL
2494
+ $this->ch = curl_init();
2495
+ // set url
2496
+ $hostURL = ($this->port != '') ? "$this->scheme://$this->host:$this->port" : "$this->scheme://$this->host";
2497
+ // add path
2498
+ $hostURL .= $this->path;
2499
+ $this->setCurlOption(CURLOPT_URL, $hostURL);
2500
+ // follow location headers (re-directs)
2501
+ if (ini_get('safe_mode') || ini_get('open_basedir')) {
2502
+ $this->debug('safe_mode or open_basedir set, so do not set CURLOPT_FOLLOWLOCATION');
2503
+ $this->debug('safe_mode = ');
2504
+ $this->appendDebug($this->varDump(ini_get('safe_mode')));
2505
+ $this->debug('open_basedir = ');
2506
+ $this->appendDebug($this->varDump(ini_get('open_basedir')));
2507
+ } else {
2508
+ $this->setCurlOption(CURLOPT_FOLLOWLOCATION, 1);
2509
+ }
2510
+ // ask for headers in the response output
2511
+ $this->setCurlOption(CURLOPT_HEADER, 1);
2512
+ // ask for the response output as the return value
2513
+ $this->setCurlOption(CURLOPT_RETURNTRANSFER, 1);
2514
+ // encode
2515
+ // We manage this ourselves through headers and encoding
2516
+ // if(function_exists('gzuncompress')){
2517
+ // $this->setCurlOption(CURLOPT_ENCODING, 'deflate');
2518
+ // }
2519
+ // persistent connection
2520
+ if ($this->persistentConnection) {
2521
+ // I believe the following comment is now bogus, having applied to
2522
+ // the code when it used CURLOPT_CUSTOMREQUEST to send the request.
2523
+ // The way we send data, we cannot use persistent connections, since
2524
+ // there will be some "junk" at the end of our request.
2525
+ //$this->setCurlOption(CURL_HTTP_VERSION_1_1, true);
2526
+ $this->persistentConnection = false;
2527
+ $this->setHeader('Connection', 'close');
2528
+ }
2529
+ // set timeouts
2530
+ if ($connection_timeout != 0) {
2531
+ $this->setCurlOption($CURLOPT_CONNECTIONTIMEOUT, $connection_timeout);
2532
+ }
2533
+ if ($response_timeout != 0) {
2534
+ $this->setCurlOption(CURLOPT_TIMEOUT, $response_timeout);
2535
+ }
2536
+
2537
+ if ($this->scheme == 'https') {
2538
+ $this->debug('set cURL SSL verify options');
2539
+ // recent versions of cURL turn on peer/host checking by default,
2540
+ // while PHP binaries are not compiled with a default location for the
2541
+ // CA cert bundle, so disable peer/host checking.
2542
+ //$this->setCurlOption(CURLOPT_CAINFO, 'f:\php-4.3.2-win32\extensions\curl-ca-bundle.crt');
2543
+ $this->setCurlOption(CURLOPT_SSL_VERIFYPEER, 0);
2544
+ $this->setCurlOption(CURLOPT_SSL_VERIFYHOST, 0);
2545
+
2546
+ // support client certificates (thanks Tobias Boes, Doug Anarino, Eryan Ariobowo)
2547
+ if ($this->authtype == 'certificate') {
2548
+ $this->debug('set cURL certificate options');
2549
+ if (isset($this->certRequest['cainfofile'])) {
2550
+ $this->setCurlOption(CURLOPT_CAINFO, $this->certRequest['cainfofile']);
2551
+ }
2552
+ if (isset($this->certRequest['verifypeer'])) {
2553
+ $this->setCurlOption(CURLOPT_SSL_VERIFYPEER, $this->certRequest['verifypeer']);
2554
+ } else {
2555
+ $this->setCurlOption(CURLOPT_SSL_VERIFYPEER, 1);
2556
+ }
2557
+ if (isset($this->certRequest['verifyhost'])) {
2558
+ $this->setCurlOption(CURLOPT_SSL_VERIFYHOST, $this->certRequest['verifyhost']);
2559
+ } else {
2560
+ $this->setCurlOption(CURLOPT_SSL_VERIFYHOST, 1);
2561
+ }
2562
+ if (isset($this->certRequest['sslcertfile'])) {
2563
+ $this->setCurlOption(CURLOPT_SSLCERT, $this->certRequest['sslcertfile']);
2564
+ }
2565
+ if (isset($this->certRequest['sslkeyfile'])) {
2566
+ $this->setCurlOption(CURLOPT_SSLKEY, $this->certRequest['sslkeyfile']);
2567
+ }
2568
+ if (isset($this->certRequest['passphrase'])) {
2569
+ $this->setCurlOption(CURLOPT_SSLKEYPASSWD, $this->certRequest['passphrase']);
2570
+ }
2571
+ if (isset($this->certRequest['certpassword'])) {
2572
+ $this->setCurlOption(CURLOPT_SSLCERTPASSWD, $this->certRequest['certpassword']);
2573
+ }
2574
+ }
2575
+ }
2576
+ if ($this->authtype && ($this->authtype != 'certificate')) {
2577
+ if ($this->username) {
2578
+ $this->debug('set cURL username/password');
2579
+ $this->setCurlOption(CURLOPT_USERPWD, "$this->username:$this->password");
2580
+ }
2581
+ if ($this->authtype == 'basic') {
2582
+ $this->debug('set cURL for Basic authentication');
2583
+ $this->setCurlOption($CURLOPT_HTTPAUTH, $CURLAUTH_BASIC);
2584
+ }
2585
+ if ($this->authtype == 'digest') {
2586
+ $this->debug('set cURL for digest authentication');
2587
+ $this->setCurlOption($CURLOPT_HTTPAUTH, $CURLAUTH_DIGEST);
2588
+ }
2589
+ if ($this->authtype == 'ntlm') {
2590
+ $this->debug('set cURL for NTLM authentication');
2591
+ $this->setCurlOption($CURLOPT_HTTPAUTH, $CURLAUTH_NTLM);
2592
+ }
2593
+ }
2594
+ if (is_array($this->proxy)) {
2595
+ $this->debug('set cURL proxy options');
2596
+ if ($this->proxy['port'] != '') {
2597
+ $this->setCurlOption(CURLOPT_PROXY, $this->proxy['host'] . ':' . $this->proxy['port']);
2598
+ } else {
2599
+ $this->setCurlOption(CURLOPT_PROXY, $this->proxy['host']);
2600
+ }
2601
+ if ($this->proxy['username'] || $this->proxy['password']) {
2602
+ $this->debug('set cURL proxy authentication options');
2603
+ $this->setCurlOption(CURLOPT_PROXYUSERPWD, $this->proxy['username'] . ':' . $this->proxy['password']);
2604
+ if ($this->proxy['authtype'] == 'basic') {
2605
+ $this->setCurlOption($CURLOPT_PROXYAUTH, $CURLAUTH_BASIC);
2606
+ }
2607
+ if ($this->proxy['authtype'] == 'ntlm') {
2608
+ $this->setCurlOption($CURLOPT_PROXYAUTH, $CURLAUTH_NTLM);
2609
+ }
2610
+ }
2611
+ }
2612
+ $this->debug('cURL connection set up');
2613
+ return true;
2614
+ } else {
2615
+ $this->setError('Unknown scheme ' . $this->scheme);
2616
+ $this->debug('Unknown scheme ' . $this->scheme);
2617
+ return false;
2618
+ }
2619
+ }
2620
+
2621
+ /**
2622
+ * sends the SOAP request and gets the SOAP response via HTTP[S]
2623
+ *
2624
+ * @param string $data message data
2625
+ * @param integer $timeout set connection timeout in seconds
2626
+ * @param integer $response_timeout set response timeout in seconds
2627
+ * @param array $cookies cookies to send
2628
+ * @return string data
2629
+ * @access public
2630
+ */
2631
+ function send($data, $timeout = 0, $response_timeout = 30, $cookies = null)
2632
+ {
2633
+
2634
+ $this->debug('entered send() with data of length: ' . strlen($data));
2635
+
2636
+ $this->tryagain = true;
2637
+ $tries = 0;
2638
+ while ($this->tryagain) {
2639
+ $this->tryagain = false;
2640
+ if ($tries++ < 2) {
2641
+ // make connnection
2642
+ if (!$this->connect($timeout, $response_timeout)) {
2643
+ return false;
2644
+ }
2645
+
2646
+ // send request
2647
+ if (!$this->sendRequest($data, $cookies)) {
2648
+ return false;
2649
+ }
2650
+
2651
+ // get response
2652
+ $respdata = $this->getResponse();
2653
+ } else {
2654
+ $this->setError("Too many tries to get an OK response ($this->response_status_line)");
2655
+ }
2656
+ }
2657
+ $this->debug('end of send()');
2658
+ return $respdata;
2659
+ }
2660
+
2661
+
2662
+ /**
2663
+ * sends the SOAP request and gets the SOAP response via HTTPS using CURL
2664
+ *
2665
+ * @param string $data message data
2666
+ * @param integer $timeout set connection timeout in seconds
2667
+ * @param integer $response_timeout set response timeout in seconds
2668
+ * @param array $cookies cookies to send
2669
+ * @return string data
2670
+ * @access public
2671
+ * @deprecated
2672
+ */
2673
+ function sendHTTPS($data, $timeout = 0, $response_timeout = 30, $cookies)
2674
+ {
2675
+ return $this->send($data, $timeout, $response_timeout, $cookies);
2676
+ }
2677
+
2678
+ /**
2679
+ * if authenticating, set user credentials here
2680
+ *
2681
+ * @param string $username
2682
+ * @param string $password
2683
+ * @param string $authtype (basic|digest|certificate|ntlm)
2684
+ * @param array $digestRequest (keys must be nonce, nc, realm, qop)
2685
+ * @param array $certRequest (keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, certpassword (optional), verifypeer (optional), verifyhost (optional): see corresponding options in cURL docs)
2686
+ * @access public
2687
+ */
2688
+ function setCredentials($username, $password, $authtype = 'basic', $digestRequest = array(), $certRequest = array())
2689
+ {
2690
+ $this->debug("setCredentials username=$username authtype=$authtype digestRequest=");
2691
+ $this->appendDebug($this->varDump($digestRequest));
2692
+ $this->debug("certRequest=");
2693
+ $this->appendDebug($this->varDump($certRequest));
2694
+ // cf. RFC 2617
2695
+ if ($authtype == 'basic') {
2696
+ $this->setHeader('Authorization', 'Basic ' . base64_encode(str_replace(':', '', $username) . ':' . $password));
2697
+ } elseif ($authtype == 'digest') {
2698
+ if (isset($digestRequest['nonce'])) {
2699
+ $digestRequest['nc'] = isset($digestRequest['nc']) ? $digestRequest['nc']++ : 1;
2700
+
2701
+ // calculate the Digest hashes (calculate code based on digest implementation found at: http://www.rassoc.com/gregr/weblog/stories/2002/07/09/webServicesSecurityHttpDigestAuthenticationWithoutActiveDirectory.html)
2702
+
2703
+ // A1 = unq(username-value) ":" unq(realm-value) ":" passwd
2704
+ $A1 = $username . ':' . (isset($digestRequest['realm']) ? $digestRequest['realm'] : '') . ':' . $password;
2705
+
2706
+ // H(A1) = MD5(A1)
2707
+ $HA1 = md5($A1);
2708
+
2709
+ // A2 = Method ":" digest-uri-value
2710
+ $A2 = $this->request_method . ':' . $this->digest_uri;
2711
+
2712
+ // H(A2)
2713
+ $HA2 = md5($A2);
2714
+
2715
+ // KD(secret, data) = H(concat(secret, ":", data))
2716
+ // if qop == auth:
2717
+ // request-digest = <"> < KD ( H(A1), unq(nonce-value)
2718
+ // ":" nc-value
2719
+ // ":" unq(cnonce-value)
2720
+ // ":" unq(qop-value)
2721
+ // ":" H(A2)
2722
+ // ) <">
2723
+ // if qop is missing,
2724
+ // request-digest = <"> < KD ( H(A1), unq(nonce-value) ":" H(A2) ) > <">
2725
+
2726
+ $unhashedDigest = '';
2727
+ $nonce = isset($digestRequest['nonce']) ? $digestRequest['nonce'] : '';
2728
+ $cnonce = $nonce;
2729
+ if ($digestRequest['qop'] != '') {
2730
+ $unhashedDigest = $HA1 . ':' . $nonce . ':' . sprintf("%08d", $digestRequest['nc']) . ':' . $cnonce . ':' . $digestRequest['qop'] . ':' . $HA2;
2731
+ } else {
2732
+ $unhashedDigest = $HA1 . ':' . $nonce . ':' . $HA2;
2733
+ }
2734
+
2735
+ $hashedDigest = md5($unhashedDigest);
2736
+
2737
+ $opaque = '';
2738
+ if (isset($digestRequest['opaque'])) {
2739
+ $opaque = ', opaque="' . $digestRequest['opaque'] . '"';
2740
+ }
2741
+
2742
+ $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 . '"');
2743
+ }
2744
+ } elseif ($authtype == 'certificate') {
2745
+ $this->certRequest = $certRequest;
2746
+ $this->debug('Authorization header not set for certificate');
2747
+ } elseif ($authtype == 'ntlm') {
2748
+ // do nothing
2749
+ $this->debug('Authorization header not set for ntlm');
2750
+ }
2751
+ $this->username = $username;
2752
+ $this->password = $password;
2753
+ $this->authtype = $authtype;
2754
+ $this->digestRequest = $digestRequest;
2755
+ }
2756
+
2757
+ /**
2758
+ * set the soapaction value
2759
+ *
2760
+ * @param string $soapaction
2761
+ * @access public
2762
+ */
2763
+ function setSOAPAction($soapaction)
2764
+ {
2765
+ $this->setHeader('SOAPAction', '"' . $soapaction . '"');
2766
+ }
2767
+
2768
+ /**
2769
+ * use http encoding
2770
+ *
2771
+ * @param string $enc encoding style. supported values: gzip, deflate, or both
2772
+ * @access public
2773
+ */
2774
+ function setEncoding($enc = 'gzip, deflate')
2775
+ {
2776
+ if (function_exists('gzdeflate')) {
2777
+ $this->protocol_version = '1.1';
2778
+ $this->setHeader('Accept-Encoding', $enc);
2779
+ if (!isset($this->outgoing_headers['Connection'])) {
2780
+ $this->setHeader('Connection', 'close');
2781
+ $this->persistentConnection = false;
2782
+ }
2783
+ // deprecated as of PHP 5.3.0
2784
+ //set_magic_quotes_runtime(0);
2785
+ $this->encoding = $enc;
2786
+ }
2787
+ }
2788
+
2789
+ /**
2790
+ * set proxy info here
2791
+ *
2792
+ * @param string $proxyhost use an empty string to remove proxy
2793
+ * @param string $proxyport
2794
+ * @param string $proxyusername
2795
+ * @param string $proxypassword
2796
+ * @param string $proxyauthtype (basic|ntlm)
2797
+ * @access public
2798
+ */
2799
+ function setProxy($proxyhost, $proxyport, $proxyusername = '', $proxypassword = '', $proxyauthtype = 'basic')
2800
+ {
2801
+ if ($proxyhost) {
2802
+ $this->proxy = array(
2803
+ 'host' => $proxyhost,
2804
+ 'port' => $proxyport,
2805
+ 'username' => $proxyusername,
2806
+ 'password' => $proxypassword,
2807
+ 'authtype' => $proxyauthtype
2808
+ );
2809
+ if ($proxyusername != '' && $proxypassword != '' && $proxyauthtype = 'basic') {
2810
+ $this->setHeader('Proxy-Authorization', ' Basic ' . base64_encode($proxyusername . ':' . $proxypassword));
2811
+ }
2812
+ } else {
2813
+ $this->debug('remove proxy');
2814
+ $proxy = null;
2815
+ unsetHeader('Proxy-Authorization');
2816
+ }
2817
+ }
2818
+
2819
+
2820
+ /**
2821
+ * Test if the given string starts with a header that is to be skipped.
2822
+ * Skippable headers result from chunked transfer and proxy requests.
2823
+ *
2824
+ * @param string $data The string to check.
2825
+ * @returns boolean Whether a skippable header was found.
2826
+ * @access private
2827
+ */
2828
+ function isSkippableCurlHeader(&$data)
2829
+ {
2830
+ $skipHeaders = array('HTTP/1.1 100',
2831
+ 'HTTP/1.0 301',
2832
+ 'HTTP/1.1 301',
2833
+ 'HTTP/1.0 302',
2834
+ 'HTTP/1.1 302',
2835
+ 'HTTP/1.0 401',
2836
+ 'HTTP/1.1 401',
2837
+ 'HTTP/1.0 200 Connection established');
2838
+ foreach ($skipHeaders as $hd) {
2839
+ $prefix = substr($data, 0, strlen($hd));
2840
+ if ($prefix == $hd) {
2841
+ return true;
2842
+ }
2843
+ }
2844
+
2845
+ return false;
2846
+ }
2847
+
2848
+ /**
2849
+ * decode a string that is encoded w/ "chunked' transfer encoding
2850
+ * as defined in RFC2068 19.4.6
2851
+ *
2852
+ * @param string $buffer
2853
+ * @param string $lb
2854
+ * @returns string
2855
+ * @access public
2856
+ * @deprecated
2857
+ */
2858
+ function decodeChunked($buffer, $lb)
2859
+ {
2860
+ // length := 0
2861
+ $length = 0;
2862
+ $new = '';
2863
+
2864
+ // read chunk-size, chunk-extension (if any) and CRLF
2865
+ // get the position of the linebreak
2866
+ $chunkend = strpos($buffer, $lb);
2867
+ if ($chunkend == false) {
2868
+ $this->debug('no linebreak found in decodeChunked');
2869
+ return $new;
2870
+ }
2871
+ $temp = substr($buffer, 0, $chunkend);
2872
+ $chunk_size = hexdec(trim($temp));
2873
+ $chunkstart = $chunkend + strlen($lb);
2874
+ // while (chunk-size > 0) {
2875
+ while ($chunk_size > 0) {
2876
+ $this->debug("chunkstart: $chunkstart chunk_size: $chunk_size");
2877
+ $chunkend = strpos($buffer, $lb, $chunkstart + $chunk_size);
2878
+
2879
+ // Just in case we got a broken connection
2880
+ if ($chunkend == false) {
2881
+ $chunk = substr($buffer, $chunkstart);
2882
+ // append chunk-data to entity-body
2883
+ $new .= $chunk;
2884
+ $length += strlen($chunk);
2885
+ break;
2886
+ }
2887
+
2888
+ // read chunk-data and CRLF
2889
+ $chunk = substr($buffer, $chunkstart, $chunkend - $chunkstart);
2890
+ // append chunk-data to entity-body
2891
+ $new .= $chunk;
2892
+ // length := length + chunk-size
2893
+ $length += strlen($chunk);
2894
+ // read chunk-size and CRLF
2895
+ $chunkstart = $chunkend + strlen($lb);
2896
+
2897
+ $chunkend = strpos($buffer, $lb, $chunkstart) + strlen($lb);
2898
+ if ($chunkend == false) {
2899
+ break; //Just in case we got a broken connection
2900
+ }
2901
+ $temp = substr($buffer, $chunkstart, $chunkend - $chunkstart);
2902
+ $chunk_size = hexdec(trim($temp));
2903
+ $chunkstart = $chunkend;
2904
+ }
2905
+ return $new;
2906
+ }
2907
+
2908
+ /**
2909
+ * Writes the payload, including HTTP headers, to $this->outgoing_payload.
2910
+ *
2911
+ * @param string $data HTTP body
2912
+ * @param string $cookie_str data for HTTP Cookie header
2913
+ * @return void
2914
+ * @access private
2915
+ */
2916
+ function buildPayload($data, $cookie_str = '')
2917
+ {
2918
+ // Note: for cURL connections, $this->outgoing_payload is ignored,
2919
+ // as is the Content-Length header, but these are still created as
2920
+ // debugging guides.
2921
+
2922
+ // add content-length header
2923
+ if ($this->request_method != 'GET') {
2924
+ $this->setHeader('Content-Length', strlen($data));
2925
+ }
2926
+
2927
+ // start building outgoing payload:
2928
+ if ($this->proxy) {
2929
+ $uri = $this->url;
2930
+ } else {
2931
+ $uri = $this->uri;
2932
+ }
2933
+ $req = "$this->request_method $uri HTTP/$this->protocol_version";
2934
+ $this->debug("HTTP request: $req");
2935
+ $this->outgoing_payload = "$req\r\n";
2936
+
2937
+ // loop thru headers, serializing
2938
+ foreach ($this->outgoing_headers as $k => $v) {
2939
+ $hdr = $k . ': ' . $v;
2940
+ $this->debug("HTTP header: $hdr");
2941
+ $this->outgoing_payload .= "$hdr\r\n";
2942
+ }
2943
+
2944
+ // add any cookies
2945
+ if ($cookie_str != '') {
2946
+ $hdr = 'Cookie: ' . $cookie_str;
2947
+ $this->debug("HTTP header: $hdr");
2948
+ $this->outgoing_payload .= "$hdr\r\n";
2949
+ }
2950
+
2951
+ // header/body separator
2952
+ $this->outgoing_payload .= "\r\n";
2953
+
2954
+ // add data
2955
+ $this->outgoing_payload .= $data;
2956
+ }
2957
+
2958
+ /**
2959
+ * sends the SOAP request via HTTP[S]
2960
+ *
2961
+ * @param string $data message data
2962
+ * @param array $cookies cookies to send
2963
+ * @return boolean true if OK, false if problem
2964
+ * @access private
2965
+ */
2966
+ function sendRequest($data, $cookies = null)
2967
+ {
2968
+ // build cookie string
2969
+ $cookie_str = $this->getCookiesForRequest($cookies, (($this->scheme == 'ssl') || ($this->scheme == 'https')));
2970
+
2971
+ // build payload
2972
+ $this->buildPayload($data, $cookie_str);
2973
+
2974
+ if ($this->io_method() == 'socket') {
2975
+ // send payload
2976
+ if (!fputs($this->fp, $this->outgoing_payload, strlen($this->outgoing_payload))) {
2977
+ $this->setError('couldn\'t write message data to socket');
2978
+ $this->debug('couldn\'t write message data to socket');
2979
+ return false;
2980
+ }
2981
+ $this->debug('wrote data to socket, length = ' . strlen($this->outgoing_payload));
2982
+ return true;
2983
+ } elseif ($this->io_method() == 'curl') {
2984
+ // set payload
2985
+ // cURL does say this should only be the verb, and in fact it
2986
+ // turns out that the URI and HTTP version are appended to this, which
2987
+ // some servers refuse to work with (so we no longer use this method!)
2988
+ //$this->setCurlOption(CURLOPT_CUSTOMREQUEST, $this->outgoing_payload);
2989
+ $curl_headers = array();
2990
+ foreach ($this->outgoing_headers as $k => $v) {
2991
+ if ($k == 'Connection' || $k == 'Content-Length' || $k == 'Host' || $k == 'Authorization' || $k == 'Proxy-Authorization') {
2992
+ $this->debug("Skip cURL header $k: $v");
2993
+ } else {
2994
+ $curl_headers[] = "$k: $v";
2995
+ }
2996
+ }
2997
+ if ($cookie_str != '') {
2998
+ $curl_headers[] = 'Cookie: ' . $cookie_str;
2999
+ }
3000
+ $this->setCurlOption(CURLOPT_HTTPHEADER, $curl_headers);
3001
+ $this->debug('set cURL HTTP headers');
3002
+ if ($this->request_method == "POST") {
3003
+ $this->setCurlOption(CURLOPT_POST, 1);
3004
+ $this->setCurlOption(CURLOPT_POSTFIELDS, $data);
3005
+ $this->debug('set cURL POST data');
3006
+ } else {
3007
+ }
3008
+ // insert custom user-set cURL options
3009
+ foreach ($this->ch_options as $key => $val) {
3010
+ $this->setCurlOption($key, $val);
3011
+ }
3012
+
3013
+ $this->debug('set cURL payload');
3014
+ return true;
3015
+ }
3016
+ }
3017
+
3018
+ /**
3019
+ * gets the SOAP response via HTTP[S]
3020
+ *
3021
+ * @return string the response (also sets member variables like incoming_payload)
3022
+ * @access private
3023
+ */
3024
+ function getResponse()
3025
+ {
3026
+ $this->incoming_payload = '';
3027
+
3028
+ if ($this->io_method() == 'socket') {
3029
+ // loop until headers have been retrieved
3030
+ $data = '';
3031
+ while (!isset($lb)) {
3032
+
3033
+ // We might EOF during header read.
3034
+ if (feof($this->fp)) {
3035
+ $this->incoming_payload = $data;
3036
+ $this->debug('found no headers before EOF after length ' . strlen($data));
3037
+ $this->debug("received before EOF:\n" . $data);
3038
+ $this->setError('server failed to send headers');
3039
+ return false;
3040
+ }
3041
+
3042
+ $tmp = fgets($this->fp, 256);
3043
+ $tmplen = strlen($tmp);
3044
+ $this->debug("read line of $tmplen bytes: " . trim($tmp));
3045
+
3046
+ if ($tmplen == 0) {
3047
+ $this->incoming_payload = $data;
3048
+ $this->debug('socket read of headers timed out after length ' . strlen($data));
3049
+ $this->debug("read before timeout: " . $data);
3050
+ $this->setError('socket read of headers timed out');
3051
+ return false;
3052
+ }
3053
+
3054
+ $data .= $tmp;
3055
+ $pos = strpos($data, "\r\n\r\n");
3056
+ if ($pos > 1) {
3057
+ $lb = "\r\n";
3058
+ } else {
3059
+ $pos = strpos($data, "\n\n");
3060
+ if ($pos > 1) {
3061
+ $lb = "\n";
3062
+ }
3063
+ }
3064
+ // remove 100 headers
3065
+ if (isset($lb) && preg_match('/^HTTP\/1.1 100/', $data)) {
3066
+ unset($lb);
3067
+ $data = '';
3068
+ }//
3069
+ }
3070
+ // store header data
3071
+ $this->incoming_payload .= $data;
3072
+ $this->debug('found end of headers after length ' . strlen($data));
3073
+ // process headers
3074
+ $header_data = trim(substr($data, 0, $pos));
3075
+ $header_array = explode($lb, $header_data);
3076
+ $this->incoming_headers = array();
3077
+ $this->incoming_cookies = array();
3078
+ foreach ($header_array as $header_line) {
3079
+ $arr = explode(':', $header_line, 2);
3080
+ if (count($arr) > 1) {
3081
+ $header_name = strtolower(trim($arr[0]));
3082
+ $this->incoming_headers[$header_name] = trim($arr[1]);
3083
+ if ($header_name == 'set-cookie') {
3084
+ // TODO: allow multiple cookies from parseCookie
3085
+ $cookie = $this->parseCookie(trim($arr[1]));
3086
+ if ($cookie) {
3087
+ $this->incoming_cookies[] = $cookie;
3088
+ $this->debug('found cookie: ' . $cookie['name'] . ' = ' . $cookie['value']);
3089
+ } else {
3090
+ $this->debug('did not find cookie in ' . trim($arr[1]));
3091
+ }
3092
+ }
3093
+ } elseif (isset($header_name)) {
3094
+ // append continuation line to previous header
3095
+ $this->incoming_headers[$header_name] .= $lb . ' ' . $header_line;
3096
+ }
3097
+ }
3098
+
3099
+ // loop until msg has been received
3100
+ if (isset($this->incoming_headers['transfer-encoding']) && strtolower($this->incoming_headers['transfer-encoding']) == 'chunked') {
3101
+ $content_length = 2147483647; // ignore any content-length header
3102
+ $chunked = true;
3103
+ $this->debug("want to read chunked content");
3104
+ } elseif (isset($this->incoming_headers['content-length'])) {
3105
+ $content_length = $this->incoming_headers['content-length'];
3106
+ $chunked = false;
3107
+ $this->debug("want to read content of length $content_length");
3108
+ } else {
3109
+ $content_length = 2147483647;
3110
+ $chunked = false;
3111
+ $this->debug("want to read content to EOF");
3112
+ }
3113
+ $data = '';
3114
+ do {
3115
+ if ($chunked) {
3116
+ $tmp = fgets($this->fp, 256);
3117
+ $tmplen = strlen($tmp);
3118
+ $this->debug("read chunk line of $tmplen bytes");
3119
+ if ($tmplen == 0) {
3120
+ $this->incoming_payload = $data;
3121
+ $this->debug('socket read of chunk length timed out after length ' . strlen($data));
3122
+ $this->debug("read before timeout:\n" . $data);
3123
+ $this->setError('socket read of chunk length timed out');
3124
+ return false;
3125
+ }
3126
+ $content_length = hexdec(trim($tmp));
3127
+ $this->debug("chunk length $content_length");
3128
+ }
3129
+ $strlen = 0;
3130
+ while (($strlen < $content_length) && (!feof($this->fp))) {
3131
+ $readlen = min(8192, $content_length - $strlen);
3132
+ $tmp = fread($this->fp, $readlen);
3133
+ $tmplen = strlen($tmp);
3134
+ $this->debug("read buffer of $tmplen bytes");
3135
+ if (($tmplen == 0) && (!feof($this->fp))) {
3136
+ $this->incoming_payload = $data;
3137
+ $this->debug('socket read of body timed out after length ' . strlen($data));
3138
+ $this->debug("read before timeout:\n" . $data);
3139
+ $this->setError('socket read of body timed out');
3140
+ return false;
3141
+ }
3142
+ $strlen += $tmplen;
3143
+ $data .= $tmp;
3144
+ }
3145
+ if ($chunked && ($content_length > 0)) {
3146
+ $tmp = fgets($this->fp, 256);
3147
+ $tmplen = strlen($tmp);
3148
+ $this->debug("read chunk terminator of $tmplen bytes");
3149
+ if ($tmplen == 0) {
3150
+ $this->incoming_payload = $data;
3151
+ $this->debug('socket read of chunk terminator timed out after length ' . strlen($data));
3152
+ $this->debug("read before timeout:\n" . $data);
3153
+ $this->setError('socket read of chunk terminator timed out');
3154
+ return false;
3155
+ }
3156
+ }
3157
+ } while ($chunked && ($content_length > 0) && (!feof($this->fp)));
3158
+ if (feof($this->fp)) {
3159
+ $this->debug('read to EOF');
3160
+ }
3161
+ $this->debug('read body of length ' . strlen($data));
3162
+ $this->incoming_payload .= $data;
3163
+ $this->debug('received a total of ' . strlen($this->incoming_payload) . ' bytes of data from server');
3164
+
3165
+ // close filepointer
3166
+ if (
3167
+ (isset($this->incoming_headers['connection']) && strtolower($this->incoming_headers['connection']) == 'close') ||
3168
+ (!$this->persistentConnection) || feof($this->fp)
3169
+ ) {
3170
+ fclose($this->fp);
3171
+ $this->fp = false;
3172
+ $this->debug('closed socket');
3173
+ }
3174
+
3175
+ // connection was closed unexpectedly
3176
+ if ($this->incoming_payload == '') {
3177
+ $this->setError('no response from server');
3178
+ return false;
3179
+ }
3180
+
3181
+ // decode transfer-encoding
3182
+ // if(isset($this->incoming_headers['transfer-encoding']) && strtolower($this->incoming_headers['transfer-encoding']) == 'chunked'){
3183
+ // if(!$data = $this->decodeChunked($data, $lb)){
3184
+ // $this->setError('Decoding of chunked data failed');
3185
+ // return false;
3186
+ // }
3187
+ //print "<pre>\nde-chunked:\n---------------\n$data\n\n---------------\n</pre>";
3188
+ // set decoded payload
3189
+ // $this->incoming_payload = $header_data.$lb.$lb.$data;
3190
+ // }
3191
+
3192
+ } elseif ($this->io_method() == 'curl') {
3193
+ // send and receive
3194
+ $this->debug('send and receive with cURL');
3195
+ $this->incoming_payload = curl_exec($this->ch);
3196
+ $data = $this->incoming_payload;
3197
+
3198
+ $cErr = curl_error($this->ch);
3199
+ if ($cErr != '') {
3200
+ $err = 'cURL ERROR: ' . curl_errno($this->ch) . ': ' . $cErr . '<br>';
3201
+ // TODO: there is a PHP bug that can cause this to SEGV for CURLINFO_CONTENT_TYPE
3202
+ foreach (curl_getinfo($this->ch) as $k => $v) {
3203
+ $err .= "$k: $v<br>";
3204
+ }
3205
+ $this->debug($err);
3206
+ $this->setError($err);
3207
+ curl_close($this->ch);
3208
+ return false;
3209
+ } else {
3210
+ //echo '<pre>';
3211
+ //var_dump(curl_getinfo($this->ch));
3212
+ //echo '</pre>';
3213
+ }
3214
+ // close curl
3215
+ $this->debug('No cURL error, closing cURL');
3216
+ curl_close($this->ch);
3217
+
3218
+ // try removing skippable headers
3219
+ $savedata = $data;
3220
+ while ($this->isSkippableCurlHeader($data)) {
3221
+ $this->debug("Found HTTP header to skip");
3222
+ if ($pos = strpos($data, "\r\n\r\n")) {
3223
+ $data = ltrim(substr($data, $pos));
3224
+ } elseif ($pos = strpos($data, "\n\n")) {
3225
+ $data = ltrim(substr($data, $pos));
3226
+ }
3227
+ }
3228
+
3229
+ if ($data == '') {
3230
+ // have nothing left; just remove 100 header(s)
3231
+ $data = $savedata;
3232
+ while (preg_match('/^HTTP\/1.1 100/', $data)) {
3233
+ if ($pos = strpos($data, "\r\n\r\n")) {
3234
+ $data = ltrim(substr($data, $pos));
3235
+ } elseif ($pos = strpos($data, "\n\n")) {
3236
+ $data = ltrim(substr($data, $pos));
3237
+ }
3238
+ }
3239
+ }
3240
+
3241
+ // separate content from HTTP headers
3242
+ if ($pos = strpos($data, "\r\n\r\n")) {
3243
+ $lb = "\r\n";
3244
+ } elseif ($pos = strpos($data, "\n\n")) {
3245
+ $lb = "\n";
3246
+ } else {
3247
+ $this->debug('no proper separation of headers and document');
3248
+ $this->setError('no proper separation of headers and document');
3249
+ return false;
3250
+ }
3251
+ $header_data = trim(substr($data, 0, $pos));
3252
+ $header_array = explode($lb, $header_data);
3253
+ $data = ltrim(substr($data, $pos));
3254
+ $this->debug('found proper separation of headers and document');
3255
+ $this->debug('cleaned data, stringlen: ' . strlen($data));
3256
+ // clean headers
3257
+ foreach ($header_array as $header_line) {
3258
+ $arr = explode(':', $header_line, 2);
3259
+ if (count($arr) > 1) {
3260
+ $header_name = strtolower(trim($arr[0]));
3261
+ $this->incoming_headers[$header_name] = trim($arr[1]);
3262
+ if ($header_name == 'set-cookie') {
3263
+ // TODO: allow multiple cookies from parseCookie
3264
+ $cookie = $this->parseCookie(trim($arr[1]));
3265
+ if ($cookie) {
3266
+ $this->incoming_cookies[] = $cookie;
3267
+ $this->debug('found cookie: ' . $cookie['name'] . ' = ' . $cookie['value']);
3268
+ } else {
3269
+ $this->debug('did not find cookie in ' . trim($arr[1]));
3270
+ }
3271
+ }
3272
+ } elseif (isset($header_name)) {
3273
+ // append continuation line to previous header
3274
+ $this->incoming_headers[$header_name] .= $lb . ' ' . $header_line;
3275
+ }
3276
+ }
3277
+ }
3278
+
3279
+ $this->response_status_line = $header_array[0];
3280
+ $arr = explode(' ', $this->response_status_line, 3);
3281
+ $http_version = $arr[0];
3282
+ $http_status = intval($arr[1]);
3283
+ $http_reason = count($arr) > 2 ? $arr[2] : '';
3284
+
3285
+ // see if we need to resend the request with http digest authentication
3286
+ if (isset($this->incoming_headers['location']) && ($http_status == 301 || $http_status == 302)) {
3287
+ $this->debug("Got $http_status $http_reason with Location: " . $this->incoming_headers['location']);
3288
+ $this->setURL($this->incoming_headers['location']);
3289
+ $this->tryagain = true;
3290
+ return false;
3291
+ }
3292
+
3293
+ // see if we need to resend the request with http digest authentication
3294
+ if (isset($this->incoming_headers['www-authenticate']) && $http_status == 401) {
3295
+ $this->debug("Got 401 $http_reason with WWW-Authenticate: " . $this->incoming_headers['www-authenticate']);
3296
+ if (strstr($this->incoming_headers['www-authenticate'], "Digest ")) {
3297
+ $this->debug('Server wants digest authentication');
3298
+ // remove "Digest " from our elements
3299
+ $digestString = str_replace('Digest ', '', $this->incoming_headers['www-authenticate']);
3300
+
3301
+ // parse elements into array
3302
+ $digestElements = explode(',', $digestString);
3303
+ foreach ($digestElements as $val) {
3304
+ $tempElement = explode('=', trim($val), 2);
3305
+ $digestRequest[$tempElement[0]] = str_replace("\"", '', $tempElement[1]);
3306
+ }
3307
+
3308
+ // should have (at least) qop, realm, nonce
3309
+ if (isset($digestRequest['nonce'])) {
3310
+ $this->setCredentials($this->username, $this->password, 'digest', $digestRequest);
3311
+ $this->tryagain = true;
3312
+ return false;
3313
+ }
3314
+ }
3315
+ $this->debug('HTTP authentication failed');
3316
+ $this->setError('HTTP authentication failed');
3317
+ return false;
3318
+ }
3319
+
3320
+ if (
3321
+ ($http_status >= 300 && $http_status <= 307) ||
3322
+ ($http_status >= 400 && $http_status <= 417) ||
3323
+ ($http_status >= 501 && $http_status <= 505)
3324
+ ) {
3325
+ $this->setError("Unsupported HTTP response status $http_status $http_reason (soapclient->response has contents of the response)");
3326
+ return false;
3327
+ }
3328
+
3329
+ // decode content-encoding
3330
+ if (isset($this->incoming_headers['content-encoding']) && $this->incoming_headers['content-encoding'] != '') {
3331
+ if (strtolower($this->incoming_headers['content-encoding']) == 'deflate' || strtolower($this->incoming_headers['content-encoding']) == 'gzip') {
3332
+ // if decoding works, use it. else assume data wasn't gzencoded
3333
+ if (function_exists('gzinflate')) {
3334
+ //$timer->setMarker('starting decoding of gzip/deflated content');
3335
+ // IIS 5 requires gzinflate instead of gzuncompress (similar to IE 5 and gzdeflate v. gzcompress)
3336
+ // this means there are no Zlib headers, although there should be
3337
+ $this->debug('The gzinflate function exists');
3338
+ $datalen = strlen($data);
3339
+ if ($this->incoming_headers['content-encoding'] == 'deflate') {
3340
+ if ($degzdata = @gzinflate($data)) {
3341
+ $data = $degzdata;
3342
+ $this->debug('The payload has been inflated to ' . strlen($data) . ' bytes');
3343
+ if (strlen($data) < $datalen) {
3344
+ // test for the case that the payload has been compressed twice
3345
+ $this->debug('The inflated payload is smaller than the gzipped one; try again');
3346
+ if ($degzdata = @gzinflate($data)) {
3347
+ $data = $degzdata;
3348
+ $this->debug('The payload has been inflated again to ' . strlen($data) . ' bytes');
3349
+ }
3350
+ }
3351
+ } else {
3352
+ $this->debug('Error using gzinflate to inflate the payload');
3353
+ $this->setError('Error using gzinflate to inflate the payload');
3354
+ }
3355
+ } elseif ($this->incoming_headers['content-encoding'] == 'gzip') {
3356
+ if ($degzdata = @gzinflate(substr($data, 10))) { // do our best
3357
+ $data = $degzdata;
3358
+ $this->debug('The payload has been un-gzipped to ' . strlen($data) . ' bytes');
3359
+ if (strlen($data) < $datalen) {
3360
+ // test for the case that the payload has been compressed twice
3361
+ $this->debug('The un-gzipped payload is smaller than the gzipped one; try again');
3362
+ if ($degzdata = @gzinflate(substr($data, 10))) {
3363
+ $data = $degzdata;
3364
+ $this->debug('The payload has been un-gzipped again to ' . strlen($data) . ' bytes');
3365
+ }
3366
+ }
3367
+ } else {
3368
+ $this->debug('Error using gzinflate to un-gzip the payload');
3369
+ $this->setError('Error using gzinflate to un-gzip the payload');
3370
+ }
3371
+ }
3372
+ //$timer->setMarker('finished decoding of gzip/deflated content');
3373
+ //print "<xmp>\nde-inflated:\n---------------\n$data\n-------------\n</xmp>";
3374
+ // set decoded payload
3375
+ $this->incoming_payload = $header_data . $lb . $lb . $data;
3376
+ } else {
3377
+ $this->debug('The server sent compressed data. Your php install must have the Zlib extension compiled in to support this.');
3378
+ $this->setError('The server sent compressed data. Your php install must have the Zlib extension compiled in to support this.');
3379
+ }
3380
+ } else {
3381
+ $this->debug('Unsupported Content-Encoding ' . $this->incoming_headers['content-encoding']);
3382
+ $this->setError('Unsupported Content-Encoding ' . $this->incoming_headers['content-encoding']);
3383
+ }
3384
+ } else {
3385
+ $this->debug('No Content-Encoding header');
3386
+ }
3387
+
3388
+ if (strlen($data) == 0) {
3389
+ $this->debug('no data after headers!');
3390
+ $this->setError('no data present after HTTP headers');
3391
+ return false;
3392
+ }
3393
+
3394
+ return $data;
3395
+ }
3396
+
3397
+ /**
3398
+ * sets the content-type for the SOAP message to be sent
3399
+ *
3400
+ * @param string $type the content type, MIME style
3401
+ * @param mixed $charset character set used for encoding (or false)
3402
+ * @access public
3403
+ */
3404
+ function setContentType($type, $charset = false)
3405
+ {
3406
+ $this->setHeader('Content-Type', $type . ($charset ? '; charset=' . $charset : ''));
3407
+ }
3408
+
3409
+ /**
3410
+ * specifies that an HTTP persistent connection should be used
3411
+ *
3412
+ * @return boolean whether the request was honored by this method.
3413
+ * @access public
3414
+ */
3415
+ function usePersistentConnection()
3416
+ {
3417
+ if (isset($this->outgoing_headers['Accept-Encoding'])) {
3418
+ return false;
3419
+ }
3420
+ $this->protocol_version = '1.1';
3421
+ $this->persistentConnection = true;
3422
+ $this->setHeader('Connection', 'Keep-Alive');
3423
+ return true;
3424
+ }
3425
+
3426
+ /**
3427
+ * parse an incoming Cookie into it's parts
3428
+ *
3429
+ * @param string $cookie_str content of cookie
3430
+ * @return array with data of that cookie
3431
+ * @access private
3432
+ */
3433
+ /*
3434
+ * TODO: allow a Set-Cookie string to be parsed into multiple cookies
3435
+ */
3436
+ function parseCookie($cookie_str)
3437
+ {
3438
+ $cookie_str = str_replace('; ', ';', $cookie_str) . ';';
3439
+ $data = preg_split('/;/', $cookie_str);
3440
+ $value_str = $data[0];
3441
+
3442
+ $cookie_param = 'domain=';
3443
+ $start = strpos($cookie_str, $cookie_param);
3444
+ if ($start > 0) {
3445
+ $domain = substr($cookie_str, $start + strlen($cookie_param));
3446
+ $domain = substr($domain, 0, strpos($domain, ';'));
3447
+ } else {
3448
+ $domain = '';
3449
+ }
3450
+
3451
+ $cookie_param = 'expires=';
3452
+ $start = strpos($cookie_str, $cookie_param);
3453
+ if ($start > 0) {
3454
+ $expires = substr($cookie_str, $start + strlen($cookie_param));
3455
+ $expires = substr($expires, 0, strpos($expires, ';'));
3456
+ } else {
3457
+ $expires = '';
3458
+ }
3459
+
3460
+ $cookie_param = 'path=';
3461
+ $start = strpos($cookie_str, $cookie_param);
3462
+ if ($start > 0) {
3463
+ $path = substr($cookie_str, $start + strlen($cookie_param));
3464
+ $path = substr($path, 0, strpos($path, ';'));
3465
+ } else {
3466
+ $path = '/';
3467
+ }
3468
+
3469
+ $cookie_param = ';secure;';
3470
+ if (strpos($cookie_str, $cookie_param) !== false) {
3471
+ $secure = true;
3472
+ } else {
3473
+ $secure = false;
3474
+ }
3475
+
3476
+ $sep_pos = strpos($value_str, '=');
3477
+
3478
+ if ($sep_pos) {
3479
+ $name = substr($value_str, 0, $sep_pos);
3480
+ $value = substr($value_str, $sep_pos + 1);
3481
+ $cookie = array('name' => $name,
3482
+ 'value' => $value,
3483
+ 'domain' => $domain,
3484
+ 'path' => $path,
3485
+ 'expires' => $expires,
3486
+ 'secure' => $secure
3487
+ );
3488
+ return $cookie;
3489
+ }
3490
+ return false;
3491
+ }
3492
+
3493
+ /**
3494
+ * sort out cookies for the current request
3495
+ *
3496
+ * @param array $cookies array with all cookies
3497
+ * @param boolean $secure is the send-content secure or not?
3498
+ * @return string for Cookie-HTTP-Header
3499
+ * @access private
3500
+ */
3501
+ function getCookiesForRequest($cookies, $secure = false)
3502
+ {
3503
+ $cookie_str = '';
3504
+ if ((!is_null($cookies)) && (is_array($cookies))) {
3505
+ foreach ($cookies as $cookie) {
3506
+ if (!is_array($cookie)) {
3507
+ continue;
3508
+ }
3509
+ $this->debug("check cookie for validity: " . $cookie['name'] . '=' . $cookie['value']);
3510
+ if ((isset($cookie['expires'])) && (!empty($cookie['expires']))) {
3511
+ if (strtotime($cookie['expires']) <= time()) {
3512
+ $this->debug('cookie has expired');
3513
+ continue;
3514
+ }
3515
+ }
3516
+ if ((isset($cookie['domain'])) && (!empty($cookie['domain']))) {
3517
+ $domain = preg_quote($cookie['domain']);
3518
+ if (!preg_match("'.*$domain$'i", $this->host)) {
3519
+ $this->debug('cookie has different domain');
3520
+ continue;
3521
+ }
3522
+ }
3523
+ if ((isset($cookie['path'])) && (!empty($cookie['path']))) {
3524
+ $path = preg_quote($cookie['path']);
3525
+ if (!preg_match("'^$path.*'i", $this->path)) {
3526
+ $this->debug('cookie is for a different path');
3527
+ continue;
3528
+ }
3529
+ }
3530
+ if ((!$secure) && (isset($cookie['secure'])) && ($cookie['secure'])) {
3531
+ $this->debug('cookie is secure, transport is not');
3532
+ continue;
3533
+ }
3534
+ $cookie_str .= $cookie['name'] . '=' . $cookie['value'] . '; ';
3535
+ $this->debug('add cookie to Cookie-String: ' . $cookie['name'] . '=' . $cookie['value']);
3536
+ }
3537
+ }
3538
+ return $cookie_str;
3539
+ }
3540
+ }
3541
+
3542
+
3543
+ /**
3544
+ *
3545
+ * nusoap_server allows the user to create a SOAP server
3546
+ * that is capable of receiving messages and returning responses
3547
+ *
3548
+ * @author Dietrich Ayala <dietrich@ganx4.com>
3549
+ * @author Scott Nichol <snichol@users.sourceforge.net>
3550
+ * @version $Id: nusoap.php,v 1.123 2010/04/26 20:15:08 snichol Exp $
3551
+ * @access public
3552
+ */
3553
+ class nusoap_server extends nusoap_base
3554
+ {
3555
+ /**
3556
+ * HTTP headers of request
3557
+ *
3558
+ * @var array
3559
+ * @access private
3560
+ */
3561
+ var $headers = array();
3562
+ /**
3563
+ * HTTP request
3564
+ *
3565
+ * @var string
3566
+ * @access private
3567
+ */
3568
+ var $request = '';
3569
+ /**
3570
+ * SOAP headers from request (incomplete namespace resolution; special characters not escaped) (text)
3571
+ *
3572
+ * @var string
3573
+ * @access public
3574
+ */
3575
+ var $requestHeaders = '';
3576
+ /**
3577
+ * SOAP Headers from request (parsed)
3578
+ *
3579
+ * @var mixed
3580
+ * @access public
3581
+ */
3582
+ var $requestHeader = null;
3583
+ /**
3584
+ * SOAP body request portion (incomplete namespace resolution; special characters not escaped) (text)
3585
+ *
3586
+ * @var string
3587
+ * @access public
3588
+ */
3589
+ var $document = '';
3590
+ /**
3591
+ * SOAP payload for request (text)
3592
+ *
3593
+ * @var string
3594
+ * @access public
3595
+ */
3596
+ var $requestSOAP = '';
3597
+ /**
3598
+ * requested method namespace URI
3599
+ *
3600
+ * @var string
3601
+ * @access private
3602
+ */
3603
+ var $methodURI = '';
3604
+ /**
3605
+ * name of method requested
3606
+ *
3607
+ * @var string
3608
+ * @access private
3609
+ */
3610
+ var $methodname = '';
3611
+ /**
3612
+ * method parameters from request
3613
+ *
3614
+ * @var array
3615
+ * @access private
3616
+ */
3617
+ var $methodparams = array();
3618
+ /**
3619
+ * SOAP Action from request
3620
+ *
3621
+ * @var string
3622
+ * @access private
3623
+ */
3624
+ var $SOAPAction = '';
3625
+ /**
3626
+ * character set encoding of incoming (request) messages
3627
+ *
3628
+ * @var string
3629
+ * @access public
3630
+ */
3631
+ var $xml_encoding = '';
3632
+ /**
3633
+ * toggles whether the parser decodes element content w/ utf8_decode()
3634
+ *
3635
+ * @var boolean
3636
+ * @access public
3637
+ */
3638
+ var $decode_utf8 = true;
3639
+
3640
+ /**
3641
+ * HTTP headers of response
3642
+ *
3643
+ * @var array
3644
+ * @access public
3645
+ */
3646
+ var $outgoing_headers = array();
3647
+ /**
3648
+ * HTTP response
3649
+ *
3650
+ * @var string
3651
+ * @access private
3652
+ */
3653
+ var $response = '';
3654
+ /**
3655
+ * SOAP headers for response (text or array of soapval or associative array)
3656
+ *
3657
+ * @var mixed
3658
+ * @access public
3659
+ */
3660
+ var $responseHeaders = '';
3661
+ /**
3662
+ * SOAP payload for response (text)
3663
+ *
3664
+ * @var string
3665
+ * @access private
3666
+ */
3667
+ var $responseSOAP = '';
3668
+ /**
3669
+ * method return value to place in response
3670
+ *
3671
+ * @var mixed
3672
+ * @access private
3673
+ */
3674
+ var $methodreturn = false;
3675
+ /**
3676
+ * whether $methodreturn is a string of literal XML
3677
+ *
3678
+ * @var boolean
3679
+ * @access public
3680
+ */
3681
+ var $methodreturnisliteralxml = false;
3682
+ /**
3683
+ * SOAP fault for response (or false)
3684
+ *
3685
+ * @var mixed
3686
+ * @access private
3687
+ */
3688
+ var $fault = false;
3689
+ /**
3690
+ * text indication of result (for debugging)
3691
+ *
3692
+ * @var string
3693
+ * @access private
3694
+ */
3695
+ var $result = 'successful';
3696
+
3697
+ /**
3698
+ * assoc array of operations => opData; operations are added by the register()
3699
+ * method or by parsing an external WSDL definition
3700
+ *
3701
+ * @var array
3702
+ * @access private
3703
+ */
3704
+ var $operations = array();
3705
+ /**
3706
+ * wsdl instance (if one)
3707
+ *
3708
+ * @var mixed
3709
+ * @access private
3710
+ */
3711
+ var $wsdl = false;
3712
+ /**
3713
+ * URL for WSDL (if one)
3714
+ *
3715
+ * @var mixed
3716
+ * @access private
3717
+ */
3718
+ var $externalWSDLURL = false;
3719
+ /**
3720
+ * whether to append debug to response as XML comment
3721
+ *
3722
+ * @var boolean
3723
+ * @access public
3724
+ */
3725
+ var $debug_flag = false;
3726
+
3727
+
3728
+ /**
3729
+ * constructor
3730
+ * the optional parameter is a path to a WSDL file that you'd like to bind the server instance to.
3731
+ *
3732
+ * @param mixed $wsdl file path or URL (string), or wsdl instance (object)
3733
+ * @access public
3734
+ */
3735
+ function __construct($wsdl = false)
3736
+ {
3737
+ parent::__construct();
3738
+ // turn on debugging?
3739
+ global $debug;
3740
+ global $HTTP_SERVER_VARS;
3741
+
3742
+ if (isset($_SERVER)) {
3743
+ $this->debug("_SERVER is defined:");
3744
+ $this->appendDebug($this->varDump($_SERVER));
3745
+ } elseif (isset($HTTP_SERVER_VARS)) {
3746
+ $this->debug("HTTP_SERVER_VARS is defined:");
3747
+ $this->appendDebug($this->varDump($HTTP_SERVER_VARS));
3748
+ } else {
3749
+ $this->debug("Neither _SERVER nor HTTP_SERVER_VARS is defined.");
3750
+ }
3751
+
3752
+ if (isset($debug)) {
3753
+ $this->debug("In nusoap_server, set debug_flag=$debug based on global flag");
3754
+ $this->debug_flag = $debug;
3755
+ } elseif (isset($_SERVER['QUERY_STRING'])) {
3756
+ $qs = explode('&', $_SERVER['QUERY_STRING']);
3757
+ foreach ($qs as $v) {
3758
+ if (substr($v, 0, 6) == 'debug=') {
3759
+ $this->debug("In nusoap_server, set debug_flag=" . substr($v, 6) . " based on query string #1");
3760
+ $this->debug_flag = substr($v, 6);
3761
+ }
3762
+ }
3763
+ } elseif (isset($HTTP_SERVER_VARS['QUERY_STRING'])) {
3764
+ $qs = explode('&', $HTTP_SERVER_VARS['QUERY_STRING']);
3765
+ foreach ($qs as $v) {
3766
+ if (substr($v, 0, 6) == 'debug=') {
3767
+ $this->debug("In nusoap_server, set debug_flag=" . substr($v, 6) . " based on query string #2");
3768
+ $this->debug_flag = substr($v, 6);
3769
+ }
3770
+ }
3771
+ }
3772
+
3773
+ // wsdl
3774
+ if ($wsdl) {
3775
+ $this->debug("In nusoap_server, WSDL is specified");
3776
+ if (is_object($wsdl) && (get_class($wsdl) == 'wsdl')) {
3777
+ $this->wsdl = $wsdl;
3778
+ $this->externalWSDLURL = $this->wsdl->wsdl;
3779
+ $this->debug('Use existing wsdl instance from ' . $this->externalWSDLURL);
3780
+ } else {
3781
+ $this->debug('Create wsdl from ' . $wsdl);
3782
+ $this->wsdl = new wsdl($wsdl);
3783
+ $this->externalWSDLURL = $wsdl;
3784
+ }
3785
+ $this->appendDebug($this->wsdl->getDebug());
3786
+ $this->wsdl->clearDebug();
3787
+ if ($err = $this->wsdl->getError()) {
3788
+ die('WSDL ERROR: ' . $err);
3789
+ }
3790
+ }
3791
+ }
3792
+
3793
+ /**
3794
+ * processes request and returns response
3795
+ *
3796
+ * @param string $data usually is the value of $HTTP_RAW_POST_DATA
3797
+ * @access public
3798
+ */
3799
+ function service($data)
3800
+ {
3801
+ global $HTTP_SERVER_VARS;
3802
+
3803
+ if (isset($_SERVER['REQUEST_METHOD'])) {
3804
+ $rm = $_SERVER['REQUEST_METHOD'];
3805
+ } elseif (isset($HTTP_SERVER_VARS['REQUEST_METHOD'])) {
3806
+ $rm = $HTTP_SERVER_VARS['REQUEST_METHOD'];
3807
+ } else {
3808
+ $rm = '';
3809
+ }
3810
+
3811
+ if (isset($_SERVER['QUERY_STRING'])) {
3812
+ $qs = $_SERVER['QUERY_STRING'];
3813
+ } elseif (isset($HTTP_SERVER_VARS['QUERY_STRING'])) {
3814
+ $qs = $HTTP_SERVER_VARS['QUERY_STRING'];
3815
+ } else {
3816
+ $qs = '';
3817
+ }
3818
+ $this->debug("In service, request method=$rm query string=$qs strlen(\$data)=" . strlen($data));
3819
+
3820
+ if ($rm == 'POST') {
3821
+ $this->debug("In service, invoke the request");
3822
+ $this->parse_request($data);
3823
+ if (!$this->fault) {
3824
+ $this->invoke_method();
3825
+ }
3826
+ if (!$this->fault) {
3827
+ $this->serialize_return();
3828
+ }
3829
+ $this->send_response();
3830
+ } elseif (preg_match('/wsdl/', $qs)) {
3831
+ $this->debug("In service, this is a request for WSDL");
3832
+ if ($this->externalWSDLURL) {
3833
+ if (strpos($this->externalWSDLURL, "http://") !== false) { // assume URL
3834
+ $this->debug("In service, re-direct for WSDL");
3835
+ header('Location: ' . $this->externalWSDLURL);
3836
+ } else { // assume file
3837
+ $this->debug("In service, use file passthru for WSDL");
3838
+ header("Content-Type: text/xml\r\n");
3839
+ $pos = strpos($this->externalWSDLURL, "file://");
3840
+ if ($pos === false) {
3841
+ $filename = $this->externalWSDLURL;
3842
+ } else {
3843
+ $filename = substr($this->externalWSDLURL, $pos + 7);
3844
+ }
3845
+ $fp = fopen($this->externalWSDLURL, 'r');
3846
+ fpassthru($fp);
3847
+ }
3848
+ } elseif ($this->wsdl) {
3849
+ $this->debug("In service, serialize WSDL");
3850
+ header("Content-Type: text/xml; charset=ISO-8859-1\r\n");
3851
+ print $this->wsdl->serialize($this->debug_flag);
3852
+ if ($this->debug_flag) {
3853
+ $this->debug('wsdl:');
3854
+ $this->appendDebug($this->varDump($this->wsdl));
3855
+ print $this->getDebugAsXMLComment();
3856
+ }
3857
+ } else {
3858
+ $this->debug("In service, there is no WSDL");
3859
+ header("Content-Type: text/html; charset=ISO-8859-1\r\n");
3860
+ print "This service does not provide WSDL";
3861
+ }
3862
+ } elseif ($this->wsdl) {
3863
+ $this->debug("In service, return Web description");
3864
+ print $this->wsdl->webDescription();
3865
+ } else {
3866
+ $this->debug("In service, no Web description");
3867
+ header("Content-Type: text/html; charset=ISO-8859-1\r\n");
3868
+ print "This service does not provide a Web description";
3869
+ }
3870
+ }
3871
+
3872
+ /**
3873
+ * parses HTTP request headers.
3874
+ *
3875
+ * The following fields are set by this function (when successful)
3876
+ *
3877
+ * headers
3878
+ * request
3879
+ * xml_encoding
3880
+ * SOAPAction
3881
+ *
3882
+ * @access private
3883
+ */
3884
+ function parse_http_headers()
3885
+ {
3886
+ global $HTTP_SERVER_VARS;
3887
+
3888
+ $this->request = '';
3889
+ $this->SOAPAction = '';
3890
+ if (function_exists('getallheaders')) {
3891
+ $this->debug("In parse_http_headers, use getallheaders");
3892
+ $headers = getallheaders();
3893
+ foreach ($headers as $k => $v) {
3894
+ $k = strtolower($k);
3895
+ $this->headers[$k] = $v;
3896
+ $this->request .= "$k: $v\r\n";
3897
+ $this->debug("$k: $v");
3898
+ }
3899
+ // get SOAPAction header
3900
+ if (isset($this->headers['soapaction'])) {
3901
+ $this->SOAPAction = str_replace('"', '', $this->headers['soapaction']);
3902
+ }
3903
+ // get the character encoding of the incoming request
3904
+ if (isset($this->headers['content-type']) && strpos($this->headers['content-type'], '=')) {
3905
+ $enc = str_replace('"', '', substr(strstr($this->headers["content-type"], '='), 1));
3906
+ if (preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i', $enc)) {
3907
+ $this->xml_encoding = strtoupper($enc);
3908
+ } else {
3909
+ $this->xml_encoding = 'US-ASCII';
3910
+ }
3911
+ } else {
3912
+ // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
3913
+ $this->xml_encoding = 'ISO-8859-1';
3914
+ }
3915
+ } elseif (isset($_SERVER) && is_array($_SERVER)) {
3916
+ $this->debug("In parse_http_headers, use _SERVER");
3917
+ foreach ($_SERVER as $k => $v) {
3918
+ if (substr($k, 0, 5) == 'HTTP_') {
3919
+ $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', substr($k, 5))));
3920
+ } else {
3921
+ $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', $k)));
3922
+ }
3923
+ if ($k == 'soapaction') {
3924
+ // get SOAPAction header
3925
+ $k = 'SOAPAction';
3926
+ $v = str_replace('"', '', $v);
3927
+ $v = str_replace('\\', '', $v);
3928
+ $this->SOAPAction = $v;
3929
+ } elseif ($k == 'content-type') {
3930
+ // get the character encoding of the incoming request
3931
+ if (strpos($v, '=')) {
3932
+ $enc = substr(strstr($v, '='), 1);
3933
+ $enc = str_replace('"', '', $enc);
3934
+ $enc = str_replace('\\', '', $enc);
3935
+ if (preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i', $enc)) {
3936
+ $this->xml_encoding = strtoupper($enc);
3937
+ } else {
3938
+ $this->xml_encoding = 'US-ASCII';
3939
+ }
3940
+ } else {
3941
+ // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
3942
+ $this->xml_encoding = 'ISO-8859-1';
3943
+ }
3944
+ }
3945
+ $this->headers[$k] = $v;
3946
+ $this->request .= "$k: $v\r\n";
3947
+ $this->debug("$k: $v");
3948
+ }
3949
+ } elseif (is_array($HTTP_SERVER_VARS)) {
3950
+ $this->debug("In parse_http_headers, use HTTP_SERVER_VARS");
3951
+ foreach ($HTTP_SERVER_VARS as $k => $v) {
3952
+ if (substr($k, 0, 5) == 'HTTP_') {
3953
+ $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', substr($k, 5))));
3954
+ $k = strtolower(substr($k, 5));
3955
+ } else {
3956
+ $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', $k)));
3957
+ $k = strtolower($k);
3958
+ }
3959
+ if ($k == 'soapaction') {
3960
+ // get SOAPAction header
3961
+ $k = 'SOAPAction';
3962
+ $v = str_replace('"', '', $v);
3963
+ $v = str_replace('\\', '', $v);
3964
+ $this->SOAPAction = $v;
3965
+ } elseif ($k == 'content-type') {
3966
+ // get the character encoding of the incoming request
3967
+ if (strpos($v, '=')) {
3968
+ $enc = substr(strstr($v, '='), 1);
3969
+ $enc = str_replace('"', '', $enc);
3970
+ $enc = str_replace('\\', '', $enc);
3971
+ if (preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i', $enc)) {
3972
+ $this->xml_encoding = strtoupper($enc);
3973
+ } else {
3974
+ $this->xml_encoding = 'US-ASCII';
3975
+ }
3976
+ } else {
3977
+ // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
3978
+ $this->xml_encoding = 'ISO-8859-1';
3979
+ }
3980
+ }
3981
+ $this->headers[$k] = $v;
3982
+ $this->request .= "$k: $v\r\n";
3983
+ $this->debug("$k: $v");
3984
+ }
3985
+ } else {
3986
+ $this->debug("In parse_http_headers, HTTP headers not accessible");
3987
+ $this->setError("HTTP headers not accessible");
3988
+ }
3989
+ }
3990
+
3991
+ /**
3992
+ * parses a request
3993
+ *
3994
+ * The following fields are set by this function (when successful)
3995
+ *
3996
+ * headers
3997
+ * request
3998
+ * xml_encoding
3999
+ * SOAPAction
4000
+ * request
4001
+ * requestSOAP
4002
+ * methodURI
4003
+ * methodname
4004
+ * methodparams
4005
+ * requestHeaders
4006
+ * document
4007
+ *
4008
+ * This sets the fault field on error
4009
+ *
4010
+ * @param string $data XML string
4011
+ * @access private
4012
+ */
4013
+ function parse_request($data = '')
4014
+ {
4015
+ $this->debug('entering parse_request()');
4016
+ $this->parse_http_headers();
4017
+ $this->debug('got character encoding: ' . $this->xml_encoding);
4018
+ // uncompress if necessary
4019
+ if (isset($this->headers['content-encoding']) && $this->headers['content-encoding'] != '') {
4020
+ $this->debug('got content encoding: ' . $this->headers['content-encoding']);
4021
+ if ($this->headers['content-encoding'] == 'deflate' || $this->headers['content-encoding'] == 'gzip') {
4022
+ // if decoding works, use it. else assume data wasn't gzencoded
4023
+ if (function_exists('gzuncompress')) {
4024
+ if ($this->headers['content-encoding'] == 'deflate' && $degzdata = @gzuncompress($data)) {
4025
+ $data = $degzdata;
4026
+ } elseif ($this->headers['content-encoding'] == 'gzip' && $degzdata = gzinflate(substr($data, 10))) {
4027
+ $data = $degzdata;
4028
+ } else {
4029
+ $this->fault('SOAP-ENV:Client', 'Errors occurred when trying to decode the data');
4030
+ return;
4031
+ }
4032
+ } else {
4033
+ $this->fault('SOAP-ENV:Client', 'This Server does not support compressed data');
4034
+ return;
4035
+ }
4036
+ }
4037
+ }
4038
+ $this->request .= "\r\n" . $data;
4039
+ $data = $this->parseRequest($this->headers, $data);
4040
+ $this->requestSOAP = $data;
4041
+ $this->debug('leaving parse_request');
4042
+ }
4043
+
4044
+ /**
4045
+ * invokes a PHP function for the requested SOAP method
4046
+ *
4047
+ * The following fields are set by this function (when successful)
4048
+ *
4049
+ * methodreturn
4050
+ *
4051
+ * Note that the PHP function that is called may also set the following
4052
+ * fields to affect the response sent to the client
4053
+ *
4054
+ * responseHeaders
4055
+ * outgoing_headers
4056
+ *
4057
+ * This sets the fault field on error
4058
+ *
4059
+ * @access private
4060
+ */
4061
+ function invoke_method()
4062
+ {
4063
+ $this->debug('in invoke_method, methodname=' . $this->methodname . ' methodURI=' . $this->methodURI . ' SOAPAction=' . $this->SOAPAction);
4064
+
4065
+ //
4066
+ // if you are debugging in this area of the code, your service uses a class to implement methods,
4067
+ // you use SOAP RPC, and the client is .NET, please be aware of the following...
4068
+ // when the .NET wsdl.exe utility generates a proxy, it will remove the '.' or '..' from the
4069
+ // method name. that is fine for naming the .NET methods. it is not fine for properly constructing
4070
+ // the XML request and reading the XML response. you need to add the RequestElementName and
4071
+ // ResponseElementName to the System.Web.Services.Protocols.SoapRpcMethodAttribute that wsdl.exe
4072
+ // generates for the method. these parameters are used to specify the correct XML element names
4073
+ // for .NET to use, i.e. the names with the '.' in them.
4074
+ //
4075
+ $orig_methodname = $this->methodname;
4076
+ if ($this->wsdl) {
4077
+ if ($this->opData = $this->wsdl->getOperationData($this->methodname)) {
4078
+ $this->debug('in invoke_method, found WSDL operation=' . $this->methodname);
4079
+ $this->appendDebug('opData=' . $this->varDump($this->opData));
4080
+ } elseif ($this->opData = $this->wsdl->getOperationDataForSoapAction($this->SOAPAction)) {
4081
+ // Note: hopefully this case will only be used for doc/lit, since rpc services should have wrapper element
4082
+ $this->debug('in invoke_method, found WSDL soapAction=' . $this->SOAPAction . ' for operation=' . $this->opData['name']);
4083
+ $this->appendDebug('opData=' . $this->varDump($this->opData));
4084
+ $this->methodname = $this->opData['name'];
4085
+ } else {
4086
+ $this->debug('in invoke_method, no WSDL for operation=' . $this->methodname);
4087
+ $this->fault('SOAP-ENV:Client', "Operation '" . $this->methodname . "' is not defined in the WSDL for this service");
4088
+ return;
4089
+ }
4090
+ } else {
4091
+ $this->debug('in invoke_method, no WSDL to validate method');
4092
+ }
4093
+
4094
+ // if a . is present in $this->methodname, we see if there is a class in scope,
4095
+ // which could be referred to. We will also distinguish between two deliminators,
4096
+ // to allow methods to be called a the class or an instance
4097
+ if (strpos($this->methodname, '..') > 0) {
4098
+ $delim = '..';
4099
+ } elseif (strpos($this->methodname, '.') > 0) {
4100
+ $delim = '.';
4101
+ } else {
4102
+ $delim = '';
4103
+ }
4104
+ $this->debug("in invoke_method, delim=$delim");
4105
+
4106
+ $class = '';
4107
+ $method = '';
4108
+ if (strlen($delim) > 0 && substr_count($this->methodname, $delim) == 1) {
4109
+ $try_class = substr($this->methodname, 0, strpos($this->methodname, $delim));
4110
+ if (class_exists($try_class)) {
4111
+ // get the class and method name
4112
+ $class = $try_class;
4113
+ $method = substr($this->methodname, strpos($this->methodname, $delim) + strlen($delim));
4114
+ $this->debug("in invoke_method, class=$class method=$method delim=$delim");
4115
+ } else {
4116
+ $this->debug("in invoke_method, class=$try_class not found");
4117
+ }
4118
+ } elseif (strlen($delim) > 0 && substr_count($this->methodname, $delim) > 1) {
4119
+ $split = explode($delim, $this->methodname);
4120
+ $method = array_pop($split);
4121
+ $class = implode('\\', $split);
4122
+ } else {
4123
+ $try_class = '';
4124
+ $this->debug("in invoke_method, no class to try");
4125
+ }
4126
+
4127
+ // does method exist?
4128
+ if ($class == '') {
4129
+ if (!function_exists($this->methodname)) {
4130
+ $this->debug("in invoke_method, function '$this->methodname' not found!");
4131
+ $this->result = 'fault: method not found';
4132
+ $this->fault('SOAP-ENV:Client', "method '$this->methodname'('$orig_methodname') not defined in service('$try_class' '$delim')");
4133
+ return;
4134
+ }
4135
+ } else {
4136
+ $method_to_compare = (substr(phpversion(), 0, 2) == '4.') ? strtolower($method) : $method;
4137
+ if (!in_array($method_to_compare, get_class_methods($class))) {
4138
+ $this->debug("in invoke_method, method '$this->methodname' not found in class '$class'!");
4139
+ $this->result = 'fault: method not found';
4140
+ $this->fault('SOAP-ENV:Client', "method '$this->methodname'/'$method_to_compare'('$orig_methodname') not defined in service/'$class'('$try_class' '$delim')");
4141
+ return;
4142
+ }
4143
+ }
4144
+
4145
+ // evaluate message, getting back parameters
4146
+ // verify that request parameters match the method's signature
4147
+ if (!$this->verify_method($this->methodname, $this->methodparams)) {
4148
+ // debug
4149
+ $this->debug('ERROR: request not verified against method signature');
4150
+ $this->result = 'fault: request failed validation against method signature';
4151
+ // return fault
4152
+ $this->fault('SOAP-ENV:Client', "Operation '$this->methodname' not defined in service.");
4153
+ return;
4154
+ }
4155
+
4156
+ // if there are parameters to pass
4157
+ $this->debug('in invoke_method, params:');
4158
+ $this->appendDebug($this->varDump($this->methodparams));
4159
+ $this->debug("in invoke_method, calling '$this->methodname'");
4160
+ if (!function_exists('call_user_func_array')) {
4161
+ if ($class == '') {
4162
+ $this->debug('in invoke_method, calling function using eval()');
4163
+ $funcCall = "\$this->methodreturn = $this->methodname(";
4164
+ } else {
4165
+ if ($delim == '..') {
4166
+ $this->debug('in invoke_method, calling class method using eval()');
4167
+ $funcCall = "\$this->methodreturn = " . $class . "::" . $method . "(";
4168
+ } else {
4169
+ $this->debug('in invoke_method, calling instance method using eval()');
4170
+ // generate unique instance name
4171
+ $instname = "\$inst_" . time();
4172
+ $funcCall = $instname . " = new " . $class . "(); ";
4173
+ $funcCall .= "\$this->methodreturn = " . $instname . "->" . $method . "(";
4174
+ }
4175
+ }
4176
+ if ($this->methodparams) {
4177
+ foreach ($this->methodparams as $param) {
4178
+ if (is_array($param) || is_object($param)) {
4179
+ $this->fault('SOAP-ENV:Client', 'NuSOAP does not handle complexType parameters correctly when using eval; call_user_func_array must be available');
4180
+ return;
4181
+ }
4182
+ $funcCall .= "\"$param\",";
4183
+ }
4184
+ $funcCall = substr($funcCall, 0, -1);
4185
+ }
4186
+ $funcCall .= ');';
4187
+ $this->debug('in invoke_method, function call: ' . $funcCall);
4188
+ @eval($funcCall);
4189
+ } else {
4190
+ if ($class == '') {
4191
+ $this->debug('in invoke_method, calling function using call_user_func_array()');
4192
+ $call_arg = "$this->methodname"; // straight assignment changes $this->methodname to lower case after call_user_func_array()
4193
+ } elseif ($delim == '..') {
4194
+ $this->debug('in invoke_method, calling class method using call_user_func_array()');
4195
+ $call_arg = array($class, $method);
4196
+ } else {
4197
+ $this->debug('in invoke_method, calling instance method using call_user_func_array()');
4198
+ $instance = new $class ();
4199
+ $call_arg = array(&$instance, $method);
4200
+ }
4201
+ if (is_array($this->methodparams)) {
4202
+ $this->methodreturn = call_user_func_array($call_arg, array_values($this->methodparams));
4203
+ } else {
4204
+ $this->methodreturn = call_user_func_array($call_arg, array());
4205
+ }
4206
+ }
4207
+ $this->debug('in invoke_method, methodreturn:');
4208
+ $this->appendDebug($this->varDump($this->methodreturn));
4209
+ $this->debug("in invoke_method, called method $this->methodname, received data of type " . gettype($this->methodreturn));
4210
+ }
4211
+
4212
+ /**
4213
+ * serializes the return value from a PHP function into a full SOAP Envelope
4214
+ *
4215
+ * The following fields are set by this function (when successful)
4216
+ *
4217
+ * responseSOAP
4218
+ *
4219
+ * This sets the fault field on error
4220
+ *
4221
+ * @access private
4222
+ */
4223
+ function serialize_return()
4224
+ {
4225
+ $this->debug('Entering serialize_return methodname: ' . $this->methodname . ' methodURI: ' . $this->methodURI);
4226
+ // if fault
4227
+ if (isset($this->methodreturn) && is_object($this->methodreturn) && ((get_class($this->methodreturn) == 'soap_fault') || (get_class($this->methodreturn) == 'nusoap_fault'))) {
4228
+ $this->debug('got a fault object from method');
4229
+ $this->fault = $this->methodreturn;
4230
+ return;
4231
+ } elseif ($this->methodreturnisliteralxml) {
4232
+ $return_val = $this->methodreturn;
4233
+ // returned value(s)
4234
+ } else {
4235
+ $this->debug('got a(n) ' . gettype($this->methodreturn) . ' from method');
4236
+ $this->debug('serializing return value');
4237
+ if ($this->wsdl) {
4238
+ if (sizeof($this->opData['output']['parts']) > 1) {
4239
+ $this->debug('more than one output part, so use the method return unchanged');
4240
+ $opParams = $this->methodreturn;
4241
+ } elseif (sizeof($this->opData['output']['parts']) == 1) {
4242
+ $this->debug('exactly one output part, so wrap the method return in a simple array');
4243
+ // TODO: verify that it is not already wrapped!
4244
+ //foreach ($this->opData['output']['parts'] as $name => $type) {
4245
+ // $this->debug('wrap in element named ' . $name);
4246
+ //}
4247
+ $opParams = array($this->methodreturn);
4248
+ }
4249
+ $return_val = $this->wsdl->serializeRPCParameters($this->methodname, 'output', $opParams);
4250
+ $this->appendDebug($this->wsdl->getDebug());
4251
+ $this->wsdl->clearDebug();
4252
+ if ($errstr = $this->wsdl->getError()) {
4253
+ $this->debug('got wsdl error: ' . $errstr);
4254
+ $this->fault('SOAP-ENV:Server', 'unable to serialize result');
4255
+ return;
4256
+ }
4257
+ } else {
4258
+ if (isset($this->methodreturn)) {
4259
+ $return_val = $this->serialize_val($this->methodreturn, 'return');
4260
+ } else {
4261
+ $return_val = '';
4262
+ $this->debug('in absence of WSDL, assume void return for backward compatibility');
4263
+ }
4264
+ }
4265
+ }
4266
+ $this->debug('return value:');
4267
+ $this->appendDebug($this->varDump($return_val));
4268
+
4269
+ $this->debug('serializing response');
4270
+ if ($this->wsdl) {
4271
+ $this->debug('have WSDL for serialization: style is ' . $this->opData['style']);
4272
+ if ($this->opData['style'] == 'rpc') {
4273
+ $this->debug('style is rpc for serialization: use is ' . $this->opData['output']['use']);
4274
+ if ($this->opData['output']['use'] == 'literal') {
4275
+ // 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
4276
+ if ($this->methodURI) {
4277
+ $payload = '<ns1:' . $this->methodname . 'Response xmlns:ns1="' . $this->methodURI . '">' . $return_val . '</ns1:' . $this->methodname . "Response>";
4278
+ } else {
4279
+ $payload = '<' . $this->methodname . 'Response>' . $return_val . '</' . $this->methodname . 'Response>';
4280
+ }
4281
+ } else {
4282
+ if ($this->methodURI) {
4283
+ $payload = '<ns1:' . $this->methodname . 'Response xmlns:ns1="' . $this->methodURI . '">' . $return_val . '</ns1:' . $this->methodname . "Response>";
4284
+ } else {
4285
+ $payload = '<' . $this->methodname . 'Response>' . $return_val . '</' . $this->methodname . 'Response>';
4286
+ }
4287
+ }
4288
+ } else {
4289
+ $this->debug('style is not rpc for serialization: assume document');
4290
+ $payload = $return_val;
4291
+ }
4292
+ } else {
4293
+ $this->debug('do not have WSDL for serialization: assume rpc/encoded');
4294
+ $payload = '<ns1:' . $this->methodname . 'Response xmlns:ns1="' . $this->methodURI . '">' . $return_val . '</ns1:' . $this->methodname . "Response>";
4295
+ }
4296
+ $this->result = 'successful';
4297
+ if ($this->wsdl) {
4298
+ //if($this->debug_flag){
4299
+ $this->appendDebug($this->wsdl->getDebug());
4300
+ // }
4301
+ if (isset($this->opData['output']['encodingStyle'])) {
4302
+ $encodingStyle = $this->opData['output']['encodingStyle'];
4303
+ } else {
4304
+ $encodingStyle = '';
4305
+ }
4306
+ // Added: In case we use a WSDL, return a serialized env. WITH the usedNamespaces.
4307
+ $this->responseSOAP = $this->serializeEnvelope($payload, $this->responseHeaders, $this->wsdl->usedNamespaces, $this->opData['style'], $this->opData['output']['use'], $encodingStyle);
4308
+ } else {
4309
+ $this->responseSOAP = $this->serializeEnvelope($payload, $this->responseHeaders);
4310
+ }
4311
+ $this->debug("Leaving serialize_return");
4312
+ }
4313
+
4314
+ /**
4315
+ * sends an HTTP response
4316
+ *
4317
+ * The following fields are set by this function (when successful)
4318
+ *
4319
+ * outgoing_headers
4320
+ * response
4321
+ *
4322
+ * @access private
4323
+ */
4324
+ function send_response()
4325
+ {
4326
+ $this->debug('Enter send_response');
4327
+ if ($this->fault) {
4328
+ $payload = $this->fault->serialize();
4329
+ $this->outgoing_headers[] = "HTTP/1.0 500 Internal Server Error";
4330
+ $this->outgoing_headers[] = "Status: 500 Internal Server Error";
4331
+ } else {
4332
+ $payload = $this->responseSOAP;
4333
+ // Some combinations of PHP+Web server allow the Status
4334
+ // to come through as a header. Since OK is the default
4335
+ // just do nothing.
4336
+ // $this->outgoing_headers[] = "HTTP/1.0 200 OK";
4337
+ // $this->outgoing_headers[] = "Status: 200 OK";
4338
+ }
4339
+ // add debug data if in debug mode
4340
+ if (isset($this->debug_flag) && $this->debug_flag) {
4341
+ $payload .= $this->getDebugAsXMLComment();
4342
+ }
4343
+ $this->outgoing_headers[] = "Server: $this->title Server v$this->version";
4344
+ preg_match('/\$Revisio' . 'n: ([^ ]+)/', $this->revision, $rev);
4345
+ $this->outgoing_headers[] = "X-SOAP-Server: $this->title/$this->version (" . $rev[1] . ")";
4346
+ // Let the Web server decide about this
4347
+ //$this->outgoing_headers[] = "Connection: Close\r\n";
4348
+ $payload = $this->getHTTPBody($payload);
4349
+ $type = $this->getHTTPContentType();
4350
+ $charset = $this->getHTTPContentTypeCharset();
4351
+ $this->outgoing_headers[] = "Content-Type: $type" . ($charset ? '; charset=' . $charset : '');
4352
+ //begin code to compress payload - by John
4353
+ // NOTE: there is no way to know whether the Web server will also compress
4354
+ // this data.
4355
+ if (strlen($payload) > 1024 && isset($this->headers) && isset($this->headers['accept-encoding'])) {
4356
+ if (strstr($this->headers['accept-encoding'], 'gzip')) {
4357
+ if (function_exists('gzencode')) {
4358
+ if (isset($this->debug_flag) && $this->debug_flag) {
4359
+ $payload .= "<!-- Content being gzipped -->";
4360
+ }
4361
+ $this->outgoing_headers[] = "Content-Encoding: gzip";
4362
+ $payload = gzencode($payload);
4363
+ } else {
4364
+ if (isset($this->debug_flag) && $this->debug_flag) {
4365
+ $payload .= "<!-- Content will not be gzipped: no gzencode -->";
4366
+ }
4367
+ }
4368
+ } elseif (strstr($this->headers['accept-encoding'], 'deflate')) {
4369
+ // Note: MSIE requires gzdeflate output (no Zlib header and checksum),
4370
+ // instead of gzcompress output,
4371
+ // which conflicts with HTTP 1.1 spec (http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.5)
4372
+ if (function_exists('gzdeflate')) {
4373
+ if (isset($this->debug_flag) && $this->debug_flag) {
4374
+ $payload .= "<!-- Content being deflated -->";
4375
+ }
4376
+ $this->outgoing_headers[] = "Content-Encoding: deflate";
4377
+ $payload = gzdeflate($payload);
4378
+ } else {
4379
+ if (isset($this->debug_flag) && $this->debug_flag) {
4380
+ $payload .= "<!-- Content will not be deflated: no gzcompress -->";
4381
+ }
4382
+ }
4383
+ }
4384
+ }
4385
+ //end code
4386
+ $this->outgoing_headers[] = "Content-Length: " . strlen($payload);
4387
+ reset($this->outgoing_headers);
4388
+ foreach ($this->outgoing_headers as $hdr) {
4389
+ header($hdr, false);
4390
+ }
4391
+ print $payload;
4392
+ $this->response = join("\r\n", $this->outgoing_headers) . "\r\n\r\n" . $payload;
4393
+ }
4394
+
4395
+ /**
4396
+ * takes the value that was created by parsing the request
4397
+ * and compares to the method's signature, if available.
4398
+ *
4399
+ * @param string $operation The operation to be invoked
4400
+ * @param array $request The array of parameter values
4401
+ * @return boolean Whether the operation was found
4402
+ * @access private
4403
+ */
4404
+ function verify_method($operation, $request)
4405
+ {
4406
+ if (isset($this->wsdl) && is_object($this->wsdl)) {
4407
+ if ($this->wsdl->getOperationData($operation)) {
4408
+ return true;
4409
+ }
4410
+ } elseif (isset($this->operations[$operation])) {
4411
+ return true;
4412
+ }
4413
+ return false;
4414
+ }
4415
+
4416
+ /**
4417
+ * processes SOAP message received from client
4418
+ *
4419
+ * @param array $headers The HTTP headers
4420
+ * @param string $data unprocessed request data from client
4421
+ * @return mixed value of the message, decoded into a PHP type
4422
+ * @access private
4423
+ */
4424
+ function parseRequest($headers, $data)
4425
+ {
4426
+ $this->debug('Entering parseRequest() for data of length ' . strlen($data) . ' headers:');
4427
+ $this->appendDebug($this->varDump($headers));
4428
+ if (!isset($headers['content-type'])) {
4429
+ $this->setError('Request not of type text/xml (no content-type header)');
4430
+ return false;
4431
+ }
4432
+ if (!strstr($headers['content-type'], 'text/xml')) {
4433
+ $this->setError('Request not of type text/xml');
4434
+ return false;
4435
+ }
4436
+ if (strpos($headers['content-type'], '=')) {
4437
+ $enc = str_replace('"', '', substr(strstr($headers["content-type"], '='), 1));
4438
+ $this->debug('Got response encoding: ' . $enc);
4439
+ if (preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i', $enc)) {
4440
+ $this->xml_encoding = strtoupper($enc);
4441
+ } else {
4442
+ $this->xml_encoding = 'US-ASCII';
4443
+ }
4444
+ } else {
4445
+ // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
4446
+ $this->xml_encoding = 'ISO-8859-1';
4447
+ }
4448
+ $this->debug('Use encoding: ' . $this->xml_encoding . ' when creating nusoap_parser');
4449
+ // parse response, get soap parser obj
4450
+ $parser = new nusoap_parser($data, $this->xml_encoding, '', $this->decode_utf8);
4451
+ // parser debug
4452
+ $this->debug("parser debug: \n" . $parser->getDebug());
4453
+ // if fault occurred during message parsing
4454
+ if ($err = $parser->getError()) {
4455
+ $this->result = 'fault: error in msg parsing: ' . $err;
4456
+ $this->fault('SOAP-ENV:Client', "error in msg parsing:\n" . $err);
4457
+ // else successfully parsed request into soapval object
4458
+ } else {
4459
+ // get/set methodname
4460
+ $this->methodURI = $parser->root_struct_namespace;
4461
+ $this->methodname = $parser->root_struct_name;
4462
+ $this->debug('methodname: ' . $this->methodname . ' methodURI: ' . $this->methodURI);
4463
+ $this->debug('calling parser->get_soapbody()');
4464
+ $this->methodparams = $parser->get_soapbody();
4465
+ // get SOAP headers
4466
+ $this->requestHeaders = $parser->getHeaders();
4467
+ // get SOAP Header
4468
+ $this->requestHeader = $parser->get_soapheader();
4469
+ // add document for doclit support
4470
+ $this->document = $parser->document;
4471
+ }
4472
+ }
4473
+
4474
+ /**
4475
+ * gets the HTTP body for the current response.
4476
+ *
4477
+ * @param string $soapmsg The SOAP payload
4478
+ * @return string The HTTP body, which includes the SOAP payload
4479
+ * @access private
4480
+ */
4481
+ function getHTTPBody($soapmsg)
4482
+ {
4483
+ return $soapmsg;
4484
+ }
4485
+
4486
+ /**
4487
+ * gets the HTTP content type for the current response.
4488
+ *
4489
+ * Note: getHTTPBody must be called before this.
4490
+ *
4491
+ * @return string the HTTP content type for the current response.
4492
+ * @access private
4493
+ */
4494
+ function getHTTPContentType()
4495
+ {
4496
+ return 'text/xml';
4497
+ }
4498
+
4499
+ /**
4500
+ * gets the HTTP content type charset for the current response.
4501
+ * returns false for non-text content types.
4502
+ *
4503
+ * Note: getHTTPBody must be called before this.
4504
+ *
4505
+ * @return string the HTTP content type charset for the current response.
4506
+ * @access private
4507
+ */
4508
+ function getHTTPContentTypeCharset()
4509
+ {
4510
+ return $this->soap_defencoding;
4511
+ }
4512
+
4513
+ /**
4514
+ * add a method to the dispatch map (this has been replaced by the register method)
4515
+ *
4516
+ * @param string $methodname
4517
+ * @param string $in array of input values
4518
+ * @param string $out array of output values
4519
+ * @access public
4520
+ * @deprecated
4521
+ */
4522
+ function add_to_map($methodname, $in, $out)
4523
+ {
4524
+ $this->operations[$methodname] = array('name' => $methodname, 'in' => $in, 'out' => $out);
4525
+ }
4526
+
4527
+ /**
4528
+ * register a service function with the server
4529
+ *
4530
+ * @param string $name the name of the PHP function, class.method or class..method
4531
+ * @param array $in assoc array of input values: key = param name, value = param type
4532
+ * @param array $out assoc array of output values: key = param name, value = param type
4533
+ * @param mixed $namespace the element namespace for the method or false
4534
+ * @param mixed $soapaction the soapaction for the method or false
4535
+ * @param mixed $style optional (rpc|document) or false Note: when 'document' is specified, parameter and return wrappers are created for you automatically
4536
+ * @param mixed $use optional (encoded|literal) or false
4537
+ * @param string $documentation optional Description to include in WSDL
4538
+ * @param string $encodingStyle optional (usually 'http://schemas.xmlsoap.org/soap/encoding/' for encoded)
4539
+ * @access public
4540
+ */
4541
+ function register($name, $in = array(), $out = array(), $namespace = false, $soapaction = false, $style = false, $use = false, $documentation = '', $encodingStyle = '')
4542
+ {
4543
+ global $HTTP_SERVER_VARS;
4544
+
4545
+ if ($this->externalWSDLURL) {
4546
+ die('You cannot bind to an external WSDL file, and register methods outside of it! Please choose either WSDL or no WSDL.');
4547
+ }
4548
+ if (!$name) {
4549
+ die('You must specify a name when you register an operation');
4550
+ }
4551
+ if (!is_array($in)) {
4552
+ die('You must provide an array for operation inputs');
4553
+ }
4554
+ if (!is_array($out)) {
4555
+ die('You must provide an array for operation outputs');
4556
+ }
4557
+ if (false == $namespace) {
4558
+ }
4559
+ if (false == $soapaction) {
4560
+ if (isset($_SERVER)) {
4561
+ $SERVER_NAME = $_SERVER['SERVER_NAME'];
4562
+ $SCRIPT_NAME = isset($_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : $_SERVER['SCRIPT_NAME'];
4563
+ $HTTPS = isset($_SERVER['HTTPS']) ? $_SERVER['HTTPS'] : (isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off');
4564
+ } elseif (isset($HTTP_SERVER_VARS)) {
4565
+ $SERVER_NAME = $HTTP_SERVER_VARS['SERVER_NAME'];
4566
+ $SCRIPT_NAME = isset($HTTP_SERVER_VARS['PHP_SELF']) ? $HTTP_SERVER_VARS['PHP_SELF'] : $HTTP_SERVER_VARS['SCRIPT_NAME'];
4567
+ $HTTPS = isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off';
4568
+ } else {
4569
+ $this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available");
4570
+ }
4571
+ if ($HTTPS == '1' || $HTTPS == 'on') {
4572
+ $SCHEME = 'https';
4573
+ } else {
4574
+ $SCHEME = 'http';
4575
+ }
4576
+ $soapaction = "$SCHEME://$SERVER_NAME$SCRIPT_NAME/$name";
4577
+ }
4578
+ if (false == $style) {
4579
+ $style = "rpc";
4580
+ }
4581
+ if (false == $use) {
4582
+ $use = "encoded";
4583
+ }
4584
+ if ($use == 'encoded' && $encodingStyle == '') {
4585
+ $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
4586
+ }
4587
+
4588
+ $this->operations[$name] = array(
4589
+ 'name' => $name,
4590
+ 'in' => $in,
4591
+ 'out' => $out,
4592
+ 'namespace' => $namespace,
4593
+ 'soapaction' => $soapaction,
4594
+ 'style' => $style);
4595
+ if ($this->wsdl) {
4596
+ $this->wsdl->addOperation($name, $in, $out, $namespace, $soapaction, $style, $use, $documentation, $encodingStyle);
4597
+ }
4598
+ return true;
4599
+ }
4600
+
4601
+ /**
4602
+ * Specify a fault to be returned to the client.
4603
+ * This also acts as a flag to the server that a fault has occured.
4604
+ *
4605
+ * @param string $faultcode
4606
+ * @param string $faultstring
4607
+ * @param string $faultactor
4608
+ * @param string $faultdetail
4609
+ * @access public
4610
+ */
4611
+ function fault($faultcode, $faultstring, $faultactor = '', $faultdetail = '')
4612
+ {
4613
+ if ($faultdetail == '' && $this->debug_flag) {
4614
+ $faultdetail = $this->getDebug();
4615
+ }
4616
+ $this->fault = new nusoap_fault($faultcode, $faultactor, $faultstring, $faultdetail);
4617
+ $this->fault->soap_defencoding = $this->soap_defencoding;
4618
+ }
4619
+
4620
+ /**
4621
+ * Sets up wsdl object.
4622
+ * Acts as a flag to enable internal WSDL generation
4623
+ *
4624
+ * @param string $serviceName , name of the service
4625
+ * @param mixed $namespace optional 'tns' service namespace or false
4626
+ * @param mixed $endpoint optional URL of service endpoint or false
4627
+ * @param string $style optional (rpc|document) WSDL style (also specified by operation)
4628
+ * @param string $transport optional SOAP transport
4629
+ * @param mixed $schemaTargetNamespace optional 'types' targetNamespace for service schema or false
4630
+ */
4631
+ function configureWSDL($serviceName, $namespace = false, $endpoint = false, $style = 'rpc', $transport = 'http://schemas.xmlsoap.org/soap/http', $schemaTargetNamespace = false)
4632
+ {
4633
+ global $HTTP_SERVER_VARS;
4634
+
4635
+ if (isset($_SERVER)) {
4636
+ $SERVER_NAME = $_SERVER['SERVER_NAME'];
4637
+ $SERVER_PORT = $_SERVER['SERVER_PORT'];
4638
+ $SCRIPT_NAME = isset($_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : $_SERVER['SCRIPT_NAME'];
4639
+ $HTTPS = isset($_SERVER['HTTPS']) ? $_SERVER['HTTPS'] : (isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off');
4640
+ } elseif (isset($HTTP_SERVER_VARS)) {
4641
+ $SERVER_NAME = $HTTP_SERVER_VARS['SERVER_NAME'];
4642
+ $SERVER_PORT = $HTTP_SERVER_VARS['SERVER_PORT'];
4643
+ $SCRIPT_NAME = isset($HTTP_SERVER_VARS['PHP_SELF']) ? $HTTP_SERVER_VARS['PHP_SELF'] : $HTTP_SERVER_VARS['SCRIPT_NAME'];
4644
+ $HTTPS = isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off';
4645
+ } else {
4646
+ $this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available");
4647
+ }
4648
+ // If server name has port number attached then strip it (else port number gets duplicated in WSDL output) (occurred using lighttpd and FastCGI)
4649
+ $colon = strpos($SERVER_NAME, ":");
4650
+ if ($colon) {
4651
+ $SERVER_NAME = substr($SERVER_NAME, 0, $colon);
4652
+ }
4653
+ if ($SERVER_PORT == 80) {
4654
+ $SERVER_PORT = '';
4655
+ } else {
4656
+ $SERVER_PORT = ':' . $SERVER_PORT;
4657
+ }
4658
+ if (false == $namespace) {
4659
+ $namespace = "http://$SERVER_NAME/soap/$serviceName";
4660
+ }
4661
+
4662
+ if (false == $endpoint) {
4663
+ if ($HTTPS == '1' || $HTTPS == 'on') {
4664
+ $SCHEME = 'https';
4665
+ } else {
4666
+ $SCHEME = 'http';
4667
+ }
4668
+ $endpoint = "$SCHEME://$SERVER_NAME$SERVER_PORT$SCRIPT_NAME";
4669
+ }
4670
+
4671
+ if (false == $schemaTargetNamespace) {
4672
+ $schemaTargetNamespace = $namespace;
4673
+ }
4674
+
4675
+ $this->wsdl = new wsdl;
4676
+ $this->wsdl->serviceName = $serviceName;
4677
+ $this->wsdl->endpoint = $endpoint;
4678
+ $this->wsdl->namespaces['tns'] = $namespace;
4679
+ $this->wsdl->namespaces['soap'] = 'http://schemas.xmlsoap.org/wsdl/soap/';
4680
+ $this->wsdl->namespaces['wsdl'] = 'http://schemas.xmlsoap.org/wsdl/';
4681
+ if ($schemaTargetNamespace != $namespace) {
4682
+ $this->wsdl->namespaces['types'] = $schemaTargetNamespace;
4683
+ }
4684
+ $this->wsdl->schemas[$schemaTargetNamespace][0] = new nusoap_xmlschema('', '', $this->wsdl->namespaces);
4685
+ if ($style == 'document') {
4686
+ $this->wsdl->schemas[$schemaTargetNamespace][0]->schemaInfo['elementFormDefault'] = 'qualified';
4687
+ }
4688
+ $this->wsdl->schemas[$schemaTargetNamespace][0]->schemaTargetNamespace = $schemaTargetNamespace;
4689
+ $this->wsdl->schemas[$schemaTargetNamespace][0]->imports['http://schemas.xmlsoap.org/soap/encoding/'][0] = array('location' => '', 'loaded' => true);
4690
+ $this->wsdl->schemas[$schemaTargetNamespace][0]->imports['http://schemas.xmlsoap.org/wsdl/'][0] = array('location' => '', 'loaded' => true);
4691
+ $this->wsdl->bindings[$serviceName . 'Binding'] = array(
4692
+ 'name' => $serviceName . 'Binding',
4693
+ 'style' => $style,
4694
+ 'transport' => $transport,
4695
+ 'portType' => $serviceName . 'PortType');
4696
+ $this->wsdl->ports[$serviceName . 'Port'] = array(
4697
+ 'binding' => $serviceName . 'Binding',
4698
+ 'location' => $endpoint,
4699
+ 'bindingType' => 'http://schemas.xmlsoap.org/wsdl/soap/');
4700
+ }
4701
+ }
4702
+
4703
+ /**
4704
+ * Backward compatibility
4705
+ */
4706
+ class soap_server extends nusoap_server
4707
+ {
4708
+ }
4709
+
4710
+
4711
+ /**
4712
+ * parses a WSDL file, allows access to it's data, other utility methods.
4713
+ * also builds WSDL structures programmatically.
4714
+ *
4715
+ * @author Dietrich Ayala <dietrich@ganx4.com>
4716
+ * @author Scott Nichol <snichol@users.sourceforge.net>
4717
+ * @version $Id: nusoap.php,v 1.123 2010/04/26 20:15:08 snichol Exp $
4718
+ * @access public
4719
+ */
4720
+ class wsdl extends nusoap_base
4721
+ {
4722
+ // URL or filename of the root of this WSDL
4723
+ var $wsdl;
4724
+ // define internal arrays of bindings, ports, operations, messages, etc.
4725
+ var $schemas = array();
4726
+ var $currentSchema;
4727
+ var $message = array();
4728
+ var $complexTypes = array();
4729
+ var $messages = array();
4730
+ var $currentMessage;
4731
+ var $currentOperation;
4732
+ var $portTypes = array();
4733
+ var $currentPortType;
4734
+ var $bindings = array();
4735
+ var $currentBinding;
4736
+ var $ports = array();
4737
+ var $currentPort;
4738
+ var $opData = array();
4739
+ var $status = '';
4740
+ var $documentation = false;
4741
+ var $endpoint = '';
4742
+ // array of wsdl docs to import
4743
+ var $import = array();
4744
+ // parser vars
4745
+ var $parser;
4746
+ var $position = 0;
4747
+ var $depth = 0;
4748
+ var $depth_array = array();
4749
+ // for getting wsdl
4750
+ var $proxyhost = '';
4751
+ var $proxyport = '';
4752
+ var $proxyusername = '';
4753
+ var $proxypassword = '';
4754
+ var $timeout = 0;
4755
+ var $response_timeout = 30;
4756
+ var $curl_options = array(); // User-specified cURL options
4757
+ var $use_curl = false; // whether to always try to use cURL
4758
+ // for HTTP authentication
4759
+ var $username = ''; // Username for HTTP authentication
4760
+ var $password = ''; // Password for HTTP authentication
4761
+ var $authtype = ''; // Type of HTTP authentication
4762
+ var $certRequest = array(); // Certificate for HTTP SSL authentication
4763
+
4764
+ /**
4765
+ * constructor
4766
+ *
4767
+ * @param string $wsdl WSDL document URL
4768
+ * @param string $proxyhost
4769
+ * @param string $proxyport
4770
+ * @param string $proxyusername
4771
+ * @param string $proxypassword
4772
+ * @param integer $timeout set the connection timeout
4773
+ * @param integer $response_timeout set the response timeout
4774
+ * @param array $curl_options user-specified cURL options
4775
+ * @param boolean $use_curl try to use cURL
4776
+ * @access public
4777
+ */
4778
+ function __construct($wsdl = '', $proxyhost = false, $proxyport = false, $proxyusername = false, $proxypassword = false, $timeout = 0, $response_timeout = 30, $curl_options = null, $use_curl = false)
4779
+ {
4780
+ parent::__construct();
4781
+ $this->debug("ctor wsdl=$wsdl timeout=$timeout response_timeout=$response_timeout");
4782
+ $this->proxyhost = $proxyhost;
4783
+ $this->proxyport = $proxyport;
4784
+ $this->proxyusername = $proxyusername;
4785
+ $this->proxypassword = $proxypassword;
4786
+ $this->timeout = $timeout;
4787
+ $this->response_timeout = $response_timeout;
4788
+ if (is_array($curl_options)) {
4789
+ $this->curl_options = $curl_options;
4790
+ }
4791
+ $this->use_curl = $use_curl;
4792
+ $this->fetchWSDL($wsdl);
4793
+ }
4794
+
4795
+ /**
4796
+ * fetches the WSDL document and parses it
4797
+ *
4798
+ * @access public
4799
+ */
4800
+ function fetchWSDL($wsdl)
4801
+ {
4802
+ $this->debug("parse and process WSDL path=$wsdl");
4803
+ $this->wsdl = $wsdl;
4804
+ // parse wsdl file
4805
+ if ($this->wsdl != "") {
4806
+ $this->parseWSDL($this->wsdl);
4807
+ }
4808
+ // imports
4809
+ // TODO: handle imports more properly, grabbing them in-line and nesting them
4810
+ $imported_urls = array();
4811
+ $imported = 1;
4812
+ while ($imported > 0) {
4813
+ $imported = 0;
4814
+ // Schema imports
4815
+ foreach ($this->schemas as $ns => $list) {
4816
+ foreach ($list as $xs) {
4817
+ $wsdlparts = parse_url($this->wsdl); // this is bogusly simple!
4818
+ foreach ($xs->imports as $ns2 => $list2) {
4819
+ for ($ii = 0; $ii < count($list2); $ii++) {
4820
+ if (!$list2[$ii]['loaded']) {
4821
+ $this->schemas[$ns][$ns2]->imports[$ns2][$ii]['loaded'] = true;
4822
+ $url = $list2[$ii]['location'];
4823
+ if ($url != '') {
4824
+ $urlparts = parse_url($url);
4825
+ if (!isset($urlparts['host'])) {
4826
+ $url = $wsdlparts['scheme'] . '://' . $wsdlparts['host'] . (isset($wsdlparts['port']) ? ':' . $wsdlparts['port'] : '') .
4827
+ substr($wsdlparts['path'], 0, strrpos($wsdlparts['path'], '/') + 1) . $urlparts['path'];
4828
+ }
4829
+ if (!in_array($url, $imported_urls)) {
4830
+ $this->parseWSDL($url);
4831
+ $imported++;
4832
+ $imported_urls[] = $url;
4833
+ }
4834
+ } else {
4835
+ $this->debug("Unexpected scenario: empty URL for unloaded import");
4836
+ }
4837
+ }
4838
+ }
4839
+ }
4840
+ }
4841
+ }
4842
+ // WSDL imports
4843
+ $wsdlparts = parse_url($this->wsdl); // this is bogusly simple!
4844
+ foreach ($this->import as $ns => $list) {
4845
+ for ($ii = 0; $ii < count($list); $ii++) {
4846
+ if (!$list[$ii]['loaded']) {
4847
+ $this->import[$ns][$ii]['loaded'] = true;
4848
+ $url = $list[$ii]['location'];
4849
+ if ($url != '') {
4850
+ $urlparts = parse_url($url);
4851
+ if (!isset($urlparts['host'])) {
4852
+ $url = $wsdlparts['scheme'] . '://' . $wsdlparts['host'] . (isset($wsdlparts['port']) ? ':' . $wsdlparts['port'] : '') .
4853
+ substr($wsdlparts['path'], 0, strrpos($wsdlparts['path'], '/') + 1) . $urlparts['path'];
4854
+ }
4855
+ if (!in_array($url, $imported_urls)) {
4856
+ $this->parseWSDL($url);
4857
+ $imported++;
4858
+ $imported_urls[] = $url;
4859
+ }
4860
+ } else {
4861
+ $this->debug("Unexpected scenario: empty URL for unloaded import");
4862
+ }
4863
+ }
4864
+ }
4865
+ }
4866
+ }
4867
+ // add new data to operation data
4868
+ foreach ($this->bindings as $binding => $bindingData) {
4869
+ if (isset($bindingData['operations']) && is_array($bindingData['operations'])) {
4870
+ foreach ($bindingData['operations'] as $operation => $data) {
4871
+ $this->debug('post-parse data gathering for ' . $operation);
4872
+ $this->bindings[$binding]['operations'][$operation]['input'] =
4873
+ isset($this->bindings[$binding]['operations'][$operation]['input']) ?
4874
+ array_merge($this->bindings[$binding]['operations'][$operation]['input'], $this->portTypes[$bindingData['portType']][$operation]['input']) :
4875
+ $this->portTypes[$bindingData['portType']][$operation]['input'];
4876
+ $this->bindings[$binding]['operations'][$operation]['output'] =
4877
+ isset($this->bindings[$binding]['operations'][$operation]['output']) ?
4878
+ array_merge($this->bindings[$binding]['operations'][$operation]['output'], $this->portTypes[$bindingData['portType']][$operation]['output']) :
4879
+ $this->portTypes[$bindingData['portType']][$operation]['output'];
4880
+ if (isset($this->messages[$this->bindings[$binding]['operations'][$operation]['input']['message']])) {
4881
+ $this->bindings[$binding]['operations'][$operation]['input']['parts'] = $this->messages[$this->bindings[$binding]['operations'][$operation]['input']['message']];
4882
+ }
4883
+ if (isset($this->messages[$this->bindings[$binding]['operations'][$operation]['output']['message']])) {
4884
+ $this->bindings[$binding]['operations'][$operation]['output']['parts'] = $this->messages[$this->bindings[$binding]['operations'][$operation]['output']['message']];
4885
+ }
4886
+ // Set operation style if necessary, but do not override one already provided
4887
+ if (isset($bindingData['style']) && !isset($this->bindings[$binding]['operations'][$operation]['style'])) {
4888
+ $this->bindings[$binding]['operations'][$operation]['style'] = $bindingData['style'];
4889
+ }
4890
+ $this->bindings[$binding]['operations'][$operation]['transport'] = isset($bindingData['transport']) ? $bindingData['transport'] : '';
4891
+ $this->bindings[$binding]['operations'][$operation]['documentation'] = isset($this->portTypes[$bindingData['portType']][$operation]['documentation']) ? $this->portTypes[$bindingData['portType']][$operation]['documentation'] : '';
4892
+ $this->bindings[$binding]['operations'][$operation]['endpoint'] = isset($bindingData['endpoint']) ? $bindingData['endpoint'] : '';
4893
+ }
4894
+ }
4895
+ }
4896
+ }
4897
+
4898
+ /**
4899
+ * parses the wsdl document
4900
+ *
4901
+ * @param string $wsdl path or URL
4902
+ * @access private
4903
+ */
4904
+ function parseWSDL($wsdl = '')
4905
+ {
4906
+ $this->debug("parse WSDL at path=$wsdl");
4907
+
4908
+ if ($wsdl == '') {
4909
+ $this->debug('no wsdl passed to parseWSDL()!!');
4910
+ $this->setError('no wsdl passed to parseWSDL()!!');
4911
+ return false;
4912
+ }
4913
+
4914
+ // parse $wsdl for url format
4915
+ $wsdl_props = parse_url($wsdl);
4916
+
4917
+ if (isset($wsdl_props['scheme']) && ($wsdl_props['scheme'] == 'http' || $wsdl_props['scheme'] == 'https')) {
4918
+ $this->debug('getting WSDL http(s) URL ' . $wsdl);
4919
+ // get wsdl
4920
+ $tr = new soap_transport_http($wsdl, $this->curl_options, $this->use_curl);
4921
+ $tr->request_method = 'GET';
4922
+ $tr->useSOAPAction = false;
4923
+ if ($this->proxyhost && $this->proxyport) {
4924
+ $tr->setProxy($this->proxyhost, $this->proxyport, $this->proxyusername, $this->proxypassword);
4925
+ }
4926
+ if ($this->authtype != '') {
4927
+ $tr->setCredentials($this->username, $this->password, $this->authtype, array(), $this->certRequest);
4928
+ }
4929
+ $tr->setEncoding('gzip, deflate');
4930
+ $wsdl_string = $tr->send('', $this->timeout, $this->response_timeout);
4931
+ //$this->debug("WSDL request\n" . $tr->outgoing_payload);
4932
+ //$this->debug("WSDL response\n" . $tr->incoming_payload);
4933
+ $this->appendDebug($tr->getDebug());
4934
+ // catch errors
4935
+ if ($err = $tr->getError()) {
4936
+ $errstr = 'Getting ' . $wsdl . ' - HTTP ERROR: ' . $err;
4937
+ $this->debug($errstr);
4938
+ $this->setError($errstr);
4939
+ unset($tr);
4940
+ return false;
4941
+ }
4942
+ unset($tr);
4943
+ $this->debug("got WSDL URL");
4944
+ } else {
4945
+ // $wsdl is not http(s), so treat it as a file URL or plain file path
4946
+ if (isset($wsdl_props['scheme']) && ($wsdl_props['scheme'] == 'file') && isset($wsdl_props['path'])) {
4947
+ $path = isset($wsdl_props['host']) ? ($wsdl_props['host'] . ':' . $wsdl_props['path']) : $wsdl_props['path'];
4948
+ } else {
4949
+ $path = $wsdl;
4950
+ }
4951
+ $this->debug('getting WSDL file ' . $path);
4952
+ if ($fp = @fopen($path, 'r')) {
4953
+ $wsdl_string = '';
4954
+ while ($data = fread($fp, 32768)) {
4955
+ $wsdl_string .= $data;
4956
+ }
4957
+ fclose($fp);
4958
+ } else {
4959
+ $errstr = "Bad path to WSDL file $path";
4960
+ $this->debug($errstr);
4961
+ $this->setError($errstr);
4962
+ return false;
4963
+ }
4964
+ }
4965
+ $this->debug('Parse WSDL');
4966
+ // end new code added
4967
+ // Create an XML parser.
4968
+ $this->parser = xml_parser_create();
4969
+ // Set the options for parsing the XML data.
4970
+ // xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
4971
+ xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
4972
+ // Set the object for the parser.
4973
+ xml_set_object($this->parser, $this);
4974
+ // Set the element handlers for the parser.
4975
+ xml_set_element_handler($this->parser, 'start_element', 'end_element');
4976
+ xml_set_character_data_handler($this->parser, 'character_data');
4977
+ // Parse the XML file.
4978
+ if (!xml_parse($this->parser, $wsdl_string, true)) {
4979
+ // Display an error message.
4980
+ $errstr = sprintf(
4981
+ 'XML error parsing WSDL from %s on line %d: %s',
4982
+ $wsdl,
4983
+ xml_get_current_line_number($this->parser),
4984
+ xml_error_string(xml_get_error_code($this->parser))
4985
+ );
4986
+ $this->debug($errstr);
4987
+ $this->debug("XML payload:\n" . $wsdl_string);
4988
+ $this->setError($errstr);
4989
+ xml_parser_free($this->parser);
4990
+ unset($this->parser);
4991
+ return false;
4992
+ }
4993
+ // free the parser
4994
+ xml_parser_free($this->parser);
4995
+ unset($this->parser);
4996
+ $this->debug('Parsing WSDL done');
4997
+ // catch wsdl parse errors
4998
+ if ($this->getError()) {
4999
+ return false;
5000
+ }
5001
+ return true;
5002
+ }
5003
+
5004
+ /**
5005
+ * start-element handler
5006
+ *
5007
+ * @param string $parser XML parser object
5008
+ * @param string $name element name
5009
+ * @param string $attrs associative array of attributes
5010
+ * @access private
5011
+ */
5012
+ function start_element($parser, $name, $attrs)
5013
+ {
5014
+ if ($this->status == 'schema') {
5015
+ $this->currentSchema->schemaStartElement($parser, $name, $attrs);
5016
+ $this->appendDebug($this->currentSchema->getDebug());
5017
+ $this->currentSchema->clearDebug();
5018
+ } elseif (preg_match('/schema$/', $name)) {
5019
+ $this->debug('Parsing WSDL schema');
5020
+ // $this->debug("startElement for $name ($attrs[name]). status = $this->status (".$this->getLocalPart($name).")");
5021
+ $this->status = 'schema';
5022
+ $this->currentSchema = new nusoap_xmlschema('', '', $this->namespaces);
5023
+ $this->currentSchema->schemaStartElement($parser, $name, $attrs);
5024
+ $this->appendDebug($this->currentSchema->getDebug());
5025
+ $this->currentSchema->clearDebug();
5026
+ } else {
5027
+ // position in the total number of elements, starting from 0
5028
+ $pos = $this->position++;
5029
+ $depth = $this->depth++;
5030
+ // set self as current value for this depth
5031
+ $this->depth_array[$depth] = $pos;
5032
+ $this->message[$pos] = array('cdata' => '');
5033
+ // process attributes
5034
+ if (count($attrs) > 0) {
5035
+ // register namespace declarations
5036
+ foreach ($attrs as $k => $v) {
5037
+ if (preg_match('/^xmlns/', $k)) {
5038
+ if ($ns_prefix = substr(strrchr($k, ':'), 1)) {
5039
+ $this->namespaces[$ns_prefix] = $v;
5040
+ } else {
5041
+ $this->namespaces['ns' . (count($this->namespaces) + 1)] = $v;
5042
+ }
5043
+ if ($v == 'http://www.w3.org/2001/XMLSchema' || $v == 'http://www.w3.org/1999/XMLSchema' || $v == 'http://www.w3.org/2000/10/XMLSchema') {
5044
+ $this->XMLSchemaVersion = $v;
5045
+ $this->namespaces['xsi'] = $v . '-instance';
5046
+ }
5047
+ }
5048
+ }
5049
+ // expand each attribute prefix to its namespace
5050
+ foreach ($attrs as $k => $v) {
5051
+ $k = strpos($k, ':') ? $this->expandQname($k) : $k;
5052
+ if ($k != 'location' && $k != 'soapAction' && $k != 'namespace') {
5053
+ $v = strpos($v, ':') ? $this->expandQname($v) : $v;
5054
+ }
5055
+ $eAttrs[$k] = $v;
5056
+ }
5057
+ $attrs = $eAttrs;
5058
+ } else {
5059
+ $attrs = array();
5060
+ }
5061
+ // Set default prefix and namespace
5062
+ // to prevent error Undefined variable $prefix and $namespace if (preg_match('/:/', $name)) return 0 or FALSE
5063
+ $prefix = '';
5064
+ $namespace = '';
5065
+ // get element prefix, namespace and name
5066
+ if (preg_match('/:/', $name)) {
5067
+ // get ns prefix
5068
+ $prefix = substr($name, 0, strpos($name, ':'));
5069
+ // get ns
5070
+ $namespace = isset($this->namespaces[$prefix]) ? $this->namespaces[$prefix] : '';
5071
+ // get unqualified name
5072
+ $name = substr(strstr($name, ':'), 1);
5073
+ }
5074
+ // process attributes, expanding any prefixes to namespaces
5075
+ // find status, register data
5076
+ switch ($this->status) {
5077
+ case 'message':
5078
+ if ($name == 'part') {
5079
+ if (isset($attrs['type'])) {
5080
+ $this->debug("msg " . $this->currentMessage . ": found part (with type) $attrs[name]: " . implode(',', $attrs));
5081
+ $this->messages[$this->currentMessage][$attrs['name']] = $attrs['type'];
5082
+ }
5083
+ if (isset($attrs['element'])) {
5084
+ $this->debug("msg " . $this->currentMessage . ": found part (with element) $attrs[name]: " . implode(',', $attrs));
5085
+ $this->messages[$this->currentMessage][$attrs['name']] = $attrs['element'] . '^';
5086
+ }
5087
+ }
5088
+ break;
5089
+ case 'portType':
5090
+ switch ($name) {
5091
+ case 'operation':
5092
+ $this->currentPortOperation = $attrs['name'];
5093
+ $this->debug("portType $this->currentPortType operation: $this->currentPortOperation");
5094
+ if (isset($attrs['parameterOrder'])) {
5095
+ $this->portTypes[$this->currentPortType][$attrs['name']]['parameterOrder'] = $attrs['parameterOrder'];
5096
+ }
5097
+ break;
5098
+ case 'documentation':
5099
+ $this->documentation = true;
5100
+ break;
5101
+ // merge input/output data
5102
+ default:
5103
+ $m = isset($attrs['message']) ? $this->getLocalPart($attrs['message']) : '';
5104
+ $this->portTypes[$this->currentPortType][$this->currentPortOperation][$name]['message'] = $m;
5105
+ break;
5106
+ }
5107
+ break;
5108
+ case 'binding':
5109
+ switch ($name) {
5110
+ case 'binding':
5111
+ // get ns prefix
5112
+ if (isset($attrs['style'])) {
5113
+ $this->bindings[$this->currentBinding]['prefix'] = $prefix;
5114
+ }
5115
+ $this->bindings[$this->currentBinding] = array_merge($this->bindings[$this->currentBinding], $attrs);
5116
+ break;
5117
+ case 'header':
5118
+ $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus]['headers'][] = $attrs;
5119
+ break;
5120
+ case 'operation':
5121
+ if (isset($attrs['soapAction'])) {
5122
+ $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['soapAction'] = $attrs['soapAction'];
5123
+ }
5124
+ if (isset($attrs['style'])) {
5125
+ $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['style'] = $attrs['style'];
5126
+ }
5127
+ if (isset($attrs['name'])) {
5128
+ $this->currentOperation = $attrs['name'];
5129
+ $this->debug("current binding operation: $this->currentOperation");
5130
+ $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['name'] = $attrs['name'];
5131
+ $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['binding'] = $this->currentBinding;
5132
+ $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['endpoint'] = isset($this->bindings[$this->currentBinding]['endpoint']) ? $this->bindings[$this->currentBinding]['endpoint'] : '';
5133
+ }
5134
+ break;
5135
+ case 'input':
5136
+ $this->opStatus = 'input';
5137
+ break;
5138
+ case 'output':
5139
+ $this->opStatus = 'output';
5140
+ break;
5141
+ case 'body':
5142
+ if (isset($this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus])) {
5143
+ $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus] = array_merge($this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus], $attrs);
5144
+ } else {
5145
+ $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus] = $attrs;
5146
+ }
5147
+ break;
5148
+ }
5149
+ break;
5150
+ case 'service':
5151
+ switch ($name) {
5152
+ case 'port':
5153
+ $this->currentPort = $attrs['name'];
5154
+ $this->debug('current port: ' . $this->currentPort);
5155
+ $this->ports[$this->currentPort]['binding'] = $this->getLocalPart($attrs['binding']);
5156
+
5157
+ break;
5158
+ case 'address':
5159
+ $this->ports[$this->currentPort]['location'] = $attrs['location'];
5160
+ $this->ports[$this->currentPort]['bindingType'] = $namespace;
5161
+ $this->bindings[$this->ports[$this->currentPort]['binding']]['bindingType'] = $namespace;
5162
+ $this->bindings[$this->ports[$this->currentPort]['binding']]['endpoint'] = $attrs['location'];
5163
+ break;
5164
+ }
5165
+ break;
5166
+ }
5167
+ // set status
5168
+ switch ($name) {
5169
+ case 'import':
5170
+ if (isset($attrs['location'])) {
5171
+ $this->import[$attrs['namespace']][] = array('location' => $attrs['location'], 'loaded' => false);
5172
+ $this->debug('parsing import ' . $attrs['namespace'] . ' - ' . $attrs['location'] . ' (' . count($this->import[$attrs['namespace']]) . ')');
5173
+ } else {
5174
+ $this->import[$attrs['namespace']][] = array('location' => '', 'loaded' => true);
5175
+ if (!$this->getPrefixFromNamespace($attrs['namespace'])) {
5176
+ $this->namespaces['ns' . (count($this->namespaces) + 1)] = $attrs['namespace'];
5177
+ }
5178
+ $this->debug('parsing import ' . $attrs['namespace'] . ' - [no location] (' . count($this->import[$attrs['namespace']]) . ')');
5179
+ }
5180
+ break;
5181
+ //wait for schema
5182
+ //case 'types':
5183
+ // $this->status = 'schema';
5184
+ // break;
5185
+ case 'message':
5186
+ $this->status = 'message';
5187
+ $this->messages[$attrs['name']] = array();
5188
+ $this->currentMessage = $attrs['name'];
5189
+ break;
5190
+ case 'portType':
5191
+ $this->status = 'portType';
5192
+ $this->portTypes[$attrs['name']] = array();
5193
+ $this->currentPortType = $attrs['name'];
5194
+ break;
5195
+ case "binding":
5196
+ if (isset($attrs['name'])) {
5197
+ // get binding name
5198
+ if (strpos($attrs['name'], ':')) {
5199
+ $this->currentBinding = $this->getLocalPart($attrs['name']);
5200
+ } else {
5201
+ $this->currentBinding = $attrs['name'];
5202
+ }
5203
+ $this->status = 'binding';
5204
+ $this->bindings[$this->currentBinding]['portType'] = $this->getLocalPart($attrs['type']);
5205
+ $this->debug("current binding: $this->currentBinding of portType: " . $attrs['type']);
5206
+ }
5207
+ break;
5208
+ case 'service':
5209
+ $this->serviceName = $attrs['name'];
5210
+ $this->status = 'service';
5211
+ $this->debug('current service: ' . $this->serviceName);
5212
+ break;
5213
+ case 'definitions':
5214
+ foreach ($attrs as $name => $value) {
5215
+ $this->wsdl_info[$name] = $value;
5216
+ }
5217
+ break;
5218
+ }
5219
+ }
5220
+ }
5221
+
5222
+ /**
5223
+ * end-element handler
5224
+ *
5225
+ * @param string $parser XML parser object
5226
+ * @param string $name element name
5227
+ * @access private
5228
+ */
5229
+ function end_element($parser, $name)
5230
+ {
5231
+ // unset schema status
5232
+ if (/*preg_match('/types$/', $name) ||*/
5233
+ preg_match('/schema$/', $name)
5234
+ ) {
5235
+ $this->status = "";
5236
+ $this->appendDebug($this->currentSchema->getDebug());
5237
+ $this->currentSchema->clearDebug();
5238
+ $this->schemas[$this->currentSchema->schemaTargetNamespace][] = $this->currentSchema;
5239
+ $this->debug('Parsing WSDL schema done');
5240
+ }
5241
+ if ($this->status == 'schema') {
5242
+ $this->currentSchema->schemaEndElement($parser, $name);
5243
+ } else {
5244
+ // bring depth down a notch
5245
+ $this->depth--;
5246
+ }
5247
+ // end documentation
5248
+ if ($this->documentation) {
5249
+ //TODO: track the node to which documentation should be assigned; it can be a part, message, etc.
5250
+ //$this->portTypes[$this->currentPortType][$this->currentPortOperation]['documentation'] = $this->documentation;
5251
+ $this->documentation = false;
5252
+ }
5253
+ }
5254
+
5255
+ /**
5256
+ * element content handler
5257
+ *
5258
+ * @param string $parser XML parser object
5259
+ * @param string $data element content
5260
+ * @access private
5261
+ */
5262
+ function character_data($parser, $data)
5263
+ {
5264
+ $pos = isset($this->depth_array[$this->depth]) ? $this->depth_array[$this->depth] : 0;
5265
+ if (isset($this->message[$pos]['cdata'])) {
5266
+ $this->message[$pos]['cdata'] .= $data;
5267
+ }
5268
+ if ($this->documentation) {
5269
+ $this->documentation .= $data;
5270
+ }
5271
+ }
5272
+
5273
+ /**
5274
+ * if authenticating, set user credentials here
5275
+ *
5276
+ * @param string $username
5277
+ * @param string $password
5278
+ * @param string $authtype (basic|digest|certificate|ntlm)
5279
+ * @param array $certRequest (keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, certpassword (optional), verifypeer (optional), verifyhost (optional): see corresponding options in cURL docs)
5280
+ * @access public
5281
+ */
5282
+ function setCredentials($username, $password, $authtype = 'basic', $certRequest = array())
5283
+ {
5284
+ $this->debug("setCredentials username=$username authtype=$authtype certRequest=");
5285
+ $this->appendDebug($this->varDump($certRequest));
5286
+ $this->username = $username;
5287
+ $this->password = $password;
5288
+ $this->authtype = $authtype;
5289
+ $this->certRequest = $certRequest;
5290
+ }
5291
+
5292
+ function getBindingData($binding)
5293
+ {
5294
+ if (is_array($this->bindings[$binding])) {
5295
+ return $this->bindings[$binding];
5296
+ }
5297
+ }
5298
+
5299
+ /**
5300
+ * returns an assoc array of operation names => operation data
5301
+ *
5302
+ * @param string $portName WSDL port name
5303
+ * @param string $bindingType eg: soap, smtp, dime (only soap and soap12 are currently supported)
5304
+ * @return array
5305
+ * @access public
5306
+ */
5307
+ function getOperations($portName = '', $bindingType = 'soap')
5308
+ {
5309
+ $ops = array();
5310
+ if ($bindingType == 'soap') {
5311
+ $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/';
5312
+ } elseif ($bindingType == 'soap12') {
5313
+ $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/';
5314
+ } else {
5315
+ $this->debug("getOperations bindingType $bindingType may not be supported");
5316
+ }
5317
+ $this->debug("getOperations for port '$portName' bindingType $bindingType");
5318
+ // loop thru ports
5319
+ foreach ($this->ports as $port => $portData) {
5320
+ $this->debug("getOperations checking port $port bindingType " . $portData['bindingType']);
5321
+ if ($portName == '' || $port == $portName) {
5322
+ // binding type of port matches parameter
5323
+ if ($portData['bindingType'] == $bindingType) {
5324
+ $this->debug("getOperations found port $port bindingType $bindingType");
5325
+ //$this->debug("port data: " . $this->varDump($portData));
5326
+ //$this->debug("bindings: " . $this->varDump($this->bindings[ $portData['binding'] ]));
5327
+ // merge bindings
5328
+ if (isset($this->bindings[$portData['binding']]['operations'])) {
5329
+ $ops = array_merge($ops, $this->bindings[$portData['binding']]['operations']);
5330
+ }
5331
+ }
5332
+ }
5333
+ }
5334
+ if (count($ops) == 0) {
5335
+ $this->debug("getOperations found no operations for port '$portName' bindingType $bindingType");
5336
+ }
5337
+ return $ops;
5338
+ }
5339
+
5340
+ /**
5341
+ * returns an associative array of data necessary for calling an operation
5342
+ *
5343
+ * @param string $operation name of operation
5344
+ * @param string $bindingType type of binding eg: soap, soap12
5345
+ * @return array
5346
+ * @access public
5347
+ */
5348
+ function getOperationData($operation, $bindingType = 'soap')
5349
+ {
5350
+ if ($bindingType == 'soap') {
5351
+ $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/';
5352
+ } elseif ($bindingType == 'soap12') {
5353
+ $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/';
5354
+ }
5355
+ // loop thru ports
5356
+ foreach ($this->ports as $port => $portData) {
5357
+ // binding type of port matches parameter
5358
+ if ($portData['bindingType'] == $bindingType) {
5359
+ // get binding
5360
+ //foreach($this->bindings[ $portData['binding'] ]['operations'] as $bOperation => $opData) {
5361
+ foreach (array_keys($this->bindings[$portData['binding']]['operations']) as $bOperation) {
5362
+ // note that we could/should also check the namespace here
5363
+ if ($operation == $bOperation) {
5364
+ $opData = $this->bindings[$portData['binding']]['operations'][$operation];
5365
+ return $opData;
5366
+ }
5367
+ }
5368
+ }
5369
+ }
5370
+ }
5371
+
5372
+ /**
5373
+ * returns an associative array of data necessary for calling an operation
5374
+ *
5375
+ * @param string $soapAction soapAction for operation
5376
+ * @param string $bindingType type of binding eg: soap, soap12
5377
+ * @return array
5378
+ * @access public
5379
+ */
5380
+ function getOperationDataForSoapAction($soapAction, $bindingType = 'soap')
5381
+ {
5382
+ if ($bindingType == 'soap') {
5383
+ $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/';
5384
+ } elseif ($bindingType == 'soap12') {
5385
+ $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/';
5386
+ }
5387
+ // loop thru ports
5388
+ foreach ($this->ports as $port => $portData) {
5389
+ // binding type of port matches parameter
5390
+ if ($portData['bindingType'] == $bindingType) {
5391
+ // loop through operations for the binding
5392
+ foreach ($this->bindings[$portData['binding']]['operations'] as $bOperation => $opData) {
5393
+ if ($opData['soapAction'] == $soapAction) {
5394
+ return $opData;
5395
+ }
5396
+ }
5397
+ }
5398
+ }
5399
+ }
5400
+
5401
+ /**
5402
+ * returns an array of information about a given type
5403
+ * returns false if no type exists by the given name
5404
+ *
5405
+ * typeDef = array(
5406
+ * 'elements' => array(), // refs to elements array
5407
+ * 'restrictionBase' => '',
5408
+ * 'phpType' => '',
5409
+ * 'order' => '(sequence|all)',
5410
+ * 'attrs' => array() // refs to attributes array
5411
+ * )
5412
+ *
5413
+ * @param string $type the type
5414
+ * @param string $ns namespace (not prefix) of the type
5415
+ * @return mixed
5416
+ * @access public
5417
+ * @see nusoap_xmlschema
5418
+ */
5419
+ function getTypeDef($type, $ns)
5420
+ {
5421
+ $this->debug("in getTypeDef: type=$type, ns=$ns");
5422
+ if ((!$ns) && isset($this->namespaces['tns'])) {
5423
+ $ns = $this->namespaces['tns'];
5424
+ $this->debug("in getTypeDef: type namespace forced to $ns");
5425
+ }
5426
+ if (!isset($this->schemas[$ns])) {
5427
+ foreach ($this->schemas as $ns0 => $schema0) {
5428
+ if (strcasecmp($ns, $ns0) == 0) {
5429
+ $this->debug("in getTypeDef: replacing schema namespace $ns with $ns0");
5430
+ $ns = $ns0;
5431
+ break;
5432
+ }
5433
+ }
5434
+ }
5435
+ if (isset($this->schemas[$ns])) {
5436
+ $this->debug("in getTypeDef: have schema for namespace $ns");
5437
+ for ($i = 0; $i < count($this->schemas[$ns]); $i++) {
5438
+ $xs = &$this->schemas[$ns][$i];
5439
+ $t = $xs->getTypeDef($type);
5440
+ $this->appendDebug($xs->getDebug());
5441
+ $xs->clearDebug();
5442
+ if ($t) {
5443
+ $this->debug("in getTypeDef: found type $type");
5444
+ if (!isset($t['phpType'])) {
5445
+ // get info for type to tack onto the element
5446
+ $uqType = substr($t['type'], strrpos($t['type'], ':') + 1);
5447
+ $ns = substr($t['type'], 0, strrpos($t['type'], ':'));
5448
+ $etype = $this->getTypeDef($uqType, $ns);
5449
+ if ($etype) {
5450
+ $this->debug("found type for [element] $type:");
5451
+ $this->debug($this->varDump($etype));
5452
+ if (isset($etype['phpType'])) {
5453
+ $t['phpType'] = $etype['phpType'];
5454
+ }
5455
+ if (isset($etype['elements'])) {
5456
+ $t['elements'] = $etype['elements'];
5457
+ }
5458
+ if (isset($etype['attrs'])) {
5459
+ $t['attrs'] = $etype['attrs'];
5460
+ }
5461
+ } else {
5462
+ $this->debug("did not find type for [element] $type");
5463
+ }
5464
+ }
5465
+ return $t;
5466
+ }
5467
+ }
5468
+ $this->debug("in getTypeDef: did not find type $type");
5469
+ } else {
5470
+ $this->debug("in getTypeDef: do not have schema for namespace $ns");
5471
+ }
5472
+ return false;
5473
+ }
5474
+
5475
+ /**
5476
+ * prints html description of services
5477
+ *
5478
+ * @access private
5479
+ */
5480
+ function webDescription()
5481
+ {
5482
+ global $HTTP_SERVER_VARS;
5483
+
5484
+ if (isset($_SERVER)) {
5485
+ $PHP_SELF = $_SERVER['PHP_SELF'];
5486
+ } elseif (isset($HTTP_SERVER_VARS)) {
5487
+ $PHP_SELF = $HTTP_SERVER_VARS['PHP_SELF'];
5488
+ } else {
5489
+ $this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available");
5490
+ }
5491
+
5492
+ $b = '
5493
+ <html><head><title>NuSOAP: ' . $this->serviceName . '</title>
5494
+ <style type="text/css">
5495
+ body { font-family: arial; color: #000000; background-color: #ffffff; margin: 0px 0px 0px 0px; }
5496
+ p { font-family: arial; color: #000000; margin-top: 0px; margin-bottom: 12px; }
5497
+ pre { background-color: silver; padding: 5px; font-family: Courier New; font-size: x-small; color: #000000;}
5498
+ ul { margin-top: 10px; margin-left: 20px; }
5499
+ li { list-style-type: none; margin-top: 10px; color: #000000; }
5500
+ .content{
5501
+ margin-left: 0px; padding-bottom: 2em; }
5502
+ .nav {
5503
+ padding-top: 10px; padding-bottom: 10px; padding-left: 15px; font-size: .70em;
5504
+ margin-top: 10px; margin-left: 0px; color: #000000;
5505
+ background-color: #ccccff; width: 20%; margin-left: 20px; margin-top: 20px; }
5506
+ .title {
5507
+ font-family: arial; font-size: 26px; color: #ffffff;
5508
+ background-color: #999999; width: 100%;
5509
+ margin-left: 0px; margin-right: 0px;
5510
+ padding-top: 10px; padding-bottom: 10px;}
5511
+ .hidden {
5512
+ position: absolute; visibility: hidden; z-index: 200; left: 250px; top: 100px;
5513
+ font-family: arial; overflow: hidden; width: 600;
5514
+ padding: 20px; font-size: 10px; background-color: #999999;
5515
+ layer-background-color:#FFFFFF; }
5516
+ a,a:active { color: charcoal; font-weight: bold; }
5517
+ a:visited { color: #666666; font-weight: bold; }
5518
+ a:hover { color: cc3300; font-weight: bold; }
5519
+ </style>
5520
+ <script language="JavaScript" type="text/javascript">
5521
+ <!--
5522
+ // POP-UP CAPTIONS...
5523
+ function lib_bwcheck(){ //Browsercheck (needed)
5524
+ this.ver=navigator.appVersion
5525
+ this.agent=navigator.userAgent
5526
+ this.dom=document.getElementById?1:0
5527
+ this.opera5=this.agent.indexOf("Opera 5")>-1
5528
+ this.ie5=(this.ver.indexOf("MSIE 5")>-1 && this.dom && !this.opera5)?1:0;
5529
+ this.ie6=(this.ver.indexOf("MSIE 6")>-1 && this.dom && !this.opera5)?1:0;
5530
+ this.ie4=(document.all && !this.dom && !this.opera5)?1:0;
5531
+ this.ie=this.ie4||this.ie5||this.ie6
5532
+ this.mac=this.agent.indexOf("Mac")>-1
5533
+ this.ns6=(this.dom && parseInt(this.ver) >= 5) ?1:0;
5534
+ this.ns4=(document.layers && !this.dom)?1:0;
5535
+ this.bw=(this.ie6 || this.ie5 || this.ie4 || this.ns4 || this.ns6 || this.opera5)
5536
+ return this
5537
+ }
5538
+ var bw = new lib_bwcheck()
5539
+ //Makes crossbrowser object.
5540
+ function makeObj(obj){
5541
+ this.evnt=bw.dom? document.getElementById(obj):bw.ie4?document.all[obj]:bw.ns4?document.layers[obj]:0;
5542
+ if(!this.evnt) return false
5543
+ this.css=bw.dom||bw.ie4?this.evnt.style:bw.ns4?this.evnt:0;
5544
+ this.wref=bw.dom||bw.ie4?this.evnt:bw.ns4?this.css.document:0;
5545
+ this.writeIt=b_writeIt;
5546
+ return this
5547
+ }
5548
+ // A unit of measure that will be added when setting the position of a layer.
5549
+ //var px = bw.ns4||window.opera?"":"px";
5550
+ function b_writeIt(text){
5551
+ if (bw.ns4){this.wref.write(text);this.wref.close()}
5552
+ else this.wref.innerHTML = text
5553
+ }
5554
+ //Shows the messages
5555
+ var oDesc;
5556
+ function popup(divid){
5557
+ if(oDesc = new makeObj(divid)){
5558
+ oDesc.css.visibility = "visible"
5559
+ }
5560
+ }
5561
+ function popout(){ // Hides message
5562
+ if(oDesc) oDesc.css.visibility = "hidden"
5563
+ }
5564
+ //-->
5565
+ </script>
5566
+ </head>
5567
+ <body>
5568
+ <div class=content>
5569
+ <br><br>
5570
+ <div class=title>' . $this->serviceName . '</div>
5571
+ <div class=nav>
5572
+ <p>View the <a href="' . $PHP_SELF . '?wsdl">WSDL</a> for the service.
5573
+ Click on an operation name to view it&apos;s details.</p>
5574
+ <ul>';
5575
+ foreach ($this->getOperations() as $op => $data) {
5576
+ $b .= "<li><a href='#' onclick=\"popout();popup('$op')\">$op</a></li>";
5577
+ // create hidden div
5578
+ $b .= "<div id='$op' class='hidden'>
5579
+ <a href='#' onclick='popout()'><font color='#ffffff'>Close</font></a><br><br>";
5580
+ foreach ($data as $donnie => $marie) { // loop through opdata
5581
+ if ($donnie == 'input' || $donnie == 'output') { // show input/output data
5582
+ $b .= "<font color='white'>" . ucfirst($donnie) . ':</font><br>';
5583
+ foreach ($marie as $captain => $tenille) { // loop through data
5584
+ if ($captain == 'parts') { // loop thru parts
5585
+ $b .= "&nbsp;&nbsp;$captain:<br>";
5586
+ //if(is_array($tenille)){
5587
+ foreach ($tenille as $joanie => $chachi) {
5588
+ $b .= "&nbsp;&nbsp;&nbsp;&nbsp;$joanie: $chachi<br>";
5589
+ }
5590
+ //}
5591
+ } else {
5592
+ $b .= "&nbsp;&nbsp;$captain: $tenille<br>";
5593
+ }
5594
+ }
5595
+ } else {
5596
+ $b .= "<font color='white'>" . ucfirst($donnie) . ":</font> $marie<br>";
5597
+ }
5598
+ }
5599
+ $b .= '</div>';
5600
+ }
5601
+ $b .= '
5602
+ <ul>
5603
+ </div>
5604
+ </div></body></html>';
5605
+ return $b;
5606
+ }
5607
+
5608
+ /**
5609
+ * serialize the parsed wsdl
5610
+ *
5611
+ * @param mixed $debug whether to put debug=1 in endpoint URL
5612
+ * @return string serialization of WSDL
5613
+ * @access public
5614
+ */
5615
+ function serialize($debug = 0)
5616
+ {
5617
+ $xml = '<?xml version="1.0" encoding="ISO-8859-1"?>';
5618
+ $xml .= "\n<definitions";
5619
+ foreach ($this->namespaces as $k => $v) {
5620
+ $xml .= " xmlns:$k=\"$v\"";
5621
+ }
5622
+ // 10.9.02 - add poulter fix for wsdl and tns declarations
5623
+ if (isset($this->namespaces['wsdl'])) {
5624
+ $xml .= " xmlns=\"" . $this->namespaces['wsdl'] . "\"";
5625
+ }
5626
+ if (isset($this->namespaces['tns'])) {
5627
+ $xml .= " targetNamespace=\"" . $this->namespaces['tns'] . "\"";
5628
+ }
5629
+ $xml .= '>';
5630
+ // imports
5631
+ if (sizeof($this->import) > 0) {
5632
+ foreach ($this->import as $ns => $list) {
5633
+ foreach ($list as $ii) {
5634
+ if ($ii['location'] != '') {
5635
+ $xml .= '<import location="' . $ii['location'] . '" namespace="' . $ns . '" />';
5636
+ } else {
5637
+ $xml .= '<import namespace="' . $ns . '" />';
5638
+ }
5639
+ }
5640
+ }
5641
+ }
5642
+ // types
5643
+ if (count($this->schemas) >= 1) {
5644
+ $xml .= "\n<types>\n";
5645
+ foreach ($this->schemas as $ns => $list) {
5646
+ foreach ($list as $xs) {
5647
+ $xml .= $xs->serializeSchema();
5648
+ }
5649
+ }
5650
+ $xml .= '</types>';
5651
+ }
5652
+ // messages
5653
+ if (count($this->messages) >= 1) {
5654
+ foreach ($this->messages as $msgName => $msgParts) {
5655
+ $xml .= "\n<message name=\"" . $msgName . '">';
5656
+ if (is_array($msgParts)) {
5657
+ foreach ($msgParts as $partName => $partType) {
5658
+ // print 'serializing '.$partType.', sv: '.$this->XMLSchemaVersion.'<br>';
5659
+ if (strpos($partType, ':')) {
5660
+ $typePrefix = $this->getPrefixFromNamespace($this->getPrefix($partType));
5661
+ } elseif (isset($this->typemap[$this->namespaces['xsd']][$partType])) {
5662
+ // print 'checking typemap: '.$this->XMLSchemaVersion.'<br>';
5663
+ $typePrefix = 'xsd';
5664
+ } else {
5665
+ foreach ($this->typemap as $ns => $types) {
5666
+ if (isset($types[$partType])) {
5667
+ $typePrefix = $this->getPrefixFromNamespace($ns);
5668
+ }
5669
+ }
5670
+ if (!isset($typePrefix)) {
5671
+ die("$partType has no namespace!");
5672
+ }
5673
+ }
5674
+ $ns = $this->getNamespaceFromPrefix($typePrefix);
5675
+ $localPart = $this->getLocalPart($partType);
5676
+ $typeDef = $this->getTypeDef($localPart, $ns);
5677
+ if ($typeDef['typeClass'] == 'element') {
5678
+ $elementortype = 'element';
5679
+ if (substr($localPart, -1) == '^') {
5680
+ $localPart = substr($localPart, 0, -1);
5681
+ }
5682
+ } else {
5683
+ $elementortype = 'type';
5684
+ }
5685
+ $xml .= "\n" . ' <part name="' . $partName . '" ' . $elementortype . '="' . $typePrefix . ':' . $localPart . '" />';
5686
+ }
5687
+ }
5688
+ $xml .= '</message>';
5689
+ }
5690
+ }
5691
+ // bindings & porttypes
5692
+ if (count($this->bindings) >= 1) {
5693
+ $binding_xml = '';
5694
+ $portType_xml = '';
5695
+ foreach ($this->bindings as $bindingName => $attrs) {
5696
+ $binding_xml .= "\n<binding name=\"" . $bindingName . '" type="tns:' . $attrs['portType'] . '">';
5697
+ $binding_xml .= "\n" . ' <soap:binding style="' . $attrs['style'] . '" transport="' . $attrs['transport'] . '"/>';
5698
+ $portType_xml .= "\n<portType name=\"" . $attrs['portType'] . '">';
5699
+ foreach ($attrs['operations'] as $opName => $opParts) {
5700
+ $binding_xml .= "\n" . ' <operation name="' . $opName . '">';
5701
+ $binding_xml .= "\n" . ' <soap:operation soapAction="' . $opParts['soapAction'] . '" style="' . $opParts['style'] . '"/>';
5702
+ if (isset($opParts['input']['encodingStyle']) && $opParts['input']['encodingStyle'] != '') {
5703
+ $enc_style = ' encodingStyle="' . $opParts['input']['encodingStyle'] . '"';
5704
+ } else {
5705
+ $enc_style = '';
5706
+ }
5707
+ $binding_xml .= "\n" . ' <input><soap:body use="' . $opParts['input']['use'] . '" namespace="' . $opParts['input']['namespace'] . '"' . $enc_style . '/></input>';
5708
+ if (isset($opParts['output']['encodingStyle']) && $opParts['output']['encodingStyle'] != '') {
5709
+ $enc_style = ' encodingStyle="' . $opParts['output']['encodingStyle'] . '"';
5710
+ } else {
5711
+ $enc_style = '';
5712
+ }
5713
+ $binding_xml .= "\n" . ' <output><soap:body use="' . $opParts['output']['use'] . '" namespace="' . $opParts['output']['namespace'] . '"' . $enc_style . '/></output>';
5714
+ $binding_xml .= "\n" . ' </operation>';
5715
+ $portType_xml .= "\n" . ' <operation name="' . $opParts['name'] . '"';
5716
+ if (isset($opParts['parameterOrder'])) {
5717
+ $portType_xml .= ' parameterOrder="' . $opParts['parameterOrder'] . '"';
5718
+ }
5719
+ $portType_xml .= '>';
5720
+ if (isset($opParts['documentation']) && $opParts['documentation'] != '') {
5721
+ $portType_xml .= "\n" . ' <documentation>' . htmlspecialchars($opParts['documentation']) . '</documentation>';
5722
+ }
5723
+ $portType_xml .= "\n" . ' <input message="tns:' . $opParts['input']['message'] . '"/>';
5724
+ $portType_xml .= "\n" . ' <output message="tns:' . $opParts['output']['message'] . '"/>';
5725
+ $portType_xml .= "\n" . ' </operation>';
5726
+ }
5727
+ $portType_xml .= "\n" . '</portType>';
5728
+ $binding_xml .= "\n" . '</binding>';
5729
+ }
5730
+ $xml .= $portType_xml . $binding_xml;
5731
+ }
5732
+ // services
5733
+ $xml .= "\n<service name=\"" . $this->serviceName . '">';
5734
+ if (count($this->ports) >= 1) {
5735
+ foreach ($this->ports as $pName => $attrs) {
5736
+ $xml .= "\n" . ' <port name="' . $pName . '" binding="tns:' . $attrs['binding'] . '">';
5737
+ $xml .= "\n" . ' <soap:address location="' . $attrs['location'] . ($debug ? '?debug=1' : '') . '"/>';
5738
+ $xml .= "\n" . ' </port>';
5739
+ }
5740
+ }
5741
+ $xml .= "\n" . '</service>';
5742
+ return $xml . "\n</definitions>";
5743
+ }
5744
+
5745
+ /**
5746
+ * determine whether a set of parameters are unwrapped
5747
+ * when they are expect to be wrapped, Microsoft-style.
5748
+ *
5749
+ * @param string $type the type (element name) of the wrapper
5750
+ * @param array $parameters the parameter values for the SOAP call
5751
+ * @return boolean whether they parameters are unwrapped (and should be wrapped)
5752
+ * @access private
5753
+ */
5754
+ function parametersMatchWrapped($type, &$parameters)
5755
+ {
5756
+ $this->debug("in parametersMatchWrapped type=$type, parameters=");
5757
+ $this->appendDebug($this->varDump($parameters));
5758
+
5759
+ // split type into namespace:unqualified-type
5760
+ if (strpos($type, ':')) {
5761
+ $uqType = substr($type, strrpos($type, ':') + 1);
5762
+ $ns = substr($type, 0, strrpos($type, ':'));
5763
+ $this->debug("in parametersMatchWrapped: got a prefixed type: $uqType, $ns");
5764
+ if ($this->getNamespaceFromPrefix($ns)) {
5765
+ $ns = $this->getNamespaceFromPrefix($ns);
5766
+ $this->debug("in parametersMatchWrapped: expanded prefixed type: $uqType, $ns");
5767
+ }
5768
+ } else {
5769
+ // TODO: should the type be compared to types in XSD, and the namespace
5770
+ // set to XSD if the type matches?
5771
+ $this->debug("in parametersMatchWrapped: No namespace for type $type");
5772
+ $ns = '';
5773
+ $uqType = $type;
5774
+ }
5775
+
5776
+ // get the type information
5777
+ if (!$typeDef = $this->getTypeDef($uqType, $ns)) {
5778
+ $this->debug("in parametersMatchWrapped: $type ($uqType) is not a supported type.");
5779
+ return false;
5780
+ }
5781
+ $this->debug("in parametersMatchWrapped: found typeDef=");
5782
+ $this->appendDebug($this->varDump($typeDef));
5783
+ if (substr($uqType, -1) == '^') {
5784
+ $uqType = substr($uqType, 0, -1);
5785
+ }
5786
+ $phpType = $typeDef['phpType'];
5787
+ $arrayType = (isset($typeDef['arrayType']) ? $typeDef['arrayType'] : '');
5788
+ $this->debug("in parametersMatchWrapped: uqType: $uqType, ns: $ns, phptype: $phpType, arrayType: $arrayType");
5789
+
5790
+ // we expect a complexType or element of complexType
5791
+ if ($phpType != 'struct') {
5792
+ $this->debug("in parametersMatchWrapped: not a struct");
5793
+ return false;
5794
+ }
5795
+
5796
+ // see whether the parameter names match the elements
5797
+ if (isset($typeDef['elements']) && is_array($typeDef['elements'])) {
5798
+ $elements = 0;
5799
+ $matches = 0;
5800
+ foreach ($typeDef['elements'] as $name => $attrs) {
5801
+ if (isset($parameters[$name])) {
5802
+ $this->debug("in parametersMatchWrapped: have parameter named $name");
5803
+ $matches++;
5804
+ } else {
5805
+ $this->debug("in parametersMatchWrapped: do not have parameter named $name");
5806
+ }
5807
+ $elements++;
5808
+ }
5809
+
5810
+ $this->debug("in parametersMatchWrapped: $matches parameter names match $elements wrapped parameter names");
5811
+ if ($matches == 0) {
5812
+ return false;
5813
+ }
5814
+ return true;
5815
+ }
5816
+
5817
+ // since there are no elements for the type, if the user passed no
5818
+ // parameters, the parameters match wrapped.
5819
+ $this->debug("in parametersMatchWrapped: no elements type $ns:$uqType");
5820
+ return count($parameters) == 0;
5821
+ }
5822
+
5823
+ /**
5824
+ * serialize PHP values according to a WSDL message definition
5825
+ * contrary to the method name, this is not limited to RPC
5826
+ *
5827
+ * TODO
5828
+ * - multi-ref serialization
5829
+ * - validate PHP values against type definitions, return errors if invalid
5830
+ *
5831
+ * @param string $operation operation name
5832
+ * @param string $direction (input|output)
5833
+ * @param mixed $parameters parameter value(s)
5834
+ * @param string $bindingType (soap|soap12)
5835
+ * @return mixed parameters serialized as XML or false on error (e.g. operation not found)
5836
+ * @access public
5837
+ */
5838
+ function serializeRPCParameters($operation, $direction, $parameters, $bindingType = 'soap')
5839
+ {
5840
+ $this->debug("in serializeRPCParameters: operation=$operation, direction=$direction, XMLSchemaVersion=$this->XMLSchemaVersion, bindingType=$bindingType");
5841
+ $this->appendDebug('parameters=' . $this->varDump($parameters));
5842
+
5843
+ if ($direction != 'input' && $direction != 'output') {
5844
+ $this->debug('The value of the \$direction argument needs to be either "input" or "output"');
5845
+ $this->setError('The value of the \$direction argument needs to be either "input" or "output"');
5846
+ return false;
5847
+ }
5848
+ if (!$opData = $this->getOperationData($operation, $bindingType)) {
5849
+ $this->debug('Unable to retrieve WSDL data for operation: ' . $operation . ' bindingType: ' . $bindingType);
5850
+ $this->setError('Unable to retrieve WSDL data for operation: ' . $operation . ' bindingType: ' . $bindingType);
5851
+ return false;
5852
+ }
5853
+ $this->debug('in serializeRPCParameters: opData:');
5854
+ $this->appendDebug($this->varDump($opData));
5855
+
5856
+ // Get encoding style for output and set to current
5857
+ $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
5858
+ if (($direction == 'input') && isset($opData['output']['encodingStyle']) && ($opData['output']['encodingStyle'] != $encodingStyle)) {
5859
+ $encodingStyle = $opData['output']['encodingStyle'];
5860
+ $enc_style = $encodingStyle;
5861
+ }
5862
+
5863
+ // set input params
5864
+ $xml = '';
5865
+ if (isset($opData[$direction]['parts']) && sizeof($opData[$direction]['parts']) > 0) {
5866
+ $parts = &$opData[$direction]['parts'];
5867
+ $part_count = sizeof($parts);
5868
+ $style = $opData['style'];
5869
+ $use = $opData[$direction]['use'];
5870
+ $this->debug("have $part_count part(s) to serialize using $style/$use");
5871
+ if (is_array($parameters)) {
5872
+ $parametersArrayType = $this->isArraySimpleOrStruct($parameters);
5873
+ $parameter_count = count($parameters);
5874
+ $this->debug("have $parameter_count parameter(s) provided as $parametersArrayType to serialize");
5875
+ // check for Microsoft-style wrapped parameters
5876
+ if ($style == 'document' && $use == 'literal' && $part_count == 1 && isset($parts['parameters'])) {
5877
+ $this->debug('check whether the caller has wrapped the parameters');
5878
+ if ($direction == 'output' && $parametersArrayType == 'arraySimple' && $parameter_count == 1) {
5879
+ // TODO: consider checking here for double-wrapping, when
5880
+ // service function wraps, then NuSOAP wraps again
5881
+ $this->debug("change simple array to associative with 'parameters' element");
5882
+ $parameters['parameters'] = $parameters[0];
5883
+ unset($parameters[0]);
5884
+ }
5885
+ if (($parametersArrayType == 'arrayStruct' || $parameter_count == 0) && !isset($parameters['parameters'])) {
5886
+ $this->debug('check whether caller\'s parameters match the wrapped ones');
5887
+ if ($this->parametersMatchWrapped($parts['parameters'], $parameters)) {
5888
+ $this->debug('wrap the parameters for the caller');
5889
+ $parameters = array('parameters' => $parameters);
5890
+ $parameter_count = 1;
5891
+ }
5892
+ }
5893
+ }
5894
+ foreach ($parts as $name => $type) {
5895
+ $this->debug("serializing part $name of type $type");
5896
+ // Track encoding style
5897
+ if (isset($opData[$direction]['encodingStyle']) && $encodingStyle != $opData[$direction]['encodingStyle']) {
5898
+ $encodingStyle = $opData[$direction]['encodingStyle'];
5899
+ $enc_style = $encodingStyle;
5900
+ } else {
5901
+ $enc_style = false;
5902
+ }
5903
+ // NOTE: add error handling here
5904
+ // if serializeType returns false, then catch global error and fault
5905
+ if ($parametersArrayType == 'arraySimple') {
5906
+ $p = array_shift($parameters);
5907
+ $this->debug('calling serializeType w/indexed param');
5908
+ $xml .= $this->serializeType($name, $type, $p, $use, $enc_style);
5909
+ } elseif (isset($parameters[$name])) {
5910
+ $this->debug('calling serializeType w/named param');
5911
+ $xml .= $this->serializeType($name, $type, $parameters[$name], $use, $enc_style);
5912
+ } else {
5913
+ // TODO: only send nillable
5914
+ $this->debug('calling serializeType w/null param');
5915
+ $xml .= $this->serializeType($name, $type, null, $use, $enc_style);
5916
+ }
5917
+ }
5918
+ } else {
5919
+ $this->debug('no parameters passed.');
5920
+ }
5921
+ }
5922
+ $this->debug("serializeRPCParameters returning: $xml");
5923
+ return $xml;
5924
+ }
5925
+
5926
+ /**
5927
+ * serialize a PHP value according to a WSDL message definition
5928
+ *
5929
+ * TODO
5930
+ * - multi-ref serialization
5931
+ * - validate PHP values against type definitions, return errors if invalid
5932
+ *
5933
+ * @param string $operation operation name
5934
+ * @param string $direction (input|output)
5935
+ * @param mixed $parameters parameter value(s)
5936
+ * @return mixed parameters serialized as XML or false on error (e.g. operation not found)
5937
+ * @access public
5938
+ * @deprecated
5939
+ */
5940
+ function serializeParameters($operation, $direction, $parameters)
5941
+ {
5942
+ $this->debug("in serializeParameters: operation=$operation, direction=$direction, XMLSchemaVersion=$this->XMLSchemaVersion");
5943
+ $this->appendDebug('parameters=' . $this->varDump($parameters));
5944
+
5945
+ if ($direction != 'input' && $direction != 'output') {
5946
+ $this->debug('The value of the \$direction argument needs to be either "input" or "output"');
5947
+ $this->setError('The value of the \$direction argument needs to be either "input" or "output"');
5948
+ return false;
5949
+ }
5950
+ if (!$opData = $this->getOperationData($operation)) {
5951
+ $this->debug('Unable to retrieve WSDL data for operation: ' . $operation);
5952
+ $this->setError('Unable to retrieve WSDL data for operation: ' . $operation);
5953
+ return false;
5954
+ }
5955
+ $this->debug('opData:');
5956
+ $this->appendDebug($this->varDump($opData));
5957
+
5958
+ // Get encoding style for output and set to current
5959
+ $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
5960
+ if (($direction == 'input') && isset($opData['output']['encodingStyle']) && ($opData['output']['encodingStyle'] != $encodingStyle)) {
5961
+ $encodingStyle = $opData['output']['encodingStyle'];
5962
+ $enc_style = $encodingStyle;
5963
+ }
5964
+
5965
+ // set input params
5966
+ $xml = '';
5967
+ if (isset($opData[$direction]['parts']) && sizeof($opData[$direction]['parts']) > 0) {
5968
+
5969
+ $use = $opData[$direction]['use'];
5970
+ $this->debug("use=$use");
5971
+ $this->debug('got ' . count($opData[$direction]['parts']) . ' part(s)');
5972
+ if (is_array($parameters)) {
5973
+ $parametersArrayType = $this->isArraySimpleOrStruct($parameters);
5974
+ $this->debug('have ' . $parametersArrayType . ' parameters');
5975
+ foreach ($opData[$direction]['parts'] as $name => $type) {
5976
+ $this->debug('serializing part "' . $name . '" of type "' . $type . '"');
5977
+ // Track encoding style
5978
+ if (isset($opData[$direction]['encodingStyle']) && $encodingStyle != $opData[$direction]['encodingStyle']) {
5979
+ $encodingStyle = $opData[$direction]['encodingStyle'];
5980
+ $enc_style = $encodingStyle;
5981
+ } else {
5982
+ $enc_style = false;
5983
+ }
5984
+ // NOTE: add error handling here
5985
+ // if serializeType returns false, then catch global error and fault
5986
+ if ($parametersArrayType == 'arraySimple') {
5987
+ $p = array_shift($parameters);
5988
+ $this->debug('calling serializeType w/indexed param');
5989
+ $xml .= $this->serializeType($name, $type, $p, $use, $enc_style);
5990
+ } elseif (isset($parameters[$name])) {
5991
+ $this->debug('calling serializeType w/named param');
5992
+ $xml .= $this->serializeType($name, $type, $parameters[$name], $use, $enc_style);
5993
+ } else {
5994
+ // TODO: only send nillable
5995
+ $this->debug('calling serializeType w/null param');
5996
+ $xml .= $this->serializeType($name, $type, null, $use, $enc_style);
5997
+ }
5998
+ }
5999
+ } else {
6000
+ $this->debug('no parameters passed.');
6001
+ }
6002
+ }
6003
+ $this->debug("serializeParameters returning: $xml");
6004
+ return $xml;
6005
+ }
6006
+
6007
+ /**
6008
+ * serializes a PHP value according a given type definition
6009
+ *
6010
+ * @param string $name name of value (part or element)
6011
+ * @param string $type XML schema type of value (type or element)
6012
+ * @param mixed $value a native PHP value (parameter value)
6013
+ * @param string $use use for part (encoded|literal)
6014
+ * @param string $encodingStyle SOAP encoding style for the value (if different than the enclosing style)
6015
+ * @param boolean $unqualified a kludge for what should be XML namespace form handling
6016
+ * @return string value serialized as an XML string
6017
+ * @access private
6018
+ */
6019
+ function serializeType($name, $type, $value, $use = 'encoded', $encodingStyle = false, $unqualified = false)
6020
+ {
6021
+ $this->debug("in serializeType: name=$name, type=$type, use=$use, encodingStyle=$encodingStyle, unqualified=" . ($unqualified ? "unqualified" : "qualified"));
6022
+ $this->appendDebug("value=" . $this->varDump($value));
6023
+ if ($use == 'encoded' && $encodingStyle) {
6024
+ $encodingStyle = ' SOAP-ENV:encodingStyle="' . $encodingStyle . '"';
6025
+ }
6026
+
6027
+ // if a soapval has been supplied, let its type override the WSDL
6028
+ if (is_object($value) && get_class($value) == 'soapval') {
6029
+ if ($value->type_ns) {
6030
+ $type = $value->type_ns . ':' . $value->type;
6031
+ $forceType = true;
6032
+ $this->debug("in serializeType: soapval overrides type to $type");
6033
+ } elseif ($value->type) {
6034
+ $type = $value->type;
6035
+ $forceType = true;
6036
+ $this->debug("in serializeType: soapval overrides type to $type");
6037
+ } else {
6038
+ $forceType = false;
6039
+ $this->debug("in serializeType: soapval does not override type");
6040
+ }
6041
+ $attrs = $value->attributes;
6042
+ $value = $value->value;
6043
+ $this->debug("in serializeType: soapval overrides value to $value");
6044
+ if ($attrs) {
6045
+ if (!is_array($value)) {
6046
+ $value['!'] = $value;
6047
+ }
6048
+ foreach ($attrs as $n => $v) {
6049
+ $value['!' . $n] = $v;
6050
+ }
6051
+ $this->debug("in serializeType: soapval provides attributes");
6052
+ }
6053
+ } else {
6054
+ $forceType = false;
6055
+ }
6056
+
6057
+ $xml = '';
6058
+ if (strpos($type, ':')) {
6059
+ $uqType = substr($type, strrpos($type, ':') + 1);
6060
+ $ns = substr($type, 0, strrpos($type, ':'));
6061
+ $this->debug("in serializeType: got a prefixed type: $uqType, $ns");
6062
+ if ($this->getNamespaceFromPrefix($ns)) {
6063
+ $ns = $this->getNamespaceFromPrefix($ns);
6064
+ $this->debug("in serializeType: expanded prefixed type: $uqType, $ns");
6065
+ }
6066
+
6067
+ if ($ns == $this->XMLSchemaVersion || $ns == 'http://schemas.xmlsoap.org/soap/encoding/') {
6068
+ $this->debug('in serializeType: type namespace indicates XML Schema or SOAP Encoding type');
6069
+ if ($unqualified && $use == 'literal') {
6070
+ $elementNS = " xmlns=\"\"";
6071
+ } else {
6072
+ $elementNS = '';
6073
+ }
6074
+ if (is_null($value)) {
6075
+ if ($use == 'literal') {
6076
+ // TODO: depends on minOccurs
6077
+ $xml = "<$name$elementNS/>";
6078
+ } else {
6079
+ // TODO: depends on nillable, which should be checked before calling this method
6080
+ $xml = "<$name$elementNS xsi:nil=\"true\" xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"/>";
6081
+ }
6082
+ $this->debug("in serializeType: returning: $xml");
6083
+ return $xml;
6084
+ }
6085
+ if ($uqType == 'Array') {
6086
+ // JBoss/Axis does this sometimes
6087
+ return $this->serialize_val($value, $name, false, false, false, false, $use);
6088
+ }
6089
+ if ($uqType == 'boolean') {
6090
+ if ((is_string($value) && $value == 'false') || (!$value)) {
6091
+ $value = 'false';
6092
+ } else {
6093
+ $value = 'true';
6094
+ }
6095
+ }
6096
+ if ($uqType == 'string' && gettype($value) == 'string') {
6097
+ $value = $this->expandEntities($value);
6098
+ }
6099
+ if (($uqType == 'long' || $uqType == 'unsignedLong') && gettype($value) == 'double') {
6100
+ $value = sprintf("%.0lf", $value);
6101
+ }
6102
+ // it's a scalar
6103
+ // TODO: what about null/nil values?
6104
+ // check type isn't a custom type extending xmlschema namespace
6105
+ if (!$this->getTypeDef($uqType, $ns)) {
6106
+ if ($use == 'literal') {
6107
+ if ($forceType) {
6108
+ $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">$value</$name>";
6109
+ } else {
6110
+ $xml = "<$name$elementNS>$value</$name>";
6111
+ }
6112
+ } else {
6113
+ $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>$value</$name>";
6114
+ }
6115
+ $this->debug("in serializeType: returning: $xml");
6116
+ return $xml;
6117
+ }
6118
+ $this->debug('custom type extends XML Schema or SOAP Encoding namespace (yuck)');
6119
+ } elseif ($ns == 'http://xml.apache.org/xml-soap') {
6120
+ $this->debug('in serializeType: appears to be Apache SOAP type');
6121
+ if ($uqType == 'Map') {
6122
+ $tt_prefix = $this->getPrefixFromNamespace('http://xml.apache.org/xml-soap');
6123
+ if (!$tt_prefix) {
6124
+ $this->debug('in serializeType: Add namespace for Apache SOAP type');
6125
+ $tt_prefix = 'ns' . rand(1000, 9999);
6126
+ $this->namespaces[$tt_prefix] = 'http://xml.apache.org/xml-soap';
6127
+ // force this to be added to usedNamespaces
6128
+ $tt_prefix = $this->getPrefixFromNamespace('http://xml.apache.org/xml-soap');
6129
+ }
6130
+ $contents = '';
6131
+ foreach ($value as $k => $v) {
6132
+ $this->debug("serializing map element: key $k, value $v");
6133
+ $contents .= '<item>';
6134
+ $contents .= $this->serialize_val($k, 'key', false, false, false, false, $use);
6135
+ $contents .= $this->serialize_val($v, 'value', false, false, false, false, $use);
6136
+ $contents .= '</item>';
6137
+ }
6138
+ if ($use == 'literal') {
6139
+ if ($forceType) {
6140
+ $xml = "<$name xsi:type=\"" . $tt_prefix . ":$uqType\">$contents</$name>";
6141
+ } else {
6142
+ $xml = "<$name>$contents</$name>";
6143
+ }
6144
+ } else {
6145
+ $xml = "<$name xsi:type=\"" . $tt_prefix . ":$uqType\"$encodingStyle>$contents</$name>";
6146
+ }
6147
+ $this->debug("in serializeType: returning: $xml");
6148
+ return $xml;
6149
+ }
6150
+ $this->debug('in serializeType: Apache SOAP type, but only support Map');
6151
+ }
6152
+ } else {
6153
+ // TODO: should the type be compared to types in XSD, and the namespace
6154
+ // set to XSD if the type matches?
6155
+ $this->debug("in serializeType: No namespace for type $type");
6156
+ $ns = '';
6157
+ $uqType = $type;
6158
+ }
6159
+ if (!$typeDef = $this->getTypeDef($uqType, $ns)) {
6160
+ $this->setError("$type ($uqType) is not a supported type.");
6161
+ $this->debug("in serializeType: $type ($uqType) is not a supported type.");
6162
+ return false;
6163
+ } else {
6164
+ $this->debug("in serializeType: found typeDef");
6165
+ $this->appendDebug('typeDef=' . $this->varDump($typeDef));
6166
+ if (substr($uqType, -1) == '^') {
6167
+ $uqType = substr($uqType, 0, -1);
6168
+ }
6169
+ }
6170
+ if (!isset($typeDef['phpType'])) {
6171
+ $this->setError("$type ($uqType) has no phpType.");
6172
+ $this->debug("in serializeType: $type ($uqType) has no phpType.");
6173
+ return false;
6174
+ }
6175
+ $phpType = $typeDef['phpType'];
6176
+ $this->debug("in serializeType: uqType: $uqType, ns: $ns, phptype: $phpType, arrayType: " . (isset($typeDef['arrayType']) ? $typeDef['arrayType'] : ''));
6177
+ // if php type == struct, map value to the <all> element names
6178
+ if ($phpType == 'struct') {
6179
+ if (isset($typeDef['typeClass']) && $typeDef['typeClass'] == 'element') {
6180
+ $elementName = $uqType;
6181
+ if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) {
6182
+ $elementNS = " xmlns=\"$ns\"";
6183
+ } else {
6184
+ $elementNS = " xmlns=\"\"";
6185
+ }
6186
+ } else {
6187
+ $elementName = $name;
6188
+ if ($unqualified) {
6189
+ $elementNS = " xmlns=\"\"";
6190
+ } else {
6191
+ $elementNS = '';
6192
+ }
6193
+ }
6194
+ if (is_null($value)) {
6195
+ if ($use == 'literal') {
6196
+ // TODO: depends on minOccurs and nillable
6197
+ $xml = "<$elementName$elementNS/>";
6198
+ } else {
6199
+ $xml = "<$elementName$elementNS xsi:nil=\"true\" xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"/>";
6200
+ }
6201
+ $this->debug("in serializeType: returning: $xml");
6202
+ return $xml;
6203
+ }
6204
+ if (is_object($value)) {
6205
+ $value = get_object_vars($value);
6206
+ }
6207
+ if (is_array($value)) {
6208
+ $elementAttrs = $this->serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType);
6209
+ if ($use == 'literal') {
6210
+ if ($forceType) {
6211
+ $xml = "<$elementName$elementNS$elementAttrs xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">";
6212
+ } else {
6213
+ $xml = "<$elementName$elementNS$elementAttrs>";
6214
+ }
6215
+ } else {
6216
+ $xml = "<$elementName$elementNS$elementAttrs xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>";
6217
+ }
6218
+
6219
+ if (isset($typeDef['simpleContent']) && $typeDef['simpleContent'] == 'true') {
6220
+ if (isset($value['!'])) {
6221
+ $xml .= $value['!'];
6222
+ $this->debug("in serializeType: serialized simpleContent for type $type");
6223
+ } else {
6224
+ $this->debug("in serializeType: no simpleContent to serialize for type $type");
6225
+ }
6226
+ } else {
6227
+ // complexContent
6228
+ $xml .= $this->serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use, $encodingStyle);
6229
+ }
6230
+ $xml .= "</$elementName>";
6231
+ } else {
6232
+ $this->debug("in serializeType: phpType is struct, but value is not an array");
6233
+ $this->setError("phpType is struct, but value is not an array: see debug output for details");
6234
+ $xml = '';
6235
+ }
6236
+ } elseif ($phpType == 'array') {
6237
+ if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) {
6238
+ $elementNS = " xmlns=\"$ns\"";
6239
+ } else {
6240
+ if ($unqualified) {
6241
+ $elementNS = " xmlns=\"\"";
6242
+ } else {
6243
+ $elementNS = '';
6244
+ }
6245
+ }
6246
+ if (is_null($value)) {
6247
+ if ($use == 'literal') {
6248
+ // TODO: depends on minOccurs
6249
+ $xml = "<$name$elementNS/>";
6250
+ } else {
6251
+ $xml = "<$name$elementNS xsi:nil=\"true\" xsi:type=\"" .
6252
+ $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/') .
6253
+ ":Array\" " .
6254
+ $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/') .
6255
+ ':arrayType="' .
6256
+ $this->getPrefixFromNamespace($this->getPrefix($typeDef['arrayType'])) .
6257
+ ':' .
6258
+ $this->getLocalPart($typeDef['arrayType']) . "[0]\"/>";
6259
+ }
6260
+ $this->debug("in serializeType: returning: $xml");
6261
+ return $xml;
6262
+ }
6263
+ if (isset($typeDef['multidimensional'])) {
6264
+ $nv = array();
6265
+ foreach ($value as $v) {
6266
+ $cols = ',' . sizeof($v);
6267
+ $nv = array_merge($nv, $v);
6268
+ }
6269
+ $value = $nv;
6270
+ } else {
6271
+ $cols = '';
6272
+ }
6273
+ if (is_array($value) && sizeof($value) >= 1) {
6274
+ $rows = sizeof($value);
6275
+ $contents = '';
6276
+ foreach ($value as $k => $v) {
6277
+ $this->debug("serializing array element: $k, " . (is_array($v) ? "array" : $v) . " of type: $typeDef[arrayType]");
6278
+ //if (strpos($typeDef['arrayType'], ':') ) {
6279
+ if (!in_array($typeDef['arrayType'], $this->typemap['http://www.w3.org/2001/XMLSchema'])) {
6280
+ $contents .= $this->serializeType('item', $typeDef['arrayType'], $v, $use);
6281
+ } else {
6282
+ $contents .= $this->serialize_val($v, 'item', $typeDef['arrayType'], null, $this->XMLSchemaVersion, false, $use);
6283
+ }
6284
+ }
6285
+ } else {
6286
+ $rows = 0;
6287
+ $contents = null;
6288
+ }
6289
+ // TODO: for now, an empty value will be serialized as a zero element
6290
+ // array. Revisit this when coding the handling of null/nil values.
6291
+ if ($use == 'literal') {
6292
+ $xml = "<$name$elementNS>"
6293
+ . $contents
6294
+ . "</$name>";
6295
+ } else {
6296
+ $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/') . ':Array" ' .
6297
+ $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/')
6298
+ . ':arrayType="'
6299
+ . $this->getPrefixFromNamespace($this->getPrefix($typeDef['arrayType']))
6300
+ . ":" . $this->getLocalPart($typeDef['arrayType']) . "[$rows$cols]\">"
6301
+ . $contents
6302
+ . "</$name>";
6303
+ }
6304
+ } elseif ($phpType == 'scalar') {
6305
+ if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) {
6306
+ $elementNS = " xmlns=\"$ns\"";
6307
+ } else {
6308
+ if ($unqualified) {
6309
+ $elementNS = " xmlns=\"\"";
6310
+ } else {
6311
+ $elementNS = '';
6312
+ }
6313
+ }
6314
+ if ($use == 'literal') {
6315
+ if ($forceType) {
6316
+ $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">$value</$name>";
6317
+ } else {
6318
+ $xml = "<$name$elementNS>$value</$name>";
6319
+ }
6320
+ } else {
6321
+ $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>$value</$name>";
6322
+ }
6323
+ }
6324
+ $this->debug("in serializeType: returning: $xml");
6325
+ return $xml;
6326
+ }
6327
+
6328
+ /**
6329
+ * serializes the attributes for a complexType
6330
+ *
6331
+ * @param array $typeDef our internal representation of an XML schema type (or element)
6332
+ * @param mixed $value a native PHP value (parameter value)
6333
+ * @param string $ns the namespace of the type
6334
+ * @param string $uqType the local part of the type
6335
+ * @return string value serialized as an XML string
6336
+ * @access private
6337
+ */
6338
+ function serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType)
6339
+ {
6340
+ $this->debug("serializeComplexTypeAttributes for XML Schema type $ns:$uqType");
6341
+ $xml = '';
6342
+ if (isset($typeDef['extensionBase'])) {
6343
+ $nsx = $this->getPrefix($typeDef['extensionBase']);
6344
+ $uqTypex = $this->getLocalPart($typeDef['extensionBase']);
6345
+ if ($this->getNamespaceFromPrefix($nsx)) {
6346
+ $nsx = $this->getNamespaceFromPrefix($nsx);
6347
+ }
6348
+ if ($typeDefx = $this->getTypeDef($uqTypex, $nsx)) {
6349
+ $this->debug("serialize attributes for extension base $nsx:$uqTypex");
6350
+ $xml .= $this->serializeComplexTypeAttributes($typeDefx, $value, $nsx, $uqTypex);
6351
+ } else {
6352
+ $this->debug("extension base $nsx:$uqTypex is not a supported type");
6353
+ }
6354
+ }
6355
+ if (isset($typeDef['attrs']) && is_array($typeDef['attrs'])) {
6356
+ $this->debug("serialize attributes for XML Schema type $ns:$uqType");
6357
+ if (is_array($value)) {
6358
+ $xvalue = $value;
6359
+ } elseif (is_object($value)) {
6360
+ $xvalue = get_object_vars($value);
6361
+ } else {
6362
+ $this->debug("value is neither an array nor an object for XML Schema type $ns:$uqType");
6363
+ $xvalue = array();
6364
+ }
6365
+ foreach ($typeDef['attrs'] as $aName => $attrs) {
6366
+ if (isset($xvalue['!' . $aName])) {
6367
+ $xname = '!' . $aName;
6368
+ $this->debug("value provided for attribute $aName with key $xname");
6369
+ } elseif (isset($xvalue[$aName])) {
6370
+ $xname = $aName;
6371
+ $this->debug("value provided for attribute $aName with key $xname");
6372
+ } elseif (isset($attrs['default'])) {
6373
+ $xname = '!' . $aName;
6374
+ $xvalue[$xname] = $attrs['default'];
6375
+ $this->debug('use default value of ' . $xvalue[$aName] . ' for attribute ' . $aName);
6376
+ } else {
6377
+ $xname = '';
6378
+ $this->debug("no value provided for attribute $aName");
6379
+ }
6380
+ if ($xname) {
6381
+ $xml .= " $aName=\"" . $this->expandEntities($xvalue[$xname]) . "\"";
6382
+ }
6383
+ }
6384
+ } else {
6385
+ $this->debug("no attributes to serialize for XML Schema type $ns:$uqType");
6386
+ }
6387
+ return $xml;
6388
+ }
6389
+
6390
+ /**
6391
+ * serializes the elements for a complexType
6392
+ *
6393
+ * @param array $typeDef our internal representation of an XML schema type (or element)
6394
+ * @param mixed $value a native PHP value (parameter value)
6395
+ * @param string $ns the namespace of the type
6396
+ * @param string $uqType the local part of the type
6397
+ * @param string $use use for part (encoded|literal)
6398
+ * @param string $encodingStyle SOAP encoding style for the value (if different than the enclosing style)
6399
+ * @return string value serialized as an XML string
6400
+ * @access private
6401
+ */
6402
+ function serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use = 'encoded', $encodingStyle = false)
6403
+ {
6404
+ $this->debug("in serializeComplexTypeElements for XML Schema type $ns:$uqType");
6405
+ $xml = '';
6406
+ if (isset($typeDef['extensionBase'])) {
6407
+ $nsx = $this->getPrefix($typeDef['extensionBase']);
6408
+ $uqTypex = $this->getLocalPart($typeDef['extensionBase']);
6409
+ if ($this->getNamespaceFromPrefix($nsx)) {
6410
+ $nsx = $this->getNamespaceFromPrefix($nsx);
6411
+ }
6412
+ if ($typeDefx = $this->getTypeDef($uqTypex, $nsx)) {
6413
+ $this->debug("serialize elements for extension base $nsx:$uqTypex");
6414
+ $xml .= $this->serializeComplexTypeElements($typeDefx, $value, $nsx, $uqTypex, $use, $encodingStyle);
6415
+ } else {
6416
+ $this->debug("extension base $nsx:$uqTypex is not a supported type");
6417
+ }
6418
+ }
6419
+ if (isset($typeDef['elements']) && is_array($typeDef['elements'])) {
6420
+ $this->debug("in serializeComplexTypeElements, serialize elements for XML Schema type $ns:$uqType");
6421
+ if (is_array($value)) {
6422
+ $xvalue = $value;
6423
+ } elseif (is_object($value)) {
6424
+ $xvalue = get_object_vars($value);
6425
+ } else {
6426
+ $this->debug("value is neither an array nor an object for XML Schema type $ns:$uqType");
6427
+ $xvalue = array();
6428
+ }
6429
+ // toggle whether all elements are present - ideally should validate against schema
6430
+ if (count($typeDef['elements']) != count($xvalue)) {
6431
+ $optionals = true;
6432
+ }
6433
+ foreach ($typeDef['elements'] as $eName => $attrs) {
6434
+ if (!isset($xvalue[$eName])) {
6435
+ if (isset($attrs['default'])) {
6436
+ $xvalue[$eName] = $attrs['default'];
6437
+ $this->debug('use default value of ' . $xvalue[$eName] . ' for element ' . $eName);
6438
+ }
6439
+ }
6440
+ // if user took advantage of a minOccurs=0, then only serialize named parameters
6441
+ if (isset($optionals)
6442
+ && (!isset($xvalue[$eName]))
6443
+ && ((!isset($attrs['nillable'])) || $attrs['nillable'] != 'true')
6444
+ ) {
6445
+ if (isset($attrs['minOccurs']) && $attrs['minOccurs'] <> '0') {
6446
+ $this->debug("apparent error: no value provided for element $eName with minOccurs=" . $attrs['minOccurs']);
6447
+ }
6448
+ // do nothing
6449
+ $this->debug("no value provided for complexType element $eName and element is not nillable, so serialize nothing");
6450
+ } else {
6451
+ // get value
6452
+ if (isset($xvalue[$eName])) {
6453
+ $v = $xvalue[$eName];
6454
+ } else {
6455
+ $v = null;
6456
+ }
6457
+ if (isset($attrs['form'])) {
6458
+ $unqualified = ($attrs['form'] == 'unqualified');
6459
+ } else {
6460
+ $unqualified = false;
6461
+ }
6462
+ if (isset($attrs['maxOccurs']) && ($attrs['maxOccurs'] == 'unbounded' || $attrs['maxOccurs'] > 1) && isset($v) && is_array($v) && $this->isArraySimpleOrStruct($v) == 'arraySimple') {
6463
+ $vv = $v;
6464
+ foreach ($vv as $k => $v) {
6465
+ if (isset($attrs['type']) || isset($attrs['ref'])) {
6466
+ // serialize schema-defined type
6467
+ $xml .= $this->serializeType($eName, isset($attrs['type']) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified);
6468
+ } else {
6469
+ // serialize generic type (can this ever really happen?)
6470
+ $this->debug("calling serialize_val() for $v, $eName, false, false, false, false, $use");
6471
+ $xml .= $this->serialize_val($v, $eName, false, false, false, false, $use);
6472
+ }
6473
+ }
6474
+ } else {
6475
+ if (is_null($v) && isset($attrs['minOccurs']) && $attrs['minOccurs'] == '0') {
6476
+ // do nothing
6477
+ } elseif (is_null($v) && isset($attrs['nillable']) && $attrs['nillable'] == 'true') {
6478
+ // TODO: serialize a nil correctly, but for now serialize schema-defined type
6479
+ $xml .= $this->serializeType($eName, isset($attrs['type']) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified);
6480
+ } elseif (isset($attrs['type']) || isset($attrs['ref'])) {
6481
+ // serialize schema-defined type
6482
+ $xml .= $this->serializeType($eName, isset($attrs['type']) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified);
6483
+ } else {
6484
+ // serialize generic type (can this ever really happen?)
6485
+ $this->debug("calling serialize_val() for $v, $eName, false, false, false, false, $use");
6486
+ $xml .= $this->serialize_val($v, $eName, false, false, false, false, $use);
6487
+ }
6488
+ }
6489
+ }
6490
+ }
6491
+ } else {
6492
+ $this->debug("no elements to serialize for XML Schema type $ns:$uqType");
6493
+ }
6494
+ return $xml;
6495
+ }
6496
+
6497
+ /**
6498
+ * adds an XML Schema complex type to the WSDL types
6499
+ *
6500
+ * @param string $name
6501
+ * @param string $typeClass (complexType|simpleType|attribute)
6502
+ * @param string $phpType currently supported are array and struct (php assoc array)
6503
+ * @param string $compositor (all|sequence|choice)
6504
+ * @param string $restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
6505
+ * @param array $elements e.g. array ( name => array(name=>'',type=>'') )
6506
+ * @param array $attrs e.g. array(array('ref'=>'SOAP-ENC:arrayType','wsdl:arrayType'=>'xsd:string[]'))
6507
+ * @param string $arrayType as namespace:name (xsd:string)
6508
+ * @see nusoap_xmlschema
6509
+ * @access public
6510
+ */
6511
+ function addComplexType($name, $typeClass = 'complexType', $phpType = 'array', $compositor = '', $restrictionBase = '', $elements = array(), $attrs = array(), $arrayType = '')
6512
+ {
6513
+ if (count($elements) > 0) {
6514
+ $eElements = array();
6515
+ foreach ($elements as $n => $e) {
6516
+ // expand each element
6517
+ $ee = array();
6518
+ foreach ($e as $k => $v) {
6519
+ $k = strpos($k, ':') ? $this->expandQname($k) : $k;
6520
+ $v = strpos($v, ':') ? $this->expandQname($v) : $v;
6521
+ $ee[$k] = $v;
6522
+ }
6523
+ $eElements[$n] = $ee;
6524
+ }
6525
+ $elements = $eElements;
6526
+ }
6527
+
6528
+ if (count($attrs) > 0) {
6529
+ foreach ($attrs as $n => $a) {
6530
+ // expand each attribute
6531
+ foreach ($a as $k => $v) {
6532
+ $k = strpos($k, ':') ? $this->expandQname($k) : $k;
6533
+ $v = strpos($v, ':') ? $this->expandQname($v) : $v;
6534
+ $aa[$k] = $v;
6535
+ }
6536
+ $eAttrs[$n] = $aa;
6537
+ }
6538
+ $attrs = $eAttrs;
6539
+ }
6540
+
6541
+ $restrictionBase = strpos($restrictionBase, ':') ? $this->expandQname($restrictionBase) : $restrictionBase;
6542
+ $arrayType = strpos($arrayType, ':') ? $this->expandQname($arrayType) : $arrayType;
6543
+
6544
+ $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns'];
6545
+ $this->schemas[$typens][0]->addComplexType($name, $typeClass, $phpType, $compositor, $restrictionBase, $elements, $attrs, $arrayType);
6546
+ }
6547
+
6548
+ /**
6549
+ * adds an XML Schema simple type to the WSDL types
6550
+ *
6551
+ * @param string $name
6552
+ * @param string $restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
6553
+ * @param string $typeClass (should always be simpleType)
6554
+ * @param string $phpType (should always be scalar)
6555
+ * @param array $enumeration array of values
6556
+ * @see nusoap_xmlschema
6557
+ * @access public
6558
+ */
6559
+ function addSimpleType($name, $restrictionBase = '', $typeClass = 'simpleType', $phpType = 'scalar', $enumeration = array())
6560
+ {
6561
+ $restrictionBase = strpos($restrictionBase, ':') ? $this->expandQname($restrictionBase) : $restrictionBase;
6562
+
6563
+ $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns'];
6564
+ $this->schemas[$typens][0]->addSimpleType($name, $restrictionBase, $typeClass, $phpType, $enumeration);
6565
+ }
6566
+
6567
+ /**
6568
+ * adds an element to the WSDL types
6569
+ *
6570
+ * @param array $attrs attributes that must include name and type
6571
+ * @see nusoap_xmlschema
6572
+ * @access public
6573
+ */
6574
+ function addElement($attrs)
6575
+ {
6576
+ $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns'];
6577
+ $this->schemas[$typens][0]->addElement($attrs);
6578
+ }
6579
+
6580
+ /**
6581
+ * register an operation with the server
6582
+ *
6583
+ * @param string $name operation (method) name
6584
+ * @param array $in assoc array of input values: key = param name, value = param type
6585
+ * @param array $out assoc array of output values: key = param name, value = param type
6586
+ * @param string $namespace optional The namespace for the operation
6587
+ * @param string $soapaction optional The soapaction for the operation
6588
+ * @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
6589
+ * @param string $use (encoded|literal) optional The use for the parameters (cannot mix right now)
6590
+ * @param string $documentation optional The description to include in the WSDL
6591
+ * @param string $encodingStyle optional (usually 'http://schemas.xmlsoap.org/soap/encoding/' for encoded)
6592
+ * @access public
6593
+ */
6594
+ function addOperation($name, $in = false, $out = false, $namespace = false, $soapaction = false, $style = 'rpc', $use = 'encoded', $documentation = '', $encodingStyle = '')
6595
+ {
6596
+ if ($use == 'encoded' && $encodingStyle == '') {
6597
+ $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
6598
+ }
6599
+
6600
+ if ($style == 'document') {
6601
+ $elements = array();
6602
+ foreach ($in as $n => $t) {
6603
+ $elements[$n] = array('name' => $n, 'type' => $t, 'form' => 'unqualified');
6604
+ }
6605
+ $this->addComplexType($name . 'RequestType', 'complexType', 'struct', 'all', '', $elements);
6606
+ $this->addElement(array('name' => $name, 'type' => $name . 'RequestType'));
6607
+ $in = array('parameters' => 'tns:' . $name . '^');
6608
+
6609
+ $elements = array();
6610
+ foreach ($out as $n => $t) {
6611
+ $elements[$n] = array('name' => $n, 'type' => $t, 'form' => 'unqualified');
6612
+ }
6613
+ $this->addComplexType($name . 'ResponseType', 'complexType', 'struct', 'all', '', $elements);
6614
+ $this->addElement(array('name' => $name . 'Response', 'type' => $name . 'ResponseType', 'form' => 'qualified'));
6615
+ $out = array('parameters' => 'tns:' . $name . 'Response' . '^');
6616
+ }
6617
+
6618
+ // get binding
6619
+ $this->bindings[$this->serviceName . 'Binding']['operations'][$name] =
6620
+ array(
6621
+ 'name' => $name,
6622
+ 'binding' => $this->serviceName . 'Binding',
6623
+ 'endpoint' => $this->endpoint,
6624
+ 'soapAction' => $soapaction,
6625
+ 'style' => $style,
6626
+ 'input' => array(
6627
+ 'use' => $use,
6628
+ 'namespace' => $namespace,
6629
+ 'encodingStyle' => $encodingStyle,
6630
+ 'message' => $name . 'Request',
6631
+ 'parts' => $in),
6632
+ 'output' => array(
6633
+ 'use' => $use,
6634
+ 'namespace' => $namespace,
6635
+ 'encodingStyle' => $encodingStyle,
6636
+ 'message' => $name . 'Response',
6637
+ 'parts' => $out),
6638
+ 'namespace' => $namespace,
6639
+ 'transport' => 'http://schemas.xmlsoap.org/soap/http',
6640
+ 'documentation' => $documentation);
6641
+ // add portTypes
6642
+ // add messages
6643
+ if ($in) {
6644
+ foreach ($in as $pName => $pType) {
6645
+ if (strpos($pType, ':')) {
6646
+ $pType = $this->getNamespaceFromPrefix($this->getPrefix($pType)) . ":" . $this->getLocalPart($pType);
6647
+ }
6648
+ $this->messages[$name . 'Request'][$pName] = $pType;
6649
+ }
6650
+ } else {
6651
+ $this->messages[$name . 'Request'] = '0';
6652
+ }
6653
+ if ($out) {
6654
+ foreach ($out as $pName => $pType) {
6655
+ if (strpos($pType, ':')) {
6656
+ $pType = $this->getNamespaceFromPrefix($this->getPrefix($pType)) . ":" . $this->getLocalPart($pType);
6657
+ }
6658
+ $this->messages[$name . 'Response'][$pName] = $pType;
6659
+ }
6660
+ } else {
6661
+ $this->messages[$name . 'Response'] = '0';
6662
+ }
6663
+ return true;
6664
+ }
6665
+ }
6666
+
6667
+
6668
+ /**
6669
+ *
6670
+ * nusoap_parser class parses SOAP XML messages into native PHP values
6671
+ *
6672
+ * @author Dietrich Ayala <dietrich@ganx4.com>
6673
+ * @author Scott Nichol <snichol@users.sourceforge.net>
6674
+ * @version $Id: nusoap.php,v 1.123 2010/04/26 20:15:08 snichol Exp $
6675
+ * @access public
6676
+ */
6677
+ class nusoap_parser extends nusoap_base
6678
+ {
6679
+
6680
+ var $xml = '';
6681
+ var $xml_encoding = '';
6682
+ var $method = '';
6683
+ var $root_struct = '';
6684
+ var $root_struct_name = '';
6685
+ var $root_struct_namespace = '';
6686
+ var $root_header = '';
6687
+ var $document = ''; // incoming SOAP body (text)
6688
+ // determines where in the message we are (envelope,header,body,method)
6689
+ var $status = '';
6690
+ var $position = 0;
6691
+ var $depth = 0;
6692
+ var $default_namespace = '';
6693
+ var $namespaces = array();
6694
+ var $message = array();
6695
+ var $parent = '';
6696
+ var $fault = false;
6697
+ var $fault_code = '';
6698
+ var $fault_str = '';
6699
+ var $fault_detail = '';
6700
+ var $depth_array = array();
6701
+ var $debug_flag = true;
6702
+ var $soapresponse = null; // parsed SOAP Body
6703
+ var $soapheader = null; // parsed SOAP Header
6704
+ var $responseHeaders = ''; // incoming SOAP headers (text)
6705
+ var $body_position = 0;
6706
+ // for multiref parsing:
6707
+ // array of id => pos
6708
+ var $ids = array();
6709
+ // array of id => hrefs => pos
6710
+ var $multirefs = array();
6711
+ // toggle for auto-decoding element content
6712
+ var $decode_utf8 = true;
6713
+
6714
+ /**
6715
+ * constructor that actually does the parsing
6716
+ *
6717
+ * @param string $xml SOAP message
6718
+ * @param string $encoding character encoding scheme of message
6719
+ * @param string $method method for which XML is parsed (unused?)
6720
+ * @param string $decode_utf8 whether to decode UTF-8 to ISO-8859-1
6721
+ * @access public
6722
+ */
6723
+ function __construct($xml, $encoding = 'UTF-8', $method = '', $decode_utf8 = true)
6724
+ {
6725
+ parent::__construct();
6726
+ $this->xml = $xml;
6727
+ $this->xml_encoding = $encoding;
6728
+ $this->method = $method;
6729
+ $this->decode_utf8 = $decode_utf8;
6730
+
6731
+ // Check whether content has been read.
6732
+ if (!empty($xml)) {
6733
+ // Check XML encoding
6734
+ $pos_xml = strpos($xml, '<?xml');
6735
+ if ($pos_xml !== false) {
6736
+ $xml_decl = substr($xml, $pos_xml, strpos($xml, '?>', $pos_xml + 2) - $pos_xml + 1);
6737
+ if (preg_match("/encoding=[\"']([^\"']*)[\"']/", $xml_decl, $res)) {
6738
+ $xml_encoding = $res[1];
6739
+ if (strtoupper($xml_encoding) != $encoding) {
6740
+ $err = "Charset from HTTP Content-Type '" . $encoding . "' does not match encoding from XML declaration '" . $xml_encoding . "'";
6741
+ $this->debug($err);
6742
+ if ($encoding != 'ISO-8859-1' || strtoupper($xml_encoding) != 'UTF-8') {
6743
+ $this->setError($err);
6744
+ return;
6745
+ }
6746
+ // when HTTP says ISO-8859-1 (the default) and XML says UTF-8 (the typical), assume the other endpoint is just sloppy and proceed
6747
+ } else {
6748
+ $this->debug('Charset from HTTP Content-Type matches encoding from XML declaration');
6749
+ }
6750
+ } else {
6751
+ $this->debug('No encoding specified in XML declaration');
6752
+ }
6753
+ } else {
6754
+ $this->debug('No XML declaration');
6755
+ }
6756
+ $this->debug('Entering nusoap_parser(), length=' . strlen($xml) . ', encoding=' . $encoding);
6757
+ // Create an XML parser - why not xml_parser_create_ns?
6758
+ $this->parser = xml_parser_create($this->xml_encoding);
6759
+ // Set the options for parsing the XML data.
6760
+ //xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
6761
+ xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
6762
+ xml_parser_set_option($this->parser, XML_OPTION_TARGET_ENCODING, $this->xml_encoding);
6763
+ // Set the object for the parser.
6764
+ xml_set_object($this->parser, $this);
6765
+ // Set the element handlers for the parser.
6766
+ xml_set_element_handler($this->parser, 'start_element', 'end_element');
6767
+ xml_set_character_data_handler($this->parser, 'character_data');
6768
+
6769
+ // Parse the XML file.
6770
+ if (!xml_parse($this->parser, $xml, true)) {
6771
+ // Display an error message.
6772
+ $err = sprintf('XML error parsing SOAP payload on line %d: %s',
6773
+ xml_get_current_line_number($this->parser),
6774
+ xml_error_string(xml_get_error_code($this->parser)));
6775
+ $this->debug($err);
6776
+ $this->debug("XML payload:\n" . $xml);
6777
+ $this->setError($err);
6778
+ } else {
6779
+ $this->debug('in nusoap_parser ctor, message:');
6780
+ $this->appendDebug($this->varDump($this->message));
6781
+ $this->debug('parsed successfully, found root struct: ' . $this->root_struct . ' of name ' . $this->root_struct_name);
6782
+ // get final value
6783
+ $this->soapresponse = $this->message[$this->root_struct]['result'];
6784
+ // get header value
6785
+ if ($this->root_header != '' && isset($this->message[$this->root_header]['result'])) {
6786
+ $this->soapheader = $this->message[$this->root_header]['result'];
6787
+ }
6788
+ // resolve hrefs/ids
6789
+ if (sizeof($this->multirefs) > 0) {
6790
+ foreach ($this->multirefs as $id => $hrefs) {
6791
+ $this->debug('resolving multirefs for id: ' . $id);
6792
+ $idVal = $this->buildVal($this->ids[$id]);
6793
+ if (is_array($idVal) && isset($idVal['!id'])) {
6794
+ unset($idVal['!id']);
6795
+ }
6796
+ foreach ($hrefs as $refPos => $ref) {
6797
+ $this->debug('resolving href at pos ' . $refPos);
6798
+ $this->multirefs[$id][$refPos] = $idVal;
6799
+ }
6800
+ }
6801
+ }
6802
+ }
6803
+ xml_parser_free($this->parser);
6804
+ unset($this->parser);
6805
+ } else {
6806
+ $this->debug('xml was empty, didn\'t parse!');
6807
+ $this->setError('xml was empty, didn\'t parse!');
6808
+ }
6809
+ }
6810
+
6811
+ /**
6812
+ * start-element handler
6813
+ *
6814
+ * @param resource $parser XML parser object
6815
+ * @param string $name element name
6816
+ * @param array $attrs associative array of attributes
6817
+ * @access private
6818
+ */
6819
+ function start_element($parser, $name, $attrs)
6820
+ {
6821
+ // position in a total number of elements, starting from 0
6822
+ // update class level pos
6823
+ $pos = $this->position++;
6824
+ // and set mine
6825
+ $this->message[$pos] = array('pos' => $pos, 'children' => '', 'cdata' => '');
6826
+ // depth = how many levels removed from root?
6827
+ // set mine as current global depth and increment global depth value
6828
+ $this->message[$pos]['depth'] = $this->depth++;
6829
+
6830
+ // else add self as child to whoever the current parent is
6831
+ if ($pos != 0) {
6832
+ $this->message[$this->parent]['children'] .= '|' . $pos;
6833
+ }
6834
+ // set my parent
6835
+ $this->message[$pos]['parent'] = $this->parent;
6836
+ // set self as current parent
6837
+ $this->parent = $pos;
6838
+ // set self as current value for this depth
6839
+ $this->depth_array[$this->depth] = $pos;
6840
+ // get element prefix
6841
+ if (strpos($name, ':')) {
6842
+ // get ns prefix
6843
+ $prefix = substr($name, 0, strpos($name, ':'));
6844
+ // get unqualified name
6845
+ $name = substr(strstr($name, ':'), 1);
6846
+ }
6847
+ // set status
6848
+ if ($name == 'Envelope' && $this->status == '') {
6849
+ $this->status = 'envelope';
6850
+ } elseif ($name == 'Header' && $this->status == 'envelope') {
6851
+ $this->root_header = $pos;
6852
+ $this->status = 'header';
6853
+ } elseif ($name == 'Body' && $this->status == 'envelope') {
6854
+ $this->status = 'body';
6855
+ $this->body_position = $pos;
6856
+ // set method
6857
+ } elseif ($this->status == 'body' && $pos == ($this->body_position + 1)) {
6858
+ $this->status = 'method';
6859
+ $this->root_struct_name = $name;
6860
+ $this->root_struct = $pos;
6861
+ $this->message[$pos]['type'] = 'struct';
6862
+ $this->debug("found root struct $this->root_struct_name, pos $this->root_struct");
6863
+ }
6864
+ // set my status
6865
+ $this->message[$pos]['status'] = $this->status;
6866
+ // set name
6867
+ $this->message[$pos]['name'] = htmlspecialchars($name);
6868
+ // set attrs
6869
+ $this->message[$pos]['attrs'] = $attrs;
6870
+
6871
+ // loop through atts, logging ns and type declarations
6872
+ $attstr = '';
6873
+ foreach ($attrs as $key => $value) {
6874
+ $key_prefix = $this->getPrefix($key);
6875
+ $key_localpart = $this->getLocalPart($key);
6876
+ // if ns declarations, add to class level array of valid namespaces
6877
+ if ($key_prefix == 'xmlns') {
6878
+ if (preg_match('/^http:\/\/www.w3.org\/[0-9]{4}\/XMLSchema$/', $value)) {
6879
+ $this->XMLSchemaVersion = $value;
6880
+ $this->namespaces['xsd'] = $this->XMLSchemaVersion;
6881
+ $this->namespaces['xsi'] = $this->XMLSchemaVersion . '-instance';
6882
+ }
6883
+ $this->namespaces[$key_localpart] = $value;
6884
+ // set method namespace
6885
+ if ($name == $this->root_struct_name) {
6886
+ $this->methodNamespace = $value;
6887
+ }
6888
+ // if it's a type declaration, set type
6889
+ } elseif ($key_localpart == 'type') {
6890
+ if (isset($this->message[$pos]['type']) && $this->message[$pos]['type'] == 'array') {
6891
+ // do nothing: already processed arrayType
6892
+ } else {
6893
+ $value_prefix = $this->getPrefix($value);
6894
+ $value_localpart = $this->getLocalPart($value);
6895
+ $this->message[$pos]['type'] = $value_localpart;
6896
+ $this->message[$pos]['typePrefix'] = $value_prefix;
6897
+ if (isset($this->namespaces[$value_prefix])) {
6898
+ $this->message[$pos]['type_namespace'] = $this->namespaces[$value_prefix];
6899
+ } elseif (isset($attrs['xmlns:' . $value_prefix])) {
6900
+ $this->message[$pos]['type_namespace'] = $attrs['xmlns:' . $value_prefix];
6901
+ }
6902
+ // should do something here with the namespace of specified type?
6903
+ }
6904
+ } elseif ($key_localpart == 'arrayType') {
6905
+ $this->message[$pos]['type'] = 'array';
6906
+ /* do arrayType ereg here
6907
+ [1] arrayTypeValue ::= atype asize
6908
+ [2] atype ::= QName rank*
6909
+ [3] rank ::= '[' (',')* ']'
6910
+ [4] asize ::= '[' length~ ']'
6911
+ [5] length ::= nextDimension* Digit+
6912
+ [6] nextDimension ::= Digit+ ','
6913
+ */
6914
+ $expr = '/([A-Za-z0-9_]+):([A-Za-z]+[A-Za-z0-9_]+)\[([0-9]+),?([0-9]*)\]/';
6915
+ if (preg_match($expr, $value, $regs)) {
6916
+ $this->message[$pos]['typePrefix'] = $regs[1];
6917
+ $this->message[$pos]['arrayTypePrefix'] = $regs[1];
6918
+ if (isset($this->namespaces[$regs[1]])) {
6919
+ $this->message[$pos]['arrayTypeNamespace'] = $this->namespaces[$regs[1]];
6920
+ } elseif (isset($attrs['xmlns:' . $regs[1]])) {
6921
+ $this->message[$pos]['arrayTypeNamespace'] = $attrs['xmlns:' . $regs[1]];
6922
+ }
6923
+ $this->message[$pos]['arrayType'] = $regs[2];
6924
+ $this->message[$pos]['arraySize'] = $regs[3];
6925
+ $this->message[$pos]['arrayCols'] = $regs[4];
6926
+ }
6927
+ // specifies nil value (or not)
6928
+ } elseif ($key_localpart == 'nil') {
6929
+ $this->message[$pos]['nil'] = ($value == 'true' || $value == '1');
6930
+ // some other attribute
6931
+ } elseif ($key != 'href' && $key != 'xmlns' && $key_localpart != 'encodingStyle' && $key_localpart != 'root') {
6932
+ $this->message[$pos]['xattrs']['!' . $key] = $value;
6933
+ }
6934
+
6935
+ if ($key == 'xmlns') {
6936
+ $this->default_namespace = $value;
6937
+ }
6938
+ // log id
6939
+ if ($key == 'id') {
6940
+ $this->ids[$value] = $pos;
6941
+ }
6942
+ // root
6943
+ if ($key_localpart == 'root' && $value == 1) {
6944
+ $this->status = 'method';
6945
+ $this->root_struct_name = $name;
6946
+ $this->root_struct = $pos;
6947
+ $this->debug("found root struct $this->root_struct_name, pos $pos");
6948
+ }
6949
+ // for doclit
6950
+ $attstr .= " $key=\"$value\"";
6951
+ }
6952
+ // get namespace - must be done after namespace atts are processed
6953
+ if (isset($prefix)) {
6954
+ $this->message[$pos]['namespace'] = $this->namespaces[$prefix];
6955
+ $this->default_namespace = $this->namespaces[$prefix];
6956
+ } else {
6957
+ $this->message[$pos]['namespace'] = $this->default_namespace;
6958
+ }
6959
+ if ($this->status == 'header') {
6960
+ if ($this->root_header != $pos) {
6961
+ $this->responseHeaders .= "<" . (isset($prefix) ? $prefix . ':' : '') . "$name$attstr>";
6962
+ }
6963
+ } elseif ($this->root_struct_name != '') {
6964
+ $this->document .= "<" . (isset($prefix) ? $prefix . ':' : '') . "$name$attstr>";
6965
+ }
6966
+ }
6967
+
6968
+ /**
6969
+ * end-element handler
6970
+ *
6971
+ * @param resource $parser XML parser object
6972
+ * @param string $name element name
6973
+ * @access private
6974
+ */
6975
+ function end_element($parser, $name)
6976
+ {
6977
+ // position of current element is equal to the last value left in depth_array for my depth
6978
+ $pos = $this->depth_array[$this->depth--];
6979
+
6980
+ // get element prefix
6981
+ if (strpos($name, ':')) {
6982
+ // get ns prefix
6983
+ $prefix = substr($name, 0, strpos($name, ':'));
6984
+ // get unqualified name
6985
+ $name = substr(strstr($name, ':'), 1);
6986
+ }
6987
+
6988
+ // build to native type
6989
+ if (isset($this->body_position) && $pos > $this->body_position) {
6990
+ // deal w/ multirefs
6991
+ if (isset($this->message[$pos]['attrs']['href'])) {
6992
+ // get id
6993
+ $id = substr($this->message[$pos]['attrs']['href'], 1);
6994
+ // add placeholder to href array
6995
+ $this->multirefs[$id][$pos] = 'placeholder';
6996
+ // add set a reference to it as the result value
6997
+ $this->message[$pos]['result'] =& $this->multirefs[$id][$pos];
6998
+ // build complexType values
6999
+ } elseif ($this->message[$pos]['children'] != '') {
7000
+ // if result has already been generated (struct/array)
7001
+ if (!isset($this->message[$pos]['result'])) {
7002
+ $this->message[$pos]['result'] = $this->buildVal($pos);
7003
+ }
7004
+ // build complexType values of attributes and possibly simpleContent
7005
+ } elseif (isset($this->message[$pos]['xattrs'])) {
7006
+ if (isset($this->message[$pos]['nil']) && $this->message[$pos]['nil']) {
7007
+ $this->message[$pos]['xattrs']['!'] = null;
7008
+ } elseif (isset($this->message[$pos]['cdata']) && trim($this->message[$pos]['cdata']) != '') {
7009
+ if (isset($this->message[$pos]['type'])) {
7010
+ $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'] : '');
7011
+ } else {
7012
+ $parent = $this->message[$pos]['parent'];
7013
+ if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
7014
+ $this->message[$pos]['xattrs']['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
7015
+ } else {
7016
+ $this->message[$pos]['xattrs']['!'] = $this->message[$pos]['cdata'];
7017
+ }
7018
+ }
7019
+ }
7020
+ $this->message[$pos]['result'] = $this->message[$pos]['xattrs'];
7021
+ // set value of simpleType (or nil complexType)
7022
+ } else {
7023
+ //$this->debug('adding data for scalar value '.$this->message[$pos]['name'].' of value '.$this->message[$pos]['cdata']);
7024
+ if (isset($this->message[$pos]['nil']) && $this->message[$pos]['nil']) {
7025
+ $this->message[$pos]['xattrs']['!'] = null;
7026
+ } elseif (isset($this->message[$pos]['type'])) {
7027
+ $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'] : '');
7028
+ } else {
7029
+ $parent = $this->message[$pos]['parent'];
7030
+ if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
7031
+ $this->message[$pos]['result'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
7032
+ } else {
7033
+ $this->message[$pos]['result'] = $this->message[$pos]['cdata'];
7034
+ }
7035
+ }
7036
+
7037
+ /* add value to parent's result, if parent is struct/array
7038
+ $parent = $this->message[$pos]['parent'];
7039
+ if($this->message[$parent]['type'] != 'map'){
7040
+ if(strtolower($this->message[$parent]['type']) == 'array'){
7041
+ $this->message[$parent]['result'][] = $this->message[$pos]['result'];
7042
+ } else {
7043
+ $this->message[$parent]['result'][$this->message[$pos]['name']] = $this->message[$pos]['result'];
7044
+ }
7045
+ }
7046
+ */
7047
+ }
7048
+ }
7049
+
7050
+ // for doclit
7051
+ if ($this->status == 'header') {
7052
+ if ($this->root_header != $pos) {
7053
+ $this->responseHeaders .= "</" . (isset($prefix) ? $prefix . ':' : '') . "$name>";
7054
+ }
7055
+ } elseif ($pos >= $this->root_struct) {
7056
+ $this->document .= "</" . (isset($prefix) ? $prefix . ':' : '') . "$name>";
7057
+ }
7058
+ // switch status
7059
+ if ($pos == $this->root_struct) {
7060
+ $this->status = 'body';
7061
+ $this->root_struct_namespace = $this->message[$pos]['namespace'];
7062
+ } elseif ($pos == $this->root_header) {
7063
+ $this->status = 'envelope';
7064
+ } elseif ($name == 'Body' && $this->status == 'body') {
7065
+ $this->status = 'envelope';
7066
+ } elseif ($name == 'Header' && $this->status == 'header') { // will never happen
7067
+ $this->status = 'envelope';
7068
+ } elseif ($name == 'Envelope' && $this->status == 'envelope') {
7069
+ $this->status = '';
7070
+ }
7071
+ // set parent back to my parent
7072
+ $this->parent = $this->message[$pos]['parent'];
7073
+ }
7074
+
7075
+ /**
7076
+ * element content handler
7077
+ *
7078
+ * @param resource $parser XML parser object
7079
+ * @param string $data element content
7080
+ * @access private
7081
+ */
7082
+ function character_data($parser, $data)
7083
+ {
7084
+ $pos = $this->depth_array[$this->depth];
7085
+ if ($this->xml_encoding == 'UTF-8') {
7086
+ // TODO: add an option to disable this for folks who want
7087
+ // raw UTF-8 that, e.g., might not map to iso-8859-1
7088
+ // TODO: this can also be handled with xml_parser_set_option($this->parser, XML_OPTION_TARGET_ENCODING, "ISO-8859-1");
7089
+ if ($this->decode_utf8) {
7090
+ $data = utf8_decode($data);
7091
+ }
7092
+ }
7093
+ $this->message[$pos]['cdata'] .= $data;
7094
+ // for doclit
7095
+ if ($this->status == 'header') {
7096
+ $this->responseHeaders .= $data;
7097
+ } else {
7098
+ $this->document .= $data;
7099
+ }
7100
+ }
7101
+
7102
+ /**
7103
+ * get the parsed message (SOAP Body)
7104
+ *
7105
+ * @return mixed
7106
+ * @access public
7107
+ * @deprecated use get_soapbody instead
7108
+ */
7109
+ function get_response()
7110
+ {
7111
+ return $this->soapresponse;
7112
+ }
7113
+
7114
+ /**
7115
+ * get the parsed SOAP Body (null if there was none)
7116
+ *
7117
+ * @return mixed
7118
+ * @access public
7119
+ */
7120
+ function get_soapbody()
7121
+ {
7122
+ return $this->soapresponse;
7123
+ }
7124
+
7125
+ /**
7126
+ * get the parsed SOAP Header (null if there was none)
7127
+ *
7128
+ * @return mixed
7129
+ * @access public
7130
+ */
7131
+ function get_soapheader()
7132
+ {
7133
+ return $this->soapheader;
7134
+ }
7135
+
7136
+ /**
7137
+ * get the unparsed SOAP Header
7138
+ *
7139
+ * @return string XML or empty if no Header
7140
+ * @access public
7141
+ */
7142
+ function getHeaders()
7143
+ {
7144
+ return $this->responseHeaders;
7145
+ }
7146
+
7147
+ /**
7148
+ * decodes simple types into PHP variables
7149
+ *
7150
+ * @param string $value value to decode
7151
+ * @param string $type XML type to decode
7152
+ * @param string $typens XML type namespace to decode
7153
+ * @return mixed PHP value
7154
+ * @access private
7155
+ */
7156
+ function decodeSimple($value, $type, $typens)
7157
+ {
7158
+ // TODO: use the namespace!
7159
+ if ((!isset($type)) || $type == 'string' || $type == 'long' || $type == 'unsignedLong') {
7160
+ return (string) $value;
7161
+ }
7162
+ if ($type == 'int' || $type == 'integer' || $type == 'short' || $type == 'byte') {
7163
+ return (int) $value;
7164
+ }
7165
+ if ($type == 'float' || $type == 'double' || $type == 'decimal') {
7166
+ return (double) $value;
7167
+ }
7168
+ if ($type == 'boolean') {
7169
+ if (strtolower($value) == 'false' || strtolower($value) == 'f') {
7170
+ return false;
7171
+ }
7172
+ return (boolean) $value;
7173
+ }
7174
+ if ($type == 'base64' || $type == 'base64Binary') {
7175
+ $this->debug('Decode base64 value');
7176
+ return base64_decode($value);
7177
+ }
7178
+ // obscure numeric types
7179
+ if ($type == 'nonPositiveInteger' || $type == 'negativeInteger'
7180
+ || $type == 'nonNegativeInteger' || $type == 'positiveInteger'
7181
+ || $type == 'unsignedInt'
7182
+ || $type == 'unsignedShort' || $type == 'unsignedByte'
7183
+ ) {
7184
+ return (int) $value;
7185
+ }
7186
+ // bogus: parser treats array with no elements as a simple type
7187
+ if ($type == 'array') {
7188
+ return array();
7189
+ }
7190
+ // everything else
7191
+ return (string) $value;
7192
+ }
7193
+
7194
+ /**
7195
+ * builds response structures for compound values (arrays/structs)
7196
+ * and scalars
7197
+ *
7198
+ * @param integer $pos position in node tree
7199
+ * @return mixed PHP value
7200
+ * @access private
7201
+ */
7202
+ function buildVal($pos)
7203
+ {
7204
+ if (!isset($this->message[$pos]['type'])) {
7205
+ $this->message[$pos]['type'] = '';
7206
+ }
7207
+ $this->debug('in buildVal() for ' . $this->message[$pos]['name'] . "(pos $pos) of type " . $this->message[$pos]['type']);
7208
+ // if there are children...
7209
+ if ($this->message[$pos]['children'] != '') {
7210
+ $this->debug('in buildVal, there are children');
7211
+ $children = explode('|', $this->message[$pos]['children']);
7212
+ array_shift($children); // knock off empty
7213
+ // md array
7214
+ if (isset($this->message[$pos]['arrayCols']) && $this->message[$pos]['arrayCols'] != '') {
7215
+ $r = 0; // rowcount
7216
+ $c = 0; // colcount
7217
+ foreach ($children as $child_pos) {
7218
+ $this->debug("in buildVal, got an MD array element: $r, $c");
7219
+ $params[$r][] = $this->message[$child_pos]['result'];
7220
+ $c++;
7221
+ if ($c == $this->message[$pos]['arrayCols']) {
7222
+ $c = 0;
7223
+ $r++;
7224
+ }
7225
+ }
7226
+ // array
7227
+ } elseif ($this->message[$pos]['type'] == 'array' || $this->message[$pos]['type'] == 'Array') {
7228
+ $this->debug('in buildVal, adding array ' . $this->message[$pos]['name']);
7229
+ foreach ($children as $child_pos) {
7230
+ $params[] = &$this->message[$child_pos]['result'];
7231
+ }
7232
+ // apache Map type: java hashtable
7233
+ } elseif ($this->message[$pos]['type'] == 'Map' && $this->message[$pos]['type_namespace'] == 'http://xml.apache.org/xml-soap') {
7234
+ $this->debug('in buildVal, Java Map ' . $this->message[$pos]['name']);
7235
+ foreach ($children as $child_pos) {
7236
+ $kv = explode("|", $this->message[$child_pos]['children']);
7237
+ $params[$this->message[$kv[1]]['result']] = &$this->message[$kv[2]]['result'];
7238
+ }
7239
+ // generic compound type
7240
+ //} elseif($this->message[$pos]['type'] == 'SOAPStruct' || $this->message[$pos]['type'] == 'struct') {
7241
+ } else {
7242
+ // Apache Vector type: treat as an array
7243
+ $this->debug('in buildVal, adding Java Vector or generic compound type ' . $this->message[$pos]['name']);
7244
+ if ($this->message[$pos]['type'] == 'Vector' && $this->message[$pos]['type_namespace'] == 'http://xml.apache.org/xml-soap') {
7245
+ $notstruct = 1;
7246
+ } else {
7247
+ $notstruct = 0;
7248
+ }
7249
+ //
7250
+ foreach ($children as $child_pos) {
7251
+ if ($notstruct) {
7252
+ $params[] = &$this->message[$child_pos]['result'];
7253
+ } else {
7254
+ if (isset($params[$this->message[$child_pos]['name']])) {
7255
+ // de-serialize repeated element name into an array
7256
+ if ((!is_array($params[$this->message[$child_pos]['name']])) || (!isset($params[$this->message[$child_pos]['name']][0]))) {
7257
+ $params[$this->message[$child_pos]['name']] = array($params[$this->message[$child_pos]['name']]);
7258
+ }
7259
+ $params[$this->message[$child_pos]['name']][] = &$this->message[$child_pos]['result'];
7260
+ } else {
7261
+ $params[$this->message[$child_pos]['name']] = &$this->message[$child_pos]['result'];
7262
+ }
7263
+ }
7264
+ }
7265
+ }
7266
+ if (isset($this->message[$pos]['xattrs'])) {
7267
+ $this->debug('in buildVal, handling attributes');
7268
+ foreach ($this->message[$pos]['xattrs'] as $n => $v) {
7269
+ $params[$n] = $v;
7270
+ }
7271
+ }
7272
+ // handle simpleContent
7273
+ if (isset($this->message[$pos]['cdata']) && trim($this->message[$pos]['cdata']) != '') {
7274
+ $this->debug('in buildVal, handling simpleContent');
7275
+ if (isset($this->message[$pos]['type'])) {
7276
+ $params['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$pos]['type'], isset($this->message[$pos]['type_namespace']) ? $this->message[$pos]['type_namespace'] : '');
7277
+ } else {
7278
+ $parent = $this->message[$pos]['parent'];
7279
+ if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
7280
+ $params['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
7281
+ } else {
7282
+ $params['!'] = $this->message[$pos]['cdata'];
7283
+ }
7284
+ }
7285
+ }
7286
+ $ret = is_array($params) ? $params : array();
7287
+ $this->debug('in buildVal, return:');
7288
+ $this->appendDebug($this->varDump($ret));
7289
+ return $ret;
7290
+ } else {
7291
+ $this->debug('in buildVal, no children, building scalar');
7292
+ $cdata = isset($this->message[$pos]['cdata']) ? $this->message[$pos]['cdata'] : '';
7293
+ if (isset($this->message[$pos]['type'])) {
7294
+ $ret = $this->decodeSimple($cdata, $this->message[$pos]['type'], isset($this->message[$pos]['type_namespace']) ? $this->message[$pos]['type_namespace'] : '');
7295
+ $this->debug("in buildVal, return: $ret");
7296
+ return $ret;
7297
+ }
7298
+ $parent = $this->message[$pos]['parent'];
7299
+ if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
7300
+ $ret = $this->decodeSimple($cdata, $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
7301
+ $this->debug("in buildVal, return: $ret");
7302
+ return $ret;
7303
+ }
7304
+ $ret = $this->message[$pos]['cdata'];
7305
+ $this->debug("in buildVal, return: $ret");
7306
+ return $ret;
7307
+ }
7308
+ }
7309
+ }
7310
+
7311
+
7312
+ /**
7313
+ * Backward compatibility
7314
+ */
7315
+ class soap_parser extends nusoap_parser
7316
+ {
7317
+ }
7318
+
7319
+
7320
+ /**
7321
+ *
7322
+ * [nu]soapclient higher level class for easy usage.
7323
+ *
7324
+ * usage:
7325
+ *
7326
+ * // instantiate client with server info
7327
+ * $soapclient = new nusoap_client( string path [ ,mixed wsdl] );
7328
+ *
7329
+ * // call method, get results
7330
+ * echo $soapclient->call( string methodname [ ,array parameters] );
7331
+ *
7332
+ * // bye bye client
7333
+ * unset($soapclient);
7334
+ *
7335
+ * @author Dietrich Ayala <dietrich@ganx4.com>
7336
+ * @author Scott Nichol <snichol@users.sourceforge.net>
7337
+ * @version $Id: nusoap.php,v 1.123 2010/04/26 20:15:08 snichol Exp $
7338
+ * @access public
7339
+ */
7340
+ class nusoap_client extends nusoap_base
7341
+ {
7342
+
7343
+ var $username = ''; // Username for HTTP authentication
7344
+ var $password = ''; // Password for HTTP authentication
7345
+ var $authtype = ''; // Type of HTTP authentication
7346
+ var $certRequest = array(); // Certificate for HTTP SSL authentication
7347
+ var $requestHeaders = false; // SOAP headers in request (text)
7348
+ var $responseHeaders = ''; // SOAP headers from response (incomplete namespace resolution) (text)
7349
+ var $responseHeader = null; // SOAP Header from response (parsed)
7350
+ var $document = ''; // SOAP body response portion (incomplete namespace resolution) (text)
7351
+ var $endpoint;
7352
+ var $forceEndpoint = ''; // overrides WSDL endpoint
7353
+ var $proxyhost = '';
7354
+ var $proxyport = '';
7355
+ var $proxyusername = '';
7356
+ var $proxypassword = '';
7357
+ var $portName = ''; // port name to use in WSDL
7358
+ var $xml_encoding = ''; // character set encoding of incoming (response) messages
7359
+ var $http_encoding = false;
7360
+ var $timeout = 0; // HTTP connection timeout
7361
+ var $response_timeout = 30; // HTTP response timeout
7362
+ var $endpointType = ''; // soap|wsdl, empty for WSDL initialization error
7363
+ var $persistentConnection = false;
7364
+ var $defaultRpcParams = false; // This is no longer used
7365
+ var $request = ''; // HTTP request
7366
+ var $response = ''; // HTTP response
7367
+ var $responseData = ''; // SOAP payload of response
7368
+ var $cookies = array(); // Cookies from response or for request
7369
+ var $decode_utf8 = true; // toggles whether the parser decodes element content w/ utf8_decode()
7370
+ var $operations = array(); // WSDL operations, empty for WSDL initialization error
7371
+ var $curl_options = array(); // User-specified cURL options
7372
+ var $bindingType = ''; // WSDL operation binding type
7373
+ var $use_curl = false; // whether to always try to use cURL
7374
+
7375
+ /*
7376
+ * fault related variables
7377
+ */
7378
+ /**
7379
+ * @var fault
7380
+ * @access public
7381
+ */
7382
+ var $fault;
7383
+ /**
7384
+ * @var faultcode
7385
+ * @access public
7386
+ */
7387
+ var $faultcode;
7388
+ /**
7389
+ * @var faultstring
7390
+ * @access public
7391
+ */
7392
+ var $faultstring;
7393
+ /**
7394
+ * @var faultdetail
7395
+ * @access public
7396
+ */
7397
+ var $faultdetail;
7398
+
7399
+ /**
7400
+ * constructor
7401
+ *
7402
+ * @param mixed $endpoint SOAP server or WSDL URL (string), or wsdl instance (object)
7403
+ * @param mixed $wsdl optional, set to 'wsdl' or true if using WSDL
7404
+ * @param string $proxyhost optional
7405
+ * @param string $proxyport optional
7406
+ * @param string $proxyusername optional
7407
+ * @param string $proxypassword optional
7408
+ * @param integer $timeout set the connection timeout
7409
+ * @param integer $response_timeout set the response timeout
7410
+ * @param string $portName optional portName in WSDL document
7411
+ * @access public
7412
+ */
7413
+ function __construct($endpoint, $wsdl = false, $proxyhost = false, $proxyport = false, $proxyusername = false, $proxypassword = false, $timeout = 0, $response_timeout = 30, $portName = '')
7414
+ {
7415
+ parent::__construct();
7416
+ $this->endpoint = $endpoint;
7417
+ $this->proxyhost = $proxyhost;
7418
+ $this->proxyport = $proxyport;
7419
+ $this->proxyusername = $proxyusername;
7420
+ $this->proxypassword = $proxypassword;
7421
+ $this->timeout = $timeout;
7422
+ $this->response_timeout = $response_timeout;
7423
+ $this->portName = $portName;
7424
+
7425
+ $this->debug("ctor wsdl=$wsdl timeout=$timeout response_timeout=$response_timeout");
7426
+ $this->appendDebug('endpoint=' . $this->varDump($endpoint));
7427
+
7428
+ // make values
7429
+ if ($wsdl) {
7430
+ if (is_object($endpoint) && (get_class($endpoint) == 'wsdl')) {
7431
+ $this->wsdl = $endpoint;
7432
+ $this->endpoint = $this->wsdl->wsdl;
7433
+ $this->wsdlFile = $this->endpoint;
7434
+ $this->debug('existing wsdl instance created from ' . $this->endpoint);
7435
+ $this->checkWSDL();
7436
+ } else {
7437
+ $this->wsdlFile = $this->endpoint;
7438
+ $this->wsdl = null;
7439
+ $this->debug('will use lazy evaluation of wsdl from ' . $this->endpoint);
7440
+ }
7441
+ $this->endpointType = 'wsdl';
7442
+ } else {
7443
+ $this->debug("instantiate SOAP with endpoint at $endpoint");
7444
+ $this->endpointType = 'soap';
7445
+ }
7446
+ }
7447
+
7448
+ /**
7449
+ * calls method, returns PHP native type
7450
+ *
7451
+ * @param string $operation SOAP server URL or path
7452
+ * @param mixed $params An array, associative or simple, of the parameters
7453
+ * for the method call, or a string that is the XML
7454
+ * for the call. For rpc style, this call will
7455
+ * wrap the XML in a tag named after the method, as
7456
+ * well as the SOAP Envelope and Body. For document
7457
+ * style, this will only wrap with the Envelope and Body.
7458
+ * IMPORTANT: when using an array with document style,
7459
+ * in which case there
7460
+ * is really one parameter, the root of the fragment
7461
+ * used in the call, which encloses what programmers
7462
+ * normally think of parameters. A parameter array
7463
+ * *must* include the wrapper.
7464
+ * @param string $namespace optional method namespace (WSDL can override)
7465
+ * @param string $soapAction optional SOAPAction value (WSDL can override)
7466
+ * @param mixed $headers optional string of XML with SOAP header content, or array of soapval objects for SOAP headers, or associative array
7467
+ * @param boolean $rpcParams optional (no longer used)
7468
+ * @param string $style optional (rpc|document) the style to use when serializing parameters (WSDL can override)
7469
+ * @param string $use optional (encoded|literal) the use when serializing parameters (WSDL can override)
7470
+ * @return mixed response from SOAP call, normally an associative array mirroring the structure of the XML response, false for certain fatal errors
7471
+ * @access public
7472
+ */
7473
+ function call($operation, $params = array(), $namespace = 'http://tempuri.org', $soapAction = '', $headers = false, $rpcParams = null, $style = 'rpc', $use = 'encoded')
7474
+ {
7475
+ $this->operation = $operation;
7476
+ $this->fault = false;
7477
+ $this->setError('');
7478
+ $this->request = '';
7479
+ $this->response = '';
7480
+ $this->responseData = '';
7481
+ $this->faultstring = '';
7482
+ $this->faultcode = '';
7483
+ $this->opData = array();
7484
+
7485
+ $this->debug("call: operation=$operation, namespace=$namespace, soapAction=$soapAction, rpcParams=$rpcParams, style=$style, use=$use, endpointType=$this->endpointType");
7486
+ $this->appendDebug('params=' . $this->varDump($params));
7487
+ $this->appendDebug('headers=' . $this->varDump($headers));
7488
+ if ($headers) {
7489
+ $this->requestHeaders = $headers;
7490
+ }
7491
+ if ($this->endpointType == 'wsdl' && is_null($this->wsdl)) {
7492
+ $this->loadWSDL();
7493
+ if ($this->getError()) {
7494
+ return false;
7495
+ }
7496
+ }
7497
+ // serialize parameters
7498
+ if ($this->endpointType == 'wsdl' && $opData = $this->getOperationData($operation)) {
7499
+ // use WSDL for operation
7500
+ $this->opData = $opData;
7501
+ $this->debug("found operation");
7502
+ $this->appendDebug('opData=' . $this->varDump($opData));
7503
+ if (isset($opData['soapAction'])) {
7504
+ $soapAction = $opData['soapAction'];
7505
+ }
7506
+ if (!$this->forceEndpoint) {
7507
+ $this->endpoint = $opData['endpoint'];
7508
+ } else {
7509
+ $this->endpoint = $this->forceEndpoint;
7510
+ }
7511
+ $namespace = isset($opData['input']['namespace']) ? $opData['input']['namespace'] : $namespace;
7512
+ $style = $opData['style'];
7513
+ $use = $opData['input']['use'];
7514
+ // add ns to ns array
7515
+ if ($namespace != '' && !isset($this->wsdl->namespaces[$namespace])) {
7516
+ $nsPrefix = 'ns' . rand(1000, 9999);
7517
+ $this->wsdl->namespaces[$nsPrefix] = $namespace;
7518
+ }
7519
+ $nsPrefix = $this->wsdl->getPrefixFromNamespace($namespace);
7520
+ // serialize payload
7521
+ if (is_string($params)) {
7522
+ $this->debug("serializing param string for WSDL operation $operation");
7523
+ $payload = $params;
7524
+ } elseif (is_array($params)) {
7525
+ $this->debug("serializing param array for WSDL operation $operation");
7526
+ $payload = $this->wsdl->serializeRPCParameters($operation, 'input', $params, $this->bindingType);
7527
+ } else {
7528
+ $this->debug('params must be array or string');
7529
+ $this->setError('params must be array or string');
7530
+ return false;
7531
+ }
7532
+ $usedNamespaces = $this->wsdl->usedNamespaces;
7533
+ if (isset($opData['input']['encodingStyle'])) {
7534
+ $encodingStyle = $opData['input']['encodingStyle'];
7535
+ } else {
7536
+ $encodingStyle = '';
7537
+ }
7538
+ $this->appendDebug($this->wsdl->getDebug());
7539
+ $this->wsdl->clearDebug();
7540
+ if ($errstr = $this->wsdl->getError()) {
7541
+ $this->debug('got wsdl error: ' . $errstr);
7542
+ $this->setError('wsdl error: ' . $errstr);
7543
+ return false;
7544
+ }
7545
+ } elseif ($this->endpointType == 'wsdl') {
7546
+ // operation not in WSDL
7547
+ $this->appendDebug($this->wsdl->getDebug());
7548
+ $this->wsdl->clearDebug();
7549
+ $this->setError('operation ' . $operation . ' not present in WSDL.');
7550
+ $this->debug("operation '$operation' not present in WSDL.");
7551
+ return false;
7552
+ } else {
7553
+ // no WSDL
7554
+ //$this->namespaces['ns1'] = $namespace;
7555
+ $nsPrefix = 'ns' . rand(1000, 9999);
7556
+ // serialize
7557
+ $payload = '';
7558
+ if (is_string($params)) {
7559
+ $this->debug("serializing param string for operation $operation");
7560
+ $payload = $params;
7561
+ } elseif (is_array($params)) {
7562
+ $this->debug("serializing param array for operation $operation");
7563
+ foreach ($params as $k => $v) {
7564
+ $payload .= $this->serialize_val($v, $k, false, false, false, false, $use);
7565
+ }
7566
+ } else {
7567
+ $this->debug('params must be array or string');
7568
+ $this->setError('params must be array or string');
7569
+ return false;
7570
+ }
7571
+ $usedNamespaces = array();
7572
+ if ($use == 'encoded') {
7573
+ $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
7574
+ } else {
7575
+ $encodingStyle = '';
7576
+ }
7577
+ }
7578
+ // wrap RPC calls with method element
7579
+ if ($style == 'rpc') {
7580
+ if ($use == 'literal') {
7581
+ $this->debug("wrapping RPC request with literal method element");
7582
+ if ($namespace) {
7583
+ // 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
7584
+ $payload = "<$nsPrefix:$operation xmlns:$nsPrefix=\"$namespace\">" .
7585
+ $payload .
7586
+ "</$nsPrefix:$operation>";
7587
+ } else {
7588
+ $payload = "<$operation>" . $payload . "</$operation>";
7589
+ }
7590
+ } else {
7591
+ $this->debug("wrapping RPC request with encoded method element");
7592
+ if ($namespace) {
7593
+ $payload = "<$nsPrefix:$operation xmlns:$nsPrefix=\"$namespace\">" .
7594
+ $payload .
7595
+ "</$nsPrefix:$operation>";
7596
+ } else {
7597
+ $payload = "<$operation>" .
7598
+ $payload .
7599
+ "</$operation>";
7600
+ }
7601
+ }
7602
+ }
7603
+ // serialize envelope
7604
+ $soapmsg = $this->serializeEnvelope($payload, $this->requestHeaders, $usedNamespaces, $style, $use, $encodingStyle);
7605
+ $this->debug("endpoint=$this->endpoint, soapAction=$soapAction, namespace=$namespace, style=$style, use=$use, encodingStyle=$encodingStyle");
7606
+ $this->debug('SOAP message length=' . strlen($soapmsg) . ' contents (max 1000 bytes)=' . substr($soapmsg, 0, 1000));
7607
+ // send
7608
+ $return = $this->send($this->getHTTPBody($soapmsg), $soapAction, $this->timeout, $this->response_timeout);
7609
+ if ($errstr = $this->getError()) {
7610
+ $this->debug('Error: ' . $errstr);
7611
+ return false;
7612
+ } else {
7613
+ $this->return = $return;
7614
+ $this->debug('sent message successfully and got a(n) ' . gettype($return));
7615
+ $this->appendDebug('return=' . $this->varDump($return));
7616
+
7617
+ // fault?
7618
+ if (is_array($return) && isset($return['faultcode'])) {
7619
+ $this->debug('got fault');
7620
+ $this->setError($return['faultcode'] . ': ' . $return['faultstring']);
7621
+ $this->fault = true;
7622
+ foreach ($return as $k => $v) {
7623
+ $this->$k = $v;
7624
+ if (is_array($v)) {
7625
+ $this->debug("$k = " . json_encode($v));
7626
+ } else {
7627
+ $this->debug("$k = $v<br>");
7628
+ }
7629
+ }
7630
+ return $return;
7631
+ } elseif ($style == 'document') {
7632
+ // NOTE: if the response is defined to have multiple parts (i.e. unwrapped),
7633
+ // we are only going to return the first part here...sorry about that
7634
+ return $return;
7635
+ } else {
7636
+ // array of return values
7637
+ if (is_array($return)) {
7638
+ // multiple 'out' parameters, which we return wrapped up
7639
+ // in the array
7640
+ if (sizeof($return) > 1) {
7641
+ return $return;
7642
+ }
7643
+ // single 'out' parameter (normally the return value)
7644
+ $return = array_shift($return);
7645
+ $this->debug('return shifted value: ');
7646
+ $this->appendDebug($this->varDump($return));
7647
+ return $return;
7648
+ // nothing returned (ie, echoVoid)
7649
+ } else {
7650
+ return "";
7651
+ }
7652
+ }
7653
+ }
7654
+ }
7655
+
7656
+ /**
7657
+ * check WSDL passed as an instance or pulled from an endpoint
7658
+ *
7659
+ * @access private
7660
+ */
7661
+ function checkWSDL()
7662
+ {
7663
+ $this->appendDebug($this->wsdl->getDebug());
7664
+ $this->wsdl->clearDebug();
7665
+ $this->debug('checkWSDL');
7666
+ // catch errors
7667
+ if ($errstr = $this->wsdl->getError()) {
7668
+ $this->appendDebug($this->wsdl->getDebug());
7669
+ $this->wsdl->clearDebug();
7670
+ $this->debug('got wsdl error: ' . $errstr);
7671
+ $this->setError('wsdl error: ' . $errstr);
7672
+ } elseif ($this->operations = $this->wsdl->getOperations($this->portName, 'soap')) {
7673
+ $this->appendDebug($this->wsdl->getDebug());
7674
+ $this->wsdl->clearDebug();
7675
+ $this->bindingType = 'soap';
7676
+ $this->debug('got ' . count($this->operations) . ' operations from wsdl ' . $this->wsdlFile . ' for binding type ' . $this->bindingType);
7677
+ } elseif ($this->operations = $this->wsdl->getOperations($this->portName, 'soap12')) {
7678
+ $this->appendDebug($this->wsdl->getDebug());
7679
+ $this->wsdl->clearDebug();
7680
+ $this->bindingType = 'soap12';
7681
+ $this->debug('got ' . count($this->operations) . ' operations from wsdl ' . $this->wsdlFile . ' for binding type ' . $this->bindingType);
7682
+ $this->debug('**************** WARNING: SOAP 1.2 BINDING *****************');
7683
+ } else {
7684
+ $this->appendDebug($this->wsdl->getDebug());
7685
+ $this->wsdl->clearDebug();
7686
+ $this->debug('getOperations returned false');
7687
+ $this->setError('no operations defined in the WSDL document!');
7688
+ }
7689
+ }
7690
+
7691
+ /**
7692
+ * instantiate wsdl object and parse wsdl file
7693
+ *
7694
+ * @access public
7695
+ */
7696
+ function loadWSDL()
7697
+ {
7698
+ $this->debug('instantiating wsdl class with doc: ' . $this->wsdlFile);
7699
+ $this->wsdl = new wsdl('', $this->proxyhost, $this->proxyport, $this->proxyusername, $this->proxypassword, $this->timeout, $this->response_timeout, $this->curl_options, $this->use_curl);
7700
+ $this->wsdl->setCredentials($this->username, $this->password, $this->authtype, $this->certRequest);
7701
+ $this->wsdl->fetchWSDL($this->wsdlFile);
7702
+ $this->checkWSDL();
7703
+ }
7704
+
7705
+ /**
7706
+ * get available data pertaining to an operation
7707
+ *
7708
+ * @param string $operation operation name
7709
+ * @return array array of data pertaining to the operation
7710
+ * @access public
7711
+ */
7712
+ function getOperationData($operation)
7713
+ {
7714
+ if ($this->endpointType == 'wsdl' && is_null($this->wsdl)) {
7715
+ $this->loadWSDL();
7716
+ if ($this->getError()) {
7717
+ return false;
7718
+ }
7719
+ }
7720
+ if (isset($this->operations[$operation])) {
7721
+ return $this->operations[$operation];
7722
+ }
7723
+ $this->debug("No data for operation: $operation");
7724
+ }
7725
+
7726
+ /**
7727
+ * send the SOAP message
7728
+ *
7729
+ * Note: if the operation has multiple return values
7730
+ * the return value of this method will be an array
7731
+ * of those values.
7732
+ *
7733
+ * @param string $msg a SOAPx4 soapmsg object
7734
+ * @param string $soapaction SOAPAction value
7735
+ * @param integer $timeout set connection timeout in seconds
7736
+ * @param integer $response_timeout set response timeout in seconds
7737
+ * @return mixed native PHP types.
7738
+ * @access private
7739
+ */
7740
+ function send($msg, $soapaction = '', $timeout = 0, $response_timeout = 30)
7741
+ {
7742
+ $this->checkCookies();
7743
+ // detect transport
7744
+ switch (true) {
7745
+ // http(s)
7746
+ case preg_match('/^http/', $this->endpoint):
7747
+ $this->debug('transporting via HTTP');
7748
+ if ($this->persistentConnection == true && is_object($this->persistentConnection)) {
7749
+ $http =& $this->persistentConnection;
7750
+ } else {
7751
+ $http = new soap_transport_http($this->endpoint, $this->curl_options, $this->use_curl);
7752
+ if ($this->persistentConnection) {
7753
+ $http->usePersistentConnection();
7754
+ }
7755
+ }
7756
+ $http->setContentType($this->getHTTPContentType(), $this->getHTTPContentTypeCharset());
7757
+ $http->setSOAPAction($soapaction);
7758
+ if ($this->proxyhost && $this->proxyport) {
7759
+ $http->setProxy($this->proxyhost, $this->proxyport, $this->proxyusername, $this->proxypassword);
7760
+ }
7761
+ if ($this->authtype != '') {
7762
+ $http->setCredentials($this->username, $this->password, $this->authtype, array(), $this->certRequest);
7763
+ }
7764
+ if ($this->http_encoding != '') {
7765
+ $http->setEncoding($this->http_encoding);
7766
+ }
7767
+ $this->debug('sending message, length=' . strlen($msg));
7768
+ if (preg_match('/^http:/', $this->endpoint)) {
7769
+ //if(strpos($this->endpoint,'http:')){
7770
+ $this->responseData = $http->send($msg, $timeout, $response_timeout, $this->cookies);
7771
+ } elseif (preg_match('/^https/', $this->endpoint)) {
7772
+ //} elseif(strpos($this->endpoint,'https:')){
7773
+ //if(phpversion() == '4.3.0-dev'){
7774
+ //$response = $http->send($msg,$timeout,$response_timeout);
7775
+ //$this->request = $http->outgoing_payload;
7776
+ //$this->response = $http->incoming_payload;
7777
+ //} else
7778
+ $this->responseData = $http->sendHTTPS($msg, $timeout, $response_timeout, $this->cookies);
7779
+ } else {
7780
+ $this->setError('no http/s in endpoint url');
7781
+ }
7782
+ $this->request = $http->outgoing_payload;
7783
+ $this->response = $http->incoming_payload;
7784
+ $this->appendDebug($http->getDebug());
7785
+ $this->UpdateCookies($http->incoming_cookies);
7786
+
7787
+ // save transport object if using persistent connections
7788
+ if ($this->persistentConnection) {
7789
+ $http->clearDebug();
7790
+ if (!is_object($this->persistentConnection)) {
7791
+ $this->persistentConnection = $http;
7792
+ }
7793
+ }
7794
+
7795
+ if ($err = $http->getError()) {
7796
+ $this->setError('HTTP Error: ' . $err);
7797
+ return false;
7798
+ } elseif ($this->getError()) {
7799
+ return false;
7800
+ } else {
7801
+ $this->debug('got response, length=' . strlen($this->responseData) . ' type=' . $http->incoming_headers['content-type']);
7802
+ return $this->parseResponse($http->incoming_headers, $this->responseData);
7803
+ }
7804
+ break;
7805
+ default:
7806
+ $this->setError('no transport found, or selected transport is not yet supported!');
7807
+ return false;
7808
+ break;
7809
+ }
7810
+ }
7811
+
7812
+ /**
7813
+ * processes SOAP message returned from server
7814
+ *
7815
+ * @param array $headers The HTTP headers
7816
+ * @param string $data unprocessed response data from server
7817
+ * @return mixed value of the message, decoded into a PHP type
7818
+ * @access private
7819
+ */
7820
+ function parseResponse($headers, $data)
7821
+ {
7822
+ $this->debug('Entering parseResponse() for data of length ' . strlen($data) . ' headers:');
7823
+ $this->appendDebug($this->varDump($headers));
7824
+ if (!isset($headers['content-type'])) {
7825
+ $this->setError('Response not of type text/xml (no content-type header)');
7826
+ return false;
7827
+ }
7828
+ if (!strstr($headers['content-type'], 'text/xml')) {
7829
+ $this->setError('Response not of type text/xml: ' . $headers['content-type']);
7830
+ return false;
7831
+ }
7832
+ if (strpos($headers['content-type'], '=')) {
7833
+ $enc = str_replace('"', '', substr(strstr($headers["content-type"], '='), 1));
7834
+ $this->debug('Got response encoding: ' . $enc);
7835
+ if (preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i', $enc)) {
7836
+ $this->xml_encoding = strtoupper($enc);
7837
+ } else {
7838
+ $this->xml_encoding = 'US-ASCII';
7839
+ }
7840
+ } else {
7841
+ // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
7842
+ $this->xml_encoding = 'ISO-8859-1';
7843
+ }
7844
+ $this->debug('Use encoding: ' . $this->xml_encoding . ' when creating nusoap_parser');
7845
+ $parser = new nusoap_parser($data, $this->xml_encoding, $this->operations, $this->decode_utf8);
7846
+ // add parser debug data to our debug
7847
+ $this->appendDebug($parser->getDebug());
7848
+ // if parse errors
7849
+ if ($errstr = $parser->getError()) {
7850
+ $this->setError($errstr);
7851
+ // destroy the parser object
7852
+ unset($parser);
7853
+ return false;
7854
+ } else {
7855
+ // get SOAP headers
7856
+ $this->responseHeaders = $parser->getHeaders();
7857
+ // get SOAP headers
7858
+ $this->responseHeader = $parser->get_soapheader();
7859
+ // get decoded message
7860
+ $return = $parser->get_soapbody();
7861
+ // add document for doclit support
7862
+ $this->document = $parser->document;
7863
+ // destroy the parser object
7864
+ unset($parser);
7865
+ // return decode message
7866
+ return $return;
7867
+ }
7868
+ }
7869
+
7870
+ /**
7871
+ * sets user-specified cURL options
7872
+ *
7873
+ * @param mixed $option The cURL option (always integer?)
7874
+ * @param mixed $value The cURL option value
7875
+ * @access public
7876
+ */
7877
+ function setCurlOption($option, $value)
7878
+ {
7879
+ $this->debug("setCurlOption option=$option, value=");
7880
+ $this->appendDebug($this->varDump($value));
7881
+ $this->curl_options[$option] = $value;
7882
+ }
7883
+
7884
+ /**
7885
+ * sets the SOAP endpoint, which can override WSDL
7886
+ *
7887
+ * @param string $endpoint The endpoint URL to use, or empty string or false to prevent override
7888
+ * @access public
7889
+ */
7890
+ function setEndpoint($endpoint)
7891
+ {
7892
+ $this->debug("setEndpoint(\"$endpoint\")");
7893
+ $this->forceEndpoint = $endpoint;
7894
+ }
7895
+
7896
+ /**
7897
+ * set the SOAP headers
7898
+ *
7899
+ * @param mixed $headers String of XML with SOAP header content, or array of soapval objects for SOAP headers
7900
+ * @access public
7901
+ */
7902
+ function setHeaders($headers)
7903
+ {
7904
+ $this->debug("setHeaders headers=");
7905
+ $this->appendDebug($this->varDump($headers));
7906
+ $this->requestHeaders = $headers;
7907
+ }
7908
+
7909
+ /**
7910
+ * get the SOAP response headers (namespace resolution incomplete)
7911
+ *
7912
+ * @return string
7913
+ * @access public
7914
+ */
7915
+ function getHeaders()
7916
+ {
7917
+ return $this->responseHeaders;
7918
+ }
7919
+
7920
+ /**
7921
+ * get the SOAP response Header (parsed)
7922
+ *
7923
+ * @return mixed
7924
+ * @access public
7925
+ */
7926
+ function getHeader()
7927
+ {
7928
+ return $this->responseHeader;
7929
+ }
7930
+
7931
+ /**
7932
+ * set proxy info here
7933
+ *
7934
+ * @param string $proxyhost
7935
+ * @param string $proxyport
7936
+ * @param string $proxyusername
7937
+ * @param string $proxypassword
7938
+ * @access public
7939
+ */
7940
+ function setHTTPProxy($proxyhost, $proxyport, $proxyusername = '', $proxypassword = '')
7941
+ {
7942
+ $this->proxyhost = $proxyhost;
7943
+ $this->proxyport = $proxyport;
7944
+ $this->proxyusername = $proxyusername;
7945
+ $this->proxypassword = $proxypassword;
7946
+ }
7947
+
7948
+ /**
7949
+ * if authenticating, set user credentials here
7950
+ *
7951
+ * @param string $username
7952
+ * @param string $password
7953
+ * @param string $authtype (basic|digest|certificate|ntlm)
7954
+ * @param array $certRequest (keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, verifypeer (optional), verifyhost (optional): see corresponding options in cURL docs)
7955
+ * @access public
7956
+ */
7957
+ function setCredentials($username, $password, $authtype = 'basic', $certRequest = array())
7958
+ {
7959
+ $this->debug("setCredentials username=$username authtype=$authtype certRequest=");
7960
+ $this->appendDebug($this->varDump($certRequest));
7961
+ $this->username = $username;
7962
+ $this->password = $password;
7963
+ $this->authtype = $authtype;
7964
+ $this->certRequest = $certRequest;
7965
+ }
7966
+
7967
+ /**
7968
+ * use HTTP encoding
7969
+ *
7970
+ * @param string $enc HTTP encoding
7971
+ * @access public
7972
+ */
7973
+ function setHTTPEncoding($enc = 'gzip, deflate')
7974
+ {
7975
+ $this->debug("setHTTPEncoding(\"$enc\")");
7976
+ $this->http_encoding = $enc;
7977
+ }
7978
+
7979
+ /**
7980
+ * Set whether to try to use cURL connections if possible
7981
+ *
7982
+ * @param boolean $use Whether to try to use cURL
7983
+ * @access public
7984
+ */
7985
+ function setUseCURL($use)
7986
+ {
7987
+ $this->debug("setUseCURL($use)");
7988
+ $this->use_curl = $use;
7989
+ }
7990
+
7991
+ /**
7992
+ * use HTTP persistent connections if possible
7993
+ *
7994
+ * @access public
7995
+ */
7996
+ function useHTTPPersistentConnection()
7997
+ {
7998
+ $this->debug("useHTTPPersistentConnection");
7999
+ $this->persistentConnection = true;
8000
+ }
8001
+
8002
+ /**
8003
+ * gets the default RPC parameter setting.
8004
+ * If true, default is that call params are like RPC even for document style.
8005
+ * Each call() can override this value.
8006
+ *
8007
+ * This is no longer used.
8008
+ *
8009
+ * @return boolean
8010
+ * @access public
8011
+ * @deprecated
8012
+ */
8013
+ function getDefaultRpcParams()
8014
+ {
8015
+ return $this->defaultRpcParams;
8016
+ }
8017
+
8018
+ /**
8019
+ * sets the default RPC parameter setting.
8020
+ * If true, default is that call params are like RPC even for document style
8021
+ * Each call() can override this value.
8022
+ *
8023
+ * This is no longer used.
8024
+ *
8025
+ * @param boolean $rpcParams
8026
+ * @access public
8027
+ * @deprecated
8028
+ */
8029
+ function setDefaultRpcParams($rpcParams)
8030
+ {
8031
+ $this->defaultRpcParams = $rpcParams;
8032
+ }
8033
+
8034
+ /**
8035
+ * dynamically creates an instance of a proxy class,
8036
+ * allowing user to directly call methods from wsdl
8037
+ *
8038
+ * @return object soap_proxy object
8039
+ * @access public
8040
+ */
8041
+ function getProxy()
8042
+ {
8043
+ $r = rand();
8044
+ $evalStr = $this->_getProxyClassCode($r);
8045
+ //$this->debug("proxy class: $evalStr");
8046
+ if ($this->getError()) {
8047
+ $this->debug("Error from _getProxyClassCode, so return null");
8048
+ return null;
8049
+ }
8050
+ // eval the class
8051
+ eval($evalStr);
8052
+ // instantiate proxy object
8053
+ eval("\$proxy = new nusoap_proxy_$r('');");
8054
+ // transfer current wsdl data to the proxy thereby avoiding parsing the wsdl twice
8055
+ $proxy->endpointType = 'wsdl';
8056
+ $proxy->wsdlFile = $this->wsdlFile;
8057
+ $proxy->wsdl = $this->wsdl;
8058
+ $proxy->operations = $this->operations;
8059
+ $proxy->defaultRpcParams = $this->defaultRpcParams;
8060
+ // transfer other state
8061
+ $proxy->soap_defencoding = $this->soap_defencoding;
8062
+ $proxy->username = $this->username;
8063
+ $proxy->password = $this->password;
8064
+ $proxy->authtype = $this->authtype;
8065
+ $proxy->certRequest = $this->certRequest;
8066
+ $proxy->requestHeaders = $this->requestHeaders;
8067
+ $proxy->endpoint = $this->endpoint;
8068
+ $proxy->forceEndpoint = $this->forceEndpoint;
8069
+ $proxy->proxyhost = $this->proxyhost;
8070
+ $proxy->proxyport = $this->proxyport;
8071
+ $proxy->proxyusername = $this->proxyusername;
8072
+ $proxy->proxypassword = $this->proxypassword;
8073
+ $proxy->http_encoding = $this->http_encoding;
8074
+ $proxy->timeout = $this->timeout;
8075
+ $proxy->response_timeout = $this->response_timeout;
8076
+ $proxy->persistentConnection = &$this->persistentConnection;
8077
+ $proxy->decode_utf8 = $this->decode_utf8;
8078
+ $proxy->curl_options = $this->curl_options;
8079
+ $proxy->bindingType = $this->bindingType;
8080
+ $proxy->use_curl = $this->use_curl;
8081
+ return $proxy;
8082
+ }
8083
+
8084
+ /**
8085
+ * dynamically creates proxy class code
8086
+ *
8087
+ * @return string PHP/NuSOAP code for the proxy class
8088
+ * @access private
8089
+ */
8090
+ function _getProxyClassCode($r)
8091
+ {
8092
+ $this->debug("in getProxy endpointType=$this->endpointType");
8093
+ $this->appendDebug("wsdl=" . $this->varDump($this->wsdl));
8094
+ if ($this->endpointType != 'wsdl') {
8095
+ $evalStr = 'A proxy can only be created for a WSDL client';
8096
+ $this->setError($evalStr);
8097
+ $evalStr = "echo \"$evalStr\";";
8098
+ return $evalStr;
8099
+ }
8100
+ if ($this->endpointType == 'wsdl' && is_null($this->wsdl)) {
8101
+ $this->loadWSDL();
8102
+ if ($this->getError()) {
8103
+ return "echo \"" . $this->getError() . "\";";
8104
+ }
8105
+ }
8106
+ $evalStr = '';
8107
+ foreach ($this->operations as $operation => $opData) {
8108
+ if ($operation != '') {
8109
+ // create param string and param comment string
8110
+ if (sizeof($opData['input']['parts']) > 0) {
8111
+ $paramStr = '';
8112
+ $paramArrayStr = '';
8113
+ $paramCommentStr = '';
8114
+ foreach ($opData['input']['parts'] as $name => $type) {
8115
+ $paramStr .= "\$$name, ";
8116
+ $paramArrayStr .= "'$name' => \$$name, ";
8117
+ $paramCommentStr .= "$type \$$name, ";
8118
+ }
8119
+ $paramStr = substr($paramStr, 0, strlen($paramStr) - 2);
8120
+ $paramArrayStr = substr($paramArrayStr, 0, strlen($paramArrayStr) - 2);
8121
+ $paramCommentStr = substr($paramCommentStr, 0, strlen($paramCommentStr) - 2);
8122
+ } else {
8123
+ $paramStr = '';
8124
+ $paramArrayStr = '';
8125
+ $paramCommentStr = 'void';
8126
+ }
8127
+ $opData['namespace'] = !isset($opData['namespace']) ? 'http://testuri.com' : $opData['namespace'];
8128
+ $evalStr .= "// $paramCommentStr
8129
+ function " . str_replace('.', '__', $operation) . "($paramStr) {
8130
+ \$params = array($paramArrayStr);
8131
+ return \$this->call('$operation', \$params, '" . $opData['namespace'] . "', '" . (isset($opData['soapAction']) ? $opData['soapAction'] : '') . "');
8132
+ }
8133
+ ";
8134
+ unset($paramStr);
8135
+ unset($paramCommentStr);
8136
+ }
8137
+ }
8138
+ $evalStr = 'class nusoap_proxy_' . $r . ' extends nusoap_client {
8139
+ ' . $evalStr . '
8140
+ }';
8141
+ return $evalStr;
8142
+ }
8143
+
8144
+ /**
8145
+ * dynamically creates proxy class code
8146
+ *
8147
+ * @return string PHP/NuSOAP code for the proxy class
8148
+ * @access public
8149
+ */
8150
+ function getProxyClassCode()
8151
+ {
8152
+ $r = rand();
8153
+ return $this->_getProxyClassCode($r);
8154
+ }
8155
+
8156
+ /**
8157
+ * gets the HTTP body for the current request.
8158
+ *
8159
+ * @param string $soapmsg The SOAP payload
8160
+ * @return string The HTTP body, which includes the SOAP payload
8161
+ * @access private
8162
+ */
8163
+ function getHTTPBody($soapmsg)
8164
+ {
8165
+ return $soapmsg;
8166
+ }
8167
+
8168
+ /**
8169
+ * gets the HTTP content type for the current request.
8170
+ *
8171
+ * Note: getHTTPBody must be called before this.
8172
+ *
8173
+ * @return string the HTTP content type for the current request.
8174
+ * @access private
8175
+ */
8176
+ function getHTTPContentType()
8177
+ {
8178
+ return 'text/xml';
8179
+ }
8180
+
8181
+ /**
8182
+ * gets the HTTP content type charset for the current request.
8183
+ * returns false for non-text content types.
8184
+ *
8185
+ * Note: getHTTPBody must be called before this.
8186
+ *
8187
+ * @return string the HTTP content type charset for the current request.
8188
+ * @access private
8189
+ */
8190
+ function getHTTPContentTypeCharset()
8191
+ {
8192
+ return $this->soap_defencoding;
8193
+ }
8194
+
8195
+ /*
8196
+ * whether or not parser should decode utf8 element content
8197
+ *
8198
+ * @return always returns true
8199
+ * @access public
8200
+ */
8201
+ function decodeUTF8($bool)
8202
+ {
8203
+ $this->decode_utf8 = $bool;
8204
+ return true;
8205
+ }
8206
+
8207
+ /**
8208
+ * adds a new Cookie into $this->cookies array
8209
+ *
8210
+ * @param string $name Cookie Name
8211
+ * @param string $value Cookie Value
8212
+ * @return boolean if cookie-set was successful returns true, else false
8213
+ * @access public
8214
+ */
8215
+ function setCookie($name, $value)
8216
+ {
8217
+ if (strlen($name) == 0) {
8218
+ return false;
8219
+ }
8220
+ $this->cookies[] = array('name' => $name, 'value' => $value);
8221
+ return true;
8222
+ }
8223
+
8224
+ /**
8225
+ * gets all Cookies
8226
+ *
8227
+ * @return array with all internal cookies
8228
+ * @access public
8229
+ */
8230
+ function getCookies()
8231
+ {
8232
+ return $this->cookies;
8233
+ }
8234
+
8235
+ /**
8236
+ * checks all Cookies and delete those which are expired
8237
+ *
8238
+ * @return boolean always return true
8239
+ * @access private
8240
+ */
8241
+ function checkCookies()
8242
+ {
8243
+ if (sizeof($this->cookies) == 0) {
8244
+ return true;
8245
+ }
8246
+ $this->debug('checkCookie: check ' . sizeof($this->cookies) . ' cookies');
8247
+ $curr_cookies = $this->cookies;
8248
+ $this->cookies = array();
8249
+ foreach ($curr_cookies as $cookie) {
8250
+ if (!is_array($cookie)) {
8251
+ $this->debug('Remove cookie that is not an array');
8252
+ continue;
8253
+ }
8254
+ if ((isset($cookie['expires'])) && (!empty($cookie['expires']))) {
8255
+ if (strtotime($cookie['expires']) > time()) {
8256
+ $this->cookies[] = $cookie;
8257
+ } else {
8258
+ $this->debug('Remove expired cookie ' . $cookie['name']);
8259
+ }
8260
+ } else {
8261
+ $this->cookies[] = $cookie;
8262
+ }
8263
+ }
8264
+ $this->debug('checkCookie: ' . sizeof($this->cookies) . ' cookies left in array');
8265
+ return true;
8266
+ }
8267
+
8268
+ /**
8269
+ * updates the current cookies with a new set
8270
+ *
8271
+ * @param array $cookies new cookies with which to update current ones
8272
+ * @return boolean always return true
8273
+ * @access private
8274
+ */
8275
+ function UpdateCookies($cookies)
8276
+ {
8277
+ if (sizeof($this->cookies) == 0) {
8278
+ // no existing cookies: take whatever is new
8279
+ if (sizeof($cookies) > 0) {
8280
+ $this->debug('Setting new cookie(s)');
8281
+ $this->cookies = $cookies;
8282
+ }
8283
+ return true;
8284
+ }
8285
+ if (sizeof($cookies) == 0) {
8286
+ // no new cookies: keep what we've got
8287
+ return true;
8288
+ }
8289
+ // merge
8290
+ foreach ($cookies as $newCookie) {
8291
+ if (!is_array($newCookie)) {
8292
+ continue;
8293
+ }
8294
+ if ((!isset($newCookie['name'])) || (!isset($newCookie['value']))) {
8295
+ continue;
8296
+ }
8297
+ $newName = $newCookie['name'];
8298
+
8299
+ $found = false;
8300
+ for ($i = 0; $i < count($this->cookies); $i++) {
8301
+ $cookie = $this->cookies[$i];
8302
+ if (!is_array($cookie)) {
8303
+ continue;
8304
+ }
8305
+ if (!isset($cookie['name'])) {
8306
+ continue;
8307
+ }
8308
+ if ($newName != $cookie['name']) {
8309
+ continue;
8310
+ }
8311
+ $newDomain = isset($newCookie['domain']) ? $newCookie['domain'] : 'NODOMAIN';
8312
+ $domain = isset($cookie['domain']) ? $cookie['domain'] : 'NODOMAIN';
8313
+ if ($newDomain != $domain) {
8314
+ continue;
8315
+ }
8316
+ $newPath = isset($newCookie['path']) ? $newCookie['path'] : 'NOPATH';
8317
+ $path = isset($cookie['path']) ? $cookie['path'] : 'NOPATH';
8318
+ if ($newPath != $path) {
8319
+ continue;
8320
+ }
8321
+ $this->cookies[$i] = $newCookie;
8322
+ $found = true;
8323
+ $this->debug('Update cookie ' . $newName . '=' . $newCookie['value']);
8324
+ break;
8325
+ }
8326
+ if (!$found) {
8327
+ $this->debug('Add cookie ' . $newName . '=' . $newCookie['value']);
8328
+ $this->cookies[] = $newCookie;
8329
+ }
8330
+ }
8331
+ return true;
8332
+ }
8333
+ }
8334
+
8335
+
8336
+ if (!extension_loaded('soap')) {
8337
+ /**
8338
+ * For backwards compatiblity, define soapclient unless the PHP SOAP extension is loaded.
8339
+ */
8340
+ class soapclient extends nusoap_client
8341
+ {
8342
+ }
8343
+ }
readme.txt CHANGED
@@ -2,8 +2,8 @@
2
  Contributors: affilinet, teraone
3
  Tags: Affiliate, affilinet, advertising, banner, performance marketing
4
  Requires at least: 3.0.1
5
- Tested up to: 4.9
6
- Stable tag: 1.9.4
7
  License: GPLv2 or later
8
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
9
 
@@ -79,6 +79,10 @@ It may take up to 90 minutes for ads to show, additionally all publisher account
79
 
80
  == Changelog ==
81
 
 
 
 
 
82
  = 1.9.4 =
83
  * Release Date: March 9, 2018
84
  * Fix: Suppress warnings on file write for ads.txt
2
  Contributors: affilinet, teraone
3
  Tags: Affiliate, affilinet, advertising, banner, performance marketing
4
  Requires at least: 3.0.1
5
+ Tested up to: 5.0
6
+ Stable tag: 1.9.5
7
  License: GPLv2 or later
8
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
9
 
79
 
80
  == Changelog ==
81
 
82
+ = 1.9.5 =
83
+ * Release Date: May 11, 2018
84
+ * Fix: Nusoap as a fallback if Soap Extension is missing
85
+
86
  = 1.9.4 =
87
  * Release Date: March 9, 2018
88
  * Fix: Suppress warnings on file write for ads.txt