MSP_Bancasella - Version 1.0.4

Version Notes

Enjoy it ;)

Download this release

Release Info

Developer Riccardo Tempesta
Extension MSP_Bancasella
Version 1.0.4
Comparing to
See all releases


Version 1.0.4

Files changed (32) hide show
  1. app/code/community/MSP/Bancasella/Block/Adminhtml/System/Config/Fieldset/Hint/Account.php +29 -0
  2. app/code/community/MSP/Bancasella/Block/Adminhtml/System/Config/Fieldset/Hint/Methods.php +29 -0
  3. app/code/community/MSP/Bancasella/Block/Gateway.php +36 -0
  4. app/code/community/MSP/Bancasella/Block/Gateway/Form.php +33 -0
  5. app/code/community/MSP/Bancasella/Block/Return.php +47 -0
  6. app/code/community/MSP/Bancasella/CHANGELOG.txt +14 -0
  7. app/code/community/MSP/Bancasella/COMPATIBILITY.txt +13 -0
  8. app/code/community/MSP/Bancasella/Helper/Data.php +161 -0
  9. app/code/community/MSP/Bancasella/LICENSE.txt +11 -0
  10. app/code/community/MSP/Bancasella/Model/Adminhtml/System/Config/Source/Language.php +51 -0
  11. app/code/community/MSP/Bancasella/Model/Adminhtml/System/Config/Source/Uic.php +72 -0
  12. app/code/community/MSP/Bancasella/Model/Api.php +203 -0
  13. app/code/community/MSP/Bancasella/Model/Gateway.php +54 -0
  14. app/code/community/MSP/Bancasella/controllers/GatewayController.php +130 -0
  15. app/code/community/MSP/Bancasella/controllers/ListenerController.php +44 -0
  16. app/code/community/MSP/Bancasella/etc/config.xml +151 -0
  17. app/code/community/MSP/Bancasella/etc/system.xml +280 -0
  18. app/code/community/MSP/Bancasella/lib/nusoap.php +8212 -0
  19. app/design/adminhtml/default/default/layout/msp_bancasella.xml +28 -0
  20. app/design/adminhtml/default/default/template/msp_bancasella/system/config/fieldset/hint/account.phtml +33 -0
  21. app/design/adminhtml/default/default/template/msp_bancasella/system/config/fieldset/hint/methods.phtml +24 -0
  22. app/design/frontend/base/default/layout/msp_bancasella.xml +49 -0
  23. app/design/frontend/base/default/template/msp_bancasella/gateway.phtml +34 -0
  24. app/design/frontend/base/default/template/msp_bancasella/gateway/form.phtml +31 -0
  25. app/etc/modules/MSP_Bancasella.xml +32 -0
  26. app/locale/it_IT/MSP_Bancasella.csv +34 -0
  27. package.xml +18 -0
  28. skin/adminhtml/default/default/msp_bancasella/bancasella.css +54 -0
  29. skin/adminhtml/default/default/msp_bancasella/bancasella_section.png +0 -0
  30. skin/adminhtml/default/default/msp_bancasella/logo.png +0 -0
  31. skin/frontend/base/default/msp_bancasella/logo.png +0 -0
  32. skin/frontend/base/default/msp_bancasella/logo_small.png +0 -0
app/code/community/MSP/Bancasella/Block/Adminhtml/System/Config/Fieldset/Hint/Account.php ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * IDEALIAGroup srl
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the Open Software License (OSL 3.0)
8
+ * that is bundled with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://opensource.org/licenses/osl-3.0.php
11
+ * If you did not receive a copy of the license and are unable to
12
+ * obtain it through the world-wide-web, please send an email
13
+ * to info@idealiagroup.com so we can send you a copy immediately.
14
+ *
15
+ * @category MSP
16
+ * @package MSP_Bancasella
17
+ * @copyright Copyright (c) 2013 IDEALIAGroup srl (http://www.idealiagroup.com)
18
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19
+ */
20
+
21
+ class MSP_Bancasella_Block_Adminhtml_System_Config_Fieldset_Hint_Account extends Mage_Adminhtml_Block_Abstract implements Varien_Data_Form_Element_Renderer_Interface
22
+ {
23
+ protected $_template = 'msp_bancasella/system/config/fieldset/hint/account.phtml';
24
+
25
+ public function render(Varien_Data_Form_Element_Abstract $element)
26
+ {
27
+ return $this->toHtml();
28
+ }
29
+ }
app/code/community/MSP/Bancasella/Block/Adminhtml/System/Config/Fieldset/Hint/Methods.php ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * IDEALIAGroup srl
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the Open Software License (OSL 3.0)
8
+ * that is bundled with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://opensource.org/licenses/osl-3.0.php
11
+ * If you did not receive a copy of the license and are unable to
12
+ * obtain it through the world-wide-web, please send an email
13
+ * to info@idealiagroup.com so we can send you a copy immediately.
14
+ *
15
+ * @category MSP
16
+ * @package MSP_Bancasella
17
+ * @copyright Copyright (c) 2013 IDEALIAGroup srl (http://www.idealiagroup.com)
18
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19
+ */
20
+
21
+ class MSP_Bancasella_Block_Adminhtml_System_Config_Fieldset_Hint_Methods extends Mage_Adminhtml_Block_Abstract implements Varien_Data_Form_Element_Renderer_Interface
22
+ {
23
+ protected $_template = 'msp_bancasella/system/config/fieldset/hint/methods.phtml';
24
+
25
+ public function render(Varien_Data_Form_Element_Abstract $element)
26
+ {
27
+ return $this->toHtml();
28
+ }
29
+ }
app/code/community/MSP/Bancasella/Block/Gateway.php ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * IDEALIAGroup srl
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the Open Software License (OSL 3.0)
8
+ * that is bundled with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://opensource.org/licenses/osl-3.0.php
11
+ * If you did not receive a copy of the license and are unable to
12
+ * obtain it through the world-wide-web, please send an email
13
+ * to info@idealiagroup.com so we can send you a copy immediately.
14
+ *
15
+ * @category MSP
16
+ * @package MSP_Bancasella
17
+ * @copyright Copyright (c) 2013 IDEALIAGroup srl (http://www.idealiagroup.com)
18
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19
+ */
20
+
21
+ class MSP_Bancasella_Block_Gateway extends Mage_Core_Block_Template
22
+ {
23
+ /**
24
+ * Return redirect URL
25
+ *
26
+ * @return string
27
+ */
28
+ public function getRedirectUrl()
29
+ {
30
+ $session = Mage::getSingleton('checkout/session');
31
+ $order = Mage::getModel('sales/order');
32
+ $order->loadByIncrementId($session->getLastRealOrderId());
33
+
34
+ return Mage::getSingleton('msp_bancasella/api')->getGatewayUrl($order);
35
+ }
36
+ }
app/code/community/MSP/Bancasella/Block/Gateway/Form.php ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * IDEALIAGroup srl
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the Open Software License (OSL 3.0)
8
+ * that is bundled with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://opensource.org/licenses/osl-3.0.php
11
+ * If you did not receive a copy of the license and are unable to
12
+ * obtain it through the world-wide-web, please send an email
13
+ * to info@idealiagroup.com so we can send you a copy immediately.
14
+ *
15
+ * @category MSP
16
+ * @package MSP_Bancasella
17
+ * @copyright Copyright (c) 2013 IDEALIAGroup srl (http://www.idealiagroup.com)
18
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19
+ */
20
+
21
+ class MSP_Bancasella_Block_Gateway_Form extends Mage_Payment_Block_Form
22
+ {
23
+ protected function _construct()
24
+ {
25
+ parent::_construct();
26
+ $this->setTemplate('msp_bancasella/gateway/form.phtml');
27
+ }
28
+
29
+ public function getPaymentImageSrc()
30
+ {
31
+ return $this->getSkinUrl('msp_bancasella/logo_small.png');
32
+ }
33
+ }
app/code/community/MSP/Bancasella/Block/Return.php ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * IDEALIAGroup srl
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the Open Software License (OSL 3.0)
8
+ * that is bundled with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://opensource.org/licenses/osl-3.0.php
11
+ * If you did not receive a copy of the license and are unable to
12
+ * obtain it through the world-wide-web, please send an email
13
+ * to info@idealiagroup.com so we can send you a copy immediately.
14
+ *
15
+ * @category MSP
16
+ * @package MSP_Bancasella
17
+ * @copyright Copyright (c) 2013 IDEALIAGroup srl (http://www.idealiagroup.com)
18
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19
+ */
20
+
21
+ class MSP_Bancasella_Block_Return extends Mage_Core_Block_Template
22
+ {
23
+ /**
24
+ * Return parameters
25
+ *
26
+ * @return array
27
+ */
28
+ public function getResults()
29
+ {
30
+ return Mage::registry('msp_bancasella_gw_result');
31
+ }
32
+
33
+ /**
34
+ * Return parameter
35
+ *
36
+ * @param string $key
37
+ * @return string
38
+ */
39
+ public function getResult($key)
40
+ {
41
+ $results = $this->getResults();
42
+ if (!isset($results))
43
+ return null;
44
+
45
+ return $results[$key];
46
+ }
47
+ }
app/code/community/MSP/Bancasella/CHANGELOG.txt ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ 1.0.0:
2
+ Release version
3
+
4
+ 1.0.1:
5
+ Corretto bug di capture delle transazioni
6
+
7
+ 1.0.2:
8
+ Corretto bug di case delle cartelle
9
+
10
+ 1.0.3:
11
+ Corretto potenziale bug del redirect del gateway
12
+
13
+ 1.0.4:
14
+ Corretti alcuni refusi
app/code/community/MSP/Bancasella/COMPATIBILITY.txt ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ This file reports the compatibility table for this extension.
2
+ If your Magento version is not included in this list you may try
3
+ using the extension but AT YOUR OWN RISK.
4
+
5
+ CE 1.4.2
6
+ CE 1.5.0
7
+ CE 1.5.1
8
+ CE 1.6.0
9
+ CE 1.6.1
10
+ CE 1.6.2
11
+ CE 1.7.x
12
+ CE 1.8.x
13
+ CE 1.9.x
app/code/community/MSP/Bancasella/Helper/Data.php ADDED
@@ -0,0 +1,161 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * IDEALIAGroup srl
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the Open Software License (OSL 3.0)
8
+ * that is bundled with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://opensource.org/licenses/osl-3.0.php
11
+ * If you did not receive a copy of the license and are unable to
12
+ * obtain it through the world-wide-web, please send an email
13
+ * to info@idealiagroup.com so we can send you a copy immediately.
14
+ *
15
+ * @category MSP
16
+ * @package MSP_Bancasella
17
+ * @copyright Copyright (c) 2013 IDEALIAGroup srl (http://www.idealiagroup.com)
18
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19
+ */
20
+
21
+ class MSP_Bancasella_Helper_Data extends Mage_Core_Helper_Abstract
22
+ {
23
+ const GW_URL = 'https://ecomm.sella.it/pagam/pagam.aspx';
24
+ const GW_URL_TEST = 'https://testecomm.sella.it/pagam/pagam.aspx';
25
+
26
+ const S2S_URL = 'https://ecomms2s.sella.it/gestpay/gestpayws/WSCryptDecrypt.asmx?WSDL';
27
+ const S2S_URL_TEST = 'https://testecomm.sella.it/gestpay/gestpayws/WSCryptDecrypt.asmx?WSDL';
28
+
29
+ const XML_PATH_ACCOUNT_TEST_MODE = 'msp_bancasella/account/test-mode';
30
+ const XML_PATH_ACCOUNT_SHOP_LOGIN = 'msp_bancasella/account/merchant';
31
+ const XML_PATH_ACCOUNT_CURRENCY_CODE = 'msp_bancasella/account/currency-code';
32
+ const XML_PATH_ACCOUNT_LANGUAGE = 'msp_bancasella/account/language';
33
+ const XML_PATH_ACCOUNT_ORDER_PREFIX = 'msp_bancasella/account/order-prefix';
34
+
35
+ const XML_PATH_FIELD_BUYER_NAME = 'msp_bancasella/fields/buyer-name';
36
+ const XML_PATH_FIELD_BUYER_EMAIL = 'msp_bancasella/fields/buyer-email';
37
+ const XML_PATH_FIELD_LANGUAGE = 'msp_bancasella/fields/language';
38
+
39
+ /**
40
+ * Return true on test mode
41
+ * @param
42
+ * @return bool
43
+ */
44
+ public function getIsTest()
45
+ {
46
+ return (bool) Mage::getStoreConfig(self::XML_PATH_ACCOUNT_TEST_MODE);
47
+ }
48
+
49
+ /**
50
+ * Get ecomm URL
51
+ * @param
52
+ * @return string
53
+ */
54
+ public function getGwUrl()
55
+ {
56
+ if ($this->getIsTest())
57
+ return self::GW_URL_TEST;
58
+
59
+ return self::GW_URL;
60
+ }
61
+
62
+ /**
63
+ * Get server-to-server URL
64
+ * @param
65
+ * @return string
66
+ */
67
+ public function getS2sUrl()
68
+ {
69
+ if ($this->getIsTest())
70
+ return self::S2S_URL_TEST;
71
+
72
+ return self::S2S_URL;
73
+ }
74
+
75
+ /**
76
+ * Get merchant login
77
+ * @return string
78
+ */
79
+ public function getShopLogin()
80
+ {
81
+ return Mage::getStoreConfig(self::XML_PATH_ACCOUNT_SHOP_LOGIN);
82
+ }
83
+
84
+ /**
85
+ * Get UIC
86
+ * @return int
87
+ */
88
+ public function getUic()
89
+ {
90
+ return intval(Mage::getStoreConfig(self::XML_PATH_ACCOUNT_CURRENCY_CODE));
91
+ }
92
+
93
+ /**
94
+ * Get language
95
+ * @return int
96
+ */
97
+ public function getLanguage()
98
+ {
99
+ return intval(Mage::getStoreConfig(self::XML_PATH_ACCOUNT_LANGUAGE));
100
+ }
101
+
102
+ /**
103
+ * Check whenever to send buyer name
104
+ * @return bool
105
+ */
106
+ public function getFieldBuyerName()
107
+ {
108
+ return intval(Mage::getStoreConfig(self::XML_PATH_FIELD_BUYER_NAME));
109
+ }
110
+
111
+ /**
112
+ * Check whenever to send buyer email
113
+ * @return bool
114
+ */
115
+ public function getFieldBuyerEmail()
116
+ {
117
+ return intval(Mage::getStoreConfig(self::XML_PATH_FIELD_BUYER_EMAIL));
118
+ }
119
+
120
+ /**
121
+ * Check whenever to send language
122
+ * @return bool
123
+ */
124
+ public function getFieldLanguage()
125
+ {
126
+ return intval(Mage::getStoreConfig(self::XML_PATH_FIELD_LANGUAGE));
127
+ }
128
+
129
+ /**
130
+ * Get order prefix
131
+ * @return string
132
+ */
133
+ public function getOrderPrefix()
134
+ {
135
+ return Mage::getStoreConfig(self::XML_PATH_ACCOUNT_ORDER_PREFIX);
136
+ }
137
+
138
+ /**
139
+ * Stripe order prefix from order number
140
+ * @param string $orderId
141
+ * @return string
142
+ */
143
+ public function stripOrderPrefix($orderId)
144
+ {
145
+ $parts = explode('_', $orderId);
146
+ return array_pop($parts);
147
+ }
148
+
149
+ /**
150
+ * Add order prefix from order number
151
+ * @param string $orderId
152
+ * @return string
153
+ */
154
+ public function addOrderPrefix($orderId)
155
+ {
156
+ if ($this->getOrderPrefix())
157
+ return $this->getOrderPrefix().'_'.$orderId;
158
+
159
+ return $orderId;
160
+ }
161
+ }
app/code/community/MSP/Bancasella/LICENSE.txt ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ IDEALIAGroup srl
2
+
3
+ NOTICE OF LICENSE
4
+
5
+ This source file is subject to the Open Software License (OSL 3.0)
6
+ that is bundled with this package in the file LICENSE.txt.
7
+ It is also available through the world-wide-web at this URL:
8
+ http://opensource.org/licenses/osl-3.0.php
9
+ If you did not receive a copy of the license and are unable to
10
+ obtain it through the world-wide-web, please send an email
11
+ to info@idealiagroup.com so we can send you a copy immediately.
app/code/community/MSP/Bancasella/Model/Adminhtml/System/Config/Source/Language.php ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * IDEALIAGroup srl
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the Open Software License (OSL 3.0)
8
+ * that is bundled with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://opensource.org/licenses/osl-3.0.php
11
+ * If you did not receive a copy of the license and are unable to
12
+ * obtain it through the world-wide-web, please send an email
13
+ * to info@idealiagroup.com so we can send you a copy immediately.
14
+ *
15
+ * @category MSP
16
+ * @package MSP_Bancasella
17
+ * @copyright Copyright (c) 2013 IDEALIAGroup srl (http://www.idealiagroup.com)
18
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19
+ */
20
+
21
+ class MSP_Bancasella_Model_Adminhtml_System_Config_Source_Language
22
+ {
23
+ protected $_options;
24
+
25
+ public function toOptionArray()
26
+ {
27
+ if (!$this->_options)
28
+ {
29
+ $this->_options = array(
30
+ array(
31
+ 'label' => Mage::helper('msp_bancasella')->__('Italian'),
32
+ 'value' => 1,
33
+ ), array(
34
+ 'label' => Mage::helper('msp_bancasella')->__('English'),
35
+ 'value' => 2,
36
+ ), array(
37
+ 'label' => Mage::helper('msp_bancasella')->__('Spanish'),
38
+ 'value' => 3,
39
+ ), array(
40
+ 'label' => Mage::helper('msp_bancasella')->__('French'),
41
+ 'value' => 4,
42
+ ), array(
43
+ 'label' => Mage::helper('msp_bancasella')->__('German'),
44
+ 'value' => 5,
45
+ ),
46
+ );
47
+ }
48
+
49
+ return $this->_options;
50
+ }
51
+ }
app/code/community/MSP/Bancasella/Model/Adminhtml/System/Config/Source/Uic.php ADDED
@@ -0,0 +1,72 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * IDEALIAGroup srl
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the Open Software License (OSL 3.0)
8
+ * that is bundled with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://opensource.org/licenses/osl-3.0.php
11
+ * If you did not receive a copy of the license and are unable to
12
+ * obtain it through the world-wide-web, please send an email
13
+ * to info@idealiagroup.com so we can send you a copy immediately.
14
+ *
15
+ * @category MSP
16
+ * @package MSP_Bancasella
17
+ * @copyright Copyright (c) 2013 IDEALIAGroup srl (http://www.idealiagroup.com)
18
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19
+ */
20
+
21
+ class MSP_Bancasella_Model_Adminhtml_System_Config_Source_Uic
22
+ {
23
+ protected $_options;
24
+
25
+ public function toOptionArray()
26
+ {
27
+ if (!$this->_options)
28
+ {
29
+ $this->_options = array(
30
+ array(
31
+ 'label' => Mage::helper('msp_bancasella')->__('USD'),
32
+ 'value' => 1,
33
+ ), array(
34
+ 'label' => Mage::helper('msp_bancasella')->__('GBP'),
35
+ 'value' => 2,
36
+ ), array(
37
+ 'label' => Mage::helper('msp_bancasella')->__('CHF'),
38
+ 'value' => 3,
39
+ ), array(
40
+ 'label' => Mage::helper('msp_bancasella')->__('DKK'),
41
+ 'value' => 7,
42
+ ), array(
43
+ 'label' => Mage::helper('msp_bancasella')->__('NOK'),
44
+ 'value' => 8,
45
+ ), array(
46
+ 'label' => Mage::helper('msp_bancasella')->__('SEK'),
47
+ 'value' => 9,
48
+ ), array(
49
+ 'label' => Mage::helper('msp_bancasella')->__('CAD'),
50
+ 'value' => 12,
51
+ ), array(
52
+ 'label' => Mage::helper('msp_bancasella')->__('ITL'),
53
+ 'value' => 18,
54
+ ), array(
55
+ 'label' => Mage::helper('msp_bancasella')->__('JPY'),
56
+ 'value' => 71,
57
+ ), array(
58
+ 'label' => Mage::helper('msp_bancasella')->__('HKD'),
59
+ 'value' => 103,
60
+ ), array(
61
+ 'label' => Mage::helper('msp_bancasella')->__('BRL'),
62
+ 'value' => 234,
63
+ ), array(
64
+ 'label' => Mage::helper('msp_bancasella')->__('EUR'),
65
+ 'value' => 242,
66
+ ),
67
+ );
68
+ }
69
+
70
+ return $this->_options;
71
+ }
72
+ }
app/code/community/MSP/Bancasella/Model/Api.php ADDED
@@ -0,0 +1,203 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * IDEALIAGroup srl
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the Open Software License (OSL 3.0)
8
+ * that is bundled with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://opensource.org/licenses/osl-3.0.php
11
+ * If you did not receive a copy of the license and are unable to
12
+ * obtain it through the world-wide-web, please send an email
13
+ * to info@idealiagroup.com so we can send you a copy immediately.
14
+ *
15
+ * @category MSP
16
+ * @package MSP_Bancasella
17
+ * @copyright Copyright (c) 2013 IDEALIAGroup srl (http://www.idealiagroup.com)
18
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19
+ */
20
+
21
+ require_once(BP.DS.'app'.DS.'code'.DS.'community'.DS.'MSP'.DS.'Bancasella'.DS.'lib'.DS.'nusoap.php');
22
+ class MSP_Bancasella_Model_Api
23
+ {
24
+ protected $_helper = null;
25
+
26
+ /**
27
+ * Return bancasella helper
28
+ * @return MSP_Bancasella_Helper_Data
29
+ */
30
+ protected function _getBancasellaHelper()
31
+ {
32
+ if (!$this->_helper)
33
+ $this->_helper = Mage::helper('msp_bancasella');
34
+
35
+ return $this->_helper;
36
+ }
37
+
38
+ /**
39
+ * Return order array params
40
+ * @param Mage_Sales_Model_Order $order
41
+ * @return array
42
+ */
43
+ protected function _getOrderParams(Mage_Sales_Model_Order $order)
44
+ {
45
+ $helper = $this->_getBancasellaHelper();
46
+
47
+ $return = array(
48
+ 'shopLogin' => $helper->getShopLogin(),
49
+ 'uicCode' => $helper->getUic(),
50
+ 'amount' => number_format($order->getGrandTotal(), 2, '.', ''),
51
+ 'shopTransactionId' => $helper->addOrderPrefix($order->getIncrementId()),
52
+ );
53
+
54
+ if ($helper->getFieldBuyerEmail())
55
+ $return['buyerEmail'] = $order->getCustomerEmail();
56
+
57
+ if ($helper->getFieldBuyerName())
58
+ $return['buyerName'] = $order->getCustomerName();
59
+
60
+ if ($helper->getFieldLanguage())
61
+ $return['languageId'] = $helper->getLanguage();
62
+
63
+ return $return;
64
+ }
65
+
66
+ /**
67
+ * Get server-to-server url
68
+ * @param Mage_Sales_Model_Order $order
69
+ * @return true
70
+ */
71
+ protected function _getEncryptedString(Mage_Sales_Model_Order $order)
72
+ {
73
+ $wsdl = $this->_getBancasellaHelper()->getS2sUrl();
74
+ $client = new nusoap_client($wsdl, true);
75
+
76
+ $params = $this->_getOrderParams($order);
77
+
78
+ $objectresult = $client->call('Encrypt', $params);
79
+
80
+ $err = $client->getError();
81
+ if ($err)
82
+ {
83
+ Mage::throwException(Mage::helper('msp_bancasella')->__('Bancasella Webservice Error: %s', $err));
84
+ return null;
85
+ }
86
+
87
+ $errCode = $objectresult['EncryptResult']['GestPayCryptDecrypt']['ErrorCode'];
88
+ if ($errCode != '0')
89
+ Mage::throwException(Mage::helper('msp_bancasella')->__('Bancasella Webservice Error(%s): %s', $errCode, $objectresult['EncryptResult']['GestPayCryptDecrypt']['ErrorDescription']));
90
+
91
+ return $objectresult['EncryptResult']['GestPayCryptDecrypt']['CryptDecryptString'];
92
+ }
93
+
94
+ /**
95
+ * Get decrypted string
96
+ * @param string $cryptedString
97
+ * @return object
98
+ */
99
+ public function getDecryptedInformation($cryptedString)
100
+ {
101
+ $helper = $this->_getBancasellaHelper();
102
+
103
+ $wsdl = $helper->getS2sUrl();
104
+ $client = new nusoap_client($wsdl, true);
105
+
106
+ $shopLogin = $helper->getShopLogin();
107
+ $params = array(
108
+ 'shopLogin' => $shopLogin,
109
+ 'CryptedString' => $cryptedString
110
+ );
111
+
112
+ $objectResult = $client->call('Decrypt', $params);
113
+ $err = $client->getError();
114
+ if ($err) return null;
115
+
116
+ return $objectResult['DecryptResult']['GestPayCryptDecrypt'];
117
+ }
118
+
119
+ /**
120
+ * Get Bancasella payment gateway URL
121
+ * @param Mage_Sales_Model_Order $order
122
+ * @return string
123
+ */
124
+ public function getGatewayUrl(Mage_Sales_Model_Order $order)
125
+ {
126
+ $helper = $this->_getBancasellaHelper();
127
+ return $helper->getGwUrl().'?a='.urlencode($helper->getShopLogin()).'&b='.urlencode($this->_getEncryptedString($order));
128
+ }
129
+
130
+ /**
131
+ * Handle listener message
132
+ * @param array $info
133
+ * @return MSP_Bancasella_Model_Api
134
+ */
135
+ public function handleListenerMessage(array $info)
136
+ {
137
+ $helper = $this->_getBancasellaHelper();
138
+
139
+ $incrementId = $helper->stripOrderPrefix($info['ShopTransactionID']);
140
+
141
+ /* @var $order Mage_Sales_Model_Order */
142
+ $order = Mage::getModel('sales/order')->loadByIncrementId($incrementId);
143
+
144
+ if (!$order->getId())
145
+ return;
146
+
147
+ $transactionUpdate = null;
148
+
149
+ $state = $order->getState();
150
+ switch ($info['TransactionResult'])
151
+ {
152
+ case 'XX':
153
+ $comment = 'Order on-hold for banck check verification';
154
+ $state = Mage_Sales_Model_Order::STATE_PENDING_PAYMENT;
155
+ break;
156
+
157
+ case 'OK':
158
+ $comment = 'Order authorized by BancaSella, auth code: '.$info['AuthorizationCode'].', tid: '.$info['BankTransactionID'];
159
+ $state = Mage_Sales_Model_Order::STATE_PROCESSING;
160
+ $transactionUpdate = Mage_Sales_Model_Order_Payment_Transaction::TYPE_CAPTURE;
161
+ break;
162
+
163
+ case 'KO':
164
+ $comment = 'Order denied by BancaSella: ['.$info['ErrorCode'].'] '.$info['ErrorDescription'];
165
+ $state = Mage_Sales_Model_Order::STATE_CANCELED;
166
+ $transactionUpdate = Mage_Sales_Model_Order_Payment_Transaction::TYPE_VOID;
167
+ break;
168
+ }
169
+
170
+ if (!$comment) return;
171
+
172
+ if ($transactionUpdate)
173
+ {
174
+ $payment = $order->getPayment();
175
+
176
+ $payment->setTransactionId($order->getIncrementId().'-'.$transactionUpdate);
177
+ $transaction = $payment->addTransaction($transactionUpdate, null, false, $comment);
178
+ $transaction->save();
179
+ }
180
+
181
+ if ($state == Mage_Sales_Model_Order::STATE_PROCESSING)
182
+ {
183
+ $order->sendNewOrderEmail();
184
+ }
185
+
186
+ $oldState = $order->getState();
187
+
188
+ $customerNotification = false;
189
+ switch ($state)
190
+ {
191
+ case Mage_Sales_Model_Order::STATE_CANCELED:
192
+ $customerNotification = true;
193
+ $order->cancel();
194
+ break;
195
+ }
196
+
197
+ $order->addStatusToHistory($state, Mage::helper('msp_bancasella')->__('BancaSella Status: %s', $comment));
198
+ if (($oldState != $state) && $customerNotification) $order->sendOrderUpdateEmail(true);
199
+ $order->save();
200
+
201
+ return $this;
202
+ }
203
+ }
app/code/community/MSP/Bancasella/Model/Gateway.php ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * IDEALIAGroup srl
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the Open Software License (OSL 3.0)
8
+ * that is bundled with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://opensource.org/licenses/osl-3.0.php
11
+ * If you did not receive a copy of the license and are unable to
12
+ * obtain it through the world-wide-web, please send an email
13
+ * to info@idealiagroup.com so we can send you a copy immediately.
14
+ *
15
+ * @category MSP
16
+ * @package MSP_Bancasella
17
+ * @copyright Copyright (c) 2013 IDEALIAGroup srl (http://www.idealiagroup.com)
18
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19
+ */
20
+
21
+ class MSP_Bancasella_Model_Gateway extends Mage_Payment_Model_Method_Abstract
22
+ {
23
+ protected $_code = 'msp_bancasella_gateway';
24
+ protected $_formBlockType = 'msp_bancasella/gateway_form';
25
+
26
+ protected $_isGateway = true;
27
+ protected $_canAuthorize = true;
28
+ protected $_canCapture = false;
29
+ protected $_canCapturePartial = false;
30
+ protected $_canRefund = false;
31
+ protected $_canRefundInvoicePartial = false;
32
+ protected $_canVoid = false;
33
+ protected $_canUseInternal = false;
34
+ protected $_canUseCheckout = true;
35
+ protected $_canUseForMultishipping = true;
36
+
37
+ public function getOrderPlaceRedirectUrl()
38
+ {
39
+ return Mage::getUrl('msp_bancasella/gateway/index');
40
+ }
41
+
42
+ public function processInvoice($invoice, $payment)
43
+ {
44
+ $invoice->setTransactionId($payment->getOrder()->getIncrementId());
45
+ $payment->setIsTransactionClosed(1);
46
+ return $this;
47
+ }
48
+
49
+ public function processBeforeRefund($invoice, $payment)
50
+ {
51
+ $payment->setRefundTransactionId($payment->getOrder()->getIncrementId());
52
+ return $this;
53
+ }
54
+ }
app/code/community/MSP/Bancasella/controllers/GatewayController.php ADDED
@@ -0,0 +1,130 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * IDEALIAGroup srl
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the Open Software License (OSL 3.0)
8
+ * that is bundled with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://opensource.org/licenses/osl-3.0.php
11
+ * If you did not receive a copy of the license and are unable to
12
+ * obtain it through the world-wide-web, please send an email
13
+ * to info@idealiagroup.com so we can send you a copy immediately.
14
+ *
15
+ * @category MSP
16
+ * @package MSP_Bancasella
17
+ * @copyright Copyright (c) 2013 IDEALIAGroup srl (http://www.idealiagroup.com)
18
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19
+ */
20
+
21
+ class MSP_Bancasella_GatewayController extends Mage_Core_Controller_Front_Action
22
+ {
23
+ protected $_orderId = null;
24
+ protected $_orderInfo = array();
25
+
26
+ /**
27
+ * Get checkout session
28
+ * @return Mage_Checkout_Model_Session
29
+ */
30
+ protected function _getCheckoutSession()
31
+ {
32
+ return Mage::getSingleton('checkout/session');
33
+ }
34
+
35
+ /**
36
+ * Get one page checkout model
37
+ * @return Mage_Checkout_Model_Type_Onepage
38
+ */
39
+ public function getOnepage()
40
+ {
41
+ return Mage::getSingleton('checkout/type_onepage');
42
+ }
43
+
44
+ /**
45
+ * Prepare response action
46
+ * @return void
47
+ */
48
+ protected function _prepareResponseAction()
49
+ {
50
+ $helper = Mage::helper('msp_bancasella');
51
+
52
+ $this->_orderId = null;
53
+ $this->_orderInfo = array();
54
+
55
+ $shopLogin = $this->getRequest()->getParam('a');
56
+ $cryptedString = $this->getRequest()->getParam('b');
57
+
58
+ $api = Mage::getSingleton('msp_bancasella/api');
59
+
60
+ $this->_orderInfo = $api->getDecryptedInformation($cryptedString);
61
+ if (!$this->_orderInfo)
62
+ return;
63
+
64
+ $order = Mage::getModel('sales/order')->loadByIncrementId($helper->stripOrderPrefix($this->_orderInfo['ShopTransactionID']));
65
+ if (!$order->getId())
66
+ return;
67
+
68
+ // Trick for redirecting to original website in case of multidomain
69
+ if ($order->getStore()->getWebsiteId() != Mage::app()->getStore()->getWebsiteId())
70
+ {
71
+ $queryString = http_build_query(array(
72
+ 'a' => $shopLogin,
73
+ 'b' => $cryptedString,
74
+ ));
75
+
76
+ $url = Mage::app()->getStore($order->getStore()->getId())->getBaseUrl(Mage_Core_Model_Store::URL_TYPE_LINK)
77
+ .'msp_bancasella/gateway/'.$this->getRequest()->getActionName().'?'.$queryString;
78
+
79
+ header('Location: '.$url);
80
+ exit;
81
+ }
82
+
83
+ $this->_getCheckoutSession()->clear();
84
+
85
+ $this->_orderId = $order->getId();
86
+ }
87
+
88
+ public function indexAction()
89
+ {
90
+ $session = $this->_getCheckoutSession();
91
+
92
+ $order = Mage::getModel('sales/order');
93
+ $order->loadByIncrementId($session->getLastRealOrderId());
94
+ $order->addStatusToHistory(Mage_Sales_Model_Order::STATE_HOLDED, Mage::helper('msp_bancasella')->__('Customer was redirected to Bancasella.'));
95
+ $order->save();
96
+
97
+ $this->loadLayout();
98
+ $this->renderLayout();
99
+
100
+ $session->unsQuoteId();
101
+ }
102
+
103
+ public function successAction()
104
+ {
105
+ $this->_prepareResponseAction();
106
+ if (!$this->_orderId)
107
+ {
108
+ $this->_redirect('checkout/cart');
109
+ return;
110
+ }
111
+
112
+ $this->loadLayout();
113
+ $this->_initLayoutMessages('checkout/session');
114
+ Mage::dispatchEvent('checkout_onepage_controller_success_action', array('order_ids' => array($this->_orderId)));
115
+ $this->renderLayout();
116
+ }
117
+
118
+ public function failureAction()
119
+ {
120
+ $this->_prepareResponseAction();
121
+ if (!$this->_orderId)
122
+ {
123
+ $this->_redirect('checkout/cart');
124
+ return;
125
+ }
126
+
127
+ $this->loadLayout();
128
+ $this->renderLayout();
129
+ }
130
+ }
app/code/community/MSP/Bancasella/controllers/ListenerController.php ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * IDEALIAGroup srl
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the Open Software License (OSL 3.0)
8
+ * that is bundled with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://opensource.org/licenses/osl-3.0.php
11
+ * If you did not receive a copy of the license and are unable to
12
+ * obtain it through the world-wide-web, please send an email
13
+ * to info@idealiagroup.com so we can send you a copy immediately.
14
+ *
15
+ * @category MSP
16
+ * @package MSP_Bancasella
17
+ * @copyright Copyright (c) 2013 IDEALIAGroup srl (http://www.idealiagroup.com)
18
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19
+ */
20
+
21
+ class MSP_Bancasella_ListenerController extends Mage_Core_Controller_Front_Action
22
+ {
23
+ /**
24
+ * Get checkout session
25
+ * @return Mage_Checkout_Model_Session
26
+ */
27
+ protected function _getCheckoutSession()
28
+ {
29
+ return Mage::getSingleton('checkout/session');
30
+ }
31
+
32
+ public function indexAction()
33
+ {
34
+ $shopLogin = $this->getRequest()->getParam('a');
35
+ $cryptedString = $this->getRequest()->getParam('b');
36
+
37
+ $api = Mage::getSingleton('msp_bancasella/api');
38
+
39
+ $info = $api->getDecryptedInformation($cryptedString);
40
+ if (!$info) return;
41
+
42
+ $api->handleListenerMessage($info);
43
+ }
44
+ }
app/code/community/MSP/Bancasella/etc/config.xml ADDED
@@ -0,0 +1,151 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <!--
3
+ /**
4
+ * IDEALIAGroup srl
5
+ *
6
+ * NOTICE OF LICENSE
7
+ *
8
+ * This source file is subject to the Open Software License (OSL 3.0)
9
+ * that is bundled with this package in the file LICENSE.txt.
10
+ * It is also available through the world-wide-web at this URL:
11
+ * http://opensource.org/licenses/osl-3.0.php
12
+ * If you did not receive a copy of the license and are unable to
13
+ * obtain it through the world-wide-web, please send an email
14
+ * to info@idealiagroup.com so we can send you a copy immediately.
15
+ *
16
+ * @category MSP
17
+ * @package MSP_Bancasella
18
+ * @copyright Copyright (c) 2013 IDEALIAGroup srl (http://www.idealiagroup.com)
19
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
20
+ */
21
+ -->
22
+ <config>
23
+ <modules>
24
+ <MSP_Bancasella>
25
+ <version>1.0.4</version>
26
+ </MSP_Bancasella>
27
+ </modules>
28
+
29
+ <global>
30
+ <models>
31
+ <msp_bancasella>
32
+ <class>MSP_Bancasella_Model</class>
33
+ </msp_bancasella>
34
+ </models>
35
+
36
+ <helpers>
37
+ <msp_bancasella>
38
+ <class>MSP_Bancasella_Helper</class>
39
+ </msp_bancasella>
40
+ </helpers>
41
+
42
+ <blocks>
43
+ <msp_bancasella>
44
+ <class>MSP_Bancasella_Block</class>
45
+ </msp_bancasella>
46
+ </blocks>
47
+ </global>
48
+
49
+ <frontend>
50
+ <routers>
51
+ <msp_bancasella>
52
+ <use>standard</use>
53
+ <args>
54
+ <module>MSP_Bancasella</module>
55
+ <frontName>msp_bancasella</frontName>
56
+ </args>
57
+ </msp_bancasella>
58
+ </routers>
59
+
60
+ <layout>
61
+ <updates>
62
+ <msp_bancasella>
63
+ <file>msp_bancasella.xml</file>
64
+ </msp_bancasella>
65
+ </updates>
66
+ </layout>
67
+
68
+ <translate>
69
+ <modules>
70
+ <msp_bancasella>
71
+ <files>
72
+ <default>MSP_Bancasella.csv</default>
73
+ </files>
74
+ </msp_bancasella>
75
+ </modules>
76
+ </translate>
77
+ </frontend>
78
+
79
+ <adminhtml>
80
+ <acl>
81
+ <resources>
82
+ <admin>
83
+ <children>
84
+ <system>
85
+ <children>
86
+ <config>
87
+ <children>
88
+ <msp_bancasella translate="title" module="msp_bancasella">
89
+ <title>MSP BancaSella</title>
90
+ <sort_order>1000</sort_order>
91
+ </msp_bancasella>
92
+ </children>
93
+ </config>
94
+ </children>
95
+ </system>
96
+ </children>
97
+ </admin>
98
+ </resources>
99
+ </acl>
100
+ <layout>
101
+ <updates>
102
+ <msp_bancasella>
103
+ <file>msp_bancasella.xml</file>
104
+ </msp_bancasella>
105
+ </updates>
106
+ </layout>
107
+ <translate>
108
+ <modules>
109
+ <msp_bancasella>
110
+ <files>
111
+ <default>MSP_Bancasella.csv</default>
112
+ </files>
113
+ </msp_bancasella>
114
+ </modules>
115
+ </translate>
116
+ </adminhtml>
117
+
118
+ <default>
119
+ <msp_bancasella>
120
+ <account>
121
+ <test-mode>1</test-mode>
122
+ <language>1</language>
123
+ <order-prefix>MAGE</order-prefix>
124
+ <merchant>GESPAYXXXXX</merchant>
125
+ <login>12345</login>
126
+ <password>MySecretPassword</password>
127
+ <currency-code>242</currency-code>
128
+ <auto-invoice>no</auto-invoice>
129
+ </account>
130
+
131
+ <fields>
132
+ <buyer-name>0</buyer-name>
133
+ <buyer-email>0</buyer-email>
134
+ <language>0</language>
135
+ </fields>
136
+ </msp_bancasella>
137
+
138
+ <payment>
139
+ <msp_bancasella_gateway>
140
+ <active>0</active>
141
+ <model>msp_bancasella/gateway</model>
142
+ <order_status>pending</order_status>
143
+ <title>Bancasella GestPay</title>
144
+ <payment_action>authorize</payment_action>
145
+ <allowspecific>0</allowspecific>
146
+ <sort_order>10</sort_order>
147
+ <specificcountry>IT</specificcountry>
148
+ </msp_bancasella_gateway>
149
+ </payment>
150
+ </default>
151
+ </config>
app/code/community/MSP/Bancasella/etc/system.xml ADDED
@@ -0,0 +1,280 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <!--
3
+ /**
4
+ * IDEALIAGroup srl
5
+ *
6
+ * NOTICE OF LICENSE
7
+ *
8
+ * This source file is subject to the Open Software License (OSL 3.0)
9
+ * that is bundled with this package in the file LICENSE.txt.
10
+ * It is also available through the world-wide-web at this URL:
11
+ * http://opensource.org/licenses/osl-3.0.php
12
+ * If you did not receive a copy of the license and are unable to
13
+ * obtain it through the world-wide-web, please send an email
14
+ * to info@idealiagroup.com so we can send you a copy immediately.
15
+ *
16
+ * @category MSP
17
+ * @package MSP_Bancasella
18
+ * @copyright Copyright (c) 2013 IDEALIAGroup srl (http://www.idealiagroup.com)
19
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
20
+ */
21
+ -->
22
+ <config>
23
+ <sections>
24
+ <payment>
25
+ <groups>
26
+ <msp_bancasella_hint>
27
+ <frontend_model>msp_bancasella/adminhtml_system_config_fieldset_hint_methods</frontend_model>
28
+ <sort_order>0</sort_order>
29
+ <show_in_default>1</show_in_default>
30
+ <show_in_website>1</show_in_website>
31
+ <show_in_store>1</show_in_store>
32
+ </msp_bancasella_hint>
33
+ </groups>
34
+ </payment>
35
+
36
+ <msp_bancasella translate="label" module="msp_bancasella">
37
+ <label>BancaSella - Account Settings</label>
38
+ <class>msp-bancasella-section</class>
39
+ <header_css>msp-bancasella-header</header_css>
40
+ <tab>sales</tab>
41
+ <frontend_type>text</frontend_type>
42
+ <sort_order>350</sort_order>
43
+ <show_in_default>1</show_in_default>
44
+ <show_in_website>1</show_in_website>
45
+ <show_in_store>1</show_in_store>
46
+ <groups>
47
+ <hint>
48
+ <frontend_model>msp_bancasella/adminhtml_system_config_fieldset_hint_account</frontend_model>
49
+ <sort_order>0</sort_order>
50
+ <show_in_default>1</show_in_default>
51
+ <show_in_website>1</show_in_website>
52
+ <show_in_store>1</show_in_store>
53
+ </hint>
54
+
55
+ <account>
56
+ <label>Account</label>
57
+ <sort_order>10</sort_order>
58
+ <show_in_default>1</show_in_default>
59
+ <show_in_website>1</show_in_website>
60
+ <show_in_store>1</show_in_store>
61
+ <fields>
62
+ <test-mode translate="label">
63
+ <label>Test Mode</label>
64
+ <frontend_type>select</frontend_type>
65
+ <source_model>adminhtml/system_config_source_yesno</source_model>
66
+ <sort_order>10</sort_order>
67
+ <show_in_default>1</show_in_default>
68
+ <show_in_website>1</show_in_website>
69
+ <show_in_store>0</show_in_store>
70
+ </test-mode>
71
+ <language>
72
+ <label>Language</label>
73
+ <frontend_type>select</frontend_type>
74
+ <source_model>msp_bancasella/adminhtml_system_config_source_language</source_model>
75
+ <sort_order>15</sort_order>
76
+ <show_in_default>1</show_in_default>
77
+ <show_in_website>1</show_in_website>
78
+ <show_in_store>1</show_in_store>
79
+ </language>
80
+ <order-prefix translate="label">
81
+ <label>Order Prefix</label>
82
+ <frontend_type>text</frontend_type>
83
+ <comment>Useful to avoid duplicates on multiple installations</comment>
84
+ <sort_order>20</sort_order>
85
+ <show_in_default>1</show_in_default>
86
+ <show_in_website>1</show_in_website>
87
+ <show_in_store>0</show_in_store>
88
+ </order-prefix>
89
+ <merchant translate="label">
90
+ <label>Merchant code</label>
91
+ <frontend_type>text</frontend_type>
92
+ <sort_order>60</sort_order>
93
+ <show_in_default>1</show_in_default>
94
+ <show_in_website>1</show_in_website>
95
+ <show_in_store>0</show_in_store>
96
+ </merchant>
97
+ <login translate="label">
98
+ <label>Merchant login</label>
99
+ <frontend_type>text</frontend_type>
100
+ <sort_order>70</sort_order>
101
+ <show_in_default>1</show_in_default>
102
+ <show_in_website>1</show_in_website>
103
+ <show_in_store>0</show_in_store>
104
+ </login>
105
+ <password translate="label">
106
+ <label>Merchant password</label>
107
+ <frontend_type>password</frontend_type>
108
+ <sort_order>80</sort_order>
109
+ <show_in_default>1</show_in_default>
110
+ <show_in_website>1</show_in_website>
111
+ <show_in_store>0</show_in_store>
112
+ </password>
113
+ <currency-code translate="label">
114
+ <label>Currency Code</label>
115
+ <frontend_type>select</frontend_type>
116
+ <source_model>msp_bancasella/adminhtml_system_config_source_uic</source_model>
117
+ <show_in_default>1</show_in_default>
118
+ <show_in_website>1</show_in_website>
119
+ <show_in_store>0</show_in_store>
120
+ </currency-code>
121
+
122
+ <credits>
123
+ <frontend_model>msp_common/adminhtml_system_config_fieldset_hint_credits</frontend_model>
124
+ <sort_order>999</sort_order>
125
+ <show_in_default>1</show_in_default>
126
+ <show_in_website>1</show_in_website>
127
+ <show_in_store>1</show_in_store>
128
+ </credits>
129
+ </fields>
130
+ </account>
131
+
132
+ <fields>
133
+ <label>Fields configuration</label>
134
+ <sort_order>20</sort_order>
135
+ <show_in_default>1</show_in_default>
136
+ <show_in_website>1</show_in_website>
137
+ <show_in_store>1</show_in_store>
138
+ <fields>
139
+ <buyer-name translate="label">
140
+ <label>Send Customer Name</label>
141
+ <frontend_type>select</frontend_type>
142
+ <source_model>adminhtml/system_config_source_yesno</source_model>
143
+ <sort_order>10</sort_order>
144
+ <show_in_default>1</show_in_default>
145
+ <show_in_website>1</show_in_website>
146
+ <show_in_store>0</show_in_store>
147
+ <comment>Must be enabled in your Bancasella account</comment>
148
+ </buyer-name>
149
+ <buyer-email>
150
+ <label>Send Customer Email</label>
151
+ <frontend_type>select</frontend_type>
152
+ <source_model>adminhtml/system_config_source_yesno</source_model>
153
+ <sort_order>15</sort_order>
154
+ <show_in_default>1</show_in_default>
155
+ <show_in_website>1</show_in_website>
156
+ <show_in_store>1</show_in_store>
157
+ <comment>Must be enabled in your Bancasella account</comment>
158
+ </buyer-email>
159
+ <language>
160
+ <label>Send Language</label>
161
+ <frontend_type>select</frontend_type>
162
+ <source_model>adminhtml/system_config_source_yesno</source_model>
163
+ <sort_order>20</sort_order>
164
+ <show_in_default>1</show_in_default>
165
+ <show_in_website>1</show_in_website>
166
+ <show_in_store>1</show_in_store>
167
+ <comment>Must be enabled in your Bancasella account</comment>
168
+ </language>
169
+
170
+ <credits>
171
+ <frontend_model>msp_common/adminhtml_system_config_fieldset_hint_credits</frontend_model>
172
+ <sort_order>999</sort_order>
173
+ <show_in_default>1</show_in_default>
174
+ <show_in_website>1</show_in_website>
175
+ <show_in_store>1</show_in_store>
176
+ </credits>
177
+ </fields>
178
+ </fields>
179
+ </groups>
180
+ </msp_bancasella>
181
+
182
+ <payment>
183
+ <groups>
184
+ <msp_bancasella_gateway translate="label">
185
+ <label>BancaSella GestPay</label>
186
+ <sort_order>900</sort_order>
187
+ <show_in_default>1</show_in_default>
188
+ <show_in_website>1</show_in_website>
189
+ <show_in_store>1</show_in_store>
190
+ <fields>
191
+ <active translate="label">
192
+ <label>Active</label>
193
+ <frontend_type>select</frontend_type>
194
+ <source_model>adminhtml/system_config_source_yesno</source_model>
195
+ <sort_order>10</sort_order>
196
+ <show_in_default>1</show_in_default>
197
+ <show_in_website>1</show_in_website>
198
+ <show_in_store>0</show_in_store>
199
+ </active>
200
+ <title translate="label">
201
+ <label>Title</label>
202
+ <frontend_type>text</frontend_type>
203
+ <sort_order>20</sort_order>
204
+ <show_in_default>1</show_in_default>
205
+ <show_in_website>1</show_in_website>
206
+ <show_in_store>1</show_in_store>
207
+ </title>
208
+ <sort_order translate="label">
209
+ <label>Sort Order</label>
210
+ <frontend_type>text</frontend_type>
211
+ <sort_order>25</sort_order>
212
+ <show_in_default>1</show_in_default>
213
+ <show_in_website>1</show_in_website>
214
+ <show_in_store>1</show_in_store>
215
+ </sort_order>
216
+ <order_status translate="label">
217
+ <label>New order status</label>
218
+ <frontend_type>select</frontend_type>
219
+ <source_model>adminhtml/system_config_source_order_status_newprocessing</source_model>
220
+ <sort_order>30</sort_order>
221
+ <show_in_default>1</show_in_default>
222
+ <show_in_website>1</show_in_website>
223
+ <show_in_store>0</show_in_store>
224
+ </order_status>
225
+ <allowspecific translate="label">
226
+ <label>Payment from applicable countries</label>
227
+ <frontend_type>allowspecific</frontend_type>
228
+ <sort_order>40</sort_order>
229
+ <source_model>adminhtml/system_config_source_payment_allspecificcountries</source_model>
230
+ <show_in_default>1</show_in_default>
231
+ <show_in_website>1</show_in_website>
232
+ <show_in_store>0</show_in_store>
233
+ </allowspecific>
234
+ <specificcountry translate="label">
235
+ <label>Payment from Specific countries</label>
236
+ <frontend_type>multiselect</frontend_type>
237
+ <sort_order>50</sort_order>
238
+ <source_model>adminhtml/system_config_source_country</source_model>
239
+ <show_in_default>1</show_in_default>
240
+ <show_in_website>1</show_in_website>
241
+ <show_in_store>0</show_in_store>
242
+ </specificcountry>
243
+ <payment_action translate="label">
244
+ <label>Payment Action</label>
245
+ <frontend_type>select</frontend_type>
246
+ <source_model>paygate/authorizenet_source_paymentAction</source_model>
247
+ <sort_order>60</sort_order>
248
+ <show_in_default>1</show_in_default>
249
+ <show_in_website>1</show_in_website>
250
+ <show_in_store>0</show_in_store>
251
+ </payment_action>
252
+ <min_order_total translate="label">
253
+ <label>Minimum Order Total</label>
254
+ <frontend_type>text</frontend_type>
255
+ <sort_order>100</sort_order>
256
+ <show_in_default>1</show_in_default>
257
+ <show_in_website>1</show_in_website>
258
+ <show_in_store>0</show_in_store>
259
+ </min_order_total>
260
+ <max_order_total translate="label">
261
+ <label>Maximum Order Total</label>
262
+ <frontend_type>text</frontend_type>
263
+ <sort_order>110</sort_order>
264
+ <show_in_default>1</show_in_default>
265
+ <show_in_website>1</show_in_website>
266
+ <show_in_store>0</show_in_store>
267
+ </max_order_total>
268
+ <credits>
269
+ <frontend_model>msp_common/adminhtml_system_config_fieldset_hint_credits</frontend_model>
270
+ <sort_order>999</sort_order>
271
+ <show_in_default>1</show_in_default>
272
+ <show_in_website>1</show_in_website>
273
+ <show_in_store>1</show_in_store>
274
+ </credits>
275
+ </fields>
276
+ </msp_bancasella_gateway>
277
+ </groups>
278
+ </payment>
279
+ </sections>
280
+ </config>
app/code/community/MSP/Bancasella/lib/nusoap.php ADDED
@@ -0,0 +1,8212 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+
3
+ <?php
4
+
5
+ /*
6
+ $Id: fsource_nusoap__nusoap.php.html,v 1.2 2010/04/26 20:25:21 snichol Exp $
7
+
8
+ NuSOAP - Web Services Toolkit for PHP
9
+
10
+ Copyright (c) 2002 NuSphere Corporation
11
+
12
+ This library is free software; you can redistribute it and/or
13
+ modify it under the terms of the GNU Lesser General Public
14
+ License as published by the Free Software Foundation; either
15
+ version 2.1 of the License, or (at your option) any later version.
16
+
17
+ This library is distributed in the hope that it will be useful,
18
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
19
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20
+ Lesser General Public License for more details.
21
+
22
+ You should have received a copy of the GNU Lesser General Public
23
+ License along with this library; if not, write to the Free Software
24
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25
+
26
+ The NuSOAP project home is:
27
+ http://sourceforge.net/projects/nusoap/
28
+
29
+ The primary support for NuSOAP is the Help forum on the project home page.
30
+
31
+ If you have any questions or comments, please email:
32
+
33
+ Dietrich Ayala
34
+ dietrich@ganx4.com
35
+ http://dietrich.ganx4.com/nusoap
36
+
37
+ NuSphere Corporation
38
+ http://www.nusphere.com
39
+
40
+ */
41
+
42
+ /*
43
+ * Some of the standards implmented in whole or part by NuSOAP:
44
+ *
45
+ * SOAP 1.1 (http://www.w3.org/TR/2000/NOTE-SOAP-20000508/)
46
+ * WSDL 1.1 (http://www.w3.org/TR/2001/NOTE-wsdl-20010315)
47
+ * SOAP Messages With Attachments (http://www.w3.org/TR/SOAP-attachments)
48
+ * XML 1.0 (http://www.w3.org/TR/2006/REC-xml-20060816/)
49
+ * Namespaces in XML 1.0 (http://www.w3.org/TR/2006/REC-xml-names-20060816/)
50
+ * XML Schema 1.0 (http://www.w3.org/TR/xmlschema-0/)
51
+ * RFC 2045 Multipurpose Internet Mail Extensions (MIME) Part One: Format of Internet Message Bodies
52
+ * RFC 2068 Hypertext Transfer Protocol -- HTTP/1.1
53
+ * RFC 2617 HTTP Authentication: Basic and Digest Access Authentication
54
+ */
55
+
56
+ /* load classes
57
+ // necessary classes
58
+ require_once('class.soapclient.php');
59
+ require_once('class.soap_val.php');
60
+ require_once('class.soap_parser.php');
61
+ require_once('class.soap_fault.php');
62
+
63
+ // transport classes
64
+ require_once('class.soap_transport_http.php');
65
+
66
+ // optional add-on classes
67
+ require_once('class.xmlschema.php');
68
+ require_once('class.wsdl.php');
69
+
70
+ // server class
71
+ require_once('class.soap_server.php');*/
72
+
73
+ // class variable emulation
74
+ // cf. http://www.webkreator.com/php/techniques/php-static-class-variables.html
75
+
76
+ $GLOBALS['_transient']['static']['nusoap_base']['globalDebugLevel'] = 9;
77
+
78
+ /**
79
+ *
80
+ * nusoap_base
81
+ *
82
+ * @author Dietrich Ayala <dietrich@ganx4.com>
83
+ * @author Scott Nichol <snichol@users.sourceforge.net>
84
+ * @version $Id: fsource_nusoap__nusoap.php.html,v 1.2 2010/04/26 20:25:21 snichol Exp $
85
+ * @access public
86
+ */
87
+ class nusoap_base {
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.2 $';
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
+
158
+ /**
159
+ * namespaces in an array of prefix => uri
160
+ *
161
+ * this is "seeded" by a set of constants, but it may be altered by code
162
+ *
163
+ * @var array
164
+ * @access public
165
+ */
166
+ var $namespaces = array(
167
+ 'SOAP-ENV' => 'http://schemas.xmlsoap.org/soap/envelope/',
168
+ 'xsd' => 'http://www.w3.org/2001/XMLSchema',
169
+ 'xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
170
+ 'SOAP-ENC' => 'http://schemas.xmlsoap.org/soap/encoding/'
171
+ );
172
+
173
+ /**
174
+ * namespaces used in the current context, e.g. during serialization
175
+ *
176
+ * @var array
177
+ * @access private
178
+ */
179
+ var $usedNamespaces = array();
180
+
181
+ /**
182
+ * XML Schema types in an array of uri => (array of xml type => php type)
183
+ * is this legacy yet?
184
+ * no, this is used by the nusoap_xmlschema class to verify type => namespace mappings.
185
+ * @var array
186
+ * @access public
187
+ */
188
+ var $typemap = array(
189
+ 'http://www.w3.org/2001/XMLSchema' => array(
190
+ 'string'=>'string','boolean'=>'boolean','float'=>'double','double'=>'double','decimal'=>'double',
191
+ 'duration'=>'','dateTime'=>'string','time'=>'string','date'=>'string','gYearMonth'=>'',
192
+ 'gYear'=>'','gMonthDay'=>'','gDay'=>'','gMonth'=>'','hexBinary'=>'string','base64Binary'=>'string',
193
+ // abstract "any" types
194
+
195
+ 'anyType'=>'string','anySimpleType'=>'string',
196
+ // derived datatypes
197
+
198
+ 'normalizedString'=>'string','token'=>'string','language'=>'','NMTOKEN'=>'','NMTOKENS'=>'','Name'=>'','NCName'=>'','ID'=>'',
199
+ 'IDREF'=>'','IDREFS'=>'','ENTITY'=>'','ENTITIES'=>'','integer'=>'integer','nonPositiveInteger'=>'integer',
200
+ 'negativeInteger'=>'integer','long'=>'integer','int'=>'integer','short'=>'integer','byte'=>'integer','nonNegativeInteger'=>'integer',
201
+ 'unsignedLong'=>'','unsignedInt'=>'','unsignedShort'=>'','unsignedByte'=>'','positiveInteger'=>''),
202
+ 'http://www.w3.org/2000/10/XMLSchema' => array(
203
+ 'i4'=>'','int'=>'integer','boolean'=>'boolean','string'=>'string','double'=>'double',
204
+ 'float'=>'double','dateTime'=>'string',
205
+ 'timeInstant'=>'string','base64Binary'=>'string','base64'=>'string','ur-type'=>'array'),
206
+ 'http://www.w3.org/1999/XMLSchema' => array(
207
+ 'i4'=>'','int'=>'integer','boolean'=>'boolean','string'=>'string','double'=>'double',
208
+ 'float'=>'double','dateTime'=>'string',
209
+ 'timeInstant'=>'string','base64Binary'=>'string','base64'=>'string','ur-type'=>'array'),
210
+ 'http://soapinterop.org/xsd' => array('SOAPStruct'=>'struct'),
211
+ 'http://schemas.xmlsoap.org/soap/encoding/' => array('base64'=>'string','array'=>'array','Array'=>'array'),
212
+ 'http://xml.apache.org/xml-soap' => array('Map')
213
+ );
214
+
215
+ /**
216
+ * XML entities to convert
217
+ *
218
+ * @var array
219
+ * @access public
220
+ * @deprecated
221
+ * @see expandEntities
222
+ */
223
+ var $xmlEntities = array('quot' => '"','amp' => '&',
224
+ 'lt' => '<','gt' => '>','apos' => "'");
225
+
226
+ /**
227
+ * constructor
228
+ *
229
+ * @access public
230
+ */
231
+ function nusoap_base() {
232
+ $this->debugLevel = $GLOBALS['_transient']['static']['nusoap_base']['globalDebugLevel'];
233
+ }
234
+
235
+ /**
236
+ * gets the global debug level, which applies to future instances
237
+ *
238
+ * @return integer Debug level 0-9, where 0 turns off
239
+ * @access public
240
+ */
241
+ function getGlobalDebugLevel() {
242
+ return $GLOBALS['_transient']['static']['nusoap_base']['globalDebugLevel'];
243
+ }
244
+
245
+ /**
246
+ * sets the global debug level, which applies to future instances
247
+ *
248
+ * @param int $level Debug level 0-9, where 0 turns off
249
+ * @access public
250
+ */
251
+ function setGlobalDebugLevel($level) {
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
+ return $this->debugLevel;
263
+ }
264
+
265
+ /**
266
+ * sets the debug level for this instance
267
+ *
268
+ * @param int $level Debug level 0-9, where 0 turns off
269
+ * @access public
270
+ */
271
+ function setDebugLevel($level) {
272
+ $this->debugLevel = $level;
273
+ }
274
+
275
+ /**
276
+ * adds debug data to the instance debug string with formatting
277
+ *
278
+ * @param string $string debug data
279
+ * @access private
280
+ */
281
+ function debug($string){
282
+ if ($this->debugLevel > 0) {
283
+ $this->appendDebug($this->getmicrotime().' '.get_class($this).": $string\n");
284
+ }
285
+ }
286
+
287
+ /**
288
+ * adds debug data to the instance debug string without formatting
289
+ *
290
+ * @param string $string debug data
291
+ * @access public
292
+ */
293
+ function appendDebug($string){
294
+ if ($this->debugLevel > 0) {
295
+ // it would be nice to use a memory stream here to use
296
+ // memory more efficiently
297
+ $this->debug_str .= $string;
298
+ }
299
+ }
300
+
301
+ /**
302
+ * clears the current debug data for this instance
303
+ *
304
+ * @access public
305
+ */
306
+ function clearDebug() {
307
+ // it would be nice to use a memory stream here to use
308
+ // memory more efficiently
309
+ $this->debug_str = '';
310
+ }
311
+
312
+ /**
313
+ * gets the current debug data for this instance
314
+ *
315
+ * @return debug data
316
+ * @access public
317
+ */
318
+ function &getDebug() {
319
+ // it would be nice to use a memory stream here to use
320
+ // memory more efficiently
321
+ return $this->debug_str;
322
+ }
323
+
324
+ /**
325
+ * gets the current debug data for this instance as an XML comment
326
+ * this may change the contents of the debug data
327
+ *
328
+ * @return debug data as an XML comment
329
+ * @access public
330
+ */
331
+ function &getDebugAsXMLComment() {
332
+ // it would be nice to use a memory stream here to use
333
+ // memory more efficiently
334
+ while (strpos($this->debug_str, '--')) {
335
+ $this->debug_str = str_replace('--', '- -', $this->debug_str);
336
+ }
337
+ $ret = "<!--\n" . $this->debug_str . "\n-->";
338
+ return $ret;
339
+ }
340
+
341
+ /**
342
+ * expands entities, e.g. changes '<' to '&lt;'.
343
+ *
344
+ * @param string $val The string in which to expand entities.
345
+ * @access private
346
+ */
347
+ function expandEntities($val) {
348
+ if ($this->charencoding) {
349
+ $val = str_replace('&', '&amp;', $val);
350
+ $val = str_replace("'", '&apos;', $val);
351
+ $val = str_replace('"', '&quot;', $val);
352
+ $val = str_replace('<', '&lt;', $val);
353
+ $val = str_replace('>', '&gt;', $val);
354
+ }
355
+ return $val;
356
+ }
357
+
358
+ /**
359
+ * returns error string if present
360
+ *
361
+ * @return mixed error string or false
362
+ * @access public
363
+ */
364
+ function getError(){
365
+ if($this->error_str != ''){
366
+ return $this->error_str;
367
+ }
368
+ return false;
369
+ }
370
+
371
+ /**
372
+ * sets error string
373
+ *
374
+ * @return boolean $string error string
375
+ * @access private
376
+ */
377
+ function setError($str){
378
+ $this->error_str = $str;
379
+ }
380
+
381
+ /**
382
+ * detect if array is a simple array or a struct (associative array)
383
+ *
384
+ * @param mixed $val The PHP array
385
+ * @return string (arraySimple|arrayStruct)
386
+ * @access private
387
+ */
388
+ function isArraySimpleOrStruct($val) {
389
+ $keyList = array_keys($val);
390
+ foreach ($keyList as $keyListValue) {
391
+ if (!is_int($keyListValue)) {
392
+ return 'arrayStruct';
393
+ }
394
+ }
395
+ return 'arraySimple';
396
+ }
397
+
398
+ /**
399
+ * serializes PHP values in accordance w/ section 5. Type information is
400
+ * not serialized if $use == 'literal'.
401
+ *
402
+ * @param mixed $val The value to serialize
403
+ * @param string $name The name (local part) of the XML element
404
+ * @param string $type The XML schema type (local part) for the element
405
+ * @param string $name_ns The namespace for the name of the XML element
406
+ * @param string $type_ns The namespace for the type of the element
407
+ * @param array $attributes The attributes to serialize as name=>value pairs
408
+ * @param string $use The WSDL "use" (encoded|literal)
409
+ * @param boolean $soapval Whether this is called from soapval.
410
+ * @return string The serialized element, possibly with child elements
411
+ * @access public
412
+ */
413
+ function serialize_val($val,$name=false,$type=false,$name_ns=false,$type_ns=false,$attributes=false,$use='encoded',$soapval=false) {
414
+ $this->debug("in serialize_val: name=$name, type=$type, name_ns=$name_ns, type_ns=$type_ns, use=$use, soapval=$soapval");
415
+ $this->appendDebug('value=' . $this->varDump($val));
416
+ $this->appendDebug('attributes=' . $this->varDump($attributes));
417
+
418
+ if (is_object($val) && get_class($val) == 'soapval' && (! $soapval)) {
419
+ $this->debug("serialize_val: serialize soapval");
420
+ $xml = $val->serialize($use);
421
+ $this->appendDebug($val->getDebug());
422
+ $val->clearDebug();
423
+ $this->debug("serialize_val of soapval returning $xml");
424
+ return $xml;
425
+ }
426
+ // force valid name if necessary
427
+ if (is_numeric($name)) {
428
+ $name = '__numeric_' . $name;
429
+ } elseif (! $name) {
430
+ $name = 'noname';
431
+ }
432
+ // if name has ns, add ns prefix to name
433
+ $xmlns = '';
434
+ if($name_ns){
435
+ $prefix = 'nu'.rand(1000,9999);
436
+ $name = $prefix.':'.$name;
437
+ $xmlns .= " xmlns:$prefix=\"$name_ns\"";
438
+ }
439
+ // if type is prefixed, create type prefix
440
+ if($type_ns != '' && $type_ns == $this->namespaces['xsd']){
441
+ // need to fix this. shouldn't default to xsd if no ns specified
442
+ // w/o checking against typemap
443
+ $type_prefix = 'xsd';
444
+ } elseif($type_ns){
445
+ $type_prefix = 'ns'.rand(1000,9999);
446
+ $xmlns .= " xmlns:$type_prefix=\"$type_ns\"";
447
+ }
448
+ // serialize attributes if present
449
+ $atts = '';
450
+ if($attributes){
451
+ foreach($attributes as $k => $v){
452
+ $atts .= " $k=\"".$this->expandEntities($v).'"';
453
+ }
454
+ }
455
+ // serialize null value
456
+ if (is_null($val)) {
457
+ $this->debug("serialize_val: serialize null");
458
+ if ($use == 'literal') {
459
+ // TODO: depends on minOccurs
460
+ $xml = "<$name$xmlns$atts/>";
461
+ $this->debug("serialize_val returning $xml");
462
+ return $xml;
463
+ } else {
464
+ if (isset($type) && isset($type_prefix)) {
465
+ $type_str = " xsi:type=\"$type_prefix:$type\"";
466
+ } else {
467
+ $type_str = '';
468
+ }
469
+ $xml = "<$name$xmlns$type_str$atts xsi:nil=\"true\"/>";
470
+ $this->debug("serialize_val returning $xml");
471
+ return $xml;
472
+ }
473
+ }
474
+ // serialize if an xsd built-in primitive type
475
+ if($type != '' && isset($this->typemap[$this->XMLSchemaVersion][$type])){
476
+ $this->debug("serialize_val: serialize xsd built-in primitive type");
477
+ if (is_bool($val)) {
478
+ if ($type == 'boolean') {
479
+ $val = $val ? 'true' : 'false';
480
+ } elseif (! $val) {
481
+ $val = 0;
482
+ }
483
+ } else if (is_string($val)) {
484
+ $val = $this->expandEntities($val);
485
+ }
486
+ if ($use == 'literal') {
487
+ $xml = "<$name$xmlns$atts>$val</$name>";
488
+ $this->debug("serialize_val returning $xml");
489
+ return $xml;
490
+ } else {
491
+ $xml = "<$name$xmlns xsi:type=\"xsd:$type\"$atts>$val</$name>";
492
+ $this->debug("serialize_val returning $xml");
493
+ return $xml;
494
+ }
495
+ }
496
+ // detect type and serialize
497
+ $xml = '';
498
+ switch(true) {
499
+ case (is_bool($val) || $type == 'boolean'):
500
+ $this->debug("serialize_val: serialize boolean");
501
+ if ($type == 'boolean') {
502
+ $val = $val ? 'true' : 'false';
503
+ } elseif (! $val) {
504
+ $val = 0;
505
+ }
506
+ if ($use == 'literal') {
507
+ $xml .= "<$name$xmlns$atts>$val</$name>";
508
+ } else {
509
+ $xml .= "<$name$xmlns xsi:type=\"xsd:boolean\"$atts>$val</$name>";
510
+ }
511
+ break;
512
+ case (is_int($val) || is_long($val) || $type == 'int'):
513
+ $this->debug("serialize_val: serialize int");
514
+ if ($use == 'literal') {
515
+ $xml .= "<$name$xmlns$atts>$val</$name>";
516
+ } else {
517
+ $xml .= "<$name$xmlns xsi:type=\"xsd:int\"$atts>$val</$name>";
518
+ }
519
+ break;
520
+ case (is_float($val)|| is_double($val) || $type == 'float'):
521
+ $this->debug("serialize_val: serialize float");
522
+ if ($use == 'literal') {
523
+ $xml .= "<$name$xmlns$atts>$val</$name>";
524
+ } else {
525
+ $xml .= "<$name$xmlns xsi:type=\"xsd:float\"$atts>$val</$name>";
526
+ }
527
+ break;
528
+ case (is_string($val) || $type == 'string'):
529
+ $this->debug("serialize_val: serialize string");
530
+ $val = $this->expandEntities($val);
531
+ if ($use == 'literal') {
532
+ $xml .= "<$name$xmlns$atts>$val</$name>";
533
+ } else {
534
+ $xml .= "<$name$xmlns xsi:type=\"xsd:string\"$atts>$val</$name>";
535
+ }
536
+ break;
537
+ case is_object($val):
538
+ $this->debug("serialize_val: serialize object");
539
+ if (get_class($val) == 'soapval') {
540
+ $this->debug("serialize_val: serialize soapval object");
541
+ $pXml = $val->serialize($use);
542
+ $this->appendDebug($val->getDebug());
543
+ $val->clearDebug();
544
+ } else {
545
+ if (! $name) {
546
+ $name = get_class($val);
547
+ $this->debug("In serialize_val, used class name $name as element name");
548
+ } else {
549
+ $this->debug("In serialize_val, do not override name $name for element name for class " . get_class($val));
550
+ }
551
+ foreach(get_object_vars($val) as $k => $v){
552
+ $pXml = isset($pXml) ? $pXml.$this->serialize_val($v,$k,false,false,false,false,$use) : $this->serialize_val($v,$k,false,false,false,false,$use);
553
+ }
554
+ }
555
+ if(isset($type) && isset($type_prefix)){
556
+ $type_str = " xsi:type=\"$type_prefix:$type\"";
557
+ } else {
558
+ $type_str = '';
559
+ }
560
+ if ($use == 'literal') {
561
+ $xml .= "<$name$xmlns$atts>$pXml</$name>";
562
+ } else {
563
+ $xml .= "<$name$xmlns$type_str$atts>$pXml</$name>";
564
+ }
565
+ break;
566
+ break;
567
+ case (is_array($val) || $type):
568
+ // detect if struct or array
569
+ $valueType = $this->isArraySimpleOrStruct($val);
570
+ if($valueType=='arraySimple' || preg_match('/^ArrayOf/',$type)){
571
+ $this->debug("serialize_val: serialize array");
572
+ $i = 0;
573
+ if(is_array($val) && count($val)> 0){
574
+ foreach($val as $v){
575
+ if(is_object($v) && get_class($v) == 'soapval'){
576
+ $tt_ns = $v->type_ns;
577
+ $tt = $v->type;
578
+ } elseif (is_array($v)) {
579
+ $tt = $this->isArraySimpleOrStruct($v);
580
+ } else {
581
+ $tt = gettype($v);
582
+ }
583
+ $array_types[$tt] = 1;
584
+ // TODO: for literal, the name should be $name
585
+ $xml .= $this->serialize_val($v,'item',false,false,false,false,$use);
586
+ ++$i;
587
+ }
588
+ if(count($array_types) > 1){
589
+ $array_typename = 'xsd:anyType';
590
+ } elseif(isset($tt) && isset($this->typemap[$this->XMLSchemaVersion][$tt])) {
591
+ if ($tt == 'integer') {
592
+ $tt = 'int';
593
+ }
594
+ $array_typename = 'xsd:'.$tt;
595
+ } elseif(isset($tt) && $tt == 'arraySimple'){
596
+ $array_typename = 'SOAP-ENC:Array';
597
+ } elseif(isset($tt) && $tt == 'arrayStruct'){
598
+ $array_typename = 'unnamed_struct_use_soapval';
599
+ } else {
600
+ // if type is prefixed, create type prefix
601
+ if ($tt_ns != '' && $tt_ns == $this->namespaces['xsd']){
602
+ $array_typename = 'xsd:' . $tt;
603
+ } elseif ($tt_ns) {
604
+ $tt_prefix = 'ns' . rand(1000, 9999);
605
+ $array_typename = "$tt_prefix:$tt";
606
+ $xmlns .= " xmlns:$tt_prefix=\"$tt_ns\"";
607
+ } else {
608
+ $array_typename = $tt;
609
+ }
610
+ }
611
+ $array_type = $i;
612
+ if ($use == 'literal') {
613
+ $type_str = '';
614
+ } else if (isset($type) && isset($type_prefix)) {
615
+ $type_str = " xsi:type=\"$type_prefix:$type\"";
616
+ } else {
617
+ $type_str = " xsi:type=\"SOAP-ENC:Array\" SOAP-ENC:arrayType=\"".$array_typename."[$array_type]\"";
618
+ }
619
+ // empty array
620
+ } else {
621
+ if ($use == 'literal') {
622
+ $type_str = '';
623
+ } else if (isset($type) && isset($type_prefix)) {
624
+ $type_str = " xsi:type=\"$type_prefix:$type\"";
625
+ } else {
626
+ $type_str = " xsi:type=\"SOAP-ENC:Array\" SOAP-ENC:arrayType=\"xsd:anyType[0]\"";
627
+ }
628
+ }
629
+ // TODO: for array in literal, there is no wrapper here
630
+ $xml = "<$name$xmlns$type_str$atts>".$xml."</$name>";
631
+ } else {
632
+ // got a struct
633
+ $this->debug("serialize_val: serialize struct");
634
+ if(isset($type) && isset($type_prefix)){
635
+ $type_str = " xsi:type=\"$type_prefix:$type\"";
636
+ } else {
637
+ $type_str = '';
638
+ }
639
+ if ($use == 'literal') {
640
+ $xml .= "<$name$xmlns$atts>";
641
+ } else {
642
+ $xml .= "<$name$xmlns$type_str$atts>";
643
+ }
644
+ foreach($val as $k => $v){
645
+ // Apache Map
646
+ if ($type == 'Map' && $type_ns == 'http://xml.apache.org/xml-soap') {
647
+ $xml .= '<item>';
648
+ $xml .= $this->serialize_val($k,'key',false,false,false,false,$use);
649
+ $xml .= $this->serialize_val($v,'value',false,false,false,false,$use);
650
+ $xml .= '</item>';
651
+ } else {
652
+ $xml .= $this->serialize_val($v,$k,false,false,false,false,$use);
653
+ }
654
+ }
655
+ $xml .= "</$name>";
656
+ }
657
+ break;
658
+ default:
659
+ $this->debug("serialize_val: serialize unknown");
660
+ $xml .= 'not detected, got '.gettype($val).' for '.$val;
661
+ break;
662
+ }
663
+ $this->debug("serialize_val returning $xml");
664
+ return $xml;
665
+ }
666
+
667
+ /**
668
+ * serializes a message
669
+ *
670
+ * @param string $body the XML of the SOAP body
671
+ * @param mixed $headers optional string of XML with SOAP header content, or array of soapval objects for SOAP headers, or associative array
672
+ * @param array $namespaces optional the namespaces used in generating the body and headers
673
+ * @param string $style optional (rpc|document)
674
+ * @param string $use optional (encoded|literal)
675
+ * @param string $encodingStyle optional (usually 'http://schemas.xmlsoap.org/soap/encoding/' for encoded)
676
+ * @return string the message
677
+ * @access public
678
+ */
679
+ function serializeEnvelope($body,$headers=false,$namespaces=array(),$style='rpc',$use='encoded',$encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'){
680
+ // TODO: add an option to automatically run utf8_encode on $body and $headers
681
+ // if $this->soap_defencoding is UTF-8. Not doing this automatically allows
682
+ // one to send arbitrary UTF-8 characters, not just characters that map to ISO-8859-1
683
+
684
+ $this->debug("In serializeEnvelope length=" . strlen($body) . " body (max 1000 characters)=" . substr($body, 0, 1000) . " style=$style use=$use encodingStyle=$encodingStyle");
685
+ $this->debug("headers:");
686
+ $this->appendDebug($this->varDump($headers));
687
+ $this->debug("namespaces:");
688
+ $this->appendDebug($this->varDump($namespaces));
689
+
690
+ // serialize namespaces
691
+ $ns_string = '';
692
+ foreach(array_merge($this->namespaces,$namespaces) as $k => $v){
693
+ $ns_string .= " xmlns:$k=\"$v\"";
694
+ }
695
+ if($encodingStyle) {
696
+ $ns_string = " SOAP-ENV:encodingStyle=\"$encodingStyle\"$ns_string";
697
+ }
698
+
699
+ // serialize headers
700
+ if($headers){
701
+ if (is_array($headers)) {
702
+ $xml = '';
703
+ foreach ($headers as $k => $v) {
704
+ if (is_object($v) && get_class($v) == 'soapval') {
705
+ $xml .= $this->serialize_val($v, false, false, false, false, false, $use);
706
+ } else {
707
+ $xml .= $this->serialize_val($v, $k, false, false, false, false, $use);
708
+ }
709
+ }
710
+ $headers = $xml;
711
+ $this->debug("In serializeEnvelope, serialized array of headers to $headers");
712
+ }
713
+ $headers = "<SOAP-ENV:Header>".$headers."</SOAP-ENV:Header>";
714
+ }
715
+ // serialize envelope
716
+ return
717
+ '<?xml version="1.0" encoding="'.$this->soap_defencoding .'"?'.">".
718
+ '<SOAP-ENV:Envelope'.$ns_string.">".
719
+ $headers.
720
+ "<SOAP-ENV:Body>".
721
+ $body.
722
+ "</SOAP-ENV:Body>".
723
+ "</SOAP-ENV:Envelope>";
724
+ }
725
+
726
+ /**
727
+ * formats a string to be inserted into an HTML stream
728
+ *
729
+ * @param string $str The string to format
730
+ * @return string The formatted string
731
+ * @access public
732
+ * @deprecated
733
+ */
734
+ function formatDump($str){
735
+ $str = htmlspecialchars($str);
736
+ return nl2br($str);
737
+ }
738
+
739
+ /**
740
+ * contracts (changes namespace to prefix) a qualified name
741
+ *
742
+ * @param string $qname qname
743
+ * @return string contracted qname
744
+ * @access private
745
+ */
746
+ function contractQname($qname){
747
+ // get element namespace
748
+ //$this->xdebug("Contract $qname");
749
+ if (strrpos($qname, ':')) {
750
+ // get unqualified name
751
+ $name = substr($qname, strrpos($qname, ':') + 1);
752
+ // get ns
753
+ $ns = substr($qname, 0, strrpos($qname, ':'));
754
+ $p = $this->getPrefixFromNamespace($ns);
755
+ if ($p) {
756
+ return $p . ':' . $name;
757
+ }
758
+ return $qname;
759
+ } else {
760
+ return $qname;
761
+ }
762
+ }
763
+
764
+ /**
765
+ * expands (changes prefix to namespace) a qualified name
766
+ *
767
+ * @param string $qname qname
768
+ * @return string expanded qname
769
+ * @access private
770
+ */
771
+ function expandQname($qname){
772
+ // get element prefix
773
+ if(strpos($qname,':') && !preg_match('/^http:\/\//',$qname)){
774
+ // get unqualified name
775
+ $name = substr(strstr($qname,':'),1);
776
+ // get ns prefix
777
+ $prefix = substr($qname,0,strpos($qname,':'));
778
+ if(isset($this->namespaces[$prefix])){
779
+ return $this->namespaces[$prefix].':'.$name;
780
+ } else {
781
+ return $qname;
782
+ }
783
+ } else {
784
+ return $qname;
785
+ }
786
+ }
787
+
788
+ /**
789
+ * returns the local part of a prefixed string
790
+ * returns the original string, if not prefixed
791
+ *
792
+ * @param string $str The prefixed string
793
+ * @return string The local part
794
+ * @access public
795
+ */
796
+ function getLocalPart($str){
797
+ if($sstr = strrchr($str,':')){
798
+ // get unqualified name
799
+ return substr( $sstr, 1 );
800
+ } else {
801
+ return $str;
802
+ }
803
+ }
804
+
805
+ /**
806
+ * returns the prefix part of a prefixed string
807
+ * returns false, if not prefixed
808
+ *
809
+ * @param string $str The prefixed string
810
+ * @return mixed The prefix or false if there is no prefix
811
+ * @access public
812
+ */
813
+ function getPrefix($str){
814
+ if($pos = strrpos($str,':')){
815
+ // get prefix
816
+ return substr($str,0,$pos);
817
+ }
818
+ return false;
819
+ }
820
+
821
+ /**
822
+ * pass it a prefix, it returns a namespace
823
+ *
824
+ * @param string $prefix The prefix
825
+ * @return mixed The namespace, false if no namespace has the specified prefix
826
+ * @access public
827
+ */
828
+ function getNamespaceFromPrefix($prefix){
829
+ if (isset($this->namespaces[$prefix])) {
830
+ return $this->namespaces[$prefix];
831
+ }
832
+ //$this->setError("No namespace registered for prefix '$prefix'");
833
+ return false;
834
+ }
835
+
836
+ /**
837
+ * returns the prefix for a given namespace (or prefix)
838
+ * or false if no prefixes registered for the given namespace
839
+ *
840
+ * @param string $ns The namespace
841
+ * @return mixed The prefix, false if the namespace has no prefixes
842
+ * @access public
843
+ */
844
+ function getPrefixFromNamespace($ns) {
845
+ foreach ($this->namespaces as $p => $n) {
846
+ if ($ns == $n || $ns == $p) {
847
+ $this->usedNamespaces[$p] = $n;
848
+ return $p;
849
+ }
850
+ }
851
+ return false;
852
+ }
853
+
854
+ /**
855
+ * returns the time in ODBC canonical form with microseconds
856
+ *
857
+ * @return string The time in ODBC canonical form with microseconds
858
+ * @access public
859
+ */
860
+ function getmicrotime() {
861
+ if (function_exists('gettimeofday')) {
862
+ $tod = gettimeofday();
863
+ $sec = $tod['sec'];
864
+ $usec = $tod['usec'];
865
+ } else {
866
+ $sec = time();
867
+ $usec = 0;
868
+ }
869
+ return strftime('%Y-%m-%d %H:%M:%S', $sec) . '.' . sprintf('%06d', $usec);
870
+ }
871
+
872
+ /**
873
+ * Returns a string with the output of var_dump
874
+ *
875
+ * @param mixed $data The variable to var_dump
876
+ * @return string The output of var_dump
877
+ * @access public
878
+ */
879
+ function varDump($data) {
880
+ ob_start();
881
+ var_dump($data);
882
+ $ret_val = ob_get_contents();
883
+ ob_end_clean();
884
+ return $ret_val;
885
+ }
886
+
887
+ /**
888
+ * represents the object as a string
889
+ *
890
+ * @return string
891
+ * @access public
892
+ */
893
+ function __toString() {
894
+ return $this->varDump($this);
895
+ }
896
+ }
897
+
898
+ // XML Schema Datatype Helper Functions
899
+ //xsd:dateTime helpers
900
+
901
+
902
+
903
+ /**
904
+ * convert unix timestamp to ISO 8601 compliant date string
905
+ *
906
+ * @param int $timestamp Unix time stamp
907
+ * @param boolean $utc Whether the time stamp is UTC or local
908
+ * @return mixed ISO 8601 date string or false
909
+ * @access public
910
+ */
911
+ function timestamp_to_iso8601($timestamp,$utc=true){
912
+ $datestr = date('Y-m-d\TH:i:sO',$timestamp);
913
+ $pos = strrpos($datestr, "+");
914
+ if ($pos === FALSE) {
915
+ $pos = strrpos($datestr, "-");
916
+ }
917
+ if ($pos !== FALSE) {
918
+ if (strlen($datestr) == $pos + 5) {
919
+ $datestr = substr($datestr, 0, $pos + 3) . ':' . substr($datestr, -2);
920
+ }
921
+ }
922
+ if($utc){
923
+ $pattern = '/'.
924
+ '([0-9]{4})-'. // centuries & years CCYY-
925
+ '([0-9]{2})-'. // months MM-
926
+ '([0-9]{2})'. // days DD
927
+ 'T'. // separator T
928
+ '([0-9]{2}):'. // hours hh:
929
+ '([0-9]{2}):'. // minutes mm:
930
+ '([0-9]{2})(\.[0-9]*)?'. // seconds ss.ss...
931
+ '(Z|[+\-][0-9]{2}:?[0-9]{2})?'. // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's
932
+ '/';
933
+
934
+ if(preg_match($pattern,$datestr,$regs)){
935
+ return sprintf('%04d-%02d-%02dT%02d:%02d:%02dZ',$regs[1],$regs[2],$regs[3],$regs[4],$regs[5],$regs[6]);
936
+ }
937
+ return false;
938
+ } else {
939
+ return $datestr;
940
+ }
941
+ }
942
+
943
+ /**
944
+ * convert ISO 8601 compliant date string to unix timestamp
945
+ *
946
+ * @param string $datestr ISO 8601 compliant date string
947
+ * @return mixed Unix timestamp (int) or false
948
+ * @access public
949
+ */
950
+ function iso8601_to_timestamp($datestr){
951
+ $pattern = '/'.
952
+ '([0-9]{4})-'. // centuries & years CCYY-
953
+ '([0-9]{2})-'. // months MM-
954
+ '([0-9]{2})'. // days DD
955
+ 'T'. // separator T
956
+ '([0-9]{2}):'. // hours hh:
957
+ '([0-9]{2}):'. // minutes mm:
958
+ '([0-9]{2})(\.[0-9]+)?'. // seconds ss.ss...
959
+ '(Z|[+\-][0-9]{2}:?[0-9]{2})?'. // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's
960
+ '/';
961
+ if(preg_match($pattern,$datestr,$regs)){
962
+ // not utc
963
+ if($regs[8] != 'Z'){
964
+ $op = substr($regs[8],0,1);
965
+ $h = substr($regs[8],1,2);
966
+ $m = substr($regs[8],strlen($regs[8])-2,2);
967
+ if($op == '-'){
968
+ $regs[4] = $regs[4] + $h;
969
+ $regs[5] = $regs[5] + $m;
970
+ } elseif($op == '+'){
971
+ $regs[4] = $regs[4] - $h;
972
+ $regs[5] = $regs[5] - $m;
973
+ }
974
+ }
975
+ return gmmktime($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]);
976
+ // return strtotime("$regs[1]-$regs[2]-$regs[3] $regs[4]:$regs[5]:$regs[6]Z");
977
+ } else {
978
+ return false;
979
+ }
980
+ }
981
+
982
+ /**
983
+ * sleeps some number of microseconds
984
+ *
985
+ * @param string $usec the number of microseconds to sleep
986
+ * @access public
987
+ * @deprecated
988
+ */
989
+ function usleepWindows($usec)
990
+ {
991
+ $start = gettimeofday();
992
+
993
+ do
994
+ {
995
+ $stop = gettimeofday();
996
+ $timePassed = 1000000 * ($stop['sec'] - $start['sec'])
997
+ + $stop['usec'] - $start['usec'];
998
+ }
999
+ while ($timePassed < $usec);
1000
+ }
1001
+
1002
+ ?><?php
1003
+
1004
+
1005
+
1006
+ /**
1007
+ * Contains information for a SOAP fault.
1008
+ * Mainly used for returning faults from deployed functions
1009
+ * in a server instance.
1010
+ * @author Dietrich Ayala <dietrich@ganx4.com>
1011
+ * @version $Id: fsource_nusoap__nusoap.php.html,v 1.2 2010/04/26 20:25:21 snichol Exp $
1012
+ * @access public
1013
+ */
1014
+ class nusoap_fault extends nusoap_base {
1015
+ /**
1016
+ * The fault code (client|server)
1017
+ * @var string
1018
+ * @access private
1019
+ */
1020
+ var $faultcode;
1021
+ /**
1022
+ * The fault actor
1023
+ * @var string
1024
+ * @access private
1025
+ */
1026
+ var $faultactor;
1027
+ /**
1028
+ * The fault string, a description of the fault
1029
+ * @var string
1030
+ * @access private
1031
+ */
1032
+ var $faultstring;
1033
+ /**
1034
+ * The fault detail, typically a string or array of string
1035
+ * @var mixed
1036
+ * @access private
1037
+ */
1038
+ var $faultdetail;
1039
+
1040
+ /**
1041
+ * constructor
1042
+ *
1043
+ * @param string $faultcode (SOAP-ENV:Client | SOAP-ENV:Server)
1044
+ * @param string $faultactor only used when msg routed between multiple actors
1045
+ * @param string $faultstring human readable error message
1046
+ * @param mixed $faultdetail detail, typically a string or array of string
1047
+ */
1048
+ function nusoap_fault($faultcode,$faultactor='',$faultstring='',$faultdetail=''){
1049
+ parent::nusoap_base();
1050
+ $this->faultcode = $faultcode;
1051
+ $this->faultactor = $faultactor;
1052
+ $this->faultstring = $faultstring;
1053
+ $this->faultdetail = $faultdetail;
1054
+ }
1055
+
1056
+ /**
1057
+ * serialize a fault
1058
+ *
1059
+ * @return string The serialization of the fault instance.
1060
+ * @access public
1061
+ */
1062
+ function serialize(){
1063
+ $ns_string = '';
1064
+ foreach($this->namespaces as $k => $v){
1065
+ $ns_string .= "\n xmlns:$k=\"$v\"";
1066
+ }
1067
+ $return_msg =
1068
+ '<?xml version="1.0" encoding="'.$this->soap_defencoding.'"?>'.
1069
+ '<SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"'.$ns_string.">\n".
1070
+ '<SOAP-ENV:Body>'.
1071
+ '<SOAP-ENV:Fault>'.
1072
+ $this->serialize_val($this->faultcode, 'faultcode').
1073
+ $this->serialize_val($this->faultactor, 'faultactor').
1074
+ $this->serialize_val($this->faultstring, 'faultstring').
1075
+ $this->serialize_val($this->faultdetail, 'detail').
1076
+ '</SOAP-ENV:Fault>'.
1077
+ '</SOAP-ENV:Body>'.
1078
+ '</SOAP-ENV:Envelope>';
1079
+ return $return_msg;
1080
+ }
1081
+ }
1082
+
1083
+ /**
1084
+ * Backward compatibility
1085
+ */
1086
+ class soap_fault extends nusoap_fault {
1087
+ }
1088
+
1089
+ ?><?php
1090
+
1091
+
1092
+
1093
+ /**
1094
+ * parses an XML Schema, allows access to it's data, other utility methods.
1095
+ * imperfect, no validation... yet, but quite functional.
1096
+ *
1097
+ * @author Dietrich Ayala <dietrich@ganx4.com>
1098
+ * @author Scott Nichol <snichol@users.sourceforge.net>
1099
+ * @version $Id: fsource_nusoap__nusoap.php.html,v 1.2 2010/04/26 20:25:21 snichol Exp $
1100
+ * @access public
1101
+ */
1102
+ class nusoap_xmlschema extends nusoap_base {
1103
+
1104
+ // files
1105
+
1106
+ var $schema = '';
1107
+ var $xml = '';
1108
+ // namespaces
1109
+
1110
+ var $enclosingNamespaces;
1111
+ // schema info
1112
+
1113
+ var $schemaInfo = array();
1114
+ var $schemaTargetNamespace = '';
1115
+ // types, elements, attributes defined by the schema
1116
+
1117
+ var $attributes = array();
1118
+ var $complexTypes = array();
1119
+ var $complexTypeStack = array();
1120
+ var $currentComplexType = null;
1121
+ var $elements = array();
1122
+ var $elementStack = array();
1123
+ var $currentElement = null;
1124
+ var $simpleTypes = array();
1125
+ var $simpleTypeStack = array();
1126
+ var $currentSimpleType = null;
1127
+ // imports
1128
+
1129
+ var $imports = array();
1130
+ // parser vars
1131
+
1132
+ var $parser;
1133
+ var $position = 0;
1134
+ var $depth = 0;
1135
+ var $depth_array = array();
1136
+ var $message = array();
1137
+ var $defaultNamespace = array();
1138
+
1139
+ /**
1140
+ * constructor
1141
+ *
1142
+ * @param string $schema schema document URI
1143
+ * @param string $xml xml document URI
1144
+ * @param string $namespaces namespaces defined in enclosing XML
1145
+ * @access public
1146
+ */
1147
+ function nusoap_xmlschema($schema='',$xml='',$namespaces=array()){
1148
+ parent::nusoap_base();
1149
+ $this->debug('nusoap_xmlschema class instantiated, inside constructor');
1150
+ // files
1151
+ $this->schema = $schema;
1152
+ $this->xml = $xml;
1153
+
1154
+ // namespaces
1155
+ $this->enclosingNamespaces = $namespaces;
1156
+ $this->namespaces = array_merge($this->namespaces, $namespaces);
1157
+
1158
+ // parse schema file
1159
+ if($schema != ''){
1160
+ $this->debug('initial schema file: '.$schema);
1161
+ $this->parseFile($schema, 'schema');
1162
+ }
1163
+
1164
+ // parse xml file
1165
+ if($xml != ''){
1166
+ $this->debug('initial xml file: '.$xml);
1167
+ $this->parseFile($xml, 'xml');
1168
+ }
1169
+
1170
+ }
1171
+
1172
+ /**
1173
+ * parse an XML file
1174
+ *
1175
+ * @param string $xml path/URL to XML file
1176
+ * @param string $type (schema | xml)
1177
+ * @return boolean
1178
+ * @access public
1179
+ */
1180
+ function parseFile($xml,$type){
1181
+ // parse xml file
1182
+ if($xml != ""){
1183
+ $xmlStr = @join("",@file($xml));
1184
+ if($xmlStr == ""){
1185
+ $msg = 'Error reading XML from '.$xml;
1186
+ $this->setError($msg);
1187
+ $this->debug($msg);
1188
+ return false;
1189
+ } else {
1190
+ $this->debug("parsing $xml");
1191
+ $this->parseString($xmlStr,$type);
1192
+ $this->debug("done parsing $xml");
1193
+ return true;
1194
+ }
1195
+ }
1196
+ return false;
1197
+ }
1198
+
1199
+ /**
1200
+ * parse an XML string
1201
+ *
1202
+ * @param string $xml path or URL
1203
+ * @param string $type (schema|xml)
1204
+ * @access private
1205
+ */
1206
+ function parseString($xml,$type){
1207
+ // parse xml string
1208
+ if($xml != ""){
1209
+
1210
+ // Create an XML parser.
1211
+ $this->parser = xml_parser_create();
1212
+ // Set the options for parsing the XML data.
1213
+ xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
1214
+
1215
+ // Set the object for the parser.
1216
+ xml_set_object($this->parser, $this);
1217
+
1218
+ // Set the element handlers for the parser.
1219
+ if($type == "schema"){
1220
+ xml_set_element_handler($this->parser, 'schemaStartElement','schemaEndElement');
1221
+ xml_set_character_data_handler($this->parser,'schemaCharacterData');
1222
+ } elseif($type == "xml"){
1223
+ xml_set_element_handler($this->parser, 'xmlStartElement','xmlEndElement');
1224
+ xml_set_character_data_handler($this->parser,'xmlCharacterData');
1225
+ }
1226
+
1227
+ // Parse the XML file.
1228
+ if(!xml_parse($this->parser,$xml,true)){
1229
+ // Display an error message.
1230
+ $errstr = sprintf('XML error parsing XML schema on line %d: %s',
1231
+ xml_get_current_line_number($this->parser),
1232
+ xml_error_string(xml_get_error_code($this->parser))
1233
+ );
1234
+ $this->debug($errstr);
1235
+ $this->debug("XML payload:\n" . $xml);
1236
+ $this->setError($errstr);
1237
+ }
1238
+
1239
+ xml_parser_free($this->parser);
1240
+ } else{
1241
+ $this->debug('no xml passed to parseString()!!');
1242
+ $this->setError('no xml passed to parseString()!!');
1243
+ }
1244
+ }
1245
+
1246
+ /**
1247
+ * gets a type name for an unnamed type
1248
+ *
1249
+ * @param string Element name
1250
+ * @return string A type name for an unnamed type
1251
+ * @access private
1252
+ */
1253
+ function CreateTypeName($ename) {
1254
+ $scope = '';
1255
+ for ($i = 0; $i < count($this->complexTypeStack); $i++) {
1256
+ $scope .= $this->complexTypeStack[$i] . '_';
1257
+ }
1258
+ return $scope . $ename . '_ContainedType';
1259
+ }
1260
+
1261
+ /**
1262
+ * start-element handler
1263
+ *
1264
+ * @param string $parser XML parser object
1265
+ * @param string $name element name
1266
+ * @param string $attrs associative array of attributes
1267
+ * @access private
1268
+ */
1269
+ function schemaStartElement($parser, $name, $attrs) {
1270
+
1271
+ // position in the total number of elements, starting from 0
1272
+ $pos = $this->position++;
1273
+ $depth = $this->depth++;
1274
+ // set self as current value for this depth
1275
+ $this->depth_array[$depth] = $pos;
1276
+ $this->message[$pos] = array('cdata' => '');
1277
+ if ($depth > 0) {
1278
+ $this->defaultNamespace[$pos] = $this->defaultNamespace[$this->depth_array[$depth - 1]];
1279
+ } else {
1280
+ $this->defaultNamespace[$pos] = false;
1281
+ }
1282
+
1283
+ // get element prefix
1284
+ if($prefix = $this->getPrefix($name)){
1285
+ // get unqualified name
1286
+ $name = $this->getLocalPart($name);
1287
+ } else {
1288
+ $prefix = '';
1289
+ }
1290
+
1291
+ // loop thru attributes, expanding, and registering namespace declarations
1292
+ if(count($attrs) > 0){
1293
+ foreach($attrs as $k => $v){
1294
+ // if ns declarations, add to class level array of valid namespaces
1295
+ if(preg_match('/^xmlns/',$k)){
1296
+ //$this->xdebug("$k: $v");
1297
+ //$this->xdebug('ns_prefix: '.$this->getPrefix($k));
1298
+ if($ns_prefix = substr(strrchr($k,':'),1)){
1299
+ //$this->xdebug("Add namespace[$ns_prefix] = $v");
1300
+ $this->namespaces[$ns_prefix] = $v;
1301
+ } else {
1302
+ $this->defaultNamespace[$pos] = $v;
1303
+ if (! $this->getPrefixFromNamespace($v)) {
1304
+ $this->namespaces['ns'.(count($this->namespaces)+1)] = $v;
1305
+ }
1306
+ }
1307
+ if($v == 'http://www.w3.org/2001/XMLSchema' || $v == 'http://www.w3.org/1999/XMLSchema' || $v == 'http://www.w3.org/2000/10/XMLSchema'){
1308
+ $this->XMLSchemaVersion = $v;
1309
+ $this->namespaces['xsi'] = $v.'-instance';
1310
+ }
1311
+ }
1312
+ }
1313
+ foreach($attrs as $k => $v){
1314
+ // expand each attribute
1315
+ $k = strpos($k,':') ? $this->expandQname($k) : $k;
1316
+ $v = strpos($v,':') ? $this->expandQname($v) : $v;
1317
+ $eAttrs[$k] = $v;
1318
+ }
1319
+ $attrs = $eAttrs;
1320
+ } else {
1321
+ $attrs = array();
1322
+ }
1323
+ // find status, register data
1324
+ switch($name){
1325
+ case 'all': // (optional) compositor content for a complexType
1326
+ case 'choice':
1327
+ case 'group':
1328
+ case 'sequence':
1329
+ //$this->xdebug("compositor $name for currentComplexType: $this->currentComplexType and currentElement: $this->currentElement");
1330
+ $this->complexTypes[$this->currentComplexType]['compositor'] = $name;
1331
+ //if($name == 'all' || $name == 'sequence'){
1332
+ // $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
1333
+ //}
1334
+ break;
1335
+ case 'attribute': // complexType attribute
1336
+ //$this->xdebug("parsing attribute $attrs[name] $attrs[ref] of value: ".$attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']);
1337
+ $this->xdebug("parsing attribute:");
1338
+ $this->appendDebug($this->varDump($attrs));
1339
+ if (!isset($attrs['form'])) {
1340
+ // TODO: handle globals
1341
+ $attrs['form'] = $this->schemaInfo['attributeFormDefault'];
1342
+ }
1343
+ if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])) {
1344
+ $v = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
1345
+ if (!strpos($v, ':')) {
1346
+ // no namespace in arrayType attribute value...
1347
+ if ($this->defaultNamespace[$pos]) {
1348
+ // ...so use the default
1349
+ $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'] = $this->defaultNamespace[$pos] . ':' . $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
1350
+ }
1351
+ }
1352
+ }
1353
+ if(isset($attrs['name'])){
1354
+ $this->attributes[$attrs['name']] = $attrs;
1355
+ $aname = $attrs['name'];
1356
+ } elseif(isset($attrs['ref']) && $attrs['ref'] == 'http://schemas.xmlsoap.org/soap/encoding/:arrayType'){
1357
+ if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])) {
1358
+ $aname = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
1359
+ } else {
1360
+ $aname = '';
1361
+ }
1362
+ } elseif(isset($attrs['ref'])){
1363
+ $aname = $attrs['ref'];
1364
+ $this->attributes[$attrs['ref']] = $attrs;
1365
+ }
1366
+
1367
+ if($this->currentComplexType){ // This should *always* be
1368
+ $this->complexTypes[$this->currentComplexType]['attrs'][$aname] = $attrs;
1369
+ }
1370
+ // arrayType attribute
1371
+ if(isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']) || $this->getLocalPart($aname) == 'arrayType'){
1372
+ $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
1373
+ $prefix = $this->getPrefix($aname);
1374
+ if(isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])){
1375
+ $v = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
1376
+ } else {
1377
+ $v = '';
1378
+ }
1379
+ if(strpos($v,'[,]')){
1380
+ $this->complexTypes[$this->currentComplexType]['multidimensional'] = true;
1381
+ }
1382
+ $v = substr($v,0,strpos($v,'[')); // clip the []
1383
+ if(!strpos($v,':') && isset($this->typemap[$this->XMLSchemaVersion][$v])){
1384
+ $v = $this->XMLSchemaVersion.':'.$v;
1385
+ }
1386
+ $this->complexTypes[$this->currentComplexType]['arrayType'] = $v;
1387
+ }
1388
+ break;
1389
+ case 'complexContent': // (optional) content for a complexType
1390
+ $this->xdebug("do nothing for element $name");
1391
+ break;
1392
+ case 'complexType':
1393
+ array_push($this->complexTypeStack, $this->currentComplexType);
1394
+ if(isset($attrs['name'])){
1395
+ // TODO: what is the scope of named complexTypes that appear
1396
+ // nested within other c complexTypes?
1397
+ $this->xdebug('processing named complexType '.$attrs['name']);
1398
+ //$this->currentElement = false;
1399
+ $this->currentComplexType = $attrs['name'];
1400
+ $this->complexTypes[$this->currentComplexType] = $attrs;
1401
+ $this->complexTypes[$this->currentComplexType]['typeClass'] = 'complexType';
1402
+ // This is for constructs like
1403
+ // <complexType name="ListOfString" base="soap:Array">
1404
+ // <sequence>
1405
+ // <element name="string" type="xsd:string"
1406
+ // minOccurs="0" maxOccurs="unbounded" />
1407
+ // </sequence>
1408
+ // </complexType>
1409
+ if(isset($attrs['base']) && preg_match('/:Array$/',$attrs['base'])){
1410
+ $this->xdebug('complexType is unusual array');
1411
+ $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
1412
+ } else {
1413
+ $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
1414
+ }
1415
+ } else {
1416
+ $name = $this->CreateTypeName($this->currentElement);
1417
+ $this->xdebug('processing unnamed complexType for element ' . $this->currentElement . ' named ' . $name);
1418
+ $this->currentComplexType = $name;
1419
+ //$this->currentElement = false;
1420
+ $this->complexTypes[$this->currentComplexType] = $attrs;
1421
+ $this->complexTypes[$this->currentComplexType]['typeClass'] = 'complexType';
1422
+ // This is for constructs like
1423
+ // <complexType name="ListOfString" base="soap:Array">
1424
+ // <sequence>
1425
+ // <element name="string" type="xsd:string"
1426
+ // minOccurs="0" maxOccurs="unbounded" />
1427
+ // </sequence>
1428
+ // </complexType>
1429
+ if(isset($attrs['base']) && preg_match('/:Array$/',$attrs['base'])){
1430
+ $this->xdebug('complexType is unusual array');
1431
+ $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
1432
+ } else {
1433
+ $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
1434
+ }
1435
+ }
1436
+ $this->complexTypes[$this->currentComplexType]['simpleContent'] = 'false';
1437
+ break;
1438
+ case 'element':
1439
+ array_push($this->elementStack, $this->currentElement);
1440
+ if (!isset($attrs['form'])) {
1441
+ if ($this->currentComplexType) {
1442
+ $attrs['form'] = $this->schemaInfo['elementFormDefault'];
1443
+ } else {
1444
+ // global
1445
+ $attrs['form'] = 'qualified';
1446
+ }
1447
+ }
1448
+ if(isset($attrs['type'])){
1449
+ $this->xdebug("processing typed element ".$attrs['name']." of type ".$attrs['type']);
1450
+ if (! $this->getPrefix($attrs['type'])) {
1451
+ if ($this->defaultNamespace[$pos]) {
1452
+ $attrs['type'] = $this->defaultNamespace[$pos] . ':' . $attrs['type'];
1453
+ $this->xdebug('used default namespace to make type ' . $attrs['type']);
1454
+ }
1455
+ }
1456
+ // This is for constructs like
1457
+ // <complexType name="ListOfString" base="soap:Array">
1458
+ // <sequence>
1459
+ // <element name="string" type="xsd:string"
1460
+ // minOccurs="0" maxOccurs="unbounded" />
1461
+ // </sequence>
1462
+ // </complexType>
1463
+ if ($this->currentComplexType && $this->complexTypes[$this->currentComplexType]['phpType'] == 'array') {
1464
+ $this->xdebug('arrayType for unusual array is ' . $attrs['type']);
1465
+ $this->complexTypes[$this->currentComplexType]['arrayType'] = $attrs['type'];
1466
+ }
1467
+ $this->currentElement = $attrs['name'];
1468
+ $ename = $attrs['name'];
1469
+ } elseif(isset($attrs['ref'])){
1470
+ $this->xdebug("processing element as ref to ".$attrs['ref']);
1471
+ $this->currentElement = "ref to ".$attrs['ref'];
1472
+ $ename = $this->getLocalPart($attrs['ref']);
1473
+ } else {
1474
+ $type = $this->CreateTypeName($this->currentComplexType . '_' . $attrs['name']);
1475
+ $this->xdebug("processing untyped element " . $attrs['name'] . ' type ' . $type);
1476
+ $this->currentElement = $attrs['name'];
1477
+ $attrs['type'] = $this->schemaTargetNamespace . ':' . $type;
1478
+ $ename = $attrs['name'];
1479
+ }
1480
+ if (isset($ename) && $this->currentComplexType) {
1481
+ $this->xdebug("add element $ename to complexType $this->currentComplexType");
1482
+ $this->complexTypes[$this->currentComplexType]['elements'][$ename] = $attrs;
1483
+ } elseif (!isset($attrs['ref'])) {
1484
+ $this->xdebug("add element $ename to elements array");
1485
+ $this->elements[ $attrs['name'] ] = $attrs;
1486
+ $this->elements[ $attrs['name'] ]['typeClass'] = 'element';
1487
+ }
1488
+ break;
1489
+ case 'enumeration': // restriction value list member
1490
+ $this->xdebug('enumeration ' . $attrs['value']);
1491
+ if ($this->currentSimpleType) {
1492
+ $this->simpleTypes[$this->currentSimpleType]['enumeration'][] = $attrs['value'];
1493
+ } elseif ($this->currentComplexType) {
1494
+ $this->complexTypes[$this->currentComplexType]['enumeration'][] = $attrs['value'];
1495
+ }
1496
+ break;
1497
+ case 'extension': // simpleContent or complexContent type extension
1498
+ $this->xdebug('extension ' . $attrs['base']);
1499
+ if ($this->currentComplexType) {
1500
+ $ns = $this->getPrefix($attrs['base']);
1501
+ if ($ns == '') {
1502
+ $this->complexTypes[$this->currentComplexType]['extensionBase'] = $this->schemaTargetNamespace . ':' . $attrs['base'];
1503
+ } else {
1504
+ $this->complexTypes[$this->currentComplexType]['extensionBase'] = $attrs['base'];
1505
+ }
1506
+ } else {
1507
+ $this->xdebug('no current complexType to set extensionBase');
1508
+ }
1509
+ break;
1510
+ case 'import':
1511
+ if (isset($attrs['schemaLocation'])) {
1512
+ $this->xdebug('import namespace ' . $attrs['namespace'] . ' from ' . $attrs['schemaLocation']);
1513
+ $this->imports[$attrs['namespace']][] = array('location' => $attrs['schemaLocation'], 'loaded' => false);
1514
+ } else {
1515
+ $this->xdebug('import namespace ' . $attrs['namespace']);
1516
+ $this->imports[$attrs['namespace']][] = array('location' => '', 'loaded' => true);
1517
+ if (! $this->getPrefixFromNamespace($attrs['namespace'])) {
1518
+ $this->namespaces['ns'.(count($this->namespaces)+1)] = $attrs['namespace'];
1519
+ }
1520
+ }
1521
+ break;
1522
+ case 'include':
1523
+ if (isset($attrs['schemaLocation'])) {
1524
+ $this->xdebug('include into namespace ' . $this->schemaTargetNamespace . ' from ' . $attrs['schemaLocation']);
1525
+ $this->imports[$this->schemaTargetNamespace][] = array('location' => $attrs['schemaLocation'], 'loaded' => false);
1526
+ } else {
1527
+ $this->xdebug('ignoring invalid XML Schema construct: include without schemaLocation attribute');
1528
+ }
1529
+ break;
1530
+ case 'list': // simpleType value list
1531
+ $this->xdebug("do nothing for element $name");
1532
+ break;
1533
+ case 'restriction': // simpleType, simpleContent or complexContent value restriction
1534
+ $this->xdebug('restriction ' . $attrs['base']);
1535
+ if($this->currentSimpleType){
1536
+ $this->simpleTypes[$this->currentSimpleType]['type'] = $attrs['base'];
1537
+ } elseif($this->currentComplexType){
1538
+ $this->complexTypes[$this->currentComplexType]['restrictionBase'] = $attrs['base'];
1539
+ if(strstr($attrs['base'],':') == ':Array'){
1540
+ $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
1541
+ }
1542
+ }
1543
+ break;
1544
+ case 'schema':
1545
+ $this->schemaInfo = $attrs;
1546
+ $this->schemaInfo['schemaVersion'] = $this->getNamespaceFromPrefix($prefix);
1547
+ if (isset($attrs['targetNamespace'])) {
1548
+ $this->schemaTargetNamespace = $attrs['targetNamespace'];
1549
+ }
1550
+ if (!isset($attrs['elementFormDefault'])) {
1551
+ $this->schemaInfo['elementFormDefault'] = 'unqualified';
1552
+ }
1553
+ if (!isset($attrs['attributeFormDefault'])) {
1554
+ $this->schemaInfo['attributeFormDefault'] = 'unqualified';
1555
+ }
1556
+ break;
1557
+ case 'simpleContent': // (optional) content for a complexType
1558
+ if ($this->currentComplexType) { // This should *always* be
1559
+ $this->complexTypes[$this->currentComplexType]['simpleContent'] = 'true';
1560
+ } else {
1561
+ $this->xdebug("do nothing for element $name because there is no current complexType");
1562
+ }
1563
+ break;
1564
+ case 'simpleType':
1565
+ array_push($this->simpleTypeStack, $this->currentSimpleType);
1566
+ if(isset($attrs['name'])){
1567
+ $this->xdebug("processing simpleType for name " . $attrs['name']);
1568
+ $this->currentSimpleType = $attrs['name'];
1569
+ $this->simpleTypes[ $attrs['name'] ] = $attrs;
1570
+ $this->simpleTypes[ $attrs['name'] ]['typeClass'] = 'simpleType';
1571
+ $this->simpleTypes[ $attrs['name'] ]['phpType'] = 'scalar';
1572
+ } else {
1573
+ $name = $this->CreateTypeName($this->currentComplexType . '_' . $this->currentElement);
1574
+ $this->xdebug('processing unnamed simpleType for element ' . $this->currentElement . ' named ' . $name);
1575
+ $this->currentSimpleType = $name;
1576
+ //$this->currentElement = false;
1577
+ $this->simpleTypes[$this->currentSimpleType] = $attrs;
1578
+ $this->simpleTypes[$this->currentSimpleType]['phpType'] = 'scalar';
1579
+ }
1580
+ break;
1581
+ case 'union': // simpleType type list
1582
+ $this->xdebug("do nothing for element $name");
1583
+ break;
1584
+ default:
1585
+ $this->xdebug("do not have any logic to process element $name");
1586
+ }
1587
+ }
1588
+
1589
+ /**
1590
+ * end-element handler
1591
+ *
1592
+ * @param string $parser XML parser object
1593
+ * @param string $name element name
1594
+ * @access private
1595
+ */
1596
+ function schemaEndElement($parser, $name) {
1597
+ // bring depth down a notch
1598
+ $this->depth--;
1599
+ // position of current element is equal to the last value left in depth_array for my depth
1600
+ if(isset($this->depth_array[$this->depth])){
1601
+ $pos = $this->depth_array[$this->depth];
1602
+ }
1603
+ // get element prefix
1604
+ if ($prefix = $this->getPrefix($name)){
1605
+ // get unqualified name
1606
+ $name = $this->getLocalPart($name);
1607
+ } else {
1608
+ $prefix = '';
1609
+ }
1610
+ // move on...
1611
+ if($name == 'complexType'){
1612
+ $this->xdebug('done processing complexType ' . ($this->currentComplexType ? $this->currentComplexType : '(unknown)'));
1613
+ $this->xdebug($this->varDump($this->complexTypes[$this->currentComplexType]));
1614
+ $this->currentComplexType = array_pop($this->complexTypeStack);
1615
+ //$this->currentElement = false;
1616
+ }
1617
+ if($name == 'element'){
1618
+ $this->xdebug('done processing element ' . ($this->currentElement ? $this->currentElement : '(unknown)'));
1619
+ $this->currentElement = array_pop($this->elementStack);
1620
+ }
1621
+ if($name == 'simpleType'){
1622
+ $this->xdebug('done processing simpleType ' . ($this->currentSimpleType ? $this->currentSimpleType : '(unknown)'));
1623
+ $this->xdebug($this->varDump($this->simpleTypes[$this->currentSimpleType]));
1624
+ $this->currentSimpleType = array_pop($this->simpleTypeStack);
1625
+ }
1626
+ }
1627
+
1628
+ /**
1629
+ * element content handler
1630
+ *
1631
+ * @param string $parser XML parser object
1632
+ * @param string $data element content
1633
+ * @access private
1634
+ */
1635
+ function schemaCharacterData($parser, $data){
1636
+ $pos = $this->depth_array[$this->depth - 1];
1637
+ $this->message[$pos]['cdata'] .= $data;
1638
+ }
1639
+
1640
+ /**
1641
+ * serialize the schema
1642
+ *
1643
+ * @access public
1644
+ */
1645
+ function serializeSchema(){
1646
+
1647
+ $schemaPrefix = $this->getPrefixFromNamespace($this->XMLSchemaVersion);
1648
+ $xml = '';
1649
+ // imports
1650
+ if (sizeof($this->imports) > 0) {
1651
+ foreach($this->imports as $ns => $list) {
1652
+ foreach ($list as $ii) {
1653
+ if ($ii['location'] != '') {
1654
+ $xml .= " <$schemaPrefix:import location=\"" . $ii['location'] . '" namespace="' . $ns . "\" />\n";
1655
+ } else {
1656
+ $xml .= " <$schemaPrefix:import namespace=\"" . $ns . "\" />\n";
1657
+ }
1658
+ }
1659
+ }
1660
+ }
1661
+ // complex types
1662
+ foreach($this->complexTypes as $typeName => $attrs){
1663
+ $contentStr = '';
1664
+ // serialize child elements
1665
+ if(isset($attrs['elements']) && (count($attrs['elements']) > 0)){
1666
+ foreach($attrs['elements'] as $element => $eParts){
1667
+ if(isset($eParts['ref'])){
1668
+ $contentStr .= " <$schemaPrefix:element ref=\"$element\"/>\n";
1669
+ } else {
1670
+ $contentStr .= " <$schemaPrefix:element name=\"$element\" type=\"" . $this->contractQName($eParts['type']) . "\"";
1671
+ foreach ($eParts as $aName => $aValue) {
1672
+ // handle, e.g., abstract, default, form, minOccurs, maxOccurs, nillable
1673
+ if ($aName != 'name' && $aName != 'type') {
1674
+ $contentStr .= " $aName=\"$aValue\"";
1675
+ }
1676
+ }
1677
+ $contentStr .= "/>\n";
1678
+ }
1679
+ }
1680
+ // compositor wraps elements
1681
+ if (isset($attrs['compositor']) && ($attrs['compositor'] != '')) {
1682
+ $contentStr = " <$schemaPrefix:$attrs[compositor]>\n".$contentStr." </$schemaPrefix:$attrs[compositor]>\n";
1683
+ }
1684
+ }
1685
+ // attributes
1686
+ if(isset($attrs['attrs']) && (count($attrs['attrs']) >= 1)){
1687
+ foreach($attrs['attrs'] as $attr => $aParts){
1688
+ $contentStr .= " <$schemaPrefix:attribute";
1689
+ foreach ($aParts as $a => $v) {
1690
+ if ($a == 'ref' || $a == 'type') {
1691
+ $contentStr .= " $a=\"".$this->contractQName($v).'"';
1692
+ } elseif ($a == 'http://schemas.xmlsoap.org/wsdl/:arrayType') {
1693
+ $this->usedNamespaces['wsdl'] = $this->namespaces['wsdl'];
1694
+ $contentStr .= ' wsdl:arrayType="'.$this->contractQName($v).'"';
1695
+ } else {
1696
+ $contentStr .= " $a=\"$v\"";
1697
+ }
1698
+ }
1699
+ $contentStr .= "/>\n";
1700
+ }
1701
+ }
1702
+ // if restriction
1703
+ if (isset($attrs['restrictionBase']) && $attrs['restrictionBase'] != ''){
1704
+ $contentStr = " <$schemaPrefix:restriction base=\"".$this->contractQName($attrs['restrictionBase'])."\">\n".$contentStr." </$schemaPrefix:restriction>\n";
1705
+ // complex or simple content
1706
+ if ((isset($attrs['elements']) && count($attrs['elements']) > 0) || (isset($attrs['attrs']) && count($attrs['attrs']) > 0)){
1707
+ $contentStr = " <$schemaPrefix:complexContent>\n".$contentStr." </$schemaPrefix:complexContent>\n";
1708
+ }
1709
+ }
1710
+ // finalize complex type
1711
+ if($contentStr != ''){
1712
+ $contentStr = " <$schemaPrefix:complexType name=\"$typeName\">\n".$contentStr." </$schemaPrefix:complexType>\n";
1713
+ } else {
1714
+ $contentStr = " <$schemaPrefix:complexType name=\"$typeName\"/>\n";
1715
+ }
1716
+ $xml .= $contentStr;
1717
+ }
1718
+ // simple types
1719
+ if(isset($this->simpleTypes) && count($this->simpleTypes) > 0){
1720
+ foreach($this->simpleTypes as $typeName => $eParts){
1721
+ $xml .= " <$schemaPrefix:simpleType name=\"$typeName\">\n <$schemaPrefix:restriction base=\"".$this->contractQName($eParts['type'])."\">\n";
1722
+ if (isset($eParts['enumeration'])) {
1723
+ foreach ($eParts['enumeration'] as $e) {
1724
+ $xml .= " <$schemaPrefix:enumeration value=\"$e\"/>\n";
1725
+ }
1726
+ }
1727
+ $xml .= " </$schemaPrefix:restriction>\n </$schemaPrefix:simpleType>";
1728
+ }
1729
+ }
1730
+ // elements
1731
+ if(isset($this->elements) && count($this->elements) > 0){
1732
+ foreach($this->elements as $element => $eParts){
1733
+ $xml .= " <$schemaPrefix:element name=\"$element\" type=\"".$this->contractQName($eParts['type'])."\"/>\n";
1734
+ }
1735
+ }
1736
+ // attributes
1737
+ if(isset($this->attributes) && count($this->attributes) > 0){
1738
+ foreach($this->attributes as $attr => $aParts){
1739
+ $xml .= " <$schemaPrefix:attribute name=\"$attr\" type=\"".$this->contractQName($aParts['type'])."\"\n/>";
1740
+ }
1741
+ }
1742
+ // finish 'er up
1743
+ $attr = '';
1744
+ foreach ($this->schemaInfo as $k => $v) {
1745
+ if ($k == 'elementFormDefault' || $k == 'attributeFormDefault') {
1746
+ $attr .= " $k=\"$v\"";
1747
+ }
1748
+ }
1749
+ $el = "<$schemaPrefix:schema$attr targetNamespace=\"$this->schemaTargetNamespace\"\n";
1750
+ foreach (array_diff($this->usedNamespaces, $this->enclosingNamespaces) as $nsp => $ns) {
1751
+ $el .= " xmlns:$nsp=\"$ns\"";
1752
+ }
1753
+ $xml = $el . ">\n".$xml."</$schemaPrefix:schema>\n";
1754
+ return $xml;
1755
+ }
1756
+
1757
+ /**
1758
+ * adds debug data to the clas level debug string
1759
+ *
1760
+ * @param string $string debug data
1761
+ * @access private
1762
+ */
1763
+ function xdebug($string){
1764
+ $this->debug('<' . $this->schemaTargetNamespace . '> '.$string);
1765
+ }
1766
+
1767
+ /**
1768
+ * get the PHP type of a user defined type in the schema
1769
+ * PHP type is kind of a misnomer since it actually returns 'struct' for assoc. arrays
1770
+ * returns false if no type exists, or not w/ the given namespace
1771
+ * else returns a string that is either a native php type, or 'struct'
1772
+ *
1773
+ * @param string $type name of defined type
1774
+ * @param string $ns namespace of type
1775
+ * @return mixed
1776
+ * @access public
1777
+ * @deprecated
1778
+ */
1779
+ function getPHPType($type,$ns){
1780
+ if(isset($this->typemap[$ns][$type])){
1781
+ //print "found type '$type' and ns $ns in typemap<br>";
1782
+ return $this->typemap[$ns][$type];
1783
+ } elseif(isset($this->complexTypes[$type])){
1784
+ //print "getting type '$type' and ns $ns from complexTypes array<br>";
1785
+ return $this->complexTypes[$type]['phpType'];
1786
+ }
1787
+ return false;
1788
+ }
1789
+
1790
+ /**
1791
+ * returns an associative array of information about a given type
1792
+ * returns false if no type exists by the given name
1793
+ *
1794
+ * For a complexType typeDef = array(
1795
+ * 'restrictionBase' => '',
1796
+ * 'phpType' => '',
1797
+ * 'compositor' => '(sequence|all)',
1798
+ * 'elements' => array(), // refs to elements array
1799
+ * 'attrs' => array() // refs to attributes array
1800
+ * ... and so on (see addComplexType)
1801
+ * )
1802
+ *
1803
+ * For simpleType or element, the array has different keys.
1804
+ *
1805
+ * @param string $type
1806
+ * @return mixed
1807
+ * @access public
1808
+ * @see addComplexType
1809
+ * @see addSimpleType
1810
+ * @see addElement
1811
+ */
1812
+ function getTypeDef($type){
1813
+ //$this->debug("in getTypeDef for type $type");
1814
+ if (substr($type, -1) == '^') {
1815
+ $is_element = 1;
1816
+ $type = substr($type, 0, -1);
1817
+ } else {
1818
+ $is_element = 0;
1819
+ }
1820
+
1821
+ if((! $is_element) && isset($this->complexTypes[$type])){
1822
+ $this->xdebug("in getTypeDef, found complexType $type");
1823
+ return $this->complexTypes[$type];
1824
+ } elseif((! $is_element) && isset($this->simpleTypes[$type])){
1825
+ $this->xdebug("in getTypeDef, found simpleType $type");
1826
+ if (!isset($this->simpleTypes[$type]['phpType'])) {
1827
+ // get info for type to tack onto the simple type
1828
+ // TODO: can this ever really apply (i.e. what is a simpleType really?)
1829
+ $uqType = substr($this->simpleTypes[$type]['type'], strrpos($this->simpleTypes[$type]['type'], ':') + 1);
1830
+ $ns = substr($this->simpleTypes[$type]['type'], 0, strrpos($this->simpleTypes[$type]['type'], ':'));
1831
+ $etype = $this->getTypeDef($uqType);
1832
+ if ($etype) {
1833
+ $this->xdebug("in getTypeDef, found type for simpleType $type:");
1834
+ $this->xdebug($this->varDump($etype));
1835
+ if (isset($etype['phpType'])) {
1836
+ $this->simpleTypes[$type]['phpType'] = $etype['phpType'];
1837
+ }
1838
+ if (isset($etype['elements'])) {
1839
+ $this->simpleTypes[$type]['elements'] = $etype['elements'];
1840
+ }
1841
+ }
1842
+ }
1843
+ return $this->simpleTypes[$type];
1844
+ } elseif(isset($this->elements[$type])){
1845
+ $this->xdebug("in getTypeDef, found element $type");
1846
+ if (!isset($this->elements[$type]['phpType'])) {
1847
+ // get info for type to tack onto the element
1848
+ $uqType = substr($this->elements[$type]['type'], strrpos($this->elements[$type]['type'], ':') + 1);
1849
+ $ns = substr($this->elements[$type]['type'], 0, strrpos($this->elements[$type]['type'], ':'));
1850
+ $etype = $this->getTypeDef($uqType);
1851
+ if ($etype) {
1852
+ $this->xdebug("in getTypeDef, found type for element $type:");
1853
+ $this->xdebug($this->varDump($etype));
1854
+ if (isset($etype['phpType'])) {
1855
+ $this->elements[$type]['phpType'] = $etype['phpType'];
1856
+ }
1857
+ if (isset($etype['elements'])) {
1858
+ $this->elements[$type]['elements'] = $etype['elements'];
1859
+ }
1860
+ if (isset($etype['extensionBase'])) {
1861
+ $this->elements[$type]['extensionBase'] = $etype['extensionBase'];
1862
+ }
1863
+ } elseif ($ns == 'http://www.w3.org/2001/XMLSchema') {
1864
+ $this->xdebug("in getTypeDef, element $type is an XSD type");
1865
+ $this->elements[$type]['phpType'] = 'scalar';
1866
+ }
1867
+ }
1868
+ return $this->elements[$type];
1869
+ } elseif(isset($this->attributes[$type])){
1870
+ $this->xdebug("in getTypeDef, found attribute $type");
1871
+ return $this->attributes[$type];
1872
+ } elseif (preg_match('/_ContainedType$/', $type)) {
1873
+ $this->xdebug("in getTypeDef, have an untyped element $type");
1874
+ $typeDef['typeClass'] = 'simpleType';
1875
+ $typeDef['phpType'] = 'scalar';
1876
+ $typeDef['type'] = 'http://www.w3.org/2001/XMLSchema:string';
1877
+ return $typeDef;
1878
+ }
1879
+ $this->xdebug("in getTypeDef, did not find $type");
1880
+ return false;
1881
+ }
1882
+
1883
+ /**
1884
+ * returns a sample serialization of a given type, or false if no type by the given name
1885
+ *
1886
+ * @param string $type name of type
1887
+ * @return mixed
1888
+ * @access public
1889
+ * @deprecated
1890
+ */
1891
+ function serializeTypeDef($type){
1892
+ //print "in sTD() for type $type<br>";
1893
+ if($typeDef = $this->getTypeDef($type)){
1894
+ $str .= '<'.$type;
1895
+ if(is_array($typeDef['attrs'])){
1896
+ foreach($typeDef['attrs'] as $attName => $data){
1897
+ $str .= " $attName=\"{type = ".$data['type']."}\"";
1898
+ }
1899
+ }
1900
+ $str .= " xmlns=\"".$this->schema['targetNamespace']."\"";
1901
+ if(count($typeDef['elements']) > 0){
1902
+ $str .= ">";
1903
+ foreach($typeDef['elements'] as $element => $eData){
1904
+ $str .= $this->serializeTypeDef($element);
1905
+ }
1906
+ $str .= "</$type>";
1907
+ } elseif($typeDef['typeClass'] == 'element') {
1908
+ $str .= "></$type>";
1909
+ } else {
1910
+ $str .= "/>";
1911
+ }
1912
+ return $str;
1913
+ }
1914
+ return false;
1915
+ }
1916
+
1917
+ /**
1918
+ * returns HTML form elements that allow a user
1919
+ * to enter values for creating an instance of the given type.
1920
+ *
1921
+ * @param string $name name for type instance
1922
+ * @param string $type name of type
1923
+ * @return string
1924
+ * @access public
1925
+ * @deprecated
1926
+ */
1927
+ function typeToForm($name,$type){
1928
+ // get typedef
1929
+ if($typeDef = $this->getTypeDef($type)){
1930
+ // if struct
1931
+ if($typeDef['phpType'] == 'struct'){
1932
+ $buffer .= '<table>';
1933
+ foreach($typeDef['elements'] as $child => $childDef){
1934
+ $buffer .= "
1935
+ <tr><td align='right'>$childDef[name] (type: ".$this->getLocalPart($childDef['type'])."):</td>
1936
+ <td><input type='text' name='parameters[".$name."][$childDef[name]]'></td></tr>";
1937
+ }
1938
+ $buffer .= '</table>';
1939
+ // if array
1940
+ } elseif($typeDef['phpType'] == 'array'){
1941
+ $buffer .= '<table>';
1942
+ for($i=0;$i < 3; $i++){
1943
+ $buffer .= "
1944
+ <tr><td align='right'>array item (type: $typeDef[arrayType]):</td>
1945
+ <td><input type='text' name='parameters[".$name."][]'></td></tr>";
1946
+ }
1947
+ $buffer .= '</table>';
1948
+ // if scalar
1949
+ } else {
1950
+ $buffer .= "<input type='text' name='parameters[$name]'>";
1951
+ }
1952
+ } else {
1953
+ $buffer .= "<input type='text' name='parameters[$name]'>";
1954
+ }
1955
+ return $buffer;
1956
+ }
1957
+
1958
+ /**
1959
+ * adds a complex type to the schema
1960
+ *
1961
+ * example: array
1962
+ *
1963
+ * addType(
1964
+ * 'ArrayOfstring',
1965
+ * 'complexType',
1966
+ * 'array',
1967
+ * '',
1968
+ * 'SOAP-ENC:Array',
1969
+ * array('ref'=>'SOAP-ENC:arrayType','wsdl:arrayType'=>'string[]'),
1970
+ * 'xsd:string'
1971
+ * );
1972
+ *
1973
+ * example: PHP associative array ( SOAP Struct )
1974
+ *
1975
+ * addType(
1976
+ * 'SOAPStruct',
1977
+ * 'complexType',
1978
+ * 'struct',
1979
+ * 'all',
1980
+ * array('myVar'=> array('name'=>'myVar','type'=>'string')
1981
+ * );
1982
+ *
1983
+ * @param name
1984
+ * @param typeClass (complexType|simpleType|attribute)
1985
+ * @param phpType: currently supported are array and struct (php assoc array)
1986
+ * @param compositor (all|sequence|choice)
1987
+ * @param restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
1988
+ * @param elements = array ( name = array(name=>'',type=>'') )
1989
+ * @param attrs = array(
1990
+ * array(
1991
+ * 'ref' => "http://schemas.xmlsoap.org/soap/encoding/:arrayType",
1992
+ * "http://schemas.xmlsoap.org/wsdl/:arrayType" => "string[]"
1993
+ * )
1994
+ * )
1995
+ * @param arrayType: namespace:name (http://www.w3.org/2001/XMLSchema:string)
1996
+ * @access public
1997
+ * @see getTypeDef
1998
+ */
1999
+ function addComplexType($name,$typeClass='complexType',$phpType='array',$compositor='',$restrictionBase='',$elements=array(),$attrs=array(),$arrayType=''){
2000
+ $this->complexTypes[$name] = array(
2001
+ 'name' => $name,
2002
+ 'typeClass' => $typeClass,
2003
+ 'phpType' => $phpType,
2004
+ 'compositor'=> $compositor,
2005
+ 'restrictionBase' => $restrictionBase,
2006
+ 'elements' => $elements,
2007
+ 'attrs' => $attrs,
2008
+ 'arrayType' => $arrayType
2009
+ );
2010
+
2011
+ $this->xdebug("addComplexType $name:");
2012
+ $this->appendDebug($this->varDump($this->complexTypes[$name]));
2013
+ }
2014
+
2015
+ /**
2016
+ * adds a simple type to the schema
2017
+ *
2018
+ * @param string $name
2019
+ * @param string $restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
2020
+ * @param string $typeClass (should always be simpleType)
2021
+ * @param string $phpType (should always be scalar)
2022
+ * @param array $enumeration array of values
2023
+ * @access public
2024
+ * @see nusoap_xmlschema
2025
+ * @see getTypeDef
2026
+ */
2027
+ function addSimpleType($name, $restrictionBase='', $typeClass='simpleType', $phpType='scalar', $enumeration=array()) {
2028
+ $this->simpleTypes[$name] = array(
2029
+ 'name' => $name,
2030
+ 'typeClass' => $typeClass,
2031
+ 'phpType' => $phpType,
2032
+ 'type' => $restrictionBase,
2033
+ 'enumeration' => $enumeration
2034
+ );
2035
+
2036
+ $this->xdebug("addSimpleType $name:");
2037
+ $this->appendDebug($this->varDump($this->simpleTypes[$name]));
2038
+ }
2039
+
2040
+ /**
2041
+ * adds an element to the schema
2042
+ *
2043
+ * @param array $attrs attributes that must include name and type
2044
+ * @see nusoap_xmlschema
2045
+ * @access public
2046
+ */
2047
+ function addElement($attrs) {
2048
+ if (! $this->getPrefix($attrs['type'])) {
2049
+ $attrs['type'] = $this->schemaTargetNamespace . ':' . $attrs['type'];
2050
+ }
2051
+ $this->elements[ $attrs['name'] ] = $attrs;
2052
+ $this->elements[ $attrs['name'] ]['typeClass'] = 'element';
2053
+
2054
+ $this->xdebug("addElement " . $attrs['name']);
2055
+ $this->appendDebug($this->varDump($this->elements[ $attrs['name'] ]));
2056
+ }
2057
+ }
2058
+
2059
+ /**
2060
+ * Backward compatibility
2061
+ */
2062
+ class XMLSchema extends nusoap_xmlschema {
2063
+ }
2064
+
2065
+ ?><?php
2066
+
2067
+
2068
+
2069
+ /**
2070
+ * For creating serializable abstractions of native PHP types. This class
2071
+ * allows element name/namespace, XSD type, and XML attributes to be
2072
+ * associated with a value. This is extremely useful when WSDL is not
2073
+ * used, but is also useful when WSDL is used with polymorphic types, including
2074
+ * xsd:anyType and user-defined types.
2075
+ *
2076
+ * @author Dietrich Ayala <dietrich@ganx4.com>
2077
+ * @version $Id: fsource_nusoap__nusoap.php.html,v 1.2 2010/04/26 20:25:21 snichol Exp $
2078
+ * @access public
2079
+ */
2080
+ class soapval extends nusoap_base {
2081
+ /**
2082
+ * The XML element name
2083
+ *
2084
+ * @var string
2085
+ * @access private
2086
+ */
2087
+ var $name;
2088
+ /**
2089
+ * The XML type name (string or false)
2090
+ *
2091
+ * @var mixed
2092
+ * @access private
2093
+ */
2094
+ var $type;
2095
+ /**
2096
+ * The PHP value
2097
+ *
2098
+ * @var mixed
2099
+ * @access private
2100
+ */
2101
+ var $value;
2102
+ /**
2103
+ * The XML element namespace (string or false)
2104
+ *
2105
+ * @var mixed
2106
+ * @access private
2107
+ */
2108
+ var $element_ns;
2109
+ /**
2110
+ * The XML type namespace (string or false)
2111
+ *
2112
+ * @var mixed
2113
+ * @access private
2114
+ */
2115
+ var $type_ns;
2116
+ /**
2117
+ * The XML element attributes (array or false)
2118
+ *
2119
+ * @var mixed
2120
+ * @access private
2121
+ */
2122
+ var $attributes;
2123
+
2124
+ /**
2125
+ * constructor
2126
+ *
2127
+ * @param string $name optional name
2128
+ * @param mixed $type optional type name
2129
+ * @param mixed $value optional value
2130
+ * @param mixed $element_ns optional namespace of value
2131
+ * @param mixed $type_ns optional namespace of type
2132
+ * @param mixed $attributes associative array of attributes to add to element serialization
2133
+ * @access public
2134
+ */
2135
+ function soapval($name='soapval',$type=false,$value=-1,$element_ns=false,$type_ns=false,$attributes=false) {
2136
+ parent::nusoap_base();
2137
+ $this->name = $name;
2138
+ $this->type = $type;
2139
+ $this->value = $value;
2140
+ $this->element_ns = $element_ns;
2141
+ $this->type_ns = $type_ns;
2142
+ $this->attributes = $attributes;
2143
+ }
2144
+
2145
+ /**
2146
+ * return serialized value
2147
+ *
2148
+ * @param string $use The WSDL use value (encoded|literal)
2149
+ * @return string XML data
2150
+ * @access public
2151
+ */
2152
+ function serialize($use='encoded') {
2153
+ return $this->serialize_val($this->value, $this->name, $this->type, $this->element_ns, $this->type_ns, $this->attributes, $use, true);
2154
+ }
2155
+
2156
+ /**
2157
+ * decodes a soapval object into a PHP native type
2158
+ *
2159
+ * @return mixed
2160
+ * @access public
2161
+ */
2162
+ function decode(){
2163
+ return $this->value;
2164
+ }
2165
+ }
2166
+
2167
+
2168
+
2169
+ ?><?php
2170
+
2171
+
2172
+
2173
+ /**
2174
+ * transport class for sending/receiving data via HTTP and HTTPS
2175
+ * NOTE: PHP must be compiled with the CURL extension for HTTPS support
2176
+ *
2177
+ * @author Dietrich Ayala <dietrich@ganx4.com>
2178
+ * @author Scott Nichol <snichol@users.sourceforge.net>
2179
+ * @version $Id: fsource_nusoap__nusoap.php.html,v 1.2 2010/04/26 20:25:21 snichol Exp $
2180
+ * @access public
2181
+ */
2182
+ class soap_transport_http extends nusoap_base {
2183
+
2184
+ var $url = '';
2185
+ var $uri = '';
2186
+ var $digest_uri = '';
2187
+ var $scheme = '';
2188
+ var $host = '';
2189
+ var $port = '';
2190
+ var $path = '';
2191
+ var $request_method = 'POST';
2192
+ var $protocol_version = '1.0';
2193
+ var $encoding = '';
2194
+ var $outgoing_headers = array();
2195
+ var $incoming_headers = array();
2196
+ var $incoming_cookies = array();
2197
+ var $outgoing_payload = '';
2198
+ var $incoming_payload = '';
2199
+ var $response_status_line; // HTTP response status line
2200
+
2201
+ var $useSOAPAction = true;
2202
+ var $persistentConnection = false;
2203
+ var $ch = false; // cURL handle
2204
+
2205
+ var $ch_options = array(); // cURL custom options
2206
+
2207
+ var $use_curl = false; // force cURL use
2208
+
2209
+ var $proxy = null; // proxy information (associative array)
2210
+
2211
+ var $username = '';
2212
+ var $password = '';
2213
+ var $authtype = '';
2214
+ var $digestRequest = array();
2215
+ var $certRequest = array(); // keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, certpassword (optional), verifypeer (optional), verifyhost (optional)
2216
+ // cainfofile: certificate authority file, e.g. '$pathToPemFiles/rootca.pem'
2217
+ // sslcertfile: SSL certificate file, e.g. '$pathToPemFiles/mycert.pem'
2218
+ // sslkeyfile: SSL key file, e.g. '$pathToPemFiles/mykey.pem'
2219
+ // passphrase: SSL key password/passphrase
2220
+ // certpassword: SSL certificate password
2221
+ // verifypeer: default is 1
2222
+ // verifyhost: default is 1
2223
+
2224
+
2225
+
2226
+ /**
2227
+ * constructor
2228
+ *
2229
+ * @param string $url The URL to which to connect
2230
+ * @param array $curl_options User-specified cURL options
2231
+ * @param boolean $use_curl Whether to try to force cURL use
2232
+ * @access public
2233
+ */
2234
+ function soap_transport_http($url, $curl_options = NULL, $use_curl = false){
2235
+ parent::nusoap_base();
2236
+ $this->debug("ctor url=$url use_curl=$use_curl curl_options:");
2237
+ $this->appendDebug($this->varDump($curl_options));
2238
+ $this->setURL($url);
2239
+ if (is_array($curl_options)) {
2240
+ $this->ch_options = $curl_options;
2241
+ }
2242
+ $this->use_curl = $use_curl;
2243
+ preg_match('/\$Revisio' . 'n: ([^ ]+)/', $this->revision, $rev);
2244
+ $this->setHeader('User-Agent', $this->title.'/'.$this->version.' ('.$rev[1].')');
2245
+ }
2246
+
2247
+ /**
2248
+ * sets a cURL option
2249
+ *
2250
+ * @param mixed $option The cURL option (always integer?)
2251
+ * @param mixed $value The cURL option value
2252
+ * @access private
2253
+ */
2254
+ function setCurlOption($option, $value) {
2255
+ $this->debug("setCurlOption option=$option, value=");
2256
+ $this->appendDebug($this->varDump($value));
2257
+ curl_setopt($this->ch, $option, $value);
2258
+ }
2259
+
2260
+ /**
2261
+ * sets an HTTP header
2262
+ *
2263
+ * @param string $name The name of the header
2264
+ * @param string $value The value of the header
2265
+ * @access private
2266
+ */
2267
+ function setHeader($name, $value) {
2268
+ $this->outgoing_headers[$name] = $value;
2269
+ $this->debug("set header $name: $value");
2270
+ }
2271
+
2272
+ /**
2273
+ * unsets an HTTP header
2274
+ *
2275
+ * @param string $name The name of the header
2276
+ * @access private
2277
+ */
2278
+ function unsetHeader($name) {
2279
+ if (isset($this->outgoing_headers[$name])) {
2280
+ $this->debug("unset header $name");
2281
+ unset($this->outgoing_headers[$name]);
2282
+ }
2283
+ }
2284
+
2285
+ /**
2286
+ * sets the URL to which to connect
2287
+ *
2288
+ * @param string $url The URL to which to connect
2289
+ * @access private
2290
+ */
2291
+ function setURL($url) {
2292
+ $this->url = $url;
2293
+
2294
+ $u = parse_url($url);
2295
+ foreach($u as $k => $v){
2296
+ $this->debug("parsed URL $k = $v");
2297
+ $this->$k = $v;
2298
+ }
2299
+
2300
+ // add any GET params to path
2301
+ if(isset($u['query']) && $u['query'] != ''){
2302
+ $this->path .= '?' . $u['query'];
2303
+ }
2304
+
2305
+ // set default port
2306
+ if(!isset($u['port'])){
2307
+ if($u['scheme'] == 'https'){
2308
+ $this->port = 443;
2309
+ } else {
2310
+ $this->port = 80;
2311
+ }
2312
+ }
2313
+
2314
+ $this->uri = $this->path;
2315
+ $this->digest_uri = $this->uri;
2316
+
2317
+ // build headers
2318
+ if (!isset($u['port'])) {
2319
+ $this->setHeader('Host', $this->host);
2320
+ } else {
2321
+ $this->setHeader('Host', $this->host.':'.$this->port);
2322
+ }
2323
+
2324
+ if (isset($u['user']) && $u['user'] != '') {
2325
+ $this->setCredentials(urldecode($u['user']), isset($u['pass']) ? urldecode($u['pass']) : '');
2326
+ }
2327
+ }
2328
+
2329
+ /**
2330
+ * gets the I/O method to use
2331
+ *
2332
+ * @return string I/O method to use (socket|curl|unknown)
2333
+ * @access private
2334
+ */
2335
+ function io_method() {
2336
+ if ($this->use_curl || ($this->scheme == 'https') || ($this->scheme == 'http' && $this->authtype == 'ntlm') || ($this->scheme == 'http' && is_array($this->proxy) && $this->proxy['authtype'] == 'ntlm'))
2337
+ return 'curl';
2338
+ if (($this->scheme == 'http' || $this->scheme == 'ssl') && $this->authtype != 'ntlm' && (!is_array($this->proxy) || $this->proxy['authtype'] != 'ntlm'))
2339
+ return 'socket';
2340
+ return 'unknown';
2341
+ }
2342
+
2343
+ /**
2344
+ * establish an HTTP connection
2345
+ *
2346
+ * @param integer $timeout set connection timeout in seconds
2347
+ * @param integer $response_timeout set response timeout in seconds
2348
+ * @return boolean true if connected, false if not
2349
+ * @access private
2350
+ */
2351
+ function connect($connection_timeout=0,$response_timeout=30){
2352
+ // For PHP 4.3 with OpenSSL, change https scheme to ssl, then treat like
2353
+ // "regular" socket.
2354
+ // TODO: disabled for now because OpenSSL must be *compiled* in (not just
2355
+ // loaded), and until PHP5 stream_get_wrappers is not available.
2356
+ // if ($this->scheme == 'https') {
2357
+ // if (version_compare(phpversion(), '4.3.0') >= 0) {
2358
+ // if (extension_loaded('openssl')) {
2359
+ // $this->scheme = 'ssl';
2360
+ // $this->debug('Using SSL over OpenSSL');
2361
+ // }
2362
+ // }
2363
+ // }
2364
+ $this->debug("connect connection_timeout $connection_timeout, response_timeout $response_timeout, scheme $this->scheme, host $this->host, port $this->port");
2365
+ if ($this->io_method() == 'socket') {
2366
+ if (!is_array($this->proxy)) {
2367
+ $host = $this->host;
2368
+ $port = $this->port;
2369
+ } else {
2370
+ $host = $this->proxy['host'];
2371
+ $port = $this->proxy['port'];
2372
+ }
2373
+
2374
+ // use persistent connection
2375
+ if($this->persistentConnection && isset($this->fp) && is_resource($this->fp)){
2376
+ if (!feof($this->fp)) {
2377
+ $this->debug('Re-use persistent connection');
2378
+ return true;
2379
+ }
2380
+ fclose($this->fp);
2381
+ $this->debug('Closed persistent connection at EOF');
2382
+ }
2383
+
2384
+ // munge host if using OpenSSL
2385
+ if ($this->scheme == 'ssl') {
2386
+ $host = 'ssl://' . $host;
2387
+ }
2388
+ $this->debug('calling fsockopen with host ' . $host . ' connection_timeout ' . $connection_timeout);
2389
+
2390
+ // open socket
2391
+ if($connection_timeout > 0){
2392
+ $this->fp = @fsockopen( $host, $this->port, $this->errno, $this->error_str, $connection_timeout);
2393
+ } else {
2394
+ $this->fp = @fsockopen( $host, $this->port, $this->errno, $this->error_str);
2395
+ }
2396
+
2397
+ // test pointer
2398
+ if(!$this->fp) {
2399
+ $msg = 'Couldn\'t open socket connection to server ' . $this->url;
2400
+ if ($this->errno) {
2401
+ $msg .= ', Error ('.$this->errno.'): '.$this->error_str;
2402
+ } else {
2403
+ $msg .= ' prior to connect(). This is often a problem looking up the host name.';
2404
+ }
2405
+ $this->debug($msg);
2406
+ $this->setError($msg);
2407
+ return false;
2408
+ }
2409
+
2410
+ // set response timeout
2411
+ $this->debug('set response timeout to ' . $response_timeout);
2412
+ socket_set_timeout( $this->fp, $response_timeout);
2413
+
2414
+ $this->debug('socket connected');
2415
+ return true;
2416
+ } else if ($this->io_method() == 'curl') {
2417
+ if (!extension_loaded('curl')) {
2418
+ // $this->setError('cURL Extension, or OpenSSL extension w/ PHP version >= 4.3 is required for HTTPS');
2419
+ $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.');
2420
+ return false;
2421
+ }
2422
+ // Avoid warnings when PHP does not have these options
2423
+ if (defined('CURLOPT_CONNECTIONTIMEOUT'))
2424
+ $CURLOPT_CONNECTIONTIMEOUT = CURLOPT_CONNECTIONTIMEOUT;
2425
+ else
2426
+ $CURLOPT_CONNECTIONTIMEOUT = 78;
2427
+ if (defined('CURLOPT_HTTPAUTH'))
2428
+ $CURLOPT_HTTPAUTH = CURLOPT_HTTPAUTH;
2429
+ else
2430
+ $CURLOPT_HTTPAUTH = 107;
2431
+ if (defined('CURLOPT_PROXYAUTH'))
2432
+ $CURLOPT_PROXYAUTH = CURLOPT_PROXYAUTH;
2433
+ else
2434
+ $CURLOPT_PROXYAUTH = 111;
2435
+ if (defined('CURLAUTH_BASIC'))
2436
+ $CURLAUTH_BASIC = CURLAUTH_BASIC;
2437
+ else
2438
+ $CURLAUTH_BASIC = 1;
2439
+ if (defined('CURLAUTH_DIGEST'))
2440
+ $CURLAUTH_DIGEST = CURLAUTH_DIGEST;
2441
+ else
2442
+ $CURLAUTH_DIGEST = 2;
2443
+ if (defined('CURLAUTH_NTLM'))
2444
+ $CURLAUTH_NTLM = CURLAUTH_NTLM;
2445
+ else
2446
+ $CURLAUTH_NTLM = 8;
2447
+
2448
+ $this->debug('connect using cURL');
2449
+ // init CURL
2450
+ $this->ch = curl_init();
2451
+ // set url
2452
+ $hostURL = ($this->port != '') ? "$this->scheme://$this->host:$this->port" : "$this->scheme://$this->host";
2453
+ // add path
2454
+ $hostURL .= $this->path;
2455
+ $this->setCurlOption(CURLOPT_URL, $hostURL);
2456
+ // follow location headers (re-directs)
2457
+ if (ini_get('safe_mode') || ini_get('open_basedir')) {
2458
+ $this->debug('safe_mode or open_basedir set, so do not set CURLOPT_FOLLOWLOCATION');
2459
+ $this->debug('safe_mode = ');
2460
+ $this->appendDebug($this->varDump(ini_get('safe_mode')));
2461
+ $this->debug('open_basedir = ');
2462
+ $this->appendDebug($this->varDump(ini_get('open_basedir')));
2463
+ } else {
2464
+ $this->setCurlOption(CURLOPT_FOLLOWLOCATION, 1);
2465
+ }
2466
+ // ask for headers in the response output
2467
+ $this->setCurlOption(CURLOPT_HEADER, 1);
2468
+ // ask for the response output as the return value
2469
+ $this->setCurlOption(CURLOPT_RETURNTRANSFER, 1);
2470
+ // encode
2471
+ // We manage this ourselves through headers and encoding
2472
+ // if(function_exists('gzuncompress')){
2473
+ // $this->setCurlOption(CURLOPT_ENCODING, 'deflate');
2474
+ // }
2475
+ // persistent connection
2476
+ if ($this->persistentConnection) {
2477
+ // I believe the following comment is now bogus, having applied to
2478
+ // the code when it used CURLOPT_CUSTOMREQUEST to send the request.
2479
+ // The way we send data, we cannot use persistent connections, since
2480
+ // there will be some "junk" at the end of our request.
2481
+ //$this->setCurlOption(CURL_HTTP_VERSION_1_1, true);
2482
+ $this->persistentConnection = false;
2483
+ $this->setHeader('Connection', 'close');
2484
+ }
2485
+ // set timeouts
2486
+ if ($connection_timeout != 0) {
2487
+ $this->setCurlOption($CURLOPT_CONNECTIONTIMEOUT, $connection_timeout);
2488
+ }
2489
+ if ($response_timeout != 0) {
2490
+ $this->setCurlOption(CURLOPT_TIMEOUT, $response_timeout);
2491
+ }
2492
+
2493
+ if ($this->scheme == 'https') {
2494
+ $this->debug('set cURL SSL verify options');
2495
+ // recent versions of cURL turn on peer/host checking by default,
2496
+ // while PHP binaries are not compiled with a default location for the
2497
+ // CA cert bundle, so disable peer/host checking.
2498
+ //$this->setCurlOption(CURLOPT_CAINFO, 'f:\php-4.3.2-win32\extensions\curl-ca-bundle.crt');
2499
+ $this->setCurlOption(CURLOPT_SSL_VERIFYPEER, 0);
2500
+ $this->setCurlOption(CURLOPT_SSL_VERIFYHOST, 0);
2501
+
2502
+ // support client certificates (thanks Tobias Boes, Doug Anarino, Eryan Ariobowo)
2503
+ if ($this->authtype == 'certificate') {
2504
+ $this->debug('set cURL certificate options');
2505
+ if (isset($this->certRequest['cainfofile'])) {
2506
+ $this->setCurlOption(CURLOPT_CAINFO, $this->certRequest['cainfofile']);
2507
+ }
2508
+ if (isset($this->certRequest['verifypeer'])) {
2509
+ $this->setCurlOption(CURLOPT_SSL_VERIFYPEER, $this->certRequest['verifypeer']);
2510
+ } else {
2511
+ $this->setCurlOption(CURLOPT_SSL_VERIFYPEER, 1);
2512
+ }
2513
+ if (isset($this->certRequest['verifyhost'])) {
2514
+ $this->setCurlOption(CURLOPT_SSL_VERIFYHOST, $this->certRequest['verifyhost']);
2515
+ } else {
2516
+ $this->setCurlOption(CURLOPT_SSL_VERIFYHOST, 1);
2517
+ }
2518
+ if (isset($this->certRequest['sslcertfile'])) {
2519
+ $this->setCurlOption(CURLOPT_SSLCERT, $this->certRequest['sslcertfile']);
2520
+ }
2521
+ if (isset($this->certRequest['sslkeyfile'])) {
2522
+ $this->setCurlOption(CURLOPT_SSLKEY, $this->certRequest['sslkeyfile']);
2523
+ }
2524
+ if (isset($this->certRequest['passphrase'])) {
2525
+ $this->setCurlOption(CURLOPT_SSLKEYPASSWD, $this->certRequest['passphrase']);
2526
+ }
2527
+ if (isset($this->certRequest['certpassword'])) {
2528
+ $this->setCurlOption(CURLOPT_SSLCERTPASSWD, $this->certRequest['certpassword']);
2529
+ }
2530
+ }
2531
+ }
2532
+ if ($this->authtype && ($this->authtype != 'certificate')) {
2533
+ if ($this->username) {
2534
+ $this->debug('set cURL username/password');
2535
+ $this->setCurlOption(CURLOPT_USERPWD, "$this->username:$this->password");
2536
+ }
2537
+ if ($this->authtype == 'basic') {
2538
+ $this->debug('set cURL for Basic authentication');
2539
+ $this->setCurlOption($CURLOPT_HTTPAUTH, $CURLAUTH_BASIC);
2540
+ }
2541
+ if ($this->authtype == 'digest') {
2542
+ $this->debug('set cURL for digest authentication');
2543
+ $this->setCurlOption($CURLOPT_HTTPAUTH, $CURLAUTH_DIGEST);
2544
+ }
2545
+ if ($this->authtype == 'ntlm') {
2546
+ $this->debug('set cURL for NTLM authentication');
2547
+ $this->setCurlOption($CURLOPT_HTTPAUTH, $CURLAUTH_NTLM);
2548
+ }
2549
+ }
2550
+ if (is_array($this->proxy)) {
2551
+ $this->debug('set cURL proxy options');
2552
+ if ($this->proxy['port'] != '') {
2553
+ $this->setCurlOption(CURLOPT_PROXY, $this->proxy['host'].':'.$this->proxy['port']);
2554
+ } else {
2555
+ $this->setCurlOption(CURLOPT_PROXY, $this->proxy['host']);
2556
+ }
2557
+ if ($this->proxy['username'] || $this->proxy['password']) {
2558
+ $this->debug('set cURL proxy authentication options');
2559
+ $this->setCurlOption(CURLOPT_PROXYUSERPWD, $this->proxy['username'].':'.$this->proxy['password']);
2560
+ if ($this->proxy['authtype'] == 'basic') {
2561
+ $this->setCurlOption($CURLOPT_PROXYAUTH, $CURLAUTH_BASIC);
2562
+ }
2563
+ if ($this->proxy['authtype'] == 'ntlm') {
2564
+ $this->setCurlOption($CURLOPT_PROXYAUTH, $CURLAUTH_NTLM);
2565
+ }
2566
+ }
2567
+ }
2568
+ $this->debug('cURL connection set up');
2569
+ return true;
2570
+ } else {
2571
+ $this->setError('Unknown scheme ' . $this->scheme);
2572
+ $this->debug('Unknown scheme ' . $this->scheme);
2573
+ return false;
2574
+ }
2575
+ }
2576
+
2577
+ /**
2578
+ * sends the SOAP request and gets the SOAP response via HTTP[S]
2579
+ *
2580
+ * @param string $data message data
2581
+ * @param integer $timeout set connection timeout in seconds
2582
+ * @param integer $response_timeout set response timeout in seconds
2583
+ * @param array $cookies cookies to send
2584
+ * @return string data
2585
+ * @access public
2586
+ */
2587
+ function send($data, $timeout=0, $response_timeout=30, $cookies=NULL) {
2588
+
2589
+ $this->debug('entered send() with data of length: '.strlen($data));
2590
+
2591
+ $this->tryagain = true;
2592
+ $tries = 0;
2593
+ while ($this->tryagain) {
2594
+ $this->tryagain = false;
2595
+ if ($tries++ < 2) {
2596
+ // make connnection
2597
+ if (!$this->connect($timeout, $response_timeout)){
2598
+ return false;
2599
+ }
2600
+
2601
+ // send request
2602
+ if (!$this->sendRequest($data, $cookies)){
2603
+ return false;
2604
+ }
2605
+
2606
+ // get response
2607
+ $respdata = $this->getResponse();
2608
+ } else {
2609
+ $this->setError("Too many tries to get an OK response ($this->response_status_line)");
2610
+ }
2611
+ }
2612
+ $this->debug('end of send()');
2613
+ return $respdata;
2614
+ }
2615
+
2616
+
2617
+ /**
2618
+ * sends the SOAP request and gets the SOAP response via HTTPS using CURL
2619
+ *
2620
+ * @param string $data message data
2621
+ * @param integer $timeout set connection timeout in seconds
2622
+ * @param integer $response_timeout set response timeout in seconds
2623
+ * @param array $cookies cookies to send
2624
+ * @return string data
2625
+ * @access public
2626
+ * @deprecated
2627
+ */
2628
+ function sendHTTPS($data, $timeout=0, $response_timeout=30, $cookies) {
2629
+ return $this->send($data, $timeout, $response_timeout, $cookies);
2630
+ }
2631
+
2632
+ /**
2633
+ * if authenticating, set user credentials here
2634
+ *
2635
+ * @param string $username
2636
+ * @param string $password
2637
+ * @param string $authtype (basic|digest|certificate|ntlm)
2638
+ * @param array $digestRequest (keys must be nonce, nc, realm, qop)
2639
+ * @param array $certRequest (keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, certpassword (optional), verifypeer (optional), verifyhost (optional): see corresponding options in cURL docs)
2640
+ * @access public
2641
+ */
2642
+ function setCredentials($username, $password, $authtype = 'basic', $digestRequest = array(), $certRequest = array()) {
2643
+ $this->debug("setCredentials username=$username authtype=$authtype digestRequest=");
2644
+ $this->appendDebug($this->varDump($digestRequest));
2645
+ $this->debug("certRequest=");
2646
+ $this->appendDebug($this->varDump($certRequest));
2647
+ // cf. RFC 2617
2648
+ if ($authtype == 'basic') {
2649
+ $this->setHeader('Authorization', 'Basic '.base64_encode(str_replace(':','',$username).':'.$password));
2650
+ } elseif ($authtype == 'digest') {
2651
+ if (isset($digestRequest['nonce'])) {
2652
+ $digestRequest['nc'] = isset($digestRequest['nc']) ? $digestRequest['nc']++ : 1;
2653
+
2654
+ // calculate the Digest hashes (calculate code based on digest implementation found at: http://www.rassoc.com/gregr/weblog/stories/2002/07/09/webServicesSecurityHttpDigestAuthenticationWithoutActiveDirectory.html)
2655
+
2656
+ // A1 = unq(username-value) ":" unq(realm-value) ":" passwd
2657
+ $A1 = $username. ':' . (isset($digestRequest['realm']) ? $digestRequest['realm'] : '') . ':' . $password;
2658
+
2659
+ // H(A1) = MD5(A1)
2660
+ $HA1 = md5($A1);
2661
+
2662
+ // A2 = Method ":" digest-uri-value
2663
+ $A2 = $this->request_method . ':' . $this->digest_uri;
2664
+
2665
+ // H(A2)
2666
+ $HA2 = md5($A2);
2667
+
2668
+ // KD(secret, data) = H(concat(secret, ":", data))
2669
+ // if qop == auth:
2670
+ // request-digest = <"> < KD ( H(A1), unq(nonce-value)
2671
+ // ":" nc-value
2672
+ // ":" unq(cnonce-value)
2673
+ // ":" unq(qop-value)
2674
+ // ":" H(A2)
2675
+ // ) <">
2676
+ // if qop is missing,
2677
+ // request-digest = <"> < KD ( H(A1), unq(nonce-value) ":" H(A2) ) > <">
2678
+
2679
+ $unhashedDigest = '';
2680
+ $nonce = isset($digestRequest['nonce']) ? $digestRequest['nonce'] : '';
2681
+ $cnonce = $nonce;
2682
+ if ($digestRequest['qop'] != '') {
2683
+ $unhashedDigest = $HA1 . ':' . $nonce . ':' . sprintf("%08d", $digestRequest['nc']) . ':' . $cnonce . ':' . $digestRequest['qop'] . ':' . $HA2;
2684
+ } else {
2685
+ $unhashedDigest = $HA1 . ':' . $nonce . ':' . $HA2;
2686
+ }
2687
+
2688
+ $hashedDigest = md5($unhashedDigest);
2689
+
2690
+ $opaque = '';
2691
+ if (isset($digestRequest['opaque'])) {
2692
+ $opaque = ', opaque="' . $digestRequest['opaque'] . '"';
2693
+ }
2694
+
2695
+ $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 . '"');
2696
+ }
2697
+ } elseif ($authtype == 'certificate') {
2698
+ $this->certRequest = $certRequest;
2699
+ $this->debug('Authorization header not set for certificate');
2700
+ } elseif ($authtype == 'ntlm') {
2701
+ // do nothing
2702
+ $this->debug('Authorization header not set for ntlm');
2703
+ }
2704
+ $this->username = $username;
2705
+ $this->password = $password;
2706
+ $this->authtype = $authtype;
2707
+ $this->digestRequest = $digestRequest;
2708
+ }
2709
+
2710
+ /**
2711
+ * set the soapaction value
2712
+ *
2713
+ * @param string $soapaction
2714
+ * @access public
2715
+ */
2716
+ function setSOAPAction($soapaction) {
2717
+ $this->setHeader('SOAPAction', '"' . $soapaction . '"');
2718
+ }
2719
+
2720
+ /**
2721
+ * use http encoding
2722
+ *
2723
+ * @param string $enc encoding style. supported values: gzip, deflate, or both
2724
+ * @access public
2725
+ */
2726
+ function setEncoding($enc='gzip, deflate') {
2727
+ if (function_exists('gzdeflate')) {
2728
+ $this->protocol_version = '1.1';
2729
+ $this->setHeader('Accept-Encoding', $enc);
2730
+ if (!isset($this->outgoing_headers['Connection'])) {
2731
+ $this->setHeader('Connection', 'close');
2732
+ $this->persistentConnection = false;
2733
+ }
2734
+ // deprecated as of PHP 5.3.0
2735
+ //set_magic_quotes_runtime(0);
2736
+ $this->encoding = $enc;
2737
+ }
2738
+ }
2739
+
2740
+ /**
2741
+ * set proxy info here
2742
+ *
2743
+ * @param string $proxyhost use an empty string to remove proxy
2744
+ * @param string $proxyport
2745
+ * @param string $proxyusername
2746
+ * @param string $proxypassword
2747
+ * @param string $proxyauthtype (basic|ntlm)
2748
+ * @access public
2749
+ */
2750
+ function setProxy($proxyhost, $proxyport, $proxyusername = '', $proxypassword = '', $proxyauthtype = 'basic') {
2751
+ if ($proxyhost) {
2752
+ $this->proxy = array(
2753
+ 'host' => $proxyhost,
2754
+ 'port' => $proxyport,
2755
+ 'username' => $proxyusername,
2756
+ 'password' => $proxypassword,
2757
+ 'authtype' => $proxyauthtype
2758
+ );
2759
+ if ($proxyusername != '' && $proxypassword != '' && $proxyauthtype = 'basic') {
2760
+ $this->setHeader('Proxy-Authorization', ' Basic '.base64_encode($proxyusername.':'.$proxypassword));
2761
+ }
2762
+ } else {
2763
+ $this->debug('remove proxy');
2764
+ $proxy = null;
2765
+ unsetHeader('Proxy-Authorization');
2766
+ }
2767
+ }
2768
+
2769
+
2770
+ /**
2771
+ * Test if the given string starts with a header that is to be skipped.
2772
+ * Skippable headers result from chunked transfer and proxy requests.
2773
+ *
2774
+ * @param string $data The string to check.
2775
+ * @returns boolean Whether a skippable header was found.
2776
+ * @access private
2777
+ */
2778
+ function isSkippableCurlHeader(&$data) {
2779
+ $skipHeaders = array( 'HTTP/1.1 100',
2780
+ 'HTTP/1.0 301',
2781
+ 'HTTP/1.1 301',
2782
+ 'HTTP/1.0 302',
2783
+ 'HTTP/1.1 302',
2784
+ 'HTTP/1.0 401',
2785
+ 'HTTP/1.1 401',
2786
+ 'HTTP/1.0 200 Connection established');
2787
+ foreach ($skipHeaders as $hd) {
2788
+ $prefix = substr($data, 0, strlen($hd));
2789
+ if ($prefix == $hd) return true;
2790
+ }
2791
+
2792
+ return false;
2793
+ }
2794
+
2795
+ /**
2796
+ * decode a string that is encoded w/ "chunked' transfer encoding
2797
+ * as defined in RFC2068 19.4.6
2798
+ *
2799
+ * @param string $buffer
2800
+ * @param string $lb
2801
+ * @returns string
2802
+ * @access public
2803
+ * @deprecated
2804
+ */
2805
+ function decodeChunked($buffer, $lb){
2806
+ // length := 0
2807
+ $length = 0;
2808
+ $new = '';
2809
+
2810
+ // read chunk-size, chunk-extension (if any) and CRLF
2811
+ // get the position of the linebreak
2812
+ $chunkend = strpos($buffer, $lb);
2813
+ if ($chunkend == FALSE) {
2814
+ $this->debug('no linebreak found in decodeChunked');
2815
+ return $new;
2816
+ }
2817
+ $temp = substr($buffer,0,$chunkend);
2818
+ $chunk_size = hexdec( trim($temp) );
2819
+ $chunkstart = $chunkend + strlen($lb);
2820
+ // while (chunk-size > 0) {
2821
+ while ($chunk_size > 0) {
2822
+ $this->debug("chunkstart: $chunkstart chunk_size: $chunk_size");
2823
+ $chunkend = strpos( $buffer, $lb, $chunkstart + $chunk_size);
2824
+
2825
+ // Just in case we got a broken connection
2826
+ if ($chunkend == FALSE) {
2827
+ $chunk = substr($buffer,$chunkstart);
2828
+ // append chunk-data to entity-body
2829
+ $new .= $chunk;
2830
+ $length += strlen($chunk);
2831
+ break;
2832
+ }
2833
+
2834
+ // read chunk-data and CRLF
2835
+ $chunk = substr($buffer,$chunkstart,$chunkend-$chunkstart);
2836
+ // append chunk-data to entity-body
2837
+ $new .= $chunk;
2838
+ // length := length + chunk-size
2839
+ $length += strlen($chunk);
2840
+ // read chunk-size and CRLF
2841
+ $chunkstart = $chunkend + strlen($lb);
2842
+
2843
+ $chunkend = strpos($buffer, $lb, $chunkstart) + strlen($lb);
2844
+ if ($chunkend == FALSE) {
2845
+ break; //Just in case we got a broken connection
2846
+ }
2847
+ $temp = substr($buffer,$chunkstart,$chunkend-$chunkstart);
2848
+ $chunk_size = hexdec( trim($temp) );
2849
+ $chunkstart = $chunkend;
2850
+ }
2851
+ return $new;
2852
+ }
2853
+
2854
+ /**
2855
+ * Writes the payload, including HTTP headers, to $this->outgoing_payload.
2856
+ *
2857
+ * @param string $data HTTP body
2858
+ * @param string $cookie_str data for HTTP Cookie header
2859
+ * @return void
2860
+ * @access private
2861
+ */
2862
+ function buildPayload($data, $cookie_str = '') {
2863
+ // Note: for cURL connections, $this->outgoing_payload is ignored,
2864
+ // as is the Content-Length header, but these are still created as
2865
+ // debugging guides.
2866
+
2867
+ // add content-length header
2868
+ if ($this->request_method != 'GET') {
2869
+ $this->setHeader('Content-Length', strlen($data));
2870
+ }
2871
+
2872
+ // start building outgoing payload:
2873
+ if ($this->proxy) {
2874
+ $uri = $this->url;
2875
+ } else {
2876
+ $uri = $this->uri;
2877
+ }
2878
+ $req = "$this->request_method $uri HTTP/$this->protocol_version";
2879
+ $this->debug("HTTP request: $req");
2880
+ $this->outgoing_payload = "$req\r\n";
2881
+
2882
+ // loop thru headers, serializing
2883
+ foreach($this->outgoing_headers as $k => $v){
2884
+ $hdr = $k.': '.$v;
2885
+ $this->debug("HTTP header: $hdr");
2886
+ $this->outgoing_payload .= "$hdr\r\n";
2887
+ }
2888
+
2889
+ // add any cookies
2890
+ if ($cookie_str != '') {
2891
+ $hdr = 'Cookie: '.$cookie_str;
2892
+ $this->debug("HTTP header: $hdr");
2893
+ $this->outgoing_payload .= "$hdr\r\n";
2894
+ }
2895
+
2896
+ // header/body separator
2897
+ $this->outgoing_payload .= "\r\n";
2898
+
2899
+ // add data
2900
+ $this->outgoing_payload .= $data;
2901
+ }
2902
+
2903
+ /**
2904
+ * sends the SOAP request via HTTP[S]
2905
+ *
2906
+ * @param string $data message data
2907
+ * @param array $cookies cookies to send
2908
+ * @return boolean true if OK, false if problem
2909
+ * @access private
2910
+ */
2911
+ function sendRequest($data, $cookies = NULL) {
2912
+ // build cookie string
2913
+ $cookie_str = $this->getCookiesForRequest($cookies, (($this->scheme == 'ssl') || ($this->scheme == 'https')));
2914
+
2915
+ // build payload
2916
+ $this->buildPayload($data, $cookie_str);
2917
+
2918
+ if ($this->io_method() == 'socket') {
2919
+ // send payload
2920
+ if(!fputs($this->fp, $this->outgoing_payload, strlen($this->outgoing_payload))) {
2921
+ $this->setError('couldn\'t write message data to socket');
2922
+ $this->debug('couldn\'t write message data to socket');
2923
+ return false;
2924
+ }
2925
+ $this->debug('wrote data to socket, length = ' . strlen($this->outgoing_payload));
2926
+ return true;
2927
+ } else if ($this->io_method() == 'curl') {
2928
+ // set payload
2929
+ // cURL does say this should only be the verb, and in fact it
2930
+ // turns out that the URI and HTTP version are appended to this, which
2931
+ // some servers refuse to work with (so we no longer use this method!)
2932
+ //$this->setCurlOption(CURLOPT_CUSTOMREQUEST, $this->outgoing_payload);
2933
+ $curl_headers = array();
2934
+ foreach($this->outgoing_headers as $k => $v){
2935
+ if ($k == 'Connection' || $k == 'Content-Length' || $k == 'Host' || $k == 'Authorization' || $k == 'Proxy-Authorization') {
2936
+ $this->debug("Skip cURL header $k: $v");
2937
+ } else {
2938
+ $curl_headers[] = "$k: $v";
2939
+ }
2940
+ }
2941
+ if ($cookie_str != '') {
2942
+ $curl_headers[] = 'Cookie: ' . $cookie_str;
2943
+ }
2944
+ $this->setCurlOption(CURLOPT_HTTPHEADER, $curl_headers);
2945
+ $this->debug('set cURL HTTP headers');
2946
+ if ($this->request_method == "POST") {
2947
+ $this->setCurlOption(CURLOPT_POST, 1);
2948
+ $this->setCurlOption(CURLOPT_POSTFIELDS, $data);
2949
+ $this->debug('set cURL POST data');
2950
+ } else {
2951
+ }
2952
+ // insert custom user-set cURL options
2953
+ foreach ($this->ch_options as $key => $val) {
2954
+ $this->setCurlOption($key, $val);
2955
+ }
2956
+
2957
+ $this->debug('set cURL payload');
2958
+ return true;
2959
+ }
2960
+ }
2961
+
2962
+ /**
2963
+ * gets the SOAP response via HTTP[S]
2964
+ *
2965
+ * @return string the response (also sets member variables like incoming_payload)
2966
+ * @access private
2967
+ */
2968
+ function getResponse(){
2969
+ $this->incoming_payload = '';
2970
+
2971
+ if ($this->io_method() == 'socket') {
2972
+ // loop until headers have been retrieved
2973
+ $data = '';
2974
+ while (!isset($lb)){
2975
+
2976
+ // We might EOF during header read.
2977
+ if(feof($this->fp)) {
2978
+ $this->incoming_payload = $data;
2979
+ $this->debug('found no headers before EOF after length ' . strlen($data));
2980
+ $this->debug("received before EOF:\n" . $data);
2981
+ $this->setError('server failed to send headers');
2982
+ return false;
2983
+ }
2984
+
2985
+ $tmp = fgets($this->fp, 256);
2986
+ $tmplen = strlen($tmp);
2987
+ $this->debug("read line of $tmplen bytes: " . trim($tmp));
2988
+
2989
+ if ($tmplen == 0) {
2990
+ $this->incoming_payload = $data;
2991
+ $this->debug('socket read of headers timed out after length ' . strlen($data));
2992
+ $this->debug("read before timeout: " . $data);
2993
+ $this->setError('socket read of headers timed out');
2994
+ return false;
2995
+ }
2996
+
2997
+ $data .= $tmp;
2998
+ $pos = strpos($data,"\r\n\r\n");
2999
+ if($pos > 1){
3000
+ $lb = "\r\n";
3001
+ } else {
3002
+ $pos = strpos($data,"\n\n");
3003
+ if($pos > 1){
3004
+ $lb = "\n";
3005
+ }
3006
+ }
3007
+ // remove 100 headers
3008
+ if (isset($lb) && preg_match('/^HTTP\/1.1 100/',$data)) {
3009
+ unset($lb);
3010
+ $data = '';
3011
+ }//
3012
+ }
3013
+ // store header data
3014
+ $this->incoming_payload .= $data;
3015
+ $this->debug('found end of headers after length ' . strlen($data));
3016
+ // process headers
3017
+ $header_data = trim(substr($data,0,$pos));
3018
+ $header_array = explode($lb,$header_data);
3019
+ $this->incoming_headers = array();
3020
+ $this->incoming_cookies = array();
3021
+ foreach($header_array as $header_line){
3022
+ $arr = explode(':',$header_line, 2);
3023
+ if(count($arr) > 1){
3024
+ $header_name = strtolower(trim($arr[0]));
3025
+ $this->incoming_headers[$header_name] = trim($arr[1]);
3026
+ if ($header_name == 'set-cookie') {
3027
+ // TODO: allow multiple cookies from parseCookie
3028
+ $cookie = $this->parseCookie(trim($arr[1]));
3029
+ if ($cookie) {
3030
+ $this->incoming_cookies[] = $cookie;
3031
+ $this->debug('found cookie: ' . $cookie['name'] . ' = ' . $cookie['value']);
3032
+ } else {
3033
+ $this->debug('did not find cookie in ' . trim($arr[1]));
3034
+ }
3035
+ }
3036
+ } else if (isset($header_name)) {
3037
+ // append continuation line to previous header
3038
+ $this->incoming_headers[$header_name] .= $lb . ' ' . $header_line;
3039
+ }
3040
+ }
3041
+
3042
+ // loop until msg has been received
3043
+ if (isset($this->incoming_headers['transfer-encoding']) && strtolower($this->incoming_headers['transfer-encoding']) == 'chunked') {
3044
+ $content_length = 2147483647; // ignore any content-length header
3045
+ $chunked = true;
3046
+ $this->debug("want to read chunked content");
3047
+ } elseif (isset($this->incoming_headers['content-length'])) {
3048
+ $content_length = $this->incoming_headers['content-length'];
3049
+ $chunked = false;
3050
+ $this->debug("want to read content of length $content_length");
3051
+ } else {
3052
+ $content_length = 2147483647;
3053
+ $chunked = false;
3054
+ $this->debug("want to read content to EOF");
3055
+ }
3056
+ $data = '';
3057
+ do {
3058
+ if ($chunked) {
3059
+ $tmp = fgets($this->fp, 256);
3060
+ $tmplen = strlen($tmp);
3061
+ $this->debug("read chunk line of $tmplen bytes");
3062
+ if ($tmplen == 0) {
3063
+ $this->incoming_payload = $data;
3064
+ $this->debug('socket read of chunk length timed out after length ' . strlen($data));
3065
+ $this->debug("read before timeout:\n" . $data);
3066
+ $this->setError('socket read of chunk length timed out');
3067
+ return false;
3068
+ }
3069
+ $content_length = hexdec(trim($tmp));
3070
+ $this->debug("chunk length $content_length");
3071
+ }
3072
+ $strlen = 0;
3073
+ while (($strlen < $content_length) && (!feof($this->fp))) {
3074
+ $readlen = min(8192, $content_length - $strlen);
3075
+ $tmp = fread($this->fp, $readlen);
3076
+ $tmplen = strlen($tmp);
3077
+ $this->debug("read buffer of $tmplen bytes");
3078
+ if (($tmplen == 0) && (!feof($this->fp))) {
3079
+ $this->incoming_payload = $data;
3080
+ $this->debug('socket read of body timed out after length ' . strlen($data));
3081
+ $this->debug("read before timeout:\n" . $data);
3082
+ $this->setError('socket read of body timed out');
3083
+ return false;
3084
+ }
3085
+ $strlen += $tmplen;
3086
+ $data .= $tmp;
3087
+ }
3088
+ if ($chunked && ($content_length > 0)) {
3089
+ $tmp = fgets($this->fp, 256);
3090
+ $tmplen = strlen($tmp);
3091
+ $this->debug("read chunk terminator of $tmplen bytes");
3092
+ if ($tmplen == 0) {
3093
+ $this->incoming_payload = $data;
3094
+ $this->debug('socket read of chunk terminator timed out after length ' . strlen($data));
3095
+ $this->debug("read before timeout:\n" . $data);
3096
+ $this->setError('socket read of chunk terminator timed out');
3097
+ return false;
3098
+ }
3099
+ }
3100
+ } while ($chunked && ($content_length > 0) && (!feof($this->fp)));
3101
+ if (feof($this->fp)) {
3102
+ $this->debug('read to EOF');
3103
+ }
3104
+ $this->debug('read body of length ' . strlen($data));
3105
+ $this->incoming_payload .= $data;
3106
+ $this->debug('received a total of '.strlen($this->incoming_payload).' bytes of data from server');
3107
+
3108
+ // close filepointer
3109
+ if(
3110
+ (isset($this->incoming_headers['connection']) && strtolower($this->incoming_headers['connection']) == 'close') ||
3111
+ (! $this->persistentConnection) || feof($this->fp)){
3112
+ fclose($this->fp);
3113
+ $this->fp = false;
3114
+ $this->debug('closed socket');
3115
+ }
3116
+
3117
+ // connection was closed unexpectedly
3118
+ if($this->incoming_payload == ''){
3119
+ $this->setError('no response from server');
3120
+ return false;
3121
+ }
3122
+
3123
+ // decode transfer-encoding
3124
+ // if(isset($this->incoming_headers['transfer-encoding']) && strtolower($this->incoming_headers['transfer-encoding']) == 'chunked'){
3125
+ // if(!$data = $this->decodeChunked($data, $lb)){
3126
+ // $this->setError('Decoding of chunked data failed');
3127
+ // return false;
3128
+ // }
3129
+ //print "<pre>\nde-chunked:\n---------------\n$data\n\n---------------\n</pre>";
3130
+ // set decoded payload
3131
+ // $this->incoming_payload = $header_data.$lb.$lb.$data;
3132
+ // }
3133
+
3134
+ } else if ($this->io_method() == 'curl') {
3135
+ // send and receive
3136
+ $this->debug('send and receive with cURL');
3137
+ $this->incoming_payload = curl_exec($this->ch);
3138
+ $data = $this->incoming_payload;
3139
+
3140
+ $cErr = curl_error($this->ch);
3141
+ if ($cErr != '') {
3142
+ $err = 'cURL ERROR: '.curl_errno($this->ch).': '.$cErr.'<br>';
3143
+ // TODO: there is a PHP bug that can cause this to SEGV for CURLINFO_CONTENT_TYPE
3144
+ foreach(curl_getinfo($this->ch) as $k => $v){
3145
+ $err .= "$k: $v<br>";
3146
+ }
3147
+ $this->debug($err);
3148
+ $this->setError($err);
3149
+ curl_close($this->ch);
3150
+ return false;
3151
+ } else {
3152
+ //echo '<pre>';
3153
+ //var_dump(curl_getinfo($this->ch));
3154
+ //echo '</pre>';
3155
+ }
3156
+ // close curl
3157
+ $this->debug('No cURL error, closing cURL');
3158
+ curl_close($this->ch);
3159
+
3160
+ // try removing skippable headers
3161
+ $savedata = $data;
3162
+ while ($this->isSkippableCurlHeader($data)) {
3163
+ $this->debug("Found HTTP header to skip");
3164
+ if ($pos = strpos($data,"\r\n\r\n")) {
3165
+ $data = ltrim(substr($data,$pos));
3166
+ } elseif($pos = strpos($data,"\n\n") ) {
3167
+ $data = ltrim(substr($data,$pos));
3168
+ }
3169
+ }
3170
+
3171
+ if ($data == '') {
3172
+ // have nothing left; just remove 100 header(s)
3173
+ $data = $savedata;
3174
+ while (preg_match('/^HTTP\/1.1 100/',$data)) {
3175
+ if ($pos = strpos($data,"\r\n\r\n")) {
3176
+ $data = ltrim(substr($data,$pos));
3177
+ } elseif($pos = strpos($data,"\n\n") ) {
3178
+ $data = ltrim(substr($data,$pos));
3179
+ }
3180
+ }
3181
+ }
3182
+
3183
+ // separate content from HTTP headers
3184
+ if ($pos = strpos($data,"\r\n\r\n")) {
3185
+ $lb = "\r\n";
3186
+ } elseif( $pos = strpos($data,"\n\n")) {
3187
+ $lb = "\n";
3188
+ } else {
3189
+ $this->debug('no proper separation of headers and document');
3190
+ $this->setError('no proper separation of headers and document');
3191
+ return false;
3192
+ }
3193
+ $header_data = trim(substr($data,0,$pos));
3194
+ $header_array = explode($lb,$header_data);
3195
+ $data = ltrim(substr($data,$pos));
3196
+ $this->debug('found proper separation of headers and document');
3197
+ $this->debug('cleaned data, stringlen: '.strlen($data));
3198
+ // clean headers
3199
+ foreach ($header_array as $header_line) {
3200
+ $arr = explode(':',$header_line,2);
3201
+ if(count($arr) > 1){
3202
+ $header_name = strtolower(trim($arr[0]));
3203
+ $this->incoming_headers[$header_name] = trim($arr[1]);
3204
+ if ($header_name == 'set-cookie') {
3205
+ // TODO: allow multiple cookies from parseCookie
3206
+ $cookie = $this->parseCookie(trim($arr[1]));
3207
+ if ($cookie) {
3208
+ $this->incoming_cookies[] = $cookie;
3209
+ $this->debug('found cookie: ' . $cookie['name'] . ' = ' . $cookie['value']);
3210
+ } else {
3211
+ $this->debug('did not find cookie in ' . trim($arr[1]));
3212
+ }
3213
+ }
3214
+ } else if (isset($header_name)) {
3215
+ // append continuation line to previous header
3216
+ $this->incoming_headers[$header_name] .= $lb . ' ' . $header_line;
3217
+ }
3218
+ }
3219
+ }
3220
+
3221
+ $this->response_status_line = $header_array[0];
3222
+ $arr = explode(' ', $this->response_status_line, 3);
3223
+ $http_version = $arr[0];
3224
+ $http_status = intval($arr[1]);
3225
+ $http_reason = count($arr) > 2 ? $arr[2] : '';
3226
+
3227
+ // see if we need to resend the request with http digest authentication
3228
+ if (isset($this->incoming_headers['location']) && ($http_status == 301 || $http_status == 302)) {
3229
+ $this->debug("Got $http_status $http_reason with Location: " . $this->incoming_headers['location']);
3230
+ $this->setURL($this->incoming_headers['location']);
3231
+ $this->tryagain = true;
3232
+ return false;
3233
+ }
3234
+
3235
+ // see if we need to resend the request with http digest authentication
3236
+ if (isset($this->incoming_headers['www-authenticate']) && $http_status == 401) {
3237
+ $this->debug("Got 401 $http_reason with WWW-Authenticate: " . $this->incoming_headers['www-authenticate']);
3238
+ if (strstr($this->incoming_headers['www-authenticate'], "Digest ")) {
3239
+ $this->debug('Server wants digest authentication');
3240
+ // remove "Digest " from our elements
3241
+ $digestString = str_replace('Digest ', '', $this->incoming_headers['www-authenticate']);
3242
+
3243
+ // parse elements into array
3244
+ $digestElements = explode(',', $digestString);
3245
+ foreach ($digestElements as $val) {
3246
+ $tempElement = explode('=', trim($val), 2);
3247
+ $digestRequest[$tempElement[0]] = str_replace("\"", '', $tempElement[1]);
3248
+ }
3249
+
3250
+ // should have (at least) qop, realm, nonce
3251
+ if (isset($digestRequest['nonce'])) {
3252
+ $this->setCredentials($this->username, $this->password, 'digest', $digestRequest);
3253
+ $this->tryagain = true;
3254
+ return false;
3255
+ }
3256
+ }
3257
+ $this->debug('HTTP authentication failed');
3258
+ $this->setError('HTTP authentication failed');
3259
+ return false;
3260
+ }
3261
+
3262
+ if (
3263
+ ($http_status >= 300 && $http_status <= 307) ||
3264
+ ($http_status >= 400 && $http_status <= 417) ||
3265
+ ($http_status >= 501 && $http_status <= 505)
3266
+ ) {
3267
+ $this->setError("Unsupported HTTP response status $http_status $http_reason (soapclient->response has contents of the response)");
3268
+ return false;
3269
+ }
3270
+
3271
+ // decode content-encoding
3272
+ if(isset($this->incoming_headers['content-encoding']) && $this->incoming_headers['content-encoding'] != ''){
3273
+ if(strtolower($this->incoming_headers['content-encoding']) == 'deflate' || strtolower($this->incoming_headers['content-encoding']) == 'gzip'){
3274
+ // if decoding works, use it. else assume data wasn't gzencoded
3275
+ if(function_exists('gzinflate')){
3276
+ //$timer->setMarker('starting decoding of gzip/deflated content');
3277
+ // IIS 5 requires gzinflate instead of gzuncompress (similar to IE 5 and gzdeflate v. gzcompress)
3278
+ // this means there are no Zlib headers, although there should be
3279
+ $this->debug('The gzinflate function exists');
3280
+ $datalen = strlen($data);
3281
+ if ($this->incoming_headers['content-encoding'] == 'deflate') {
3282
+ if ($degzdata = @gzinflate($data)) {
3283
+ $data = $degzdata;
3284
+ $this->debug('The payload has been inflated to ' . strlen($data) . ' bytes');
3285
+ if (strlen($data) < $datalen) {
3286
+ // test for the case that the payload has been compressed twice
3287
+ $this->debug('The inflated payload is smaller than the gzipped one; try again');
3288
+ if ($degzdata = @gzinflate($data)) {
3289
+ $data = $degzdata;
3290
+ $this->debug('The payload has been inflated again to ' . strlen($data) . ' bytes');
3291
+ }
3292
+ }
3293
+ } else {
3294
+ $this->debug('Error using gzinflate to inflate the payload');
3295
+ $this->setError('Error using gzinflate to inflate the payload');
3296
+ }
3297
+ } elseif ($this->incoming_headers['content-encoding'] == 'gzip') {
3298
+ if ($degzdata = @gzinflate(substr($data, 10))) { // do our best
3299
+ $data = $degzdata;
3300
+ $this->debug('The payload has been un-gzipped to ' . strlen($data) . ' bytes');
3301
+ if (strlen($data) < $datalen) {
3302
+ // test for the case that the payload has been compressed twice
3303
+ $this->debug('The un-gzipped payload is smaller than the gzipped one; try again');
3304
+ if ($degzdata = @gzinflate(substr($data, 10))) {
3305
+ $data = $degzdata;
3306
+ $this->debug('The payload has been un-gzipped again to ' . strlen($data) . ' bytes');
3307
+ }
3308
+ }
3309
+ } else {
3310
+ $this->debug('Error using gzinflate to un-gzip the payload');
3311
+ $this->setError('Error using gzinflate to un-gzip the payload');
3312
+ }
3313
+ }
3314
+ //$timer->setMarker('finished decoding of gzip/deflated content');
3315
+ //print "<xmp>\nde-inflated:\n---------------\n$data\n-------------\n</xmp>";
3316
+ // set decoded payload
3317
+ $this->incoming_payload = $header_data.$lb.$lb.$data;
3318
+ } else {
3319
+ $this->debug('The server sent compressed data. Your php install must have the Zlib extension compiled in to support this.');
3320
+ $this->setError('The server sent compressed data. Your php install must have the Zlib extension compiled in to support this.');
3321
+ }
3322
+ } else {
3323
+ $this->debug('Unsupported Content-Encoding ' . $this->incoming_headers['content-encoding']);
3324
+ $this->setError('Unsupported Content-Encoding ' . $this->incoming_headers['content-encoding']);
3325
+ }
3326
+ } else {
3327
+ $this->debug('No Content-Encoding header');
3328
+ }
3329
+
3330
+ if(strlen($data) == 0){
3331
+ $this->debug('no data after headers!');
3332
+ $this->setError('no data present after HTTP headers');
3333
+ return false;
3334
+ }
3335
+
3336
+ return $data;
3337
+ }
3338
+
3339
+ /**
3340
+ * sets the content-type for the SOAP message to be sent
3341
+ *
3342
+ * @param string $type the content type, MIME style
3343
+ * @param mixed $charset character set used for encoding (or false)
3344
+ * @access public
3345
+ */
3346
+ function setContentType($type, $charset = false) {
3347
+ $this->setHeader('Content-Type', $type . ($charset ? '; charset=' . $charset : ''));
3348
+ }
3349
+
3350
+ /**
3351
+ * specifies that an HTTP persistent connection should be used
3352
+ *
3353
+ * @return boolean whether the request was honored by this method.
3354
+ * @access public
3355
+ */
3356
+ function usePersistentConnection(){
3357
+ if (isset($this->outgoing_headers['Accept-Encoding'])) {
3358
+ return false;
3359
+ }
3360
+ $this->protocol_version = '1.1';
3361
+ $this->persistentConnection = true;
3362
+ $this->setHeader('Connection', 'Keep-Alive');
3363
+ return true;
3364
+ }
3365
+
3366
+ /**
3367
+ * parse an incoming Cookie into it's parts
3368
+ *
3369
+ * @param string $cookie_str content of cookie
3370
+ * @return array with data of that cookie
3371
+ * @access private
3372
+ */
3373
+ /*
3374
+ * TODO: allow a Set-Cookie string to be parsed into multiple cookies
3375
+ */
3376
+ function parseCookie($cookie_str) {
3377
+ $cookie_str = str_replace('; ', ';', $cookie_str) . ';';
3378
+ $data = preg_split('/;/', $cookie_str);
3379
+ $value_str = $data[0];
3380
+
3381
+ $cookie_param = 'domain=';
3382
+ $start = strpos($cookie_str, $cookie_param);
3383
+ if ($start > 0) {
3384
+ $domain = substr($cookie_str, $start + strlen($cookie_param));
3385
+ $domain = substr($domain, 0, strpos($domain, ';'));
3386
+ } else {
3387
+ $domain = '';
3388
+ }
3389
+
3390
+ $cookie_param = 'expires=';
3391
+ $start = strpos($cookie_str, $cookie_param);
3392
+ if ($start > 0) {
3393
+ $expires = substr($cookie_str, $start + strlen($cookie_param));
3394
+ $expires = substr($expires, 0, strpos($expires, ';'));
3395
+ } else {
3396
+ $expires = '';
3397
+ }
3398
+
3399
+ $cookie_param = 'path=';
3400
+ $start = strpos($cookie_str, $cookie_param);
3401
+ if ( $start > 0 ) {
3402
+ $path = substr($cookie_str, $start + strlen($cookie_param));
3403
+ $path = substr($path, 0, strpos($path, ';'));
3404
+ } else {
3405
+ $path = '/';
3406
+ }
3407
+
3408
+ $cookie_param = ';secure;';
3409
+ if (strpos($cookie_str, $cookie_param) !== FALSE) {
3410
+ $secure = true;
3411
+ } else {
3412
+ $secure = false;
3413
+ }
3414
+
3415
+ $sep_pos = strpos($value_str, '=');
3416
+
3417
+ if ($sep_pos) {
3418
+ $name = substr($value_str, 0, $sep_pos);
3419
+ $value = substr($value_str, $sep_pos + 1);
3420
+ $cookie= array( 'name' => $name,
3421
+ 'value' => $value,
3422
+ 'domain' => $domain,
3423
+ 'path' => $path,
3424
+ 'expires' => $expires,
3425
+ 'secure' => $secure
3426
+ );
3427
+ return $cookie;
3428
+ }
3429
+ return false;
3430
+ }
3431
+
3432
+ /**
3433
+ * sort out cookies for the current request
3434
+ *
3435
+ * @param array $cookies array with all cookies
3436
+ * @param boolean $secure is the send-content secure or not?
3437
+ * @return string for Cookie-HTTP-Header
3438
+ * @access private
3439
+ */
3440
+ function getCookiesForRequest($cookies, $secure=false) {
3441
+ $cookie_str = '';
3442
+ if ((! is_null($cookies)) && (is_array($cookies))) {
3443
+ foreach ($cookies as $cookie) {
3444
+ if (! is_array($cookie)) {
3445
+ continue;
3446
+ }
3447
+ $this->debug("check cookie for validity: ".$cookie['name'].'='.$cookie['value']);
3448
+ if ((isset($cookie['expires'])) && (! empty($cookie['expires']))) {
3449
+ if (strtotime($cookie['expires']) <= time()) {
3450
+ $this->debug('cookie has expired');
3451
+ continue;
3452
+ }
3453
+ }
3454
+ if ((isset($cookie['domain'])) && (! empty($cookie['domain']))) {
3455
+ $domain = preg_quote($cookie['domain']);
3456
+ if (! preg_match("'.*$domain$'i", $this->host)) {
3457
+ $this->debug('cookie has different domain');
3458
+ continue;
3459
+ }
3460
+ }
3461
+ if ((isset($cookie['path'])) && (! empty($cookie['path']))) {
3462
+ $path = preg_quote($cookie['path']);
3463
+ if (! preg_match("'^$path.*'i", $this->path)) {
3464
+ $this->debug('cookie is for a different path');
3465
+ continue;
3466
+ }
3467
+ }
3468
+ if ((! $secure) && (isset($cookie['secure'])) && ($cookie['secure'])) {
3469
+ $this->debug('cookie is secure, transport is not');
3470
+ continue;
3471
+ }
3472
+ $cookie_str .= $cookie['name'] . '=' . $cookie['value'] . '; ';
3473
+ $this->debug('add cookie to Cookie-String: ' . $cookie['name'] . '=' . $cookie['value']);
3474
+ }
3475
+ }
3476
+ return $cookie_str;
3477
+ }
3478
+ }
3479
+
3480
+ ?><?php
3481
+
3482
+
3483
+
3484
+ /**
3485
+ *
3486
+ * nusoap_server allows the user to create a SOAP server
3487
+ * that is capable of receiving messages and returning responses
3488
+ *
3489
+ * @author Dietrich Ayala <dietrich@ganx4.com>
3490
+ * @author Scott Nichol <snichol@users.sourceforge.net>
3491
+ * @version $Id: fsource_nusoap__nusoap.php.html,v 1.2 2010/04/26 20:25:21 snichol Exp $
3492
+ * @access public
3493
+ */
3494
+ class nusoap_server extends nusoap_base {
3495
+ /**
3496
+ * HTTP headers of request
3497
+ * @var array
3498
+ * @access private
3499
+ */
3500
+ var $headers = array();
3501
+ /**
3502
+ * HTTP request
3503
+ * @var string
3504
+ * @access private
3505
+ */
3506
+ var $request = '';
3507
+ /**
3508
+ * SOAP headers from request (incomplete namespace resolution; special characters not escaped) (text)
3509
+ * @var string
3510
+ * @access public
3511
+ */
3512
+ var $requestHeaders = '';
3513
+ /**
3514
+ * SOAP Headers from request (parsed)
3515
+ * @var mixed
3516
+ * @access public
3517
+ */
3518
+ var $requestHeader = NULL;
3519
+ /**
3520
+ * SOAP body request portion (incomplete namespace resolution; special characters not escaped) (text)
3521
+ * @var string
3522
+ * @access public
3523
+ */
3524
+ var $document = '';
3525
+ /**
3526
+ * SOAP payload for request (text)
3527
+ * @var string
3528
+ * @access public
3529
+ */
3530
+ var $requestSOAP = '';
3531
+ /**
3532
+ * requested method namespace URI
3533
+ * @var string
3534
+ * @access private
3535
+ */
3536
+ var $methodURI = '';
3537
+ /**
3538
+ * name of method requested
3539
+ * @var string
3540
+ * @access private
3541
+ */
3542
+ var $methodname = '';
3543
+ /**
3544
+ * method parameters from request
3545
+ * @var array
3546
+ * @access private
3547
+ */
3548
+ var $methodparams = array();
3549
+ /**
3550
+ * SOAP Action from request
3551
+ * @var string
3552
+ * @access private
3553
+ */
3554
+ var $SOAPAction = '';
3555
+ /**
3556
+ * character set encoding of incoming (request) messages
3557
+ * @var string
3558
+ * @access public
3559
+ */
3560
+ var $xml_encoding = '';
3561
+ /**
3562
+ * toggles whether the parser decodes element content w/ utf8_decode()
3563
+ * @var boolean
3564
+ * @access public
3565
+ */
3566
+ var $decode_utf8 = true;
3567
+
3568
+ /**
3569
+ * HTTP headers of response
3570
+ * @var array
3571
+ * @access public
3572
+ */
3573
+ var $outgoing_headers = array();
3574
+ /**
3575
+ * HTTP response
3576
+ * @var string
3577
+ * @access private
3578
+ */
3579
+ var $response = '';
3580
+ /**
3581
+ * SOAP headers for response (text or array of soapval or associative array)
3582
+ * @var mixed
3583
+ * @access public
3584
+ */
3585
+ var $responseHeaders = '';
3586
+ /**
3587
+ * SOAP payload for response (text)
3588
+ * @var string
3589
+ * @access private
3590
+ */
3591
+ var $responseSOAP = '';
3592
+ /**
3593
+ * method return value to place in response
3594
+ * @var mixed
3595
+ * @access private
3596
+ */
3597
+ var $methodreturn = false;
3598
+ /**
3599
+ * whether $methodreturn is a string of literal XML
3600
+ * @var boolean
3601
+ * @access public
3602
+ */
3603
+ var $methodreturnisliteralxml = false;
3604
+ /**
3605
+ * SOAP fault for response (or false)
3606
+ * @var mixed
3607
+ * @access private
3608
+ */
3609
+ var $fault = false;
3610
+ /**
3611
+ * text indication of result (for debugging)
3612
+ * @var string
3613
+ * @access private
3614
+ */
3615
+ var $result = 'successful';
3616
+
3617
+ /**
3618
+ * assoc array of operations => opData; operations are added by the register()
3619
+ * method or by parsing an external WSDL definition
3620
+ * @var array
3621
+ * @access private
3622
+ */
3623
+ var $operations = array();
3624
+ /**
3625
+ * wsdl instance (if one)
3626
+ * @var mixed
3627
+ * @access private
3628
+ */
3629
+ var $wsdl = false;
3630
+ /**
3631
+ * URL for WSDL (if one)
3632
+ * @var mixed
3633
+ * @access private
3634
+ */
3635
+ var $externalWSDLURL = false;
3636
+ /**
3637
+ * whether to append debug to response as XML comment
3638
+ * @var boolean
3639
+ * @access public
3640
+ */
3641
+ var $debug_flag = false;
3642
+
3643
+
3644
+ /**
3645
+ * constructor
3646
+ * the optional parameter is a path to a WSDL file that you'd like to bind the server instance to.
3647
+ *
3648
+ * @param mixed $wsdl file path or URL (string), or wsdl instance (object)
3649
+ * @access public
3650
+ */
3651
+ function nusoap_server($wsdl=false){
3652
+ parent::nusoap_base();
3653
+ // turn on debugging?
3654
+ global $debug;
3655
+ global $HTTP_SERVER_VARS;
3656
+
3657
+ if (isset($_SERVER)) {
3658
+ $this->debug("_SERVER is defined:");
3659
+ $this->appendDebug($this->varDump($_SERVER));
3660
+ } elseif (isset($HTTP_SERVER_VARS)) {
3661
+ $this->debug("HTTP_SERVER_VARS is defined:");
3662
+ $this->appendDebug($this->varDump($HTTP_SERVER_VARS));
3663
+ } else {
3664
+ $this->debug("Neither _SERVER nor HTTP_SERVER_VARS is defined.");
3665
+ }
3666
+
3667
+ if (isset($debug)) {
3668
+ $this->debug("In nusoap_server, set debug_flag=$debug based on global flag");
3669
+ $this->debug_flag = $debug;
3670
+ } elseif (isset($_SERVER['QUERY_STRING'])) {
3671
+ $qs = explode('&', $_SERVER['QUERY_STRING']);
3672
+ foreach ($qs as $v) {
3673
+ if (substr($v, 0, 6) == 'debug=') {
3674
+ $this->debug("In nusoap_server, set debug_flag=" . substr($v, 6) . " based on query string #1");
3675
+ $this->debug_flag = substr($v, 6);
3676
+ }
3677
+ }
3678
+ } elseif (isset($HTTP_SERVER_VARS['QUERY_STRING'])) {
3679
+ $qs = explode('&', $HTTP_SERVER_VARS['QUERY_STRING']);
3680
+ foreach ($qs as $v) {
3681
+ if (substr($v, 0, 6) == 'debug=') {
3682
+ $this->debug("In nusoap_server, set debug_flag=" . substr($v, 6) . " based on query string #2");
3683
+ $this->debug_flag = substr($v, 6);
3684
+ }
3685
+ }
3686
+ }
3687
+
3688
+ // wsdl
3689
+ if($wsdl){
3690
+ $this->debug("In nusoap_server, WSDL is specified");
3691
+ if (is_object($wsdl) && (get_class($wsdl) == 'wsdl')) {
3692
+ $this->wsdl = $wsdl;
3693
+ $this->externalWSDLURL = $this->wsdl->wsdl;
3694
+ $this->debug('Use existing wsdl instance from ' . $this->externalWSDLURL);
3695
+ } else {
3696
+ $this->debug('Create wsdl from ' . $wsdl);
3697
+ $this->wsdl = new wsdl($wsdl);
3698
+ $this->externalWSDLURL = $wsdl;
3699
+ }
3700
+ $this->appendDebug($this->wsdl->getDebug());
3701
+ $this->wsdl->clearDebug();
3702
+ if($err = $this->wsdl->getError()){
3703
+ die('WSDL ERROR: '.$err);
3704
+ }
3705
+ }
3706
+ }
3707
+
3708
+ /**
3709
+ * processes request and returns response
3710
+ *
3711
+ * @param string $data usually is the value of $HTTP_RAW_POST_DATA
3712
+ * @access public
3713
+ */
3714
+ function service($data){
3715
+ global $HTTP_SERVER_VARS;
3716
+
3717
+ if (isset($_SERVER['REQUEST_METHOD'])) {
3718
+ $rm = $_SERVER['REQUEST_METHOD'];
3719
+ } elseif (isset($HTTP_SERVER_VARS['REQUEST_METHOD'])) {
3720
+ $rm = $HTTP_SERVER_VARS['REQUEST_METHOD'];
3721
+ } else {
3722
+ $rm = '';
3723
+ }
3724
+
3725
+ if (isset($_SERVER['QUERY_STRING'])) {
3726
+ $qs = $_SERVER['QUERY_STRING'];
3727
+ } elseif (isset($HTTP_SERVER_VARS['QUERY_STRING'])) {
3728
+ $qs = $HTTP_SERVER_VARS['QUERY_STRING'];
3729
+ } else {
3730
+ $qs = '';
3731
+ }
3732
+ $this->debug("In service, request method=$rm query string=$qs strlen(\$data)=" . strlen($data));
3733
+
3734
+ if ($rm == 'POST') {
3735
+ $this->debug("In service, invoke the request");
3736
+ $this->parse_request($data);
3737
+ if (! $this->fault) {
3738
+ $this->invoke_method();
3739
+ }
3740
+ if (! $this->fault) {
3741
+ $this->serialize_return();
3742
+ }
3743
+ $this->send_response();
3744
+ } elseif (preg_match('/wsdl/', $qs) ){
3745
+ $this->debug("In service, this is a request for WSDL");
3746
+ if ($this->externalWSDLURL){
3747
+ if (strpos($this->externalWSDLURL, "http://") !== false) { // assume URL
3748
+ $this->debug("In service, re-direct for WSDL");
3749
+ header('Location: '.$this->externalWSDLURL);
3750
+ } else { // assume file
3751
+ $this->debug("In service, use file passthru for WSDL");
3752
+ header("Content-Type: text/xml\r\n");
3753
+ $pos = strpos($this->externalWSDLURL, "file://");
3754
+ if ($pos === false) {
3755
+ $filename = $this->externalWSDLURL;
3756
+ } else {
3757
+ $filename = substr($this->externalWSDLURL, $pos + 7);
3758
+ }
3759
+ $fp = fopen($this->externalWSDLURL, 'r');
3760
+ fpassthru($fp);
3761
+ }
3762
+ } elseif ($this->wsdl) {
3763
+ $this->debug("In service, serialize WSDL");
3764
+ header("Content-Type: text/xml; charset=ISO-8859-1\r\n");
3765
+ print $this->wsdl->serialize($this->debug_flag);
3766
+ if ($this->debug_flag) {
3767
+ $this->debug('wsdl:');
3768
+ $this->appendDebug($this->varDump($this->wsdl));
3769
+ print $this->getDebugAsXMLComment();
3770
+ }
3771
+ } else {
3772
+ $this->debug("In service, there is no WSDL");
3773
+ header("Content-Type: text/html; charset=ISO-8859-1\r\n");
3774
+ print "This service does not provide WSDL";
3775
+ }
3776
+ } elseif ($this->wsdl) {
3777
+ $this->debug("In service, return Web description");
3778
+ print $this->wsdl->webDescription();
3779
+ } else {
3780
+ $this->debug("In service, no Web description");
3781
+ header("Content-Type: text/html; charset=ISO-8859-1\r\n");
3782
+ print "This service does not provide a Web description";
3783
+ }
3784
+ }
3785
+
3786
+ /**
3787
+ * parses HTTP request headers.
3788
+ *
3789
+ * The following fields are set by this function (when successful)
3790
+ *
3791
+ * headers
3792
+ * request
3793
+ * xml_encoding
3794
+ * SOAPAction
3795
+ *
3796
+ * @access private
3797
+ */
3798
+ function parse_http_headers() {
3799
+ global $HTTP_SERVER_VARS;
3800
+
3801
+ $this->request = '';
3802
+ $this->SOAPAction = '';
3803
+ if(function_exists('getallheaders')){
3804
+ $this->debug("In parse_http_headers, use getallheaders");
3805
+ $headers = getallheaders();
3806
+ foreach($headers as $k=>$v){
3807
+ $k = strtolower($k);
3808
+ $this->headers[$k] = $v;
3809
+ $this->request .= "$k: $v\r\n";
3810
+ $this->debug("$k: $v");
3811
+ }
3812
+ // get SOAPAction header
3813
+ if(isset($this->headers['soapaction'])){
3814
+ $this->SOAPAction = str_replace('"','',$this->headers['soapaction']);
3815
+ }
3816
+ // get the character encoding of the incoming request
3817
+ if(isset($this->headers['content-type']) && strpos($this->headers['content-type'],'=')){
3818
+ $enc = str_replace('"','',substr(strstr($this->headers["content-type"],'='),1));
3819
+ if(preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i',$enc)){
3820
+ $this->xml_encoding = strtoupper($enc);
3821
+ } else {
3822
+ $this->xml_encoding = 'US-ASCII';
3823
+ }
3824
+ } else {
3825
+ // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
3826
+ $this->xml_encoding = 'ISO-8859-1';
3827
+ }
3828
+ } elseif(isset($_SERVER) && is_array($_SERVER)){
3829
+ $this->debug("In parse_http_headers, use _SERVER");
3830
+ foreach ($_SERVER as $k => $v) {
3831
+ if (substr($k, 0, 5) == 'HTTP_') {
3832
+ $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', substr($k, 5))));
3833
+ } else {
3834
+ $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', $k)));
3835
+ }
3836
+ if ($k == 'soapaction') {
3837
+ // get SOAPAction header
3838
+ $k = 'SOAPAction';
3839
+ $v = str_replace('"', '', $v);
3840
+ $v = str_replace('\\', '', $v);
3841
+ $this->SOAPAction = $v;
3842
+ } else if ($k == 'content-type') {
3843
+ // get the character encoding of the incoming request
3844
+ if (strpos($v, '=')) {
3845
+ $enc = substr(strstr($v, '='), 1);
3846
+ $enc = str_replace('"', '', $enc);
3847
+ $enc = str_replace('\\', '', $enc);
3848
+ if (preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i',$enc)) {
3849
+ $this->xml_encoding = strtoupper($enc);
3850
+ } else {
3851
+ $this->xml_encoding = 'US-ASCII';
3852
+ }
3853
+ } else {
3854
+ // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
3855
+ $this->xml_encoding = 'ISO-8859-1';
3856
+ }
3857
+ }
3858
+ $this->headers[$k] = $v;
3859
+ $this->request .= "$k: $v\r\n";
3860
+ $this->debug("$k: $v");
3861
+ }
3862
+ } elseif (is_array($HTTP_SERVER_VARS)) {
3863
+ $this->debug("In parse_http_headers, use HTTP_SERVER_VARS");
3864
+ foreach ($HTTP_SERVER_VARS as $k => $v) {
3865
+ if (substr($k, 0, 5) == 'HTTP_') {
3866
+ $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', substr($k, 5)))); $k = strtolower(substr($k, 5));
3867
+ } else {
3868
+ $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', $k))); $k = strtolower($k);
3869
+ }
3870
+ if ($k == 'soapaction') {
3871
+ // get SOAPAction header
3872
+ $k = 'SOAPAction';
3873
+ $v = str_replace('"', '', $v);
3874
+ $v = str_replace('\\', '', $v);
3875
+ $this->SOAPAction = $v;
3876
+ } else if ($k == 'content-type') {
3877
+ // get the character encoding of the incoming request
3878
+ if (strpos($v, '=')) {
3879
+ $enc = substr(strstr($v, '='), 1);
3880
+ $enc = str_replace('"', '', $enc);
3881
+ $enc = str_replace('\\', '', $enc);
3882
+ if (preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i',$enc)) {
3883
+ $this->xml_encoding = strtoupper($enc);
3884
+ } else {
3885
+ $this->xml_encoding = 'US-ASCII';
3886
+ }
3887
+ } else {
3888
+ // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
3889
+ $this->xml_encoding = 'ISO-8859-1';
3890
+ }
3891
+ }
3892
+ $this->headers[$k] = $v;
3893
+ $this->request .= "$k: $v\r\n";
3894
+ $this->debug("$k: $v");
3895
+ }
3896
+ } else {
3897
+ $this->debug("In parse_http_headers, HTTP headers not accessible");
3898
+ $this->setError("HTTP headers not accessible");
3899
+ }
3900
+ }
3901
+
3902
+ /**
3903
+ * parses a request
3904
+ *
3905
+ * The following fields are set by this function (when successful)
3906
+ *
3907
+ * headers
3908
+ * request
3909
+ * xml_encoding
3910
+ * SOAPAction
3911
+ * request
3912
+ * requestSOAP
3913
+ * methodURI
3914
+ * methodname
3915
+ * methodparams
3916
+ * requestHeaders
3917
+ * document
3918
+ *
3919
+ * This sets the fault field on error
3920
+ *
3921
+ * @param string $data XML string
3922
+ * @access private
3923
+ */
3924
+ function parse_request($data='') {
3925
+ $this->debug('entering parse_request()');
3926
+ $this->parse_http_headers();
3927
+ $this->debug('got character encoding: '.$this->xml_encoding);
3928
+ // uncompress if necessary
3929
+ if (isset($this->headers['content-encoding']) && $this->headers['content-encoding'] != '') {
3930
+ $this->debug('got content encoding: ' . $this->headers['content-encoding']);
3931
+ if ($this->headers['content-encoding'] == 'deflate' || $this->headers['content-encoding'] == 'gzip') {
3932
+ // if decoding works, use it. else assume data wasn't gzencoded
3933
+ if (function_exists('gzuncompress')) {
3934
+ if ($this->headers['content-encoding'] == 'deflate' && $degzdata = @gzuncompress($data)) {
3935
+ $data = $degzdata;
3936
+ } elseif ($this->headers['content-encoding'] == 'gzip' && $degzdata = gzinflate(substr($data, 10))) {
3937
+ $data = $degzdata;
3938
+ } else {
3939
+ $this->fault('SOAP-ENV:Client', 'Errors occurred when trying to decode the data');
3940
+ return;
3941
+ }
3942
+ } else {
3943
+ $this->fault('SOAP-ENV:Client', 'This Server does not support compressed data');
3944
+ return;
3945
+ }
3946
+ }
3947
+ }
3948
+ $this->request .= "\r\n".$data;
3949
+ $data = $this->parseRequest($this->headers, $data);
3950
+ $this->requestSOAP = $data;
3951
+ $this->debug('leaving parse_request');
3952
+ }
3953
+
3954
+ /**
3955
+ * invokes a PHP function for the requested SOAP method
3956
+ *
3957
+ * The following fields are set by this function (when successful)
3958
+ *
3959
+ * methodreturn
3960
+ *
3961
+ * Note that the PHP function that is called may also set the following
3962
+ * fields to affect the response sent to the client
3963
+ *
3964
+ * responseHeaders
3965
+ * outgoing_headers
3966
+ *
3967
+ * This sets the fault field on error
3968
+ *
3969
+ * @access private
3970
+ */
3971
+ function invoke_method() {
3972
+ $this->debug('in invoke_method, methodname=' . $this->methodname . ' methodURI=' . $this->methodURI . ' SOAPAction=' . $this->SOAPAction);
3973
+
3974
+ //
3975
+ // if you are debugging in this area of the code, your service uses a class to implement methods,
3976
+ // you use SOAP RPC, and the client is .NET, please be aware of the following...
3977
+ // when the .NET wsdl.exe utility generates a proxy, it will remove the '.' or '..' from the
3978
+ // method name. that is fine for naming the .NET methods. it is not fine for properly constructing
3979
+ // the XML request and reading the XML response. you need to add the RequestElementName and
3980
+ // ResponseElementName to the System.Web.Services.Protocols.SoapRpcMethodAttribute that wsdl.exe
3981
+ // generates for the method. these parameters are used to specify the correct XML element names
3982
+ // for .NET to use, i.e. the names with the '.' in them.
3983
+ //
3984
+ $orig_methodname = $this->methodname;
3985
+ if ($this->wsdl) {
3986
+ if ($this->opData = $this->wsdl->getOperationData($this->methodname)) {
3987
+ $this->debug('in invoke_method, found WSDL operation=' . $this->methodname);
3988
+ $this->appendDebug('opData=' . $this->varDump($this->opData));
3989
+ } elseif ($this->opData = $this->wsdl->getOperationDataForSoapAction($this->SOAPAction)) {
3990
+ // Note: hopefully this case will only be used for doc/lit, since rpc services should have wrapper element
3991
+ $this->debug('in invoke_method, found WSDL soapAction=' . $this->SOAPAction . ' for operation=' . $this->opData['name']);
3992
+ $this->appendDebug('opData=' . $this->varDump($this->opData));
3993
+ $this->methodname = $this->opData['name'];
3994
+ } else {
3995
+ $this->debug('in invoke_method, no WSDL for operation=' . $this->methodname);
3996
+ $this->fault('SOAP-ENV:Client', "Operation '" . $this->methodname . "' is not defined in the WSDL for this service");
3997
+ return;
3998
+ }
3999
+ } else {
4000
+ $this->debug('in invoke_method, no WSDL to validate method');
4001
+ }
4002
+
4003
+ // if a . is present in $this->methodname, we see if there is a class in scope,
4004
+ // which could be referred to. We will also distinguish between two deliminators,
4005
+ // to allow methods to be called a the class or an instance
4006
+ if (strpos($this->methodname, '..') > 0) {
4007
+ $delim = '..';
4008
+ } else if (strpos($this->methodname, '.') > 0) {
4009
+ $delim = '.';
4010
+ } else {
4011
+ $delim = '';
4012
+ }
4013
+ $this->debug("in invoke_method, delim=$delim");
4014
+
4015
+ $class = '';
4016
+ $method = '';
4017
+ if (strlen($delim) > 0 && substr_count($this->methodname, $delim) == 1) {
4018
+ $try_class = substr($this->methodname, 0, strpos($this->methodname, $delim));
4019
+ if (class_exists($try_class)) {
4020
+ // get the class and method name
4021
+ $class = $try_class;
4022
+ $method = substr($this->methodname, strpos($this->methodname, $delim) + strlen($delim));
4023
+ $this->debug("in invoke_method, class=$class method=$method delim=$delim");
4024
+ } else {
4025
+ $this->debug("in invoke_method, class=$try_class not found");
4026
+ }
4027
+ } else {
4028
+ $try_class = '';
4029
+ $this->debug("in invoke_method, no class to try");
4030
+ }
4031
+
4032
+ // does method exist?
4033
+ if ($class == '') {
4034
+ if (!function_exists($this->methodname)) {
4035
+ $this->debug("in invoke_method, function '$this->methodname' not found!");
4036
+ $this->result = 'fault: method not found';
4037
+ $this->fault('SOAP-ENV:Client',"method '$this->methodname'('$orig_methodname') not defined in service('$try_class' '$delim')");
4038
+ return;
4039
+ }
4040
+ } else {
4041
+ $method_to_compare = (substr(phpversion(), 0, 2) == '4.') ? strtolower($method) : $method;
4042
+ if (!in_array($method_to_compare, get_class_methods($class))) {
4043
+ $this->debug("in invoke_method, method '$this->methodname' not found in class '$class'!");
4044
+ $this->result = 'fault: method not found';
4045
+ $this->fault('SOAP-ENV:Client',"method '$this->methodname'/'$method_to_compare'('$orig_methodname') not defined in service/'$class'('$try_class' '$delim')");
4046
+ return;
4047
+ }
4048
+ }
4049
+
4050
+ // evaluate message, getting back parameters
4051
+ // verify that request parameters match the method's signature
4052
+ if(! $this->verify_method($this->methodname,$this->methodparams)){
4053
+ // debug
4054
+ $this->debug('ERROR: request not verified against method signature');
4055
+ $this->result = 'fault: request failed validation against method signature';
4056
+ // return fault
4057
+ $this->fault('SOAP-ENV:Client',"Operation '$this->methodname' not defined in service.");
4058
+ return;
4059
+ }
4060
+
4061
+ // if there are parameters to pass
4062
+ $this->debug('in invoke_method, params:');
4063
+ $this->appendDebug($this->varDump($this->methodparams));
4064
+ $this->debug("in invoke_method, calling '$this->methodname'");
4065
+ if (!function_exists('call_user_func_array')) {
4066
+ if ($class == '') {
4067
+ $this->debug('in invoke_method, calling function using eval()');
4068
+ $funcCall = "\$this->methodreturn = $this->methodname(";
4069
+ } else {
4070
+ if ($delim == '..') {
4071
+ $this->debug('in invoke_method, calling class method using eval()');
4072
+ $funcCall = "\$this->methodreturn = ".$class."::".$method."(";
4073
+ } else {
4074
+ $this->debug('in invoke_method, calling instance method using eval()');
4075
+ // generate unique instance name
4076
+ $instname = "\$inst_".time();
4077
+ $funcCall = $instname." = new ".$class."(); ";
4078
+ $funcCall .= "\$this->methodreturn = ".$instname."->".$method."(";
4079
+ }
4080
+ }
4081
+ if ($this->methodparams) {
4082
+ foreach ($this->methodparams as $param) {
4083
+ if (is_array($param) || is_object($param)) {
4084
+ $this->fault('SOAP-ENV:Client', 'NuSOAP does not handle complexType parameters correctly when using eval; call_user_func_array must be available');
4085
+ return;
4086
+ }
4087
+ $funcCall .= "\"$param\",";
4088
+ }
4089
+ $funcCall = substr($funcCall, 0, -1);
4090
+ }
4091
+ $funcCall .= ');';
4092
+ $this->debug('in invoke_method, function call: '.$funcCall);
4093
+ @eval($funcCall);
4094
+ } else {
4095
+ if ($class == '') {
4096
+ $this->debug('in invoke_method, calling function using call_user_func_array()');
4097
+ $call_arg = "$this->methodname"; // straight assignment changes $this->methodname to lower case after call_user_func_array()
4098
+ } elseif ($delim == '..') {
4099
+ $this->debug('in invoke_method, calling class method using call_user_func_array()');
4100
+ $call_arg = array ($class, $method);
4101
+ } else {
4102
+ $this->debug('in invoke_method, calling instance method using call_user_func_array()');
4103
+ $instance = new $class ();
4104
+ $call_arg = array(&$instance, $method);
4105
+ }
4106
+ if (is_array($this->methodparams)) {
4107
+ $this->methodreturn = call_user_func_array($call_arg, array_values($this->methodparams));
4108
+ } else {
4109
+ $this->methodreturn = call_user_func_array($call_arg, array());
4110
+ }
4111
+ }
4112
+ $this->debug('in invoke_method, methodreturn:');
4113
+ $this->appendDebug($this->varDump($this->methodreturn));
4114
+ $this->debug("in invoke_method, called method $this->methodname, received data of type ".gettype($this->methodreturn));
4115
+ }
4116
+
4117
+ /**
4118
+ * serializes the return value from a PHP function into a full SOAP Envelope
4119
+ *
4120
+ * The following fields are set by this function (when successful)
4121
+ *
4122
+ * responseSOAP
4123
+ *
4124
+ * This sets the fault field on error
4125
+ *
4126
+ * @access private
4127
+ */
4128
+ function serialize_return() {
4129
+ $this->debug('Entering serialize_return methodname: ' . $this->methodname . ' methodURI: ' . $this->methodURI);
4130
+ // if fault
4131
+ if (isset($this->methodreturn) && is_object($this->methodreturn) && ((get_class($this->methodreturn) == 'soap_fault') || (get_class($this->methodreturn) == 'nusoap_fault'))) {
4132
+ $this->debug('got a fault object from method');
4133
+ $this->fault = $this->methodreturn;
4134
+ return;
4135
+ } elseif ($this->methodreturnisliteralxml) {
4136
+ $return_val = $this->methodreturn;
4137
+ // returned value(s)
4138
+ } else {
4139
+ $this->debug('got a(n) '.gettype($this->methodreturn).' from method');
4140
+ $this->debug('serializing return value');
4141
+ if($this->wsdl){
4142
+ if (sizeof($this->opData['output']['parts']) > 1) {
4143
+ $this->debug('more than one output part, so use the method return unchanged');
4144
+ $opParams = $this->methodreturn;
4145
+ } elseif (sizeof($this->opData['output']['parts']) == 1) {
4146
+ $this->debug('exactly one output part, so wrap the method return in a simple array');
4147
+ // TODO: verify that it is not already wrapped!
4148
+ //foreach ($this->opData['output']['parts'] as $name => $type) {
4149
+ // $this->debug('wrap in element named ' . $name);
4150
+ //}
4151
+ $opParams = array($this->methodreturn);
4152
+ }
4153
+ $return_val = $this->wsdl->serializeRPCParameters($this->methodname,'output',$opParams);
4154
+ $this->appendDebug($this->wsdl->getDebug());
4155
+ $this->wsdl->clearDebug();
4156
+ if($errstr = $this->wsdl->getError()){
4157
+ $this->debug('got wsdl error: '.$errstr);
4158
+ $this->fault('SOAP-ENV:Server', 'unable to serialize result');
4159
+ return;
4160
+ }
4161
+ } else {
4162
+ if (isset($this->methodreturn)) {
4163
+ $return_val = $this->serialize_val($this->methodreturn, 'return');
4164
+ } else {
4165
+ $return_val = '';
4166
+ $this->debug('in absence of WSDL, assume void return for backward compatibility');
4167
+ }
4168
+ }
4169
+ }
4170
+ $this->debug('return value:');
4171
+ $this->appendDebug($this->varDump($return_val));
4172
+
4173
+ $this->debug('serializing response');
4174
+ if ($this->wsdl) {
4175
+ $this->debug('have WSDL for serialization: style is ' . $this->opData['style']);
4176
+ if ($this->opData['style'] == 'rpc') {
4177
+ $this->debug('style is rpc for serialization: use is ' . $this->opData['output']['use']);
4178
+ if ($this->opData['output']['use'] == 'literal') {
4179
+ // 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
4180
+ if ($this->methodURI) {
4181
+ $payload = '<ns1:'.$this->methodname.'Response xmlns:ns1="'.$this->methodURI.'">'.$return_val.'</ns1:'.$this->methodname."Response>";
4182
+ } else {
4183
+ $payload = '<'.$this->methodname.'Response>'.$return_val.'</'.$this->methodname.'Response>';
4184
+ }
4185
+ } else {
4186
+ if ($this->methodURI) {
4187
+ $payload = '<ns1:'.$this->methodname.'Response xmlns:ns1="'.$this->methodURI.'">'.$return_val.'</ns1:'.$this->methodname."Response>";
4188
+ } else {
4189
+ $payload = '<'.$this->methodname.'Response>'.$return_val.'</'.$this->methodname.'Response>';
4190
+ }
4191
+ }
4192
+ } else {
4193
+ $this->debug('style is not rpc for serialization: assume document');
4194
+ $payload = $return_val;
4195
+ }
4196
+ } else {
4197
+ $this->debug('do not have WSDL for serialization: assume rpc/encoded');
4198
+ $payload = '<ns1:'.$this->methodname.'Response xmlns:ns1="'.$this->methodURI.'">'.$return_val.'</ns1:'.$this->methodname."Response>";
4199
+ }
4200
+ $this->result = 'successful';
4201
+ if($this->wsdl){
4202
+ //if($this->debug_flag){
4203
+ $this->appendDebug($this->wsdl->getDebug());
4204
+ // }
4205
+ if (isset($this->opData['output']['encodingStyle'])) {
4206
+ $encodingStyle = $this->opData['output']['encodingStyle'];
4207
+ } else {
4208
+ $encodingStyle = '';
4209
+ }
4210
+ // Added: In case we use a WSDL, return a serialized env. WITH the usedNamespaces.
4211
+ $this->responseSOAP = $this->serializeEnvelope($payload,$this->responseHeaders,$this->wsdl->usedNamespaces,$this->opData['style'],$this->opData['output']['use'],$encodingStyle);
4212
+ } else {
4213
+ $this->responseSOAP = $this->serializeEnvelope($payload,$this->responseHeaders);
4214
+ }
4215
+ $this->debug("Leaving serialize_return");
4216
+ }
4217
+
4218
+ /**
4219
+ * sends an HTTP response
4220
+ *
4221
+ * The following fields are set by this function (when successful)
4222
+ *
4223
+ * outgoing_headers
4224
+ * response
4225
+ *
4226
+ * @access private
4227
+ */
4228
+ function send_response() {
4229
+ $this->debug('Enter send_response');
4230
+ if ($this->fault) {
4231
+ $payload = $this->fault->serialize();
4232
+ $this->outgoing_headers[] = "HTTP/1.0 500 Internal Server Error";
4233
+ $this->outgoing_headers[] = "Status: 500 Internal Server Error";
4234
+ } else {
4235
+ $payload = $this->responseSOAP;
4236
+ // Some combinations of PHP+Web server allow the Status
4237
+ // to come through as a header. Since OK is the default
4238
+ // just do nothing.
4239
+ // $this->outgoing_headers[] = "HTTP/1.0 200 OK";
4240
+ // $this->outgoing_headers[] = "Status: 200 OK";
4241
+ }
4242
+ // add debug data if in debug mode
4243
+ if(isset($this->debug_flag) && $this->debug_flag){
4244
+ $payload .= $this->getDebugAsXMLComment();
4245
+ }
4246
+ $this->outgoing_headers[] = "Server: $this->title Server v$this->version";
4247
+ preg_match('/\$Revisio' . 'n: ([^ ]+)/', $this->revision, $rev);
4248
+ $this->outgoing_headers[] = "X-SOAP-Server: $this->title/$this->version (".$rev[1].")";
4249
+ // Let the Web server decide about this
4250
+ //$this->outgoing_headers[] = "Connection: Close\r\n";
4251
+ $payload = $this->getHTTPBody($payload);
4252
+ $type = $this->getHTTPContentType();
4253
+ $charset = $this->getHTTPContentTypeCharset();
4254
+ $this->outgoing_headers[] = "Content-Type: $type" . ($charset ? '; charset=' . $charset : '');
4255
+ //begin code to compress payload - by John
4256
+ // NOTE: there is no way to know whether the Web server will also compress
4257
+ // this data.
4258
+ if (strlen($payload) > 1024 && isset($this->headers) && isset($this->headers['accept-encoding'])) {
4259
+ if (strstr($this->headers['accept-encoding'], 'gzip')) {
4260
+ if (function_exists('gzencode')) {
4261
+ if (isset($this->debug_flag) && $this->debug_flag) {
4262
+ $payload .= "<!-- Content being gzipped -->";
4263
+ }
4264
+ $this->outgoing_headers[] = "Content-Encoding: gzip";
4265
+ $payload = gzencode($payload);
4266
+ } else {
4267
+ if (isset($this->debug_flag) && $this->debug_flag) {
4268
+ $payload .= "<!-- Content will not be gzipped: no gzencode -->";
4269
+ }
4270
+ }
4271
+ } elseif (strstr($this->headers['accept-encoding'], 'deflate')) {
4272
+ // Note: MSIE requires gzdeflate output (no Zlib header and checksum),
4273
+ // instead of gzcompress output,
4274
+ // which conflicts with HTTP 1.1 spec (http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.5)
4275
+ if (function_exists('gzdeflate')) {
4276
+ if (isset($this->debug_flag) && $this->debug_flag) {
4277
+ $payload .= "<!-- Content being deflated -->";
4278
+ }
4279
+ $this->outgoing_headers[] = "Content-Encoding: deflate";
4280
+ $payload = gzdeflate($payload);
4281
+ } else {
4282
+ if (isset($this->debug_flag) && $this->debug_flag) {
4283
+ $payload .= "<!-- Content will not be deflated: no gzcompress -->";
4284
+ }
4285
+ }
4286
+ }
4287
+ }
4288
+ //end code
4289
+ $this->outgoing_headers[] = "Content-Length: ".strlen($payload);
4290
+ reset($this->outgoing_headers);
4291
+ foreach($this->outgoing_headers as $hdr){
4292
+ header($hdr, false);
4293
+ }
4294
+ print $payload;
4295
+ $this->response = join("\r\n",$this->outgoing_headers)."\r\n\r\n".$payload;
4296
+ }
4297
+
4298
+ /**
4299
+ * takes the value that was created by parsing the request
4300
+ * and compares to the method's signature, if available.
4301
+ *
4302
+ * @param string $operation The operation to be invoked
4303
+ * @param array $request The array of parameter values
4304
+ * @return boolean Whether the operation was found
4305
+ * @access private
4306
+ */
4307
+ function verify_method($operation,$request){
4308
+ if(isset($this->wsdl) && is_object($this->wsdl)){
4309
+ if($this->wsdl->getOperationData($operation)){
4310
+ return true;
4311
+ }
4312
+ } elseif(isset($this->operations[$operation])){
4313
+ return true;
4314
+ }
4315
+ return false;
4316
+ }
4317
+
4318
+ /**
4319
+ * processes SOAP message received from client
4320
+ *
4321
+ * @param array $headers The HTTP headers
4322
+ * @param string $data unprocessed request data from client
4323
+ * @return mixed value of the message, decoded into a PHP type
4324
+ * @access private
4325
+ */
4326
+ function parseRequest($headers, $data) {
4327
+ $this->debug('Entering parseRequest() for data of length ' . strlen($data) . ' headers:');
4328
+ $this->appendDebug($this->varDump($headers));
4329
+ if (!isset($headers['content-type'])) {
4330
+ $this->setError('Request not of type text/xml (no content-type header)');
4331
+ return false;
4332
+ }
4333
+ if (!strstr($headers['content-type'], 'text/xml')) {
4334
+ $this->setError('Request not of type text/xml');
4335
+ return false;
4336
+ }
4337
+ if (strpos($headers['content-type'], '=')) {
4338
+ $enc = str_replace('"', '', substr(strstr($headers["content-type"], '='), 1));
4339
+ $this->debug('Got response encoding: ' . $enc);
4340
+ if(preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i',$enc)){
4341
+ $this->xml_encoding = strtoupper($enc);
4342
+ } else {
4343
+ $this->xml_encoding = 'US-ASCII';
4344
+ }
4345
+ } else {
4346
+ // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
4347
+ $this->xml_encoding = 'ISO-8859-1';
4348
+ }
4349
+ $this->debug('Use encoding: ' . $this->xml_encoding . ' when creating nusoap_parser');
4350
+ // parse response, get soap parser obj
4351
+ $parser = new nusoap_parser($data,$this->xml_encoding,'',$this->decode_utf8);
4352
+ // parser debug
4353
+ $this->debug("parser debug: \n".$parser->getDebug());
4354
+ // if fault occurred during message parsing
4355
+ if($err = $parser->getError()){
4356
+ $this->result = 'fault: error in msg parsing: '.$err;
4357
+ $this->fault('SOAP-ENV:Client',"error in msg parsing:\n".$err);
4358
+ // else successfully parsed request into soapval object
4359
+ } else {
4360
+ // get/set methodname
4361
+ $this->methodURI = $parser->root_struct_namespace;
4362
+ $this->methodname = $parser->root_struct_name;
4363
+ $this->debug('methodname: '.$this->methodname.' methodURI: '.$this->methodURI);
4364
+ $this->debug('calling parser->get_soapbody()');
4365
+ $this->methodparams = $parser->get_soapbody();
4366
+ // get SOAP headers
4367
+ $this->requestHeaders = $parser->getHeaders();
4368
+ // get SOAP Header
4369
+ $this->requestHeader = $parser->get_soapheader();
4370
+ // add document for doclit support
4371
+ $this->document = $parser->document;
4372
+ }
4373
+ }
4374
+
4375
+ /**
4376
+ * gets the HTTP body for the current response.
4377
+ *
4378
+ * @param string $soapmsg The SOAP payload
4379
+ * @return string The HTTP body, which includes the SOAP payload
4380
+ * @access private
4381
+ */
4382
+ function getHTTPBody($soapmsg) {
4383
+ return $soapmsg;
4384
+ }
4385
+
4386
+ /**
4387
+ * gets the HTTP content type for the current response.
4388
+ *
4389
+ * Note: getHTTPBody must be called before this.
4390
+ *
4391
+ * @return string the HTTP content type for the current response.
4392
+ * @access private
4393
+ */
4394
+ function getHTTPContentType() {
4395
+ return 'text/xml';
4396
+ }
4397
+
4398
+ /**
4399
+ * gets the HTTP content type charset for the current response.
4400
+ * returns false for non-text content types.
4401
+ *
4402
+ * Note: getHTTPBody must be called before this.
4403
+ *
4404
+ * @return string the HTTP content type charset for the current response.
4405
+ * @access private
4406
+ */
4407
+ function getHTTPContentTypeCharset() {
4408
+ return $this->soap_defencoding;
4409
+ }
4410
+
4411
+ /**
4412
+ * add a method to the dispatch map (this has been replaced by the register method)
4413
+ *
4414
+ * @param string $methodname
4415
+ * @param string $in array of input values
4416
+ * @param string $out array of output values
4417
+ * @access public
4418
+ * @deprecated
4419
+ */
4420
+ function add_to_map($methodname,$in,$out){
4421
+ $this->operations[$methodname] = array('name' => $methodname,'in' => $in,'out' => $out);
4422
+ }
4423
+
4424
+ /**
4425
+ * register a service function with the server
4426
+ *
4427
+ * @param string $name the name of the PHP function, class.method or class..method
4428
+ * @param array $in assoc array of input values: key = param name, value = param type
4429
+ * @param array $out assoc array of output values: key = param name, value = param type
4430
+ * @param mixed $namespace the element namespace for the method or false
4431
+ * @param mixed $soapaction the soapaction for the method or false
4432
+ * @param mixed $style optional (rpc|document) or false Note: when 'document' is specified, parameter and return wrappers are created for you automatically
4433
+ * @param mixed $use optional (encoded|literal) or false
4434
+ * @param string $documentation optional Description to include in WSDL
4435
+ * @param string $encodingStyle optional (usually 'http://schemas.xmlsoap.org/soap/encoding/' for encoded)
4436
+ * @access public
4437
+ */
4438
+ function register($name,$in=array(),$out=array(),$namespace=false,$soapaction=false,$style=false,$use=false,$documentation='',$encodingStyle=''){
4439
+ global $HTTP_SERVER_VARS;
4440
+
4441
+ if($this->externalWSDLURL){
4442
+ die('You cannot bind to an external WSDL file, and register methods outside of it! Please choose either WSDL or no WSDL.');
4443
+ }
4444
+ if (! $name) {
4445
+ die('You must specify a name when you register an operation');
4446
+ }
4447
+ if (!is_array($in)) {
4448
+ die('You must provide an array for operation inputs');
4449
+ }
4450
+ if (!is_array($out)) {
4451
+ die('You must provide an array for operation outputs');
4452
+ }
4453
+ if(false == $namespace) {
4454
+ }
4455
+ if(false == $soapaction) {
4456
+ if (isset($_SERVER)) {
4457
+ $SERVER_NAME = $_SERVER['SERVER_NAME'];
4458
+ $SCRIPT_NAME = isset($_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : $_SERVER['SCRIPT_NAME'];
4459
+ $HTTPS = isset($_SERVER['HTTPS']) ? $_SERVER['HTTPS'] : (isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off');
4460
+ } elseif (isset($HTTP_SERVER_VARS)) {
4461
+ $SERVER_NAME = $HTTP_SERVER_VARS['SERVER_NAME'];
4462
+ $SCRIPT_NAME = isset($HTTP_SERVER_VARS['PHP_SELF']) ? $HTTP_SERVER_VARS['PHP_SELF'] : $HTTP_SERVER_VARS['SCRIPT_NAME'];
4463
+ $HTTPS = isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off';
4464
+ } else {
4465
+ $this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available");
4466
+ }
4467
+ if ($HTTPS == '1' || $HTTPS == 'on') {
4468
+ $SCHEME = 'https';
4469
+ } else {
4470
+ $SCHEME = 'http';
4471
+ }
4472
+ $soapaction = "$SCHEME://$SERVER_NAME$SCRIPT_NAME/$name";
4473
+ }
4474
+ if(false == $style) {
4475
+ $style = "rpc";
4476
+ }
4477
+ if(false == $use) {
4478
+ $use = "encoded";
4479
+ }
4480
+ if ($use == 'encoded' && $encodingStyle == '') {
4481
+ $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
4482
+ }
4483
+
4484
+ $this->operations[$name] = array(
4485
+ 'name' => $name,
4486
+ 'in' => $in,
4487
+ 'out' => $out,
4488
+ 'namespace' => $namespace,
4489
+ 'soapaction' => $soapaction,
4490
+ 'style' => $style);
4491
+ if($this->wsdl){
4492
+ $this->wsdl->addOperation($name,$in,$out,$namespace,$soapaction,$style,$use,$documentation,$encodingStyle);
4493
+ }
4494
+ return true;
4495
+ }
4496
+
4497
+ /**
4498
+ * Specify a fault to be returned to the client.
4499
+ * This also acts as a flag to the server that a fault has occured.
4500
+ *
4501
+ * @param string $faultcode
4502
+ * @param string $faultstring
4503
+ * @param string $faultactor
4504
+ * @param string $faultdetail
4505
+ * @access public
4506
+ */
4507
+ function fault($faultcode,$faultstring,$faultactor='',$faultdetail=''){
4508
+ if ($faultdetail == '' && $this->debug_flag) {
4509
+ $faultdetail = $this->getDebug();
4510
+ }
4511
+ $this->fault = new nusoap_fault($faultcode,$faultactor,$faultstring,$faultdetail);
4512
+ $this->fault->soap_defencoding = $this->soap_defencoding;
4513
+ }
4514
+
4515
+ /**
4516
+ * Sets up wsdl object.
4517
+ * Acts as a flag to enable internal WSDL generation
4518
+ *
4519
+ * @param string $serviceName, name of the service
4520
+ * @param mixed $namespace optional 'tns' service namespace or false
4521
+ * @param mixed $endpoint optional URL of service endpoint or false
4522
+ * @param string $style optional (rpc|document) WSDL style (also specified by operation)
4523
+ * @param string $transport optional SOAP transport
4524
+ * @param mixed $schemaTargetNamespace optional 'types' targetNamespace for service schema or false
4525
+ */
4526
+ function configureWSDL($serviceName,$namespace = false,$endpoint = false,$style='rpc', $transport = 'http://schemas.xmlsoap.org/soap/http', $schemaTargetNamespace = false)
4527
+ {
4528
+ global $HTTP_SERVER_VARS;
4529
+
4530
+ if (isset($_SERVER)) {
4531
+ $SERVER_NAME = $_SERVER['SERVER_NAME'];
4532
+ $SERVER_PORT = $_SERVER['SERVER_PORT'];
4533
+ $SCRIPT_NAME = isset($_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : $_SERVER['SCRIPT_NAME'];
4534
+ $HTTPS = isset($_SERVER['HTTPS']) ? $_SERVER['HTTPS'] : (isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off');
4535
+ } elseif (isset($HTTP_SERVER_VARS)) {
4536
+ $SERVER_NAME = $HTTP_SERVER_VARS['SERVER_NAME'];
4537
+ $SERVER_PORT = $HTTP_SERVER_VARS['SERVER_PORT'];
4538
+ $SCRIPT_NAME = isset($HTTP_SERVER_VARS['PHP_SELF']) ? $HTTP_SERVER_VARS['PHP_SELF'] : $HTTP_SERVER_VARS['SCRIPT_NAME'];
4539
+ $HTTPS = isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off';
4540
+ } else {
4541
+ $this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available");
4542
+ }
4543
+ // If server name has port number attached then strip it (else port number gets duplicated in WSDL output) (occurred using lighttpd and FastCGI)
4544
+ $colon = strpos($SERVER_NAME,":");
4545
+ if ($colon) {
4546
+ $SERVER_NAME = substr($SERVER_NAME, 0, $colon);
4547
+ }
4548
+ if ($SERVER_PORT == 80) {
4549
+ $SERVER_PORT = '';
4550
+ } else {
4551
+ $SERVER_PORT = ':' . $SERVER_PORT;
4552
+ }
4553
+ if(false == $namespace) {
4554
+ $namespace = "http://$SERVER_NAME/soap/$serviceName";
4555
+ }
4556
+
4557
+ if(false == $endpoint) {
4558
+ if ($HTTPS == '1' || $HTTPS == 'on') {
4559
+ $SCHEME = 'https';
4560
+ } else {
4561
+ $SCHEME = 'http';
4562
+ }
4563
+ $endpoint = "$SCHEME://$SERVER_NAME$SERVER_PORT$SCRIPT_NAME";
4564
+ }
4565
+
4566
+ if(false == $schemaTargetNamespace) {
4567
+ $schemaTargetNamespace = $namespace;
4568
+ }
4569
+
4570
+ $this->wsdl = new wsdl;
4571
+ $this->wsdl->serviceName = $serviceName;
4572
+ $this->wsdl->endpoint = $endpoint;
4573
+ $this->wsdl->namespaces['tns'] = $namespace;
4574
+ $this->wsdl->namespaces['soap'] = 'http://schemas.xmlsoap.org/wsdl/soap/';
4575
+ $this->wsdl->namespaces['wsdl'] = 'http://schemas.xmlsoap.org/wsdl/';
4576
+ if ($schemaTargetNamespace != $namespace) {
4577
+ $this->wsdl->namespaces['types'] = $schemaTargetNamespace;
4578
+ }
4579
+ $this->wsdl->schemas[$schemaTargetNamespace][0] = new nusoap_xmlschema('', '', $this->wsdl->namespaces);
4580
+ if ($style == 'document') {
4581
+ $this->wsdl->schemas[$schemaTargetNamespace][0]->schemaInfo['elementFormDefault'] = 'qualified';
4582
+ }
4583
+ $this->wsdl->schemas[$schemaTargetNamespace][0]->schemaTargetNamespace = $schemaTargetNamespace;
4584
+ $this->wsdl->schemas[$schemaTargetNamespace][0]->imports['http://schemas.xmlsoap.org/soap/encoding/'][0] = array('location' => '', 'loaded' => true);
4585
+ $this->wsdl->schemas[$schemaTargetNamespace][0]->imports['http://schemas.xmlsoap.org/wsdl/'][0] = array('location' => '', 'loaded' => true);
4586
+ $this->wsdl->bindings[$serviceName.'Binding'] = array(
4587
+ 'name'=>$serviceName.'Binding',
4588
+ 'style'=>$style,
4589
+ 'transport'=>$transport,
4590
+ 'portType'=>$serviceName.'PortType');
4591
+ $this->wsdl->ports[$serviceName.'Port'] = array(
4592
+ 'binding'=>$serviceName.'Binding',
4593
+ 'location'=>$endpoint,
4594
+ 'bindingType'=>'http://schemas.xmlsoap.org/wsdl/soap/');
4595
+ }
4596
+ }
4597
+
4598
+ /**
4599
+ * Backward compatibility
4600
+ */
4601
+ class soap_server extends nusoap_server {
4602
+ }
4603
+
4604
+ ?><?php
4605
+
4606
+
4607
+
4608
+ /**
4609
+ * parses a WSDL file, allows access to it's data, other utility methods.
4610
+ * also builds WSDL structures programmatically.
4611
+ *
4612
+ * @author Dietrich Ayala <dietrich@ganx4.com>
4613
+ * @author Scott Nichol <snichol@users.sourceforge.net>
4614
+ * @version $Id: fsource_nusoap__nusoap.php.html,v 1.2 2010/04/26 20:25:21 snichol Exp $
4615
+ * @access public
4616
+ */
4617
+ class wsdl extends nusoap_base {
4618
+ // URL or filename of the root of this WSDL
4619
+
4620
+ var $wsdl;
4621
+ // define internal arrays of bindings, ports, operations, messages, etc.
4622
+
4623
+ var $schemas = array();
4624
+ var $currentSchema;
4625
+ var $message = array();
4626
+ var $complexTypes = array();
4627
+ var $messages = array();
4628
+ var $currentMessage;
4629
+ var $currentOperation;
4630
+ var $portTypes = array();
4631
+ var $currentPortType;
4632
+ var $bindings = array();
4633
+ var $currentBinding;
4634
+ var $ports = array();
4635
+ var $currentPort;
4636
+ var $opData = array();
4637
+ var $status = '';
4638
+ var $documentation = false;
4639
+ var $endpoint = '';
4640
+ // array of wsdl docs to import
4641
+
4642
+ var $import = array();
4643
+ // parser vars
4644
+
4645
+ var $parser;
4646
+ var $position = 0;
4647
+ var $depth = 0;
4648
+ var $depth_array = array();
4649
+ // for getting wsdl
4650
+
4651
+ var $proxyhost = '';
4652
+ var $proxyport = '';
4653
+ var $proxyusername = '';
4654
+ var $proxypassword = '';
4655
+ var $timeout = 0;
4656
+ var $response_timeout = 30;
4657
+ var $curl_options = array(); // User-specified cURL options
4658
+
4659
+ var $use_curl = false; // whether to always try to use cURL
4660
+ // for HTTP authentication
4661
+
4662
+ var $username = ''; // Username for HTTP authentication
4663
+
4664
+ var $password = ''; // Password for HTTP authentication
4665
+
4666
+ var $authtype = ''; // Type of HTTP authentication
4667
+
4668
+ var $certRequest = array(); // Certificate for HTTP SSL authentication
4669
+
4670
+
4671
+
4672
+ /**
4673
+ * constructor
4674
+ *
4675
+ * @param string $wsdl WSDL document URL
4676
+ * @param string $proxyhost
4677
+ * @param string $proxyport
4678
+ * @param string $proxyusername
4679
+ * @param string $proxypassword
4680
+ * @param integer $timeout set the connection timeout
4681
+ * @param integer $response_timeout set the response timeout
4682
+ * @param array $curl_options user-specified cURL options
4683
+ * @param boolean $use_curl try to use cURL
4684
+ * @access public
4685
+ */
4686
+ function wsdl($wsdl = '',$proxyhost=false,$proxyport=false,$proxyusername=false,$proxypassword=false,$timeout=0,$response_timeout=30,$curl_options=null,$use_curl=false){
4687
+ parent::nusoap_base();
4688
+ $this->debug("ctor wsdl=$wsdl timeout=$timeout response_timeout=$response_timeout");
4689
+ $this->proxyhost = $proxyhost;
4690
+ $this->proxyport = $proxyport;
4691
+ $this->proxyusername = $proxyusername;
4692
+ $this->proxypassword = $proxypassword;
4693
+ $this->timeout = $timeout;
4694
+ $this->response_timeout = $response_timeout;
4695
+ if (is_array($curl_options))
4696
+ $this->curl_options = $curl_options;
4697
+ $this->use_curl = $use_curl;
4698
+ $this->fetchWSDL($wsdl);
4699
+ }
4700
+
4701
+ /**
4702
+ * fetches the WSDL document and parses it
4703
+ *
4704
+ * @access public
4705
+ */
4706
+ function fetchWSDL($wsdl) {
4707
+ $this->debug("parse and process WSDL path=$wsdl");
4708
+ $this->wsdl = $wsdl;
4709
+ // parse wsdl file
4710
+ if ($this->wsdl != "") {
4711
+ $this->parseWSDL($this->wsdl);
4712
+ }
4713
+ // imports
4714
+ // TODO: handle imports more properly, grabbing them in-line and nesting them
4715
+ $imported_urls = array();
4716
+ $imported = 1;
4717
+ while ($imported > 0) {
4718
+ $imported = 0;
4719
+ // Schema imports
4720
+ foreach ($this->schemas as $ns => $list) {
4721
+ foreach ($list as $xs) {
4722
+ $wsdlparts = parse_url($this->wsdl); // this is bogusly simple!
4723
+ foreach ($xs->imports as $ns2 => $list2) {
4724
+ for ($ii = 0; $ii < count($list2); $ii++) {
4725
+ if (! $list2[$ii]['loaded']) {
4726
+ $this->schemas[$ns]->imports[$ns2][$ii]['loaded'] = true;
4727
+ $url = $list2[$ii]['location'];
4728
+ if ($url != '') {
4729
+ $urlparts = parse_url($url);
4730
+ if (!isset($urlparts['host'])) {
4731
+ $url = $wsdlparts['scheme'] . '://' . $wsdlparts['host'] . (isset($wsdlparts['port']) ? ':' .$wsdlparts['port'] : '') .
4732
+ substr($wsdlparts['path'],0,strrpos($wsdlparts['path'],'/') + 1) .$urlparts['path'];
4733
+ }
4734
+ if (! in_array($url, $imported_urls)) {
4735
+ $this->parseWSDL($url);
4736
+ $imported++;
4737
+ $imported_urls[] = $url;
4738
+ }
4739
+ } else {
4740
+ $this->debug("Unexpected scenario: empty URL for unloaded import");
4741
+ }
4742
+ }
4743
+ }
4744
+ }
4745
+ }
4746
+ }
4747
+ // WSDL imports
4748
+ $wsdlparts = parse_url($this->wsdl); // this is bogusly simple!
4749
+ foreach ($this->import as $ns => $list) {
4750
+ for ($ii = 0; $ii < count($list); $ii++) {
4751
+ if (! $list[$ii]['loaded']) {
4752
+ $this->import[$ns][$ii]['loaded'] = true;
4753
+ $url = $list[$ii]['location'];
4754
+ if ($url != '') {
4755
+ $urlparts = parse_url($url);
4756
+ if (!isset($urlparts['host'])) {
4757
+ $url = $wsdlparts['scheme'] . '://' . $wsdlparts['host'] . (isset($wsdlparts['port']) ? ':' . $wsdlparts['port'] : '') .
4758
+ substr($wsdlparts['path'],0,strrpos($wsdlparts['path'],'/') + 1) .$urlparts['path'];
4759
+ }
4760
+ if (! in_array($url, $imported_urls)) {
4761
+ $this->parseWSDL($url);
4762
+ $imported++;
4763
+ $imported_urls[] = $url;
4764
+ }
4765
+ } else {
4766
+ $this->debug("Unexpected scenario: empty URL for unloaded import");
4767
+ }
4768
+ }
4769
+ }
4770
+ }
4771
+ }
4772
+ // add new data to operation data
4773
+ foreach($this->bindings as $binding => $bindingData) {
4774
+ if (isset($bindingData['operations']) && is_array($bindingData['operations'])) {
4775
+ foreach($bindingData['operations'] as $operation => $data) {
4776
+ $this->debug('post-parse data gathering for ' . $operation);
4777
+ $this->bindings[$binding]['operations'][$operation]['input'] =
4778
+ isset($this->bindings[$binding]['operations'][$operation]['input']) ?
4779
+ array_merge($this->bindings[$binding]['operations'][$operation]['input'], $this->portTypes[ $bindingData['portType'] ][$operation]['input']) :
4780
+ $this->portTypes[ $bindingData['portType'] ][$operation]['input'];
4781
+ $this->bindings[$binding]['operations'][$operation]['output'] =
4782
+ isset($this->bindings[$binding]['operations'][$operation]['output']) ?
4783
+ array_merge($this->bindings[$binding]['operations'][$operation]['output'], $this->portTypes[ $bindingData['portType'] ][$operation]['output']) :
4784
+ $this->portTypes[ $bindingData['portType'] ][$operation]['output'];
4785
+ if(isset($this->messages[ $this->bindings[$binding]['operations'][$operation]['input']['message'] ])){
4786
+ $this->bindings[$binding]['operations'][$operation]['input']['parts'] = $this->messages[ $this->bindings[$binding]['operations'][$operation]['input']['message'] ];
4787
+ }
4788
+ if(isset($this->messages[ $this->bindings[$binding]['operations'][$operation]['output']['message'] ])){
4789
+ $this->bindings[$binding]['operations'][$operation]['output']['parts'] = $this->messages[ $this->bindings[$binding]['operations'][$operation]['output']['message'] ];
4790
+ }
4791
+ // Set operation style if necessary, but do not override one already provided
4792
+ if (isset($bindingData['style']) && !isset($this->bindings[$binding]['operations'][$operation]['style'])) {
4793
+ $this->bindings[$binding]['operations'][$operation]['style'] = $bindingData['style'];
4794
+ }
4795
+ $this->bindings[$binding]['operations'][$operation]['transport'] = isset($bindingData['transport']) ? $bindingData['transport'] : '';
4796
+ $this->bindings[$binding]['operations'][$operation]['documentation'] = isset($this->portTypes[ $bindingData['portType'] ][$operation]['documentation']) ? $this->portTypes[ $bindingData['portType'] ][$operation]['documentation'] : '';
4797
+ $this->bindings[$binding]['operations'][$operation]['endpoint'] = isset($bindingData['endpoint']) ? $bindingData['endpoint'] : '';
4798
+ }
4799
+ }
4800
+ }
4801
+ }
4802
+
4803
+ /**
4804
+ * parses the wsdl document
4805
+ *
4806
+ * @param string $wsdl path or URL
4807
+ * @access private
4808
+ */
4809
+ function parseWSDL($wsdl = '') {
4810
+ $this->debug("parse WSDL at path=$wsdl");
4811
+
4812
+ if ($wsdl == '') {
4813
+ $this->debug('no wsdl passed to parseWSDL()!!');
4814
+ $this->setError('no wsdl passed to parseWSDL()!!');
4815
+ return false;
4816
+ }
4817
+
4818
+ // parse $wsdl for url format
4819
+ $wsdl_props = parse_url($wsdl);
4820
+
4821
+ if (isset($wsdl_props['scheme']) && ($wsdl_props['scheme'] == 'http' || $wsdl_props['scheme'] == 'https')) {
4822
+ $this->debug('getting WSDL http(s) URL ' . $wsdl);
4823
+ // get wsdl
4824
+ $tr = new soap_transport_http($wsdl, $this->curl_options, $this->use_curl);
4825
+ $tr->request_method = 'GET';
4826
+ $tr->useSOAPAction = false;
4827
+ if($this->proxyhost && $this->proxyport){
4828
+ $tr->setProxy($this->proxyhost,$this->proxyport,$this->proxyusername,$this->proxypassword);
4829
+ }
4830
+ if ($this->authtype != '') {
4831
+ $tr->setCredentials($this->username, $this->password, $this->authtype, array(), $this->certRequest);
4832
+ }
4833
+ $tr->setEncoding('gzip, deflate');
4834
+ $wsdl_string = $tr->send('', $this->timeout, $this->response_timeout);
4835
+ //$this->debug("WSDL request\n" . $tr->outgoing_payload);
4836
+ //$this->debug("WSDL response\n" . $tr->incoming_payload);
4837
+ $this->appendDebug($tr->getDebug());
4838
+ // catch errors
4839
+ if($err = $tr->getError() ){
4840
+ $errstr = 'Getting ' . $wsdl . ' - HTTP ERROR: '.$err;
4841
+ $this->debug($errstr);
4842
+ $this->setError($errstr);
4843
+ unset($tr);
4844
+ return false;
4845
+ }
4846
+ unset($tr);
4847
+ $this->debug("got WSDL URL");
4848
+ } else {
4849
+ // $wsdl is not http(s), so treat it as a file URL or plain file path
4850
+ if (isset($wsdl_props['scheme']) && ($wsdl_props['scheme'] == 'file') && isset($wsdl_props['path'])) {
4851
+ $path = isset($wsdl_props['host']) ? ($wsdl_props['host'] . ':' . $wsdl_props['path']) : $wsdl_props['path'];
4852
+ } else {
4853
+ $path = $wsdl;
4854
+ }
4855
+ $this->debug('getting WSDL file ' . $path);
4856
+ if ($fp = @fopen($path, 'r')) {
4857
+ $wsdl_string = '';
4858
+ while ($data = fread($fp, 32768)) {
4859
+ $wsdl_string .= $data;
4860
+ }
4861
+ fclose($fp);
4862
+ } else {
4863
+ $errstr = "Bad path to WSDL file $path";
4864
+ $this->debug($errstr);
4865
+ $this->setError($errstr);
4866
+ return false;
4867
+ }
4868
+ }
4869
+ $this->debug('Parse WSDL');
4870
+ // end new code added
4871
+ // Create an XML parser.
4872
+ $this->parser = xml_parser_create();
4873
+ // Set the options for parsing the XML data.
4874
+ // xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
4875
+ xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
4876
+ // Set the object for the parser.
4877
+ xml_set_object($this->parser, $this);
4878
+ // Set the element handlers for the parser.
4879
+ xml_set_element_handler($this->parser, 'start_element', 'end_element');
4880
+ xml_set_character_data_handler($this->parser, 'character_data');
4881
+ // Parse the XML file.
4882
+ if (!xml_parse($this->parser, $wsdl_string, true)) {
4883
+ // Display an error message.
4884
+ $errstr = sprintf(
4885
+ 'XML error parsing WSDL from %s on line %d: %s',
4886
+ $wsdl,
4887
+ xml_get_current_line_number($this->parser),
4888
+ xml_error_string(xml_get_error_code($this->parser))
4889
+ );
4890
+ $this->debug($errstr);
4891
+ $this->debug("XML payload:\n" . $wsdl_string);
4892
+ $this->setError($errstr);
4893
+ return false;
4894
+ }
4895
+ // free the parser
4896
+ xml_parser_free($this->parser);
4897
+ $this->debug('Parsing WSDL done');
4898
+ // catch wsdl parse errors
4899
+ if($this->getError()){
4900
+ return false;
4901
+ }
4902
+ return true;
4903
+ }
4904
+
4905
+ /**
4906
+ * start-element handler
4907
+ *
4908
+ * @param string $parser XML parser object
4909
+ * @param string $name element name
4910
+ * @param string $attrs associative array of attributes
4911
+ * @access private
4912
+ */
4913
+ function start_element($parser, $name, $attrs)
4914
+ {
4915
+ if ($this->status == 'schema') {
4916
+ $this->currentSchema->schemaStartElement($parser, $name, $attrs);
4917
+ $this->appendDebug($this->currentSchema->getDebug());
4918
+ $this->currentSchema->clearDebug();
4919
+ } elseif (preg_match('/schema$/', $name)) {
4920
+ $this->debug('Parsing WSDL schema');
4921
+ // $this->debug("startElement for $name ($attrs[name]). status = $this->status (".$this->getLocalPart($name).")");
4922
+ $this->status = 'schema';
4923
+ $this->currentSchema = new nusoap_xmlschema('', '', $this->namespaces);
4924
+ $this->currentSchema->schemaStartElement($parser, $name, $attrs);
4925
+ $this->appendDebug($this->currentSchema->getDebug());
4926
+ $this->currentSchema->clearDebug();
4927
+ } else {
4928
+ // position in the total number of elements, starting from 0
4929
+ $pos = $this->position++;
4930
+ $depth = $this->depth++;
4931
+ // set self as current value for this depth
4932
+ $this->depth_array[$depth] = $pos;
4933
+ $this->message[$pos] = array('cdata' => '');
4934
+ // process attributes
4935
+ if (count($attrs) > 0) {
4936
+ // register namespace declarations
4937
+ foreach($attrs as $k => $v) {
4938
+ if (preg_match('/^xmlns/',$k)) {
4939
+ if ($ns_prefix = substr(strrchr($k, ':'), 1)) {
4940
+ $this->namespaces[$ns_prefix] = $v;
4941
+ } else {
4942
+ $this->namespaces['ns' . (count($this->namespaces) + 1)] = $v;
4943
+ }
4944
+ if ($v == 'http://www.w3.org/2001/XMLSchema' || $v == 'http://www.w3.org/1999/XMLSchema' || $v == 'http://www.w3.org/2000/10/XMLSchema') {
4945
+ $this->XMLSchemaVersion = $v;
4946
+ $this->namespaces['xsi'] = $v . '-instance';
4947
+ }
4948
+ }
4949
+ }
4950
+ // expand each attribute prefix to its namespace
4951
+ foreach($attrs as $k => $v) {
4952
+ $k = strpos($k, ':') ? $this->expandQname($k) : $k;
4953
+ if ($k != 'location' && $k != 'soapAction' && $k != 'namespace') {
4954
+ $v = strpos($v, ':') ? $this->expandQname($v) : $v;
4955
+ }
4956
+ $eAttrs[$k] = $v;
4957
+ }
4958
+ $attrs = $eAttrs;
4959
+ } else {
4960
+ $attrs = array();
4961
+ }
4962
+ // get element prefix, namespace and name
4963
+ if (preg_match('/:/', $name)) {
4964
+ // get ns prefix
4965
+ $prefix = substr($name, 0, strpos($name, ':'));
4966
+ // get ns
4967
+ $namespace = isset($this->namespaces[$prefix]) ? $this->namespaces[$prefix] : '';
4968
+ // get unqualified name
4969
+ $name = substr(strstr($name, ':'), 1);
4970
+ }
4971
+ // process attributes, expanding any prefixes to namespaces
4972
+ // find status, register data
4973
+ switch ($this->status) {
4974
+ case 'message':
4975
+ if ($name == 'part') {
4976
+ if (isset($attrs['type'])) {
4977
+ $this->debug("msg " . $this->currentMessage . ": found part (with type) $attrs[name]: " . implode(',', $attrs));
4978
+ $this->messages[$this->currentMessage][$attrs['name']] = $attrs['type'];
4979
+ }
4980
+ if (isset($attrs['element'])) {
4981
+ $this->debug("msg " . $this->currentMessage . ": found part (with element) $attrs[name]: " . implode(',', $attrs));
4982
+ $this->messages[$this->currentMessage][$attrs['name']] = $attrs['element'] . '^';
4983
+ }
4984
+ }
4985
+ break;
4986
+ case 'portType':
4987
+ switch ($name) {
4988
+ case 'operation':
4989
+ $this->currentPortOperation = $attrs['name'];
4990
+ $this->debug("portType $this->currentPortType operation: $this->currentPortOperation");
4991
+ if (isset($attrs['parameterOrder'])) {
4992
+ $this->portTypes[$this->currentPortType][$attrs['name']]['parameterOrder'] = $attrs['parameterOrder'];
4993
+ }
4994
+ break;
4995
+ case 'documentation':
4996
+ $this->documentation = true;
4997
+ break;
4998
+ // merge input/output data
4999
+ default:
5000
+ $m = isset($attrs['message']) ? $this->getLocalPart($attrs['message']) : '';
5001
+ $this->portTypes[$this->currentPortType][$this->currentPortOperation][$name]['message'] = $m;
5002
+ break;
5003
+ }
5004
+ break;
5005
+ case 'binding':
5006
+ switch ($name) {
5007
+ case 'binding':
5008
+ // get ns prefix
5009
+ if (isset($attrs['style'])) {
5010
+ $this->bindings[$this->currentBinding]['prefix'] = $prefix;
5011
+ }
5012
+ $this->bindings[$this->currentBinding] = array_merge($this->bindings[$this->currentBinding], $attrs);
5013
+ break;
5014
+ case 'header':
5015
+ $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus]['headers'][] = $attrs;
5016
+ break;
5017
+ case 'operation':
5018
+ if (isset($attrs['soapAction'])) {
5019
+ $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['soapAction'] = $attrs['soapAction'];
5020
+ }
5021
+ if (isset($attrs['style'])) {
5022
+ $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['style'] = $attrs['style'];
5023
+ }
5024
+ if (isset($attrs['name'])) {
5025
+ $this->currentOperation = $attrs['name'];
5026
+ $this->debug("current binding operation: $this->currentOperation");
5027
+ $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['name'] = $attrs['name'];
5028
+ $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['binding'] = $this->currentBinding;
5029
+ $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['endpoint'] = isset($this->bindings[$this->currentBinding]['endpoint']) ? $this->bindings[$this->currentBinding]['endpoint'] : '';
5030
+ }
5031
+ break;
5032
+ case 'input':
5033
+ $this->opStatus = 'input';
5034
+ break;
5035
+ case 'output':
5036
+ $this->opStatus = 'output';
5037
+ break;
5038
+ case 'body':
5039
+ if (isset($this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus])) {
5040
+ $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus] = array_merge($this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus], $attrs);
5041
+ } else {
5042
+ $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus] = $attrs;
5043
+ }
5044
+ break;
5045
+ }
5046
+ break;
5047
+ case 'service':
5048
+ switch ($name) {
5049
+ case 'port':
5050
+ $this->currentPort = $attrs['name'];
5051
+ $this->debug('current port: ' . $this->currentPort);
5052
+ $this->ports[$this->currentPort]['binding'] = $this->getLocalPart($attrs['binding']);
5053
+
5054
+ break;
5055
+ case 'address':
5056
+ $this->ports[$this->currentPort]['location'] = $attrs['location'];
5057
+ $this->ports[$this->currentPort]['bindingType'] = $namespace;
5058
+ $this->bindings[ $this->ports[$this->currentPort]['binding'] ]['bindingType'] = $namespace;
5059
+ $this->bindings[ $this->ports[$this->currentPort]['binding'] ]['endpoint'] = $attrs['location'];
5060
+ break;
5061
+ }
5062
+ break;
5063
+ }
5064
+ // set status
5065
+ switch ($name) {
5066
+ case 'import':
5067
+ if (isset($attrs['location'])) {
5068
+ $this->import[$attrs['namespace']][] = array('location' => $attrs['location'], 'loaded' => false);
5069
+ $this->debug('parsing import ' . $attrs['namespace']. ' - ' . $attrs['location'] . ' (' . count($this->import[$attrs['namespace']]).')');
5070
+ } else {
5071
+ $this->import[$attrs['namespace']][] = array('location' => '', 'loaded' => true);
5072
+ if (! $this->getPrefixFromNamespace($attrs['namespace'])) {
5073
+ $this->namespaces['ns'.(count($this->namespaces)+1)] = $attrs['namespace'];
5074
+ }
5075
+ $this->debug('parsing import ' . $attrs['namespace']. ' - [no location] (' . count($this->import[$attrs['namespace']]).')');
5076
+ }
5077
+ break;
5078
+ //wait for schema
5079
+ //case 'types':
5080
+ // $this->status = 'schema';
5081
+ // break;
5082
+ case 'message':
5083
+ $this->status = 'message';
5084
+ $this->messages[$attrs['name']] = array();
5085
+ $this->currentMessage = $attrs['name'];
5086
+ break;
5087
+ case 'portType':
5088
+ $this->status = 'portType';
5089
+ $this->portTypes[$attrs['name']] = array();
5090
+ $this->currentPortType = $attrs['name'];
5091
+ break;
5092
+ case "binding":
5093
+ if (isset($attrs['name'])) {
5094
+ // get binding name
5095
+ if (strpos($attrs['name'], ':')) {
5096
+ $this->currentBinding = $this->getLocalPart($attrs['name']);
5097
+ } else {
5098
+ $this->currentBinding = $attrs['name'];
5099
+ }
5100
+ $this->status = 'binding';
5101
+ $this->bindings[$this->currentBinding]['portType'] = $this->getLocalPart($attrs['type']);
5102
+ $this->debug("current binding: $this->currentBinding of portType: " . $attrs['type']);
5103
+ }
5104
+ break;
5105
+ case 'service':
5106
+ $this->serviceName = $attrs['name'];
5107
+ $this->status = 'service';
5108
+ $this->debug('current service: ' . $this->serviceName);
5109
+ break;
5110
+ case 'definitions':
5111
+ foreach ($attrs as $name => $value) {
5112
+ $this->wsdl_info[$name] = $value;
5113
+ }
5114
+ break;
5115
+ }
5116
+ }
5117
+ }
5118
+
5119
+ /**
5120
+ * end-element handler
5121
+ *
5122
+ * @param string $parser XML parser object
5123
+ * @param string $name element name
5124
+ * @access private
5125
+ */
5126
+ function end_element($parser, $name){
5127
+ // unset schema status
5128
+ if (/*preg_match('/types$/', $name) ||*/ preg_match('/schema$/', $name)) {
5129
+ $this->status = "";
5130
+ $this->appendDebug($this->currentSchema->getDebug());
5131
+ $this->currentSchema->clearDebug();
5132
+ $this->schemas[$this->currentSchema->schemaTargetNamespace][] = $this->currentSchema;
5133
+ $this->debug('Parsing WSDL schema done');
5134
+ }
5135
+ if ($this->status == 'schema') {
5136
+ $this->currentSchema->schemaEndElement($parser, $name);
5137
+ } else {
5138
+ // bring depth down a notch
5139
+ $this->depth--;
5140
+ }
5141
+ // end documentation
5142
+ if ($this->documentation) {
5143
+ //TODO: track the node to which documentation should be assigned; it can be a part, message, etc.
5144
+ //$this->portTypes[$this->currentPortType][$this->currentPortOperation]['documentation'] = $this->documentation;
5145
+ $this->documentation = false;
5146
+ }
5147
+ }
5148
+
5149
+ /**
5150
+ * element content handler
5151
+ *
5152
+ * @param string $parser XML parser object
5153
+ * @param string $data element content
5154
+ * @access private
5155
+ */
5156
+ function character_data($parser, $data)
5157
+ {
5158
+ $pos = isset($this->depth_array[$this->depth]) ? $this->depth_array[$this->depth] : 0;
5159
+ if (isset($this->message[$pos]['cdata'])) {
5160
+ $this->message[$pos]['cdata'] .= $data;
5161
+ }
5162
+ if ($this->documentation) {
5163
+ $this->documentation .= $data;
5164
+ }
5165
+ }
5166
+
5167
+ /**
5168
+ * if authenticating, set user credentials here
5169
+ *
5170
+ * @param string $username
5171
+ * @param string $password
5172
+ * @param string $authtype (basic|digest|certificate|ntlm)
5173
+ * @param array $certRequest (keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, certpassword (optional), verifypeer (optional), verifyhost (optional): see corresponding options in cURL docs)
5174
+ * @access public
5175
+ */
5176
+ function setCredentials($username, $password, $authtype = 'basic', $certRequest = array()) {
5177
+ $this->debug("setCredentials username=$username authtype=$authtype certRequest=");
5178
+ $this->appendDebug($this->varDump($certRequest));
5179
+ $this->username = $username;
5180
+ $this->password = $password;
5181
+ $this->authtype = $authtype;
5182
+ $this->certRequest = $certRequest;
5183
+ }
5184
+
5185
+ function getBindingData($binding)
5186
+ {
5187
+ if (is_array($this->bindings[$binding])) {
5188
+ return $this->bindings[$binding];
5189
+ }
5190
+ }
5191
+
5192
+ /**
5193
+ * returns an assoc array of operation names => operation data
5194
+ *
5195
+ * @param string $portName WSDL port name
5196
+ * @param string $bindingType eg: soap, smtp, dime (only soap and soap12 are currently supported)
5197
+ * @return array
5198
+ * @access public
5199
+ */
5200
+ function getOperations($portName = '', $bindingType = 'soap') {
5201
+ $ops = array();
5202
+ if ($bindingType == 'soap') {
5203
+ $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/';
5204
+ } elseif ($bindingType == 'soap12') {
5205
+ $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/';
5206
+ } else {
5207
+ $this->debug("getOperations bindingType $bindingType may not be supported");
5208
+ }
5209
+ $this->debug("getOperations for port '$portName' bindingType $bindingType");
5210
+ // loop thru ports
5211
+ foreach($this->ports as $port => $portData) {
5212
+ $this->debug("getOperations checking port $port bindingType " . $portData['bindingType']);
5213
+ if ($portName == '' || $port == $portName) {
5214
+ // binding type of port matches parameter
5215
+ if ($portData['bindingType'] == $bindingType) {
5216
+ $this->debug("getOperations found port $port bindingType $bindingType");
5217
+ //$this->debug("port data: " . $this->varDump($portData));
5218
+ //$this->debug("bindings: " . $this->varDump($this->bindings[ $portData['binding'] ]));
5219
+ // merge bindings
5220
+ if (isset($this->bindings[ $portData['binding'] ]['operations'])) {
5221
+ $ops = array_merge ($ops, $this->bindings[ $portData['binding'] ]['operations']);
5222
+ }
5223
+ }
5224
+ }
5225
+ }
5226
+ if (count($ops) == 0) {
5227
+ $this->debug("getOperations found no operations for port '$portName' bindingType $bindingType");
5228
+ }
5229
+ return $ops;
5230
+ }
5231
+
5232
+ /**
5233
+ * returns an associative array of data necessary for calling an operation
5234
+ *
5235
+ * @param string $operation name of operation
5236
+ * @param string $bindingType type of binding eg: soap, soap12
5237
+ * @return array
5238
+ * @access public
5239
+ */
5240
+ function getOperationData($operation, $bindingType = 'soap')
5241
+ {
5242
+ if ($bindingType == 'soap') {
5243
+ $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/';
5244
+ } elseif ($bindingType == 'soap12') {
5245
+ $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/';
5246
+ }
5247
+ // loop thru ports
5248
+ foreach($this->ports as $port => $portData) {
5249
+ // binding type of port matches parameter
5250
+ if ($portData['bindingType'] == $bindingType) {
5251
+ // get binding
5252
+ //foreach($this->bindings[ $portData['binding'] ]['operations'] as $bOperation => $opData) {
5253
+ foreach(array_keys($this->bindings[ $portData['binding'] ]['operations']) as $bOperation) {
5254
+ // note that we could/should also check the namespace here
5255
+ if ($operation == $bOperation) {
5256
+ $opData = $this->bindings[ $portData['binding'] ]['operations'][$operation];
5257
+ return $opData;
5258
+ }
5259
+ }
5260
+ }
5261
+ }
5262
+ }
5263
+
5264
+ /**
5265
+ * returns an associative array of data necessary for calling an operation
5266
+ *
5267
+ * @param string $soapAction soapAction for operation
5268
+ * @param string $bindingType type of binding eg: soap, soap12
5269
+ * @return array
5270
+ * @access public
5271
+ */
5272
+ function getOperationDataForSoapAction($soapAction, $bindingType = 'soap') {
5273
+ if ($bindingType == 'soap') {
5274
+ $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/';
5275
+ } elseif ($bindingType == 'soap12') {
5276
+ $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/';
5277
+ }
5278
+ // loop thru ports
5279
+ foreach($this->ports as $port => $portData) {
5280
+ // binding type of port matches parameter
5281
+ if ($portData['bindingType'] == $bindingType) {
5282
+ // loop through operations for the binding
5283
+ foreach ($this->bindings[ $portData['binding'] ]['operations'] as $bOperation => $opData) {
5284
+ if ($opData['soapAction'] == $soapAction) {
5285
+ return $opData;
5286
+ }
5287
+ }
5288
+ }
5289
+ }
5290
+ }
5291
+
5292
+ /**
5293
+ * returns an array of information about a given type
5294
+ * returns false if no type exists by the given name
5295
+ *
5296
+ * typeDef = array(
5297
+ * 'elements' => array(), // refs to elements array
5298
+ * 'restrictionBase' => '',
5299
+ * 'phpType' => '',
5300
+ * 'order' => '(sequence|all)',
5301
+ * 'attrs' => array() // refs to attributes array
5302
+ * )
5303
+ *
5304
+ * @param string $type the type
5305
+ * @param string $ns namespace (not prefix) of the type
5306
+ * @return mixed
5307
+ * @access public
5308
+ * @see nusoap_xmlschema
5309
+ */
5310
+ function getTypeDef($type, $ns) {
5311
+ $this->debug("in getTypeDef: type=$type, ns=$ns");
5312
+ if ((! $ns) && isset($this->namespaces['tns'])) {
5313
+ $ns = $this->namespaces['tns'];
5314
+ $this->debug("in getTypeDef: type namespace forced to $ns");
5315
+ }
5316
+ if (!isset($this->schemas[$ns])) {
5317
+ foreach ($this->schemas as $ns0 => $schema0) {
5318
+ if (strcasecmp($ns, $ns0) == 0) {
5319
+ $this->debug("in getTypeDef: replacing schema namespace $ns with $ns0");
5320
+ $ns = $ns0;
5321
+ break;
5322
+ }
5323
+ }
5324
+ }
5325
+ if (isset($this->schemas[$ns])) {
5326
+ $this->debug("in getTypeDef: have schema for namespace $ns");
5327
+ for ($i = 0; $i < count($this->schemas[$ns]); $i++) {
5328
+ $xs = &$this->schemas[$ns][$i];
5329
+ $t = $xs->getTypeDef($type);
5330
+ $this->appendDebug($xs->getDebug());
5331
+ $xs->clearDebug();
5332
+ if ($t) {
5333
+ $this->debug("in getTypeDef: found type $type");
5334
+ if (!isset($t['phpType'])) {
5335
+ // get info for type to tack onto the element
5336
+ $uqType = substr($t['type'], strrpos($t['type'], ':') + 1);
5337
+ $ns = substr($t['type'], 0, strrpos($t['type'], ':'));
5338
+ $etype = $this->getTypeDef($uqType, $ns);
5339
+ if ($etype) {
5340
+ $this->debug("found type for [element] $type:");
5341
+ $this->debug($this->varDump($etype));
5342
+ if (isset($etype['phpType'])) {
5343
+ $t['phpType'] = $etype['phpType'];
5344
+ }
5345
+ if (isset($etype['elements'])) {
5346
+ $t['elements'] = $etype['elements'];
5347
+ }
5348
+ if (isset($etype['attrs'])) {
5349
+ $t['attrs'] = $etype['attrs'];
5350
+ }
5351
+ } else {
5352
+ $this->debug("did not find type for [element] $type");
5353
+ }
5354
+ }
5355
+ return $t;
5356
+ }
5357
+ }
5358
+ $this->debug("in getTypeDef: did not find type $type");
5359
+ } else {
5360
+ $this->debug("in getTypeDef: do not have schema for namespace $ns");
5361
+ }
5362
+ return false;
5363
+ }
5364
+
5365
+ /**
5366
+ * prints html description of services
5367
+ *
5368
+ * @access private
5369
+ */
5370
+ function webDescription(){
5371
+ global $HTTP_SERVER_VARS;
5372
+
5373
+ if (isset($_SERVER)) {
5374
+ $PHP_SELF = $_SERVER['PHP_SELF'];
5375
+ } elseif (isset($HTTP_SERVER_VARS)) {
5376
+ $PHP_SELF = $HTTP_SERVER_VARS['PHP_SELF'];
5377
+ } else {
5378
+ $this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available");
5379
+ }
5380
+
5381
+ $b = '
5382
+ <html><head><title>NuSOAP: '.$this->serviceName.'</title>
5383
+ <style type="text/css">
5384
+ body { font-family: arial; color: #000000; background-color: #ffffff; margin: 0px 0px 0px 0px; }
5385
+ p { font-family: arial; color: #000000; margin-top: 0px; margin-bottom: 12px; }
5386
+ pre { background-color: silver; padding: 5px; font-family: Courier New; font-size: x-small; color: #000000;}
5387
+ ul { margin-top: 10px; margin-left: 20px; }
5388
+ li { list-style-type: none; margin-top: 10px; color: #000000; }
5389
+ .content{
5390
+ margin-left: 0px; padding-bottom: 2em; }
5391
+ .nav {
5392
+ padding-top: 10px; padding-bottom: 10px; padding-left: 15px; font-size: .70em;
5393
+ margin-top: 10px; margin-left: 0px; color: #000000;
5394
+ background-color: #ccccff; width: 20%; margin-left: 20px; margin-top: 20px; }
5395
+ .title {
5396
+ font-family: arial; font-size: 26px; color: #ffffff;
5397
+ background-color: #999999; width: 100%;
5398
+ margin-left: 0px; margin-right: 0px;
5399
+ padding-top: 10px; padding-bottom: 10px;}
5400
+ .hidden {
5401
+ position: absolute; visibility: hidden; z-index: 200; left: 250px; top: 100px;
5402
+ font-family: arial; overflow: hidden; width: 600;
5403
+ padding: 20px; font-size: 10px; background-color: #999999;
5404
+ layer-background-color:#FFFFFF; }
5405
+ a,a:active { color: charcoal; font-weight: bold; }
5406
+ a:visited { color: #666666; font-weight: bold; }
5407
+ a:hover { color: cc3300; font-weight: bold; }
5408
+ </style>
5409
+ <script language="JavaScript" type="text/javascript">
5410
+ <!--
5411
+ // POP-UP CAPTIONS...
5412
+ function lib_bwcheck(){ //Browsercheck (needed)
5413
+ this.ver=navigator.appVersion
5414
+ this.agent=navigator.userAgent
5415
+ this.dom=document.getElementById?1:0
5416
+ this.opera5=this.agent.indexOf("Opera 5")>-1
5417
+ this.ie5=(this.ver.indexOf("MSIE 5")>-1 && this.dom && !this.opera5)?1:0;
5418
+ this.ie6=(this.ver.indexOf("MSIE 6")>-1 && this.dom && !this.opera5)?1:0;
5419
+ this.ie4=(document.all && !this.dom && !this.opera5)?1:0;
5420
+ this.ie=this.ie4||this.ie5||this.ie6
5421
+ this.mac=this.agent.indexOf("Mac")>-1
5422
+ this.ns6=(this.dom && parseInt(this.ver) >= 5) ?1:0;
5423
+ this.ns4=(document.layers && !this.dom)?1:0;
5424
+ this.bw=(this.ie6 || this.ie5 || this.ie4 || this.ns4 || this.ns6 || this.opera5)
5425
+ return this
5426
+ }
5427
+ var bw = new lib_bwcheck()
5428
+ //Makes crossbrowser object.
5429
+ function makeObj(obj){
5430
+ this.evnt=bw.dom? document.getElementById(obj):bw.ie4?document.all[obj]:bw.ns4?document.layers[obj]:0;
5431
+ if(!this.evnt) return false
5432
+ this.css=bw.dom||bw.ie4?this.evnt.style:bw.ns4?this.evnt:0;
5433
+ this.wref=bw.dom||bw.ie4?this.evnt:bw.ns4?this.css.document:0;
5434
+ this.writeIt=b_writeIt;
5435
+ return this
5436
+ }
5437
+ // A unit of measure that will be added when setting the position of a layer.
5438
+ //var px = bw.ns4||window.opera?"":"px";
5439
+ function b_writeIt(text){
5440
+ if (bw.ns4){this.wref.write(text);this.wref.close()}
5441
+ else this.wref.innerHTML = text
5442
+ }
5443
+ //Shows the messages
5444
+ var oDesc;
5445
+ function popup(divid){
5446
+ if(oDesc = new makeObj(divid)){
5447
+ oDesc.css.visibility = "visible"
5448
+ }
5449
+ }
5450
+ function popout(){ // Hides message
5451
+ if(oDesc) oDesc.css.visibility = "hidden"
5452
+ }
5453
+ //-->
5454
+ </script>
5455
+ </head>
5456
+ <body>
5457
+ <div class=content>
5458
+ <br><br>
5459
+ <div class=title>'.$this->serviceName.'</div>
5460
+ <div class=nav>
5461
+ <p>View the <a href="'.$PHP_SELF.'?wsdl">WSDL</a> for the service.
5462
+ Click on an operation name to view it&apos;s details.</p>
5463
+ <ul>';
5464
+ foreach($this->getOperations() as $op => $data){
5465
+ $b .= "<li><a href='#' onclick=\"popout();popup('$op')\">$op</a></li>";
5466
+ // create hidden div
5467
+ $b .= "<div id='$op' class='hidden'>
5468
+ <a href='#' onclick='popout()'><font color='#ffffff'>Close</font></a><br><br>";
5469
+ foreach($data as $donnie => $marie){ // loop through opdata
5470
+ if($donnie == 'input' || $donnie == 'output'){ // show input/output data
5471
+ $b .= "<font color='white'>".ucfirst($donnie).':</font><br>';
5472
+ foreach($marie as $captain => $tenille){ // loop through data
5473
+ if($captain == 'parts'){ // loop thru parts
5474
+ $b .= "&nbsp;&nbsp;$captain:<br>";
5475
+ //if(is_array($tenille)){
5476
+ foreach($tenille as $joanie => $chachi){
5477
+ $b .= "&nbsp;&nbsp;&nbsp;&nbsp;$joanie: $chachi<br>";
5478
+ }
5479
+ //}
5480
+ } else {
5481
+ $b .= "&nbsp;&nbsp;$captain: $tenille<br>";
5482
+ }
5483
+ }
5484
+ } else {
5485
+ $b .= "<font color='white'>".ucfirst($donnie).":</font> $marie<br>";
5486
+ }
5487
+ }
5488
+ $b .= '</div>';
5489
+ }
5490
+ $b .= '
5491
+ <ul>
5492
+ </div>
5493
+ </div></body></html>';
5494
+ return $b;
5495
+ }
5496
+
5497
+ /**
5498
+ * serialize the parsed wsdl
5499
+ *
5500
+ * @param mixed $debug whether to put debug=1 in endpoint URL
5501
+ * @return string serialization of WSDL
5502
+ * @access public
5503
+ */
5504
+ function serialize($debug = 0)
5505
+ {
5506
+ $xml = '<?xml version="1.0" encoding="ISO-8859-1"?>';
5507
+ $xml .= "\n<definitions";
5508
+ foreach($this->namespaces as $k => $v) {
5509
+ $xml .= " xmlns:$k=\"$v\"";
5510
+ }
5511
+ // 10.9.02 - add poulter fix for wsdl and tns declarations
5512
+ if (isset($this->namespaces['wsdl'])) {
5513
+ $xml .= " xmlns=\"" . $this->namespaces['wsdl'] . "\"";
5514
+ }
5515
+ if (isset($this->namespaces['tns'])) {
5516
+ $xml .= " targetNamespace=\"" . $this->namespaces['tns'] . "\"";
5517
+ }
5518
+ $xml .= '>';
5519
+ // imports
5520
+ if (sizeof($this->import) > 0) {
5521
+ foreach($this->import as $ns => $list) {
5522
+ foreach ($list as $ii) {
5523
+ if ($ii['location'] != '') {
5524
+ $xml .= '<import location="' . $ii['location'] . '" namespace="' . $ns . '" />';
5525
+ } else {
5526
+ $xml .= '<import namespace="' . $ns . '" />';
5527
+ }
5528
+ }
5529
+ }
5530
+ }
5531
+ // types
5532
+ if (count($this->schemas)>=1) {
5533
+ $xml .= "\n<types>\n";
5534
+ foreach ($this->schemas as $ns => $list) {
5535
+ foreach ($list as $xs) {
5536
+ $xml .= $xs->serializeSchema();
5537
+ }
5538
+ }
5539
+ $xml .= '</types>';
5540
+ }
5541
+ // messages
5542
+ if (count($this->messages) >= 1) {
5543
+ foreach($this->messages as $msgName => $msgParts) {
5544
+ $xml .= "\n<message name=\"" . $msgName . '">';
5545
+ if(is_array($msgParts)){
5546
+ foreach($msgParts as $partName => $partType) {
5547
+ // print 'serializing '.$partType.', sv: '.$this->XMLSchemaVersion.'<br>';
5548
+ if (strpos($partType, ':')) {
5549
+ $typePrefix = $this->getPrefixFromNamespace($this->getPrefix($partType));
5550
+ } elseif (isset($this->typemap[$this->namespaces['xsd']][$partType])) {
5551
+ // print 'checking typemap: '.$this->XMLSchemaVersion.'<br>';
5552
+ $typePrefix = 'xsd';
5553
+ } else {
5554
+ foreach($this->typemap as $ns => $types) {
5555
+ if (isset($types[$partType])) {
5556
+ $typePrefix = $this->getPrefixFromNamespace($ns);
5557
+ }
5558
+ }
5559
+ if (!isset($typePrefix)) {
5560
+ die("$partType has no namespace!");
5561
+ }
5562
+ }
5563
+ $ns = $this->getNamespaceFromPrefix($typePrefix);
5564
+ $localPart = $this->getLocalPart($partType);
5565
+ $typeDef = $this->getTypeDef($localPart, $ns);
5566
+ if ($typeDef['typeClass'] == 'element') {
5567
+ $elementortype = 'element';
5568
+ if (substr($localPart, -1) == '^') {
5569
+ $localPart = substr($localPart, 0, -1);
5570
+ }
5571
+ } else {
5572
+ $elementortype = 'type';
5573
+ }
5574
+ $xml .= "\n" . ' <part name="' . $partName . '" ' . $elementortype . '="' . $typePrefix . ':' . $localPart . '" />';
5575
+ }
5576
+ }
5577
+ $xml .= '</message>';
5578
+ }
5579
+ }
5580
+ // bindings & porttypes
5581
+ if (count($this->bindings) >= 1) {
5582
+ $binding_xml = '';
5583
+ $portType_xml = '';
5584
+ foreach($this->bindings as $bindingName => $attrs) {
5585
+ $binding_xml .= "\n<binding name=\"" . $bindingName . '" type="tns:' . $attrs['portType'] . '">';
5586
+ $binding_xml .= "\n" . ' <soap:binding style="' . $attrs['style'] . '" transport="' . $attrs['transport'] . '"/>';
5587
+ $portType_xml .= "\n<portType name=\"" . $attrs['portType'] . '">';
5588
+ foreach($attrs['operations'] as $opName => $opParts) {
5589
+ $binding_xml .= "\n" . ' <operation name="' . $opName . '">';
5590
+ $binding_xml .= "\n" . ' <soap:operation soapAction="' . $opParts['soapAction'] . '" style="'. $opParts['style'] . '"/>';
5591
+ if (isset($opParts['input']['encodingStyle']) && $opParts['input']['encodingStyle'] != '') {
5592
+ $enc_style = ' encodingStyle="' . $opParts['input']['encodingStyle'] . '"';
5593
+ } else {
5594
+ $enc_style = '';
5595
+ }
5596
+ $binding_xml .= "\n" . ' <input><soap:body use="' . $opParts['input']['use'] . '" namespace="' . $opParts['input']['namespace'] . '"' . $enc_style . '/></input>';
5597
+ if (isset($opParts['output']['encodingStyle']) && $opParts['output']['encodingStyle'] != '') {
5598
+ $enc_style = ' encodingStyle="' . $opParts['output']['encodingStyle'] . '"';
5599
+ } else {
5600
+ $enc_style = '';
5601
+ }
5602
+ $binding_xml .= "\n" . ' <output><soap:body use="' . $opParts['output']['use'] . '" namespace="' . $opParts['output']['namespace'] . '"' . $enc_style . '/></output>';
5603
+ $binding_xml .= "\n" . ' </operation>';
5604
+ $portType_xml .= "\n" . ' <operation name="' . $opParts['name'] . '"';
5605
+ if (isset($opParts['parameterOrder'])) {
5606
+ $portType_xml .= ' parameterOrder="' . $opParts['parameterOrder'] . '"';
5607
+ }
5608
+ $portType_xml .= '>';
5609
+ if(isset($opParts['documentation']) && $opParts['documentation'] != '') {
5610
+ $portType_xml .= "\n" . ' <documentation>' . htmlspecialchars($opParts['documentation']) . '</documentation>';
5611
+ }
5612
+ $portType_xml .= "\n" . ' <input message="tns:' . $opParts['input']['message'] . '"/>';
5613
+ $portType_xml .= "\n" . ' <output message="tns:' . $opParts['output']['message'] . '"/>';
5614
+ $portType_xml .= "\n" . ' </operation>';
5615
+ }
5616
+ $portType_xml .= "\n" . '</portType>';
5617
+ $binding_xml .= "\n" . '</binding>';
5618
+ }
5619
+ $xml .= $portType_xml . $binding_xml;
5620
+ }
5621
+ // services
5622
+ $xml .= "\n<service name=\"" . $this->serviceName . '">';
5623
+ if (count($this->ports) >= 1) {
5624
+ foreach($this->ports as $pName => $attrs) {
5625
+ $xml .= "\n" . ' <port name="' . $pName . '" binding="tns:' . $attrs['binding'] . '">';
5626
+ $xml .= "\n" . ' <soap:address location="' . $attrs['location'] . ($debug ? '?debug=1' : '') . '"/>';
5627
+ $xml .= "\n" . ' </port>';
5628
+ }
5629
+ }
5630
+ $xml .= "\n" . '</service>';
5631
+ return $xml . "\n</definitions>";
5632
+ }
5633
+
5634
+ /**
5635
+ * determine whether a set of parameters are unwrapped
5636
+ * when they are expect to be wrapped, Microsoft-style.
5637
+ *
5638
+ * @param string $type the type (element name) of the wrapper
5639
+ * @param array $parameters the parameter values for the SOAP call
5640
+ * @return boolean whether they parameters are unwrapped (and should be wrapped)
5641
+ * @access private
5642
+ */
5643
+ function parametersMatchWrapped($type, &$parameters) {
5644
+ $this->debug("in parametersMatchWrapped type=$type, parameters=");
5645
+ $this->appendDebug($this->varDump($parameters));
5646
+
5647
+ // split type into namespace:unqualified-type
5648
+ if (strpos($type, ':')) {
5649
+ $uqType = substr($type, strrpos($type, ':') + 1);
5650
+ $ns = substr($type, 0, strrpos($type, ':'));
5651
+ $this->debug("in parametersMatchWrapped: got a prefixed type: $uqType, $ns");
5652
+ if ($this->getNamespaceFromPrefix($ns)) {
5653
+ $ns = $this->getNamespaceFromPrefix($ns);
5654
+ $this->debug("in parametersMatchWrapped: expanded prefixed type: $uqType, $ns");
5655
+ }
5656
+ } else {
5657
+ // TODO: should the type be compared to types in XSD, and the namespace
5658
+ // set to XSD if the type matches?
5659
+ $this->debug("in parametersMatchWrapped: No namespace for type $type");
5660
+ $ns = '';
5661
+ $uqType = $type;
5662
+ }
5663
+
5664
+ // get the type information
5665
+ if (!$typeDef = $this->getTypeDef($uqType, $ns)) {
5666
+ $this->debug("in parametersMatchWrapped: $type ($uqType) is not a supported type.");
5667
+ return false;
5668
+ }
5669
+ $this->debug("in parametersMatchWrapped: found typeDef=");
5670
+ $this->appendDebug($this->varDump($typeDef));
5671
+ if (substr($uqType, -1) == '^') {
5672
+ $uqType = substr($uqType, 0, -1);
5673
+ }
5674
+ $phpType = $typeDef['phpType'];
5675
+ $arrayType = (isset($typeDef['arrayType']) ? $typeDef['arrayType'] : '');
5676
+ $this->debug("in parametersMatchWrapped: uqType: $uqType, ns: $ns, phptype: $phpType, arrayType: $arrayType");
5677
+
5678
+ // we expect a complexType or element of complexType
5679
+ if ($phpType != 'struct') {
5680
+ $this->debug("in parametersMatchWrapped: not a struct");
5681
+ return false;
5682
+ }
5683
+
5684
+ // see whether the parameter names match the elements
5685
+ if (isset($typeDef['elements']) && is_array($typeDef['elements'])) {
5686
+ $elements = 0;
5687
+ $matches = 0;
5688
+ foreach ($typeDef['elements'] as $name => $attrs) {
5689
+ if (isset($parameters[$name])) {
5690
+ $this->debug("in parametersMatchWrapped: have parameter named $name");
5691
+ $matches++;
5692
+ } else {
5693
+ $this->debug("in parametersMatchWrapped: do not have parameter named $name");
5694
+ }
5695
+ $elements++;
5696
+ }
5697
+
5698
+ $this->debug("in parametersMatchWrapped: $matches parameter names match $elements wrapped parameter names");
5699
+ if ($matches == 0) {
5700
+ return false;
5701
+ }
5702
+ return true;
5703
+ }
5704
+
5705
+ // since there are no elements for the type, if the user passed no
5706
+ // parameters, the parameters match wrapped.
5707
+ $this->debug("in parametersMatchWrapped: no elements type $ns:$uqType");
5708
+ return count($parameters) == 0;
5709
+ }
5710
+
5711
+ /**
5712
+ * serialize PHP values according to a WSDL message definition
5713
+ * contrary to the method name, this is not limited to RPC
5714
+ *
5715
+ * TODO
5716
+ * - multi-ref serialization
5717
+ * - validate PHP values against type definitions, return errors if invalid
5718
+ *
5719
+ * @param string $operation operation name
5720
+ * @param string $direction (input|output)
5721
+ * @param mixed $parameters parameter value(s)
5722
+ * @param string $bindingType (soap|soap12)
5723
+ * @return mixed parameters serialized as XML or false on error (e.g. operation not found)
5724
+ * @access public
5725
+ */
5726
+ function serializeRPCParameters($operation, $direction, $parameters, $bindingType = 'soap') {
5727
+ $this->debug("in serializeRPCParameters: operation=$operation, direction=$direction, XMLSchemaVersion=$this->XMLSchemaVersion, bindingType=$bindingType");
5728
+ $this->appendDebug('parameters=' . $this->varDump($parameters));
5729
+
5730
+ if ($direction != 'input' && $direction != 'output') {
5731
+ $this->debug('The value of the \$direction argument needs to be either "input" or "output"');
5732
+ $this->setError('The value of the \$direction argument needs to be either "input" or "output"');
5733
+ return false;
5734
+ }
5735
+ if (!$opData = $this->getOperationData($operation, $bindingType)) {
5736
+ $this->debug('Unable to retrieve WSDL data for operation: ' . $operation . ' bindingType: ' . $bindingType);
5737
+ $this->setError('Unable to retrieve WSDL data for operation: ' . $operation . ' bindingType: ' . $bindingType);
5738
+ return false;
5739
+ }
5740
+ $this->debug('in serializeRPCParameters: opData:');
5741
+ $this->appendDebug($this->varDump($opData));
5742
+
5743
+ // Get encoding style for output and set to current
5744
+ $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
5745
+ if(($direction == 'input') && isset($opData['output']['encodingStyle']) && ($opData['output']['encodingStyle'] != $encodingStyle)) {
5746
+ $encodingStyle = $opData['output']['encodingStyle'];
5747
+ $enc_style = $encodingStyle;
5748
+ }
5749
+
5750
+ // set input params
5751
+ $xml = '';
5752
+ if (isset($opData[$direction]['parts']) && sizeof($opData[$direction]['parts']) > 0) {
5753
+ $parts = &$opData[$direction]['parts'];
5754
+ $part_count = sizeof($parts);
5755
+ $style = $opData['style'];
5756
+ $use = $opData[$direction]['use'];
5757
+ $this->debug("have $part_count part(s) to serialize using $style/$use");
5758
+ if (is_array($parameters)) {
5759
+ $parametersArrayType = $this->isArraySimpleOrStruct($parameters);
5760
+ $parameter_count = count($parameters);
5761
+ $this->debug("have $parameter_count parameter(s) provided as $parametersArrayType to serialize");
5762
+ // check for Microsoft-style wrapped parameters
5763
+ if ($style == 'document' && $use == 'literal' && $part_count == 1 && isset($parts['parameters'])) {
5764
+ $this->debug('check whether the caller has wrapped the parameters');
5765
+ if ($direction == 'output' && $parametersArrayType == 'arraySimple' && $parameter_count == 1) {
5766
+ // TODO: consider checking here for double-wrapping, when
5767
+ // service function wraps, then NuSOAP wraps again
5768
+ $this->debug("change simple array to associative with 'parameters' element");
5769
+ $parameters['parameters'] = $parameters[0];
5770
+ unset($parameters[0]);
5771
+ }
5772
+ if (($parametersArrayType == 'arrayStruct' || $parameter_count == 0) && !isset($parameters['parameters'])) {
5773
+ $this->debug('check whether caller\'s parameters match the wrapped ones');
5774
+ if ($this->parametersMatchWrapped($parts['parameters'], $parameters)) {
5775
+ $this->debug('wrap the parameters for the caller');
5776
+ $parameters = array('parameters' => $parameters);
5777
+ $parameter_count = 1;
5778
+ }
5779
+ }
5780
+ }
5781
+ foreach ($parts as $name => $type) {
5782
+ $this->debug("serializing part $name of type $type");
5783
+ // Track encoding style
5784
+ if (isset($opData[$direction]['encodingStyle']) && $encodingStyle != $opData[$direction]['encodingStyle']) {
5785
+ $encodingStyle = $opData[$direction]['encodingStyle'];
5786
+ $enc_style = $encodingStyle;
5787
+ } else {
5788
+ $enc_style = false;
5789
+ }
5790
+ // NOTE: add error handling here
5791
+ // if serializeType returns false, then catch global error and fault
5792
+ if ($parametersArrayType == 'arraySimple') {
5793
+ $p = array_shift($parameters);
5794
+ $this->debug('calling serializeType w/indexed param');
5795
+ $xml .= $this->serializeType($name, $type, $p, $use, $enc_style);
5796
+ } elseif (isset($parameters[$name])) {
5797
+ $this->debug('calling serializeType w/named param');
5798
+ $xml .= $this->serializeType($name, $type, $parameters[$name], $use, $enc_style);
5799
+ } else {
5800
+ // TODO: only send nillable
5801
+ $this->debug('calling serializeType w/null param');
5802
+ $xml .= $this->serializeType($name, $type, null, $use, $enc_style);
5803
+ }
5804
+ }
5805
+ } else {
5806
+ $this->debug('no parameters passed.');
5807
+ }
5808
+ }
5809
+ $this->debug("serializeRPCParameters returning: $xml");
5810
+ return $xml;
5811
+ }
5812
+
5813
+ /**
5814
+ * serialize a PHP value according to a WSDL message definition
5815
+ *
5816
+ * TODO
5817
+ * - multi-ref serialization
5818
+ * - validate PHP values against type definitions, return errors if invalid
5819
+ *
5820
+ * @param string $operation operation name
5821
+ * @param string $direction (input|output)
5822
+ * @param mixed $parameters parameter value(s)
5823
+ * @return mixed parameters serialized as XML or false on error (e.g. operation not found)
5824
+ * @access public
5825
+ * @deprecated
5826
+ */
5827
+ function serializeParameters($operation, $direction, $parameters)
5828
+ {
5829
+ $this->debug("in serializeParameters: operation=$operation, direction=$direction, XMLSchemaVersion=$this->XMLSchemaVersion");
5830
+ $this->appendDebug('parameters=' . $this->varDump($parameters));
5831
+
5832
+ if ($direction != 'input' && $direction != 'output') {
5833
+ $this->debug('The value of the \$direction argument needs to be either "input" or "output"');
5834
+ $this->setError('The value of the \$direction argument needs to be either "input" or "output"');
5835
+ return false;
5836
+ }
5837
+ if (!$opData = $this->getOperationData($operation)) {
5838
+ $this->debug('Unable to retrieve WSDL data for operation: ' . $operation);
5839
+ $this->setError('Unable to retrieve WSDL data for operation: ' . $operation);
5840
+ return false;
5841
+ }
5842
+ $this->debug('opData:');
5843
+ $this->appendDebug($this->varDump($opData));
5844
+
5845
+ // Get encoding style for output and set to current
5846
+ $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
5847
+ if(($direction == 'input') && isset($opData['output']['encodingStyle']) && ($opData['output']['encodingStyle'] != $encodingStyle)) {
5848
+ $encodingStyle = $opData['output']['encodingStyle'];
5849
+ $enc_style = $encodingStyle;
5850
+ }
5851
+
5852
+ // set input params
5853
+ $xml = '';
5854
+ if (isset($opData[$direction]['parts']) && sizeof($opData[$direction]['parts']) > 0) {
5855
+
5856
+ $use = $opData[$direction]['use'];
5857
+ $this->debug("use=$use");
5858
+ $this->debug('got ' . count($opData[$direction]['parts']) . ' part(s)');
5859
+ if (is_array($parameters)) {
5860
+ $parametersArrayType = $this->isArraySimpleOrStruct($parameters);
5861
+ $this->debug('have ' . $parametersArrayType . ' parameters');
5862
+ foreach($opData[$direction]['parts'] as $name => $type) {
5863
+ $this->debug('serializing part "'.$name.'" of type "'.$type.'"');
5864
+ // Track encoding style
5865
+ if(isset($opData[$direction]['encodingStyle']) && $encodingStyle != $opData[$direction]['encodingStyle']) {
5866
+ $encodingStyle = $opData[$direction]['encodingStyle'];
5867
+ $enc_style = $encodingStyle;
5868
+ } else {
5869
+ $enc_style = false;
5870
+ }
5871
+ // NOTE: add error handling here
5872
+ // if serializeType returns false, then catch global error and fault
5873
+ if ($parametersArrayType == 'arraySimple') {
5874
+ $p = array_shift($parameters);
5875
+ $this->debug('calling serializeType w/indexed param');
5876
+ $xml .= $this->serializeType($name, $type, $p, $use, $enc_style);
5877
+ } elseif (isset($parameters[$name])) {
5878
+ $this->debug('calling serializeType w/named param');
5879
+ $xml .= $this->serializeType($name, $type, $parameters[$name], $use, $enc_style);
5880
+ } else {
5881
+ // TODO: only send nillable
5882
+ $this->debug('calling serializeType w/null param');
5883
+ $xml .= $this->serializeType($name, $type, null, $use, $enc_style);
5884
+ }
5885
+ }
5886
+ } else {
5887
+ $this->debug('no parameters passed.');
5888
+ }
5889
+ }
5890
+ $this->debug("serializeParameters returning: $xml");
5891
+ return $xml;
5892
+ }
5893
+
5894
+ /**
5895
+ * serializes a PHP value according a given type definition
5896
+ *
5897
+ * @param string $name name of value (part or element)
5898
+ * @param string $type XML schema type of value (type or element)
5899
+ * @param mixed $value a native PHP value (parameter value)
5900
+ * @param string $use use for part (encoded|literal)
5901
+ * @param string $encodingStyle SOAP encoding style for the value (if different than the enclosing style)
5902
+ * @param boolean $unqualified a kludge for what should be XML namespace form handling
5903
+ * @return string value serialized as an XML string
5904
+ * @access private
5905
+ */
5906
+ function serializeType($name, $type, $value, $use='encoded', $encodingStyle=false, $unqualified=false)
5907
+ {
5908
+ $this->debug("in serializeType: name=$name, type=$type, use=$use, encodingStyle=$encodingStyle, unqualified=" . ($unqualified ? "unqualified" : "qualified"));
5909
+ $this->appendDebug("value=" . $this->varDump($value));
5910
+ if($use == 'encoded' && $encodingStyle) {
5911
+ $encodingStyle = ' SOAP-ENV:encodingStyle="' . $encodingStyle . '"';
5912
+ }
5913
+
5914
+ // if a soapval has been supplied, let its type override the WSDL
5915
+ if (is_object($value) && get_class($value) == 'soapval') {
5916
+ if ($value->type_ns) {
5917
+ $type = $value->type_ns . ':' . $value->type;
5918
+ $forceType = true;
5919
+ $this->debug("in serializeType: soapval overrides type to $type");
5920
+ } elseif ($value->type) {
5921
+ $type = $value->type;
5922
+ $forceType = true;
5923
+ $this->debug("in serializeType: soapval overrides type to $type");
5924
+ } else {
5925
+ $forceType = false;
5926
+ $this->debug("in serializeType: soapval does not override type");
5927
+ }
5928
+ $attrs = $value->attributes;
5929
+ $value = $value->value;
5930
+ $this->debug("in serializeType: soapval overrides value to $value");
5931
+ if ($attrs) {
5932
+ if (!is_array($value)) {
5933
+ $value['!'] = $value;
5934
+ }
5935
+ foreach ($attrs as $n => $v) {
5936
+ $value['!' . $n] = $v;
5937
+ }
5938
+ $this->debug("in serializeType: soapval provides attributes");
5939
+ }
5940
+ } else {
5941
+ $forceType = false;
5942
+ }
5943
+
5944
+ $xml = '';
5945
+ if (strpos($type, ':')) {
5946
+ $uqType = substr($type, strrpos($type, ':') + 1);
5947
+ $ns = substr($type, 0, strrpos($type, ':'));
5948
+ $this->debug("in serializeType: got a prefixed type: $uqType, $ns");
5949
+ if ($this->getNamespaceFromPrefix($ns)) {
5950
+ $ns = $this->getNamespaceFromPrefix($ns);
5951
+ $this->debug("in serializeType: expanded prefixed type: $uqType, $ns");
5952
+ }
5953
+
5954
+ if($ns == $this->XMLSchemaVersion || $ns == 'http://schemas.xmlsoap.org/soap/encoding/'){
5955
+ $this->debug('in serializeType: type namespace indicates XML Schema or SOAP Encoding type');
5956
+ if ($unqualified && $use == 'literal') {
5957
+ $elementNS = " xmlns=\"\"";
5958
+ } else {
5959
+ $elementNS = '';
5960
+ }
5961
+ if (is_null($value)) {
5962
+ if ($use == 'literal') {
5963
+ // TODO: depends on minOccurs
5964
+ $xml = "<$name$elementNS/>";
5965
+ } else {
5966
+ // TODO: depends on nillable, which should be checked before calling this method
5967
+ $xml = "<$name$elementNS xsi:nil=\"true\" xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"/>";
5968
+ }
5969
+ $this->debug("in serializeType: returning: $xml");
5970
+ return $xml;
5971
+ }
5972
+ if ($uqType == 'Array') {
5973
+ // JBoss/Axis does this sometimes
5974
+ return $this->serialize_val($value, $name, false, false, false, false, $use);
5975
+ }
5976
+ if ($uqType == 'boolean') {
5977
+ if ((is_string($value) && $value == 'false') || (! $value)) {
5978
+ $value = 'false';
5979
+ } else {
5980
+ $value = 'true';
5981
+ }
5982
+ }
5983
+ if ($uqType == 'string' && gettype($value) == 'string') {
5984
+ $value = $this->expandEntities($value);
5985
+ }
5986
+ if (($uqType == 'long' || $uqType == 'unsignedLong') && gettype($value) == 'double') {
5987
+ $value = sprintf("%.0lf", $value);
5988
+ }
5989
+ // it's a scalar
5990
+ // TODO: what about null/nil values?
5991
+ // check type isn't a custom type extending xmlschema namespace
5992
+ if (!$this->getTypeDef($uqType, $ns)) {
5993
+ if ($use == 'literal') {
5994
+ if ($forceType) {
5995
+ $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">$value</$name>";
5996
+ } else {
5997
+ $xml = "<$name$elementNS>$value</$name>";
5998
+ }
5999
+ } else {
6000
+ $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>$value</$name>";
6001
+ }
6002
+ $this->debug("in serializeType: returning: $xml");
6003
+ return $xml;
6004
+ }
6005
+ $this->debug('custom type extends XML Schema or SOAP Encoding namespace (yuck)');
6006
+ } else if ($ns == 'http://xml.apache.org/xml-soap') {
6007
+ $this->debug('in serializeType: appears to be Apache SOAP type');
6008
+ if ($uqType == 'Map') {
6009
+ $tt_prefix = $this->getPrefixFromNamespace('http://xml.apache.org/xml-soap');
6010
+ if (! $tt_prefix) {
6011
+ $this->debug('in serializeType: Add namespace for Apache SOAP type');
6012
+ $tt_prefix = 'ns' . rand(1000, 9999);
6013
+ $this->namespaces[$tt_prefix] = 'http://xml.apache.org/xml-soap';
6014
+ // force this to be added to usedNamespaces
6015
+ $tt_prefix = $this->getPrefixFromNamespace('http://xml.apache.org/xml-soap');
6016
+ }
6017
+ $contents = '';
6018
+ foreach($value as $k => $v) {
6019
+ $this->debug("serializing map element: key $k, value $v");
6020
+ $contents .= '<item>';
6021
+ $contents .= $this->serialize_val($k,'key',false,false,false,false,$use);
6022
+ $contents .= $this->serialize_val($v,'value',false,false,false,false,$use);
6023
+ $contents .= '</item>';
6024
+ }
6025
+ if ($use == 'literal') {
6026
+ if ($forceType) {
6027
+ $xml = "<$name xsi:type=\"" . $tt_prefix . ":$uqType\">$contents</$name>";
6028
+ } else {
6029
+ $xml = "<$name>$contents</$name>";
6030
+ }
6031
+ } else {
6032
+ $xml = "<$name xsi:type=\"" . $tt_prefix . ":$uqType\"$encodingStyle>$contents</$name>";
6033
+ }
6034
+ $this->debug("in serializeType: returning: $xml");
6035
+ return $xml;
6036
+ }
6037
+ $this->debug('in serializeType: Apache SOAP type, but only support Map');
6038
+ }
6039
+ } else {
6040
+ // TODO: should the type be compared to types in XSD, and the namespace
6041
+ // set to XSD if the type matches?
6042
+ $this->debug("in serializeType: No namespace for type $type");
6043
+ $ns = '';
6044
+ $uqType = $type;
6045
+ }
6046
+ if(!$typeDef = $this->getTypeDef($uqType, $ns)){
6047
+ $this->setError("$type ($uqType) is not a supported type.");
6048
+ $this->debug("in serializeType: $type ($uqType) is not a supported type.");
6049
+ return false;
6050
+ } else {
6051
+ $this->debug("in serializeType: found typeDef");
6052
+ $this->appendDebug('typeDef=' . $this->varDump($typeDef));
6053
+ if (substr($uqType, -1) == '^') {
6054
+ $uqType = substr($uqType, 0, -1);
6055
+ }
6056
+ }
6057
+ if (!isset($typeDef['phpType'])) {
6058
+ $this->setError("$type ($uqType) has no phpType.");
6059
+ $this->debug("in serializeType: $type ($uqType) has no phpType.");
6060
+ return false;
6061
+ }
6062
+ $phpType = $typeDef['phpType'];
6063
+ $this->debug("in serializeType: uqType: $uqType, ns: $ns, phptype: $phpType, arrayType: " . (isset($typeDef['arrayType']) ? $typeDef['arrayType'] : '') );
6064
+ // if php type == struct, map value to the <all> element names
6065
+ if ($phpType == 'struct') {
6066
+ if (isset($typeDef['typeClass']) && $typeDef['typeClass'] == 'element') {
6067
+ $elementName = $uqType;
6068
+ if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) {
6069
+ $elementNS = " xmlns=\"$ns\"";
6070
+ } else {
6071
+ $elementNS = " xmlns=\"\"";
6072
+ }
6073
+ } else {
6074
+ $elementName = $name;
6075
+ if ($unqualified) {
6076
+ $elementNS = " xmlns=\"\"";
6077
+ } else {
6078
+ $elementNS = '';
6079
+ }
6080
+ }
6081
+ if (is_null($value)) {
6082
+ if ($use == 'literal') {
6083
+ // TODO: depends on minOccurs and nillable
6084
+ $xml = "<$elementName$elementNS/>";
6085
+ } else {
6086
+ $xml = "<$elementName$elementNS xsi:nil=\"true\" xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"/>";
6087
+ }
6088
+ $this->debug("in serializeType: returning: $xml");
6089
+ return $xml;
6090
+ }
6091
+ if (is_object($value)) {
6092
+ $value = get_object_vars($value);
6093
+ }
6094
+ if (is_array($value)) {
6095
+ $elementAttrs = $this->serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType);
6096
+ if ($use == 'literal') {
6097
+ if ($forceType) {
6098
+ $xml = "<$elementName$elementNS$elementAttrs xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">";
6099
+ } else {
6100
+ $xml = "<$elementName$elementNS$elementAttrs>";
6101
+ }
6102
+ } else {
6103
+ $xml = "<$elementName$elementNS$elementAttrs xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>";
6104
+ }
6105
+
6106
+ if (isset($typeDef['simpleContent']) && $typeDef['simpleContent'] == 'true') {
6107
+ if (isset($value['!'])) {
6108
+ $xml .= $value['!'];
6109
+ $this->debug("in serializeType: serialized simpleContent for type $type");
6110
+ } else {
6111
+ $this->debug("in serializeType: no simpleContent to serialize for type $type");
6112
+ }
6113
+ } else {
6114
+ // complexContent
6115
+ $xml .= $this->serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use, $encodingStyle);
6116
+ }
6117
+ $xml .= "</$elementName>";
6118
+ } else {
6119
+ $this->debug("in serializeType: phpType is struct, but value is not an array");
6120
+ $this->setError("phpType is struct, but value is not an array: see debug output for details");
6121
+ $xml = '';
6122
+ }
6123
+ } elseif ($phpType == 'array') {
6124
+ if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) {
6125
+ $elementNS = " xmlns=\"$ns\"";
6126
+ } else {
6127
+ if ($unqualified) {
6128
+ $elementNS = " xmlns=\"\"";
6129
+ } else {
6130
+ $elementNS = '';
6131
+ }
6132
+ }
6133
+ if (is_null($value)) {
6134
+ if ($use == 'literal') {
6135
+ // TODO: depends on minOccurs
6136
+ $xml = "<$name$elementNS/>";
6137
+ } else {
6138
+ $xml = "<$name$elementNS xsi:nil=\"true\" xsi:type=\"" .
6139
+ $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/') .
6140
+ ":Array\" " .
6141
+ $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/') .
6142
+ ':arrayType="' .
6143
+ $this->getPrefixFromNamespace($this->getPrefix($typeDef['arrayType'])) .
6144
+ ':' .
6145
+ $this->getLocalPart($typeDef['arrayType'])."[0]\"/>";
6146
+ }
6147
+ $this->debug("in serializeType: returning: $xml");
6148
+ return $xml;
6149
+ }
6150
+ if (isset($typeDef['multidimensional'])) {
6151
+ $nv = array();
6152
+ foreach($value as $v) {
6153
+ $cols = ',' . sizeof($v);
6154
+ $nv = array_merge($nv, $v);
6155
+ }
6156
+ $value = $nv;
6157
+ } else {
6158
+ $cols = '';
6159
+ }
6160
+ if (is_array($value) && sizeof($value) >= 1) {
6161
+ $rows = sizeof($value);
6162
+ $contents = '';
6163
+ foreach($value as $k => $v) {
6164
+ $this->debug("serializing array element: $k, $v of type: $typeDef[arrayType]");
6165
+ //if (strpos($typeDef['arrayType'], ':') ) {
6166
+ if (!in_array($typeDef['arrayType'],$this->typemap['http://www.w3.org/2001/XMLSchema'])) {
6167
+ $contents .= $this->serializeType('item', $typeDef['arrayType'], $v, $use);
6168
+ } else {
6169
+ $contents .= $this->serialize_val($v, 'item', $typeDef['arrayType'], null, $this->XMLSchemaVersion, false, $use);
6170
+ }
6171
+ }
6172
+ } else {
6173
+ $rows = 0;
6174
+ $contents = null;
6175
+ }
6176
+ // TODO: for now, an empty value will be serialized as a zero element
6177
+ // array. Revisit this when coding the handling of null/nil values.
6178
+ if ($use == 'literal') {
6179
+ $xml = "<$name$elementNS>"
6180
+ .$contents
6181
+ ."</$name>";
6182
+ } else {
6183
+ $xml = "<$name$elementNS xsi:type=\"".$this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/').':Array" '.
6184
+ $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/')
6185
+ .':arrayType="'
6186
+ .$this->getPrefixFromNamespace($this->getPrefix($typeDef['arrayType']))
6187
+ .":".$this->getLocalPart($typeDef['arrayType'])."[$rows$cols]\">"
6188
+ .$contents
6189
+ ."</$name>";
6190
+ }
6191
+ } elseif ($phpType == 'scalar') {
6192
+ if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) {
6193
+ $elementNS = " xmlns=\"$ns\"";
6194
+ } else {
6195
+ if ($unqualified) {
6196
+ $elementNS = " xmlns=\"\"";
6197
+ } else {
6198
+ $elementNS = '';
6199
+ }
6200
+ }
6201
+ if ($use == 'literal') {
6202
+ if ($forceType) {
6203
+ $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">$value</$name>";
6204
+ } else {
6205
+ $xml = "<$name$elementNS>$value</$name>";
6206
+ }
6207
+ } else {
6208
+ $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>$value</$name>";
6209
+ }
6210
+ }
6211
+ $this->debug("in serializeType: returning: $xml");
6212
+ return $xml;
6213
+ }
6214
+
6215
+ /**
6216
+ * serializes the attributes for a complexType
6217
+ *
6218
+ * @param array $typeDef our internal representation of an XML schema type (or element)
6219
+ * @param mixed $value a native PHP value (parameter value)
6220
+ * @param string $ns the namespace of the type
6221
+ * @param string $uqType the local part of the type
6222
+ * @return string value serialized as an XML string
6223
+ * @access private
6224
+ */
6225
+ function serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType) {
6226
+ $this->debug("serializeComplexTypeAttributes for XML Schema type $ns:$uqType");
6227
+ $xml = '';
6228
+ if (isset($typeDef['extensionBase'])) {
6229
+ $nsx = $this->getPrefix($typeDef['extensionBase']);
6230
+ $uqTypex = $this->getLocalPart($typeDef['extensionBase']);
6231
+ if ($this->getNamespaceFromPrefix($nsx)) {
6232
+ $nsx = $this->getNamespaceFromPrefix($nsx);
6233
+ }
6234
+ if ($typeDefx = $this->getTypeDef($uqTypex, $nsx)) {
6235
+ $this->debug("serialize attributes for extension base $nsx:$uqTypex");
6236
+ $xml .= $this->serializeComplexTypeAttributes($typeDefx, $value, $nsx, $uqTypex);
6237
+ } else {
6238
+ $this->debug("extension base $nsx:$uqTypex is not a supported type");
6239
+ }
6240
+ }
6241
+ if (isset($typeDef['attrs']) && is_array($typeDef['attrs'])) {
6242
+ $this->debug("serialize attributes for XML Schema type $ns:$uqType");
6243
+ if (is_array($value)) {
6244
+ $xvalue = $value;
6245
+ } elseif (is_object($value)) {
6246
+ $xvalue = get_object_vars($value);
6247
+ } else {
6248
+ $this->debug("value is neither an array nor an object for XML Schema type $ns:$uqType");
6249
+ $xvalue = array();
6250
+ }
6251
+ foreach ($typeDef['attrs'] as $aName => $attrs) {
6252
+ if (isset($xvalue['!' . $aName])) {
6253
+ $xname = '!' . $aName;
6254
+ $this->debug("value provided for attribute $aName with key $xname");
6255
+ } elseif (isset($xvalue[$aName])) {
6256
+ $xname = $aName;
6257
+ $this->debug("value provided for attribute $aName with key $xname");
6258
+ } elseif (isset($attrs['default'])) {
6259
+ $xname = '!' . $aName;
6260
+ $xvalue[$xname] = $attrs['default'];
6261
+ $this->debug('use default value of ' . $xvalue[$aName] . ' for attribute ' . $aName);
6262
+ } else {
6263
+ $xname = '';
6264
+ $this->debug("no value provided for attribute $aName");
6265
+ }
6266
+ if ($xname) {
6267
+ $xml .= " $aName=\"" . $this->expandEntities($xvalue[$xname]) . "\"";
6268
+ }
6269
+ }
6270
+ } else {
6271
+ $this->debug("no attributes to serialize for XML Schema type $ns:$uqType");
6272
+ }
6273
+ return $xml;
6274
+ }
6275
+
6276
+ /**
6277
+ * serializes the elements for a complexType
6278
+ *
6279
+ * @param array $typeDef our internal representation of an XML schema type (or element)
6280
+ * @param mixed $value a native PHP value (parameter value)
6281
+ * @param string $ns the namespace of the type
6282
+ * @param string $uqType the local part of the type
6283
+ * @param string $use use for part (encoded|literal)
6284
+ * @param string $encodingStyle SOAP encoding style for the value (if different than the enclosing style)
6285
+ * @return string value serialized as an XML string
6286
+ * @access private
6287
+ */
6288
+ function serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use='encoded', $encodingStyle=false) {
6289
+ $this->debug("in serializeComplexTypeElements for XML Schema type $ns:$uqType");
6290
+ $xml = '';
6291
+ if (isset($typeDef['extensionBase'])) {
6292
+ $nsx = $this->getPrefix($typeDef['extensionBase']);
6293
+ $uqTypex = $this->getLocalPart($typeDef['extensionBase']);
6294
+ if ($this->getNamespaceFromPrefix($nsx)) {
6295
+ $nsx = $this->getNamespaceFromPrefix($nsx);
6296
+ }
6297
+ if ($typeDefx = $this->getTypeDef($uqTypex, $nsx)) {
6298
+ $this->debug("serialize elements for extension base $nsx:$uqTypex");
6299
+ $xml .= $this->serializeComplexTypeElements($typeDefx, $value, $nsx, $uqTypex, $use, $encodingStyle);
6300
+ } else {
6301
+ $this->debug("extension base $nsx:$uqTypex is not a supported type");
6302
+ }
6303
+ }
6304
+ if (isset($typeDef['elements']) && is_array($typeDef['elements'])) {
6305
+ $this->debug("in serializeComplexTypeElements, serialize elements for XML Schema type $ns:$uqType");
6306
+ if (is_array($value)) {
6307
+ $xvalue = $value;
6308
+ } elseif (is_object($value)) {
6309
+ $xvalue = get_object_vars($value);
6310
+ } else {
6311
+ $this->debug("value is neither an array nor an object for XML Schema type $ns:$uqType");
6312
+ $xvalue = array();
6313
+ }
6314
+ // toggle whether all elements are present - ideally should validate against schema
6315
+ if (count($typeDef['elements']) != count($xvalue)){
6316
+ $optionals = true;
6317
+ }
6318
+ foreach ($typeDef['elements'] as $eName => $attrs) {
6319
+ if (!isset($xvalue[$eName])) {
6320
+ if (isset($attrs['default'])) {
6321
+ $xvalue[$eName] = $attrs['default'];
6322
+ $this->debug('use default value of ' . $xvalue[$eName] . ' for element ' . $eName);
6323
+ }
6324
+ }
6325
+ // if user took advantage of a minOccurs=0, then only serialize named parameters
6326
+ if (isset($optionals)
6327
+ && (!isset($xvalue[$eName]))
6328
+ && ( (!isset($attrs['nillable'])) || $attrs['nillable'] != 'true')
6329
+ ){
6330
+ if (isset($attrs['minOccurs']) && $attrs['minOccurs'] <> '0') {
6331
+ $this->debug("apparent error: no value provided for element $eName with minOccurs=" . $attrs['minOccurs']);
6332
+ }
6333
+ // do nothing
6334
+ $this->debug("no value provided for complexType element $eName and element is not nillable, so serialize nothing");
6335
+ } else {
6336
+ // get value
6337
+ if (isset($xvalue[$eName])) {
6338
+ $v = $xvalue[$eName];
6339
+ } else {
6340
+ $v = null;
6341
+ }
6342
+ if (isset($attrs['form'])) {
6343
+ $unqualified = ($attrs['form'] == 'unqualified');
6344
+ } else {
6345
+ $unqualified = false;
6346
+ }
6347
+ if (isset($attrs['maxOccurs']) && ($attrs['maxOccurs'] == 'unbounded' || $attrs['maxOccurs'] > 1) && isset($v) && is_array($v) && $this->isArraySimpleOrStruct($v) == 'arraySimple') {
6348
+ $vv = $v;
6349
+ foreach ($vv as $k => $v) {
6350
+ if (isset($attrs['type']) || isset($attrs['ref'])) {
6351
+ // serialize schema-defined type
6352
+ $xml .= $this->serializeType($eName, isset($attrs['type']) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified);
6353
+ } else {
6354
+ // serialize generic type (can this ever really happen?)
6355
+ $this->debug("calling serialize_val() for $v, $eName, false, false, false, false, $use");
6356
+ $xml .= $this->serialize_val($v, $eName, false, false, false, false, $use);
6357
+ }
6358
+ }
6359
+ } else {
6360
+ if (is_null($v) && isset($attrs['minOccurs']) && $attrs['minOccurs'] == '0') {
6361
+ // do nothing
6362
+ } elseif (is_null($v) && isset($attrs['nillable']) && $attrs['nillable'] == 'true') {
6363
+ // TODO: serialize a nil correctly, but for now serialize schema-defined type
6364
+ $xml .= $this->serializeType($eName, isset($attrs['type']) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified);
6365
+ } elseif (isset($attrs['type']) || isset($attrs['ref'])) {
6366
+ // serialize schema-defined type
6367
+ $xml .= $this->serializeType($eName, isset($attrs['type']) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified);
6368
+ } else {
6369
+ // serialize generic type (can this ever really happen?)
6370
+ $this->debug("calling serialize_val() for $v, $eName, false, false, false, false, $use");
6371
+ $xml .= $this->serialize_val($v, $eName, false, false, false, false, $use);
6372
+ }
6373
+ }
6374
+ }
6375
+ }
6376
+ } else {
6377
+ $this->debug("no elements to serialize for XML Schema type $ns:$uqType");
6378
+ }
6379
+ return $xml;
6380
+ }
6381
+
6382
+ /**
6383
+ * adds an XML Schema complex type to the WSDL types
6384
+ *
6385
+ * @param string $name
6386
+ * @param string $typeClass (complexType|simpleType|attribute)
6387
+ * @param string $phpType currently supported are array and struct (php assoc array)
6388
+ * @param string $compositor (all|sequence|choice)
6389
+ * @param string $restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
6390
+ * @param array $elements e.g. array ( name => array(name=>'',type=>'') )
6391
+ * @param array $attrs e.g. array(array('ref'=>'SOAP-ENC:arrayType','wsdl:arrayType'=>'xsd:string[]'))
6392
+ * @param string $arrayType as namespace:name (xsd:string)
6393
+ * @see nusoap_xmlschema
6394
+ * @access public
6395
+ */
6396
+ function addComplexType($name,$typeClass='complexType',$phpType='array',$compositor='',$restrictionBase='',$elements=array(),$attrs=array(),$arrayType='') {
6397
+ if (count($elements) > 0) {
6398
+ $eElements = array();
6399
+ foreach($elements as $n => $e){
6400
+ // expand each element
6401
+ $ee = array();
6402
+ foreach ($e as $k => $v) {
6403
+ $k = strpos($k,':') ? $this->expandQname($k) : $k;
6404
+ $v = strpos($v,':') ? $this->expandQname($v) : $v;
6405
+ $ee[$k] = $v;
6406
+ }
6407
+ $eElements[$n] = $ee;
6408
+ }
6409
+ $elements = $eElements;
6410
+ }
6411
+
6412
+ if (count($attrs) > 0) {
6413
+ foreach($attrs as $n => $a){
6414
+ // expand each attribute
6415
+ foreach ($a as $k => $v) {
6416
+ $k = strpos($k,':') ? $this->expandQname($k) : $k;
6417
+ $v = strpos($v,':') ? $this->expandQname($v) : $v;
6418
+ $aa[$k] = $v;
6419
+ }
6420
+ $eAttrs[$n] = $aa;
6421
+ }
6422
+ $attrs = $eAttrs;
6423
+ }
6424
+
6425
+ $restrictionBase = strpos($restrictionBase,':') ? $this->expandQname($restrictionBase) : $restrictionBase;
6426
+ $arrayType = strpos($arrayType,':') ? $this->expandQname($arrayType) : $arrayType;
6427
+
6428
+ $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns'];
6429
+ $this->schemas[$typens][0]->addComplexType($name,$typeClass,$phpType,$compositor,$restrictionBase,$elements,$attrs,$arrayType);
6430
+ }
6431
+
6432
+ /**
6433
+ * adds an XML Schema simple type to the WSDL types
6434
+ *
6435
+ * @param string $name
6436
+ * @param string $restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
6437
+ * @param string $typeClass (should always be simpleType)
6438
+ * @param string $phpType (should always be scalar)
6439
+ * @param array $enumeration array of values
6440
+ * @see nusoap_xmlschema
6441
+ * @access public
6442
+ */
6443
+ function addSimpleType($name, $restrictionBase='', $typeClass='simpleType', $phpType='scalar', $enumeration=array()) {
6444
+ $restrictionBase = strpos($restrictionBase,':') ? $this->expandQname($restrictionBase) : $restrictionBase;
6445
+
6446
+ $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns'];
6447
+ $this->schemas[$typens][0]->addSimpleType($name, $restrictionBase, $typeClass, $phpType, $enumeration);
6448
+ }
6449
+
6450
+ /**
6451
+ * adds an element to the WSDL types
6452
+ *
6453
+ * @param array $attrs attributes that must include name and type
6454
+ * @see nusoap_xmlschema
6455
+ * @access public
6456
+ */
6457
+ function addElement($attrs) {
6458
+ $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns'];
6459
+ $this->schemas[$typens][0]->addElement($attrs);
6460
+ }
6461
+
6462
+ /**
6463
+ * register an operation with the server
6464
+ *
6465
+ * @param string $name operation (method) name
6466
+ * @param array $in assoc array of input values: key = param name, value = param type
6467
+ * @param array $out assoc array of output values: key = param name, value = param type
6468
+ * @param string $namespace optional The namespace for the operation
6469
+ * @param string $soapaction optional The soapaction for the operation
6470
+ * @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
6471
+ * @param string $use (encoded|literal) optional The use for the parameters (cannot mix right now)
6472
+ * @param string $documentation optional The description to include in the WSDL
6473
+ * @param string $encodingStyle optional (usually 'http://schemas.xmlsoap.org/soap/encoding/' for encoded)
6474
+ * @access public
6475
+ */
6476
+ function addOperation($name, $in = false, $out = false, $namespace = false, $soapaction = false, $style = 'rpc', $use = 'encoded', $documentation = '', $encodingStyle = ''){
6477
+ if ($use == 'encoded' && $encodingStyle == '') {
6478
+ $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
6479
+ }
6480
+
6481
+ if ($style == 'document') {
6482
+ $elements = array();
6483
+ foreach ($in as $n => $t) {
6484
+ $elements[$n] = array('name' => $n, 'type' => $t, 'form' => 'unqualified');
6485
+ }
6486
+ $this->addComplexType($name . 'RequestType', 'complexType', 'struct', 'all', '', $elements);
6487
+ $this->addElement(array('name' => $name, 'type' => $name . 'RequestType'));
6488
+ $in = array('parameters' => 'tns:' . $name . '^');
6489
+
6490
+ $elements = array();
6491
+ foreach ($out as $n => $t) {
6492
+ $elements[$n] = array('name' => $n, 'type' => $t, 'form' => 'unqualified');
6493
+ }
6494
+ $this->addComplexType($name . 'ResponseType', 'complexType', 'struct', 'all', '', $elements);
6495
+ $this->addElement(array('name' => $name . 'Response', 'type' => $name . 'ResponseType', 'form' => 'qualified'));
6496
+ $out = array('parameters' => 'tns:' . $name . 'Response' . '^');
6497
+ }
6498
+
6499
+ // get binding
6500
+ $this->bindings[ $this->serviceName . 'Binding' ]['operations'][$name] =
6501
+ array(
6502
+ 'name' => $name,
6503
+ 'binding' => $this->serviceName . 'Binding',
6504
+ 'endpoint' => $this->endpoint,
6505
+ 'soapAction' => $soapaction,
6506
+ 'style' => $style,
6507
+ 'input' => array(
6508
+ 'use' => $use,
6509
+ 'namespace' => $namespace,
6510
+ 'encodingStyle' => $encodingStyle,
6511
+ 'message' => $name . 'Request',
6512
+ 'parts' => $in),
6513
+ 'output' => array(
6514
+ 'use' => $use,
6515
+ 'namespace' => $namespace,
6516
+ 'encodingStyle' => $encodingStyle,
6517
+ 'message' => $name . 'Response',
6518
+ 'parts' => $out),
6519
+ 'namespace' => $namespace,
6520
+ 'transport' => 'http://schemas.xmlsoap.org/soap/http',
6521
+ 'documentation' => $documentation);
6522
+ // add portTypes
6523
+ // add messages
6524
+ if($in)
6525
+ {
6526
+ foreach($in as $pName => $pType)
6527
+ {
6528
+ if(strpos($pType,':')) {
6529
+ $pType = $this->getNamespaceFromPrefix($this->getPrefix($pType)).":".$this->getLocalPart($pType);
6530
+ }
6531
+ $this->messages[$name.'Request'][$pName] = $pType;
6532
+ }
6533
+ } else {
6534
+ $this->messages[$name.'Request']= '0';
6535
+ }
6536
+ if($out)
6537
+ {
6538
+ foreach($out as $pName => $pType)
6539
+ {
6540
+ if(strpos($pType,':')) {
6541
+ $pType = $this->getNamespaceFromPrefix($this->getPrefix($pType)).":".$this->getLocalPart($pType);
6542
+ }
6543
+ $this->messages[$name.'Response'][$pName] = $pType;
6544
+ }
6545
+ } else {
6546
+ $this->messages[$name.'Response']= '0';
6547
+ }
6548
+ return true;
6549
+ }
6550
+ }
6551
+ ?><?php
6552
+
6553
+
6554
+
6555
+ /**
6556
+ *
6557
+ * nusoap_parser class parses SOAP XML messages into native PHP values
6558
+ *
6559
+ * @author Dietrich Ayala <dietrich@ganx4.com>
6560
+ * @author Scott Nichol <snichol@users.sourceforge.net>
6561
+ * @version $Id: fsource_nusoap__nusoap.php.html,v 1.2 2010/04/26 20:25:21 snichol Exp $
6562
+ * @access public
6563
+ */
6564
+ class nusoap_parser extends nusoap_base {
6565
+
6566
+ var $xml = '';
6567
+ var $xml_encoding = '';
6568
+ var $method = '';
6569
+ var $root_struct = '';
6570
+ var $root_struct_name = '';
6571
+ var $root_struct_namespace = '';
6572
+ var $root_header = '';
6573
+ var $document = ''; // incoming SOAP body (text)
6574
+ // determines where in the message we are (envelope,header,body,method)
6575
+
6576
+ var $status = '';
6577
+ var $position = 0;
6578
+ var $depth = 0;
6579
+ var $default_namespace = '';
6580
+ var $namespaces = array();
6581
+ var $message = array();
6582
+ var $parent = '';
6583
+ var $fault = false;
6584
+ var $fault_code = '';
6585
+ var $fault_str = '';
6586
+ var $fault_detail = '';
6587
+ var $depth_array = array();
6588
+ var $debug_flag = true;
6589
+ var $soapresponse = NULL; // parsed SOAP Body
6590
+
6591
+ var $soapheader = NULL; // parsed SOAP Header
6592
+
6593
+ var $responseHeaders = ''; // incoming SOAP headers (text)
6594
+
6595
+ var $body_position = 0;
6596
+ // for multiref parsing:
6597
+ // array of id => pos
6598
+
6599
+ var $ids = array();
6600
+ // array of id => hrefs => pos
6601
+
6602
+ var $multirefs = array();
6603
+ // toggle for auto-decoding element content
6604
+
6605
+ var $decode_utf8 = true;
6606
+
6607
+ /**
6608
+ * constructor that actually does the parsing
6609
+ *
6610
+ * @param string $xml SOAP message
6611
+ * @param string $encoding character encoding scheme of message
6612
+ * @param string $method method for which XML is parsed (unused?)
6613
+ * @param string $decode_utf8 whether to decode UTF-8 to ISO-8859-1
6614
+ * @access public
6615
+ */
6616
+ function nusoap_parser($xml,$encoding='UTF-8',$method='',$decode_utf8=true){
6617
+ parent::nusoap_base();
6618
+ $this->xml = $xml;
6619
+ $this->xml_encoding = $encoding;
6620
+ $this->method = $method;
6621
+ $this->decode_utf8 = $decode_utf8;
6622
+
6623
+ // Check whether content has been read.
6624
+ if(!empty($xml)){
6625
+ // Check XML encoding
6626
+ $pos_xml = strpos($xml, '<?xml');
6627
+ if ($pos_xml !== FALSE) {
6628
+ $xml_decl = substr($xml, $pos_xml, strpos($xml, '?>', $pos_xml + 2) - $pos_xml + 1);
6629
+ if (preg_match("/encoding=[\"']([^\"']*)[\"']/", $xml_decl, $res)) {
6630
+ $xml_encoding = $res[1];
6631
+ if (strtoupper($xml_encoding) != $encoding) {
6632
+ $err = "Charset from HTTP Content-Type '" . $encoding . "' does not match encoding from XML declaration '" . $xml_encoding . "'";
6633
+ $this->debug($err);
6634
+ if ($encoding != 'ISO-8859-1' || strtoupper($xml_encoding) != 'UTF-8') {
6635
+ $this->setError($err);
6636
+ return;
6637
+ }
6638
+ // when HTTP says ISO-8859-1 (the default) and XML says UTF-8 (the typical), assume the other endpoint is just sloppy and proceed
6639
+ } else {
6640
+ $this->debug('Charset from HTTP Content-Type matches encoding from XML declaration');
6641
+ }
6642
+ } else {
6643
+ $this->debug('No encoding specified in XML declaration');
6644
+ }
6645
+ } else {
6646
+ $this->debug('No XML declaration');
6647
+ }
6648
+ $this->debug('Entering nusoap_parser(), length='.strlen($xml).', encoding='.$encoding);
6649
+ // Create an XML parser - why not xml_parser_create_ns?
6650
+ $this->parser = xml_parser_create($this->xml_encoding);
6651
+ // Set the options for parsing the XML data.
6652
+ //xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
6653
+ xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
6654
+ xml_parser_set_option($this->parser, XML_OPTION_TARGET_ENCODING, $this->xml_encoding);
6655
+ // Set the object for the parser.
6656
+ xml_set_object($this->parser, $this);
6657
+ // Set the element handlers for the parser.
6658
+ xml_set_element_handler($this->parser, 'start_element','end_element');
6659
+ xml_set_character_data_handler($this->parser,'character_data');
6660
+
6661
+ // Parse the XML file.
6662
+ if(!xml_parse($this->parser,$xml,true)){
6663
+ // Display an error message.
6664
+ $err = sprintf('XML error parsing SOAP payload on line %d: %s',
6665
+ xml_get_current_line_number($this->parser),
6666
+ xml_error_string(xml_get_error_code($this->parser)));
6667
+ $this->debug($err);
6668
+ $this->debug("XML payload:\n" . $xml);
6669
+ $this->setError($err);
6670
+ } else {
6671
+ $this->debug('in nusoap_parser ctor, message:');
6672
+ $this->appendDebug($this->varDump($this->message));
6673
+ $this->debug('parsed successfully, found root struct: '.$this->root_struct.' of name '.$this->root_struct_name);
6674
+ // get final value
6675
+ $this->soapresponse = $this->message[$this->root_struct]['result'];
6676
+ // get header value
6677
+ if($this->root_header != '' && isset($this->message[$this->root_header]['result'])){
6678
+ $this->soapheader = $this->message[$this->root_header]['result'];
6679
+ }
6680
+ // resolve hrefs/ids
6681
+ if(sizeof($this->multirefs) > 0){
6682
+ foreach($this->multirefs as $id => $hrefs){
6683
+ $this->debug('resolving multirefs for id: '.$id);
6684
+ $idVal = $this->buildVal($this->ids[$id]);
6685
+ if (is_array($idVal) && isset($idVal['!id'])) {
6686
+ unset($idVal['!id']);
6687
+ }
6688
+ foreach($hrefs as $refPos => $ref){
6689
+ $this->debug('resolving href at pos '.$refPos);
6690
+ $this->multirefs[$id][$refPos] = $idVal;
6691
+ }
6692
+ }
6693
+ }
6694
+ }
6695
+ xml_parser_free($this->parser);
6696
+ } else {
6697
+ $this->debug('xml was empty, didn\'t parse!');
6698
+ $this->setError('xml was empty, didn\'t parse!');
6699
+ }
6700
+ }
6701
+
6702
+ /**
6703
+ * start-element handler
6704
+ *
6705
+ * @param resource $parser XML parser object
6706
+ * @param string $name element name
6707
+ * @param array $attrs associative array of attributes
6708
+ * @access private
6709
+ */
6710
+ function start_element($parser, $name, $attrs) {
6711
+ // position in a total number of elements, starting from 0
6712
+ // update class level pos
6713
+ $pos = $this->position++;
6714
+ // and set mine
6715
+ $this->message[$pos] = array('pos' => $pos,'children'=>'','cdata'=>'');
6716
+ // depth = how many levels removed from root?
6717
+ // set mine as current global depth and increment global depth value
6718
+ $this->message[$pos]['depth'] = $this->depth++;
6719
+
6720
+ // else add self as child to whoever the current parent is
6721
+ if($pos != 0){
6722
+ $this->message[$this->parent]['children'] .= '|'.$pos;
6723
+ }
6724
+ // set my parent
6725
+ $this->message[$pos]['parent'] = $this->parent;
6726
+ // set self as current parent
6727
+ $this->parent = $pos;
6728
+ // set self as current value for this depth
6729
+ $this->depth_array[$this->depth] = $pos;
6730
+ // get element prefix
6731
+ if(strpos($name,':')){
6732
+ // get ns prefix
6733
+ $prefix = substr($name,0,strpos($name,':'));
6734
+ // get unqualified name
6735
+ $name = substr(strstr($name,':'),1);
6736
+ }
6737
+ // set status
6738
+ if ($name == 'Envelope' && $this->status == '') {
6739
+ $this->status = 'envelope';
6740
+ } elseif ($name == 'Header' && $this->status == 'envelope') {
6741
+ $this->root_header = $pos;
6742
+ $this->status = 'header';
6743
+ } elseif ($name == 'Body' && $this->status == 'envelope'){
6744
+ $this->status = 'body';
6745
+ $this->body_position = $pos;
6746
+ // set method
6747
+ } elseif($this->status == 'body' && $pos == ($this->body_position+1)) {
6748
+ $this->status = 'method';
6749
+ $this->root_struct_name = $name;
6750
+ $this->root_struct = $pos;
6751
+ $this->message[$pos]['type'] = 'struct';
6752
+ $this->debug("found root struct $this->root_struct_name, pos $this->root_struct");
6753
+ }
6754
+ // set my status
6755
+ $this->message[$pos]['status'] = $this->status;
6756
+ // set name
6757
+ $this->message[$pos]['name'] = htmlspecialchars($name);
6758
+ // set attrs
6759
+ $this->message[$pos]['attrs'] = $attrs;
6760
+
6761
+ // loop through atts, logging ns and type declarations
6762
+ $attstr = '';
6763
+ foreach($attrs as $key => $value){
6764
+ $key_prefix = $this->getPrefix($key);
6765
+ $key_localpart = $this->getLocalPart($key);
6766
+ // if ns declarations, add to class level array of valid namespaces
6767
+ if($key_prefix == 'xmlns'){
6768
+ if(preg_match('/^http:\/\/www.w3.org\/[0-9]{4}\/XMLSchema$/',$value)){
6769
+ $this->XMLSchemaVersion = $value;
6770
+ $this->namespaces['xsd'] = $this->XMLSchemaVersion;
6771
+ $this->namespaces['xsi'] = $this->XMLSchemaVersion.'-instance';
6772
+ }
6773
+ $this->namespaces[$key_localpart] = $value;
6774
+ // set method namespace
6775
+ if($name == $this->root_struct_name){
6776
+ $this->methodNamespace = $value;
6777
+ }
6778
+ // if it's a type declaration, set type
6779
+ } elseif($key_localpart == 'type'){
6780
+ if (isset($this->message[$pos]['type']) && $this->message[$pos]['type'] == 'array') {
6781
+ // do nothing: already processed arrayType
6782
+ } else {
6783
+ $value_prefix = $this->getPrefix($value);
6784
+ $value_localpart = $this->getLocalPart($value);
6785
+ $this->message[$pos]['type'] = $value_localpart;
6786
+ $this->message[$pos]['typePrefix'] = $value_prefix;
6787
+ if(isset($this->namespaces[$value_prefix])){
6788
+ $this->message[$pos]['type_namespace'] = $this->namespaces[$value_prefix];
6789
+ } else if(isset($attrs['xmlns:'.$value_prefix])) {
6790
+ $this->message[$pos]['type_namespace'] = $attrs['xmlns:'.$value_prefix];
6791
+ }
6792
+ // should do something here with the namespace of specified type?
6793
+ }
6794
+ } elseif($key_localpart == 'arrayType'){
6795
+ $this->message[$pos]['type'] = 'array';
6796
+ /* do arrayType ereg here
6797
+ [1] arrayTypeValue ::= atype asize
6798
+ [2] atype ::= QName rank*
6799
+ [3] rank ::= '[' (',')* ']'
6800
+ [4] asize ::= '[' length~ ']'
6801
+ [5] length ::= nextDimension* Digit+
6802
+ [6] nextDimension ::= Digit+ ','
6803
+ */
6804
+ $expr = '/([A-Za-z0-9_]+):([A-Za-z]+[A-Za-z0-9_]+)\[([0-9]+),?([0-9]*)\]/';
6805
+ if(preg_match($expr,$value,$regs)){
6806
+ $this->message[$pos]['typePrefix'] = $regs[1];
6807
+ $this->message[$pos]['arrayTypePrefix'] = $regs[1];
6808
+ if (isset($this->namespaces[$regs[1]])) {
6809
+ $this->message[$pos]['arrayTypeNamespace'] = $this->namespaces[$regs[1]];
6810
+ } else if (isset($attrs['xmlns:'.$regs[1]])) {
6811
+ $this->message[$pos]['arrayTypeNamespace'] = $attrs['xmlns:'.$regs[1]];
6812
+ }
6813
+ $this->message[$pos]['arrayType'] = $regs[2];
6814
+ $this->message[$pos]['arraySize'] = $regs[3];
6815
+ $this->message[$pos]['arrayCols'] = $regs[4];
6816
+ }
6817
+ // specifies nil value (or not)
6818
+ } elseif ($key_localpart == 'nil'){
6819
+ $this->message[$pos]['nil'] = ($value == 'true' || $value == '1');
6820
+ // some other attribute
6821
+ } elseif ($key != 'href' && $key != 'xmlns' && $key_localpart != 'encodingStyle' && $key_localpart != 'root') {
6822
+ $this->message[$pos]['xattrs']['!' . $key] = $value;
6823
+ }
6824
+
6825
+ if ($key == 'xmlns') {
6826
+ $this->default_namespace = $value;
6827
+ }
6828
+ // log id
6829
+ if($key == 'id'){
6830
+ $this->ids[$value] = $pos;
6831
+ }
6832
+ // root
6833
+ if($key_localpart == 'root' && $value == 1){
6834
+ $this->status = 'method';
6835
+ $this->root_struct_name = $name;
6836
+ $this->root_struct = $pos;
6837
+ $this->debug("found root struct $this->root_struct_name, pos $pos");
6838
+ }
6839
+ // for doclit
6840
+ $attstr .= " $key=\"$value\"";
6841
+ }
6842
+ // get namespace - must be done after namespace atts are processed
6843
+ if(isset($prefix)){
6844
+ $this->message[$pos]['namespace'] = $this->namespaces[$prefix];
6845
+ $this->default_namespace = $this->namespaces[$prefix];
6846
+ } else {
6847
+ $this->message[$pos]['namespace'] = $this->default_namespace;
6848
+ }
6849
+ if($this->status == 'header'){
6850
+ if ($this->root_header != $pos) {
6851
+ $this->responseHeaders .= "<" . (isset($prefix) ? $prefix . ':' : '') . "$name$attstr>";
6852
+ }
6853
+ } elseif($this->root_struct_name != ''){
6854
+ $this->document .= "<" . (isset($prefix) ? $prefix . ':' : '') . "$name$attstr>";
6855
+ }
6856
+ }
6857
+
6858
+ /**
6859
+ * end-element handler
6860
+ *
6861
+ * @param resource $parser XML parser object
6862
+ * @param string $name element name
6863
+ * @access private
6864
+ */
6865
+ function end_element($parser, $name) {
6866
+ // position of current element is equal to the last value left in depth_array for my depth
6867
+ $pos = $this->depth_array[$this->depth--];
6868
+
6869
+ // get element prefix
6870
+ if(strpos($name,':')){
6871
+ // get ns prefix
6872
+ $prefix = substr($name,0,strpos($name,':'));
6873
+ // get unqualified name
6874
+ $name = substr(strstr($name,':'),1);
6875
+ }
6876
+
6877
+ // build to native type
6878
+ if(isset($this->body_position) && $pos > $this->body_position){
6879
+ // deal w/ multirefs
6880
+ if(isset($this->message[$pos]['attrs']['href'])){
6881
+ // get id
6882
+ $id = substr($this->message[$pos]['attrs']['href'],1);
6883
+ // add placeholder to href array
6884
+ $this->multirefs[$id][$pos] = 'placeholder';
6885
+ // add set a reference to it as the result value
6886
+ $this->message[$pos]['result'] =& $this->multirefs[$id][$pos];
6887
+ // build complexType values
6888
+ } elseif($this->message[$pos]['children'] != ''){
6889
+ // if result has already been generated (struct/array)
6890
+ if(!isset($this->message[$pos]['result'])){
6891
+ $this->message[$pos]['result'] = $this->buildVal($pos);
6892
+ }
6893
+ // build complexType values of attributes and possibly simpleContent
6894
+ } elseif (isset($this->message[$pos]['xattrs'])) {
6895
+ if (isset($this->message[$pos]['nil']) && $this->message[$pos]['nil']) {
6896
+ $this->message[$pos]['xattrs']['!'] = null;
6897
+ } elseif (isset($this->message[$pos]['cdata']) && trim($this->message[$pos]['cdata']) != '') {
6898
+ if (isset($this->message[$pos]['type'])) {
6899
+ $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'] : '');
6900
+ } else {
6901
+ $parent = $this->message[$pos]['parent'];
6902
+ if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
6903
+ $this->message[$pos]['xattrs']['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
6904
+ } else {
6905
+ $this->message[$pos]['xattrs']['!'] = $this->message[$pos]['cdata'];
6906
+ }
6907
+ }
6908
+ }
6909
+ $this->message[$pos]['result'] = $this->message[$pos]['xattrs'];
6910
+ // set value of simpleType (or nil complexType)
6911
+ } else {
6912
+ //$this->debug('adding data for scalar value '.$this->message[$pos]['name'].' of value '.$this->message[$pos]['cdata']);
6913
+ if (isset($this->message[$pos]['nil']) && $this->message[$pos]['nil']) {
6914
+ $this->message[$pos]['xattrs']['!'] = null;
6915
+ } elseif (isset($this->message[$pos]['type'])) {
6916
+ $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'] : '');
6917
+ } else {
6918
+ $parent = $this->message[$pos]['parent'];
6919
+ if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
6920
+ $this->message[$pos]['result'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
6921
+ } else {
6922
+ $this->message[$pos]['result'] = $this->message[$pos]['cdata'];
6923
+ }
6924
+ }
6925
+
6926
+ /* add value to parent's result, if parent is struct/array
6927
+ $parent = $this->message[$pos]['parent'];
6928
+ if($this->message[$parent]['type'] != 'map'){
6929
+ if(strtolower($this->message[$parent]['type']) == 'array'){
6930
+ $this->message[$parent]['result'][] = $this->message[$pos]['result'];
6931
+ } else {
6932
+ $this->message[$parent]['result'][$this->message[$pos]['name']] = $this->message[$pos]['result'];
6933
+ }
6934
+ }
6935
+ */
6936
+ }
6937
+ }
6938
+
6939
+ // for doclit
6940
+ if($this->status == 'header'){
6941
+ if ($this->root_header != $pos) {
6942
+ $this->responseHeaders .= "</" . (isset($prefix) ? $prefix . ':' : '') . "$name>";
6943
+ }
6944
+ } elseif($pos >= $this->root_struct){
6945
+ $this->document .= "</" . (isset($prefix) ? $prefix . ':' : '') . "$name>";
6946
+ }
6947
+ // switch status
6948
+ if ($pos == $this->root_struct){
6949
+ $this->status = 'body';
6950
+ $this->root_struct_namespace = $this->message[$pos]['namespace'];
6951
+ } elseif ($pos == $this->root_header) {
6952
+ $this->status = 'envelope';
6953
+ } elseif ($name == 'Body' && $this->status == 'body') {
6954
+ $this->status = 'envelope';
6955
+ } elseif ($name == 'Header' && $this->status == 'header') { // will never happen
6956
+ $this->status = 'envelope';
6957
+ } elseif ($name == 'Envelope' && $this->status == 'envelope') {
6958
+ $this->status = '';
6959
+ }
6960
+ // set parent back to my parent
6961
+ $this->parent = $this->message[$pos]['parent'];
6962
+ }
6963
+
6964
+ /**
6965
+ * element content handler
6966
+ *
6967
+ * @param resource $parser XML parser object
6968
+ * @param string $data element content
6969
+ * @access private
6970
+ */
6971
+ function character_data($parser, $data){
6972
+ $pos = $this->depth_array[$this->depth];
6973
+ if ($this->xml_encoding=='UTF-8'){
6974
+ // TODO: add an option to disable this for folks who want
6975
+ // raw UTF-8 that, e.g., might not map to iso-8859-1
6976
+ // TODO: this can also be handled with xml_parser_set_option($this->parser, XML_OPTION_TARGET_ENCODING, "ISO-8859-1");
6977
+ if($this->decode_utf8){
6978
+ $data = utf8_decode($data);
6979
+ }
6980
+ }
6981
+ $this->message[$pos]['cdata'] .= $data;
6982
+ // for doclit
6983
+ if($this->status == 'header'){
6984
+ $this->responseHeaders .= $data;
6985
+ } else {
6986
+ $this->document .= $data;
6987
+ }
6988
+ }
6989
+
6990
+ /**
6991
+ * get the parsed message (SOAP Body)
6992
+ *
6993
+ * @return mixed
6994
+ * @access public
6995
+ * @deprecated use get_soapbody instead
6996
+ */
6997
+ function get_response(){
6998
+ return $this->soapresponse;
6999
+ }
7000
+
7001
+ /**
7002
+ * get the parsed SOAP Body (NULL if there was none)
7003
+ *
7004
+ * @return mixed
7005
+ * @access public
7006
+ */
7007
+ function get_soapbody(){
7008
+ return $this->soapresponse;
7009
+ }
7010
+
7011
+ /**
7012
+ * get the parsed SOAP Header (NULL if there was none)
7013
+ *
7014
+ * @return mixed
7015
+ * @access public
7016
+ */
7017
+ function get_soapheader(){
7018
+ return $this->soapheader;
7019
+ }
7020
+
7021
+ /**
7022
+ * get the unparsed SOAP Header
7023
+ *
7024
+ * @return string XML or empty if no Header
7025
+ * @access public
7026
+ */
7027
+ function getHeaders(){
7028
+ return $this->responseHeaders;
7029
+ }
7030
+
7031
+ /**
7032
+ * decodes simple types into PHP variables
7033
+ *
7034
+ * @param string $value value to decode
7035
+ * @param string $type XML type to decode
7036
+ * @param string $typens XML type namespace to decode
7037
+ * @return mixed PHP value
7038
+ * @access private
7039
+ */
7040
+ function decodeSimple($value, $type, $typens) {
7041
+ // TODO: use the namespace!
7042
+ if ((!isset($type)) || $type == 'string' || $type == 'long' || $type == 'unsignedLong') {
7043
+ return (string) $value;
7044
+ }
7045
+ if ($type == 'int' || $type == 'integer' || $type == 'short' || $type == 'byte') {
7046
+ return (int) $value;
7047
+ }
7048
+ if ($type == 'float' || $type == 'double' || $type == 'decimal') {
7049
+ return (double) $value;
7050
+ }
7051
+ if ($type == 'boolean') {
7052
+ if (strtolower($value) == 'false' || strtolower($value) == 'f') {
7053
+ return false;
7054
+ }
7055
+ return (boolean) $value;
7056
+ }
7057
+ if ($type == 'base64' || $type == 'base64Binary') {
7058
+ $this->debug('Decode base64 value');
7059
+ return base64_decode($value);
7060
+ }
7061
+ // obscure numeric types
7062
+ if ($type == 'nonPositiveInteger' || $type == 'negativeInteger'
7063
+ || $type == 'nonNegativeInteger' || $type == 'positiveInteger'
7064
+ || $type == 'unsignedInt'
7065
+ || $type == 'unsignedShort' || $type == 'unsignedByte') {
7066
+ return (int) $value;
7067
+ }
7068
+ // bogus: parser treats array with no elements as a simple type
7069
+ if ($type == 'array') {
7070
+ return array();
7071
+ }
7072
+ // everything else
7073
+ return (string) $value;
7074
+ }
7075
+
7076
+ /**
7077
+ * builds response structures for compound values (arrays/structs)
7078
+ * and scalars
7079
+ *
7080
+ * @param integer $pos position in node tree
7081
+ * @return mixed PHP value
7082
+ * @access private
7083
+ */
7084
+ function buildVal($pos){
7085
+ if(!isset($this->message[$pos]['type'])){
7086
+ $this->message[$pos]['type'] = '';
7087
+ }
7088
+ $this->debug('in buildVal() for '.$this->message[$pos]['name']."(pos $pos) of type ".$this->message[$pos]['type']);
7089
+ // if there are children...
7090
+ if($this->message[$pos]['children'] != ''){
7091
+ $this->debug('in buildVal, there are children');
7092
+ $children = explode('|',$this->message[$pos]['children']);
7093
+ array_shift($children); // knock off empty
7094
+ // md array
7095
+ if(isset($this->message[$pos]['arrayCols']) && $this->message[$pos]['arrayCols'] != ''){
7096
+ $r=0; // rowcount
7097
+ $c=0; // colcount
7098
+ foreach($children as $child_pos){
7099
+ $this->debug("in buildVal, got an MD array element: $r, $c");
7100
+ $params[$r][] = $this->message[$child_pos]['result'];
7101
+ $c++;
7102
+ if($c == $this->message[$pos]['arrayCols']){
7103
+ $c = 0;
7104
+ $r++;
7105
+ }
7106
+ }
7107
+ // array
7108
+ } elseif($this->message[$pos]['type'] == 'array' || $this->message[$pos]['type'] == 'Array'){
7109
+ $this->debug('in buildVal, adding array '.$this->message[$pos]['name']);
7110
+ foreach($children as $child_pos){
7111
+ $params[] = &$this->message[$child_pos]['result'];
7112
+ }
7113
+ // apache Map type: java hashtable
7114
+ } elseif($this->message[$pos]['type'] == 'Map' && $this->message[$pos]['type_namespace'] == 'http://xml.apache.org/xml-soap'){
7115
+ $this->debug('in buildVal, Java Map '.$this->message[$pos]['name']);
7116
+ foreach($children as $child_pos){
7117
+ $kv = explode("|",$this->message[$child_pos]['children']);
7118
+ $params[$this->message[$kv[1]]['result']] = &$this->message[$kv[2]]['result'];
7119
+ }
7120
+ // generic compound type
7121
+ //} elseif($this->message[$pos]['type'] == 'SOAPStruct' || $this->message[$pos]['type'] == 'struct') {
7122
+ } else {
7123
+ // Apache Vector type: treat as an array
7124
+ $this->debug('in buildVal, adding Java Vector or generic compound type '.$this->message[$pos]['name']);
7125
+ if ($this->message[$pos]['type'] == 'Vector' && $this->message[$pos]['type_namespace'] == 'http://xml.apache.org/xml-soap') {
7126
+ $notstruct = 1;
7127
+ } else {
7128
+ $notstruct = 0;
7129
+ }
7130
+ //
7131
+ foreach($children as $child_pos){
7132
+ if($notstruct){
7133
+ $params[] = &$this->message[$child_pos]['result'];
7134
+ } else {
7135
+ if (isset($params[$this->message[$child_pos]['name']])) {
7136
+ // de-serialize repeated element name into an array
7137
+ if ((!is_array($params[$this->message[$child_pos]['name']])) || (!isset($params[$this->message[$child_pos]['name']][0]))) {
7138
+ $params[$this->message[$child_pos]['name']] = array($params[$this->message[$child_pos]['name']]);
7139
+ }
7140
+ $params[$this->message[$child_pos]['name']][] = &$this->message[$child_pos]['result'];
7141
+ } else {
7142
+ $params[$this->message[$child_pos]['name']] = &$this->message[$child_pos]['result'];
7143
+ }
7144
+ }
7145
+ }
7146
+ }
7147
+ if (isset($this->message[$pos]['xattrs'])) {
7148
+ $this->debug('in buildVal, handling attributes');
7149
+ foreach ($this->message[$pos]['xattrs'] as $n => $v) {
7150
+ $params[$n] = $v;
7151
+ }
7152
+ }
7153
+ // handle simpleContent
7154
+ if (isset($this->message[$pos]['cdata']) && trim($this->message[$pos]['cdata']) != '') {
7155
+ $this->debug('in buildVal, handling simpleContent');
7156
+ if (isset($this->message[$pos]['type'])) {
7157
+ $params['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$pos]['type'], isset($this->message[$pos]['type_namespace']) ? $this->message[$pos]['type_namespace'] : '');
7158
+ } else {
7159
+ $parent = $this->message[$pos]['parent'];
7160
+ if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
7161
+ $params['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
7162
+ } else {
7163
+ $params['!'] = $this->message[$pos]['cdata'];
7164
+ }
7165
+ }
7166
+ }
7167
+ $ret = is_array($params) ? $params : array();
7168
+ $this->debug('in buildVal, return:');
7169
+ $this->appendDebug($this->varDump($ret));
7170
+ return $ret;
7171
+ } else {
7172
+ $this->debug('in buildVal, no children, building scalar');
7173
+ $cdata = isset($this->message[$pos]['cdata']) ? $this->message[$pos]['cdata'] : '';
7174
+ if (isset($this->message[$pos]['type'])) {
7175
+ $ret = $this->decodeSimple($cdata, $this->message[$pos]['type'], isset($this->message[$pos]['type_namespace']) ? $this->message[$pos]['type_namespace'] : '');
7176
+ $this->debug("in buildVal, return: $ret");
7177
+ return $ret;
7178
+ }
7179
+ $parent = $this->message[$pos]['parent'];
7180
+ if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
7181
+ $ret = $this->decodeSimple($cdata, $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
7182
+ $this->debug("in buildVal, return: $ret");
7183
+ return $ret;
7184
+ }
7185
+ $ret = $this->message[$pos]['cdata'];
7186
+ $this->debug("in buildVal, return: $ret");
7187
+ return $ret;
7188
+ }
7189
+ }
7190
+ }
7191
+
7192
+ /**
7193
+ * Backward compatibility
7194
+ */
7195
+ class soap_parser extends nusoap_parser {
7196
+ }
7197
+
7198
+ ?><?php
7199
+
7200
+
7201
+
7202
+ /**
7203
+ *
7204
+ * [nu]soapclient higher level class for easy usage.
7205
+ *
7206
+ * usage:
7207
+ *
7208
+ * // instantiate client with server info
7209
+ * $soapclient = new nusoap_client( string path [ ,mixed wsdl] );
7210
+ *
7211
+ * // call method, get results
7212
+ * echo $soapclient->call( string methodname [ ,array parameters] );
7213
+ *
7214
+ * // bye bye client
7215
+ * unset($soapclient);
7216
+ *
7217
+ * @author Dietrich Ayala <dietrich@ganx4.com>
7218
+ * @author Scott Nichol <snichol@users.sourceforge.net>
7219
+ * @version $Id: fsource_nusoap__nusoap.php.html,v 1.2 2010/04/26 20:25:21 snichol Exp $
7220
+ * @access public
7221
+ */
7222
+ class nusoap_client extends nusoap_base {
7223
+
7224
+ var $username = ''; // Username for HTTP authentication
7225
+
7226
+ var $password = ''; // Password for HTTP authentication
7227
+
7228
+ var $authtype = ''; // Type of HTTP authentication
7229
+
7230
+ var $certRequest = array(); // Certificate for HTTP SSL authentication
7231
+
7232
+ var $requestHeaders = false; // SOAP headers in request (text)
7233
+
7234
+ var $responseHeaders = ''; // SOAP headers from response (incomplete namespace resolution) (text)
7235
+
7236
+ var $responseHeader = NULL; // SOAP Header from response (parsed)
7237
+
7238
+ var $document = ''; // SOAP body response portion (incomplete namespace resolution) (text)
7239
+
7240
+ var $endpoint;
7241
+ var $forceEndpoint = ''; // overrides WSDL endpoint
7242
+
7243
+ var $proxyhost = '';
7244
+ var $proxyport = '';
7245
+ var $proxyusername = '';
7246
+ var $proxypassword = '';
7247
+ var $portName = ''; // port name to use in WSDL
7248
+
7249
+ var $xml_encoding = ''; // character set encoding of incoming (response) messages
7250
+
7251
+ var $http_encoding = false;
7252
+ var $timeout = 0; // HTTP connection timeout
7253
+
7254
+ var $response_timeout = 30; // HTTP response timeout
7255
+
7256
+ var $endpointType = ''; // soap|wsdl, empty for WSDL initialization error
7257
+
7258
+ var $persistentConnection = false;
7259
+ var $defaultRpcParams = false; // This is no longer used
7260
+
7261
+ var $request = ''; // HTTP request
7262
+
7263
+ var $response = ''; // HTTP response
7264
+
7265
+ var $responseData = ''; // SOAP payload of response
7266
+
7267
+ var $cookies = array(); // Cookies from response or for request
7268
+
7269
+ var $decode_utf8 = true; // toggles whether the parser decodes element content w/ utf8_decode()
7270
+
7271
+ var $operations = array(); // WSDL operations, empty for WSDL initialization error
7272
+
7273
+ var $curl_options = array(); // User-specified cURL options
7274
+
7275
+ var $bindingType = ''; // WSDL operation binding type
7276
+
7277
+ var $use_curl = false; // whether to always try to use cURL
7278
+
7279
+ /*
7280
+ * fault related variables
7281
+ */
7282
+ /**
7283
+ * @var fault
7284
+ * @access public
7285
+ */
7286
+ var $fault;
7287
+ /**
7288
+ * @var faultcode
7289
+ * @access public
7290
+ */
7291
+ var $faultcode;
7292
+ /**
7293
+ * @var faultstring
7294
+ * @access public
7295
+ */
7296
+ var $faultstring;
7297
+ /**
7298
+ * @var faultdetail
7299
+ * @access public
7300
+ */
7301
+ var $faultdetail;
7302
+
7303
+ /**
7304
+ * constructor
7305
+ *
7306
+ * @param mixed $endpoint SOAP server or WSDL URL (string), or wsdl instance (object)
7307
+ * @param mixed $wsdl optional, set to 'wsdl' or true if using WSDL
7308
+ * @param string $proxyhost optional
7309
+ * @param string $proxyport optional
7310
+ * @param string $proxyusername optional
7311
+ * @param string $proxypassword optional
7312
+ * @param integer $timeout set the connection timeout
7313
+ * @param integer $response_timeout set the response timeout
7314
+ * @param string $portName optional portName in WSDL document
7315
+ * @access public
7316
+ */
7317
+ function nusoap_client($endpoint,$wsdl = false,$proxyhost = false,$proxyport = false,$proxyusername = false, $proxypassword = false, $timeout = 0, $response_timeout = 30, $portName = ''){
7318
+ parent::nusoap_base();
7319
+ $this->endpoint = $endpoint;
7320
+ $this->proxyhost = $proxyhost;
7321
+ $this->proxyport = $proxyport;
7322
+ $this->proxyusername = $proxyusername;
7323
+ $this->proxypassword = $proxypassword;
7324
+ $this->timeout = $timeout;
7325
+ $this->response_timeout = $response_timeout;
7326
+ $this->portName = $portName;
7327
+
7328
+ $this->debug("ctor wsdl=$wsdl timeout=$timeout response_timeout=$response_timeout");
7329
+ $this->appendDebug('endpoint=' . $this->varDump($endpoint));
7330
+
7331
+ // make values
7332
+ if($wsdl){
7333
+ if (is_object($endpoint) && (get_class($endpoint) == 'wsdl')) {
7334
+ $this->wsdl = $endpoint;
7335
+ $this->endpoint = $this->wsdl->wsdl;
7336
+ $this->wsdlFile = $this->endpoint;
7337
+ $this->debug('existing wsdl instance created from ' . $this->endpoint);
7338
+ $this->checkWSDL();
7339
+ } else {
7340
+ $this->wsdlFile = $this->endpoint;
7341
+ $this->wsdl = null;
7342
+ $this->debug('will use lazy evaluation of wsdl from ' . $this->endpoint);
7343
+ }
7344
+ $this->endpointType = 'wsdl';
7345
+ } else {
7346
+ $this->debug("instantiate SOAP with endpoint at $endpoint");
7347
+ $this->endpointType = 'soap';
7348
+ }
7349
+ }
7350
+
7351
+ /**
7352
+ * calls method, returns PHP native type
7353
+ *
7354
+ * @param string $operation SOAP server URL or path
7355
+ * @param mixed $params An array, associative or simple, of the parameters
7356
+ * for the method call, or a string that is the XML
7357
+ * for the call. For rpc style, this call will
7358
+ * wrap the XML in a tag named after the method, as
7359
+ * well as the SOAP Envelope and Body. For document
7360
+ * style, this will only wrap with the Envelope and Body.
7361
+ * IMPORTANT: when using an array with document style,
7362
+ * in which case there
7363
+ * is really one parameter, the root of the fragment
7364
+ * used in the call, which encloses what programmers
7365
+ * normally think of parameters. A parameter array
7366
+ * *must* include the wrapper.
7367
+ * @param string $namespace optional method namespace (WSDL can override)
7368
+ * @param string $soapAction optional SOAPAction value (WSDL can override)
7369
+ * @param mixed $headers optional string of XML with SOAP header content, or array of soapval objects for SOAP headers, or associative array
7370
+ * @param boolean $rpcParams optional (no longer used)
7371
+ * @param string $style optional (rpc|document) the style to use when serializing parameters (WSDL can override)
7372
+ * @param string $use optional (encoded|literal) the use when serializing parameters (WSDL can override)
7373
+ * @return mixed response from SOAP call, normally an associative array mirroring the structure of the XML response, false for certain fatal errors
7374
+ * @access public
7375
+ */
7376
+ function call($operation,$params=array(),$namespace='http://tempuri.org',$soapAction='',$headers=false,$rpcParams=null,$style='rpc',$use='encoded'){
7377
+ $this->operation = $operation;
7378
+ $this->fault = false;
7379
+ $this->setError('');
7380
+ $this->request = '';
7381
+ $this->response = '';
7382
+ $this->responseData = '';
7383
+ $this->faultstring = '';
7384
+ $this->faultcode = '';
7385
+ $this->opData = array();
7386
+
7387
+ $this->debug("call: operation=$operation, namespace=$namespace, soapAction=$soapAction, rpcParams=$rpcParams, style=$style, use=$use, endpointType=$this->endpointType");
7388
+ $this->appendDebug('params=' . $this->varDump($params));
7389
+ $this->appendDebug('headers=' . $this->varDump($headers));
7390
+ if ($headers) {
7391
+ $this->requestHeaders = $headers;
7392
+ }
7393
+ if ($this->endpointType == 'wsdl' && is_null($this->wsdl)) {
7394
+ $this->loadWSDL();
7395
+ if ($this->getError())
7396
+ return false;
7397
+ }
7398
+ // serialize parameters
7399
+ if($this->endpointType == 'wsdl' && $opData = $this->getOperationData($operation)){
7400
+ // use WSDL for operation
7401
+ $this->opData = $opData;
7402
+ $this->debug("found operation");
7403
+ $this->appendDebug('opData=' . $this->varDump($opData));
7404
+ if (isset($opData['soapAction'])) {
7405
+ $soapAction = $opData['soapAction'];
7406
+ }
7407
+ if (! $this->forceEndpoint) {
7408
+ $this->endpoint = $opData['endpoint'];
7409
+ } else {
7410
+ $this->endpoint = $this->forceEndpoint;
7411
+ }
7412
+ $namespace = isset($opData['input']['namespace']) ? $opData['input']['namespace'] : $namespace;
7413
+ $style = $opData['style'];
7414
+ $use = $opData['input']['use'];
7415
+ // add ns to ns array
7416
+ if($namespace != '' && !isset($this->wsdl->namespaces[$namespace])){
7417
+ $nsPrefix = 'ns' . rand(1000, 9999);
7418
+ $this->wsdl->namespaces[$nsPrefix] = $namespace;
7419
+ }
7420
+ $nsPrefix = $this->wsdl->getPrefixFromNamespace($namespace);
7421
+ // serialize payload
7422
+ if (is_string($params)) {
7423
+ $this->debug("serializing param string for WSDL operation $operation");
7424
+ $payload = $params;
7425
+ } elseif (is_array($params)) {
7426
+ $this->debug("serializing param array for WSDL operation $operation");
7427
+ $payload = $this->wsdl->serializeRPCParameters($operation,'input',$params,$this->bindingType);
7428
+ } else {
7429
+ $this->debug('params must be array or string');
7430
+ $this->setError('params must be array or string');
7431
+ return false;
7432
+ }
7433
+ $usedNamespaces = $this->wsdl->usedNamespaces;
7434
+ if (isset($opData['input']['encodingStyle'])) {
7435
+ $encodingStyle = $opData['input']['encodingStyle'];
7436
+ } else {
7437
+ $encodingStyle = '';
7438
+ }
7439
+ $this->appendDebug($this->wsdl->getDebug());
7440
+ $this->wsdl->clearDebug();
7441
+ if ($errstr = $this->wsdl->getError()) {
7442
+ $this->debug('got wsdl error: '.$errstr);
7443
+ $this->setError('wsdl error: '.$errstr);
7444
+ return false;
7445
+ }
7446
+ } elseif($this->endpointType == 'wsdl') {
7447
+ // operation not in WSDL
7448
+ $this->appendDebug($this->wsdl->getDebug());
7449
+ $this->wsdl->clearDebug();
7450
+ $this->setError('operation '.$operation.' not present in WSDL.');
7451
+ $this->debug("operation '$operation' not present in WSDL.");
7452
+ return false;
7453
+ } else {
7454
+ // no WSDL
7455
+ //$this->namespaces['ns1'] = $namespace;
7456
+ $nsPrefix = 'ns' . rand(1000, 9999);
7457
+ // serialize
7458
+ $payload = '';
7459
+ if (is_string($params)) {
7460
+ $this->debug("serializing param string for operation $operation");
7461
+ $payload = $params;
7462
+ } elseif (is_array($params)) {
7463
+ $this->debug("serializing param array for operation $operation");
7464
+ foreach($params as $k => $v){
7465
+ $payload .= $this->serialize_val($v,$k,false,false,false,false,$use);
7466
+ }
7467
+ } else {
7468
+ $this->debug('params must be array or string');
7469
+ $this->setError('params must be array or string');
7470
+ return false;
7471
+ }
7472
+ $usedNamespaces = array();
7473
+ if ($use == 'encoded') {
7474
+ $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
7475
+ } else {
7476
+ $encodingStyle = '';
7477
+ }
7478
+ }
7479
+ // wrap RPC calls with method element
7480
+ if ($style == 'rpc') {
7481
+ if ($use == 'literal') {
7482
+ $this->debug("wrapping RPC request with literal method element");
7483
+ if ($namespace) {
7484
+ // 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
7485
+ $payload = "<$nsPrefix:$operation xmlns:$nsPrefix=\"$namespace\">" .
7486
+ $payload .
7487
+ "</$nsPrefix:$operation>";
7488
+ } else {
7489
+ $payload = "<$operation>" . $payload . "</$operation>";
7490
+ }
7491
+ } else {
7492
+ $this->debug("wrapping RPC request with encoded method element");
7493
+ if ($namespace) {
7494
+ $payload = "<$nsPrefix:$operation xmlns:$nsPrefix=\"$namespace\">" .
7495
+ $payload .
7496
+ "</$nsPrefix:$operation>";
7497
+ } else {
7498
+ $payload = "<$operation>" .
7499
+ $payload .
7500
+ "</$operation>";
7501
+ }
7502
+ }
7503
+ }
7504
+ // serialize envelope
7505
+ $soapmsg = $this->serializeEnvelope($payload,$this->requestHeaders,$usedNamespaces,$style,$use,$encodingStyle);
7506
+ $this->debug("endpoint=$this->endpoint, soapAction=$soapAction, namespace=$namespace, style=$style, use=$use, encodingStyle=$encodingStyle");
7507
+ $this->debug('SOAP message length=' . strlen($soapmsg) . ' contents (max 1000 bytes)=' . substr($soapmsg, 0, 1000));
7508
+ // send
7509
+ $return = $this->send($this->getHTTPBody($soapmsg),$soapAction,$this->timeout,$this->response_timeout);
7510
+ if($errstr = $this->getError()){
7511
+ $this->debug('Error: '.$errstr);
7512
+ return false;
7513
+ } else {
7514
+ $this->return = $return;
7515
+ $this->debug('sent message successfully and got a(n) '.gettype($return));
7516
+ $this->appendDebug('return=' . $this->varDump($return));
7517
+
7518
+ // fault?
7519
+ if(is_array($return) && isset($return['faultcode'])){
7520
+ $this->debug('got fault');
7521
+ $this->setError($return['faultcode'].': '.$return['faultstring']);
7522
+ $this->fault = true;
7523
+ foreach($return as $k => $v){
7524
+ $this->$k = $v;
7525
+ $this->debug("$k = $v<br>");
7526
+ }
7527
+ return $return;
7528
+ } elseif ($style == 'document') {
7529
+ // NOTE: if the response is defined to have multiple parts (i.e. unwrapped),
7530
+ // we are only going to return the first part here...sorry about that
7531
+ return $return;
7532
+ } else {
7533
+ // array of return values
7534
+ if(is_array($return)){
7535
+ // multiple 'out' parameters, which we return wrapped up
7536
+ // in the array
7537
+ if(sizeof($return) > 1){
7538
+ return $return;
7539
+ }
7540
+ // single 'out' parameter (normally the return value)
7541
+ $return = array_shift($return);
7542
+ $this->debug('return shifted value: ');
7543
+ $this->appendDebug($this->varDump($return));
7544
+ return $return;
7545
+ // nothing returned (ie, echoVoid)
7546
+ } else {
7547
+ return "";
7548
+ }
7549
+ }
7550
+ }
7551
+ }
7552
+
7553
+ /**
7554
+ * check WSDL passed as an instance or pulled from an endpoint
7555
+ *
7556
+ * @access private
7557
+ */
7558
+ function checkWSDL() {
7559
+ $this->appendDebug($this->wsdl->getDebug());
7560
+ $this->wsdl->clearDebug();
7561
+ $this->debug('checkWSDL');
7562
+ // catch errors
7563
+ if ($errstr = $this->wsdl->getError()) {
7564
+ $this->appendDebug($this->wsdl->getDebug());
7565
+ $this->wsdl->clearDebug();
7566
+ $this->debug('got wsdl error: '.$errstr);
7567
+ $this->setError('wsdl error: '.$errstr);
7568
+ } elseif ($this->operations = $this->wsdl->getOperations($this->portName, 'soap')) {
7569
+ $this->appendDebug($this->wsdl->getDebug());
7570
+ $this->wsdl->clearDebug();
7571
+ $this->bindingType = 'soap';
7572
+ $this->debug('got '.count($this->operations).' operations from wsdl '.$this->wsdlFile.' for binding type '.$this->bindingType);
7573
+ } elseif ($this->operations = $this->wsdl->getOperations($this->portName, 'soap12')) {
7574
+ $this->appendDebug($this->wsdl->getDebug());
7575
+ $this->wsdl->clearDebug();
7576
+ $this->bindingType = 'soap12';
7577
+ $this->debug('got '.count($this->operations).' operations from wsdl '.$this->wsdlFile.' for binding type '.$this->bindingType);
7578
+ $this->debug('**************** WARNING: SOAP 1.2 BINDING *****************');
7579
+ } else {
7580
+ $this->appendDebug($this->wsdl->getDebug());
7581
+ $this->wsdl->clearDebug();
7582
+ $this->debug('getOperations returned false');
7583
+ $this->setError('no operations defined in the WSDL document!');
7584
+ }
7585
+ }
7586
+
7587
+ /**
7588
+ * instantiate wsdl object and parse wsdl file
7589
+ *
7590
+ * @access public
7591
+ */
7592
+ function loadWSDL() {
7593
+ $this->debug('instantiating wsdl class with doc: '.$this->wsdlFile);
7594
+ $this->wsdl = new wsdl('',$this->proxyhost,$this->proxyport,$this->proxyusername,$this->proxypassword,$this->timeout,$this->response_timeout,$this->curl_options,$this->use_curl);
7595
+ $this->wsdl->setCredentials($this->username, $this->password, $this->authtype, $this->certRequest);
7596
+ $this->wsdl->fetchWSDL($this->wsdlFile);
7597
+ $this->checkWSDL();
7598
+ }
7599
+
7600
+ /**
7601
+ * get available data pertaining to an operation
7602
+ *
7603
+ * @param string $operation operation name
7604
+ * @return array array of data pertaining to the operation
7605
+ * @access public
7606
+ */
7607
+ function getOperationData($operation){
7608
+ if ($this->endpointType == 'wsdl' && is_null($this->wsdl)) {
7609
+ $this->loadWSDL();
7610
+ if ($this->getError())
7611
+ return false;
7612
+ }
7613
+ if(isset($this->operations[$operation])){
7614
+ return $this->operations[$operation];
7615
+ }
7616
+ $this->debug("No data for operation: $operation");
7617
+ }
7618
+
7619
+ /**
7620
+ * send the SOAP message
7621
+ *
7622
+ * Note: if the operation has multiple return values
7623
+ * the return value of this method will be an array
7624
+ * of those values.
7625
+ *
7626
+ * @param string $msg a SOAPx4 soapmsg object
7627
+ * @param string $soapaction SOAPAction value
7628
+ * @param integer $timeout set connection timeout in seconds
7629
+ * @param integer $response_timeout set response timeout in seconds
7630
+ * @return mixed native PHP types.
7631
+ * @access private
7632
+ */
7633
+ function send($msg, $soapaction = '', $timeout=0, $response_timeout=30) {
7634
+ $this->checkCookies();
7635
+ // detect transport
7636
+ switch(true){
7637
+ // http(s)
7638
+ case preg_match('/^http/',$this->endpoint):
7639
+ $this->debug('transporting via HTTP');
7640
+ if($this->persistentConnection == true && is_object($this->persistentConnection)){
7641
+ $http =& $this->persistentConnection;
7642
+ } else {
7643
+ $http = new soap_transport_http($this->endpoint, $this->curl_options, $this->use_curl);
7644
+ if ($this->persistentConnection) {
7645
+ $http->usePersistentConnection();
7646
+ }
7647
+ }
7648
+ $http->setContentType($this->getHTTPContentType(), $this->getHTTPContentTypeCharset());
7649
+ $http->setSOAPAction($soapaction);
7650
+ if($this->proxyhost && $this->proxyport){
7651
+ $http->setProxy($this->proxyhost,$this->proxyport,$this->proxyusername,$this->proxypassword);
7652
+ }
7653
+ if($this->authtype != '') {
7654
+ $http->setCredentials($this->username, $this->password, $this->authtype, array(), $this->certRequest);
7655
+ }
7656
+ if($this->http_encoding != ''){
7657
+ $http->setEncoding($this->http_encoding);
7658
+ }
7659
+ $this->debug('sending message, length='.strlen($msg));
7660
+ if(preg_match('/^http:/',$this->endpoint)){
7661
+ //if(strpos($this->endpoint,'http:')){
7662
+ $this->responseData = $http->send($msg,$timeout,$response_timeout,$this->cookies);
7663
+ } elseif(preg_match('/^https/',$this->endpoint)){
7664
+ //} elseif(strpos($this->endpoint,'https:')){
7665
+ //if(phpversion() == '4.3.0-dev'){
7666
+ //$response = $http->send($msg,$timeout,$response_timeout);
7667
+ //$this->request = $http->outgoing_payload;
7668
+ //$this->response = $http->incoming_payload;
7669
+ //} else
7670
+ $this->responseData = $http->sendHTTPS($msg,$timeout,$response_timeout,$this->cookies);
7671
+ } else {
7672
+ $this->setError('no http/s in endpoint url');
7673
+ }
7674
+ $this->request = $http->outgoing_payload;
7675
+ $this->response = $http->incoming_payload;
7676
+ $this->appendDebug($http->getDebug());
7677
+ $this->UpdateCookies($http->incoming_cookies);
7678
+
7679
+ // save transport object if using persistent connections
7680
+ if ($this->persistentConnection) {
7681
+ $http->clearDebug();
7682
+ if (!is_object($this->persistentConnection)) {
7683
+ $this->persistentConnection = $http;
7684
+ }
7685
+ }
7686
+
7687
+ if($err = $http->getError()){
7688
+ $this->setError('HTTP Error: '.$err);
7689
+ return false;
7690
+ } elseif($this->getError()){
7691
+ return false;
7692
+ } else {
7693
+ $this->debug('got response, length='. strlen($this->responseData).' type='.$http->incoming_headers['content-type']);
7694
+ return $this->parseResponse($http->incoming_headers, $this->responseData);
7695
+ }
7696
+ break;
7697
+ default:
7698
+ $this->setError('no transport found, or selected transport is not yet supported!');
7699
+ return false;
7700
+ break;
7701
+ }
7702
+ }
7703
+
7704
+ /**
7705
+ * processes SOAP message returned from server
7706
+ *
7707
+ * @param array $headers The HTTP headers
7708
+ * @param string $data unprocessed response data from server
7709
+ * @return mixed value of the message, decoded into a PHP type
7710
+ * @access private
7711
+ */
7712
+ function parseResponse($headers, $data) {
7713
+ $this->debug('Entering parseResponse() for data of length ' . strlen($data) . ' headers:');
7714
+ $this->appendDebug($this->varDump($headers));
7715
+ if (!isset($headers['content-type'])) {
7716
+ $this->setError('Response not of type text/xml (no content-type header)');
7717
+ return false;
7718
+ }
7719
+ if (!strstr($headers['content-type'], 'text/xml')) {
7720
+ $this->setError('Response not of type text/xml: ' . $headers['content-type']);
7721
+ return false;
7722
+ }
7723
+ if (strpos($headers['content-type'], '=')) {
7724
+ $enc = str_replace('"', '', substr(strstr($headers["content-type"], '='), 1));
7725
+ $this->debug('Got response encoding: ' . $enc);
7726
+ if(preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i',$enc)){
7727
+ $this->xml_encoding = strtoupper($enc);
7728
+ } else {
7729
+ $this->xml_encoding = 'US-ASCII';
7730
+ }
7731
+ } else {
7732
+ // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
7733
+ $this->xml_encoding = 'ISO-8859-1';
7734
+ }
7735
+ $this->debug('Use encoding: ' . $this->xml_encoding . ' when creating nusoap_parser');
7736
+ $parser = new nusoap_parser($data,$this->xml_encoding,$this->operation,$this->decode_utf8);
7737
+ // add parser debug data to our debug
7738
+ $this->appendDebug($parser->getDebug());
7739
+ // if parse errors
7740
+ if($errstr = $parser->getError()){
7741
+ $this->setError( $errstr);
7742
+ // destroy the parser object
7743
+ unset($parser);
7744
+ return false;
7745
+ } else {
7746
+ // get SOAP headers
7747
+ $this->responseHeaders = $parser->getHeaders();
7748
+ // get SOAP headers
7749
+ $this->responseHeader = $parser->get_soapheader();
7750
+ // get decoded message
7751
+ $return = $parser->get_soapbody();
7752
+ // add document for doclit support
7753
+ $this->document = $parser->document;
7754
+ // destroy the parser object
7755
+ unset($parser);
7756
+ // return decode message
7757
+ return $return;
7758
+ }
7759
+ }
7760
+
7761
+ /**
7762
+ * sets user-specified cURL options
7763
+ *
7764
+ * @param mixed $option The cURL option (always integer?)
7765
+ * @param mixed $value The cURL option value
7766
+ * @access public
7767
+ */
7768
+ function setCurlOption($option, $value) {
7769
+ $this->debug("setCurlOption option=$option, value=");
7770
+ $this->appendDebug($this->varDump($value));
7771
+ $this->curl_options[$option] = $value;
7772
+ }
7773
+
7774
+ /**
7775
+ * sets the SOAP endpoint, which can override WSDL
7776
+ *
7777
+ * @param string $endpoint The endpoint URL to use, or empty string or false to prevent override
7778
+ * @access public
7779
+ */
7780
+ function setEndpoint($endpoint) {
7781
+ $this->debug("setEndpoint(\"$endpoint\")");
7782
+ $this->forceEndpoint = $endpoint;
7783
+ }
7784
+
7785
+ /**
7786
+ * set the SOAP headers
7787
+ *
7788
+ * @param mixed $headers String of XML with SOAP header content, or array of soapval objects for SOAP headers
7789
+ * @access public
7790
+ */
7791
+ function setHeaders($headers){
7792
+ $this->debug("setHeaders headers=");
7793
+ $this->appendDebug($this->varDump($headers));
7794
+ $this->requestHeaders = $headers;
7795
+ }
7796
+
7797
+ /**
7798
+ * get the SOAP response headers (namespace resolution incomplete)
7799
+ *
7800
+ * @return string
7801
+ * @access public
7802
+ */
7803
+ function getHeaders(){
7804
+ return $this->responseHeaders;
7805
+ }
7806
+
7807
+ /**
7808
+ * get the SOAP response Header (parsed)
7809
+ *
7810
+ * @return mixed
7811
+ * @access public
7812
+ */
7813
+ function getHeader(){
7814
+ return $this->responseHeader;
7815
+ }
7816
+
7817
+ /**
7818
+ * set proxy info here
7819
+ *
7820
+ * @param string $proxyhost
7821
+ * @param string $proxyport
7822
+ * @param string $proxyusername
7823
+ * @param string $proxypassword
7824
+ * @access public
7825
+ */
7826
+ function setHTTPProxy($proxyhost, $proxyport, $proxyusername = '', $proxypassword = '') {
7827
+ $this->proxyhost = $proxyhost;
7828
+ $this->proxyport = $proxyport;
7829
+ $this->proxyusername = $proxyusername;
7830
+ $this->proxypassword = $proxypassword;
7831
+ }
7832
+
7833
+ /**
7834
+ * if authenticating, set user credentials here
7835
+ *
7836
+ * @param string $username
7837
+ * @param string $password
7838
+ * @param string $authtype (basic|digest|certificate|ntlm)
7839
+ * @param array $certRequest (keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, verifypeer (optional), verifyhost (optional): see corresponding options in cURL docs)
7840
+ * @access public
7841
+ */
7842
+ function setCredentials($username, $password, $authtype = 'basic', $certRequest = array()) {
7843
+ $this->debug("setCredentials username=$username authtype=$authtype certRequest=");
7844
+ $this->appendDebug($this->varDump($certRequest));
7845
+ $this->username = $username;
7846
+ $this->password = $password;
7847
+ $this->authtype = $authtype;
7848
+ $this->certRequest = $certRequest;
7849
+ }
7850
+
7851
+ /**
7852
+ * use HTTP encoding
7853
+ *
7854
+ * @param string $enc HTTP encoding
7855
+ * @access public
7856
+ */
7857
+ function setHTTPEncoding($enc='gzip, deflate'){
7858
+ $this->debug("setHTTPEncoding(\"$enc\")");
7859
+ $this->http_encoding = $enc;
7860
+ }
7861
+
7862
+ /**
7863
+ * Set whether to try to use cURL connections if possible
7864
+ *
7865
+ * @param boolean $use Whether to try to use cURL
7866
+ * @access public
7867
+ */
7868
+ function setUseCURL($use) {
7869
+ $this->debug("setUseCURL($use)");
7870
+ $this->use_curl = $use;
7871
+ }
7872
+
7873
+ /**
7874
+ * use HTTP persistent connections if possible
7875
+ *
7876
+ * @access public
7877
+ */
7878
+ function useHTTPPersistentConnection(){
7879
+ $this->debug("useHTTPPersistentConnection");
7880
+ $this->persistentConnection = true;
7881
+ }
7882
+
7883
+ /**
7884
+ * gets the default RPC parameter setting.
7885
+ * If true, default is that call params are like RPC even for document style.
7886
+ * Each call() can override this value.
7887
+ *
7888
+ * This is no longer used.
7889
+ *
7890
+ * @return boolean
7891
+ * @access public
7892
+ * @deprecated
7893
+ */
7894
+ function getDefaultRpcParams() {
7895
+ return $this->defaultRpcParams;
7896
+ }
7897
+
7898
+ /**
7899
+ * sets the default RPC parameter setting.
7900
+ * If true, default is that call params are like RPC even for document style
7901
+ * Each call() can override this value.
7902
+ *
7903
+ * This is no longer used.
7904
+ *
7905
+ * @param boolean $rpcParams
7906
+ * @access public
7907
+ * @deprecated
7908
+ */
7909
+ function setDefaultRpcParams($rpcParams) {
7910
+ $this->defaultRpcParams = $rpcParams;
7911
+ }
7912
+
7913
+ /**
7914
+ * dynamically creates an instance of a proxy class,
7915
+ * allowing user to directly call methods from wsdl
7916
+ *
7917
+ * @return object soap_proxy object
7918
+ * @access public
7919
+ */
7920
+ function getProxy() {
7921
+ $r = rand();
7922
+ $evalStr = $this->_getProxyClassCode($r);
7923
+ //$this->debug("proxy class: $evalStr");
7924
+ if ($this->getError()) {
7925
+ $this->debug("Error from _getProxyClassCode, so return NULL");
7926
+ return null;
7927
+ }
7928
+ // eval the class
7929
+ eval($evalStr);
7930
+ // instantiate proxy object
7931
+ eval("\$proxy = new nusoap_proxy_$r('');");
7932
+ // transfer current wsdl data to the proxy thereby avoiding parsing the wsdl twice
7933
+ $proxy->endpointType = 'wsdl';
7934
+ $proxy->wsdlFile = $this->wsdlFile;
7935
+ $proxy->wsdl = $this->wsdl;
7936
+ $proxy->operations = $this->operations;
7937
+ $proxy->defaultRpcParams = $this->defaultRpcParams;
7938
+ // transfer other state
7939
+ $proxy->soap_defencoding = $this->soap_defencoding;
7940
+ $proxy->username = $this->username;
7941
+ $proxy->password = $this->password;
7942
+ $proxy->authtype = $this->authtype;
7943
+ $proxy->certRequest = $this->certRequest;
7944
+ $proxy->requestHeaders = $this->requestHeaders;
7945
+ $proxy->endpoint = $this->endpoint;
7946
+ $proxy->forceEndpoint = $this->forceEndpoint;
7947
+ $proxy->proxyhost = $this->proxyhost;
7948
+ $proxy->proxyport = $this->proxyport;
7949
+ $proxy->proxyusername = $this->proxyusername;
7950
+ $proxy->proxypassword = $this->proxypassword;
7951
+ $proxy->http_encoding = $this->http_encoding;
7952
+ $proxy->timeout = $this->timeout;
7953
+ $proxy->response_timeout = $this->response_timeout;
7954
+ $proxy->persistentConnection = &$this->persistentConnection;
7955
+ $proxy->decode_utf8 = $this->decode_utf8;
7956
+ $proxy->curl_options = $this->curl_options;
7957
+ $proxy->bindingType = $this->bindingType;
7958
+ $proxy->use_curl = $this->use_curl;
7959
+ return $proxy;
7960
+ }
7961
+
7962
+ /**
7963
+ * dynamically creates proxy class code
7964
+ *
7965
+ * @return string PHP/NuSOAP code for the proxy class
7966
+ * @access private
7967
+ */
7968
+ function _getProxyClassCode($r) {
7969
+ $this->debug("in getProxy endpointType=$this->endpointType");
7970
+ $this->appendDebug("wsdl=" . $this->varDump($this->wsdl));
7971
+ if ($this->endpointType != 'wsdl') {
7972
+ $evalStr = 'A proxy can only be created for a WSDL client';
7973
+ $this->setError($evalStr);
7974
+ $evalStr = "echo \"$evalStr\";";
7975
+ return $evalStr;
7976
+ }
7977
+ if ($this->endpointType == 'wsdl' && is_null($this->wsdl)) {
7978
+ $this->loadWSDL();
7979
+ if ($this->getError()) {
7980
+ return "echo \"" . $this->getError() . "\";";
7981
+ }
7982
+ }
7983
+ $evalStr = '';
7984
+ foreach ($this->operations as $operation => $opData) {
7985
+ if ($operation != '') {
7986
+ // create param string and param comment string
7987
+ if (sizeof($opData['input']['parts']) > 0) {
7988
+ $paramStr = '';
7989
+ $paramArrayStr = '';
7990
+ $paramCommentStr = '';
7991
+ foreach ($opData['input']['parts'] as $name => $type) {
7992
+ $paramStr .= "\$$name, ";
7993
+ $paramArrayStr .= "'$name' => \$$name, ";
7994
+ $paramCommentStr .= "$type \$$name, ";
7995
+ }
7996
+ $paramStr = substr($paramStr, 0, strlen($paramStr)-2);
7997
+ $paramArrayStr = substr($paramArrayStr, 0, strlen($paramArrayStr)-2);
7998
+ $paramCommentStr = substr($paramCommentStr, 0, strlen($paramCommentStr)-2);
7999
+ } else {
8000
+ $paramStr = '';
8001
+ $paramArrayStr = '';
8002
+ $paramCommentStr = 'void';
8003
+ }
8004
+ $opData['namespace'] = !isset($opData['namespace']) ? 'http://testuri.com' : $opData['namespace'];
8005
+ $evalStr .= "// $paramCommentStr
8006
+ function " . str_replace('.', '__', $operation) . "($paramStr) {
8007
+ \$params = array($paramArrayStr);
8008
+ return \$this->call('$operation', \$params, '".$opData['namespace']."', '".(isset($opData['soapAction']) ? $opData['soapAction'] : '')."');
8009
+ }
8010
+ ";
8011
+ unset($paramStr);
8012
+ unset($paramCommentStr);
8013
+ }
8014
+ }
8015
+ $evalStr = 'class nusoap_proxy_'.$r.' extends nusoap_client {
8016
+ '.$evalStr.'
8017
+ }';
8018
+ return $evalStr;
8019
+ }
8020
+
8021
+ /**
8022
+ * dynamically creates proxy class code
8023
+ *
8024
+ * @return string PHP/NuSOAP code for the proxy class
8025
+ * @access public
8026
+ */
8027
+ function getProxyClassCode() {
8028
+ $r = rand();
8029
+ return $this->_getProxyClassCode($r);
8030
+ }
8031
+
8032
+ /**
8033
+ * gets the HTTP body for the current request.
8034
+ *
8035
+ * @param string $soapmsg The SOAP payload
8036
+ * @return string The HTTP body, which includes the SOAP payload
8037
+ * @access private
8038
+ */
8039
+ function getHTTPBody($soapmsg) {
8040
+ return $soapmsg;
8041
+ }
8042
+
8043
+ /**
8044
+ * gets the HTTP content type for the current request.
8045
+ *
8046
+ * Note: getHTTPBody must be called before this.
8047
+ *
8048
+ * @return string the HTTP content type for the current request.
8049
+ * @access private
8050
+ */
8051
+ function getHTTPContentType() {
8052
+ return 'text/xml';
8053
+ }
8054
+
8055
+ /**
8056
+ * gets the HTTP content type charset for the current request.
8057
+ * returns false for non-text content types.
8058
+ *
8059
+ * Note: getHTTPBody must be called before this.
8060
+ *
8061
+ * @return string the HTTP content type charset for the current request.
8062
+ * @access private
8063
+ */
8064
+ function getHTTPContentTypeCharset() {
8065
+ return $this->soap_defencoding;
8066
+ }
8067
+
8068
+ /*
8069
+ * whether or not parser should decode utf8 element content
8070
+ *
8071
+ * @return always returns true
8072
+ * @access public
8073
+ */
8074
+ function decodeUTF8($bool){
8075
+ $this->decode_utf8 = $bool;
8076
+ return true;
8077
+ }
8078
+
8079
+ /**
8080
+ * adds a new Cookie into $this->cookies array
8081
+ *
8082
+ * @param string $name Cookie Name
8083
+ * @param string $value Cookie Value
8084
+ * @return boolean if cookie-set was successful returns true, else false
8085
+ * @access public
8086
+ */
8087
+ function setCookie($name, $value) {
8088
+ if (strlen($name) == 0) {
8089
+ return false;
8090
+ }
8091
+ $this->cookies[] = array('name' => $name, 'value' => $value);
8092
+ return true;
8093
+ }
8094
+
8095
+ /**
8096
+ * gets all Cookies
8097
+ *
8098
+ * @return array with all internal cookies
8099
+ * @access public
8100
+ */
8101
+ function getCookies() {
8102
+ return $this->cookies;
8103
+ }
8104
+
8105
+ /**
8106
+ * checks all Cookies and delete those which are expired
8107
+ *
8108
+ * @return boolean always return true
8109
+ * @access private
8110
+ */
8111
+ function checkCookies() {
8112
+ if (sizeof($this->cookies) == 0) {
8113
+ return true;
8114
+ }
8115
+ $this->debug('checkCookie: check ' . sizeof($this->cookies) . ' cookies');
8116
+ $curr_cookies = $this->cookies;
8117
+ $this->cookies = array();
8118
+ foreach ($curr_cookies as $cookie) {
8119
+ if (! is_array($cookie)) {
8120
+ $this->debug('Remove cookie that is not an array');
8121
+ continue;
8122
+ }
8123
+ if ((isset($cookie['expires'])) && (! empty($cookie['expires']))) {
8124
+ if (strtotime($cookie['expires']) > time()) {
8125
+ $this->cookies[] = $cookie;
8126
+ } else {
8127
+ $this->debug('Remove expired cookie ' . $cookie['name']);
8128
+ }
8129
+ } else {
8130
+ $this->cookies[] = $cookie;
8131
+ }
8132
+ }
8133
+ $this->debug('checkCookie: '.sizeof($this->cookies).' cookies left in array');
8134
+ return true;
8135
+ }
8136
+
8137
+ /**
8138
+ * updates the current cookies with a new set
8139
+ *
8140
+ * @param array $cookies new cookies with which to update current ones
8141
+ * @return boolean always return true
8142
+ * @access private
8143
+ */
8144
+ function UpdateCookies($cookies) {
8145
+ if (sizeof($this->cookies) == 0) {
8146
+ // no existing cookies: take whatever is new
8147
+ if (sizeof($cookies) > 0) {
8148
+ $this->debug('Setting new cookie(s)');
8149
+ $this->cookies = $cookies;
8150
+ }
8151
+ return true;
8152
+ }
8153
+ if (sizeof($cookies) == 0) {
8154
+ // no new cookies: keep what we've got
8155
+ return true;
8156
+ }
8157
+ // merge
8158
+ foreach ($cookies as $newCookie) {
8159
+ if (!is_array($newCookie)) {
8160
+ continue;
8161
+ }
8162
+ if ((!isset($newCookie['name'])) || (!isset($newCookie['value']))) {
8163
+ continue;
8164
+ }
8165
+ $newName = $newCookie['name'];
8166
+
8167
+ $found = false;
8168
+ for ($i = 0; $i < count($this->cookies); $i++) {
8169
+ $cookie = $this->cookies[$i];
8170
+ if (!is_array($cookie)) {
8171
+ continue;
8172
+ }
8173
+ if (!isset($cookie['name'])) {
8174
+ continue;
8175
+ }
8176
+ if ($newName != $cookie['name']) {
8177
+ continue;
8178
+ }
8179
+ $newDomain = isset($newCookie['domain']) ? $newCookie['domain'] : 'NODOMAIN';
8180
+ $domain = isset($cookie['domain']) ? $cookie['domain'] : 'NODOMAIN';
8181
+ if ($newDomain != $domain) {
8182
+ continue;
8183
+ }
8184
+ $newPath = isset($newCookie['path']) ? $newCookie['path'] : 'NOPATH';
8185
+ $path = isset($cookie['path']) ? $cookie['path'] : 'NOPATH';
8186
+ if ($newPath != $path) {
8187
+ continue;
8188
+ }
8189
+ $this->cookies[$i] = $newCookie;
8190
+ $found = true;
8191
+ $this->debug('Update cookie ' . $newName . '=' . $newCookie['value']);
8192
+ break;
8193
+ }
8194
+ if (! $found) {
8195
+ $this->debug('Add cookie ' . $newName . '=' . $newCookie['value']);
8196
+ $this->cookies[] = $newCookie;
8197
+ }
8198
+ }
8199
+ return true;
8200
+ }
8201
+ }
8202
+
8203
+ if (!extension_loaded('soap')) {
8204
+ /**
8205
+ * For backwards compatiblity, define soapclient unless the PHP SOAP extension is loaded.
8206
+ */
8207
+ class soapclient extends nusoap_client {
8208
+ }
8209
+ }
8210
+ ?>
8211
+
8212
+
app/design/adminhtml/default/default/layout/msp_bancasella.xml ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!--
3
+ /**
4
+ * IDEALIAGroup srl
5
+ *
6
+ * NOTICE OF LICENSE
7
+ *
8
+ * This source file is subject to the Open Software License (OSL 3.0)
9
+ * that is bundled with this package in the file LICENSE.txt.
10
+ * It is also available through the world-wide-web at this URL:
11
+ * http://opensource.org/licenses/osl-3.0.php
12
+ * If you did not receive a copy of the license and are unable to
13
+ * obtain it through the world-wide-web, please send an email
14
+ * to info@idealiagroup.com so we can send you a copy immediately.
15
+ *
16
+ * @category MSP
17
+ * @package MSP_Bancasella
18
+ * @copyright Copyright (c) 2013 IDEALIAGroup srl (http://www.idealiagroup.com)
19
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
20
+ */
21
+ -->
22
+ <layout version="0.1.0">
23
+ <default>
24
+ <reference name="head">
25
+ <action method="addItem"><type>skin_css</type><name>msp_bancasella/bancasella.css</name></action>
26
+ </reference>
27
+ </default>
28
+ </layout>
app/design/adminhtml/default/default/template/msp_bancasella/system/config/fieldset/hint/account.phtml ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * IDEALIAGroup srl
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the Open Software License (OSL 3.0)
8
+ * that is bundled with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://opensource.org/licenses/osl-3.0.php
11
+ * If you did not receive a copy of the license and are unable to
12
+ * obtain it through the world-wide-web, please send an email
13
+ * to info@idealiagroup.com so we can send you a copy immediately.
14
+ *
15
+ * @category MSP
16
+ * @package MSP_Bancasella
17
+ * @copyright Copyright (c) 2013 IDEALIAGroup srl (http://www.idealiagroup.com)
18
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19
+ */
20
+ ?>
21
+ <div class="msp-bancasella-payment-notice">
22
+ <h4><?php echo $this->__('Remember to correctly configure your BancaSella backend panel while using in production.')?></h4>
23
+ <p>
24
+ <ul>
25
+ <li><?php echo $this->__("Log in your backend at <a target=\"_blank\" href=\"%s\">%s</a>", 'https://ecomm.sella.it/gestpay/backoffice/LoginGestPay.asp', 'https://ecomm.sella.it/gestpay/backoffice/LoginGestPay.asp') ?></li>
26
+ <li><?php echo $this->__("Configure your server's public IP") ?></li>
27
+ <li><?php echo $this->__("Configure your server-to-server URL with \"<b>http://www.yourwebsite.com/msp_bancasella/listener/index</b>\"") ?></li>
28
+ <li><?php echo $this->__("Configure your positive URL with \"<b>http://www.yourwebsite.com/msp_bancasella/gateway/success</b>\"") ?></li>
29
+ <li><?php echo $this->__("Configure your negative URL with \"<b>http://www.yourwebsite.com/msp_bancasella/gateway/failure</b>\"") ?></li>
30
+ </ul>
31
+ </p>
32
+ <p><a href="<?php echo $this->escapeHtml($this->getUrl('adminhtml/system_config/edit', array('section' => 'payment'))) ?>"><?php echo $this->__('Click here to configure BancaSella payment method.')?></a></p>
33
+ </div>
app/design/adminhtml/default/default/template/msp_bancasella/system/config/fieldset/hint/methods.phtml ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * IDEALIAGroup srl
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the Open Software License (OSL 3.0)
8
+ * that is bundled with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://opensource.org/licenses/osl-3.0.php
11
+ * If you did not receive a copy of the license and are unable to
12
+ * obtain it through the world-wide-web, please send an email
13
+ * to info@idealiagroup.com so we can send you a copy immediately.
14
+ *
15
+ * @category MSP
16
+ * @package MSP_Bancasella
17
+ * @copyright Copyright (c) 2013 IDEALIAGroup srl (http://www.idealiagroup.com)
18
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19
+ */
20
+ ?>
21
+ <div class="msp-bancasella-payment-notice">
22
+ <h4><?php echo $this->__('Before configuring BancaSella Gateway please fill-in your account information in the dedicated tab to the left under Sales.')?></h4>
23
+ <p><a href="<?php echo $this->escapeHtml($this->getUrl('adminhtml/system_config/edit', array('section' => 'msp_bancasella'))) ?>"><?php echo $this->__('Edit BancaSella account information.')?></a></p>
24
+ </div>
app/design/frontend/base/default/layout/msp_bancasella.xml ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <!--
3
+ /**
4
+ * IDEALIAGroup srl
5
+ *
6
+ * NOTICE OF LICENSE
7
+ *
8
+ * This source file is subject to the Open Software License (OSL 3.0)
9
+ * that is bundled with this package in the file LICENSE.txt.
10
+ * It is also available through the world-wide-web at this URL:
11
+ * http://opensource.org/licenses/osl-3.0.php
12
+ * If you did not receive a copy of the license and are unable to
13
+ * obtain it through the world-wide-web, please send an email
14
+ * to info@idealiagroup.com so we can send you a copy immediately.
15
+ *
16
+ * @category MSP
17
+ * @package MSP_Bancasella
18
+ * @copyright Copyright (c) 2013 IDEALIAGroup srl (http://www.idealiagroup.com)
19
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
20
+ */
21
+ -->
22
+ <layout version="0.1.0">
23
+ <msp_bancasella_gateway_index>
24
+ <reference name="root">
25
+ <action method="setTemplate"><template>page/1column.phtml</template></action>
26
+ </reference>
27
+ <reference name="content">
28
+ <block type="msp_bancasella/gateway" name="msp_bancasella.gateway" template="msp_bancasella/gateway.phtml" />
29
+ </reference>
30
+ </msp_bancasella_gateway_index>
31
+
32
+ <msp_bancasella_gateway_success>
33
+ <reference name="root">
34
+ <action method="setTemplate"><template>page/2columns-right.phtml</template></action>
35
+ </reference>
36
+ <reference name="content">
37
+ <block type="checkout/onepage_success" name="checkout.success" template="checkout/success.phtml"/>
38
+ </reference>
39
+ </msp_bancasella_gateway_success>
40
+
41
+ <msp_bancasella_gateway_failure>
42
+ <reference name="root">
43
+ <action method="setTemplate"><template>page/2columns-right.phtml</template></action>
44
+ </reference>
45
+ <reference name="content">
46
+ <block type="checkout/onepage_failure" name="checkout.failure" template="checkout/onepage/failure.phtml"/>
47
+ </reference>
48
+ </msp_bancasella_gateway_failure>
49
+ </layout>
app/design/frontend/base/default/template/msp_bancasella/gateway.phtml ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * IDEALIAGroup srl
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the Open Software License (OSL 3.0)
8
+ * that is bundled with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://opensource.org/licenses/osl-3.0.php
11
+ * If you did not receive a copy of the license and are unable to
12
+ * obtain it through the world-wide-web, please send an email
13
+ * to info@idealiagroup.com so we can send you a copy immediately.
14
+ *
15
+ * @category MSP
16
+ * @package MSP_Bancasella
17
+ * @copyright Copyright (c) 2013 IDEALIAGroup srl (http://www.idealiagroup.com)
18
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19
+ */
20
+ ?>
21
+ <div class="page-title">
22
+ <h1><?php echo $this->__('Redirecting to BancaSella') ?></h1>
23
+ </div>
24
+
25
+ <div style="text-align: center">
26
+ <img src="<?php echo $this->getSkinUrl('msp_bancasella/logo.png') ?>">
27
+ <br />
28
+ <h2><?php echo $this->__('Please wait while you are beeing redirected to BancaSella payment website...') ?></h2>
29
+ </div>
30
+ <script type="text/javascript">
31
+ //<![CDATA[
32
+ window.location.replace(<?php echo json_encode($this->getRedirectUrl()); ?>);
33
+ //]]>
34
+ </script>
app/design/frontend/base/default/template/msp_bancasella/gateway/form.phtml ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * IDEALIAGroup srl
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the Open Software License (OSL 3.0)
8
+ * that is bundled with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://opensource.org/licenses/osl-3.0.php
11
+ * If you did not receive a copy of the license and are unable to
12
+ * obtain it through the world-wide-web, please send an email
13
+ * to info@idealiagroup.com so we can send you a copy immediately.
14
+ *
15
+ * @category MSP
16
+ * @package MSP_Bancasella
17
+ * @copyright Copyright (c) 2013 IDEALIAGroup srl (http://www.idealiagroup.com)
18
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19
+ */
20
+ ?>
21
+ <?php
22
+ $_code = $this->getMethodCode();
23
+ $_img = $this->getPaymentImageSrc();
24
+ ?>
25
+ <fieldset class="form-list">
26
+ <ul id="payment_form_<?php echo $_code ?>" style="display:none;">
27
+ <li>
28
+ <?php echo $this->__('You will be redirected to BancaSella secure payment page when you place an order.') ?><br />
29
+ </li>
30
+ </ul>
31
+ </fieldset>
app/etc/modules/MSP_Bancasella.xml ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <!--
3
+ /**
4
+ * IDEALIAGroup srl
5
+ *
6
+ * NOTICE OF LICENSE
7
+ *
8
+ * This source file is subject to the Open Software License (OSL 3.0)
9
+ * that is bundled with this package in the file LICENSE.txt.
10
+ * It is also available through the world-wide-web at this URL:
11
+ * http://opensource.org/licenses/osl-3.0.php
12
+ * If you did not receive a copy of the license and are unable to
13
+ * obtain it through the world-wide-web, please send an email
14
+ * to info@idealiagroup.com so we can send you a copy immediately.
15
+ *
16
+ * @category MSP
17
+ * @package MSP_Bancasella
18
+ * @copyright Copyright (c) 2013 IDEALIAGroup srl (http://www.idealiagroup.com)
19
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
20
+ */
21
+ -->
22
+ <config>
23
+ <modules>
24
+ <MSP_Bancasella>
25
+ <active>true</active>
26
+ <codePool>community</codePool>
27
+ <depends>
28
+ <MSP_Common/>
29
+ </depends>
30
+ </MSP_Bancasella>
31
+ </modules>
32
+ </config>
app/locale/it_IT/MSP_Bancasella.csv ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ "Customer was redirected to Bancasella.","Cliente reindirizzato al sito di Bancasella."
2
+ "BancaSella - Account Settings","BancaSella - Impostazioni Account"
3
+ "Language","Lingua"
4
+ "Order Prefix","Preffisso ordine"
5
+ "Useful to avoid duplicates on multiple installations","Utile per evitare duplicati su installazioni multiple"
6
+ "Merchant code","Codice esercente"
7
+ "Merchant login","Login esercente"
8
+ "Merchant password","Password esercente"
9
+ "Currency Code","Codice valuta"
10
+ "Fields configuration","Configurazione campi"
11
+ "Send Customer Name","Invia il nome del cliente"
12
+ "Must be enabled in your Bancasella account","Deve essere abilitato nel tuo account di Bancasella"
13
+ "Send Customer Email","Invia l'email del cliente"
14
+ "Send Language","Invia la lingua predefinita"
15
+ "BancaSella GestPay","BancaSella GestPay"
16
+ "Italian","Italiano"
17
+ "English","Inglese"
18
+ "Spanish","Spagnolo"
19
+ "French","Francese"
20
+ "German","Tedesco"
21
+ "BancaSella Status: %s","Stato Bancasella: %s"
22
+ "Remember to correctly configure your BancaSella backend panel while using in production.","Ricorda che devi configurare il tuo account Bancasella prima di poterlo usare in produzione."
23
+ "Log in your backend at <a target=""_blank"" href=""%s"">%s</a>","Accedi al tuo pannello su <a target=""_blank"" href=""%s"">%s</a>"
24
+ "Configure your server's public IP","Configura l'IP pubblico del tuo server"
25
+ "Configure your server-to-server URL with ""<b>http://www.yourwebsite.com/msp_bancasella/listener/index</b>""","Configura l'URL server-to-server con ""<b>http://www.yourwebsite.com/msp_bancasella/listener/index</b>"""
26
+ "Configure your positive URL with ""<b>http://www.yourwebsite.com/msp_bancasella/gateway/success</b>""","Configura l'URL per le transazioni andate a buon fine con ""<b>http://www.yourwebsite.com/msp_bancasella/gateway/success</b>"""
27
+ "Configure your negative URL with ""<b>http://www.yourwebsite.com/msp_bancasella/gateway/failure</b>""","Configura l'URL per le transazioni fallite con ""<b>http://www.yourwebsite.com/msp_bancasella/gateway/failure</b>"""
28
+ "By MageSpecialist - <a target="_blank" href="http://www.magespecialist.it">www.magespecialist.it</a>","By MageSpecialist - <a target="_blank" href="http://www.magespecialist.it">www.magespecialist.it</a>"
29
+ "Before configuring BancaSella Gateway please fill-in your account information in the dedicated tab to the left under Sales.","Prima di configurare il gateway di BancaSella inserisci le informazioni del tuo account nella sezione dedicata nel men&ugrave; di sinistra sotto la voce Vendite."
30
+ "Edit BancaSella account information.","Imposta le informazioni dell'account Bancasella."
31
+ "You will be redirected to BancaSella secure payment page when you place an order.","Sarai spostato alla pagina del pagamento sicuro con BancaSella appena confermato l'ordine."
32
+ "Redirecting to BancaSella","Inoltro a BancaSella in corso"
33
+ "Please wait while you are beeing redirected to BancaSella payment website...","Attendere prego mentre si attende la connessione con il sito di pagamento di BancaSella..."
34
+ "Click here to configure BancaSella payment method.","Clicca qui per configurare il metodo di pagamento con BancaSella."
package.xml ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <package>
3
+ <name>MSP_Bancasella</name>
4
+ <version>1.0.4</version>
5
+ <stability>stable</stability>
6
+ <license uri="http://www.opensource.org/licenses/osl-3.0.php">OSL</license>
7
+ <channel>community</channel>
8
+ <extends/>
9
+ <summary>MageSpecialist Bancasella payment gateway</summary>
10
+ <description>MageSpecialist Bancasella payment gateway</description>
11
+ <notes>Enjoy it ;)</notes>
12
+ <authors><author><name>Riccardo Tempesta</name><user>idealiagroup</user><email>tempesta@idealiagroup.com</email></author><author><name>Paolo Vecchiocattivi</name><user>idealiagroup</user><email>vecchiocattivi@idealiagroup.com</email></author></authors>
13
+ <date>2014-08-27</date>
14
+ <time>15:08:59</time>
15
+ <contents><target name="magecommunity"><dir name="MSP"><dir name="Bancasella"><dir name="Block"><dir name="Adminhtml"><dir name="System"><dir name="Config"><dir name="Fieldset"><dir name="Hint"><file name="Account.php" hash="8f582004d272df0092dae62b528aa6f3"/><file name="Methods.php" hash="a620668b324ea2ce541304491435fd79"/></dir></dir></dir></dir></dir><dir name="Gateway"><file name="Form.php" hash="9df841615010a6ccd858204ffdb16783"/></dir><file name="Gateway.php" hash="b6ee61d4e12ad8bd6e09749718a243af"/><file name="Return.php" hash="628326d7a20e0d93d9096699f545e5da"/></dir><file name="CHANGELOG.txt" hash="544b9922155f9cdb103a4fb56cf10fb6"/><file name="COMPATIBILITY.txt" hash="fe84ccdf4e7963c6e847a7ee1201a0ac"/><dir name="Helper"><file name="Data.php" hash="b7f87777052840fbeabb63bbeac8bb54"/></dir><file name="LICENSE.txt" hash="43d8581f57722664f478fccb6e71f99b"/><dir name="Model"><dir name="Adminhtml"><dir name="System"><dir name="Config"><dir name="Source"><file name="Language.php" hash="09b4465ed58a49a62f5bb90e51ed4aa4"/><file name="Uic.php" hash="2e886497f3e8eab28bb9d16d714efed8"/></dir></dir></dir></dir><file name="Api.php" hash="296b66f161292de2269a9a312730f2b0"/><file name="Gateway.php" hash="3c037e0b205c6500d965808c95239079"/></dir><dir name="controllers"><file name="GatewayController.php" hash="4c8aaf5ff28b59962bab1f0cbd12e0b9"/><file name="ListenerController.php" hash="9bba53294d4793bbeeaa7728316a51b3"/></dir><dir name="etc"><file name="config.xml" hash="05ce0bcc7bb3d1c4342a366266f0f70e"/><file name="system.xml" hash="3b349af69a4c3160688f39804bfcdb33"/></dir><dir name="lib"><file name="nusoap.php" hash="7a1001878404cf863bf2f664a9b4cdda"/></dir></dir></dir></target><target name="magedesign"><dir name="frontend"><dir name="base"><dir name="default"><dir name="template"><dir name="msp_bancasella"><dir name="gateway"><file name="form.phtml" hash="78183d9071445e3ae0c6a30fab1a1f6e"/></dir><file name="gateway.phtml" hash="61dc0df61cca13515db71b89d4280676"/></dir></dir><dir name="layout"><file name="msp_bancasella.xml" hash="dff251dfea458d95b9fc275daee584aa"/></dir></dir></dir></dir><dir name="adminhtml"><dir name="default"><dir name="default"><dir name="template"><dir name="msp_bancasella"><dir name="system"><dir name="config"><dir name="fieldset"><dir name="hint"><file name="account.phtml" hash="b6b66bee4800871da07fad84220fb399"/><file name="methods.phtml" hash="b4946d19f5bedeb9d440943cc8d7de1b"/></dir></dir></dir></dir></dir></dir><dir name="layout"><file name="msp_bancasella.xml" hash="f22b98b7dcd93920dbfe33e92f8e2021"/></dir></dir></dir></dir></target><target name="mageetc"><dir name="modules"><file name="MSP_Bancasella.xml" hash="318573c7db0098e8336a1cfb8af55c60"/></dir></target><target name="magelocale"><dir name="it_IT"><file name="MSP_Bancasella.csv" hash="159bdf0adb78c813612287fd820ff833"/></dir></target><target name="mageskin"><dir name="adminhtml"><dir name="default"><dir name="default"><dir name="msp_bancasella"><file name="bancasella.css" hash="e3754beefc081a207cdf4e8f897cb4b9"/><file name="bancasella_section.png" hash="8dffc573ff53e6a250e3ea1031797fab"/><file name="logo.png" hash="8286454cb4e8495245d639daa61de290"/></dir></dir></dir></dir><dir name="frontend"><dir name="base"><dir name="default"><dir name="msp_bancasella"><file name="logo.png" hash="e7649845c664b9fe8284c2122052ca4d"/><file name="logo_small.png" hash="0d5e20b324fee3c1e4b2d89ed6e386bc"/></dir></dir></dir></dir></target></contents>
16
+ <compatible/>
17
+ <dependencies><required><php><min>5.2.0</min><max>6.0.0</max></php></required></dependencies>
18
+ </package>
skin/adminhtml/default/default/msp_bancasella/bancasella.css ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * IDEALIAGroup srl
3
+ *
4
+ * NOTICE OF LICENSE
5
+ *
6
+ * This source file is subject to the Open Software License (OSL 3.0)
7
+ * that is bundled with this package in the file LICENSE.txt.
8
+ * It is also available through the world-wide-web at this URL:
9
+ * http://opensource.org/licenses/osl-3.0.php
10
+ * If you did not receive a copy of the license and are unable to
11
+ * obtain it through the world-wide-web, please send an email
12
+ * to info@idealiagroup.com so we can send you a copy immediately.
13
+ *
14
+ * @category MSP
15
+ * @package MSP_Bancasella
16
+ * @copyright Copyright (c) 2013 IDEALIAGroup srl (http://www.idealiagroup.com)
17
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
18
+ */
19
+
20
+ .msp-bancasella-payment-notice {
21
+ background: url("logo.png") no-repeat scroll 15px center #EAF0EE;
22
+ border: 1px solid #CCCCCC;
23
+ margin-bottom: 10px;
24
+ padding: 10px 5px 5px 115px;
25
+ }
26
+
27
+ ul.tabs a.msp-bancasella-section, ul.tabs a.msp-bancasella-section:hover {
28
+ background: url("../images/tabs_span_bg.gif") repeat-x scroll 0 100% transparent;
29
+ border-bottom: medium none;
30
+ padding: 0.2em 0.5em 0.28em 1.5em;
31
+ }
32
+ ul.tabs a.msp-bancasella-section span, ul.tabs a.msp-bancasella-section:hover span {
33
+ background: url("bancasella_section.png") no-repeat scroll 0 0 transparent;
34
+ height: 0;
35
+ overflow: hidden;
36
+ padding: 18px 0 0;
37
+ width: 107px;
38
+ }
39
+
40
+ ul.tabs a.msp-bancasella-section:hover {
41
+ background-color: #d8e6e6;
42
+ }
43
+ ul.tabs a.msp-bancasella-section.active, ul.tabs a.msp-bancasella-section.active:hover {
44
+ background-color: #fff;
45
+ }
46
+
47
+ .msp-bancasella-warning {
48
+ border: 1px solid #cc0000;
49
+ background: #dcb0b0;
50
+ margin-bottom: 10px;
51
+ padding: 10px 5px 5px 5px;
52
+ text-align: center;
53
+ }
54
+
skin/adminhtml/default/default/msp_bancasella/bancasella_section.png ADDED
Binary file
skin/adminhtml/default/default/msp_bancasella/logo.png ADDED
Binary file
skin/frontend/base/default/msp_bancasella/logo.png ADDED
Binary file
skin/frontend/base/default/msp_bancasella/logo_small.png ADDED
Binary file